[Comunicato stampa] Codemotion 2012

La seconda edizione del Codemotion, l’evento aperto a tutti i linguaggi e tecnologie, si terrà il 23 e 24 marzo 2012 a Roma. Le novità principali del Codemotion 2012 consisteranno in: due giorni di interventi tecnici e doppio evento in contemporanea a Roma e Madrid.

Il prolungamento, da uno a due giorni, sarà l’occasione per distribuire le attività del Codemotion in un arco temporale più vasto. I partecipanti avranno così la possibilità di poter seguire i talk da loro desiderati con minore probabilità di incorrere nel rischio di sovrapposizioni di interventi.

La contemporaneità fra Roma e Madrid permetterà di costruire un evento che unirà le due capitali attraverso la passione per la tecnologia e per la programmazione. Codemotion Roma e Codemotion Madrid sono organizzati con lo stesso spirito e format, i protagonisti saranno i contenuti tecnici e le Codemotion People.

Il Codemotion si terrà a Roma il 23 e 24 marzo 2012.
L’ingresso all’evento è come sempre gratuito.
Per ogni informazione: http://www.codemotion.it

Soluzione problema Wi-Fi Mac OS X Lion (10.7)

Circa un mese e mezzo fa (il 20 luglio per l’esattezza) Apple rendeva disponibile ufficialmente su App Store l’ultima versione del suo celebre ed amato sistema operativo.

Approssimativamente un mese dopo non resistendo alla tentazione di provarlo, consapevole dei potenziali problemi ai quali sarei andato incontro, decidevo di acquistare l’aggiornamento e provarlo sul mio iMac (un 21.5 pollici, mid-2010). Proponendomi di testarlo per bene prima di aggiornare il MacBook Pro che utilizzo esclusivamente per lavoro.

Soddisfatto dell’acquisto per la migliorata usabilità generale del sistema e per la perfetta compatibilità con tutte le applicazioni che utilizzo più di frequente, inizio qualche giorno dopo a notare alcuni problemi legati alla connessione di rete wireless che inizialmente avevo sottovalutato pensando fossero legati ad un momentaneo malfunzionamento dell’access point (che avevo provveduto a riavviare).

Insospettito (ed innervosito) iniziavo così ad approfondire la questione facendo alcune ricerche su Google trovando su vari gruppi di discussione, tra i quali quello del forum ufficiale Apple, una notevole quantità di messaggi di utenti che lamentavano lo stesso mio problema.

Nemmeno l’aggiornamento alla versione 10.7.1, ormai disponibile da diverse settimane, riuscì a risolvere il problema.

Dopo aver provato tutti i possibili workaround trovati in rete continuavo a non riuscire a risolvere il problema il quale sembrava anzi peggiorare in quanto adesso il sistema andava, quasi regolarmente almeno un paio di volte al giorno, in kernel panic!

Ma non tutti i mali vengono per nuocere. Lo stacktrace dell’errore mi aiutava infatti a restringere la cerchia dei “potenziali colpevoli” del malfunzionamento:

Kernel Extensions in backtrace:
com.apple.driver.AirPort.Atheros40(500.55.5)[01000ACB-C064-3F42-820F-BDE200826725]@0xffffff7f80e64000->0xffffff7f80fa3fff
dependency: com.apple.iokit.IOPCIFamily(2.6.5)[95ABB490-3AB5-3D5E-9C21-67089A9AE6A1]@0xffffff7f80821000
dependency: com.apple.iokit.IO80211Family(400.40)[78A58272-2170-3068-9C63-88301C99C406]@0xffffff7f80e2c000
dependency: com.apple.iokit.IONetworkingFamily(2.0)[59A00F6B-3710-3E07-9921-70C45782FF8C]@0xffffff7f8090e000

Decido tuttavia di tagliare la testa al toro procedendo con un backup dei dati ed una reinstallazione completa del nuovo sistema operativo su una nuova partizione vuota. Niente da fare. Stessi malfunzionamenti (continue disconnessioni dalla rete wireless) e frequenti kernel panic.

Tentato di procedere al downgrade a Snow Leopard decido così di fare l’ultimo tentativo sostituendo una kext (ossia un modulo del kernel Darwin), così come suggerito da un utente su questo thread del forum di supporto Apple.

