Merge branch 'v2.0'

This commit is contained in:
Christophe Maudoux 2020-04-05 12:23:00 +02:00
commit 57f6a10a3e
35 changed files with 442 additions and 73 deletions

View File

@ -41,6 +41,7 @@ sub defaultValues {
'checkXSS' => 1,
'confirmFormMethod' => 'post',
'contextSwitchingIdRule' => 1,
'contextSwitchingPrefix' => 'switching',
'contextSwitchingRule' => 0,
'contextSwitchingStopWithLogout' => 1,
'cookieName' => 'lemonldap',

View File

@ -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)) {

View File

@ -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)) {

View File

@ -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

View File

@ -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'

View File

@ -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,

View File

@ -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;

View File

@ -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} );

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 );
}

View File

@ -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":"بوابة سيئة: غير قادر على الانضمام لالخادم البعيد",

View File

@ -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",

View File

@ -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",

View File

@ -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",

View File

@ -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",

View File

@ -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",

View File

@ -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",

View File

@ -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",

View File

@ -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",

View File

@ -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",

View File

@ -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",

View File

@ -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",

View File

@ -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":"错误的网关:无法连接远程服务器",

View File

@ -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>

View 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() );

View File

@ -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(

View File

@ -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>%,

View 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() );

View File

@ -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',

View File

@ -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,

View File

@ -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' )

View File

@ -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' )

View File

@ -21,6 +21,8 @@ SKIP: {
totp2fTTL => 120,
u2fTTL => 120,
sfRemovedMsgRule => 1,
sfRemovedUseNotif => 1,
notification => 0,
}
}
);