package Lemonldap::NG::Portal::Auth::LDAP; use strict; use Mouse; use Lemonldap::NG::Portal::Main::Constants qw( PE_OK PE_DONE PE_ERROR PE_BADOLDPASSWORD PE_LDAPCONNECTFAILED PE_PASSWORDFORMEMPTY PE_PASSWORD_MISMATCH PE_PP_CHANGE_AFTER_RESET PE_PP_PASSWORD_EXPIRED PE_PP_INSUFFICIENT_PASSWORD_QUALITY PE_PP_PASSWORD_TOO_SHORT PE_PP_PASSWORD_TOO_YOUNG PE_PP_PASSWORD_IN_HISTORY PE_PP_MUST_SUPPLY_OLD_PASSWORD ); our $VERSION = '2.1.0'; # Inheritance: UserDB::LDAP provides all needed ldap functions extends qw(Lemonldap::NG::Portal::Auth::_WebForm Lemonldap::NG::Portal::Lib::LDAP); sub init { my ($self) = @_; return ( $self->Lemonldap::NG::Portal::Auth::_WebForm::init and $self->Lemonldap::NG::Portal::Lib::LDAP::init ); } has authnLevel => ( is => 'rw', lazy => 1, default => sub { $_[0]->conf->{ldapAuthnLevel}; } ); # RUNNING METHODS sub authenticate { my ( $self, $req ) = @_; # Set the dn unless done before unless ( $req->data->{dn} ) { if ( my $tmp = $self->getUser($req) ) { eval { $self->setSecurity($req) }; $self->logger->warn($@) if ($@); return $tmp; } } unless ( $req->data->{password} ) { $self->p->{user} = $req->userData->{_dn} = $req->data->{dn}; unless ( $self->p->{_passwordDB} ) { $self->logger->error('No password database configured, aborting'); return PE_ERROR; } my $res = $self->p->{_passwordDB}->_modifyPassword( $req, 1 ); # Refresh entry if ( $self->p->{_userDB}->getUser($req) != PE_OK ) { $self->logger->error( "Unable to refresh entry for " . $self->p->{user} ); } $req->data->{noerror} = 1; $self->setSecurity($req); # Security: never create session here return $res || PE_DONE; } $self->validateLdap; unless ( $self->ldap ) { return PE_LDAPCONNECTFAILED; } my $res = $self->ldap->userBind( $req, $req->data->{dn}, password => $req->data->{password} ); $self->setSecurity($req) if ( $res > PE_OK ); # Remember password if password reset needed if ( $res == PE_PP_CHANGE_AFTER_RESET or ( $res == PE_PP_PASSWORD_EXPIRED and $self->conf->{ldapAllowResetExpiredPassword} ) ) { $req->data->{oldpassword} = $self->{password}; $req->data->{noerror} = 1; $self->setSecurity($req); } return $res; } sub authLogout { PE_OK; } sub getForm { my ( $self, $req ) = @_; if ( $req->{error} == PE_PP_CHANGE_AFTER_RESET or $req->{error} == PE_PP_MUST_SUPPLY_OLD_PASSWORD or $req->{error} == PE_PP_INSUFFICIENT_PASSWORD_QUALITY or $req->{error} == PE_PP_PASSWORD_TOO_SHORT or $req->{error} == PE_PP_PASSWORD_TOO_YOUNG or $req->{error} == PE_PP_PASSWORD_IN_HISTORY or $req->{error} == PE_PASSWORD_MISMATCH or $req->{error} == PE_BADOLDPASSWORD or $req->{error} == PE_PASSWORDFORMEMPTY or ( $req->{error} == PE_PP_PASSWORD_EXPIRED and $self->conf->{ldapAllowResetExpiredPassword} ) ) { $req->tplParams->{DISPLAY_PPOLICY} = $self->conf->{portalDisplayPasswordPolicy}; $req->tplParams->{PPOLICY_MINSIZE} = $self->conf->{passwordPolicyMinSize}; $req->tplParams->{PPOLICY_MINLOWER} = $self->conf->{passwordPolicyMinLower}; $req->tplParams->{PPOLICY_MINUPPER} = $self->conf->{passwordPolicyMinUpper}; $req->tplParams->{PPOLICY_MINDIGIT} = $self->conf->{passwordPolicyMinDigit}; return 'password'; } else { return $self->SUPER::getForm($req); } } # Test LDAP connection before trying to bind sub userBind { my $self = shift; unless ($self->ldap and $self->ldap->root_dse( attrs => ['supportedLDAPVersion'] ) ) { $self->ldap( $self->newLdap ); } return $self->ldap ? $self->ldap->userBind(@_) : undef; } 1;