From - Sun Apr 10 15:34:50 2005 X-Spam-Check-By: la.mx.develooper.com Received-SPF: pass (x1.develooper.com: domain of [EMAIL PROTECTED] designates 67.99.13.172 as permitted sender) Message-ID: <[EMAIL PROTECTED]> Date: Sun, 10 Apr 2005 12:04:40 -0400 From: Bob <[EMAIL PROTECTED]> To: qpsmtpd@perl.org Subject: auth_ldap using tinyldap on localhost
http://perlq.org/tinyldap/auth_ldap.html http://perlq.org/tinyldap/
./plugins/extra/auth_ldap works
....April 10, 2005, plugin named "auth_ldap", "works".
April 13, 2005, "auth_ldap" still works. I use Net::LDAP::Entry to skip some iteration and the superfluous anonymous bind.
Any thoughts yet?
-Bob Dodds
use Net::LDAP ; use Net::LDAP::Entry ; use Digest::HMAC_MD5 qw( hmac_md5_hex ) ;
my $VERSION = '0.01' ;
my %LDAPSEARCH = map { $_ => 1 } qw ( ip port base_dn timeout filter_attr target ) ;
my %DEFAULTS = (
ip => "127.0.0.1" ,
port => 389 ,
base_dn => "o=q" ,
timeout => 5 ,
filter_attr => "mail" ,
target => "userPassword" ) ;
sub register { my ( $self , $qp , %arg ) = @_ ; my $config = { %DEFAULTS , map { split /\s+/ , $_ , 2 } $self->qp->config( 'authldap' ) , %arg } ; if ( my @bad = grep { ! exists $LDAPSEARCH{$_} } sort keys %$config ) { $self->log( LOGERROR , "invalid parameter(s): " . join( ',' , @bad ) ) ; } my $ip = "" ;
map { $ip = ( ( $_ || 0 ) > ( length ( $ip ) ? -1 : 0 ) and ( ( $_ || 0 ) >= 0 ? $_ : 256 ) < 256 ) ? $ip . $_ . "." : $ip } split ( /[^0-9]+/ , $config->{ip} ) ;
$config->{ip} = (
index ( $ip , '.' , index ( $ip , '.' , index ( $ip , '.' ) + 1 ) + 1 ) >= 0
and
substr ( $ip , rindex ( $ip , '.' , length ( $ip ) - 2 ) + 1 ) > 0
)
? substr ( ( join "." , split ( /\./ , ( $ip || "bad" ) , 4 ) ) , 0 , -1 )
: "" ; # <---empty because 0=IP=0.0.0.0, not for plaintext passwords
if ( int $config->{port} and $config->{port} >= 389 and $config->{ip} ) {
$self->register_hook( "auth-cram-md5" , "authldap" ) ;
$self->{_authldap_config} = $config ;
}
else {
$self->log( LOGWARN, "authldap - config error ip $config->{ip} or port $config->{port}" ) ;
}
}
sub authldap {
my ( $self , $transaction , $method , $user , $passClear , $passHash , $ticket ) =
@_ ;
my $config = $self->{_authldap_config} ;
my ( $auth_pass , $pw_name , $pw_domain ) = ( 0 , split "@" , lc ( $user ) ) ;
unless ( defined $pw_domain ) { return DECLINED; }
my ( $ldip , $ldport , $ldbase , $ldwait , $ldmattr , $ldpwd ) = ( $config->{ip} , $config->{port} , $config->{base_dn} , $config->{timeout} , $config->{filter_attr} , $config->{target} ) ;
my $ldh = Net::LDAP->new( $ldip , port => $ldport , timeout => $ldwait ) or
$self->log( LOGWARN , "authldap - new\(\) error: " , $@ ) &&
return DECLINED ;
my $mesg = $ldh->search( base => $ldbase , filter => "\([EMAIL PROTECTED])" , attrs => [ $ldpwd ] , sizelimit => 2 ) or $self->log( LOGWARN, "authldap - search error" ) && return DECLINED ;
$ldh->unbind if $ldh ;
$auth_pass = $mesg->entry->get_value( $ldpwd ) if $mesg->count == 1 ;
$ldh->disconnect if $ldh ;
return DECLINED unless $auth_pass ;
my $hmac = "" ;
if (
( defined $passClear
and $auth_pass eq $passClear ) or
( defined $passHash and ( $hmac = hmac_md5_hex ( $ticket , $auth_pass ) )
eq $passHash )
)
{
# $self->log( LOGDEBUG , "authldap/$method OK passHash "
# . $passHash . " hmac " . $hmac ) ;
return OK ;
}
else {
# $self->log( LOGDEBUG , "authldap/$method DENY auth_pass "
# . substr ( $auth_pass , 1 , 3 ) ) ;
return DENY ;
}
}