Table of Contents

Courier authdaemon

Courier authdaemon problem

I got an hard-to-solve problem on a Debian Sarge box, using Exim4 and SMTP authentication against Courier authdaemon. This is also reported as Debian bug 336979, which is now solved but deep insight is missing there.

The symptom was that an existing user can provide a random password and gain authenticated user rights. An existing user means that also root can succeed. Here it is an SMTP session:

# telnet localhost 25
Trying 127.0.0.1...
Connected to localhost.localdomain.
Escape character is '^]'.
220 petra-osm.texnet.org ESMTP Exim 4.50 Wed, 07 Mar 2007 16:12:47 +0100
EHLO test
250-petra-osm.texnet.org Hello test [127.0.0.1]
250-SIZE 52428800
250-PIPELINING
250-AUTH PLAIN LOGIN
250-STARTTLS
250 HELP
AUTH LOGIN
334 VXNlcm5hbWU6
cm9vdA==
334 UGFzc3dvcmQ6
bXlzZWNyZXQ=
235 Authentication succeeded

Notice that cm9vdA== means root in base64 encoding, and bXlzZWNyZXQ= is a random password. The problem turned out to be the sum of two bugs.

The first bug was in the Exim4 authenticators configuration copied from this site: www.devco.net. The snippet of configration is:

# WARNING: DO NOT USE THIS UNSAFE AUTHENTICATOR!!!
login:
        driver = plaintext
        public_name = LOGIN
        server_prompts = Username:: : Password::
        server_condition = ${if eq {${readsocket{/usr/run/courier/authdaemon/socket} \
                 {AUTH ${strlen:exim\nlogin\n$1\n$2\n}\nexim\nlogin\n$1\n$2\n}}}{FAIL\n} {no}{yes}}
        server_set_id = $1

The very problem of this configuration is that Exim will exptect the string FAIL from the Courier authdaemon socket on authentication failure. Every other result will be interpreted as an authentication success.

The second problem is that the authdaemon has a bug (at least on Debian Sarge, authdaemon version 0.47-4sarge5): in case of an existing user with a wrong password nor the authentication data nor the FAIL string is returned.

The problem was solved changing the Exim4 authenticator as suggested by the Exim FAQ (here my actual config). Also upgrading to courier-authdaemon 0.58-4 (Debian Etch) fixed the authdaemon bug.

Crittografia TLS

Per abilitare la crittografia TLS sulla connessione POP3 bisogna installare il pacchetto courier-pop-ssl, per verificare se TLS รจ disponibile basta eseguire il comando STLS dentro una sessione POP3, la risposta deve essere qualcosa del genere:

+OK Hello there.
STLS
+OK Begin SSL/TLS negotiation now.

Tracing the Courier authdaemon socket

I wrote a little perl script to trace and debug the talk to the authdaemon named socket. The authdaemon expects 5 parameters to be written to the socket: the length in bytes of the entire input, the SERVICE name (tipically the name of the program requesting the authentication), the AUTHTYPE login (a typical userid/password authentication request) and the AUTHDATA consisting of login and password. Each piece of input is separated by a new line.

#!/usr/bin/perl
 
use Socket;
use strict;
 
my $login  = $ARGV[0];
my $pass   = $ARGV[1];
my $socket = '/var/run/courier/authdaemon/socket';
 
my $line;
my $auth_string;
 
if ( $#ARGV != 1 ) {
    print "Usage: courier-authdaemon-test [login] [password]\n";
    exit 1;
}
 
socket(SOCK, PF_UNIX, SOCK_STREAM, 0) || die "socket: $!";
connect(SOCK, sockaddr_un($socket))   || die "connect: $!";
 
$line = "postfix\nlogin\n$login\n$pass\n";
$line = length($line) . "\n" . $line;
print "=== Send to socket:\n" . $line;
 
send (SOCK, "AUTH $line", 0);
while ($line = <SOCK>) { print "=== Read from socket: " . $line; }

And here it is the output of the script, using an existing user with a fake password:

# ./authdaemon_test root mysecret
=== Send to socket:
25
exim
login
root
mysecret

