Merge branch 'v2.0'

This commit is contained in:
Xavier Guimard 2019-05-27 12:03:45 +02:00
commit 1509d44d5f
36 changed files with 509 additions and 179 deletions

View File

@ -37,12 +37,16 @@
# Note that Content-Security-Policy header is generated by portal itself
<Files *.fcgi>
SetHandler fcgid-script
# For Authorization header to be passed, please uncomment one of the following:
# for Apache >= 2.4.13
#CGIPassAuth On
# for Apache < 2.4.13
#RewriteCond %{HTTP:Authorization} ^(.*)
#RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]
# Authorization header needs to be passed when using Kerberos or OIDC
<IfVersion >= 2.4.13>
CGIPassAuth On
</IfVersion>
<IfVersion < 2.4.13>
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]
</IfVersion>
Options +ExecCGI
header unset Lm-Remote-User
</Files>

View File

@ -38,12 +38,16 @@
# Note that Content-Security-Policy header is generated by portal itself
<Files *.fcgi>
SetHandler fcgid-script
# For Authorization header to be passed, please uncomment one of the following:
# for Apache >= 2.4.13
#CGIPassAuth On
# for Apache < 2.4.13
#RewriteCond %{HTTP:Authorization} ^(.*)
#RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]
# Authorization header needs to be passed when using Kerberos or OIDC
<IfVersion >= 2.4.13>
CGIPassAuth On
</IfVersion>
<IfVersion < 2.4.13>
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]
</IfVersion>
Options +ExecCGI
header unset Lm-Remote-User
</Files>

View File

@ -33,12 +33,11 @@
# Note that Content-Security-Policy header is generated by portal itself
<Files *.fcgi>
SetHandler fcgid-script
# For Authorization header to be passed, please uncomment one of the following:
# for Apache >= 2.4.13
#CGIPassAuth On
# for Apache < 2.4.13
#RewriteCond %{HTTP:Authorization} ^(.*)
#RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]
# Authorization header needs to be passed when using Kerberos or OIDC
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]
Options +ExecCGI
header unset Lm-Remote-User
</Files>

View File

@ -324,6 +324,8 @@ status = 0
;useRedirectOnForbidden = 1
; Hide LemonLDAP::NG Handler in Apache Server Signature
;hideSignature = 1
; Set ServiceToken timeout
;handlerServiceTokenTTL = 30
useRedirectOnError = 1
; Zimbra Handler parameters

View File

