Posts Tagged ‘smtp auth’

Como probar SMTP AUTH mediante CRAM-MD5

Thursday, December 9th, 2010

En artículos anteriores ya he hecho referencia al excelente artículo de Jaume Sabater sobre la instalación y configuración de un servidor de correo con Postfix. En su artículo hace el razonamiento de que como la autenticación se va a realizar sobre un canal cifrado no hace falta habilitar los métodos de autenticación CRAM-MD5 o DIGEST-MD5, que permiten hacer login sin transmitir la contraseña en plano (como pasa con los métodos PLAIN o LOGIN). Y no le falta razon, pero yo he tomado un camino intermedio: en el servidor SMTP por el puerto 587 (submission) están permitidos todos los métodos de autenticación ya que se fuerza el cifrado de la conexión; pero por el 25 no permito los métodos de autenticación PLAIN o LOGIN para evitar la tentación de hacer login con uno de esos métodos mediante un canal inseguro, pero sí permito CRAM-MD5 o DIGEST-MD5.

Para conseguir este efecto, nos aseguraremos que el siguiente parametro este definido en el fichero /etc/postfix/main.cf
smtpd_sasl_security_options = noplaintext, noanonymous

Con esto conseguiremos que por defecto no se permita ni PLAIN ni LOGIN. Para habilitarlos por el puerto de submission, modificaremos la definición del servicio submission en el fichero /etc/postfix/master.cf añadiendo la línea:
-o smtpd_sasl_security_options=noanonymous

El problema viene a la hora de comprobar que podemos hacer login mediante, por ejemplo, CRAM-MD5 ya que el cliente debe calcular el HMAC-MD5 de un string generado por el servidor, siendo la clave del algoritmo la contraseña del usuario, para realizar la autenticación sin que el usuario deba revelar su contraseña. Pero no es nada que unas cuantas lineas de Perl no puedan resolver:

#!/usr/bin/perl
use MIME::Base64
use Digest::HMAC_MD5 qw(hmac_md5_hex);
print encode_base64($ARGV[1] . " " . hmac_md5_hex(decode_base64($ARGV[0]), $ARGV[2]));

Los argumentos a pasarle son:

  1. el challenge generado por el servidor
  2. el nombre de usuario
  3. la contraseña

Pero nada mejor que un ejemplo para ver como funciona.

S: 220 mail.example.com ESMTP Postfix (Debian/GNU)
C: ehlo client.example.com
S: 250-mail.example.com
S: 250-PIPELINING
S: 250-SIZE 10240000
S: 250-ETRN
S: 250-STARTTLS
S: 250-AUTH DIGEST-MD5 NTLM CRAM-MD5
S: 250-AUTH=DIGEST-MD5 NTLM CRAM-MD5
S: 250-ENHANCEDSTATUSCODES
S: 250-8BITMIME
S: 250 DSN
C: AUTH CRAM-MD5
S: 334 PDQwMTc3NTY4MTAuODMzNzFAb3ZoMjAxMC5sbHVsbC5uZXQ+

Al indicarle que queremos autenticarnos mediante CRAM-MD5 el servidor nos proporciona el challenge que pasaremos al script en Perl junto con el nombre de usuario y la contraseña en otra consola.

$ ./cram-md5.pl PDQwMTc3NTY4MTAuODMzNzFAb3ZoMjAxMC5sbHVsbC5uZXQ+ user password
dXNlciA3MTUxODVjYTRkMzMxOGRkMzYxZTg2NDg4M2ZkNmE3NA==

Para autenticarnos, le enviaremos el string obtenido al servidor.

C: dXNlciA3MTUxODVjYTRkMzMxOGRkMzYxZTg2NDg4M2ZkNmE3NA==
S: 235 2.7.0 Authentication successful
C: quit
S: 221 2.0.0 Bye

(‘$’ denota el promt de la shell, ‘S’ una línea recibida del servidor y ‘C’ una línea enviada por el cliente)