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 )