Procedo così nella creazione di un archivio della directory /System/Library/Extensions/IO80211Family.kext dalla versione Snow Leopard installata sul mio MacBook Pro e nella successiva installazione dello stesso su Lion.

Una aggiustatina ai permessi:

$ sudo chmod -R 755 /System/Library/Extensions/IO80211Family.kext
$ sudo chown -R root:wheel /System/Library/Extensions/IO80211Family.kext

e via con il reboot incrociando le dita.

Bingo! Problema risolto.

Attualmente sto utilizzando la versione 3.1.2 della kext “incriminata” al posto della 4.0.4 fornita “di serie” su Lion. In attesa di una soluzione definitiva che mi aspetto arrivi con uno dei prossimi aggiornamenti software ufficiali.

Di certo da mamma Apple mi sarei aspettato dei test più accurati prima del rilascio della versione “stabile” della nuova versione di OS X.

Linux Active Directory domain join HOWTO

Una problematica che qualsiasi sistemista si trova a dover affrontare, prima o poi durante la sua carriera, riguarda l’integrazione di macchine Linux in una rete basata su domini Windows.

Circa un anno fa mi proposi di fare ordine all’interno della rete dell’azienda presso la quale lavoro ed iniziai a pianificare l’implementazione di un meccanismo di SSO (Single Sign On) che avrebbe evitato il classico caos causato dal proliferare di credenziali (username/password) di accesso ai vari server ed ai relativi servizi offerti dagli stessi.

L’azienda disponeva già da parecchi anni di un robusto e collaudato controller di dominio Windows basato su Active Directory utilizzato, fino ad allora, quasi esclusivamente per l’autenticazione degli utenti della rete sulle workstation (Windows pure loro) di lavoro. Nessuno si era mai posto concretamente il problema dell’integrazione di macchine Linux all’interno del dominio fino a quando il numero delle stesse non era diventato “rilevante”.

Mi sembrò fin da subito abbastanza scontato mantenere il domain controller Windows continuandolo ad utilizzare come sistema di identity management. Iniziai così ad approfondire gli aspetti tecnici riguardanti l’integrazione del sistema di autenticazione utilizzato nei sistemi Active Directory (ossia il protocollo Kerberos) con il meccanismo di autenticazione “modulare” (ossia pam – pluggable authentication module) dei sistemi GNU/Linux.

Il sistema operativo del pinguino dispone infatti di un meccanismo, chiamato pam per l’appunto, che consente al software di utilizzare delle API di alto livello per la gestione dell’autenticazione e delle autorizzazioni in modo indipendente da come queste ultime sono realizzate negli strati sottostanti.

