Jak dziurę w OpenLDAP znalazłem (CVE-2022-29155)

Potrzebowałem zrobić bramkę LDAP do istniejącej bazy adresowej. To wziąłem to, co wydawało się oczywistym wyborem: OpenLDAP i jego plugin ‚back-sql’. Skonfigurowanie bramki okazało się niespodziewanie skomplikowane. Nie dość, że schemat LDAP niespecjalnie jest kompatybilny z naszym schematem bazy (generalnie struktura katalogu LDAP niespecjalnie się mapuje do
relacyjnej bazy danych), to jeszcze ten ‚back-sql’ wydawał się nieco przekombinowany. Szczegóły mapowania schematów same musiały być zapisane w bazie SQL. No ale coś udało mi się wydziergać i jakoś działało.

Problem wyszedł gdy próbowałem wyszukać kontakt z apostrofem w nazwisku (ktoś się naprawdę postarał przygotowując nasze dane testowe). Wyszukiwanie zamiast oczekiwanego wyniku dawało błędy SQL w logach serwera. Nieładnie.

Wiedząc czym to pachnie zacząłem kombinować z zapytaniami, aż udało mi się to, czego się obawiałem: byłem w stanie wykonać dowolną instrukcję SQL na serwerze. Niby nie był to duży problem, bo uprawnienia bramki LDAP były ograniczone tylko do odczytu konkretnych tabel, ale jednak uznałem to za niedopuszczalne.

Następny krok to Google: na pewno ktoś już to zauważył, może jest już poprawioen. I tu niespodzianka: ani śladu zgłoszenia takiego błędu. Co wciąż nie wykluczało możliwości, że jest dawno poprawiony. Użyłem jakiegoś antycznego OpenLDAP 2.4 (swoją drogą nawet Debian wciąż na 2.4 stoi), a już był dostępny OpenLDAP 2.6.1. No to czas na aktualizację!

Przy okazji okazało się, że ‚back-sql’ już nie tylko jest ‚experimental’, ale też ‚obsolete’ i w ogóle nie zalecany… No fajnie, ale ja już tego użyłem, a implementacja bramki od nowa, w Perlu, jakoś mnie nie pociąga. Tak, czy siak, ‚back-sql’ wciąż jest częścią OpenLDAP i powinien działać. Niestety, w 2.6.1 bez zmian: babol ‚SQL injection’ jak był, tak jest.

Zajrzałem do kodu, może jestem w stanie to poprawić. Ale szybko się poddałem. Ten ‚back-sql’ jest faktycznie przekombinowany. Kod masakrycznie złożony, prościej będzie już nową bramkę z użyciem ‚back-perl’ napisać niż się w tym połapać i czegoś bardziej nie zepsuć.

Błąd postanowiłem jednak zgłosić do autorów, bez większej nadziei na jego poprawę (skoro siedzi tam od kilkunastu lat, a plugin jest ‚experimental’ i ‚obsolete’). Skleciłem do tego prosty ‚proof of concept’ kasujący rekordy w przykładowej bazie. Ku mojemu zaskoczeniu już po paru godzinach dostałem pierwszego patcha który miał to poprawić. Patch nie do końca działał, ale ewidentnie wola rozwiązania problemu była.

Po dwóch dniach miałem już działającą poprawkę. A teraz poprawiona wersja OpenLDAP jest już publicznie dostępna, a problem zarejestrowany jako CVE-2022-29155.

Kerbal Space Program

W ostatnich latach na blogu było raczej pustawo. To co robiłem, gdy nic nie pisałem? Głównie… grałem na komputerze. Tak, w ostatnich latach na nowo odkryłem tę rozrywkę, dzięki temu, że powychodziła cała masa gier pod Linuksa (szerzej o tym może  w innym wpisie). Jedną z gier, w którą grałem najwięcej (i dalej gram) jest Kerbal Space Program. Żona twierdzi, że już zielenieję od tego.

Idea gry jest taka: Na planecie Kerbin, krążącej wokół gwiazdy Kerbol żyją zielone stworki zwane Kerbalami. Właśnie rozpoczęli program kosmiczny, którym przewodzi czwórka „weteranów” – Jebediah, Bob, Bill i Valentina. Zadaniem gracza jest budować rakiety i wysyłać nimi Kerbale w kosmos. Zadanie nie jest łatwe, bo trzeba brać pod uwagę prawa fizyki, które, chociaż łagodniejsze niż w naszej rzeczywistości, są wciąż bezlitosne.

Bez zrozumienia podstaw mechaniki orbitalnej, pojęć jak Δv, perycentrum (peryapsis), apocentrum (apoapsis), czy tego, co wynika ze wzoru Ciołkowskiego trudno coś w tej grze osiągnąć. Z drugiej strony, gra jest zabawna, wciągająca i, w sumie, zadziwiająco prosta. Moja czternastoletnia córka też w to gra, chociaż wcześniej nie wykazywała przesadnego zainteresowania fizyką, czy kosmosem.

Wysyłanie rakiet w kosmos, najpierw na orbitę Kerbina, potem na jego księżyce – Mün i Minmus (i, co trudniejsze, z powrotem), aż w końcu na odległe planety i ich księżyce, to podstawowy cel gry, ale gra nie ogranicza się do tego. Są gracze, co w ogóle rakiet nie budują, tylko samoloty i tymi samolotami latają w atmosferze Kerbina. Są tacy, co nie sterują zbudowanymi rakietami „bo to nudne”, zdając się na mody implementujące auto-pilota, a tylko projektują różne statki kosmiczne, często na wzór istniejących lub znanych z filmów science-fiction. Są tacy, którzy z KSP robią strzelankę, gdzie zamiast rakiet pilotują myśliwce i bombowce z pełnym uzbrojeniem.

Grać można w trybie „sandbox”, mając od razu do dyspozycji wszystkie części i nie dbając o pieniądze, czy rozwój naukowy; w trybie „science”, gdzie pieniądze też nie są problemem, ale odpowiednią technikę trzeba dopiero zdobyć oraz „career” gdzie na wszystko trzeba sobie zarobić wypełniając zadania dla zewnętrznych zleceniodawców. Wbrew pozorom „sandbox” niekoniecznie jest dobry dla początkujących – ilość opcji od razu dostępnych może być przytłaczający i tylko utrudnić zbudowanie pierwszej działającej rakiety.

„Gołe” Kerbal Space Program to gotowa gra, a ilość funkcji i dostępnych części może przytłaczać, ale jednak szybko się okazuje, że sporo brakuje. Braki te uzupełniają setki dostępnych modów. Od podstawowych narzędzi przydatnych przy projektowaniu i pilotowaniu rakiety, przez ulepszenia grafiki i dźwięku, po zupełnie nowe elementy gry.