@ -70,6 +70,7 @@ sub defaultValues {
'gpgDb' => '',
'groups' => {},
'handlerInternalCache' => 15,
'handlerServiceTokenTTL' => 30,
'hiddenAttributes' => '_password',
'httpOnly' => 1,
'https' => -1,

View File

@ -30,7 +30,7 @@ our $oidcOPMetaDataNodeKeys = 'oidcOPMetaData(?:Options(?:C(?:lient(?:Secret|ID)
our $oidcRPMetaDataNodeKeys = 'oidcRPMetaData(?:Options(?:I(?:DToken(?:Expiration|SignAlg)|con)|Logout(?:SessionRequired|Type|Url)|R(?:e(?:directUris|quirePKCE)|ule)|P(?:ostLogoutRedirectUris|ublic)|AccessTokenExpiration|Client(?:Secret|ID)|BypassConsent|DisplayName|ExtraClaims|UserIDAttr)|ExportedVars)';
our $samlIDPMetaDataNodeKeys = 'samlIDPMetaData(?:Options(?:(?:Check(?:S[LS]OMessageSignatur|Audienc|Tim)|EncryptionMod|UserAttribut|DisplayNam)e|S(?:ignS[LS]OMessage|toreSAMLToken|[LS]OBinding|ortNumber)|A(?:llow(?:LoginFromIDP|ProxiedAuthn)|daptSessionUtime)|Re(?:questedAuthnContext|solutionRule|layStateURL)|Force(?:Authn|UTF8)|I(?:sPassive|con)|NameIDFormat)|ExportedAttributes|XML)';
our $samlSPMetaDataNodeKeys = 'samlSPMetaData(?:Options(?:N(?:ameID(?:SessionKey|Format)|otOnOrAfterTimeout)|S(?:essionNotOnOrAfterTimeout|ignS[LS]OMessage)|(?:CheckS[LS]OMessageSignatur|OneTimeUs|Rul)e|En(?:ableIDPInitiatedURL|cryptionMode)|ForceUTF8)|ExportedAttributes|XML)';
our $virtualHostKeys = '(?:vhost(?:A(?:uthnLevel|liases)|(?:Maintenanc|Typ)e|Https|Port)|(?:exportedHeader|locationRule)s|post)';
our $virtualHostKeys = '(?:vhost(?:A(?:uthnLevel|liases)|(?:Maintenanc|Typ)e|ServiceTokenTTL|Https|Port)|(?:exportedHeader|locationRule)s|post)';
our $authParameters = {
adParams => [qw(ADPwdMaxAge ADPwdExpireWarning)],

View File

@ -1,6 +1,7 @@
package Lemonldap::NG::Handler::Lib::ServiceToken;
use strict;
use Data::Dumper;
our $VERSION = '2.1.0';
@ -23,19 +24,22 @@ sub fetchId {
return 0;
}
# Is token in good interval ?
unless ( $t <= time and $t > time - 30 ) {
$class->userLogger->warn('Expired service token');
return 0;
}
# Is vhost listed in token ?
my $vh = $class->resolveAlias($req);
unless ( grep { $_ eq $vh } @vhosts ) {
$class->userLogger->error(
"$vh not authorizated in token (" . join( ', ', @vhosts ) . ')' );
"$vh not authorized in token (" . join( ', ', @vhosts ) . ')' );
return 0;
}
# Is token in good interval ?
my $localConfig = $class->localConfig;
my $ttl = $localConfig->{vhostOptions}->{$vh}->{vhostServiceTokenTTL} || $class->tsv->{handlerServiceTokenTTL};
unless ( $t <= time and $t > time - $ttl ) {
$class->userLogger->warn('Expired service token');
return 0;
}
return $_session_id;
}

View File

@ -197,6 +197,7 @@ sub defaultValuesInit {
securedCookie timeout timeoutActivity
timeoutActivityInterval useRedirectOnError useRedirectOnForbidden
useSafeJail whatToTrace handlerInternalCache
handlerServiceTokenTTL
)
);

View File