Qui di seguito la procedura per installare sulla nostra Linux-box tutti i moduli necessari:

  • Per prima cosa dovremo installare il pacchetto “kerberos client” utilizzando il gestore software della nostra distribuzione. Fatto ciò andremo ad inserire i parametri di configurazione corretti nel file (che solitamente si trova dentro la directory /etc) krb5.conf.

    Esempio:

    [logging]
    default = FILE:/var/log/krb5libs.log
    kdc = FILE:/var/log/krb5kdc.log
    admin_server = FILE:/var/log/kadmind.log
    [libdefaults]
    default_realm = YOURDOMAIN.NET
    dns_lookup_realm = false
    dns_lookup_kdc = false
    ticket_lifetime = 24h
    forwardable = yes
    [realms]
    YOURDOMAIN = {
    kdc = kdc.yourdomain.net
    admin_server = ad.yourdomain.net
    default_domain = YOURDOMAIN.NET
    }
    [domain_realm]
    .yourdomain.net = YOURDOMAIN.NET
    yourdomain.net = YOURDOMAIN.NET
    [appdefaults]
    pam = {
    debug = false
    ticket_lifetime = 36000
    renew_lifetime = 36000
    forwardable = true
    krb4_convert = false
    }

    Fatto ciò saremo in grado di testare il corretto funzionamento del client lanciando il comando:

    $ kinit User@YOURDOMAIN.NET

  • Il secondo passo è quello di installare e configurare winbind, modulo samba che consente al sistema di utilizzare utenti e gruppi definiti sul server di dominio facendoli apparire come utenti locali.

    Avremo la necessità di creare un file smb.conf minimale tipo:

    [global]
    workgroup = YOURDOMAIN
    realm = YOURDOMAIN.NET
    security = ADS
    password server = ad.yourdomain.net
    log file = /var/log/samba/log.%m
    max log size = 50
    socket options = TCP_NODELAY SO_RCVBUF=8192 SO_SNDBUF=8192
    idmap uid = 16777216-33554431
    idmap gid = 16777216-33554431
    template shell = /bin/bash
    winbind use default domain = Yes
    winbind offline logon = Yes

    Completato questo passo, se tutto è stato configurato correttamente, saremo in grado di effettuare il join della macchina al dominio lanciando il comando:

    $ net ads join -­‐U Administrator -­‐S ad.yourdomain.net

  • L’ultimo step consiste nel configurare il sottosistema di autenticazione, pam, per poter utilizzare le nostre credenziali di dominio con i vari software (esempio ssh).

    Andremo quindi a modificare il file /etc/nsswitch.conf modificando le righe:

    passwd: files winbind
    shadow: files winbind
    group: files winbind

    ed il file /etc/pam.d/system-­auth inserendo le entry relative al modulo pam_winbind:

    auth required pam_env.so
    auth sufficient pam_unix.so nullok try_first_pass
    auth requisite pam_succeed_if.so uid >= 500 quiet
    auth sufficient pam_winbind.so cached_login use_first_pass
    auth required pam_deny.so
    account required pam_unix.so
    account sufficient pam_succeed_if.so uid < 500 quiet
    account sufficient pam_winbind.so
    account required pam_permit.so
    password requisite pam_cracklib.so try_first_pass retry=3
    password sufficient pam_unix.so md5 shadow nullok
    try_first_pass use_authtok
    password sufficient pam_winbind.so use_authtok
    password required pam_deny.so
    session optional pam_keyinit.so revoke
    session required pam_limits.so
    session [success=1 default=ignore] pam_succeed_if.so service
    in crond quiet use_uid
    session required pam_unix.so
    session required pam_mkhomedir.so
    session optional pam_krb5.so

Adesso basterà riavviare il servizio winbind ed accedere al sistema con le credenziali di dominio.

Apache Killer: analisi e contromisure

In rete oggi non si fa altro che parlare dell’exploit di Apache che sta facendo tremare il mondo. Un piccolo script Perl che sfruttando una vulnerabilità nota già nel 2007 consente di mettere in difficoltà le macchine che ospitano il celebre web server opensource.

Vediamo di capire meglio di cosa si tratta e, soprattutto, di come mettere al sicuro le proprie macchine adottando alcune semplici contromisure.

L’advisory ufficiale recita:

“A denial of service vulnerability has been found in the way the multiple overlapping ranges are handled by the Apache HTTPD server”

La causa della vulnerabilità sarebbe la cattiva implementazione del codice responsabile di ottenere il valore dell’leaderRange“; header che consente ad un client di richiedere una o più “porzioni” di file senza la necessità di doverlo scaricare per intero. Funzionalità, ad esempio, molto utilizzata dagli eReader e dai player multimediali (pensate alla visualizzazione di documenti PDF di grosse dimensioni od allo streaming di files audio/video).

La falla è sfruttata dallo script killapache.pl, facilmente reperibile in rete, creando una serie di richieste contenenti un campo leader Range particolarmente “corposo”:

...
$p = "";
for ($k=0;$k<1300;$k++) {
	$p .= ",5-$k";
}
...
$p = "HEAD / HTTP/1.1\r\nHost: $ARGV[0]\r\nRange:bytes=0-$p\r\nAccept-Encoding: gzip\r\nConnection: close\r\n\r\n";
print $sock $p;
...

in grado di saturare in pochissimo tempo le risorse (memoria e CPU) del server sottoposto ad attacco.

Per mitigare gli effetti dell’attacco, in attesa di una patch ufficiale che dovrebbe essere rilasciata entro le prossime 48 ore, allo stato attuale è possibile utilizzare uno dei seguenti workaround:

  • Disabilitare completamente l’header Range attraverso l’utilizzo di mod_headers:

    RequestHeader unset Range
  • Utilizzare SetEnvIf per identificare ed ignorare solo le richieste contenenti valori “anomali”:

    SetEnvIf Range (,.*?){5,} bad-range=1
    RequestHeader unset Range env=bad-range

    (solo Apache 2.0 e 2.2)
  • Utilizzare mod_rewrite per ottenere il medesimo risultato di cui sopra (applicabile anche ad Apache 1.3):

    RewriteEngine on
    RewriteCond %{HTTP:range} !(^bytes=[^,]+(,[^,]+){0,4}$|^$)
    RewriteRule .* – [F]
  • Limitare la dimensione di tutti gli headers:

    LimitRequestFieldSize 200

    soluzione che potrebbe però compromettere il corretto funzionamento di alcune applicazioni (es. cookies)

