Merge branch 'v2.0'
This commit is contained in:
commit
57f6a10a3e
|
@ -41,6 +41,7 @@ sub defaultValues {
|
|||
'checkXSS' => 1,
|
||||
'confirmFormMethod' => 'post',
|
||||
'contextSwitchingIdRule' => 1,
|
||||
'contextSwitchingPrefix' => 'switching',
|
||||
'contextSwitchingRule' => 0,
|
||||
'contextSwitchingStopWithLogout' => 1,
|
||||
'cookieName' => 'lemonldap',
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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} );
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
|
|
@ -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":"بوابة سيئة: غير قادر على الانضمام لالخادم البعيد",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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":"错误的网关:无法连接远程服务器",
|
||||
|
|
|
@ -20,4 +20,7 @@
|
|||
<li><span trspan="passwordPolicySpecialChar">Allowed special characters:</span> <TMPL_VAR NAME="PPOLICY_ALLOWEDSPECHAR"></li>
|
||||
</TMPL_IF>
|
||||
</ul>
|
||||
<TMPL_IF NAME="PPOLICY_NOPOLICY">
|
||||
<span trspan="passwordPolicyNone">You are free to choose your password! ;-)</span>
|
||||
</TMPL_IF>
|
||||
</div>
|
||||
|
|
62
lemonldap-ng-portal/t/02-Password-Demo-Local-noPpolicy.t
Normal file
62
lemonldap-ng-portal/t/02-Password-Demo-Local-noPpolicy.t
Normal file
|
@ -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%<input id="oldpassword" name="oldpassword"%,
|
||||
' Old password input' )
|
||||
or print STDERR Dumper( $res->[2]->[0] );
|
||||
ok( $res->[2]->[0] =~ m%<span trspan="passwordPolicyNone">%,
|
||||
' passwordPolicyNone' )
|
||||
or print STDERR Dumper( $res->[2]->[0] );
|
||||
count(3);
|
||||
|
||||
# Test $client->logout
|
||||
$client->logout($id);
|
||||
|
||||
clean_sessions();
|
||||
|
||||
done_testing( count() );
|
|
@ -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(
|
||||
|
|
|
@ -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 = '<?xml version="1.0" encoding="UTF-8"?>
|
|||
<text>This is a test text</text>
|
||||
<check>I agree</check>
|
||||
</notification>
|
||||
<notification uid="rtyler" date="2016-05-31" reference="ABC2">
|
||||
<notification uid="rtyler" date="2016-05-31" reference="AB_C_2">
|
||||
<title>Test title</title>
|
||||
<subtitle>Test subtitle</subtitle>
|
||||
<text>This is a test text</text>
|
||||
|
@ -202,6 +202,11 @@ SKIP: {
|
|||
expectOK($res);
|
||||
$id = expectCookie($res);
|
||||
expectForm( $res, undef, '/notifback', 'reference1x1' );
|
||||
ok(
|
||||
$res->[2]->[0] =~
|
||||
m%<input type="hidden" name="reference1x1" value="AB-C-2">%,
|
||||
'Reference found'
|
||||
) or print STDERR Dumper( $res->[2]->[0] );
|
||||
ok(
|
||||
$res->[2]->[0] =~
|
||||
m%<input type="checkbox" name="check1x1x1" id="check1x1x1" value="accepted">I agree</label>%,
|
||||
|
|
251
lemonldap-ng-portal/t/68-ContextSwitching-with-Impersonation.t
Normal file
251
lemonldap-ng-portal/t/68-ContextSwitching-with-Impersonation.t
Normal file
|
@ -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%<span trspan="connectedAs">Connected as</span> dwho%,
|
||||
'Connected as dwho' )
|
||||
or print STDERR Dumper( $res->[2]->[0] );
|
||||
expectAuthenticatedAs( $res, 'dwho' );
|
||||
ok(
|
||||
$res->[2]->[0] =~
|
||||
m%<span trspan="contextSwitching_ON">contextSwitching_ON</span>%,
|
||||
'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%<span trspan="contextSwitching_ON">%,
|
||||
'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%<span trspan="contextSwitching_OFF">%,
|
||||
'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%<span trspan="contextSwitching_ON">%,
|
||||
'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%<span trspan="contextSwitching_OFF">%,
|
||||
'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%<span trspan="contextSwitching_ON">%,
|
||||
'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%<div class="message message-positive alert"><span trmsg="47">%,
|
||||
'Dwho has been well disconnected'
|
||||
) or print STDERR Dumper( $res->[2]->[0] );
|
||||
count(2);
|
||||
|
||||
clean_sessions();
|
||||
|
||||
done_testing( count() );
|
|
@ -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%<div class="message message-negative alert"><span trmsg="82"></span>%,
|
||||
m%<div class="message message-negative alert"><span trmsg="82"></span>%,
|
||||
'Found "<span trmsg="82">"'
|
||||
) or explain( $res->[2]->[0], '<span trmsg="82">' );
|
||||
count(3);
|
||||
|
@ -147,12 +148,12 @@ ok(
|
|||
ok( $res->[2]->[0] =~ m%<span trspan="contextSwitching_OFF">%,
|
||||
'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%<span trspan="contextSwitching_OFF">%,
|
|||
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%<td scope="row">testPrefix__session_id</td>%,
|
|||
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',
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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%<input type="hidden" name="reference1x1" value="RemoveTOTP-(\d{10})">%,
|
||||
qr%<input type="hidden" name="reference1x1" value="Remov-e-TOTP-(\d{10})">%,
|
||||
'Notification reference found'
|
||||
) or print STDERR Dumper( $res->[2]->[0] );
|
||||
ok( time() + 300 <= $1 && $1 <= time() + 305, 'Right reference found' )
|
||||
|
|
|
@ -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%<input type="hidden" name="reference1x1" value="RemoveTOTP-(\d{10})">%,
|
||||
qr%<input type="hidden" name="reference1x1" value="Remove-TOTP-(\d{10})">%,
|
||||
'Notification reference found'
|
||||
) or print STDERR Dumper( $res->[2]->[0] );
|
||||
ok( time() + 300 <= $1 && $1 <= time() + 305, 'Right reference found' )
|
||||
|
|
|
@ -21,6 +21,8 @@ SKIP: {
|
|||
totp2fTTL => 120,
|
||||
u2fTTL => 120,
|
||||
sfRemovedMsgRule => 1,
|
||||
sfRemovedUseNotif => 1,
|
||||
notification => 0,
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue
Block a user