Modify password for Active Directory (#513)

This commit is contained in:
Clément Oudot 2013-06-01 13:40:29 +00:00
parent da268cff7f
commit c8f8e78546
2 changed files with 77 additions and 28 deletions

View File

@ -40,11 +40,10 @@ sub modifyPassword {
$self->lmLog( "Modify password request for " . $self->{dn}, 'debug' ); $self->lmLog( "Modify password request for " . $self->{dn}, 'debug' );
# Call the modify password method for AD # Call the modify password method for AD
# TODO my $code =
my $code = $self->ldap->userModifyADPassword( $self->ldap->userModifyPassword( $self->{dn}, $self->{newpassword},
$self->{dn}, $self->{newpassword}, $self->{confirmpassword},
$self->{confirmpassword}, $self->{oldpassword} $self->{oldpassword}, 1 );
);
return $code unless ( $code == PE_PASSWORD_OK ); return $code unless ( $code == PE_PASSWORD_OK );

View File

@ -11,6 +11,7 @@ use Exporter;
use base qw(Exporter Net::LDAP); use base qw(Exporter Net::LDAP);
use Lemonldap::NG::Portal::Simple; use Lemonldap::NG::Portal::Simple;
use Encode; use Encode;
use Unicode::String qw(utf8);
use strict; use strict;
our @EXPORT = qw(ldap); our @EXPORT = qw(ldap);
@ -215,31 +216,61 @@ sub userBind {
return PE_BADCREDENTIALS; return PE_BADCREDENTIALS;
} }
## @method private int _changePassword(string newpassword,string confirmpassword,string oldpassword) ## @method int userModifyPassword(string dn, string newpassword, string confirmpassword, string oldpassword, boolean ad)
# Change user's password. # Change user's password.
# @param $dn DN
# @param $newpassword New password # @param $newpassword New password
# @param $confirmpassword New password # @param $confirmpassword New password
# @param $oldpassword Current password # @param $oldpassword Current password
# @param $ad Active Directory mode
# @return Lemonldap::NG::Portal constant # @return Lemonldap::NG::Portal constant
sub userModifyPassword { sub userModifyPassword {
my ( $self, $dn, $newpassword, $confirmpassword, $oldpassword ) = splice @_; my ( $self, $dn, $newpassword, $confirmpassword, $oldpassword, $ad ) =
splice @_;
my $ppolicyControl = $self->{portal}->{ldapPpolicyControl};
my $setPassword = $self->{portal}->{ldapSetPassword};
my $asUser = $self->{portal}->{ldapChangePasswordAsUser};
my $requireOldPassword = $self->{portal}->{portalRequireOldPassword};
my $passwordAttribute = "userPassword";
my $err; my $err;
my $mesg; my $mesg;
# Verify confirmation password matching # Verify confirmation password matching
return PE_PASSWORD_MISMATCH unless ( $newpassword eq $confirmpassword ); unless ( $newpassword eq $confirmpassword ) {
$self->{portal}->lmLog(
"Password $newpassword and password $confirmpassword are not the same",
'debug'
);
return PE_PASSWORD_MISMATCH;
}
# Adjust configuration for AD
if ($ad) {
$ppolicyControl = 0;
$setPassword = 0;
$asUser = 0;
$passwordAttribute = "unicodePwd";
# Encode password for AD
$newpassword = utf8( chr(34) . $newpassword . chr(34) )->utf16le();
$self->{portal}->lmLog( "Active Directory mode enabled", 'debug' );
}
# First case: no ppolicy # First case: no ppolicy
if ( !$self->{portal}->{ldapPpolicyControl} ) { if ( !$ppolicyControl ) {
if ( $self->{portal}->{ldapSetPassword} ) { if ($setPassword) {
# Bind as user if oldpassword and ldapChangePasswordAsUser # Bind as user if oldpassword and ldapChangePasswordAsUser
if ( $oldpassword and $self->{portal}->{ldapChangePasswordAsUser} ) if ( $oldpassword and $asUser ) {
{
$mesg = $self->bind( $dn, password => $oldpassword ); $mesg = $self->bind( $dn, password => $oldpassword );
return PE_BADOLDPASSWORD if ( $mesg->code != 0 ); if ( $mesg->code != 0 ) {
$self->{portal}->lmLog( "Bad old password", 'debug' );
return PE_BADOLDPASSWORD;
}
} }
# Use SetPassword extended operation # Use SetPassword extended operation
@ -257,29 +288,39 @@ sub userModifyPassword {
); );
# Catch the "Unwilling to perform" error # Catch the "Unwilling to perform" error
return PE_BADOLDPASSWORD if ( $mesg->code == 53 ); if ( $mesg->code == 53 ) {
$self->{portal}->lmLog( "Bad old password", 'debug' );
return PE_BADOLDPASSWORD;
}
} }
else { else {
if ( $self->{portal}->{portalRequireOldPassword} ) { if ($requireOldPassword) {
return PE_MUST_SUPPLY_OLD_PASSWORD if ( !$oldpassword ); return PE_MUST_SUPPLY_OLD_PASSWORD if ( !$oldpassword );
# Check old password with a bind # Check old password with a bind
$mesg = $self->bind( $dn, password => $oldpassword ); $mesg = $self->bind( $dn, password => $oldpassword );
return PE_BADOLDPASSWORD if ( $mesg->code != 0 ); if ( $mesg->code != 0 ) {
$self->{portal}->lmLog( "Bad old password", 'debug' );
return PE_BADOLDPASSWORD;
}
# Rebind as Manager only if user is not granted to change its password # Rebind as Manager only if user is not granted to change its password
$self->bind() $self->bind() unless $asUser;
unless $self->{portal}->{ldapChangePasswordAsUser};
} }
# Use standard modification # Use standard modification
$mesg = $mesg =
$self->modify( $dn, replace => { userPassword => $newpassword } ); $self->modify( $dn,
replace => { $passwordAttribute => $newpassword } );
} }
$self->{portal}
->lmLog( "Modification return code: " . $mesg->code, 'debug' );
return PE_WRONGMANAGERACCOUNT return PE_WRONGMANAGERACCOUNT
if ( $mesg->code == 50 || $mesg->code == 8 ); if ( $mesg->code == 50 || $mesg->code == 8 );
return PE_PP_INSUFFICIENT_PASSWORD_QUALITY
if ( $mesg->code == 53 && $ad );
return PE_LDAPERROR unless ( $mesg->code == 0 ); return PE_LDAPERROR unless ( $mesg->code == 0 );
$self->{portal} $self->{portal}
->_sub( 'userNotice', "Password changed $self->{portal}->{user}" ); ->_sub( 'userNotice', "Password changed $self->{portal}->{user}" );
@ -290,14 +331,15 @@ sub userModifyPassword {
# Create Control object # Create Control object
my $pp = Net::LDAP::Control::PasswordPolicy->new; my $pp = Net::LDAP::Control::PasswordPolicy->new;
if ( $self->{portal}->{ldapSetPassword} ) { if ($setPassword) {
# Bind as user if oldpassword and ldapChangePasswordAsUser # Bind as user if oldpassword and ldapChangePasswordAsUser
if ( $oldpassword and $self->{portal}->{ldapChangePasswordAsUser} ) if ( $oldpassword and $asUser ) {
{
$mesg = $self->bind( $dn, password => $oldpassword ); $mesg = $self->bind( $dn, password => $oldpassword );
return PE_BADOLDPASSWORD if ( $mesg->code != 0 ); if ( $mesg->code != 0 ) {
$self->{portal}->lmLog( "Bad old password", 'debug' );
return PE_BADOLDPASSWORD;
}
} }
# Use SetPassword extended operation # Use SetPassword extended operation
@ -319,24 +361,30 @@ sub userModifyPassword {
); );
# Catch the "Unwilling to perform" error # Catch the "Unwilling to perform" error
return PE_BADOLDPASSWORD if ( $mesg->code == 53 ); if ( $mesg->code == 53 ) {
$self->{portal}->lmLog( "Bad old password", 'debug' );
return PE_BADOLDPASSWORD;
}
} }
else { else {
if ($oldpassword) { if ($oldpassword) {
# Check old password with a bind # Check old password with a bind
$mesg = $self->bind( $dn, password => $oldpassword ); $mesg = $self->bind( $dn, password => $oldpassword );
return PE_BADOLDPASSWORD if ( $mesg->code != 0 ); if ( $mesg->code != 0 ) {
$self->{portal}->lmLog( "Bad old password", 'debug' );
return PE_BADOLDPASSWORD;
}
# Rebind as Manager only if user is not granted to change its password # Rebind as Manager only if user is not granted to change its password
$self->bind() $self->bind()
unless $self->{portal}->{ldapChangePasswordAsUser}; unless $asUser;
} }
# Use standard modification # Use standard modification
$mesg = $self->modify( $mesg = $self->modify(
$dn, $dn,
replace => { userPassword => $newpassword }, replace => { $passwordAttribute => $newpassword },
control => [$pp] control => [$pp]
); );
} }
@ -344,6 +392,8 @@ sub userModifyPassword {
# Get server control response # Get server control response
my ($resp) = $mesg->control("1.3.6.1.4.1.42.2.27.8.5.1"); my ($resp) = $mesg->control("1.3.6.1.4.1.42.2.27.8.5.1");
$self->{portal}
->lmLog( "Modification return code: " . $mesg->code, 'debug' );
return PE_WRONGMANAGERACCOUNT return PE_WRONGMANAGERACCOUNT
if ( $mesg->code == 50 || $mesg->code == 8 ); if ( $mesg->code == 50 || $mesg->code == 8 );
if ( $mesg->code == 0 ) { if ( $mesg->code == 0 ) {