Allo stato attuale è possibile utilizzare anche il modulo Range count o una patch non ufficiale.

Come per tutte le “patologie” non esiste quasi mai un farmaco adatto a tutte le situazioni e privo di effetti collaterali. La soluzione migliore, in attesa di una patch ufficiale e risolutiva del problema, va analizzata caso per caso.

Per quanto mi riguarda, sul server che ospita questo blog, ho deciso di disabilitare l’header Range.

P.S.
Un doveroso ringraziamento all’amico, nonché validissimo professionista, Marco Ortisi per avermi messo a conoscenza del problema prima che venisse diffuso dai maggiori siti web di settore.

Buon compleanno Linux!

Vent’anni fa, il 25 agosto, Linus Torvalds annunciava così sul newsgroup comp.os.minix la nascita del sistema operativo del pinguino:

From: Linus Benedict Torvalds (torvalds@klaava.Helsinki.FI)
Subject: What would you like to see most in minix?
Newsgroups: comp.os.minix
Date: 1991-08-25 23:12:08 PST
Hello everybody out there using minix -
I’m doing a (free) operating system (just a hobby, won’t be big and professional like gnu) for 386 (486) AT clones. This has been brewing
since april, and is starting to get ready. I’d like any feedback on things people like/dislike in minix, as my OS resembles it somewhat (same physical layout of the file-system (due to practical reasons) among other things).
I’ve currently ported bash(1.08) and gcc(1.40), and things seem to work.
This implies that I’ll get something practical within a few months, and I’d like to know what features most people would want. Any suggestions are welcome, but I won’t promise I’ll implement them :-)
Linus (torvalds@kruuna.helsinki.fi)
PS. Yes – it’s free of any minix code, and it has a multi-threaded fs.
It is NOT protable (uses 386 task switching etc), and it probably never
will support anything other than AT-harddisks, as that’s all I have :-( .

Firma digitale CAdES in Java

Chi per vari motivi abbia avuto a che fare con l’integrazione delle funzionalità di firma digitale all’interno delle proprie applicazioni, si sarà sicuramente scontrato con qualche piccola difficoltà dovuta all’aggiornamento del formato di memorizzazione dei files imposto dalle recenti modifiche normative.

Il 17 agosto 2010 veniva infatti pubblicata in Gazzetta Ufficiale la Determinazione Commissariale n.69/2010 DigitaPA che fissava il 30/06/2011 quale data ultima per l’adeguamento dei formati di firma alle specifiche CAdES.

CMS Advanced Electronic Signatures è un set di estensioni della specifica Cryptographic Message Syntax per la realizzazione di firme digitali avanzate particolarmente sicure e, soprattutto, conformi con la Direttiva Europea 1999/93/EC.

Di fatto il formato è molto simile al “vecchio” PKCS-7 e richiede, per lo meno al fine di soddisfare i requisiti minimi definiti dalle specifiche CAdES Basic Electronic Signature (CAdES-BES), solo l’inserimento di un attributo firmato all’interno del “contenitore” multipart.

Qui di seguito uno snippet di codice Java di esempio che utilizza le librerie Bouncy Castle per la creazione del file p7m CAdES:

/**
* Simula il file di configurazione
* serve principalmente per settare il path della lilbreria pkcs11
*/
String pkcs11config ="name = SmartCard\n library = /path/to/libbit4opki.dylib";
byte[] pkcs11configBytes = pkcs11config.getBytes();
ByteArrayInputStream configStream =new ByteArrayInputStream(pkcs11configBytes);

// Inizializza il security provider pkcs11
Provider pkcs11Provider =new sun.security.pkcs11.SunPKCS11(configStream);
Security.addProvider(pkcs11Provider);
Security.addProvider(new BouncyCastleProvider());

/**
*  Setta la classe che implementa l'handler per l'inserimento
*  del PIN per l'accesso ai dati contenuti nella smartcard
*/
Password ps = new Password(null, true);

/**
* Inizializza il keystore per l'accesso ai certificati contenuti
* nella smartcard
*/
KeyStore.Builder builder = KeyStore.Builder.newInstance("PKCS11", pkcs11Provider, new KeyStore.CallbackHandlerProtection(ps));
KeyStore keyStore = builder.getKeyStore();

/**
* Ottiene la lista degli alias dei certificati memorizzati
* sulla smartcard
*/
Enumeration<String> aliases = keyStore.aliases();

/**
* Cicla gli alias e stampa a video il toString()
* di ogni certificato
*/
while (aliases.hasMoreElements())
 {
 String alias = aliases.nextElement();
 System.out.println("alias: "+alias+"\n----------");
 X509Certificate certTmp=(X509Certificate) keyStore.getCertificate(alias);
 System.out.println("DN: "+certTmp.getSubjectDN().toString()+"\n");
 }

String fileDaFirmarePath = "/path/to/file.txt";
String fileFirmatoPath = fileDaFirmarePath+".p7m";

/**
* Ottengo il certificato e la chiave privata dal keystore (l'inserimento
* del PIN è sempre a carico dell'handler)
*/
Certificate cert = keyStore.getCertificate("DS0");
PrivateKey pKey = (PrivateKey) keyStore.getKey("DS0", null);

/**
* Inizializzo il generatore impostando l'algoritmo di
* hashing desiderato ed aggiungendo un firmatario
*/
CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
ContentSigner sigGen = new JcaContentSignerBuilder("SHA256withRSA").setProvider(pkcs11Provider.getName()).build(pKey);

/**
* -- CADES --
*/
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(cert.getEncoded());
byte[] certHash = md.digest();
ESSCertIDv2 essCert1 = new ESSCertIDv2(new AlgorithmIdentifier("2.16.840.1.101.3.4.2.1"),certHash);
ESSCertIDv2[] essCert1Arr = {essCert1};
SigningCertificateV2 scv2 = new SigningCertificateV2(essCert1Arr);
Attribute certHAttribute = new Attribute(PKCSObjectIdentifiers.id_aa_signingCertificateV2,new DERSet(scv2));
ASN1EncodableVector v = new ASN1EncodableVector();
v.add(certHAttribute);
AttributeTable at = new AttributeTable(v);
/**
* -- END CADES --
*/

CMSAttributeTableGenerator attrGen = new DefaultSignedAttributeTableGenerator(at);
SignerInfoGeneratorBuilder genBuild = new SignerInfoGeneratorBuilder(new BcDigestCalculatorProvider());
genBuild.setSignedAttributeGenerator(attrGen);
SignerInfoGenerator sifGen = genBuild.build(sigGen, new X509CertificateHolder(cert.getEncoded()));

gen.addSignerInfoGenerator(sifGen);

/**
* Popolo la "catena di certificazione" (certificate chain)
*/
ArrayList certList = new ArrayList();
certList.add(cert);

X509CollectionStoreParameters x509CollectionStoreParameters = new X509CollectionStoreParameters(certList);
JcaCertStore jcaCertStore = new JcaCertStore(certList);
gen.addCertificates(jcaCertStore);

/**
*  Genera il file p7m e lo salva nel path specificato. Inserendo "false" come secondo parametro di generate() si
*  otterrebbe invece un file p7s, ovvero la sola firma "detached".
*/
CMSProcessableFile content = new CMSProcessableFile(new File(fileDaFirmarePath));
CMSSignedData data = gen.generate(content, true);
byte[] res = data.getEncoded();
FileOutputStream fos = new FileOutputStream(new File(fileFirmatoPath));
fos.write(res);
fos.close();

la classe Password serve a gestire l’inserimento del PIN della smartcard. Deve implementare javax.security.auth.callback.CallbackHandler e quindi il metodo public void handle(Callback[] callbacks) che nel più semplice dei casi si limiterà a fornire il PIN al provider:

public void handle(Callback[] callbacks) {
 for (int i = 0; i < callbacks.length; i++) {
  if (callbacks[i] instanceof PasswordCallback) {
  PasswordCallback pass = (PasswordCallback) callbacks[i];
  pass.setPassword("12345678".toCharArray());
  } else {
    System.out.println("+" + callbacks[i].getClass().getName());
    }
  }
}

Altre letture consigliate: