diff --git a/build/lemonldap-ng/changelog b/build/lemonldap-ng/changelog index 5cc934be2..0b42e9caa 100644 --- a/build/lemonldap-ng/changelog +++ b/build/lemonldap-ng/changelog @@ -2,9 +2,10 @@ lemonldap-ng (0.9.2) unstable; urgency=low * New css in manager * cleaning Handler code - * Status system for Lemonldap::NG::Handler + * Status system for Lemonldap::NG::Handler and for the portal + * Debian Czech translation for debconf (Closes: #483301 / bugs.debian.org) - -- Xavier Guimard Fri, 09 May 2008 22:10:37 +0200 + -- Xavier Guimard Wed, 28 May 2008 10:53:28 +0200 lemonldap-ng (0.9.1) unstable; urgency=low diff --git a/modules/lemonldap-ng-portal/MANIFEST b/modules/lemonldap-ng-portal/MANIFEST index de315fb06..18b18c891 100644 --- a/modules/lemonldap-ng-portal/MANIFEST +++ b/modules/lemonldap-ng-portal/MANIFEST @@ -62,6 +62,7 @@ t/99-pod.t t/Lemonldap-NG-Portal-AuthApache.t t/Lemonldap-NG-Portal-AuthCAS.t t/Lemonldap-NG-Portal-AuthLA.t +t/Lemonldap-NG-Portal-AuthLDAP.t t/Lemonldap-NG-Portal-AuthSSL.t t/Lemonldap-NG-Portal-CDA.t t/Lemonldap-NG-Portal-i18n.t diff --git a/modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/AuthApache.pm b/modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/AuthApache.pm index a0f95c83d..2c9b5e02a 100644 --- a/modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/AuthApache.pm +++ b/modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/AuthApache.pm @@ -2,26 +2,26 @@ package Lemonldap::NG::Portal::AuthApache; use strict; use Lemonldap::NG::Portal::Simple; +our @ISA = qw(Lemonldap::NG::Portal::Simple); -our $VERSION = '0.01'; +our $VERSION = '0.02'; -our $OVERRIDE = { - # By default, authentication is valid if REMOTE_USER environment - # variable is present. Change formateFilter if this does not match with - # UID. - extractFormInfo => sub { - my $self = shift; - return PE_FORMEMPTY unless( $self->{user} = $ENV{REMOTE_USER} ); - # This is needed for Kerberos authentication - $self->{user} =~ s/(.*)@(.*)/$1/g; - PE_OK; - }, +# By default, authentication is valid if REMOTE_USER environment +# variable is present. Change formateFilter if this does not match with +# UID. +sub extractFormInfo { + my $self = shift; + return PE_FORMEMPTY unless ( $self->{user} = $ENV{REMOTE_USER} ); - # Authentication is made by Apache. - authenticate => sub { - PE_OK; - }, -}; + # This is needed for Kerberos authentication + $self->{user} =~ s/(.*)@(.*)/$1/g; + PE_OK; +} + +# Authentication is made by Apache. +sub authenticate { + PE_OK; +} 1; __END__ diff --git a/modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/AuthCAS.pm b/modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/AuthCAS.pm index a56b6fdaf..498d01de4 100644 --- a/modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/AuthCAS.pm +++ b/modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/AuthCAS.pm @@ -2,12 +2,12 @@ package Lemonldap::NG::Portal::AuthCAS; use strict; use Lemonldap::NG::Portal::Simple; +our @ISA = qw(Lemonldap::NG::Portal::Simple); use AuthCAS; -our $VERSION = '0.02'; +our $VERSION = '0.03'; -our $OVERRIDE = { - extractFormInfo => sub { +sub extractFormInfo { my $self = shift; my $cas = new AuthCAS(casUrl => $self->{CAS_url}, CAFile => $self->{CAS_CAFile}, @@ -24,12 +24,11 @@ our $OVERRIDE = { exit; } PE_OK; - }, +} - authenticate => sub { +sub authenticate { PE_OK; - }, -}; +} 1; __END__ diff --git a/modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/AuthLDAP.pm b/modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/AuthLDAP.pm new file mode 100644 index 000000000..889a1afde --- /dev/null +++ b/modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/AuthLDAP.pm @@ -0,0 +1,77 @@ +package Lemonldap::NG::Portal::AuthLDAP; + +use strict; +use Lemonldap::NG::Portal::Simple; + +our @ISA = qw(Lemonldap::NG::Portal::Simple); + +our $VERSION = '0.1'; + +sub extractFormInfo { + my $self = shift; + return PE_FIRSTACCESS + unless ( $self->param('user') ); + return PE_FORMEMPTY + unless ( length( $self->{'user'} = $self->param('user') ) > 0 + && length( $self->{'password'} = $self->param('password') ) > 0 ); + PE_OK; +} + +sub authenticate { + my $self = shift; + $self->unbind(); + my $err; + return $err unless ( ( $err = $self->connectLDAP ) == PE_OK ); + + # Check if we use Ppolicy control + if ( $self->{ldapPpolicyControl} ) { + + # require Perl module + eval 'require Net::LDAP::Control::PasswordPolicy'; + die('Module Net::LDAP::Control::PasswordPolicy not found in @INC') + if ($@); + eval +'use Net::LDAP::Constant qw( LDAP_CONTROL_PASSWORDPOLICY LDAP_PP_ACCOUNT_LOCKED LDAP_PP_PASSWORD_EXPIRED );'; + no strict 'subs'; + + # Create Control object + my $pp = Net::LDAP::Control::PasswordPolicy->new; + + # Bind with user credentials + my $mesg = $self->{ldap}->bind( + $self->{dn}, + password => $self->{password}, + control => [$pp] + ); + + # Get bind response + return PE_OK if ( $mesg->code == 0 ); + + # Get server control response + my ($resp) = $mesg->control(LDAP_CONTROL_PASSWORDPOLICY); + + if ( defined $resp ) { + my $pp_error = $resp->error; + if ($pp_error) { + return PE_PP_ACCOUNT_LOCKED + if ( $pp_error == LDAP_PP_ACCOUNT_LOCKED ); + return PE_PP_PASSWORD_EXPIRED + if ( $pp_error == LDAP_PP_PASSWORD_EXPIRED ); + } + else { + return PE_BADCREDENTIALS; + } + } + else { + return PE_LDAPERROR; + } + } + else { + return PE_BADCREDENTIALS + unless ( + $self->_bind( $self->{ldap}, $self->{dn}, $self->{password} ) ); + } + $self->{sessionInfo}->{authenticationLevel} = 2; + PE_OK; +} +1; diff --git a/modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/AuthSSL.pm b/modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/AuthSSL.pm index c5cb0b34b..52a55706f 100644 --- a/modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/AuthSSL.pm +++ b/modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/AuthSSL.pm @@ -2,6 +2,9 @@ package Lemonldap::NG::Portal::AuthSSL; use strict; use Lemonldap::NG::Portal::Simple; +use Lemonldap::NG::Portal::AuthLDAP; + +our @ISA = qw(Lemonldap::NG::Portal::AuthLDAP Lemonldap::NG::Portal::Simple); our $VERSION = '0.1'; @@ -9,70 +12,71 @@ our $VERSION = '0.1'; # Directory. # So authenticate is overloaded to return only PE_OK. -our $OVERRIDE = { +# By default, authentication is valid if SSL_CLIENT_S_DN_Email environment +# variable is present. Adapt it if you want +sub extractFormInfo { + my $self = shift; - # By default, authentication is valid if SSL_CLIENT_S_DN_Email environment - # variable is present. Adapt it if you want - extractFormInfo => sub { - my $self = shift; + # Defaults values + $self->{SSLRequire} = 1 unless ( defined $self->{SSLRequire} ); + $self->{SSLVar} ||= 'SSL_CLIENT_S_DN_Email'; + $self->{SSLLDAPField} ||= 'mail'; - # Defaults values - $self->{SSLRequire} = 1 unless ( defined $self->{SSLRequire} ); - $self->{SSLVar} ||= 'SSL_CLIENT_S_DN_Email'; - $self->{SSLLDAPField} ||= 'mail'; + my $user = $self->https ? $ENV{ $self->{SSLVar} } : 0; + if ($user) { + $self->{sessionInfo}->{authenticationLevel} = 5; + $self->{user} = $user; + return PE_OK; + } + elsif ( $self->{SSLRequire} ) { + return PE_CERTIFICATEREQUIRED; + } + return $self->SUPER::extractFormInfo(@_); +} - my $user = $self->https ? $ENV{$self->{SSLVar}} : 0; - if ($user) { - $self->{sessionInfo}->{authenticationLevel} = 5; - $self->{user} = $user; - return PE_OK; - } - elsif ( $self->{SSLRequire} ) { - return PE_CERTIFICATEREQUIRED; - } - return $self->extractFormInfo(@_); - }, +# As we know only user mail (or SSLVar), we have to use it to find him in +# the LDAP directory +sub formateFilter { + my $self = shift; + if ( $self->{sessionInfo}->{authenticationLevel} + and $self->{sessionInfo}->{authenticationLevel} > 4 ) + { + $self->{filter} = '(&(' + . $self->{SSLLDAPField} . '=' + . $self->{user} + . ")(objectClass=person))"; + return PE_OK; + } + return $self->SUPER::formateFilter(@_); +} - # As we know only user mail (or SSLVar), we have to use it to find him in - # the LDAP directory - formateFilter => sub { - my $self = shift; - if ( $self->{sessionInfo}->{authenticationLevel} and $self->{sessionInfo}->{authenticationLevel} > 4 ) { - $self->{filter} = '(&(' - . $self->{SSLLDAPField} . '=' - . $self->{user} - . ")(objectClass=person))"; - return PE_OK; - } - return $self->formateFilter(@_); - }, - - # Apache SSL environment variable are available in exportedVars: - setSessionInfo => sub { - my $self = shift; - my $save = $self->{exportedVars}; - if ( ref( $self->{exportedVars} ) eq 'HASH' ) { - foreach ( keys %{ $self->{exportedVars} } ) { - if (/^SSL/) { - $self->{sessionInfo}->{$_} = $ENV{$_}; - delete $self->{exportedVars}->{$_}; - } +# Apache SSL environment variable are available in exportedVars: +sub setSessionInfo { + my $self = shift; + my $save = $self->{exportedVars}; + if ( ref( $self->{exportedVars} ) eq 'HASH' ) { + foreach ( keys %{ $self->{exportedVars} } ) { + if (/^SSL/) { + $self->{sessionInfo}->{$_} = $ENV{$_}; + delete $self->{exportedVars}->{$_}; } } - my $r = $self->setSessionInfo(@_); - $self->{exportedVars} = $save; - return $r; - }, + } + my $r = $self->SUPER::setSessionInfo(@_); + $self->{exportedVars} = $save; + return $r; +} - # If authentication has been done with SSL, LDAP bind is disabled - authenticate => sub { - my $self = shift; - if ( $self->{sessionInfo}->{authenticationLevel} and $self->{sessionInfo}->{authenticationLevel} > 4 ) { - return PE_OK; - } - return $self->authenticate(@_); - }, -}; +# If authentication has been done with SSL, LDAP bind is disabled +sub authenticate { + my $self = shift; + if ( $self->{sessionInfo}->{authenticationLevel} + and $self->{sessionInfo}->{authenticationLevel} > 4 ) + { + return PE_OK; + } + return $self->SUPER::authenticate(@_); +} 1; __END__ diff --git a/modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Simple.pm b/modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Simple.pm index 21609ef33..49f13d7c2 100644 --- a/modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Simple.pm +++ b/modules/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Simple.pm @@ -61,21 +61,14 @@ sub new { $self->{securedCookie} ||= 0; $self->{cookieName} ||= "lemonldap"; $self->{ldapPpolicyControl} ||= 0; + $self->{authentication} ||= 'LDAP'; + $self->{authentication} =~ s/^ldap/LDAP/; - if ( $self->{authentication} and $self->{authentication} ne "ldap" ) { - - # $Lemonldap::NG::Portal::AuthSSL::OVERRIDE does not overload $self - # variables: if the administrator has defined a sub, we respect it - my $tmp = - 'require Lemonldap::NG::Portal::Auth' - . $self->{authentication} - . '; $tmp = $Lemonldap::NG::Portal::Auth' - . $self->{authentication} - . '::OVERRIDE;'; - eval $tmp; - die($@) if ($@); - %$self = ( %$tmp, %$self ); - } + # $Lemonldap::NG::Portal::AuthSSL::OVERRIDE does not overload $self + # variables: if the administrator has defined a sub, we respect it + eval 'require Lemonldap::NG::Portal::Auth' . $self->{authentication}; + die($@) if ($@); + bless $self, 'Lemonldap::NG::Portal::Auth' . $self->{authentication}; return $self; } @@ -103,6 +96,7 @@ sub error { # Private sub used to bind to LDAP server both with Lemonldap::NG account and user # credentials if LDAP authentication is used sub _bind { + my $self = shift; my ( $ldap, $dn, $password ) = @_; my $mesg; if ( $dn and $password ) { # named bind @@ -270,15 +264,8 @@ sub existingSession { # 3. In ldap authentication scheme, we load here user and password from HTML # form -sub extractFormInfo { - my $self = shift; - return PE_FIRSTACCESS - unless ( $self->param('user') ); - return PE_FORMEMPTY - unless ( length( $self->{'user'} = $self->param('user') ) > 0 - && length( $self->{'password'} = $self->param('password') ) > 0 ); - PE_OK; -} + +# sub extractFormInfo has to be defined in Auth module used # Unused. You can overload if you have to modify user and password before # authentication @@ -290,7 +277,7 @@ sub formateParams() { # it with Active Directory, overload it to use CN instead of UID. sub formateFilter { my $self = shift; - $self->{filter} = "(&(uid=" . $self->{user} . ")(objectClass=person))"; + $self->{filter} = "(&(uid=" . $self->{user} . ")(objectClass=inetOrgPerson))"; PE_OK; } @@ -333,7 +320,7 @@ sub bind { $self->connectLDAP unless ( $self->{ldap} ); return PE_WRONGMANAGERACCOUNT unless ( - &_bind( $self->{ldap}, $self->{managerDn}, $self->{managerPassword} ) ); + $self->_bind( $self->{ldap}, $self->{managerDn}, $self->{managerPassword} ) ); PE_OK; } @@ -404,62 +391,8 @@ sub unbind { } # 12. Default authentication: LDAP bind with user credentials -sub authenticate { - my $self = shift; - $self->unbind(); - my $err; - return $err unless ( ( $err = $self->connectLDAP ) == PE_OK ); - # Check if we use Ppolicy control - if ( $self->{ldapPpolicyControl} ) { - - # require Perl module - eval 'require Net::LDAP::Control::PasswordPolicy'; - die('Module Net::LDAP::Control::PasswordPolicy not found in @INC') - if ($@); - eval -'use Net::LDAP::Constant qw( LDAP_CONTROL_PASSWORDPOLICY LDAP_PP_ACCOUNT_LOCKED LDAP_PP_PASSWORD_EXPIRED );'; - no strict 'subs'; - - # Create Control object - my $pp = Net::LDAP::Control::PasswordPolicy->new; - - # Bind with user credentials - my $mesg = $self->{ldap}->bind( - $self->{dn}, - password => $self->{password}, - control => [$pp] - ); - - # Get bind response - return PE_OK if ( $mesg->code == 0 ); - - # Get server control response - my ($resp) = $mesg->control(LDAP_CONTROL_PASSWORDPOLICY); - - if ( defined $resp ) { - my $pp_error = $resp->error; - if ($pp_error) { - return PE_PP_ACCOUNT_LOCKED - if ( $pp_error == LDAP_PP_ACCOUNT_LOCKED ); - return PE_PP_PASSWORD_EXPIRED - if ( $pp_error == LDAP_PP_PASSWORD_EXPIRED ); - } - else { - return PE_BADCREDENTIALS; - } - } - else { - return PE_LDAPERROR; - } - } - else { - return PE_BADCREDENTIALS - unless ( &_bind( $self->{ldap}, $self->{dn}, $self->{password} ) ); - } - $self->{sessionInfo}->{authenticationLevel} = 2; - PE_OK; -} +# sub authenticate has to be defined in Auth module used # 13. Now, the user is authenticated. It's time to store his parameters with # Apache::Session::* module @@ -696,7 +629,7 @@ Does nothing. To be overloaded if needed. Creates the ldap filter using $self->{user}. By default : - $self->{filter} = "(&(uid=" . $self->{user} . ")(objectClass=person))"; + $self->{filter} = "(&(uid=" . $self->{user} . ")(objectClass=inetOrgPerson))"; =head3 connectLDAP @@ -761,7 +694,7 @@ described above =head3 _bind( $ldap, $dn, $password ) -Non-object method used to bind to the ldap server. +Method used to bind to the ldap server. =head3 header