Merge branch '2178-new' into 'v2.0'
Make require old password option configurable by a rule See merge request lemonldap-ng/lemonldap-ng!143
This commit is contained in:
commit
b3b354853b
|
@ -24,7 +24,7 @@ use constant MANAGERSECTION => "manager";
|
|||
use constant SESSIONSEXPLORERSECTION => "sessionsExplorer";
|
||||
use constant APPLYSECTION => "apply";
|
||||
our $hashParameters = qr/^(?:(?:l(?:o(?:ca(?:lSessionStorageOption|tionRule)|goutService)|dapExportedVar|wp(?:Ssl)?Opt)|(?:(?:d(?:emo|bi)|facebook|webID)ExportedVa|exported(?:Heade|Va)|issuerDBGetParamete)r|re(?:moteGlobalStorageOption|st2f(?:Verify|Init)Arg|loadUrl)|g(?:r(?:antSessionRule|oup)|lobalStorageOption)|n(?:otificationStorageOption|ginxCustomHandler)|macro)s|o(?:idc(?:S(?:ervice(?:DynamicRegistrationEx(?:portedVar|traClaim)s|MetaDataAuthnContext)|torageOptions)|RPMetaData(?:(?:Option(?:sExtraClaim)?|ExportedVar|Macro)s|Node)|OPMetaData(?:(?:ExportedVar|Option)s|J(?:SON|WKS)|Node))|penIdExportedVars)|s(?:aml(?:S(?:PMetaData(?:(?:ExportedAttribute|Option|Macro)s|Node|XML)|torageOptions)|IDPMetaData(?:(?:ExportedAttribute|Option)s|Node|XML))|essionDataToRemember|laveExportedVars|fExtra)|c(?:as(?:A(?:ppMetaData(?:(?:ExportedVar|Option|Macro)s|Node)|ttributes)|S(?:rvMetaData(?:(?:ExportedVar|Option)s|Node)|torageOptions))|(?:ustom(?:Plugins|Add)Param|ombModule)s)|p(?:ersistentStorageOptions|o(?:rtalSkinRules|st))|a(?:ut(?:hChoiceMod|oSigninR)ules|pplicationList)|v(?:hostOptions|irtualHost)|S(?:MTPTLSOpts|SLVarIf))$/;
|
||||
our $boolKeys = qr/^(?:s(?:aml(?:IDP(?:MetaDataOptions(?:(?:Check(?:S[LS]OMessageSignatur|Audienc|Tim)|IsPassiv)e|A(?:llow(?:LoginFromIDP|ProxiedAuthn)|daptSessionUtime)|Force(?:Authn|UTF8)|StoreSAMLToken|RelayStateURL)|SSODescriptorWantAuthnRequestsSigned)|S(?:P(?:MetaDataOptions(?:(?:CheckS[LS]OMessageSignatur|OneTimeUs)e|EnableIDPInitiatedURL|ForceUTF8)|SSODescriptor(?:WantAssertion|AuthnRequest)sSigned)|erviceUseCertificateInResponse)|DiscoveryProtocol(?:Activation|IsPassive)|CommonDomainCookieActivation|UseQueryStringSpecific|MetadataForceUTF8)|oap(?:Session|Config)Server|t(?:ayConnecte|orePasswor)d|kipRenewConfirmation|fRemovedUseNotif|laveDisplayLogo|howLanguages|slByAjax)|o(?:idc(?:RPMetaDataOptions(?:Allow(?:PasswordGrant|Offline)|Re(?:freshToken|quirePKCE)|LogoutSessionRequired|IDTokenForceClaims|BypassConsent|Public)|ServiceAllow(?:(?:AuthorizationCode|Implicit|Hybrid)Flow|DynamicRegistration)|OPMetaDataOptions(?:(?:CheckJWTSignatur|UseNonc)e|StoreIDToken))|ldNotifFormat)|p(?:ortal(?:Display(?:Re(?:freshMyRights|setPassword|gister)|GeneratePassword|PasswordPolicy)|ErrorOn(?:ExpiredSession|MailNotFound)|(?:CheckLogin|Statu)s|OpenLinkInNewWindow|RequireOldPassword|ForceAuthn|AntiFrame)|roxyUseSoap)|l(?:dap(?:(?:Group(?:DecodeSearchedValu|Recursiv)|UsePasswordResetAttribut)e|(?:AllowResetExpired|Set)Password|ChangePasswordAsUser|PpolicyControl|ITDS)|oginHistoryEnabled)|c(?:a(?:ptcha_(?:register|login|mail)_enabled|sSrvMetaDataOptions(?:Gateway|Renew))|o(?:ntextSwitchingStopWithLogout|mpactConf|rsEnabled)|heck(?:State|User|XSS)|da)|no(?:tif(?:ication(?:Server(?:(?:POS|GE)T|DELETE)?|sExplorer)?|y(?:Deleted|Other))|AjaxHook)|i(?:ssuerDB(?:OpenID(?:Connect)?|SAML|CAS|Get)Activation|mpersonationSkipEmptyValues)|to(?:tp2f(?:UserCan(?:Chang|Remov)eKey|DisplayExistingSecret)|kenUseGlobalStorage)|u(?:se(?:RedirectOn(?:Forbidden|Error)|SafeJail)|2fUserCanRemoveKey|pgradeSession)|br(?:uteForceProtection(?:IncrementalTempo)?|owsersDontStorePassword)|re(?:st(?:(?:Session|Config)Server|ExportSecretKeys)|freshSessions)|(?:mai(?:lOnPasswordChang|ntenanc)|vhostMaintenanc)e|d(?:isablePersistentStorage|biDynamicHashEnabled)|g(?:roupsBeforeMacros|lobalLogoutTimer)|h(?:ideOldPassword|ttpOnly)|yubikey2fUserCanRemoveKey|(?:activeTim|wsdlServ)er|krb(?:RemoveDomain|ByJs))$/;
|
||||
our $boolKeys = qr/^(?:s(?:aml(?:IDP(?:MetaDataOptions(?:(?:Check(?:S[LS]OMessageSignatur|Audienc|Tim)|IsPassiv)e|A(?:llow(?:LoginFromIDP|ProxiedAuthn)|daptSessionUtime)|Force(?:Authn|UTF8)|StoreSAMLToken|RelayStateURL)|SSODescriptorWantAuthnRequestsSigned)|S(?:P(?:MetaDataOptions(?:(?:CheckS[LS]OMessageSignatur|OneTimeUs)e|EnableIDPInitiatedURL|ForceUTF8)|SSODescriptor(?:WantAssertion|AuthnRequest)sSigned)|erviceUseCertificateInResponse)|DiscoveryProtocol(?:Activation|IsPassive)|CommonDomainCookieActivation|UseQueryStringSpecific|MetadataForceUTF8)|oap(?:Session|Config)Server|t(?:ayConnecte|orePasswor)d|kipRenewConfirmation|fRemovedUseNotif|laveDisplayLogo|howLanguages|slByAjax)|o(?:idc(?:RPMetaDataOptions(?:Allow(?:PasswordGrant|Offline)|Re(?:freshToken|quirePKCE)|LogoutSessionRequired|IDTokenForceClaims|BypassConsent|Public)|ServiceAllow(?:(?:AuthorizationCode|Implicit|Hybrid)Flow|DynamicRegistration)|OPMetaDataOptions(?:(?:CheckJWTSignatur|UseNonc)e|StoreIDToken))|ldNotifFormat)|p(?:ortal(?:Display(?:Re(?:freshMyRights|setPassword|gister)|GeneratePassword|PasswordPolicy)|ErrorOn(?:ExpiredSession|MailNotFound)|(?:CheckLogin|Statu)s|OpenLinkInNewWindow|ForceAuthn|AntiFrame)|roxyUseSoap)|l(?:dap(?:(?:Group(?:DecodeSearchedValu|Recursiv)|UsePasswordResetAttribut)e|(?:AllowResetExpired|Set)Password|ChangePasswordAsUser|PpolicyControl|ITDS)|oginHistoryEnabled)|c(?:a(?:ptcha_(?:register|login|mail)_enabled|sSrvMetaDataOptions(?:Gateway|Renew))|o(?:ntextSwitchingStopWithLogout|mpactConf|rsEnabled)|heck(?:State|User|XSS)|da)|no(?:tif(?:ication(?:Server(?:(?:POS|GE)T|DELETE)?|sExplorer)?|y(?:Deleted|Other))|AjaxHook)|i(?:ssuerDB(?:OpenID(?:Connect)?|SAML|CAS|Get)Activation|mpersonationSkipEmptyValues)|to(?:tp2f(?:UserCan(?:Chang|Remov)eKey|DisplayExistingSecret)|kenUseGlobalStorage)|u(?:se(?:RedirectOn(?:Forbidden|Error)|SafeJail)|2fUserCanRemoveKey|pgradeSession)|br(?:uteForceProtection(?:IncrementalTempo)?|owsersDontStorePassword)|re(?:st(?:(?:Session|Config)Server|ExportSecretKeys)|freshSessions)|(?:mai(?:lOnPasswordChang|ntenanc)|vhostMaintenanc)e|d(?:isablePersistentStorage|biDynamicHashEnabled)|g(?:roupsBeforeMacros|lobalLogoutTimer)|h(?:ideOldPassword|ttpOnly)|yubikey2fUserCanRemoveKey|(?:activeTim|wsdlServ)er|krb(?:RemoveDomain|ByJs))$/;
|
||||
|
||||
our @sessionTypes = ( 'remoteGlobal', 'global', 'localSession', 'persistent', 'saml', 'oidc', 'cas' );
|
||||
|
||||
|
|
|
@ -2610,7 +2610,7 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.]
|
|||
},
|
||||
'portalRequireOldPassword' => {
|
||||
'default' => 1,
|
||||
'type' => 'bool'
|
||||
'type' => 'boolOrExpr'
|
||||
},
|
||||
'portalSkin' => {
|
||||
'default' => 'bootstrap',
|
||||
|
|
|
@ -1425,8 +1425,8 @@ sub attributes {
|
|||
},
|
||||
portalRequireOldPassword => {
|
||||
default => 1,
|
||||
type => 'bool',
|
||||
documentation => 'Old password is required to change the password',
|
||||
type => 'boolOrExpr',
|
||||
documentation => 'Rule to require old password to change the password',
|
||||
},
|
||||
hideOldPassword => {
|
||||
default => 0,
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -266,20 +266,21 @@ sub userBind {
|
|||
return PE_BADCREDENTIALS;
|
||||
}
|
||||
|
||||
## @method int userModifyPassword(string dn, string newpassword, string oldpassword, boolean ad)
|
||||
## @method int userModifyPassword(string dn, string newpassword, string oldpassword, boolean ad, boolean requireOldPassword)
|
||||
# Change user's password.
|
||||
# @param $dn DN
|
||||
# @param $newpassword New password
|
||||
# @param $oldpassword Current password
|
||||
# @param $ad Active Directory mode
|
||||
# @param $requireOldPassword Old password is needed to update
|
||||
# @return Lemonldap::NG::Portal constant
|
||||
sub userModifyPassword {
|
||||
my ( $self, $dn, $newpassword, $oldpassword, $ad ) = @_;
|
||||
my $ppolicyControl = $self->{conf}->{ldapPpolicyControl};
|
||||
my $setPassword = $self->{conf}->{ldapSetPassword};
|
||||
my $asUser = $self->{conf}->{ldapChangePasswordAsUser};
|
||||
my $requireOldPassword = $self->{conf}->{portalRequireOldPassword};
|
||||
my $passwordAttribute = "userPassword";
|
||||
my ( $self, $dn, $newpassword, $oldpassword, $ad, $requireOldPassword ) =
|
||||
@_;
|
||||
my $ppolicyControl = $self->{conf}->{ldapPpolicyControl};
|
||||
my $setPassword = $self->{conf}->{ldapSetPassword};
|
||||
my $asUser = $self->{conf}->{ldapChangePasswordAsUser};
|
||||
my $passwordAttribute = "userPassword";
|
||||
my $err;
|
||||
my $mesg;
|
||||
|
||||
|
|
|
@ -10,7 +10,8 @@ use Mouse;
|
|||
use JSON;
|
||||
use URI;
|
||||
|
||||
has skinRules => ( is => 'rw' );
|
||||
has skinRules => ( is => 'rw' );
|
||||
has requireOldPwd => ( is => 'rw', default => sub { 1 } );
|
||||
|
||||
sub displayInit {
|
||||
my ($self) = @_;
|
||||
|
@ -29,6 +30,13 @@ sub displayInit {
|
|||
}
|
||||
}
|
||||
}
|
||||
my $rule = HANDLER->buildSub(
|
||||
HANDLER->substitute( $self->conf->{portalRequireOldPassword} ) );
|
||||
unless ($rule) {
|
||||
my $error = HANDLER->tsv->{jail}->error || '???';
|
||||
$self->logger->error( "Bad requireOldPwd rule: " . $error );
|
||||
}
|
||||
$self->requireOldPwd($rule);
|
||||
}
|
||||
|
||||
# Call portal process and set template parameters
|
||||
|
@ -143,7 +151,7 @@ sub display {
|
|||
CHOICE_VALUE => $req->data->{_authChoice},
|
||||
FORM_METHOD => $method,
|
||||
(
|
||||
(not $req->{urldc}) ? ( SEND_PARAMS => 1 )
|
||||
( not $req->{urldc} ) ? ( SEND_PARAMS => 1 )
|
||||
: ()
|
||||
),
|
||||
(
|
||||
|
@ -222,7 +230,7 @@ sub display {
|
|||
LOGOUT_URL => $self->conf->{portal} . "?logout=1",
|
||||
APPSLIST_ORDER => $req->{sessionInfo}->{'_appsListOrder'},
|
||||
PING => $self->conf->{portalPingInterval},
|
||||
REQUIRE_OLDPASSWORD => $self->conf->{portalRequireOldPassword},
|
||||
REQUIRE_OLDPASSWORD => $self->requireOldPwd->($req, $req->userData),
|
||||
HIDE_OLDPASSWORD => 0,
|
||||
DISPLAY_PPOLICY => $self->conf->{portalDisplayPasswordPolicy},
|
||||
PPOLICY_MINSIZE => $self->conf->{passwordPolicyMinSize},
|
||||
|
|
|
@ -33,6 +33,19 @@ sub modifyPassword {
|
|||
$self->logger->error('"dn" is not set, aborting password modification');
|
||||
return PE_ERROR;
|
||||
}
|
||||
my $rule = $self->p->HANDLER->buildSub(
|
||||
$self->p->HANDLER->substitute(
|
||||
$self->conf->{portalRequireOldPassword}
|
||||
)
|
||||
);
|
||||
unless ($rule) {
|
||||
my $error = $self->p->HANDLER->tsv->{jail}->error || '???';
|
||||
}
|
||||
my $requireOldPassword = (
|
||||
$req->userData
|
||||
? $rule->( $req, $req->userData )
|
||||
: $rule->( $req, $req->sessionInfo )
|
||||
);
|
||||
|
||||
# Ensure connection is valid
|
||||
$self->bind;
|
||||
|
@ -41,7 +54,7 @@ sub modifyPassword {
|
|||
# Call the modify password method
|
||||
my $code =
|
||||
$self->ldap->userModifyPassword( $dn, $pwd, $req->data->{oldpassword},
|
||||
1 );
|
||||
1, $requireOldPassword );
|
||||
|
||||
unless ( $code == PE_PASSWORD_OK ) {
|
||||
return $code;
|
||||
|
|
|
@ -42,8 +42,14 @@ sub _modifyPassword {
|
|||
return PE_PASSWORD_MISMATCH
|
||||
unless ( $req->data->{newpassword} eq $req->param('confirmpassword') );
|
||||
|
||||
my $rule =
|
||||
$self->p->HANDLER->buildSub( $self->p->HANDLER->substitute( $self->conf->{portalRequireOldPassword} ) );
|
||||
unless ($rule) {
|
||||
my $error = $self->p->HANDLER->tsv->{jail}->error || '???';
|
||||
}
|
||||
|
||||
# Check if portal require old password
|
||||
if ( $self->conf->{portalRequireOldPassword} or $requireOldPwd ) {
|
||||
if ( $rule->($req, $req->userData) or $requireOldPwd ) {
|
||||
|
||||
# TODO: verify oldpassword
|
||||
unless ( $req->data->{oldpassword} = $req->param('oldpassword') ) {
|
||||
|
|
|
@ -29,12 +29,23 @@ sub confirm {
|
|||
sub modifyPassword {
|
||||
my ( $self, $req, $pwd ) = @_;
|
||||
my $dn;
|
||||
my $requireOldPassword;
|
||||
my $rule = $self->p->HANDLER->buildSub(
|
||||
$self->p->HANDLER->substitute(
|
||||
$self->conf->{portalRequireOldPassword}
|
||||
)
|
||||
);
|
||||
unless ($rule) {
|
||||
my $error = $self->p->HANDLER->tsv->{jail}->error || '???';
|
||||
}
|
||||
if ( $req->userData->{_dn} ) {
|
||||
$dn = $req->userData->{_dn};
|
||||
$requireOldPassword = $rule->( $req, $req->userData );
|
||||
$self->logger->debug("Get DN from request data: $dn");
|
||||
}
|
||||
else {
|
||||
$dn = $req->sessionInfo->{_dn};
|
||||
$requireOldPassword = $rule->( $req, $req->sessionInfo );
|
||||
$self->logger->debug("Get DN from session data: $dn");
|
||||
}
|
||||
unless ($dn) {
|
||||
|
@ -48,7 +59,7 @@ sub modifyPassword {
|
|||
|
||||
# Call the modify password method
|
||||
my $code =
|
||||
$self->ldap->userModifyPassword( $dn, $pwd, $req->data->{oldpassword} );
|
||||
$self->ldap->userModifyPassword( $dn, $pwd, $req->data->{oldpassword}, 0 , $requireOldPassword );
|
||||
|
||||
unless ( $code == PE_PASSWORD_OK ) {
|
||||
return $code;
|
||||
|
|
|
@ -19,7 +19,7 @@ SKIP: {
|
|||
portal => 'http://auth.example.com/',
|
||||
userDB => 'Same',
|
||||
passwordDB => 'LDAP',
|
||||
portalRequireOldPassword => 1,
|
||||
portalRequireOldPassword => '$uid eq "dwho"',
|
||||
ldapServer => 'ldap://127.0.0.1:19389/',
|
||||
ldapBase => 'ou=users,dc=example,dc=com',
|
||||
managerDn => 'cn=admin,dc=example,dc=com',
|
||||
|
|
Loading…
Reference in New Issue
Block a user