Hi,
Ok thanks for the repsonses so far - especially from William Thompson who was kind enough
to provide some code for authenticating against a linux shadow password file.
Unfortunately I'm no C coder and so porting this to freebsd is out. Yes I know I should learn
C, but I'm short on time as always :)
Anyway, I've come up with the following perl script which I'm including into exim as follows:
perl_startup = do '/usr/local/etc/exim/exim.pl'
'/usr/local/etc/exim/exim.pl' is as follows:
------------------------------------------------------------------------------
#!/usr/bin/perl
use strict;
use Crypt::PasswdMD5;
=comment
Note this perl script should be SUID 0 and be placed in your exim config dir.
It should be included into exim via the exim configure file with a line like:
perl_startup = do '/usr/local/etc/exim/exim.pl'
The relevant subroutines can then be called from the exim configure file
using:
${perl{foo}}
where 'foo' is a subroutine defined within this script.
=cut
my($user, $pass, $salt, $hash)=(undef,undef,undef,undef);
my $err=undef;
my $progname = $0;
$progname =~ s,.*/,,; # use basename only
$progname =~ s/\.\w*$//; # strip extension, if any
my $VERSION=0.1;
# &MD5_auth(@ARGV); # For testing in a shell
sub MD5_auth(){
=comment
#
# Not needed in exim mode
#
# Get options:
&Getopts();
# data validation:
if(!$user || !$pass || $user=~/[^0-9A-Za-z]/ || $pass=~/[^0-9A-Za-z]/){ &usage(); }
=cut
$user=shift;
$pass=shift;
# get the line from the pwd db based on $user:
my (undef,$sys_pass) = getpwnam($user);
# get the salt:
($salt) = $sys_pass =~ /\$.*\$(.*)\$/;
# get our hash:
$hash=unix_md5_crypt($pass, $salt);
#die("user: $user submitted pass: $pass salt: $salt myhash: $hash syshash: $sys_pass\n"); # for exim debug output to mainlog
# if hash!=syspass:
if($hash ne $sys_pass) { die("Bad user/pass pair\n"); }
return 0;
}
sub usage{
$err && (print $err,"\n");
die<<"~USAGE~";
Usage: $progname -u user -p pass [-h]
-h Display this help.
-u user User to search the /etc/master.passwd file for.
-p pass user's pass to authenticate against the entry
in /etc/master.passwd
Version $VERSION
~USAGE~
}
sub Getopts(){
# Get opts:
ARG: while (@ARGV && $ARGV[0] =~ s/-(?=.)//){
OPT: for (shift @ARGV){
s/h// && do { usage(); exit; };
s/u// && do { $user = shift @ARGV; next ARG; };
s/p// && do { $pass = shift @ARGV; next ARG; };
usage("Unknown option: $_");
}
}
}
__END__
------------------------------------------------------------------------------
This perl script works ok in a shell - for example on a dummy account I setup for
testing the output looks something like this:
[11:41:18] root@users /usr/local/etc/exim# ./exim.pl dummy dummy
user: dummy submitted pass: dummy salt: koz3aLbT myhash: $1$koz3aLbT$j9Srfw60S7U6MnjGN2Met1 syshash: $1$koz3aLbT$j9Srfw60S7U6MnjGN2Met1
which corresponds to the entry for 'dummy' in /etc/master.passwd:
[11:41:53] root@users /usr/local/etc/exim# grep ^dummy: /etc/master.passwd
dummy:$1$koz3aLbT$j9Srfw60S7U6MnjGN2Met1:1124:1124::0:0:User &:/home/dummy:/sbin/nologin
Now my authenticator in /usr/local/etc/exim/configure looks like this (this is the problem I think!):
------------------------------------------------------------------------------
begin authenticators
plain:
driver = plaintext
public_name = PLAIN
server_condition = ${perl{MD5_auth}{$1}{$2}}
# server_condition = "${if and {{!eq{$2}{}}{!eq{$3}{}} \
# {crypteq{$3}{${extract{1}{:} \
#{${lookup{$2}lsearch{/etc/master.passwd}{$value}{*:*}}}}}}}{1}{0}}"
# server_set_id = $2
login:
driver = plaintext
public_name = LOGIN
server_prompts = "Username:: : Password::"
server_condition = ${perl{MD5_auth}{$2}{$3}}
# server_condition = "${if and {{!eq{$1}{}}{!eq{$2}{}} \
# {crypteq{$2}{${extract{1}{:} \
#{${lookup{$1}lsearch{/etc/master.passwd}{$value}{*:*}}}}}}}{1}{0}}"
# server_set_id = $1
------------------------------------------------------------------------------
Which is yielding nothing but 'Bad user/pass pair' in my exim mainlog.
Can anyone shed some light on how my authenticator should look. Also how can I debug this
better. Currently I'm doing this:
[11:55:09] root@users /usr/local/etc/exim# ./encode.pl '\0dummy\0dummy'
AGR1bW15AGR1bW15
[11:55:11] root@users /usr/local/etc/exim# exim -d+auth -bh 127.0.0.1
Exim version 4.14 uid=0 gid=0 pid=17877 D=fbb95cfd
Probably Berkeley DB version 1.8x (native mode)
Support for: IPv6 PAM Perl OpenSSL
Authenticators: cram_md5 plaintext
Routers: accept dnslookup ipliteral manualroute queryprogram redirect
Transports: appendfile/maildir/mailstore/mbx autoreply lmtp pipe smtp
changed uid/gid: forcing real = effective
uid=0 gid=0 pid=17877
auxiliary group list: 0
configuration file is /usr/local/etc/exim/configure
log selector = 020d99d8
trusted user
admin user
changed uid/gid: privilege not needed
uid=26 gid=6 pid=17877
auxiliary group list: 6
originator: uid=0 gid=0 login=root name=Charlie Root
sender address = root@???
sender_fullhost = [127.0.0.1]
sender_rcvhost = [127.0.0.1]
**** SMTP testing session as if from host 127.0.0.1
**** but without any ident (RFC 1413) callback.
**** This is not for real!
host in host_lookup? yes (matched "*")
looking up host name for 127.0.0.1
IP address lookup yielded localhost
gethostbyname2 returned 4 (NO_DATA)
gethostbyname2 looked up these IP addresses:
name=localhost address=127.0.0.1
checking addresses for localhost
127.0.0.1
sender_fullhost = localhost [127.0.0.1]
sender_rcvhost = localhost ([127.0.0.1])
set_process_info: 17877 handling incoming connection from localhost [127.0.0.1]
host in host_reject_connection? no (option unset)
host in sender_unqualified_hosts? no (option unset)
host in recipient_unqualified_hosts? no (option unset)
host in helo_verify_hosts? no (option unset)
host in helo_try_verify_hosts? no (option unset)
host in helo_accept_junk_hosts? no (option unset)
LOG: smtp_connection MAIN
SMTP connection from localhost [127.0.0.1]
SMTP>> 220 mail.munk.nu ESMTP Exim 4.14 Tue, 22 Apr 2003 11:55:18 +0100
220 mail.munk.nu ESMTP Exim 4.14 Tue, 22 Apr 2003 11:55:18 +0100
smtp_setup_msg entered
ehlo localhost
SMTP<< ehlo localhost
sender_fullhost = localhost [127.0.0.1]
sender_rcvhost = localhost ([127.0.0.1])
set_process_info: 17877 handling incoming connection from localhost [127.0.0.1]
host in pipelining_advertise_hosts? yes (matched "*")
host in auth_advertise_hosts? yes (matched "*")
host in tls_advertise_hosts? no (option unset)
250-mail.munk.nu Hello localhost [127.0.0.1]
250-SIZE 52428800
250-PIPELINING
250-AUTH PLAIN LOGIN
250 HELP
SMTP>> 250-mail.munk.nu Hello localhost [127.0.0.1]
250-SIZE 52428800
250-PIPELINING
250-AUTH PLAIN LOGIN
250 HELP
AUTH LOGIN
SMTP<< AUTH LOGIN
SMTP>> 334 VXNlcm5hbWU6
334 VXNlcm5hbWU6
AGR1bW15AGR1bW15
Starting Perl interpreter
login authenticator:
$1 =
$2 = dummy
$3 = dummy
expansion failed: error in perl_startup code: user: submitted pass: salt: myhash: $1$$qRPK7m23GJusamGpoGLby/ syshash:
SMTP>> 435 Unable to authenticate at present
435 Unable to authenticate at present
LOG: MAIN REJECT
login authenticator failed for localhost [127.0.0.1]: 435 Unable to authenticate at present: error in perl_startup code: user: submitted pass: salt: myhash: $1$$qRPK7m23GJusamGpoGLby/ syshash:
quit
SMTP<< quit
SMTP>> 221 mail.munk.nu closing connection
221 mail.munk.nu closing connection
LOG: smtp_connection MAIN
SMTP connection from localhost [127.0.0.1] closed by QUIT
search_tidyup called
>>>>>>>>>>>>>>>> Exim pid=17877 terminating with rc=0 >>>>>>>>>>>>>>>>
Sorry if this is too much information!
Thanks in advance,
Jez