Są mody, które można uznać za „obowiązkowe”, bo przydadzą się każdemu od początku gry. Inne mogą służyć ułatwieniu lub utrudnieniu gry,  według potrzeb konkretnego gracza. Są też takie, które dadzą KSP nowe życie przez nowe zasady i cele gry.

W swojej poprzedniej „sesji” z KSP grałem prawie „vanilla”  – prawie bez modów, a właściwie tylko z takimi „narzędziowymi”, jak Kerbal Engineer Redux, czy Kerbal Alarm Clock. Z bardziej ingerujących w grę tylko KIS/KAS, bo znacznie wzbogacają one możliwości Kerbali poza statkiem.

Po wyjściu KSP 1.1, parę tygodni temu, zacząłem nową grę. Tym razem już ze sporą ilością modów, w szczególności zestawu modów USI do kolonizacji i utrzymania życia oraz RemoteTech wymagającego utrzymywania radiowej łączności ze statkami bezzałogowymi. Dzięki nim mam dodatkowe wyzwania – muszę pilnować, żeby moje Kerbale miały co jeść, zapewnić im odpowiednie warunki „mieszkaniowe”, a bezzałogowe misje planować z odpowiednim wyprzedzeniem, zapewniając infrastrukturę.

Obecnie buduję kolonię na Münie i chcę ją doprowadzić do stanu samowystarczalności (teraz wymaga ciągłych dostaw z Kerbina). Następnie spróbuję zbudować kolonię na Eve i to taką, żeby mogła wysyłać statki z powrotem na Kerbina (a to wyjątkowo trudne, ze względu na grawitację i gęstą atmosferę na Eve). Zobaczymy, czy dotrwam do tego celu.

baza

Gdyby to KSP się jeszcze tak ciągle nie wieszało… Pod tym względem wersja 1.0.5 była dużo lepsza (niektórzy użytkownicy Windows specjalnie Linuksa instalowali, żeby KSP dobrze działało) – Unity 5 pod Linuksem nie działa najlepiej.

 

Jak zabezpieczyć VPN L2TP/IPsec na Androidzie

Pisałem, że namęczyłem się, żeby odpalić L2TP/IPsec między PLD i Androidem.

Napisałem też, że taki tunel nie zupełnie jest bezpieczny

I co? Zrezygnować z tego IPsec i VPN w ogóle? Czy może kombinować z innym rozwiązaniem? A może jednak załatać tego IPSec?

Wybrałem trzecią opcję. Jeśli chodzi o sprawdzanie certyfikatu, to obejście problemu już opisałem – trzeba zrobić własne CA, które wystawi jeden certyfikat, dla serwera.

Drugi problem (10 sekund plain tekstu) nie da się obejść po stronie serwera, ale da się coś zrobić na telefonie. Na zrootowanym telefonie na pewno.

Okazało się, że na kernel w telefonie posiada pełnosprawny podsystem netfilter i za pomocą iptables można zablokować nieszyfrowany ruch. Używam już Droidwalla, więc wystarczyło dołożyć mu kilka regułek.

No to, po kolei:

Stworzenie prostego CA:

cat >ca.cnf <<EOF
[ req ]
default_bits        = 2048
default_keyfile     = ca-key.pem
distinguished_name  = req_distinguished_name
x509_extensions     = v3_ca
string_mask         = nombstr
attributes          = req_attributes
prompt              = no

[ req_attributes ]

[ req_distinguished_name ]
commonName = VPN CA

[ v3_ca ]
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer:always
basicConstraints = CA:true
EOF
openssl req -new -x509 -config ca.cnf -batch -nodes -days 3650 -out ca-cert.pem

Za pomocą tego CA tworzę certyfikat dla serwera (sensowne subjectName i subjectAltName na wypadek jakbym czymś normalnym też chciał się łączyć, bo Android ma to w nosie):

cat >vpn.cnf <<EOF
[ req ]
default_bits        = 2048
default_keyfile     = vpn-key.pem
distinguished_name  = req_distinguished_name
attributes          = req_attributes
prompt              = no

[ req_distinguished_name ]
commonName                  = vpn.example.org

[ req_attributes ]
subjectAltName=IP:10.20.30.40;DNS:vpn.example.org

[ cert ]
basicConstraints=CA:FALSE
keyUsage = digitalSignature, keyEncipherment, keyAgreement
EOF
openssl req -new -batch -nodes -config vpn.cnf -out vpn-req.pem
openssl x509 -req -in vpn-req.pem -CA ca-cert.pem -CAkey ca-key.pem -set_serial $RANDOM -out vpn-cert.pem

vpn-key.pem i vpn-cert.pem wrzucam do konfiguracji Racoona. ca-cert.pem trzeba zainstalować na telefonie – ja wrzuciłem na swój serwer WWW, pod nazwą ca-cert.crt i załadowałem przeglądarką z telefonu. Potem trzeba wybrać to zaimportowane CA w konfiguracji łącza VPN. Należy pamiętać, że nie wolno tego samego CA używać do wystawiania certyfikatów klientów, ani najlepiej żadnych innych.

Teraz blokowanie plaintekstu… Wchodzę do DroidWall, tam z menu wybieram więcej/Set custom script i wklejam następujące skrypty:

# allow Android only to connect to L2TP over ipsec
$IPTABLES -A "droidwall" -m udp -p 17 --dport 1701 -m policy --pol ipsec --dir out -j ACCEPT
$IPTABLES -A "droidwall" -m udp -p 17 --dport 1701 -j DROP

# prevent injection of unauthenticated packets
$IPTABLES -F INPUT
$IPTABLES -A INPUT -m udp -p 17 --sport 1701 -m policy --pol ipsec --dir in -j ACCEPT
$IPTABLES -A INPUT -m udp -p 17 --sport 1701 -j DROP

oraz (shutdown script):

# clean the rules added to INPUT
$IPTABLES -F INPUT

I to by było na tyle.

VPN L2TP/IPSEC między PLD Linuksem i Androidem

Jeszcze się tu nie chwaliłem, ale kupiłem sobie mojego pierwszego smartfonika (Samsung Galaxy S Plus). Oczywiście odkąd go mam (nieco ponad dwa tygodnie) bawię się wszelkimi możliwymi jego funkcjami… W głębi menu „ustawienia” znalazłem „sieci VPN”. W sumie dobrze by było mieć w komórce dostępne bezpieczne połączenie do domowej sieci lokalnej…

