Newsgroup: it.comp.lang.perl
Titolo: Authen::SASL in SMTP

Vorrei usare il modulo Authen::SASL per autenticarmi presso un server SMTP.
Mi sono letto la documentazione del modulo e qualche stralcio di RFC, ma non
e` che ci abbia capito granche'.
Qualcuno per caso l'ha gia` fatto e puo` darmi un piccolo esempio?
Ciao.

 ha scritto nel messaggio
news:tf2piu4f9h0dmn3o7...@4ax.com...

Quando inizi la chat col server SMTP prova a dirgli "HELO" + il tuo nome e
vedi se nella lista di comandi che ti restituisce c'è "AUTH".
Se c'è vuol dire che accetta l'autenticazione per il RELY. Digli "AUTH
LOGIN", lui ti dirà qualcosa di incomprensibile, tu rispondi col tuo user
name codificato in Base64 (use MIME::Base64;), puoi lui risponde di nuovo
qualcosa di strano e stavolta gli dici la password sempre in base64. Se dice
Authentication Successful, vuol dire che accetta tutti gli indirizzi dopo il
"RCPT TO:".
Ecco una chat tipo:
220 localhost ESMTP send HELO or EHLO
helo UMS
250 Hello UMS, pleased to meet you
auth login
334 VXNlcm5hbWU6
[username codificato in Base64]
334 UGFzc3dvcmQ6
[password codificata in Base64]
235 Authentication successful
mail from: <indi...@del.mittente>
250 <indi...@del.mittente>, Sender ok
rcpt to: <indi...@del.destinatario>
250 <indi...@del.destinatario>, Recipient ok
data
354 Enter mail, end with <CRLF>.<CRLF>
From: "Guido" <indi...@del.mittente>
To: "Guido" <indi...@del.destinatario>
Subject: prova messaggio
Date: Wed, May/22/2002 1:34:33
Bla Bla...
Messaggio di posta...
.
250 Ok, message queued
quit
221 ESMTP Closing channel
Non badare ai messaggi verbali del server, ma ai codici numerici. In linea
di massima un 250 significa "tutto ok" ;-)
Ciao,
Guido.

"RCPT TO:".
Ti ringrazio per la risposta, ma non e' proprio quello che speravo.
Quello che dici riguarda l'autenticazione LOGIN, immagino. Io pero' volevo
usare CRAM-MD5, se disponibile. E, francamente, speravo di non entrare
tanto nel dettaglio, cioe' che il modulo Authen::SASL si occupasse un po'
piu' della cosa (se no, che ci sta a fare?). Anche, tra le altre cose, di
verificare quali metodi di autenticazione sono disponibili e usare il piu'
sicuro tra questi.
Tra l'altro, anche in LOGIN, possibile che il "qualcosa di strano" non
serva a nulla? Se c'e' solo di mezzo una codifica base64, alla fine e' come
se nome e password passassero in chiaro.
Ho fatto comunque nel frattempo un po' di tentativi, anche se non mi e'
ancora riuscito di risolvere. Se concludo qualcosa magari pubblico.
Ciao.

sicuro tra questi.
O sono cieco, o stavo guardando documentazione non aggiornata di Net::SMTP:
il metodo AUTH e' gia' supportato, con pochissima fatica da parte mia,
esattamente come volevo.
Peccato che l'unico meccanismo supportato per ora sia PLAIN. E NON usa il
pacchetto Authen::SASL.
Ciao.

pacchetto Authen::SASL.
C'e` qualcosa nella libnet 1.12 (che, chissa` perche', non e` disponibile
come pacchetto PPM), ma ancora solo PLAIN.
Ciao.

   235 Authentication successful.
