diff --git a/lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf/DefaultValues.pm b/lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf/DefaultValues.pm index 4227a27cf..2173354b2 100644 --- a/lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf/DefaultValues.pm +++ b/lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf/DefaultValues.pm @@ -41,6 +41,7 @@ sub defaultValues { 'checkXSS' => 1, 'confirmFormMethod' => 'post', 'contextSwitchingIdRule' => 1, + 'contextSwitchingPrefix' => 'switching', 'contextSwitchingRule' => 0, 'contextSwitchingStopWithLogout' => 1, 'cookieName' => 'lemonldap', diff --git a/lemonldap-ng-common/lib/Lemonldap/NG/Common/Notifications/JSON.pm b/lemonldap-ng-common/lib/Lemonldap/NG/Common/Notifications/JSON.pm index 3424b8cca..b1df8a22b 100644 --- a/lemonldap-ng-common/lib/Lemonldap/NG/Common/Notifications/JSON.pm +++ b/lemonldap-ng-common/lib/Lemonldap/NG/Common/Notifications/JSON.pm @@ -15,10 +15,13 @@ sub newNotification { eval { $self->logger->error("Unable to decode JSON file: $err") }; return 0; } + my @notifs; $json = [$json] unless ( ref($json) eq 'ARRAY' ); + foreach my $notif (@$json) { my @data; + $notif->{reference} =~ s/_/-/g; # Remove underscores (#2135) # Mandatory information foreach (qw(date uid reference)) { diff --git a/lemonldap-ng-common/lib/Lemonldap/NG/Common/Notifications/XML.pm b/lemonldap-ng-common/lib/Lemonldap/NG/Common/Notifications/XML.pm index 557b6fd5e..3e0c30221 100644 --- a/lemonldap-ng-common/lib/Lemonldap/NG/Common/Notifications/XML.pm +++ b/lemonldap-ng-common/lib/Lemonldap/NG/Common/Notifications/XML.pm @@ -25,12 +25,15 @@ sub newNotification { eval { $self->logger->error("Unable to read XML file : $err") }; return 0; } + my @notifs; my ( $version, $encoding ) = ( $xml->version(), $xml->encoding() ); + foreach my $notif ( $xml->documentElement->getElementsByTagName('notification') ) { my @data = (); + $notif->{reference} =~ s/_/-/g; # Remove underscores (#2135) # Mandatory information foreach (qw(date uid reference)) { diff --git a/lemonldap-ng-manager/MANIFEST b/lemonldap-ng-manager/MANIFEST index b8209c036..d6b813cc8 100644 --- a/lemonldap-ng-manager/MANIFEST +++ b/lemonldap-ng-manager/MANIFEST @@ -37,6 +37,8 @@ README REST-API.md scripts/lmConfigEditor scripts/testConfBackend.pl +site/api/api.fcgi +site/api/api.psgi site/coffee/2ndfa.coffee site/coffee/diff.coffee site/coffee/filterFunctions.coffee @@ -46,8 +48,6 @@ site/coffee/notifications.coffee site/coffee/sessions.coffee site/coffee/viewDiff.coffee site/coffee/viewer.coffee -site/api/api.fcgi -site/api/api.psgi site/htdocs/manager.fcgi site/htdocs/manager.psgi site/htdocs/static/bwr/angular-animate/angular-animate.js diff --git a/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Attributes.pm b/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Attributes.pm index 8b78ee2ad..bcab1736d 100644 --- a/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Attributes.pm +++ b/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Attributes.pm @@ -1007,6 +1007,10 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.] }, 'type' => 'text' }, + 'contextSwitchingPrefix' => { + 'default' => 'switching', + 'type' => 'text' + }, 'contextSwitchingRule' => { 'default' => 0, 'type' => 'boolOrExpr' diff --git a/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Build/Attributes.pm b/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Build/Attributes.pm index 7cc2632d0..b4d805a8d 100644 --- a/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Build/Attributes.pm +++ b/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Build/Attributes.pm @@ -562,6 +562,12 @@ sub attributes { documentation => 'Stop context switching by logout', flags => 'p', }, + contextSwitchingPrefix => { + type => 'text', + default => 'switching', + documentation => 'Prefix to store real session Id', + flags => 'p', + }, decryptValueRule => { type => 'boolOrExpr', default => 0, diff --git a/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Conf/Tests.pm b/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Conf/Tests.pm index d90f37648..f11fdc2d4 100644 --- a/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Conf/Tests.pm +++ b/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Conf/Tests.pm @@ -42,14 +42,8 @@ sub tests { # Check if portal URL is well formated portalURL => sub { - # Checking for ending slash - $conf->{portal} .= '/' - unless ( $conf->{portal} =~ qr#/$# ); - - # Deleting trailing ending slash - my $regex = qr#/+$#; - $conf->{portal} =~ s/$regex/\//; - + # Append or remove trailing ending slashes + $conf->{portal} =~ s%/*$%/%; return 1; }, @@ -779,7 +773,7 @@ sub tests { # Notification system required with removed SF notification sfRemovedNotification => sub { return 1 unless ( $conf->{sfRemovedMsgRule} ); - return ( -1, + return ( 1, 'Notification system must be enabled to display a notification if a SF is removed' ) if ( $conf->{sfRemovedUseNotif} and not $conf->{notification} ); return 1; diff --git a/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Notifications.pm b/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Notifications.pm index a6f16df7f..89a2abb94 100644 --- a/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Notifications.pm +++ b/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Notifications.pm @@ -271,6 +271,8 @@ sub newNotification { return $self->sendError( $req, undef, 200 ); } + $json->{reference} =~ s/_/-/g; # Remove underscores (#2135) + foreach my $r (qw(uid reference xml)) { return $self->sendError( $req, "Missing $r", 200 ) unless ( $json->{$r} ); diff --git a/lemonldap-ng-manager/t/80-attributes.t b/lemonldap-ng-manager/t/80-attributes.t index b413726a7..4b9838b52 100644 --- a/lemonldap-ng-manager/t/80-attributes.t +++ b/lemonldap-ng-manager/t/80-attributes.t @@ -66,7 +66,7 @@ my @notManagedAttributes = ( # Other ini-only prms 'checkTime', 'status', 'soapProxyUrn', 'impersonationPrefix', 'pdataDomain', - 'mySessionAuthorizedRWKeys', + 'mySessionAuthorizedRWKeys', 'contextSwitchingPrefix' ); # Words used either as attribute name and node title diff --git a/lemonldap-ng-portal/MANIFEST b/lemonldap-ng-portal/MANIFEST index 8ffebee06..c3f2bd118 100644 --- a/lemonldap-ng-portal/MANIFEST +++ b/lemonldap-ng-portal/MANIFEST @@ -476,6 +476,7 @@ site/templates/common/script.tpl t/01-AuthDemo.t t/01-CSP-and-CORS-headers.t t/01-pdata.t +t/02-Password-Demo-Local-noPpolicy.t t/02-Password-Demo-Local-Ppolicy.t t/02-Password-Demo.t t/03-ConfTimeout.t @@ -641,6 +642,7 @@ t/67-CheckUser-with-Impersonation-and-Macros.t t/67-CheckUser-with-issuer-SAML-POST.t t/67-CheckUser-with-token.t t/67-CheckUser.t +t/68-ContextSwitching-with-Impersonation.t t/68-ContextSwitching-with-Logout.t t/68-ContextSwitching-with-TOTP-and-Notification.t t/68-ContextSwitching.t diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Display.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Display.pm index 6629b0e01..4b530987d 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Display.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Display.pm @@ -213,6 +213,13 @@ sub display { $speChars =~ s/(?:^\s|\s$)//g; $skinfile = 'menu'; + my $isPP = + $self->conf->{passwordPolicyMinSize} + || $self->conf->{passwordPolicyMinLower} + || $self->conf->{passwordPolicyMinUpper} + || $self->conf->{passwordPolicyMinDigit} + || $speChars; + #utf8::decode($auth_user); %templateParams = ( AUTH_USER => $req->{sessionInfo}->{ $self->conf->{portalUserAttr} }, @@ -228,6 +235,7 @@ sub display { PPOLICY_MINLOWER => $self->conf->{passwordPolicyMinLower}, PPOLICY_MINUPPER => $self->conf->{passwordPolicyMinUpper}, PPOLICY_MINDIGIT => $self->conf->{passwordPolicyMinDigit}, + PPOLICY_NOPOLICY => !$isPP, PPOLICY_ALLOWEDSPECHAR => $speChars, ( $speChars diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/ContextSwitching.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/ContextSwitching.pm index 6cb2f9670..051748dd0 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/ContextSwitching.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/ContextSwitching.pm @@ -75,7 +75,7 @@ sub init { sub display { my ( $self, $req ) = @_; my $realSessionId = - $req->userData->{"$self->{conf}->{impersonationPrefix}_session_id"}; + $req->userData->{"$self->{conf}->{contextSwitchingPrefix}_session_id"}; my $realSession; unless ( $realSession = $self->p->getApacheSession($realSessionId) ) { $self->userLogger->info( @@ -85,14 +85,17 @@ sub display { # Check access rules unless ( $self->rule->( $req, $req->userData ) - || $req->userData->{"$self->{conf}->{impersonationPrefix}_session_id"} ) + || $req->userData->{ + "$self->{conf}->{contextSwitchingPrefix}_session_id"} ) { $self->userLogger->warn('ContextSwitching service NOT authorized'); return $self->p->do( $req, [ sub { PE_IMPERSONATION_SERVICE_NOT_ALLOWED } ] ); } - if ( $req->userData->{"$self->{conf}->{impersonationPrefix}_session_id"} ) { + if ( + $req->userData->{"$self->{conf}->{contextSwitchingPrefix}_session_id"} ) + { $self->logger->debug('Request to stop ContextSwitching'); if ( $self->conf->{contextSwitchingStopWithLogout} ) { $self->userLogger->notice("Stop ContextSwitching for $req->{user}"); @@ -177,14 +180,9 @@ sub run { # Create spoofed session $req = $self->_switchContext( $req, $spoofId ); - if ( $req->error ) { - if ( $req->error == PE_BADCREDENTIALS ) { - $statut = PE_MALFORMEDUSER; - } - else { - $statut = $req->error; - } - } + $statut = + ( $req->error == PE_BADCREDENTIALS ? PE_MALFORMEDUSER : $req->error ) + if $req->error; # Main session $self->p->updateSession( $req, $req->sessionInfo ); @@ -211,12 +209,11 @@ sub _switchContext { ] ); if ( my $error = $self->p->process($req) ) { - if ( $error == PE_BADCREDENTIALS ) { - $self->userLogger->warn( - 'ContextSwitching requested for an unvalid user (' - . $req->{user} - . ")" ); - } + $self->userLogger->warn( + 'ContextSwitching requested for an unvalid user (' + . $req->{user} + . ")" ) + if ( $error == PE_BADCREDENTIALS ); $self->logger->debug("Process returned error: $error"); $req->error($error); $raz = 1; @@ -233,37 +230,34 @@ sub _switchContext { $raz = 1; } - $req->sessionInfo->{"$self->{conf}->{impersonationPrefix}_session_id"} = + $req->sessionInfo->{"$self->{conf}->{contextSwitchingPrefix}_session_id"} = $realSessionId; - if ($raz) { - return $self->_abortImpersonation( $req, $spoofId, $realId, 1 ); - } - else { + return $self->_abortImpersonation( $req, $spoofId, $realId, 1 ) if $raz; + + $self->logger->debug( + "Update sessionInfo with real authenticationLevel: $realAuthLevel"); + $req->sessionInfo->{authenticationLevel} = $realAuthLevel; + delete $req->sessionInfo->{groups}; + + # Compute groups & macros again with real authenticationLevel + $req->steps( [ $self->p->groupsAndMacros, 'setLocalGroups' ] ); + if ( my $error = $self->p->process($req) ) { $self->logger->debug( - "Update sessionInfo with real authenticationLevel: $realAuthLevel"); - $req->sessionInfo->{authenticationLevel} = $realAuthLevel; - delete $req->sessionInfo->{groups}; - - # Compute groups & macros again with real authenticationLevel - $req->steps( [ $self->p->groupsAndMacros, 'setLocalGroups' ] ); - if ( my $error = $self->p->process($req) ) { - $self->logger->debug( - "ContextSwitching: Process returned error: $error"); - $req->error($error); - } - - $self->userLogger->notice( - "Start ContextSwitching: $realId becomes $spoofId "); - return $req; + "ContextSwitching: Process returned error: $error"); + $req->error($error); } + + $self->userLogger->notice( + "Start ContextSwitching: $realId becomes $spoofId "); + return $req; } sub _abortImpersonation { my ( $self, $req, $spoofId, $realId, $abort ) = @_; my $type = $abort ? 'sessionInfo' : 'userData'; my $realSessionId = - $req->{$type}->{"$self->{conf}->{impersonationPrefix}_session_id"}; + $req->{$type}->{"$self->{conf}->{contextSwitchingPrefix}_session_id"}; my $session; unless ( $session = $self->p->getApacheSession($realSessionId) ) { $self->userLogger->info("Session $session expired"); @@ -293,7 +287,8 @@ sub _abortImpersonation { $req->urldc( $self->conf->{portal} ); $req->id($realSessionId); $self->p->buildCookie($req); - delete $req->{$type}->{"$self->{conf}->{impersonationPrefix}_session_id"}; + delete $req->{$type} + ->{"$self->{conf}->{contextSwitchingPrefix}_session_id"}; return $req; } @@ -301,7 +296,7 @@ sub _abortImpersonation { sub displayLink { my ( $self, $req ) = @_; return 'OFF' - if $req->userData->{"$self->{conf}->{impersonationPrefix}_session_id"}; + if $req->userData->{"$self->{conf}->{contextSwitchingPrefix}_session_id"}; return 'ON' if $self->rule->( $req, $req->userData ); } diff --git a/lemonldap-ng-portal/site/htdocs/static/languages/ar.json b/lemonldap-ng-portal/site/htdocs/static/languages/ar.json index ded8409c1..36b569650 100644 --- a/lemonldap-ng-portal/site/htdocs/static/languages/ar.json +++ b/lemonldap-ng-portal/site/htdocs/static/languages/ar.json @@ -229,6 +229,7 @@ "passwordPolicyMinUpper":"Minimal upper characters:", "passwordPolicyMinDigit":"Minimal digit characters:", "passwordPolicyMinSpeChar":"Minimal special characters:", +"passwordPolicyNone":"You are free to choose your password!", "passwordPolicySpecialChar":"Allowed special characters:", "ppGrace":"المصادقات المتبقية، غير كلمة المرور الخاصة بك!", "proxyError":"بوابة سيئة: غير قادر على الانضمام لالخادم البعيد", diff --git a/lemonldap-ng-portal/site/htdocs/static/languages/de.json b/lemonldap-ng-portal/site/htdocs/static/languages/de.json index a9fc69593..7c04224c3 100644 --- a/lemonldap-ng-portal/site/htdocs/static/languages/de.json +++ b/lemonldap-ng-portal/site/htdocs/static/languages/de.json @@ -228,6 +228,7 @@ "passwordPolicyMinUpper":"Minimal upper characters:", "passwordPolicyMinDigit":"Minimal digit characters:", "passwordPolicyMinSpeChar":"Minimal special characters:", +"passwordPolicyNone":"You are free to choose your password!", "passwordPolicySpecialChar":"Allowed special characters:", "ppGrace":"verbleibende Authentifizierungen, bitte Passwort ändern !", "proxyError":"Bad gateway: Der Remote-Server kann nicht verbunden werden", diff --git a/lemonldap-ng-portal/site/htdocs/static/languages/en.json b/lemonldap-ng-portal/site/htdocs/static/languages/en.json index 71129f550..a75049524 100644 --- a/lemonldap-ng-portal/site/htdocs/static/languages/en.json +++ b/lemonldap-ng-portal/site/htdocs/static/languages/en.json @@ -229,6 +229,7 @@ "passwordPolicyMinUpper":"Minimal upper characters:", "passwordPolicyMinDigit":"Minimal digit characters:", "passwordPolicyMinSpeChar":"Minimal special characters:", +"passwordPolicyNone":"You are free to choose your password!", "passwordPolicySpecialChar":"Allowed special characters:", "ppGrace":"authentications remaining, change your password!", "proxyError":"Bad gateway: unable to join remote server", diff --git a/lemonldap-ng-portal/site/htdocs/static/languages/es.json b/lemonldap-ng-portal/site/htdocs/static/languages/es.json index d437c34db..e7f0005b9 100644 --- a/lemonldap-ng-portal/site/htdocs/static/languages/es.json +++ b/lemonldap-ng-portal/site/htdocs/static/languages/es.json @@ -228,6 +228,7 @@ "passwordPolicyMinUpper":"Mayúsculas, como mínimo:", "passwordPolicyMinDigit":"Dígitos, como mínimo:", "passwordPolicyMinSpeChar":"Minimal special characters:", +"passwordPolicyNone":"You are free to choose your password!", "passwordPolicySpecialChar":"Allowed special characters:", "ppGrace":"autenticaciones restantes, ¡cambie su contraseña!.", "proxyError":"Puerta de enlace no válida: servidor remoto inalcanzable", diff --git a/lemonldap-ng-portal/site/htdocs/static/languages/fi.json b/lemonldap-ng-portal/site/htdocs/static/languages/fi.json index baa406552..4f541555b 100644 --- a/lemonldap-ng-portal/site/htdocs/static/languages/fi.json +++ b/lemonldap-ng-portal/site/htdocs/static/languages/fi.json @@ -228,6 +228,7 @@ "passwordPolicyMinUpper":"Minimal upper characters:", "passwordPolicyMinDigit":"Minimal digit characters:", "passwordPolicyMinSpeChar":"Minimal special characters:", +"passwordPolicyNone":"You are free to choose your password!", "passwordPolicySpecialChar":"Allowed special characters:", "ppGrace":"authentications remaining, change your password!", "proxyError":"Bad gateway: unable to join remote server", diff --git a/lemonldap-ng-portal/site/htdocs/static/languages/fr.json b/lemonldap-ng-portal/site/htdocs/static/languages/fr.json index a13601570..8e4cd824e 100644 --- a/lemonldap-ng-portal/site/htdocs/static/languages/fr.json +++ b/lemonldap-ng-portal/site/htdocs/static/languages/fr.json @@ -228,6 +228,7 @@ "passwordPolicyMinUpper": "Minimum de majuscules :", "passwordPolicyMinDigit": "Minimum de chiffres :", "passwordPolicyMinSpeChar":"Minimum de caractères spéciaux :", +"passwordPolicyNone":"Vous êtes libre de choisir votre mot de passe !", "passwordPolicySpecialChar":"Caractères spéciaux autorisés :", "ppGrace": "authentifications restantes, changez votre mot de passe !", "proxyError": "Mauvaise passerelle : impossible de joindre le serveur amont", diff --git a/lemonldap-ng-portal/site/htdocs/static/languages/it.json b/lemonldap-ng-portal/site/htdocs/static/languages/it.json index aaf0b57b0..af2a55ac2 100644 --- a/lemonldap-ng-portal/site/htdocs/static/languages/it.json +++ b/lemonldap-ng-portal/site/htdocs/static/languages/it.json @@ -228,6 +228,7 @@ "passwordPolicyMinUpper":"Minimal upper characters:", "passwordPolicyMinDigit":"Minimal digit characters:", "passwordPolicyMinSpeChar":"Minimal special characters:", +"passwordPolicyNone":"You are free to choose your password!", "passwordPolicySpecialChar":"Allowed special characters:", "ppGrace":"autenticazioni restanti, modifica la tua password!", "proxyError":"Gateway errata: impossibile associarsi a un server remoto", diff --git a/lemonldap-ng-portal/site/htdocs/static/languages/nl.json b/lemonldap-ng-portal/site/htdocs/static/languages/nl.json index e289b5218..230ebfc05 100644 --- a/lemonldap-ng-portal/site/htdocs/static/languages/nl.json +++ b/lemonldap-ng-portal/site/htdocs/static/languages/nl.json @@ -228,6 +228,7 @@ "passwordPolicyMinUpper":"Minimal upper characters:", "passwordPolicyMinDigit":"Minimal digit characters:", "passwordPolicyMinSpeChar":"Minimal special characters:", +"passwordPolicyNone":"You are free to choose your password!", "passwordPolicySpecialChar":"Allowed special characters:", "ppGrace":"authentications remaining, change your password!", "proxyError":"Bad gateway: unable to join remote server", diff --git a/lemonldap-ng-portal/site/htdocs/static/languages/pt.json b/lemonldap-ng-portal/site/htdocs/static/languages/pt.json index 1296debcb..c7d64d37c 100644 --- a/lemonldap-ng-portal/site/htdocs/static/languages/pt.json +++ b/lemonldap-ng-portal/site/htdocs/static/languages/pt.json @@ -228,6 +228,7 @@ "passwordPolicyMinUpper":"Minimal upper characters:", "passwordPolicyMinDigit":"Minimal digit characters:", "passwordPolicyMinSpeChar":"Minimal special characters:", +"passwordPolicyNone":"You are free to choose your password!", "passwordPolicySpecialChar":"Allowed special characters:", "ppGrace":"authentications remaining, change your password!", "proxyError":"Bad gateway: unable to join remote server", diff --git a/lemonldap-ng-portal/site/htdocs/static/languages/ro.json b/lemonldap-ng-portal/site/htdocs/static/languages/ro.json index 241cdbd5f..25fdb79f8 100644 --- a/lemonldap-ng-portal/site/htdocs/static/languages/ro.json +++ b/lemonldap-ng-portal/site/htdocs/static/languages/ro.json @@ -228,6 +228,7 @@ "passwordPolicyMinUpper":"Minimal upper characters:", "passwordPolicyMinDigit":"Minimal digit characters:", "passwordPolicyMinSpeChar":"Minimal special characters:", +"passwordPolicyNone":"You are free to choose your password!", "passwordPolicySpecialChar":"Allowed special characters:", "ppGrace":"authentications remaining, change your password!", "proxyError":"Bad gateway: unable to join remote server", diff --git a/lemonldap-ng-portal/site/htdocs/static/languages/tr.json b/lemonldap-ng-portal/site/htdocs/static/languages/tr.json index 3c0484554..1078c3a36 100644 --- a/lemonldap-ng-portal/site/htdocs/static/languages/tr.json +++ b/lemonldap-ng-portal/site/htdocs/static/languages/tr.json @@ -229,6 +229,7 @@ "passwordPolicyMinUpper":"Minimum büyük harf karakter sayısı :", "passwordPolicyMinDigit":"Minimum rakam karakter sayısı :", "passwordPolicyMinSpeChar":"Minimal special characters:", +"passwordPolicyNone":"You are free to choose your password!", "passwordPolicySpecialChar":"Allowed special characters:", "ppGrace":"kimlik doğrulaması kaldı, parolanızı değiştirin!", "proxyError":"Kötü ağ geçidi: uzak sunucuya katılamıyor", diff --git a/lemonldap-ng-portal/site/htdocs/static/languages/vi.json b/lemonldap-ng-portal/site/htdocs/static/languages/vi.json index 13c35d45b..c3efd4986 100644 --- a/lemonldap-ng-portal/site/htdocs/static/languages/vi.json +++ b/lemonldap-ng-portal/site/htdocs/static/languages/vi.json @@ -228,6 +228,7 @@ "passwordPolicyMinUpper":"Minimal upper characters:", "passwordPolicyMinDigit":"Minimal digit characters:", "passwordPolicyMinSpeChar":"Minimal special characters:", +"passwordPolicyNone":"You are free to choose your password!", "passwordPolicySpecialChar":"Allowed special characters:", "ppGrace":"chứng thực vẫn còn, thay đổi mật khẩu của bạn!", "proxyError":"Gateway không chính xác: không thể kết nối máy chủ từ xa", diff --git a/lemonldap-ng-portal/site/htdocs/static/languages/zh.json b/lemonldap-ng-portal/site/htdocs/static/languages/zh.json index b6bffb441..f32bf96f5 100644 --- a/lemonldap-ng-portal/site/htdocs/static/languages/zh.json +++ b/lemonldap-ng-portal/site/htdocs/static/languages/zh.json @@ -228,6 +228,7 @@ "passwordPolicyMinUpper":"Minimal upper characters:", "passwordPolicyMinDigit":"Minimal digit characters:", "passwordPolicyMinSpeChar":"Minimal special characters:", +"passwordPolicyNone":"You are free to choose your password!", "passwordPolicySpecialChar":"Allowed special characters:", "ppGrace":"authentications remaining, change your password!", "proxyError":"错误的网关:无法连接远程服务器", diff --git a/lemonldap-ng-portal/site/templates/bootstrap/passwordpolicy.tpl b/lemonldap-ng-portal/site/templates/bootstrap/passwordpolicy.tpl index 561f02c35..9db1268b3 100644 --- a/lemonldap-ng-portal/site/templates/bootstrap/passwordpolicy.tpl +++ b/lemonldap-ng-portal/site/templates/bootstrap/passwordpolicy.tpl @@ -20,4 +20,7 @@
  • Allowed special characters:
  • + + You are free to choose your password! ;-) + diff --git a/lemonldap-ng-portal/t/02-Password-Demo-Local-noPpolicy.t b/lemonldap-ng-portal/t/02-Password-Demo-Local-noPpolicy.t new file mode 100644 index 000000000..388854a33 --- /dev/null +++ b/lemonldap-ng-portal/t/02-Password-Demo-Local-noPpolicy.t @@ -0,0 +1,62 @@ +use Test::More; +use strict; +use IO::String; +use JSON; +use Lemonldap::NG::Portal::Main::Constants qw( + PE_PP_PASSWORD_TOO_SHORT PE_PP_INSUFFICIENT_PASSWORD_QUALITY + PE_PP_NOT_ALLOWED_CHARACTER PE_PP_NOT_ALLOWED_CHARACTERS +); + +require 't/test-lib.pm'; + +my $res; + +my $client = LLNG::Manager::Test->new( { + ini => { + logLevel => 'error', + passwordDB => 'Demo', + portalRequireOldPassword => 1, + passwordPolicyMinSize => 0, + passwordPolicyMinLower => 0, + passwordPolicyMinUpper => 0, + passwordPolicyMinDigit => 0, + passwordPolicyMinSpeChar => 2, + passwordPolicySpecialChar => '', + portalDisplayPasswordPolicy => 1 + } + } +); + +# Try to authenticate +# ------------------- +ok( + $res = $client->_post( + '/', + IO::String->new('user=dwho&password=dwho'), + length => 23 + ), + 'Auth query' +); +count(1); +expectOK($res); +my $id = expectCookie($res); + +ok( + $res = + $client->_get( '/', cookie => "lemonldap=$id", accept => 'text/html' ), + 'Get Menu' +); +ok( $res->[2]->[0] =~ m%[2]->[0] ); +ok( $res->[2]->[0] =~ m%%, + ' passwordPolicyNone' ) + or print STDERR Dumper( $res->[2]->[0] ); +count(3); + +# Test $client->logout +$client->logout($id); + +clean_sessions(); + +done_testing( count() ); diff --git a/lemonldap-ng-portal/t/40-Notifications-JSON-Server.t b/lemonldap-ng-portal/t/40-Notifications-JSON-Server.t index 807b848a3..92cd9c19e 100644 --- a/lemonldap-ng-portal/t/40-Notifications-JSON-Server.t +++ b/lemonldap-ng-portal/t/40-Notifications-JSON-Server.t @@ -41,7 +41,7 @@ my $jsonbis = '{ my $json2 = q%{ "date": "2016-05-30", -"reference": "testref2", +"reference": "test_ref2", "uid": "dwho", "title": "Test2 title", "text": "This is a second test text", @@ -187,7 +187,7 @@ ok( scalar @{ $json->{result} } == 3, 'Three notifications found' ) or print STDERR Dumper($json); foreach ( @{ $json->{result} } ) { - ok( $_->{reference} =~ /^testref/, "Reference \'$_->{reference}\' found" ) + ok( $_->{reference} =~ /^test-?ref/, "Reference \'$_->{reference}\' found" ) or print STDERR Dumper($json); ok( $_->{uid} =~ /^(dwho|everyone)$/, "UID \'$_->{uid}\' found" ) or print STDERR Dumper($json); @@ -204,7 +204,7 @@ ok( $res->[2]->[0] =~ /"result"\s*:\s*/, 'Result found' ) or print STDERR Dumper( $res->[2]->[0] ); ok( $res->[2]->[0] =~ /"reference":"testref"/, 'First notification found' ) or print STDERR Dumper( $res->[2]->[0] ); -ok( $res->[2]->[0] =~ /"reference":"testref2"/, 'Second notification found' ) +ok( $res->[2]->[0] =~ /"reference":"test-ref2"/, 'Second notification found' ) or print STDERR Dumper( $res->[2]->[0] ); ok( $res->[2]->[0] =~ /"reference":"testrefall"/, @@ -236,14 +236,14 @@ count(7); ok( $res = $client->_get( - '/notifications/dwho/testref2', + '/notifications/dwho/test-ref2', type => 'application/json', ), - 'List notification with reference "testref2"' + 'List notification with reference "test-ref2"' ); ok( $res->[2]->[0] =~ /"result"\s*:\s*/, 'Result found' ) or print STDERR Dumper( $res->[2]->[0] ); -ok( $res->[2]->[0] =~ /"reference"\s*:\s*"testref2"/, +ok( $res->[2]->[0] =~ /"reference"\s*:\s*"test-ref2"/, 'Notification reference found' ) or print STDERR Dumper( $res->[2]->[0] ); ok( $res->[2]->[0] =~ /"title"\s*:\s*"Test2 title"/, @@ -275,7 +275,7 @@ ok( ok( $res->[2]->[0] =~ /"error"\s*:\s*"Bad request"/, 'Bad method is refused' ); count(2); -foreach (qw(testrefall testref2)) { +foreach (qw(testrefall test-ref2)) { my $user = $_ eq 'testrefall' ? 'everyone' : 'dwho'; ok( $res = $client->_delete( diff --git a/lemonldap-ng-portal/t/40-Notifications-XML-Server.t b/lemonldap-ng-portal/t/40-Notifications-XML-Server.t index 9a77004e5..7425f7070 100644 --- a/lemonldap-ng-portal/t/40-Notifications-XML-Server.t +++ b/lemonldap-ng-portal/t/40-Notifications-XML-Server.t @@ -9,7 +9,7 @@ BEGIN { require 't/test-lib.pm'; } -my $maintests = 12; +my $maintests = 13; my $client; # Redefine LWP methods for tests @@ -63,7 +63,7 @@ my $combined = ' This is a test text I agree - + Test title Test subtitle This is a test text @@ -202,6 +202,11 @@ SKIP: { expectOK($res); $id = expectCookie($res); expectForm( $res, undef, '/notifback', 'reference1x1' ); + ok( + $res->[2]->[0] =~ + m%%, + 'Reference found' + ) or print STDERR Dumper( $res->[2]->[0] ); ok( $res->[2]->[0] =~ m%I agree%, diff --git a/lemonldap-ng-portal/t/68-ContextSwitching-with-Impersonation.t b/lemonldap-ng-portal/t/68-ContextSwitching-with-Impersonation.t new file mode 100644 index 000000000..b6fc7247a --- /dev/null +++ b/lemonldap-ng-portal/t/68-ContextSwitching-with-Impersonation.t @@ -0,0 +1,251 @@ +use Test::More; +use strict; +use IO::String; +use JSON; + +require 't/test-lib.pm'; + +my $res; +my $client = LLNG::Manager::Test->new( { + ini => { + logLevel => 'error', + authentication => 'Demo', + userDB => 'Same', + loginHistoryEnabled => 0, + portalMainLogo => 'common/logos/logo_llng_old.png', + requireToken => 0, + checkUser => 1, + securedCookie => 0, + https => 0, + checkUserDisplayPersistentInfo => 0, + checkUserDisplayEmptyValues => 0, + contextSwitchingRule => '$uid eq "dwho"', + contextSwitchingIdRule => '$uid ne "msmith"', + impersonationRule => '$uid ne "msmith"', + impersonationIdRule => '$uid ne "msmith"', + contextSwitchingStopWithLogout => 0, + } + } +); + +## Try to impersonate: rtyler -> dwho +ok( $res = $client->_get( '/', accept => 'text/html' ), 'Get Menu', ); +my ( $host, $url, $query ) = + expectForm( $res, '#', undef, 'user', 'password', 'spoofId' ); + +$query =~ s/user=/user=rtyler/; +$query =~ s/password=/password=rtyler/; +$query =~ s/spoofId=/spoofId=dwho/; + +ok( + $res = $client->_post( + '/', + IO::String->new($query), + length => length($query), + accept => 'text/html', + ), + 'Auth query' +); +count(2); +my $id = expectCookie($res); +expectRedirection( $res, 'http://auth.example.com/' ); + +# Get Menu +# ------------------------ +ok( + $res = $client->_get( + '/', + cookie => "lemonldap=$id", + accept => 'text/html' + ), + 'Get Menu', +); +expectOK($res); +ok( $res->[2]->[0] =~ m%Connected as dwho%, + 'Connected as dwho' ) + or print STDERR Dumper( $res->[2]->[0] ); +expectAuthenticatedAs( $res, 'dwho' ); +ok( + $res->[2]->[0] =~ + m%contextSwitching_ON%, + 'Connected as dwho' +) or print STDERR Dumper( $res->[2]->[0] ); +count(3); + +# ContextSwitching form: dwho -> rtyler +# ------------------------ +ok( + $res = $client->_get( + '/switchcontext', + cookie => "lemonldap=$id", + accept => 'text/html' + ), + 'ContextSwitching form: dwho -> rtyler', +); +( $host, $url, $query ) = + expectForm( $res, undef, '/switchcontext', 'spoofId' ); +ok( $res->[2]->[0] =~ m%%, + 'Found trspan="contextSwitching_ON"' ) + or explain( $res->[2]->[0], 'trspan="contextSwitching_ON"' ); +$query =~ s/spoofId=/spoofId=rtyler/; +ok( + $res = $client->_post( + '/switchcontext', + IO::String->new($query), + cookie => "lemonldap=$id", + length => length($query), + accept => 'text/html', + ), + 'POST switchcontext' +); + +# Refresh cookie value +my $id2 = expectCookie($res); +ok( + $res = $client->_get( + '/', + cookie => "lemonldap=$id2", + accept => 'text/html' + ), + 'Get Menu', +); +expectAuthenticatedAs( $res, 'rtyler' ); +ok( $res->[2]->[0] =~ m%%, + 'Found trspan="contextSwitching_OFF"' ) + or explain( $res->[2]->[0], 'trspan="contextSwitching_OFF"' ); +ok( + $res = $client->_get( + '/switchcontext', + cookie => "lemonldap=$id2", + accept => 'text/html' + ), + 'Stop context switching rtyler', +); +count(6); + +# Refresh cookie value +$id = expectCookie($res); + +# ContextSwitching form: dwho -> french +# ------------------------ +ok( + $res = $client->_get( + '/switchcontext', + cookie => "lemonldap=$id", + accept => 'text/html' + ), + 'ContextSwitching form: dwho -> french', +); +( $host, $url, $query ) = + expectForm( $res, undef, '/switchcontext', 'spoofId' ); +ok( $res->[2]->[0] =~ m%%, + 'Found trspan="contextSwitching_ON"' ) + or explain( $res->[2]->[0], 'trspan="contextSwitching_ON"' ); +$query =~ s/spoofId=/spoofId=french/; +ok( + $res = $client->_post( + '/switchcontext', + IO::String->new($query), + cookie => "lemonldap=$id", + length => length($query), + accept => 'text/html', + ), + 'POST switchcontext' +); + +# Refresh cookie value +$id2 = expectCookie($res); +ok( + $res = $client->_get( + '/', + cookie => "lemonldap=$id2", + accept => 'text/html' + ), + 'Get Menu', +); +expectAuthenticatedAs( $res, 'french' ); +ok( $res->[2]->[0] =~ m%%, + 'Found trspan="contextSwitching_OFF"' ) + or explain( $res->[2]->[0], 'trspan="contextSwitching_OFF"' ); +count(5); + +# CheckUser request +ok( + $res = $client->_get( + '/checkuser', cookie => "lemonldap=$id2", + ), + 'CheckUser form', +); +eval { $res = JSON::from_json( $res->[2]->[0] ) }; +ok( not($@), 'Content is JSON' ) + or explain( $res->[2]->[0], 'JSON content' ); +my @sessions_id = + map { $_->{key} =~ /_session_id$/ ? $_ : () } @{ $res->{ATTRIBUTES} }; +ok( $sessions_id[0]->{value} eq $id, 'Good switching_id found' ) + or explain( $sessions_id[0]->{value}, 'Switching_session_id' ); +ok( $sessions_id[1]->{value} eq $id, 'Good Real_session_id found' ) + or explain( $sessions_id[1]->{value}, 'Real_session_id' ); +count(4); + +ok( + $res = $client->_get( + '/switchcontext', + cookie => "lemonldap=$id2", + accept => 'text/html' + ), + 'Stop context switching french', +); + +# Refresh cookie value +$id = expectCookie($res); +ok( + $res = $client->_get( + '/', + cookie => "lemonldap=$id", + accept => 'text/html' + ), + 'Get Menu', +); +expectAuthenticatedAs( $res, 'dwho' ); +ok( $res->[2]->[0] =~ m%%, + 'Found trspan="contextSwitching_ON"' ) + or explain( $res->[2]->[0], 'trspan="contextSwitching_ON"' ); + +# CheckUser request +ok( + $res = $client->_get( + '/checkuser', cookie => "lemonldap=$id", + ), + 'CheckUser form', +); +eval { $res = JSON::from_json( $res->[2]->[0] ) }; +ok( not($@), 'Content is JSON' ) + or explain( $res->[2]->[0], 'JSON content' ); +@sessions_id = + map { $_->{key} =~ /_session_id$/ ? $_ : () } @{ $res->{ATTRIBUTES} }; +ok( $sessions_id[0]->{value} eq $id, 'Good switching_id found' ) + or explain( $sessions_id[0]->{value}, 'Switching_session_id' ); +count(6); + +# Log out request -> dwho +# ------------------------ +ok( + $res = $client->_get( + '/', + query => 'logout=1', + cookie => "lemonldap=$id", + accept => 'text/html' + ), + 'Get Menu', +); +expectOK($res); +ok( + $res->[2]->[0] =~ + m%
    %, + 'Dwho has been well disconnected' +) or print STDERR Dumper( $res->[2]->[0] ); +count(2); + +clean_sessions(); + +done_testing( count() ); diff --git a/lemonldap-ng-portal/t/68-ContextSwitching-with-Logout.t b/lemonldap-ng-portal/t/68-ContextSwitching-with-Logout.t index 5a71b1d4c..6d4bf64a8 100644 --- a/lemonldap-ng-portal/t/68-ContextSwitching-with-Logout.t +++ b/lemonldap-ng-portal/t/68-ContextSwitching-with-Logout.t @@ -1,6 +1,7 @@ use Test::More; use strict; use IO::String; +use JSON; BEGIN { require 't/test-lib.pm'; @@ -13,19 +14,19 @@ my $client = LLNG::Manager::Test->new( { logLevel => 'error', authentication => 'Demo', userDB => 'Same', + https => 0, loginHistoryEnabled => 0, brutForceProtection => 0, portalMainLogo => 'common/logos/logo_llng_old.png', requireToken => 1, checkUser => 1, - impersonationPrefix => 'testPrefix_', securedCookie => 0, - https => 0, checkUserDisplayPersistentInfo => 0, checkUserDisplayEmptyValues => 0, contextSwitchingRule => 1, contextSwitchingIdRule => 1, contextSwitchingStopWithLogout => 1, + contextSwitchingPrefix => 'testPrefix_', } } ); @@ -109,7 +110,7 @@ ok( ); ok( $res->[2]->[0] =~ -m%
    %, + m%
    %, 'Found ""' ) or explain( $res->[2]->[0], '' ); count(3); @@ -147,12 +148,12 @@ ok( ok( $res->[2]->[0] =~ m%%, 'Found trspan="contextSwitching_OFF"' ) or explain( $res->[2]->[0], 'trspan="contextSwitching_OFF"' ); -$id = expectCookie($res); +my $id2 = expectCookie($res); ok( $res = $client->_get( '/', - cookie => "lemonldap=$id", + cookie => "lemonldap=$id2", accept => 'text/html' ), 'Get Menu', @@ -165,7 +166,7 @@ ok( $res->[2]->[0] =~ m%%, ok( $res = $client->_get( '/checkuser', - cookie => "lemonldap=$id", + cookie => "lemonldap=$id2", accept => 'text/html' ), 'CheckUser form', @@ -187,12 +188,27 @@ ok( $res->[2]->[0] =~ m%testPrefix__session_id%, or explain( $res->[2]->[0], 'Spoofed _id_session' ); count(5); +ok( + $res = $client->_get( + '/checkuser', cookie => "lemonldap=$id2", + ), + 'CheckUser form', +); +eval { $res = JSON::from_json( $res->[2]->[0] ) }; +ok( not($@), 'Content is JSON' ) + or explain( $res->[2]->[0], 'JSON content' ); +my @switching_id = map { $_->{key} eq 'testPrefix__session_id' ? $_ : () } + @{ $res->{ATTRIBUTES} }; +ok( $switching_id[0]->{value} eq $id, 'Good switching_id found' ) + or explain( $switching_id[0]->{value}, 'Switching_id' ); +count(3); + # Stop ContextSwitching # ------------------------ ok( $res = $client->_get( '/switchcontext', - cookie => "lemonldap=$id", + cookie => "lemonldap=$id2", accept => 'text/html' ), 'Stop context switching', diff --git a/lemonldap-ng-portal/t/68-ContextSwitching.t b/lemonldap-ng-portal/t/68-ContextSwitching.t index ef870c175..b5faa75d4 100644 --- a/lemonldap-ng-portal/t/68-ContextSwitching.t +++ b/lemonldap-ng-portal/t/68-ContextSwitching.t @@ -14,7 +14,6 @@ my $client = LLNG::Manager::Test->new( { portalMainLogo => 'common/logos/logo_llng_old.png', requireToken => 0, checkUser => 0, - impersonationPrefix => 'testPrefix_', securedCookie => 0, https => 0, checkUserDisplayPersistentInfo => 0, diff --git a/lemonldap-ng-portal/t/70-2F-TOTP-with-TTL-and-JSON.t b/lemonldap-ng-portal/t/70-2F-TOTP-with-TTL-and-JSON.t index b36bf7184..486b44e61 100644 --- a/lemonldap-ng-portal/t/70-2F-TOTP-with-TTL-and-JSON.t +++ b/lemonldap-ng-portal/t/70-2F-TOTP-with-TTL-and-JSON.t @@ -20,7 +20,7 @@ SKIP: { totp2fTTL => 120, sfRemovedMsgRule => '$uid eq "dwho"', sfRemovedUseNotif => 1, - sfRemovedNotifRef => 'RemoveTOTP', + sfRemovedNotifRef => 'Remov_e_TOTP', portalMainLogo => 'common/logos/logo_llng_old.png', notification => 1, notificationStorage => 'File', @@ -146,7 +146,7 @@ SKIP: { expectOK($res); ok( $res->[2]->[0] =~ -qr%%, +qr%%, 'Notification reference found' ) or print STDERR Dumper( $res->[2]->[0] ); ok( time() + 300 <= $1 && $1 <= time() + 305, 'Right reference found' ) diff --git a/lemonldap-ng-portal/t/70-2F-TOTP-with-TTL-and-XML.t b/lemonldap-ng-portal/t/70-2F-TOTP-with-TTL-and-XML.t index 927a08d0e..b1bcc99cf 100644 --- a/lemonldap-ng-portal/t/70-2F-TOTP-with-TTL-and-XML.t +++ b/lemonldap-ng-portal/t/70-2F-TOTP-with-TTL-and-XML.t @@ -24,7 +24,7 @@ SKIP: { totp2fTTL => 120, sfRemovedMsgRule => '$uid eq "dwho"', sfRemovedUseNotif => 1, - sfRemovedNotifRef => 'RemoveTOTP', + sfRemovedNotifRef => 'Remove_TOTP', portalMainLogo => 'common/logos/logo_llng_old.png', notification => 1, notificationStorage => 'File', @@ -150,7 +150,7 @@ SKIP: { expectOK($res); ok( $res->[2]->[0] =~ -qr%%, +qr%%, 'Notification reference found' ) or print STDERR Dumper( $res->[2]->[0] ); ok( time() + 300 <= $1 && $1 <= time() + 305, 'Right reference found' ) diff --git a/lemonldap-ng-portal/t/71-2F-U2F-with-TTL-and-msg.t b/lemonldap-ng-portal/t/71-2F-U2F-with-TTL-and-msg.t index 6e68cef10..2da741fc5 100644 --- a/lemonldap-ng-portal/t/71-2F-U2F-with-TTL-and-msg.t +++ b/lemonldap-ng-portal/t/71-2F-U2F-with-TTL-and-msg.t @@ -21,6 +21,8 @@ SKIP: { totp2fTTL => 120, u2fTTL => 120, sfRemovedMsgRule => 1, + sfRemovedUseNotif => 1, + notification => 0, } } );