Telefonik fabrycznie obsługuje cztery opcje: „PPTP”, „L2TP”, „L2TP/IPSec PSK” i „L2TP/IPSec CRT”. PPTP jakoś źle mi się kojarzy (nie wiem czemu i nie wnikam), zerknąłem na opis L2TP w Wikipedii i uznałem, że L2TP/IPSec to będzie sensowny wybór, szczególnie że IPSec pewnie niedługo będę przerabiał w robocie. Od razu postanowiłem też użyć uwierzytelniania za pomocą certyfikatu.

Od początku zdawałem sobie sprawę, że zapewne dużo prościej byłoby znaleźć OpenVPN na Androida i tym tunel zestawić… ale to nie byłoby żadne wyzwanie ;-). Nie sądziłem jednak, że uruchomienie L2TP/IPSec będzie aż takim problemem…

Zacząłem tradycyjnie, jak to się w PLD robi: „poldek:/all-avail> ls *l2tp*„. Nic. „search -a *L2TP*” pokazało nie wiele więcej, nic czego bym szukał. Kolej na Google… tu parę różnych tekstów… Że w PLD obecnie do IPSec mamy tylko ipsec-tool i ten pakiet mam opanowany, to pominąłem wszystkie HOWTO dotyczące OpenSWAN/FreeSWAN itp… Zresztą, nie tylko mnogość implementacji IPSec była problemem. Samego L2TP też było wymienionych kilka implementacji i chyba żadna aktywnie nie rozwijana…

Znalazłem jakiś obiecujący opis użycia l2tpd… było tam wspomniane, że ten demon już nierozwijany, ale jest jakaś kontynuacja – xl2tpd. O, nawet w PLD spec był… okazało się, że niedokończony… a właściwie nawet dobrze nie zaczęty. Dokończyłem, zbudowałem, zainstalowałem…

IPSec w ogóle nie skonfigurowałem, chciałem tylko to xl2tpd wypróbować, a nawet nie do końca wiedziałem czy IPSec działa pod, czy nad L2TP (potem doczytałem – transmisja L2TP odbywa się wewnątrz IPSec, a więc IPSec należałoby skonfigurować najpierw). Telefon się nawet łączył, xl2tpd coś w logach pisał, ale wyglądało to, jakby telefon próbował otworzyć jeden tunel za drugim, żadnego nie zestawiając do końca. Późno już było, dałem sobie z tym spokój.

Wczoraj pogooglałem dalej i trafiłem na openl2tp. Projekt prawie żywy, ostatnie wydanie sprzed roku. Zrobiłem pakiet dla PLD. Żeby kod się skompilował wystarczyło „-Werror” z Makefile wywalić. Demon się uruchamiał, l2tpconfig działał.

Tym razem postanowiłem najpierw uruchomić IPSec. Racoonem już się kiedyś bawiłem, ale wciąż jego konfiguracja nie jest dla mnie całkiem jasna. Posiłkowałem się gotowcem z Quick Start Guide openl2tp, uzupełniłem tylko konfigurację, żeby uwierzytelnianie było zrobione certyfikatami (co wymagało wielu prób i błędów). Niby już było wszystko ok, ale:

racoon: ERROR: no policy found: 192.168.1.10/32[0] 192.168.0.1/32[1701] proto=udp dir=in
racoon: ERROR: failed to get proposal for responder.

…okazało się, że to błąd w rzeczonym Quick Start. Kolejność parametrów w skrypcie setkey była zła. Powinno być:

#!/usr/sbin/setkey -f
flush; 
spdflush;

spdadd 0.0.0.0/0 192.168.0.1 [1701] udp -P in ipsec esp/transport//require;

(192.168.0.1 to będzie adres serwera VPN, 192.168.1.10 – klienta) Policy ‚out’ na serwerze nie potrzebne, bo odpowiednie wpisy openl2tpd powinien dodać sam, dla konkretnych połączeć.

Po poprawieniu tego, Racoon uraczył mnie kolejnym błędem:

racoon: ERROR: long lifetime proposed: my:3600 peer:28800
racoon: ERROR: not matched
racoon: ERROR: no suitable policy found

Do było proste, trzeba było znaleźć „lifetime” w racoon.conf i poprawić na wartość oczekiwaną przez Androida.

Jak już poprawnie przychodziły requesty z telefonu po IPSec, przyszedł czas skonfigurować openl2tpd

. Jednak ten już przy starcie wołał:

openl2tpd[12257]: IPSec support disabled. No setkey found.

…i nie bardzo dalej działał. Nie podobało mi się to, ale od razu domyśliłem się o co chodzi – openl2tpd miał zaszytą złą ścieżkę do setkey. Szybko odnalazłem odpowiedni fragment kodu, w plugins/ipsec.c:

#define IPSEC_SETKEY_CMD        "/sbin/setkey"
#define IPSEC_SETKEY_FILE       "/tmp/openl2tpd-tmp"
#define IPSEC_SETKEY_ACTION     IPSEC_SETKEY_CMD " -f " IPSEC_SETKEY_FILE

Poprawka była oczywista (w PLD setkey leży w /usr/sbin), ale nie spodobało mi się coś innego… Moje obawy potwierdziły się niżej w kodzie:

FILE *f = fopen(IPSEC_SETKEY_FILE, "w");

…ciekawe co by było jakby jakiś user zrobił np. „ln -s /bin/sh /tmp/openl2tpd-tmp”…

Załatałem to (przenosząc plik tymczasowy do /var/run/openl2tp) razem z poprawkę ścieżki do setkey, ale trochę zaufania do tego kodu już utraciłem…

Połatany openl2tp już poprawnie ustawiał policy dla wysyłanych pakietów, ale znowu Racoon zaczął marudzić:

racoon: ERROR: phase1 negotiation failed due to send error. b842e7fcf5598054:0000000000000000
racoon: ERROR: failed to begin ipsec sa negotication.

To już była bardziej tajemnicza sprawa. Nawet bardziej szczegółowe logi nie mówiły nic konkretnego. Dopiero w źródłach udało mi się znaleźć co może powodować ten błąd, bez żadnego innego sensownego komunikatu. Dzieje się tak, gdy Racoon nie może znaleźć socketu z którego ma wysłać pakiet. Testowałem połączenie z sieci lokalnej, ale łączyłem się na zewnętrzny adres mojego routera i tylko do tego zewnętrznego adresu kazałem się Racoonowi przyczepić. A openl2tpd na żądania z sieci lokalnej odpowiadał z adresu lokalnego. Racoon próbował zestawić sesję IPSec z tego samego adresu i mu się nie udawało. Problem udało się rozwiązać wywalając całą sekcję „listen” z racoon.conf (sam niepotrzebnie tam adresy pododawałem – nadgorliwość się mści) oraz ustawiając ‚src_ipaddr’ w profilu tuneli openl2tpd. Dla pewności, że to samo nie będzie mi dalej zawadzać, dalsze próby robiłem z pominięciem lokalnego WiFi.

