%%
%% LDAP 
%%
%% Copyright (C) 2002-2018 Simone Piccardi and Truelite Srl.
%%
%% This work is licensed under the Creative Commons Attribution-ShareAlike 4.0
%% International License. To view a copy of the license, visit
%% https://creativecommons.org/licenses/by-sa/4.0/ Quest'opera è distribuita
%% con Licenza Creative Commons Attribuzione - Condividi allo stesso modo 4.0
%% Internazionale. Per una copia di questa licenza visitare
%% https://creativecommons.org/licenses/by-sa/4.0/
%%
%% Corsi GNU/Linux: Dispense dei corsi GNU/Linux di Truelite
%%
%% S. Piccardi Aug. 2002
%%
%% ldap.tex: Dispense su LDAP
%%
 
%
% To avoid these definition when included from outside
%
\providecommand{\setflag}{\newif \ifwhole \wholefalse}
\setflag

\ifwhole\else

% old A4 format
%\documentclass[a4paper,11pt,twoside]{book} 

\documentclass[10pt,twoside]{book} 

% production
\usepackage[paperwidth=18.91cm,paperheight=24.589cm,
inner=2.5cm,outer=1.8cm,bottom=3.3cm,top=2.3cm]{geometry}

\input{../commons/packages2}
\input{../commons/front2}

\svnidlong
{$HeadURL$}
{$LastChangedDate$}
{$LastChangedRevision$}
{$LastChangedBy$}

\makeindex

\begin{document}

\newcommand{\CopyrightRange}{2002-2017}
\newcommand{\BookFullTitle}{Integrazione Sistemistica con LDAP}
\newcommand{\BookEdition}{Seconda edizione}
\newcommand{\BookISBN}{-nessuno-} 

\pagenumbering{roman}

\begin{titlepage}
    \centering
    \phantom{}
    \vfill
    {\Huge \textbf{\textsf{Integrazione Sistemistica con LDAP}}}
    \vfill
    {\huge \textsf{Simone Piccardi}}

    {\large \textsf{piccardi@truelite.it}}

    {\large \textsf{Revisione: \svnrev}}

    \vspace{2.5cm} {\textsf{Truelite Srl \hfill http://www.truelite.it \hfill
      info@truelite.it}}
\end{titlepage}

%\frontmatter
%\pagenumbering{roman} 
%\maketitle

\ClearShipoutPicture

\newcommand{\clearemptydoublepage}{\newpage{\pagestyle{empty}
\cleardoublepage}}

\cleardoublepage

% scegliere 
\input{../commons/seconda}

\cleardoublepage
\tableofcontents

\cleardoublepage
\mainmatter

\pagenumbering{arabic}

\fi

\chapter{Il servizio LDAP}
\label{cha:LDAP}


\section{Il protocollo LDAP}
\label{sec:ldap_protocol}

In questa prima sezione faremo una introduzione generale su LDAP, trattando le
caratteristiche essenziali del protocollo, la strutturazione dei dati, le
varie convenzioni adottate ed il formato di interscambio in cui questi vengono
usualmente tradotti.

\subsection{Una visione di insieme}
\label{sec:ldap_intro}

Il nome LDAP è l'acronimo di \textit{Lightweight Directory Access Protocol};
si tratta di un protocollo che permette di accedere ad un servizio di
\textsl{elenco} (non ho trovato una traduzione migliore del termine
\textit{directory} in questo contesto) in versione elettronica, analogo a
quello che potrebbe essere un elenco telefonico, ma generalizzato nei
contenuti.  In sostanza si tratta di un database, ma il cui scopo principale è
la ricerca di informazioni, e non la gestione (nel senso di registrazione ed
aggiornamento continuo) delle stesse.

Per capire l'utilità di un servizio generico di questo tipo consideriamo come
in un sistema GNU/Linux siano già presenti molteplici elenchi di informazioni:
la lista degli utenti, quella dei gruppi, quella delle porte TCP e UDP,
ecc.\footnote{buona parte di questi sono gestiti dal sistema del \textit{Name
    Service Switch}, vedremo come potranno essere portati su LDAP in
  sez.~\ref{sec:ldap_NSS}.} In generale si tende a distinguere fra quelli che
sono i servizi di elenco \textsl{locali}, come la lista degli utenti di
\texttt{/etc/passwd}, e quelli che invece sono \textsl{globali}, come la lista
delle corrispondente fra nomi a dominio e numeri IP fornite dal DNS.

La presenza di un servizio che permetta di mantenere diversi tipi di
informazione e di recuperarli in maniera efficiente sulla base di criteri di
ricerca generici viene allora a costituire uno strumento fondamentale in tutti
quei casi in cui si debbano integrare fra loro sistemi diversi che necessitano
di accedere a informazioni comuni, che a questo punto possono essere mantenute
in maniera centralizzata all'interno di questo servizio.

I servizi di \textsl{elenco} sono stati standardizzati (partendo dall'idea
dell'elenco telefonico) a livello internazionale nello standard
ISO\footnote{la \textit{International Organization for Standardization}, una
  organizzazione non governativa dedicata allo sviluppo di standard,
  costituita da una rete di istituti nazionali, che invece sono spesso di
  origine governativa.} \index{ISO X.500} X.500, che prevede sia un modello di
dati che un protocollo di accesso (il DAP, acronimo di \textit{Directory
  Access Protocol}); LDAP parte dal modello di dati di X.500 ma implementa un
protocollo di accesso semplificato basato esclusivamente su TCP/IP, che è
stato standardizzato
dall'\href{http://www.ietf.org/rfc/rfc2251.txt}{RFC~2251}. Oltre a questo sono
state semplificate alcune rappresentazioni dei dati e cancellate alcune
funzionalità oscure e poco utilizzate.

Il protocollo LDAP è strutturato sul classico modello client-server, in cui in
server mantiene le informazioni dell'elenco ed i client eseguono le
interrogazioni e le ricerche. Inoltre in maniera analoga a quanto accade per i
DNS qualora un server non possieda le informazioni richieste, può trasferire
le richieste ad un altro server adottando un'organizzazione ad albero (che
approfondiremo in sez.~\ref{sec:ldap_general_structure}) che permetterebbe di
integrare le informazioni locali all'interno di una struttura globale di tutti
i servizi di elenco.

Il protocollo è costituito da una parte che definisce l'organizzazione dei
dati, chiamata \textit{Data model}, che permette di stabilire come viene
rappresentata l'informazione, uno schema di assegnazione dei nomi, detto
\textit{Naming model}, che identifica il singolo dato mantenuto nel sistema,
ed infine una modalità di accesso ai dati con tanto di meccanismi molto
dettagliati, come vedremo in sez.~\ref{sec:ldap_access_control}, per il
controllo degli accessi.

Il protocollo invece non dice niente rispetto alle modalità specifiche in cui
i dati vengono memorizzati, tratta solo la loro strutturazione astratta, e le
modalità con cui possono essere compiute sugli stessi le operazioni previste
dal protocollo (ricerca, lettura o scrittura); l'implementazione è lasciata al
funzionamento del singolo server.

Per la natura stessa del servizio le informazioni mantenute in un server LDAP
sono per lo più lette, vengono scritte o aggiornate soltanto in maniera
occasionale; per questo motivo non sono necessari i complessi meccanismi di
\textit{roll-back}\footnote{si chiama così quella funzionalità che consente di
  finalizzare una serie di operazioni di modifica dei contenuti in un'unica
  volta, garantendo la possibilità, fintanto che non la si esegue, di
  ritornare allo stato precedente.} e sincronizzazione usualmente presenti nei
più comuni database relazionali. Inoltre l'organizzazione delle informazioni è
di tipo descrittivo e non relazionale e come accennato la struttura è ad
albero e non a tabelle. Nonostante queste differenze con quella che è
l'accezione più comune del termine,\footnote{quella che porta a identificare i
  database con i database relazionali interrogabili con il linguaggio SQL,
  ignorando che questo è solo uno dei tanti modi in cui è possibile
  organizzare una base di dati.}  faremo comunque riferimento alle
informazioni mantenute in un server LDAP chiamandole \textsl{database}.

Un database LDAP pertanto deve essere ottimizzato per fornire risposte rapide
in lettura e nelle ricerche, per essere facilmente replicato, e per supportare
la distribuzione di carico su più server.  Per questo motivo il protocollo,
contrariamente a quanto è richiesto per i database relazionali, considera come
accettabili delle inconsistenze temporanee nelle informazioni.


\subsection{La strutturazione dei dati di LDAP}
\label{sec:ldap_general_structure}

La caratteristica fondamentale del modello di dati usato da LDAP è la sua
struttura ad albero, si parla infatti di \itindex{DIT~(Data~Information~Tree)}
DIT o \textit{Data Information Tree}. Le informazioni sono infatti mantenute
in una gerarchia di \textsl{oggetti} o \textsl{voci} (in inglese sono chiamati
\textit{entries}) a partire da un oggetto o voce iniziale che costituisce la
radice dell'albero (identificato con i termini \textit{base} o
\textit{suffix}), con i successivi oggetti ``\textsl{contenuti}''all'interno
di altri oggetti del livello precedente.

In realtà i singoli oggetti di per sé non contengono altri oggetti, ma solo
gli \textsl{attributi} delle \textsl{classi} cui appartengono, parlare di
\textsl{contenuto} in questo contesto può essere fuorviante, perché in questo
caso va solo inteso come modo di rappresentare la struttura ad albero, per cui
sotto un oggetto possono situarsene degli altri che a loro volta possono
averne altri al di sotto, ecc. È grazie a questa strutturazione che il
protocollo permette di suddividere le informazioni in maniera gerarchica, ed
eventualmente di tenerle separate su diversi alberi, che in generale possono
stare su server diversi, gestendo in maniera naturale la distribuzione dei
dati.

\index{objectclass|(}

Si parla di oggetti e classi perché la strutturazione dei dati contenuti in
una voce segue il paradigma della programmazione ad oggetti: ciascun oggetto è
una \textsl{istanza} di una o più \textsl{classi}, e può contenere i valori di
uno o più degli \textsl{attributi} che sono definiti all'interno delle classi
da cui deriva.  La strutturazione dell'informazione è infatti basata sulla
cosiddetta \textit{objectclass}, una sorta di ``\textit{meta-classe}'' che
viene usata per definire le singole classi assegnando loro un nome che le
identifichi e definendo gli attributi che le compongono.  In questo modo il
modello dei dati consente anche di utilizzare il concetto di ereditarietà
tipico della programmazione ad oggetti, e costruire delle classi derivate a
partire da una classe di base, estendendone gli attributi.

Si rammenti comunque che sono le singole voci nell'albero che contengono i
dati reali, specificati dai valori assegnati ai rispettivi attributi: una
\textit{objectclass} definisce solo quali sono gli attributi possibili per
quella classe, e quali fra questi sono eventualmente necessari. Come accennato
un oggetto può utilizzare in contemporanea più di una \textit{objectclass}, ma
solo una di queste può essere di tipo \textsl{strutturale}, cioè in grado di
definire la struttura dell'oggetto. Ad essa si possono poi associare delle
classi \textsl{ausiliarie} che possono definire altri attributi che estendono
la possibilità di associare dei dati ulteriori all'oggetto.

Ogni \textit{objectclass} è identificata univocamente da un
\itindex{OID~(Object~ID)} OID\footnote{gli OID sono dei codici numerici
  univoci, organizzati in forma gerarchica a livello globale, usati
  identificare un \textsl{oggetto}; i vari numeri sono standardizzati dalla
  IANA, e per LDAP vengono prevalentemente utilizzati numeri al di sotto del
  prefisso \texttt{1.3.6.1.4.1.}; per maggiori dettagli si consulti
  \url{http://en.wikipedia.org/wiki/Object_identifier}.}  (sigla che sta per
\textit{Object Identifier}) e da un nome mnemonico, e viene definita indicando
se è strutturale o ausiliaria, quali attributi ne fanno parte e quali sono
quelli necessari e quelli opzionali, e se è derivata da un'altra classe o
meno. Nel primo caso verranno definiti solo gli eventuali attributi aggiuntivi
rispetto alla classe originaria, altrimenti deriverà soltanto dalla
\textit{objectclass} speciale \objcl{top}, che viene usata come radice
dell'albero della gerarchia delle \textit{objectclass}, ed è pertanto sempre
presente.

Una delle \textit{objectclass} più comuni è ad esempio \objcl{inetOrgPerson},
una classe derivata (vedi sez.~\ref{sec:ldap_address_book}) di tipo
strutturale, che viene utilizzata principalmente per gestire indirizzari; nel
caso la classe richiede obbligatoriamente la presenza di un \textit{Common
  Name} e consente di definire una lunga lista di altri attributi per
informazioni come indirizzi, telefoni, ruoli, ecc.

Come ad ogni classe, anche ad ogni attributo viene associato un OID ed un nome
mnemonico che lo identifica (in alcuni casi anche più di uno); inoltre nella
sua definizione viene specificato da quale tipo di dati questo può essere
costituito (stringa, valore numerico, ecc.), se può essere presente più volte
o meno in uno stesso oggetto, e che criteri di ricerca per i valori contenuti
sono eventualmente supportati.

\index{objectclass|)}


Un attributo usato comunemente è il citato \textit{Common Name}, identificato
dalla stringa ``\texttt{cn}'', che viene usato per memorizzare il nome di una
persona (ad esempio ``\texttt{Simone Piccardi}''). Un altro attributo comune è
``\texttt{mail}'', che viene utilizzato invece per memorizzare un indirizzo di
posta elettronica (ad esempio ``\texttt{piccardi@truelite.it}'').

Inoltre per identificare da quali classi deriva ogni oggetto presente
nell'albero, per ciascuno di essi vengono comunque sempre definiti una serie
di attributi ``\texttt{objectClass}'' il cui valore corrisponde al nome di
ciascuna di dette classi. L'indicazione di questi argomenti consente di
specificare le ``\texttt{objectClass}'' che si vogliono usare per l'oggetto ed
ovviamente il nome ``\texttt{objectClass}'' è riservato.

Buona parte della standardizzazione di LDAP consiste appunto nella definizione
di una serie di \textit{objectclass} e dei relativi attributi per la
memorizzazione di specifiche informazioni;\footnote{ad esempio la citata
  \texttt{inetOrgPerson} è definita
  nell'\href{http://www.ietf.org/rfc/rfc2798.txt}{RFC~2798}.} uno degli esempi
più significativi è la classe \objcl{organizationalUnit}, che definisce una
unità organizzativa (una \textit{Organizational Unit} appunto) che viene usata
quasi esclusivamente per creare rami di albero, e che per questo riveste un
ruolo importante nella strutturazione dei dati di un server.

La classe richiede l'attributo obbligatorio ``\texttt{ou}'' che contiene il
nome dell'unità organizzativa. Le sue modalità di utilizzo prevedono che le
voci relative a persone o ad altri tipi di dati attinenti ad una certa unità
organizzativa debbano essere inserite al di sotto della voce che identifica
l'unità stessa. In questo modo si può suddividere l'albero in tanti rami alla
base di ciascuno dei quali c'è una \textit{Organizational Unit} che ne
classifica il contenuto.

\begin{figure}[!h!bt]
  \centering \includegraphics[width=10cm]{images/geo_tree}
  \caption{Strutturazione di un albero LDAP su base geografica.}
  \label{fig:ldap_geo_tree}
\end{figure}

Come accennato la struttura ad albero dei dati di un server, oltre a
consentire una suddivisione gerarchica delle informazioni in esso contenute,
può permettere anche di inserire i vari alberi dei singoli server all'interno
di una organizzazione dei dati \textsl{globale} (in maniera analoga alla
struttura dei nomi a dominio), in cui si possono riunire in maniera coerente
alberi diversi sotto una radice unica. Questo ovviamente richiede che la
radice usata dai singoli server sia scelta con un criterio coerente che
consenta questa integrazione; di questi criteri ne esistono in sostanza due.

Il primo criterio deriva direttamente dallo scopo originale di LDAP, che era
quello di fornire un database distribuito, analogo a quello del DNS, che
costituisse l'analogo dell'elenco del telefono su internet, contenente cioè
informazioni riguardo nomi, indirizzi e dati specifici di società e persone.

In questo caso le informazioni sono gerarchizzate su base geografica: alla
radice dell'albero stanno allora degli oggetti ``\textit{Country}'' che
specificano il paese con l'attributo ``\texttt{c}'', sotto i quali poi si
situeranno ulteriori oggetti di specificazione geografica più limitata come
``\texttt{st}'', che indica lo ``\textit{State}'' dove il concetto deriva
dall'ambito statunitense dove la suddivisione geografica successiva è da
``\textsl{nazione}'' (gli USA) a singolo ``\textsl{stato}'' (il Texas); in
ambito europeo in genere questo campo indica la provincia o viene omesso. A
questi seguono ``\texttt{l}'' che indica la località (città, o più in generale
il comune) ed infine ``\texttt{o}'' che indica una organizzazione.\footnote{si
  sono identificati gli oggetti col nome dell'attributo obbligatorio che essi
  prevedono, piuttosto che con quello della rispettiva \textit{objectclass},
  dato che sono i valori di questi nomi a referenziare i singoli oggetti
  nell'albero.}  

Un esempio di questo criterio di strutturazione è riportato in
fig.~\ref{fig:ldap_geo_tree}, ma lo citiamo solo per riferimento, oggi su LDAP
esso è totalmente in disuso, anche se questa suddivisione si ritrova pari pari
nelle informazioni inserite nei certificati TLS/SSL, che anch'esse originano
dallo standard ISO X.500. 

Il secondo criterio è invece ripreso direttamente dall'albero dei domini del
DNS, di cui LDAP ricalca la filosofia anche per quanto riguarda la
distribuzione dell'informazione. In questo caso alla radice dell'albero stanno
sempre degli oggetti \textit{Domain Component}, (la cui \textit{objectclass} è
\objcl{dcObject}), identificati tramite il valore del rispettivo attributo
obbligatorio ``\texttt{dc}'', ed inseriti uno sotto l'altro nell'albero in
modo da replicare la struttura dei domini su internet. Le successive
classificazioni ripartono dal livello di organizzazione o unità organizzativa
già visto nella precedente struttura.  Un esempio di questa strutturazione è
riportato in fig.~\ref{fig:ldap_internet_tree}.

\begin{figure}[!htb]
  \centering \includegraphics[width=10cm]{images/internet_tree}
  \caption{Strutturazione di un albero LDAP sulla base dell'albero dei
    domini.}
  \label{fig:ldap_internet_tree}
\end{figure}

\itindbeg{Distinguished~Name}

All'interno dell'albero dei dati (indipendentemente da quale delle due
precedenti strutturazioni si è scelta) ogni oggetto è identificato
univocamente dal cosiddetto \textit{Distinguished Name} (che in seguito
abbrevieremo spesso in DN);\footnote{il formato dei \textit{Distinguished
    Name} è definito
  dall'\href{http://www.ietf.org/rfc/rfc2253.txt}{RFC~2253}, che si può 
  consultare per avere tutti i dettagli al proposito.} questo altro non è che
il percorso da fare a partire dalla radice dell'albero, in cui si specificano,
sulla base del loro \textsl{nome relativo} (detto anche \textit{Relative
  Distinguished Name}, o RDN) i singoli oggetti da attraversare per arrivare a
quello voluto.

Il nome relativo di un oggetto è sempre specificato nella forma
\texttt{tipo=valore}, dove \texttt{tipo} è la stringa identificativa
dell'attributo usato per indicare l'oggetto (come \texttt{dc}, \texttt{ou} o
\texttt{cn}) mentre \texttt{valore} ne indica il contenuto, pertanto si potrà
avere qualcosa come \texttt{ou=Ricerca}, o \texttt{cn=Simone Piccardi}.  Per
specificare un \textit{Distinguished Name} basta scrivere la lista dei nomi
dei singoli oggetti separati da virgole, iniziando dal fondo dell'albero fino
e risalendo fino alla radice; ad esempio nel caso di
fig.~\ref{fig:ldap_internet_tree} per indicare l'oggetto di tipo
\textit{Person} corrispondente a Simone Piccardi si userà:
\begin{Example}
cn=Simone Piccardi,ou=ricerca,o=Truelite Srl,dc=truelite,dc=it
\end{Example}

\itindend{Distinguished~Name} 

\index{suffisso~base|(} 

Tutte le volte che si installa un server LDAP occorre scegliere quale delle
due strutturazioni illustrate si vuole usare, e definire in quale punto
dell'albero compariranno i dati in esso presenti. Come accennato oggi viene
universalmente utilizzata quella dei nomi a dominio.\footnote{questo è ad
  esempio il default di Debian a partire dalla release 3.1 (Sarge).} La scelta
del punto di partenza al di sotto del quale si specificano i DN definisce
quello che viene denominato il ``\textsl{suffisso}'' di tutti i nomi degli
oggetti contenuti nell'albero. 

Talvolta si riferimento ad esso anche con il nome di ``\textsl{base}'' (nel
senso di ``\textsl{base}'' dell'albero dei dati), anche se questo nome è più
comunemente utilizzato per indicare il punto di partenza di una ricerca, dato
che esse di default coincide il suffisso. Come possibili esempi, se si è
scelto il criterio basato sui nomi a dominio, potremo avere un suffisso del
tipo \texttt{dc=truelite,dc=it}, mentre se si è scelto il criterio geografico,
potremo avere un suffisso del tipo \texttt{o=Truelite Srl,c=IT}.

\index{suffisso~base|)}


\subsection{Il formato LDIF}
\label{sec:ldap_ldif_format}

In generale ogni server LDAP mantiene i dati contenuti nell'elenco tramite un
opportuno meccanismo di supporto (per \textit{OpenLDAP} tratteremo l'argomento
in sez.~\ref{sec:ldap_server_base_config}). Per permettere di trasferire i
dati fra server diversi è stato definito un apposito formato di interscambio,
\itindex{LDIF (LDAP Data Interchange Format)} l'\textit{LDAP Data Interchange
  Format}, denominato in breve LDIF, che permette di esprimere una qualunque
voce usando dei semplici file di testo.

Lo standard che definisce il formato LDIF è specificato
dall'\href{http://www.ietf.org/rfc/rfc2849.txt}{RFC~2849} che prevede che ogni
voce nel database possa essere espressa in testo semplice, con una
schematizzazione della stessa nella forma generica seguente:
\begin{FormattedExample}
# commento
dn: \textsl{<distinguished name>}
\textsl{<nome attributo>}: \textsl{<valore>}
\textsl{<nome attributo>}: \textsl{<valore>}
...
\end{FormattedExample}

Al solito il carattere ``\texttt{\#}'' viene usato per indicare una linea di
commento e le righe vuote vengono ignorate. Ciascuna voce deve essere
introdotta da una riga iniziante per \texttt{dn:} che ne dichiari il
\textit{Distinguished Name} in modo da identificarla univocamente; questo deve
essere espresso come visto in sez.~\ref{sec:ldap_general_structure}.

Alla dichiarazione del \textit{Distinguished Name} seguono le assegnazioni dei
vari attributi nella forma illustrata, questi devono essere indicati tramite
il relativo nome (come \texttt{cn} o \texttt{objectClass}), seguito dal
carattere ``\texttt{:}'' da uno spazio singolo e poi dal valore. Per poter
utilizzare uno specifico attributo occorrerà ovviamente che l'oggetto derivi
da una \textit{objectclass} che lo definisce; se il file specifica un oggetto
che deve essere creato si può indicare da quali \textit{objectclass} derivarlo
attraverso l'attributo speciale \texttt{objectClass}.

Se una riga è troppo lunga può essere fatta proseguire sulla successiva usando
come primo carattere di quest'ultima o uno spazio o un tabulatore, questo
significa che la specificazione del nome di un attributo deve sempre essere
iniziata sul primo carattere di una riga. Si tenga inoltre conto che gli
ulteriori spazi iniziali che seguono il carattere ``\texttt{:}'' non vengono
ignorati, e che la presenza di spazi multipli all'interno dei valori viene
mantenuta tale e quale; pertanto se non si vogliono spazi aggiuntivi occorre
stare attenti a non metterceli.

Qualora il valore dell'attributo non sia esprimibile con caratteri stampabili,
o inizi per uno spazio o con i caratteri riservati ``\texttt{:}'' e
``\texttt{<}'' questo dovrà essere specificato usando una sintassi diversa; le
opzioni sono due, la prima prevede l'uso di un valore codificato in formato
\itindex{Base-64} \textit{Base-64}\footnote{questa è una semplice codifica, le
  cui specifiche si possono trovare all'interno
  dell'\href{http://www.ietf.org/rfc/rfc2045.txt}{RFC~2045}, che permette di
  esprimere un qualunque dato binario codificando lo stesso in un formato che
  prevede l'uso di 64 caratteri stampabili (le lettere maiuscole e minuscole,
  i numeri ed i caratteri ``\texttt{+}'' e ``\texttt{/}'').}, la seconda
invece prevede la lettura dei dati direttamente da una fonte di dati esterna
specificata tramite la sua URL. In tal caso la dichiarazione del valore di un
attributo userà le due forme alternative ``\texttt{::}'' e ``\texttt{:<}'' ad
esempio per specificare il valore di un attributo \texttt{jpegPhoto} si
potranno usare le sintassi:
\begin{Example}
jpegPhoto:: /9j/4AAQSkZJRgABAgAAZABkAAD/7AARRHVja3kAAQAEAAAAUAAA/+4ADkFk
 b2JlAGTAAAAAAf/bAIQAAgICAgICAgICAgMCAgIDBAMCAgMEBQQEBAQEBQYF
 BQUFBQUGBgcHCAcHBgkJCgoJCQwMDAwMDAwMDAwMDAwMDAEDAwMFBAUJBgYJ
 ...
jpegPhoto:< file:///path/to/photo.jpeg
\end{Example}

Qualora un attributo compaia più volte questo dovrà essere ripetuto su righe
distinte; infine si possono inserire più voci all'interno di uno stesso file
separandole con una o più righe vuote. Un esempio di file LDIF è allora il
seguente: 
\begin{FileExample}[label=ldapsample.ldif]
# Truelite Srl, Contacts, truelite.it
dn: cn=Truelite Srl,ou=Contacts,dc=truelite,dc=it
cn: Truelite Srl
sn: Srl
mail: info@truelite.it
telephoneNumber: 0557879597
facsimileTelephoneNumber: 0557333336
postalAddress:: VmlhIE1vbmZlcnJhdG8sIDYKRmlyZW56ZSwgRkkgNTAxNDIKSXRhbHk=
labeledURI: http://www.truelite.it
o: Truelite Srl

# Antonio Javier Russo, Contacts, truelite.it
dn: cn=Antonio Javier Russo,ou=Contacts,dc=truelite,dc=it
cn: Antonio Javier Russo
sn: Russo
mobile: 0471XXXXXX
fileAs: Russo, Antonio
mail: russo@indirizzo.fake.it
mail: antonio.russo@no.spamming.allowed.de
o: Associazione Software Libero
title: Coordinatore 
\end{FileExample}
in cui sono definite due voci nella unità operativa \texttt{Contacts} (nel
caso utilizzata per mantenere un indirizzario); si noti come trattandosi di
voci relative a tipi di dati diversi queste siano realizzate con oggetti
diversi, che hanno diversi attributi.



\subsection{Il meccanismo delle interrogazioni su LDAP}
\label{sec:ldap_query_mechanism}

Come accennato in sez.~\ref{sec:ldap_intro} LDAP nasce come un sistema in
grado di offrire dei servizi di elenco a livello globale. Questo significa
che, come accade con il meccanismo delle delegazioni del DNS, è possibile
adottare una strutturazione coerente degli alberi dei dati che consenta di
affidare ad un server le risposte relative alla sua sezione della gerarchia
globale, ottenendo così la distribuzione delle informazioni.

Il protocollo LDAP prevede una modalità generica con cui possono essere
richieste le informazioni ad un server; questa può essere indicata con
l'utilizzo di una URL estesa, così come con una URL usuale è possibile
interrogare un server web. Questa URL estesa per LDAP ha la seguente forma
generica:
\begin{Example}
ldap://server.dominio.it/base?attributi?profondità?filtro
\end{Example}

Come per le URL del web, la prima parte, dopo l'indicazione del protocollo che
prevede l'uso di \texttt{ldap} al posto di \texttt{http}, specifica
l'indirizzo del server da contattare, e consente come per le URL ordinarie
anche di indicare una eventuale porta nella forma
\texttt{ldap://server.dominio.it:porta} o di usare un indirizzo IP al posto
del nome. 

La seconda parte della URL indica invece la ricerca da effettuare, ed ha una
sua sintassi specifica composta, come mostrato nell'esempio, da diversi
elementi separati dal carattere ``\texttt{?}''.  Questi elementi sono quelli
che costituiscono il contenuto di una ricerca col protocollo LDAP e sono gli
stessi indipendentemente dalla forma specifica con cui poi li si va ad
esprimere. In sostanza sono gli argomenti previsti dalle funzioni che
realizzano le richieste di ricerca secondo il protocollo e quelli che vedremo
in sez.~\ref{sec:ldap_search} possono essere indicati al comando
\texttt{ldapsearch}.

Il primo elemento è l'indicazione del punto di partenza della ricerca
all'interno dell'albero dei dati, la cosiddetta \textsl{base} della ricerca,
che deve essere espressa con il suo \textit{Distinguished Name}. In genere
corrisponde al \textsl{suffisso} della radice dell'albero illustrato in
sez.~\ref{sec:ldap_general_structure}, ma le ricerche possono essere
effettuate a partire da qualunque profondità e non solo dalla radice.

Il secondo elemento indica la lista, separata da virgole, dei nomi degli
attributi dei quali si vuole ottenere il valore; se non specificato verranno
restituiti i valori di tutti gli attributi presenti in ciascun oggetto che
corrisponde alla ricerca.

Il terzo elemento è una parola chiave che indica la \textsl{profondità} della
ricerca all'interno dell'albero, ed è espresso da uno dei valori di
tab.~\ref{tab:ldap_scope_values}. Il quarto ed ultimo elemento è un
\textsl{filtro di ricerca}; il protocollo infatti consente di indicare al
server un criterio di selezione degli oggetti dei quali si vogliono ottenere i
dati. Tratteremo con maggiore dettaglio il significato di questi ultimi due
elementi in sez.~\ref{sec:ldap_search}.

Infine dato che esistono diversi meccanismi di connessione con cui si può
contattare un server (torneremo su questo in
sez.~\ref{sec:ldap_client_base_config} e
sez.~\ref{sec:ldap_server_base_config}), l'identificativo iniziale della URI,
oltre a quanto mostrato nell'esempio precedente, può assumere anche una delle
tre forme illustrate in tab.~\ref{tab:ldap_URL}, che identificano altrettante
modalità diverse con cui collegarsi al server.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|l|}
    \hline
    \textbf{Indicatore} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{ldap://} & indica una normale connessione tramite socket TCP.\\
    \texttt{ldaps://}& indica una connessione di rete cifrata con SSL (vedi
                       sez.~\ref{sec:ldap_SSL}) \\
    \texttt{ldapi://}& indica una connessione ad un socket locale.\\
    \hline
  \end{tabular}
  \caption{Gli indicatori di protocollo per le URL del servizio LDAP.} 
  \label{tab:ldap_URL}
\end{table}

Il caso più comune di uso di interrogazione col protocollo LDAP resta quello
in cui un client effettua una richiesta ad un server via rete (che si usi o
meno SSL dal punto di vista del protocollo è indifferente) e ottiene
direttamente da questo la risposta, secondo lo schema illustrato in
fig.~\ref{fig:ldap_direct_request}.  Questo caso ovviamente è quello in cui il
server interrogato è quello che gestisce i dati dell'albero per cui è stata
eseguita la richiesta, che quando si usano delle risorse \textsl{locali} è
quello che avviene sempre.  Se si fa una analogia con il DNS questo è quanto
equivale all'effettuare una richiesta per il dominio di cui è responsabili.

\begin{figure}[!htb]
  \centering \includegraphics[width=10cm]{images/req_direct}
  \caption{Struttura di una richiesta diretta ad un server LDAP.}
  \label{fig:ldap_direct_request}
\end{figure}

Benché ormai LDAP venga utilizzato prevalentemente per mantenere informazioni
locali secondo lo scenario di fig.~\ref{fig:ldap_direct_request}, il
protocollo rende comunque possibile l'uscita dall'ambito locale e l'esecuzione
di interrogazioni generiche anche in un ambito globale. In questo caso il
meccanismo di funzionamento del protocollo è simile a quello del DNS, è
necessario cioè inserire il server a cui si fanno le richieste all'interno di
una gerarchia globale, così che diventi possibile redirigere le richieste
attinenti ad altri rami di albero verso server di livello superiore che
possano a loro volta inviarle a quei server subordinati che mantengono le
informazioni richieste.

\itindbeg{referral}

\begin{figure}[!htb]
  \centering \includegraphics[width=10cm]{images/req_referral}
  \caption{Il meccanismo dei \textit{referral} di LDAP.}
  \label{fig:ldap_referral_reques}
\end{figure}

La redirezione avviene tramite il meccanismo detto dei \textit{referral}, che
si è illustrato in fig.~\ref{fig:ldap_referral_reques}.  Si può cioè
configurare un server LDAP che fornisce dati per un certa sezione di una
gerarchia globale perché per richieste che escono da detta sezione possa
fornire un \textsl{riferimento} ad un altro server a cui ripetere la
richiesta. Questo può essere sia un server di livello superiore che sia in
grado di rispondere direttamente o di fornire ulteriori riferimenti ad altri
server sotto di lui che mantengono i dati quella particolare sezione di
albero.

La potenza del meccanismo dei \textit{referral} è che, come per il DNS, esso è
del può essere reso del tutto trasparente rispetto alle richieste, per le
quali riceverà solo la risposta finale; occorre precisare però che non tutti i
client sono in grado di seguire i \textit{referral} in maniera autonoma, ma in
questo caso esiste una estensione del server \textit{OpenLDAP} in grado di
fare il lavoro per loro conto.

Ovviamente perché tutto questo sia possibile occorre, come per il DNS, la
presenza di una gerarchia globale di server. Benché questa funzionalità sia
scarsamente utilizzata dato che l'uso prevalente di LDAP è per mantenere dati
ed informazioni relativi alla propria organizzazione, una tale gerarchia è
possibile e ad esempio lo stesso progetto della \textit{OpenLDAP Foundation}
gestisce un servizio di questo tipo su \url{ldap://root.openldap.org/}.

Si tenga presente comunque che anche se non si è interessati a far parte di un
servizio strutturato a livello globale questa caratteristica di LDAP risulta
particolarmente utile in quanto consente, anche all'interno di una singola
organizzazione, di suddividere le informazioni (ad esempio relative alle varie
divisioni) su server diversi messi in relazione fra loro e mantenuti coerenti
in un unico albero grazie alla presenza dei riferimenti.

\itindend{referral}


\section{Installazione e configurazione del server}
\label{sec:slapd_installazione}

Tratteremo in questa sezione l'installazione del server LDAP fornito dal
progetto \textit{OpenLDAP}, che oltre al server fornisce alcuni programmi di
gestione, le librerie ed alcuni client per l'accesso ad un servizio LDAP (che
tratteremo in sez.~\ref{sec:ldap_client}).  Il pacchetto è sviluppato dalla
\textit{OpenLDAP Foundation} e viene usato come implementazione di riferimento
di LDAP in tutte le distribuzioni di GNU/Linux, anche se con l'acquisto da
parte di RedHat del server LDAP di di Netscape, esistono anche delle
alternative completamente diverse, che comunque non prenderemo in esame.


\subsection{Installazione ed avvio del servizio}
\label{sec:slapd_install}

Tutte le più importanti distribuzioni forniscono versioni già pacchettizzate
di \textit{OpenLDAP}, per cui in generale tutto quello che serve è usare il
rispettivo gestore di pacchetti per eseguire l'installazione. In certi casi
però la versione fornita potrebbe non avere tutte le estensioni o il supporto
per le funzionalità volute o non essere sufficientemente aggiornata per cui
può risultare necessario reinstallare dai sorgenti. Questa è anche la sola
modalità supportata dagli sviluppatori, che in genere rispondono soltanto a
richieste relative all'ultima versione rilasciata. I sorgenti di
\textit{OpenLDAP} sono disponibili sul sito del progetto a partire dalla
pagina web \url{http://www.openldap.org/software/download/}; i file sono
sempre nella forma \texttt{openldap-\textsl{VERSIONE}.tgz}, che vanno
scompattati al solito nella directory in cui si eseguirà la compilazione.

Molte delle funzionalità di \textit{OpenLDAP} si basano su altri pacchetti e
librerie, per poterle utilizzare è ovviamente necessario che questi siano
presenti; non è fondamentale che siano presenti tutti (lo script di
configurazione consente di selezionare quelli che servono) ma ovviamente per
quelli che si intende utilizzare dovranno essere presenti anche i relativi
pacchetti di sviluppo.  L'elenco dei prerequisiti è il seguente, torneremo
sulla configurazione di alcune di queste funzionalità in
sez.~\ref{sec:ldap_advanced}:
\begin{basedescript}{\desclabelwidth{3.0cm}}
\item[SSL/TLS] Per l'uso di connessioni cifrate con il \textit{Transport Layer
    Security}\footnote{questa è la standardizzazione ufficiale fatta dalla
    IETF del protocollo di cifratura delle comunicazioni a livello di socket
    introdotta con il \textit{Secure Socket Layer} di Netscape, per maggiori
    dettagli si consulti sez.~2.1.3 di \cite{SGL}.}  \textit{OpenLDAP}
  richiede la presenza delle librerie OpenSSL o delle alternative GnuTLS; non
  si potrà avere una piena conformità allo standard LDAPv3 se
  \textit{OpenLDAP} non rileva la presenza di una libreria che supporti SSL.
\item[Kerberos] \textit{OpenLDAP} supporta i servizi di autenticazione basati su
  Kerberos, in particolare si possono utilizzare le due implementazioni libere
  di Kerberos V: \href{http://www.pdc.kth.se/heimdal/}{Heimdal} e
  \href{http://web.mit.edu/kerberos/www/}{MIT Kerberos}.
\item[SASL] \textit{OpenLDAP} può utilizzare  SASL
  (\textit{Simple Authentication and Security Layer}) per l'autenticazione
  degli utenti.  Questo richiede la presenza delle librerie
  \href{https://cyrusimap.org/docs/cyrus-sasl/2.1.25/}{Cyrus SASL} senza le
  quali non si potrà avere una piena conformità allo standard LDAPv3.
% \item[DBM] per mantenere i suoi dati un server OpenLDAP necessita del supporto
%   di un database su cui salvarli, ed nelle versioni recenti questo avviene
%   utilizzando, sia pure con possibili modalità diverse, Berkley DB, del quale
%   necessitano le librerie di gestione.\footnote{nelle vecchie versioni era
%     possibile supportare anche usare una interfaccia generica aderente a alla
%     versione originale del DBM di BSD (come GDBM, disponibile su
%     \url{http://www.gnu.org/software/gdbm/}), rimossa per le scarse
%     prestazioni e la complessità di manutenzione.}
\item[TCP wrapper] \textit{OpenLDAP} supporta i \textit{TCP wrapper} per un
  controllo di accesso elementare degli accessi sulla base degli indirizzi di
  provenienza delle connessioni al server, che può essere utilizzato qualora
  essi siano stati installati.
\end{basedescript}

La procedura di installazione dei sorgenti è effettuata con gli
\textit{Autotools GNU},\footnote{per una descrizione più dettagliata di questa
  procedura si può fare riferimento a sez.~4.2.1 di \cite{AGL}.} e viene
controllata dallo script \texttt{configure}.  Lo script di configurazione
riconosce le opzioni standard degli autotools, e permette di abilitare le
varie funzionalità aggiuntive di \textit{OpenLDAP} con le opzioni
\texttt{-{}-enable-FEATURE} e \texttt{-{}-with-PACKAGE}, dove \texttt{FEATURE}
e \texttt{PACKAGE} indicano rispettivamente una funzionalità da abilitare o un
pacchetto esterno da utilizzare. Un elenco delle opzioni disponibili si può
ottenere invocando lo script di configurazione come:
\begin{Console}
$ \textbf{./configure --help}
...
Optional Features:
  ...
  --enable-syslog         enable syslog support [auto]
  --enable-proctitle      enable proctitle support [yes]
  --enable-ipv6           enable IPv6 support [auto]
  --enable-local          enable AF_LOCAL (AF_UNIX) socket support [auto]
...
SLAPD Backend Options:
    ...
    --enable-hdb          enable Hierarchical DB backend no|yes|mod [yes]
    --enable-ldap	  enable ldap backend no|yes|mod [no]
    --enable-mdb	  enable mdb database backend no|yes|mod [yes]
...
SLAPD Overlay Options:
    ...
    --enable-accesslog    In-Directory Access Logging overlay no|yes|mod [no]
    --enable-auditlog     Audit Logging overlay no|yes|mod [no]
    --enable-collect      Collect overlay no|yes|mod [no]
    --enable-constraint   Attribute Constraint overlay no|yes|mod [no]
    ...

Optional Packages:
  ...
  --with-cyrus-sasl       with Cyrus SASL support [auto]
  --with-fetch            with fetch(3) URL support [auto]
  --with-threads          with threads [auto]
...
\end{Console}
%$

In tab.~\ref{tab:ldap_configure_options} si sono riportate le opzioni
principali con il relativo valore di default, si tenga presente che gli
\textit{overlay} (vedi sez.~\ref{sec:ldap_overlay}) che estendono le
funzionalità rientrano nelle funzionalità e si abilitano con opzioni del tipo
\texttt{-{}-enable-OVERLAY} dove \texttt{OVERLAY} è il nome dello stesso.
Qualora si voglia abilitare una funzionalità che usualmente non è attiva (ad
esempio i TCP wrapper) la si dovrà abilitare esplicitamente passandola come
argomento al comando. 

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|c|p{8cm}|}
    \hline
    \textbf{Opzione} & \textbf{Default} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{-{}-enable-debug}    & si & abilita il supporto per il debug.\\
    \texttt{-{}-enable-syslog}   &auto& abilita il supporto per l'uso del
                                        \textit{syslog}.\\ 
    \texttt{-{}-enable-ipv6}     &auto& abilita il supporto per IPv6.\\
    \texttt{-{}-enable-local}    &auto& abilita il supporto per i socket
                                        locali.\\
    \texttt{-{}-enable-cleartext}& si & abilita il supporto per mantenere le
                                        password in chiaro.\\
    \texttt{-{}-enable-crypt}    & no & abilita il supporto per mantenere le
                                        password cifrate con \texttt{crypt}.\\
    \texttt{-{}-enable-modules}  & no & abilita il supporto dinamico per i
                                        moduli.\\
    \texttt{-{}-enable-wrappers} & no & abilita l'uso dei \textit{TCP
                                        wrapper}.\\ 
    % \texttt{-{}-enable-bdb}      & si & abilita il supporto dei dati su
    %                                     Berkley DB classico.\\
    \texttt{-{}-enable-hdb}      & si & abilita il supporto più avanzato dei
                                        dati su Berkley DB.\\
    \texttt{-{}-enable-mdb}      & si & abilita il nuovo supporto dei dati su
                                        database in memoria (mdb).\\
    \texttt{-{}-enable-ldap}     & no & abilita il supporto per il proxy su un
                                        altro server LDAP.\\
    % \texttt{-{}-enable-ldbm}     & no & abilita il supporto dei dati
    %                                     sull'interfaccia generica DBM.\\
    % \texttt{-{}-enable-perl}     & no & abilita il supporto dei dati 
    %                                     tramite script perl.\\
    % \texttt{-{}-enable-shell}    & no & abilita il supporto dei dati 
    %                                     tramite script di shell.\\
    \texttt{-{}-enable-sql}      & no & abilita il supporto dei dati
                                        su un database relazionale.\\
    \texttt{-{}-enable-ppolicy}  & si & abilita l'\textit{overlay}
                                        \texttt{ppolicy}.\\ 
    \texttt{-{}-enable-syncprov} & si & abilita l'\textit{overlay}
                                        \texttt{syncprov} per la 
                                        replicazione (vedi
                                        sez.~\ref{sec:ldap_replication}).\\ 
    \texttt{-{}-with-cyrus-sasl} &auto& abilita l'utilizzo delle librerie SASL
                                        di Cyrus.\\
    \texttt{-{}-with-threads}    &auto& abilita l'utilizzo dei thread.\\
    \texttt{-{}-with-tls}        &auto& abilita l'utilizzo del TLS con
                                        OpenSSL.\\ 
    \hline
  \end{tabular}
  \caption{Le opzioni usate dallo script di configurazione per
    la compilazione di \textit{OpenLDAP}.}
  \label{tab:ldap_configure_options}
\end{table}

Una volta eseguito con successo lo script di configurazione, a differenza di
quanto avviene normalmente con gli \textit{autotools}, si dovranno costruire
le dipendenze con \texttt{make depend} come riportato sull'ultima riga
stampata dallo stesso, e poi compilare con \texttt{make}. A questo punto è
anche disponibile il comando \texttt{make test} per verificare il
funzionamento del pacchetto. Infine \texttt{make install}, eseguito con i
privilegi di amministratore installerà sia il server, che le librerie, che i
programmi di utilità a riga di comando (di default sotto \texttt{/usr/local}).

Se invece si procede all'installazione dalla versione fornita dalla propria
distribuzione si tenga presente che in molti casi le varie parti di
\textit{OpenLDAP} sono separate in pacchetti diversi; ad esempio nel caso di
Debian il server è nel pacchetto \texttt{slapd}, le librerie nel pacchetto
\texttt{libldap-\textsl{versione}} e i programmi di utilità a riga di comando
in \texttt{ldap-utils}, mentre per RedHat/CentOS il server è nel pacchetto
\texttt{openldap-servers}, le librerie nel pacchetto \texttt{openldap} ed i
programmi in \texttt{openldap-clients}. A questi si aggiungono poi, qualora si
debbano compilare altri programmi che li richiedono, i pacchetti di sviluppo.

Qualora si sia installato \textit{OpenLDAP} dai sorgenti si troverà un file di
configurazione di esempio per il server in \texttt{/usr/local/etc/openldap};
in genere i pacchetti delle distribuzioni installano i file di configurazione
in una directory direttamente sotto \texttt{/etc}, ad esempio
\texttt{/etc/ldap} per Debian e \texttt{/etc/openldap} per RedHat/CentOS.  In
questa directory si trova il file di configurazione delle librerie,
\texttt{ldap.conf}, il file di configurazione del server, \texttt{slapd.conf},
oppure, nelle versioni più recenti, la directory \texttt{slapd.d}, oltre ad
eventuali altri file di configurazione.

Su una macchina che deve fare da server LDAP, benché non siano strettamente
necessarie, si devono installare tutte le componenti. Per utilizzare
\textit{OpenLDAP} a livello client invece l'unica componente necessaria è la
libreria \texttt{libldap2} che viene usata da tutti i programmi (comprese le
utilità fornite da \textit{OpenLDAP} stesso) che devono interrogare un server
LDAP; in genere si installano anche i programmi di utilità.

Nel caso si usi Debian installando il server il sistema del \textit{debconf}
si curerà anche di chiedere alcuni dei parametri di base per la creazione di
una struttura minimale per il proprio albero dei dati (in sostanza le
informazioni necessarie a stabilire quale sarà la propria \textsl{radice
  locale}), ed una password da associare ad un utente amministrativo che avrà
accesso completo al database. Installando il client \textit{debconf} chiede
invece i dati del server e della radice da usare come valore preimpostato (le
ultime versioni del pacchetto cercano di automatizzare al massimo il
procedimento usando il dominio della macchina specificato in fase di
installazione).

Una volta installato il server questo potrà essere avviato direttamente con il
comando \index{demone!\texttt{slapd}} \texttt{slapd}. Questo, se eseguito
senza l'opzione \texttt{-d} che abilita la modalità di debug, crea un nuovo
processo figlio e si dissocia dal terminale continuando a girare come demone,
utilizzando le impostazioni che trova nel file di configurazione
\texttt{/etc/ldap/slapd.conf} o con i dati del database di configurazione
nella directory \texttt{/etc/ldap/slapd.d} (che tratteremo in
sez.~\ref{sec:ldap_server_base_config}). Un file di configurazione alternativo
può essere indicato con l'opzione \texttt{-f}, ed una directory alternativa
con l'opzione \texttt{-F}.

Di default il server si pone in ascolto per connessioni TCP in chiaro su tutte
le interfacce di rete usando la porta standard del servizio LDAP, la 389.  Si
può però modificare questo comportamento con l'opzione \texttt{-h} che prende
come parametro una URL con gli indicatori di tab.~\ref{tab:ldap_URL}, che
definisce le modalità (e l'indirizzo locale) con cui ci si potrà connettere al
server.  Come riportato in tab.~\ref{tab:ldap_URL}, oltre la modalità classica
si ha a disposizione, se si sono abilitati i relativi supporti, la possibilità
di usare connessioni cifrate con SSL/TLS e la connessione su socket locali.

Nei primi due casi si dovranno specificare nella URL l'indirizzo IP e la porta
nella sintassi classica delle URL, cioè qualcosa nella forma
``\texttt{ldap://indirizzo:porta/}'' per ascoltare in chiaro sulla porta e
l'indirizzo IP specificati, o qualcosa nella forma ``\texttt{ldaps:///}'' per
ascoltare sull'indirizzo generico e sulla porta standard, che avendo richiesto
SSL, stavolta è la 636. Invece nel terzo caso si dovrà specificare il pathname
assoluto del socket locale.\footnote{si ricordi che i socket locali sono un
  meccanismo di intercomunicazione fra processi basato sull'uso di un file
  speciale, di tipo socket; per maggiori dettagli si veda la sez.~1.2 di
  \cite{AGL}.}

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Indicatore} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{-d \textsl{N}}   & indica il livello di debug, secondo i valori di
                               tab.~\ref{tab:slapd_debug_bits}.\\
    \texttt{-f \textsl{file}}& indica un file di configurazione alternativo.\\
    \texttt{-F \textsl{dir}} & indica una directory di configurazione
                               alternativa.\\ 
    \texttt{-g \textsl{group}}& indica il gruppo per conto del quale eseguire
                                il server.\\ 
    \texttt{-h \textsl{uri}} & indica a quali collegamenti risponde il server.\\
    \texttt{-l \textsl{fac}} & indica quale facility usare nel sistema del
                               \textit{syslog}.\\ 
%    \texttt{-r} & indica una directory di \texttt{chroot}.\\
    \texttt{-s \textsl{prio}}& indica la priorità da assegnare ai messaggi di
                               \texttt{slapd} nel sistema del
                               \textit{syslog}.\\ 
    \texttt{-t} & esegue un controllo sintattico del file di configurazione
                  (è deprecato con la 2.4, sostituito da \texttt{slaptest}).\\
    \texttt{-u \textsl{user}}& indica l'utente per conto del quale eseguire il
                               server.\\ 
   \hline
  \end{tabular}
  \caption{Opzioni del comando \texttt{slapd}.}
  \label{tab:slapd_options}
\end{table}

Si sono riportate le altre opzioni principali di \texttt{slapd} in
tab.~\ref{tab:slapd_options}. Al solito per l'elenco completo si può fare
riferimento alla pagina di manuale del comando; inoltre buona parte di esse
può essere specificata con apposite direttive nel file di configurazione (vedi
sez.~\ref{sec:ldap_server_base_config}). Normalmente per lanciare il server è
sempre opportuno utilizzare l'opportuno script di avvio messo a disposizione
dalla propria distribuzione, nel caso di Debian \texttt{/etc/init.d/slapd},
per RedHat/CentOS \texttt{/etc/init.d/ldap}, oppure, nelle versioni più
recenti che usano \texttt{systemd}, le relative \textit{unit file}.

Nel caso di Debian poi in \texttt{/etc/defaults/slapd} sono utilizzabili le
due variabili di ambiente \texttt{SLAPD\_SERVICES} e \texttt{SLAPD\_OPTIONS}
da utilizzare rispettivamente per passare agli script di avvio del servizio
una diversa URL rispetto al default di \texttt{ldap:///} (la variabile deve
contenere il valore del parametro per l'opzione \texttt{-h}) e per indicare
eventuali opzioni aggiuntive (ad esempio di debug) da usare all'avvio del
server. Lo stesso effetto si può ottenere con RedHat/Fedora/CentOS usando il
file \texttt{/etc/sysconfig/ldap} e le relative variabili.\footnote{il sistema
  è in questo caso meno flessibile perché pur restando \texttt{SLAPD\_OPTIONS}
  non è previsto un equivalente di \texttt{SLAPD\_SERVICES}, ma il parametro
  di \texttt{-h} viene deciso con i valori di \texttt{SLAPD\_LDAP},
  \texttt{SLAPD\_LDAPS}, \texttt{SLAPD\_LDAPI} che sono nella forma
  \texttt{yes}/\texttt{no} e non consentono di passare una URI.}

Una delle opzioni più importanti è \texttt{-d} che attiva la modalità di
debug; essa permette di eseguire il server interattivamente, ottenendo così i
messaggi direttamente sul terminale. L'opzione richiede un parametro che
indica quali informazioni di debug debbano essere stampate, questo viene
interpretato come maschera binaria, ed ogni bit attiva la stampa di una certa
classe di messaggi, secondo lo schema di tab.~\ref{tab:slapd_debug_bits}.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|c|p{8cm}|}
    \hline
    \textbf{Indicatore}&\textbf{Sigla}&\textbf{Significato} \\
    \hline
    \hline
      0 & -- & nessuna informazione.\\
      1 &\texttt{trace} & traccia le chiamate alle singole funzioni.\\
      2 &\texttt{packet}& informazioni sulla gestione dei pacchetti.\\
      4 &\texttt{args}  & informazioni di debug generico.\\
      8 &\texttt{conns} & informazioni sulla gestione della connessione.\\
     16 &\texttt{BER}   & stampa i pacchetti ricevuti ed inviati.\\
     32 &\texttt{filter}& informazioni sull'uso dei filtri.\\
     64 &\texttt{config}& informazioni sulla scansione della configurazione.\\
    128 &\texttt{ACL}   & informazioni sull'uso delle regole di accesso.\\
    256 &\texttt{stats} & statistiche delle operazioni e delle connessioni.\\
    512 &\texttt{stats2}& statistiche sulle voci inviate.\\
   1024 &\texttt{shell} & stampa la comunicazioni con il \textit{backend} di
                          shell (vedi sez.~\ref{sec:ldap_server_base_config}).\\
   2048 &\texttt{parse} & informazioni sulla scansione delle voci.\\
   4096 &\texttt{cache} & informazioni sulla cache (inutilizzate).\\
   8192 &\texttt{index} & informazioni sugli indici (inutilizzate).\\
  16384 &\texttt{sync}  & informazioni sulla replicazione LDAPSync.\\
  32768 &\texttt{none}  & nessuna informazione.\\
    -1  &  & abilita tutte le informazioni.\\
     ?  &  & stampa i valori precedenti.\\
   \hline
  \end{tabular}
  \caption{Significato dei bit di debug.}
  \label{tab:slapd_debug_bits}
\end{table}

Specificando un valore nullo si disattivano i messaggi di debug, mentre con -1
si attivano tutti quanti; in genere per non restare affogati nell'output del
server è opportuno selezionare solo i messaggi della classe cui fa riferimento
il problema che si vuole investigare; questo si fa semplicemente sommando i
valori riportati nella prima colonna di tab.~\ref{tab:slapd_debug_bits}. Così
se si vogliono verificare le modalità della connessione su SSL/TLS e la
verifica delle regole di accesso si potrà invocare il programma come:
\begin{Console}
# \textbf{slapd -d 8 -h ldaps:///} 
\end{Console}


\subsection{La configurazione tradizionale del server}
\label{sec:ldap_server_base_config}

La configurazione del server è ovviamente molto più complessa e ne tratteremo
in questa sezione solo gli aspetti generali, rimandando a
sez.~\ref{sec:ldap_advanced} i dettagli relativi alle funzionalità più
avanzate. Come accennato il file di configurazione di default è
\index{configurazione!\texttt{/etc/ldap/slapd.conf}} \texttt{slapd.conf};
questo contiene una serie di direttive, una per riga, nella forma classica di
una parola chiave seguita da un valore, separati da uno o più spazi o altri
caratteri vuoti. Quando un valore contiene degli spazi questo deve essere
indicato delimitandolo con delle virgolette, se queste ultime sono contenute
in un valore devono essere protette dal carattere di escape
``\texttt{\bslash}'' che può essere usato anch'esso nello stesso modo.  Come
al solito le righe che iniziano per un ``\texttt{\#}'' sono considerate
commenti e vengono ignorate come le righe vuote,\footnote{stando attenti a che
  le righe siano effettivamente vuote: infatti la presenza di uno spazio
  all'inizio di una riga implica che questa è la continuazione della
  precedente, e si possono avere effetti inaspettati quando una riga
  \textsl{sembra} essere vuota ma non lo è davvero.} infine una riga che
inizia con uno spazio è considerata la continuazione della precedente.

A partire dalla versione 2.4 di \textit{OpenLDAP} inoltre la configurazione
può essere effettuata usando direttamente il protocollo LDAP stesso (ci
torneremo in sez.~\ref{sec:slapd_database_config}), con un ramo di albero
dedicato, \texttt{cn=config}, i cui dati vengono mantenuti in forma di file
LDIF in una specifica gerarchia di directory sul filesystem. Il server
comunque riconosce ancora il file \texttt{slapd.conf}, ed in questa sezione
faremo riferimento solo alla modalità classica.

Il file prevede tre tipi di direttive di configurazione: quelle generali che
sono applicabili a tutto il server, quelle specifiche che sono applicabili
solo ad un tipo di supporto e quelle ancor più specifiche che si applicano ad
un singolo database. Una delle caratteristiche più interessanti di
\textit{OpenLDAP} infatti è che una singola istanza del server \texttt{slapd}
può gestire diversi database, inoltre per mantenere i dati è possibile usare
diversi supporti, (quelli che in gergo vengono chiamati \textit{backend}) che
sono disponibili in forma modulare.

La possibilità di avere diversi \textit{backend} consente così di svincolare
completamente la parte del server che gestisce le operazioni previste dal
protocollo LDAP, dal codice che gestisce i dati presenti in un database,
garantendo una enorme flessibilità nel mantenimento degli stessi sui supporti
e le modalità più varie.  Ad esempio è con uno di questi supporti che si può
gestire la cosiddetta \textit{proxy-replication} che tratteremo in
sez.~\ref{sec:advanced-replication}.

Due direttive, \index{OpenLDAP!direttiva~server!\texttt{backend}}
\texttt{backend} e \index{OpenLDAP!direttiva~server!\texttt{database}}
\texttt{database}, servono a definire l'inizio di una sezione del file di
configurazione in cui si immettono rispettivamente le direttive di
configurazione relative ad un certo supporto (volte a controllarne le
caratteristiche specifiche) e ad uno specifico database (coi dati ad esso
attinenti); la fine di una sezione è delimitata dall'inizio di un'altra
sezione con la presenza di una di queste due direttive, o dalla fine del file
di configurazione. 

Le direttive inoltre prevedono una gerarchia ed un ambito di validità. Quelle
globali possono essere usate anche all'interno di una sezione \texttt{backend}
o \texttt{database} ma in tal caso il loro valore sarà applicato soltanto a
detta sezione, e lo stesso vale per direttive relative ad un supporto usate in
una sezione \texttt{database}. Inoltre una direttiva utilizzata in una sezione
\texttt{backend} soprassiederà il valore assegnato globalmente, ed una
direttiva utilizzata in una sezione \texttt{database} soprassiederà sia il
valore globale che quello assegnato in una sezione \texttt{backend}.  Se una
direttiva compare più volte all'interno di una stessa sezione verrà utilizzato
il valore dell'ultima assegnazione.  Questo in sostanza comporta una struttura
del tipo:
\begin{FormattedExample}
# Configurazioni di carattere generale
\textsl{<direttiva generale>} \textsl{<valore>}
\textsl{<direttiva generale>} \textsl{<valore>}
...
# Primo tipo di supporto
backend \textsl{<tipo1>}
\textsl{<direttiva specifica per supporto>} \textsl{<valore>}
...
database \textsl{<tipo1>}
\textsl{<direttiva specifica per database>} \textsl{<valore>}
...
database \textsl{<tipo1>}
\textsl{<direttiva specifica per database>} \textsl{<valore>}
...
# Secondo tipo di supporto
backend \textsl{<tipo2>}
\textsl{<direttiva specifica per supporto>} \textsl{<valore>}
...
database <tipo2>
\textsl{<direttiva specifica per database>} \textsl{<valore>}
...
\end{FormattedExample}
in cui prima si dichiara il tipo di supporto, seguito dalle configurazioni
specifiche dello stesso, e poi i vari database che utilizzano quel supporto
(con le loro configurazioni specifiche). Si tenga presente che il server non
esegue controlli sulla correttezza della sintassi, per cui si faccia
attenzione a rispettare la struttura illustrata.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|l|}
    \hline
    \textbf{Tipo} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{mdb}   & usa il nuovo default del
                     \textit{Lightweight Memory-Mapped DB}.\\ 
    \texttt{bdb}   & usa Berkley DB (con vecchia interfaccia, deprecata).\\ 
    \texttt{hdb}   & nuova interfaccia (evoluzione di \texttt{bdb}) per
                     Berkley DB.\\
    \texttt{ldif}  & mantiene i dati su file LDIF nel filesystem.\\
    \texttt{ndb}   & interfaccia verso le NDB API di MySQL, sperimentale.\\
    % \texttt{ldbm}  & usa un qualunque database compatibile con l'interfaccia
    %                  DBM.\\ % rimosso
    \hline
    \texttt{ldap}  & fa da proxy verso un altro server LDAP.\\
    \texttt{meta}  & fa da proxy verso un gruppo di server LDAP.\\
    \texttt{sql}   & mappa i dati in un database relazionale su LDAP.\\
    \texttt{relay} & fa da proxy nei confronti di un database locale
                     (sperimentale).\\
    \hline
    \texttt{shell} & ottiene i dati da script di shell.\\
    \texttt{perl}  & ottiene i dati da script Perl.\\
    \texttt{sock}  & ottiene i dati da un altro programma con un socket.\\
    \texttt{monitor}&riporta dati statistici del server.\\
    \texttt{passwd}& riporta i dati di \texttt{/etc/passwd}.\\
    \texttt{dnssrv}& riporta i dati da un DNS.\\
    \texttt{null}  & non fa nulla.\\
    \hline
  \end{tabular}
  \caption{I vari tipi di supporto per i dati di \texttt{slapd}.}
  \label{tab:ldap_backend_type}
\end{table}

Entrambe le direttive \texttt{backend} e \texttt{database} prendono come
argomento uno degli identificativi dei vari supporti disponibili riportati in
tab.~\ref{tab:ldap_backend_type}, un database infatti deve comunque essere
mantenuto in un qualche supporto. Fino alla versione 2.3 di \textit{OpenLDAP}
il supporto consigliato dal progetto era \texttt{bdb}, che indica l'utilizzo
delle librerie Berkley DB (si ricordi quanto detto in
sez.~\ref{sec:slapd_install}) che offrono funzionalità avanzate per le
transazioni\footnote{le cosiddette funzionalità \textit{ACID}, un acronimo che
  indica le quattro proprietà di \textit{Atomicity}, \textit{Consistency},
  \textit{Isolation}, e \textit{Durability} che assicurano la consistenza dei
  dati e la possibilità di riportare il database in uno stato coerente anche
  in caso di terminazioni anormali.} e consente l'accesso simultaneo in
lettura e scrittura da più processi. Nelle versioni più recenti viene invece
consigliato l'uso del nuovo \textit{backend} \texttt{hdb}, (era ad esempio il
default installato anche su Debian a partire dalla versione 5.0) che si
appoggia sempre a Berkley DB ed ha le stesse caratteristiche di \texttt{bdb},
ma con alcune ottimizzazioni sulla gestione degli indici, che sono mantenuti
in memoria e non su file (ottenendo maggiori prestazioni in scrittura, ma un
avvio più lento).

A partire dalla versione 2.4.39 il default è diventato invece \texttt{mdb}, un
database in memoria sviluppato specificamente come supporto per
\textit{OpenLDAP}, che assicura prestazioni nettamente superiori e che ha
iniziato a soppiantare i precedenti, ed è diventato il default di Debian a
partire dalla versione 8.0. Rispetto ai \textit{backend} basati su Berkley DB
presenta un notevole vantaggio in velocità ed un configurazione molto più
semplice, non esiste motivo (a parte l'utilizzo di una versione non
sufficientemente recente del server) per non utilizzarlo.


%
% ldbm non è più presente
%
% L'unico altro supporto che è stato effettivamente utilizzato in ambiti di
% produzione, ma ormai sostanzialmente abbandonato, è \texttt{ldbm} che
% implementa l'interfaccia generica di DBM, (la libreria di funzioni per gestire
% un database su file all'interno di qualunque programma) da cui deriva anche
% Berkley DB. L'interfaccia non supporta le funzionalità avanzate, e non sono
% disponibili le transazioni; questo comporta che mentre è possibile l'accesso
% in lettura da più processi, quello in scrittura deve essere
% esclusivo.\footnote{cioè un accesso in scrittura deve avvenire senza che in
%   quel momento venga compiuta sul database una qualunque altra operazione, sia
%   di lettura che di scrittura.}

Tutti i supporti disponibili sono elencati in
tab.~\ref{tab:ldap_backend_type}.  In generale i supporti si possono
suddividere in tre categorie generali: quelli che mantengono effettivamente
dei dati, quelli che servono come intermediari per dati mantenuti altrove, e
quelli che generano i dati al volo. Il primo gruppo, quello usato normalmente,
contiene i precedenti \texttt{mdb}, \texttt{bdb} e \texttt{hdb}. A questi si
aggiungono \texttt{ldif}, che scrive i dati su dei file LDIF direttamente sul
filesystem (è quella usata internamente per la nuova modalità di
configurazione del server direttamente via LDAP) e lo sperimentale
\texttt{ndb} che consente di inserire i dati su un cluster MySQL usando la API
omonima (NDB).

Al secondo gruppo appartengono \texttt{ldap}, \texttt{meta}, \texttt{sql} e lo
sperimentale \texttt{relay}; il primo serve a fare da proxy per un altro
server, mentre il secondo può fare da proxy per un pool di server che
condividono la gestione di una sezione di albero. Il terzo permette di
utilizzare attraverso LDAP i dati già presenti in un database relazionale,
come accennato infatti il modello di dati di un albero LDAP non si adatta alla
struttura a tabelle di un database relazionale;\footnote{una interessante
  discussione di questa problematica si trova nelle FAQ di \textit{OpenLDAP}
  all'indirizzo \url{http://www.openldap.org/faq/data/cache/378.html}.}
pertanto questo \textit{backend} non è un sostituto per mantenere i dati di un
albero quanto una soluzione che consente, fornendo le opportune associazioni,
di mappare il contenuto di un database relazionale su un albero.  Infine
\texttt{relay} permette di creare un proxy al contenuto di un database locale
(e può essere utilizzato per creare delle \textsl{viste} sullo stesso).

Al terzo gruppo appartengono \texttt{perl}, \texttt{shell}, \texttt{sock},
\texttt{monitor}, \texttt{passwd}, \texttt{dnssrv} e \texttt{null}. I primi
due consentono di abbinare ad ogni operazione l'esecuzione di script Perl o di
shell, restituendo i relativi risultati, il terzo esegue la stessa operazione
girando le richieste su un socket locale su cui si può far operare un
programma esterno qualunque che generi le risposte; \texttt{monitor} è una
interfaccia alle informazioni statistiche del server stesso, mentre
\texttt{passwd} e \texttt{dnssrv} fanno da ponte per le informazioni mantenute
nel file \texttt{/etc/passwd} e nei record \texttt{SRV} di un DNS. Infine
\texttt{null} non fa proprio nulla.

Un server in cui si usano più supporti per dati gestiti direttamente è poco
comune, in quanto ha poco senso usare supporti diversi (si complica soltanto
la gestione), a meno che l'uso non sia dettato da esigenze specifiche di
compatibilità con vecchi dati o di accesso a formati particolari, per i quali
comunque converrebbe effettuare una conversione. Può invece capitare di dover
gestire più database, ad esempio per gestire indirizzari di diverse
organizzazioni.

Il primo gruppo di direttive che esamineremo sono quelle globali, intese come
quelle che sono applicabili a tutto il server. Si tenga presente comunque che
alcune di esse, come le direttive per il controllo degli accessi che
tratteremo in sez.~\ref{sec:ldap_access_control}, normalmente non vengono
utilizzate a livello globale quanto piuttosto a livello dei singoli database,
come è logico aspettarsi dato che questi possono avere logiche di gestione
diverse.

Per semplificare la gestione dei file di configurazione inoltre si può usare
la direttiva \index{OpenLDAP!direttiva~server!\texttt{include}}
\texttt{include} che prende come argomento il nome di un file, il cui
contenuto viene incluso automaticamente nel file principale come se fosse
stato scritto direttamente all'interno di esso. La direttiva può essere usata
ricorsivamente, ma attenzione, non esiste un limite sul numero di annidamenti
e non c'è nessun meccanismo che rilevi la presenza di circoli viziosi in cui
due file si includono a vicenda. Normalmente questa direttiva viene utilizzata
per includere nella configurazione i cosiddetti file di \textit{schema} che
contengono le definizioni delle \textit{objectclass} degli oggetti che stanno
nell'albero.\footnote{questi si dichiarano a loro volta con delle direttive
  apposite, \texttt{objectclass} e \texttt{attributetype}, che hanno una
  sintassi specifica che non tratteremo, in genere infatti con
  \textit{OpenLDAP} vengono distribuiti dei file di \textit{schema} già pronti
  contenenti tutte le \textit{objectclass} principali necessarie al normale
  funzionamento del server.}

Una direttiva molto importante, specie se si hanno elenchi molto grandi, è
\index{OpenLDAP!direttiva~server!\texttt{sizelimit}} \texttt{sizelimit}, che
impone un limite sul numero massimo di voci, da specificare come argomento,
che il server restituisce come risultato di una ricerca; il default è di 500,
e non è detto che sia sufficiente in tutte le situazioni. Analoga è
\index{OpenLDAP!direttiva~server!\texttt{timelimit}} \texttt{timelimit} che
impone un limite sulla durata del tempo speso dal server a fornire una
risposta, questo fa riferimento al tempo reale e deve essere specificato in
numero di secondi. Entrambe prevedono l'uso del valore \texttt{unlimited} per
rimuovere i limiti. 

%\index{OpenLDAP!direttiva~server!\texttt{allow}}
\index{OpenLDAP!direttiva~server!\texttt{idletimeout}}
\index{OpenLDAP!direttiva~server!\texttt{loglevel}}
\index{OpenLDAP!direttiva~server!\texttt{disallow}}
\index{OpenLDAP!direttiva~server!\texttt{argsfile}}
\index{OpenLDAP!direttiva~server!\texttt{pidfile}}
\index{OpenLDAP!direttiva~server!\texttt{moduleload}}
\index{OpenLDAP!direttiva~server!\texttt{modulepath}}
%\index{OpenLDAP!direttiva~server!\texttt{schemacheck}}
\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Direttiva} & \textbf{Significato} \\
    \hline
    \hline
    % inusata e poco rilevante... per ora commento
    % \texttt{allow}     & abilita una funzionalità specifica; valori possibili
    %                      sono \texttt{bind\_v2} che consente collegamenti con
    %                      LDAPv2, \texttt{bind\_anon\_cred} che consente
    %                      collegamenti non autenticati quando il DN è vuoto,
    %                      \texttt{bind\_anon\_dn}  che consente collegamenti
    %                      non autenticati quando il DN non è vuoto, e
    %                      \texttt{update\_anon} che consente modifiche con
    %                      collegamenti non autenticati.\\ 
    \texttt{argsfile}  & indica un file in cui sono scritti gli argomenti a
                         passati a riga di comando nell'avviare il server
                         (quando non è eseguito interattivamente).\\
    % \texttt{disallow}  & permette di disabilitare una delle funzionalità già
    %                      elencate per \texttt{allow}.\\
    \texttt{idletimeout}&specifica il numero di secondi da aspettare prima di
                         chiudere forzatamente una connessione inattiva.\\
    \texttt{include}   & permette di includere le direttive da un altro file.\\
    \texttt{loglevel}  & abilita la registrazione di eventi ed operazioni sul
                         sistema del \textit{syslog} (di default viene usata
                         la facility \texttt{LOCAL4}), usa come argomento un
                         intero che specifica una maschera binaria i cui bit
                         sono illustrati in tab.~\ref{tab:slapd_debug_bits}
                         (lo stesso valore usato con l'opzione \texttt{-d}),
                         il valore di default è 128, \texttt{none} disabilita
                         la registrazione.\\
    \texttt{moduleload}& indica un modulo di estensione da caricare (in genere
                         relativo al supporto per uno specifico tipo di
                         database o per un \textit{overlay}); prende o un
                         pathname assoluto o uno relativo alla directory
                         specificata con \texttt{modulepath}.\\ 
    \texttt{modulepath}& indica la directory in cui vengono cercati i moduli
                         di estensione.\\
    \texttt{password-hash}& configura il tipo di hash delle password
                         utilizzate nel contenuto degli attributi
                         \texttt{userPassword} quando si usano le 
                         \itindex{LDAP~Password~Modify~Extended~Operations}
                         \textit{LDAP Password Modify Extended Operations}, 
                         usa i valori della prima colonna di
                         tab.~\ref{tab:slappasswd_password_types}.\\ 
    \texttt{pidfile}   & indica il file in cui viene registrato il PID del
                         server quando questo viene eseguito come demone in
                         modalità non interattiva.\\
%    \texttt{referral}  & consente di indicare la URL con cui passare il
%                         riferimento ad un altro server, secondo il
%                         meccasnismo illustrato in
%                         fig.~\ref{fig:ldap_referral_reques}, quando viene
%                         fatta una richiesta che non può essere esaudita
%                         localmente. 
    \texttt{sizelimit} & indica il numero massimo di voci che
                         possono essere restituite in risposta ad una
                         ricerca, il default è 500 (\texttt{unlimited}
                         consente di restituire tutti i risultati).\\ 
    \texttt{timelimit} & indica il limite massimo in secondi che il server  
                         può impiegare nel soddisfare una richiesta, il
                         default è 30 secondi 
                         (\texttt{unlimited} indica di aspettare
                         indefinitamente).\\
    % \texttt{schemacheck}&richiede che il server, prima di accettare un
    %                      oggetto, controlli che esso sia conforme agli 
    %                      \textit{schema} utilizzati, deve essere mantenuto al
    %                      valore di default che è \texttt{on}, onde evitare
    %                      errori nell'immissione di nuovi oggetti, deprecata ed
    %                      inutile nelle versioni più recenti di
    %                      OpenLDAP.\footnotemark\\ % obsoleta
    \hline
  \end{tabular}
  \caption{Le direttive generali di \texttt{slapd.conf}.}
  \label{tab:slapd_general_directives}
\end{table}

% nota obsoleta per schemacheck
% \footnotetext{la direttiva è ignorata nella versione 2.3 di OpenLDAP, ed è
%   deprecata nella versione 2.4, dove il suo uso genera un errore perché la
%   consistenza viene comunque verificata.}

Altre direttive importanti sono \texttt{modulepath} e \texttt{moduleload} che
consentono di indicare rispettivamente la directory dove sono stati installati
i moduli di estensione del server e quali moduli caricare.  Dato che molte
funzionalità del server sono normalmente fornite dai moduli (ad esempio i vari
\textit{backend} su cui si salvano i dati o gli \textit{overlay} che
tratteremo in sez.~\ref{sec:ldap_overlay}) queste vanno sempre dichiarate. Si
tenga inoltre presente che nel caso di \texttt{moduleload} i moduli verranno
caricati nell'ordine in cui vengono indicati, in modo da poter caricare per
primo un moduli necessario al funzionamento di un altro.

Le principali direttive globali sono riportate in
tab.~\ref{tab:slapd_general_directives}, ma ne esistono diverse altre,
relative a configurazioni più avanzate che tratteremo in seguito quando
affronteremo gli argomenti specifici a cui attengono; l'elenco completo viene
comunque riportato nella pagina di manuale accessibile con \texttt{man
  slapd.conf}.

Un esempio dell'uso di questo primo gruppo di direttive si trova nel seguente
estratto del file di configurazione standard installato da una Debian Lenny,
da cui si sono rimossi per brevità righe vuote e commenti:
\begin{FileExample}[label=slapd.conf]
include         /etc/ldap/schema/core.schema
include         /etc/ldap/schema/cosine.schema
include         /etc/ldap/schema/nis.schema
include         /etc/ldap/schema/inetorgperson.schema
pidfile         /var/run/slapd/slapd.pid
argsfile        /var/run/slapd.args
loglevel        none
modulepath      /usr/lib/ldap
moduleload      back_hdb
sizelimit       500
\end{FileExample}

Si noti come nell'esempio prima si includono i vari file con gli schemi che
definisco le \textit{objectclass} degli oggetti che immetteremo nel database,
poi si impostano i file dove si troveranno memorizzate le informazioni
relative al server, si disabilitano i messaggi di debug, si imposta la
directory da cui caricare i moduli ed infine si attiva il supporto
\texttt{hdb} per Berkley DB.

Il secondo gruppo di direttive è quello delle direttive relative ad un
determinato tipo di supporto, che vanno specificate dopo una direttiva
\texttt{backend}. Si ricordi che in questo modo esse verranno applicate a
tutti i database che usano quello stesso \textit{backend}.  Come per le
direttive globali anche queste possono essere sovrascritte con valori diversi
se riutilizzate in una sezione relativa ad uno specifico database che usi quel
supporto, ed in effetti in genere è proprio in questo modo che vengono usate,
ed è estremamente raro vederle applicate al di fuori di una sezione relativa
ad un singolo database.

Dato che ogni \textit{backend} ha delle caratteristiche proprie, ognuno
definisce anche delle direttive specifiche, che saranno supportate soltanto se
si è caricato il modulo che fornisce il supporto richiesto e che saranno
valide per i database che lo utilizzano. Per ciascuno dei supporti descritti
in tab.~\ref{tab:ldap_backend_type} esiste allora una apposita pagina di
manuale, nella forma \texttt{slapd-\textsl{SUPPORTO}}, contenente tutte le
informazioni ad esso relative.

Dato che questo è il supporto con la configurazione più complessa ed ancora in
uso nelle versioni usate da molte distribuzioni, tratteremo sommariamente le
direttive relative ai \textit{backend} \texttt{bdb} e \texttt{hdb} (che sono
le stesse). Le direttive principali in questo caso sono:
\index{OpenLDAP!direttiva~server!\texttt{cachesize}} \texttt{cachesize} che
indica quante voci mantenere in memoria e \texttt{checkpoint}
\index{OpenLDAP!direttiva~server!\texttt{checkpoint}} che indica la frequenza
con cui scarica su disco il registro delle transazioni.  Le altre direttive
principali sono riportate in tab.~\ref{tab:slapd_bdb_directives} mentre
l'elenco completo è accessibile con \texttt{man slapd-hdb}.

\index{OpenLDAP!direttiva~server!\texttt{mode}}
\index{OpenLDAP!direttiva~server!\texttt{dbconfig}}
\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Direttiva} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{cachesize} & il numero di voci mantenute nella cache in memoria
                         (se non specificata il valore di default è 2000).\\
    \texttt{checkpoint}& la frequenza con cui viene scaricato su disco il
                         registro delle transazioni, la direttiva prende due
                         parametri, il primo che indica ogni quanti kilobyte
                         ed il secondo che indica ogni quanti minuti deve
                         essere eseguita l'operazione (il valore di default è
                         nullo che significa che essi vengano ignorati).\\
    \texttt{dbconfig}  & inserisce una direttiva di basso livello per Berkeley
                         DB, come se la si fosse scritta in un file
                         \texttt{DB\_CONFIG} nella directory dei dati,
                         effettiva soltanto se questo non esiste.\\
    \texttt{index}     & le opzioni di indicizzazione (vedi anche
                         tab.~\ref{tab:ldap_indexing_type}).\\
    \texttt{mode}      & i permessi con cui vengono creati i file dei dati,
                         espressi in notazione ottale, come per \texttt{chmod}
                         (il valore di default è \texttt{200}).\\
    \hline
  \end{tabular}
  \caption{Le direttive per i supporti \texttt{bdb} e \texttt{hdb}.}
  \label{tab:slapd_bdb_directives}
\end{table}

In realtà le configurazioni più sofisticate relative a Berkley DB sono
mantenute nel file \texttt{DB\_CONFIG} nella directory dove i file del
database, perché le librerie di Berkley DB fanno riferimento ultimativo alle
impostazioni che sono in questo file. Per questo il team di sviluppo di
\textit{OpenLDAP} non ha ritenuto opportuno ridefinire direttive specifiche
dentro la configurazione del server poiché questo avrebbe creato tutta una
serie di possibili conflitti in caso di modifiche di questo file, difficili da
rilevare.\footnote{la direttiva \texttt{dbconfig} consente comunque di
  definire per comodità alcune di queste configurazioni direttamente
  all'interno di \texttt{slapd.conf}, ma avranno effetto solo se il file
  \texttt{DB\_CONFIG} non esiste.} Per la configurazione specialistica di
Berkley DB si rimanda direttamente alla documentazione originale, che un tempo
era disponibile su \url{http://www.sleepycat.com/docs/} e adesso è ben sepolta
nel sito di Oracle che ha acquisito i diritti sullo stesso.

Uno dei grandi vantaggi del nuovo supporto \texttt{mdb}, oltre al notevole
miglioramento delle prestazioni, è anche la semplificazione della
configurazione, la sola direttiva a cui bisogna realmente fare attenzione
infatti è \texttt{maxsize} che indica la dimensione massima in byte del
database, dato che questo non potrà crescere oltre questa dimensione, e che un
ridimensionamento a server attivo non è praticabile.

Con \texttt{mdb} i dati verranno mantenuti in un file di questa dimensione (ed
occorrerà pertanto che nel filesystem ci sia spazio sufficiente per lo stesso)
che verrà poi mappato in memoria. I dati resteranno in memoria e salvati in
maniera sincrono ad ogni scrittura, a meno che non si sia specificata anche la
direttiva \texttt{dbnosync}. In tal caso i dati verranno salvati su disco
secondo quanto indicato dalla direttiva \texttt{checkpoint}, che ha la stessa
sintassi già vista in tab.~\ref{tab:slapd_bdb_directives}.  Questa modalità
\textsl{asincrona} dei salvataggi consente di ottenere migliori prestazioni a
scapito dell'affidabilità (si possono perdere i dati non ancora scritti in
caso di crash), ed è sconsigliata. Le altre principali opzioni di \texttt{mdb}
sono elencate in tab.~\ref{tab:slapd_mdb_directives}, l'elenco completo è
accessibile con \texttt{man slapd-mdb}.

\index{OpenLDAP!direttiva~server!\texttt{dbnosync}}
\index{OpenLDAP!direttiva~server!\texttt{maxsize}}
\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Direttiva} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{checkpoint}& la frequenza con cui vengono salvati i dati, usata
                         solo in congiunzione con \texttt{dbnosync}; la
                         direttiva prende due parametri, il primo che indica
                         ogni quanti kilobyte ed il secondo che indica ogni
                         quanti minuti deve essere eseguita l'operazione (il
                         valore di default è nullo che significa che essi
                         vengano ignorati), al momento il primo argomento
                         viene ignorato.\\ 
    \texttt{dbnosync}  & indica si deve disabilitare il salvataggio sincrono
                         dei dati su disco, usandola si aumentano le
                         prestazioni a scapito della salvaguardia dei dati, di
                         default è disattiva.\\
    \texttt{index}     & le opzioni di indicizzazione (vedi anche
                         tab.~\ref{tab:ldap_indexing_type}).\\
    \texttt{maxsize}   & la dimensione massima in byte del database
                         (il valore di default è \texttt{10485760}).\\
    \texttt{mode}      & i permessi con cui vengono creati i file dei dati,
                         espressi in notazione ottale, come per \texttt{chmod}
                         (il valore di default è \texttt{600}).\\
    \hline
  \end{tabular}
  \caption{Le direttive per il supporto \texttt{mdb}.}
  \label{tab:slapd_mdb_directives}
\end{table}

Un'altra direttiva definita a livello di supporto, ma disponibile per tutti i
\textit{backend} relativi alla gestione dei dati, ed usata sempre a livello di
singolo database, è \index{OpenLDAP!direttiva~server!\texttt{index}}
\texttt{index}, che permette di definire quali informazioni indicizzare per un
accesso più veloce ai dati.  Dato che comunque questa direttiva fa riferimento
a dati specifici, anche questa non viene quasi mai utilizzata a livello di
supporto generico, quanto piuttosto per ogni singolo database.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Tipo} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{pres}  & indicizza per la presenza dell'attributo nel database
                     qualunque valore esso abbia, permette di ottimizzare le
                     ricerche in cui si richiedono tutti gli attributi di un
                     certo tipo (ad esempio \texttt{cn=*}).\\ 
    \texttt{eq}    & indicizza per la ricerca di una eguaglianza esatta del
                     valore dell'attributo (ad esempio
                     \texttt{uid=piccardi}).\\
    \texttt{sub}   & indicizza per ricerca della presenza di una stringa
                     all'interno del valore dell'attributo (ad esempio 
                     \texttt{cn=Simo*}). Questo tipo di indicizzazione può
                     essere indicato in maniera specializzata usando al
                     posto di \texttt{sub} i valori \texttt{subinitial},
                     \texttt{subfinal} e \texttt{subany} per specificare
                     situazioni in cui la ricerca è eseguita su sotto-stringhe
                     che stanno rispettivamente all'inizio (ad esempio
                     \texttt{uid=sim*}), alla fine (ad esempio
                     \texttt{uid=*ardi}) o nel mezzo (ad esempio
                     \texttt{uid=*icc*}).\\
    \texttt{approx}& indicizza per la ricerca di stringhe approssimativamente
                     uguali, (cioè ricerche eseguite con la sintassi
                     \texttt{cn\tild=simone}).\\ 
    \texttt{none}  & disabilita la generazione di indici (per attributi non
                     indicizzabili come \texttt{jpegPhoto}). \\
    \hline
  \end{tabular}
  \caption{I vari tipi di indicizzazione usati come argomento della direttiva
    \texttt{index}.} 
  \label{tab:ldap_indexing_type}
\end{table}

La direttiva prevede due argomenti, il primo è il nome dell'attributo da
indicizzare mentre il secondo, opzionale, indica quale tipo di indicizzazioni
effettuare, e prende una lista, separata da virgole, dei valori di
tab.~\ref{tab:ldap_indexing_type}. Se come attributo si usa il valore
riservato \texttt{default} si possono impostare una serie di indicizzazioni di
default, che saranno applicate quando non si fornisce il valore di una
indicizzazione specifica.

La scelta dei giusti valori per le indicizzazioni è di fondamentale importanza
per le prestazioni del server, pertanto è sempre opportuno indicizzare gli
attributi sui quali si compiono le ricerche più frequenti; vedremo con
maggiore dettaglio in sez.~\ref{sec:ldap_search} quando tratteremo i filtri di
ricerca a quali indici queste corrispondono. Non è però il caso di esagerare
in quanto la creazione di indici inutili comporta spreco di memoria e rallenta
le prestazioni in caso di scrittura, in maniera anche sensibile se il database
contiene molti dati.\footnote{come illustrato in sez.~\ref{sec:ldap_intro}, le
  operazioni di scrittura su un database LDAP sono sporadiche: la gran del
  tempo impiegato da esse è proprio nella manutenzione degli indici che
  servono ad ottimizzare la lettura; evidentemente più dati sono mantenuti nel
  database, più costosa diventa l'operazione di aggiornamento degli indici.}
Inoltre è sempre opportuno selezionare il tipo di indici sulla base delle
ricerche a cui vengono sottoposti i rispettivi attributi, ad esempio non ha
senso indicizzare un attributo come \texttt{userPassword} per la ricerca di
sotto-stringhe.

Il terzo gruppo di direttive sono quelle che eseguono le impostazioni
specifiche di ciascun database. Esse sono utilizzabili soltanto all'interno di
una sezione introdotta dalla direttiva \texttt{database} e sono indipendenti
dal tipo di supporto utilizzato per lo stesso. Dato che nella maggior parte
dei casi si ha un solo database che fa riferimento ad un unico supporto, e che
anche quando i database sono più di uno, ognuno può avere sue specifiche
esigenze relative alla modalità di gestire il supporto sottostante, in genere
queste si trovano sempre mescolate con le precedenti in una stessa sezione.

Si ricordi infatti che un database corrisponde ad una specifica sezione di un
albero LDAP, che viene definita dalla direttiva
\index{OpenLDAP!direttiva~server!\texttt{suffix}} \texttt{suffix}. Questa
definisce la radice del DIT dei dati presenti in quel database, e prende come
parametro il relativo \textit{Distinguished Name}.\footnote{corrispondente al
  valore che si usa nella direttiva \texttt{BASE} per la configurazione del
  client.} Una direttiva \texttt{suffix} deve essere obbligatoriamente
presente in ogni sezione \texttt{database}, una seconda direttiva obbligatoria
in ciascuna di queste sezioni è
\index{OpenLDAP!direttiva~server!\texttt{directory}} \texttt{directory} che
indica appunto in quale directory sono mantenuti i file con i dati.


\index{OpenLDAP!direttiva~server!\texttt{readonly}}
\index{OpenLDAP!direttiva~server!\texttt{lastmod}}
\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Direttiva} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{directory} & la directory in cui vengono mantenuti i file su cui
                         sono registrati i dati (su Debian il default è
                         \texttt{/var/lib/ldap}).\\ 
    \texttt{lastmod} & richiede che il server memorizzi nel database (in
                       appositi attributi gestiti internamente) le informazioni
                       relative all'ultima modifica di un oggetto, il valore
                       di default è \texttt{on}.\\
    \texttt{readonly}& consente l'accesso al database in sola lettura.\\
    \texttt{rootdn}  & imposta il \textit{Distinguished Name} associato
                       all'utente che amministra il database per il quale non
                       valgono i controlli di accesso (vedi
                       sez.~\ref{sec:ldap_authentication_methods}).\\
    \texttt{rootpw}  & imposta la password dell'utente di amministrazione.\\
    \texttt{suffix}  & imposta la radice del DIT associato al database, prende
                       come argomento il \textit{Distinguished Name} della
                       stessa.\\ 
    \hline
  \end{tabular}
  \caption{Le direttive generiche per i database.}
  \label{tab:slapd_database_directives}
\end{table}

Un elenco delle principali direttive generiche relative ad un database è
riportato in tab.~\ref{tab:slapd_database_directives}; la tabella contiene
soltanto le direttive attinenti le funzionalità di base, tratteremo le
direttive relative alle varie funzionalità avanzate più avanti, nelle relative
sezioni. Un esempio dell'uso di alcune di queste direttive è il seguente
proseguimento del precedente estratto dal file di configurazione standard
installato da una Debian Lenny:
\begin{FileExample}[label=slapd.conf]
backend         hdb
database        hdb
suffix          "dc=truelite,dc=it"
directory       "/var/lib/ldap"
dbconfig set_cachesize 0 2097152 0
dbconfig set_lk_max_objects 1500
dbconfig set_lk_max_lockers 1500
index           objectClass eq
lastmod         on
checkpoint      512 30
\end{FileExample}
dove si dichiarano un supporto ed un database per il ramo di albero
\texttt{dc=truelite,dc=it"}; i file relativi saranno mantenuti in
\texttt{/var/lib/ldap}, con un indice di uguaglianza per gli attributi
\texttt{objectClass} e si richiede che il database registri i dati di ultima
modifica degli oggetti.


\subsection{La configurazione via LDAP}
\label{sec:slapd_database_config}

A partire dalla versione 2.4 le modalità di configurazione del server sono
state modificate, introducendo il supporto per un sistema, denominato
\textit{On-Line Configuration} e contraddistinto dalla sigla OLC, che
consentisse la modifica al volo delle configurazioni, senza necessità di
riavvio del servizio, utilizzando direttamente il protocollo LDAP.  Questo ha
comportato il passaggio dal tradizionale file di configurazione
\texttt{slapd.conf} appena trattato all'utilizzo di uno specifico database
LDAP interno al server identificato dal suffisso, non modificabile,
\texttt{cn=config}, che definisce uno specifico DIT relativo alla
configurazione. La configurazione viene pertanto rappresentata con opportuni
oggetti mantenuti dentro questo database ed all'interno di questo DIT (devono
cioè avere sempre questo suffisso), da modificare con le ordinarie operazioni
di LDAP.

Con la versione attuale del server i dati di questo DIT sono mantenuti in un
database che usa il \textit{backend} \texttt{ldif} e salvati nella directory
\index{configurazione!\texttt{/etc/ldap/slapd.d}} \texttt{/etc/ldap/slapd.d/},
che assume il ruolo di ``\textsl{directory di configurazione}'', sostituendo
il file \texttt{slapd.conf}, che viene ignorato se questa è presente.  In
realtà deve essere chiarito immediatamente che l'uso della locuzione
``\textsl{directory di configurazione}'', per quanto si ritrovi nella
documentazione stessa del progetto, che non brilla per chiarezza, completezza
e coerenza nella notazione, è molto fuorviante.

Se infatti è vero che è all'interno di detta directory che sono mantenuti i
dati di configurazione, e che è questa directory che viene indicata nelle
opzioni dei vari comandi quando si fa riferimento alla configurazione, non è
accedendo alla stessa o modificandone il contenuto (anche se comunque si
tratta di file di testo in formato LDIF) che si esegue la configurazione del
server. Questa deve essere sempre e comunque eseguita attraverso il protocollo
LDAP, o utilizzando i comandi \texttt{slapcat} e \texttt{slapadd} per trattare
i dati relativi. Non ci si faccia quindi prendere dalla tentazione di
modificare direttamente i file sotto \texttt{slapd.d}, i risultati potrebbero
risultare anche molto spiacevoli.

Il passaggio al nuovo meccanismo di configurazione può essere eseguito con il
comando \index{comando!\texttt{slaptest}} \texttt{slaptest} il cui scopo
ordinario è quello di eseguire un controllo sulla correttezza di una
configurazione del server, da indicare a seconda dei casi o con \texttt{-f},
nel caso si usi un file di configurazione, o con \texttt{-F} qualora si usi il
nuovo sistema. Se invece li si indicano entrambi il comportamento del comando
è di convertire il contenuto del file di configurazione specificato da
\texttt{-f} al nuovo formato e salvarlo nella directory indicata con
\texttt{-F}.

\begin{figure}[!h!bt]
  \centering \includegraphics[width=10cm]{images/cn-config-dit}
  \caption{Il DIT del database di configurazione \texttt{cn=config}.}
  \label{fig:cn_config_tree}
\end{figure}

Non esiste invece nessun programma in grado di eseguire il lavoro opposto, in
quanto gli sviluppatori avevano manifestato l'intenzione di deprecare l'uso
del file di configurazione a partire dalla nuova versione del server. A causa
della fortissima reazione contraria di molti utenti (compresa quella
dell'autore di questo testo) questa eventualità pare momentaneamente
rientrata, ma comunque la funzionalità di ritorno ad un ordinario file di
configurazione non esiste, e il passaggio all'indietro può essere realizzato
solo manualmente.

Il DIT del database di configurazione è illustrato sinteticamente in
fig.~\ref{fig:cn_config_tree}. Alla base dell'albero sta la voce
\texttt{cn=config}, ed al di sotto viene strutturata tutta la configurazione
del server. La convenzione generale è che quella che era una direttiva di
\texttt{slapd.conf} diventa un attributo di una opportuna voce all'interno del
DIT; il nome di questo attributo si ottiene aggiungendo il prefisso
\texttt{olc} al nome della direttiva di \texttt{slapd.conf}, scritto nel
cosiddetto ``\textit{CamelCase}'', vale a dire con le parole che la compongono
scritte con l'iniziale in maiuscolo (eliminando eventuali separatori presenti,
ad esempio \texttt{password-hash} diventerà \texttt{olcPasswordHash}). 

Le configurazioni globali del server sono inserite direttamente nella voce
\texttt{cn=config} che costituisce la radice dell'albero, questa deriva dalla
\textit{objectclass} \objcl{olcGlobal} che definisce i vari attributi
corrispondenti alle direttive di tab.~\ref{tab:slapd_general_directives}; per
cui si otterrà che la direttiva \texttt{argsfile} diventa l'attributo
\texttt{olcArgsFile}, la direttiva \texttt{loglevel} diventa l'attributo
\texttt{olcLogLevel} e così via; a ciascuno di essi dovrà poi essere assegnato
il relativo valore, nella stessa forma usata per la direttiva tradizionale
(per gli attributi non assegnati viene usato il default) con l'eccezione degli
attributi che prendevano un valore dal significato booleano (che in precedenza
potevano essere \texttt{yes} o \texttt{no} oppure \texttt{on} e \texttt{off}),
in cui i valori possibili diventano solo \texttt{TRUE} o \texttt{FALSE}. Il
contenuto di questa voce potrebbe essere pertanto qualcosa del tipo:

\begin{FileExample}[label=cn{=}config.ldif]
dn: cn=config
objectClass: olcGlobal
cn: config
olcArgsFile: /var/run/slapd/slapd.args
olcLogLevel: none
olcPidFile: /var/run/slapd/slapd.pid
olcToolThreads: 1  
\end{FileExample}

Una specifica eccezione per quanto riguarda le direttive che in
\texttt{slapd.conf} facevano parte della configurazione globale sono le
direttive relative al caricamento dei moduli e quelle relative alla
definizione degli \textit{schema}, per questo compito infatti è previsto l'uso
di opportune voci ulteriori nell'albero della configurazione. In particolare
le direttive \texttt{moduleload} e \texttt{modulepath} devono essere inserite
nella voce \texttt{cn=module\{0\},cn=config}, usata specificamente per
configurare i moduli, e derivante dalla \textit{objectclass}
\objcl{olcModuleList}.  In questa voce occorrerà definire l'attributo
\texttt{olcModulePath} per indicare la directory dove sono installati i moduli
e per ciascun modulo da caricare usare l'attributo \texttt{olcModuleLoad} per
indicarne il nome.

Già nel nome della voce (\texttt{cn=module\{0\}}) però si può notare uno degli
inconvenienti che si devono affrontare nella nuova modalità di gestione delle
configurazioni, non esiste infatti un modo di specificare un ordinamento
sequenziale delle direttive, come avveniva naturalmente dentro
\texttt{slapd.conf} scrivendole una di seguito all'altra, dato che l'unico
ordinamento supportato da LDAP è quello gerarchico. Questo significa che
quando occorre indicare una sequenza specifica in cui processare le
configurazioni (come avviene anche per gli \textit{schema} e per le direttive
che definiscono il controllo degli accessi che tratteremo in
sez.~\ref{sec:ldap_access_control}) questo deve essere fatto in forma
esplicita, introducendo un indice progressivo nella forma
``\texttt{\{\textsl{N}\}}'',\footnote{questo è in tutte le altre
  configurazioni sempre usato come prefisso, ma per motivi ignoti all'autore
  (a quello di questo testo, ma presumibilmente anche a quello del codice) in
  questo caso viene usato un suffisso.} come nel caso precedente.

Nel caso dei moduli l'ordinamento in sequenza è essenziale, dato che alcuni di
essi possono dipendere da funzionalità fornite da altri moduli, che quindi
devono essere caricati per primi. Nello specifico il problema si pone in due
occasioni: si possono avere più directory in cui sono installati i moduli, ma
una voce \texttt{olcModuleLoad} può specificare una sola directory
\texttt{olcModulePath}, per cui in tal caso occorreranno più voci
(\texttt{cn=module\{0\}}, \texttt{cn=module\{1\}}, ecc.) inoltre anche
restando all'interno di una sola directory si possono dover caricare più
moduli, di nuovo nella opportuna sequenza, per cui non si può usare come
valore di \texttt{olcModuleLoad} solo il nome del modulo, ma questo deve avere
come prefisso l'indice che ne identifica l'ordine di caricamento. Un esempio
di questa voce, come installato nel default di Debian Jessie, è il seguente:

\begin{FileExample}[label=cn{=}module\{0\}{,}cn{=}config.ldif]
dn: cn=module{0},cn=config
objectClass: olcModuleList
cn: module{0}
olcModulePath: /usr/lib/ldap
olcModuleLoad: {0}back_mdb
\end{FileExample}

La presenza dell'indice ovviamente complica la cosa perché come si può
immaginare per inserire una voce in una sequenza già presente occorrerà
inserire anche gli opportuni valori dell'indice.  Il sistema prevede che se si
deve aggiungere una configurazione si possano specificare i dati (voce o
attributo che sia) senza indicare l'indice, e questo verrà assegnato
automaticamente al valore in coda alla sequenza, mentre se si indica un indice
i valori già eventualmente presenti a partire da quella posizione verranno
automaticamente spostati in avanti. Inoltre se si cancella una voce o un
attributo in una certa ``\textsl{posizione}'' gli indici di quelli seguenti
verranno automaticamente ricalcolati e spostati all'indietro.  

Il problema comunque è che anche se per generare la sequenza della
configurazione si può usare un file LDIF, con le voci ordinate senza
l'appesantimento degli indici, nella rilettura dal server della configurazione
queste saranno necessariamente presenti, per cui il confronto fra due diverse
configurazioni (prima banalmente ottenibile con un \texttt{diff}) risulterà
complicato da tutti i cambiamenti dovuti solo alla variazione dell'indice del
prefisso.

Un secondo aspetto delle configurazioni globali gestito diversamente nel nuovo
sistema è quello relativo alle definizioni delle \textit{objectclass} e degli
attributi, che con \texttt{slapd.conf} vengono normalmente effettuate
includendo direttamente i cosiddetti file di \textit{schema}, che contengono
le relative dichiarazioni. In questo caso, come illustrato in
fig.~\ref{fig:cn_config_tree}, queste configurazioni prevedono un apposito
ramo dell'albero alla cui radice è posta la voce \texttt{cn=schema,cn=config}
che contiene la definizione degli schema interni forniti direttamente dal
server. Si tenga presente che la voce \texttt{cn=schema,cn=config} non può
essere modificata, ma leggendola gli si otterranno le definizioni delle classi
e degli attributi predefiniti.\footnote{di nuovo si introduce una differenza
  fra quanto ottenibile dalla lettura dei dati dell'albero, rispetto ad un
  eventuale file LDIF usato per crearlo, in questo caso nella lettura (via
  LDAP, nei dump con \texttt{slapcat} questi dati non vengono scritti)
  compariranno anche i dati degli \textit{schema} interni, che non si possono
  impostare in scrittura.}

Al di sotto di questa voce vanno inserite tutte le ulteriori voci (derivate
anch'esse dalla classe \objcl{olcSchemaConfig}) contenenti gli \textit{schema}
definiti dagli utenti. Dato che uno \textit{schema} può usare
\textit{objectclass} e attributi definiti in uno \textit{schema} precedente,
anche in questo caso è necessario un indice per impostare l'ordine in cui le
direttive vengono processate. Questo comporta la presenza di ulteriori voci
\texttt{cn=\{0\}core,cn=schema,cn=config},
\texttt{cn=\{1\}cosine,cn=schema,cn=config}, ecc.

Le direttive \texttt{backend} e \texttt{database}, rispecchiando anche il loro
speciale significato in \texttt{slapd.conf}, sono gestite diversamente: pur
essendo state anch'esse trasformate in attributi (rispettivamente
\texttt{olcBackend} e \texttt{olcDatabase}) devono però essere usate in
altrettante voci (rispettivamente di classe \objcl{olcBackendConfig} e
\objcl{olcDatabaseConfig}) da inserire direttamente sotto \texttt{cn=config}
nella forma illustrata in fig.~\ref{fig:cn_config_tree}.

Questo significa che per ogni \textit{backend} che si intende usare deve
essere presente una voce \texttt{olcBackend}, in cui il valore di questo
attributo indica il nome del \textit{backend} (quello di
tab.~\ref{tab:ldap_backend_type}). In questa voce è previsto che vengano
specificate le configurazioni generali applicate a tutti i database che
useranno quel \textit{backend}, ma al momento non esiste attributo/direttiva
specifico di questo tipo e l'unico usato è \texttt{olcBackend}. La voce però
deve essere inserita comunque per ogni \textit{backend} che si intende usare,
inoltre è previsto anche in questo caso l'uso di un indice per indicare la
sequenza dei \textit{backend} da utilizzare, per cui se ad esempio si
utilizza \texttt{mdb}, si avrà comunque la voce
\texttt{olcBackend=\{0\}mdb,cn=config}, il cui contenuto sarà qualcosa del
tipo:

\begin{FileExample}[label=olcBackend{=}\{0\}mdb{,}cn{=}config.ldif]
dn: olcBackend={0}mdb,cn=config
objectClass: olcBackendConfig
olcBackend: {0}mdb
\end{FileExample}

Allo stesso livello dell'albero andranno poi inserite le voci
\texttt{olcDatabase} che identificano ogni database gestito dal server, in cui
si inseriranno le configurazioni di quel database, e per queste, oltre alla
classe generica \objcl{olcDatabaseConfig}, occorrerà utilizzare anche la
\textit{objectclass} che definisce gli attributi/direttive specifici di quel
tipo di database, per cui per un database di tipo \texttt{mdb} si userà
\objcl{olcMdbConfig}, per uno di tipo \texttt{hdb} \objcl{olcHdbConfig} e così
via. Come per la direttiva \texttt{database} il valore di \texttt{olcDatabase}
deve corrispondere al nome del \textit{backend} che questo usa, e per
distinguere i diversi database deve essere aggiunto il solito indice
progressivo come prefisso.

Si tenga presente però che ci sono sempre due database predefiniti,
identificati dagli indici speciali ``\texttt{\{-1\}}'' e ``\texttt{\{0\}}''.
Il primo è \texttt{frontend}, che non corrisponde a nessun database reale, ma
in cui si inseriscono le direttive generali (come \texttt{sizelimit} o quelle
attinenti il controllo di accesso che vedremo in
sez.~\ref{sec:ldap_access_control}) che devono essere usate da tutti i
database presenti come default, a meno di non essere sovrascritte nelle
successive voci specifiche di ciascuno di essi; un esempio di questa voce,
come installato in una Debian Jessie, è:

\begin{FileExample}[label=olcDatabase{=}\{-1\}frontend{,}cn{=}config.ldif]
dn: olcDatabase={-1}frontend,cn=config
objectClass: olcDatabaseConfig
objectClass: olcFrontendConfig
olcDatabase: {-1}frontend
olcAccess: {0}to * by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage 
                   by * break
olcAccess: {1}to dn.exact="" by * read
olcAccess: {2}to dn.base="cn=Subschema" by * read
olcSizeLimit: 500
\end{FileExample}

Il secondo database speciale è \texttt{config}, che fa riferimento al database
di configurazione stesso, e che avendo l'indice ``\texttt{\{0\}}'' è sempre il
primo database definito. In questo caso la configurazione attiene
principalmente alle regole di accesso da applicare per le modifiche alla
configurazione del server; un esempio di questa voce, preso sempre dal default
installato con \texttt{slapd} in una Debian Jessie, è:

\begin{FileExample}[label=olcDatabase{=}\{0\}config{,}cn{=}config.ldif]
dn: olcDatabase={0}config,cn=config
objectClass: olcDatabaseConfig
olcDatabase: {0}config
olcAccess: {0}to * by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage
                   by * break
olcRootDN: cn=admin,cn=config
\end{FileExample}
\label{olcDatabase_config}

Oltre a questi due database che devono essere sempre presenti e definiti e che
non compaiono mai in una configurazione con \texttt{slapd.conf}, si dovranno
poi definire quelli per ospitare i propri dati, facendo riferimento, come per
la direttiva \texttt{database} classica, al \textit{backend} che si intende
utilizzare, indicato per nome nell'attributo \texttt{olcDatabase}, numerato
progressivamente con il solito indice di prefisso. 

A complicare le cose occorrerà pure tener presente che gli attributi che
sostituiscono direttive specifiche del tipo di \textit{backend} scelto non
seguono la regola generale illustrata all'inizio (quella di prendere il
prefisso \texttt{olc}) ma usano invece il più specifico \texttt{olcDb} (a meno
che la direttiva non inizi già per \texttt{db}). Questo significa ad esempio
che la direttiva \texttt{directory} verrà trasformata nell'attributo
\texttt{olcDbDirectory}, la direttiva \texttt{index} nell'attributo
\texttt{olcDbIndex}, la direttiva \texttt{checkpoint} nell'attributo
\texttt{olcDbCheckpoint} e così via. 

Come esempio di questo tipo di configurazione prendiamo la voce creata dal
\textit{debconf} all'installazione del server su una Debian Jessie nel caso in
cui si sia impostato come radice dell'albero \texttt{dc=truelite,dc=it};
otterremo qualcosa del tipo:

\begin{FileExample}[label=olcDatabase{=}\{1\}mdb{,}cn{=}config.ldif]
dn: olcDatabase={1}mdb,cn=config
objectClass: olcDatabaseConfig
objectClass: olcMdbConfig
olcDatabase: {1}mdb
olcDbDirectory: /var/lib/ldap
olcSuffix: dc=truelite,dc=it
olcAccess: {0}to attrs=userPassword,shadowLastChange by self write 
                 by anonymous auth
                 by * none
olcAccess: {1}to dn.base="" by * read
olcAccess: {2}to * by * read
olcLastMod: TRUE
olcRootDN: cn=admin,dc=truelite,dc=it
olcRootPW: {SSHA}Ek/IqQKbG7ZEvbg0jDrVvU+pFLkSdLdI
olcDbCheckpoint: 512 30
olcDbIndex: objectClass eq
olcDbIndex: cn,uid eq
olcDbIndex: uidNumber,gidNumber eq
olcDbIndex: member,memberUid eq
olcDbMaxSize: 1073741824
\end{FileExample}

Infine, qualora di volessero attivare degli \textit{overlay} (tratteremo
l'argomento in sez.~\ref{sec:ldap_overlay}) questi dovrebbero essere indicati
con altrettante voci di classe \objcl{olcOverlayConfig}, identificate
dall'attributo \texttt{olcOverlay}, poste nell'albero al di sotto della voce
del database a cui li si applicano (si faccia di nuovo riferimento a
fig.~\ref{fig:cn_config_tree}). Di nuovo questo attributo richiede che in
\texttt{olcOverlay} si indichi il nome dell'\textit{overlay}, a cui deve
essere aggiunto il solito prefisso per ordinarne la sequenza dato che alcuni
\textit{overlay} necessitano di altri per poter funzionare. Nella voce poi
saranno inserite le specifiche direttive di configurazione, tradotte alla
solita maniera (con la convenzione abbondantemente illustrata dagli esempi
precedenti) nei corrispondenti attributi.

Tutto questo ci mostra come il vantaggio di poter modificare le configurazioni
senza dover riavviare il server comporti un prezzo piuttosto alto dato che
l'uso del DIT di \texttt{cn=config} introduce una notevole complessità di
gestione, il cui impatto va valutato; in particolare i principali svantaggi
sono che:
\begin{enumerate}
\item occorre usare degli strumenti specifici e non un editor generico per
  modificare la configurazione.
\item la configurazione non è più su semplici file, per cui se si vogliono
  usare strumenti di versionamento o di gestione automatica occorre prendere
  le opportune misure di conversione dei dati.
\item in caso di errore nella configurazione che non fa ripartire il server,
  non si ha più modo di modificare la configurazione errata attraverso LDAP, e
  l'unica possibilità è ripartire da un precedente backup della stessa (vedi
  sez.~\ref{sec:ldap_content_management}) o provare a modificare manualmente,
  a proprio rischio e pericolo, i file in \texttt{slapd.d}.
\item una volta inseriti alcuni dati diventa impossibile eliminarli; in
  particolare è impossibile cancellare uno \textit{schema}, anche se questo
  non viene più usato, ed ugualmente è impossibile eliminare un database una
  volta creato; per farlo occorre fermare il server, creare un dump della
  configurazione con \texttt{slapcat} modificarlo e ricreare la nuova
  configurazione con \texttt{slapadd} (vedi
  sez.~\ref{sec:ldap_content_management}).
\item non è più possibile commentare la propria configurazione (si possono
  mettere commenti in un eventuale file LDIF iniziale, ma questi spariranno
  nel database) anche se per questo è in corso di studio un possibile
  meccanismo per aggiungere commenti negli oggetti dell'albero.
\item la configurazione è assai poco leggibile anche disponendo di un unico
  file LDIF, sia per la presenza del prefisso \texttt{olc} in tutti gli
  attributi, sia per la necessità di inserire gli indici tutte le volte che è
  necessario un ordinamento.
\end{enumerate}

Deve infine essere evidenziato che adottando il nuovo sistema occorrerà
prevedere anche una specifica politica di backup delle configurazioni, dato
che queste non possono essere semplicemente ripristinate ricopiando
all'indietro un file (specie se si sono aggiunte parti non cancellabili). Per
questo occorrerà allora ricorrere ai comandi \texttt{slapcat} e
\texttt{slapadd} (che tratteremo in sez.~\ref{sec:ldap_content_management}).

Come conseguenza di tutto ciò, in tutti i casi in cui un semplice riavvio del
servizio non costituisce un problema (ed anche in casi di requisiti di accesso
al servizio molto stringenti il ricorso ad un sistema di bilanciamento del
carico come HAProxy è probabilmente una soluzione altrettanto efficace)
occorre valutare se vale davvero la pena usare il nuovo sistema.

Nel prosieguo di questo testo tratteremo, per semplicità espositiva e per la
maggiore chiarezza della notazione, soltanto le direttive di configurazione
classiche, che peraltro, nonostante l'enfasi del progetto sul nuovo sistema di
configurazione, sono ancora quelle usate in buona parte della documentazione
della guida ufficiale di \url{http://www.openldap.org/doc/admin24/index.html}
e delle pagine di manuale.


\section{L'uso del servizio LDAP e la gestione dei dati}
\label{sec:ldap_client}

Tratteremo in questa sezione le funzionalità relative all'uso del servizio
LDAP dal lato client. Non tratteremo specificatamente la loro installazione,
dato che normalmente si usano i pacchetti forniti dalla propria
distribuzioni. Faremo comunque riferimento ai programmi forniti dal progetto
\texttt{OpenLDAP}, la cui installazione manuale avviene insieme a quella del
server, che è già stata affrontata in
sez.~\ref{sec:slapd_installazione}. Prenderemo inoltre in esame anche i
programmi di gestione amministrativa usati per la manipolazione diretta dei
dati dal server \texttt{slapd} di \textit{OpenLDAP}.


\subsection{La configurazione generica per l'accesso client}
\label{sec:ldap_client_base_config}

Come illustrato in sez.~\ref{sec:ldap_query_mechanism} l'accesso ai dati
forniti da un servizio LDAP avviene tramite l'omonimo protocollo con una
comunicazione fra un client ed un server. Oltre alle interrogazioni, che
tratteremo in dettaglio in sez.~\ref{sec:ldap_search}, il protocollo fornisce
anche le funzionalità per inserire e modificare i dati su un server, ed in
sez.~\ref{sec:ldap_content_management} tratteremo l'uso dei programmi a riga
di comando forniti allo scopo dal progetto \textit{OpenLDAP}.

Nella gran parte dei casi la comunicazione fra client e server con il
protocollo LDAP viene effettuata facendo ricorso a delle opportune librerie
(nel nostro caso quelle fornite da \textit{OpenLDAP}), che implementano
l'interfaccia di programmazione generica che poi verrà usata dai vari
programmi. Per questo effettuare la configurazione delle suddette librerie
comporta automaticamente anche la configurazione di tutti i programmi che
usano le funzionalità che esse mettono a disposizione.

Il file di configurazione generale delle librerie di \textit{OpenLDAP}, che
sono le più usate, è \index{configurazione!\texttt{/etc/ldap/ldap.conf}}
\texttt{ldap.conf} (installato sotto \texttt{/etc/ldap/} su Debian e sotto
\texttt{/etc/openldap/} su RedHat), e per quanto riguarda l'espressione delle
direttive esso ha un formato generale identico a quello di
\texttt{slapd.conf}, anche se in questo caso non esistono diversi livelli in
cui queste sono ordinate.

\index{OpenLDAP!direttiva~client!\texttt{BINDDN}}
\index{OpenLDAP!direttiva~client!\texttt{SIZELIMIT}}
\index{OpenLDAP!direttiva~client!\texttt{TIMELIMIT}}
%\index{OpenLDAP!direttiva~client!\texttt{bind\_timelimit}}
\index{OpenLDAP!direttiva~client!\texttt{scope}}
\index{OpenLDAP!direttiva~client!\texttt{rootbinddn}}
\index{OpenLDAP!direttiva~client!\texttt{debug}}
\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Direttiva} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{BASE}     & indica il \textit{Distinguished Name} usato come base
                        per le ricerche nell'albero.\\ 
    \texttt{BINDDN}   & indica il \textit{Distinguished Name} dell'utente
                        per conto del quale viene eseguito il collegamento di
                        default, se non lo si indica il collegamento è
                        anonimo.\\
    \texttt{BINDPW}   & la password da usare per collegarsi con il
                        \textit{Distinguished Name} specificato dalla
                        precedente \texttt{BINDDN}.\\
    \texttt{DEREF}    & specifica come viene eseguito la dereferenziazione
                        degli alias quando si esegue una ricerca, prende i
                        valori \texttt{never} (default) per non eseguirla mai,
                        \texttt{searching} per eseguirla solo per oggetti
                        sotto la base ma non per la base stessa,
                        \texttt{finding} solo per la base e \texttt{always}
                        per farla comunque.\\
    \texttt{HOST}     & indica il nome o l'indirizzo IP del server a cui
                        collegarsi di default, nella forma
                        \texttt{indirizzo:porta}, deprecato.\\ 
    \texttt{PORT}     & indica la porta da usare quando ci si collega ad un
                        server LDAP, deprecato.\\
    \texttt{REFERRALS}& indica se i client deve seguire automaticamente
                        eventuali \textit{referral} restituiti dal server, i
                        valori possibili sono \texttt{on} (default),
                        \texttt{true}, \texttt{yes}, \texttt{off},
                        \texttt{false}, \texttt{no}.\\
    \texttt{SCOPE}    & indica la profondità su cui viene eseguita la
                        ricerca dei dati, prende i valori illustrati in
                        tab.~\ref{tab:ldap_scope_values}. \\
    \texttt{SIZELIMIT}& indica un limite massimo di dimensioni nelle ricerche,
                        deve essere un valore positivo; un valore nullo (il
                        default) indica una dimensione illimitata.\\
    \texttt{TIMELIMIT}& indica un limite massimo di tempo nell'eseguire una
                        ricerca, deve essere un valore positivo; un valore
                        nullo (il default) indica un tempo illimitato.\\
    \texttt{URI}      & indica la URL (nel formato illustrato in
                        tab.~\ref{tab:ldap_URL}) con cui contattare il
                        server.\\
    % \texttt{ROOTBINDDN}&specifica l'utente del database con il quale devono
    %                     essere eseguiti gli accessi a LDAP effettuati da un
    %                     processo che viene eseguito con i privilegi
    %                     di amministratore (necessita della relativa
    %                     password nel file \texttt{/etc/ldap.secret}).\\
    % \texttt{DEBUG}    & indica il livello di debug per i messaggi di errore
    %                     del client, prende un valore
    %                     numerico con lo stesso significato visto in 
    %                     tab.\ref{tab:slapd_debug_bits} per
    %                     l'analoga direttiva del server.\\ % obsoleto?
    % \texttt{TIMEOUT}  & .\\
    % \texttt{bind\_timelimit}& indica un tempo massimo di collegamento al
    %                        server (in secondi) oltre il quale la connessione
    %                        viene automaticamente chiusa.\\
    % \texttt{bind\_policy}& .\\
    \hline
  \end{tabular}
  \caption{Le principali direttive di \texttt{ldap.conf}.}
  \label{tab:ldap_conf_directives}
\end{table}

L'impostazione principale che si esegue in questo file è quella del server di
default, a cui verranno rivolte le interrogazioni quando non se ne è indicato
uno esplicitamente.  Questo può essere fatto con le direttive
\index{OpenLDAP!direttiva~client!\texttt{HOST}} \texttt{HOST} e
\index{OpenLDAP!direttiva~client!\texttt{PORT}} \texttt{PORT}, cui deve
seguire rispettivamente l'indirizzo IP (o il nome) del server e il numero di
porta. Quest'ultimo può anche essere indicato direttamente nell'argomento di
\texttt{HOST} scrivendolo separato con un carattere ``\texttt{:}'' di seguito
al nome (o all'indirizzo); si può anche non specificare la porta, nel qual
caso sarà utilizzata la porta standard associata al servizio LDAP, la 389.

Le direttive \texttt{HOST} e \texttt{PORT} sono comunque deprecate in favore
della nuova direttiva \index{OpenLDAP!direttiva~client!\texttt{URI}}
\texttt{URI}; questa prende un indirizzo nella forma della URL estesa già
illustrata in precedenza, che specifica l'indirizzo (ed eventuale porta) del
server a cui ci si rivolge, o, nel caso di \texttt{ldapi://}, il pathname del
socket locale su cui è in ascolto il server.  Si tenga presente che con
\texttt{URI} si possono specificare più URL (separate da spazi) e che queste
verranno utilizzate una dopo l'altra in caso di mancata risposta; questo
consente di avere un meccanismo di \textit{failover} automatico della
connessione verso un server, supportato direttamente da qualunque programma
usi le librerie standard.

Un'altra direttiva fondamentale è
\index{OpenLDAP!direttiva~client!\texttt{BASE}} \texttt{BASE} che permette di
definire il \textit{Distinguished Name} da usare come suffisso base per le
ricerche; serve cioè ad impostare la radice dell'albero dei dati presenti sul
server, ma può essere anche usata per restringere l'accesso delle
interrogazioni ad una sezione particolare dell'albero (ad esempio alla sola
parte che contiene l'indirizzario, o a quella relativa ad una sola unità
operativa).

Le altre direttive comuni più usate sono riportate in
tab.~\ref{tab:ldap_conf_directives}, i nomi in tabella sono indicati in
maiuscolo, ma il loro valore è \textit{case insensitive} e negli esempi sono
spesso utilizzati, in maniera altrettanto valida, caratteri minuscoli. Il file
prevede inoltre la presenza di ulteriori direttive relative alla
configurazione di alcune funzionalità specifiche come SASL o SSL che non sono
riportate qui e che esamineremo più avanti quando tratteremo i relativi
argomenti. Per l'elenco completo si può comunque consultare la pagina di
manuale, accessibile con \texttt{man ldap.conf}.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Variabile} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{LDAPNOINIT} & se definita disabilita tutti i valori di default,
                          nessuno dei file di configurazione o delle variabili
                          seguenti ha effetto.\\
    \texttt{LDAPCONF}   & deve essere assegnata al nome del file da usare come
                          file di configurazione aggiuntivo rispetto a
                          \texttt{ldap.conf}, le cui direttive soprassiedono
                          quest'ultimo e quelle di \texttt{.ldaprc}.\\ 
    \texttt{LDAPRC}     & indica il nome di un file aggiuntivo rispetto a
                          \texttt{.ldaprc}, da cercare nella directory
                          corrente o nella home dell'utente, i cui contenuti
                          hanno la precedenza rispetto a quanto indicato in 
                          un eventuale \texttt{LDAPCONF}.\\
    \texttt{LDAP<XXX>}  & soprassiede il valore della direttiva 
                          \texttt{XXX} in una qualunque delle indicazioni
                          precedenti (ad esempio \texttt{LDAPURI} soprassiede
                          il valore di \texttt{URI}).\\ 
    \hline
  \end{tabular}
  \caption{Variabili di ambiente che controllano il comportamento delle
    librerie di accesso di \textit{OpenLDAP}.}
  \label{tab:ldap_conf_environment}
\end{table}

Oltre alla configurazione generale di \texttt{ldap.conf}, le librerie seguono
anche quella personale che un utente può creare usando le stesse direttive
all'interno di un file \index{configurazione!\texttt{.ldaprc}}
\texttt{.ldaprc} posto nella sua home directory; così facendo le nuove
impostazioni soprassiederanno quelle generali. Di solito è in questo file che
è opportuno inserire (proteggendolo dalla lettura) eventuali direttive
\texttt{BINDDN} e \texttt{BINDPW} per definire un accesso autenticato.

Una ulteriore capacità di personalizzazione si può ottenere con l'uso di
alcune variabili di ambiente, ad esempio con \texttt{LDAPCONF} si può indicare
un file di configurazione aggiuntivo con cui sovrascrivere le direttive dei
file precedenti. Un elenco di queste variabili di ambiente, del loro effetto e
delle priorità delle relative configurazioni è riportato in
tab.~\ref{tab:ldap_conf_environment}.

In generale tutto quello che c'è da impostare sul lato client è il server a
cui rivolgersi e la base della ricerca; il contenuto tipico di un file
\texttt{ldap.conf} è pertanto analogo al seguente, estratto dal file
installato su Debian Wheezy, a cui si sono aggiunte le configurazioni per
raggiungere un server (definendo \texttt{BASE} e \texttt{URI}):
\begin{FileExample}[label=ldap.conf]
#
# LDAP Defaults
#

# See ldap.conf(5) for details
# This file should be world readable but not world writable.

#BASE   dc=example, dc=com
#URI    ldap://ldap.example.com ldap://ldap-master.example.com:666
BASE    dc=truelite, dc=it
URI     ldaps://ldap.truelite.it

#SIZELIMIT      12
#TIMELIMIT      15
#DEREF          never

# TLS certificates (needed for GnuTLS)
TLS_CACERT	/etc/ssl/certs/ca-certificates.crt
\end{FileExample}




\subsection{Interrogazioni e ricerche su LDAP}
\label{sec:ldap_search}


L'utilizzo principale che viene fatto di un server LDAP è quello di eseguire
interrogazioni e ricerche sui dati in esso mantenuti. Per la gran parte dei
programmi che utilizzano LDAP (quelli che vedremo in
sez.~\ref{sec:ldap_integration}) queste interrogazioni avvengono direttamente
attraverso le funzioni di libreria, ma \textit{OpenLDAP} fornisce anche un
client a riga di comando: \index{comando!\texttt{ldapsearch}}
\texttt{ldapsearch}.

Il comando di default si rivolge al server (o ai server) indicati in
\texttt{ldap.conf}, ma si può specificare a quale server LDAP collegarsi
usando l'opzione \texttt{-H} ed indicando il server con la sintassi delle URI
estese illustrata in sez.~\ref{sec:ldap_client_base_config}. In caso di
problemi di connessione si può abilitare la stampa di messaggi di debug dal
lato client usando l'opzione \texttt{-d}, che prende gli stessi valori usati
da \texttt{slapd}, già visti in tab.~\ref{tab:slapd_debug_bits}.

In generale, oltre ad indicare a quale server rivolgersi, per poter eseguire
una qualunque operazione su un server LDAP è necessario anche autenticarsi.
L'autenticazione è un argomento complesso, che tratteremo in
sez.~\ref{sec:ldap_authentication_methods}, per adesso basti sapere che
esistono diverse modalità di autenticazione, e che tutti i programmi client
forniti da \textit{OpenLDAP} supportano un gruppo di opzioni comuni relative
all'autenticazione.

In particolare negli esempi utilizzeremo solo quella che viene chiamata
modalità di \textsl{autenticazione semplice}, per attivare la quale occorre
usare l'opzione \texttt{-x}.  Questa opzione deve essere indicata sempre, i
programmi infatti richiedono una modalità di autenticazione ed il default è di
usare quella basata sulle librerie SASL (che affronteremo in
sez.~\ref{sec:ldap_authentication_methods}); tutto ciò richiederebbe la
presenza della relativa infrastruttura, che la gran parte delle distribuzioni
non installano neanche, per cui diventa necessario forzare l'uso
dell'autenticazione semplice.

Se non si specifica altro che \texttt{-x} si effettuerà un accesso anonimo,
mentre per specificare per conto di quale utente ci si vuole collegare si deve
usare l'opzione \texttt{-D} seguita del DN che si vuole utilizzare come
utente, in tal caso si potrà usare l'opzione \texttt{-W} per richiedere
l'immissione della relativa password sul terminale, mentre con \texttt{-w}
questa potrà essere specificata direttamente sulla linea di comando. Abbiamo
visto in sez.~\ref{sec:ldap_client_base_config} come queste informazioni
possano essere specificate in un file di configurazione con le direttive
\texttt{BINDDN} e \texttt{BINDPW}, in modo da non doverle indicare tutte le
volte.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{-d \textsl{N}}   & abilita la modalità di debug, prende come
                               parametro una maschera binaria secondo i valori
                               illustrati in tab.~\ref{tab:slapd_debug_bits}.\\ 
    \texttt{-D \textsl{dn}}  & specifica il DN da usare come utente per
                               collegarsi al server.\\  
    \texttt{-h \textsl{host}}& specifica il server a cui collegarsi per
                               hostname o indirizzo IP (deprecato in favore di
                               \texttt{-H}).\\
    \texttt{-H \textsl{uri}} & specifica il server a cui collegarsi con la
                               sintassi delle URL di LDAP.\\ 
    \texttt{-p \textsl{port}}& specifica la porta a cui collegarsi sul server
                               indicato con \texttt{-h} (deprecato in favore
                               di \texttt{-H}).\\
    \texttt{-v}& stampa maggiori informazioni sullo \textit{standard output}.\\ 
    \texttt{-x}& usa l'autenticazione semplice.\\ 
    \texttt{-y \textsl{file}}& specifica un file contenente la password.\\ 
    \texttt{-w \textsl{pass}}& specifica direttamente la password, passata
                               come parametro, per l'autenticazione semplice.\\ 
    \texttt{-W}& richiede l'immissione di una password per l'autenticazione
                 semplice.\\  
    \texttt{-Z}& invia una richiesta di \textit{StartTLS} sulla connessione in
                 chiaro per attivarne la cifratura con TLS, una seconda
                 ``\texttt{Z}'' richiede che l'operazione abbia successo per
                 proseguire.\\  
    \hline
  \end{tabular}
  \caption{Le opzioni comuni dei programmi client di \textit{OpenLDAP}.}
  \label{tab:ldap_client_options}
\end{table}


Si tenga presente che in ogni caso con \texttt{ldapsearch} si potranno
ottenere soltanto quelle informazioni a cui i privilegi dell'utente con cui ci
si collega danno accesso, e nel caso di accesso anonimo solo a quelle rese
pubbliche.  Le principali principali opzioni comuni, usate da
\texttt{ldapsearch} e da tutti gli altri programmi client forniti da
\textit{OpenLDAP} sono riportate in tab.~\ref{tab:ldap_client_options}.

Il comando prende come primo argomento un filtro di ricerca, lo stesso che può
comparire nelle URL estese viste in sez.~\ref{sec:ldap_query_mechanism} (sulla
cui sintassi torneremo più avanti) seguito da una lista opzionale di
attributi. Se una o più voci corrispondenti al filtro di ricerca vengono
trovate, il comando stampa sullo \textit{standard output} i relativi risultati
in formato LDIF. Se non si specifica un filtro verrà stampato il contenuto di
tutto l'albero, compatibilmente con il numero massimo di voci restituite dal
server (secondo il valore della direttiva \texttt{sizelimit}, vedi
sez.~\ref{sec:ldap_server_base_config}).

Se si sono indicati degli attributi (per nome) verranno stampati solo i valori
di questi ultimi, altrimenti verranno stampati tutti gli attributi ordinari
presenti nell'oggetto, compatibilmente con i privilegi dell'utente con cui ci
si è collegati, ad esempio nel caso di collegamento anonimo si potranno
stampare solo i valori degli attributi dichiarati pubblici.

Come attributo si può anche specificare il valore riservato ``\texttt{+}'' che
identifica i cosiddetti \index{attributi~speciali} \textsl{attributi speciali}
associati ad un oggetto, cioè quelli mantenuti direttamente dal server, come
le date di modifica, creazione, ecc. o l'attributo \texttt{hasSubordinates}
che indica che un oggetto ha altri oggetti al disotto nella gerarchia
dell'albero, che di default non vengono mai stampati. Il server riconosce
anche l'attributo ``\texttt{*}'' che stampa tutti gli attributi ordinari,
equivalente a non indicare nulla, ma utilizzabile insieme a ``\texttt{+}'' per
ottenere tutti gli attributi (ordinari e speciali). In sostanza se si usa solo
``\texttt{+}'' verranno stampati solo gli attributi speciali, con ``\texttt{'+'
  '*'}'' vengono stampati tutti gli attributi, speciali e non.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
%    \texttt{-u}& include nell'output .\\ 
    \texttt{-A}& ricava solo la presenza degli attributi e non il loro
                 valore.\\  
    \texttt{-L}& richiede che i risultati siano riportati in formato LDIF;
                 specificato una sola restringe l'output a LDIFv1, usato due
                 volte elimina i commenti, una terza volta non scrive la
                 versione usata; il default è la versione estesa di LDIF.\\ 
%    \texttt{-f}& legge una serie di linee da un file, eseguendo una ricerca
%                 per ogni riga.\\ 
    \texttt{-b \textsl{base}}& indica la base della ricerca da specificare con
                               il corrispondente \textit{Distinguished Name}.\\
    \texttt{-l \textsl{sec}} & indica un limite di tempo nell'esecuzione della
                               ricerca (specificato in numero di secondi); un
                               valore nullo soprassiede un eventuale limite
                               specificato in \texttt{ldap.conf}.\\ 
    \texttt{-s \textsl{scope}}&indica la profondità della ricerca, prende come 
                               argomento uno dei tre valori di
                               tab.~\ref{tab:ldap_scope_values}.\\  
    \texttt{-S \textsl{attr}}& ordina i risultati sulla base dell'attributo
                               passato come argomento.\\ 
    \texttt{-t}& scrive i risultati su un insieme di file temporanei (è utile
                 per tutti quei casi in cui un attributo contiene dati non
                 testuali). \\ 
    \texttt{-z \textsl{size}}& indica un limite sul numero di voci riportate
                               come risultato della  ricerca; un valore nullo
                               soprassiede un eventuale limite specificato in
                               \texttt{ldap.conf}.\\
    \hline
  \end{tabular}
  \caption{Le opzioni principali di \texttt{ldapsearch}.}
  \label{tab:ldapsearch_options}
\end{table}

Con l'opzione \texttt{-b} inoltre si può restringere la ricerca ad una sezione
dell'albero indicando la base della ricerca con il DN da cui partire (il
default è usare la base dell'albero specificata in \texttt{ldap.conf}); si può
poi definire la profondità a cui viene eseguita la ricerca con l'opzione
\texttt{-s}, questa prende tre valori, illustrati in
tab.~\ref{tab:ldap_scope_values}. Le altre opzioni principali del comando sono
riportate in tab.~\ref{tab:ldapsearch_options}, al solito l'elenco completo è
nella pagina di manuale.

\begin{table}[!hbt]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|l|}
    \hline
    \textbf{Valore} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{base}& indica il livello esatto del DN indicato.\\ 
    \texttt{one} & indica il livello successivo a quello del DN indicato.\\ 
    \texttt{sub} & indica tutti i livelli successivi a quello del DN 
                   indicato.\\ 
    \hline
  \end{tabular}
  \caption{Valori per il parametro che indica il livello di profondità di una
    ricerca.} 
  \label{tab:ldap_scope_values}
\end{table}

\index{filtri~di~ricerca|(}

I filtri di ricerca sono una delle funzionalità previste dal protocollo LDAP
per ottimizzare le interrogazioni; il filtro infatti viene inviato
direttamente al server come parte della richiesta, ed è quest'ultimo che si
incarica di eseguire la ricerca con le condizioni in esso specificate,
restituendo soltanto i risultati che corrispondono. Questo consente di ridurre
la quantità dei dati trasmessi, effettuando la selezione degli stessi
direttamente sul server; uno degli errori più comuni per i programmatori alle
prime armi con LDAP è proprio quello di farsi restituire tutti i dati per poi
eseguire la ricerca sul lato del client.  Per questo motivo, oltre ad essere
l'argomento principale di \texttt{ldapsearch}, essi sono riconosciuti da
qualunque client e vengono utilizzati tutte le volte che si vogliono definire
dei criteri di ricerca per la selezione delle informazioni.

La sintassi dei filtri di ricerca è piuttosto complessa ed è stata
standardizzata nell'\href{http://www.ietf.org/rfc/rfc2254.txt}{RFC~2254}; essi
si basano su delle espressioni di base che poi possono essere combinate fra di
loro. Ogni espressione deve comunque essere racchiusa fra parentesi tonde,
così come ogni combinazione di espressioni, pertanto un filtro sarà sempre
espresso con una stringa del tipo: ``\texttt{(filtro)}''. Si tenga presente
però, nel caso di uso di \texttt{ldapsearch} dalla riga di comando, che le
parentesi tonde sono caratteri riservati, per cui l'espressione del filtro
dovrà essere adeguatamente protetta dall'interpretazione della shell.

Le espressioni di base sono riportate in tab.~\ref{tab:ldap_filter_base}; le
prime quattro operano sui valori degli attributi, mentre la quinta seleziona
tutti gli oggetti nell'albero che appartengono ad una certa
\texttt{objectclass}; questo vale anche per le \texttt{objectclass} derivate
da altre, per cui se si richiede \texttt{objectclass=person} saranno
selezionati anche gli oggetti delle classi \texttt{inetOrgPerson} o
\objcl{organizationalPerson}, che dalla classe \objcl{person} sono derivate.
Il tipo di ricerca che viene effettuata dipende dall'espressione utilizzata;
inoltre le espressioni supportano la presenza del carattere jolly
``\texttt{*}'' che ne modifica il significato. Il filtro di default usato da
\texttt{ldapsearch} quando non se ne specifica uno è \texttt{(objectclass=*)},
che indica tutti gli oggetti presenti nel database.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Espressione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{attr=val}       & richiede l'uguaglianza del valore o la ricerca
                              di una sotto-stringa se il valore contiene il
                              carattere jolly ``\texttt{*}'' o la semplice
                              presenza se si è usato solo ``\texttt{*}''.\\ 
    \texttt{attr\tild =val} & esegue una ricerca di uguaglianza
                              \textsl{approssimata} secondo uno degli
                              algoritmi di somiglianza definiti dal
                              protocollo (in questo caso è necessaria la
                              presenza di un indice di tipo 
                              \texttt{approx} (vedi
                              tab.~\ref{tab:ldap_indexing_type}) per
                              l'attributo in questione).\\ 
    \texttt{attr>=val}      & seleziona tutti i valori che siano lessicalmente
                              uguali o \textsl{maggiori} di quello
                              specificato.\footnotemark \\ 
    \texttt{attr<=val}      & seleziona tutti i valori che siano lessicalmente
                              uguali o \textsl{minori} di quello
                              specificato.\\ 
    \texttt{objectclass=val}& seleziona tutti gli oggetti della
                              \texttt{objectclass} specificata.\\ 
    \hline
  \end{tabular}
  \caption{Espressioni di base di un filtro di ricerca.}
  \label{tab:ldap_filter_base}
\end{table}

\footnotetext{questa regola di selezione richiede che l'attributo sia definito
  con una regola di ordinamento opportuna; in generale questo non avviene
  quasi mai e l'uso di un filtro che contenga una tale espressione, o la
  analoga \texttt{<=}, è estremamente raro.}

Dato che l'espressione utilizzata in un filtro ha un diretto riscontro nel
tipo di ricerca che il server si trova ad effettuare, e che per
l'ottimizzazione delle ricerche sono necessari diversi metodi di
indicizzazione del database (quelli indicati dai vari valori della direttiva
\texttt{index} che tratteremo in tab.~\ref{tab:ldap_indexing_type}), è bene
trattare in dettaglio tutti i possibili casi, in quanto la configurazione
delle indicizzazioni da fare sul server è strettamente connessa al tipo di
ricerche che vengono eseguite.

Se si richiede solo la corrispondenza di un attributo ad un certo valore, con
una espressione del tipo ``\texttt{(uid=piccardi)}'', verrà eseguito un test
di uguaglianza e si dovrà utilizzare una indicizzazione di tipo \texttt{eq}.
Con l'uso del carattere jolly si possono però anche eseguire ricerche sulla
presenza di una certa stringa, come \texttt{(mail=*@truelite.it)}, ed in
questo caso si dovrà usare una indicizzazione di tipo \texttt{sub}.\footnote{o
  una delle varie forme \texttt{subinitial}, \texttt{subfinal} e
  \texttt{subany} a seconda della posizione.} Infine se si usa soltanto il
carattere jolly, con una espressione del tipo di \texttt{(ou=*)} la ricerca
sarà eseguita richiedendo solo la presenza di quell'attributo, e
l'indicizzazione dovrà essere di tipo \texttt{pres}; lo stesso avviene per
tutte le ricerche sulle \textit{objectclass}.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|l|l|}
    \hline
    \textbf{Operatore} & \textbf{Esempio} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{\&}&\texttt{(\&(exp1)(exp2)(exp3))}& devono valere sia
                                                 \texttt{exp1} che 
                                                 \texttt{exp2} che
                                                 \texttt{exp3}.\\ 
    \texttt{|} &\texttt{(|(exp1)(exp2)(exp3))} & devono valere o
                                                 \texttt{exp1} o
                                                 \texttt{exp2} o
                                                 \texttt{exp3}.\\ 
    \texttt{!} &\texttt{(!(exp))}              & non deve valere
                                                 \texttt{exp}.\\ 
    \hline
  \end{tabular}
  \caption{Operatori per le espressioni sui filtri di ricerca.}
  \label{tab:ldap_filter_operator}
\end{table}

La potenza dei filtri di ricerca è che si possono combinare fra di loro più
espressioni (di base, o costruite come combinazione di altre espressioni)
utilizzando tre operatori logici che hanno rispettivamente il significato di
AND, OR e NOT logico, secondo la sintassi illustrata in
tab.~\ref{tab:ldap_filter_operator}. In questo modo è possibile ottenere dei
filtri di ricerca anche molto complessi.

Ad esempio se si vogliono ricercare in un indirizzario tutte le persone il cui
cognome inizia o per ``S'' o per ``D'', si potrà usare l'espressione:
\begin{Console}
$ \textbf{ldapsearch -x "(|(sn=S*)(sn=D*))"} 
\end{Console}
%$

\index{filtri~di~ricerca|)}

Oltre alle interrogazioni generiche dei dati mantenuti dal server LDAP di cui
si è parlato finora, molti server, fra cui \texttt{slapd}, supportano delle
interrogazioni speciali che consentono di ottenere informazioni relative al
server stesso. In particolare essendo previste diverse versioni e revisioni
del protocollo, ed potendo essere adottate una grande quantità di estensioni
può risultare estremamente utile sapere quali sono quelle disponibili.

I dati relativi alle funzionalità ed alle estensioni presenti vengono in
genere pubblicati come specifici attributi della radice dell'albero (il
cosiddetto \itindex{Root DSE} \textit{Root DSE}), e possono essere richiesti
direttamente attraverso il protocollo con una operazione di ricerca, per cui
si può utilizzare di nuovo \texttt{ldapsearch} per ottenere le
informazioni. In questo caso però occorre indicare esplicitamente che si
intendono ottenere i dati relativi al \textit{Root DSE} e non al proprio
albero, pertanto occorrerà indicare quest'ultimo, che è contraddistinto da una
base vuota.

Gli attributi disponibili per questa ricerca sono \texttt{supportedFeatures},
\texttt{supportedControl} e \texttt{supportedExtension}, che però essendo
\textsl{attributi speciali} devono essere essere richiesti esplicitamente, ma
si possono ottenere direttamente usando la richiesta esplicita con il filtro
``\texttt{+}''. Così per conoscere i dati relativi al proprio server sarà
sufficiente eseguire il comando:
\begin{Console}
$ \textbf{ldapsearch -x -b "" -s base +}
# extended LDIF
#
# LDAPv3
# base <> with scope baseObject
# filter: (objectclass=*)
# requesting: + 
#

#
dn:
structuralObjectClass: OpenLDAProotDSE
configContext: cn=config
namingContexts: dc=truelite,dc=it
supportedControl: 2.16.840.1.113730.3.4.18
supportedControl: 2.16.840.1.113730.3.4.2
supportedControl: 1.3.6.1.4.1.4203.1.10.1
supportedControl: 1.2.840.113556.1.4.319
supportedControl: 1.2.826.0.1.3344810.2.3
supportedControl: 1.3.6.1.1.13.2
supportedControl: 1.3.6.1.1.13.1
supportedControl: 1.3.6.1.1.12
supportedExtension: 1.3.6.1.4.1.1466.20037
supportedExtension: 1.3.6.1.4.1.4203.1.11.1
supportedExtension: 1.3.6.1.4.1.4203.1.11.3
supportedExtension: 1.3.6.1.1.8
supportedFeatures: 1.3.6.1.1.14
supportedFeatures: 1.3.6.1.4.1.4203.1.5.1
supportedFeatures: 1.3.6.1.4.1.4203.1.5.2
supportedFeatures: 1.3.6.1.4.1.4203.1.5.3
supportedFeatures: 1.3.6.1.4.1.4203.1.5.4
supportedFeatures: 1.3.6.1.4.1.4203.1.5.5
supportedLDAPVersion: 3
supportedSASLMechanisms: NTLM
supportedSASLMechanisms: DIGEST-MD5
supportedSASLMechanisms: CRAM-MD5
entryDN:
subschemaSubentry: cn=Subschema
\end{Console}
%$
e come si può vedere oltre ai tre attributi citati se ne ottengono pure altri,
che indicano il contesto (assimilabile alla radice dell'albero) di
configurazione (\texttt{configContext}) ed eventuali \textsl{contesti nominali}
(\texttt{namingContexts}), corrispondenti ai suffissi usati per ciascun
database mantenuto nel server (nell'esempio precedente ce n'è uno solo,
\texttt{dc=truelite,dc=it}).

Per quanto riguarda gli altri attributi invece il risultato non è molto
leggibile, dato che funzionalità, estensioni e controlli non vengono descritti
esplicitamente, ma identificati dal relativo OID il cui valore è quello
indicato nei vari RFC che descrivono le estensioni e le aggiunte del
protocollo.\footnote{un elenco di quelle supportate da \textit{OpenLDAP} è
  illustrato su \url{http://www.openldap.org/faq/data/cache/645.html}.}


\subsection{Creazione e manutenzione di un database LDAP}
\label{sec:ldap_content_management}

Una volta installato e configurato il server, per poter immettere le
informazioni sull'elenco occorre predisporre l'infrastruttura che permetta di
inserirle negli appropriati rami dell'albero. Nel caso di Debian installando
\texttt{slapd} il sistema del \textit{debconf} provvede a chiedere le
informazioni necessarie alla creazione della struttura iniziale dell'albero,
contenente soltanto la radice del dominio e l'utente usato per
l'amministrazione. Negli altri casi occorre decidere quale sarà la radice
dell'albero (quella della direttiva \texttt{suffix} vista in
sez.~\ref{sec:ldap_server_base_config}) per poi inserire le informazioni a
mano.

In generale, anche se non è strettamente necessario,\footnote{si potrebbe
  partire direttamente anche con un oggetto di tipo \textit{Organization}, che
  è un contenitore sufficientemente generico, l'uso di una delle due
  strutturazioni di sez.~\ref{sec:ldap_general_structure} infatti ha senso
  solo se si ha intenzione di inserire l'elenco in un albero di visibilità
  globale, cosa che in realtà accade assai raramente.} è uso seguire la
seconda delle due strutturazioni illustrate in
sez.~\ref{sec:ldap_general_structure}, quella che fa riferimento ad i nomi a
dominio, e poi occorre inserire nel database gli opportuni dati.  Questo si
può fare in due modi: il primo prevede l'uso del protocollo stesso per
inserire informazioni all'interno dell'albero, il che comporta l'uso di un
qualunque client LDAP in grado di parlare con il server. Il secondo invece usa
il programma di utilità \texttt{slapadd}, che fornisce un accesso diretto al
database, ma che è specifico di \textit{OpenLDAP} essendo questo uno programmi
specifici usati per la manutenzione dei dati di \texttt{slapd}.

La differenza fra le due modalità è che nel primo caso si potrà operare anche
da remoto, ed usando il protocollo le operazioni saranno valide per qualunque
tipo di server. Nel secondo caso il comando potrà essere eseguito solo sulla
macchina su cui si trova il database e si potrà usare solo per i dati gestiti
con \texttt{slapd}.  Inoltre, dato che \texttt{slapadd} opera sui dati in
maniera indipendente, è necessario utilizzarlo quando il server non è attivo.
Il vantaggio è però che, con file di grosse dimensioni (ad esempio nel
ripristinare un backup) il comando è molto più veloce e non necessita del
collegamento al server con un utente dotato di sufficienti privilegi di
accesso, né che questo sia attivo.

Il comando infatti agisce direttamente sui file del database e l'accesso è
diretto sul filesystem senza dover passare dall'autenticazione di
LDAP. Ovviamente occorre il permesso di scrittura sui file del database, che
di norma ha soltanto l'amministratore, ed occorre anche verificare, quando si
creano i file, che questi poi possano essere usati dall'utente per conto del
quale si esegue il server LDAP (quello dell'opzione \texttt{-u} di
tab.~\ref{tab:slapd_options}, in genere \texttt{openldap}).  Un'altra
differenza fra le due modalità di creazione dei dati è che nel primo caso le
informazioni di controllo su un oggetto come il tempo di ultima
modifica\footnote{quello che \texttt{slapd} mantiene automaticamente negli
  opportuni attributi interni quando si è impostata la direttiva
  \texttt{lastmod} a \texttt{on} (vedi
  sez.~\ref{sec:ldap_server_base_config}).} non possono venire impostate, in
quanto la loro scrittura viene gestita autonomamente dal server, mentre
\texttt{slapadd} può inserire anche queste informazioni (nasce infatti come
strumento di ripristino da un backup, dove anche queste informazioni vengono
salvate).

Per inserire i dati con \index{comando!\texttt{slapadd}} \texttt{slapadd}
basta avere questi ultimi in formato LDIF. Il comando legge di default i dati
dallo \textit{standard input}, ma l'uso più comune è quello di usare l'opzione
\texttt{-l} per farglieli leggere da un file. Si tenga presente che il comando
si aspetta di ricevere i dati nell'ordine in cui i database sono dichiarati
nella configurazione del server, che non esegue nessun controllo sulla
presenza di una infrastruttura in cui inserire i dati (questo vuol dire che si
avrà un errore se il dato esiste già o si cerca di inserirlo in una sezione
dell'albero che ancora non esiste) né che questi siano consistenti con gli
\textit{schema} utilizzati (e di nuovo si avrà un errore se contengono oggetti
con attributi o \textit{objectclass} non definite nel server); per questo
motivo lo si usa principalmente per ripristinare i dati ottenuti da un dump
eseguito da \texttt{slapcat}.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{-b \textsl{suffix}}& opera sul database identificato dal suffisso
                                 \texttt{\textsl{suffix}}.\\ 
    \texttt{-c}              & continua l'esecuzione del comando anche se
                               riscontra degli errori, processando i dati
                               restanti.\\ 
    \texttt{-d \textsl{N}}   & abilita la stampa di messaggi di debug delle
                               operazioni, prende i valori illustrati
                               in tab.~\ref{tab:slapd_debug_bits}.\\ 
    \texttt{-f \textsl{file}}& esegue le operazioni usando la configurazione 
                               letta dal file \texttt{\textsl{file}}.\\
    \texttt{-F \textsl{dir}} & esegue le operazioni usando la configurazione 
                               letta dalla dire-ctory \texttt{\textsl{dir}}.\\
    \texttt{-n \textsl{N}}   & opera sull'\textsl{\texttt{N}}-simo database
                               configurato; prende anche il valore 0
                               che indica il database della configurazione
                               (vedi sez.~\ref{sec:slapd_database_config}); è
                               incompatibile con \texttt{-b}.\\
    \hline
  \end{tabular}
  \caption{Le opzioni comuni dei comandi di gestione (\texttt{slapadd},
    \texttt{slapcat}, \texttt{slapindex}, ecc.).}
  \label{tab:slapd_tools_options}
\end{table}

Qualora si voglia utilizzare un file di configurazione o una directory di
configurazione alternativi li si possono specificare rispettivamente con
l'opzione \texttt{-f} o \texttt{-F}.  Inoltre in presenza di più database
mantenuti dallo stesso server si può indicare su quale database operare, sulla
base del valore della rispettiva radice, usando l'opzione \texttt{-b}, che
prende come valore lo stesso parametro usato nella direttiva \texttt{suffix}
di \texttt{slapd} (vedi sez.~\ref{sec:ldap_server_base_config}).

In tab.~\ref{tab:slapd_tools_options} si sono riportate le principali opzioni
di \texttt{slapadd} comuni con tutti gli altri programmi di gestione associati
a \texttt{slapd}, mentre in tab.~\ref{tab:slapadd_options}, sono illustrate
quelle specifiche del comando. Per l'elenco completo si consulti la pagina di
manuale.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{-l \textsl{file}}& legge i dati in formato LDIF dal file
                               specificato come parametro.\\
    \texttt{-u}              & abilita le operazioni in modalità di test,
                               senza scrivere sul database.\\
    \hline
  \end{tabular}
  \caption{Le opzioni specifiche del comando \texttt{slapadd}.}
  \label{tab:slapadd_options}
\end{table}

Come controparte di \texttt{slapadd} \textit{OpenLDAP} fornisce anche il
comando \index{comando!\texttt{slapcat}} \texttt{slapcat}, che permette di
estratte tutti i dati presenti in un database scrivendoli in formato LDIF. Il
comando è pertanto utilissimo per eseguire un backup completo del contenuto di
un database, da riutilizzare come input per \texttt{slapadd} per ricreare da
zero un albero. Se infatti ci si limitasse a salvare i file binari contenenti
i dati del database, questi sarebbero riutilizzabili solo a uno \texttt{slapd}
che utilizzi lo stesso tipo di supporto e con versione compatibile, mentre con
un dump in formato LDIF è sempre possibile ricreare il contenuto di un
database utilizzando qualunque supporto e qualunque versione del programma.

Oltre alle opzioni comuni riportate in tab.~\ref{tab:slapd_tools_options},
\texttt{slapcat} condivide con \texttt{slapadd} anche l'opzione \texttt{-l}
che in questo caso indicherà il file su cui scrivere invece che quello da cui
leggere. Un'altra opzione specifica è \texttt{-H} che consente di indicare una
URI di ricerca (nel formato illustrato in sez.~\ref{sec:ldap_query_mechanism})
per restringere la selezione dei dati; allo stesso scopo si possono anche
usare \texttt{-a} per indicare un filtro e \texttt{-s} per indicare un
sottoramo di albero, ma queste sono deprecate.  Per la descrizione completa
del comando si faccia riferimento alla pagina di manuale.


\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{-a \textsl{fltr}}& scrive solo le voci corrispondenti al filtro di
                               ricerca \texttt{\textsl{fltr}} (vedi
                               sez.~\ref{sec:ldap_search}).\\
    \texttt{-H \textsl{uri}} & scrive solo le voci corrispondenti alla URI di
                               ricerca \texttt{\textsl{uri}} (da indicare nel
                               formato illustrato in 
                               sez.~\ref{sec:ldap_query_mechanism}).\\
    \texttt{-l \textsl{file}}& scrive i dati in formato LDIF sul file
                               specificato come parametro.\\
    \texttt{-s \textsl{sub}} & scrive solo le voci corrispondenti al ramo di
                               albero indicato da \texttt{\textsl{sub}}
                               (indicato con il suo DN).\\
    \hline
  \end{tabular}
  \caption{Le opzioni specifiche del comando \texttt{slapcat}.}
  \label{tab:slapcat_options}
\end{table}

Come accennato la combinazione di \texttt{slapcat} e \texttt{slapadd} è la
modalità consigliata per effettuare il salvataggio ed il ripristino dei dati
mantenuti da \texttt{slapd}. I programmi infatti, oltre a salvare e
ripristinare i dati interni usati da \texttt{slapd} assicurano anche che
questi vengano ordinati correttamente.  Si ricordi infatti che LDAP non
supporta nessun ordinamento dei risultati ottenuti da una interrogazione, per
cui quanto ottenibile con \texttt{ldapsearch}, anche se completo, potrebbe non
essere riutilizzabile per ricreare il database, dato che una voce subordinata
ad un'altra potrebbe comparire nell'elenco per prima.

Per questo in generale si usa \texttt{slapcat} creare i backup del database da
usare per ripristinare lo stesso in caso di errore o corruzione; ad esempio si
può mettere uno script nei lavori giornalieri di \textit{cron} che esegue
\texttt{slapcat} per creare un file LDIF con il contenuto del proprio albero.
Per il ripristino basterà fermare il server, cancellare tutti i file usati per
il supporto dei dati (nel caso di Debian il contenuto \texttt{/var/lib/ldap}),
e poi ricreare il tutto con \texttt{slapadd} avendo cura di verificare che i
file appartengano all'utente per conto del quale viene eseguito
\texttt{slapd}. Nel caso si usino più database l'operazione andrà compiuta
separatamente per ciascuno di essi.

Si tenga presente comunque che, anche se \texttt{slapcat} può essere usato
quando \texttt{slapd} è attivo, può essere necessario effettuare il
salvataggio quando quest'ultimo è in sola lettura o fermo se si vuole essere
garantiti contro il rischio di una inconsistenza dei dati dal punto di vista
delle applicazioni; se infatti queste eseguono diverse scritture mentre si
esegue \texttt{slapcat} solo alcune di esse potrebbero risultare nel file
prodotto da quest'ultimo. I dati sarebbero comunque coerenti per quanto
riguarda \texttt{slapd}, ma potrebbero non esserlo per l'applicazione.

Infine l'uso di \texttt{slapcat} e \texttt{slapadd} per eseguire i backup vale
in particolare per quanto riguarda il salvataggio dei dati del nuovo sistema
di configurazione illustrato in sez.~\ref{sec:slapd_database_config}, dove
l'uso di \texttt{ldapsearch} porterebbe, come accennato, alla presenza di dati
spuri. Dato che normalmente \texttt{slapcat} esegue il dump del primo database
che contiene dati effettivi, se si vuole salvare il database delle
configurazioni occorre indicarlo esplicitamente, e questo in genere si fa con
l'opzione \texttt{-n} sfruttando il fatto che questo avrà comunque indice
0. Pertanto per generare un backup delle configurazioni sarà sufficiente
eseguire il comando:

\begin{Console}
# \textbf{slapcat -n 0 > config.ldif}
\end{Console}

Il ripristino in questo caso è più complesso, specie quando è già presente una
directory di configurazione. In tal caso infatti questa deve essere rimossa o
spostata, e poi ne deve essere creata una vuota, perché altrimenti
\texttt{slapadd} non è in grado di funzionare, per questo la procedura di
ripristino da seguire è esattamente la seguente:

\begin{Console}
# \textbf{service slapd stop}
# \textbf{mv /etc/ldap/slapd.d /etc/ldap/slapd.d-\$(date)}
# \textbf{mkdir /etc/ldap/slapd.d}
# \textbf{slapadd -F /etc/ldap/slapd.d -n 0 < config.ldif}
_#################### 100.00% eta   none elapsed            none fast!         
# \textbf{chown -R openldap.openldap /etc/ldap/slapd.d}
# \textbf{service slapd start}
\end{Console}


Un ultimo comando di manutenzione che permette di operare direttamente sui
dati database è \index{comando!\texttt{slapindex}} \texttt{slapindex}, che
viene usato per rigenerare gli indici del database rispetto ai contenuti
correnti.  In genere lo si usa tutte le volte che si vuole aggiungere (o
rimuovere) manualmente un qualche indice. Se infatti ci si limita ad
aggiungere o modificare una direttiva \texttt{index} in \texttt{slapd.conf}
gli indici non vengono comunque ricostruiti fintanto che non lo si richiede
esplicitamente con questo comando.\footnote{non è invece necessario usarlo se
  si configurano gli indici direttamente su \texttt{cn=config} con la nuova
  modalità di configurazione del server illustrata in
  sez.~\ref{sec:slapd_database_config}.} Anche \texttt{slapindex} supporta le
opzioni di tab.~\ref{tab:slapd_tools_options}, ed inoltre prevede che si possa
indicare l'attributo che si intende reindicizzare (il default è reindicizzare
tutto) passandolo come argomento. Si verifichino sempre i permessi di eventuali
nuovi file creati dal comando, e che questi siano accessibili (in lettura e
scrittura) dall'utente per conto del quale si esegue \texttt{slapd}.

Qualora si voglia popolare il proprio albero inserendo delle ulteriori singole
voci si potrebbe usare ancora \texttt{slapadd}, ma come accennato questo
presenta degli inconvenienti. Anzitutto con \texttt{slapadd} non si ha la
generazione automatica delle informazioni di ultima modifica, che devono
essere inserite a mano; inoltre la sintassi dei file LDIF deve essere
assolutamente corretta,\footnote{ad esempio la presenza di una riga vuota
  all'inizio di un file LDIF è causa comune di errori nella creazione del
  database.} altrimenti nonostante l'apparente successo dell'operazione si
rischia di non essere in grado di accedere alle informazioni; è pertanto il
caso di usare \texttt{slapadd} soltanto con dei file LDIF di cui sia certa la
validità, come quelli creati da \texttt{slapcat}, e non nelle operazioni
ordinarie. Infine, e questo è ciò che lo rende del tutto inadatto alle
operazioni ordinarie, il comando deve essere utilizzato quando \texttt{slapd}
è fermo.

Per questo motivo la modalità ordinaria di inserimento di dati in un server
LDAP è attraverso l'uso di un qualunque client che utilizzi le funzionalità di
scrittura fornite dal protocollo stesso. Nel caso di Linux esistono parecchi
programmi in grado di fare da client,\footnote{per gli amanti dell'interfaccia
  grafica \texttt{gq} è un ottimo client basato su GTK che fornisce una
  interfaccia grafica per l'accesso a qualunque tipo di informazione
  memorizzata su un server LDAP.} ma abbiamo già visto come \textit{OpenLDAP}
fornisca anche un insieme di programmi di utilità a riga di comando e fra
questi \index{comando!\texttt{ldapmodify}} \texttt{ldapmodify} è quello che
viene usato per manipolare le voci presenti su un server ed aggiungerne di
nuove. Trattandosi di uno dei comandi client di \textit{OpenLDAP} valgono le
stesse indicazioni generali relative alle modalità con cui ci si collega ed
autentica presso il server, illustrate in
sez.~\ref{sec:ldap_client_base_config}, ed il comando prende tutte le opzioni
comuni riportate in tab.~\ref{tab:ldap_client_options}.

Quando \texttt{ldapmodify} viene invocato con l'opzione \texttt{-a}, o
lanciato come \index{comando!\texttt{ldapadd}} \texttt{ldapadd}, il comando
permette anche di aggiungere nuove voci. Ovviamente perché sia possibile
effettuare le operazioni è necessario che l'utente con cui ci si collega al
server, da specificare con l'opzione \texttt{-D}, abbia i privilegi
necessari. Si tenga presente che se non si specifica nessun utente viene fatto
un collegamento anonimo che non consente di operare nessuna
modifica.\footnote{a meno ... di non aver effettuato una configurazione
  completamente sbagliata dei privilegi di accesso.}

Il comando legge i dati dallo \textit{standard input}, o da un file
specificato con l'opzione \texttt{-f}. Oltre a quelle di
tab.~\ref{tab:ldap_client_options} il comando prevede l'opzione \texttt{-c}
che permette di proseguire nelle modifiche anche se c'è stato un errore (il
default è uscire al primo errore), e \texttt{-n} che si limita a mostrare
quello che accadrebbe (permettendo così di rilevare eventuali errori) senza
modificare effettivamente il contenuto del database. Le principali opzioni
sono illustrate in tab.~\ref{tab:ldapmodify_options}, ed al solito l'elenco
completo è riportato nella pagina di manuale.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{-a}              & aggiunge una voce.\\ 
    \texttt{-c}              & prosegue l'elaborazione dei dati successivi
                               anche in caso di errori.\\  
    \texttt{-f \textsl{file}}& legge i dati dal file indicato invece che dallo
                               \textit{standard input}.\\ 
    \texttt{-n}              & esegue il comando in modalità di test senza
                               eseguire le scritture.\\ 
    \texttt{-S \textsl{file}}& scrive sul file indicato i dati che sono stati
                               saltati in caso di errore (da usare con
                               \texttt{-c}).\\ 
    \hline
  \end{tabular}
  \caption{Le principali opzioni di \texttt{ldapmodify}.}
  \label{tab:ldapmodify_options}
\end{table}

Fintanto che lo si usa per aggiungere una voce (con l'opzione \texttt{-a} o
come \texttt{ldapadd}) i dati possono essere specificati nell'ordinario
formato LDIF, in generale però il comando usa la notazione dei cosiddetti
\itindex{change records} \textit{change records}. Questo è un formato che
descrive le modalità con cui si compiono le modifiche degli oggetti ed i
valori dei relativi attributi utilizzando dei file LDIF (i \textit{change
  records} appunto) in cui si usano una serie attributi speciali per indicare 
le operazioni da fare.\footnote{caso di \texttt{ldapadd} quello che accade è
  che se questi attributi speciali non sono presenti vengono utilizzati di
  default i valori che indicano l'aggiunta di una voce; dato che in questo
  modo l'informazione che resta è quella di un LDIF normale, diventa possibile
  indicare la voce da aggiungere esprimendone direttamente il contenuto con un
  normale file LDIF senza \textit{change records}.}  La descrizione del
formato usato per queste operazioni è disponibile nella pagina di manuale del
formato LDIF (accessibile con \texttt{man ldif}), non entreremo qui nei
dettagli dato che l'uso più comune di \texttt{ldapmodify} è quello
dell'aggiunta di nuove voci, per il quale basta usare LDIF.

Se si devono modificare dei dati l'uso di \texttt{ldapmodify} è piuttosto
scomodo dato che costringe ad usare questo formato, che è piuttosto
macchinoso; data la presenza di innumerevoli alternative più semplici da
usare, come \texttt{gq} per l'interfaccia grafica o \texttt{ldapvi} per la
riga di comando, non vale la pena approfondire l'uso di un programma che ben
difficilmente sarà usato a questo scopo.

Si tenga presente però che \texttt{ldapmodify} non è in grado di modificare il
DN di un oggetto; se cioè di un oggetto si vuole modificare l'attributo che
mantiene il \textit{Relative Distinguished Name} l'uso di \texttt{ldapmodify}
darà luogo ad un errore; per farlo infatti occorre usare una operazione
speciale, in quanto il DN è la chiave che consente a \texttt{ldapmodify} di
accedere all'oggetto, ed è un parametro fisso della funzione che permette di
modificare un oggetto. Per compiere questa operazione occorre allora usare il
comando apposito \index{comando!\texttt{ldapmodrdn}} \texttt{ldapmodrdn}.
Questo comando prende le stesse opzioni di \texttt{ldapmodify}, e prende come
argomenti il DN dell'oggetto da modificare seguito da nuovo valore dell'RDN.
Gli stessi valori si possono passare (ripetuti anche più volte, nel qual caso
andranno separati da linee vuote) sullo \textit{standard input} o su un file
specificato con l'opzione \texttt{-f}.

Infine se si vogliono cancellare delle voci dall'albero \textit{OpenLDAP}
fornisce un comando specifico, \index{comando!\texttt{ldapdelete}}
\texttt{ldapdelete}.  Questo prende come argomento uno o più
\textit{Distinguished Name} delle voci da cancellare. Se non si passa nessun
argomento il comando cerca di leggere i suddetti DN dallo \textit{standard
  input}.  Oltre alle opzioni di tab.~\ref{tab:ldap_client_options} anche
\texttt{ldapdelete} prende le opzioni \texttt{-c} e \texttt{-n}, con lo stesso
significato che hanno per di \texttt{ldapmodify}. Al solito l'elenco completo
è nella pagina di manuale. Si tenga presente che anche in questo caso fintanto
che non ci si collega al server usando un utente con privilegi appropriati le
operazioni non saranno eseguite.

Data la sua utilità, anche se non fa parte dei programmi di gestione
distribuiti con \textit{OpenLDAP}, tratteremo brevemente anche
\index{comando!\texttt{ldapvi}} \texttt{ldapvi}, che consente di eseguire in
maniera piuttosto semplice (una volta che si diventi pratici del formato
LDIF), le operazioni di modifica dei dati su un server; il programma infatti
consente di ottenere di visualizzare i dati di un server LDAP all'interno di
un qualunque editor di testo in formato LDIF, per poterli modificare, e
salvare all'indietro.

Benché molte opzioni (ad esempio \texttt{-s}, \texttt{-b}, \texttt{-D} e
\texttt{-w}) abbiano lo stesso significato di quelle dei programmi client di
\textit{OpenLDAP} (quello illustrato in tab.~\ref{tab:ldap_client_options}),
la sintassi di \texttt{ldapvi} è soltanto simile a questi. Ad esempio per
indicare il server da interrogare il comando usa l'opzione \texttt{-h}, che
supporta però sia l'indicazione di un hostname che quella di una URL.

Il comando usa per i propri default il contenuto dei file
\texttt{/etc/ldap/ldap.conf} e \texttt{.ldaprc}, per cui, se questi sono stati
già configurati per indicare a quale server rivolgersi, quando viene invocato
visualizza all'interno di un editor tutte le voci disponibili sul server
(viene usato l'editor di default del sistema, se ne può sempre indicare uno
con la variabile di ambiente \texttt{EDITOR}).  Si può passare come argomento
un filtro di ricerca, nel qual caso saranno mostrate solo le voci ad esso
corrispondenti. Ovviamente in entrambi i casi si potranno ottenere soltanto le
voci leggibili con una connessione anonima.

Dato che l'uso principale del comando è la modifica dei dati presenti su un
database LDAP, è normalmente necessario autenticarsi per avere i diritti di
scrittura (l'autenticazione sarà trattata in dettaglio in
sez.~\ref{sec:ldap_authentication_methods}). Come per \texttt{ldapmodify}
questo si fa utilizzando l'opzione \texttt{-D}, ma a differenza di questo
\texttt{ldapvi} consente di indicare anche un filtro di ricerca e non solo un
DN, ed inoltre usa di default l'autenticazione semplice (non esiste e non è
necessaria l'opzione \texttt{-x}) e chiede da solo la password sul terminale.

Una volta autenticati, ottenuti i contenuti del database in formato LDIF,
basterà modificarli direttamente con l'editor, cambiando i valori degli
attributi, cancellandoli, o cancellando intere voci. All'uscita il programma
riprenderà il testo generato, verificandone la correttezza come LDIF (in caso
contrario chiederà se uscire o rimodificare) ed identificando le modifiche da
applicare. A meno di non aver eseguito nessuna modifica il programma chiede
sempre quale azione eseguire una volta che si esce dall'editor, se ad esempio
si è modificato un valore si avrà un qualcosa del tipo:
\begin{Terminal}
add: 0, rename: 0, modify: 1, delete: 0
Action? [yYqQvVebB*rsf+?] 
\end{Terminal}
dove occorre indicare l'azione da eseguire premendo il tasto corrispondente;
il significato dei possibili valori si può ottenere usando ``\texttt{?}'',
con:
\begin{Console}
add: 0, rename: 0, modify: 1, delete: 0
Action? [yYqQvVebB*rsf+?] \textbf{?}
Commands:
  y -- commit changes
  Y -- commit, ignoring all errors
  q -- save changes as LDIF and quit
  Q -- discard changes and quit
  v -- view changes as LDIF change records
  V -- view changes as ldapvi change records
  e -- open editor again
  b -- show login dialog and rebind
  B -- toggle SASL
  * -- set SASL mechanism
  r -- reconnect to server
  s -- skip one entry
  f -- forget deletions
  + -- rewrite file to include schema comments
  ? -- this help
Action? [yYqQvVebB*rsf+?] 
\end{Console}

In particolare si può uscire senza salvare nulla con ``\texttt{Q}'',
rimodificare il risultato nell'editor con ``\texttt{e}'', tentare la scrittura
con ``\texttt{y}'' (che si bloccherà al primo errore). Con ``\texttt{q}'' si
possono salvare le modifiche su un file ed uscire, mentre ci si può
riautenticare con ``\texttt{b}''.

Il programma supporta anche altre opzioni (l'elenco completo si ottiene al
solito con la pagina di manuale) ed in particolare con \texttt{-{}-discover} è
in grado di interrogare un server (da indicare sempre con \texttt{-h}) per
ottenere i parametri (come la base dell'albero) utili per una eventuale
configurazione, che possono essere stampati in una forma adatta per
l'inclusione in \texttt{ldap.conf}. Inoltre può usare l'opzione
\texttt{-{}-diff} per confrontare due file LDIF (che devono essere generati da
\texttt{ldapvi} con l'opzione \texttt{-{}-out}) da indicare come argomenti.



\section{Configurazioni avanzate}
\label{sec:ldap_advanced}

Tratteremo in questa sezione la configurazione delle funzionalità più avanzate
del server \texttt{slapd}, come le diverse modalità per l'autenticazione degli
utenti, il controllo degli accessi ai dati mantenuti nel server, l'uso di
TLS/SSL per la comunicazione fra client e server e le estensioni delle
funzionalità del server tramite l'uso dei cosiddetti ``\textit{overlay}''.


\subsection{I meccanismi di autenticazione}
\label{sec:ldap_authentication_methods}

Il protocollo LDAP, anche a causa delle sue origini, prevede che sia
possibile, una volta eseguita la connessione ad un server, effettuare delle
richieste in forma anonima, una funzionalità che può essere usata per
permettere a chiunque l'accesso alle informazioni pubbliche mantenute su un
server. Ovviamente se si intende fornire un tale accesso, questo dovrà avere
privilegi estremamente ridotti ed essere limitato ad un insieme limitato di
informazioni; non sarebbe molto saggio permettere a chiunque di scrivere sul
proprio database, né di ottenere informazioni sensibili come le password degli
utenti.

Oggi però questa modalità di utilizzo è praticamente scomparsa, e l'accesso
nella quasi totalità dei casi deve essere controllato. Per questo motivo oltre
alla precedente forma anonima LDAP prevede anche la possibilità di avere
connessioni autenticate, che vengono realizzate attraverso una specifica
operazione del protocollo denominata ``\textit{binding}''. L'operazione
prevede che una volta ottenuta la connessione al server un client possa
autenticarsi presso di esso come un determinato \textsl{utente} fornendo una
password, così che ad esso possano essere assegnati specifici privilegi di
accesso che gli consentano o meno di eseguire le successive operazioni
richieste sul server tramite quella connessione.

Il meccanismo in realtà è piuttosto complesso dato che \textit{OpenLDAP}
prevede due metodi di autenticazione. Il primo, richiesto anche dallo standard
LDAPv3 ed usato di default da tutti i client a riga di comando distribuiti da
\textit{OpenLDAP} è quello che prevede l'uso di SASL, che però, oltre
all'installazione delle relative librerie, richiede in genere anche una
gestione separata delle informazioni di autenticazione degli utenti; questo
può portare ad una configurazione più complessa, coinvolgendo anche altri
servizi, e ci torneremo più avanti.

Per questo motivo \textit{OpenLDAP} supporta anche un secondo metodo di
autenticazione, detto \textsl{autenticazione semplice} (\textit{simple
  authentication}), in cui un utente non è altro che un qualunque oggetto
presente nel database che abbia un attributo \texttt{userPassword}. In questo
caso l'utente che sarà identificato dal suo \textit{Distinguished Name}, ed
autenticato direttamente dal server tramite la password mantenuta nel suddetto
attributo.  Per semplicità nell'illustrare l'uso dei comandi abbiamo finora
preso in considerazione solo questo metodo, il cui svantaggio è che la
password viene trasmessa in chiaro, e richiede pertanto una adeguata
protezione del flusso dei dati; in sostanza se si utilizza una connessione
remota sarà necessario accertarsi che questa sia cifrata con SSL/TLS (vedi
sez.~\ref{sec:ldap_SSL}).

Si tenga presente inoltre che, come illustrato in
tab.~\ref{tab:slapd_database_directives}, il server supporta la presenza di un
utente amministrativo privilegiato, analogo all'utente \texttt{root} dei
sistemi Unix, per il quale non vengono mai eseguiti i controlli di accesso che
illustreremo in seguito.  L'utente è quello definito dalla direttiva
\index{OpenLDAP!direttiva~server!\texttt{rootdn}} \texttt{rootdn}, che ne
indica il \textit{Distinguished Name}, e può anche non corrispondere ad una
voce presente nel database. Se questa direttiva non viene specificata non ci
sarà nessun utente amministrativo speciale e tutti gli utenti saranno
sottoposti al controllo di accesso.

Sebbene in teoria l'utente amministrativo possa avere un \textit{Distinguished
  Name} arbitrario, in genere conviene usarne uno corrispondente ad un
suffisso utilizzato dal database, in tal caso infatti è possibile usare per
l'autenticazione i dati (l'attributo \texttt{userPassword}) ad esso
corrispondente. Comunque è sempre possibile specificare direttamente nel file
di configurazione una password di accesso per l'autenticazione semplice
tramite la direttiva \index{OpenLDAP!direttiva~server!\texttt{rootpw}}
\texttt{rootpw}, che può essere indicata con lo stesso formato che si usa per
\texttt{userPassword}; in tal caso si può usare come \texttt{rootdn} anche un
utente non esistente nel database.

\textit{OpenLDAP} supporta diversi formati per i valori delle password, che
prevedono differenti hash crittografici utilizzati per generarle. Questo in
realtà costituisce una contraddizione con lo standard stabilito
nell'\href{http://www.ietf.org/rfc/rfc2256.txt}{RFC~2256} che richiede che
l'attributo \texttt{userPassword} contenga solo testo in chiaro,\footnote{una
  nuova specificazione, introdotta
  nell'\href{http://www.ietf.org/rfc/rfc3112.txt}{RFC~3112} prevederebbe per
  questo l'uso di un nuovo attributo, \texttt{authPassword}, che però
  \texttt{slapd} non ha implementato e che in pratica non viene usato quasi
  mai.} ma consente di evitare che una compromissione dei dati del database
permetta di ottenere il testo delle password.  L'elenco dei diversi algoritmi
di hash supportati da \texttt{slapd} è riportato in
tab.~\ref{tab:slappasswd_password_types},\footnote{quelli indicati in questa
  tabella sono quelli supportate nativamente da \texttt{slapd}, ma questo può
  essere esteso caricando gli opportuni moduli, ad esempio con Debian Jessie
  viene distribuito il modulo \texttt{pw-sha2} che rende disponibili gli
  ulteriori algoritmi \texttt{\{SSHA256\}}, \texttt{\{SSHA384\}},
  \texttt{\{SSHA512\}}, \texttt{\{SHA256\}}, \texttt{\{SHA384\}} e
  \texttt{\{SHA512\}}.} si tenga conto inoltre che l'attributo
\texttt{userPassword} può essere presente più volte, o meglio avere più
valori, e questo anche con algoritmi di hash diversi. In questo caso
l'autenticazione verrà effettuata iterando su tutti i valori presenti
fermandosi quando ne viene trovato uno che corrisponde, o fallendo altrimenti.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|l|}
    \hline
    \textbf{Identificativo} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{\{SHA\}}      & usa l'algoritmo SHA-1.\\ 
    \texttt{\{SSHA\}}     & usa l'algoritmo Salted-SHA-1.\\ 
    \texttt{\{MD5\}}      & usa l'algoritmo MD5.\\ 
    \texttt{\{SMD5\}}     & usa l'algoritmo Salted-MD5.\\ 
    \texttt{\{CRYPT\}}    & usa la funzione \texttt{crypt}\\ 
    \texttt{\{CLEARTEXT\}}& lascia la password in chiaro\\ 
    \hline
  \end{tabular}
  \caption{Identificativi degli algoritmi di hash crittografico supportati da
    \texttt{slapd}.}
  \label{tab:slappasswd_password_types}
\end{table}

Per ottenere il valore da assegnare ad \texttt{userPassword} nel formato
corretto, in modo da poterlo scrivere in un file LDIF, è disponibile un
apposito comando, \index{comando!\texttt{slappasswd}} \texttt{slappasswd}. Il
comando prevede l'opzione \texttt{-s} per immettere direttamente la password
come parametro e \texttt{-T} per leggerla da un file; altrimenti questa verrà
chiesta sul terminale (due volte per conferma) senza che il suo valore sia
visualizzato.

Infine l'opzione \texttt{-h} permette di scegliere l'algoritmo cui l'hash
viene generato usando uno dei parametri elencati in
tab.~\ref{tab:slappasswd_password_types} (il default è
\texttt{\{SSHA\}}). Come risultato \texttt{slappasswd} stampa sullo
\textit{standard output} il valore da usare per \texttt{userPassword}
all'interno di un file LDIF; ad esempio si avrà:
\begin{Console}
# \textbf{slappasswd}
New password:
Re-enter new password:
\{SSHA\}xTelsDLvGxL2oqVrAS23HslitgVecAPs
\end{Console}
dove per tutti i formati a parte \texttt{\{CLEARTEXT\}} (nel qual caso occorre
semplicemente assegnare ad \texttt{userPassword} il valore della password)
viene aggiunto alla codifica dell'hash il prefisso che lo identifica.

\itindbeg{LDAP~Password~Modify~Extended~Operations}

Per evitare la noia di doversi generare a mano un LDIF solo per modificare il
valore di un attributo, fra i vari programmi client distribuiti da
\textit{OpenLDAP} c'è anche il programma \index{comando!\texttt{ldappasswd}}
\texttt{ldappasswd}, che permette di impostare o modificare la password
associata ad un utente. Il comando in realtà non è strettamente equivalente ad
impostare la password come si farebbe andando a fare una modifica diretta
dell'attributo \texttt{userPassword}, in quanto opera effettuando quella che
viene chiamata una \textit{LDAP Password Modify Extended Operation}.

Questa è una delle tante estensioni del protocollo LDAP, standardizzata
dall'\href{http://www.ietf.org/rfc/rfc3062.txt}{RFC~3062}, che prevede che sia
il server stesso ad aggiornare il valore di \texttt{userPassword} creando
l'hash della password che viene trasmessa in chiaro dal client, quindi è
opportuna, se non necessaria, una connessione cifrata.  In questo caso il
server userà il tipo di hash specificato con la direttiva
\index{OpenLDAP!direttiva~server!\texttt{password-hash}}
\texttt{password-hash} vista in tab.~\ref{tab:slapd_general_directives}, che
richiede come argomento uno dei valori della prima colonna di
tab.~\ref{tab:slappasswd_password_types}, ed il cui default è
\texttt{\{SSHA\}}, considerato il più sicuro fra quelli supportati. La
direttiva consente anche di indicare, separati da spazi, più formati fra
quelli di tab.~\ref{tab:slapd_general_directives}, nel qual caso verranno
generati altrettanti attributi \texttt{userPassword}, uno per ciascun formato
indicato.

\itindend{LDAP~Password~Modify~Extended~Operations}

L'utilità di questa estensione, oltre al non doversi generare a mano l'hash
crittografico per applicare i cambiamenti con un \texttt{ldapmodify}, è che
l'uso di una operazione estesa consente di intercettare il cambiamento della
password tramite un \textit{overlay} (vedi sez.~\ref{sec:ldap_overlay}) per
eseguire eventuali ulteriori operazioni ad esso collegate; è quello che fa ad
esempio l'\textit{overlay} \texttt{smbk5pwd} per aggiornare contestualmente
altri attributi o l'\textit{overlay} \texttt{ppolicy} per imporre dei
requisiti di robustezza sulla password.


\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{-a \textsl{pass}}& usa \texttt{pass} come password precedente.\\ 
    \texttt{-A}              & richiede la password precedente sul terminale.\\ 
    \texttt{-s \textsl{pass}}& usa \texttt{pass} come nuova password.\\
    \texttt{-S}              & richiede l'immissione della nuova password sul
                               terminale.\\
    \texttt{-t \textsl{file}}& legge la nuova password dal file \texttt{file}.\\
    \hline
  \end{tabular}
  \caption{Le principali opzioni di \texttt{ldappasswd}.}
  \label{tab:ldappasswd_options}
\end{table}

Oltre alle opzioni comuni di tutti i client di \textit{OpenLDAP} già
illustrate in tab.~\ref{tab:ldap_client_options}, \texttt{ldappasswd} prevede
l'opzione \texttt{-A} che richiede la immissione del precedente valore della
password sul terminale; questa può anche essere specificata direttamente sulla
riga di comando come parametro per l'opzione \texttt{-a}. Inoltre con
\texttt{-S} si richiede l'immissione della nuova password su terminale, mentre
la si può specificare direttamente come parametro per l'opzione \texttt{-s} o
nel contenuto del file indicato con l'opzione \texttt{-t}. Le principali
opzioni sono riassunte in tab.~\ref{tab:ldappasswd_options}, per l'elenco
completo si consulti al solito la pagina di manuale.

% TODO trattazione di SASL qui, in particolare della parte relativa a SASL
% external 

Come detto all'inizio di questa sezione, la modalità di autenticazione di
default, prevista esplicitamente dalla standardizzazione di LDAP, è quella che
sfrutta SASL, \itindex{SASL (Simple Authentication and Security Layer)}
acronimo di \textit{Simple Authentication and Security Layer}, un
\textit{framework} che definisce una modalità generica con cui un protocollo
può delegare l'autenticazione, tramite l'uso di una libreria che fornisce una
interfaccia di programmazione standardizzata, ad una serie di possibili
``\textsl{meccanismi}'' esterni, gestiti dalla libreria stessa. In questo
modo, realizzando solo l'interfaccia verso SASL, il servizio guadagnerà il
supporto di tutti i meccanismi di autenticazione che questa fornisce.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Meccanismo} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{GSSAPI}    & l'autenticazione viene effettuata via \textit{GSSAPI}
                         rivolgendosi ad un server \textit{Kerberos}.\\ 
    \texttt{DIGEST-MD5}& l'autenticazione si basa su meccanismo di
                         \textit{challenge and response} in cui client e
                         server dimostrano di conoscere un segreto condiviso
                         (una password); questa può essere mantenuto
                         direttamente dalle librerie nel database interno
                         \texttt{sasldb}, in un sistema esterno acceduto
                         tramite il demone \texttt{saslauthd} o nello stesso
                         albero LDAP (come password in formato
                         \texttt{\{CLEARTEXT\}}).\\ 
%    \texttt{CRAM-MD5}& deprecato usare \texttt{DIGEST-MD5}.\\ 
    \texttt{NTML}     & l'autenticazione viene effettuata verso una macchina
                        Windows con l'omonimo protocollo.\\ 
    \texttt{EXTERNAL} & l'autenticazione è implicita dal contesto, e deriva
                        direttamente dalle modalità di collegamento.\\ 
    \hline
  \end{tabular}
  \caption{Principali \textit{mechanism} disponibili, come indicati 
    con l'opzione \texttt{-Y} dei client di \textit{OpenLDAP}.}
  \label{tab:sasl_mechanism_names}
\end{table}


Nel caso di \textit{OpenLDAP} abbiamo già detto in
sez.~\ref{sec:slapd_install} che l'implementazione di SASL utilizzata è quella
fornita della libreria \textit{Cyrus SASL}, che fornisce un'ampia selezione di
meccanismi, i principali dei quali sono illustrati in
tab.~\ref{tab:sasl_mechanism_names}. Oltre a supportare diversi meccanismi di
autenticazione, SASL supporta anche la cosiddetta \textit{proxy
  authentication}, cioè la possibilità che ci si possa autenticare con un
``utente'' ma poi agire anche per conto di un altro. Questo comporta la
presenza di due identificativi, un \textit{authentication ID} che identifica
chi si autentica (ed è quello associato alle credenziali di autenticazione),
ed un \textit{authorization ID} che identifica per conto di chi si vuole
operare nel servizio che usa SASL.

Infine SASL supporta i cosiddetti \textit{realm}, è possibile cioè raggruppare
gli utenti identificandoli come appartenenti ad un certo ``\textsl{dominio}''
(indicandoli in genere come \texttt{utente@dominio}).  Questa funzionalità
consente di distinguere le identità su un piano globale, ed è usata da vari
meccanismi di autenticazione, come \textit{Kerberos}, che richiedono si
specifichi di quale dominio gli utenti fanno parte. Se non lo si indica viene
assunto come default il valore del nome a dominio completo del server.

Per potersi autenticare con SASL un client (uno qualunque dei vari comandi
\texttt{ldap*} visti in sez.~\ref{sec:ldap_client}) deve indicare quale
meccanismo utilizzare usando l'opzione \texttt{-Y}, se non la si specifica
verrà utilizzato il meccanismo considerato migliore dal server, che per
\texttt{slapd} normalmente è \texttt{DIGEST-MD5}, ed in questo caso è
richiesta una password, che verrà chiesta sul terminale, ma tutto ciò richiede
una opportuna configurazione delle librerie SASL sul server.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
%    \texttt{-O \textsl{sec}}  & specifica una .\\  
%    \texttt{-Q}               & abilità la modalità silenziosa, non esegue mai
%                                richieste sul terminale.\\  
    \texttt{-R \textsl{realm}}& indica il \textit{realm} (dominio) di
                                autenticazione.\\   
    \texttt{-U \textsl{auth}} & indica l'\textit{authentication ID} con il
                                quale autenticarsi, la forma dipende dal
                                meccanismo utilizzato.\\  
    \texttt{-X \textsl{user}} & indica l'\textit{authorization ID} per conto
                                del quale si vuole operare, è nella forma
                                \texttt{u:\textsl{username}} o
                                \texttt{dn:\textsl{distinguished name}}.\\
    \texttt{-Y \textsl{mech}} & specifica quale meccanismo di SASL deve essere 
                                usato per l'autenticazione (vedi
                                tab.~\ref{tab:sasl_mechanism_names}).\\
    \hline
  \end{tabular}
  \caption{Le opzioni comuni dei programmi client di \textit{OpenLDAP} per
    l'autenticazione con SASL.}
  \label{tab:ldap_client_sasl_options}
\end{table}

Le modalità con cui un client può effettuare l'autenticazione dipendono
pertanto strettamente dal meccanismo utilizzato, ed in tutti i casi il server
deve essere opportunamente configurato. Inoltre, a meno che non si usi
\texttt{GSSAPI}, nel qual caso occorrerà aver preventivamente ottenuto un
\textit{Ticket Granting Ticket} con \texttt{kinit}, occorrerà indicare alle
librerie anche con quale utente ci si vuole autenticare (vale a dire
l'\textit{authentication ID}) usando l'opzione \texttt{-U}. Le altre
principali opzioni utilizzate dai programmi client riguardanti
l'autenticazione con SASL sono state riassunte in
tab.~\ref{tab:ldap_client_sasl_options}, ma queste possono essere omesse
utilizzando i file di configurazione delle librerie (quelli di
sez.~\ref{sec:ldap_client_base_config}) con le direttive di
tab.~\ref{tab:ldap_conf_sasl_directives}.

\index{OpenLDAP!direttiva~client!\texttt{SASL\_MECH}}
\index{OpenLDAP!direttiva~client!\texttt{SASL\_REALM}}
\index{OpenLDAP!direttiva~client!\texttt{SASL\_AUTHCID}}
\index{OpenLDAP!direttiva~client!\texttt{SASL\_AUTHZID}}
\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Direttiva} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{SASL\_MECH}   & indica il meccanismo (stesso effetto 
                            e valori dell'opzione \texttt{-Y}), è usabile solo
                            a livello utente.\\  
    \texttt{SASL\_REALM}  & indica il \textit{realm} (stesso effetto e valori
                            dell'opzione \texttt{-R}), è usabile solo
                            a livello utente.\\
    \texttt{SASL\_AUTHCID}& indica l'\textit{authentication ID} (stesso effetto
                            e valori dell'opzione \texttt{-U}), è usabile solo
                            a livello utente.\\ 
    \texttt{SASL\_AUTHZID}& indica l'\textit{authorization ID} (stesso
                            effetto e valori dell'opzione \texttt{-X}), è
                            usabile solo a livello utente.\\ 
    \hline
  \end{tabular}
  \caption{Le principali direttive di \texttt{ldap.conf} concernenti SASL.}
  \label{tab:ldap_conf_sasl_directives}
\end{table}

Dato che l'identificazione di un utente su LDAP è fatta eseguendo un
\textit{binding} con il suo \textit{Distinguished Name}, un passo comunque
necessario per poter utilizzare l'autenticazione con SASL è quello di
rimappare l'utente usato con quest'ultima su un DN corrispondente nel proprio
DIT. Per poterlo fare \texttt{slapd} traduce ogni \textit{authentication ID}
(vale a dire il nome utente che si è indicato con l'opzione \texttt{-U} dei
vari programmi client) in un \textit{Distinguished Name} speciale, che ha
sempre la forma:
\begin{FormattedExample}
uid=\textsl{<authentication_ID>},cn=\textsl{<realm>},cn=\textsl{<mechanism>},cn=auth
\end{FormattedExample}
o più semplicemente, se non si è indicato o non esiste un \textit{realm}, con:
\begin{FormattedExample}
uid=\textsl{<authentication_ID>},cn=\textsl{<mechanism>},cn=auth
\end{FormattedExample}

Se non si esegue nessuna mappatura, l'accesso viene eseguito con questo
\textit{Distinguished Name}, che in genere, non corrispondendo a nessuno di
quelli normalmente presenti in un DIT ordinario, non è in grado di fare alcuna
operazione, a meno di non usare delle regole di accesso specifiche per lo
stesso che lo consentano, (vedremo un caso con il meccanismo
\texttt{EXTERNAL}).  Per risolvere il problema viene fornita la direttiva
generale \index{OpenLDAP!direttiva~server!\texttt{authz-regexp}}
\texttt{authz-regexp} che consente di eseguire questa mappatura esprimendola
nella forma:
\begin{FormattedExample}
authz-regexp \textsl{<ricerca>} \textsl{<risultato>}
\end{FormattedExample}

La direttiva esegue una ricerca usando il suo primo argomento come espressione
regolare con cui effettuare una corrispondenza sul DN generato dal server in
corrispondenza all'\textit{authentication ID}, e se questa ha successo questo
viene rimappato nell'espressione fornita come risultato. La direttiva ricalca
la sintassi dei comandi di sostituzione di \texttt{sed} e come in questi
l'\textit{n}-simo \textit{subpattern}\footnote{un \textit{subpattern} in una
  espressione regolare è la parte di corrispondenza che sta fra due parentesi
  tonde, non è ovviamente possibile effettuare qui una trattazione
  approfondita delle espressioni regolari, argomento già di suo molto
  complesso, ma una trattazione di base, sufficiente all'utilizzo che se ne fa
  in questo contesto, si trova in sez.~2.2.5 di \cite{AGL}, per un
  approfondimento si veda invece \cite{RegExp}.}  trovato nell'espressione di
ricerca, può essere reimpiegato nell'espressione che genera il risultato nella
forma \texttt{\$\textsl{n}}. Questo permette di mappare un username passato
con l'opzione \texttt{-U} in un \textit{Distinguished Name} nel proprio DIT
con qualcosa del tipo:
\begin{Example}
authz-regexp uid=([^,]*),cn=.*,cn=auth uid=\$1,ou=People,dc=truelite,dc=it
\end{Example}
in questo modo collegandosi ad esempio con l'utente \texttt{piccardi}, si
otterrà un collegamento corrispondente al DN
\texttt{uid=piccardi,ou=People,dc=truelite,dc=it}.


Nell'uso dei vari meccanismi di SASL il solo caso in cui non è necessario
configurare separatamente l'autenticazione (e non serve neanche indicare un
\textit{authentication ID} con \texttt{-U}) è quello in cui si usa
\texttt{EXTERNAL}. In questo caso infatti l'autenticazione viene fornita dal
contesto in cui avviene la connessione al server, e non da un sistema di
autenticazione. 

Questo meccanismo trova la sua principale applicazione nelle interrogazioni
fatte al server attraverso il socket locale (cioè con una URI nel formato
\texttt{ldapi://}); in tal caso infatti il server può determinare con
certezza l'utente (necessariamente locale) che esegue il comando sulla base
dell'\textit{user ID} del processo che si collega al socket locale,\footnote{è
  una delle funzionalità fornite dal kernel per i socket locali, che consente
  ad un programma di ottenere \textit{UID} e \textit{GID} del processo che
  apre l'altro lato del socket.}  e non è più necessario autenticarlo. In
questo caso l'\textit{authentication ID} verrà automaticamente creato dal
server nella forma generica:
\begin{FormattedExample}
gidNumber=\textsl{N}+uidNumber=\textsl{M},cn=peercred,cn=external,cn=auth
\end{FormattedExample}
usando \textit{UID} e \textit{GID} del processo che esegue la richiesta, per
cui se ad esempio si effettua una ricerca con l'utente di amministrazione
nella forma:
\begin{Console}
# \textbf{ldapsearch -h ldapi:/// -Y EXTERNAL}
\end{Console}
si otterrà come corrispondente dell'\textit{authentication ID} il DN:
\begin{FormattedExample}
gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
\end{FormattedExample}
e si noti come nell'estratto del contenuto del database di configurazione
mostrato a pag.~\pageref{olcDatabase_config} sia stata usata una regola di
accesso (argomento trattato in dettaglio in
sez.~\ref{sec:ldap_access_control}) che fa riferimento esattamente a questo
DN, e che è quella che consente di gestire, quando si eseguono i comandi da
root collegandosi via socket, di operare con privilegi amministrativi sulla
configurazione anche in assenza di qualunque dato nel DIT associabile ad un
utente amministrativo.

Lo stesso meccanismo di autenticazione esterna può essere utilizzato usando
una connessione con TLS/SSL, richiedendo che il server effettui
l'identificazione dell'utente che esegue la connessione con l'uso di un
certificato client (torneremo su questo in sez.~\ref{sec:ldap_SSL}. In questo
caso l'autenticazione deriverà semplicemente dall'aver presentato un
certificato valido nella creazione della connessione, e verranno usati i dati
presenti nel certificato stesso per identificare l'utente. In tal caso si
otterrà un DN invertendo i dati X.509 inseriti nel certificato, per cui se nel
certificato si sono indicate informazioni nella forma: \texttt{C=IT,O=Truelite
  SRL,CN=piccardi} queste verranno convertite nel DN
\texttt{cn=piccardi,o=Truelite SRL,c=IT}.

Per tutte le altre forme di autenticazione, oltre a fornire la mappatura, si
dovrà anche configurare il server per l'uso del corrispondente meccanismo di
SASL. Come accennato il default è l'uso di \texttt{DIGEST-MD5}, che prevede
che le credenziali di autenticazione siano salvate, in chiaro, in un opportuno
supporto per poter generare una sfida (in sostanza la cifratura di un numero
casuale) che il client deve risolvere decifrandolo, e dimostrando così il
possesso del segreto condiviso costituito dalla credenziali stesse (la
password).

Nel caso delle librerie \textit{Cyrus SASL} le credenziali di autenticazione
possono essere mantenute nei supporti più diversi, sia direttamente, tramite
un sistema di plugin denominati \textit{auxprop}, che delegando le richieste
ad un demone ausiliario (\texttt{saslauthd}) che a sua volta si può
interfacciare ai verso i meccanismi più vari (sia di autenticazione locale,
che verso lo stesso LDAP). Tutto ciò viene normalmente indicato con le
opportune direttive di configurazione per la libreria, il problema però è che
dato che essa può essere usata da programmi diversi, è previsto che ogni
servizio usi un suo specifico file di configurazione, che nel caso di
\texttt{slapd} è \index{configurazione!\texttt{/etc/ldap/sasl/slapd.conf}}
\texttt{sasl/slapd.conf}, relativo alla directory in cui sono installati gli
altri file di configurazione del server.

A complicare ulteriormente una situazione già sufficientemente intricata si
aggiunge il fatto che le versioni più recenti di \texttt{slapd} il contenuto
di questo file viene ignorato (o meglio viene soprasseduto), per tutto quello
che indica il tipo di supporto da usare,\footnote{il parametro
  \texttt{auxprop\_plugin} nel file di configurazione, che dovrebbe essere
  usato per indicare l'uso di \texttt{sasldb}, viene ignorato, però la gran
  parte degli altri, ed in particolare \texttt{pwcheck\_method}, vengono
  onorati; la cosa comunque è più complicata del necessario.} da quanto viene
impostato con la direttiva
\index{OpenLDAP!direttiva~server!\texttt{sasl-auxprops}}
\texttt{sasl-auxprops}. Il punto è che anche se questa direttiva non viene
definita (come avviene normalmente), il suo default, che indica di usare le
password mantenute internamente nel server, viene utilizzato lo stesso,
indipendentemente da quello che si può indicare in \texttt{sasl/slapd.conf}.

In realtà fare conto su questo default semplifica le cose, posto che si sia
usata l'accortezza di salvare le password degli utenti su LDAP in chiaro, e
cioè che si sia inserita la direttiva \texttt{password-hash \{CLEARTEXT\}}
nella configurazione iniziale del server. Qualora questo sia stato fatto in un
secondo tempo, occorrerà portare in chiaro anche eventuali password create
dopo l'installazione, che se no resterebbero al default di
\texttt{\{SSHA\}}. In tal caso tutto quello che resta da fare è mappare gli
\textit{authentication ID}, che in questo caso sono, a seconda che si sia
usato o meno un \texttt{realm}, in una delle due forme:
\begin{FormattedExample}
uid=\textsl{<utente>},cn=\textsl{<realm>},cn=digest-md5,cn=auth
uid=\textsl{<utente>},cn=digest-md5,cn=auth
\end{FormattedExample}
dove l'utente si indica con \texttt{-U} o corrisponde, se non si indica nulla,
all'utente che si usa per eseguire i comandi. Fatta la mappatura
l'autenticazione verrà eseguita usando come password il valore di
\texttt{userPassword} per il DN corrispondente.

Se invece si vuole utilizzare il database degli utenti gestito direttamente
con i programmi della libreria \textit{Cyrus SASL}, mantenuto nel file
\texttt{sasldb} (la cui posizione può variare a seconda dell'installazione,
anche se il default è in genere \texttt{/etc/sasldb}) occorrerà indicarlo
esplicitamente al server con la direttiva:
\begin{Example}
sasl-auxprops sasldb
\end{Example}

In tal caso il server userà il contenuto di detto file e gli utenti dovranno
esser creati e gestiti all'esterno di LDAP, con i comandi di \textit{Cyrus
  SASL}. In particolare con \texttt{saslpasswd2} li possono creare (con
\texttt{-c}), cancellare (con \texttt{-d}) e modificare (indicandone solo il
nome e reimmettendo la password), mentre con \texttt{sasldblistusers2} se ne
può ottenere la lista. Ovviamente anche questi dovranno essere opportunamente
mappati,\footnote{e si tenga presente che in genere agli utenti in questo caso
  viene aggiunto un dominio, si verifichi sempre come sono registrati gli
  utenti con \texttt{sasldblistusers2}.} ma in questo caso le informazioni di
autenticazione risulteranno esterne al server. 

A meno di esigenze specifiche che vincolino all'uso di questo tipo di
autenticazione, dato che comunque le password restano in chiaro, non c'è
nessun motivo per usare SASL con questo meccanismo, quando si può ricorrere,
con maggiore semplicità e sicurezza, all'autenticazione semplice.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Direttiva} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{sasl-auxprops} & prende un argomento che indica quale plugin di
                             autenticazione di SASL utilizzare; il default
                             \texttt{slapd} usa le password mantenute nel
                             server, usando \texttt{sasldb} verranno usate
                             quelle di \texttt{/etc/sasldb}.\\
    \texttt{authz-regexp}  & prende due argomenti che indicano come mappare
                             gli \textit{authentication ID} usati
                             nell'autenticazione con SASL (l'argomento
                             dell'opzione \texttt{-U}) negli utenti interni (i
                             DN).\\
    \texttt{sasl-realm}    & prende un argomento che indica il \textit{realm}
                             SASL, il default è un \textit{realm} vuoto.\\
%    \texttt{authz-policy} & specifica le regole per la \textit{Proxy
%    Authorization}, .\\ 
%    \texttt{sasl-secprops} & .\\
    \hline
  \end{tabular}
  \caption{Principali direttive di \texttt{slapd} concernenti SASL.}
  \label{tab:slapd_sasl_directives}
\end{table}

Si sono riassunti in tab.~\ref{tab:slapd_sasl_directives} le principali
direttive usate per configurare il server nel supporto dell'autenticazione con
SASL. Si tratta in tutti i casi di direttive globali, che vanno pertanto
inserite nella relativa sezione della configurazione (cioè nella parte
iniziale di \texttt{slapd.conf} o come attributi diretti della voce
\texttt{cn=config}).


\subsection{Il controllo degli accessi}
\label{sec:ldap_access_control}

Una volta che gli utenti sono presenti sul database la direttiva che consente
di impostarne i privilegi di accesso sul server è
\index{OpenLDAP!direttiva~server!\texttt{access}} \texttt{access}. Si tenga
presente però che questa direttiva non ha alcun significato per l'eventuale
utente di amministrazione indicato con \texttt{rootdn}, che avrà
\textsl{sempre} accesso completo (ed il cui uso in una regola di accesso
provoca l'emissione di un avviso).  

La direttiva \texttt{access} è una di quelle generali che può essere
utilizzata a livello di server, ma la si usa in genere, facendo riferimento ai
relativi utenti, a livello del singolo database. La sua forma generale, così
come riportata nella pagina di manuale ad essa esplicitamente dedicata
(accessibile con \texttt{man slapd.access}), è la seguente:
\begin{FormattedExample}
access to \textsl{<what>} [ by \textsl{<who>} \textsl{<access>} [\textsl{<control>}] ]+
\end{FormattedExample}
dove gli elementi fra \texttt{<>} indicano i diversi argomenti della direttiva
che dovranno essere opportunamente specificati, le sezioni fra parentesi
quadra sono opzionali, ed il simbolo \texttt{+} indica che esse possono essere
ripetute più volte.

L'argomento \texttt{\textsl{<what>}} permette di specificare a quali oggetti
si applica la direttiva di accesso e può assumere diverse forme, in base ai
diversi criteri che si possono usare per effettuare la soluzione degli
oggetti. Una prima forma elementare è utilizzare semplicemente ``\texttt{*}''
che indica la selezione di tutte le voci presenti nel database. A parte questa
selezione generica, i meccanismi di selezione possibili sono tre, e vengono
sempre espressi in forma di assegnazione, usando le parole chiave riportate in
tab.~\ref{tab:ldap_access_what_selector}.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Stile} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{attrs}  & indica una selezione degli attributi a cui si applica la
                      regola di accesso. \\  
    \texttt{filter} & indica una selezione delle voci a cui si applica la
                      regola di accesso utilizzando un filtro di ricerca.\\ 
    \texttt{dn}     & indica una selezione delle voci a cui si applica la
                      regola di accesso utilizzando il loro
                      \textit{Distinguished Name}. \\  
    \hline 
  \end{tabular}
  \caption{Direttive di selezione degli oggetti sottoposti ad una regola di
    accesso.}
  \label{tab:ldap_access_what_selector}
\end{table}

Il primo meccanismo di selezione è quello in cui si usa la direttiva
\texttt{attrs}, che consente di specificare le regole di accesso per i singoli
attributi di un oggetto, ad esempio con una regola del tipo:
\begin{Example}
access to attrs=userPassword
\end{Example}
si specificano i criteri di accesso per l'attributo che contiene la password,
in qualunque oggetto esso si trovi. 

Con la stessa sintassi si possono specificare anche delle liste di attributi,
da indicare con l'elenco dei rispettivi nomi separati da virgole.  Allo stesso
modo si può inserire nella lista il nome di una \textit{objectclass}, usando
il prefisso ``\texttt{@}'', nel qual caso la selezione si applicherà a tutti
gli attributi in essa definiti; se invece si usa il prefisso ``\texttt{!}'' si
selezioneranno tutti gli attributi che non sono nella \textit{objectclass}.

Nella lista degli attributi specificata da \texttt{attrs} si possono poi
utilizzare anche due valori speciali: \texttt{entry}, che se inserito indica
la voce stessa, così da selezionare tutte le voci che contengono uno qualunque
degli altri attributi della lista, e \texttt{children} che indica tutte le
voci sottostanti quella contenente l'attributo. Con queste due parole chiave
il significato della selezione cambia, e non riguarda più gli attributi ma
l'intera voce, ed è così possibile impostare gli accessi selezionando le voci
in base alla presenza di un attributo senza dover ricorrere all'uso di
un'espressione regolare che sarebbe molto più costosa in termini di
prestazioni.

Una forma alternativa dell'uso di \texttt{attrs} è quando questa viene usata
insieme alla ulteriore direttiva \texttt{val} per selezionare gli attributi
che hanno un certo valore. In questo caso si può indicare per \texttt{attrs}
un solo attributo e non una lista, seguito dalla specificazione dei valori con
\texttt{val}. Questa può essere effettuata in diverse forme, di cui più
immediata è quella \texttt{val=valore} (corrispondente in realtà a
\texttt{val.exact=valore}) in cui si richiede appunto una corrispondenza
esatta.  È però disponibile anche la forma \texttt{val.regex}, dove come
valore si può usare una espressione regolare, che permette così di selezionare
solo gli attributi il cui valore corrisponda ad essa.

Il secondo meccanismo di selezione è quello in cui si usa \texttt{filter} per
indicare a quali voci del database si applica la regola di accesso tramite un
\textit{filtro di ricerca}. Questo è il meccanismo più semplice da utilizzare,
dato che basta esprimere il filtro con la sintassi standard già vista per
\texttt{ldapsearch} ed illustrata in sez.~\ref{sec:ldap_search}. Un esempio di
regola di questo tipo potrebbe essere il seguente:
\begin{Example}
access to filter=(|(sn=S*)(sn=D*))
\end{Example}
dove si selezionano tutti gli oggetti che hanno un attributo \texttt{sn} che
inizia con la lettera S o con la lettera D. 

Il terzo ed ultimo meccanismo è quello che prevede l'uso di \texttt{dn} per la
specificazione degli oggetti sulla base di espressioni indicanti il loro
\textit{Distinguished Name}, questo è il meccanismo di selezione più complesso
in quanto si possono usare diversi ``\textsl{stili}'' di selezione; la sua
espressione generica è:
\begin{FormattedExample}
dn[.\textsl{<dnstyle>}]=\textsl{<valore>}
\end{FormattedExample}
dove con \texttt{<dnstyle>} si indica uno degli stili di selezione elencati in
tab.~\ref{tab:ldap_access_dn_selector}, mentre \texttt{<valore>} indica
l'espressione di selezione. Questa per i primi 4 valori di
tab.~\ref{tab:ldap_access_dn_selector} assume il valore di un DN, nel caso di
\texttt{regex} invece sarà una espressione regolare che sarà verificata contro
tutti i DN degli oggetti dell'albero, selezionando quelli che corrispondono.
Se non si specifica nessuno stile si applica \texttt{base}.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Stile} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{base}    & indica una corrispondenza esatta con l'oggetto
                       corrispondente al \textit{Distinguished Name}
                       specificato. È il valore di default, se non si
                       specifica nulla viene assunta questa modalità.\\  
    \texttt{exact}   & sinonimo di \texttt{base}. \\  
    \texttt{one}     & indica tutti gli oggetti contenuti nel livello
                       dell'albero sottostante.\\ 
    \texttt{onelevel}& sinonimo di \texttt{one}.\\  
    \texttt{subtree} & indica tutti gli oggetti contenuti nella sezione di
                       albero che inizia dal \textit{Distinguished Name}
                       specificato.\\ 
    \texttt{sub}     & sinonimo di \texttt{subtree}.\\  
    \texttt{children}& indica tutti gli oggetti contenuti nella sezione di
                       albero a partire dal livello successivo a quello
                       del \textit{Distinguished Name} specificato.\\ 
    \hline 
    \texttt{regex}   & indica tutti gli oggetti i cui \textit{Distinguished
                         Name} che corrispondono alla espressione regolare
                       passata come argomento.\\   
    \hline 
  \end{tabular}
  \caption{Stile di selezione degli oggetti per le direttive di accesso in
    base al \textit{Distinguished Name}.}
  \label{tab:ldap_access_dn_selector}
\end{table}

Quando si utilizza una espressione regolare si tenga presente che, dato un
oggetto per cui essa corrisponde, corrisponderanno anche tutti gli oggetti che
si trovano nella parte di albero sottostante il primo oggetto (in quanto il
loro DN conterrà la parte già corrispondente), si ha cioè una selezione il cui
\textit{scope} è analogo a quello di \texttt{subtree}.

Dato che l'uso di questa modalità comporta una scansione di tutti i DN degli
oggetti è il caso di usarla con parsimonia, se si vuole ad esempio prendere
una sezione di albero al di sotto di un oggetto preciso è il caso si usare
\texttt{dn.subtree} che è molto meno pesante in termini di operazioni
richieste al server.

Si tenga presente infine che le varie forme di espressione delle regole di
selezione tab.~\ref{tab:ldap_access_what_selector} possono essere
\textsl{sommate} fra loro scrivendole in sequenza una dopo l'altra, in questo
modo si potrà ottenere un risultato che sia una opportuna combinazione delle
tre diverse modalità di selezione.

Una volta definito a \textsl{cosa} si applica la nostra regola, l'argomento
\texttt{\textsl{<who>}} permette di definire a \textsl{chi} assegnare il
relativo l'accesso. Dato che il ``\textsl{chi}'' che identifica un utente può
corrispondere ad oggetto mantenuto nell'albero stesso, di nuovo si potranno
usare alcune modalità di selezione analoghe alle precedenti, come
``\texttt{*}'' che indica l'accesso generico per tutti e le varie forme basate
su \texttt{dn} (che supportano gli stessi stili già illustrati in
tab.~\ref{tab:ldap_access_dn_selector}), per effettuare una indicazione in base
a dei DN.

Una delle caratteristiche più interessanti di questa selezione basata sul
\textit{Distinguished Name} è che se in una precedente selezione del
\texttt{\textsl{<what>}} fatta con espressioni regolari si sono usati dei
\textit{subpattern}, i valori di corrispondenza da essi ottenuti possono
essere riutilizzati all'interno dell'espressione usata con
\texttt{\textsl{<who>}} nella forma \texttt{\$\textsl{n}}, dove
\texttt{\textsl{n}} indica la $n$-sima corrispondenza nella selezione
precedente.  Diventa allora possibile definire criteri di accesso complessi
come il seguente:
\begin{Example}
access to dn.regex="ou=Contacts,cn=([^,]+),ou=UserData,dc=truelite,dc=it"
  by dn.regex="uid=$1,ou=People,dc=truelite,dc=it" read
  by * none
\end{Example}
%$
in cui si dà accesso a ciascun utente ad una distinta sezione dell'albero in
cui si suppone siano stati inseriti i suoi contatti personali, evitando però
che i singoli utenti possano accedere ai contatti personali degli altri. 

Nell'esempio la cosa viene fatta supponendo che si disponga di una struttura
dell'albero in cui i dati personali dei contatti di ciascun utente vengano
mantenuti sotto il \textit{Distinguished Name}
``\texttt{ou=Contacts,cn=nomeutente,ou=UserData,dc=truelite,dc=it}'';
l'espressione regolare utilizzata seleziona il valore dell'attributo
\texttt{cn} (che sarà il nome di un utente) composto da un numero arbitrario
(ma maggiore di zero) di caratteri qualunque esclusa la virgola (che serve a
separare i vari componenti del DN); il valore trovato è l'username che viene
riutilizzato per identificare, nel ramo di albero in cui sono mantenuti gli
utenti, quello a cui dare l'accesso alla rispettiva sezione di dati.

L'argomento \texttt{\textsl{<who>}} supporta inoltre tre valori speciali,
\texttt{self}, \texttt{anonymous} e \texttt{users}. In genere \texttt{self} è
abbinato ad una selezione basata sugli attributi; con esso si indicano quali
sono i permessi che un utente, cioè l'oggetto con il quale si è effettuato il
collegamento al server, ha sui propri attributi, cioè sugli attributi della
voce corrispondente al proprio DN. Il caso classico infatti è:
\begin{Example}
access to attrs=userPassword
        by self write
\end{Example}
che consente ad un utente di modificare la propria password, senza però essere
in grado di fare nulla con quella degli altri.

% TODO documentare self.limit 

Con \texttt{anonymous} si indica l'utente generico non ancora autenticato; di
norma si utilizza questo valore insieme al livello di autorizzazione
\texttt{auth} per indicare un accesso in cui l'oggetto richiesto (usualmente
\texttt{userPassword}) può essere acceduto solo a scopo di autenticazione. Se
non si avesse questo tipo di accesso consentito per un utente anonimo
diventerebbe impossibile effettuare un collegamento autenticato al server, non
potendo disporre delle informazioni necessarie all'autenticazione. 

Infine con \texttt{users} si indica il generico utente autenticato sul server,
in questo caso si potrebbe dare l'accesso in scrittura ad una sezione
particolare dell'albero (ad esempio quella dove sono mantenuti i contatti) ai
soli utenti autenticati con una direttiva del tipo:
\begin{Example}
access to dn.subtree="ou=Contacts,dc=truelite,dc=it"
        by users write
\end{Example}

La forma \texttt{dnattr} consente invece di utilizzare un attributo contenuto
in una voce (quello specificato con \texttt{dnattr=attributo}) per dare
l'accesso alla voce stessa. Questo è consentito se nell'attributo specificato
è presente il valore del DN con cui viene effettuata la richiesta. Con questa
forma si può specificare il \textsl{chi} può accedere direttamente all'interno
della voce acceduta.
 
Un'altra forma molto utile è \texttt{group} che consente di dare accesso a
tutti gli ``\textsl{utenti}'' di un ``\textsl{gruppo}''. In questo caso il
gruppo viene costituito da una voce apposita voce che contenga le relative
informazioni.\footnote{il default è l'uso della \textit{objectclass}
  \texttt{groupOfNames}, che nei suoi attributi \texttt{member} elenca i DN
  dei componenti del gruppo; si tenga presente che si possono usare altre
  \textit{objectclass} con altri attributi, ma che i membri del gruppo devono
  essere specificati come DN; questo rende inutilizzabile a questo scopo l'uso
  di \texttt{posixGroup}.}  La forma generale di questa indicazione è:
\begin{FormattedExample}
group[/\textsl{objectclass}[/\textsl{attributo}]][.\textsl{stile}]=\textsl{gruppo}
\end{FormattedExample}
dove \texttt{\textsl{objectclass}} indica la \textit{objectclass} utilizzata
per definire il gruppo e \texttt{\textsl{attributo}} l'attributo al suo
interno che contiene i DN dei membri del gruppo. Un esempio di uso di questa
forma è il seguente:
\begin{Example}
access to dn="ou=amministrazione,ou=Contacts,dc=truelite,dc=it"
  by group="cn=amministrazione,ou=Groups,dc=truelite,dc=it" read
\end{Example}

Ulteriori forme speciali sono quelle che permettono di selezionare l'accesso
in base ad informazioni esterne all'albero LDAP ottenute in genere
direttamente dai parametri della connessione, come \texttt{domain},
\texttt{sockname}, \texttt{sockurl}, \texttt{peername} e \texttt{sockname}.

Tutte queste forme prevedono che si possano utilizzare stili diversi per
indicare il valore del parametro passato come argomento, che come per
\texttt{dn} devono essere specificati scrivendole come \texttt{forma.stile};
nel caso di \texttt{sockname}, \texttt{sockurl} gli stili possibili sono
\texttt{exact} e \texttt{regex}, con \texttt{domain} a questi si aggiunge
anche \texttt{sub} (o \texttt{subtree}) per indicare la scelta di tutto quello
che sta sotto un dominio. Nel caso di \texttt{peername} si può avere invece lo
stile \texttt{ip} in cui si specifica invece di un nome un indirizzo IP.

Come esempio di queste direttive, se si vuole fornire l'accesso anonimo in
lettura ma solo per applicazioni residenti sul server, si potrà utilizzare una
direttiva nella forma:
\begin{Example}
access to *
        by dn="cn=admin,dc=truelite,dc=it" write
        by peername.ip=127.0.0.1 read
        by self read
        by * none
\end{Example}
con la quale per i collegamenti al server effettuati su \texttt{localhost} si
garantisce comunque un accesso in lettura.

% TODO documentare i vari ssf e *_ssf

Dopo aver specificato \textsl{cosa} (\texttt{\textsl{<what>}}) e a
\textsl{chi} (\texttt{\textsl{<who>}}) si fa riferimento in una regola, il
successivo argomento (\texttt{\textsl{<access>}}) serve ad indicare quale
privilegi di accesso devono essere assegnati. Questo può essere espresso in
due modi: il primo è attraverso l'indicazione di un \textsl{livello di
  autorizzazione}, che deve essere specificato con uno dei nomi elencati nella
prima colonna di tab.~\ref{tab:ldap_access_auth_level}, dove i livelli sono
riportati in ordine decrescente di priorità. L'assegnazione di un certo
livello di priorità implica sempre anche tutti quelli di ordine inferiore,
inoltre l'uso di \texttt{write} in questo caso comprende anche la possibilità
di aggiungere e cancellare voci.

\begin{table}[!hbt]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|c|p{6cm}|}
    \hline
    \multicolumn{2}{|c|}{\textbf{Livello}} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{manage}  &\texttt{m}& consente l'accesso amministrativo.\\
    \texttt{write}   &\texttt{w}& consente la scrittura dei dati.\\
                     &\texttt{a}& consente l'aggiunta di dati.\\
                     &\texttt{d}& consente la cancellazione di dati.\\
    \texttt{read}    &\texttt{r}& consente la lettura dei dati.\\
    \texttt{search}  &\texttt{s}& consente l'accesso nelle ricerche.\\
    \texttt{compare} &\texttt{c}& consente l'accesso nelle ricerche ordinate.\\
    \texttt{auth}    &\texttt{x}& l'accesso è consentito internamente al
                                  server a solo scopo di autenticazione.\\
    \texttt{disclose}&\texttt{d}& consente l'accesso alle informazioni di
                                  errore.\\   
    \texttt{none}    &\texttt{0}& nessun accesso.\\  
    \hline 
  \end{tabular}
  \caption{Livelli di accesso usati dalla direttiva \texttt{access}.}
  \label{tab:ldap_access_auth_level}
\end{table}

Qualora invece l'indicazione dei permessi di accesso necessiti di una maggiore
flessibilità si dovrà usare la seconda modalità che consente specificare una
combinazione arbitraria dei singoli permessi. In questo caso un permesso dovrà
essere specificato da una indicazione composta di un operatore seguito da una
lista di permessi espressi tramite le lettere della seconda colonna di
tab.~\ref{tab:ldap_access_auth_level}.
Gli operatori utilizzabili per questa seconda modalità sono ``\texttt{+}'',
che aggiunge i permessi indicati dalle lettere seguenti, ``\texttt{-}'' che li
toglie e ``\texttt{=}'' che li assegna esattamente.  Si possono associare ad
un operatore quanti permessi si vuole, con l'eccezione di \texttt{0} che,
indicando la rimozione di qualunque privilegio, deve sempre essere usato da
solo. Si tenga presente che in questo caso il permesso ``\texttt{w}'' è
semplicemente la somma dei due permessi ``\texttt{a}'' e ``\texttt{z}'' che
non esistono come livelli separati, in sostanza \texttt{+w} è equivalente a
\texttt{+az}.

Infine è possibile, come indicato nella forma generica delle regole di accesso
illustrata all'inizio, aggiungere in coda alla specificazione dei permessi una
istruzione di controllo finale (\texttt{\textsl{<control>}}) che consente di
modificare la modalità con cui le regole vengono esaminate.

Il meccanismo ordinario con cui vengono applicate le regole di accesso prevede
infatti che queste vengano esaminate in sequenza; in caso di corrispondenza
del \texttt{\textsl{<what>}} verranno immediatamente controllati i vari
\texttt{\textsl{<who>}} ad essa relativi, e applicati i permessi indicati dal
primo che corrisponde.  Se nessun \texttt{\textsl{<who>}} corrisponde tutti i
permessi verranno rimossi; è cioè sempre sottintesa una regola finale del
tipo: ``\texttt{by * none}''.  In ogni caso la scansione delle regole termina
immediatamente una volta presa la decisione riguardo ai permessi.

Questo avviene perché il default per il valore di \texttt{\textsl{<control>}}
è \texttt{stop}, che causa appunto la terminazione della scansione delle
regole.  Gli altri due valori possibili sono \texttt{continue}, che fa
proseguire la scansione nei \texttt{\textsl{<who>}} successivi (se ve ne sono)
e o \texttt{break} che invece fa passare alla regola successiva. In genere, a
parte esigenze molto specifiche, questi non vengono usati.

Un esempio reale di utilizzo della direttiva \texttt{access} è riportato nel
seguente estratto del file di configurazione standard installato da Debian
Lenny, dal quale al solito si sono eliminati commenti e righe vuote:
\begin{FileExample}[label=slapd.conf]
access to attrs=userPassword
        by dn="cn=admin,dc=truelite,dc=it" write
        by anonymous auth
        by self write
        by * none
access to dn.base="" by * read
access to *
        by dn="cn=admin,dc=truelite,dc=it" write
        by * read
\end{FileExample}

Si faccia attenzione a non inserire commenti a metà di una direttiva
\texttt{access} come le precedenti, quando le si sono suddivise su più righe
sfruttando la caratteristica del file di configurazione che considera una
prosecuzione della precedente una riga che inizia per spazio; in tal caso
infatti se ad un certo punto si inserisce un commento la direttiva risulterà
spezzata, e gli effetti saranno tutt'altro che piacevoli.

Si noti come nell'esempio sia stato usato per l'attributo
\texttt{userPassword} un accesso di livello \texttt{auth} associato ad
\texttt{anonymous}, questo perché prima di potersi collegare l'utente non è
ancora autenticato, per cui l'accesso sarà in forma anonima, ma il server, per
poter effettuare l'autenticazione, ha necessità di poter accedere alla
password. Si noti anche come con \texttt{self} si sia consentito agli utenti
stessi di modificare la propria password.

L'esempio evidenzia anche le conseguenze delle modalità di scansione delle
regole di accesso appena illustrata, che spesso provoca errori in quanto non
se ne tiene dovutamente conto: dato che le regole vengono esaminate
nell'ordine in cui sono scritte quando si ha una corrispondenza sull'oggetto a
cui si applicano la scansione si ferma immediatamente ed i permessi indicati
vengono applicati.

Questo significa che occorre sempre mettere le regole più specifiche in testa,
come viene fatto nell'esempio per la regola che riguarda solo l'attributo
\texttt{userPassword}. Se prima di questa si fosse messa una regola generica
come quella finale il risultato sarebbe stato che le successive regole non
sarebbero mai state prese in considerazione e quindi chiunque avrebbe potuto
leggere il dato della password e solo l'amministratore modificarlo.

Si noti anche come per le regole specifiche sia necessario ripetere
l'indicazione degli stessi criteri di accesso (come quello per
l'amministratore) elencati nella successiva regola generica, questo perché, se
non ci fossero, essendo ignorate in caso di corrispondenza le regole seguenti,
ci si sarebbe trovati con un utente amministrativo incapace di accedere
autonomamente in scrittura al campo \texttt{userPassword} di tutti gli utenti.


\subsection{La configurazione per l'uso di SSL/TLS}
\label{sec:ldap_SSL}

La configurazione di \textit{OpenLDAP} per l'uso di TLS/SSL è tutto sommato
abbastanza semplice e si riduce in sostanza alle impostazioni necessarie ad
indicare quali sono i certificati da usare per l'uso del protocollo ed
eventualmente impostare quale tipo di comportamento assumere in caso di
assenza o di non correttezza delle stesse.

La parte più complicata è che se non si usano certificati pubblici già pronti
è necessario approntare una propria \textit{Certification Authority} che firmi
i certificati delle varie macchine, specie se oltre al server presso i client
si vogliono anche autenticare i client presso il server, quest'ultimo caso
comunque è piuttosto raro, per i problemi che vedremo più avanti. Non
tratteremo qui le modalità con cui creare e gestire una tale CA, argomento per
il quale si rimanda alla sezione 2.1.4 di \cite{SGL}.

Una volta che si disponga dei certificati necessari si tratta semplicemente di
configurare il server per il relativo utilizzo; per questo \texttt{slapd.conf}
prevede un gruppo di direttive specifiche per la configurazione di SSL/TLS,
che consentono di indicare al server i file dei certificati. Si sono
illustrate le direttive più rilevanti in tab.~\ref{tab:ldap_ssl_directives},
al solito l'elenco completo è riportato nella pagina di manuale di
\texttt{slapd.conf}, nella sezione \textit{TLS options}.

\index{OpenLDAP!direttiva~server!\texttt{TLSCertificateFile}}
\index{OpenLDAP!direttiva~server!\texttt{TLSCACertificateFile}}
\index{OpenLDAP!direttiva~server!\texttt{TLSCertificateKeyFile}}
\index{OpenLDAP!direttiva~server!\texttt{TLSVerifyClient}}
\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Direttiva} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{TLSCertificateFile}  & indica il file in cui è contenuto il
                                   certificato usato dal server.\\
    \texttt{TLSCACertificateFile}& indica il file in cui è contenuto il
                                   certificato della CA riconosciuta dal
                                   server.\\ 
%    \texttt{TLSCipherSuite}      & .\\
    \texttt{TLSCertificateKeyFile}&indica il file che contiene la chiave del
                                   certificato del server.\\
    \texttt{TLSVerifyClient}     & richiede che anche il client si identifichi
                                   con SSL presso il server, prende uno dei
                                   valori di
                                   tab.~\ref{tab:ldap_ssl_verify_values}, il
                                   default è \texttt{never}.\\
%    \texttt{TLSCACertificatePath}     & .\\
    \hline 
  \end{tabular}
  \caption{Le principali direttive di \texttt{slapd.conf} per l'uso di
    TLS/SSL.}
  \label{tab:ldap_ssl_directives}
\end{table}

Un estratto della sezione di \texttt{slapd.conf} in cui si sono inserite le
direttive necessarie per abilitare l'uso di TLS/SSL con le impostazioni per
indicare i certificati, è allora il seguente:
\begin{FileExample}[label=slapd.conf]
# For SSL/TLS authentication
TLSCertificateFile      /etc/ssl/certs/ldapcert.pem
TLSCertificateKeyFile   /etc/ssl/private/ldapkey.pem
TLSCACertificateFile    /etc/ssl/certs/cacert.pem
\end{FileExample}

Si tenga conto inoltre, quando si copiano i certificati e le chiavi da
un'altra macchina o da un'altra directory, che questi devono poter essere
acceduti dal programma, ma che la chiave deve essere adeguatamente protetta da
lettura da parte di terzi, questo significa che questa deve avere permessi
adeguati a consentire l'accesso da parte dell'utente per conto del quale viene
eseguito \texttt{slapd}.\footnote{se come nel caso si è usato
  \texttt{/etc/ssl/private/ldapkey.pem}, su Debian, dove
  \texttt{/etc/ssl/private} può essere attraversata solo dal gruppo
  \texttt{ssl-cert}, occorrerà anche aggiungere l'utente \texttt{openldap} a
  tale gruppo.}

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Direttiva} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{never} & non viene richiesto ne controllato un certificato.\\
    \texttt{allow} & viene richiesto un certificato, ma se non viene fornito o
                     se non è valido prosegue ugualmente.\\
    \texttt{try}   & viene richiesto un certificato, se non viene fornito
                     prosegue ugualmente ma se non è valido si ferma.\\
    \texttt{hard}  & viene richiesto un certificato, e si ferma se non viene
                     fornito o se non è valido.\\
    \texttt{true}  & equivalente a \texttt{hard}.\\
    \texttt{demand}& equivalente a \texttt{hard}.\\
    \hline 
  \end{tabular}
  \caption{Valori possibili per le direttive di verifica dei certificati nella
    comunicazione con SSL/TLS.}
  \label{tab:ldap_ssl_verify_values}
\end{table}

Si tenga presente infine che per poter utilizzare TLS occorre anche avviare
opportunamente il server (si ricordi quanto detto in
sez.~\ref{sec:slapd_install}). Nel caso di Debian per questo si può usare la
variabile di ambiente \texttt{SLAPD\_SERVER} definita in
\texttt{/etc/default/slapd} che permette di indicare esplicitamente le
modalità di avvio del server, una configurazione tipica potrebbe essere la
seguente:
\begin{Example}
SLAPD_SERVICES="ldap://127.0.0.1/ ldaps:/// ldapi:///"
\end{Example}
con cui si mette il server in ascolto in chiaro per le connessioni locali e si
usa TLS/SSL per tutte quelle remote. Nel caso di Fedora/RedHat/CentOS, si può
richiedere l'avvio su SSL effettuando l'impostazione della variabile
\texttt{SLAPD\_LDAPS=yes} in \texttt{/etc/sysconfig/ldap}.

Oltre al server, per poter utilizzare TLS, occorre anche fornire le adeguate
impostazioni al client, si dovranno cioè utilizzare le opportune direttive di
configurazione previste per \texttt{ldap.conf}.  In questo caso, nello
specificare quale è il server a cui si fa riferimento, sarà necessario usare
la direttiva \texttt{URI}, che permette la sintassi estesa delle URL di
tab.~\ref{tab:ldap_URL}. Nel nostro caso dovremo specificare l'indirizzo del
server come \texttt{ldaps://ldap.truelite.it} eliminando eventuali direttive
\texttt{HOST} e \texttt{PORT}.

Inoltre per il funzionamento del protocollo si deve anche indicare il file
contenente il certificato della \textit{Certification Authority} che
testimonia la validità dei certificati forniti del server usando l'apposita
direttiva \texttt{TLS\_CACERT}. Il default infatti richiede riconoscimento del
server, e che questo presenti un certificato valido, per cui se si sono usati
dei certificati autoprodotti come quelli illustrati nell'esempio precedente,
occorrerà aggiungere all'esempio di file di configurazione visto in
sez.~\ref{sec:ldap_client_base_config} una sezione apposita con un contenuto
del tipo:
\begin{FileExample}[label=ldap.conf]
TLS_CACERT     /etc/ssl/certs/cacert.pem
\end{FileExample}

Se invece l'unico scopo dell'uso di SSL/TLS è la cifratura della connessione,
tutto ciò non è necessario, e si può rilassare la richiesta usando
esplicitamente la direttiva \texttt{TLS\_REQCERT} (il cui default è
\texttt{hard}), in tal caso non interessa la verifica del certificato
(qualunque esso sia) per cui si può rimuovere la direttiva
\texttt{TLS\_CACERT} e indicare semplicemente:\footnote{questo può essere
  comunque necessario con Debian, dove \texttt{slapd} è linkato con
  \textit{GnuTLS}, se si generano i certificati con \texttt{openssl}, in tal
  caso infatti, per un problema di compatibilità, questi ultimi non verrebbero
  comunque riconosciuti come validi.}
\begin{FileExample}[label=ldap.conf]
#TLS_CACERT     /etc/ssl/certs/cacert.pem
TLS_REQCERT    never
\end{FileExample}

Un elenco delle principali direttive usate per la configurazione dell'accesso
via SSL ad un server LDAP da parte di un client è riportato in
tab.~\ref{tab:ldap_ssl_directives_client} (le direttive sono riportate in
maiuscolo, ma si possono specificare anche in caratteri minuscoli); per
l'elenco completo al solito si faccia riferimento alla pagina di manuale di
\texttt{ldap.conf}.

\index{OpenLDAP!direttiva~client!\texttt{TLS\_CERT}}
\index{OpenLDAP!direttiva~client!\texttt{TLS\_CACERT}}
\index{OpenLDAP!direttiva~client!\texttt{TLS\_KEY}}
\index{OpenLDAP!direttiva~client!\texttt{TLS\_REQCERT}}
\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Direttiva} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{TLS\_CERT}  & indica il file in cui è contenuto il certificato 
                          del client, è usabile solo a livello utente.\\
    \texttt{TLS\_CACERT}& indica il file in cui è contenuto il certificato
                          della CA riconosciuta dal client, è usabile solo a
                          livello utente.\\
    \texttt{TLS\_KEY}   & indica il file che contiene la chiave del certificato
                          del client, è usabile solo a livello utente.\\
    \texttt{TLS\_REQCERT}&indica il livello di controllo che si richiede sui
                           certificati del server, da indicare con uno dei
                           valori di tab.~\ref{tab:ldap_ssl_verify_values}, il
                           default è \texttt{hard}, è usabile solo a livello
                           utente.\\
    \hline 
  \end{tabular}
  \caption{Direttive per la configurazione di \texttt{ldap.conf} per l'uso di
    TLS/SSL.} 
  \label{tab:ldap_ssl_directives_client}
\end{table}

Se si è attivata la richiesta di verifica del client da parte di
\texttt{slapd} (lo si fa con la direttiva \texttt{TLSVerifyClient} illustrata
in tab.~\ref{tab:ldap_ssl_directives}) occorre configurare il client perché
invii il suo certificato. Per ciascun client si dovranno pertanto ripetere le
precedenti operazioni per creare un certificato firmato da una CA riconosciuta
del server (in genere si usa sempre la stessa, ma non è necessario).  Anche
qui deve avere cura di usare come \textit{Common Name} il nome a dominio (in
forma di FQDN) del client.

In questo caso si ha il problema che a livello di \texttt{ldap.conf} sarebbe
possibile specificare solo un certificato per ciascuna macchina, da mantenere
in una opportuna directory (in genere si usa comunque
\texttt{/etc/ssl/certs/}). Questo significa però che la chiave privata del
certificato, per poter essere utilizzata, dovrebbe essere leggibile da ogni
utente, e non è una buona pratica di sicurezza il fatto che un singolo utente
possa avere pieno accesso ad un certificato che identifica una intera macchina
(ed influire quindi anche sulle capacità degli altri utenti).

Per questo motivo una configurazione in cui si richiede il riconoscimento dei
client non può essere fatta sul file di configurazione generale
\texttt{ldap.conf}, ma deve essere specificata per il singolo utente usando il
file di configurazione personale \texttt{.ldaprc} in cui l'utente può
specificare le sue opzioni; in questo caso dovrebbero esservi inserite delle
direttive del tipo:
\begin{FileExample}[label=.ldaprc]
TLS_CACERT      cacert.pem
TLS_CERT        my_cert.pem
TLS_KEY         my_key.pem
TLS_REQCERT     hard
\end{FileExample}
che permettono l'uso di un certificato personale (la prima è opzionale se il
file della CA è già stato impostato in \texttt{ldap.conf}).  Questo significa
però che se si deve autenticare il client rispetto al server, occorrerà anche
dotare ciascun utente di un suo certificato, rendendo ovviamente la gestione
degli utenti molto più macchinosa, ma questo è anche quello che potrebbe
consentire una autenticazione diretta usando i dati del certificato e il
meccanismo \texttt{EXTERNAL} di SASL. In generale la complessità del tutto va
valutata rispetto allo scopo che si vuole ottenere.

Una volta che si sia configurato il server e le librerie per l'uso di SSL se
ne potrà verificare il funzionamento direttamente con \texttt{ldapsearch},
si può richiedere l'uso di SSL direttamente sulla riga di comando con
l'opzione \texttt{-H} usando la apposita URL estesa (vedi
tab.~\ref{tab:ldap_URL}), un esempio potrebbe essere:
\begin{Console}
$ \textbf{ldapsearch -x -H ldaps://ldap.truelite.it}
\end{Console}
%$

Si tenga presente che in caso di mancato riconoscimento del certificato la
connessione fallirà con un messaggio abbastanza stringato che non rende facile
risolvere il problema. Per capire quale possa essere la causa, le più comuni
sono la non corrispondenza fra il nome a dominio con cui si contatta il server
e quello presente nel certificato, o la scadenza dello stesso, si può ripetere
il precedente comando utilizzando l'opzione \texttt{-d 1} per aumentare le
informazioni relative alla connessione, questo in genere consente anche di
ottenere le motivazioni di eventuali malfunzionamenti.


\subsection{Gli \textit{overlay}}
\label{sec:ldap_overlay}

Con la versione 2.2 di \textit{OpenLDAP} è stato introdotto un ulteriore
meccanismo di estensione e modularizzazione delle funzionalità del server
nella forma dei cosiddetti \textit{overlay}, che vanno a costituire una
estensione del modello che consente di usare diversi \textit{backend} per la
memorizzazione dei dati e consentono di ottenere un potente mezzo per
aumentarne le funzionalità.

In sostanza il meccanismo prevede la possibilità di interporsi fra il
funzionamento del \textit{frontend} del server LDAP, che riceve le richieste,
le decodifica e le passa al \textit{backend}, e quest'ultimo che fornisce le
relative risposte. Con questa interposizione sia le richieste che le risposte
possono essere intercettate in modo da potervi eseguire sopra le operazioni
volute. In questo modo si può personalizzare il funzionamento di un
\textit{backend} senza doverne creare una versione modificata, e usare le
estensioni solo dove necessario.

Inizialmente questa funzionalità era utilizzabile solo in corrispondenza ad
uno specifico \textit{backend}; partire dalla versione 2.3 è divenuto
possibile utilizzare gli \textit{overlay} in maniera generica, ad esempio per
ottenere funzionalità indipendenti dai diversi \textit{backend} o anche
utilizzare le informazioni della richiesta per selezionare l'uso di uno
specifico \textit{backend} piuttosto di un altro.

Gli \textit{overlay}, come i \textit{backend}, sono realizzati tramite codice
fornito da moduli,\footnote{si tratta di codice disponibile in forma di
  libreria condivisa che viene installato nella directory dei moduli
  (usualmente \texttt{/usr/lib/ldap}).}  per cui prima di poterne utilizzare
uno il modulo che lo implementa deve essere caricato con l'uso della
appropriata direttiva \texttt{moduleload}. Una volta che il modulo sia stato
caricato le funzionalità devono essere esplicitamente attivate per ciascun
\textit{backend} o \textit{database} attraverso la direttiva
\index{OpenLDAP!direttiva~server!\texttt{overlay}} \texttt{overlay}. Questa è
una direttiva che opera a livello di database, e dovrà essere specificata per
ciascun database per cui si vuole utilizzare il relativo
\textit{overlay}. Pertanto se si vuole utilizzare l'\textit{overlay}
\texttt{unique} si dovranno specificare le direttive:
\begin{Example}
moduleload unique
overlay unique
\end{Example}
e si tenga conto che il fatto che il modulo e l'\textit{overlay} dell'esempio
abbiano lo stesso nome è un caso specifico e non una regola generale.

La direttiva richiede come argomenti il nome dell'\textit{overlay} che si
vuole usare. In tab.~\ref{tab:ldap_overlay_list} si è riportata una lista dei
principali \textit{overlay} disponibili, con una breve descrizione degli
stessi, l'elenco completo può essere ottenuto consultando la relativa pagina
di manuale, accessibile con \texttt{man slapd.overlays}; la documentazione dei
singoli overlay è invece mantenuta in altrettante pagine di manuale,
accessibili a loro volta con \texttt{man slapo-nomeoverlay}.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Nome} & \textbf{Descrizione} \\
    \hline
    \hline
    \texttt{syncprov}  & Implementa il \textit{provider} per una replicazione
                         con \texttt{syncrepl} (vedi
                         sez.~\ref{sec:ldap_replication_syncrepl}).\\ 
    \texttt{ppolicy}   & Implementa politiche di controllo di qualità sulle 
                         password degli utenti LDAP.\\
    \texttt{valsort}   & Consente di richiedere uno specifico ordinamento 
                         dei valori di un attributo a valori multipli in
                         risposta alle ricerche.\\
    \texttt{unique}    & Consente di garantire l'unicità del valore di un
                         attributo in un ramo di albero (ad esempio per
                         richiedere che un attributo che identifica un utente
                         sia unico).\\
    \texttt{constraint}& Consente di impostare dei vincoli sui valori che
                         possono essere assegnati ad un attributo (ad esempio
                         per forzare l'inserimento di valori corretti per
                         codici postali, numeri telefonici, nomi a dominio,
                         ecc.).\\ 
    \texttt{accesslog} & Consente di registrare tutti gli accessi ad un dato
                         database su un altro database, in modo che sia
                         possibile ottenerli da quest'ultimo attraverso
                         richieste LDAP; in questo modo si possono revisionare
                         col protocollo stesso le operazioni fatte su un
                         albero (il meccanismo viene usato per la cosiddetta
                         \textit{delta-replication}, vedi
                         sez.~\ref{sec:advanced-replication}).\\ 
    \texttt{chain}  &    Consente di far seguire un \textit{referral} 
                         direttamente al server a cui è stata effettuata la
                         richiesta, per supportare i client difettosi che non
                         sono in grado di farlo correttamente (fa parte del
                         modulo \texttt{back\_ldap}).\\
    \texttt{smbk5pwd} &  Consente di eseguire una sincronizzazione automatica
                         degli attributi contenenti gli hash delle password
                         per Samba e per Kerberos 5 quando viene eseguita una 
                         \textit{LDAP Password Modify Extended Operation}.\\
%    \texttt{}  & .\\
    \hline 
  \end{tabular}
  \caption{Principali \textit{overlay} disponibili per \texttt{slapd} (usabili
    come argomenti per la direttiva \texttt{overlay}).} 
  \label{tab:ldap_overlay_list}
\end{table}

Una delle caratteristiche più interessanti degli \textit{overlay} e che se ne
possono utilizzare anche più di uno ripetendo la direttiva per ciascuno di
essi; in questo caso gli \textit{overlay} vengono \textsl{impilati} uno
sull'altro nell'ordine in cui li si dichiarano, quindi verrà eseguito per
primo quello dichiarato per ultimo. Il concetto è quello che ogni richiesta
viene passata allo strato degli \textit{overlay} prima di arrivare al
database, il primo la riceve, la tratta e passa il risultato al successivo e
via seguendo; le risposte fanno il percorso inverso. Questo consente di
combinare fra loro le diverse funzionalità fornite dai singoli
\textit{overlay}.


% \subsection{Ottimizzare le prestazioni}
% \label{sec:ldap_performance_tuning}

% Da fare.

% TODO: documentare meglio limits


\section{La replicazione}
\label{sec:ldap_replication}

Affronteremo in questa sezione l'argomento della replicazione, che è una delle
caratteristiche più interessanti di LDAP. La replicazione è il meccanismo che
consente di distribuire su più server mantenendole coerenti fra loro le
informazioni di un albero di dati LDAP. Esamineremo le varie modalità con cui
la replicazione viene effettuata e le relative configurazioni.

\subsection{Il meccanismo della replicazione}
\label{sec:ldap_replication_intro}

Una delle caratteristiche più interessanti di LDAP è la facilità con cui,
grazie al supporto dei \textit{referral} (vedi
sez.~\ref{sec:ldap_query_mechanism}) fornito dal protocollo stesso, è
possibile creare e mantenere aggiornate automaticamente varie copie del
database, così da poter distribuire le richieste o creare dei backup
automaticamente. Questo viene realizzato attraverso una funzionalità che viene
chiamata in modo generico ``\textsl{replicazione}'', che consente di creare
dei server secondari (i cosiddetti \textit{slave}) che mantengono
automaticamente le stesse informazioni presenti su un server primario (il
cosiddetto \textit{master}).

\begin{figure}[!htb]
  \centering \includegraphics[width=10cm]{images/req_replicated}
  \caption{Il funzionamento della replicazione.}
  \label{fig:ldap_replication_request}
\end{figure}

Il funzionamento generale della replicazione, sommariamente illustrato in
fig.~\ref{fig:ldap_replication_request}, prevede che quando un client effettua
una richiesta per leggere dei dati di un albero tramite un secondario
quest'ultimo risponda direttamente, quando invece si vogliono effettuare delle
modifiche il secondario risponderà al programma che ha richiesto la modifica
inviando un riferimento al server primario,\footnote{il meccanismo è sempre
  quello dei \textit{referral} che abbiamo illustrato in
  fig.~\ref{fig:ldap_referral_reques}, in questo caso però i riferimenti
  vengono inviati solo, a cura del secondario, per le richieste di scrittura.}
in modo che la richiesta possa essere fatta direttamente a lui. Se si è
attivato un opportuno meccanismo di replicazione, una volta che il server
primario ha effettuato la modifica, sarà compito di tale meccanismo far sì che
i dati modificati vengano aggiornati sui vari secondari, attraverso i canali
di comunicazione usati per la replicazione.

Una volta completato il ciclo di aggiornamento tutti i secondari avranno i
dati coerenti fra loro e con il primario; si tenga presente però, come
accennato in sez.~\ref{sec:ldap_intro}, che il protocollo LDAP non esclude
delle inconsistenze temporanee nei dati, e questo vale anche per differenze
fra il primario ed i vari secondari, e anche di questi ultimi fra loro, dovute
appunto al fatto che il meccanismo appena illustrato non dà nessuna garanzia
sulla immediatezza della sincronizzazione dei dati.

Come per le modalità con cui vengono mantenuti i dati dell'albero, anche per
il meccanismo della replicazione il protocollo LDAP non prevede una specifica
modalità realizzativa, infatti tutto quello che serve è che i vari server
gestiscano in maniera coerente i riferimenti e mantengano coordinate le
informazioni. Esistono pertanto diverse implementazioni della replicazione,
che tratteremo nelle prossime sezioni.

Infine, a partire dalla versione 2.4 di \textit{OpenLDAP} viene supportata
anche una diversa modalità di replicazione in cui non si ha più la restrizione
di un singolo \textit{master} che raccoglie e distribuisce tutte le modifiche
agli \textit{slave} come illustrato in
fig.~\ref{fig:ldap_replication_request}. La nuova modalità di replicazione,
denominata \textit{multi-master}, consente infatti ad ogni server di agire sia
come \textit{master}, eseguendo direttamente le richieste di modifica per poi
trasmetterle agli altri server con gli opportuni meccanismi di
sincronizzazione, sia come \textit{slave} per ottenere le modifiche effettuate
allo stesso modo dagli altri server.


\subsection{La replicazione con \texttt{slurpd}}
\label{sec:ldap_replication_slurpd}

Fino alla versione 2.3 di \textit{OpenLDAP}, quando è stato introdotto il nuovo
meccanismo denominato \textit{syncrepl}, la replicazione veniva realizzata
esclusivamente attraverso l'utilizzo sul server principale di un demone
dedicato, \index{demone!\texttt{slurpd}} \texttt{slurpd}, che si incaricava di
inviare ai secondari le modifiche effettuate sulla copia principale
dell'albero, secondo lo schema illustrato in
fig.~\ref{fig:ldap_slurpd_replication}. A partire dalla versione 2.4 l'uso di
\texttt{slurpd} non è più supportato ed occorre utilizzare obbligatoriamente
\textit{syncrepl}, che tratteremo in sez.~\ref{sec:ldap_replication_syncrepl}.

\begin{figure}[!htb]
  \centering \includegraphics[width=10cm]{images/slurpd_replication}
  \caption{Il funzionamento della replicazione con \texttt{slurpd}.}
  \label{fig:ldap_slurpd_replication}
\end{figure}

Il funzionamento della replicazione con \texttt{slurpd} prevede che il demone
rilevi le modifiche ai dati che vengono effettuate sul server principale
leggendole su un apposito file, detto \textsl{giornale di
  replicazione}. Questo file viene opportunamente creato e mantenuto dal
server \texttt{slapd} del \textit{master}, che vi salva tutte le modifiche
effettuate al database con la relativa marca temporale.  Quando
\texttt{slurpd} rileva nel \textsl{giornale di replicazione} delle modifiche
non ancora applicate (usando la marca temporale) il programma crea un file di
lock e le trascrive in una copia privata, e poi le invia ai secondari
effettuando semplicemente delle richieste di scrittura LDAP, che in questo
caso, essendo i secondari configurati per riconoscerle ed accettarle, verranno
eseguite.  Nel caso di Debian viene usato il file \texttt{slurpd.replog},
mantenuto, come gli altri file usati da \texttt{slurpd}, sotto
\texttt{/var/spool/slurpd/replica/}.

L'opzione \texttt{-r} di \texttt{slurpd} permette di indicare manualmente un
\textsl{giornale di replicazione} alternativo a quello di default (letto dalla
configurazione), ed in genere la si usa insieme all'opzione \texttt{-o} che
attiva la cosiddetta modalità \textit{one-shot}, in cui il programma legge il
file, applica le modifiche ed esce subito dopo. Questa è la modalità che si
usa per eseguire manualmente (a demone fermo) eventuali modifiche rimaste
bloccate per un qualche errore.  Infine l'opzione \texttt{-d} attiva la
modalità di debug; in questo caso il programma, a meno di non aver usato anche
\texttt{-o} nel qual caso termina dopo aver eseguito le modifiche, resta
agganciato al terminale e verranno stampate a video tutte le informazioni di
controllo specificate dalla maschera binaria passata come parametro
dell'opzione; per i valori di questo parametro si consulti la pagina di
manuale, accessibile con \texttt{man slurpd}.

Come demone \texttt{slurpd} non ha un suo file di configurazione; per gestire
la replicazione normalmente viene usato lo stesso \texttt{slapd.conf}, in cui
devono essere presenti le apposite direttive di replicazione riassunte in
tab.~\ref{tab:ldap_replica_directive}. Si tenga presente che queste direttive
riguardano comunque anche il funzionamento del demone principale
\texttt{slapd}.  Con l'opzione \texttt{-f} comunque si può indicare al
programma l'uso un file di configurazione alternativo.

\index{OpenLDAP!direttiva~server!\texttt{replicationinterval}}
\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Direttiva} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{replica}   & Definisce i parametri che indicano un server
                         secondario da usare come replica.\\
    \texttt{replicationinterval} & Indica l'intervallo in secondi usato
                         da \texttt{slurpd} nel controllare la presenza di
                         cambiamenti sul giornale di replicazione.\\
    \texttt{replogfile}& Indica il file sul quale viene mantenuto il giornale
                         di replicazione.\\
    \texttt{updatedn}  & Indica sul secondario quale DN è utilizzato per
                         ricevere i dati di replicazione.\\
    \texttt{updateref} & Indica sul secondario quale a quale server primario
                         fare riferimento in caso di richieste di modifica.\\
    \hline 
  \end{tabular}
  \caption{Le principali direttive usate per la replicazione con
    \texttt{slurpd}.}  
  \label{tab:ldap_replica_directive}
\end{table}

Il primo passo da fare per impostare una replicazione è di configurare il
primario perché generi le informazioni ad essa necessarie, per questo c'è la
direttiva \index{OpenLDAP!direttiva~server!\texttt{replogfile}}
\texttt{replogfile}, che permette di indicare un file sul quale sarà scritto
il cosiddetto \index{giornale~di~replicazione} \textsl{giornale di
  replicazione} (o \textit{replication logfile}).  La direttiva richiede come
parametro il nome del file che verrà scritto da \texttt{slapd}, e poi letto da
\texttt{slurpd}.

La seconda direttiva necessaria sul primario è
\index{OpenLDAP!direttiva~server!\texttt{replica}} \texttt{replica}, che
permette di specificare tutti i dati che indicano a \texttt{slurpd} verso chi
inviare le informazioni di replicazione. La direttiva prevede l'indicazione di
una serie di argomenti nella forma \texttt{nome=valore}, separati da spazi.
Di questi l'unico obbligatorio è \texttt{uri} che serve ad indicare la URI del
server secondario su cui verranno replicati i dati. Se si hanno più secondari
basterà usare una diversa direttiva \texttt{replica} per ciascuno di essi.

Normalmente oltre alla URI del server deve essere anche specificato, con
l'argomento \texttt{binddn}, l'utente con cui collegarsi sul secondario per
scrivere i dati, con \texttt{bindmethod} il metodo di autenticazione, e con
\texttt{credentials} il valore della password da usare.  In generale questo
utente dovrebbe essere diverso da quello di amministrazione del database, dato
che un secondario può ospitare anche altri alberi; ma qualora il secondario
sia semplicemente usato come replica del primario si può anche usare lo stesso
utente.  Un elenco degli altri principali argomenti della direttiva
\texttt{replica} è illustrato in tab.~\ref{tab:ldap_replica_parameters}.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Argomento} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{uri}        & indica la URI del server secondario, con la stessa
                          sintassi illustrata in tab.~\ref{tab:ldap_URL}.\\
%    \texttt{starttls}   & indica, in caso do.\\
    \texttt{suffix}     & indica quali sezioni dell'albero devono essere
                          replicate, se non specificato è l'intero albero,
                          altrimenti si possono indicare più sezioni
                          attraverso il rispettivo DN.\\
    \texttt{binddn}     & indica (come DN) l'utente con il quale effettuare il
                          collegamento al server secondario; ci si accerti che
                          questo abbia privilegi sufficienti per poter scrivere
                          le relative informazioni.\\
    \texttt{bindmethod} & indica la modalità con cui effettuare il
                          collegamento al server, può assumere i valori
                          \texttt{simple} o \texttt{sasl}.\\
    \texttt{credentials}& indica la password dell'utente con cui effettuare il
                          collegamento.\\
    \texttt{attr}       & indica gli attributi da replicare.\\
    \hline 
  \end{tabular}
  \caption{Principali argomenti della direttiva \texttt{replica}.} 
  \label{tab:ldap_replica_parameters}
\end{table}

Un possibile esempio delle direttive di configurazione da inserire su un
server primario per la creazione di una replica di un albero è allora quello
contenuto nel seguente estratto di \texttt{slapd.conf}:
\begin{FileExample}[label=slapd.conf]
replogfile /var/lib/ldap/replog

replica uri=ldaps://slave.truelite.it:636
        binddn="cn=replicatore,dc=truelite,dc=it"
        bindmethod=simple credentials=password_segretissima
\end{FileExample}

Nel caso di Debian una volta aggiunte dette istruzioni lo script di avvio del
servizio resta \texttt{/etc/init.d/slapd}, che quando rileva la presenza di
una direttiva \texttt{replica} nel file di configurazione si prende cura di
lanciare nell'ordine corretto sia \texttt{slapd} che \texttt{slurpd}, che
significa lanciare prima \texttt{slapd} e poi \texttt{slurpd} all'avvio e
bloccare prima \texttt{slurpd} e poi \texttt{slapd} allo stop.

La configurazione dei secondari deve ovviamente indicare al demone
\texttt{slapd} che gira su di essi il loro stato di \textit{slave}, in modo
che le richieste di modifica dei dati che dovessero pervenire per la parte di
albero replicata vengano reinviate al primario, così che la propagazione delle
stesse possa avvenire sempre in maniera unidirezionale dal primario al
secondario. Questo viene eseguito con la direttiva
\index{OpenLDAP!direttiva~server!\texttt{updateref}} \texttt{updateref} che
prende come argomento la URL del primario che il secondario deve restituire
alle richieste di scrittura.

Inoltre occorre segnalare a \texttt{slapd} il suo stato di secondario e quale
utente è usato per ricevere i relativi dati; questo si fa tramite la direttiva
\index{OpenLDAP!direttiva~server!\texttt{updatedn}} \texttt{updatedn} che deve
corrispondere esattamente all'utente specificato nella direttiva
\texttt{replica} usata nel primario.  Un esempio delle direttive da inserire
nel file \texttt{slapd.conf} del secondario, corrispondenti alle precedenti
viste per il primario, è allora il seguente:
\begin{FileExample}[label=slapd.conf]
updatedn   cn=replicatore,dc=truelite,dc=it
updateref  uri=ldaps://master.truelite.it:636
\end{FileExample}
e si ricordi che l'utente qui specificato deve avere privilegi sufficienti a
poter scrivere i dati.

Si tenga presente infine che se come negli esempi \texttt{slurpd} necessita di
collegarsi via SSL ai vari secondari per la trasmissione delle modifiche,
occorrerà anche aver definito opportunamente in \texttt{ldap.conf} le
direttive illustrate in sez.~\ref{sec:ldap_SSL} per indicare il certificato
della Certification Authority. Si tenga inoltre presente che qualora si siano
fatti degli errori o sia caduta la rete, per cui \texttt{slurpd} non riesce a
contattare il server secondario, le modifiche fatte al primario restano
comunque memorizzate nel giornale di replicazione, e verranno applicate
automaticamente una volta ristabilita la connessione.

La caratteristica della replicazione effettuata con \texttt{slurpd} è che
quest'ultimo trasmette solo le modifiche effettuate sul server primario,
perché il meccanismo funzioni occorre allora che prima dell'avvio della
replicazione il secondario sia sincronizzato col primario. Se si è configurato
il sistema per eseguire la replicazione fin dall'inizio e si è creato il
database da zero non ci sono problemi, altrimenti si avranno degli errori
tutte le volte che \texttt{slurpd} si trova ad eseguire operazioni facenti
riferimento a sezioni di albero, dati o attributi inesistenti sul
secondario. In tal caso quello che accade è che \texttt{slurpd} genera dei
file \texttt{.rej} contenenti le modifiche che sono state
\textsl{rigettate},\footnote{sempre sotto \texttt{/var/spool/slurpd/replica/},
  almeno per Debian.} così che sia possibile effettuare un inserimento manuale
una volta corrette le inconsistenze.

Quello della sincronizzazione iniziale è il maggior limite del meccanismo
illustrato, infatti il caso più comune è quello in cui si vogliono replicare i
dati di un server già presente.  Questo vuol dire che prima di poter
utilizzare il meccanismo occorrerà caricare sul secondario gli stessi dati del
primario. L'operazione di per sé è relativamente semplice, in quanto basta
fermare il primario, eseguire un dump dei dati con \texttt{slapcat} e caricare
quest'ultimo sul secondario con \texttt{slapadd}. Dove possono sorgere
problemi è quando si è eseguita una replica parziale, e ci si trova con delle
inconsistenze di dati, pertanto anche la precedente operazione deve essere
fatta con il primario fermo, in modo da essere sicuri che il secondario abbia
gli stessi dati del primario.

Uno degli errori più comuni è quello in cui si vuole aggiungere un nuovo ramo
dell'albero, e si crea detto ramo \textsl{prima} di aver impostato la sua
replicazione. In tal caso quello che accade è che le successive immissioni dei
dati falliranno, in quanto sul secondario non esiste la radice del nuovo
ramo. Inoltre per il funzionamento è cruciale il corretto ordinamento delle
operazioni ed il fatto che non si perda per troppo tempo la connessione fra i
server, altrimenti le differenze possono crescere oltre il limite in cui
\texttt{slurpd} è in grado di gestirle.

Inoltre tutte le volte che per un qualche motivo la sincronizzazione fallisce,
le differenze devono essere riapplicate manualmente con la procedura
descritta; in casi come questo diventa molto utile conoscere il formato dei
dati del giornale di replicazione, e del file \texttt{replog.status} che viene
utilizzato da \texttt{slurpd} per indicare lo stato delle operazioni di
replicazione. Questo è sostanzialmente, a parte alcune estensioni, lo stesso
formato adottato per i file usati con il comando \texttt{ldapadd} per eseguire
modifiche ad un albero LDAP, ed è descritto in una specifica pagina di
manuale, accessibile con \texttt{man slapd.replog}.


\subsection{La replicazione con \textit{syncrepl}}
\label{sec:ldap_replication_syncrepl}

Date le molteplici problematiche che presenta l'uso di \texttt{slurpd} a
partire dalla versione 2.3 di \textit{OpenLDAP} è stato introdotto un nuovo
meccanismo per gestire la replicazione denominato \textit{syncrepl}. Il
meccanismo è basato sull'utilizzo di uno specifico protocollo di
sincronizzazione,\footnote{il meccanismo è comunque realizzato in forma
  generica e può essere esteso ad altri protocolli qualora questi venissero
  ideati.} denominato \itindex{LDAP Content Synchronization Protocol}
\textit{LDAP Content Synchronization Protocol} e standardizzato
nell'\href{http://www.ietf.org/rfc/rfc4533.txt}{RFC~4533}, che consente di
estendere opportunamente le richieste di ricerche per farsi fornire i
cambiamenti apportati o presenti su un ramo di albero, così da poter mantenere
la propria copia in uno stato coerente, in maniera indipendente dalle
differenze correnti al momento della sincronizzazione.

\begin{figure}[!htb]
  \centering \includegraphics[width=10cm]{images/syncrepl_mech}
  \caption{Il funzionamento della replicazione con \textit{syncrepl}.}
  \label{fig:ldap_replication_syncrepl}
\end{figure}

Questo protocollo consente in sostanza di effettuare delle ricerche speciali
che trasmettano soltanto le differenze presenti fra due versioni dello stesso
albero, fornendo così una grande flessibilità nelle modalità con cui si può
effettuare la replicazione,\footnote{si tratta comunque di ricerche LDAP, che
  supportano quindi l'indicazione di filtri, profondità, attributi da
  restituire, ecc. come illustrato in sez.~\ref{sec:ldap_query_mechanism}.}
compresa la possibilità di alternative al modello classico di un server
\textit{master} che pilota il contenuto di vari server \textit{slave}, con la
possibilità di avere sistemi con più server \textit{master} o server in cui i
ruoli di \textit{master} o \textit{slave} vengono mescolati. Per questo motivo
nella documentazione di \textit{OpenLDAP} è stata introdotta una terminologia
alternativa, in cui si indicano come \textit{provider} i server che forniscono
le informazioni di replicazione, mentre si chiamano \textit{consumer} quelli
che le ricevono, ed un server può agire sia da \textit{consumer} verso un
server, che da \textit{provider} per un altro.

Il protocollo prevede che sia sempre il \textit{consumer} a collegarsi al
\textit{provider} eseguendo poi la sincronizzazione secondo lo schema
illustrato in fig.~\ref{fig:ldap_replication_syncrepl}. Questo ha un preciso
significato dal punto di vista dei protocolli di rete, è cioè il
\textit{consumer} che deve iniziare la connessione verso il \textit{producer},
ed un eventuale firewall interposto fra i due deve consentire questa
comunicazione, questo può talvolta essere un problema, come vedremo in
sez.~\ref{sec:advanced-replication}.

Una volta effettuato il collegamento il \textit{consumer} può fornire nelle
richieste un opportuno \textit{cookie} di sincronizzazione che indica lo stato
del suo database (in sostanza quando è stata fatta l'ultima sincronizzazione),
in modo che il \textit{producer} possa fornire tutte le modifiche effettuate
in seguito. Se non viene inviato nessun \textit{cookie} il primario invierà
tutto il contenuto del database, cosa che può portare ad un carico pesante in
caso di database molto grandi; in tal caso è opportuno effettuare un dump e
ripristinarlo come per \texttt{slurpd}, il vantaggio è che lo si può fare
senza spegnere il primario, perché eventuali modifiche successive verranno
sincronizzate automaticamente.

É compito del primario mantenere le informazioni di sincronizzazione ed
aggiornare ad ogni modifica il cosiddetto \textit{Change Sequence Number} (o
CSN) dell'albero, una sorta di marca temporale che consente al primario di
identificare quali sono le informazioni da inviare al secondario nella fase di
sincronizzazione.\footnote{esistono in realtà due diverse modalità di
  sincronizzazione, usate alternativamente o insieme a seconda dei casi: la
  cosiddetta \textit{delete phase} in cui si trasmettono DN ed
  \texttt{entryUUID} delle voci cancellate e la \textit{present phase} in cui
  si trasmettono integralmente i dati modificati e solo DN ed
  \texttt{entryUUID} di quelli presenti (da cui si desume quali sono quelli
  cancellati).}  Alla fine di ciascuna fase di sincronizzazione viene inviato
al secondario anche il CSN corrente, così che in seguito questo non debba
ripartire da zero.

Nel suo uso più elementare il meccanismo di \textit{syncrepl} fornisce due
diverse modalità di eseguire la sincronizzazione. La prima modalità,
denominata \textit{refreshOnly}, prevede connessioni periodiche da parte del
\textit{consumer} verso il \textit{provider} per ottenere le differenze
intercorse.  La seconda modalità, denominata \textit{refreshAndPersist},
prevede che il \textit{consumer} esegua una sincronizzazione iniziale ma poi
resti connesso e che poi sia il \textit{provider} ad inviare le ulteriori
modifiche quando queste vengono effettuate, utilizzando la connessione rimasta
attiva.

In entrambi i casi non è più necessaria la presenza di un demone esterno e
tutte le operazioni vengono eseguite direttamente da \texttt{slapd}, che deve
essere opportunamente configurato.  Quanto necessario per utilizzare la
replicazione sul \textit{provider} viene realizzato con un apposito
\textit{overlay}, \texttt{syncprov}, il cui compito è fornire il supporto per
l'uso dell'\textit{LDAP Content Synchronization Protocol}. Questo
\textit{overlay} può essere usato in combinazione con un qualunque database
che supporti l'uso degli attributi speciali \texttt{entryUUID} e
\texttt{entryCSN},\footnote{sia \texttt{hdb} che \texttt{mdb} li supportano,
  il loro uso deve anche essere abilitato con l'uso della direttiva
  \texttt{lastmod on}, ma in genere non è necessaria una configurazione
  esplicita dato che questo è il valore di default.} che sono quelli
consentono rispettivamente di identificare in maniera univoca ogni voce e di
tener conto di quando è stata modificata.

Inoltre siccome tutte le ricerche utilizzate nel protocollo di
sincronizzazione fanno ampio uso dei dati memorizzati nei due attributi
citati, per avere buone prestazioni è sempre opportuno eseguire una
indicizzazione di questi attributi aggiungendo alle direttive di
indicizzazione del database su cui si vuole utilizzare \textit{syncrepl} una
riga del tipo:
\begin{Example}
index entryCSN,entryUUID eq
\end{Example}

L'\textit{overlay} \texttt{syncprov} mantiene inoltre un'ulteriore attributo
speciale, \texttt{contextCSN}, aggiunto alla radice del database, che indica
lo stato attuale dell'albero e consente di tracciare le differenze introdotte
e replicare solo le modifiche effettuate successivamente al valore
corrente. Questo comporta che occorre stare molto attenti a non creare sulla
replica un database iniziale, dal quale poi far partire la replicazione, con
un valore già assegnato per questo attributo. Infatti se detto valore è
successivo a quello dell'\texttt{entryCSN} di una voce, questa non verrà presa
in considerazione essendo considerata già presente, e non sarà
replicata.

\index{OpenLDAP!direttiva~server!\texttt{syncprov-checkpoint}}
\index{OpenLDAP!direttiva~server!\texttt{syncprov-sessionlog}}
\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Direttiva} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{syncprov-checkpoint} & configura i salvataggi periodici delle 
                                   informazioni di modifica del database;
                                   richiede due argomenti numerici indicanti
                                   rispettivamente ogni quante operazioni ed
                                   ogni quanti minuti operare il salvataggio 
                                   (se non specificata non viene effettuato
                                   nessun salvataggio periodico).\\
    \texttt{syncprov-sessionlog} & indica la lunghezza del registro delle
                                   operazioni di scrittura da mantenere in
                                   memoria; richiede come argomento il numero
                                   di operazioni.\\ 
%    \texttt{syncprov-nopresent} & .\\
%    \texttt{syncprov-reloadhint}& .\\
%    \texttt{} & .\\
    \hline 
  \end{tabular}
  \caption{Principali direttive utilizzabili con l'\textit{overlay}
    \texttt{syncprov}.}
  \label{tab:syncprov_directives}
\end{table}

Per evitare operazioni aggiuntive su disco (in particolare il blocco sul
database di \textit{backend} necessario per un aggiornamento affidabile)
questo attributo viene letto all'avvio di \texttt{slapd} e mantenuto in
memoria. Di default il valore viene aggiornato solo alla chiusura del server,
ma l'uso della direttiva \texttt{syncprov-checkpoint} consente di richiedere
salvataggi periodici dello stato; la sua sintassi, come quella delle altre
principali direttive fornite dall'\textit{overlay} \texttt{syncprov} sono
riassunte in tab.~\ref{tab:syncprov_directives}.

Riassumendo, per configurare \texttt{slapd} per fare da \textit{provider} ed
agire come \textit{master} per la replicazione occorrerà anzitutto richiedere
il caricamento del modulo per l'\textit{overlay} \texttt{syncprov} nella
sezione generale del file di configurazione, e poi abilitarne l'uso e
configurarlo per i vari database di cui si vuole effettuare la replicazione;
in sostanza la configurazione dovrà contenere delle direttive analoghe alle
seguenti:
\begin{FileExample}[label=slapd.conf]
...
moduleload syncprov
...
...
# provider DB
database hdb
suffix          "dc=truelite,dc=it"
lastmod on
...
index           entryCSN,entryUUID eq
overlay syncprov
syncprov-checkpoint  100  10
syncprov-sessionlog  100
...
\end{FileExample}

Per la configurazione di un server secondario come \textit{consumer} invece
non serve nessun \textit{overlay} ma la funzionalità viene gestita
direttamente da \texttt{slapd} tramite la direttiva
\index{OpenLDAP!direttiva~server!\texttt{syncrepl}} \texttt{syncrepl}, da
dichiarare per ogni database viene che si vuole gestire come replica. La
direttiva è simile alla analoga \texttt{replica} usata con \texttt{slurpd}, e
prevede l'uso di una serie di argomenti da indicare nella stessa forma
\texttt{nome=valore}, alcuni dei quali sono identici ed hanno lo stesso
significato di quelli usati per \texttt{replica}.

In tab.~\ref{tab:ldap_syncrepl_argument} si sono riportati gli argomenti
principali, ma la direttiva è complessa, in quanto consente di eseguire la
replicazione in modalità diverse con configurazioni molto sofisticate (su cui
torneremo in sez.~\ref{sec:advanced-replication}) per cui vedremo qui soltanto
quelli relativi ad una configurazione di base in cui la si utilizza per
mantenere sincronizzato un albero secondario in maniera analoga a come si fa
con \texttt{slurpd}.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Argomento} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{rid}        & indica il numero identificativo (composto da tre cifre
                          decimali) associato all'istanza di replicazione; deve
                          essere specificato ad un valore diverso per ogni
                          utilizzo della direttiva
                          \texttt{syncrepl}.\footnotemark\\  
    \texttt{provider}   & indica la URI del \textit{provider}, con la stessa
                          sintassi illustrata in tab.~\ref{tab:ldap_URL}; deve
                          essere sempre specificato.\\
%    \texttt{starttls}   & indica, in caso do.\\
    \texttt{type}       & indica la modalità di sincronizzazione da usare: può
                          assumere solo i due valori \texttt{refreshOnly} o
                          \texttt{refreshAndPersist}.\\
    \texttt{retry}      & controlla i tentativi di riconnessione che
                          devono essere eseguiti qualora la replicazione
                          fallisca; prevede almeno una coppia di argomenti
                          numerici indicanti rispettivamente l'intervallo fra un
                          tentativo e l'altro (in secondi) ed il numero di
                          ripetizioni (il carattere \texttt{+} indica un numero
                          infinito), possono essere indicate più coppie di
                          valori (in genere con intervalli crescenti) per
                          specificare come continuare le riconnessioni una
                          volta esauriti i tentativi indicati in una coppia
                          precedente (il default è ripetere indefinitamente le
                          riconnessioni ogni ora).\\  
    \texttt{searchbase} & indica la base della sezione di albero che si vuole
                          replicare (è la base delle ricerche usate per il
                          protocollo di sincronizzazione); deve essere sempre
                          specificato.\\
    \texttt{filter}     & indica un eventuale filtro di ricerca che consente
                          di selezionare quali dati si vogliono replicare, il
                          default è \texttt{(objectclass=*)} per indicare una
                          ricerca generica.\\ 
    \texttt{scope}      & indica la profondità della ricerca, il default è
                          \texttt{sub}.\\ 
    \texttt{schemachecking} & indica se è attivo il controllo di consistenza
                          dei dati, di default è \texttt{off} dato che in
                          caso di replicazione parziale si possono avere
                          inconsistenze temporanee negli attributi.\\
    \texttt{binddn}     & indica (come DN) l'utente con il quale effettuare il
                          collegamento al \textit{producer}; ci si accerti che
                          questo abbia privilegi sufficienti per poter ottenere
                          i dati.\\
    \texttt{bindmethod} & indica la modalità con cui effettuare il
                          collegamento al \textit{producer}, può assumere i
                          valori \texttt{simple} o \texttt{sasl}.\\
    \texttt{credentials}& indica la password dell'utente con cui effettuare il
                          collegamento.\\
    \texttt{attrs}      & indica gli attributi da replicare, se non indicato
                          verranno presi tutti gli attributi definiti (il
                          valore di default è ``\texttt{*,+}'' che indica sia
                          gli attributi ordinari che quelli interni).\\
    \hline 
  \end{tabular}
  \caption{Principali argomenti della direttiva \texttt{syncrepl}.} 
  \label{tab:ldap_syncrepl_argument}
\end{table}

\footnotetext{essendo possibili replicazioni \textit{multi-master} si possono
  avere nella stessa configurazione più istanze della direttiva
  \texttt{syncrepl} per tutti quei casi in cui il \textit{consumer} ottiene i
  dati da più \textit{provider}; ciascuna di queste deve avere un diverso
  \texttt{rid}.}

Qualunque sia la modalità di replicazione che si vuole attivare, è comunque
necessario fornire a \texttt{syncrepl} alcuni argomenti; il primo di questo è
\texttt{rid}, un identificatore di tre cifre decimali che deve essere
associato a ciascuna dichiarazione della direttiva. Si può scegliere un valore
qualsiasi, purché univoco, in modo da distinguere, qualora come possibile se
ne usi più di una, le diverse istanze della replicazione.

L'argomento \texttt{provider} deve invece indicare, nella forma di una URI di
LDAP (la stessa usata per la direttiva \texttt{URI} di \texttt{ldap.conf})
quale è il server che deve essere usato come \textit{provider}. Se necessario,
ed in genere lo è sempre, si dovranno poi specificare con \texttt{binddn},
\texttt{bindmethod} e \texttt{credentials} le modalità con cui ci si dovrà
collegare a quest'ultimo. Si ricordi infatti che la replicazione con
\textit{syncrepl} avviene nella forma di una interrogazione LDAP, e dato che
sarà necessario accedere a tutti i dati del server che fa da
\textit{provider}, occorrerà utilizzare per l'accesso un utente dello stesso
che abbia sufficienti privilegi di accesso (almeno la lettura) per tutto
quanto si vuole replicare.

Si tenga presente inoltre che la trasmissione dei dati viene fatta in chiaro,
pertanto è comunque opportuno usare una connessione cifrata con SSL. In questo
caso occorre (nelle versioni più recenti del server, nelle precedenti venivano
usati i valori in \texttt{ldap.conf}) specificare esplicitamente i parametri
di configurazione per la connessione in maniera con altrettanti argomenti
elencati in tab.~\ref{tab:ldap_syncrepl_ssl_argument}, che ricalcano gli
omonimi di \texttt{ldap.conf} visti in sez.~\ref{sec:ldap_SSL}.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Argomento} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{tls\_cert}   & analogo di \texttt{TLS\_CERT}, indica il
                           file che contiene il certificato.\\  
    \texttt{tls\_key}    & analogo di \texttt{TLS\_KEY}, indica il
                           file che contiene la chiave.\\  
    \texttt{tls\_cacert} & analogo di \texttt{TLS\_CACERT}, indica il
                           file che contiene il certificato della CA.\\  
    \texttt{tls\_reqcert}& analogo di \texttt{TLS\_REQCERT}, indica il
                           livello di controllo che si richiede per i
                           certificati, usa i valori di
                           tab.~\ref{tab:ldap_ssl_verify_values}.\\  
%    \texttt{}        & \\  
    \hline 
  \end{tabular}
  \caption{Argomenti per SSL della direttiva \texttt{syncrepl}.} 
  \label{tab:ldap_syncrepl_ssl_argument}
\end{table}

Il terzo argomento necessario è \texttt{searchbase} che indica la base delle
richieste dei dati che verranno effettuate sul \textit{provider}, a questo si
possono aggiungere come ulteriori parametri per la ricerca gli argomenti
\texttt{scope}, \texttt{filter}, \texttt{attrs}, che indicano rispettivamente
la profondità della stessa, un eventuale filtro (con la sintassi vista in
sez.~\ref{sec:ldap_search}) e la lista, separata da virgole, degli attributi
richiesti. Questi possono non essere specificati, nel qual caso varranno i
valori di default, che comportano una ricerca generica su tutto l'albero e per
qualunque attributo al di sotto di \texttt{searchbase}.

Infine è sempre opportuno specificare le modalità con cui effettuare la
replicazione tramite l'argomento \texttt{type}; questo può assumere uno dei
due valori \texttt{refreshOnly} e \texttt{refreshAndPersist}, nel primo caso è
compito del \textit{consumer} ricontattare il \textit{provider} ad intervalli
regolari per farsi consegnare gli aggiornamenti (il default è un giorno ma può
essere modificato con l'argomento \texttt{interval}), nel secondo caso una
volta stabilita la connessione iniziale da parte del \textit{consumer} è
compito del \textit{provider} fornire i successivi aggiornamenti.

Pertanto un esempio di una possibile configurazione di \texttt{slapd} per
effettuare la replicazione sul server secondario (cioè sul \textit{consumer})
facendo riferimento al \textit{provider} configurato in precedenza, potrebbe
essere la seguente:
\begin{FileExample}[label=slapd.conf]
rootdn cn=admin_cons,dc=truelite,dc=it
index entryCSN,entryUUID eq

syncrepl rid=123
    provider=ldaps://master.truelite.it
    type=refreshAndPersist
    searchbase="dc=truelite,dc=it"
    filter="(objectClass=organizationalPerson)"
    scope=sub
    retry="60 10 300 3 3600 +"
    schemachecking=off
    bindmethod=simple
    binddn="cn=repl_user_prov,dc=truelite,dc=it"
    credentials=password_segretissima
    tls_cacert=/etc/ssl/certs/ca-cert.pem
    tls_reqcert=never
\end{FileExample}

Si tenga presente che la direttiva \texttt{syncrepl} consente anche delle
repliche parziali, con una selezione di attributi o l'uso di una
profondità. Quello che non è banale ottenere è la replicazione di singole
sezioni di un albero in quanto la direttiva \texttt{searchbase} può essere
usata una sola volta. Si potrebbe pensare di ottenere il risultato usando
istanze multiple della direttiva per ciascun ramo di albero che si vuole
replicare, ma neanche questo funziona in quanto un \textit{consumer} può
effettuare una sola sessione di replicazione nei confronti dello stesso
\textit{provider}.\footnote{questo perché come accennato alla fine di ogni
  replicazione viene aggiornato il valore del \texttt{contextCSN} che è unico
  per ogni \textit{provider}, per cui una seconda richiesta allo stesso
  \textit{provider} troverebbe un valore già aggiornato e non verrebbe
  eseguita.}

In questo caso possono venire in aiuto i filtri estesi applicati al DN, con la
regola di corrispondenza \texttt{dnSubtreeMatch}, pertanto se ad esempio si
vogliono replicare solo due sezioni dell'albero precedente, invece che solo
gli oggetti di tipo \texttt{organizationalPerson}, si potrà usare una
configurazione come la seguente:
\begin{FileExample}[label=slapd.conf]
rootdn cn=admin_cons,dc=truelite,dc=it
index entryCSN,entryUUID eq

syncrepl rid=123
    provider=ldaps://master.truelite.it
    type=refreshAndPersist
    searchbase="dc=truelite,dc=it"
    filter="(|(entrydn:dnSubtreeMatch:=ou=People,dc=truelite,dc=it)
       (entrydn:dnSubtreeMatch:=ou=group,dc=truelite,dc=it))"
    scope=sub
    schemachecking=off
    bindmethod=simple
    binddn="cn=repl_user_prov,dc=truelite,dc=it"
    credentials=password_segretissima
    tls_cacert=/etc/ssl/certs/ca-cert.pem
    tls_reqcert=never
\end{FileExample}

Infine si tenga presente che un database replicato è, come naturale,
accessibile in sola lettura, per questo motivo ogni tentativo di scrittura
normalmente viene rifiutato, si può però indicare al server di fornire un
\textit{referral} al master utilizzando la direttiva \texttt{updateref} già
vista in sez.~\ref{sec:ldap_replication_slurpd}. In questo caso non si deve
impostare \texttt{updatedn}, mentre \texttt{updateref} deve essere inserita
\textsl{dopo} la direttiva \texttt{syncrepl} per indicare come raggiungere il
master, cioè con qualcosa del tipo:
\begin{FileExample}[label=slapd.conf]
syncrepl rid=123
    provider=ldaps://master.truelite.it
    ...

updateref ldaps://master.truelite.it
\end{FileExample}



\subsection{Utilizzo avanzato di \textit{syncrepl}}
\label{sec:advanced-replication}

Nella precedente sezione abbiamo esaminato l'uso più elementare del meccanismo
di \textit{syncrepl} per realizzare una replicazione dei dati di un albero
LDAP, in cui il \textit{consumer} si collega al \textit{provider}.  Benché
questa replicazione possa essere effettuata sia nelle due modalità
\textit{refreshOnly} e \textit{refreshAndPersist}, in entrambi i casi deve
comunque essere il server che fa da \textit{consumer} a contattare
inizialmente il server che fa da \textit{provider}. Come accennato questo
comporta un problema quando fra i due server è presente un firewall che non
consente questo tipo di connessioni, come può avvenire quando il
\textit{consumer} è su una rete esterna ed il \textit{provider} su una rete
interna.

\itindbeg{proxy~replication}

Con la replicazione classica effettuata con \texttt{slurpd} questo problema
non si sussisteva in quanto era comunque il server \textit{master} a
contattare lo \textit{slave} inviando i relativi cambiamenti, ma con l'uso di
\textit{syncrepl} appena illustrato questo non avviene e ci si trova nella
necessità, in caso di presenza di un firewall di protezione, di dover aprire
un accesso dall'esterno all'interno, cosa che non è detto sia sempre
compatibile con le politiche di sicurezza.

Dato che a partire dalla versione 2.4 di \textit{OpenLDAP} il supporto per
\texttt{slurpd} è stato eliminato, per ovviare a questo problema è possibile
utilizzare una diversa configurazione, chiamata \textit{proxy replication}, in
cui la replicazione avviene sempre a partire da connessioni originanti dal
server \textit{master}. In questo caso il risultato può essere ottenuto
utilizzando sul server \textit{master} una seconda istanza dell'albero che si
appoggi però al \textit{backend} \texttt{ldap}. Sarà questa ad agire come
\textit{consumer} rispetto all'istanza principale ottenendo gli aggiornamenti
tramite \textit{syncrepl}; questi poi verranno inviati al server
\textit{slave} secondo lo schema illustrato in
fig.~\ref{fig:ldap_proxy_replication} utilizzando le funzionalità di
\textit{proxy} fornite dal \textit{backend} \texttt{ldap}.

\begin{figure}[!htb]
  \centering \includegraphics[width=10cm]{images/proxy_replication}
  \caption{Il funzionamento della \textit{proxy replication}.}
  \label{fig:ldap_proxy_replication}
\end{figure}

In questo caso primo passo è quello di abilitare sul server \textit{master}
sia il modulo di gestione di \textit{syncrepl} che quello del \textit{backend}
LDAP che utilizzeremo per fare da \textit{proxy}, questo si fa aggiungendo con
le direttive:
\begin{Example}
moduleload     syncrepl
moduleload     back_ldap
\end{Example}
alla sezione generale del server \textit{master}.

Il secondo passo è abilitare un ulteriore database che usi il \textit{backend}
\texttt{ldap} per fare da \textit{proxy}. Questo database dovrà avere lo
stesso suffisso usato per il database effettivo, ed accedervi con l'utente di
amministrazione. Inoltre occorrerà configurarlo come \textit{consumer} per
\textit{syncrepl} in maniera analoga a come fatto in
sez.~\ref{sec:ldap_replication_syncrepl} per un server \textit{slave}
distinto, le direttive per fare tutto ciò sono le seguenti:
\begin{FileExample}[label=slapd.conf]
database        ldap
hidden          on
lastmod         on
suffix          "dc=truelite,dc=it"
restrict        all

# how to access to slave (where we proxy things)
# here must use slave user/base/credentials
rootdn          "cn=admin,dc=truelite,dc=it"
uri             ldaps://slave.truelite.it
acl-bind        bindmethod=simple
                binddn="cn=admin,dc=truelite,dc=it"
                credentials=slave_secret

# how we get thing from the syncrepl overlay
# here must use master user/base/credentials
overlay         syncprov
syncrepl        rid=001
                provider=ldap://127.0.0.1
                binddn="cn=admin,dc=truelite,dc=it"
                bindmethod=simple
                credentials=master_secret
                searchbase="dc=truelite,dc=it"
                type=refreshAndPersist
                retry="5 5 300 5"
\end{FileExample}

Fatto questo sarà sufficiente rendere edotto il lato \textit{slave} di
comportarsi come replica, in questo caso infatti non è il server
\textit{slave} a dover fare da \textit{consumer} ma l'istanza di
\textit{proxy} che gira sul server \textit{master} e che invia le modifiche
allo \textit{slave}. Pertanto, in maniera identica a come si faceva con
\texttt{slurpd} dato che le operazioni svolte su di esso sono sostanzialmente
le stesse, sul server \textit{slave} sarà sufficiente aggiungere le direttive:
\begin{FileExample}[label=slapd.conf]
updatedn   cn=admin,dc=truelite,dc=it
updateref  uri=ldaps://master.truelite.it:636
\end{FileExample}

Si tenga presente però che questa configurazione, se da una parte risolve il
problema di inviare i dati a partire dal \textit{master}, dall'altra perde il
vantaggio della garanzia del mantenimento automatico della coerenza dei dati
dello \textit{slave} che si aveva quando \textit{syncrepl} viene eseguita
dallo stesso.

In questo caso infatti è l'istanza del \textit{proxy} che gira sul
\textit{master} ad accorgersi dei cambiamenti e a spingerli sullo
\textit{slave}, essa però non ha modo di sapere se quest'ultimo, per un
qualche motivo (perdita di dati, cancellazione accidentale sullo slave,
richiesta di nuovi dati da replicare da parte del master, ecc.) non è più
sincronizzato, in quanto il controllo viene effettuato solo sulla base del
valore del \texttt{contextCSN} presente sullo \textit{slave} e se questo è
coincidente con quello del \textit{master} i dati non vengono più reinviati.

Questo comporta alcune conseguenze, ad esempio si effettua una replica
parziale, ed in un secondo tempo si decide di aggiungere altri dati (ad
esempio un altro ramo di albero), essendo il \texttt{contextCSN} sullo slave
aggiornato dalla replica iniziale, i dati aggiuntivi che si vorrebbero
replicare non saranno inviati.  Allo stesso modo se per un qualche motivo lo
\textit{slave} perde dei dati questi non saranno ritrasmessi e se il relativo
database diventa inconsistente l'intera replicazione potrebbe fermarsi.

Per ovviare a questo tipo di problemi la soluzione più semplice, ancorché
costosa in termini di disservizio, è quella di riportare il database dello
\textit{slave} al contenuto iniziale della radice e dell'utente di
replicazione, cancellando al contempo l'attributo \texttt{contextCSN} della
radice, in questo modo la replicazione verrà rieseguita dal principio.


\itindend{proxy~replication}

\chapter{L'integrazione con LDAP}
\label{cha:integration}


\section{La gestione centralizzata di utenti e gruppi}
\label{sec:ldap_user_management}

Affronteremo in questa sezione le tematiche relative all'utilizzo di LDAP per
la gestione centralizzata di utenti e gruppi per sistemi Unix. In realtà
tratteremo più genericamente le modalità con cui è possibile gestire le
informazioni di autenticazione (attraverso l'uso di PAM) e tutte le altre
informazioni che di norma sono gestite dal \textit{Name Service Switch}
(password, hosts, gruppi, ecc.) appoggiandosi ad un server LDAP.


\subsection{La creazione della infrastruttura dei dati}
\label{sec:ldap_userdata_management}

Per poter effettuare la gestione di utenti e gruppi di un sistema Unix su LDAP
è necessario disporre delle \textit{objectclass} che definiscono gli attributi
necessari a mantenere tutte le informazioni ad essi relative, le stesse che
nella gestione classica stanno nei file \texttt{/etc/passwd},
\texttt{/etc/shadow}, \texttt{/etc/group}, ecc.\footnote{per una trattazione
  dettagliata dell'argomento si consulti sez.~4.3.3 di \cite{AGL}.}

Queste informazioni sono state standardizzate da un RFC (per essere precisi
l'\href{http://www.ietf.org/rfc/rfc2307.txt}{RFC~2307}) e per quanto riguarda
\texttt{slapd} sono definite dalle direttive nel file \texttt{nis.schema}. In
genere tutte le \textit{objectclass} necessarie (comprese quelle per le altre
informazioni del NSS) vengono incluse con la configurazione di default di
\texttt{slapd.conf}, per cui normalmente non è necessaria nessuna
riconfigurazione del server.

Per la gestione degli utenti le \textit{objectclass} in questione sono
\objcl{posixAccount}, che contiene i dati classici che normalmente vengono
mantenuti in \texttt{/etc/passwd} e \objcl{shadowAccount}, che contiene i dati
relativi alle estensioni delle \textit{Shadow password}, usualmente mantenuti
in \texttt{/etc/shadow}. Nelle due sezioni di
tab.~\ref{tab:ldap_user_attributes} si sono riportati, nell'ordine, i relativi
attributi, con l'indicazione dell'informazione in essi contenuta.

Oltre alle informazioni relative agli utenti, occorre ovviamente poter gestire
anche quelle relative ai gruppi, per questo viene utilizzata la
\textit{objectclass} \objcl{posixGroup} (sempre definita in
\texttt{nis.schema}), che contiene i dati che classicamente vengono mantenuti
in \texttt{/etc/group};\footnote{in questo caso vengono mantenute solo le
  informazioni di base di \texttt{/etc/group}, non le estensioni relative a
  \texttt{/etc/gshadow}.}  in tab.~\ref{tab:ldap_group_attributes} si sono
riportati i vari attributi definiti in detta \textit{objectclass} assieme al
relativo significato.


\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Attributo} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{uid}           & nome utente, equivalente del nome di login, è
                             l'attributo principale usato anche nei DN che
                             identificano le voci degli utenti; equivalente al
                             primo campo di \texttt{/etc/passwd}.\\
    \texttt{uidNumber}     & valore numerico dell'\textit{user-id}
                             dell'utente; equivalente al terzo campo di
                             \texttt{/etc/passwd}.\\ 
    \texttt{gidNumber}     & valore numerico del \textit{group-id} del gruppo
                             primario dell'utente; equivalente al
                             quarto campo di \texttt{/etc/passwd}.\\
    \texttt{gecos}         & informazioni varie sull'utente; equivalente al
                             quinto campo di \texttt{/etc/passwd}.\\
    \texttt{homeDirectory} & home directory dell'utente; equivalente al
                             sesto campo di \texttt{/etc/passwd}.\\
    \texttt{loginShell}    & shell di login dell'utente; equivalente al
                             settimo campo di \texttt{/etc/passwd}.\\
    \texttt{userPassword}  & password cifrata dell'utente.\footnotemark\\
    \hline
    \texttt{shadowLastChange}& numero del giorno, contato a partire dal 1
                             gennaio 1970, in cui la password è stata cambiata
                             l'ultima volta; equivalente al terzo campo di
                             \texttt{/etc/shadow}.\\
    \texttt{shadowMin}     & numero di giorni dall'ultimo cambiamento prima
                             dei quali la password non può essere cambiata di
                             nuovo; equivalente al quarto campo di
                             \texttt{/etc/shadow}.\\
    \texttt{shadowMax}     & numero di giorni dall'ultimo cambiamento,
                             dopo i quali la password scade e deve essere
                             rinnovata; equivalente al quinto campo di
                             \texttt{/etc/shadow}.\\
    \texttt{shadowWarning} & numero di giorni prima della scadenza della 
                             password durante i quali l'utente viene avvertito;
                             equivalente al sesto campo di
                             \texttt{/etc/shadow}.\\  
    \texttt{shadowInactive}& numero di giorni dopo i quali, una volta scaduta
                             la password senza rinnovo, l'account viene
                             disabilitato; equivalente al settimo campo di
                             \texttt{/etc/shadow}.\\
    \texttt{shadowExpire}  & numero del giorno, contato dal 1 gennaio 1970, in
                             cui l'account viene disabilitato; equivalente 
                             all'ottavo campo di \texttt{/etc/shadow}.\\
    \texttt{shadowFlag}    & valore riservato, al momento non è utilizzato; 
                             equivalente al nono campo di
                             \texttt{/etc/shadow}.\\
%    \texttt{}& .\\
    \hline 
  \end{tabular}
  \caption{Gli attributi contenenti i dati degli utenti, definiti nelle
    \textit{objectclass} \texttt{posixAccount} e \texttt{shadowAccount}.}  
  \label{tab:ldap_user_attributes}
\end{table}

\footnotetext{si è riportato anche questo attributo, che essendo definito in
  maniera più generale non è specifico né di \texttt{posixAccount} né di
  \texttt{shadowAccount}, in quanto contiene una delle informazioni essenziali
  per la gestione degli utenti.}

Come per qualunque altro dato è possibile utilizzare un client LDAP generico
per inserire le informazioni relative ad utenti e gruppi direttamente
nell'albero, andando a modificare gli attributi elencati in
tab.~\ref{tab:ldap_user_attributes} e tab.~\ref{tab:ldap_group_attributes};
fare questa operazione manualmente è però un lavoro noioso e facilmente
soggetto ad errori (molti dati, come ad esempio gli identificativi, sono
correlati fra loro), per cui spesso si utilizzano dei programmi espressamente
dedicati a questo scopo, che semplificano il lavoro e consentono di ricavare
automaticamente le informazioni necessarie correlando i vari dati.

\begin{table}[!h!bt]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Attributo} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{cn}            & nome del gruppo; equivalente al primo campo di
                             \texttt{/etc/group}.\\
    \texttt{gidNumber}     & valore numerico del \textit{group-id} del gruppo;
                             equivalente al terzo campo di
                             \texttt{/etc/group}.\\
    \texttt{memberUid}     & username di un utente del gruppo, viene ripetuto
                             per ciascun utente membro; equivalente ad un
                             nome della lista mantenuta nel quarto campo di
                             \texttt{/etc/group}.\\
    \texttt{userPassword}  & password cifrata del gruppo.\footnotemark\\
%    \texttt{}& .\\
    \hline 
  \end{tabular}
  \caption{Gli attributi contenenti i dati dei gruppi, definiti nella
    \textit{objectclass} \texttt{posixGroup}.}  
  \label{tab:ldap_group_attributes}
\end{table}

\footnotetext{anche in questo caso vale quanto detto per l'analogo attributo
  di \texttt{posixAccount}.}

Uno dei pacchetti usati più spesso è quello dei \texttt{migrationtools}, un
insieme di script che consentono sia di generare lo schema di
un'infrastruttura su cui inserire le informazioni tipiche del NSS, che di
migrare su LDAP i dati presenti nei vari file \texttt{/etc/passwd},
\texttt{/etc/shadow}, \texttt{/etc/hosts}, ecc.  Per ciascuno di questi file
gli script producono un corrispondente file \texttt{.ldif} contenente le
stesse informazioni, che poi potranno essere inserite direttamente sul server
LDAP con \texttt{ldapadd}.

Prima di poter utilizzare gli script di migrazione occorre specificare nel
loro file di configurazione (su Debian è accessibile sotto
\texttt{/etc/migrationtools/migrate\_common.ph})
\index{configurazione!\texttt{/etc/migrationtools/migrate\_common.ph}} le
impostazioni che indicano la sezione di albero in cui andranno inseriti i
dati.  Per far questo dovranno essere adattate al proprio caso le righe
seguenti:
\begin{FileExample}[label=migrate\_common.ph]
# Default DNS domain
$DEFAULT_MAIL_DOMAIN = "truelite.it";

# Default base 
$DEFAULT_BASE = "dc=truelite,dc=it";
\end{FileExample}
dopo di che il file \texttt{migrate\_common.ph} deve essere copiato in
\texttt{/usr/share/migrationtools/}, dove sono installati gli script, o essere
referenziato con un link simbolico.\footnote{il pacchetto Debian esegue questa
  installazione di default.} Per usare gli script di conversione ci si dovrà
porre in detta directory.

Il primo passo è sempre quello di generare l'infrastruttura di base, lo script
\texttt{migrate\_base.pl} permette di creare un file \texttt{base.ldif} che
contiene quanto necessario; il comando è:
\begin{Console}
$ \textbf{./migrate_base.pl > base.ldif}
\end{Console}
%$

In genere l'infrastruttura sui cui si mantengono i dati è costituita da una
serie di \texttt{organizationalUnit} che devono essere inserite nell'albero
per fare da radice delle varie sezioni al cui interno inseriremo i dati
relativi ai servizi NSS che possono essere spostati su LDAP. Un esempio di una
queste voci, estratto dal file \texttt{base.ldif} generato dal comando
precedente, è il seguente:
\begin{FileExample}[label=base.ldif]
...
dn: ou=Hosts,dc=truelite,dc=it
ou: Hosts
objectClass: top
objectClass: organizationalUnit
...
\end{FileExample}
che definisce una \texttt{organizationalUnit} per fare da radice alla sezione
di albero su cui poi verrà inserito l'elenco degli \textit{host} mantenuti su
LDAP che può essere aggiunto a quello di \texttt{/etc/hosts}.

Si tenga presente che alcune delle voci generate da \texttt{migrate\_base.pl}
possono essere superflue, inoltre sono previste delle voci anche per i dati di
NIS, che certamente non interessano in quanto esso verrà sostituito appunto da
LDAP.  Infine alcune voci possono essere duplicate, come la base dell'albero,
con problemi di funzionamento del comando di inserimento a meno di non
invocare \texttt{ldapadd} con l'opzione \texttt{-c}. Per questo conviene
comunque modificare opportunamente file \texttt{base.ldif} prodotto dal
comando, per adattarlo ai propri scopi. Dopo di che si potranno inserire le
nuove voci nell'elenco con qualcosa del tipo:
\begin{Console}
$ \textbf{ldapadd -x -D"cn=admin,dc=truelite,dc=it" -W -f base.ldif}
\end{Console}
%$
e si noti come si sia specificato un collegamento con il DN che ha i privilegi
di amministrazione (sarà anche richiesta la relativa password) per poter
scrivere sull'albero.

Un servizio che è possibile migrare su LDAP per fare una prova è quello della
risoluzione statica dei nomi delle macchine usualmente fatta tramite il file
\texttt{/etc/hosts}. Questo è un modo per mantenere gli indirizzi delle
macchine di una rete locale che vengono modificati spesso, senza dover stare a
configurare un DNS per un dominio fittizio. Il relativo script di migrazione è
\texttt{migrate\_hosts.pl}, che si esegue con il comando:
\begin{Console}
$ \textbf{./migrate_hosts.pl /etc/hosts hosts.ldif }
\end{Console}
%$
questo genererà il file \texttt{hosts.ldif} con le voci relative a ciascuna
macchina già presente in \texttt{/etc/hosts}; una voce del tipo di:
\begin{Example}
192.168.1.152  roke.truelite.it      roke
\end{Example}
sarà trasformata, utilizzando la \textit{objectclass}
\texttt{ipHost},\footnote{definita anch'essa all'interno del file
  \texttt{nis.schema}.} che definisce gli attributi necessari, in:
\begin{FileExample}[label=hosts.ldif]
...
dn: cn=roke.truelite.it,ou=Hosts,dc=truelite,dc=it
objectClass: top
objectClass: ipHost
objectClass: device
ipHostNumber: 192.168.1.152
cn: roke.truelite.it
cn: roke
...
\end{FileExample}

Dato che in \texttt{/etc/hosts} sono normalmente presenti anche gli indirizzi
multicast di IPv6 ed il \texttt{localhost}, installati di default con la
distribuzione, conviene di nuovo modificare a mano il file per togliere questi
e tutti gli eventuali indirizzi che non si vogliono inserire nell'elenco;
inoltre conviene anche controllare, e rimuovere, eventuali le voci duplicate.
Effettuata la pulizia si potranno di nuovo immettere i dati con il comando:
\begin{Console}
$ \textbf{ldapadd -x -D"cn=admin,dc=truelite,dc=it" -W -f hosts.ldif}
\end{Console}
%$
ed a questo punto si potrà verificare che le informazioni immesse siano
effettivamente disponibili usando il comando:
\begin{Console}
$ \textbf{ldapsearch -x -LL "(cn=roke)"}
\end{Console}
%$

In questo modo, una volta configurato il servizio del \textit{Name Service
  Switch} come illustrato in sez.~\ref{sec:ldap_NSS}, si potrà verificare che
la risoluzione del nome funzioni\footnote{con alcune versioni di
  \texttt{libnss-ldap} la cosa sembra funzionare solo per programmi che usano
  la funzione \texttt{gethostbyname}, i programmi (come \texttt{ssh},
  \texttt{telnet}, ecc.)  che usano \texttt{getaddrinfo} non funzionano.} con:
\begin{Console}
$ \textbf{ping roke}
PING roke.truelite.it (192.168.1.152): 56 data bytes
64 bytes from 192.168.1.152: icmp_seq=0 ttl=255 time=9.5 ms
64 bytes from 192.168.1.152: icmp_seq=1 ttl=255 time=11.4 ms
64 bytes from 192.168.1.152: icmp_seq=2 ttl=255 time=8.0 ms
64 bytes from 192.168.1.152: icmp_seq=3 ttl=255 time=8.2 ms

--- roke.truelite.it ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
round-trip min/avg/max = 8.0/9.2/11.4 ms
\end{Console}
%$

Questo primo passo può essere fatto come esercizio per verificare se si è
capito bene il funzionamento del meccanismo, sul piano pratico è in genere
molto più semplice definire una zona locale sul DNS. Le informazioni che
invece è sicuramente interessante portare su LDAP sono quelle relativi agli
utenti e ai gruppi, così da centralizzarne la gestione.

In questo caso il primo passo è inserire i dati dei gruppi.  Al solito si
usano gli script del pacchetto \texttt{migrationtools}. Con lo script
\texttt{migrate\_group.pl} si effettua la conversione in formato LDIF dei dati
di \texttt{/etc/group}; il comando da utilizzare è:
\begin{Console}
$ \textbf{./migrate_group.pl /etc/group group.ldif}
\end{Console}
%$
che crea le voci relative a tutti i gruppi presenti in \texttt{/etc/group} in
\texttt{group.ldif}. 

Il problema è che in \texttt{/etc/group} sono presenti anche tutti i gruppi di
sistema (come \texttt{cdrom}, \texttt{audio}, ecc.) che non ha molto senso
spostare su LDAP, poiché sono collegati a quanto è stato installato sulla
singola macchina, e che per questo possono anche essere diversi da una
installazione ad un'altra.  Per questo motivo è opportuno modificare il file
lasciando solo le voci relative ai gruppi effettivamente utilizzati nella
gestione degli utenti. Così per i gruppi principali degli utenti avremo
qualcosa delle voci del tipo:
\begin{FileExample}[label=group.ldif]
...
dn: cn=piccardi,ou=Group,dc=truelite,dc=it
objectClass: posixGroup
objectClass: top
cn: piccardi
userPassword: {crypt}x
gidNumber: 1000
...
\end{FileExample}
mentre se abbiamo dei gruppi utilizzati come gruppi di lavoro avremo qualcosa
del tipo di:
\begin{FileExample}[label=group.ldif]
...
dn: cn=cvsusers,ou=Group,dc=truelite,dc=it
objectClass: posixGroup
objectClass: top
cn: cvsusers
userPassword: {crypt}x
gidNumber: 103
memberUid: simone
memberUid: chris
memberUid: csurchi
...
\end{FileExample}

Una volta migrati i gruppi si potrà ripetere il procedimento con gli utenti,
in questo caso lo script da utilizzare è \texttt{migrate\_passwd.pl}, ed il
comando usato è:
\begin{Console}
# \textbf{./migrate_passwd.pl /etc/passwd passwd.ldif}
\end{Console}
che migrerà sia le informazioni presenti in \texttt{/etc/passwd} che quelle
presenti in \texttt{/etc/shadow}; si noti però come in questo caso si sia
eseguito il comando come amministratore per consentire la lettura di
\texttt{/etc/shadow}.

Anche in questo caso occorrerà provvedere ad eliminare dall'elenco tutti gli
utenti di sistema (come \texttt{root}, \texttt{daemon}, ecc.) che di norma
sono locali alle varie macchine e non devono (in particolar modo
\texttt{root}) essere messi su LDAP. Un esempio di voce relativa ad un
utente reale è la seguente:
\begin{FileExample}[label=passwd.ldif]
...
dn: uid=piccardi,ou=People,dc=truelite,dc=it
uid: piccardi
cn::U2ltb25lIFBpY2NhcmRp
objectClass: account
objectClass: posixAccount
objectClass: top
objectClass: shadowAccount
userPassword: {crypt}$1$7IDw9Tn0$/QvjoR4CNuQptwLmtGIQA0
shadowLastChange: 11354
shadowMax: 99999
shadowWarning: 7
loginShell: /bin/bash
uidNumber: 1002
gidNumber: 1002
homeDirectory: /home/piccardi
gecos: Simone Piccardi,,,
...
\end{FileExample}
%$

Una volta ripuliti entrambi i file generati con gli script di migrazione si
potrà passare all'inserimento dei dati nell'elenco, questo si fa con i
comandi:
\begin{Console}
$ \textbf{ldapadd -x -D"cn=admin,dc=truelite,dc=it" -W -f group.ldif}
$ \textbf{ldapadd -x -D"cn=admin,dc=truelite,dc=it" -W -f passwd.ldif}
\end{Console}

Una volta inseriti i dati iniziali resta il problema di come creare o
cancellare gli utenti quando questi sono su LDAP. Infatti benché alcune delle
informazioni relative agli utenti siano gestite in maniera trasparente da
PAM,\footnote{ad esempio il cambio password, come vedremo in
  sez.~\ref{sec:ldap_auth}.} questo non avviene per la creazione e rimozione
di utenti e gruppi, in quanto i comandi classici \texttt{useradd} e
\texttt{userdel} (e gli analoghi per i gruppi illustrati in sez.~4.3.2 di
\cite{AGL}) operano esclusivamente sui file \texttt{/etc/passwd} ed
\texttt{/etc/shadow}.

Un programma che consente di ottenere le stesse funzionalità di questi
programmi, ma che è in grado di operare anche quando gli utenti sono su LDAP,
è \index{comando!\texttt{cpu}} \texttt{cpu}.\footnote{su Debian è installabile
  con il pacchetto omonimo.} Il comando replica le funzionalità dei comandi
classici Unix per la creazione di utenti e gruppi, \texttt{useradd},
\texttt{userdel}, \texttt{usermod}, e gli analoghi per i gruppi,\footnote{ma
  non le funzioni delle versioni ``\textsl{semplificate}'' come
  \texttt{adduser} e \texttt{deluser}.}  utilizzando anche la stessa sintassi;
basterà cioè scrivere dopo \texttt{cpu} il comando che si sarebbe utilizzato
normalmente, perché l'operazione venga eseguita su LDAP.

Per poter utilizzare \texttt{cpu} occorre però, come per i
\texttt{migrationtools}, indicare su quale sezione dell'albero sono mantenuti
i dati degli utenti.  Inoltre il programma opera direttamente sull'albero
usando il protocollo, per cui occorre anche definire un utente per conto del
quale collegarsi al server, che ovviamente deve essere in grado di modificare
i dati presenti su di esso. Tutto questo viene fatto nel file di
configurazione \index{configurazione!\texttt{/etc/cpu/cpu.conf}}
\texttt{/etc/cpu/cpu.conf}, che usa il formato dei file \texttt{.ini} di
Windows.

Il file prevede al momento due sole sezioni, la sezione che contiene le
configurazioni generali, identificata dalla parola chiave \texttt{GLOBAL}, e
quella che contiene le configurazioni di LDAP, identificata dalla parola
chiave \texttt{LDAP}. Essendo \texttt{cpu} sviluppato modularmente è previsto
che esso possa operare utilizzando diversi tipi di supporto per i dati degli
utenti, ciascuno dei quali dovrebbe avere una sua sezione di configurazione
specifica.  Al momento gli unici supporti indicati sono LDAP e i file classici
di Unix, e questi ultimi non sono supportati, per cui si usa solo la sezione
globale e quella relativa a LDAP.

La sezione generale supporta due sole opzioni, \texttt{DEFAULT\_METHOD}, che
indica il metodo di amministrazione degli utenti, e può solo assumere i valori
\texttt{ldap} o \texttt{passwd}, e \texttt{CRACKLIB\_DICTIONARY} che permette
di indicare un file con il dizionario delle password da controllare, qualora
sia abilitato il supporto per le \textit{cracklib}.\footnote{le
  \textit{cracklib} sono costituite da una libreria ed un insieme di programmi
  che consentono di verificare la \textsl{forza} di una password, intesa come
  capacità di resistenza ad un tentativo di \textit{attacco a dizionario} (una
  trattazione di queste problematiche è in sez.~1.2.1 di \cite{SGL}).}

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{DEFAULT\_METHOD}     & metodo di autenticazione; può assumere 
                                   soltanto i valori \texttt{ldap} e
                                   \texttt{passwd}.\\
    \texttt{CRACKLIB\_DICTIONARY}& indica il file (con il pathname) del
                                   dizionario delle password per
                                   le \textit{cracklib}.\\
    \hline
    \texttt{LDAP\_URI}           & la URI del server LDAP su cui sono
                                   mantenute le informazioni di utenti e
                                   gruppi.\\ 
    \texttt{BIND\_DN}            & il \textit{Distinguished Name} dell'utente
                                   di LDAP per conto del quale collegarsi al
                                   server.\\ 
    \texttt{BIND\_PASS}          & la password del precedente utente (in
                                   chiaro).\\
    \texttt{USER\_BASE}          & la sezione di albero (la base della
                                   ricerca) sotto la quale sono mantenuti i
                                   dati degli utenti.\\
    \texttt{GROUP\_BASE}         & la sezione di albero (la base della
                                   ricerca) sotto la quale sono mantenuti i
                                   dati dei gruppi.\\
    \texttt{DEFAULT\_SHELL}      & la shell di default assegnata all'utente.\\
    \hline 
  \end{tabular}
  \caption{Principali opzioni di configurazione usate da \texttt{cpu.conf}.}  
  \label{tab:cpu.conf}
\end{table}


La sezione di configurazione principale è pertanto quella relativa ai
parametri di LDAP, i principali dei quali sono riportati nella seconda parte
di tab.~\ref{tab:cpu.conf}. In particolare si dovrà specificare con
\texttt{LDAP\_URI} il server a cui rivolgersi, con \texttt{BIND\_DN} il
\textit{Distinguished Name} l'utente con cui collegarsi al server e con
\texttt{BIND\_PASS} la password di detto utente.  Dato che la password è
mantenuta in chiaro è importante verificare che il file non sia leggibile.  Le
sezioni di albero su cui si trovano i dati di utenti e gruppi dovranno essere
indicate rispettivamente con \texttt{USER\_BASE} e \texttt{GROUP\_BASE} in
forma di basi di ricerca.

I principali parametri da modificare rispetto al file installato con il
pacchetto sono illustrati dal seguente esempio; tutti gli altri possono essere
lasciati ai valori di default:
\begin{FileExample}[label=cpu.conf]
[GLOBAL]
DEFAULT_METHOD  = ldap
#CRACKLIB_DICTIONARY = /var/cache/cracklib/cracklib_dict

[LDAP]
LDAP_URI                = ldap://localhost
BIND_DN                 = cn=admin,dc=truelite,dc=it
BIND_PASS               = passwordsegretissima
USER_BASE               = ou=People,dc=truelite,dc=it
GROUP_BASE              = ou=Group,dc=truelite,dc=it
\end{FileExample}



\subsection{La configurazione del \textit{Name Service Switch} su LDAP}
\label{sec:ldap_NSS}

\itindbeg{Name~Service~Switch}

Il \textit{Name Service Switch} è l'infrastruttura fornita dalle librerie di
sistema per consentire di ottenere in maniera generica le informazioni
relative a nomi a dominio, utenti, gruppi, ecc. interrogando i possibili vari
servizi su queste sono mantenute.\footnote{daremo per acquisita la familiarità
  con i concetti del \textit{Name Service Switch} in caso contrario una
  trattazione degli stessi è disponibile in sez.~4.3.6 di \cite{AGL}.}

L'uso di LDAP per la gestione di queste informazioni è una delle applicazioni
più comuni di un server LDAP, ma per poterlo utilizzare occorre installare gli
opportuni programmi di interfaccia.  Tradizionalmente questo compito veniva
effettuato con il pacchetto \texttt{libnss-ldap}, che fornisce la libreria
dinamica \textit{libnss-ldap.so.2} usata allo scopo.  I dati di configurazione
per l'accesso al server LDAP sono mantenuti nel file
\index{configurazione!\texttt{/etc/libnss-ldap.conf}}
\texttt{/etc/libnss-ldap.conf},\footnote{questo vale per le ultime versioni di
  Debian, in alcune versioni di RedHat/CentOS viene usato invece
  \texttt{/etc/ldap.conf}; per sapere quale è il file che viene usato nella
  vostra distribuzione potete guardare all'output di un comando come:
  \texttt{strings /lib/libnss\_ldap.so.2 | grep /etc}.} che ha la stessa
sintassi di \texttt{ldap.conf}, solo che in questo caso, oltre alle direttive
già viste in tab.~\ref{tab:ldap_conf_directives} (che mantengono lo stesso
significato) sono disponibili alcune direttive aggiuntive, riconosciute solo
per questo file. Le più significative sono illustrate in
tab.~\ref{tab:ldap_libnss-ldap_conf}, al solito l'elenco completo è
disponibile nella pagina di manuale, accessibile con \texttt{man
  libnss-ldap.conf}.

\itindend{Name~Service~Switch}


\index{OpenLDAP!direttiva~client!\texttt{bind\_policy}}
\index{OpenLDAP!direttiva~client!\texttt{nss\_connect\_policy}}
\index{OpenLDAP!direttiva~client!\texttt{idle\_timelimit}}
\index{OpenLDAP!direttiva~client!\texttt{nss\_base\_<map>}}
\index{OpenLDAP!direttiva~client!\texttt{nss\_map\_attribute}}
\index{OpenLDAP!direttiva~client!\texttt{nss\_map\_objectclass}}
\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Direttiva} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{bind\_policy}         & imposta la politica di collegamento al
                                    server ed il comportamento in caso di
                                    fallimento della connessione; prende i
                                    valori \texttt{hard\_open},
                                    \texttt{hard\_init} e \texttt{soft}.\\
    \texttt{nss\_connect\_policy} & imposta la politica per le connessioni
                                    delle ricerche, prende i valori
                                    \texttt{persist}, che mantiene aperta la
                                    connessione (il default) e
                                    \texttt{oneshot} che la chiude
                                    esaurita la ricerca.\\
    \texttt{idle\_timelimit}      & in caso di politica \texttt{connect}
                                    imposta un valore di timeout (in secondi)
                                    oltre il quale chiude la connessione se
                                    non ci sono richieste (il default è zero,
                                    che mantiene sempre la connessione
                                    attiva). \\ 
    \texttt{nss\_base\_\textsl{<map>}}& specifica la base di ricerca per i vari
                                    servizi del NSS (dove
                                        \texttt{\textsl{<map>}} può 
                                    assumere i valori \texttt{passwd},
                                    \texttt{shadow}, \texttt{group}, ecc.) e
                                    prende come argomento il DN della base
                                    della ricerca nella forma
                                    \texttt{basedn?scope?filter}.\\ 
    \texttt{nss\_map\_attribute}  & consente di rimappare la richiesta di un
                                    certo attributo su un altro; prende come
                                    argomenti il nome dell'attributo da
                                    rimappare seguito da quello su cui
                                    rimapparlo.\\
    \texttt{nss\_map\_objectclass}& consente di rimappare la richiesta di una 
                                    \textit{objectclass}; prende come
                                    argomenti il nome
                                    dell'\textit{objectclass} da
                                    rimappare, seguito da quella su cui
                                    rimapparla.\\
    \hline 
  \end{tabular}
  \caption{Direttive di configurazione specifiche di \texttt{libnss-ldap.conf}
    riconosciute anche da \texttt{pam\_ldap.conf}.}  
  \label{tab:ldap_libnss-ldap_conf}
\end{table}

In genere le direttive di tab.~\ref{tab:ldap_libnss-ldap_conf} non vengono
usate esplicitamente, essendo i loro valori di default validi per la maggior
parte degli usi; restano pertanto solo le direttive di base, e, se si
utilizzano connessioni su TLS/SSL (come è sempre opportuno fare) occorrerà
anche ricorrere alle direttive illustrate in
tab.~\ref{tab:ldap_ssl_directives_client} come fatto per \texttt{ldap.conf}.
Un esempio di \texttt{/etc/libnss-ldap.conf} è il seguente:
\begin{FileExample}[label=libnss-ldap.conf]
BASE           dc=truelite,dc=it
URI            ldaps://ldap.truelite.it/
TLS_CHECKPEER  yes
TLS_CACERT     /etc/ssl/certs/cacert.pem
rootbinddn     cn=admin,dc=truelite,dc=it
\end{FileExample}

In questo caso si usa la direttiva \texttt{URI} che permette di specificare il
server LDAP su cui sono mantenuti i dati, mentre tramite la direttiva
\texttt{BASE} si indica la base delle ricerche all'interno
dell'albero\footnote{nel caso è la stessa che abbiamo in
  \texttt{/etc/ldap/ldap.conf} e la si potrebbe omettere.} per ottenere i dati
relativi agli utenti.  Seguono le direttive già viste in
sez.~\ref{sec:ldap_SSL} per attivare la connessione cifrata con SSL;
ovviamente si dovrà aver cura di copiare il certificato \texttt{cacert.pem} su
tutte le macchine che centralizzeranno NSS su LDAP.

Infine con \texttt{rootbinddn} si specifica il DN dell'utente LDAP con il
quale ci si vuole autenticare presso il server quando l'utente (quello Unix
della macchina locale) per conto del quale si esegue un comando che utilizza
le funzioni del \textit{Name Service Switch} è l'amministratore.  Come
accennato in tab.~\ref{tab:ldap_conf_directives}, la password associata a
questo utente deve essere specificata su una riga singola nel file
\texttt{/etc/ldap.secret}; trattandosi della password che da l'accesso
completo ai dati degli utenti sul server LDAP questo file deve essere
opportunamente protetto da lettura.\footnote{è per poter mantenere
  \texttt{/etc/libnss-ldap.conf} accessibile in lettura che la password viene
  messa a parte su questo file.}  Questo è necessario per garantire
all'amministratore di una macchina di avere sugli utenti mantenuti su LDAP gli
stessi privilegi che avrebbe sugli utenti locali, in particolare quello di
poter operare sui campi relativi alle password.

In generale non è mai una buona politica garantire questo privilegio alle
macchine che usano il server per l'autenticazione centralizzata, dato che su
di esse non si può avere un controllo diretto, per cui chiunque abbia accesso
fisico alle macchine stesse potrebbe facilmente leggere il file
\texttt{/etc/ldap.secret}.  Non ha senso infatti che l'amministratore di un
client abbia le capacità di conoscere e modificare i dati relativi ad utenti
presenti anche su altre macchine che non sono sotto il suo diretto controllo.
L'unico caso in cui vale la pena usare questa configurazione è sul server LDAP
stesso (che si suppone adeguatamente protetto rispetto l'accesso fisico); in
tal caso infatti ha senso che l'amministratore possa avere gli stessi
privilegi sia sugli utenti locali che su quelli mantenuti su
LDAP.\footnote{nel caso, ovviamente, che anche sul server si stia usando LDAP
  per mantenere i dati degli utenti.}

Normalmente la ricerca dei dati per il \textit{Name Service Switch} viene
effettuata su tutto l'albero, a partire dalla base impostata con la direttiva
\texttt{BASE}, richiedendo tutti gli attributi delle voci che appartengono
alle \textit{objectclass} necessarie;\footnote{il pacchetto
  \texttt{libnss-ldap} contiene il supporto per la ricerca delle informazioni
  sulle \textit{objectclass} definite
  nell'\href{http://www.ietf.org/rfc/rfc2307.txt}{RFC~2307}.}  esistono però
dei casi in cui è necessario essere più specifici; ad esempio si può volere
limitare la ricerca, anche solo per renderla più veloce ad una certa sezione
dell'albero.

Per questo si possono usare le varie direttive
\texttt{nss\_base\_\textsl{<map>}} (dove \texttt{\textsl{<map>}} può essere
\texttt{hosts}, \texttt{passwd}, \texttt{group} o uno qualunque dei servizi
che vengono forniti dal \textit{Name Service Switch}). Esse permettono, per
ciascuna delle diverse classi di informazioni, di recuperare i relativi dati
su diverse specifiche sezioni dell'albero. Così per indicare dove reperire le
informazioni sugli hostname delle macchine, dei dati delle password, degli
utenti e dei gruppi si potrà utilizzare qualcosa del tipo:
\begin{FileExample}[label=libnss-ldap.conf]
nss_base_hosts     ou=Hosts,dc=truelite,dc=it?one
nss_base_passwd    ou=People,dc=truelite,dc=it?one
nss_base_shadow    ou=People,dc=truelite,dc=it?one
nss_base_group     ou=Group,dc=truelite,dc=it?one
\end{FileExample}
dove l'argomento è sempre nella forma di un DN seguito da un punto
interrogativo e da un indicatore della profondità a cui effettuare la
ricerca,\footnote{ed eventualmente da un altro punto interrogativo e da un
  filtro di ricerca, anche se questo non è molto comune.} che assume uno dei
valori fra quelli già illustrati in tab.~\ref{tab:ldap_scope_values}.

Una volta impostato \texttt{libnss-ldap.conf}, che si limita a indicare dove
recuperare le informazioni sul server, occorrerà indicare al \textit{Name
  Service Switch} di utilizzare anche LDAP per eseguire le sue ricerche,
questo va fatto modificando opportunamente il file \texttt{/etc/nsswitch.conf}
per fargli prendere i dati da LDAP, inserendo al suo interno un contenuto del
tipo:
\begin{FileExample}[label=libnss-ldap.conf]
passwd:         compat ldap
group:          compat ldap
shadow:         compat ldap
hosts:          files dns ldap
\end{FileExample}
nel caso si utilizzi LDAP per risolvere i nomi delle
macchine\footnote{soluzione sconsigliata, è molto più semplice predisporre una
  zona locale su un server DNS ad uso interno.} si deve fare attenzione che la
macchina su cui sta il server LDAP sia risolvibile senza l'uso di LDAP, (è
pertanto escluso di utilizzare come primo supporto \texttt{ldap}) altrimenti
si creerebbe un ciclo vizioso,\footnote{in cui \texttt{libnss-ldap} chiama
  \texttt{gethostbyname} per avere tale indirizzo, che a sua volta richiama di
  nuovo \texttt{libnss-ldap} per interrogare LDAP.} con la conseguenza di
generare un errore per tutti i programmi che usano tale funzione.

A questo punto si può verificare che le informazioni di utenti e gruppi
vengano viste correttamente, per questo si può usare il comando
\texttt{getent} che interroga il \textit{Name Service Switch}. Per verificare
che gli utenti siano correttamente rilevati si potrà usare il comando:
\begin{Console}
# \textbf{getent passwd}
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
...
piccardi:x:1002:1002:Simone Piccardi,,,:/home/piccardi:/bin/bash
admin:x:1003:1003:Utente Amministrativo,,,:/home/admin:/bin/bash
cgabriel:x:1004:1004:Christopher R. Gabriel,,,:/home/cgabriel:/bin/bash
csurchi:x:1005:1005:Christian Surchi,,,:/home/csurchi:/bin/bash
...
\end{Console}
e si dovrà ottenere una lista comprendente anche gli utenti mantenuti su LDAP,
mentre per verificare che sia corretta l'impostazione dei gruppi si potrà
usare il comando:
\begin{Console}
# \textbf{getent group}
root:x:0:
daemon:x:1:
bin:x:2:
...
piccardi:x:1002:
admin:x:1003:
cgabriel:x:1004:
csurchi:x:1005:
...
\end{Console}
e di nuovo si dovranno ottenere i gruppi mantenuti su LDAP; infine per
verificare anche le altre impostazioni sulle \textit{Shadow password} si potrà
eseguire il comando:
\begin{Console}
# \textbf{getent shadow}
root:$1$jjGU2TK$jHJVQBp/Xb6bmUBzmT7ubjY:11376:0:99999:7:::
daemon:*:11376:0:99999:7:::
bin:*:11376:0:99999:7:::
...
piccardi:x:12271::99999:7:::0
admin:x:12261::99999:7:::0
cgabriel:x:12289::99999:7:::0
csurchi:x:12289::99999:7:::0
...
\end{Console}
%$
ottenendo di nuovo gli utenti di LDAP.

Si noti come il risultato per gli utenti ed i gruppi appena ottenuto sia
identico a quello che si avrebbe con la configurazione classica,\footnote{una
  possibile anomalia potrebbe verificarsi con la presenza doppia di un utente,
  qualora esso sia stato inserito sia come utente locale che su LDAP; in casi
  come questo i programmi che si appoggiano al NSS usano sempre il valore
  restituito per primo (nel nostro caso l'utente locale).} mentre quello delle
\textit{shadow password} non restituisce nessun valore per l'hash della
password per tutti gli utenti che abbiamo messo su LDAP. Questo è corretto
perché da un client non si deve avere un accesso privilegiato, ed è quindi
impossibile leggere il campo che contiene le password.  Per poter permettere
all'amministratore di leggere le password degli utenti si deve usare la
direttiva \texttt{rootbinddn}, ed in tal caso si potrebbe ottenere un
risultato del tipo:
\begin{Terminal}
...
piccardi:$1$YhWNGGxB$nGFYcKX3g/Ep3NkNSJUGT1:12271::99999:7:::0
admin:$1$VwgNDkZj$mpT4ZN452yjMGqioqN/Ej0:12261::99999:7:::0
cgabriel:shUXAXmXNOs/Y:12289::99999:7:::0
csurchi:5.1Fn2ynoiIqs:12289::99999:7:::0
...
\end{Terminal}
che effettivamente contiene tutti i dati che ci aspettiamo.

Si tenga presente però che questo può avvenire soltanto se la password viene
mantenuta su LDAP in un formato riconoscibile dalle librerie di interrogazione
degli utenti usate da \texttt{getent}; in sostanza vale solo se fra i tipi di
\textit{hash} di tab.~\ref{tab:slappasswd_password_types} si è scelto
\texttt{\{CRYPT\}} o \texttt{\{SMD5\}}, se invece si è usato il default
\texttt{\{SSHA\}} questo non avverrà e si otterrà lo stesso risultato di prima
anche se il dato della password è in realtà accessibile.

Infine se si vogliono ottimizzare le prestazioni sarà necessario indicizzare
opportunamente gli attributi usati per la gestione degli utenti su LDAP. Un
esempio di indicizzazione per la configurazione nell'uso come server di
autenticazione è dato dal seguente estratto di \texttt{slapd.conf}:
\begin{FileExample}[label=slapd.conf]
index objectClass                        eq
index cn,sn,displayName,givenName,mail   eq,sub
index uid,memberUid,gidNumber,uidNumber  eq
index uniqueMember                       eq
\end{FileExample}

% TODO trattare libnss-ldapd e nslcd


\subsection{La configurazione di PAM per l'autenticazione su LDAP}
\label{sec:ldap_auth}

Una volta centralizzati gli identificativi su NSS, il passo successivo è
quello di configurare le librerie di PAM\footnote{per una trattazione più
  dettagliata dei \textit{Pluggable Authentication Method} e della loro
  architettura si veda la sez.~4.3.7 di \cite{AGL}, qui daremo per acquisita
  una conoscenza di base dell'argomento.} per utilizzare e mantenere su LDAP
le credenziali di autenticazione di utenti e gruppi. Una volta fatto questo si
avrà un sistema di autenticazione e gestione degli utenti centralizzato in
grado di sostituire il servizio NIS.

Rispetto a NIS infatti l'uso di PAM su LDAP presenta numerosi vantaggi:
anzitutto l'informazione mantenuta nel database può essere utilizzata anche
per altri scopi (come per la gestione degli account di posta o di altre
informazioni generali) e le informazioni di autenticazione possono essere
usate anche da altri programmi. Inoltre LDAP permette un controllo di accesso
alle varie informazioni memorizzate nell'elenco molto più dettagliato
attraverso l'uso delle \textit{access list} trattate in
sez.~\ref{sec:ldap_access_control}, infine supporta la replicazione e la
ridondanza, ed è pertanto in grado di rispondere ad esigenze di resistenza
agli incidenti.  Il vantaggio più importante rispetto a NIS però è quello
della sicurezza: LDAP può essere utilizzato attraverso TLS/SSL, consentendo la
trasmissione cifrata dei dati, la autenticazione di client e server, e la
verifica dell'integrità dei dati trasmessi.

Il pacchetto che consente l'uso di PAM con LDAP è \texttt{libpam-ldap}, che
fornisce l'apposito modulo \texttt{libpam\_ldap.so}. Il comportamento del
modulo è controllato dal file di configurazione
\index{configurazione!\texttt{/etc/pam\_ldap.conf}}
\texttt{/etc/pam\_ldap.conf}.\footnote{di nuovo questo è il default usato da
  Debian, sono possibili altre scelte; in caso di dubbi si può verificare
  quale file viene utilizzato con lo stesso metodo illustrato in
  sez.~\ref{sec:ldap_NSS} per \texttt{libnss-ldap.conf}.} Questo ha un formato
sostanzialmente identico a quello di \texttt{libnss-ldap.conf}, e prevede,
oltre alle direttive di base di tab.~\ref{tab:ldap_conf_directives}, anche le
estensioni illustrate in tab.~\ref{tab:ldap_libnss-ldap_conf}.

Sono inoltre previste ulteriori direttive specifiche, che permettono di
impostare le caratteristiche di funzionamento proprie di questo modulo, come
\texttt{pam\_min\_uid} che può essere utile per restringere gli
\textit{user-id} degli utenti gestiti su LDAP.\footnote{ad esempio impostando
  \texttt{pam\_min\_uid 100} si fa sì che non si possano ottenere da LDAP gli
  utenti di sistema usati per i demoni, e lo stesso root, evitando che
  un'eventuale capacità di scrittura sull'albero consenta l'inserimento di
  utenti privilegiati.} o
\index{OpenLDAP!direttiva~client!\texttt{pam\_password}}
\texttt{pam\_password} che indica il formato con cui la password deve essere
memorizzata su LDAP, per il quale si consiglia sempre il valore \texttt{exop}
che indica l'uso delle \textit{LDAP Password Modify Extended Operation}.

Un elenco delle principali direttive specifiche di \texttt{pam\_ldap.conf} è
riportato in tab.~\ref{tab:ldap_pam_ldap_conf}, l'elenco completo è nella
pagina di manuale, accessibile con \texttt{man pam\_ldap.conf}. Per la maggior
parte di esse è corretto il valore di default e non è necessario utilizzarle
esplicitamente.

\index{OpenLDAP!direttiva~client!\texttt{pam\_login\_attribute}}
%\index{OpenLDAP!direttiva~client!\texttt{pam\_filter}}
\index{OpenLDAP!direttiva~client!\texttt{pam\_min\_uid}}
\index{OpenLDAP!direttiva~client!\texttt{pam\_max\_uid}}
\index{OpenLDAP!direttiva~client!\texttt{pam\_lookup\_policy}}
\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Direttiva} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{pam\_password}& specifica il protocollo con cui eseguire la
                            modifica di una password all'interno dell'albero
                            di LDAP, può assumere i valori: \texttt{plain} per
                            una semplice trasmissione in chiaro,
                            \texttt{crypt} per una cifratura nel 
                            formato tradizionale di Unix, ed \texttt{exop} per 
                            l'uso delle
                            \textit{LDAP Password Modify Extended Operation}.\\ 
    \texttt{pam\_login\_attribute}& indica l'attributo che deve essere
                            utilizzato per la ricerca dello \textit{username}
                            dell'utente; il default è \texttt{uid}.\\
%    \texttt{pam\_filter}  & . \\
%    \texttt{pam\_check\_host\_attr}  & . \\
    \texttt{pam\_min\_uid}& indica il numero minimo di user ID consentito.\\
    \texttt{pam\_max\_uid}& indica il numero massimo di user ID consentito.\\
    \texttt{pam\_lookup\_policy} & indica se deve essere effettuata una
                            scansione dell'albero LDAP per individuare una
                            \textit{policy} delle password mantenuta
                            direttamente sul server (tramite
                            l'\textit{overlay} \texttt{ppolicy}) invece di
                            usare gli attributi previsti in
                            tab.~\ref{tab:ldap_user_attributes}; prende i
                            valori \texttt{yes} e \texttt{no} ed il default è
                            \texttt{no}. \\
    \hline 
  \end{tabular}
  \caption{Direttive di configurazione usate da \texttt{pam\_ldap.conf}.}
  \label{tab:ldap_pam_ldap_conf}
\end{table}

Con Debian all'installazione del pacchetto il sistema del \textit{debconf}
richiede i dati per collegarsi al server creando automaticamente uno scheletro
di configurazione per \texttt{pam\_ldap.conf}. Se si vuole utilizzare TLS/SSL,
occorrerà inoltre impostare le direttive illustrate in
sez.~\ref{sec:ldap_SSL}. Un esempio di questo file, eliminati commenti e righe
vuote, è il seguente:
\begin{FileExample}[label=pam\_ldap.conf]
base dc=truelite,dc=it
uri ldaps://ldap.truelite.it/
ldap_version 3
rootbinddn cn=admin,dc=truelite,dc=it
pam_min_uid 999
pam_password exop
tls_checkpeer yes
TLS_CACERT /etc/ssl/certs/cacert.pem
\end{FileExample}

Per gestire i dati di autenticazione può convenire creare un utente dedicato
sull'elenco, da tenere separato dall'utente usato come amministratore per
tutto l'elenco. Questo può permettere di avere un maggiore controllo su quanto
i vari client potranno fare, limitando l'accesso alle sole informazioni che
riguardano l'autenticazione. Spesso però, quando le informazioni di
autenticazione sono le più rilevanti fra quelle che si mantengono nell'albero,
si preferisce adottare questa politica per le altre informazioni meno
importanti in esso presenti, ed utilizzare per i dati di autenticazione
direttamente l'amministratore del database.

Per l'uso di PAM hanno particolare rilevanza i privilegi di accesso per
l'attributo \texttt{userPassword}, in quanto è questo che viene utilizzato per
l'autenticazione degli utenti; infatti se riprendiamo l'estratto del file di
configurazione standard installato da Debian, già illustrato in
sez.~\ref{sec:ldap_access_control}, vediamo che questo è trattato in modo
particolare:
\begin{FileExample}[label=slapd.conf]
access to attrs=userPassword
        by dn="cn=admin,dc=truelite,dc=it" write
        by anonymous auth
        by self write
        by * none
\end{FileExample}

L'accesso in scrittura all'utente di amministrazione del server è equivalente
a quello che ha \textit{root} per le password normali, esso cioè può cambiare
le password di tutti gli utenti.  Se si volesse introdurre un utente di
amministrazione da usare al posto dell'amministratore generale si dovrebbe
inserire anche per lui un adeguato permesso di accesso.

Come nel caso del NSS si ripresenta il problema di come trattare le richieste
fatte dall'amministratore delle varie macchine che si appoggiano al server
LDAP per l'autenticazione. La direttiva \texttt{rootbinddn} consente di
associare queste all'utente di amministrazione, ma si ha il solito problema
che l'amministratore del client avrebbe la capacità di modificare le
credenziali di autenticazione sul server. Come nel caso precedente questa
impostazione ha senso solo sul server LDAP stesso. 

Si tenga presente che perché un utente possa modificare la propria password
non è necessario che il client abbia pieno accesso a LDAP, in quanto esso
potrà farlo una volta che si è autenticato, avendo utilizzato la ACL
``\texttt{by self write}''. Questo stesso privilegio dovrà essere assegnato
per gli altri attributi che si vuole l'utente possa modificare; in particolare
l'accesso a \texttt{shadowLastChange} è fondamentale perché all'aggiornamento
della password questo dato venga aggiornato.\footnote{altrimenti la password
  verrebbe cambiata, ma per il meccanismo di verifica della durata il
  cambiamento non avrebbe effetto, non venendo aggiornato il valore di questo
  attributo.} Per questo motivo una configurazione più adeguata delle ACL per
gli attributi usati nell'autenticazione degli utenti potrebbe essere:
\begin{FileExample}[label=slapd.conf]
access to attrs=userPassword
        by dn="cn=admin,dc=truelite,dc=it" write
        by anonymous auth
        by self write
        by * none
access to attrs=shadowLastChange,loginShell,gecos
        by dn="cn=admin,dc=truelite,dc=it" write
        by self write
        by * none
\end{FileExample}

Una volta configurate le librerie per l'accesso al server, per poter
centralizzare l'autenticazione occorrerà anche configurare PAM per fargli
utilizzare il modulo \texttt{pam\_ldap.so} per gestire i vari servizi da esso
coperti. Nel caso di Debian e di tutte le distribuzioni più recenti la
configurazione di PAM avviene attraverso una serie di file posti nella
directory \texttt{/etc/pam.d}, uno per servizio, che indicano quali moduli
devono essere utilizzati.

Per indicare l'uso di LDAP per i servizi di autenticazione, gestione
dell'account e delle password si potrebbero allora aggiungere in ciascuno dei
file di configurazione dei programmi, prima delle equivalenti configurazioni
che indicano quella ordinaria (in genere effettuata con \texttt{pam\_unix.so})
delle righe come le seguenti:
\begin{FileExample}
auth       sufficient pam_ldap.so
account    sufficient pam_ldap.so
password   sufficient pam_ldap.so
\end{FileExample}
e si noti che non si sia specificato niente per i servizi di sessione; questo
avviene perché \texttt{libpam-ldap} gestisce solo l'autenticazione
centralizzata; le informazioni sulla sessione sono invece locali e non vengono
mantenute su LDAP.

Una configurazione come quella indicata richiede di utilizzare, se presenti,
le informazioni su LDAP per i servizi indicati, ed altrimenti passare al
meccanismo classico di autenticazione di Unix. Si tenga presente che non si
può rimuovere la parte relativa all'autenticazione ordinaria, altrimenti gli
utenti locali (come \texttt{root}) non potrebbero più collegarsi al sistema.

Questo metodo ha però diversi svantaggi il primo dei quali, non collegato
all'uso di LDAP, è quello di dover modificare tutti i file presenti in
\texttt{/etc/pam.d}.  Le versioni più recenti di PAM, quelle in uso in tutte
le principali distribuzioni, consentono l'inclusione di alcuni valori comuni
mantenuti su file a parte. Questo in Debian è realizzato tramite i 4 file
\texttt{common-auth}, \texttt{common-session}, \texttt{common-account} e
\texttt{common-password}, per cui sarà sufficiente effettuare le modifiche
citate all'interno di questi. Altre distribuzioni usano altri file, ma sarà
sufficiente aggiungere ad essi direttive analoghe a quelle illustrate in
seguito.

La configurazione suggerita presenta comunque anche altri inconvenienti: il
primo è che cominciando con \texttt{pam\_ldap.so} si andrà sempre a cercare
prima su LDAP e poi in locale; questo comporta del traffico inutile quando si
cercano dei dati relativi agli utenti locali. Dato che la ricerca in locale è
molto meno onerosa sarebbe preferibile utilizzare \texttt{pam\_ldap.so} dopo
l'uso del classico \texttt{pam\_unix.so}. Il secondo problema è che tutte le
volte che un utente non è presente su LDAP la password verrebbe richiesta una
seconda volta per poterlo autenticare localmente.

Per questo motivo riportiamo di seguito, per ciascuno dei quattro file comuni
appena citati, una configurazione più corretta. Per \texttt{common-auth} si
potranno utilizzare le seguenti impostazioni:
\begin{FileExample}[label=common-auth]
auth        required      /lib/security/pam_env.so
auth        sufficient    /lib/security/pam_unix.so likeauth nullok
auth        required      /lib/security/pam_ldap.so use_first_pass
\end{FileExample}
in cui prima si esegue la richiesta in locale e solo in caso di fallimento si
effettua la richiesta su LDAP; l'uso dell'argomento \texttt{try\_first\_pass}
consente poi di riutilizzare la password immessa per l'autenticazione classica
anche per LDAP, evitando così la ripetizione della richiesta. In maniera
analoga si potrà inserire in \texttt{common-password} qualcosa del tipo:
\begin{FileExample}[label=common-password]
password    sufficient    /lib/security/pam_unix.so nullok obscure md5 
password    required      /lib/security/pam_ldap.so try_first_pass
\end{FileExample}
infine per \texttt{common-account} si potrà utilizzare:
\begin{FileExample}[label=common-auth]
account sufficient  /lib/security/pam_ldap.so
account sufficient  /lib/security/pam_unix.so
\end{FileExample}
mentre per quanto riguarda \texttt{common-session} (per il quale non vengono
sostanzialmente utilizzate le informazioni di LDAP) si potrà usare:
\begin{FileExample}[label=common-session]
session required    /lib/security/pam_unix.so
session optional    /lib/security/pam_ldap.so
\end{FileExample}

% TODO rivedere le configurazioni, con qualcosa di più moderno


\section{L'integrazione dei servizi su LDAP}
\label{sec:ldap_integration}

Vedremo in questa sezione come si può utilizzare LDAP come supporto di
integrazione per mantenere centralizzate informazioni utilizzate da una serie
di altri servizi e programmi che non siano la gestione di utenti e gruppi di
un insieme di macchine, già illustrata in sez.~\ref{sec:ldap_user_management}.


\subsection{La gestione dell'indirizzario}
\label{sec:ldap_address_book}

L'utilizzo classico di LDAP, quello per cui il servizio è nato, è quello di
permettere la gestione centralizzata e la distribuzione via rete di un
indirizzario (o rubrica). Vedremo in questa sezione quali sono gli schemi da
utilizzare a questo scopo, e come configurare i vari client che possono
appoggiarsi ad LDAP per la gestione dell'indirizzario.

Per la gestione dei dati di una rubrica condivisa esiste già una
standardizzazione che definisce una serie di classi e relativi attributi che
consentono di memorizzare i dati classici (nome, cognome, numero di telefono,
indirizzo fisico e di posta elettronica, ecc.) che si trovano solitamente in
un indirizzario.  Alcuni programmi poi utilizzano delle estensioni per
mantenere dati aggiuntivi ad uso del programma; in questo caso occorrerà
utilizzare i relativi schemi (includendoli nella configurazione di
\texttt{slapd}, si veda sez.~\ref{sec:ldap_server_base_config}) che
definiscono le classi e gli attributi necessari.\footnote{nel caso di
  \textit{Evolution} ad esempio viene fornito col pacchetto uno schema
  \texttt{evolutionperson.schema} che permette di inserire nell'indirizzario
  dati aggiuntivi come indirizzi secondari, ecc.}

L'utilizzo di questi schemi aggiuntivi di norma è da sconsigliare, a meno di
non avere fin dall'inizio la possibilità di imporre a lungo termine una forte
uniformità nell'uso delle specifiche applicazioni che ne fanno uso. Questo
perché quando si introducono classi ed attributi particolari, essi sono
riconosciuti solo dall'applicazione che li usa, e l'interoperabilità con altre
applicazioni diventa più complessa,\footnote{sempre nel caso di
  \textit{Evolution} poi la cosa è assolutamente da evitare, in quanto di
  default detto programma, quando lo schema aggiuntivo è presente, salva certi
  dati negli attributi da esso definiti, anche quando sarebbero disponibili
  attributi analoghi nella classe standard \texttt{inetOrgPerson}.}  non
essendo queste consapevoli della presenza di dati aggiuntivi, che in un
eventuale passaggio diventerebbero inutilizzabili.

Lo schema classico usato per la gestione delle informazioni di un indirizzario
di persone è \texttt{inetorgperson.schema}, distribuito con gli
\textit{schema} di default di \textit{OpenLDAP}; esso di solito viene incluso
nella configurazione di default in \texttt{slapd.conf}.  Questo schema
contiene la definizione della \textit{objectclass} \texttt{inetOrgPerson}
relativa ad una persona, che definisce una lunga lista di attributi contenenti
dati personali come il telefono, l'indirizzo di casa, quello di posta
elettronica e similari.\footnote{per un elenco completo occorre sommare quelli
  della \textit{objectclass} \texttt{person} definita in \texttt{core.schema},
  da cui deriva \texttt{organizationalPerson}, definita in
  \texttt{cosine.schema}, da cui finalmente deriva \texttt{inetOrgPerson}.}

Se su un database si mantengono sia questi dati che quelli di un insieme di
utenti centralizzati, è buona norma dedicare ai dati della rubrica una sezione
dell'albero a parte (in genere è sempre un qualcosa sotto una
\textit{organizationalUnit} a parte, ad esempio \texttt{ou=Contacts}) così da
restringere le ricerche su quella sezione specifica di albero e non mescolare
dati di minore rilevanza, come questi, coi dati degli utenti.

\begin{figure}[!htb]
  \centering \includegraphics[scale=0.5]{images/thunderbird-LDAP-1}
  \caption{Schermata di configurazione della rubrica di \textit{Thunderbird}
    per l'utilizzo di un server LDAP.}
\label{fig:ldap_thuderbird_conf}
\end{figure}

Per l'utilizzo dei dati della rubrica basta utilizzare un qualunque client
LDAP adatto allo scopo, cioè in grado di riconoscere i dati e di presentarli
all'utente in maniera opportuna. Alcuni programmi ad interfaccia grafica che
sono in grado di interfacciarsi con LDAP per accedere ai dati di una rubrica
condivisa sono \textit{Evolution}, \textit{Thunderbird},
\textit{Kaddressbook}.

In tutti questi casi occorre comunque indicare al programma come collegarsi
con il server LDAP; ed in genere questo deve essere fatto in maniera
esplicita. Tutti i programmi citati hanno una opportuna schermata di
configurazione che consente di immettere i dati necessari; le informazioni
essenziali sono le coordinate del server e la base della ricerca, che è
opportuno limitare alla sezione di albero su cui sono mantenuti i dati
dell'indirizzario. 

Tutti i programmi citati consentono inoltre di specificare un eventuale utente
tramite il suo DN con cui collegarsi al server (una eventuale password verrà
richiesta al momento dell'accesso) e di abilitare o meno le connessioni
cifrate con SSL.\footnote{in questo caso si tenga presente che deve essere già
  stato configurato \texttt{ldap.conf} come in sez.~\ref{sec:ldap_SSL} per
  indicare quali certificati usare, dato che i programmi citati non consentono
  di fare questa impostazione nella loro schermata di configurazione.} Un
esempio di questo tipo di schermata è illustrato in
fig.~\ref{fig:ldap_thuderbird_conf}, dove è riportata quella utilizzata da
\textit{Thunderbird}.

In genere ha senso utilizzare un accesso autenticato (e in tal caso anche SSL)
soltanto per l'accesso ad un eventuale sezione riservata dell'indirizzario, o
per fornire, per un client che lo supporti, l'accesso in scrittura per la
modifica dei dati dell'indirizzario.


\subsection{Apache e LDAP}
\label{sec:ldap_apache}

L'uso classico dei dati di LDAP da parte di Apache è quello della gestione
delle restrizioni di accesso previa autenticazione degli
utenti.\footnote{esiste anche un modulo, \texttt{mod\_vhost\_ldap} (si veda
  \url{http://modvhostldap.alioth.debian.org/}) per mantenere su LDAP le
  informazioni relative ai \textit{Virtual Host}, ma non lo prenderemo in
  considerazione.} Invece di confrontare le credenziali di accesso con il
classico file generato con \texttt{htpasswd}, queste possono essere mantenute
su un database LDAP, permettendo così una gestione integrata con gli utenti
presenti sul server.

Per poter utilizzare Apache in questo modo è necessario che siano stati
caricati gli opportuni moduli; fino ad Apache 2.0 questi erano
\texttt{mod\_ldap} e \texttt{mod\_auth\_ldap}, con Apache 2.2 l'infrastruttura
dell'autenticazione è cambiata, e al posto di \texttt{mod\_auth\_ldap} occorre
usare \texttt{mod\_authnz\_ldap}. In entrambi i casi comunque questi fanno
parte dei moduli base di Apache (in Debian sono nel pacchetto
\texttt{apache2-common}) e per caricarli basta assicurarsi della presenza
degli opportuni link simbolici in \texttt{mods-enabled}, creandoli, qualora
necessario, con il comando \texttt{a2enmod}.

Al solito l'autenticazione si attiva con le direttive \texttt{AuthType} e
\texttt{AuthName},\footnote{per una trattazione dell'argomento si può
  consultare sez.~1.4.2 di \cite{WebServ}.} ma la presenza dei moduli citati
consente di rimpiazzare le direttive che specificano l'elenco degli utenti con
quelle che permettono utilizzare un server LDAP, e di estendere le capacità
della direttiva \texttt{Require} così che essa possa usare dati peculiari di
LDAP; a questa si accompagnano poi una serie di direttive aggiuntive per
gestire le modalità con cui si eseguono le interrogazioni al server.

Il funzionamento dei moduli di autenticazione è infatti suddiviso in due fasi,
la prima fase è quella detta di \textsl{autenticazione}, che prevede la
verifica delle credenziali fornite dall'utente, vale a dire nome utente e
password immesse nel browser. su LDAP. Questo viene fatto eseguendo prima una
ricerca sul database con l'interrogazione specificata dalla URL passata come
argomento della direttiva \texttt{AuthLDAPURL}. La ricerca viene eseguita di
default sull'attributo \texttt{uid} a partire dalla base specificata nella
URL, ma si può scegliere un altro attributo (ad esempio \texttt{cn}) o
l'applicazione di un filtro di ricerca utilizzando la sintassi estesa delle
URL di LDAP illustrata in sez.~\ref{sec:ldap_query_mechanism}.

Se la ricerca restituisce un unico risultato, il DN così ottenuto viene usato
per collegarsi al server con la password fornita dell'utente: un risultato
positivo completa la fase di autenticazione.  Si tenga presente che se la
ricerca non restituisce esattamente \textsl{un} risultato l'accesso viene
negato immediatamente: questo significa anche che se non è possibile eseguire
una ricerca anonima occorrerà specificare, con le direttive illustrate in
tab.~\ref{tab:apache_ldap_auth}, un DN e relativa password con cui effettuare
il collegamento iniziale per la ricerca, altrimenti la fase di autenticazione
non verrà mai completata.

Alla fase di autenticazione segue quella di \textsl{autorizzazione}, in cui
l'accesso viene consentito o meno a seconda di quanto specificato nella
direttiva \texttt{Require}.  In questo caso però i parametri che si possono
indicare alla direttiva sono cambiati nel passaggio da Apache 2.0 ad Apache
2.2, ed i due casi vanno trattati separatamente.

Nel caso di Apache 2.0 la direttiva \texttt{Require} continua a supportare
come primo argomento i valori classici \texttt{valid-user}, che indica un
utente generico, \texttt{user} che indica uno specifico utente e
\texttt{group} che indica un gruppo. A questi si aggiungono due nuovi valori,
\texttt{ldap-attribute} che permette di autorizzare l'accesso sulla base del
valore di un attributo dell'utente e \texttt{dn} che consente l'accesso
specificando direttamente un \textit{Distinguished Name}.

Nel caso di Apache 2.2 invece il sistema di autenticazione richiede
l'indicazione esplicita, tramite la direttiva \texttt{AuthBasicProvider}, di
quale supporto di autorizzazione si intende utilizzare, che nel caso specifico
dovrà usare l'argomento \texttt{ldap}.\footnote{normalmente questa non viene
  usata dato che il valore di default è \texttt{file}.}  Inoltre cambiano gli
argomenti da passare alla direttiva \texttt{Require}; in particolare si
dovranno usare \texttt{ldap-user} e \texttt{ldap-group} al posto di
\texttt{user} e \texttt{group}.

Quando si effettua l'autorizzazione per utenti e gruppi (quale che sia la
versione di Apache usata) essendo i relativi dati mantenuti su LDAP se ne
dovranno tenere in considerazione le caratteristiche, che si riflettono sulla
forma dei successivi argomenti di \texttt{Require}. Come abbiamo accennato
l'username che identifica un utente sul browser può assumere le forme più
diverse a seconda dell'attributo che si usa nella interrogazione specificata
da \texttt{AuthLDAPURL}. Pertanto quando si deve indicare un utente occorrerà
usare il valore con cui si è fatto la ricerca nella fase di autenticazione; se
ad esempio si fosse utilizzata una ricerca sul \textit{Common Name}, le
direttive di autorizzazione sarebbero dovute essere qualcosa del tipo
di:\footnote{si è usata la sintassi di Apache 2.2, nel caso di Apache 2.0 si
  sarebbe dovuto usare \texttt{user}, con le stesse avvertenze riguardo gli
  argomenti successivi.}
\begin{Example}
Require ldap-user "Simone Piccardi"
Require ldap-user "Christian Surchi"
\end{Example}
dove si sono usate le virgolette dato che lo spazio viene utilizzato come
separatore per indicare gli utenti all'interno di una lista.

Lo stesso tipo di problematica si presenta se si esegue una autorizzazione in
base all'appartenenza ad un gruppo: in primo luogo occorrerà identificare
quale gruppo indicando come argomento di \texttt{require group} (o
\texttt{require ldap-group}) il \textit{Distinguished Name} della voce ad esso
corrispondente; inoltre, dato che per definire dei gruppi si possono usare
diversi tipi di \textit{objectclass}, occorrerà anche prendere in
considerazione le modalità con cui vengono mantenuti gli utenti all'interno
del gruppo.

In questo caso gli aspetti di cui tenere conto sono due. Il primo riguarda
quale attributo viene usato per identificare gli utenti; il default usato da
\texttt{mod\_auth\_ldap} e \texttt{mod\_authnz\_ldap} è cercare degli
attributi di tipo \texttt{member} o \texttt{uniqueMember}. Dato che questi
attributi sono tipici di alcune \textit{objectclass} se ne possono anche
specificare di diversi, passando i rispettivi nomi come argomenti della
direttiva \texttt{AuthLDAPGroupAttribute}. Se ad esempio per i gruppi viene
usata una \textit{objectclass} di tipo \texttt{posixGroup} sarà necessario
utilizzare una direttiva del tipo:
\begin{Example}
AuthLDAPGroupAttribute memberUid
\end{Example}
dato che in questo caso i membri del gruppo saranno indicati da altrettanti
valori di detto attributo.

Il secondo aspetto è quello del valore che viene preso per identificare
l'utente nel gruppo; il default di \texttt{mod\_auth\_ldap} (e
\texttt{mod\_authnz\_ldap}) prevede infatti che i membri di un gruppo siano
indicati con il \textit{Distinguished Name},\footnote{è il caso tipico della
  \textit{objectclass} standard \objcl{groupOfNames}.}
il controllo di appartenenza pertanto viene effettuato normalmente usando il
DN corrispondente all'username fornito dal browser, come lo si è ottenuto
dalla ricerca della fase di autenticazione.  Di nuovo esistono casi, come
quando si usa l'\textit{objectclass} \texttt{posixGroup}, in cui i membri del
gruppo sono indicati con un semplice nome, in tal caso si dovrà cambiare la
modalità di ricerca dei membri con la direttiva
\texttt{AuthLDAPGroupAttributeIsDN}, impostando:
\begin{Example}
AuthLDAPGroupAttributeIsDN off
\end{Example}
ed in questo caso verrà usato direttamente l'username ottenuto dal browser.


Nel caso di Apache 2.0 oltre alla autorizzazione per utenti e gruppi, ci sono
altre due modalità aggiuntive realizzate da \texttt{mod\_auth\_ldap}; con
``\texttt{Require dn}'' si potrà specificare direttamente (senza usare le
virgolette) il \textit{Distinguished Name} degli utenti che si vogliono far
accedere, mentre con ``\texttt{Require attribute}'' si potrà specificare un
attributo, nella forma \texttt{nome=valore}, ed una volta passata la fase di
autenticazione, l'autorizzazione sarà concessa soltanto se nella voce
corrispondente all'utente è presente quell'attributo, con quel valore.

Qualora si utilizzi Apache 2.2 queste due modalità aggiuntive permangono, con
la sola differenza che occorre usare \texttt{ldap-dn} al posto di \texttt{dn}.
Viene però introdotta una ulteriore modalità di autorizzazione grazie
all'argomento \texttt{ldap-filter}, che permette di effettuare la selezione
specificando direttamente un filtro di ricerca, e consente l'accesso a tutti
gli utenti autenticati che corrispondono allo stesso. In tab.


% \begin{table}[!htb]
%   \centering
%   \footnotesize
%   \begin{tabular}[c]{|l|l|p{8cm}|}
%     \hline
%     \multicolumn{2}{|c|}{\textbf{Argomenti}} & \textbf{Significato} \\
%     \hline
%     \hline
%     \texttt{user} &\texttt{ldap-user}  & indica un utente su LDAP.\\
%     \texttt{group}&\texttt{ldap-group} & indica un gruppo su LDAP.\\
%     \multicolumn{2}{|c|}{\texttt{valid-user}}& .\\
%     \multicolumn{2}{|c|}{\texttt{ldap-attribute}}& .\\
%     \texttt{dn}   &\texttt{ldap-dn}    &.\\
%        --         &\texttt{ldap-filter}&.\\
% %    \texttt{}&\texttt{}&.\\
%     \hline 
%   \end{tabular}
%   \caption{Gli argomenti specifici della direttiva \texttt{Require} quando
%     utilizzata con i moduli di autenticazione su LDAP.}
%   \label{tab:apache_ldap_auth_require}
% \end{table}


Infine occorre tenere presente che \texttt{mod\_authnz\_ldap} non supporta
direttamente l'uso dell'argomento \texttt{valid-user}. É possibile però
utilizzarlo ugualmente, riportandosi nella stessa situazione che si avrebbe
con Apache 2.0, impostando la direttiva \texttt{AuthzLDAPAuthoritative} ad
\texttt{off}.  In questo caso infatti quando la procedura di autorizzazione su
LDAP fallisce, si passa ad utilizzare quella di eventuali altri moduli.  Nel
caso specifico quello che succede è che la richiesta di autorizzazione viene
passata alla procedura di autorizzazione standard tramite file, che supporta
\texttt{valid-user} e che autorizza un qualunque utente autenticato, e questo
vale anche se la procedura di autenticazione era stata fatta su LDAP.


\index{Apache!direttiva!\texttt{AuthLDAPURL}}
\index{Apache!direttiva!\texttt{AuthLDAPGroupAttribute}}
\index{Apache!direttiva!\texttt{AuthLDAPGroupAttributeIsDN}}
\index{Apache!direttiva!\texttt{AuthLDAPCompareDNOnServer}}
\index{Apache!direttiva!\texttt{AuthLDAPBindDN}}
\index{Apache!direttiva!\texttt{AuthLDAPBindPassword}}
\index{Apache!direttiva!\texttt{AuthLDAPGroupAttribute}}
\index{Apache!direttiva!\texttt{AuthLDAPGroupAttributeIsDN}}
\index{Apache!direttiva!\texttt{AuthLDAPCompareDNOnServer}}
\index{Apache!direttiva!\texttt{AuthzLDAPAuthoritative}}
%\index{Apache!direttiva!\texttt{}}
\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Direttiva} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{AuthLDAPURL}           & specifica una URL (con la sintassi estesa
                                     illustrata in
                                     sez.~\ref{sec:ldap_query_mechanism}) sulla
                                     quale viene compiuta la ricerca degli
                                     utenti.\\ 
    \texttt{AuthLDAPBindDN}        & specifica il DN con cui collegarsi al
                                     server LDAP, se per la ricerca eseguita
                                     nella fase di autenticazione non è
                                     sufficiente il collegamento anonimo.\\
    \texttt{AuthLDAPBindPassword}  & specifica la password da usare per
                                     eseguire il collegamento con  
                                     l'utente indicato da 
                                     \texttt{AuthLDAPBindDN}.\\
    \hline 
    \texttt{AuthLDAPGroupAttribute}& specifica quali attributi usare per
                                     identificare i membri di un gruppo; il
                                     default è l'uso di \texttt{member} e
                                     \texttt{uniqueMember}.\\ 
    \texttt{AuthLDAPGroupAttributeIsDN}& esegue la ricerca dei membri di un
                                     gruppo usando il DN dell'utente
                                     specificato, se disabilitato (con
                                     argomento \texttt{off}) esegue la ricerca
                                     con il nome passato in fase di
                                     autenticazione (il default è
                                     \texttt{on}).\\
    \texttt{AuthzLDAPAuthoritative}& direttiva specifica di Apache 2.2;
                                     se posta ad \texttt{off} consente ad 
                                     altri moduli di autenticazione di
                                     effettuare l'autorizzazione dell'utente
                                     quando non funziona quella su LDAP, il
                                     default è \texttt{on} e deve essere
                                     modificato quando si vuole utilizzare la
                                     direttiva \texttt{Require} con argomento
                                     \texttt{valid-user}.\\ 
%    \texttt{AuthLDAPCompareDNOnServer}& .\\
%    \texttt{}& .\\
    \hline 
  \end{tabular}
  \caption{Le direttive specifiche della configurazione di Apache per
    l'autenticazione su LDAP.}
  \label{tab:apache_ldap_auth}
\end{table}

In tab.~\ref{tab:apache_ldap_auth} si sono riportate le principali direttive
di Apache relative all'autenticazione degli utenti su LDAP, la tabella è
divisa in due sezioni, nella parte superiore sono indicate le direttive
attinenti la fase di autenticazione, nella parte inferiore quelle attinenti la
fase di autorizzazione. Per ulteriori dettagli si può consultare la
documentazione dei moduli citati, disponibile a partire da
\url{http://httpd.apache.org/docs/}.


\subsection{Postfix e LDAP}
\label{sec:ldap_postfix}

Una delle caratteristiche più interessanti di Postfix è la sua capacità di
utilizzare per gran parte dei suoi parametri di configurazione delle tabelle
dalle quali estrarre dei valori con una ricerca su un campo che fa da chiave.
La potenza di questa caratteristica è che queste tabelle possono essere
mantenute sui più vari tipi di supporti: file, hash binari, database
relazionali, ed ovviamente anche su LDAP.

Se si installa Postfix con il supporto per LDAP, (su Debian il pacchetto che
lo fornisce è \texttt{postfix-ldap}) diventa allora possibile inserire le
informazioni di una qualunque tabella all'interno di un database, ed ottenerne
i valori con delle interrogazioni allo stesso. In questo caso la
sintassi\footnote{questa è la sintassi introdotta con le versioni di Postfix
  successive alla 2.0, in precedenza usava una notazione diversa, che, come
  incentivo all'aggiornamento, non tratteremo affatto (essa viene comunque
  riconosciuta, per compatibilità, nelle nuove versioni).}  con cui fare
riferimento ad una tale tabella è analoga alla seguente:
\begin{Example}
alias_maps = ldap:/etc/postfix/ldap-aliases.cf
\end{Example}
che è del tutto analoga alla sintassi usata per le altre tabelle, ma con
l'indicativo ``\texttt{ldap:}'' al posto del più comune ``\texttt{hash:}''
usato per le tabelle ordinarie su DBM. In questo modo è possibile specificare
un file (nel precedente esempio \texttt{/etc/postfix/ldap-aliases.cf}) da cui
vengono prese le impostazioni di accesso a LDAP, e vengono indicati i criteri
di ricerca e quali informazioni richiedere.

Questo file supporta la stessa sintassi generale dei file di configurazione di
Postfix, che prevede una serie di direttive nella forma \texttt{chiave =
  valore}. Le direttive fondamentali da inserire in questo file sono quattro:
la prima è \texttt{server\_host} che consente di specificare il server LDAP a
cui rivolgersi (il default è \texttt{localhost}) e supporta anche la sintassi
delle URL estese vista in sez.~\ref{sec:ldap_query_mechanism}.

La seconda è \texttt{search\_base} che indica la base
della ricerca (secondo quanto visto in sez.~\ref{sec:ldap_search})
nell'albero, questa può coincidere con la radice del database, ma in genere è
opportuno utilizzarla per indicare la sezione dell'albero su cui stanno i dati
di interesse.\footnote{a partire da Postfix 2.2 si possono usare nel valore di
  questa direttiva le espansioni di tab.~\ref{tab:postfix_ldap_expansion}.}

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Espressioni} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{\%s} & chiave di ricerca o valore del risultato.\\
    \texttt{\%u} & quando la chiave di ricerca o il valore del risultato sono
                   nella forma canonica di un indirizzo di posta
                   (\texttt{utente@dominio)}) restituisce la parte locale
                   dell'indirizzo (nel caso \texttt{utente}); altrimenti
                   riporta l'intera chiave.\\
    \texttt{\%d} & quando la chiave di ricerca o il valore del risultato sono
                   nella forma canonica di un indirizzo di posta
                   (\texttt{utente@dominio)}) restituisce la parte di dominio
                   dell'indirizzo (nel caso \texttt{dominio}); altrimenti non
                   riporta nulla.\\
    \texttt{\%\%}& il carattere \texttt{\%}.\\
     \texttt{\%[SUD]}& gli equivalenti maiuscoli di \texttt{\%s}, \texttt{\%u}
                   e \texttt{\%d}.\\
     \texttt{\%[1-0]} & nel caso di chiave o valore contenente un nome a
                   dominio riporta le componenti dei vari livelli (ad esempio
                   nel caso di \texttt{piccardi@truelite.it} \texttt{\%1} è
                   \texttt{it} e \texttt{\%2} è \texttt{truelite}).\\
%     \texttt{} & .\\
    \hline 
  \end{tabular}
  \caption{La sintassi delle espressioni di sostituzione nelle direttive di
    LDAP.} 
  \label{tab:postfix_ldap_expansion}
\end{table}

La terza direttiva è \texttt{query\_filter}, che imposta un filtro di ricerca
con il quale si selezionano i risultati che si vogliono estrarre dal database
LDAP. Questa direttiva prende come valore un filtro di ricerca (nella forma
illustrata in sez.~\ref{sec:ldap_search}) che supporta una sintassi estesa che
permette di utilizzare delle espressioni che fanno riferimento a dati forniti
direttamente da Postfix; ad esempio con \texttt{\%s} si indica la chiave di
ricerca passata direttamente dal server (in genere l'indirizzo di posta).  Una
lista delle espressioni supportate è riportata in
tab.~\ref{tab:postfix_ldap_expansion} (la lista fa riferimento alla versione
2.2 di Postfix; nelle versioni precedenti erano disponibili solo le prime tre
espressioni).

La quarta direttiva è \texttt{result\_attribute}, che permette di indicare
quale attributo delle voci ottenute con la ricerca deve essere come valore
della tabella; a questa si può aggiungere \texttt{result\_format} che consente
di riformattare il risultato precedente utilizzando le stesse espressioni di
tab.~\ref{tab:postfix_ldap_expansion}. 

Con queste quattro direttive diventa possibile fare eseguire a Postfix una
ricerca su LDAP per qualunque direttiva che prenda fra i suoi argomenti una
tabella, ad esempio se si vogliono mantenere gli alias degli su LDAP,
utilizzando l'attributo \texttt{mail} della \textit{objectclass}
\texttt{inetOrgPerson}, si potrà utilizzare la direttiva usata prima come
esempio, ed il contenuto del file \texttt{ldap-aliases.cf} sarà qualcosa del
tipo:
\begin{FileExample}[label=ldap-aliases.cf]
server_host  = 127.0.0.1
search_base  = ou=People,dc=truelite,dc=it
query_filter = mail=%u@truelite.it
result_attribute = uid
version = 3
\end{FileExample}

Le altre principali direttive utilizzabili nel file di configurazione di una
tabella LDAP sono illustrate in tab.~\ref{tab:postfix_ldap_table}; un elenco
completo delle direttive, insieme ad una descrizione dettagliata del formato
del file, sono riportati nella apposita pagina di manuale accessibile con
\texttt{man ldap\_table}.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Direttiva} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{server\_host}  & indirizzo (o URL) del server LDAP.\\
    \texttt{server\_port}  & porta del server LDAP.\\
    \texttt{search\_base}  & base delle ricerche.\\
    \texttt{query\_filter} & filtro di ricerca, supporta le estensioni di
                             tab.~\ref{tab:postfix_ldap_expansion}.\\ 
    \texttt{result\_format}& una stringa di formattazione per i risultati
                             della ricerca.\footnotemark\\
    \texttt{result\_attribute}& attributo della voce restituita nella ricerca,
                             che viene preso come valore della tabella.\\
    \texttt{bind}          & indica che occorre collegarsi al server LDAP come
                             utente, prende i valori \texttt{yes} o
                             \texttt{no}.\\ 
    \texttt{bind\_dn}      & il \textit{Distinguished Name} dell'utente con
                             cui collegarsi al database.\\
    \texttt{bind\_pw}      & la password dell'utente indicato da
                             \texttt{bind\_dn}.\\ 
%    \texttt{size\_limit}   & .\\
%    \texttt{version}       & .\\
%    \texttt{} & .\\
    \hline 
  \end{tabular}
  \caption{Le direttive di configurazione di una tabella di Postfix su LDAP.}
  \label{tab:postfix_ldap_table}
\end{table}

\footnotetext{per le versioni precedenti Postfix 2.2 il nome di questa
  direttiva era \texttt{result\_filter}, ma poi è stato cambiato data la sua
  ambiguità.}


\subsection{Samba e LDAP}
\label{sec:ldap_samba}

Una delle applicazioni più interessanti di LDAP è quella della sua
integrazione con Samba, grazie alla quale diventa possibile fornire un
servizio di autenticazione centralizzato che può essere utilizzato in
contemporanea sia da sistemi Unix che da sistemi Windows. È infatti possibile
indicare a Samba di inserire le informazioni con cui effettua la gestione di
un \textsl{Dominio} Windows, comprese quelle dei relativi utenti, su
LDAP. 

Dato che Samba per poter funzionare necessita di associare gli utenti Windows
ad altrettanti utenti Unix, il presupposto per utilizzare Samba con LDAP è che
anche questi siano stati centralizzati su LDAP secondo quanto illustrato in
sez.~\ref{sec:ldap_user_management}.  Si tenga presente però che
l'autenticazione centralizzata nel mondo Windows è fondata su concetti
completamente diversi rispetto a quanto utilizzato in ambito Unix, e questo
porta ad una lunga serie di complicazioni. 

Una prima complicazione è che nel mondo Windows gli utenti di un
\textit{Domain Controller}\footnote{non entreremo nei dettagli della
  terminologia Windows, che si suppone nota.}  sono di due tipi, gli utenti
associati ad una persona, del tutto analoghi agli utenti Unix, e quelli
associati ad una macchina, corrispondenti al nome della stessa. Samba deve
poter mappare entrambi i tipi utenti di un dominio Windows su altrettanti
utenti di una macchina Unix, ma quelli associati ad una macchina non devono
essere usati come normali utenti, dato che ad esempio non necessitano di
credenziali di autenticazione. 

Per questo motivo, nell'inserire i dati di un dominio Samba su LDAP, sono
previsti due rami distinti, uno per gli utenti ordinari, che potranno
corrispondere anche ai normali utenti Unix, ed un altro per le macchine, ad
uso esclusivo di Samba.\footnote{questi ultimi sono riconoscibili, oltre che
  per l'uso di un ramo separato su LDAP, per il fatto che il nome della
  macchina viene inserito sull'albero aggiungendovi in fondo il carattere
  ``\texttt{\$}''.}  Questo comporta alcuni cambiamenti rispetto a quanto
visto in sez.~\ref{sec:ldap_NSS}, in quanto si dovranno rendere noti al
\textit{Name Service Switch} anche gli utenti associati alle macchine,
pertanto, si dovrà utilizzare per \texttt{libnss-ldap.conf} qualcosa del
tipo:\footnote{si è usata la suddivisione in rami diversi di utenti, macchine
  e gruppi su altrettante unità operative con lo schema di default prodotto
  dal programma \texttt{smbldap-populate} che tratteremo più avanti. }
\begin{FileExample}[label=libnss-ldap.conf]
nss_base_passwd    ou=Users,dc=truelite,dc=it?one
nss_base_passwd    ou=Computers,dc=domain,dc=local?one
nss_base_shadow    ou=Users,dc=truelite,dc=it?one
nss_base_group     ou=Groups,dc=truelite,dc=it?one
\end{FileExample}

Si noti come nell'esempio precedente si sia aggiunto, ma solo per
\texttt{nss\_base\_passwd}, il ramo delle macchine. Queste infatti non
corrispondono ad utenti ordinari Unix, e pertanto non necessitano né dell'uso
dei dati relativi a \texttt{nss\_base\_shadow}, né dei dati di
autenticazione. Per questo motivo non sono necessari cambiamenti alla
configurazione di PAM vista in sez.~\ref{sec:ldap_auth}.\footnote{a parte
  ovviamente indicare correttamente i DN dei rami di albero che si stanno
  utilizzando, che se si fa riferimento all'esempio precedente sono
  \texttt{ou=Users} per gli utenti e \texttt{ou=Groups} per i gruppi.}

\itindbeg{SID~(Security~ID)}

Una seconda complicazione nell'uso di Samba è quella relativa alla gestione
degli identificativi. Questi su Windows hanno una forma completamente diversa
rispetto ad Unix, ed ogni ``\textsl{oggetto}'' (utente, macchina, gruppo) è
associato ad un identificativo (il cosiddetto \textit{Security ID} o SID) che
si suppone debba essere univoco a livello globale. La parte iniziale del SID
infatti è diversa fra dominio e dominio, quindi la stessa macchina o lo stesso
utente avranno identificativi diversi in domini diversi. Questo può comportare
problemi nella migrazione dei dati da un server ad un altro, dato che in
genere fra due istanze diverse di Samba i SID non corrispondono.

\itindend{SID~(Security~ID)} 

Non tratteremo qui i dettagli relativi alla configurazione di Samba come
server di dominio, dando per acquisita la familiarità con il servizio e
limitandoci a trattare quanto attiene la interazione con LDAP.\footnote{per
  una introduzione all'uso di Samba si può consultare sez.~8.4.3 di
  \cite{AGL}.}  La direttiva principale che per dire a Samba di registrare le
sue informazioni su LDAP è ``\texttt{passdb backend}'', che nel caso deve
indicare l'utilizzo di LDAP attraverso la parola chiave \texttt{ldapsam},
seguita dalle modalità con cui contattare il server, un esempio di questa
direttiva è il seguente:
\begin{Example}
passdb backend = ldapsam:ldap://127.0.0.1/
\end{Example}
dove si fa riferimento ad una installazione locale cui accedere in chiaro; ma
\texttt{ldapsam} consente di usare URL generiche come quelle di
tab.~\ref{tab:ldap_URL}, e con queste specificare anche più di un server,
facendo seguire al separatore ``\texttt{:}'' una lista separata da spazi
racchiusa fra doppie virgolette.

Per poter eseguire la manutenzione dei suoi dati Samba necessita di poter
accedere al server LDAP con un utente che abbia adeguati privilegi di
scrittura; per questo la seconda direttiva essenziale è ``\texttt{ldap admin
  dn}'' che ne indica il \textit{Distinguished Name}. Molto spesso viene
consigliato di usare per questo un opportuno utente LDAP dedicato,
assegnandogli i diritti di accesso strettamente necessari, onde evitare che
Samba possa modificare dati di LDAP non attinenti.

Nella quasi totalità dei casi però i dati di un database sono solo quelli
degli utenti, cui comunque Samba deve poter accedere, per cui alla fine è
legittimo assumere che la complessità amministrativa di una tale scelta non
porti miglioramenti di sicurezza che ne giustifichino il costo, e si può anche
usare direttamente, come faremo nel seguito, l'utente di amministrazione del
database.

Si dovranno infine indicare a Samba quali sono le varie sezioni dell'albero su
cui vengono mantenuti i dati. Per far questo, come per configurare tutte le
modalità di interazione con LDAP, esistono una serie di direttive dedicate
introdotte dalla parola chiave \texttt{ldap}. Dato che l'interazione con LDAP
è generale queste direttive dovranno essere specificate all'interno della
sezione \texttt{global} di \texttt{smb.conf}.

Si sono illustrate le direttive specifiche per LDAP più significative in
tab.~\ref{tab:ldap_samba}, per un elenco completo si rimanda al solito alla
lettura della pagina di manuale del file di configurazione, accessibile con
\texttt{man smb.conf}.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Direttiva} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{ldap suffix}        & il suffisso che il ramo di albero contenente
                                  i dati che Samba mantiene su LDAP; prende
                                  come argomento il relativo DN.\\ 
    \texttt{ldap user suffix}   & la base della ricerca dei dati relativi 
                                  agli utenti; specificato come RDN rispetto
                                  al suffisso generale dato da
                                  \texttt{ldap suffix} (in genere è qualcosa
                                  del tipo \texttt{ou=users}).\\
    \texttt{ldap group suffix}  & la base della ricerca dei dati relativi
                                  ai gruppi di utenti, con la stessa
                                  sintassi del precedente (è in genere
                                  qualcosa del tipo \texttt{ou=group}).\\
    \texttt{ldap machine suffix}& la base della ricerca dei dati relativi agli
                                  account associati alle macchine del dominio
                                  (è in genere qualcosa del tipo
                                  \texttt{ou=computers}).\\
    \texttt{ldap idmap suffix}  & la base della ricerca dei dati relativi alle
                                  alla mappatura degli
                                  identificatori.\footnotemark\\ 
    \texttt{ldap admin dn}      & il \textit{Distinguished Name} dell'utente
                                  usato da Samba per operare sul server LDAP.\\
    \texttt{ldap delete dn}     & specifica se una operazione di cancellazione
                                  di un utente cancella tutta la voce su LDAP
                                  o soltanto la parte relativa a Samba.\\
    \texttt{ldap passwd sync}   & specifica se eseguire la sincronizzazione 
                                  della password Unix quando viene modificata
                                  quella Windows.\\ 
    \texttt{ldap ssl}           & indica se per il collegamento al server deve
                                  essere usato SSL o meno.\\
    \texttt{ldapsam:trusted}    & indica che tutti i dati relativi agli utenti
                                  e ai gruppi condivisi fra Unix e Samba sono
                                  interamente contenuti nell'albero LDAP, ed
                                  abilitando un accesso ottimizzato, prevede i
                                  valori \texttt{yes} e \texttt{no}.\\
    \hline 
  \end{tabular}
  \caption{Le direttive di Samba per la configurazione su LDAP.}
  \label{tab:ldap_samba}
\end{table}

\footnotetext{quella degli \texttt{idmap} è una funzionalità di Samba che
  permette di memorizzare le corrispondenze fra gli indicativi usati da
  Windows, e gli ID usati su sistemi Unix.}

Un esempio delle direttive necessarie per quanto riguarda la configurazione
dell'utilizzo di LDAP è riportato nel seguente estratto di \texttt{smb.conf},
preso dalla versione installata con il pacchetto \texttt{truelite-fileserver},
disponibile su \url{http://debian.truelite.it}:
\begin{FileExample}[label=smb.conf]
passdb backend = ldapsam:ldap://127.0.0.1/
ldapsam:trusted = yes
ldap passwd sync = yes
ldap admin dn = cn=admin,dc=truelite,dc=it
ldap suffix = dc=truelite,dc=it
ldap group suffix = ou=Groups
ldap user suffix = ou=Users
ldap machine suffix = ou=Computers
ldap ssl = off
\end{FileExample}

Si noti che fra le direttive di tab.~\ref{tab:ldap_samba} non ne esiste
nessuna che indichi la password con la quale collegarsi al server LDAP, non
esiste cioè l'analogo di \texttt{bindpw} che avevamo visto in
sez.~\ref{sec:ldap_NSS}.  Questa infatti deve essere impostata manualmente con
il comando \texttt{smbpasswd}, che prevede l'uso dell'apposita opzione
\texttt{-w} che memorizza nei file di gestione di Samba\footnote{per la
  precisione in \texttt{/var/lib/secrets.tdb}.} la password da usare in
corrispondenza al DN indicato dalla direttiva ``\texttt{ldap admin dn}'' per
collegarsi al server LDAP.  Per far sì che Samba sia in grado di appoggiarsi a
LDAP si dovrà dunque eseguire a parte il comando:
\begin{Console}
# \textbf{smbpasswd -w password_difficile_e_segreta}
\end{Console}

Ovviamente oltre a configurare Samba per utilizzare LDAP, occorrerà anche
configurare il server LDAP per fornire a Samba il supporto necessario. A
questo scopo il primo punto è quello di attivare l'uso delle
\textit{objectclass} che definiscono gli attributi e gli oggetti aggiuntivi
usati da Samba per mantenere le informazioni che gli sono necessarie. 

Per questo insieme a Samba viene distribuito un file \texttt{samba.schema} che
contiene le definizioni di tutte le \textit{objectclass} e gli attributi
occorrenti.\footnote{nel caso di Debian il file viene distribuito col
  pacchetto \texttt{samba-doc}, ed installato in forma compressa sotto
  \texttt{/usr/share/samba-doc/examples/LDAP/samba.schema.gz}, per
  RedHat/CentOS/Fedora si trova nel file
  \texttt{/usr/share/doc/samba-<versione>/LDAP/samba.schema}, e altrimenti può
  essere trovato nella directory \texttt{examples/LDAP/samba.schema} dei
  sorgenti di Samba.} Detto file dovrà essere copiato in
\texttt{/etc/ldap/schema} e si dovrà riconfigurare \texttt{slapd.conf}
aggiungendo alle altre direttive di inclusione degli schemi una riga del tipo:
\begin{Example}
include       /etc/ldap/schema/samba.schema
\end{Example}

In tab.~\ref{tab:ldap_samba_attributes} si sono illustrati i principali
attributi della \textit{objectclass} ausiliaria \objcl{sambaSamAccount}, che
è l'analoga della \texttt{posixAccount} vista in
sez.~\ref{sec:ldap_userdata_management} per gli utenti Unix, a cui deve essere
abbinata per aggiungere quanto necessario per Samba. In questo modo alle voci
già presenti per definite un utente Unix si potranno impostare anche gli
ulteriori attributi che mantengono le informazioni usate da Samba.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Attributo} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{sambaNTPassword}   & password nel formato NT (hash MD4 della
                                 password in Unicode).\\
    \texttt{sambaLMPassword}   & password nel formato LAN manager.\\
    \texttt{sambaPwdLastSet}   & tempo di ultima modifica delle
                                 password.\footnotemark \\
    \texttt{sambaPwdMustChange}& tempo in cui la password dovrà essere 
                                 modificata.\\
    \texttt{sambaKickoffTime}  & tempo in cui l'account sarà bloccato, analogo
                                 dell'attributo \texttt{shadowExpire} di
                                 \texttt{shadowAccount} (vedi
                                 tab.~\ref{tab:ldap_user_attributes}).\\
    \texttt{sambaPasswordHistory}&password precedenti, non potranno essere
                                 riutilizzate al momento della modifica della
                                 password.\\
    \texttt{sambaSID}          & \textit{Security ID} (SID) dell'utente.\\
    \texttt{sambaPrimaryGroupSID}& \textit{Security ID} (SID) del gruppo 
                                 principale dell'utente.\\
    \texttt{sambaAcctFlags}    & flag, una stringa di 11 caratteri delimitata 
                                 da parentesi quadre che definisce le
                                 caratteristiche dell'account.\\
    \texttt{sambaDomainName}   & dominio Windows di cui l'utente fa parte.\\
%    \texttt{}& .\\
    \hline 
  \end{tabular}
  \caption{I principali attributi della \textit{objectclass}
    \texttt{sambaSamAccount} usata da Samba per mantenere i dati di un
    utente.}
  \label{tab:ldap_samba_attributes}
\end{table}

\footnotetext{tutti i tempi usati da Samba in questo e negli altri attributi
  sono espressi nel cosiddetto \textit{unix-time}, vale a dire in numero di
  secondi a partire dal 1 Gennaio 1970.}

Analogamente, per mantenere le informazioni relative ai gruppi di dominio,
occorrerà abbinare a \texttt{posixGroup} la \textit{objectclass} ausiliaria
\objcl{sambaGroupMapping}. Oltre a queste due nel file \texttt{samba.schema}
sono definite alcune ulteriori \textit{objectclass} che consentono a Samba di
mantenere su LDAP anche altri dati relativi alla gestione di un dominio
Windows.

Come accennato è inoltre necessario che l'utente specificato dalla direttiva
``\texttt{ldap admin dn}'' abbia sufficienti privilegi di accesso, ed inoltre
si dovrà permettere agli utenti di modificare le informazioni relative al
proprio account. Per far questo devono essere impostate delle ACL opportune
per i nuovi attributi; un esempio di quanto è necessario aggiungere a
\texttt{slapd.conf} è il seguente estratto della versione di
\texttt{slapd.conf} usata nel citato pacchetto \texttt{truelite-fileserver}:
\begin{FileExample}[label=slapd.conf]
access to attrs=userPassword,sambaNTPassword,sambaLMPassword
        by dn="cn=admin,dc=truelite,dc=it" write
        by anonymous auth
        by self write
        by * none

access to attrs=description,telephoneNumber,shadowLastChange,sambaPwdLastSet,
                sambaPwdMustChange,sambaPasswordHistory
        by dn="cn=admin,dc=truelite,dc=it" write
        by self write
        by * read
\end{FileExample}

Occorrerà inoltre, se si vogliono avere prestazioni accettabili, indicizzare
opportunamente gli ulteriori attributi usati da Samba; un esempio di
configurazione, sempre estratto dalla versione di \texttt{slapd.conf} usata
nel pacchetto \texttt{truelite-fileserver}, è il seguente:
\begin{FileExample}[label=slapd.conf]
index   objectClass                                     eq
index   cn,sn,displayName,givenName,mail,sambaSID       eq,sub
index   uid,uidNumber,gidNumber,memberUid               eq
index   sambaPrimaryGroupSID,sambaDomainName            eq
index   sambaSIDList,sambaGroupType                     eq
index   uniqueMember                                    eq
\end{FileExample}


Infine, come per la centralizzazione degli utenti Unix, anche in questo caso è
necessario che le informazioni siano adeguatamente strutturate all'interno
dell'albero. Questa struttura è analoga a quella già vista in
sez.~\ref{sec:ldap_userdata_management}, dato che questa deve essere
riutilizzata per la parte di utenti e gruppi; ma come accennato si avrà
necessità di almeno di un ramo ulteriore per mantenere gli elenchi delle
macchine nel dominio.\footnote{e di un altro ramo qualora si intenda usare gli
  \textit{idmap}.}

Si tenga presente che molti dei dati utilizzati da Samba sono del tutto
indipendenti rispetto agli analoghi di sez.~\ref{sec:ldap_user_management} per
le credenziali degli utenti Unix, in particolare Samba utilizza dei dati
propri sia per gli identificativi che per le password. Questo comporta una
ulteriore complicazione, se infatti lo scopo è quello di unificare le
autenticazioni in un ambiente misto, occorrerà assicurarsi che le credenziali
degli utenti (ed in particolare la password) siano sempre le stesse, sia per la
parte Windows gestita da Samba che per quella Unix gestita da PAM.

Il problema che può sorgere è che un utente Unix cambi la sua password, ad
esempio con \texttt{passwd}, modificando su LDAP solo l'attributo
\texttt{userPassword}, mentre la relativa password per Windows che viene
mantenuta negli appositi attributi illustrati in
tab.~\ref{tab:ldap_samba_attributes} resta invariata.  Nel caso opposto è
possibile dire a Samba, con la direttiva \texttt{ldap passwd sync}, di
mantenere sincronizzate tutte le password, ma questo comporta comunque che in
un ambiente misto operazioni come il cambiamento della password debbano essere
gestite in maniera opportuna.

Per questo motivo esistono vari programmi di ausilio che consentono di
eseguire una gestione \textsl{unificata} degli utenti, tenendo conto
automaticamente di queste problematiche di sincronizzazione. In questo ambito
i più utilizzati sono i cosiddetti \texttt{smbldap-tools},\footnote{in Debian
  sono installabili direttamente tramite l'omonimo pacchetto.} un insieme di
script in Perl che consente di gestire su LDAP le credenziali di
autenticazione per un ambiente misto Unix/Windows.\footnote{con la versione
  3.0.23 di Samba alcune di queste funzionalità sono state inserite
  direttamente all'interno di Samba, e possono essere gestite con il comando
  \texttt{net}.}

% TODO vedere/trattare l'uso del comando net per la gestione utenti

Questi script ricalcano il principio di funzionamento del programma
\texttt{cpu} illustrato in sez.~\ref{sec:ldap_userdata_management}, e
forniscono una serie di comandi (\texttt{smbldap-useradd},
\texttt{smbldap-userdel}, \texttt{smbldap-usermod} e gli analoghi per i
gruppi) che hanno una sintassi praticamente identica ai relativi comandi
classici, ma effettuano la gestione di utenti e gruppi sull'albero LDAP,
tenendo anche conto, a differenza di quanto avviene per \texttt{cpu}, della
necessità di mantenere anche le informazioni usate da Samba.

Dato che questi programmi operano direttamente sui dati di LDAP, occorre
configurarli opportunamente in modo da consentire loro l'accesso; questo viene
fatto attraverso due file di configurazione in \texttt{/etc/smbldap/}. Il
primo file è \texttt{smbldap\_bind.conf}, che contiene esclusivamente i dati
da usare per il collegamento al server, vale a dire il DN dell'utente con cui
collegarsi e la relativa password. Dato che i comandi supportano l'utilizzo di
due server (un master ed uno slave) esistono in tutto quattro direttive da
usare, illustrate in tab.~\ref{tab:ldap_smbldap_bind}. 

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Direttiva} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{masterDN} & il \textit{Distinguished Name} dell'utente usato per
                        collegarsi al server LDAP.\\ 
    \texttt{slaveDN}  & il \textit{Distinguished Name} dell'utente usato per
                        collegarsi ad un eventuale server LDAP secondario.\\ 
    \texttt{masterPw} & la password dell'utente usato per
                        collegarsi al server LDAP principale.\\ 
    \texttt{slavePw}  & la password dell'utente usato per collegarsi ad un
                        eventuale server LDAP secondario.\\  
    \hline 
  \end{tabular}
  \caption{Le direttive di configurazione del file
    \texttt{smbldap\_bind.conf}.}
  \label{tab:ldap_smbldap_bind}
\end{table}

Siccome i dati mantenuti in \texttt{smbldap\_bind.conf} prevedono la presenza
della password di accesso in chiaro, detto file deve essere protetto da
lettura. Si tenga conto che l'esistenza di un server secondario è del tutto
opzionale, qualora non esista basterà usare gli stessi valori indicati per il
primario; un esempio del contenuto di questo file è il seguente:
\begin{FileExample}[label=smbldap\_bind.conf]
slaveDN="cn=admin,dc=truelite,dc=it"
slavePw="password_segretissima"
masterDN="cn=admin,dc=truelite,dc=it"
masterPw="altra_password_altrettanto_segreta"
\end{FileExample}

Tutte le restanti configurazioni sono invece mantenute nel file
\texttt{smbldap.conf}, a partire dall'indicazione del server a cui rivolgersi,
del ramo di albero su cui sono mantenute le informazioni, le modalità per
eseguire le ricerche ed una serie di valori di default da utilizzare nella
gestione di utenti e gruppi e per la configurazione di varie caratteristiche
di Samba. 

Il file \texttt{smbldap.conf} è sostanzialmente uno spezzone di codice Perl
che viene incluso dai vari comandi dei \texttt{smbldap-tools}, per cui le
\textsl{direttive} sono tutte nella forma di una assegnazione di variabile
(giacché in realtà proprio di questo si tratta) in cui il valore assegnato è
fra virgolette.\footnote{e nell'assegnazione si può anche fare riferimento al
  valore di un'altra variabile con la sintassi \texttt{\$\{variabile\}}.}

Le principali direttive (o variabili, a seconda del punto di vista) sono
illustrate brevemente in tab.~\ref{tab:ldap_smbldap_conf}, il file di
configurazione installato di default normalmente è ampiamente commentato con
una descrizione dettagliata del significato di ciascuna variabile.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|p{8cm}|}
    \hline
    \textbf{Direttiva} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{masterLDAP} & indirizzo IP del server LDAP.\\ 
    \texttt{masterPort} & porta del server LDAP.\\ 
    \texttt{slaveLDAP}  & indirizzo IP di un eventuale server LDAP
                          secondario.\\  
    \texttt{slavePort}  & porta di un eventuale server LDAP secondario.\\ 
    \texttt{suffix}     & la base della sezione di albero su cui sono
                          mantenuti i dati degli account; in genere coincide
                          con la base dell'albero stesso.\\
    \texttt{usersdn}    & il DN della sezione di albero su cui sono mantenuti
                          i dati degli utenti.\\
    \texttt{groupsdn}   & il DN della sezione di albero su cui sono mantenuti
                          i dati dei gruppi.\\
    \texttt{computersdn}& il DN della sezione di albero su cui sono mantenuti
                          i dati delle macchine.\\
    \texttt{scope}      & la \textsl{profondità} della ricerca (secondo i
                          valori di tab.~\ref{tab:ldap_scope_values}).\\ 
    \hline 
    \texttt{SID}        & il suffisso dei \textit{Security ID} del dominio.\\  
    \hline 
    \texttt{userLoginShell}& la shell di default assegnata ai nuovi utenti.\\ 
    \texttt{defaultUserGid}& il \textsl{group-id} del gruppo di default
                          assegnato ai nuovi utenti.\\ 
    \texttt{defaultComputerGid}& il \textsl{group-id} del gruppo di default 
                          assegnato agli utenti usati per identificare le
                          macchine nel dominio.\\ 
    \texttt{skeletonDir}& la directory da cui prendere i file da mettere nella
                          home di un nuovo utente.\\
    \texttt{userSmbHome}& lo share su cui viene mappata la directory 
                          home dell'utente.\\ 
    \texttt{userProfile}& lo share su cui sono mantenuti i profili degli
                          utenti. \\ 
    \texttt{userHomeDrive}& il disco Windows su cui viene mappato la directory 
                          home dell'utente.\\  
    \texttt{userScript} & lo script di avvio per Windows (preso dalla home
                          dell'utente) che viene eseguito all'ingresso nel
                          dominio.\\  
%    \texttt{} & .\\ 
    \hline 
  \end{tabular}
  \caption{Le direttive di configurazione del file \texttt{smbldap.conf}.}
  \label{tab:ldap_smbldap_conf}
\end{table}

Le direttive essenziali sono \texttt{masterLDAP} e \texttt{masterPort} che
permettono di indicare l'indirizzo del server (e rispettiva porta) a cui
rivolgersi, la maggior parte delle altre (quelle riportate nella prima parte
di tab.~\ref{tab:ldap_smbldap_conf}) servono ad impostare le caratteristiche
della connessione al server, (ad esempio \texttt{suffix} indica la base
dell'albero, e le varie \texttt{*dn} specificano poi i sottorami in cui sono
mantenute le varie informazioni).  Una serie di altre direttive (quelle
riportate nella parte finale di tab.~\ref{tab:ldap_smbldap_conf}) permettono
invece di impostare caratteristiche standard degli utenti creati con i comandi
degli \texttt{smbldap-tools}, (ad esempio la shell di login con
\texttt{userLoginShell}, o la directory da usare per mantenere i profili
Windows con \texttt{userProfile}).

Un ruolo particolare è però quello svolto dalla direttiva \texttt{SID}, essa
infatti indica il \textit{Security ID} del dominio Samba; e serve come
suffisso a tutti gli identificativi usati in ambito Windows. Questo valore non
può essere assegnato a piacere, ma deve corrispondere a quello usato da Samba,
pertanto prima di poter usare gli \texttt{smbldap-tools} occorrerà eseguire il
comando:
\begin{Console}
# \textbf{net getlocalsid}
SID for domain DOMAIN is: S-1-5-21-1911238739-97561441-2706018148
\end{Console}
sulla macchina su cui gira il server Samba, per ottenere il valore da
assegnare a questa variabile.\footnote{in genere il \textit{Security ID} viene
  impostato autonomamente da Samba al proprio interno.} Questo infatti deve
corrispondere ai valori che Samba mantiene internamente, altrimenti i dati di
LDAP saranno considerati come appartenenti ad utenti di un altro dominio ed
ignorati.

Qualora si avesse un albero già popolato di dati, e quindi con una serie di
SID già determinati, sarebbe comunque possibile forzare Samba ad utilizzare un
SID diverso da quello adottato internamente con il comando:
\begin{Console}
# \textbf{net setlocalsid S-1-5-21-1911238739-97561441-2706018148}
\end{Console}

Per concludere un esempio del contenuto del file \texttt{smbldap.conf}, preso
dall'estratto di una configurazione creata da pacchetto
\texttt{truelite-fileserver} citato in precedenza, è il seguente:
\begin{FileExample}[label=smbldap.conf]
SID="S-1-5-21-1911238739-97561441-2706018148"
sambaDomain="DOMAIN"
slaveLDAP="127.0.0.1"
slavePort="389"
masterLDAP="127.0.0.1"
masterPort="389"
...
usersdn="ou=Users,${suffix}"
computersdn="ou=Computers,${suffix}"
groupsdn="ou=Groups,${suffix}"
idmapdn="ou=Idmap,${suffix}"
...
userLoginShell="/bin/bash"
userHome="/home/%U"
userGecos="System User"
defaultUserGid="513"
defaultComputerGid="515"
skeletonDir="/etc/skel"
defaultMaxPasswordAge="175"
userSmbHome=""
userProfile=""
userHomeDrive="H:"
userScript="%U.cmd"
...
\end{FileExample}

Una volta completata la configurazione in genere il primo passo che è quello
di usare il comando \index{comando!\texttt{smbldap-populate}}
\texttt{smbldap-populate}, che permette di creare su LDAP l'infrastruttura
iniziale necessaria per gestire gli utenti di un dominio Windows, in maniera
analoga alla procedura che si è vista in
sez.~\ref{sec:ldap_userdata_management} con l'uso dei \texttt{migrationtools}.

Una delle caratteristiche del comando è quella di creare, oltre ad una serie
di gruppi standard dei domini Windows, un utente ospite per l'accesso anonimo
(il default è \texttt{nobody}, ma lo si può cambiare specificando un nome
diverso con l'opzione \texttt{-b}) ed un utente amministratore del dominio (il
default è \texttt{Admininistrator}, che come prima può essere cambiato, usando
l'opzione \texttt{-a}). Quest'ultimo è molto importante, dato che è l'utente
per conto del quale si potranno aggiungere macchine al dominio. Altre due
opzioni supportate sono \texttt{-e} che invece di inserire i dati li esporta
su un file LDIF (specificato come parametro dell'opzione) e \texttt{-i} che
crea l'infrastruttura leggendola da un file LDIF (sempre passato come
parametro).

Alla sua esecuzione il comando chiede la password dell'amministratore
(l'utente ospite è senza password) ed esegue la creazione dell'infrastruttura
notificando a video la creazione delle varie voci, con un qualcosa del tipo:
\begin{Console}
# \textbf{smbldap-populate}
Using workgroup name from sambaUnixIdPooldn (smbldap.conf): sambaDomainName=DOMAIN
Using builtin directory structure
entry dc=truelite,dc=it already exist.
adding new entry: ou=Users,dc=truelite,dc=it
adding new entry: ou=Groups,dc=truelite,dc=it
adding new entry: ou=Computers,dc=truelite,dc=it
adding new entry: ou=Idmap,dc=truelite,dc=it
entry sambaDomainName=DOMAIN,dc=truelite,dc=it already exist. Updating it...
adding new entry: uid=admin,ou=Users,dc=truelite,dc=it
adding new entry: uid=nobody,ou=Users,dc=truelite,dc=it
adding new entry: cn=Domain Admins,ou=Groups,dc=truelite,dc=it
adding new entry: cn=Domain Users,ou=Groups,dc=truelite,dc=it
adding new entry: cn=Domain Guests,ou=Groups,dc=truelite,dc=it
adding new entry: cn=Domain Computers,ou=Groups,dc=truelite,dc=it
adding new entry: cn=Administrators,ou=Groups,dc=truelite,dc=it
adding new entry: cn=Print Operators,ou=Groups,dc=truelite,dc=it
adding new entry: cn=Backup Operators,ou=Groups,dc=truelite,dc=it
adding new entry: cn=Replicators,ou=Groups,dc=truelite,dc=it
Changing password for admin
New password :
Retype new password :
\end{Console}

Una volta che l'infrastruttura iniziale dell'albero è a posto, i vari comandi
del pacchetto consentiranno di creare, cancellare e modificare i dati di
utenti e gruppi operando direttamente su LDAP, mantenendo allo stesso tempo la
coerenza degli stessi per il loro utilizzo sia da parte di Samba che da parte
di PAM e NSS ed ottenere un meccanismo di gestione centralizzata sia in
ambiente Unix che Windows. In tab.~\ref{tab:ldap_smbldap_commands} si è
riportato un riassunto dei vari comandi che fanno parte degli
\textit{smbldap-tools}.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|l|l|}
    \hline
    \textbf{Comando} & \textbf{Scopo} \\
    \hline
    \hline
    \texttt{smbldap-populate}& crea l'infrastruttura iniziale dei dati su
                               LDAP.\\
    \texttt{smbldap-useradd} & crea un nuovo utente.\\ 
    \texttt{smbldap-usermod} & modifica le caratteristiche di un utente.\\ 
    \texttt{smbldap-userdel} & cancella un utente.\\ 
%    \texttt{smbldap-usershow}& .\\
%    \texttt{smbldap-userchfn}& .\\
    \texttt{smbldap-groupadd}& aggiunge un gruppo.\\
    \texttt{smbldap-groupmod}& modifica le caratteristiche di un gruppo.\\
    \texttt{smbldap-groupdel}& cancella un gruppo.\\ 
    \texttt{smbldap-passwd}  & cambia la password di un utente.\\ 
%    \texttt{smbldap-}& .\\ 
    \hline
  \end{tabular}
  \caption{I comandi che fanno parte del pacchetto \texttt{smbldap-tools}.}
  \label{tab:ldap_smbldap_commands}
\end{table}


I comandi per creare, modificare e cancellare un utente sono rispettivamente
\texttt{smbldap-useradd}, \texttt{smbldap-usermod} e
\index{comando!\texttt{smbldap-userdel}} \texttt{smbldap-userdel}.
Quest'ultimo prende come unica opzione \texttt{-r}, che se specificata rimuove
anche la home directory dell'utente. I primi due supportano un insieme comune
di opzioni, le principali delle quali sono illustrate in
tab.~\ref{tab:ldap_smbldap_user_common}. La tabella è suddivisa in due
sezioni, in alto si sono riportate le opzioni relative all'ambiente Unix,
simili a quelle degli analoghi comandi classici, ed in basso quelle relative
all'ambiente Windows. Per un elenco completo si può al solito fare riferimento
alle pagine di manuale dei vari comandi.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|c|p{8cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{-g}& imposta il gruppo principale dell'utente, se non
                 specificato viene usato il valore corrispondente a quanto
                 indicato da \texttt{defaultUserGid}.\\
    \texttt{-G}& imposta una lista (specificata come elenco separato da
                 virgole) di gruppi ausiliari di cui l'utente è membro, se non
                 specificato l'utente sarà membro solo del suo gruppo
                 principale.\\
    \texttt{-P}& termina invocando \texttt{smbldap-passwd} per impostare una 
                 password per l'utente.\\ 
    \texttt{-s}& imposta la shell passata come parametro come shell di
                 default.\\ 
    \texttt{-u}& imposta un valore numerico (passato come parametro) per 
                 l'\textsl{uid} dell'utente.\\ 
%    \texttt{-}& .\\ 
%    \texttt{-}& .\\ 
    \hline
%    \texttt{-A}& imposta la proprietà che consente o meno (rispettivamente
%                 valori 0 e 1) all'utente Windows di cambiare la propria
%                 password.\\  
    \texttt{-B}& imposta la proprietà che forza l'utente Windows a eseguire il
                 cambiamento della password al primo accesso; prende
                 rispettivamente i valori 0 (no) e 1 (si).\\  
    \texttt{-C}& imposta lo share su cui viene mappata la directory home
                 dell'utente.\\
    \texttt{-D}& imposta la lettera associata al disco Windows su cui viene
                 mappata la directory home dell'utente.\\ 
    \texttt{-E}& imposta lo script Windows eseguito all'ingresso nel
                 dominio.\\  
    \texttt{-F}& imposta lo share usata per mantenere i profili dell'utente.\\ 
%    \texttt{-}& .\\ 
    \hline
  \end{tabular}
  \caption{Le opzioni comuni dei comandi \texttt{smbldap-useradd} e
    \texttt{smbldap-usermod}.}
  \label{tab:ldap_smbldap_user_common}
\end{table}

Il comando \index{comando!\texttt{smbldap-useradd}} \texttt{smbldap-useradd}
prende come argomento l'username dell'utente da creare, e rispetto a quelle
già illustrate in tab.~\ref{tab:ldap_smbldap_user_common} prevede alcune
opzioni specifiche, riportate in tab.~\ref{tab:ldap_smbldap_useradd}. In
genere lo si invoca semplicemente con \texttt{-m} per richiedere la creazione
della home directory e con \texttt{-a} per avere un utente utilizzabile anche
in ambito Windows.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|c|p{8cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{-a}& aggiunge le \textit{objectclass} e gli attributi necessari per
                 mantenere i valori delle credenziali in ambito Windows.\\ 
    \texttt{-m}& crea la home directory dell'utente se non esiste già.\\ 
    \texttt{-k}& copia i file della directory definita da \texttt{skeletonDir}
                 nella home dell'utente, altrimenti viene usata
                 \texttt{/etc/skel} (valida solo se congiunta a
                 \texttt{-m}).\\
    \texttt{-w}& crea un utente speciale da associare ad una workstation nel
                 dominio (ad uso di Samba per la gestione delle macchine nel
                 dominio).\\
    \hline
  \end{tabular}
  \caption{Le opzioni specifiche del comando \texttt{smbldap-useradd}.}
  \label{tab:ldap_smbldap_useradd}
\end{table}

Per modificare le caratteristiche di un utente già presente si può invece
usare il comando \index{comando!\texttt{smbldap-usermod}}
\texttt{smbldap-usermod} che prende come argomento il nome dell'utente. Le
principali opzioni specifiche di questo comando sono riportate in
tab.~\ref{tab:ldap_smbldap_usermod}.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|c|p{8cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{-e}& imposta una data di scadenza dell'account.\\ 
    \texttt{-L}& disabilita l'utente lato Unix.\\ 
    \texttt{-U}& riabilita l'utente lato Unix.\\ 
    \texttt{-I}& disabilita l'utente lato Windows.\\ 
    \texttt{-J}& riabilita l'utente lato Windows.\\ 
    \hline
  \end{tabular}
  \caption{Le opzioni specifiche del comando \texttt{smbldap-usermod}.}
  \label{tab:ldap_smbldap_usermod}
\end{table}

Infine per modificare la password di un utente, con la sicurezza che questa
venga aggiornata sia per quanto riguarda la parte usata in ambiente Unix e per
LDAP stesso (in sostanza l'attributo \texttt{userPassword}) che per l'ambiente
Windows (gli attributi usati da Samba allo scopo), è disponibile il comando
\index{comando!\texttt{smbldap-passwd}} \texttt{smbldap-passwd}, che prende
come argomento il nome utente e chiede (due volte, la seconda per conferma) la
nuova password. Il comando prende solo due opzioni: \texttt{-u} per modificare
solo la password Unix e \texttt{-s} per modificare solo quella Windows.

Come avviene per comandi classici anche negli \texttt{smbldap-tools} sono
presenti degli opportuni script per operare sui gruppi; in particolare i
comandi analoghi ai precedenti visti per gli utenti sono
\texttt{smbldap-groupadd}, \texttt{smbldap-groupmod} e
\index{comando!\texttt{smbldap-groupdel}} \texttt{smbldap-groupdel};
quest'ultimo permette di cancellare un gruppo, passato come argomento, e non
ha nessuna opzione, gli altri due invece supportano alcune opzioni comuni, le
principali delle quali riportate in tab.~\ref{tab:ldap_smbldap_group_common}.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|c|p{8cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{-g}& imposta il valore numerico del \textsl{gid} al valore
                 passato come parametro.\\
    \texttt{-a}& aggiunge automaticamente al gruppo un SID opportuno  
                 per renderlo utilizzabile in ambito Windows.\\ 
    \texttt{-s}& imposta il valore del SID del gruppo al valore passato come
                 parametro.\\
%    \texttt{-}& .\\ 
    \hline
  \end{tabular}
  \caption{Le opzioni comuni dei comandi \texttt{smbldap-groupadd} e
    \texttt{smbldap-groupmod}.}
  \label{tab:ldap_smbldap_group_common}
\end{table}

Un nuovo gruppo può essere creato con il comando
\index{comando!\texttt{smbldap-groupadd}} \texttt{smbldap-groupadd},
specificando il nome del gruppo. In genere l'unica opzione che si usa è
\texttt{-a} per richiedere al comando anche la creazione dei dati che verranno
utilizzati da Samba per gestire le credenziali per Windows. Altre
caratteristiche possono essere impostate manualmente con le opzioni di
tab.~\ref{tab:ldap_smbldap_group_common}. 

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|c|p{8cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{-x}& elimina dal gruppo la lista degli utenti (separata da virgole)
                 passata come parametro.\\ 
    \texttt{-m}& aggiunge al gruppo la lista degli utenti (separata da virgole)
                 passata come parametro.\\ 
    \texttt{-n}& modifica il nome del gruppo sostituendolo con quello passato
                 come parametro.\\ 
    \hline
  \end{tabular}
  \caption{Le opzioni specifiche del comando \texttt{smbldap-groupmod}.}
  \label{tab:ldap_smbldap_groupmod}
\end{table}


Una volta creato un gruppo può essere modificato con il comando
\index{comando!\texttt{smbldap-groupmod}} \texttt{smbldap-groupmod}, che di
nuovo prende come argomento il nome del gruppo. Oltre a quelle illustrate in
tab.~\ref{tab:ldap_smbldap_group_common} le altre opzioni rilevanti specifiche
di questo comando sono state elencate in
tab.~\ref{tab:ldap_smbldap_group_common}.



\subsection{Squid e LDAP}
\label{sec:ldap_squid}

Come proxy per l'accesso alle pagine web, una delle caratteristiche di Squid è
quella di consentire l'accesso al servizio solo ad utenti autenticati, ed una
delle modalità di autenticazione supportate è appunto quella che ricorre ai
dati mantenuti su un server LDAP.

Per utilizzare questa funzionalità occorre anzitutto richiedere a Squid di
abilitare l'autenticazione degli utenti; per poter usare utenti mantenuti su
LDAP l'unico \textsl{schema}\footnote{Squid supporta tre schemi di
  autenticazione, \texttt{basic}, \texttt{ntml} e \texttt{digest},
  corrispondenti a tre diversi metodi di richiedere le credenziali al client.
  Si tenga presente che l'autenticazione \texttt{basic} trasmette in chiaro le
  credenziali stesse, per cui si possono avere degli ovvi problemi di
  sicurezza.} disponibile è \texttt{basic}.\footnote{in realtà appoggiandosi a
  Samba (vedi sez.~\ref{sec:ldap_samba}) si potrebbe usare anche
  l'autenticazione NTML, ma questo non riguarda più l'interazione fra Squid e
  LDAP, ma fra Squid ed un generico PDC Windows.} La direttiva di base che
permette di impostare l'autenticazione degli utenti è \texttt{auth\_param},
che prende come primo argomento lo schema da utilizzare (nel nostro caso
\texttt{basic}), e come terzo argomento il parametro da configurare.

La direttiva deve essere ripetuta per ciascun parametro che si intende
configurare, ma quello principale è \texttt{program}, che consente di indicare
il programma da utilizzare per autenticare gli utenti, che nel caso si voglia
usare LDAP è appunto \texttt{ldap\_auth}; un esempio possibile di uso di
questa configurazione è allora quello presa dal seguente estratto di
\texttt{squid.conf}:
\begin{FileExample}[label=squid.conf]
auth_param basic children 5
auth_param basic credentialsttl 30 minutes
auth_param basic realm Truelite Proxy Server
auth_param basic program /usr/lib/squid/ldap_auth \
    -b "ou=Users,dc=truelite,dc=it" -v3 -f(uid=%s) -h localhost
\end{FileExample}

Nel nostro caso, volendo autenticare gli utenti su LDAP, ricorreremo
all'apposito programma \index{comando!\texttt{ldap\_auth}} \texttt{ldap\_auth}
(distribuito insieme con Squid) il cui unico scopo è interrogare il server per
autenticare l'utente. Il programma richiede come opzione obbligatoria
\texttt{-b} che specifica la base dell'albero, e di default si collega su
\textit{localhost}. Si può specificare un server diverso per indirizzo con
\texttt{-h} o con una URL estesa (quelle di tab.~\ref{tab:ldap_URL}) con
\texttt{-H}; le altre principali opzioni sono riportate in
tab.~\ref{tab:ldap_squid_ldap_auth}.

\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|c|p{8cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{-b}& specifica la base dell'albero, passata come parametro.\\ 
    \texttt{-f}& consente di impostare un filtro, passato come parametro, con 
                 cui eseguire la ricerca degli utenti.\\ 
    \texttt{-u}& consente di impostare l'attributo, passato come parametro, da
                 utilizzare per la ricerca del nome utente.\\ 
    \texttt{-s}& consente di specificare la profondità della ricerca, prende
                 come parametro uno dei valori di
                 tab.~\ref{tab:ldap_scope_values}.\\ 
    \texttt{-D}& specifica un eventuale DN con cui collegarsi al server
                 LDAP.\\
    \texttt{-h}& specifica l'indirizzo del server LDAP.\\ 
    \texttt{-H}& imposta la URL a cui contattare il server LDAP.\\ 
    \texttt{-p}& specifica la porta da utilizzare per la connessione.\\ 
    \texttt{-v}& imposta la versione di protocollo da usare (prende i valori 2
                 e 3, ed il default, da cambiare, è 2).\\ 
%    \texttt{-t}& imopsta un timeout (in secondi) per la connessione.\\ 
%    \texttt{-Z}& richiede l'uso di TLS sulla connessione al server.\\ 
%    \texttt{-}& .\\ 
    \hline
  \end{tabular}
  \caption{Le opzioni del programma \texttt{ldap\_auth} usato da Squid per
    l'autenticazione su LDAP.}
  \label{tab:ldap_squid_ldap_auth}
\end{table}

Una volta abilitata l'autenticazione degli utenti, ed istruito Squid ad
eseguire la ricerca degli stessi su LDAP, sarà possibile impostare il
controllo di accesso per fornire il servizio solo agli utenti autenticati. Per
farlo occorre anzitutto impostare una ACL di tipo \texttt{proxy\_auth}, ed
utilizzarla in una direttiva di accesso, cioè utilizzare qualcosa del
tipo:\footnote{si ricordi anche che le regole che usano una ACL di tipo
  \texttt{proxy\_auth} devono usualmente essere specificata per ultime, in
  quanto una volta determinato che l'utente è valido, una tale regola consente
  l'accesso e tutto è permesso; occorre quindi impostare in precedenza le
  eventuali ulteriori restrizioni (ad esempio sui siti non raggiungibili) da
  applicare agli utenti autenticati.}
\begin{Example}
acl password proxy_auth REQUIRED
http_access allow password
\end{Example}

Se tutto quello che interessa è consentire un accesso generico agli utenti
autenticati questo è sufficiente, Squid però consente anche un controllo molto
più dettagliato, che permette di impostare ACL diverse a seconda del gruppo di
cui gli utenti fanno parte, anch'esso mantenuto su LDAP. Per questo occorre
sfruttare una caratteristica particolare di Squid che è quella che gli
permette di ampliare le ACL disponibili appoggiandosi ad un programma esterno,
in maniera analoga a quanto avviene per eseguire l'autenticazione.

Per far questo le ACL di Squid comprendono una classe speciale,
\texttt{external}, che consente di effettuare un controllo invocando un
opportuno programma di ausilio definito attraverso la direttiva,
\texttt{external\_acl\_type}. Quest'ultima prende come argomento un nome, che
identificherà quel particolare tipo di ACL, seguita dalle indicazioni
necessarie ad invocare il programma esterno. 


\begin{table}[!htb]
  \centering
  \footnotesize
  \begin{tabular}[c]{|c|p{8cm}|}
    \hline
    \textbf{Opzione} & \textbf{Significato} \\
    \hline
    \hline
    \texttt{-b}& specifica la sezione dell'albero, passata come parametro,
                 nella quale sono mantenuti i dati dei gruppi.\\ 
    \texttt{-B}& specifica la sezione dell'albero, passata come parametro,
                 nella quale sono mantenuti i dati degli utenti (se diversa
                 da quella dei gruppi).\\ 
    \texttt{-f}& consente di impostare un filtro, passato come parametro, con 
                 cui eseguire la ricerca degli utenti appartenenti ad un
                 gruppo; nel filtro si potrà indicare l'utente con
                 \texttt{\%u} ed il gruppo con \texttt{\%g}.\\  
%    \texttt{-F}& .\\ 
%    \texttt{-u}& consente di impostare l'attributo, passato come parametro, da
%                 utilizzare per la ricerca del nome utente.\\ 
    \texttt{-s}& consente di specificare la profondità della ricerca, prende
                 come parametro uno dei valori di
                 tab.~\ref{tab:ldap_scope_values}.\\ 
    \texttt{-D}& specifica un eventuale DN con cui collegarsi al server
                 LDAP qualora non fossero consentite ricerche anonime.\\
    \texttt{-w}& specifica la password da usare per collegarsi al server
                 LDAP (con l'utente specificato da \texttt{-D}).\\
    \texttt{-h}& specifica l'indirizzo del server LDAP.\\ 
    \texttt{-H}& imposta la URL a cui contattare il server LDAP.\\ 
    \texttt{-p}& specifica la porta da utilizzare per la connessione.\\ 
    \texttt{-v}& imposta la versione di protocollo da usare (prende i valori 2
                 e 3, ed il default è 2).\\ 
%    \texttt{-t}& imopsta un timeout (in secondi) per la connessione.\\ 
%    \texttt{-Z}& richiede l'uso di TLS sulla connessione al server.\\ 
%    \texttt{-}& .\\ 
    \hline
  \end{tabular}
  \caption{Le opzioni del programma \texttt{squid\_ldap\_group} per la
    creazione di ACL sui gruppi.} 
  \label{tab:ldap_squid_ldap_group}
\end{table}

Nel caso si voglia usare come ACL l'appartenenza di un utente ad un gruppo su
LDAP si può utilizzare un apposito programma, \texttt{squid\_ldap\_group},
distribuito insieme a Squid,\footnote{almeno questo è quanto avviene per il
  pacchetto Debian.} che permette di effettuare questa verifica.  Un possibile
esempio di configurazione è allora quello del seguente estratto di
\texttt{squid.conf}:
\begin{FileExample}[label=squid.conf]
external_acl_type ldap_group %LOGIN /usr/lib/squid/squid_ldap_group \
    -b "ou=Groups,dc=truelite,dc=it" -B "ou=Users,dc=truelite,dc=it" \
    -f "(&(uniqueMember=%u)(cn=%g))" -h localhost
acl normal_access external ldap_group normal
acl restricted_access external ldap_group restricted
acl full_access external ldap_group full
\end{FileExample}
dove si definisce un tipo di ACL esterna \texttt{ldap\_group}, che fa ricorso
al suddetto programma, e poi lo si utilizza per creare delle nuove ACL (le
varie \texttt{*\_access} dell'esempio) da usare per imporre diverse
restrizioni a seconda dell'appartenenza ad un certo gruppo (nel caso uno fra
\texttt{normal}, \texttt{restricted}, \texttt{full}).

Il programma \index{comando!\texttt{squid\_ldap\_group}}
\texttt{squid\_ldap\_group} prende in input una riga contenente utente e
gruppo e restituisce il risultato (come richiesto per l'uso da parte di
\texttt{external\_acl\_type}) sullo \textit{standard output},\footnote{la
  risposta può essere \texttt{OK} se l'utente corrisponde, o \texttt{ERR} se
  non corrisponde.} per cui può essere anche usato da riga comando per
verificarne il funzionamento. Come per il precedente \texttt{ldap\_auth} il
comando supporta diverse opzioni, le principali delle quali sono illustrate in
tab.~\ref{tab:ldap_squid_ldap_group}.

La complessità dell'uso di \texttt{squid\_ldap\_group} sta nel modo in cui
viene fatta la ricerca della presenza di un utente in un gruppo, che è
governata dal filtro di ricerca specificato con l'opzione \texttt{-f}. Il
filtro infatti supporta una sintassi speciale nella quale si possono usare le
notazioni \texttt{\%u} e \texttt{\%g} per indicare rispettivamente il nome
dell'utente ed il nome del gruppo ottenuti in ingresso. Qualora si trovi una
voce corrispondente il programma avrà successo.



\ifwhole\else

\appendix
%\input{../commons/fdl-1.3}
\input{../commons/end}

\end{document}

\fi

%%% Local Variables: 
%%% mode: latex
%%% TeX-master: t
%%% End: 

% LocalWords:  LDAP Truelite Srl Lightweight TCP UDP Name sez searching add
% LocalWords:  Service Switch DNS International Organization for DAP RFC save
% LocalWords:  Standardization client Naming back DIT Information Tree entries
% LocalWords:  suffix objectClass common name cn Organizational Unit ou Country
% LocalWords:  organizationalUnit st fig Domain Component dcObject RDN  quit
% LocalWords:  truelite it LDIF OpenLDAP Interchange Format dn sn finding mdb
% LocalWords:  distinguished URL jpegPhoto Contacts telephoneNumber title olc
% LocalWords:  facsimileTelephoneNumber postalAddress labeledURI Javier fileAs
% LocalWords:  referral Foundation SSL TLS stable openldap tgz Transport view
% LocalWords:  Layer Security IETF socket Secure OpenSSL LDAPv Kerberos Heimdal
% LocalWords:  MIT SASL Simple Authentication and Cyrus DBM Berkley DB BSD GDBM
% LocalWords:  tab shell wrapper autotools configure CFLAGS CPPFLAGS LDFLAGS Di
% LocalWords:  linker LIBS enable FEATURE with PACKAGE debug syslog bdb again
% LocalWords:  local cleartext crypt wrappers ldbm perl sql slurpd cyrus sasl
% LocalWords:  threads thread tls make depend install slapd libldap ldap utils
% LocalWords:  conf debconf pathname facility SERVICES OPTIONS backend HOST bin
% LocalWords:  escape PORT BINDDN SIZELIMIT TIMELIMIT ldaprc home LDAPCONF Sid
% LocalWords:  LDAPNOINIT LDAPURI Defaults See details This should world but eq
% LocalWords:  readable not writable example com DEREF never hdb proxy relay is
% LocalWords:  passwd dnssrv null ACID Atomicity Consistency Isolation FAQ SRV
% LocalWords:  Durability objectclass attributetype sizelimit timelimit allow
% LocalWords:  idletimeout loglevel disallow argsfile moduleload modulepath PID
% LocalWords:  schemacheck pidfile bind anon cred update cachesize checkpoint
% LocalWords:  cache chmod index CONFIG pres uid subinitial subfinal subany sim
% LocalWords:  icc approx userPassword readonly lastmod rootdn rootpw slapadd
% LocalWords:  lbdm filesystem slapcat entry dump slapindex cron gq GTK ldapadd
% LocalWords:  ldapmodify hostname replog ldapdelete ldapsearch LDIFv one sed
% LocalWords:  attr person inetOrgPerson organizationalPerson exp binding hash
% LocalWords:  libsasl simple authPassword slappasswd SHA SSHA Salted SMD new
% LocalWords:  l'hash ldappasswd access to what who control attrs subtree write
% LocalWords:  organizationalRole exact regex children filter groupOfNames grep
% LocalWords:  dnstyle onelevel subpattern UserData People read nomeutente
% LocalWords:  self anonymous users auth dnattr group posixGroup style domain
% LocalWords:  sockname sockurl peername ip admin localhost level search binddn
% LocalWords:  replicationinterval replogfile updatedn updateref replication pl
% LocalWords:  logfile bindmethod credentials replicatore Certification openssl
% LocalWords:  authority wipe DAYS days newca parker CertAuth filename Making
% LocalWords:  using configuration from Generating RSA key writing PEM pass You
% LocalWords:  phrase Verifying about asked information that will incorporated
% LocalWords:  into your request you called There quite few fields can leave If
% LocalWords:  blank there value the field left letter AU Locality eg company
% LocalWords:  Widgits Pty Ltd section Address demoCA text noout Version Number
% LocalWords:  Signature Algorithm WithRSAEncryption Issuer Validity Before May
% LocalWords:  GMT After Subject Public Info rsaEncryption newreq Please member
% LocalWords:  following attributes sent challenge An pem FQDN Fully Qualified
% LocalWords:  req VPN Modulus sign matches signature Subjects as follows until
% LocalWords:  countryName PRINTABLE stateOrProvinceName localityName certified
% LocalWords:  organizationName commonName emailAddress Aug of requests commit
% LocalWords:  Updated Signed newcert rsa newkey root umask usr cert cnf certs
% LocalWords:  subjectAltName ls total cacert ldapcert ldapkey ldapreq host yes
% LocalWords:  TLSCertificateFile TLSCACertificateFile TLSCertificateKeyFile my
% LocalWords:  TLSVerifyClient authentication port CHECKPEER REQCERT PAM hosts
% LocalWords:  ldif migrationtools apt get shadow ph NIS roke ipHost device LL
% LocalWords:  ipHostNumber multicast gethostbyname ssh telnet getaddrinfo ping
% LocalWords:  bytes icmp seq ttl ms statistics packets transmitted received pw
% LocalWords:  trip min news gidNumber cvsusers memberUid chris csurchi daemon
% LocalWords:  posixAccount shadowAccount shadowLastChange shadowMax loginShell
% LocalWords:  shadowWarning uidNumber homeDirectory gecos libnss RedHat pam cf
% LocalWords:  rootbinddn NSS nss compat files dns segmentation fault getent fà
% LocalWords:  libpam Gabriel Surchi Pluggable Method list plain username first
% LocalWords:  checkpeer version sufficient session required likeauth nullok by
% LocalWords:  uniqueMember evolution mod vhost Piccardi bindpw insensitive map
% LocalWords:  Virtual htpasswd load mods enabled Postfix Windows Groups Sarge
% LocalWords:  strings evolutionperson require AuthLDAPURL AuthLDAPBindDN valid
% LocalWords:  AuthLDAPGroupAttribute AuthLDAPGroupAttributeIsDN AuthType doc
% LocalWords:  AuthLDAPCompareDNOnServer AuthLDAPBindPassword AuthName postfix
% LocalWords:  l'username off html nis useradd userdel cpu usermod adduser ini
% LocalWords:  GLOBAL CRACKLIB DICTIONARY cracklib passwordsegretissima exop sh
% LocalWords:  enmod all'username maps query result format table Squid kilobyte
% LocalWords:  ReservedContacts deluser policy people Controller global smb ssl
% LocalWords:  connect idle init soft persist oneshot basedn inetorgperson sync
% LocalWords:  Thunderbird Kaddressbook aliases passdb ldapsam machine idmap NT
% LocalWords:  delete smbpasswd HOWTO fileserver sambaNTPassword smbldap tools
% LocalWords:  sambaLMPassword sambaPwdLastSet sambaPwdMustChange masterDN gid
% LocalWords:  sambaPasswordHistory slaveDN masterPw slavePw masterLDAP usersdn
% LocalWords:  masterPort slaveLDAP slavePort groupsdn computersdn skeletonDir
% LocalWords:  userLoginShell defaultUserGid defaultComputerGid userSmbHome PDC
% LocalWords:  share userProfile userHomeDrive userScript getlocalsid Computers
% LocalWords:  setlocalsid idmapdn userHome userGecos System populate migration
% LocalWords:  defaultMaxPasswordAge nobody Admininistrator monk workgroup ntml
% LocalWords:  sambaUnixIdPooldn sambaDomainName builtin structure already acl
% LocalWords:  exist adding Updating Admins Guests Administrators print Retype
% LocalWords:  Operators Replicators Changing groupadd groupmod groupdel ldapvi
% LocalWords:  shadowMin shadowInactive shadowExpire shadowFlag nsswitch cdrom
% LocalWords:  computers sottorami basic digest param program squid minutes GNU
% LocalWords:  credentialsttl realm external type normal restricted Permission
% LocalWords:  granted copy distribute modify this document under terms free we
% LocalWords:  Documentation License any later published Invariant Sections ERR
% LocalWords:  being Front Cover Texts license included entitled avoid packet
% LocalWords:  these definition when outside tinyca options displayName args
% LocalWords:  givenname sambaSamAccount Unicode sambaKickoffTime sambaSID lock
% LocalWords:  sambaPrimaryGroupSID sambaAcctFlags conns config stats LDAPSync
% LocalWords:  ldapmodrdn dell'RDN hasSubordinates syncrepl shot rej attribute
% LocalWords:  AuthBasicProvider authnz AuthzLDAPAuthoritative overlay protocol
% LocalWords:  consumer entryCSN entryUUID syncprov sessionlog rid searchbase
% LocalWords:  refreshAndPersist schemachecking poll push firewall all frontend
% LocalWords:  hidden restrict how where things here must thing retry unlimited
% LocalWords:  valsort ppolicy overlays slapo nomeoverlay Lenny unique Content
% LocalWords:  constraint accesslog Synchronization producer refreshOnly cookie
% LocalWords:  contextCSN Change Sequence CSN phase interval GnuTLS wildcard
% LocalWords:  chain dnSubtreeMatch DSE supportedFeatures supportedControl NTLM
% LocalWords:  supportedExtension baseObject requesting structuralObjectClass
% LocalWords:  OpenLDAProotDSE configContext namingContexts CRAM entryDN OID
% LocalWords:  supportedLDAPVersion supportedSASLMechanisms subschemaSubentry
% LocalWords:  Subschema cons repl prov Object Identifier IANA Features AF lk
% LocalWords:  support proctitle Hierarchical Logging auditlog Audit collect
% LocalWords:  Packages fetch modules CentOS servers clients slaptest LDAPS
% LocalWords:  LDAPI REFERRALS true ndb NDB MySQL sock Operations dbconfig
% LocalWords:  Oracle objects lockers Operation manage disclose break try
% LocalWords:  demand givenName lookup obscure trusted examples description
% LocalWords:  sambaGroupMapping sambaSIDList sambaGroupType sambaDomain skip
% LocalWords:  always Wheezy certificates needed rename Action changes diff
% LocalWords:  ignoring errors discard change records dialog rebind toggle
% LocalWords:  mechanism reconnect forget deletions rewrite comments Memory
% LocalWords:  discover StartTLS Mapped Jessie reqcert systemd unit maxsize
% LocalWords:  dbnosync CamelCase olcGlobal olcArgsFile olcLogLevel module
% LocalWords:  olcPidFile olcToolThreads olcModuleList olcModulePath size
% LocalWords:  olcModuleLoad failover Commands crash olcSchemaConfig HAProxy
% LocalWords:  olcBackend olcDatabase olcBackendConfig olcDatabaseConfig
% LocalWords:  olcMdbConfig olcHdbConfig olcFrontendConfig olcAccess service
% LocalWords:  peercred olcSizeLimit olcRootDN olcDbDirectory olcSuffix mkdir
% LocalWords:  olcLastMod olcRootPW olcDbCheckpoint olcDbIndex olcDbMaxSize
% LocalWords:  olcOverlayConfig olcOverlay chown framework GSSAPI response
%  LocalWords:  sasldb saslauthd authorization Granting kinit authz regexp
%  LocalWords:  kernel auxprop method auxprops


%%% Local Variables:
%%% mode: latex
%%% TeX-master: t
%%% End:
