Autenticazione web con Kerberos

Una delle cose sorprendenti dell’integrazione realizzata da Microsoft è relativa all’autenticazione degli utenti che hanno fatto log-on al dominio Active Directory sugli applicativi Web. Attraverso Internet Information Server (IIS) e il Web browser Microsoft Internet Explorer, l’utente viene riconosciuto trasparentemente, realizzando così un vero e proprio Single Sign-On. La tecnologia usata per effettuare un login dell’utente attraverso il Web è SPNEGO, già descritto nel paragrafo SPNEGO e l’autenticazione Web. Grazie allo sforzo della comunità OpenSource, è possibile utilizzare SPENGO anche su Unix, sia come client che come server Web. In questo capitolo spiegheremo come sia possibile realizzare con Apache l’autenticazione attraverso SPNEGO e Mozilla come client di autenticazione, oltre a vedere più da vicino l’utilizzo di Microsoft Internet Explorer.

Configurazione di Apache per Unix

La scelta del Web server da utilizzare per l’autenticazione è ricaduta sul popolarissmo Apache (http://httpd.apache.org/), in quanto è il Web server più usato su Internet. Sebbene non si tratti di un requisito fondamentale, si è scelto di installare anche PHP, uno scripting language molto diffuso, che permetterà in seguito di poter presentare un esempio di programma. Si assume che il Web server Apache sia stato correttamente installato e configurato e che risponda correttamente ad un browser. Si assume inoltre che il development kit (gli include file e il tool apxs), necessario per compilare i moduli aggiuntivi, sia installato (per Debian è il pacchetto apache-dev).

Per effettuare l’autenticazione Kerberos/SPNEGO si è utilizzato il modulo mod_auth_kerb scaricabile dal sito Internet http://modauthkerb.sourceforge.net/. Una volta scompattato, si è proceduto alla compilazione del sorgente con il seguente comando:

# ./configure --with-krb5=/usr --with-apache=/usr
# make
# make install

Dove –with-krb5 rappresenta la directory base contenente gli include file di Kerberos, mentre –with-apache la directory base con gli include file di Apache e il tool apxs. Successivamente il make compilerà il modulo e make install lo installerà nella directory dei moduli.

A questo punto è necessario creare una nuova directory che dovrà essere protetta dall’accesso non autorizzato ed inserirvi una pagina di esempio. A partire dalla directory dei documenti di Apache (DocumentRoot), nel nostro caso /var/www/, si è creata un’ulteriore directory chiamata protected. In questa directory è stato creato un file index.php contenente la seguente linea:

<? phpinfo() ?>

Questa istruzione fa vedere tutte le informazioni relative al PHP e al Web server su cui sta girando: ci servirà come pagina di test. Successivamente, è necessario configurare il Web server per caricare il modulo compilato e configurare la protezione sulla directory /protected, aggiungendo al file di configurazione httpd.conf le seguenti linee:

# Load Kerberos module
LoadModule auth_kerb_module /usr/lib/apache/1.3/mod_auth_kerb.so

# Protected directory
<Directory /var/www/protected>
    Options Indexes SymLinksIfOwnerMatch

    AuthType Kerberos
    AuthName "AZIENDA.IT Login"
    Krb5Keytab /etc/apache/krb5.keytab
    KrbAuthRealms AZIENDA.IT
    require valid-user
</Directory>

La prima riga fa sì che il modulo di autenticazione venga caricato all’interno di Apache. Successivamente si definisce la directory protetta e si specifica attraverso AuthType il tipo di autenticazione, ovvero Kerberos. È necessario soffermarsi su altre due keyword di questa configurazione: KrbAuthRealms che specifica i realm verso cui si effettuerà l’autenticazione e Krb5Keytab che specifica il file keytab di Kerberos 5 contenente il principal associato al servizio Web. In un Web server il principal deve essere nella forma HTTP/hostname.dominio@REALM e nel nostro caso sarà quindi HTTP/venere.azienda.it@AZIENDA.IT. Prima di fare rileggere la configurazione al server Apache, è necessario pertanto creare tale realm sul server zeus con i seguenti comandi:

# kadmin.local -q “addprinc -randkey HTTP/venere.azienda.it@AZIENDA.IT”
# kadmin.local -q “ktadd -k /tmp/http-venere.key HTTP/venere.azienda.it@AZIENDA.IT”

L’ultimo comando crea un file /tmp/http-venere.key contenente la chiave Kerberos corrispondente al nostro servizio Web: è necessario trasferire in modo sicuro (ad esempio tramite ssh) la chiave da zeus a venere e copiare la stessa sul file /etc/apache/krb5.keytab specificato nel parametro KrbAuthRealms. A questo punto è possibile riavviare il server Apache con il comando apachectl restart.

A titolo di esempio, apriremo un browser qualsiasi (non ancora modificato) e inseriremo l’URL http://venere.azienda.it/protected/. Il server ci risponderà con un codice di errore 401 Authorization Required: abbiamo verificato che il server richiede un’autenticazione. Ma come fare adesso ad accedere lecitamente?

Accedere con Mozilla per Linux e MacOS X

Mozilla è uno dei Web browser più diffusi su piattaforma Unix, ma anche su piattaforma Windows, che permette di estendere le proprie funzionalità attraverso dei plugin. Precedentemente alla versione 1.7 di Mozilla, era necessario scaricare un Plugin chiamato Negotiateauth, presente all’indirizzo http://negotiateauth.mozdev.org/index.html, il cui scopo era la creazione di un plugin che supportasse il metodo di autenticazione HTTP Negotiate (ovvero SPNEGO), in particolare implementando il meccanismo Kerberos attraverso le GSSAPI. A partire da Mozilla 1.7 il supporto SPNEGO è incorporato per tutte le versioni Unix e MacOS X, mentre è ancora in fase di adattamento alle API SSPI per Windows. Descriveremo la procedura per MacOS X, tenendo presente che la stessa è applicabile anche a Linux: la differenza è sostanzialmente grafica. Mozilla 1.7 è disponibile al sito Internet http://www.mozilla.org; una volta scaricato ed installato, si proceda ad avviarlo normalmente. Quando l’applicazione apre una finestra del browser, inserire come URL about:config e premere invio: questa schermata permette la configurazione di tutti i parametri del browser. È necessario modificare il parametro network.negotiate-auth.trusted-uris in modo da fornire informazioni relative al nostro kerberos principal: di default le informazioni vengono fornite a tutti i siti HTTPS (con SSL). Per il nostro scopo abbiamo modificato il parametro inserendo i valor https://,http:// come nella figura 14.

Una volta effettuata la modifica, ci colleghiamo al Web server all’URL http://venere.azienda.it/protected/: automaticamente verremo riconosciuti nel sistema, non ricevendo più l’errore 401 Authorization Required come avvenuto precedentemente, e avremo la nostra pagina di test con il logo di PHP:

Da notare che nella sezione Apache Environment della pagina di test, la variabile REMOTE_USER è impostata a mrossi@AZIENDA.IT: il modulo di autenticazione ha anche riportato ad Apache qual è il nostro Kerberos Principal. In seguito vedremo in che modo possiamo sfruttare questa variabile.

Accedere con Microsoft Internet Explorer

Sebbene Microsoft Internet Explorer abbia di default il supporto Kerberos, questo va comunque configurato in modo da mandare informazioni relative all’autenticazione: di default, infatti, MSIE non tenta di negoziare l’autenticazione in quanto non riconosce i Web site come “Local Intranet”.

Aprendo Internet Explorer, cliccare su Tools e poi Internet Options. Cliccare sulla sezione Security, selezionare Local Intranet e successivamente Sites:

Assicurarsi che Include all sites that bypass proxy server sia selezionato e premere Advanced:

Nella finestra di dialogo Local Intranet (Advanced), inserire tutti i siti verso i quali si intende effettuare l’autenticazione Kerberos, nel nostro caso *.azienda.it. Selezionare Ok:

Successivamente, nella sezione Security, selezionare Local Intranet e poi il bottone Custom Level. Nella finestra di dialogo Security Settings, cercare la sezione User Authentication e selezionare Automatic logon only in Intranet zone e premere Ok:

Per Internet Explorer 6.0, selezionare Advanced e nella sezione security selezionare la voce Enable integrated Windows Authentication (requires restat). Premere Ok ed eseguire il reboot del computer.

Proviamo anche con Internet Explorer a collegarci al Web server http://venere.azienda.it/protected, in modo da verificare di essere riconosciuti sul sistema e che la variabile REMOTE_USER sia impostata correttamente.

Un esempio di applicazione web

Questo esempio vuole dimostrare come sia possibile identificare e successivamente assegnare il profilo all’utente attraverso Kerberos e LDAP. Così come per una sessione interattiva al sistema, l’autenticazione Kerberos infatti è solo il primo step: è poi necessario ricavare le informazioni relative all’utente, ad esempio a quale gruppo appartiene, ed assegnargli i privilegi corrispondenti. L’esempio che segue, scritto in PHP, è in grado di ricavare il Kerberos Principal dalla variabile di ambiente REMOTE_USER, quindi effettua due query all’LDAP server per ricavarne nome (givenName) e User ID (uid), per poi individuare i gruppi di appartenenza.

<?php
// Sample authentication module for GSSAPI
// By Giuseppe Paternò <gpaterno@gpaterno.com>

$krbuser=getenv("REMOTE_USER");
echo "<h3>Autenticazione utente kerberos<br>$krbuser</h3><br>";
$ds=ldap_connect("ldaps://ldap.azienda.it/"); 

if ($ds) {
   // Bind and search for Given Name and uid
   $r=ldap_bind($ds);  
   $sr_user=ldap_search($ds, "ou=People, dc=azienda,dc=it", "krb5PrincipalName=$krbuser"); 

   if (ldap_count_entries($ds, $sr_user)>1) {
       echo "Error, too many entries with the same user $krbuser<br>";
   }

   $info = ldap_get_entries($ds, $sr_user);
   $givenname = $info[0]["givenname"][0];
   $uid = $info[0]["uid"][0];

   // Print out welcome message
   echo "Ciao $givenname!<br><br>";

   // Search for groups in which we are members
   $sr_group=ldap_search($ds, "ou=Group,dc=azienda,dc=it", "memberUid=$uid");

   if (ldap_count_entries($ds, $sr_group) == 0) {
       echo "L'utente $uid non fa parte di nessun gruppo.<br>";
   } else{
      $group_info = ldap_get_entries($ds, $sr_group);
      echo "Fai parte dei seguenti gruppi:<br>";
      for ($i=0; $i<$group_info["count"]; $i++) {
         echo "Gruppo <b>" . $group_info[$i]["cn"][0] . "</b> (gid=" .  $group_info[$i]["gidnumber"][0] . ")<br>"; 
      }
      echo "<br><br>";
      echo "Qui verrà creata la sessione PHP e ti verranno concesse le autorizzazioni appropriate.<br>";
      // Create session here for further access: profile user and
      // give permissions to data.
   }

   ldap_close($ds);

} else {
   echo "<h4>Unable to connect to LDAP server</h4>";
}
?> 

In un’applicazione reale, bisognerebbe aggiungere più controlli di errore nello script e creare successivamente una sessione in cui all’utente viene assegnato un profilo in base ai gruppi di appartenenza.

Applicazioni Web, Kerberos e l’accesso sicuro ai database

Potremmo spingerci oltre con l’accesso Web: alcuni database, ad esempio PostgresSQL (http://www.postgresql.org/), supportano l’autenticazione Kerberos. Attivando l’opzione KrbSaveCredentials del modulo mod_auth_kerb è possibile salvare il file del ticket dopo che l’utente viene autenticato, in modo da poterlo sfruttare attraverso gli script CGI. Combinando entrambe le funzionalità è possibile collegarsi al database con l’utente che effettua la richiesta Web, applicandone così le policy di accesso ai dati implementati direttamente nel database server. Il vantaggio è che non è più necessario inserire nella configurazione del CGI l’utente e la password con cui accedere al database, con una conseguente maggiore sicurezza.