Problem Racoona rozwiązałem, ale openl2tpd dalej się nie łączył. Podobnie, jak w przypadku xl2tpd było widać wiele prób zestawienia tunelu, ale żadna nie kończyła się sukcesem. Żeby przyjrzeć się ruchowi tcpdumpem wyłączyłem IPSec i próbowałem kontynuować „gołym L2TP”.

Wymiana pakietów wyglądała mniej-więcej tak:

KLIENT -> SERWER:   UDP port xxxx -> port 1701
SERWER -> KLIENT:   UDP port yyyy -> port xxxx
KLIENT -> SERVER:  ICMP port xxxx unreachable

Winnym okazał się feature openl2tpd – demon domyślnie wykorzystuje „efemeryczne” porty UDP dla każdego połączenia. Żądanie przychodzi na port 1701, ale odpowiedź serwera już wychodzi z nowego, losowego portu. Najwyraźniej Android tego się nie spodziewa i odpowiada błędem „port unreachable”, jakby to po jego stronie czegoś brakowałem. Na szczęście można ten feature wyłączyć przez l2tpconfig:

tunnel profile modify profile_name=default our_udp_port=1701

Potem było już z górki… jeszcze jeden błąd z openl2tpd:

openl2tpd[9952]: PROTO: tunl 23305: STOPCCN error 5/0: The protocol version of the requester is not supported - no challenge response AVP received

Już nie pamiętam czym dokładnie to rozwiązałem, ale jakąś zmianą w konfiguracji openl2tpd. Potem pomarudził jeszcze pppd:

The remote system is required to authenticate itself
but I couldn't find any suitable secret (password) for it to use to do so.
(None of the available passwords would let it use an IP address.)

Tu wystarczyło poprawić /etc/ppp/pap-secret. Gdy już się telefon z serwerem połączył jeszcze takie w logach w kółko leciały:

pppd[14786]: sent [CCP ConfReq id=0x1 ]
pppd[14786]: rcvd [CCP ConfReq id=0x2]
pppd[14786]: sent [CCP ConfAck id=0x2]
pppd[14786]: rcvd [CCP ConfRej id=0x1 ]
pppd[14786]: Received bad configure-rej:  12 06 00 00 00 00

…najwyraźniej kolejne głupie rozszerzenie PPP do Microsoftu, nie wiedzieć czemu domyślnie włączone. Pomogło „nomppe” w /etc/ppp/options

Jeszcze tylko wyregulowanie firewalla i tunel wydaje się działać jak należy. Przynajmniej ze strony telefonu, w drugą nawet ping za bardzo nie chodzi, bo Android odpowiada z innego IP niż ten pingowany przez tunel. Ale z tym już raczej nic nie zrobię.

Ostatecznie moja konfiguracja wygląda mniej-więcej tak:

/etc/racoon/racoon.conf:

path include "/etc/racoon";
path pre_shared_key "/etc/racoon/psk.txt";
path certificate "/etc/racoon/cert";
padding
{
        maximum_length 20;
        randomize off;
        strict_check off;
        exclusive_tail off;
}

timer
{
        counter 5;
        interval 20 sec;
        persend 1;
        phase1 30 sec;
        phase2 15 sec;
}

remote "l2tpclient"
{
        exchange_mode main;
        doi ipsec_doi;
        situation identity_only;

        ca_type x509 "cacert.pem";

        my_identifier asn1dn;
        certificate_type x509 "cert.pem" "key.pem";

        verify_identifier on;
        verify_cert on;
        peers_identifier asn1dn "CN=*, emailAddress=jajcus@example.com";
        peers_identifier user_fqdn "jajcus@example.com";
        peers_identifier asn1dn "CN=*, emailAddress=jajcus@example.org";
        peers_identifier user_fqdn "jajcus@example.org";

        nonce_size 16;
        initial_contact on;
        proposal_check strict;

        proposal {
                encryption_algorithm 3des;
                hash_algorithm sha1;
                authentication_method rsasig;
                dh_group 2;
        }
}

sainfo anonymous
{
        lifetime time 12 hour;
        encryption_algorithm aes 256, rijndael 256, blowfish 448, 3des;
        authentication_algorithm hmac_sha256, hmac_sha1, hmac_md5;
        compression_algorithm deflate;
}

/etc/racoon/setkey.conf:

#!/usr/sbin/setkey -f
flush;
spdflush;

spdadd 0.0.0.0/0 192.168.0.1 [1701] udp -P in ipsec esp/transport//require;

/etc/openl2tpd.conf:

# system

# peer profiles
peer profile modify profile_name=default \
        lac_lns=lns \

# tunnel profiles
tunnel profile modify profile_name=default \
        auth_mode=none \
        host_name=tropek \
        src_ipaddr=192.168.0.1 \
        our_udp_port=1701 \

# ppp profiles
ppp profile modify profile_name=default \
        auth_mschapv1=no \
        auth_mschapv2=no \
        auth_eap=no \
        local_ipaddr=10.0.0.1 \
        ip_pool_name=l2tp \

# locally created tunnels and sessions

/etc/ipoold.conf:

# ip pools
pool create pool_name=l2tp \

pool address add pool_name=l2tp first_addr=10.0.0.100 num_addrs=100 \
        netmask=255.255.255.0

/etc/ppp/options:

ms-dns 192.168.0.1
ms-dns 192.168.0.2
asyncmap 0
auth
crtscts
lock
modem
proxyarp
lcp-echo-interval 30
lcp-echo-failure 4
noipx
nomppe

/etc/ppp/pap-secrets:

username hostname "passsword"        *

I jeszcze w firewallu regułka dla pewności sprawdzająca użycie IPSec (domyślna regułka u mnie to DROP dla wszystkiego):

iptables -A INPUT -p udp --dport 1701 -m policy --pol ipsec --dir in -j ACCEPT

Tak więc, działać już mi ten VPN działa i pozostaje mieć nadzieję, że jest bezpieczny. A wszystko to tu opisałem, żeby następnym razem wujek Google umiał pomóc, gdy ktoś tak jak ja będzie się męczył…

Update: Proste testy sugerują, że ze strony telefonu to ten VPN niespecjalnie bezpieczny jest. To się pobawiłem, ale na razie używać tego chyba nie będę na poważnie.

Update 2:: Tak, tak zestawiony tunel nie jest specjalnie bezpieczny, ale można sobie z tym poradzić (o ile telefon jest zrootowany).

Dofus pod PLD Linux

…czyli walki z Adobe AIR.

Przeglądając The Linux Game Tome natrafiłem na opis gry Dofus. MMORPG, z ładną grafiką, ale bez zbytnich wymagań do sprzętu (grafika 2D) – wyglądało zachęcająco, postanowiłem więc spróbować.

Ściągnąłem instalator, uruchomiłem… i nic, okazuje się że RPMowych dystrybucji nie obsługuje. Jak to tak?! Odpaliłem z opcją ‚–keep’, żeby zobaczyć co jest w środku i ewentualnie zainstalować ręcznie. W środku trochę plików, skrypt instalacyjny, deinstalacyjny i jakaś binarka „UpLauncher”. Spróbowałem odpalić binarkę, brakowało starej wersji libjpeg. W PLDowych CVS na szczęście jest spec, to dobudowałem, doinstalowałem i coś ruszyło. Ruszyło, „uaktualniło grę”, ale odpalić już się nie dało. Okazało się, że czegoś brakuje…

Znalazłem logi (po francusku) i rzeczywiście jakby jakiś plików brakuje. Zajrzałem do skryptu instalacyjnego (komentarze częściowo po francusku) i zrozumiałem, że to miało sobie jeszcze Adobe AIR zainstalować, potem tym Adobe AIR zainstalować grę z plików *.air, a dopiero to ostatecznie jest uruchamiane…

Udałem się więc do Adobe po to całe AIR. Do wyboru paczki ‚deb’, ‚yum’, ‚rpm’ i ‚bin’. Wybrałem ostatnie, nie licząc na kompatybilność tego RPMa z PLD. Okazało się jednak, że to ‚bin’ to niby samo-rozpakowujące-się-archiwum, ale potem i tak próbuje budować i instalować RPM. Budować w PLD tym bardziej nie umie, więc nic z tego nie wyszło. Wziąłem więc paczkę rpm (albo jednak z tego ‚bin’ coś wykopałem, nie pamiętam)… coś się zainstalowało.

Zainstalowanym „Adobe AIR Application Installer” próbowałem zainstalować „Dofus.air” i „Reg.air” jak to miał robić skrypt instalacyjny Dofusa. Nie udało się. Okazało się, że ten cały „application installer” też próbuje jakieś RPMy budować, co mu nie wychodzi. Czemu nie można jak np. z javowymi aplikacjami „java -jar cośtam.jar”? Ja rozumiem, że developerzy postawili sobie za cel zrobić tak, że user dwa razy kliknie w paczkę i mu się zainstaluje jak każda inna aplikacje, ale żeby to osiągnąć strasznie przekombinowali jednocześnie zapewniając sobie kompatybilność tylko z kilkoma konkretnymi dystrybucjami, właściwie uniemożliwiając użycie tego w innych…

W końcu, jakoś strasznie hackując udało mi się to jednak opanować i grę zainstalować tak, że zadziałała. Właściwie zadziałało wszystko poza dźwiękami i urwanymi tekstami NPC już w samej grze (ten drugi problem najwyraźniej doskwiera też innym linuksowym użytkownikom Dofusa). Skoro zadziałało, to sobie trochę pograłem. I spodobało mi się. Prawie że noce nad tym zarywam, jak kiedyś nad Crossfire ;-)

Wciąż jednak nie dawało mi spokoju pytanie: „czy na prawdę nie dałoby się prościej”. I dzisiaj wygooglałem coś takiego: Adobe® AIR on Gentoo Linux. Artykuł ten mówi jak można uruchamiać aplikacje AIR używają ichniejszego SDK. Bez żadnych śmiesznych „instalatorów” próbujących budować paczki. Sprawdziłem, rzeczywiście działa. Przygotowałem też „uproszczoną procedurę” instalacji Dofusa pod prawie każdym Linuksem (poniżej). Co więcej, tym razem udało mi się uzyskać także dźwięk! :-)

Instalacja Dofusa pod ulubioną dystrybucją

  1. Ściągnijmy Adobe AIR SDK z http://www.adobe.com/cfusion/entitlement/index.cfm?e=airsdk
  2. Zainstalujmy Adobe AIR SDK (tutaj do /opt, więc potrzebne prawa roota):
    mkdir -p /opt/AdobeAIRSDK
    cd /opt/AdobeAIRSDK
    tar xjvf AdobeAIRSDK.tbz2
    cat >/usr/local/bin/adl <<'EOF'
    #!/bin/sh
    
    exec /opt/AdobeAIRSDK/bin/adl "$@"
    EOF
    
  3. Ściągnij instalator Dofusa dla Linuksa ze strony gry i rozpakuj do tymczasowej lokalizacji. To (i wszystko następne) już z prawami zwykłego użytkownika.
    mkdir /tmp/dofus-inst
    cd /tmp
    wget http://dl.ak.ankama.com/games/dofus2/setup/DofusInstall.run
    chmod a+x DofusInstall.run
    ./DofusInstall.run --keep --noexec --target /tmp/dofus-inst
    
  4. Stwórz katalog dla gry (tutaj w $HOME/Gry/Dofus) i rozpakuj tam aplikacje AIR:
    mkdir -p ~/Gry/Dofus
    cd ~/Gry/Dofus
    mkdir -p share/reg
    cd share
    unzip /tmp/dofus-inst/Dofus.air 
    cd reg
    unzip /tmp/dofus-inst/Reg.air
    cd ../..
    
  5. Stwórz pliki wykonywalne dla tych aplikacji:
    mkdir -p bin share/reg/bin
    cat >bin/Dofus << 'EOF'
    #!/bin/sh
    
    exec /opt/AdobeAIRSDK/bin/adl -nodebug ~/Gry/Dofus/share/META-INF/AIR/application.xml ~/Gry/Dofus/share
    EOF
    chmod a+x bin/Dofus
    cat >share/reg/bin/Reg << 'EOF'
    #!/bin/sh
    
    exec /opt/AdobeAIRSDK/bin/adl -nodebug ~/Gry/Dofus/share/reg/META-INF/AIR/application.xml ~/Gry/Dofus/share/reg
    EOF
    chmod a+x share/reg/bin/Reg
    
  6. Oryginalny instalator robi jakieś dziwne symlinki. Więc i my je zróbmy:
    mkdir share/reg/share
    ln -s ../Reg.swf share/reg/share/Reg.swf
    ln -s ../content share/reg/share/content
    
  7. Teraz skopiujmy pliki z instalatora:
    cp /tmp/dofus-inst/UpLauncher share
    cp /tmp/dofus-inst/games.xml share
    chmod a+x share/UpLauncher
    
  8. I zróbmy skrypt do uruchamiania gry:
    cat > start-dofus << 'EOF'
    #!/bin/sh
    
    cd ~/Gry/Dofus/share
    exec ./UpLauncher
    EOF
    chmod a+x start-dofus
    
  9. Teraz można spróbować uruchomić grę:
    ./start-dofus
    

    To może się nie udać, jeśli w systemie brakuje odpowiednich bibliotek w odpowiednich wersjach. W PLD Th np. trzeba było zbudować i doinstalować libjpeg6.

    Po doinstalowaniu brakujących bibliotek powinien się Launcher uruchomić i zacząć „uaktualniać” grę. Gdy Launcher ściągnie najnowszą wersję Dofusa będzie go można uruchomić.