The FAIL string is missing. Here instead the result with a non-existing user:

# ./authdaemon_test username mysecret
=== Send to socket:
29
exim
login
username
mysecret
=== Read from socket: FAIL

When an authentication request succeed, this is the output of authdaemon:

# ./authdaemon_test niccolo my_secret
=== Send to socket:
28
exim
login
niccolo
my_secret
=== Read from socket: USERNAME=niccolo
=== Read from socket: GID=111
=== Read from socket: HOME=/home/niccolo
=== Read from socket: ADDRESS=niccolo
=== Read from socket: NAME=Niccolo Rigacci,,,
=== Read from socket: PASSWD=$1$0GPemE0H$Ki8KAUWDrxX2SMBA.r84W1
=== Read from socket: .

A more secure Exim authenticator

This is a more secure and robust authenticator (against Courier authdaemon) for Exim4 on a Debian Etch. It serves both the AUTH LOGIN and the AUTH PLAIN schemas:

### auth/25_local-courier_authdaemon
#################################

# Authenticate against courier authdaemon

# This has been copied from
# http://www.exim.org/eximwiki/FAQ/Policy_controls/Q0730
# Possible pitfall: access rights on /var/run/courier/authdaemon/socket.

# SMTP authenticator "AUTH LOGIN"
login_courier_authdaemon:
  driver = plaintext
  public_name = LOGIN
  server_prompts = Username:: : Password::
  server_condition = ${extract {address} {${readsocket{/var/run/courier/authdaemon/socket} \
      {AUTH ${strlen:exim\nlogin\n$1\n$2\n}\nexim\nlogin\n$1\n$2\n} }} {yes} fail}
  server_set_id = $1
  # Announce this authenticator also if unencrypted connection?
  .ifndef AUTH_SERVER_ALLOW_NOTLS_PASSWORDS
  server_advertise_condition = ${if eq{$tls_cipher}{} {no} {yes}}
  .endif

# SMTP authenticator "AUTH PLAIN"
plain_courier_authdaemon:
  driver = plaintext
  public_name = PLAIN
  server_prompts = :
  server_condition = ${extract {address} {${readsocket{/var/run/courier/authdaemon/socket} \
      {AUTH ${strlen:exim\nlogin\n$2\n$3\n}\nexim\nlogin\n$2\n$3\n} }} {yes} fail}
  server_set_id = $2
  # Announce this authenticator also if unencrypted connection?
  .ifndef AUTH_SERVER_ALLOW_NOTLS_PASSWORDS
  server_advertise_condition = ${if eq{$tls_cipher}{} {no} {yes}}
  .endif

Authenticate with an alternative login name

How to authenticate users with a login name like user@doamain.org, instead of the Unix system name (Debian GNU/Linux 4.0 Etch).

Create a password file /etc/courier/userdb with all the relevant information (do not break the line!):

info@2domain.org    uid=1086|gid=1086|home=/home/info|shell=/bin/false
    |systempw=$1$GiNkrEZX$UTOWQkZZf0pp2TEOuyEu1/|mail=/home/info/Maildir

WARNING: after the login name there must be a tab character, not spaces.

Compile the file with makeuserdb.

Add the authuserdb module to the authmodulelist into configuration file /etc/courier/authdaemonrc:

authmodulelist="authuserdb authpam"

Reload the courier-authdaemon.

Problema con dhparams.pem e SSL

Facendo un aggiornamento Debian da Wheezy a Jessie la connessione cifrata SSL di IMAP e POP3 smette di funzionare. Pare che il problema sia nella lunghezza del file /etc/courier/dhparams.pem, che con la nuova versione deve essere di almeno 2048 bit. Nei file di log si trova:

couriertls: accept: error:14094417:SSL routines:SSL3_READ_BYTES:sslv3 alert illegal parameter

Vedere i due bug report: #787579 e #741620. Per generare un file nuovo:

DH_BITS=2048 mkdhparams

oppure

cd /etc/courier/
openssl dhparam -out dhparams.pem 2048