@ -4,13 +4,31 @@ BEGIN {
require 't/test-psgi-lib.pm';
}
init('Lemonldap::NG::Handler::Server');
init(
'Lemonldap::NG::Handler::Server',
{
logLevel => 'error',
handlerServiceTokenTTL => 2,
vhostOptions => {
'test1.example.com' => {
vhostHttps => 0,
vhostPort => 80,
vhostMaintenance => 0,
vhostServiceTokenTTL => 3,
},
'test2.example.com' => {
vhostHttps => 0,
vhostPort => 80,
vhostMaintenance => 0,
vhostServiceTokenTTL => 5,
}
},
}
);
my $res;
my $crypt = Lemonldap::NG::Common::Crypto->new('qwertyui');
my $token = $crypt->encrypt( join ':', time, $sessionId, 'test1.example.com' );
my $token = $crypt->encrypt( join ':', time, $sessionId, 'test1.example.com', 'test2.example.com' );
ok(
$res = $client->_get(
@ -23,6 +41,81 @@ ok(
ok( $res->[0] == 200, 'Code is 200' ) or explain( $res->[0], 200 );
count(2);
sleep 2;
ok(
$res = $client->_get(
'/', undef, 'test1.example.com', undef,
VHOSTTYPE => 'ServiceToken',
'HTTP_X_LLNG_TOKEN' => $token,
),
'Query with token'
);
ok( $res->[0] == 200, 'Code is 200' ) or explain( $res->[0], 200 );
count(2);
sleep 1;
ok(
$res = $client->_get(
'/', undef, 'test1.example.com', undef,
VHOSTTYPE => 'ServiceToken',
'HTTP_X_LLNG_TOKEN' => $token,
),
'Query with token'
);
ok( $res->[0] == 302, 'Code is 200' ) or explain( $res->[0], 302 );
count(2);
sleep 1;
ok(
$res = $client->_get(
'/', undef, 'test2.example.com', undef,
VHOSTTYPE => 'ServiceToken',
'HTTP_X_LLNG_TOKEN' => $token,
),
'Query with token'
);
ok( $res->[0] == 200, 'Code is 200' ) or explain( $res->[0], 200 );
count(2);
sleep 1;
ok(
$res = $client->_get(
'/', undef, 'test2.example.com', undef,
VHOSTTYPE => 'ServiceToken',
'HTTP_X_LLNG_TOKEN' => $token,
),
'Query with token'
);
ok( $res->[0] == 302, 'Code is 302' ) or explain( $res->[0], 302 );
count(2);
ok(
$res = $client->_get(
'/', undef, 'test3.example.com', undef,
VHOSTTYPE => 'ServiceToken',
'HTTP_X_LLNG_TOKEN' => $token,
),
'Query with token'
);
ok( $res->[0] == 302, 'Code is 302' ) or explain( $res->[0], 302 );
count(2);
$token = $crypt->encrypt( join ':', time, $sessionId, '' );
ok(
$res = $client->_get(
'/', undef, 'test2.example.com', undef,
VHOSTTYPE => 'ServiceToken',
'HTTP_X_LLNG_TOKEN' => $token,
),
'Query with token'
);
ok( $res->[0] == 302, 'Code is 302' ) or explain( $res->[0], 302 );
count(2);
done_testing( count() );
clean();

View File

@ -1215,6 +1215,10 @@ qr/^(?:\*\.)?(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][
'default' => 15,
'type' => 'int'
},
'handlerServiceTokenTTL' => {
'default' => 30,
'type' => 'int'
},
'hiddenAttributes' => {
'default' => '_password',
'type' => 'text'
@ -3564,6 +3568,10 @@ qr/^(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-
'default' => -1,
'type' => 'int'
},
'vhostServiceTokenTTL' => {
'default' => 30,
'type' => 'int'
},
'vhostType' => {
'default' => 'Main',
'select' => [ {

View File

@ -505,7 +505,12 @@ sub attributes {
documentation => 'Handler internal cache timeout',
flags => 'hp',
},
handlerServiceTokenTTL => {
type => 'int',
default => 30,
documentation => 'Handler ServiceToken timeout',
flags => 'hp',
},
# Loggers (ini only)
logLevel => {
type => 'text',
@ -1703,6 +1708,10 @@ sub attributes {
type => 'bool',
default => 0,
},
vhostServiceTokenTTL => {
type => 'int',
default => 30,
},
vhostAliases => { type => 'text', },
vhostType => {
type => 'select',

View File

@ -30,6 +30,7 @@ sub cTrees {
'vhostPort', 'vhostHttps',
'vhostMaintenance', 'vhostAliases',
'vhostType', 'vhostAuthnLevel',
'vhostServiceTokenTTL'
],
},
],

View File

@ -1203,6 +1203,13 @@ function templates(tpl,key) {
"id" : tpl+"s/"+key+"/"+"vhostAuthnLevel",
"title" : "vhostAuthnLevel",
"type" : "int"
},
{
"default" : 30,
"get" : tpl+"s/"+key+"/"+"vhostServiceTokenTTL",
"id" : tpl+"s/"+key+"/"+"vhostServiceTokenTTL",
"title" : "vhostServiceTokenTTL",
"type" : "int"
}
],
"help" : "configvhost.html#options",

File diff suppressed because one or more lines are too long

View File

@ -830,6 +830,7 @@
"vhostMaintenance":"وضع الصيانة",
"vhostOptions":"الخيارات",
"vhostPort":"المنفذ",
"vhostServiceTokenTTL":"ServiceToken timeout",
"vhostType":"نوع",
"view":"عرض",
"viewer":"Viewer",

View File

@ -830,6 +830,7 @@
"vhostMaintenance":"Maintenance mode",
"vhostOptions":"Options",
"vhostPort":"Port",
"vhostServiceTokenTTL":"ServiceToken timeout",
"vhostType":"Type",
"view":"View",
"viewer":"Viewer",

View File

@ -830,6 +830,7 @@
"vhostMaintenance":"Maintenance mode",
"vhostOptions":"Options",
"vhostPort":"Port",
"vhostServiceTokenTTL":"ServiceToken timeout",
"vhostType":"Type",
"view":"View",
"viewer":"Viewer",

View File

@ -830,6 +830,7 @@
"vhostMaintenance":"Mode maintenance",
"vhostOptions":"Options",
"vhostPort":"Port",
"vhostServiceTokenTTL":"Durée de validité du ServiceToken",
"vhostType":"Type",
"view":"Aperçu",
"viewer":"Explorateur",

View File

@ -830,6 +830,7 @@
"vhostMaintenance":"Modalità di manutenzione",
"vhostOptions":"Opzioni",
"vhostPort":"Porta",
"vhostServiceTokenTTL":"ServiceToken timeout",
"vhostType":"Typo",
"view":"Visualizzazione",
"viewer":"Viewer",

View File

@ -830,6 +830,7 @@
"vhostMaintenance":"Chế độ bảo trì",
"vhostOptions":"Tùy chọn",
"vhostPort":"Port",
"vhostServiceTokenTTL":"ServiceToken timeout",
"vhostType":"Loại",
"view":"Khung nhìn",
"viewer":"Viewer",

View File

@ -830,6 +830,7 @@
"vhostMaintenance":"Maintenance mode",
"vhostOptions":"Options",
"vhostPort":"Port",
"vhostServiceTokenTTL":"ServiceToken timeout",
"vhostType":"Type",
"view":"View",
"viewer":"Viewer",

View File

@ -54,7 +54,7 @@ my @notManagedAttributes = (
# Other ini-only prms
'configStorage', 'status', 'localStorageOptions', 'localStorage',
'max2FDevices', 'max2FDevicesNameLength', 'checkTime',
'mySessionAuthorizedRWKeys', 'handlerInternalCache'
'mySessionAuthorizedRWKeys', 'handlerInternalCache', 'handlerServiceTokenTTL'
);
# Words used either as attribute name and node title

View File

@ -105,6 +105,12 @@ ok( @unTr == 0,
'All "trspan" attribute translated' . ( @unTr ? " (@unTr)" : "" ) );
$count += 3;
# Check for flag icons
foreach my $lang (@langs) {
ok( -f "site/htdocs/static/logos/$lang.png", "Flag icon found for $lang" );
$count += 1;
}
done_testing($count);
sub getNodes {

View File

@ -434,6 +434,8 @@ sub store {
# Create second session for unsecure cookie
if ( $self->conf->{securedCookie} == 2 and !$req->refresh() ) {
my %infos = %{ $req->{sessionInfo} };
$infos{_updateTime} = strftime( "%Y%m%d%H%M%S", localtime() );
$self->logger->debug( "Set _updateTime with $infos{_updateTime}" );
$infos{_httpSessionType} = 1;
my $session2 = $self->getApacheSession( undef, info => \%infos );

View File

@ -153,6 +153,8 @@ sub refresh {
foreach ( keys %data ) {
delete $data{$_} unless ( /^_/ or /^(?:startTime)$/ );
}
$data{_updateTime} = strftime( "%Y%m%d%H%M%S", localtime() );
$self->logger->debug( "Set session $req->{id} _updateTime with $data{_updateTime}" );
$req->steps( [
'getUser',
@{ $self->betweenAuthAndData },

Binary file not shown.

After

Width:  |  Height:  |  Size: 321 B

View File

@ -0,0 +1,222 @@
use Test::More;
use strict;
use IO::String;
BEGIN {
require 't/test-lib.pm';
}
my $res;
my $client = LLNG::Manager::Test->new( {
ini => {
logLevel => 'error',
authentication => 'Demo',
userDB => 'Same',
loginHistoryEnabled => 0,
brutForceProtection => 0,
portalMainLogo => 'common/logos/logo_llng_old.png',
requireToken => 0,
securedCookie => 2,
https => 0,
checkUser => 1,
handlerInternalCache => 0,
}
}
);
## Try to authenticate
ok( $res = $client->_get( '/', accept => 'text/html' ), 'Get Menu', );
count(1);
my ( $host, $url, $query ) = expectForm( $res, '#', undef, 'user', 'password' );
$query =~ s/user=/user=dwho/;
$query =~ s/password=/password=dwho/;
ok(
$res = $client->_post(
'/',
IO::String->new($query),
length => length($query),
accept => 'text/html',
),
'Auth query'
);
count(1);
my $id1 = expectCookie($res);
my $id2 = expectCookie( $res, 'lemonldaphttp' );
# Check lemonldap Cookie
ok( $id1 =~ /^\w{64}$/, " -> Get cookie : lemonldap=something" )
or explain( $res->[1], "Set-Cookie: lemonldap=$id1" );
ok( ${ $res->[1] }[3] =~ /HttpOnly=1/, " -> Cookie 'lemonldap' is HttpOnly" )
or explain( $res->[1] );
ok( ${ $res->[1] }[3] =~ /secure/, " -> Cookie 'lemonldap' is secure" )
or explain( $res->[1] );
count(3);
# Check lemonldaphttp Cookie
ok( $id2 =~ /^\w{64}$/, " -> Get cookie lemonldaphttp=something" )
or explain( $res->[1], "Set-Cookie: lemonldaphttp=$id2" );
ok(
${ $res->[1] }[5] =~ /HttpOnly=1/,
" -> Cookie 'lemonldaphttp' is HttpOnly"
) or explain( $res->[1] );
ok( ${ $res->[1] }[5] !~ /secure/, " -> Cookie 'lemonldaphttp' is NOT secure" )
or explain( $res->[1] );
count(3);
my $nbr = count_sessions();
ok( $nbr == 2, " -> Doule Cookies for two sessions found" )
or explain("Number of session(s) found = $nbr");
count(1);
expectRedirection( $res, 'http://auth.example.com/' );
# Get Menu
# ------------------------
ok(
$res = $client->_get(
'/',
cookie => "lemonldap=$id1,lemonldaphttp=$id2",
accept => 'text/html'
),
'Get Menu',
);
count(1);
expectOK($res);
ok( $res->[2]->[0] =~ m%<span trspan="connectedAs">Connected as</span> dwho%,
'Connected as Dwho' )
or print STDERR Dumper( $res->[2]->[0] );
count(1);
# CheckUser form
# ------------------------
ok(
$res = $client->_get(
'/checkuser',
cookie => "lemonldap=$id1,lemonldaphttp=$id2",
accept => 'text/html'
),
'CheckUser form',
);
count(1);
( $host, $url, $query ) =
expectForm( $res, undef, '/checkuser', 'user', 'url' );
ok( $res->[2]->[0] =~ m%<span trspan="checkUser">%, 'Found trspan="checkUser"' )
or explain( $res->[2]->[0], 'trspan="checkUser"' );
count(1);
ok(
$res = $client->_post(
'/checkuser',
IO::String->new($query),
cookie => "lemonldap=$id1,lemonldaphttp=$id2",
length => length($query),
accept => 'text/html',
),
'POST checkuser'
);
my @attributes = map /<td class="text-left">(.+)?<\/td>/g, $res->[2]->[0];
ok( scalar @attributes == 30, 'Found 30 attributes' )
or print STDERR "Missing attributes -> " . scalar @attributes;
ok( $attributes[12] eq '_updateTime', '_updateTime' )
or print STDERR Dumper( \@attributes );
ok( $attributes[13] =~ /^\d{14}$/, 'Timestamp found' )
or print STDERR Dumper( \@attributes );
count(4);
sleep 3;
# Refresh rights
# ------------------------
ok(
$res = $client->_get(
'/refresh',
cookie => "lemonldap=$id1,lemonldaphttp=$id2",
accept => 'text/html'
),
'Refresh query',
);
count(1);
expectRedirection( $res, 'http://auth.example.com/' );
# Get Menu
# ------------------------
ok(
$res = $client->_get(
'/',
cookie => "lemonldap=$id1,lemonldaphttp=$id2",
accept => 'text/html'
),
'Get Menu',
);
count(1);
expectOK($res);
ok( $res->[2]->[0] =~ m%<span trspan="connectedAs">Connected as</span> dwho%,
'Connected as Dwho' )
or print STDERR Dumper( $res->[2]->[0] );
count(1);
# CheckUser form
# ------------------------
ok(
$res = $client->_get(
'/checkuser',
cookie => "lemonldap=$id1,lemonldaphttp=$id2",
accept => 'text/html'
),
'CheckUser form',
);
count(1);
( $host, $url, $query ) =
expectForm( $res, undef, '/checkuser', 'user', 'url' );
ok( $res->[2]->[0] =~ m%<span trspan="checkUser">%, 'Found trspan="checkUser"' )
or explain( $res->[2]->[0], 'trspan="checkUser"' );
count(1);
ok(
$res = $client->_post(
'/checkuser',
IO::String->new($query),
cookie => "lemonldap=$id1,lemonldaphttp=$id2",
length => length($query),
accept => 'text/html',
),
'POST checkuser'
);
my @attributes2 = map /<td class="text-left">(.+)?<\/td>/g, $res->[2]->[0];
ok( scalar @attributes2 == 30, 'Found 30 attributes' )
or print STDERR "Missing attributes -> " . scalar @attributes2;
ok( $attributes2[12] eq '_updateTime', '_updateTime' )
or print STDERR Dumper( \@attributes2 );
ok( $attributes2[13] =~ /^\d{14}$/, 'Timestamp found' )
or print STDERR Dumper( \@attributes2 );
count(4);
ok( $attributes2[13] - $attributes[13] >= 3, '_updateTime has been updated' )
or print STDERR Dumper( \@attributes2 );
count(1);
# Log out request
# ------------------------
ok(
$res = $client->_get(
'/',
query => 'logout=1',
cookie => "lemonldap=$id1,lemonldaphttp=$id2",
accept => 'text/html'
),
'Get Menu',
);
count(1);
expectOK($res);
ok(
$res->[2]->[0] =~
m%<div class="message message-positive alert"><span trmsg="47"></span></div>%,
'Dwho has been well disconnected'
) or print STDERR Dumper( $res->[2]->[0] );
count(1);
clean_sessions();
done_testing( count() );

View File

@ -139,8 +139,30 @@ ok(
count(1);
my $id = expectCookie($res);
my $id2 = expectCookie( $res, 'lemonldaphttp' );
expectRedirection( $res, 'http://auth.example.com/' );
# Check lemonldap Cookie
ok( $id =~ /^\w{64}$/, " -> Get cookie : lemonldap=something" )
or explain( $res->[1], "Set-Cookie: lemonldap=$id" );
ok( ${ $res->[1] }[3] =~ /HttpOnly=1/, " -> Cookie 'lemonldap' is HttpOnly" )
or explain( $res->[1] );
ok( ${ $res->[1] }[3] =~ /secure/, " -> Cookie 'lemonldap' is secure" )
or explain( $res->[1] );
count(3);
# ????????
# # Check lemonldaphttp Cookie
# ok( $id2 =~ /^\w{64}$/, " -> Get cookie lemonldaphttp=something" )
# or explain( $res->[1], "Set-Cookie: lemonldaphttp=$id2" );
# ok(
# ${ $res->[1] }[5] =~ /HttpOnly=1/,
# " -> Cookie 'lemonldaphttp' is HttpOnly"
# ) or explain( $res->[1] );
# ok( ${ $res->[1] }[5] !~ /secure/, " -> Cookie 'lemonldaphttp' is NOT secure" )
# or explain( $res->[1] );
# count(3);
# CheckUser form
# ------------------------
ok(
@ -203,6 +225,25 @@ count(1);
$id = expectCookie($res);
expectRedirection( $res, 'http://auth.example.com/' );
# Get Menu
# ------------------------
ok(
$res = $client->_get(
'/',
cookie => "lemonldap=$id",
accept => 'text/html'
),
'Get Menu',
);
count(1);
expectOK($res);
ok(
$res->[2]->[0] =~
m%<span trspan="connectedAs">Connected as</span> dwho%,
'Connected as dwho'
) or print STDERR Dumper( $res->[2]->[0] );
count(1);
# CheckUser form
# ------------------------
ok(

View File

@ -49,6 +49,25 @@ count(1);
my $id = expectCookie($res);
expectRedirection( $res, 'http://auth.example.com/' );
# Get Menu
# ------------------------
ok(
$res = $client->_get(
'/',
cookie => "lemonldap=$id",
accept => 'text/html'
),
'Get Menu',
);
count(1);
expectOK($res);
ok(
$res->[2]->[0] =~
m%<span trspan="connectedAs">Connected as</span> dwho%,
'Connected as dwho'
) or print STDERR Dumper( $res->[2]->[0] );
count(1);
# CheckUser form
# ------------------------
ok(

View File

@ -141,6 +141,25 @@ count(1);
my $id = expectCookie($res);
expectRedirection( $res, 'http://auth.example.com/' );
# Get Menu
# ------------------------
ok(
$res = $client->_get(
'/',
cookie => "lemonldap=$id",
accept => 'text/html'
),
'Get Menu',
);
count(1);
expectOK($res);
ok(
$res->[2]->[0] =~
m%<span trspan="connectedAs">Connected as</span> msmith%,
'Connected as msmith'
) or print STDERR Dumper( $res->[2]->[0] );
count(1);
# CheckUser form
# ------------------------
ok(
@ -203,6 +222,25 @@ count(1);
$id = expectCookie($res);
expectRedirection( $res, 'http://auth.example.com/' );
# Get Menu
# ------------------------
ok(
$res = $client->_get(
'/',
cookie => "lemonldap=$id",
accept => 'text/html'
),
'Get Menu',
);
count(1);
expectOK($res);
ok(
$res->[2]->[0] =~
m%<span trspan="connectedAs">Connected as</span> dwho%,
'Connected as dwho'
) or print STDERR Dumper( $res->[2]->[0] );
count(1);
# CheckUser form
# ------------------------
ok(

View File

@ -1,146 +0,0 @@
use Test::More;
use strict;
use IO::String;
BEGIN {
require 't/test-lib.pm';
}
my $res;
my $client = LLNG::Manager::Test->new( {
ini => {
logLevel => 'error',
authentication => 'Demo',
userDB => 'Same',
loginHistoryEnabled => 0,
brutForceProtection => 0,
portalMainLogo => 'common/logos/logo_llng_old.png',
requireToken => 0,
securedCookie => 2,
https => 0,
}
}
);
## Try to authenticate
ok( $res = $client->_get( '/', accept => 'text/html' ), 'Get Menu', );
count(1);
my ( $host, $url, $query ) = expectForm( $res, '#', undef, 'user', 'password' );
$query =~ s/user=/user=dwho/;
$query =~ s/password=/password=dwho/;
ok(
$res = $client->_post(
'/',
IO::String->new($query),
length => length($query),
accept => 'text/html',
),
'Auth query'
);
count(1);
my $id1 = expectCookie($res);
my $id2 = expectCookie( $res, 'lemonldaphttp' );
# Check lemonldap Cookie
ok( $id1 =~ /^\w{64}$/, " -> Get cookie : lemonldap=something" )
or explain( $res->[1], "Set-Cookie: lemonldap=$id1" );
ok( ${ $res->[1] }[3] =~ /HttpOnly=1/, " -> Cookie 'lemonldap' is HttpOnly" )
or explain( $res->[1] );
ok( ${ $res->[1] }[3] =~ /secure/, " -> Cookie 'lemonldap' is secure" )
or explain( $res->[1] );
count(3);
# Check lemonldaphttp Cookie
ok( $id2 =~ /^\w{64}$/, " -> Get cookie lemonldaphttp=something" )
or explain( $res->[1], "Set-Cookie: lemonldaphttp=$id2" );
ok(
${ $res->[1] }[5] =~ /HttpOnly=1/,
" -> Cookie 'lemonldaphttp' is HttpOnly"
) or explain( $res->[1] );
ok( ${ $res->[1] }[5] !~ /secure/, " -> Cookie 'lemonldaphttp' is NOT secure" )
or explain( $res->[1] );
count(3);
my $nbr = count_sessions();
ok( $nbr == 2, " -> Doule Cookies for two sessions found" )
or explain("Number of session(s) found = $nbr");
count(1);
expectRedirection( $res, 'http://auth.example.com/' );
# Get Menu
# ------------------------
ok(
$res = $client->_get(
'/',
cookie => "lemonldap=$id1,lemonldaphttp=$id2",
accept => 'text/html'
),
'Get Menu',
);
count(1);
expectOK($res);
ok(
$res->[2]->[0] =~
m%<span trspan="connectedAs">Connected as</span> dwho%,
'Connected as Dwho'
) or print STDERR Dumper( $res->[2]->[0] );
count(1);
# Refresh rights
# ------------------------
ok(
$res = $client->_get(
'/refresh',
cookie => "lemonldap=$id1,lemonldaphttp=$id2",
accept => 'text/html'
),
'Refresh query',
);
count(1);
expectRedirection( $res, 'http://auth.example.com/' );
# Get Menu
# ------------------------
ok(
$res = $client->_get(
'/',
cookie => "lemonldap=$id1,lemonldaphttp=$id2",
accept => 'text/html'
),
'Get Menu',
);
count(1);
expectOK($res);
ok(
$res->[2]->[0] =~
m%<span trspan="connectedAs">Connected as</span> dwho%,
'Connected as Dwho'
) or print STDERR Dumper( $res->[2]->[0] );
count(1);
# Log out request
# ------------------------
ok(
$res = $client->_get(
'/',
query => 'logout=1',
cookie => "lemonldap=$id1,lemonldaphttp=$id2",
accept => 'text/html'
),
'Get Menu',
);
count(1);
expectOK($res);
ok(
$res->[2]->[0] =~
m%<div class="message message-positive alert"><span trmsg="47"></span></div>%,
'Dwho has been well disconnected'
) or print STDERR Dumper( $res->[2]->[0] );
count(1);
clean_sessions();
done_testing( count() );

View File

@ -86,4 +86,9 @@ ok( @unTr == 0,
'All "trspan" attribute translated' . ( @unTr ? " (@unTr)" : "" ) );
$count += 2;
foreach my $lang (@langs) {
ok( -f "site/htdocs/static/common/$lang.png", "Flag icon found for $lang" );
$count += 1;
}
done_testing($count);

View File

@ -324,6 +324,7 @@ Nginx support for LemonLDAP::NG.
#==============================================================================
%package -n perl-Lemonldap-NG-Common
Summary: LemonLDAP-NG Common Modules
Requires: perl(JSON::XS)
%description -n perl-Lemonldap-NG-Common
This package installs the configuration libraries used by other LemonLDAP::NG