Jak kupowałem kabelek

W komentarzach do poprzedniego wpisu wspomniałem że chcę córce nowy „kabelek MIDI” kupić. Dokładnie to chodzi o konwerter USB-MIDI, żeby jej instrument do komputera podłączyć. Widziałem takie na Allegro za dwadzieścia-parę złotych i wyczytałem że nawet najtańsze byle-co powinno pod Linuksem zadziałać. Dzisiaj miałem do załatwienia coś na mieście, postanowiłem zobaczyć, czy gdzieś w sklepie tego nie ma. Przy okazji rozglądałem się też za jakimś fajnym ale tanim (kiepskim) mikrofonem do Performousa…

Najpierw trafiłem do sklepu z urządzeniami muzycznymi. Konwertera USB-MIDI nie mają, ale mieli/miewają… za jakieś 150zł (porządnej firmy). Pan był chyba trochę zniesmaczony tym, że ja chcę jakieś byle-co, sporo taniej. Jeszcze bardziej zniesmaczony był później, gdy pytałem o jakiś „tani mikrofon” dając do zrozumienia, że za 50zł to stanowczo za drogi. :-)

Następnie udałem się do jakiegoś sklepu komputerowego. Spytałem o mikrofony. Mieli sporo różnego badziewia, ale nic co można by trzymać w ręce i do tego „śpiewać”. Bez nadziei na sukces spytałem też o „kabelek USB-MIDI”. „Nie, takiego raczej nie. Mamy do drukarki…”. Stwierdziłem, że rozumiem, bo to raczej w muzycznym, nie komputerowym… to pani się coś przypomniało. „O, tu mam jakieś MIDI!” i pokazała jakiś zakurzony blister. Tak, to było dokładnie to, identyczne jak te na allegro. Pani stwierdziła jednak, że to drogie, że tak „po kosztach” to za 57zł mogłaby mi sprzedać. Gdy podziękowałem wspominając, że na Allegro są po 20zł zgodziła się sprzedać mi to za 30zł. „Od ponad pół roku to tu leży i nieprędko to raczej sprzedam. Myśleliśmy, że to coś innego…”. Fajnie udało mi się kupić to co chciałem, bo towar do sklepu trafił przez pomyłkę. :-)

Swoją drogą, lubię zakupy w tym sklepie i nie mogę powiedzieć, że sprzedawczyni jest niekompetentna, wręcz przeciwnie. Po prostu raz się trafił nietypowy towar.

Świat Gu – kupiłem sobie gierkę na Linuksa

Zajrzałem sobie na Linux News i od razu rzuciła mi się w oczy informacja, że jakaś Linuksowa gra, normalnie kosztująca $20 jest teraz (do 19 października) dostępna za „co łaska”. World of Goo niewiele mi mówiło, ale po przejrzeniu opisu i obrazków uznałem, że czemu by nie spróbować. Może nie dałem ile gra jest warta, ale tylko tyle na ile obecnie mnie stać (nowe mieszkanie jednak nieźle wysysa bankowe konta), ale to zawsze lepsze od „piracenia”.

[screenshot]

Gierka to takie połączenie starych dobrych „Lemingów” z popularnymi ostatnio grami „konstrukcyjnymi” (typu: zbuduj most, żeby pociąg przejechał). Trzeba spuścić sympatyczne gluty (kulki Goo) rurami. Te same gluty służą jako element konstrukcyjny drogi do celu. Może nie ma powalającej fabuły, ale jest sympatycznie i dużo ładniej niż w większości gier dostępnych pod Linuksem. Ja już chyba kończę pierwszy rozdział, a Krysia skończyła pierwsze trzy poziomy. Nawet, jeśli za tydzień się znudzi, to trochę rozrywki jest. :-)

Co ja knułem przez ostatnie dwa tygodnie

Od dwóch tygodni byłem wyraźnie czymś zajęty. Tak, że aż żona zaczęła się niepokoić… A o co chodziło okaże się już za chwilę.

Wszystko zaczęło się od szwankującego odtwarzacza DVD. Dokładnie tego, o którym już tutaj pisałem. Tak jak się można było spodziewać, to było„ wszystkomające”, ale jednak tanie badziewie. Właściwie od początku coś szwankowało (np. OGGów w końcu nigdy na tym nie słuchałem, bo się nie dało), a od jakiegoś czasu kłopotliwe było normalne używanie, czyli puszczanie dziecku bajki: urządzenie długo się włączało, potem nie chciało wysunąć tacki (trzeba ręcznie wyciągnąć). Po filmie podobne problemy z wyciągnięciem płytki. I tak dużo z tym badziewiem wytrzymaliśmy (właśnie stuknęły by tej Mancie cztery lata), więc uznałem, że można by kupić coś nowego, markowego…

Jak już kupować, to czemu tylko odtwarzacz? Lepiej od razu nagrywarkę. Jak nagrywarkę, to tylko z twardym dyskiem. No i nie byle co, tylko, żeby wszystko działało jak należy. Przejrzałem w sieci co jest dostępne, poczytałem opinie i nieźle się napaliłem na nową zabawkę… Niestety, taka zabawka, jaka mi się podobała, to kosztowałaby około tysiąca złotych. Uznaliśmy z żonką, że to jednak byłoby zbytnie szaleństwo. A ja dalej byłem napalony na nagrywarkę… i zacząłem knuć…

Tydzień temu kupiliśmy dużo tańszy odtwarzacz DVD. Ma nawet wejście USB i potrafi odtwarzać muzykę i filmy z pamięci masowych USB (to taki bonus, bo chcieliśmy tylko odtwarzacza DVD i VCD). Ale ja już od tygodnia kombinowałem coś innego…

Gdy przekonałem się, że o nagrywarce z prawdziwego zdarzenia nie ma co marzyć, z ciekawości zacząłem się rozglądać za innymi opcjami. Rozejrzałem się na Allegro za tunerami do komputera. Poczytałem na ten temat. Zastanowiłem się, czy mógłbym coś z tym zrobić… i wyszło mi, że może dałoby się coś wykombinować.