WOW!!
Non e` che abbia capito proprio tutto, comunque a quanto pare funziona:
#============================================================
use Net::SMTP;
use Net::Cmd qw(CMD_INFO CMD_OK CMD_MORE CMD_REJECT
                CMD_ERROR CMD_PENDING);
use Authen::SASL;
use MIME::Base64 qw(encode_base64 decode_base64);
use constant SMTP_SERVER => 'server';
use constant HELO => 'mio.dominio';
use constant USER => 'utente';
use constant PASS => 'password';
my $sasl = Authen::SASL->new(
   mechanism => 'CRAM-MD5',
   callback => {
     pass => PASS,
     user => USER,
     authname => USER,
   }
 );
my $smtp = Net::SMTP->new(SMTP_SERVER,
               Hello => HELO) or die;
my $client = $sasl->client_new('smtp', SMTP_SERVER, 0);
my $str    = $client->client_start;
my @cmd = ("AUTH", $client->mechanism);
my $code;
$code = $smtp->command(@cmd)->response();
my $msg = decode_base64(($smtp->message)[0]);
while ($code == CMD_MORE) {
    @cmd = (encode_base64($client->client_step($msg)));
    $code = $smtp->command(@cmd)->response();
    $msg = decode_base64(($smtp->message)[0]);
}
if ($code == CMD_OK) {
    print "OK\n";
}
$smtp->quit;
#============================================================
La cosa migliore, naturalmente, sarebbe inserire la procedura in Net::SMTP:
bisognerebbe estendere il metodo auth (gia` basato su Authen::SASL in libnet
1.12) in modo che usi il meccanismo di autenticazione preferito fra quelli
disponibili.
Ciao.

disponibili.
Giovanni carissimo, ti sarai accorto che hai di fatto duplicato il metodo
auth, cosi` come compare nella versione 2.24 di Net::SMTP (contenuto nel
pacchetto libnet 1.12).
Di fatto, COSI` COM'E`, il metodo e` in grado di utilizzare uno qualunque
dei meccanismi implementati in Authen::SASL::Perl, secondo la lista di
meccanismi disponibili fornita dal server SMTP.
Perche' allora non ti funzionava? Perche' hai utilizzato per le prove il
server SMTP Mercury che, chissa` perche', non elimina gli spazi in eccesso
in un comando; sicche', in "AUTH CRAM-MD5 " non riconosce il meccanismo
"CRAM-MD5" (disponibile), ma un fantomatico "CRAM-MD5 " (ignoto).
Non ho la piu` pallida idea se, a colpi di RFC, abbia ragione Mercury o
abbiano ragione gli altri. Presumo gli altri.
In ogni caso, e` possibile modificare Net:SMTP, in modo che faccia contenti
tutti; nel metodo auth, in luogo di:
    my @cmd = ("AUTH", $client->mechanism,
    MIME::Base64::encode_base64($str,''));
basta mettere:
    my @cmd;
    if ($str eq '') {
        @cmd = ("AUTH", $client->mechanism);
    } else {
        @cmd = ("AUTH", $client->mechanism,
        MIME::Base64::encode_base64($str,''));
    }
L'unica cosa che un po' mi dispiace e` che cosi` e` in realta` il server
SMTP a decidere quale meccanismo verra` utilizzato, perche' Authen::SASL
seleziona il primo che conosce nella lista fornita dal server. Sicche', per
esempio, con 
mail.tin.it
 (che risponde "LOGIN CRAM-MD5 PLAIN") questo vuol
dire usare sempre il meccanismo LOGIN.
Di nuovo, non so, in termini di RFC, se questo sia il comportamento corretto
e/o preferibile.
ActiveState, poi, potrebbe gentilmente rendere disponibile in PPM l'ultima
versione di libnet, invece che la quartultima.
E con cio`, credo che questo mio soliloquio possa dirsi definitivamente
concluso. E` stato in fondo divertente, e ho imparato anche qualcosina,
anche se la scoperta che avrei potuto risolvere tutto in una riga
("$smtp->auth(USER, PASS);") non e` particolarmente esaltante.  
Ciao.

serva a nulla?
Certo che "serve": il primo dice "Username:", e il secondo "Password:".
E` accettata pero` anche la forma:
   auth login [username codificato in Base64]
che elimina la richiesta "Username:".
Ciao.