#!/usr/bin/perl # Dovecot external auth script using SASL # 2012-01-16 # By Frederik Teichert, http://teichert-ing.de # # Features: auth and isUser work, but setPass doesn't. # Restrictions: Username or passwords may not contain some special characters: $'"` nor line breaks # Based on the Mysql external auth script by Alejandro Grijalba (SuD) http://www.latinsud.com # http://www.ejabberd.im/check_mysql_perl # Changes I made in dovecot.conf: # To have multiple client sockets, create multiple "socket liste" entries. # # socket listen { # client { # path = /var/run/dovecot/ejabberd # mode = 0660 # user = ejabberd # group = ejabberd # } # } # # The user and group called 'ejabberd' must exist! # Troubleshooting: # Because debugging this auth-script is hard, try to run it as the ejabberd user from # the commandline: # echo "2nauth:user:domain:password" | sudo -u ejabberd ./dovecot_auth.pl # This helped a lot. # Replace '2' with the length of your string if it doesn't work # # If authentification hangs try to relace a line in Authd.pm (e.g. /usr/local/share/perl/5.10.1/Authen/SASL/Authd.pm) # as mentioned in http://www.mail-archive.com/dovecot@dovecot.org/msg29498.html . # # my $base64 = encode_base64("\0$login\0$passwd"); # becomes # my $base64 = encode_base64("\0$login\0$passwd", ''); # # This helped a lot, too. # To use internal and external auth in ejabberd, use this two lines: # {auth_method, [internal, external]}. # {extauth_program, "/path/to/check_dovecot.pl"}. # And finally: # $ chown ejabberd:ejabberd /path/to/check_dovecot.pl # $ chmod u+x /path/to/check_dovecot.pl # Restart ejabberd and enjoy! # I'm using this version: # dovecot 1.2.15 # ejabberd 2.1.5 # perl 5.10.1 use Unix::Syslog qw(:macros :subs); use Authen::SASL::Authd qw(auth_dovecot user_dovecot); while(1) { my $buf = ""; syslog LOG_INFO,"ejabberd-dovecot-auth: waiting for packet"; my $nread = sysread STDIN,$buf,2; do { syslog LOG_INFO,"ejabberd-dovecot-auth: port closed"; exit; } unless $nread == 2; my $len = unpack "n",$buf; my $nread = sysread STDIN,$buf,$len; my ($op,$user,$domain,$password) = split /:/,$buf; # Filter dangerous characters $user =~ s/[."\n\r'\$`]//g; $password =~ s/[."\n\r'\$`]//g; #$user =~ s/\./\//og; my $result; syslog(LOG_INFO,"ejabberd-dovecot-auth: request ($op, \"$user\@$domain\", '****')"); #print "ejabberd-dovecot-auth: request ($op, \"$user\@$domain\", $password)"; SWITCH: { $op eq 'auth' and do { if (auth_dovecot("$user\@$domain", $password, timeout => 3, socket => '/var/run/dovecot/ejabberd')) { $result = true; syslog(LOG_INFO,"ejabberd-dovecot-auth: -> +OK"); } else { $result = false; syslog(LOG_INFO,"ejabberd-dovecot-auth: -> -ERR"); } },last SWITCH; $op eq 'setpass' and do { $result = 0; },last SWITCH; $op eq 'isuser' and do { if (user_dovecot("$user\@$domain", timeout => 3, socket => '/var/run/dovecot/ejabberd')) { $result = true; syslog(LOG_INFO,"ejabberd-dovecot-auth: -> +OK"); } else { $result = false; syslog(LOG_INFO,"ejabberd-dovecot-auth: -> -ERR"); } },last SWITCH; }; my $out = pack "nn",2,$result ? 1 : 0; syswrite STDOUT,$out; } closelog;