Akurat na Allegro dość tanio dostępny był tuner na USB ze sprzętową kompresją MPEG-2: Hauppauge WinTV-PVR-USB2, najwyraźniej dość dobrze obsługiwany przez Linuksa i MythTV. Do tego miałem nadzieję wskrzesić laptopa, który umarł podczas mojego pobytu w Reptach. Nawet udało się osiągnąć pewne efekty: przestał się przegrzewać, pracuje już z pełną prędkością i wentylatory nie wyją mu cały czas. Zamówiłem więc tuner i zacząłem się szkolić i szykować inne elementy systemu.

Niestety, laptop działać działał, ale odmówił wyświetlania grafiki. Na wbudowanej matrycy często obrazu brakowało już przy starcie, a na zewnętrznym monitorze, niestety było niewiele lepiej: karta graficzna odmawiała współpracy już przy próbie zmiany trybu na graficzny. Co gorsza, to prawdopodobnie uszkodzenie płyty głównej (nie działa też jeden slot pamięci). Laptop się więc na nagrywarkę nie nada. Szkoda.

Na szczęście miałem w biurze jeszcze jedną maszynkę. Mały komputerek z procesorem VIA Eden 1GHz. Dostałem go, żeby przystosować do tej platformy sprzętowej nasze oprogramowanie, a od wielu miesięcy tylko się nudził Mogę go więc z czystym sumieniem pożyczyć na domowe multimedia. Pudełko ma wyjście TV i audio, wiec jest w sam raz.

Zamontowałem tam dysk z laptopa, zainstalowałem system i MythTV, wstępnie skonfigurowałem. Denerwowały mnie wentylatorki. Według tego co znalazłem w sieci, ten procesor i chipset powinny sobie radzić i z pasywnym chłodzeniem, ale niestety w tej „hermetycznej” obudowie i z tymi marnymi radiatorkami to się trochę grzeje i nie odważyłem się wiatraczków całkiem wyłączyć. Za to skonfigurowałem fancontrole z pakietu lm_sensors, żeby je wyłączał lub spowalniał, gdy pełna prędkość nie jest potrzebna. Przydała się też lutownica, bo płyta główna nie chciała sterować wiatraczkiem z obudowy, podłączyłem go więc do zasilania chłodzenia procesora. Teraz oba są sterowane razem. A kiedyś może zamontuje tam po prostu większe radiatory i zostawię tylko jeden wentylator na wszelki wypadek (normalnie wyłączony, mam nadzieję).

W końcu przyszedł tuner. Mogłem dokończyć konfigurację MythTV, niestety bez sygnału antenowego nie bardzo mogłem przetestować, a robiłem to wszystko przecież w biurze, w wolnych chwilach w pracy, bo nie chciałem wielkiego eksperymentu w domu zrobić. Do domu miałem zamiar przynieść gotowe rozwiązanie.

Gotowy zestaw przyniosłem do domu w czwartek i podłączyłem, gdy Ika była w szkole muzycznej. Niestety, nie działało jak należy. Obraz strasznie rwał, dźwięk przerywał i raczej oglądać TV się przez to nie dało, ale włączyłem nagrywanie House’a. Okazało się, że nagrało się prawidłowo, tylko z wyświetlaniem były problemy.

Dzisiaj parę godzin z tym walczyłem… i udało się. Najwyraźniej wbudowany programowy dekoder MPEG się nie wyrabiał (dziwne, bo mplayer nie ma żadnych problemów, nawet z „-vo x11” radził sobie nieco lepiej niż MythTV). Na szczęście ta płyta główna ma wbudowany dekoder MPEG2, który nawet zadziałał. Ze sprzętowym dekodowaniem działa. Są jeszcze pewne problemy z jakością obrazu, ale to głównie z powodu zamieszania z kabelkami, które tu teraz mamy, to powinno się dać jakoś poprawić.

No więc miałem przez dwa tygodnie rozrywkę i chyba nawet udało mi się nagrywarkę TV zbudować. Czy jest nam potrzebna? Czy będziemy jej używać? Prawdę mówiąc nie wiem, ale chyba po prostu czasem muszę coś „zmajsterkować” :-)

Nowa zabawka: Samsung SCX-4300

W poprzednim biurze miałem drukarkę i skaner. Tyle, że drukarka tylko stała i kurzyła się w kącie właściwie odkąd się tam wprowadziłem – tusz był zaschnięty, a kupowanie nowego sensu większego nie miało: kosztowałby tyle co nowa drukarka i zasechłby parę tygodni po pierwszym wydruku – rzadko potrzebuję coś wydrukować. Poza tym to był właściwie antyk, miała ponad dziesięć lat i problemy chociażby z pobieraniem kartek.

Ze skanerem sprawa wyglądała nieco lepiej. Też antyk (w podobnym wieku), na SCSI z nietypowym złączem (przy pomocy lutownicy, starej taśmy SCSI, odpowiedniej wtyczki i lutownicy udało mi się to podłączyć do współczesnego kontrolera), ale działa. No może nie za pierwszym razem po uruchomieniu, ale jak się go wyłączyło i włączyło to nawet dało się coś poprawnie zeskanować.

Nie chciało mi się tego złomu zabierać ze sobą przy przeprowadzce. Zadzwoniłem więc do firmy utylizacyjnej, żeby oni to zabrali. Dorzuciłem przy okazji z trzy stare karty muzyczne, dwie graficzne, parę płyt głównych, z trzy karty TokenRing i co tam jeszcze mi się w biurze czy domu walało.

Jak już wspominałem nie potrzebuję dużo drukować. Skanować też nie. Ale dość już miałem proszenia się za każdym razem gdy jednak trzeba było coś wydrukować, albo biegania z dokumentami do punktu Xero (a raczej do pani Reni z biura inżynierskiego na tym samym piętrze), gdy mi jakaś kopia była potrzebna. Postanowiłem więc sobie kupić urządzenie wielofunkcyjne.

Urządzenia wielofunkcyjne można teraz kupić za mniej niż 300zł. Ale to atramentówki. Teoretycznie opłacalne przy małym przerobie. Ale nie tak małym, jak u mnie. Nie chciałem ryzykować, że mi tusz zaschnie, więc wolałem urządzenie z drukarką laserową. Na kolorze mi tak nie zależy.

