Connector
view release on metacpan or search on metacpan
lib/Connector/Builtin/Authentication/LDAP.pm view on Meta::CPAN
my $dn = $entry->dn();
if(defined $self->groupdn()) {
if(!$self->_check_user_group($dn)) {
next;
}
}
push @entries, $dn;
}
return unless(@entries);
$self->log()->debug('Found '.scalar @entries.' LDAP entries matching the user "'.$user.'"');
if (@entries > 1 && !$self->ambiguous()) {
$self->log()->error('Ambiguous search result');
return $self->_node_not_exists($user);
}
return \@entries;
}
sub _check_user_group {
my $self = shift;
my $dn = shift;
my $ldap = $self->ldap();
$self->log()->debug('Checking if "'.$dn.'" belongs to group "'.$self->groupdn().'"');
my $result = $ldap->compare($self->groupdn(), attr => $self->groupattr(), value => $dn);
if($result->is_error()) {
$self->log()->error('LDAP compare returned error code '.$result->code.' (error: '.$result->error_desc().')');
return 0;
}
if($result->code != 6) { # !compareTrue
$self->log()->debug('User "'.$dn.'" does not belong to group "'.$self->groupdn().'"');
return 0;
}
$self->log()->debug('User "'.$dn.'" belongs to group "'.$self->groupdn().'"');
return 1
}
sub _check_user_password {
my $self = shift;
my $userdns = shift;
my $password = shift;
my $ldap = $self->ldap;
my $userdn;
foreach my $dn (@$userdns) {
# Try to bind to $dn
$self->log()->debug('Trying to bind to dn: '.$dn);
my $mesg = $ldap->bind($dn, password => $password);
if($mesg->is_error()) {
$self->log()->debug('LDAP bind to '.$dn.' returned error code '.$mesg->code.' (error: '.$mesg->error_desc().')');
} else {
$self->log()->debug('LDAP bind to '.$dn.' succeeded');
$userdn = $dn;
last;
}
}
# restore the connection using the orginal credentials
$self->rebind();
if(!defined $userdn) {
$self->log()->warn('Authentication failed');
return 0;
} else {
$self->log()->info('User successfuly authenticated: (dn: '.$userdn.')');
return $userdn;
}
}
sub get {
my $self = shift;
my $arg = shift;
my $params = shift;
my @args = $self->_build_path( $arg );
my $user = shift @args;
my $password = $params->{password};
if(!$user) {
$self->log()->warn('Missing user name');
return undef;
}
# enforce valueencoding, see RFC4515, note that we allow non-ascii (utf-8) characters
# I assume that Net::LDAP->search() escapes them internally as needed
if (!($user =~ /^([\x01-\x27\x2B-\x5B\x5D-\x7F]|[^[:ascii:]]|\\[0-9a-fA-F][0-9a-fA-F])*$/)) {
$self->log()->warn('Invalid chars in username ("'.$user.'")');
return undef;
}
# let's check if we were instructed to search for the auth user
if($self->indirect()) {
my $result = $self->_search_user( $user );
if(!defined $result) {
$self->log()->warn('User not found in LDAP database');
return $self->_node_not_exists($user);
}
return $self->_check_user_password($result, $password);
}
# direct bind = username is the DN to bind
my $res = $self->_check_user_password([$user], $password);
# we can not check if the user or the password is wrong
return unless($res);
# if we are here we have a successful direct bind, we now check
# for the group using the bound connection, this requires that the
# user himself has access permissions on the group objects
if($self->groupdn()) {
if(!$self->_check_user_group($user)) {
$self->log()->warn('User was authenticated but is not member of this group');
return $self->_node_not_exists($user);
}
}
return $res;
}
( run in 0.645 second using v1.01-cache-2.11-cpan-5a3173703d6 )