%%
%% Dispense WEB SERVER / MAIL SERVER
%%
%% Copyright \copyright\ 2000-2005 Truelite S.r.l.  Permission is granted to
%% copy, distribute and/or modify this document under the terms of the GNU Free
%% Documentation License, Version 1.1 or any later version published by the
%% Free Software Foundation; with no Invariant Sections, with Front-Cover
%% Texts: ``Truelite Srl http://www.truelite.it info@truelite.it'', and with no
%% Back-Cover Texts.  A copy of the license is included in the section entitled
%% ``GNU Free Documentation License''.
%%
%% C. Surchi Apr. 2003
%%

%
% To avoid these definition when included from outside
%
\providecommand{\setflag}{\newif \ifwhole \wholefalse}
\setflag

\ifwhole\else

\documentclass[a4paper,11pt,twoside,italian]{book}
\input{../commons/packages}
\input{../commons/front}

\makeindex

\begin{document}

\pagenumbering{roman}

\begin{titlepage}
    \centering
    \phantom{}
    \vfill
    {\Huge \textbf{\textsf{GNU/Linux amministrazione internet}}}
    \vfill
    {\huge \textsf{Christian Surchi}}

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

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

\ClearShipoutPicture

%\pagenumbering{roman} 
%\maketitle

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

\begin{quote}
  
  Copyright \copyright\ 2003-2004 Christian Surchi \& Truelite S.r.l.
  Permission is granted to copy, distribute and/or modify this document under
  the terms of the GNU Free Documentation License, Version 1.1 or any later
  version published by the Free Software Foundation; with no Invariant
  Sections, with Front-Cover Texts: ``Truelite Srl http://www.truelite.it
  info@truelite.it'', and with no Back-Cover Texts.  A copy of the license is
  included in the section entitled ``GNU Free Documentation License''.

  \vfill 
  
  Questa documentazione libera è stata sviluppata all'interno delle attività
  formative effettuate da Truelite S.r.l. Il materiale è stato finanziato nel
  corso della realizzazione dei corsi erogati dall'azienda, e viene messo a
  disposizione di tutti sotto licenza GNU FDL.
  
  Questo testo, insieme al resto della documentazione libera realizzata da
  Truelite S.r.l., viene distribuito su internet all'indirizzo:

  \href{https://labs.truelite.it/truedoc/}
  {\textsf{https://labs.truelite.it/truedoc/}}

  dove saranno pubblicate nuove versioni ed aggiornamenti.

  \vspace{0.5cm}


  \includegraphics[width=3cm,keepaspectratio]{../images/logo} \\
  Società italiana specializzata nella fornitura di servizi, consulenza e
  formazione esclusivamente su GNU/Linux e software libero.

  \vspace{0.5cm}
  
  Per informazioni:

  \begin{tabular}[left]{p{10cm}l}
  \textbf{Truelite S.r.l}& \multirow{7}{3.cm}
  {\includegraphics[width=3.0cm,keepaspectratio]{../images/sfoglino}}\\
  Via Monferrato 6,      & \\
  50142 Firenze.         & \\
  Tel: 055-7879597       & \\
  Fax: 055-7333336       & \\
  e-mail: \href{mailto:info@truelite.it}{\textsf{info@truelite.it}}     &\\
  web: \href{http://www.truelite.it}{\textsf{http://www.truelite.it}}   &\\
  \end{tabular}

\end{quote}

%\pagenumbering{arabic}

\clearemptydoublepage
\tableofcontents
\clearemptydoublepage
\mainmatter

\fi


\chapter{La posta elettronica}
\label{cha:email}


\section{Cos'è la posta elettronica}
\label{sec:mail_whatis}

La posta elettronica è uno dei più antichi servizi disponibili sui sistemi
Unix. Essa nasce, insieme con i servizi di news, ben prima di internet (uno
dei primi protocolli di scambio, UUCP, è ancora usato) ed è tutt'oggi, insieme
alle pagine web uno dei servizi principali che si trovano su internet.

Benché il concetto di posta elettronica sia estremamente semplice, il servizio
è in realtà uno dei più complessi, e prevede, per la sua realizzazione, la
presenza di numerosi attori e diveri programmi sia sul lato server che su
quello client.  In questa prima sezione faremo una panoramica sulle
caratteristiche del servizio e sulle modalità con cui questo viene
implementato.


\section{La struttura del servizio}
\label{sec:mail_structure}

Come per la posta ordinaria (quella che viene usualmente detta \textit{snail
  mail}), anche il servizio per la gestione della posta elettronica prevede la
presenza di diverse infrastrutture deputate alla spedizione, all'inoltro ed
alla ricezione dei vari messaggi. 

La struttura classica del servizio, come fornita nel caso di due server con
connessione continua alla rete, è illustrata nello schema in
fig.~\ref{fig:mail_server_server}. Il meccanismo è analogo a quello della
posta ordinaria, colui che invia la posta (il cosiddetto \textit{sender})
utilizza un apposito programma, un \textit{Mail User Agent} o MUA, detto
comunemente anche client di posta, che serve ad ``\textsl{imbucare}'' la
propria posta elettronica presso un altro programma, il \textit{Mail Transport
  Agent} (o MTA), che è quello che si incarica del trasporto.

\begin{figure}[htb]
  \centering
  \includegraphics[width=13cm]{images/MailSending}
  \caption{Schema del funzionamento della posta elettronica nel caso di due
    server in rete.}
  \label{fig:mail_server_server}
\end{figure}

Nel caso illustrato in fig.~\ref{fig:mail_server_server} questo è posto sulla
stessa macchina del mittente, questo ha il vantaggio che, in caso di macchina
scollegata dalla rete, la posta in uscita verrà mantenuta in coda dal
programma, che provvederà ad inviarla non appena la connessione sarà
disponibile. Qualora (come è comune su sistemi non Unix) non si disponga di un
server mail locale, si potrà comunque contattare il server che il proprio
provider mette a disposizione.

Il server di posta (più precisamente il server che fornisce il servizio di
trasporto come MTA, di norma un server che implementa il protocollo SMTP
illustrato in sez.~\ref{sec:mail_SMTP}) si incaricherà a sua volta di
effettuare la comunicazione del messaggio al destinatario attraverso un
opportuno protocollo; nella gran parte dei casi questo è SMTP, ma è possibile
anche usare protocolli alternativi come UUCP.

Una volta inoltrato il messaggio potrà arrivare al MTA del destinatario che lo
riceverà, provvedendo a depositarlo nella casella di posta (la cosiddetta
\textit{mailbox}) dell'utente. Si noti come in
fig.~\ref{fig:mail_server_server} sia evidenziata la possibilità di usare un
\textit{Local Delivery Agente}, cioè un programma in grado di eseguire una
serie di operazioni nella consegna finale del messaggio (come quelle di
classificare e distribuire i messaggi su diverse mailbox, scartare messaggi
indesiderati, ecc.). Inoltre tutti gli MTA prevedono la possibilità di
ricevere messaggi per diversi \textit{alias} dell'utente finale, come quella
di reinviare gli stessi ad un altro server corrispondente ad un altro
indirizzo di posta.

Si tenga presente infine che non è detto che la comunicazione avvenga
direttamente fra l'MTA del mittente e quello del destinatario; ad esempio per
gli utenti in dial-up è sempre opportuno far eseguire, anche quando si ha un
server in locale, un passaggio (chiamato in gergo \textit{relay}) al server
del provider, che essendo sempre in rete oltre a ritrasmettere il messaggio,
sarà anche in grado di ricevere eventuali messaggi di errore da parte della
destinazione, che altrimenti rischierebbero di essere persi.

La struttura del servizio illustrata in precedenza può essere applicata solo
agli utenti appartenenti a entità che hanno a disposizione un server che
dispone di una connessione permanente su internet; in generale gli utenti
normali non dispongono di tali strutture, ma si collegano da casa per
intervalli di tempo limitato, e pertanto il servizio della posta elettronica
deve eseguito in una modalità diversa, facendo ricorso ad un analogo di quello
che è il \textsl{fermoposta} per la posta ordinaria, secondo le modalità di
gestione illustrate nello schema in fig.~\ref{fig:mail_server_client}.

\begin{figure}[htb]
  \centering
  \includegraphics[width=13cm]{images/MailReceiving}
  \caption{Schema del funzionamento della posta elettronica nel caso di
    ricezione da parte di un utente con connessione non permanente.}
  \label{fig:mail_server_client}
\end{figure}

In questo caso infatti, anche se presente, l'MTA del mittente non può eseguire
dirattamente la ricezione dei messaggi, poiché essendo connesso per tempi
limitati, non sarebbe in grado di rispondere alle richieste. Questo comporta
allora l'uso di un server di posta remoto che si incarica di ricevere e
stoccare i messaggi in una mailbox, dalla quale potranno essere riletti in un
tempo seguente.

Dato che in questo caso non si ha un accesso diretto alla mailbox (come
potrebbe essere nel caso in cui questa sta sul nostro disco) il client di
posta non può leggere direttamente il contenuto di quest'ultima. In questo
caso ci sono sostanzialmente due alternative. La prima è quella di usare un
opportuno protocollo per interrogare il server su cui è la mailbox, in modo da
poter scaricare i messaggi che il client leggerà direttamente dalla rete; in
questo caso sul server deve essere installato un opportuno programma di
servizio (un server POP o IMAP) che esegua questo compito.

La seconda possibilità, che permette un uso più efficiente delle connessioni
in cui il tempo di collegamento è un costo, è quella di usare un opportuno
programma di lettura come \texttt{fetchmail} che sempre attraverso uno di
questi due servizi (POP o IMAP) scarica i messaggi dal server remoto,
ritrasmettendoli ad un MTA locale che li invia in una mailbox locale, che
potrà essere acceduta con comodo in un secondo tempo dal client di posta.



\section{La struttura dei messaggi di posta.}
\label{sec:mail_message_struct}

Per poter eseguire l'invio a destinazione dei messaggi di posta sono
necessarie una serie di informazioni; per questo in genere questi sono
composti da una serie di dati amministrativi, più il corpo del messaggio vero
e proprio. 

I dati amministrativi sono a loro volta suddivisi nei dati specifici del mezzo
di trasporto utilizzato (come destinatario e mittente) che vengono creati ed
utilizzati direttamente dai server SMTP: questi formano la cosiddetta
\textit{envelope} (la \textsl{busta}) del messaggio, e vengono scartati una
volta che esso giunge a destinazione.

Una seconda parte di questi dati sono generali, e non dipendono dal mezzo di
trasporto, come l'oggetto del messaggio, la data, la lista dei destinatari ed
vari altri, e vanno a costituire quello che viene detto l'\textit{header}
(l'\textsl{intestazione}) del messaggio.  Questi vengono salvati insieme al
messaggio e possono essere riletti. Di norma tutti i client di posta mostrano
alcuni di questi (come il mittente e l'oggetto), ma è sempre possibile vederli
tutti.

Infine, separato dagli header da una riga vuota, c'è il \textit{body} (il
\textsl{corpo}) del messaggio, contenente quanto si è stato scritto dal
mittente con il MUA.




\section{Il protocollo SMTP.}
\label{sec:mail_SMTP}


Il protocollo SMTP (\textit{Simple Mail Transfer Protocol}) è lo standard per
il trasporto della posta elettronica ed è definito
nell'\href{http://www.ietf.org/rfc/rfc2821.txt}{RFC~2821
  (http://www.ietf.org/rfc/rfc2821.txt)}. In realtà le specifiche erano
presenti in RFC precedenti, ma poi sono state raccolte in questo. L'obiettivo
del protocollo è quello di trasferire posta in modo affidabile ed efficiente.
SMTP è indipendente dal sistema di trasmissione e dal sistema di trasporto
utilizzati; nel nostro caso faremo riferimento comunque al trasporto su TCP.
SMTP permette anche di trasferire posta elettronica da una rete all'altra
facendo uso di host su Internet o intranet accessibili via TCP oppure host su
reti interne accessibili con altri protocolli di trasporto (mail relaying). In
questo modo i messaggi vengono trasferiti attraverso relay o gateway intermedi
tra il mittente ed il destinatario. L'identificazione dei passi di questo
percorso è stabilito dal meccanismo di DNS (Domain Name System) dei Mail
eXchanger (che vedremo più avanti) e non tramite un routing prestabilito.

Quello illustrato in fig.~\ref{fig:mail_SMTP_protocol} è un modello che
descrive il sistema del protocollo SMTP.


\begin{figure}[htb]
  \centering
  \includegraphics[width=13cm]{images/SMTP_diagram}
  \caption{Schema del protocollo SMTP.}
  \label{fig:mail_SMTP_protocol}
\end{figure}


Lo scambio di messaggi avviene quindi su un canale bidirezionale
creato tra client e server.

Un server SMTP può essere il destinatario finale, oppure un "relay" intermedio
(che dopo aver ricevuto il messaggio farà da client verso un altro server,
oppure un "gateway" (nel caso in cui la posta venga poi instradata usando
protocolli diversi da SMTP).

Il trasferimento dei messaggi avviene tramite transazioni basate su scambio di
comandi, una volta che è andato a buon fine l'handshaking tra client e
server. I comandi servono, ad esempio, per definire mittente e destinatari del
messaggio, mentre le risposte indicano se il messaggio è stato accettato
o rifiutato a causa di qualche errore temporaneo o permanente. Di solito ogni
transazione viene eseguita in modo in modo esclusivo, anche se è possibile
richiedere al server una funzionalità estesa di pipelining. Per una singola
connessione si possono avere più di una transazione. La porta standard del
servizio SMTP è la 25.


Esempio di transazione (C: è il client, S: è il server):
\begin{verbatim}
      S: 220 foo.com ESMTP Postfix
      C: EHLO bar.com
      S: 250-foo.com
      S: 250-PIPELINING
      S: 250-SIZE 10240000
      S: 250-VRFY
      S: 250-ETRN
      S: 250-XVERP
      S: 250 8BITMIME
      C: MAIL FROM:<Smith@bar.com>
      S: 250 OK
      C: RCPT TO:<Jones@foo.com>
      S: 250 OK
      C: DATA
      S: 354 End data with <CR><LF>.<CR><LF>
      C: Blah blah blah...
      C: ...etc. etc. etc.
      C: .
      S: 250 Ok: queued as A738ED8355
      C: QUIT
      S: 221 Bye
\end{verbatim}

Il percorso dei messaggi è determinato dai passi intermedi che coinvolgono uno
o più server SMTP. La scelta è dettata dal DNS in base ad una richiesta fatta
per il dominio del destinatario.

Prendiamo in considerazione record di tipo MX (Mail eXchanger), CNAME
(Canonical NAME), e A (Address).

Prima di tutto la ricerca ha come obiettivo un record MX associato a quel
dominio. Nel caso in cui ci sia un CNAME, la ricerca riparte dal risultato
ottenuto. Se non c'è un MX ma un record A, quel record viene considerato come
un MX implicito a priorità 0. Se esistono uno o più MX non si prendono in
considerazione i record A, a meno che questi non siano ricavati in base ad una
ulteriore risoluzione di uno degli MX. Il record A altrimenti viene utilizzato
solo se non sono indicati record MX. Nel caso in cui nessuno degli MX sia
utilizzabile, viene riportato un errore.

Nel caso in cui siano indicati più di un record MX, i tentativi di invio
devono seguire un criterio basato sulla priorità del record MX, priorità più
basse hanno la precedenza. Se ci sono priorità uguali la scelta deve essere
casuale (in modo da suddividere in qualche modo il carico).

Nel caso in cui invece ci siano più indirizzi IP per un record MX, i
tentativi di invio devono seguire l'ordine stesso che è stato ottenuto dalla
risposta alla richiesta al DNS.

Una volta che il server SMTP ha ricevuto il messaggio per un destinatario per
il quale è un MX, decide cosa farne, se inviarlo ad un altro server
(riscrivendo pertanto gli indirizzi per MAIL FROM ed RCTP TO, o inoltrarlo
localmente, o usare un meccanismo di trasporto ulteriore diverso, senza
esaminare ulteriormente i record MX.

Se invece il messaggio deve essere inoltrato senza riscrivere gli indirizzi,
allora deve ordinare i record MX per determinare con quale provare a spedire.
I record vengono ordinati per priorità e la scelta cade su quelli con
priorità minore. Vengono scartati i record che fanno riferimento allo stesso
server SMTP e poi quelli che hanno priorità uguale o maggiore di quella presa
in considerazione. A questo punto se non rimangono record, siamo in una
condizione di errore e il messaggio deve essere rimandato indietro, altrimenti
i record rimasti devono essere provati in ordine di priorità come descritto in
precedenza.


\section{Introduzione a Postfix}
\label{sec:mail_postfix_intro}

Postfix (http://www.postfix.org) è un server SMTP, creato da Wietse Venema
come alternativa al diffusissimo Sendmail (il server di posta più usato).
Ha come obiettivo quello di essere veloce, facile da amministrare, robusto e
sicuro, mantenendo allo stesso tempo il più possibile la compatibilità con
Sendmail.  Postfix tra l'altro permette di avere meccanismi di trasporto
multipli, di gestire domini virtuali in modo semplice e di mettere in atto
sistemi di controllo per ridurre lo SPAM.

In questo documento facciamo riferimento alle versioni di Postfix 1.1.11 o
2.0.9 rispettivamente su Debian GNU/Linux 3.0 "Woody" (Stable) e Sid
(Unstable). I cambiamenti per quanto riguarda la configurazione nel nostro
caso sono minimi e anche quando alcuni parametri sono cambiati tra una
versione e l'altra, i vecchi solitamente funzionano anche sulle versioni
2.0.x.

\section{Architettura di Postfix}
\label{sec:mail_postfix_arch}

Postfix è costituito da numerosi processi, ognuno dei quali è legato ad un
compito ben definito.

I processi comunicano attraverso socket UNIX o FIFO opportunamente protette.
Un ulteriore vantaggio di questa architettura è la facilità di ridurre al
minimo l'attività dei processi, evitando ad esempio di avere posta inoltrata
localmente su macchine che non ne hanno bisogno, oppure evitando di avere
attivo il processo che sta in ascolto sulla porta SMTP.


\begin{figure}[htb]
  \centering
  \includegraphics[width=13cm]{images/big-picture}
  \caption{Architettura di Postfix}
  \label{fig:Le componenti di Postfix}
\end{figure}

Nel diagramma gli ellissoidi gialli sono programmi di Postfix, i rettangoli
gialli sono file o code di posta, i rettangoli blu sono tabelle. I programmi
contenuti nel rettangolo grande girano sotto il controllo del demone
\texttt{master}.  I file contenuti nello stesso spazio appartengono al sistema
di Postfix.

Il demone \texttt{master} è l'unico che gira con privilegi di root, è un
demone residente e si occupa di richiamare di gli altri processi quando
necessario: ad esempio \texttt{smtpd} nel caso si tratti di aprire una
connessione.  Il file di configurazione \texttt{master.cf} contiene i dettagli
sull'attività dei vari processi richiamati dal demone.

Postfix ha quattro code principali: \textit{maildrop}, \textit{incoming},
\textit{active}, \textit{deferred}.

\begin{basedescript}{\desclabelwidth{2.0cm}\desclabelstyle{\nextlinelabel}}
\item[\textit{maildrop}] è dedicata alla posta locale, che dopo l'opportuna
  "pulizia" viene spostata nella coda di incoming.

\item[\textit{incoming}]  è dedicata alla posta al momento in arrivo o a
  quella che il gestore delle code non ha ancora avuto modo di guardare. 

\item[\textit{active}]  ha una dimensione limitata ed è dedicata alla
  posta che il gestore delle code ha preso in considerazione per l'invio.
  
\item[\textit{deferred}] è dedicata alla posta che non può essere inoltrata.
\end{basedescript}

La limitazione sulla dimensione della coda \textit{active} è dettata dalla
necessità di evitare l'esaurimento di memoria dovuto a carico molto elevato di
messaggi.  Il gestore delle code, infatti, tiene informazioni in memoria
soltanto sulla coda \textit{active}. Questa coda è gestita in moda tale da
permettere l'entrata di un messaggio da \textit{incoming} ed uno da
\textit{deferred}, in modo da evitare ritardi alla posta nuova anche quando
c'è un pesante arretrato.

Ci sono altre due code, ma in realtà fungono da contenitori. \textit{hold} è
dedicata alla posta che rimane in coda. Non verranno fatti ulteriori tentativi
di invio, a meno che questo non venga fatto tramite il comando
\texttt{postsuper}.  \textit{corrupt} invece è dedicata a file danneggiati,
che rimangono quindi a disposizione per essere controllati manualmente.

Vediamo adesso come interagire con Postfix utilizzando la linea di
comando. Naturalmente abbiamo \texttt{sendmail},
\texttt{mailq} e \texttt{newaliases} (compatibilità con
\texttt{sendmail}). Gli altri comandi sono:

\begin{basedescript}{\desclabelwidth{2.0cm}\desclabelstyle{\nextlinelabel}}
\item[\texttt{postfix}] permette di controllare l'attività del server e
  permette di far partire o fermare il sistema
\item[\texttt{postalias}] permette di gestire i database degli alias 
\item[\texttt{postcat}] permette di visualizzare il contenuto delle code
\item[\texttt{postconf}] permette di visualizzare e modificare i parametri del
  \texttt{main.cf}
\item[\texttt{postdrop}] permette di mandare la posta nella coda maildrop
\item[\texttt{postkick}] permette di comunicare con alcuni processi
\item[\texttt{postlock}] permette di effettuare lock sulle caselle e di
  eseguire dei comandi
\item[\texttt{postlog}] permette di avere un'interfaccia al sistema di log
\item[\texttt{postmap}] permette di gestire la tabelle (canonical, virtual,
  ...)
\item[\texttt{postqueue}] permette di gestire la coda di posta o di svuotarla
\item[\texttt{postsuper}] permetta di gestire la coda spostando le mail e
  togliendo i vecchi file temporanei
\end{basedescript}

Le garanzie di sicurezza derivano soprattutto da una serie di scelte di design
e di architettura, alcune delle quali sono:

\begin{itemize}
\item la possibilità di eseguire la maggior parte dei demoni con privilegi
  minimi e in un chroot
\item l'uso di processi separati
\item la presenza di un ambiente controllato (dal demone \texttt{master})
  senza processi che si riproducono
\item l'assenza di programmi setuid, se non nel caso di \texttt{postdrop}, per
  permettere di abbandonare la directory maildrop accessibile a tutti in
  scrittura
\end{itemize}

La configurazione di Postfix, come vedremo più avanti, è basata principalmente
su un file di configurazione, mentre per tutto quanto riguarda alias,
controlli sull'accesso, configurazione utenti su domini virtuali, può fare
riferimento ad apposite tabelle che possono essere su file di testo
(espressioni regolari standard o perl) e annessi hash (si veda ad esempio
\texttt{postmap}), oppure basate su qualsiasi altro meccanismo per cui Postfix
preveda un supporto (ad es. LDAP o SQL).

\section{Configurazione di base}
\label{sec:mail_postfix_base_conf} 

I parametri di configurazione di Postfix sono tantissimi, e il file in cui si
trovano è \texttt{main.cf} (di solito \texttt{/etc/postfix/main.cf}).
L'installazione fornisce comunque valori di default accettabili per buona
parte di questi. Vediamo quindi quali sono quelli davvero necessari:

\begin{basedescript}{\desclabelwidth{1.5cm}\desclabelstyle{\nextlinelabel}}
\item[\texttt{myorigin}] indica il dominio che appare nella posta in uscita
  dalla macchina. Il default è il nome locale della macchina e questo spesso
  può non essere la scelta giusta, ed è preferibile cambiarlo in
  \texttt{\$mydomain}, che contiene il dominio corrispondente a
  \texttt{\$myhostname}.

Esempi:
\begin{verbatim}
    myorigin = $myhostname (di default) 
    myorigin = $mydomain (preferito) 
\end{verbatim}

\item[\texttt{mydestination}] indica per quali domini inoltrare la posta
  localmente, invece di inviarla ad un'altra macchina. Il default è impostato
  in modo tale che riceva posta solo per la macchina stessa.  Si possono
  specificare nessun dominio o più domini, oppure un file (/nome/file) da
  includere o un certo tipo di tabella (tipo:nome) su cui cercare. I campi
  sono separati da virgole o spazi.

Esempi:

Default:
\begin{verbatim}
    mydestination = $myhostname localhost.$mydomain
\end{verbatim}

Mail server per un dominio:
\begin{verbatim}
    mydestination = $myhostname localhost.$mydomain $mydomain
\end{verbatim}

Host con nomi diversi nel DNS:
\begin{verbatim}
    mydestination = $myhostname localhost.$mydomain www.$mydomain ftp.$mydomain
\end{verbatim}

L'uso di \texttt{\$myhostname} e \texttt{localhost.\$mydomain} è necessario
per evitare comunque possibili loop.

\item[\texttt{mynetworks}] indica tutte le reti di cui questa macchina si fida
  e identifica quindi i client a cui permettere il relay.  Si possono
  specificare le singole reti oppure farle calcolare direttamente a postfix
  (default).  Questo è modificabile col parametro \texttt{mynetworks\_style}:

Default:
\begin{verbatim}
    mynetworks_style = subnet
\end{verbatim}

Le alternative sono:
\begin{basedescript}{\desclabelwidth{1.5cm}\desclabelstyle{\nextlinelabel}}
\item[\texttt{class}] si fida dei client nella classe a cui è connesso (A, B o
  C).
\item[\texttt{subnet}] si fida dei client nelle sottoreti IP a cui è connesso
  (default)
\item[\texttt{host}] si fida solo della macchina locale
\end{basedescript}

Se si specifica manualmente il valore di \texttt{mynetworks}, Postfix non
terrà conto di \texttt{mynetworks\_style}.

Esempio:
\begin{verbatim}
    mynetworks = 192.168.0.0/24, 127.0.0.0/8 
\end{verbatim}
\end{basedescript}


Una volta fatto questo, Postfix è già pronto a funzionare, naturalmente con la
configurazione di default e senza alcun supporto per le sue funzionalità
avanzate. Ogni volta che si modifica la configurazione occorre farla
ricaricare (\texttt{/etc/init.d/postfix reload}) oppure riavviarlo
(\texttt{/etc/init.d/postfix restart}).

Un altro aspetto da tenere in considerazione può essere quello del formato
delle caselle di posta. Di default la posta viene inoltrata nelle mailbox UNIX
standard (\texttt{/var/mail/utente}), in cui c'è un file per ogni utente.
Altrimenti è possibile specificare una mailbox particolare, oppure è possibile
anche fare uso del formato Maildir in cui ogni messaggio è contenuto in un
singolo file.

Per cambiare comportamento basta modificare il parametro
\texttt{home\_mailbox} nel \texttt{main.cf}.

Esempi:
\begin{verbatim}
home_mailbox = Mailbox
\end{verbatim}
in questo caso la casella (mbox) si chiama Mailbox e si trova all'interno
della home dell'utente:
\begin{verbatim}
home_mailbox = Maildir/
\end{verbatim}
in questo caso invece avremo la posta in formato Maildir nella home
dell'utente.


\section{Riscrittura degli indirizzi e domini virtuali}
\label{sec:mail_address_rewrite}

Nel passaggio dei messaggi di posta elettronica tra un server e
l'altro o nelle fasi che precedono l'inoltro vero e proprio nelle
caselle di posta degli utenti, gli indirizzi che sono presenti nei
messaggi (envelope e header) possono richiedere una riscrittura dovuta
a motivi di natura diversa. Adesso ne vediamo le ragioni e analizziamo
in concreto la situazione che stiamo considerando.

Postfix riscrive gli indirizzi in diversi modi. In alcuni casi avremo
bisogno di definire delle vere e proprie tabelle in cui il sistema
andrà a cercare le ``regole'' per queste riscritture. 

Vediamo le possibili riscritture (utilizziamo i nomi originali per
facilitare la ricerca delle sezioni apposite nella documentazione di Postfix).

Per tutta la posta:
\begin{itemize}
\item \textit{Rewrite addresses to standard form}
\item \textit{Canonical address mapping}
\item \textit{Address masquerading}
\item \textit{Virtual address mapping}
\item \textit{Mail transport switch}
\item \textit{Relocated users table}
\end{itemize}

Per la posta locale:
\begin{itemize}
\item \textit{Alias database}
\item \textit{Per-user \texttt{.forward} files}
\item \textit{Non-existent users}
\end{itemize}

Nei dettagli:


\subsection{\textit{Rewrite addresses to standard form}}
 
Prima che il demone \texttt{cleanup} si serva di una qualsiasi tabella, si
occupa di riscrivere l'indirizzo nella forma standard
\verb|utente@dominio.FQDN| tramite il demone \texttt{trivial-rewrite}.
L'obiettivo di questa riscrittura è di ridurre la quantità di informazioni
necessarie da inserire nelle tabelle.

Le riscritture di cui si occupa \texttt{trivial-rewrite} riguardano
l'eliminazione dagli indirizzi di eventuali route esplicite, non supportate,
gli indirizzi in stile UUCP, formati strani come \texttt{utente\%dominio},
l'aggiunta di \texttt{\$myorigin} agli indirizzi (\verb|utente@$myorigin|),
perché Postfix si aspetta indirizza nella forma utente@dominio, l'aggiunta di
\texttt{\$mydomain} a \verb|utente@host| (\verb|utente@host.$mydomain|),
oppure l'eliminazione del punto finale in \verb|utente@site|.
(\verb|utente@site|).

\subsection{\textit{Canonical address mapping}}

Prima che il messaggio finisca nella coda \textit{incoming}, Postfix usa la
canonical table per riscrivere tutti gli indirizzi nell'envelope e negli
header del messaggio. Questo può servire ad esempio per avere indirizzi in
stile \texttt{Nome.Cognome}, piuttosto che basati sul login name.

Il canonical mapping è disabilitato di default. Per abilitarlo basta
modificare il parametro \texttt{canonical\_maps} nel \texttt{main.cf} in modo
da specificare le tabelle di ricerca opportune (una o più di una separate da
spazi o virgole).

Esempio:
\begin{verbatim}
    canonical_maps = hash:/etc/postfix/canonical 
\end{verbatim}

Mentre \texttt{canonical\_maps} si applica a sender e recipient, è possibile
influire anche soltanto su uno dei due tipi di indirizzi, utilizzando
\texttt{sender\_canonical\_maps} e \texttt{recipient\_canonical\_maps}.

Esempio:
\begin{verbatim}
    sender_canonical_maps = hash:/etc/postfix/sender_canonical
    recipient_canonical_maps = hash:/etc/postfix/recipient_canonical 
\end{verbatim}

La loro applicazione avviene prima di \texttt{canonical\_maps}.

Una riscrittura solo per il sender è utile ad esempio quando si vogliono
riscrivere indirizzi non troppo carini in altri esteticamente migliori,
mantenendo però la possibilità di ricevere posta anche sui primi.

\subsection{\textit{Address masquerading}}
 
Questo è un sistema che permette di nascondere tutti gli host all'interno di
un dominio che stanno dietro ad un gateway di posta, in modo tale da far
apparire la posta come proveniente solo dal gateway, invece che dalle singole
macchine.

L'\textit{address masquerading} è disabilitato di default. Per abilitarlo,
occorre modificare il parametro \texttt{masquerade\_domains} nel
\texttt{main.cf}, specificando uno o più domini separati da spazi o virgole.
Il contenuto di questo parametro viene preso in considerazione da sinistra a
destra, e si ferma al primo esito positivo.

Esempio:
\begin{verbatim}
    masquerade_domains = mio.dominio.it dominio.it 
\end{verbatim}
trasforma \texttt{un.mio.dominio.it} in \texttt{mio.dominio.it}, ma
\texttt{un.altro.dominio.it} in \texttt{dominio.it}.

Il prefisso \texttt{!} evita che venga mascherato quel dominio o i suoi
sottodomini.

Esempio:
\begin{verbatim}
    masquerade_domains = !mio.dominio.it dominio.it 
\end{verbatim}
non influisce su \texttt{un.altro.mio.dominio.it} e \texttt{mio.dominio.it},
ma riscrive \texttt{un.altro.dominio.it }in \texttt{dominio.it}.

Il parametro di configurazione \texttt{masquerade\_exceptions} specifica quali
username non devono essere mascherati. Si possono specificare uno o più
username separati da spazi o virgole.

Esempio:
\begin{verbatim}
    masquerade_exceptions = root 
\end{verbatim}
Di default, non ci sono eccezioni.

Di default, il mascheramento avviene solo per gli header del messaggio e per
gli indirizzi dell'envelope sender, ma non per gli envelope recipients.
Questo permette di utilizzare il mascheramento su un mail gateway, senza
impedire la possibilità di inviare posta che arriva dall'esterno a utenti
sulle singole macchine.

Questo comportamento può essere cambiato specificando il parametro
\texttt{masquerade\_classes}.

Esempio:
\begin{verbatim}
    masquerade_classes = envelope_sender, envelope_recipient, header_sender, header_recipient 
\end{verbatim}
In questo modo, non sarà più possibile mandare posta alle singole macchine.

\subsection{\textit{Virtual address aliasing}}

Dopo aver applicato le riscritture basate su canonical e masquerade,
\texttt{cleanup} utilizza la virtual alias table per redirigere la posta per
tutti i destinatari, locali o remoti che siano. Questo influenza soltanto gli
envelope recipient e non ha un effetto sugli header o sugli envelope sender. I
virtual alias sono utili per avere domini virtuali basati su caselle di posta
di utenti reali del sistema e per redirigere la posta per domini che non
esistono più. La ricerca anche in questo caso può essere utilizzata per
trasformare Nome.Cognome nel corrispondente login UNIX, ma il meccanismo
migliore in questo caso sarebbe quello basato su alias locali.

Il virtual aliasing è disabilitato di default. Per abilitarlo occorre
modificare il parametro \texttt{virtual\_alias\_maps} nel \texttt{main.cf},
specificando una o più tabelle, separate da spazi o virgole.

Esempio:
\begin{verbatim}
    virtual_alias_maps = hash:/etc/postfix/virtual 
\end{verbatim}

Gli indirizzi verranno trattati in base al virtual aliasing, ma non in base al
canonical mapping, in modo da evitare cicli.


\subsection{\textit{Mail transport switch}}

Quando è stata definita la destinazione di un messaggio, essa diventa il
default delivery per quel destinatario. Postfix distingue quattro classi di
indirizzi, ognuna delle quali gestita in modo diverso:

\begin{table}[htb]
  \centering
  \footnotesize
  \begin{tabular}{|l|l|l|}
    \hline
    \textbf{Destination matches} & \textbf{Default delivery agent} 
                                 & \textbf{Controlling parameter}  \\
    \hline
    \hline
    \texttt{\$mydestination} or \texttt{\$inet\_interfaces} & local
                                              & \texttt{\$local\_transport} \\
    \texttt{\$virtual\_mailbox\_domains}                    & virtual 
                                              & \texttt{\$virtual\_transport}\\
    \texttt{\$relay\_domains}                           &relay (clone of smtp) 
                                              & \texttt{\$relay\_transport}\\
    none & smtp & \texttt{\$default\_transport}\\
    \hline
  \end{tabular}
\caption{Delivery.}
\label{tab:mail_transport_table}
\end{table}

Una transport table opzionale permette di cambiare questo comportamento. In
questo modo è possibile ad esempio mandare posta via UUCP o mandare posta ad
un sistema di posta "problematico" in grado di gestire al più una connessione
SMTP alla volta.

La transport table è disabilita di default. Per abilitarla occorre modificare
il parametro \texttt{transport\_maps} nel \texttt{main.cf}, specificando una o
più tabelle, separate da spazi o virgole.

Esempio:
\begin{verbatim}
    transport_maps = hash:/etc/postfix/transport 
\end{verbatim}


\subsection{\textit{Alias database}}
 

Quando il messaggio viene inoltrato localmente, \texttt{local} controlla il
destinatario in base al database degli alias. Sono esclusi gli indirizzi
presenti negli header del messaggio. Gli alias locali sono tipicamente
utilizzati per gestire mailing list, o per redirigere la posta del postmaster
o di altri indirizzi particolati su utenti reali.  Naturalmente, come abbiamo
già visto, questo è il meccanismo ideale per gestire indirizzi del tipo
\texttt{Nome.Cognome}.

Il meccanismo di alias è abilitato di default e la configurazione solitamente
dipende dal sistema.

Esempi:
\begin{verbatim}
    alias_maps = hash:/etc/aliases 
    alias_maps = dbm:/etc/aliases, nis:mail.aliases 
\end{verbatim}
Il parametro \texttt{alias\_database} identifica il percorso del file degli
alias.

Esempi:
\begin{verbatim}
    alias_database = hash:/etc/aliases (4.4BSD, LINUX) 
    alias_database = dbm:/etc/aliases (4.3BSD, SYSV<4) 
    alias_database = dbm:/etc/mail/aliases (SYSV4) 
\end{verbatim}


\subsection{\textit{Per-user \texttt{.forward} files}}

Gli utenti possono controllare la destinazione della propria posta utilizzando
un file \texttt{.forward} nella loro home directory. La sintassi del file è la
stessa di quella usata negli alias di sistema, anche se non sono presenti né
la chiave di ricerca, né i due punti. Generalmente si possono inserire
indirizzi mail e mandare il contenuto della mail in pipe a qualche programma.

\subsection{\textit{Non-existent users}}

È possibile gestire in modo particolare la situazione in cui il local delivery
agent abbia a che fare con un destinatario inesistente. In questo si può
decidere di inviare la mail in base ad una serie di regole. I dettagli ed i
parametri da utilizzare sono descritti nella documentazione di Postfix.


\section{Controllo antispam e content filtering}
\label{sec:mail_antispam_filtering}

Come abbiamo visto, Postfix accetta posta solo per i domini e dai client che
gli abbiamo indicato.  Questo evita la possibilità di trovarsi a fare da open
relay e quindi di spedire quantitativi elevati di spam o UCE (Unsolicited
Commercial Email).  Questo non ci salva comunque dall'arrivo di spam verso i
nostri domini ed i nostri utenti.  Per questo ci viene in aiuto una serie di
funzionalità di Postfix. Queste possono servire come controllo antispam o
comunque per rifiutare messaggi secondo criteri ben precisi, tra i quali il
controllo di header e corpo dei messaggi, le restrizioni in base a indirizzi,
mittenti e destinatari, il rispetto degli RFC e dei passi della transazione
SMTP, e l'uso di RBL (Real-time Blackhole List).


I controlli vengono divisi in gruppi ed eseguiti nell'ordine in cui sono
indicati; le varie tipologie di controlli vengono prese in considerazione in
questo ordine:
\begin{verbatim}
smtpd_client_restrictions
smtpd_helo_restrictions
smtpd_sender_restrictions
smtpd_recipient_restrictions
\end{verbatim}

Se tutte le liste restituiscono una risposta positiva, allora il client può
proseguire col comando DATA per mandare il contenuto del messaggio.
Naturalmente i controlli su header e body (\texttt{header\_checks} e
\texttt{body\_checks}) possono ancora provocare un rifiuto del messaggio da
parte di Postfix.

Ognuna delle liste che abbiamo elencato sopra permette le restrizioni
generiche, che sono descritte più avanti.

\texttt{smtpd\_client\_restrictions} può includere inoltre altre restrizioni
più specifiche, e lo stesso vale per \texttt{smtpd\_helo\_restrictions},
\texttt{smtpd\_sender\_restrictions}, e
\texttt{smtpd\_recipient\_restrictions}.

Esiste anche \texttt{smtpd\_etrn\_restrictions}, ma è un controllo non
direttamente legato allo spam.

Vediamo adesso in dettaglio i vari tipi di controllo:

\subsection{\textit{Header filtering}} 

con \texttt{header\_check} possiamo restringere la ricezione dei messaggi in
base a controlli fatti sull'header dei messaggi.

Default:
    Permette qualunque contenuto negli header dei messaggi
    
    Sintassi: una lista di tabelle in cui viene indicato il criterio e
    l'azione da eseguire quando la ricerca porta ad un risultato positivo

\begin{verbatim}
    REJECT
    REJECT testo...
\end{verbatim}
    rifiuta il messaggio, tiene traccia di header e testo opzionale e poi
    manda il testo al mittente

\begin{verbatim}
    IGNORE
\end{verbatim}
    cancella l'header dal messaggio

\begin{verbatim}
    WARN
    WARN testo...
\end{verbatim}
    tiene traccia dell'header con uno warning e del testo opzionale, ma non
    rifiuta il messaggio

\begin{verbatim}
    HOLD
    HOLD testo...
\end{verbatim}
    sposta il messaggio nella coda \textit{hold}. Tiene traccia del testo
    trovato e del testo opzionale.

\begin{verbatim}
    DISCARD
    DISCARD testo...
\end{verbatim}
    finge di accettare correttamente il messaggio e poi lo scarta. Tiene
    traccia del testo trovato e del testo opzionale

\begin{verbatim}
    FILTER transport:nexthop
\end{verbatim}
    Mette in coda il messaggio e poi filtra il messaggio intero. Questo
    naturalmente richiede un cleanup diverso da quello prima del filtro, con
    controllo di header e body disabilitati.  Questo sostituisce l'eventuale
    \texttt{content\_filter} presente nel \texttt{main.cf}. 

Esempi (\texttt{main.cf}):
\begin{verbatim}
    header_checks = regexp:/etc/postfix/header_checks 
    header_checks = pcre:/etc/postfix/header_checks
\end{verbatim}

Esempi (\texttt{header\_checks}):
\begin{verbatim}
    /^to: *utente@dominio\.it/ REJECT
    /^Content-Type: text\/html; charset=euc-kr/     REJECT
    /^Subject:.*mortgage.*/ REJECT   
\end{verbatim}


\subsection{\textit{Body filtering}} 

con \texttt{body\_check} è possibile controllare il testo permesso nel corpo
dei messaggi (il controllo è fatto uno linea alla volta e non c'è possibilità
di gestire più linee come con gli header)

    Default:
        Permette qualunque contenuto nel corpo dei messaggi
        
    Sintassi: 
        una lista di tabelle in cui viene indicato il criterio e
        l'azione da eseguire quando la ricerca porta ad un risultato positivo

\begin{verbatim}
        REJECT
        REJECT testo...
\end{verbatim}
        rifiuta il messaggio, tiene traccia delle linee individuate nel corpo
        e del testo opzionale e poi manda il testo al mittente

\begin{verbatim}
        WARN
        WARN testo...
\end{verbatim}
        tiene traccia delle linee individuate con uno warning e del testo
        opzionale, ma non rifiuta il messaggio

\begin{verbatim}
        IGNORE
\end{verbatim}
        cancella dal messaggio le linee individuate

\begin{verbatim}
        HOLD
        HOLD testo...
\end{verbatim}
        sposta il messaggio nella coda \textit{hold}. Tiene traccia del testo
        trovato e del testo opzionale.

\begin{verbatim}
        DISCARD
        DISCARD testo...
\end{verbatim}
        finge di accettare correttamente il messaggio e poi lo scarta. Tiene
        traccia del testo trovato e del testo opzionale

\begin{verbatim}
        FILTER transport:nexthop
\end{verbatim}
        Mette in coda il messaggio e poi filtra il messaggio intero. Questo
        naturalmente richiede un cleanup diverso da quello prima del filtro,
        con controllo di header e body disabilitati.  Questo sostituisce
        l'eventuale \texttt{content\_filter} presente nel \texttt{main.cf.}

Esempi (\texttt{main.cf}):

\begin{verbatim}
    body_checks = regexp:/etc/postfix/body_checks  
    body_checks = pcre:/etc/postfix/body_checks
\end{verbatim}

Esempio (\texttt{body\_checks}):

\begin{verbatim}
     /^content-disposition: attachment;.*filename=.*\.(bat|pif|com|exe|scr|lnk|vbs)/ REJECT

\end{verbatim}

\subsection{\textit{Client hostname/address restrictions}} 
\texttt{smtpd\_client\_restrictions} permette di filtrare i client da cui
accettare connessioni SMTP

Default:
\begin{verbatim}
    smtpd_client_restrictions =    
\end{verbatim}
    Permette connessioni SMTP da qualunque client

Sintassi:
una lista di restrizioni, separate da spazi o virgole. Le restrizioni vengono
applicate nell'ordine specificato, cioè la prima verificata viene applicata.

Le restrizioni possono riguardare l'hostname del client, l'indirizzo IP, le
informazioni ricevute insieme ai comandi HELO/EHLO, il sender address, o il
recipient address. Le restrizioni su HELO/EHLO, sender e recipient hanno
effetto solo se \texttt{smtpd\_delay\_reject = yes}, cioè quando tutte le
restrizioni vengono valutate dopo il comando RCPT TO.

Esempi:
\begin{verbatim}
    smtpd_client_restrictions = hash:/etc/postfix/access, reject_rbl_client relays.ordb.org  
    smtpd_client_restrictions = hash:/etc/postfix/access, reject_rhsbl_client dsn.rfc-ignorant.org 
    smtpd_client_restrictions = permit_mynetworks, reject_unknown_client
\end{verbatim}

Restrizioni:
\begin{verbatim}
reject_unknown_client
\end{verbatim}
Rifiuta la richiesta quando l'indirizzo IP del client non ha un record PTR nel
DNS, o quando ne ha uno che non coincide con il record A.
\texttt{unknown\_client\_reject\_code} specifica il codice di richiesta
rifiutata (450 di default).

\begin{verbatim}
permit_mynetworks
\end{verbatim}
Permette la richiesta quando l'indirizzo IP del client fa parte di una delle
reti indicate in \texttt{\$mynetworks}.

\begin{verbatim}
reject_rbl_client dominio.tld
\end{verbatim}
Rifiuta la richiesta quando l'indirizzo invertito del client è presente con
record A nel \texttt{dominio.tld}.

\begin{verbatim}
   maps_rbl_reject_code 
\end{verbatim}
specifica il codice di risposta per le richieste rifiutate (554 di default),

\begin{verbatim}
default_rbl_reply 
\end{verbatim}
specifica la risposta di default del server, 

\begin{verbatim}
rbl_reply_maps
\end{verbatim}
specifica le tabelle con le risposte del server indicizzate per dominio RBL.

\begin{verbatim}
reject_rhsbl_client dominio.tld
\end{verbatim}
    Rifiuta la richiesta quando l'hostname del client è presente con un record
    A nel \texttt{dominio.tld}. Ci sono parametri analoghi a quelli della
    restrizione precedente.

\begin{verbatim}
check_client_access maptype:mapname
\end{verbatim}
    Cerca nella mappa indicata restrizioni per hostname, dominio, indirizzo IP
    o di rete.

In questo caso si applicano le restrizioni generiche.

\subsection{\textit{Require HELO (EHLO) command}}

\texttt{smtpd\_helo\_required} indica che il
client \emph{deve} mandare un comando HELO (o EHLO) all'inizio della sessione.
Questo può fermare alcuni software usati per mandare UCE.

Default:
\begin{verbatim}
    smtpd_helo_required = no
\end{verbatim}
    Per default, Postfix non richiede l'uso di HELO (o EHLO).

Sintassi:
    Si o no

Esempio:
\begin{verbatim}
    smtpd_helo_required = yes 
\end{verbatim}

\subsection{\textit{HELO (EHLO) hostname restrictions}}

\texttt{smtpd\_helo\_restrictions} restringe in base agli hostname che
i client possono associare al comando HELO (o EHLO). Alcuni software
possono essere fermati anche usando questo controllo.

Per default, questa restrizione si applica quando il client manda il comando
RCPT TO.

Default:
\begin{verbatim}
    smtpd_helo_restrictions =
\end{verbatim}
Per default, Postfix accetta qualunque cosa ci sia nel comando HELO (o EHLO).
Ci sono tantissimi programmi mal configurati o scritti male.

Sintassi: 
una lista di restrizioni, separate da spazi o virgole. Le restrizioni vengono
applicate nell'ordine specificato, cioè la prima verificata viene applicata.

In aggiunta alle restrizioni che sono caratteristiche dei parametri del
comando HELO (o EHLO), si possono inserire anche quelle sull'hostname del
client, sull'indirizzo del client o su sender e recipient address. 


Esempio:
\begin{verbatim}
    smtpd_helo_restrictions = permit_mynetworks, reject_invalid_hostname
\end{verbatim}
Restrizioni:

\begin{verbatim}
reject_invalid_hostname
\end{verbatim}
Rifiuta la richiesta quando il parametro del comando HELO o EHLO ha una
sintassi di hostname sbagliata. \texttt{invalid\_hostname\_reject\_code}
specifica il codice di risposta per le richieste rifiutate (di default 501).

\begin{verbatim}
reject_unknown_hostname
\end{verbatim}
Rifiuta la richiesta quando l'hostname nel comando non ha né un record A né un
record MX nel DNS.  \texttt{unknown\_hostname\_reject\_code} specifica il
codice di risposta per le richieste rifiutate (di default 450).

\begin{verbatim}
reject_non_fqdn_hostname
\end{verbatim}
Rifiuta la richiesta quando l'hostname non è nella forma di FQDN (Fully
Qualified Domain Name), come richiesto dall'RFC.
\texttt{non\_fqdn\_reject\_code} specifica il codice di risposta per le
richieste rifiutate (di default 504).


\begin{verbatim}
check_helo_access maptype:mapname
\end{verbatim}
Cerca nella mappa indicata l'hostname o il dominio.

Anche qui valgono le restrizioni generiche.

\subsection{\textit{Require strict RFC 821-style envelope
    addresses}}

\texttt{strict\_rfc821\_envelopes} controlla quanto Postfix tolleri il
rispetto nei confronti dei parametri dei comandi MAIL FROM o RCPT TO. Sendmail
ad esempio è molto tollerante, per cui questa possibilità può far perdere
anche molta posta "buona".

Default:
\begin{verbatim}
    strict_rfc821_envelopes = no
\end{verbatim}
    Per default, Postfix accetta qualunque forma di indirizzo.

Esempio:
\begin{verbatim}
    strict_rfc821_envelopes = yes 
\end{verbatim}

\subsection{\textit{Sender address restrictions}}

\texttt{smtpd\_sender\_restrictions} restringe i sender addresses che il sistema accetta nel comando MAIL FROM.

Per default la restrizione si applica quando il client manda il comando RCPT
TO.

Default:
\begin{verbatim}
    smtpd_sender_restrictions =
\end{verbatim}
    Per default, Postfix accetta qualunque sender address.

Sintassi:
    una lista di restrizioni, separate da spazi o virgole. Le restrizioni
    vengono applicate nell'ordine specificato, cioè la prima verificata viene
    applicata.


In aggiunta alle restrizioni che sono caratteristiche dei sender address, si
possono inserire anche quelle sul comando HELO (o EHLO), sull'hostname del
client o sull'indirizzo del client, o sul recipient address. 


Esempio:
\begin{verbatim}
    smtpd_sender_restrictions = hash:/etc/postfix/access, reject_unknown_sender_domain
\end{verbatim}
Restrizioni:

\begin{verbatim}
reject_unknown_sender_domain
\end{verbatim}
Rifiuta la richiesta quando l'indirizzo del sender non ha un record A o MX
sul DNS. \texttt{unknown\_address\_reject\_code} specifica il codice di
risposta per le richieste rifiutate (di default 450: errore temporaneo di
DNS).

\begin{verbatim}
reject_rhsbl_sender dominio.tld
\end{verbatim}
Rifiuta la richiesta quando l'indirizzo invertito del client è presente con
record A nel dominio.  tld. \texttt{maps\_rbl\_reject\_code} specifica il
codice di risposta per le richieste rifiutate (554 di default),
\texttt{default\_rbl\_reply} specifica la risposta di default del server,
\texttt{rbl\_reply\_maps} specifica le tabelle con le risposte del server
indicizzate per dominio RBL.

\begin{verbatim}
check_sender_access maptype:mapname
\end{verbatim}
Cerca nella mappa indicata l'indirizzo del sender e il dominio del sender o la
\verb|localpart@|.

\begin{verbatim}
reject_non_fqdn_sender
\end{verbatim}
Rifiuta la richiesta quando l'indirizzo nel comando MAIL FROM non è nella
forma di FQDN (Fully Qualified Domain Name), come richiesto dall'RFC.
\texttt{non\_fqdn\_reject\_code} specifica il codice di risposta per le
richieste rifiutate (di default 504).

\begin{verbatim}
reject_sender_login_mismatch
\end{verbatim}
Rifiuta la richiesta quando \texttt{\$smtpd\_sender\_owner\_maps} specifica un
owner per l'indirizzo del MAIL FROM, ma il client non è autenticato (SASL) con
quell'indirizzo, o quando il login con cui il client è autenticato non ha un
MAIL FROM corretto secondo \texttt{\$smtpd\_sender\_login\_maps}.

Anche qui si applicano le restrizioni generiche.

\subsection{\textit{Recipient address restrictions}}

\texttt{smtpd\_recipient\_restrictions} riduce i recipient address che
il sistema accetta nei comandi RCPT TO.

Default:
\begin{verbatim}
    smtpd_recipient_restrictions = permit_mynetworks, reject_unauth_destination
\end{verbatim}
    Per default Postfix accetta posta:
    \begin{itemize}
    \item da client fidati i cui IP appartengono a \texttt{\$mynetworks} per
      qualunque destinatario
    \item da client non fidati verso destinatari in \texttt{\$relay\_domains}
      o sottodomini corrispondenti, esclusi indirizzi contenenti routing
      esplicito (\verb|utente@daqualcheparte@dominio|)
  \end{itemize}
In più, accetta posta per cui sa di essere il destinatario finale:

\begin{itemize}
\item per destinatari compresi in \texttt{\$inet\_interfaces}
\item per destinatari compresi in \texttt{\$mydestination}
\item per destinatari compresi in \texttt{\$virtual\_alias\_domains}
\item per destinatari compresi in \texttt{\$virtual\_mailbox\_domains}
\end{itemize}

Sintassi:
    una lista di restrizioni, separate da spazi o virgole. Le restrizioni
    vengono applicate nell'ordine specificato, cioè la prima verificata viene
    applicata. 

In aggiunta alle restrizioni che sono caratteristiche dei recipient address,
si possono inserire anche quelle sul sender address, sul comando HELO (o
EHLO), sull'hostname del client o sull'indirizzo del client. 


Esempio:
\begin{verbatim}
smtpd_recipient_restrictions = permit_mynetworks, reject_unauth_destination
\end{verbatim}
N.B. Occorre specificare almeno una delle restrizioni: \texttt{reject},
\texttt{defer}, \texttt{defer\_if\_permit}, o
\texttt{reject\_unauth\_destination}.  Altrimenti Postfix si rifiuterà di
ricevere posta.

Restrizioni:

\begin{verbatim}
permit_auth_destination
\end{verbatim}
Accetta la richiesta quando una delle seguenti condizioni è vera:
\begin{itemize}
\item l'indirizzo del destinatario è compreso in \texttt{\$relay\_domains} o
  in un sottodominio corrispondente, e l'indirizzo non contiene routing
  esplicito (\verb|utente@daqualcheparte@dominio|)
\item Postfix è il destinatario finale: un destinatario compreso cioè in
  \texttt{\$mydestination}, \texttt{\$inet\_interfaces},
  \texttt{\$virtual\_alias\_domains}, o \texttt{\$virtual\_mailbox\_domains}.
\end{itemize}

\begin{verbatim}
reject_unauth_destination
\end{verbatim}
Rifiuta la richiesta a meno che non sia una vera una delle seguenti condizioni:
\begin{itemize}
\item l'indirizzo di destinazione è compreso in \texttt{\$relay\_domains} o in
  un sottodominio corrispondente, e l'indirizzo non contiene routing esplicito
  (utente@daqualcheparte@dominio)
\item Postfix è il destinatario finale: un destinatario compreso cioè in
  \texttt{\$mydestination}, \texttt{\$inet\_interfaces},
  \texttt{\$virtual\_alias\_domains}, o \texttt{\$virtual\_mailbox\_domains}.
\end{itemize}
\texttt{relay\_domains\_reject\_code} specifica il codice di risposta per le
richieste rifiutate (554 di default).

\begin{verbatim}
permit_mx_backup
\end{verbatim}
Accetta la richiesta quando il sistema locale è un MX per la destinazione.
Vale anche il caso in cui il sistema locale sia la destinazione finale.
Comunque, anche in questo caso, il server non invierà mail con indirizzi che
abbiano un routing esplicito (\verb|utente@daqualcheparte@dominio|)

\texttt{permit\_mx\_backup\_networks} è un parametro opzionale per richiedere
che l'MX primario sia compreso in una lista di reti.

Parametri di configurazione rilevanti: \texttt{permit\_mx\_backup\_networks},
\texttt{\$mydestination}, \texttt{\$inet\_interfaces}.

\begin{verbatim}
check_recipient_access maptype:mapname
\end{verbatim}
Cerca nella mappa indicata indirizzi di destinazione, dominio del destinatario
o \verb|localpart@|

\begin{verbatim}
check_recipient_maps
\end{verbatim}
Rifiuta la richiesta quando il recipient address non è presente in una delle
seguenti tabelle:

\begin{table}[htb]
  \centering
  \footnotesize
  \begin{tabular}{|l|l|}
    \hline
    \textbf{Recipient domain matches} & \textbf{Recipient lookup table}   \\
    \hline
    \hline
    \texttt{\$mydestination} or \texttt{\$inet\_interfaces} &  
                                         \texttt{\$local\_recipient\_maps} \\
    \texttt{\$virtual\_alias\_domains} & \texttt{\$virtual\_alias\_maps} \\
    \texttt{\$virtual\_mailbox\_domains} & \texttt{\$virtual\_mailbox\_maps} \\
    \texttt{\$relay\_domains} & \texttt{\$relay\_recipient\_maps} \\
    \hline
  \end{tabular}
\caption{Tabelle}
\label{tab:mail_recipient_table}
\end{table}


Note: 

- in assenza di \texttt{\$local\_recipient\_maps} o
\texttt{\$relay\_recipient\_maps} non viene effettuato alcun controllo per il
dominio corrispondente.

- Postfix effettua un controllo implicito su \texttt{check\_recipient\_maps}
alla fine di tutte le recipient restrictions.

\begin{verbatim}
reject_unknown_recipient_domain
\end{verbatim}
Rifiuta la richiesta quando l'indirizzo del recipient non ha un record A o MX
sul DNS. \texttt{unknown\_address\_reject\_code} specifica il codice di
risposta per le richieste rifiutate (di default 450: errore temporaneo di
DNS).

\begin{verbatim}
reject_rhsbl_recipient dominio.tld
\end{verbatim}
Rifiuta la richiesta quando l'indirizzo del recipient è presente con record A
nel \texttt{dominio.tld}. \texttt{maps\_rbl\_reject\_code} specifica il codice
di risposta per le richieste rifiutate (554 di default),
\texttt{default\_rbl\_reply} specifica la risposta di default del server,
\texttt{rbl\_reply\_maps} specifica le tabelle con le risposte del server
indicizzate per dominio RBL.

\begin{verbatim}
reject_non_fqdn_recipient
\end{verbatim}
Rifiuta la richiesta quando l'indirizzo nel comando RCPT TO non è nella forma
di FQDN (Fully Qualified Domain Name), come richiesto dall'RFC.
\texttt{non\_fqdn\_reject\_code} specifica il codice di risposta per le
richieste rifiutate (di default 504).

Anche qui si applicano le restrizioni generiche.

\subsection{\textit{Restrizioni generiche}}

Queste restrizioni possono essere usate per gli hostname o gli indirizzi dei
client, per gli hostname forniti dal comando HELO (o EHLO), e per gli
indirizzi di sender e recipient.

Restrizioni:

\begin{basedescript}{\desclabelwidth{1.5cm}\desclabelstyle{\nextlinelabel}}
  
\item[\texttt{permit}] Accetta la richiesta. Questa restrizione è utile alla
  fine di una lista di restrizioni, per chiarire la politica di default.
  
\item[\texttt{defer}] Rimanda la richiesta e invita il client a prova più
  tardi. Questa restrizione è utile alla fine di una lista di restrizioni, per
  chiarire la politica di default.
  
\item[\texttt{reject}] Rifiuta la richiesta. Questa restrizione è utile alla
  fine di una lista dei restrizioni, per chiarire la politica di default.
  \texttt{reject\_code} specifica il codice di risposta per le
  richieste rifiutate (di default 554)
    
  \item[\texttt{warn\_if\_reject}] Cambia il significato della restrizione
    successiva, in modo che tenga traccia con uno warning invece di rifiutare
    una richiesta (cerca "\texttt{reject\_warning}" nel logfile). Questa ad
    esempio è utile per provare nuove restrizioni in un ambiente di produzione
    senza rischiare di perdere posta.
    
  \item[\texttt{reject\_unauth\_pipelining}] Rifiuta la richiesta quando il
    client manda comandi prima del tempo senza controllare che Postfix
    fornisca davvero il supporto per il pipelining dei comandi. Questo
    impedisce ad alcuni bulk mailer di abusare del pipelining per velocizzare
    l'invio di mail.
\end{basedescript}

\subsection{\textit{Controlli ulteriori e filtri}}

Ci sono anche alcune altre opzioni, ma non sono molto usate e comunque sono
documentate nella sezione "UCE control" della documentazione di Postfix,
insieme a quelle fino ad ora descritte.

Esiste inoltre la possibilità di fare content filtering. In questo modo un
filtro è in grado di cambiare il contenuto di un messaggio prima di rimandarlo
a Postfix, rifiutare completamente il messaggio comunicandolo a Postfix,
oppure mandare la mail a qualcun altro.

C'è anche la possibilità di decidere se filtrare solo la posta di certi utenti
o certi domini.

Per abilitare questa funzione, occorre modificare opportunamente il
\texttt{master.cf}, inserendo i dettagli sul filtro e sul suo utilizzo. Questa
è comunque una funzionalità ancora in sviluppo ed è documentata in uno dei
file di testo aggiuntivi che fanno parte della documentazione.

 
\section{Configurazioni di esempio}
\label{sec:mail_example_conf}

\texttt{main.cf}:
\begin{verbatim}
queue_directory = /var/spool/postfix
command_directory = /usr/sbin
daemon_directory = /usr/lib/postfix
program_directory = /usr/lib/postfix

header_checks = pcre:/etc/postfix/header_checks
body_checks = pcre:/etc/postfix/body_checks

myhostname = mio.dominio.it

relay_domains = altro.dominio.it

smtpd_helo_required = yes

smtpd_recipient_restrictions =
        reject_unauth_pipelining,
        check_sender_access hash:/etc/postfix/access,
        check_client_access hash:/etc/postfix/access,
        reject_invalid_hostname,
        reject_non_fqdn_sender,
        reject_non_fqdn_recipient,
        reject_unknown_sender_domain,
        reject_rbl_client relays.ordb.org,
        permit_mynetworks,
        reject_unauth_destination

alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases

virtual_alias_maps = hash:/etc/postfix/altro.dominio.it

\end{verbatim}

\texttt{header\_checks}:
\begin{verbatim}

/^From: matrix-mail@263.net/ REJECT
/^From: web@chinapccom.com/ REJECT
/^From: mayores21@ono.com/ REJECT
/^to: friend@public\.com$/      REJECT
/^x-mailer: mail bomber$/       REJECT
/^x-mailer: multimailer$/       REJECT

/^Content-Type: text\/html; charset=euc-kr/     REJECT
/^content-type: text\/html; charset="?ks_c_5601-1987"?/ REJECT
/^subject: =\?ks_c_5601-1987\?b\?/      REJECT

/^Subject:.*XXX.*/ REJECT
/^Subject:.*save[ ]refinance.*/ REJECT
/^Subject:.*refinance[ ]save.*/ REJECT
...

\end{verbatim}

\texttt{body\_checks}:
\begin{verbatim}

/^content-disposition: attachment;.*filename=.*\.(bat|pif|com|exe|scr|lnk|vbs)"?$/ REJECT
/^       name=".*\.(bat|pif|com|exe|scr|lnk|vbs)"$/     REJECT
/^begin 666 www.myparty.yahoo.com$/     REJECT
/emailads\.8k\.com/     REJECT 551 we are not the source of this spam
...

\end{verbatim}

\texttt{access}:
\begin{verbatim}

80.116.226 OK
217.230.160 OK
217.230.161 OK
217.230.162 OK
217.230.163 OK
...

\end{verbatim}

\texttt{aliases}:
\begin{verbatim}

root:           roots
uucp:           roots
abuse:          postmaster
mailman-owner:  postmaster
www-data:       webmaster
postfix:        postmaster
...
cvs-commits:             "|/var/lib/mailman/mail/wrapper post cvs-commits"
cvs-commits-admin:       "|/var/lib/mailman/mail/wrapper mailowner cvs-commits"
cvs-commits-request:     "|/var/lib/mailman/mail/wrapper mailcmd cvs-commits"
owner-cvs-commits:       cvs-commits-admin
cvs-commits-owner:       cvs-commits-admin
...
nome.cognome             ncognome
...

\end{verbatim}

\texttt{altro.dominio.it}:
\begin{verbatim}

webmaster@altro.dominio.it   admin1,admin2
...
diabolik@altro.dominio.it    diabolik@un.dominio.com
...

\end{verbatim}


\section{Cenni sull'autenticazione SMTP}
\label{sec:mail_SMTP_auth}

Il protocollo SMTP è un protocollo con grossi limiti per quanto riguarda la
sicurezza. Non c'è ad esempio alcuna possibilità di essere certi della
provenienza di un messaggio, né di trasferire la posta in modo crittato.  Per
questo si fa uso di controlli di vario tipo per evitare l'abuso del relay da
parte di terzi. Questo però è un grosso limite perché occorre per forza che le
macchine siano collocate su apposite reti e abbiano indirizzi ben precisi per
fare in modo che possano usufruire del relay del server di posta che abbiamo
configurato.

La possibilità che abbiamo di risolvere questo problema è quella di usare SSL
(Secure Socket Layer).  Nel caso di Postfix è ad esempio possibile utilizzare
TLS (Transport Layer Security) per trasmettere la posta non in chiaro e per
autenticare le connessioni. I passi necessari alla configurazione si limitano
all'abilitazione del supporto TLS e alla creazione dei certificati necessari
per usare l'autenticazione SMTP.

Questa estensione di SMTP è invece descritta
nell'\href{http://www.rfc-editor.org/rfc/rfc3207.txt}{RFC~3207
  (http://www.ietf.org/rfc/rfc3207.txt)}.

\section{Cenni sui protocolli POP3 e IMAP}
\label{sec:mail_POP_IMAP}

POP3 (Post Office Protocol 3) è attualmente il protocollo più utilizzato per
scaricare la posta elettronica da un server. Le sue specifiche sono descritte
nella \href{http://www.ietf.org/rfc/rfc1939.txt}{RFC~1939
  (http://www.ietf.org/rfc/rfc1939.txt)}.  Lo scambio di comandi tra client e
server permettono di scaricare la posta e cancellarla dal server.

Nella prima fase di una transazione il client si connette al server (porta
standard 110) riceve il saluto (greeting) dal server e si autentica. Una volta
ottenuta l'autorizzazione, il client può inviare al server i comandi per
leggere o cancellare la posta. Dopo il comando QUIT viene eseguita la
cancellazione dei messaggi, in base alle richieste precedenti del client.

Esempio di una transazione:

Un esempio di sessione POP3 da linea di comando:
\begin{verbatim}
S: +OK POP3 Server (Version 4.13) ready.
C: USER utente
S: +OK Password required for utente.
C: PASS ******
S: +OK utente has 1 visible message (0 hidden) in 3472 octets.
C: STAT
S: +OK 1 3472
C: LIST
S: +OK 1 visible messages (1256 octets)
S: 1 1256
S: .
C: RETR 1
S: +OK 1256 octets
S: Return-Path:
S: Received:  
... (header del messaggio)
S: Date: Sun, 04 May 2003 19:54:05 +0200
S: From: Amico
S: To: utente@mio.dominio
S: Subject: corso 
S: Content-Type: text/plain; charset=ISO-8859-1; format=flowed
S: Content-Transfer-Encoding: 8bit
S: X-UIDL: d0Yef2wU43400rWVot
S: Ciao,
S: ci vediamo al corso!
S: .
C: DELE 1
S: +OK Message 1 has been deleted.
S: .
C: QUIT
S: +OK POP3 Server (Version 4.13) shutdown.
\end{verbatim}

IMAP (Internet Message Access Protocol) è un protocollo che invece permette di
accedere ai messaggi di posta elettronica sul server come se fossero presenti
localmente ed descritto nella
\href{http://www.ietf.org/rfc/rfc3501.txt}{RFC~3501
  (http://www.ietf.org/rfc/rfc3501.txt)}.

Ad esempio, posta elettronica presente su un server IMAP può essere consultata
attraverso computer diversi senza bisogno di trasferire i messaggi tra questi,
perché in effetti la posta rimane sul server.

Se POP3 funziona bene con un singolo computer e permette la lettura "offline"
della posta, non consente però di condividere l'accesso alla posta tra
postazioni diverse.

IMAP permette inoltre di accedere alla posta in modalità diverse ("online",
"offline", "disconnected"), e supporta accessi concorrenti a caselle di posta
condivise. Dal lato client, naturalmente, non c'è alcun bisogno di conoscere
il formato in cui i messaggi vengono poi effettivamente archiviati sul server.

I comandi del protocollo permettono di creare, cancellare e rinominare la
mailbox, di controllare la presenza di nuovi messaggi, di cancellarli per
sempre, di impostare flag particolari sui messaggi, di fare ricerche e
scaricare i messaggi in base a certi criteri.

Entrambi i protocollo sono stati successivamente integrati in modo da
permettere l'accesso sicuro alla propria posta elettronica, evitando di
mandare in chiaro le password o il contenuto dei messaggi.



\chapter{Il Web}
\label{cha:web_intro}


\section{Il Web}
\label{sec:web_intro}


\section{Il protocollo HTTP}
\label{sec:web_HTTP_protocol}

Il protocollo HTTP (\textit{HyperText Transfer Protocol}) permette di
trasferire dati indipendentemente dal sistema che lo utilizza. Generalmente è
utilizzato per contenuti ipertestuali, ed è il protocollo standard per il
World Wide Web, dai primi anni '90. E' descritto nella
\href{http://www.ietf.org/rfc/rfc2616.txt}{RFC~2616}, che definisce "HTTP/1.1"
e aggiorna la precendente RFC~2068.

La prima versione era identificata come HTTP/0.9 e permetteva semplicemente
uno scambio di dati attraverso la rete. La versione successiva, HTTP/1.0, ha
invece permesso di scambiare messaggi in formato MIME (Multipurpose Internet
Mail Extensions), con informazioni sui dati, le richieste e le risposte
trasmesse. Questa versione però non andava molto d'accordo con gli effetti
dell'esistenza di proxy, di cache, né con l'esigenza di gestire connessioni
persistenti o virtual host. In più non permetteva a due applicazione di
"dialogare" per capire quali fossero le caratteristiche supportate e quali no.
Questa nuova specifica, HTTP/1.1, ha anche dei requisiti più precisi in modo
garantire l'affidabilità delle funzionalità che prevede.

HTTP è utilizzato anche come protocollo generico per servizi di tipo diverso,
o per comunicare con proxy per altri protocolli (SMTP, NNTP, FTP, ...).

L'utilizzo più comune resta comunque lo scambio di pagine HTML e di file in
genere tra un server web ed un client (un browser ad esempio). Il client
riceve la pagina e poi richiede gli eventuali altri file (immagini, fogli di
stile, ...) per mostrare i contenuti richiesti.

Generalmente una richiesta HTTP è caratterizzata da un metodo (GET, POST,
...), da un URI (Uniform Resource Identifier) che identifica la risorsa a cui
ci si riferisce e dalla versione del protocollo (es. HTTP/1.1).

Esempio:
\begin{verbatim}
GET / HTTP/1.1
\end{verbatim}

In questo caso la risorsa non è altro che il path assoluto (/).

In una richiesta poi possiamo avere una serie di header HTTP (come
\texttt{Accept-Language}, \texttt{Expires}, ...).

Vediamo quindi che un metodo HTTP non è altro che un comando (richiesta al
server) specificato nel protocollo stesso.  Ci sono metodi diversi, vediamone
alcuni tra i più comuni.

GET è sicuramente il più comune, perché permette di richiedere un file al
server.

Esempio: (C: è il client, S: è il server)
\begin{verbatim}
C: GET / HTTP/1.0

S: HTTP/1.1 200 OK
S: Date: Fri, 09 May 2003 10:25:09 GMT
S: Server: Apache/1.3.26 (Unix) PHP/4.2.3
S: X-Powered-By: PHP/4.2.3
S: Connection: close
S: Content-Type: text/html
\end{verbatim}
(segue il contenuto della pagina html).

In questo caso la richiesta è andata a buon fine (200 è uno dei possibili
Status Code, ed indica l'esito positivo della richiesta).

HEAD permette di richiedere solo l'header di una risorsa.

Esempio:
\begin{verbatim}
C: HEAD / HTTP/1.0
\end{verbatim}
in questo caso la risposta sarebbe identica a quella dell'esempio precedente,
ma priva del contenuto del file html.

POST permette di inviare delle informazioni nella forma di un attributo e di
un valore.

Esempio:
\begin{verbatim}
C: POST /search.php HTTP/1.1
Host: www.truelite.it
User-Agent: curl/7.9.5 (i586-pc-linux-gnu) libcurl 7.9.5 (ipv6 enabled)
Pragma: no-cache
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
Keep-Alive: 300
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 2098

mode=1&text=Debian

HTTP/1.1 200 OK
Date: Fri, 09 May 2003 10:45:09 GMT
Server: Apache/1.3.26 (Unix) PHP/4.2.3
X-Powered-By: PHP/4.2.3
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: text/html

(contenuto della pagina html)
\end{verbatim}

In questo caso abbiamo richiesto una pagina tramite uno script in php che si
occupa di fare delle ricerche.

Ci sono alcuni metodi che sono disponibili soltanto col protocollo HTTP/1.1,
ad esempio il metodo PUT, che permette di inviare un file sul server, cioè di
fare un upload del file.

Come si vede dagli esempi, la comunicazione tra client e server è spesso
caratterizzata dalla presenza di molti header, che forniscono informazioni su
quanto viene trasferito.  Abbiamo cioè qualcosa del tipo:
\begin{verbatim}
Header: valore
\end{verbatim}

Gli header HTTP (sempre secondo la RFC del protocollo) si dividono in 4
categorie:
\begin{basedescript}{\desclabelwidth{1.5cm}\desclabelstyle{\nextlinelabel}}  
\item[\textit{GENERAL HEADERS}] 
Contengono informazioni generali sui dati trasferiti e sul protocollo. Fanno
parte di questa categoria le direttive legate all'uso della cache, le data, e
l'eventuale supporto di una versione specifica del protocollo HTTP.
\item[\textit{REQUEST HEADERS}] 
Contengono informazioni sulle richieste effettuate o sul client. Fanno parte
ad esempio di questa categoria Accept:, Accept-Encoding:, Accept-Language:,
che permettono di indicare il tipo di file accettati dal client (indicato come
MIME type), il tipo di encoding (ad esempio per accettare file compressi), e
le lingue preferite o accettate.
\item[\textit{RESPONSE HEADERS }] 
Contengono informazioni sulle risorse richieste e sul server.  Un esempio di
questa categoria è l'header Server: che fornisce informazioni sul software
utilizzato dal server.
\item[\textit{ENTITY HEADERS}] 
Contengono informazioni sull'entità di quanto trasferito. Fanno parte di
questa categoria Content-Encoding:, Content-Language: e Content-Lenght, che
permettono di indicare l'encoding del contenuto, la lingua e la lunghezza del
file.
\end{basedescript}


Per quanto riguarda invece le risposte, il protocollo prevede Status Code ben
precisi.  La risposta contiene la versione del protocollo HTTP, lo Status Code
(composto da tre cifre) e la descrizione.

Gli esempi che abbiamo visto in precedenza fornivano una risposta positiva:
\begin{verbatim}
HTTP/1.1 200 OK
\end{verbatim}

Il significato del codice è determinato prima di tutto dalla prima cifra dello
Status Code; una classificazione dei significati dei vari codici (con
alcunio esempi) si è riportata in tab.~\ref{tab:web_http_codes}.

\begin{table}[htb]
  \centering
  \footnotesize
  \begin{tabular}{|l|p{8cm}|}
    \hline
    \textbf{Codice di risposta} & \textbf{Significato}  \\
    \hline
    \hline
    \texttt{1XX}                    & \textit{Informational}: 
                                      Codici informativi. \\
    \texttt{101 Switching Protocols}& Usato in seguito ad una richiesta di 
                                      cambiamento di protocollo. \\
    \hline
    \texttt{2XX}                    & \textit{Client request successful}: 
                                      Indicano che la richiesta da parte del
                                      client è stata ricevuta ed accettata. \\
    \texttt{200 OK}                 & Richiesta accettata e il server 
                                      porterà a termine il trasferimento
                                      del file richiesto. \\
    \texttt{202 Accepted}           & Richiesta accettata anche se
                                      il server ancora non sta
                                      portando avanti il trasferimento del file
                                      richiesto. \\ 
    \hline
    \texttt{3XX}                    & \textit{Client request redirected,
                                      further action necessary}:  
                                      Indicano che il server ha bisogno di
                                      ulteriori informazioni per portare a
                                      termine la richiesta. \\
    \texttt{301 Moved Permanently}  & Il file richiesto è stato
                                      definitivamente spostato ad un altro
                                      indirizzo. \\
    \texttt{304 Not Modified}       & La richiesta del client prevedeva un
                                      header If-Modified-Since, che permette
                                      di ricevere un file solo se
                                      modificato. In questo caso la risposta è
                                      negativa ed il client non riceverà il
                                      file perché ne è già in possesso.\\ 
    \hline
    \texttt{4XX}                    & \textit{Client request incomplete}:  
                                      Indica un errore commesso dal client. \\
    \texttt{400 Bad Request}        & La richiesta non è comprensibile
                                      (es. sintassi errata). \\
    \texttt{405 Method Not Allowed} & Il metodo specificato non è un metodo
                                      permesso per quell'URI. \\
    \hline
    \texttt{5XX}                    & \textit{Server errors}:  
                                      Indica un errore da parte del server. \\
    \texttt{500 Internal Server Error}& Errore non precisato e il server non
                                      può rispondere alla richiesta. \\
    \texttt{503 Service Unavailable}& Il server al momento non è in grado di
                                      rispondere (es. per troppo carico). \\
    \hline
  \end{tabular}
\caption{I codici di risposta del protocollo HTTP.}
\label{tab:web_http_codes}
\end{table}



\section{Introduzione ad Apache}
\label{sec:web_apache_intro}

Apache (http://httpd.apache.org) è il server HTTP più usato ed è rilasciato
con licenza libera.  Le statistiche di Netcraft
(http://www.netcraft.com/survey/) attribuiscono ad Apache oltre il 60\% dei
siti attivi su Internet.  Il progetto che segue Apache è un progetto aperto ed
estremamente attivo, ed il suo team prende il nome di Apache Group. Lo
sviluppo è iniziato tra il 1994 ed il 1995, partendo dal codice dello storico
server web NCSA (National Center for Supercomputing Applications)
\texttt{httpd}. La prima release di Apache fu la 0.6.2, rilasciata nell'aprile
del 1995.

Apache è un server web potente e flessibile, conforme ad HTTP/1.1. E'
altamente configurabile e estendibile tramite moduli. 

E' disponibile per Windows, Netware, OS/2 e su quasi tutte le piattaforme
UNIX, e naturalmente per GNU/Linux.

Tra le tante caratteristiche:

\begin{itemize}
\item permette di avere pagine ad accesso autenticato con diversi meccanismi 
\item consente i server side include
\item consente l'utilizzo dei CGI
\item permette di gestire infiniti alias e infinite regole di rewrite 
\item permette la negoziazione dei contenuti in base alle capacità del client
\item ha un supporto completo per i Virtual Host
\item è altamente configurabile per quanto riguarda la gestione dei file di
  log
\end{itemize}

Le ultime versioni di Apache rilasciate sono quelle dello sviluppo della 2.0,
disponibile da alcuni mesi. Le versioni ormai stabilissime e complete della
1.3 sono però ancora le più utilizzate e per questo faremo riferimento ad una
installazione di Apache 1.3.26 o 1.3.27 su Debian GNU/Linux.

Apache è un demone solitamente sempre attivo sul sistema (raramente è
consigliabile farlo partire a richiesta da inetd o demoni simili, a meno che
non venga utilizzato davvero occasionalmente), in ascolto sulla porta standard
del servizio HTTP (80). Naturalmente questo può essere cambiato modificando il
suo file di configurazione.

All'avvio, Apache legge il file di configurazione, apre i file di log e poi fa
partire un certo numero di processi in attesa di richieste (numero definibile
dall'amministratore del server). In questo modo solo il processo padre ha i
diritti di superutente, mentre i processi hanno privilegi inferiori. Nel
nostro caso i processi girano con i privilegi dell'utente \texttt{www-data}.

Per avviare Apache, è possibile lanciare direttamente il comando
\texttt{apache} (su altre distribuzioni o se installato dai sorgenti
\texttt{httpd}), oppure si può utilizzare lo script \texttt{apachectl} o,
ancora piú comodamente, lanciare lo script di avvio
\texttt{/etc/init.d/apache}.

Esempi:
\begin{verbatim}
# apache 
# apachectl start
# /etc/init.d/apache start
\end{verbatim}

Per controllare se tutto è andato bene basterà connettersi al server web sulla
porta di default 80.

La configurazione con cui lo abbiamo lanciato è quella di default, contenuta
nel file \texttt{/etc/apache/httpd.conf}, ma è anche possibile specificare da
linea di comando il file di configurazione da usare.

Esempio:
\begin{verbatim}
# apache -f /home/christian/conf/httpd_prova.conf
\end{verbatim}

Per visualizzare la versione di Apache in uso ed i parametri di configurazione
impostati durante la compilazione, basta lanciare apache con il parametro
"-V":
\begin{verbatim}
# apache -V
Server version: Apache/1.3.27 (Unix) Debian GNU/Linux
Server built:   Apr 28 2003 15:38:28
Server's Module Magic Number: 19990320:13
Server compiled with....
 -D EAPI
 -D HAVE_MMAP
 -D HAVE_SHMGET
 -D USE_SHMGET_SCOREBOARD
 -D USE_MMAP_FILES
 -D HAVE_FCNTL_SERIALIZED_ACCEPT
 -D HAVE_SYSVSEM_SERIALIZED_ACCEPT
 -D SINGLE_LISTEN_UNSERIALIZED_ACCEPT
 -D HARD_SERVER_LIMIT=4096
 -D HTTPD_ROOT="/usr"
 -D SUEXEC_BIN="/usr/lib/apache/suexec"
 -D DEFAULT_PIDLOG="/var/run/apache.pid"
 -D DEFAULT_SCOREBOARD="/var/run/apache.scoreboard"
 -D DEFAULT_LOCKFILE="/var/run/apache.lock"
 -D DEFAULT_ERRORLOG="/var/log/apache/error.log"
 -D TYPES_CONFIG_FILE="/etc/mime.types"
 -D SERVER_CONFIG_FILE="/etc/apache/httpd.conf"
 -D ACCESS_CONFIG_FILE="/etc/apache/access.conf"
 -D RESOURCE_CONFIG_FILE="/etc/apache/srm.conf"
\end{verbatim}

La man page di apache fornisce informazioni su tutte le opzioni con cui è
possibile avviare apache.



\section{Configurazione di base}
\label{sec:web_apache_base_conf}


Come abbiamo detto, la configurazione di apache può essere fatta attraverso il
suo file di configurazione. Nel nostro caso \texttt{/etc/apache/httpd.conf}.

Il file può contenere direttive e commenti (preceduti da \texttt{\#}). Ci sono
direttive generali, che valgono cioè per ogni situazione, e direttive che
permettono invece di specificare il contesto nel quale valgono, ad esempio per
una particolare risorsa, una particolare directory, o un particolare modulo
attivo. Questi contesti si chiamano "container".

In generale quindi ci sono direttive a livello server (utilizzabili quindi
soltanto quando si definiscono le caratteristiche del nostro server),
direttive globali e locali (utilizzabili per tutto il server o solo nei casi
specifici) e direttive locali (usate solo all'interno di un container).

I parametri necessari per la configurazione si limitano a:
\begin{itemize}
\item nome del server
\item porta su cui mettere in ascolto il demone (ed eventualmente l'IP
  particolare da utilizzare)
\item utente e gruppo con cui far girare i processi 
\item directory contenente le pagine HTML
\item l'indirizzo dell'amministratore del sistema (non è obbligatorio ma è
  bene definirlo)
\end{itemize}

Esempio:
\begin{verbatim}
ServerName zaphod
Listen 80
User www-data
Group www-data
DocumentRoot /var/www
ServerAdmin webmaster@zaphod
\end{verbatim}

Vediamo adesso nei dettagli un file di configurazione un po' più completo:

\begin{verbatim}
### Section 1: Global Environment
# Il demone è sempre attivo
ServerType standalone
# la root per i file del server (configurazione, log,... se non specificato diversamente)
ServerRoot /etc/apache
LockFile /var/lock/apache.lock
PidFile /var/run/apache.pid
ScoreBoardFile /var/run/apache.scoreboard
Timeout 300
# permette connessioni persistenti (più di una richiesta per connessione)
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 15
# numero server attivi
MinSpareServers 5
MaxSpareServers 10
# numero server lanciati all'avvio
StartServers 5
# numero massimo server attivi
MaxClients 150
# caricamento di alcuni moduli
LoadModule config_log_module /usr/lib/apache/1.3/mod_log_config.so
LoadModule mime_magic_module /usr/lib/apache/1.3/mod_mime_magic.so
LoadModule mime_module /usr/lib/apache/1.3/mod_mime.so
LoadModule negotiation_module /usr/lib/apache/1.3/mod_negotiation.so
LoadModule status_module /usr/lib/apache/1.3/mod_status.so
LoadModule autoindex_module /usr/lib/apache/1.3/mod_autoindex.so
LoadModule dir_module /usr/lib/apache/1.3/mod_dir.so
LoadModule cgi_module /usr/lib/apache/1.3/mod_cgi.so
LoadModule userdir_module /usr/lib/apache/1.3/mod_userdir.so
LoadModule alias_module /usr/lib/apache/1.3/mod_alias.so
LoadModule rewrite_module /usr/lib/apache/1.3/mod_rewrite.so
LoadModule access_module /usr/lib/apache/1.3/mod_access.so
LoadModule auth_module /usr/lib/apache/1.3/mod_auth.so
LoadModule expires_module /usr/lib/apache/1.3/mod_expires.so
LoadModule unique_id_module /usr/lib/apache/1.3/mod_unique_id.so
LoadModule setenvif_module /usr/lib/apache/1.3/mod_setenvif.so
<IfModule mod_status.c>
  ExtendedStatus On
</IfModule>
### Section 2: 'Main' server configuration
Port 80
User www-data
Group www-data
ServerAdmin webmaster@zaphod
DocumentRoot /var/www
# container per la DocumentRoot
<Directory /var/www/>
    Options Indexes Includes FollowSymLinks MultiViews
    AllowOverride None
    Order allow,deny
    Allow from all
</Directory>
# home directory degli utenti: richieste per /~utente
<IfModule mod_userdir.c>
    UserDir public_html
</IfModule>
<Directory /home/*/public_html>
    AllowOverride FileInfo AuthConfig Limit
    Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
    <Limit GET POST OPTIONS PROPFIND>
        Order allow,deny
        Allow from all
    </Limit>
    <Limit PUT DELETE PATCH PROPPATCH MKCOL COPY MOVE LOCK UNLOCK>
        Order deny,allow
        Deny from all
    </Limit>
</Directory>
# uso di .htaccess per definire gli accessi
AccessFileName .htaccess
<Files ~ "^\.ht">
    Order allow,deny
    Deny from all
</Files>
# mime type
TypesConfig /etc/mime.types
DefaultType text/plain
<IfModule mod_mime_magic.c>
    MIMEMagicFile /usr/share/misc/magic.mime
</IfModule>
HostnameLookups Off
ErrorLog /var/log/apache/error.log
LogLevel warn
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
CustomLog /var/log/apache/access.log combined
# alias
Alias /icons/ /usr/share/apache/icons/
<Directory /usr/share/apache/icons>
    Options Indexes MultiViews
    AllowOverride None
    Order allow,deny
    Allow from all
</Directory>
Alias /images/ /usr/share/images/
<Directory /usr/share/images>
    Options MultiViews
    AllowOverride None
    Order allow,deny
    Allow from all
</Directory>
# scriptalias
ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
<Directory /usr/lib/cgi-bin/>
    AllowOverride None
    Options ExecCGI -MultiViews
    Order allow,deny
    Allow from all
</Directory>
\end{verbatim}

Prendiamo in considerazione adesso alcuni aspetti fondamentali legati alle
direttive della configurazione di Apache.

Vediamo ad esempio le direttive container. Esse identificano per quali risorse
vengano specificate alcune direttive di configurazione.  Una direttiva si apre
e si chiude con dei tag simili a quelli HTML. Alcune di queste direttive
possono incluse una dentro l'altra.

Esempio:
\begin{verbatim}
<Directory /var/www/private>
Order deny,allow
Deny from all
Allow from 127.0.0.1
</Directory>
\end{verbatim}

In questo modo neghiamo l'accesso a quella directory a tutti i client che non
siano connessi dalla macchina stessa su cui gira il server web.

Alcuni esempi di direttive container sono:

\begin{basedescript}{\desclabelwidth{1.5cm}\desclabelstyle{\nextlinelabel}}  
\item[\texttt{Directory}] (per una directory definita nel contesto del file
  system locale)
\item[\texttt{Files}] (come per la precedente, ma si riferisce a uno o più
  file; permette l'uso di wildcard)
\item[\texttt{Location}] (come Directory, ma si applica agli URL e non al file
  system locale)
\item[\texttt{Virtualhost}] (per i domini virtuali)
\item[\texttt{Limit}] (per determinati metodi HTTP)
\end{basedescript}

Ci sono poi direttive "dinamiche" che si applicano soltanto se valgono certe
condizioni.  Un esempio è il caricamento di un modulo.

Esempio:
\begin{verbatim}
<IfModule mod_userdir.c>
    UserDir public_html
</IfModule>
\end{verbatim}

Se abbiamo caricato il modulo per la visualizzazione delle home degli utenti,
la directory da prendere in considerazione per i file HTML sarà
\texttt{\tild/public\_html}.

Per definire le opzioni da impostare su una determinata directory, si fa uso
della direttiva Options.

Esempio:
\begin{verbatim}
Options ExecCGI FollowSymLinks MultiViews
\end{verbatim}

Permette ad Apache di eseguire script CGI, di seguire i link simbolici e di
abilitare la content negotiation.

Le direttive vengono ereditate dalle directory superiori se non vengono
esplicitamente definite. E' possibile intervenire utilizzando i caratteri
\texttt{+} e \texttt{-} prima delle opzioni che intendiamo modificare.

Esempio:
\begin{verbatim}
<Directory /var/www/articoli>
    Options FollowSymlinks Includes
</Directory>
<Directory /var/www/articoli/nuovi>
    Options +Indexes -FollowSymlinks
</Directory>
\end{verbatim}

In questo caso la seconda directory eredita la possibilità di eseguire SSI, ma
non la possibilità di seguire link simbolici, ed in più abilita la generazione
della lista del contenuto della directory.

Possiamo anche includere nel file di configurazione un singolo file o i file
contenuti in intere directory.

Esempio:
\begin{verbatim}
Include "vhosts/*"
\end{verbatim}

Potremmo ad esempio fare uso di virtual host (li vedremo nei dettagli più
avanti) e includere nel file di configurazione generale un file di
configurazione per singolo dominio. In questo modo avremmo i file presenti in
una directory \texttt{vhosts} della \texttt{ServerRoot} specificata.


\section{Virtual Hosts}
\label{sec:web_virtual_host}

Il termine Virtual Host indica la possibilità di gestire uno o più server
sulla stessa macchina, distinguendoli in base al loro hostname. Apache è stato
uno dei primi server che ha permesso di avere virtual host IP-based in modo
molto semplice. Dalla versione 1.1 in poi, permette di avere sia virtual host
IP-based, che virtual host name-based.

Nel primo caso (IP-based) ad ogni host virtuale corrisponde un IP differente.
La soluzione è comoda ma ben poco praticabile con molti domini virtuali, e per
lo spreco di IP. Nel secondo caso (Name-based), più virtual host puntano allo
stesso indirizzo IP. In questo caso si risparmiano gli indirizzi IP, anche se
è richiesto il supporto HTTP/1.1 da parte del browser (soltanto browser molto
vecchi non lo supportano), perché fa uso dell'header Host: inviato dal client
durante la richiesta.

Mettere in funzione un virtual host IP-based è molto semplice. Basta
specificare l'indirizzo con la direttiva \texttt{Listen} e poi definire un
container VirtualHost.

Esempio:
\begin{verbatim}
Listen 192.168.10.10:80
...
<VirtualHost 192.168.10.10:80>
ServerAdmin hostmaster@dominio.tld
DocumentRoot /var/www/virtualhosts
ServerName www.dominio.tld
ServerAlias dominio.tld
ErrorLog logs/dominio.tld-error.log
CustomLog logs/dominio.tld-access.log combined
</VirtualHost>
...
\end{verbatim}

Per attivare un virtual host Name-based invece basta soltanto usare un'altra
direttiva, \texttt{NameVirtualHost}:

\begin{verbatim}
NameVirtualHost 192.168.10.10
...
<VirtualHost 192.168.10.10>
ServerAdmin hostmaster@dominio.tld
DocumentRoot /var/www/virtualhosts
ServerName www.dominio.tld
ServerAlias dominio.tld
ErrorLog logs/dominio.tld-error.log
CustomLog logs/dominio.tld-access.log combined
</VirtualHost>
...
\end{verbatim}

Apache prende quindi in considerazione tutte le richieste per l'IP specificato
da \texttt{NameVirtualHost} e confronta l'header \texttt{Host}: inviato dal
client con \texttt{ServerName} e con ogni eventuale \texttt{ServerAlias}, in
modo da restituire le pagine corrette.

Per rendere la gestione dei virtual host ancora più comoda è possibile fare
uso della direttiva Include che abbiamo visto prima che ci permette di
includere uno o più file di configurazione specifici contenenti le direttive
\texttt{VirtualHost}. In questo modo è anche possibile delegarne la gestione
anche a un utente senza fornigli anche la possibilità di alterare la
configurazione di tutto il server.

Un sistema altrettanto utile, in particolare per gestire una situazione in cui
occorre gestire un gran numero di domini virtuali, è quello di utilizzare
\texttt{mod\_rewrite}, un modulo di Apache che permette di manipolare e
riscrivere un URL. Lo approfondiremo più avanti, ma nel frattempo
applichiamolo alle nostre necessità.

Esempio:
\begin{verbatim}
# Carichiamo il modulo 
LoadModule rewrite_module /usr/lib/apache/1.3/mod_rewrite.so
# Lo abilitiamo
RewriteEngine on
# Estrae il nome del dominio
RewriteCond %{HTTP_HOST} ^www\.(.+)$
# e riscrive l'URL per indirizzare correttamente il client
RewriteRule ^/(.+)$ /var/www/virtualhosts/%1/$1 [L]
\end{verbatim}%$

In questo modo la regola applicata "riscrive" ad esempio un indirizzo
www.dominio.tld in modo che vada a puntare ai file nella directory
\texttt{/var/www/virtualhosts/dominio.tld}.


\section{Autenticazione e controllo degli accessi}
\label{sec:web_access_control}


Esistono sistemi diversi per fare in modo che Apache permetta o neghi
l'accesso ad una risorsa ad un client:

\begin{itemize}
\item tramite l'uso delle direttive \texttt{allow} e \texttt{deny} di
  \texttt{mod\_access} (controlli basati su hostname, IP e header HTTP)
\item tramite i moduli di autenticazione standard di Apache (con file di
  testo, anonima, con database DBM, database DB e Digest) 
\item tramite moduli di Apache "esterni" (basati ad esempio su MYSQL, LDAP,
  Kerberos, SMB...)
\end{itemize}

Nel primo caso Apache verifica semplicemente da dove proviene la richiesta e
decide se permettere o meno l'accesso alla risorsa. Negli altri casi invece
Apache richiede al client ulteriori informazioni (ad esempio utente e
password) prima di decidere.

Nel caso di \texttt{mod\_access} tutto è gestito tramite le direttive
\texttt{allow}, \texttt{deny} e \texttt{order}.

La direttiva \texttt{allow} permette l'accesso, \texttt{deny} lo nega, mentre
\texttt{order} indica l'ordine secondo il quale vengono interpretate le due
direttive precedenti, quando naturalmente vengono utilizzate entrambe.

Esempi:

Se vogliamo permettere o negare l'accesso al singolo host
\texttt{dominio.tld}, possiamo usare:
\begin{verbatim}
allow from dominio.tld
deny from dominio.tld
\end{verbatim}

Se invece vogliamo riferirci a tutti gli host del dominio, possiamo far
precedere il dominio dal punto (\texttt{.}):
\begin{verbatim}
allow from .dominio.tld
deny from .dominio.tld
\end{verbatim}

Se invece specifichiamo entrambe le direttive, usiamo anche \texttt{order} per
definire la policy:

In questo modo potranno accedere tutti, tranne l'host \texttt{domain.tld}.
\begin{verbatim}
order allow,deny
allow from all
deny from domain.tld
\end{verbatim}

Adesso invece neghiamo l'accesso a tutti e lo permettiamo solo al singolo
host:
\begin{verbatim}
order deny,allow
deny from all
allow from domain.tld
\end{verbatim}

Allo stesso modo possiamo controllare gli accessi da IP ben precisi o da range
di IP:
\begin{verbatim}
allow from 127.0.0.1 192.168.0.0/16 192.168.100.0/255.255.255.0 10.10.10
\end{verbatim}

Gli indirizzi possono essere specificati con il singolo IP, la singola rete,
specificando rete e netmask, oppure attraverso il CIDR.

Il controllo tramite gli header HTTP funziona allo stesso modo, usando ad
esempio la direttiva \texttt{SetEnvIf}":
\begin{verbatim}
SetEnvIf Referer "^http://www.dominio.tld/" local_referal
# Permette l'accesso ai browser che non mandano informazioni sul Referer
SetEnvIf Referer "^$" local_referal
<Directory /var/www/immagini>
   Order Deny,Allow
   Deny from all
   Allow from env=local_referal
</Directory>
\end{verbatim}%$

In questo modo, ad esempio, possiamo evitare di far utilizzare le immagini del
nostro sito da altri facendo in modo che possano essere utilizzate solo dalle
nostre pagine.

Un altro esempio sarebbe quello di usare la direttiva \texttt{BrowserMatch}
per restringere l'accesso ad alcuni User-Agent, come qualche spider
particolare.  Oppure per restringere l'accesso ad una directory di pagine
scritte per un determinato browser.


Per quanto riguarda l'accesso con autenticazione, facciamo invece uso delle
direttive \texttt{AuthName} e \texttt{AuthType}, che ci permettono di definire
il nome (realm) inviato al modulo di autenticazione di Apache che stiamo
usando e il tipo di invio di nome utente e password: Basic (in chiaro) o
Digest (MD5).  

Ogni modulo avrà poi un specifica direttiva per indicare dove si trovano i
parametri per l'autenticazione, ad esempio \texttt{AuthUserFile} per
l'autenticazione attraverso \texttt{mod\_auth}. Alcuni moduli poi permettono
di controllare anche l'appartenenza ad un gruppo specifico, con
\texttt{AuthGroupFile} sempre per \texttt{mod\_auth}.

La direttiva \texttt{Require} ci permette invece di definire il criterio di
autenticazione autoritativo, nel caso ce ne siano diversi.  Possiamo indicare
in questo caso un utente o una lista di utenti o gruppi, oppure "valid-user",
ed in questo caso l'accesso è consentito ad ogni utente che abbia superato con
successo la fase di autenticazione. In questo modo è possibile utilizzare gli
stessi file con nomi utente e password, ma restringere ulteriormente l'accesso
ad alcune risorse del nostro server.

Avremo quindi un container di questo tipo:
\begin{verbatim}
<Location /private>
AuthName "Nome o realm"
AuthType Basic | Digest
Auth...UserFile /path/to/user/file
Auth...GroupFile /path/to/group/file
require valid-user | user utente1 utente2... | group gruppo1 gruppo2 ...
</Location>
\end{verbatim}

E' possibile utilizzare il file \texttt{.htaccess} all'interno della
directory, purché si utilizzi la direttiva \texttt{AllowOverride}:
\begin{verbatim}
AllowOverride AuthConfig
\end{verbatim}
Esempio:

Vediamo un esempio di autenticazione Basic:
\begin{verbatim}
<Location /private>
AuthName "Area riservata"
AuthType "Basic"
AuthUserFile /etc/apache/passwd
AuthGroupFile /etc/apache/group
require valid-user
</Location>
\end{verbatim}

La gestione di utenti e password può essere fatta utilizzando
\texttt{htpasswd}, che permette di creare e modificare i file che contengono
utenti e password:

Per creare il file ed inserire il primo utente:
\begin{verbatim}
# htpasswd -c /etc/apache/passwd utente1
\end{verbatim}

e poi per aggiungere l'altro:
\begin{verbatim}
# htpasswd /usr/local/apache/auth/passwd paperino
\end{verbatim}

Il file conterrà semplicemente utenti e password crittate, uno per riga,
separati dal simbolo dei due punti (\texttt{:}).

Per l'autenticazione digest si usa in modo analogo \texttt{htdigest}, mentre
se utenti e password si trovano in un database, si usa \texttt{dbmmanage}.

Nel caso in cui volessimo utilizzare un sistema di autenticazione basato su
nome utente e password e nello stesso tempo un controllo su IP o hostname di
provenienza, è possibile utilizzare la direttiva \texttt{Satisfy} per decidere
se l'accesso è consentito a chi ha superato almeno uno dei controlli oppure
entrambi (\texttt{any} o \texttt{all}).

Analogamente al sistema che abbiamo descritto è possibile autenticare gli
accessi con altri moduli di Apache.

\section{Redirezione}
\label{sec:redirezione}

La possibilità di gestire le richieste di risorse inviate al server in modo
tale che possano essere interpretate in modo conforme alle nostre esigenze può
essere attuata principalmente con tre diversi meccanismi:

\begin{basedescript}{\desclabelwidth{1.5cm}\desclabelstyle{\nextlinelabel}}  
\item[\textit{aliasing}] la richiesta permette di accedere in modo trasparente
  alla risorsa locale che vogliamo (tramite \texttt{mod\_alias})
\item[\textit{redirecting}] il client riceve una notifica sul nuovo indirizzo
  della risorsa e viene redirezionato (tramite \texttt{mod\_alias})
\item[\textit{rewriting}] l'URL viene parzialmente o completamente riscritto
  (tramite \texttt{mod\_rewrite})
\end{basedescript}

Con la direttiva \texttt{Alias} possiamo utilizzare il primo dei meccanismi
descritti.

Esempio
\begin{verbatim}
Alias /icons/ /usr/share/apache/icons/
\end{verbatim}

In questo modo possiamo rendere accessibili anche delle risorse al di fuori
della nostra \texttt{DocumentRoot}.

Ogni risorsa che nell'URL faccia riferimento a \texttt{/icons/} viene cercate
nella directory locale \texttt{/usr/share/apache/icons/}.

\texttt{AliasMatch} invece permette di controllare l'aliasing tramite
espressioni regolari:
\begin{verbatim}
AliasMatch /foto/(.*)\.jpg$ /immagini/altaqualita/foto/$1.jpg
\end{verbatim}

Per fare un alias di script CGI analogamente usiamo \texttt{ScriptAlias} e
\texttt{ScriptAliasMatch}:
\begin{verbatim}
ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
ScriptAliasMatch /cgi-bin/(.*)\.pl$ /usr/lib/cgi-bin/perl/$1.pl 
\end{verbatim}

Mentre questo meccanismo è completamente trasparente al client, potremmo voler
notificare al client un eventuale cambiamento di URL.  Possiamo farlo
utilizzando la direttiva \texttt{Redirect}.  Se la richiesta necessita di un
reindirizzamento, il server lo comunica al client con l'apposito Status Code
HTTP.

\begin{verbatim}
Redirect [status] [prefisso dell'URL] [destinazione]
\end{verbatim}

Lo status può assumere i seguenti valori:

\begin{basedescript}{\desclabelwidth{1.5cm}\desclabelstyle{\nextlinelabel}}  
  
\item[\texttt{permament}] (associato allo Status Code HTTP 301): redirect
  permanente
\item[\texttt{temp}] (associato allo Status Code HTTP 302): redirect
  temporaneo (default) 
\item[\texttt{gone}] (associato allo Status Code HTTP 410): non è un redirect
  vero e proprio, la risorsa non è più disponibile.
\end{basedescript}

Esempio:
\begin{verbatim}
Redirect permanent /notizie http://www.dominio.tld/news/old/
\end{verbatim}

Anche in questo caso abbiamo una direttiva \texttt{RedirectMatch}, che fa uso
di espressioni regolari.

Esempio:
\begin{verbatim}
RedirectMatch (.*)\.(zip|gz)$ http://www.dominio.tld/archivi/$1.$2
\end{verbatim}%$

In questo modo abbiamo fatto in modo che ogni richiesta di un file con
estensione \texttt{.zip} o \texttt{.gz} venga reindirizzata correttamente.


L'utilizzo di \texttt{mod\_rewrite} permette invece di utilizzare un
meccanismo molto più avanzato per reindirizzare le richieste, utilizzando
criteri diversi, come ad esempio un'autenticazione, oppure l'indirizzo di
provenienza, o il browser utilizzato.

La direttiva da utilizzare è \texttt{RewriteRule}, ed ha una sintassi identica
a quella di \texttt{AliasMatch}, ma si possono specificare dei flag ulteriori
(tra parentesi quadre) che permettono di definire in che modo viene fatta la
riscrittura.

\begin{verbatim}
RewriteRule [URL da riscrivere] [nuovo URL] [[flags]]
\end{verbatim}
Esempio:
\begin{verbatim}
RewriteRule /icons/(.*) /usr/share/apache/icons/$1
\end{verbatim}
Alcuni flag che si possono inserire sono:

- R [=code] permette di definire il tipo di redirect
- F rende irraggiungibile quella risorsa (403 Forbidden)
- NC per evitare che l'espressione regolare sia case sensitive

Esempio:
\begin{verbatim}
RewriteRule /icons/(.*) /usr/share/apache/icons/$1 [R=permanent,NC]
\end{verbatim}%$

Le regole di rewriting sono estremamente potenti quando vengono associate a
controlli di altro tipo e non soltanto sull'URL. Possiamo controllare ad
esempio il browser utilizzato, oppure l'IP da cui proviene la richiesta. Per
fare questo abbiamo bisogno di una direttiva ulteriore per specificare le
condizioni, la \texttt{RewriteCond}.

Esempi:
\begin{verbatim}
RewriteCond %{REMOTE_ADDR} ^192.168\.1\.1
RewriteCond %{REMOTE_USER} utente
RewriteRule ^/$ /private/ [L]
\end{verbatim}%$

In questo caso la regola di rewrite viene eseguita soltanto se l'indirizzo IP
del client e l'utente remoto sono quelli specificati.

Per far eseguire la regola anche nel caso in cui valga solo una delle due
condizioni basta specificare "[or]" tra una condizione e l'altra.
\begin{verbatim}
RewriteCond %{REMOTE_ADDR} ^192.168\.1\.1 [or]
RewriteCond %{REMOTE_USER} utente
RewriteRule ^/$ /private/ [L]
\end{verbatim}%$

Se abbiamo bisogno di molte regole, possono essere inserite un file apposito
(di testo, un database DBM, un programma esterno), che poi possiamo richiamare
con la direttiva \texttt{RewriteMap}.



\section{File di log}
\label{sec:web_log_file}

La gestione dei log permette di tenere traccia di tutte le richieste HTTP che
il server web riceve. In questo modo è possibile controllare nei dettagli
l'attività del server, e gli eventuali errori.

Distinguiamo due tipi di file di log, quelli di errore e quelli di accesso.
Quelli di errore vengono generati comunque, mentre quelli di accesso devono
essere appositamente configurati.
 
I log di errore, di default, finiscono nel file \texttt{logs/error.log} nella
root directory di Apache, ma è possibile modificare questa impostazione in
modo da redirigerli su un altro file, oppure farli gestire al syslog.

Esempio:
\begin{verbatim}
ErrorLog /var/log/apache/error.log
ErrorLog syslog
\end{verbatim}

Naturalmente, nel caso di una gestione di Virtual Host, è possibile avere un
file di log di errore per ognuno di essi.

Possiamo definirne il livello, utilizzando la direttiva \texttt{LogLevel} con
uno dei seguenti valori: \texttt{debug}, \texttt{info}, \texttt{notice},
\texttt{warn}, \texttt{error}, \texttt{crit}, \texttt{alert}, \texttt{emerg}.

Esempio:
\begin{verbatim}
LogLevel warn
\end{verbatim}

I log di accesso registrano tutte le richieste HTTP che sono state fatte al
server e permettono ad esempio di creare delle statistiche sul lavoro fatto
dal server o sulle visite o il traffico generato da particolari siti o
Virtual Host. Questo è possibile perché il server inserisce nei log
una serie di informazioni legate ad ogni richiesta HTTP (data ed ora, indirizzo
del client, browser utilizzato, referrer, nome del file, ...).

L'analisi dei log permette quindi di ottenere tutte questa statistiche,
utilizzando applicazioni dedicate a questo, come Awstats, Webalizer, o Analog.

Usando la direttiva \texttt{TransferLog} otteniamo i log nel formato di
default "\textit{Common Log Format}", mentre possiamo definire un formato
specifico utilizzando la direttiva \texttt{LogFormat} e definendo poi i file
di log con \texttt{CustomLog}. Anche in questo caso possiamo avere file di log
diversi per Virtual Host diversi.

Esempio:
\begin{verbatim}
TransferLog /var/log/apache/access.log
\end{verbatim}
Genera i log in formato Common.

\begin{verbatim}
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
CustomLog /var/log/apache/access.log combined
\end{verbatim}

Genera i log in formato \textit{Combined} come specificato. Il formato
Combined è molto comune e molto usato dai programmi che generano statistiche
perché fornisce molte informazioni. Possiamo ad esempio valutare non soltanto
gli accessi ai singoli siti, ma la loro provenienza, il numero di pagine
visitate, e il modo in cui si è arrivati a quella pagine.

Per la gestione dei log (che spesso su server altamente utilizzati raggiungono
dimensioni consistenti) occorre predisporre molto spazio su disco, magari in
una partizione apposita e dotarsi di strumenti che ci permettano di archiviare
comodamente i vari file. Per questo possiamo utilizzare "logrotate" che
generalmente gestisce la rotazione di buona parte dei log di un sistema
GNU/Linux preoccupandosi periodicamente di rinominarli e comprimerli,
archiviarli o cancellarli. Altrimenti possiamo scegliere altri strumenti
appositi per i log dei server web, ad esempio "Cronolog", che ci
permette diavere i log suddivisi in base al mese o alla settimana a
cui si riferiscono, il tutto in modo completamente automatico.



\section{I moduli}
\label{sec:web_modules}

Apache ha la possibilità di caricare moduli mentre è in esecuzione attraverso
il supporto DSO (Dynamic Shared Object).

Questi moduli, come abbiamo visto anche in precedenza, permettono di gestire
diverse funzionalità, che vanno dall'interazione di Apache con
linguaggi di scripting, alla possibilità di utilizzare il potente
motore di rewriting, al supporto di pressochè infiniti meccanismi di
autenticazione di accesso alle risorse.

Il meccanismo dei moduli permette di non dover ricompilare Apache ogni volta
che si ha bisogno di una funzionalità nuova, e permette anche di cambiare al
volo la configurazione e di avere diverse istanze di Apache che girano sulla
stessa macchina con configurazioni profondamente diverse.

Altri esempi di moduli molto usati, e che vediamo brevemente, sono quelli per
supportare CGI, SSI, PHP, e SSL.

\section{CGI}
\label{sec:web_CGI}

I CGI (\textit{Common Gateway Interface}) vengono gestiti dal modulo
\texttt{mod\_cgi} e permettono ad un server web di interagire con programmi
esterni, che prendono il nome di CGI o script CGI. Questo è il modo più
semplice di avere siti con un contenuto dinamico.

Per abilitare il supporto dei CGI è possibile abilitare la direttiva Options
utilizzando come argomento ExecCGI all'interno del container in cui prevediamo
di mettere gli script, oppure usare una direttiva ScriptAlias come abbiamo
visto in precedenza:
\begin{verbatim}
ScriptAlias /cgi-bin /usr/lib/cgi-bin
\end{verbatim}

Se intendiamo utilizzare degli script al di fuori di quella directory occorre
anche che ne abilitiamo la loro gestione con una direttiva \texttt{AddHandler}:
\begin{verbatim}
AddHandler cgi-script .cgi .sh .pl
\end{verbatim}

In questo caso abilitiamo all'esecuzione script con estensione \texttt{.cgi},
\texttt{.sh} (script di shell per esempio), e \texttt{.pl} (script in perl,
tra i più comuni script CGI).

\section{SSI}
\label{sec:web_server_side_include}

Le Inclusioni Lato Server (SSI, \textit{Server Side Includes}, gestite dal
modulo \texttt{mod\_include}) permettono di inserire comandi all'interno delle
pagine web, in modo che possano essere eseguiti prima dell'invio del file al
client che l'ha richiesto. Le operazioni generalmente riguardano inclusione di
file esterni e esecuzione di script CGI.

Per fare in modo che Apache le gestisca, basta modificare il file di
configurazione in modo da aggiungere:
\begin{verbatim}
AddType text/html .shtml
AddHandler server-parsed .shtml
\end{verbatim}

In questo modo stabiliamo che i file con estensione \texttt{.shtml} sono file
html e devono essere gestiti da Apache nel modo che abbiamo descritto.

Naturalmente occorre anche che abilitiamo la loro esecuzione all'interno della
\texttt{DocumentRoot} o in una parte di essa utilizzando la direttiva:
\begin{verbatim}
Options +Includes
\end{verbatim}

Non siamo obbligati a utilizzare file \texttt{.shtml} (anche se è una pratica
molto comune) e possiamo ad esempio permettere la possibilità di usare SSI
anche nei file con estensione \texttt{.html}, semplicemente aggiungendola come
parametro nella direttiva AddHandler:
\begin{verbatim}
AddHandler server-parsed .shtml .html
\end{verbatim}


\section{PHP}
\label{sec:web_PHP}

PHP (acronimo ricorsivo per \texttt{PHP: Hypertext Preprocessor}) è un
linguaggio di scripting general-purpose rilasciato con licenza libera molto
utilizzato; è molto adatto per lo sviluppo Web e può essere integrato
nell'HTML. PHP è utilizzabile su tutti i principali sistemi operativi e server
web, ed è possibile avere accesso ad una quantità enorme di moduli per gestire
qualunque tipo di necessità, dalla semplice gestione del testo, all'XML,
all'interfaccia con i database SQL, ecc ecc.

Nonostante possa essere usato anche per altri obiettivi, il campo di maggiore
utilizzo di PHP è lo scripting server-side. Per utilizzarlo con Apache
generalmente si fa uso di un modulo apposito, anche se è possibile utilizzarlo
anche come script CGI (questo permette di utilizzarlo con quasi tutti gli
altri server web ma non è certo una scelta ottimale se usato con Apache).

Le modifiche alla configurazione di Apache necessarie per installarlo
riguardano il caricamento del modulo opportuno:
\begin{verbatim}
LoadModule php4_module /usr/lib/apache/1.3/libphp4.so
\end{verbatim}

e l'aggiunta delle direttive \texttt{AddType} per permettere ad Apache di
gestire correttamente gli script:
\begin{verbatim}
AddType application/x-httpd-php .php .phtml .php3
AddType application/x-httpd-php-source .phps
\end{verbatim}


\section{Cenni sul protocollo HTTPS}
\label{sec:web_HTTPS_protocol}

Il protocollo HTTPS è una variante di HTTP creata da Netscape per gestire
transazioni sicure. 

HTTPS è semplicemente HTTP su SSL (Secure Socket Layer). La porta standard per
HTTPS è la 443, come assegnato dalla IANA (Internet Assigned Numbers
Authority) e le richieste possono essere semplicemente effettuate con un
browser che le supporto utilizzando come protocollo "\texttt{https://}".

Per usare Apache con HTTPS ci sono due alternative. Una è quella di usare un
modulo apposito, \texttt{mod\_ssl}, l'altra è quella di usare Apache-SSL.

\texttt{mod\_ssl} fornisce crittografia forte per Apache 1.3 attraverso SSL
(v2/v3) e TLS (Transport Layer Security). Il suo sviluppo è partito nel 1998
dal codice scritto per Apache-SSL.

\texttt{mod\_ssl} è software libero (licenza BSD-style), è disponibile sia per
Unix che per Win32, permette crittografia forte a 128 bit, algoritmi RSA e
Diffie-Hellman. In più è perfettamente conforme ed integrato nella struttura
modulare di Apache.

Apache-SSL invece è una versione di Apache ricompilato con alcune patch e
linkato ad openssl.


\section{Un esempio: un sistema di webmail basato su IMAP}
\label{sec:mail_webmail_IMAP}


Un sistema di webmail è una delle applicazioni più utili e diffuse. Con gli
strumenti che abbiamo preso in considerazione possiamo costruire un sistema
affidabile ed estremamente configurabile per gestire la posta attraverso
un'interfaccia web.

Gli strumenti che utilizzeremo saranno Postfix, come MTA, Courier, come server
IMAP, e Squirrelmail, come sistema di webmail.

I passi da fare sono molto semplici, una volta installati velocemente vari
applicativi dai pacchetti della nostra distribuzione:
\begin{verbatim}
# apt-get install postfix apache courier-imap squirrelmail
\end{verbatim}

Per quanto riguarda Postfix, ci preoccuperemo di configurarlo come meglio
crediamo dal punto di vista dell'invio e della ricezione della posta, e
verificheremo di usare le caselle di posta in formato Maildir (come abbiamo
già visto), inserendo questa riga nel file di configurazione \texttt{mail.cf}:
\begin{verbatim}
home_mailbox = Maildir/
\end{verbatim}

In questo modo potremo usare Courier come server IMAP, dato che gestisce le
caselle soltanto in quel formato. Sarebbe possibile utilizzare anche il
formato mbox con un altro server, ad esempio dovecot, ma la scelta del formato
Maildir ci permette anche di avere un sistema più affidabile e performante.

A questo punto sappiamo di poter accedere tramite IMAP alle caselle in cui
Postfix metterà la posta degli utenti del nostro sistema.  L'unica accortezza
in più che potremmo voler prendere è quella di fare in modo che ogni nuovo
utente creato sul sistema abbia già una casella di posta in formato Maildir,
anche se vuota. Per evitare quindi dover creare manualmente la directory
Maildir nella home dei nuovi utenti possiamo crearla in \texttt{/etc/skel}. In
questa directory ci sono file (ed eventualmente directory) che verranno
copiati nella home di ogni nuovo utente creato tramite il comando
\texttt{adduser}.
\begin{verbatim}
/etc/skel# maildirmake
\end{verbatim}

Per quanto ci serve adesso, la configurazione di default di Courier-IMAP ci
soddisfa.

Adesso possiamo preoccuparci di Squirrelmail. Squirrelmail è scritto in PHP, e
per questo, durante la sua installazione avremo installato anche PHP4, e
configurato Apache in modo da poter eseguire gli script in PHP, nel modo che
abbiamo descritto precedentemente.

In più dobbiamo permettere ad Apache di rendere disponibili i file installati
da Squirrelmail, che in questo caso sono in \texttt{/usr/share/squirrelmail}:
\begin{verbatim}
Alias /squirrelmail /usr/share/squirrelmail/
\end{verbatim}

Naturalmente potremmo voler definire un Virtual Host apposito per il nostro
webmail, ad esempio \texttt{mail.dominio.tld} o \texttt{webmail.dominio.tld},
e configurarlo di conseguenza.

Proviamo a richiedere al nostro server web l'URL
\texttt{http://localhost/squirrelmail} e otteniamo un errore. Apache ci dice
che non abbiamo il permesso di accedere a quella risorsa. Questo perché ci
siamo dimenticati di aggiungere anche \texttt{index.php} ai file che vengono
mostrati di default quando viene richiesta una directory del sito e non un
file preciso.

Nel file di configurazione di Apache dovremo quindi avere qualcosa del genere.
Nel nostro caso mancava \texttt{index.php}.
\begin{verbatim}
<IfModule mod_dir.c>
    DirectoryIndex index.html index.htm index.shtml index.cgi index.php
</IfModule>
\end{verbatim}

Adesso possiamo vedere tranquillamente la pagina di login di Squirrelmail,
autenticarci, e gestire la posta attraverso il server IMAP, come se
utilizzassimo un client di posta. La comodità di usare IMAP è che in questo
modo possiamo condividere l'accesso tra il sistema di webmail e un client di
posta che supporti IMAP e utilizzare senza problemi uno dei due sistemi.

Per motivi di privacy e sicurezza potremo naturalmente voler evitare di leggere la
posta e di trasferire in chiaro la nostra password, e per questo potremmo
voler configurare Apache in modo da permettere la lettura della posta
attraverso HTTPS piuttosto che HTTP. Lo stesso discorso vale per IMAP. Courier
permette anche di fare accedere in modo sicuro alla caselle attraverso IMAP su
SSL. Nel caso in cui avessimo anche bisogno di fornire un servizio di accesso
alla posta tramite POP3 (o POP3 su SSL) possiamo installare anche il pacchetto
di Courier apposito.

Questi sono i pacchetti che ci potrebbero interessare:
\begin{verbatim}
courier-imap-ssl - IMAP daemon with SSL, PAM and Maildir support
courier-pop - POP3 daemon with PAM and Maildir support
courier-pop-ssl - POP3 daemon with SSL, PAM and Maildir support
\end{verbatim}

In questo caso abbiamo presupposto di gestire semplicemente utenti reali del
nostro sistema, ma, nel caso volessimo realizzare un server di posta per molti
utenti e molti domini virtuali gestiti sulla stessa macchina, possiamo evitare
di dover creare utenti UNIX e gestire il tutto (Postfix e Courier) con le
informazioni su utenti e domini accessibili via SQL o LDAP, o su altri db o
file. Postfix inoltrerà la posta seguendo le impostazioni contenute in uno di
questi sistemi, e Courier autenticherà gli utenti allo stesso modo.

\ifwhole\else

\clearpage

\tableofcontents

\end{document}

\fi