Planowałem pójść do centrum handlowego, do sklepu Vobis i tam coś kupić. Taki sprzęt wolę kupić w normalnym pobliskim sklepie. Na stronach Vobis.pl wypatrzyłem najtańsze tam laserowe urządzenie wielofunkcyjne: Samsung SCX-4300. Może nie jest to marka znana z drukarek, ale recenzje w sieci nie zniechęcały, a do tego producent przyznawał się do wsparcia dla Linuksa. W przypadku innych tanich drukarek nie tak łatwo o taki luksus, a bezpośredniej obsłudze PostScript, PCL, czy PDF w tanim urządzeniu można raczej zapomnieć. Postanowiłem, że to właśnie sobie kupię.

Jakoś jednak do sklepu Vobisa było mi nie po drodze. Poza tym, musiałbym to sobie przywieźć do biura… może by więc kupić przez Internet? Vobis.pl okazał się bardzo przyjemnym sklepem internetowym, a ceny nie były tam gorsze niż na Allegro. Zamówiłem więc we wtorek wieczorem drukarkę, papier i kabelek wprost do biura.

Jeszcze w środę, zanim paczka przyszła, zainstalowałem sobie Unified Linux Driver ze strony producenta – niecierpliwy jestem. Instalacja przeszła gładko, urządzenia oczywiście oprogramowanie nie wykryło, ale pozwoliło skonfigurować ręcznie. Nie sądziłem, że to może być takie proste, spodziewałem się problemów później.

Wczoraj kurier przyniósł pudło. Urządzenie okazało się zaskakująco duże, ale całkiem ładne. Pozwoliłem drukarce spokojnie się ogrzać do temperatury pokojowej i dopiero wtedy podłączyłem. Najpierw próba kopiowania – bez użycia komputera. I bez żadnych problemów. Ha, mam wreszcie własną kserokopiarkę! :-)

Potem z komputera. Włączam ten Configurator od Samsunga, wybieram drukarkę, klikam drukuj stronę testową… i drukuje. Bez żadnej dodatkowej konfiguracji. Standardowa strona testowa CUPS. Sprawdziłem jeszcze w OpenOffice – widzi drukarkę, drukuje. Zero problemów.

Pozostał skaner. Wybieram zakładkę skanery w Configuratorze. Nic tam nie ma. Aaa… bo jeszcze się coś drukuję. Po chwili robię to samo i jest skaner. Klikam Properties… i pojawia się GUI do skanowania. Działa, jedyny drobny problem, to że na podglądzie skanu czarno-białej kartki widać jakieś kolory (trochę mnie to zaskoczyło, aż sprawdziłem, czy strona testowa, którą próbowałem zeskanować, nie wydrukowała się w kolorze), ale to tylko podgląd. Skan wyszedł poprawni. Sprawdziłem też skanowanie z poziomu GIMPa z XSane – też żadnych problemów.

Jedyne z czym, moim zdaniem, trochę przedobrzyli, to zamiana standardowego CUPSowego /usr/bin/lpr na symlink do ich interaktywnego odpowiednika. Rozumiem, że to miało poprawić user experience w przypadku programów nie używających cups, tylko wołających lpr, ale sprawiało, że standardowe nieinteraktywne polecenie wymagało uwagi użytkownika i, co więcej, działającej sesji X11. Proste rm /usr/bin/lpr; mv /usr/bin/lpr{.orig,} rozwiązało sprawę.

Zajrzałem na płytkę dostarczoną przez producenta: była tam instrukcja w wielu językach i ten UnifiedLinuxDriver. Windowsy i Maki najwyraźniej biorą sterowniki z innego źródła, pewnie z samej drukarki. Obsługa drukarki pod Linuksem jest także opisana w instrukcji.

Ostatni test zleciła mi żona: dała mi linka do kolorowanek z Garfieldem dla naszej córki. Ponad 100 plików GIF. Oczywiście uparłem, się, że załatwię to jakimś skryptem z ImageMagick, na co straciłem sporo czasu. Ale wydrukowałem, na 27 stronach, cztery obrazki na stronę.

Podsumowując: na razie jestem bardzo zadowolony z zakupu, a wsparcie dla Linuksa mnie miło zaskoczyło. Z żadną inną drukarką, czy skanerem jakie miałem okazje konfigurować w Linuksie, nie było mi tak łatwo. Oczywiście, mogłem mieć trochę szczęścia z tym, co aktualnie miałem zainstalowane, ale producent najwyraźniej też się postarał.

CJC i PyXMPP 1.0.1

Ostatnie wydanie CJC i PyXMPP było ponad trzy lata temu – w grudniu 2005 roku. Po tamtym wydaniu zacząłem poważne zmiany w API… i nigdy ich nie skończyłem, a niedokończonego dzieła wydawać nie chciałem. Potem przyszły kłopoty ze zdrowiem, pośrednio wynikłe też z mojego zaangażowania w Open Source (czyt. siedzenia całymi dniami przed kompem, świata nie widząc) i postanowiłem unikać angażowania się w kodowanie. Tak więc, planowane zmiany nigdy nie miały być dokończone.

W międzyczasie jednak w starym kodzie znajdowane były błędy, od czasu do czasu jakiś błąd poprawiłem, czasem ktoś podesłał patcha, to wrzucałem do SVN. Pojawiały się nowe wersje Pythona, czy M2Crypto, to kod dostosowywałem odpowiednio (CJC używam na co dzień, moja żona też, więc to musi działać). Właściwie, jak ktoś jeszcze używał PyXMPP albo CJC, to któryś z ostatnich snapshotów.

Ostatnio zastanawiałem się też, czy nie spróbować do CJC wreszcie dodać obsługi UTF-8. Wcześniej tego odmawiałem, bo Pythonowy moduł curses w ogóle nie ma obsługi Unicode, tylko start 8-bitowe API. I nic nie wskazuje na to, że to ktoś poprawi, ale uż jakiś czas temu jeden z użytkowników udowadniał mi, że to się jednak da zrobić, jeśli tylko moduł curses jest zlinkowany z biblioteką „libncursesw”. W PLD długo tak nie było, ale w Th już jest. To czemu by nie spróbować?

Wczoraj więc spróbowałem. Wyświetlanie UTF-8 działało bez żadnych zmian w kodzie, ale żeby wczytywać znaki Unicode z klawiatury musiałem dodać brzydkiego hacka. I w ogóle trochę obsługi klawiatury przerobić. Udało się. A skoro wreszcie się pojawiła funkcjonalność tak wyczekiwana przez użytkowników, to czemu by nie wydać nowej wersji? Resztę dnia spędziłem
przygotowując paczki z PyXMPP 1.0.1 (w tym jeszcze przed wydaniem poprawiłem jednego paskudnego babola) i CJC 1.0.1. Dzisiaj wysłałem informacje o wydaniach na listy mailowe dotyczące tych produktów. No to chyba udało mi się coś wydać. :-)

Po następne wersje zapraszam za trzy lata. ;-)