====== LDAP ====== LDAP definisce un semplice protocollo basato su TCP per la ricerca e l'aggiornamento di informazioni contenute all'interno di un **[[wp>Directory service|directory service]]** (database gerarchico). Un elemento in una //directory LDAP// è referenziato in modo non ambiguo tramite un nome, detto **//distinguished name//** (DN), per esempio "cn=John Doe,ou=people,dc=wikipedia,dc=org". Ogni elemento inoltre comprende una collezione di **attributi**. Ognuno degli attributi dell'elemento è definito come membro di una classe di oggetti, raggruppati in uno schema. Ogni elemento nel database è associato a una o più classi di oggetti, che definiscono se un attributo sia opzionale o meno e che tipo di informazioni questo contenga. I nomi degli attributi solitamente sono scelti per essere facilmente memorizzabili, per esempio "//cn//" per //common name//, o "//mail//" per un indirizzo e-mail. È possibile utilizzare LDAP per numerosi scopi; come database per l'**autenticazione** degli utenti Unix, come **rubrica di contatti** email, ecc. Utilizzando **LDAP per l'autenticazione** è interessante la possibile integrazione con il sottosistema //**[[kerberos|Kerberos]]** versione 5//. Le informazioni relative all'autenticazione (estremamente sensibili dal punto di vista della sicurezza) vengono tolte dal database LDAP e memorizzate nel più sicuro database Kerberos, inoltre si viene ad usufruire del sistema di ticketing di Kerberos, utilie ad esempio per abbinare il montaggio sicuro delle home directory via **NFSv4**. * [[http://www.linuxjournal.com/article/6876|Paranoid Penguin - Authenticate with LDAP]] * [[http://www.linux.com/feature/114074|Linux LDAP authentication]] * [[http://linuxwiki.riverworth.com/index.php/LDAP_Authentication|LDAP Authentication]] * [[http://it.wikipedia.org/wiki/LDAP|LDAP su Wikipedia]] * [[http://aput.net/~jheiss/krbldap/|Replacing NIS with Kerberos and LDAP]] * [[http://www.linux-nis.org/nis-howto/HOWTO/NIS-HOWTO.html|The Linux NIS(YP)/NYS/NIS+ HOWTO]] ===== Attributi LDAP ===== Questo è un elenco degli attributi più comuni utilizzati in una directory LDAP: ^ DN ^ Distinguished_Name | As the word 'distinguished' suggests, this is THE LDAP attribute that uniquely defines an object. Each DN must have a different name and location from all other objects. The other side of the coin is that DN provides a way of selecting any object in the LDAP directory. Once you have select the object, then you can change its attributes. | ^ DC ^ Domain_Content | Example: ''**DC=rigacci, DC=org**''. Note that ''DC=rigacci.org'' would be wrong. | ^ CN ^ Common Name | From RFC2256: This is the X.500 commonName attribute, which contains a name of an object. If the object corresponds to a person, it is typically the person's full name. | ^ OU ^ Organizational_Unit | | ^ O ^ OrganizationName | | ^ C ^ CountryName | | ^ ST ^ StateOrProvinceName | | ^ SN ^ SurName | From RFC2256: This is the X.500 surname attribute, which contains the family name of a person. | ===== Schemi LDAP ===== Ognuno è libero di creare lo schema LDAP (struttura del database) che preferisce, è possibile anche disattivare l'opzione **schemacheck** in modo da poter inserire nel database oggetti non conformi allo schema (altamente sconsigliato). Esistono comunque degli schemi predefiniti molto utilizzati, conviene adottare questi schemi in modo che i vari applicativi trovino il database nella forma in cui se lo aspettano. Ad esempio per memorizzare un archivio di contatti e-mail utilizzabile direttamente da Firefox si può utilizzare lo schema ''**InetOrgPerson**'' (RFC2798), un database per l'autenticazione può essere invece basato sullo schema ''**posixAccount**'' (nisSchema in RFC2307). Il pacchetto //slapd// di Debian arriva con alcuni schemi predefiniti memorizzati in ''**/etc/ldap/schema**''; fare riferimento ad essi anche per sapere quali sono gli attributi obbligatori (''**MUST**'') e quali facoltativi (''**MAY**'') di un oggetto, ad esempio: objectclass ( 1.3.6.1.1.1.2.0 NAME 'posixAccount' SUP top AUXILIARY DESC 'Abstraction of an account with POSIX attributes' MUST ( cn $ uid $ uidNumber $ gidNumber $ homeDirectory ) MAY ( userPassword $ loginShell $ gecos $ description ) ) Fare attenzione che gli schemi possono essere di tipo **STRUCTURAL**, **AUXILIARY** o **ABSTRACT** (si guardi le definizioni dentro i file ''/etc/ldap/schema''): ^ STRUCTURAL | Indicates the attributes that the entry may have and where each entry may occur in the DIT. | ^ AUXILIARY | Indicates the attributes that the entry may have. | ^ ABSTRACT | Indicates a "partial" specification in the object class hierarchy; only structural and auxiliary subclasses may appear as entries in the directory. | Quindi quando si carica un oggetto dentro LDAP bisogna che sia riconducibile ad una ''**objectClass**'' di tipo **STRUCTURAL**. Ad esempio un oggetto non può essere dichiarato come semplice ''**objectClass: posixAccount**'' (che è una classe ''AUXILIARY''); lo si deve completare dichiarando almeno una classe ''STRUCTURAL''. Tra le classi STRUCTURAL predefinite si potrebbe optare per la ''**objectClass: top**'' che è la più generica di tutte, infatti non impone la presenza di alcun attributo salvo un altro objectClass. In alternativa si potrebbe scegliere una ''**objectClass: organizationalUnit**'' adatta a descrivere persone ma anche gruppi, oppure la più specifica ''**objectClass: person**''. ====== Autenticazione LDAP ====== In questo esempio si configura un server ed un client LDAP per effettuare l'autenticazione (login, ecc.). La distribuzione di riferimento è una **Debian Lenny**. In pratica dovremmo configurare il sistema di autenticazione **PAM** (il più usato in ambiente GNU/Linux) in modo tale che sia client di un **server LDAP**. ===== Configurazione del server ===== Dopo aver configurato il server potrebbe essere utile configurare un altro server che replichi lo stesso database, utilizzando **[[ldap_replica|Syncrepl]]**. I pacchetti da installare sul server sono: * **slapd** * **ldap-utils** L'installazione predefinita di Debian Lenny crea un database la cui radice ha un **DN** (Distinguished Name) **dc=rigacci,dc=org** che segue lo standard RFC2247 e un amministratore **cn=admin** con password: dn: dc=rigacci,dc=org dn: cn=admin,dc=rigacci,dc=org Tutto è memorizzato nel database **bdb** (Berkeley DB) contenuto in ''**/var/lib/ldap/**'', quindi nel file di configurazione **''/etc/ldap/slapd.conf''** non viene scritta alcuna password. Queste le parti salienti del file di configurazione: # Database specific directives apply to this databasse until another # 'database' directive occurs database bdb # The base of your directory in database #1 suffix "dc=rigacci,dc=org" # rootdn directive for specifying a superuser on the database. # rootdn "cn=admin,dc=rigacci,dc=org" # rootpw {SSHA}lzz5HF6eP7fRaB3G6L85zhk6zWWP8+Fk # Where the database file are physically stored for database #1 directory "/var/lib/ldap" # Who can change the userPassword. access to attrs=userPassword,shadowLastChange by dn="cn=admin,dc=rigacci,dc=org" write by anonymous auth by self write by * none # The admin dn has full write access, everyone else # can read everything. access to * by dn="cn=admin,dc=rigacci,dc=org" write by * read Attenzione: l'intero database è accessibile in lettura anche agli utenti anonimi. Eventualmente aggiungere una clausola **''by anonymous auth''** anche alla seconda ACL. Le voci **rootdn** e **rootpw** (sopra commentate) possono essere utilizzate per memorizzare le credenziali di amministratore nel file di configurazione invece che nel database. Volendo utilizzare LDAP per l'autenticazione è opportuno attivare la **cifratura TLS**. Bisogna creare un certificato, per semplificare le cose si crea un certificato auto-firmato e quindi faremo a meno di una Certification Authority. Questo è il file di configurazione utilizzato per creare il certificato, nei commenti le istruzioni per utilizzarlo: #---------------------------------------------------------------- # Create an RSA key and a self-signed Certificate with the # following command: # # openssl req -config /etc/ldap/ssl/ldap.rigacci.org.cnf \ # -new -x509 -days 1461 -nodes \ # -keyout /etc/ldap/ssl/ldap.rigacci.org.pem \ # -out /etc/ldap/ssl/ldap.rigacci.org.pem # # The resulting file (unencrypted otherwise Slapd can't start # automatically) will contains the RSA private key, so be sure # to set its mode to 0400. #---------------------------------------------------------------- [ req ] prompt = no default_bits = 2048 distinguished_name = ldap.rigacci.org_distinguished_name [ ldap.rigacci.org_distinguished_name ] countryName = IT stateOrProvinceName = Italy localityName = Firenze organizationName = Rigacci.Org organizationalUnitName = Information and Communications Technology commonName = ldap.rigacci.org emailAddress = webmaster@rigacci.org Il certificato **''/etc/ldap/ssl/ldap.rigacci.org.pem''** deve essere protetto con permessi **0400** e deve appartenere all'utente LDAP (**openldap:openldap** in Debian). Per utilizzarlo si aggiunge a ''/etc/ldap/slapd.conf'' le righe: # Allow the server to picks-up the default cypher. # TLSCipherSuite HIGH:MEDIUM:+SSLv2 TLSCertificateFile /etc/ldap/ssl/ldap.rigacci.org.pem TLSCertificateKeyFile /etc/ldap/ssl/ldap.rigacci.org.pem Conviene limitare il protocollo **ldap** all'indirizzo loopback e attivare pubblicamente solo **ldaps**. Questo in Debian Lenny si ottiene modificando **''/etc/default/slapd''**: SLAPD_SERVICES="ldap://127.0.0.1:389/ ldaps:///" Se il server **ldap** è protetto da **firewall** bisogna aprire la **porta 389** TCP e UDP, il protocollo **ldpas** (LDAP su SSL) invece è sulla **porta 636** TCP e UDP. In generale si dovrà indicare al client di accettare il certificato del server che non è firmato da alcuna Certificate Authority. Dovrebbe essere sufficiente aggiungere a **''/etc/ldap/ldap.conf''** la riga: TLS_REQCERT allow **Attenzione ai nomi!** Se il certificato contiene un **commonName** diverso dal nome del server che useranno i client, bisogna rilassare ancora di più i vincoli del client, impostando: TLS_REQCERT never Invece di usare **ldaps** (LDAP su SSL) Si potrebbe usare **StartTLS**, cioè una **connessione cifrata sulla porta standard 389**. Sarebbe però necessario configurare ulteriori vincoli (vedi //Security Strength Factors//) per evitare che i client usino connessioni non cifrate. Per ottenere un dump del database in formato **LDIF**, da utente root si può usare il comando **slapcat** (che agisce direttamente sul database, senza passare per il demone ''slapd''): slapcat -b "dc=rigacci,dc=org" dn: dc=rigacci,dc=org objectClass: top objectClass: dcObject objectClass: organization ... dn: cn=admin,dc=rigacci,dc=org objectClass: simpleSecurityObject objectClass: organizationalRole cn: admin description: LDAP administrator userPassword:: e2MyeXB0hXhlTk95V1pJMu9J8FU= structuralObjectClass: organizationalRole ... Da utente non privilegiato si può utilizzare il comando **ldapsearch**. Nel primo esempio si utilizzano le credenziali di **admin** fornendo la relativa password (opzioni **-D** e **-W**). Nel secondo esempio si utilizza il protocollo **ldaps**, ma senza utilizzare credenziali privilegiate, pertanto si otterranno solo le informazioni pubbliche. ldapsearch -x -D "cn=admin,dc=rigacci,dc=org" -W -b "dc=rigacci,dc=org" ldapsearch -x -H ldaps://127.0.0.1/ -b "dc=rigacci,dc=org" "(objectclass=*)" Per effettuare il restore di un dump ottenuto con ''slapcat'' si può utilizzare **''slapadd''**. Anch'esso agisce direttamente sul database, quindi è necessario fermare il demone ''slapd'' prima di eseguirlo. Questo è il modo giusto per fare il restore di tutti gli oggetti del database senza alterare gli attributi di sistema come ''createTimestamp'', ecc. ===== Popolare il database ===== :!: **ATTENZIONE:** I nomi utente verranno memorizzati nel ramo LDAP **People**, i gruppi invece nel ramo **Group**. Conviene rispettare questo schema nonostante l'inconsistenza tra plurale (People) e singolare (Group) in quanto **libnss-ldap** usa questo schema per default (forse segue l'RFC2307?). L'installazione Debian ha provveduto a creare solo la radice del database, ora vogliamo creare alcuni rami che conterranno alcuni oggetti. Ad esempio creiamo il ramo **People**, definito dal seguente schema ldif (lo salviamo in un file ''people.rigacci.org.ldif''): dn: ou=People,dc=rigacci,dc=org ou: People objectClass: top objectClass: organizationalUnit objectClass: domainRelatedObject associatedDomain: rigacci.org Lo schema viene aggiunto al database con il comando **ldapadd**: ldapadd -x -D "cn=admin,dc=rigacci,dc=org" -W -f people.rigacci.org.ldif Enter LDAP Password: adding new entry "ou=People,dc=rigacci,dc=org" Il database adesso è pronto per ricevere gli utenti. Volendo memorizzare gli account di sistema conviene utilizzare gli schemi **posixAccount** e **shadowAccount**. La migrazione dai tradizionali ''/etc/passwd'' e ''/etc/shadow'' può essere facilitata dagli script **[[http://www.padl.com/download/MigrationTools.tgz|Migration Tools]]**. Ecco un estratto di un file LDIF con un account: dn: uid=niccolo,ou=People,dc=rigacci,dc=org uid: niccolo cn: niccolo objectClass: account objectClass: posixAccount objectClass: top objectClass: shadowAccount userPassword: {crypt}$1$hr0T2eCW$L.Rk7J9R1oOzJ3qTgv1YB0 shadowLastChange: 13815 shadowMax: 99999 shadowWarning: 7 loginShell: /bin/bash uidNumber: 1000 gidNumber: 1000 homeDirectory: /home/niccolo gecos: Niccolo Rigacci,,, Ecco il comando per aggiungere un record nel database a partire dal file.ldif: ldapadd -v -H ldap://127.0.0.1/ -x -D "cn=admin,dc=rigacci,dc=org" -W -f file.ldif Per la modifica invece è richiesto un file più complesso, in cui prima si seleziona il record e quindi si indicano le operazioni da effettuare: dn: uid=niccolo,ou=People,dc=rigacci,dc=org changetype: modify add: objectClass objectClass: sambaSamAccount - replace: userPassword userPassword: {crypt}$1$hr0T2eCW$L.Rk7J9E3oTvJ6qTgv1YB0 e il comando necessario è **ldapmodify**: ldapmodify -v -x -D "cn=admin,dc=rigacci,dc=org" -W -f file.ldif Attenzione ai caratteri **NON ASCII**: bisogna codificarli in **UTF-8**, ad esempio usando **''iconv(1)''**. Attenzione però anche ai vincoli imposti dallo schema; ad esempio lo schema ''posixAccount'' non accetta caratteri non ASCII nel campo **gecos** e restituisce un errore del tipo: Invalid Syntax additional info: gecos: value #0 invalid per syntax Per eliminare qualcosa dal database si prepara un file.ldif con i DN che si vogliono eliminare, ad esempio: uid=niccolo,ou=People,dc=rigacci,dc=org uid=angela,ou=People,dc=rigacci,dc=org e poi si utilizza il comando **''ldapdelete''**: ldapdelete -v -x -D "cn=admin,dc=rigacci,dc=org" -W -f file.ldif Per verificare che l'interrogazione dal client verso un server remoto funzioni si usa **''ldapsearch''** (notare l'uso del protocollo LDAP su SSL): ldapsearch -v -x -H ldaps://ldap.rigacci.org -b "uid=niccolo,ou=People,dc=rigacci,dc=org" Operazione del tutto analoga per aggiungere il ramo **Group**, ecco lo schema (lo conserviamo nel file ''group_rigacci_org.ldif''): dn: ou=Group,dc=rigacci,dc=org ou: Group objectClass: top objectClass: organizationalUnit Dopo aver aggiunto il ramo, lo si può popolare con entry del tipo: dn: cn=dialout,ou=Group,dc=rigacci,dc=org objectClass: posixGroup objectClass: top cn: dialout userPassword: {crypt}x gidNumber: 20 memberUid: niccolo memberUid: angela dn: cn=niccolo,ou=Group,dc=rigacci,dc=org objectClass: posixGroup objectClass: top cn: niccolo userPassword: {crypt}x gidNumber: 1000 ===== Indici ===== Per una maggiore efficienza delle query sul database LDAP è necessario mantenere degli indici sulle chiavi di ricerca più utilizzate. Se vengono fatte richieste su campi non indicizzati (e con ''loglevel stats'') il file ''/var/log/syslog'' riporta: slapd[30935]: <= bdb_equality_candidates: (uid) not indexed Si aggiungono direttive in **''/etc/ldap/slapd.conf''**: index uid,uidNumber,gidNumber,memberUid eq Purtroppo per reindicizzare il database bisogna fermare il demone, eseguire il comando **''slapindex(8)''** e riavviare il demone: /etc/init.d/slapd stop slapindex -b "dc=rigacci,dc=org" chown -R openldap:openldap /var/lib/ldap/ /etc/init.d/slapd start ==== Password aging ==== Per la scadenza delle password si utilizza il campo **shadowMax** dello schema shadowAccount, con la stessa semantica del file ''shadow(5)''. Se invece di un sistema basato completamente su LDAP si implementa un sistema misto LDAP + Kerberos, la scadenza delle password dovrebbe essere gestita da Kerberos (come?) e quindi il campo shadowMax si imposta convenzionalmente a **99999** per indicare nessuna scadenza (in realtà sono circa 273 anni). ==== Migration tools ==== Scompattati i sorgenti, modificato **''migrate_common.ph''** impostando quanto segue: # Default DNS domain $DEFAULT_MAIL_DOMAIN = "rigacci.org"; # Default base $DEFAULT_BASE = "dc=rigacci,dc=org"; per esportare gli utenti e i gruppi in un file LDIF è sufficiente eseguire: ./migrate_passwd.pl /etc/passwd > etc_passwd.ldif ./migrate_group.pl /etc/group > etc_group.ldif Conviene ovviamente togliere gli account di sistema dal file LDIF risultante oppure (meglio!) far lavorare il migration tool su una versione emendata di ''/etc/passwd''. **NOTA**: in Debian gli account normali sono quelli con **UID** compreso tra **1000** e **29999**. ===== Configurare il client ===== Sul client che vuole fare autenticazione LDAP si devono configurare due componenti: **PAM su LDAP** (Pluggable Authentication Modules) e **NSS su LDAP** (Network Service Switch). **NOTA**: Se la gestione delle password avviene tramite Kerberos //single sign-on system//, non si deve installare la componente PAM su LDAP. In tal caso si può comunque utilizzare NSS su LDAP. Se si desidera amministrare il database LDAP dal client (non indispensabile) si installa il pacchetto **ldap-utils**. ==== PAM subsystem ==== I pacchetti da installare sono: * **libpam-ldap** Il sistema PAM (Pluggable Authentication Modules) fornisce ai programmi che devono fare autenticazione una serie di servizi tramite una interfaccia di programmazione standard, in questo modo è possibile cambiare il sistema di autenticazione senza dover modificare i programmi. I servizi offerti dai moduli PAM si dividono in quattro categorie: ^ account | Verifica se l'utente ha il permesso di compiere una determinata azione. | ^ auth | **Auth**entication: certifica l'identità dell'utente, in genere verificando una password. | ^ password | Funzioni per aggiornare il sistema di **auth**entication (es. modifica password). | ^ session | Provvede funzioni per iniziare e chiudere una sessione, ad esempio il mount della home directory. | In generale i servizi di **auth**entication sono i più importanti. Per un modulo PAM non è obbligatorio fornire tutti i servizi; ad esempio alcuni moduli PAM potrebbero non fornire la possibilità di cambiare la password. La procedura Debian (Squeeze) di configurazione per **libpam-ldap** richiede diversi parametri, si può ri-eseguire con ''dpkg-reconfigure libpam-ldap'': LDAP server URI: ldaps://127.0.0.1/ Distinguished name of the search base: dc=rigacci,dc=org LDAP version to use: 3 Allow LDAP admin account to behave like local root? Yes Does the LDAP database require login? No LDAP administrative account: cn=admin,dc=rigacci,dc=org LDAP administrative password: **** Local encryption algorithm to use for passwords: crypt PAM profiles to enable: Unix authentication, LDAP Authentication Le impostazioni vengono salvate in **''/etc/pam_ldap.conf''** e in **''/etc/pam_ldap.secret''**. **NOTA:** L'help allegato alla domanda //Allow LDAP admin account to behave like local root?// non è chiaro: rispondendo //No// il file ''/etc/pam_ldap.secret'' contenente la password di amministratore LDAP **non** viene creato, quindi PAM non sarà in grado di modificare il database con i privilegi di amministratore. **NOTA:** Non dovrebbe essere strettamente necessario che l'utente root del client sia amministratore del database LDAP, quindi si dovrebbe poter evitare che la password relativa venga memorizzata sul client. **ATTENZIONE**: per evitare che le password possano essere facilmente intercettate **è obbligatorio utilizzare il protocollo ldaps**. Poiché il server utilizza un certificato auto-firmato è necessario disabilitarne la verifica. Editare il file **''/etc/pam_ldap.conf''** e aggiungere le opzioni: ssl on tls_checkpeer no Per testare la componente PAM si può creare il file **''/etc/pam.d/test_ldap''** con le seguenti direttive: auth required pam_ldap.so account required pam_ldap.so password required pam_ldap.so ed utilizzare l'utility **[[http://pamtester.sourceforge.net/|pamtester]]** in questo modo: ./pamtester -v test_ldap niccolo authenticate pamtester: invoking pam_start(test_ldap, niccolo, ...) pamtester: performing operation - authenticate Password: pamtester: successfully authenticated Contrariamente a quello che viene riportato in alcuni documenti pare che non sia obbligatorio risolvere l'indirizzo IP del server LDAP nel nome definito nel certificato del server stesso. A questo punto, se le cose sembrano funzionare, si può configurare PAM in modo che utilizzi sempre LDAP, ritornando al tradizionale schema Unix in caso di fallimento. In Debian dovrebbe bastare modificare i file **common-account**, **common-auth** e **common-password** contenuti in ''/etc/pam.d/'' **/etc/pam.d/common-account** account sufficient pam_ldap.so account required pam_unix.so try_first_pass **/etc/pam.d/common-auth** auth sufficient pam_ldap.so auth required pam_unix.so nullok_secure try_first_pass **/etc/pam.d/common-password** password sufficient pam_ldap.so password required pam_unix.so nullok obscure md5 try_first_pass FIXME La sintassi dei dei file sopra non mi convince, sonsultare anche i documenti [[http://techpubs.spinlocksolutions.com/dklar/ldap.html|Setting up OpenLDAP]] e [[http://techpubs.spinlocksolutions.com/dklar/kerberos.html|Setting up MIT Kerberos 5]]. === Autenticazione PAM per ssh === :!: La configurazione del **demone ssh** in Debian potrebbe **non utilizzare PAM** :!: Per aumentare la sicurezza viene abilitata l'opzione **''UsePrivilegeSeparation''** rendendo non privilegiato il processo che riceve la connessione TCP, questo nelle vecchie versioni di OpenSSH creava problemi all'autenticazione PAM. Inoltre per mitigare un bug di sicurezza scoperto in passato si consigliava di impostare **''PAMAuthenticationViaKbdInt no''**. Con **OpenSSH 4.4p1** il problema è risolto e si può impostare l'opzione **''UsePAM yes''**. Consultare la man page di **''sshd_config(5)''** e controllare in **''/etc/ssh/sshd_config''** le seguenti opzioni: UsePrivilegeSeparation yes PasswordAuthentication yes ChallengeResponseAuthentication no UsePAM yes ==== NSS subsystem ==== Tradizionalmente sui sistemi Unix alcune informazioni sugli utenti e sugli host sono contenute in file di configurazione (''/etc/passwd'', ''/etc/shadow'', ''/etc/hosts'', ...). Il **[[wp>Name Service Switch|Name Service Switch (NSS)]]** è un servizio che consente di sostituire questi file con uno o più database. Nel nostro caso vogliamo che le informazioni sugli **utenti** e sui **gruppi** siano su un **database LDAP**. I pacchetti Debian da installare sono: * **libnss-ldap** modulo NSS basato su database LDAP * **nscd** demone per il caching delle informazioni NSS, altamente consigliato * **libnss-db** e **nss-updatedb** alternativi a ''libnss-ldap'': crea una copia locale dei database, usabile in modalità off-line La procedura Debian di configurazione per **libnss-ldap** richiede diversi parametri (eseguire '''' per vedere tutte le domande): LDAP server Uniform Resource Identifier: ldap://127.0.0.1/ Distinguished name of the search base: dc=rigacci,dc=org LDAP version to use: 3 Does the LDAP database require login? No Special LDAP privileges for root? No Make the configuration file readable/writeable by its owner only? Yes Le impostazioni vengono salvate in **''/etc/libnss-ldap.conf''**. Attivare i privilegi speciali LDAP per root vorrebbe dire che l'utente root del client ha i privilegi di amministratore su LDAP, questo però richiederebbe di memorizzare in chiaro la password di amministratore LDAP nel file **''/etc/libnss-ldap.secret''**. :!: **NOTA:** Forse è opportuno rispondere **No** all'ultima domanda, visto che anche gli utenti non privilegiati devono poter accedere (in modo anonimo) al database LDAP. Vedi avanti. :!: **ATTENZIONE:** Se in **''/etc/libnss-ldap.conf''** viene impostata l'opzione **binddn**, allora il collegamento al server LDAP avviene con quel nome **invece che in modo anonimo**. Nel nostro caso si preferisce che l'utente non privilegiato faccia collegamenti anonimi, pertanto l'opzione viene omessa. Se l'utente è root allora l'accesso LDAP avviene con le credenziali specificate in **rootbinddn** e la password contenuta in ''/etc/libnss-ldap.secret''. Anche in questo caso è necessario disabilitare la verifica del certificato dal momento che non è firmato da alcuna Certificate Authority. Forziamo anche l'uso di SSL che altrimenti fallisce nonostante la scelta del protocollo ldaps. Quindi in **''/etc/libnss-ldap.conf''** si imposta: ssl on tls_checkpeer no L'opzione **tls_checkpeer** potrebbe essere impostata a livello di libldap nel file **''/etc/openldap/ldap.conf''**, come dice il commento in ''libnss-ldap.conf''. :!: **ATTENZIONE:** Debian **imposta i permessi di ''/etc/libnss-ldap.conf'' a 0600** perché in questo file potrebbero trovarsi le credenziali per accedere al database LDAP. Non è il caso nostro, anzi le interrogazioni per i database ''passwd'' e ''group'' vengono fatte in modo anonimo e devono essere eseguibili dall'utente non privilegiato (ad es. con ''getent(1)''). Per ottenere questo risultato bisogna fare: chmod 0644 /etc/libnss-ldap.conf Nel caso serva memorizzare la password per accedere al database LDAP si utilizza il file **''/etc/libnss-ldap.secret''** (contiene solo la passwrod, senza il newline!) e si protegge il file con **''chmod 0600''**. Rimane infine da configurare il file **''/etc/nsswitch.conf''**, in questo esempio la ricerca su LDAP viene fatta solo se fallisce la ricerca sui tradizionali file: passwd: files ldap group: files ldap shadow: files ldap In Debian al posto della ricerca **files** si trova quella **compat** (che sta per //NIS compatibility//), questa modalità consente di utilizzare una speciale sintassi nel file ''/etc/passwd'' per includere gruppi di utenti. :!: **ATTENZIONE:** la **modifica del file** **''/etc/nsswitch.conf''** **__non ha effetto immediato__** su tutti i programmi in esecuzione, ogni programma infatti legge la configurazione del NSS solo al suo avvio. Se si cambia il file di configurazione ad esempio si deve riavviare il demone **nscd**, utile anche il comando per invalidare la cache di nscd: /etc/init.d/nscd reload nscd --invalidate passwd Per testare il funzionamento del NSS si può utilizzare il comando **''getent(1)''** che cerca nei database (passwd, group, ...) una specifica chiave: getent passwd niccolo niccolo:x:1002:1002:Niccolo Rigacci,,,:/home/niccolo:/bin/bash L'installazione di **nscd** è praticamente obbligatoria se il server LDAP è su una macchina diversa da localhost. Infatti anche la più semplice operazione (ad esempio un **''ls -l''**) provoca numerose interrogazioni del NSS, ripetere le interrogazione su un database remoto risulterebbe in un rallentamento non accettabile. Volendo una **copia locale** dei database //passwd// e //group// **da usare quando disconnessi** si può usare il pacchetto **libnss-db** e un cron-job che replica le informazioni dalla sorgente LDAP (pacchetto **nss-updatedb**). ====== Autenticazione Kerberos e LDAP ====== **[[kerberos|Kerberos]]** si propone come sistema di **Single Sign-On** (SSO), cioè con una sola autenticazione è possibile accedere a molti servizi. Il server di autenticazione Kerberos mantiene solo le informazioni su nome/password (chiamate //principals//) e poco altro (scadenza, ecc.), non contiene informazioni su UID, GID, ecc. Al momento del login il server Kerberos autentica l'utente e rialscia un **//Ticket-granting Ticket//** (TGT), cioè un ticket che verrà utilizzato in seguito per ottenere i ticket specifici per accedere ai servizi, senza dover ripetere la procedura di autenticazione. Con il comando **''klist(1)''** è possibile sapere quali ticket abbiamo ricevuto, con **kinit(1)** è possibile ottenere un nuovo TGT. Grazie ad un robusto progetto di sicurezza, Kerberos non trasmette mail le password in rete. L'accoppiata **PAM + Kerberos** può sostituire utilmente **PAM + LDAP**, migliorando la procedura di autenticazione. Ad esempio sarà possibile effettuare login su un host e montare una directory NFSv4 in modo sicuro, effettuando una sola autenticazione. Configurando PAM opportunamente, non solo l'autenticazione del login verrà fatta sul server Kerberos, ma verrà anche rilasciato automaticamente il //Ticket-granting Ticket//, senza bisogno di eseguire ''kinit'' e digitare nuovamente la password. Questo è il motivo per cui è importante configurare il modulo //session// di PAM. Il resto delle informazioni utente (UID, GID, home directory, shell, ...) non sono memorizzati nel database Kerberos, pertanto staranno nei tradizionali file Unix oppure su un **server LDAP** e gestiti dal **Name Service Switch (NSS)**. Tradizionalmente la shadow password viene impostata a **%%*K*%%**, per significare che è nel database Kerberos. Qui abbiamo una guida all'installazione di **[[kerberos|Kerberos]]** per NFSv4 (utile per la configurazione del server KDC), esiste inoltre questa guida all'installazione di Kerberos per l'autenticazione: **[[http://www.spinlocksolutions.com/info/kerberos.html|MIT Kerberos installation on Debian]]**. Sull'host che deve usufruire di questa autenticazione si installa il modulo PAM che si appoggia al server Kerberos e le utility di supporto Kerberos. In pratica servono i pacchetti Debian: * **libpam-krb5** * **krb5-config** * **krb5-user** L'installazione di krb5-config genera il file di configurazione **''/etc/krb5.conf''** che contiene il //realm// di appartenenza e il nome DNS del //server KDC//. Eventualmente eseguire **''dpkg-reconfigure krb5-config''** per specificare nuovamente i parametri, ad esempio: Default Kerberos version 5 realm: RIGACCI.ORG Does DNS contain pointers to your realm's Kerberos Servers? No Kerberos servers for your realm: kdc.soluzioni.per Administrative server for your Kerberos realm: kdc.soluzioni.per Nel database Kerberos deve essere presente solo il //principal// (account) dell'utente. Non è necessario creare un principal per l'host su cui si effettua il login, né tantomeno sull'host è necessario creare una chiave nel keytab file. Per verificare che l'autenticazione Kerberos funzioni un utente qualunque può utilizzare **''kinit''**, verificare il risultato con **''klist''** e rimuovere il ticket con **''kdestroy''**: # kinit angela@RIGACCI.ORG Password for angela@RIGACCI.ORG: # klist -5 Ticket cache: FILE:/tmp/krb5cc_0 Default principal: angela@RIGACCI.ORG Valid starting Expires Service principal 01/07/08 22:36:23 01/08/08 08:36:23 krbtgt/RIGACCI.ORG@RIGACCI.ORG renew until 01/08/08 22:36:19 # kdestroy Per fare in modo che tutti i programmi PAM utilizzino Kerberos si modificano alcuni file in **''/etc/pam.d/''**, aggiungendo al tradizionale **''pam_unix.so''** il modulo **''pam_krb5.so''**. **ATTENZIONE**: Con Debian Squeeze queste aggiunte vengono effettuate automaticamente con l'installazione del pacchetto **libpam-krb5**, grazie al comando **''pam-auth-update''**. Le regole sono in realtà molto più elaborate ed efficaci. common-auth: auth sufficient pam_krb5.so minimum_uid=1000 auth required pam_unix.so try_first_pass nullok_secure common-session: session optional pam_krb5.so minimum_uid=1000 session required pam_unix.so common-account: account required pam_krb5.so minimum_uid=1000 account required pam_unix.so common-password: password sufficient pam_krb5.so minimum_uid=1000 password required pam_unix.so nullok obscure md5 FIXME La sintassi dei dei file sopra non mi convince, sonsultare anche i documenti [[http://techpubs.spinlocksolutions.com/dklar/ldap.html|Setting up OpenLDAP]] e [[http://techpubs.spinlocksolutions.com/dklar/kerberos.html|Setting up MIT Kerberos 5]]. ===== File temporanei krb5cc_pam in /tmp/ ===== Pare che il modulo **''pam_krb5''** in alcune circostanze non cancelli il file temporaneo con il ticket rilasciato da Kerberos. Tali file si accumulano indefinitamente in ''/tmp'' con nomi del tipo **''krb5cc_pam_*''**, tale situazione si verifica ad esempio con il courier authdaemon per ogni login POP3. Forse è possibile configurare meglio il modulo pam, nel dubbio si attiva un cronjob che cancella i ticket più vecchi di qualche ora (non ha senso tenere i ticket oltre le 10 ore, vedere qual'è il ''max_life'' dei ticket): #!/bin/sh # Remove temporary Kerberos ticket cache left by PAM subsystem. find /tmp -name "krb5cc_pam_*" -mmin +240 | xargs -r rm ====== Rubrica contatti su LDAP ====== La distribuzione di riferimento è una **Debian Sarge**. Si installano i seguenti pacchetti: apt-get install slapd ldap-utils Durante l'installazione viene chiesto come costruire il **DN** (Distinguished Name) dell'archivio LDAP, si suggerisce di usare il nome del dominio DNS. Ad esempio con il dominio ''**rigacci.org**'', la radice dell'albero LDAP diventa ''**DN dc=rigacci, dc=org**''. Ogni oggetto dovrà essere figlio di questo. La porta da aprire sul firewall è la **389** TCP e UDP. ===== Pacchetti Debian Sarge ===== * ''slapd'' * ''ldap-utils'' * ''db4.2-util'', ''libiodbc2'', ''libltdl3'', ''libsasl2-modules'', ''libslp1'' * ''phpldapadmin'', ''php4-ldap'' Il pacchetto Debian Sarge propone di supportare solo la v.3 del protocollo. ===== Configurazione ===== **''/etc/ldap/slapd.conf''** Dentro il file di configurazione del server LDAP ci sono alcune opzioni globali (già presenti nel file di configurazione), si aggiunge la definizione del database da gestire (oppure la si include da un file esterno). Una struttura di database d'esempio è la seguente: # See man slapd.conf # Log connections/operations/results loglevel 256 database dbm suffix "o=ipbox" rootdn "cn=LdapAdmin,o=ipbox" #rootpw {SSHA}lxy7HF6eP7fRaA3G5L85zhk6zWZP8+Fk rootpw soloperprova schemacheck on lastmod on directory /var/lib/ldap/ipbox index cn,sn pres,eq,sub access to attrs=userPassword by dn="cn=LdapAdmin,o=ipbox" write by anonymous auth by self write by * none access to * by dn="cn=LdapAdmin,o=ipbox" write by * read Come si vede nel file di configurazione viene indicato quali indici mantenere nel database ed acluni criteri di accesso. Nell'esempio sopra ciascun utente può cambiare la propria password, l'utente ''**cn=LdapAdmin,o=ipbox**'' ha accesso completo in scrittura, tutti gli altri in sola lettura. L'utente privilegiato e la sua password è definito direttamente nel file di configurazione, quindi non è necessario inserirlo nel database vero e proprio. Dopo aver modificato il file di configurazione si esegue ''/etc/init.d/slapd restart'', il log viene scritto in ''/var/log/syslog''. ===== Importare/esportare dati da file .ldif ===== **NOTA:** Prima di poter importare un oggetto nel database LDAP bisogna aver creato tutti gli **oggetti parent**, a partire dalla radice (ricordarsi che LDAP gestisce un database ad albero gerarchico). Ad esempio prima di aggiungere un distinguished name **uid=jdoe,ou=people,dc=example,dc=com**, bisogna che siano stati aggiunti gli oggetti **dc=example,dc=com** e **ou=people,dc=example,dc=com**. In questo esempio si crea l'oggetto ''o=ipbox'' prima di poter aggiungere le persone del tipo ''cn=Mario,o=ipbox''. Questo si può fare con un primo file ''.ldif'' (vedere più avanti com caricare un file ''.ldif''): dn: o=ipbox objectClass: top objectClass: organization o: ipbox Si possono importare dei dati nel database a partire da un file ''.ldif'', ecco ad esempio ''rubrica.ldif'' con un record: dn: cn=Mario Rossi,o=ipbox objectClass: top objectClass: inetOrgPerson cn: Mario Rossi displayName: Mario Rossi givenName: Mario sn: Rossi uid: oqY6hwrjK3 mail: mario.rossi@texnet.it Si importa il file nel database con comandi del tipo: ldapadd -h 127.0.0.1 -D "cn=LdapAdmin,o=ipbox" -W -xv -f rubrica.ldif ldapadd -H ldap://127.0.0.1/ -D "cn=LdapAdmin,o=ipbox" -W -xv -f rubrica.ldif Per esportare il contenuto del database in un file ''.ldif'' invece si usa il comando: slapcat -b "o=ipbox" ===== Struttura dati ===== Per creare una rubrica si consiglia di seguire uno dei due schemi più diffusi: ''**inetOrgPerson**'' oppure ''**mozillaOrgPerson**''. Il secondo è più ricco di attributi, ma non è compreso nella pacchettizzazione standard Debian. Si scarica il file ''.schema'' da Internet, lo si salva in ''/etc/ldap/schema/'', si aggiunge a ''/etc/ldap/slapd.conf'' una riga: include /etc/ldap/schema/mozillaorgperson.schema Pare che Outlook e Outlook Express si trovino a proprio agio con entrambe le strutture dati, altrettanto per Kmail. ===== Accesso ai dati ===== Come client possiamo utilizzare KAddressBook (la rubrica di KDE), oppure LDAP Explorer (un applicativo in PHP basato sul web, puntare il browser su http://ldapserver/ldapexplorer/). I parametri necessari alla connessione in lettura/scrittura sono i seguenti: ^ Server LDAP | 10.0.1.111 | ^ Porta | TCP 389 | ^ Base DN | o=ipbox | ^ Query type | One level (not recursive) | ^ User (Bind DN as) | cn=LdapAdmin,o=ipbox | ^ Password | soloperprova | Per un accesso in sola consultazione si immettono gli stessi dati, omettendo User e Password. ===== phpLDAPadmin ===== Si installa il pacchetto Debian **phpldapadmin**. Il file di configurazione **''/etc/phpldapadmin/config.php''** contiene il nome derl server LDAP, la porta, il nome con cui collegarsi. Se la connessione viene fatta alla porta **636 ldaps** bisogna **non attivare** l'opzione **tls**, altrimenti si ottiene l'errore: slapd[29352]: conn=40 op=0 STARTTLS slapd[29352]: conn=40 op=0 RESULT oid= err=1 text=TLS already started Per accedere all'interfaccia web di amministrazione si punta il browser su **%%http://ldap.mydomain.org/phpldapadmin/%%**, usando le opportune credenziali.