Lemonldap-NG-Portal

 view release on metacpan or  search on metacpan

lib/Lemonldap/NG/Portal/Lib/Net/LDAP.pm  view on Meta::CPAN

use Lemonldap::NG::Portal::Main::Constants ':all';
use Net::LDAP::Control::PasswordPolicy;
use Encode;
use Scalar::Util 'weaken';
use IO::Socket::Timeout;
use Net::LDAP qw(LDAP_PP_PASSWORD_EXPIRED LDAP_PP_ACCOUNT_LOCKED
  LDAP_PP_CHANGE_AFTER_RESET LDAP_PP_PASSWORD_MOD_NOT_ALLOWED
  LDAP_PP_MUST_SUPPLY_OLD_PASSWORD LDAP_PP_INSUFFICIENT_PASSWORD_QUALITY
  LDAP_PP_PASSWORD_TOO_SHORT LDAP_PP_PASSWORD_TOO_YOUNG
  LDAP_PP_PASSWORD_IN_HISTORY );

use utf8;

our $VERSION = '2.23.0';

# INITIALIZATION

# Build a Net::LDAP object using parameters issued from $portal
sub new {
    my ( $class, $args ) = @_;
    my $portal = $args->{p}    or die "$class: p argument is required!";
    my $conf   = $args->{conf} or die "$class: conf argument is required!";
    my ( $self, @servers, %tlsParams );
    my $useStartTls = 0;

    foreach my $server ( split /[\s,]+/, $conf->{ldapServer} ) {
        if ( $server =~ m{^ldap\+tls://([^/]+)/?\??(.*)$} ) {
            $useStartTls = 1;
            $server      = $1;
            %tlsParams   = split( /[&=]/, $2 || "" );
        }
        elsif ( $server =~ m{^(ldaps://[^/]+)/?\??(.*)$} ) {
            $useStartTls = 0;
            $server      = $1;
            %tlsParams   = split( /[&=]/, $2 || "" );
        }
        else {
            $useStartTls = 0;
        }
        push @servers, $server;
    }
    $tlsParams{cafile} ||= $conf->{ldapCAFile} if $conf->{ldapCAFile};
    $tlsParams{capath} ||= $conf->{ldapCAPath} if $conf->{ldapCAPath};
    $tlsParams{verify} ||= $conf->{ldapVerify} if $conf->{ldapVerify};
    $self = Net::LDAP->new(
        \@servers,
        onerror   => undef,
        keepalive => 1,
        %tlsParams,
        ( $conf->{ldapPort}    ? ( port    => $conf->{ldapPort} )    : () ),
        ( $conf->{ldapTimeout} ? ( timeout => $conf->{ldapTimeout} ) : () ),
        ( $conf->{ldapVersion} ? ( version => $conf->{ldapVersion} ) : () ),
        ( $conf->{ldapRaw}     ? ( raw     => $conf->{ldapRaw} )     : () ),
    );
    unless ($self) {
        $portal->logger->error( "LDAP initialization error: " . $@ );
        return 0;
    }
    elsif ( $Net::LDAP::VERSION < '0.64' ) {

        # CentOS7 has a bug in which IO::Socket::SSL will return a broken
        # socket when certificate validation fails. Net::LDAP does not catch
        # it, and the process ends up crashing.
        # As a precaution, make sure the underlying socket is doing fine:
        if (    $self->socket->isa('IO::Socket::SSL')
            and $self->socket->errstr < 0 )
        {
            $portal->logger->error(
                "LDAP SSL connection failed: " . $self->socket->errstr );
            return 0;
        }
    }
    bless $self, $class;

    # Set socket timeouts
    my $socket = $self->socket;
    IO::Socket::Timeout->enable_timeouts_on($socket);
    $socket->read_timeout( $conf->{ldapIOTimeout} );
    $socket->write_timeout( $conf->{ldapIOTimeout} );

    if ($useStartTls) {
        my $mesg = $self->start_tls(%tlsParams);
        if ( $mesg->code ) {
            $portal->logger->error( 'LDAP StartTLS failed: ' . $mesg->error );
            return 0;
        }
    }
    $self->{portal} = $portal;
    $self->{conf}   = $conf;
    weaken $self->{portal};

    # Setting default LDAP password storage encoding to utf-8
    return $self;
}

# RUNNING METHODS

## @method Net::LDAP::Message bind(string dn, hash args)
# Reimplementation of Net::LDAP::bind(). Connection is done :
# - with $dn and $args->{password} as dn/password if defined,
# - or with Lemonldap::NG account,
# - or with an anonymous bind.
# @param $dn LDAP distinguish name
# @param %args See Net::LDAP(3) manpage for more
# @return Net::LDAP::Message
sub bind {
    my ( $self, $dn, %args ) = @_;
    my $mesg;

    $self->{portal}->logger->debug("Call bind for $dn") if $dn;
    unless ($dn) {
        $dn = $self->{conf}->{managerDn};
        $args{password} =
          decode( 'utf-8', $self->{conf}->{managerPassword} );
    }
    if ( $dn && $args{password} ) {
        if ( $self->{conf}->{ldapPwdEnc} ne 'utf-8' ) {
            eval {
                my $tmp = encode(
                    $self->{conf}->{ldapPwdEnc},
                    decode( 'utf-8', $args{password} )
                );
                $args{password} = $tmp;
            };
            print STDERR "$@\n" if ($@);



( run in 0.960 second using v1.01-cache-2.11-cpan-5a3173703d6 )