Merge branch 'v2.0'

This commit is contained in:
Xavier 2019-05-11 20:25:11 +02:00
commit 224307515f
90 changed files with 2697 additions and 211 deletions

View File

@ -46,7 +46,7 @@ ErrorDocument 503 http://auth.__DNSDOMAIN__/lmerror/503
#</Location> #</Location>
# Uncomment this if site if you use SSL only # Uncomment this if site if you use SSL only
#Header set Strict-Transport-Security 15768000 #Header set Strict-Transport-Security "max-age=15768000"
</VirtualHost> </VirtualHost>

View File

@ -63,7 +63,7 @@ ErrorDocument 503 http://auth.__DNSDOMAIN__/lmerror/503
#</Location> #</Location>
# Uncomment this if site if you use SSL only # Uncomment this if site if you use SSL only
#Header set Strict-Transport-Security 15768000 #Header set Strict-Transport-Security "max-age=15768000"
</VirtualHost> </VirtualHost>

View File

@ -53,7 +53,7 @@ ErrorDocument 503 http://auth.__DNSDOMAIN__/lmerror/503
#</Location> #</Location>
# Uncomment this if site if you use SSL only # Uncomment this if site if you use SSL only
#Header set Strict-Transport-Security 15768000 #Header set Strict-Transport-Security "max-age=15768000"
</VirtualHost> </VirtualHost>

View File

@ -94,5 +94,5 @@
</Directory> </Directory>
# Uncomment this if site if you use SSL only # Uncomment this if site if you use SSL only
#Header set Strict-Transport-Security 15768000 #Header set Strict-Transport-Security "max-age=15768000"
</VirtualHost> </VirtualHost>

View File

@ -107,5 +107,5 @@
</Directory> </Directory>
# Uncomment this if site if you use SSL only # Uncomment this if site if you use SSL only
#Header set Strict-Transport-Security 15768000 #Header set Strict-Transport-Security "max-age=15768000"
</VirtualHost> </VirtualHost>

View File

@ -91,5 +91,5 @@
</Directory> </Directory>
# Uncomment this if site if you use SSL only # Uncomment this if site if you use SSL only
#Header set Strict-Transport-Security 15768000 #Header set Strict-Transport-Security "max-age=15768000"
</VirtualHost> </VirtualHost>

View File

@ -36,7 +36,7 @@ server {
#uwsgi_param SCRIPT_NAME $sc; #uwsgi_param SCRIPT_NAME $sc;
# Uncomment this if you use https only # Uncomment this if you use https only
#add_header Strict-Transport-Security "15768000"; #add_header Strict-Transport-Security "max-age=15768000";
} }
location / { location / {

View File

@ -103,6 +103,6 @@
</Location> </Location>
# Uncomment this if site if you use SSL only # Uncomment this if site if you use SSL only
#Header set Strict-Transport-Security 15768000 #Header set Strict-Transport-Security "max-age=15768000"
</VirtualHost> </VirtualHost>

View File

@ -128,6 +128,6 @@
</Location> </Location>
# Uncomment this if site if you use SSL only # Uncomment this if site if you use SSL only
#Header set Strict-Transport-Security 15768000 #Header set Strict-Transport-Security "max-age=15768000"
</VirtualHost> </VirtualHost>

View File

@ -104,6 +104,6 @@
</Location> </Location>
# Uncomment this if site if you use SSL only # Uncomment this if site if you use SSL only
#Header set Strict-Transport-Security 15768000 #Header set Strict-Transport-Security "max-age=15768000"
</VirtualHost> </VirtualHost>

View File

@ -54,7 +54,7 @@ server {
try_files $uri $uri/ =404; try_files $uri $uri/ =404;
# Uncomment this if you use https only # Uncomment this if you use https only
#add_header Strict-Transport-Security max-age=15768000; #add_header Strict-Transport-Security "max-age=15768000";
} }
location /static/ { location /static/ {

View File

@ -43,5 +43,5 @@ PerlModule Lemonldap::NG::Handler::ApacheMP2::Menu
</IfModule> </IfModule>
# Uncomment this if site if you use SSL only # Uncomment this if site if you use SSL only
#Header set Strict-Transport-Security 15768000 #Header set Strict-Transport-Security "max-age=15768000"
</VirtualHost> </VirtualHost>

View File

@ -43,5 +43,5 @@ PerlModule Lemonldap::NG::Handler::ApacheMP2::Menu
</IfModule> </IfModule>
# Uncomment this if site if you use SSL only # Uncomment this if site if you use SSL only
#Header set Strict-Transport-Security 15768000 #Header set Strict-Transport-Security "max-age=15768000"
</VirtualHost> </VirtualHost>

View File

@ -38,5 +38,5 @@ PerlModule Lemonldap::NG::Handler::ApacheMP2::Menu
</IfModule> </IfModule>
# Uncomment this if site if you use SSL only # Uncomment this if site if you use SSL only
#Header set Strict-Transport-Security 15768000 #Header set Strict-Transport-Security "max-age=15768000"
</VirtualHost> </VirtualHost>

View File

@ -86,7 +86,7 @@ server {
#fastcgi_param HTTP_COOKIE $lmcookie; #fastcgi_param HTTP_COOKIE $lmcookie;
# Uncomment this if you use https only # Uncomment this if you use https only
#add_header Strict-Transport-Security "15768000"; #add_header Strict-Transport-Security "max-age=15768000";
# Set REMOTE_USER (for FastCGI apps only) # Set REMOTE_USER (for FastCGI apps only)
#fastcgi_param REMOTE_USER $lmremote_user; #fastcgi_param REMOTE_USER $lmremote_user;

View File

@ -21,7 +21,7 @@ sub TIEHASH {
modified => 0, modified => 0,
}; };
foreach ( foreach (
qw(baseUrl user password realm localStorage localStorageOptions lwpOpts lwpSslOpts) qw(baseUrl user password realm localStorage localStorageOptions lwpOpts lwpSslOpts kind)
) )
{ {
$self->{$_} = $args->{$_}; $self->{$_} = $args->{$_};
@ -116,8 +116,13 @@ sub ua {
sub getJson { sub getJson {
my $self = shift; my $self = shift;
my $url = shift; my $id = shift;
my $resp = $self->ua->get( $self->base . $url, @_ ); my $resp = $self->ua->get(
$self->base
. $id
. ( $self->{kind} ne 'SSO' ? "?kind=$self->{kind}" : '' ),
@_
);
if ( $resp->is_success ) { if ( $resp->is_success ) {
my $res; my $res;
eval { $res = from_json( $resp->content, { allow_nonref => 1 } ) }; eval { $res = from_json( $resp->content, { allow_nonref => 1 } ) };
@ -155,7 +160,7 @@ sub get {
} }
# No cache, use REST and set cache # No cache, use REST and set cache
my $res = $self->getJson("$id") or return 0; my $res = $self->getJson($id) or return 0;
$self->{data} = $res; $self->{data} = $res;
$self->cache->set( "rest$id", $self->{data} ) if $self->{localStorage}; $self->cache->set( "rest$id", $self->{data} ) if $self->{localStorage};

View File

@ -113,8 +113,8 @@ sub load {
$Lemonldap::NG::Common::Conf::msg .= "YAML fails to read file: $@ \n"; $Lemonldap::NG::Common::Conf::msg .= "YAML fails to read file: $@ \n";
return undef; return undef;
} }
foreach (keys $ret) { foreach ( keys %$ret ) {
if($_ =~ $boolKeys) { if ( $_ =~ $boolKeys ) {
$ret->{$_} = $ret->{$_} ? 1 : 0; $ret->{$_} = $ret->{$_} ? 1 : 0;
} }
} }

View File

@ -53,7 +53,7 @@ sub serviceToXML {
$template->param( $_, $self->getValue( $_, $conf ) ); $template->param( $_, $self->getValue( $_, $conf ) );
} }
# When asked to provide only IDP metadata, take into account EntityID override # When asked to provide only IDP metadata, take into account EntityID override
if ( $type eq "idp" and $conf->{samlOverrideIDPEntityID} ) { if ( $type eq "idp" and $conf->{samlOverrideIDPEntityID} ) {
$template->param( 'samlEntityID', $conf->{samlOverrideIDPEntityID} ); $template->param( 'samlEntityID', $conf->{samlOverrideIDPEntityID} );
} }

View File

@ -139,6 +139,14 @@ sub BUILD {
# Load session data into object # Load session data into object
if ($data) { if ($data) {
if ( $self->kind and $data->{_session_kind} ) {
unless ( $data->{_session_kind} eq $self->kind ) {
$self->error(
"Session kind mismatch : $data->{_session_kind} is not "
. $self->kind );
return undef;
}
}
$self->_save_data($data); $self->_save_data($data);
$self->kind( $data->{_session_kind} ); $self->kind( $data->{_session_kind} );
$self->id( $data->{_session_id} ); $self->id( $data->{_session_id} );
@ -158,7 +166,7 @@ sub _tie_session {
if ( $self->storageModule =~ /^Lemonldap::NG::Common::Apache::Session/ ) if ( $self->storageModule =~ /^Lemonldap::NG::Common::Apache::Session/ )
{ {
tie %h, $self->storageModule, $self->id, tie %h, $self->storageModule, $self->id,
{ %{ $self->options }, %$options }; { %{ $self->options }, %$options, kind => $self->kind };
} }
else { else {
tie %h, 'Lemonldap::NG::Common::Apache::Session', $self->id, tie %h, 'Lemonldap::NG::Common::Apache::Session', $self->id,

View File

@ -248,7 +248,7 @@ sub getApacheSession {
Lemonldap::NG::Handler::PSGI::Main->tsv->{sessionCacheOptions}, Lemonldap::NG::Handler::PSGI::Main->tsv->{sessionCacheOptions},
id => $id, id => $id,
force => $force, force => $force,
kind => $mod->{kind}, ( $id ? () : ( kind => $mod->{kind} ) ),
( $info ? ( info => $info ) : () ), ( $info ? ( info => $info ) : () ),
} }
); );
@ -271,6 +271,9 @@ sub getMod {
$self->error('Unknown (or unconfigured) session type'); $self->error('Unknown (or unconfigured) session type');
return (); return ();
} }
if ( my $kind = $req->params('kind') ) {
$m->{kind} = $kind;
}
return $m; return $m;
} }

View File

@ -377,15 +377,15 @@ sub headersInit {
$class->tsv->{headerList}->{$vhost} = [ keys %headers ]; $class->tsv->{headerList}->{$vhost} = [ keys %headers ];
my $sub = ''; my $sub = '';
foreach ( keys %headers ) { foreach ( keys %headers ) {
my $val = $class->substitute( $headers{$_} ); my $val = $class->substitute( $headers{$_} ) . " || ''";
$sub .= "('$_' => $val || ''),"; $sub .= "('$_' => $val),";
} }
unless ( $class->tsv->{forgeHeaders}->{$vhost} = unless ( $class->tsv->{forgeHeaders}->{$vhost} =
$class->buildSub($sub) ) $class->buildSub($sub) )
{ {
$class->tsv->{maintenance}->{$vhost} = 1; $class->tsv->{maintenance}->{$vhost} = 1;
$class->logger->error( "$class Unable to forge headers: " $class->logger->error( "$class Unable to forge $vhost headers: "
. $class->tsv->{jail}->error ); . $class->tsv->{jail}->error );
} }
} }

View File

@ -203,6 +203,7 @@ t/05-rest-api.t
t/06-rest-api.t t/06-rest-api.t
t/07-utf8.t t/07-utf8.t
t/10-save-unchanged-conf.t t/10-save-unchanged-conf.t
t/11-save-appCat-changed-conf.t
t/11-save-changed-conf-with-confirmation.t t/11-save-changed-conf-with-confirmation.t
t/12-save-changed-conf.t t/12-save-changed-conf.t
t/14-bad-changes-in-conf.t t/14-bad-changes-in-conf.t
@ -220,6 +221,7 @@ t/99-pod.t
t/conf/lmConf-1.json t/conf/lmConf-1.json
t/jsonfiles/01-base-tree.json t/jsonfiles/01-base-tree.json
t/jsonfiles/02-base-tree-all-nodes-opened.json t/jsonfiles/02-base-tree-all-nodes-opened.json
t/jsonfiles/03-base-tree-appCat-modifed.json
t/jsonfiles/11-modified-with-confirmation.json t/jsonfiles/11-modified-with-confirmation.json
t/jsonfiles/12-modified.json t/jsonfiles/12-modified.json
t/jsonfiles/14-bad.json t/jsonfiles/14-bad.json

View File

@ -140,14 +140,15 @@ sub tplParams {
sub javascript { sub javascript {
my ( $self, $req ) = @_; my ( $self, $req ) = @_;
my $res = $self->diffRule->( $req, $req->{userData} ) || 0; my $res = $self->diffRule->( $req, $req->{userData} ) || 0;
my $impPrefix = $self->{impersonationPrefix}; my $impPrefix = $self->{impersonationPrefix};
my $ttl = $self->{timeout} || 72000; my $ttl = $self->{timeout} || 72000;
return return
'var formPrefix=staticPrefix+"forms/";var confPrefix=scriptname+"confs/";var viewPrefix=scriptname+"view/";' 'var formPrefix=staticPrefix+"forms/";var confPrefix=scriptname+"confs/";var viewPrefix=scriptname+"view/";'
. 'var allowDiff=' . "$res;" . 'var allowDiff=' . "$res;"
. 'var impPrefix=' . "'" . $impPrefix . "'" . ';' . 'var impPrefix=' . "'"
. $impPrefix . "'" . ';'
. 'var sessionTTL=' . "$ttl;" . 'var sessionTTL=' . "$ttl;"
. ( $self->links ? 'var links=' . to_json( $self->links ) . ';' : '' ) . ( $self->links ? 'var links=' . to_json( $self->links ) . ';' : '' )
. ( . (

View File

@ -536,21 +536,24 @@ sub _scanNodes {
} }
); );
@listCatRef = map { $_ ? $_ : () } @listCatRef;
@listCatNew = map { $_ ? $_ : () } @listCatNew;
@listCatRef = sort @listCatRef; @listCatRef = sort @listCatRef;
@listCatNew = sort @listCatNew; @listCatNew = sort @listCatNew;
hdebug( '# @listCatRef : ' . \@listCatRef ); hdebug( '# @listCatRef : ', \@listCatRef );
hdebug( '# @listCatNew : ' . \@listCatNew ); hdebug( '# @listCatNew : ', \@listCatNew );
for ( my $i = 0 ; $i < @listCatNew ; $i++ ) {
if ( not( defined $listCatRef[$i] ) # Check for deleted
or $listCatRef[$i] ne $listCatNew[$i] ) my @diff =
{ grep !${ { map { $_, 1 } @listCatNew } }{$_}, @listCatRef;
push @{ $self->changes }, if ( scalar @diff ) {
{ $self->confChanged(1);
key => $leaf->{id}, push @{ $self->changes },
new => $listCatNew[$i], {
old => $listCatRef[$i] new => join( ', ', 'categoryList', @listCatNew ),
}; key => join( ', ', 'Deletes in cat(s)', @diff ),
} old => join( ', ', 'categoryList', @listCatRef ),
};
} }
} }
next; next;

View File

@ -646,7 +646,8 @@ sub tests {
# Warn if Impersonation is enabled without prefix # Warn if Impersonation is enabled without prefix
impersonationPrefix => sub { impersonationPrefix => sub {
return 1 unless ( $conf->{impersonationRule} ); return 1 unless ( $conf->{impersonationRule} );
return ( 1, "Impersonation is enabled without real attributes prefix" ) return ( 1,
"Impersonation is enabled without real attributes prefix" )
unless ( $conf->{impersonationPrefix} ); unless ( $conf->{impersonationPrefix} );
# Return # Return

View File

@ -149,8 +149,8 @@ sub zeroConf {
'locationRules' => { 'locationRules' => {
"auth.$domain" => { "auth.$domain" => {
'(?#checkUser)^/checkuser' => '$uid eq "dwho"', '(?#checkUser)^/checkuser' => '$uid eq "dwho"',
'(?#errors)^/lmerror/' => 'accept', '(?#errors)^/lmerror/' => 'accept',
'default' => 'accept' 'default' => 'accept'
}, },
"test1.$domain" => { "test1.$domain" => {
'default' => 'accept', 'default' => 'accept',
@ -162,7 +162,8 @@ sub zeroConf {
}, },
"manager.$domain" => { "manager.$domain" => {
'default' => '$uid eq "dwho" or $uid eq "rtyler"', 'default' => '$uid eq "dwho" or $uid eq "rtyler"',
'(?#Configuration)^/(manager\.html|confs|$)' => '$uid eq "dwho"', '(?#Configuration)^/(manager\.html|confs|$)' =>
'$uid eq "dwho"',
'(?#Sessions)/sessions' => '$uid eq "dwho" or $uid eq "rtyler"', '(?#Sessions)/sessions' => '$uid eq "dwho" or $uid eq "rtyler"',
'(?#Notifications)/notifications' => '(?#Notifications)/notifications' =>
'$uid eq "dwho" or $uid eq "rtyler"', '$uid eq "dwho" or $uid eq "rtyler"',

View File

@ -53,7 +53,7 @@ sub addRoutes {
$self->{ipField} ||= 'ipAddr'; $self->{ipField} ||= 'ipAddr';
$self->{multiValuesSeparator} ||= '; '; $self->{multiValuesSeparator} ||= '; ';
$self->{impersonationPrefix} = $conf->{impersonationPrefix} || 'real_'; $self->{impersonationPrefix} = $conf->{impersonationPrefix} || 'real_';
$self->{hiddenAttributes} //= "_password"; $self->{hiddenAttributes} //= "_password";
} }

View File

@ -694,7 +694,9 @@ llapp.controller 'TreeCtrl', [
if typeof node.data == 'string' and node.data.match /^(?:-1|0|1)$/ if typeof node.data == 'string' and node.data.match /^(?:-1|0|1)$/
node.data = parseInt(node.data, 10) node.data = parseInt(node.data, 10)
if node.type and node.type.match /^int$/ if node.type and node.type.match /^int$/
node.data = parseInt(node.data, 10) node.data = parseInt(node.data, 10)
if node.type and node.type.match /^select$/
node.data = node.data.toString()
# Split SAML types # Split SAML types
else if node.type and node.type.match(/^(saml(Service|Assertion)|blackWhiteList)$/) and not (typeof node.data == 'object') else if node.type and node.type.match(/^(saml(Service|Assertion)|blackWhiteList)$/) and not (typeof node.data == 'object')
node.data = node.data.split ';' node.data = node.data.split ';'

View File

@ -842,6 +842,9 @@ This file contains:
} }
if (node.type && node.type.match(/^int$/)) { if (node.type && node.type.match(/^int$/)) {
node.data = parseInt(node.data, 10); node.data = parseInt(node.data, 10);
}
if (node.type && node.type.match(/^select$/)) {
node.data = node.data.toString();
} else if (node.type && node.type.match(/^(saml(Service|Assertion)|blackWhiteList)$/) && !(typeof node.data === 'object')) { } else if (node.type && node.type.match(/^(saml(Service|Assertion)|blackWhiteList)$/) && !(typeof node.data === 'object')) {
node.data = node.data.split(';'); node.data = node.data.split(';');
} }

File diff suppressed because one or more lines are too long

View File

@ -254,7 +254,7 @@
"ext2fCodeActivation":"Code regex", "ext2fCodeActivation":"Code regex",
"ext2fAuthnLevel":"Authentication level", "ext2fAuthnLevel":"Authentication level",
"ext2fLogo":"Logo", "ext2fLogo":"Logo",
"ext2FSendCommand":"Send comand", "ext2FSendCommand":"Send command",
"ext2FValidateCommand":"Validation command", "ext2FValidateCommand":"Validation command",
"facebookAppId":"Facebook application ID", "facebookAppId":"Facebook application ID",
"facebookAppSecret":"Facebook application secret", "facebookAppSecret":"Facebook application secret",
@ -758,7 +758,7 @@
"stateCheck":"State Check", "stateCheck":"State Check",
"stayConnected":"Persistent connections", "stayConnected":"Persistent connections",
"successfullySaved":"Successfully saved", "successfullySaved":"Successfully saved",
"storePassword":"Store user password in session datas", "storePassword":"Store user password in session",
"successLoginNumber":"Number of registered logins", "successLoginNumber":"Number of registered logins",
"sympaHandler":"Sympa", "sympaHandler":"Sympa",
"sympaMailKey":"Mail session key", "sympaMailKey":"Mail session key",

View File

@ -254,7 +254,7 @@
"ext2fCodeActivation":"Code regex", "ext2fCodeActivation":"Code regex",
"ext2fAuthnLevel":"Authentication level", "ext2fAuthnLevel":"Authentication level",
"ext2fLogo":"Logo", "ext2fLogo":"Logo",
"ext2FSendCommand":"Send comand", "ext2FSendCommand":"Send command",
"ext2FValidateCommand":"Validation command", "ext2FValidateCommand":"Validation command",
"facebookAppId":"Facebook application ID", "facebookAppId":"Facebook application ID",
"facebookAppSecret":"Facebook application secret", "facebookAppSecret":"Facebook application secret",
@ -758,7 +758,7 @@
"stateCheck":"State Check", "stateCheck":"State Check",
"stayConnected":"Persistent connections", "stayConnected":"Persistent connections",
"successfullySaved":"Successfully saved", "successfullySaved":"Successfully saved",
"storePassword":"Store user password in session datas", "storePassword":"Store user password in session",
"successLoginNumber":"Number of registered logins", "successLoginNumber":"Number of registered logins",
"sympaHandler":"Sympa", "sympaHandler":"Sympa",
"sympaMailKey":"Mail session key", "sympaMailKey":"Mail session key",

View File

@ -130,7 +130,7 @@
"casSrvMetaDataOptionsGateway":"Authentification transparente", "casSrvMetaDataOptionsGateway":"Authentification transparente",
"casSrvMetaDataOptionsIcon":"Chemin de l'icône", "casSrvMetaDataOptionsIcon":"Chemin de l'icône",
"casSrvMetaDataOptionsSortNumber":"Ordre", "casSrvMetaDataOptionsSortNumber":"Ordre",
"casSrvMetaDataOptionsRenew":"Renouveller l'authentification", "casSrvMetaDataOptionsRenew":"Renouveler l'authentification",
"casSrvMetaDataOptionsProxiedServices":"Services mandatés", "casSrvMetaDataOptionsProxiedServices":"Services mandatés",
"casSrvMetaDataOptionsUrl":"URL du serveur", "casSrvMetaDataOptionsUrl":"URL du serveur",
"casSrvMetaDataNodes":"Serveurs CAS", "casSrvMetaDataNodes":"Serveurs CAS",
@ -145,7 +145,7 @@
"cspImg":"Sources des images", "cspImg":"Sources des images",
"cspScript":"Sources des scripts", "cspScript":"Sources des scripts",
"cspStyle":"Sources des styles", "cspStyle":"Sources des styles",
"cspConnect":"Destinations des requêtes Ajax", "cspConnect":"Destinations des requêtes AJAX",
"cspFont":"Sources des polices", "cspFont":"Sources des polices",
"cfgLog":"Résumé", "cfgLog":"Résumé",
"cfgVersion":"Version de la configuration", "cfgVersion":"Version de la configuration",
@ -276,7 +276,7 @@
"generalParameters":"Paramètres généraux", "generalParameters":"Paramètres généraux",
"globalStorage":"Module Apache::Session", "globalStorage":"Module Apache::Session",
"globalStorageOptions":"Paramètres du module Apache::Session", "globalStorageOptions":"Paramètres du module Apache::Session",
"gpgAuthnLevel":"Niveau d'authentication", "gpgAuthnLevel":"Niveau d'authentification",
"gpgDb":"Base de données GPG", "gpgDb":"Base de données GPG",
"gpgParams":"Paramètres GPG", "gpgParams":"Paramètres GPG",
"grantSessionRules":"Conditions d'ouverture", "grantSessionRules":"Conditions d'ouverture",
@ -331,8 +331,8 @@
"issuerDBOpenIDConnectRule":"Règle d'utilisation", "issuerDBOpenIDConnectRule":"Règle d'utilisation",
"issuerParams":"Modules fournisseur", "issuerParams":"Modules fournisseur",
"jsRedirect":"Message de redirection", "jsRedirect":"Message de redirection",
"jqueryButtonSelector":"Selecteur jQuery du bouton (optionnel)", "jqueryButtonSelector":"Sélecteur jQuery du bouton (optionnel)",
"jqueryFormSelector":"Selecteur jQuery du formulaire (optionnel)", "jqueryFormSelector":"Sélecteur jQuery du formulaire (optionnel)",
"jqueryUrl":"URL jQuery (optionnel)", "jqueryUrl":"URL jQuery (optionnel)",
"key":"Clef de chiffrement", "key":"Clef de chiffrement",
"keys":"Clefs", "keys":"Clefs",
@ -623,13 +623,13 @@
"portalErrorOnExpiredSession":"Affiche une erreur si la session est expirée", "portalErrorOnExpiredSession":"Affiche une erreur si la session est expirée",
"portalErrorOnMailNotFound":"Affiche une erreur si le mail n'est pas trouvé", "portalErrorOnMailNotFound":"Affiche une erreur si le mail n'est pas trouvé",
"portalForceAuthn":"Authentification forcée", "portalForceAuthn":"Authentification forcée",
"portalForceAuthnInterval":"Interval d'authentification forcée", "portalForceAuthnInterval":"Intervalle d'authentification forcée",
"portalMenu":"Menu", "portalMenu":"Menu",
"portalModules":"Modules", "portalModules":"Modules",
"portalOpenLinkInNewWindow":"Nouvelle fenêtre", "portalOpenLinkInNewWindow":"Nouvelle fenêtre",
"portalOther":"Autres", "portalOther":"Autres",
"portalParams":"Portail", "portalParams":"Portail",
"portalPingInterval":"Interval du ping", "portalPingInterval":"Intervalle du ping",
"portalRedirection":"Redirections du Portail", "portalRedirection":"Redirections du Portail",
"portalRequireOldPassword":"Ancien mot de passe requis", "portalRequireOldPassword":"Ancien mot de passe requis",
"portalServers":"Serveurs du portail", "portalServers":"Serveurs du portail",
@ -656,7 +656,7 @@
"radiusParams":"Paramètres Radius", "radiusParams":"Paramètres Radius",
"radiusSecret":"Secret partagé", "radiusSecret":"Secret partagé",
"radiusServer":"Nom d'hôte du serveur", "radiusServer":"Nom d'hôte du serveur",
"randomPasswordRegexp":"Expression regulière pour la génération des mots de passe", "randomPasswordRegexp":"Expression régulière pour la génération des mots de passe",
"readOnlyMode":"Mode lecture seule", "readOnlyMode":"Mode lecture seule",
"redirectFormMethod":"Méthode du formulaire de redirection", "redirectFormMethod":"Méthode du formulaire de redirection",
"redirection":"Redirections du Handler", "redirection":"Redirections du Handler",
@ -679,7 +679,7 @@
"remotePortal":"URL du portail", "remotePortal":"URL du portail",
"replaceByFile":"Remplacer par le fichier", "replaceByFile":"Remplacer par le fichier",
"requireToken":"Exige un jeton pour les formulaires", "requireToken":"Exige un jeton pour les formulaires",
"restAuthnLevel":"Niveau d'authentication", "restAuthnLevel":"Niveau d'authentification",
"restAuthUrl":"URL d'authentification", "restAuthUrl":"URL d'authentification",
"restConfigServer":"Serveur de configurations REST", "restConfigServer":"Serveur de configurations REST",
"restore":"Restaurer", "restore":"Restaurer",
@ -905,7 +905,7 @@
"samlIDPMetaDataOptionsSecurity":"Sécurité", "samlIDPMetaDataOptionsSecurity":"Sécurité",
"samlIDPMetaDataOptionsSortNumber":"Ordre", "samlIDPMetaDataOptionsSortNumber":"Ordre",
"samlIDPMetaDataOptionsStoreSAMLToken":"Conserver le jeton SAML", "samlIDPMetaDataOptionsStoreSAMLToken":"Conserver le jeton SAML",
"samlIDPMetaDataOptionsRelayStateURL":"Pemettre une URL dans le RelayState", "samlIDPMetaDataOptionsRelayStateURL":"Permettre une URL dans le RelayState",
"samlIDPMetaDataOptionsUserAttribute":"Attribut contenant l'identité de l'utilisateur", "samlIDPMetaDataOptionsUserAttribute":"Attribut contenant l'identité de l'utilisateur",
"samlSPMetaDataNodes":"Fournisseurs de service SAML", "samlSPMetaDataNodes":"Fournisseurs de service SAML",
"samlSPMetaDataXML":"Metadonnées", "samlSPMetaDataXML":"Metadonnées",

View File

@ -509,8 +509,8 @@
"oidcRPMetaDataOptionsLogoutType":"Tipo", "oidcRPMetaDataOptionsLogoutType":"Tipo",
"oidcRPMetaDataOptionsLogoutUrl":"URL", "oidcRPMetaDataOptionsLogoutUrl":"URL",
"oidcOPMetaDataOptionsProtocol":"Protocollo", "oidcOPMetaDataOptionsProtocol":"Protocollo",
"oidcRPMetaDataOptionsPublic":"Public client", "oidcRPMetaDataOptionsPublic":"Cliente pubblico",
"oidcRPMetaDataOptionsRequirePKCE":"Require PKCE", "oidcRPMetaDataOptionsRequirePKCE":"Richiedi PKCE",
"oidcRPMetaDataOptionsRule":"Regola di accesso", "oidcRPMetaDataOptionsRule":"Regola di accesso",
"oidcOPMetaDataOptionsScope":"Scopo", "oidcOPMetaDataOptionsScope":"Scopo",
"oidcOPMetaDataOptionsStoreIDToken":"Immagazzina ID Token", "oidcOPMetaDataOptionsStoreIDToken":"Immagazzina ID Token",
@ -716,7 +716,7 @@
"session_s":"sessione(i)", "session_s":"sessione(i)",
"sessionDataToRemember":"Dati di sessione da memorizzare", "sessionDataToRemember":"Dati di sessione da memorizzare",
"sessionDeleted":"La sessione è stata rimossa", "sessionDeleted":"La sessione è stata rimossa",
"sessionExpired":"The session is expired", "sessionExpired":"La sessione è scaduta",
"sessionParams":"Sessioni", "sessionParams":"Sessioni",
"sessionStartedAt":"La sessione è stata avviata", "sessionStartedAt":"La sessione è stata avviata",
"sessionStorage":"Conservazione di sessioni", "sessionStorage":"Conservazione di sessioni",

View File

@ -254,7 +254,7 @@
"ext2fCodeActivation":"Code regex", "ext2fCodeActivation":"Code regex",
"ext2fAuthnLevel":"认证级别", "ext2fAuthnLevel":"认证级别",
"ext2fLogo":"Logo", "ext2fLogo":"Logo",
"ext2FSendCommand":"Send comand", "ext2FSendCommand":"Send command",
"ext2FValidateCommand":"Validation command", "ext2FValidateCommand":"Validation command",
"facebookAppId":"Facebook application ID", "facebookAppId":"Facebook application ID",
"facebookAppSecret":"Facebook application secret", "facebookAppSecret":"Facebook application secret",
@ -758,7 +758,7 @@
"stateCheck":"State Check", "stateCheck":"State Check",
"stayConnected":"Persistent connections", "stayConnected":"Persistent connections",
"successfullySaved":"Successfully saved", "successfullySaved":"Successfully saved",
"storePassword":"Store user password in session datas", "storePassword":"Store user password in session",
"successLoginNumber":"Number of registered logins", "successLoginNumber":"Number of registered logins",
"sympaHandler":"Sympa", "sympaHandler":"Sympa",
"sympaMailKey":"Mail session key", "sympaMailKey":"Mail session key",

View File

@ -0,0 +1,70 @@
# Verify that an unmodified configuration is rejected
use Data::Dumper;
use Test::More;
use strict;
use JSON;
require 't/test-lib.pm';
my @struct = qw[t/jsonfiles/03-base-tree-appCat-modifed.json];
my @desc = ('Changed conf with deleted Category');
my $confFiles = [ 't/conf/lmConf-1.json', 't/conf/lmConf-2.json' ];
sub body {
return 0 unless (@struct);
my $t = shift @struct;
return IO::File->new( $t, 'r' );
}
# Delete lmConf-2.json if exists
eval { unlink $confFiles->[1]; };
mkdir 't/sessions';
# Try to save a modified conf
while ( my $body = &body() ) {
my $desc = shift @desc;
my ( $res, $resBody );
ok(
$res =
&client->_post( '/confs/', 'cfgNum=1', $body, 'application/json' ),
"$desc: positive result"
);
ok( $res->[0] == 200, "$desc: result code is 200" )
or print STDERR Dumper($res);
ok(
$resBody = from_json( $res->[2]->[0] ),
"$desc: result body contains JSON text"
);
#print STDERR Dumper($resBody);
ok( $resBody->{result} == 1, "$desc: JSON response contains \"result:1\"" );
ok( @{ $resBody->{details}->{__changes__} } eq 1,
"$desc: conf has changed" )
or print STDERR Dumper($resBody);
ok(
$resBody->{details}->{__changes__}->[0]->{new} eq
'categoryList, Administration, Documentation',
"$desc: new key received"
) or print STDERR Dumper($resBody);
ok(
$resBody->{details}->{__changes__}->[0]->{old} eq
'categoryList, Administration, Documentation, Sample applications',
"$desc: old key received"
) or print STDERR Dumper($resBody);
ok(
$resBody->{details}->{__changes__}->[0]->{key} eq
'Deletes in cat(s), Sample applications',
"$desc: key received"
) or print STDERR Dumper($resBody);
ok( -e $confFiles->[1], "$desc: file is created" );
#print STDERR Dumper($resBody);
count(9);
}
eval { unlink $confFiles->[1]; rmdir 't/sessions'; };
done_testing( count() );
# Remove sessions directory
`rm -rf t/sessions`;

View File

@ -39,7 +39,7 @@ foreach my $i ( 0 .. 1 ) {
ok( ok(
@{ $resBody->{details}->{__changes__} } == 20, @{ $resBody->{details}->{__changes__} } == 20,
'JSON response contains 24 changes' 'JSON response contains 20 changes'
) or print STDERR Dumper($resBody); ) or print STDERR Dumper($resBody);
#print STDERR Dumper($resBody); #print STDERR Dumper($resBody);

View File

@ -64,7 +64,7 @@ count(2);
# Try to display previous conf # Try to display previous conf
$res = &client->jsonResponse('/view/1'); $res = &client->jsonResponse('/view/1');
ok( $res->{cfgNum} eq '1', 'Browser is allowed' ) ok( $res->{cfgNum} eq '1', 'Browser is allowed' )
or print STDERR Dumper($res); or print STDERR Dumper($res);
count(1); count(1);
# Remove new conf # Remove new conf

File diff suppressed because it is too large Load Diff

View File

@ -493,11 +493,13 @@ t/40-Notifications-XML-DBI.t
t/40-Notifications-XML-File.t t/40-Notifications-XML-File.t
t/40-Notifications-XML-Server.t t/40-Notifications-XML-Server.t
t/41-Captcha.t t/41-Captcha.t
t/41-Token-Global-Storage.t
t/41-Token.t t/41-Token.t
t/42-Register-Demo-with-captcha.t t/42-Register-Demo-with-captcha.t
t/42-Register-Demo-with-token.t t/42-Register-Demo-with-token.t
t/42-Register-Demo.t t/42-Register-Demo.t
t/42-Register-LDAP.t t/42-Register-LDAP.t
t/42-Register-Security.t
t/43-MailPasswordReset-Choice.t t/43-MailPasswordReset-Choice.t
t/43-MailPasswordReset-DBI.t t/43-MailPasswordReset-DBI.t
t/43-MailPasswordReset-LDAP.t t/43-MailPasswordReset-LDAP.t

View File

@ -305,7 +305,7 @@ sub run {
$self->logger->debug( $self->logger->debug(
"Delete 2F Device : { type => 'TOTP', epoch => $epoch }"); "Delete 2F Device : { type => 'TOTP', epoch => $epoch }");
$self->p->updatePersistentSession( $req, $self->p->updatePersistentSession( $req,
{ _2fDevices => to_json( $_2fDevices ) } ); { _2fDevices => to_json($_2fDevices) } );
$self->userLogger->notice('TOTP deletion succeed'); $self->userLogger->notice('TOTP deletion succeed');
return [ return [
200, 200,

View File

@ -292,7 +292,7 @@ sub run {
$self->logger->debug( $self->logger->debug(
"Delete 2F Device : { type => 'U2F', epoch => $epoch }"); "Delete 2F Device : { type => 'U2F', epoch => $epoch }");
$self->p->updatePersistentSession( $req, $self->p->updatePersistentSession( $req,
{ _2fDevices => to_json( $_2fDevices ) } ); { _2fDevices => to_json($_2fDevices) } );
$self->userLogger->notice('U2F key unregistration succeed'); $self->userLogger->notice('U2F key unregistration succeed');
return [ return [
200, 200,

View File

@ -186,7 +186,7 @@ sub run {
$self->logger->debug( $self->logger->debug(
"Delete 2F Device : { type => 'UBK', epoch => $epoch }"); "Delete 2F Device : { type => 'UBK', epoch => $epoch }");
$self->p->updatePersistentSession( $req, $self->p->updatePersistentSession( $req,
{ _2fDevices => to_json( $_2fDevices ) } ); { _2fDevices => to_json($_2fDevices) } );
$self->userLogger->notice('Yubikey deletion succeed'); $self->userLogger->notice('Yubikey deletion succeed');
return [ return [
200, 200,

View File

@ -142,7 +142,7 @@ sub authenticate {
sub setAuthSessionInfo { sub setAuthSessionInfo {
my ( $self, $req ) = @_; my ( $self, $req ) = @_;
$req->sessionInfo->{gpgMail} = $req->data->{gpgMail}; $req->sessionInfo->{gpgMail} = $req->data->{gpgMail};
$req->sessionInfo->{authenticationLevel} = $self->conf->{gpgAuthnLevel}; $req->sessionInfo->{authenticationLevel} = $self->conf->{gpgAuthnLevel};
PE_OK; PE_OK;
} }

View File

@ -16,7 +16,7 @@ extends 'Lemonldap::NG::Portal::Main::Auth',
# INTERFACE # INTERFACE
has opList => ( is => 'rw', default => sub { [] } ); has opList => ( is => 'rw', default => sub { [] } );
has opNumber => ( is => 'rw', default => 0 ); has opNumber => ( is => 'rw', default => 0 );
has path => ( is => 'rw', default => 'oauth2' ); has path => ( is => 'rw', default => 'oauth2' );
@ -34,7 +34,7 @@ sub init {
return 0; return 0;
} }
$self->opNumber( scalar @tab ); $self->opNumber( scalar @tab );
my @list = (); my @list = ();
my $portalPath = $self->conf->{portal}; my $portalPath = $self->conf->{portal};
foreach (@tab) { foreach (@tab) {

View File

@ -76,7 +76,8 @@ sub createToken {
else { else {
# Create a new session # Create a new session
my $tsession = $self->p->getApacheSession( undef, info => $infos ); my $tsession =
$self->p->getApacheSession( undef, info => $infos, kind => 'TOKEN' );
$self->logger->debug("Token $tsession->{id} created"); $self->logger->debug("Token $tsession->{id} created");
return $tsession->id; return $tsession->id;
} }
@ -108,7 +109,7 @@ sub getToken {
else { else {
# Get token session # Get token session
my $tsession = $self->p->getApacheSession($id); my $tsession = $self->p->getApacheSession( $id, kind => 'TOKEN' );
unless ($tsession) { unless ($tsession) {
$self->logger->notice("Bad (or expired) token $id"); $self->logger->notice("Bad (or expired) token $id");
return undef; return undef;

View File

@ -50,7 +50,7 @@ sub checkRemoteId {
cacheModule => $self->conf->{localSessionStorage}, cacheModule => $self->conf->{localSessionStorage},
cacheModuleOptions => $self->conf->{localSessionStorageOptions}, cacheModuleOptions => $self->conf->{localSessionStorageOptions},
id => $rId, id => $rId,
kind => "REMOTE", kind => "SSO",
} }
); );

View File

@ -184,7 +184,7 @@ sub send_mail {
foreach ( keys %cid ) { foreach ( keys %cid ) {
$message->attach( $message->attach(
Type => "image/" . ( $cid{$_} =~ m/\.(\w+)/ )[0], Type => "image/" . ( $cid{$_} =~ m/\.(\w+)/ )[0],
Id => $_, Id => $_,
Path => $self->conf->{templateDir} . "/" Path => $self->conf->{templateDir} . "/"
. $self->conf->{portalSkin} . "/" . $self->conf->{portalSkin} . "/"
. $cid{$_}, . $cid{$_},

View File

@ -126,7 +126,7 @@ sub display {
&& $req->data->{login}, && $req->data->{login},
ASK_LOGINS => $req->param('checkLogins') || 0, ASK_LOGINS => $req->param('checkLogins') || 0,
CONFIRMKEY => $self->stamp(), CONFIRMKEY => $self->stamp(),
LIST => $req->data->{list} || [], LIST => $req->data->{list} || [],
REMEMBER => $req->data->{confirmRemember}, REMEMBER => $req->data->{confirmRemember},
( (
$req->data->{customScript} $req->data->{customScript}

View File

@ -113,7 +113,7 @@ sub _redirect {
delete $req->pdata->{ $self->ipath }; delete $req->pdata->{ $self->ipath };
delete $req->pdata->{ $self->ipath . 'Path' }; delete $req->pdata->{ $self->ipath . 'Path' };
return $self->run( @_, @path ); return $self->run( @_, @path );
} }
: () : ()
) )
] ]

View File

@ -331,7 +331,7 @@ sub autoRedirect {
# If $id is set to undef or if $args{force} is true, return a new session. # If $id is set to undef or if $args{force} is true, return a new session.
sub getApacheSession { sub getApacheSession {
my ( $self, $id, %args ) = @_; my ( $self, $id, %args ) = @_;
$args{kind} ||= "SSO"; $args{kind} //= "SSO";
if ($id) { if ($id) {
$self->logger->debug("Try to get $args{kind} session $id"); $self->logger->debug("Try to get $args{kind} session $id");
} }

View File

@ -31,37 +31,34 @@ sub changeUrldc {
$self->logger->debug('CDA request'); $self->logger->debug('CDA request');
# Create CDA session # Create CDA session
if ( my $cdaSession = my $cdaInfos = { '_utime' => time };
$self->p->getApacheSession( undef, kind => "CDA" ) ) if ( $self->{conf}->{securedCookie} < 2 or $ssl ) {
{ $cdaInfos->{cookie_value} = $req->id;
my $cdaInfos = { '_utime' => time }; $cdaInfos->{cookie_name} = $self->{conf}->{cookieName};
if ( $self->{conf}->{securedCookie} < 2 or $ssl ) {
$cdaInfos->{cookie_value} = $req->id;
$cdaInfos->{cookie_name} = $self->{conf}->{cookieName};
}
else {
$cdaInfos->{cookie_value} =
$req->{sessionInfo}->{_httpSession};
$cdaInfos->{cookie_name} = $self->{conf}->{cookieName} . "http";
}
$self->p->updateSession( $req, $cdaInfos, $cdaSession->id );
# We are about to redirect the user to the CDA application,
# dismiss any previously stored redirections (#1650)
delete $req->{pdata}->{_url};
$req->{urldc} .=
( $urldc =~ /\?/ ? '&' : '?' )
. $self->{conf}->{cookieName} . "cda="
. $cdaSession->id;
$self->logger->debug( "CDA redirection to " . $req->{urldc} );
} }
else { else {
$cdaInfos->{cookie_value} =
$req->{sessionInfo}->{_httpSession};
$cdaInfos->{cookie_name} = $self->{conf}->{cookieName} . "http";
}
my $cdaSession =
$self->p->getApacheSession( undef, kind => "CDA", info => $cdaInfos );
unless ($cdaSession) {
$self->logger->error("Unable to create CDA session"); $self->logger->error("Unable to create CDA session");
return PE_APACHESESSIONERROR; return PE_APACHESESSIONERROR;
} }
# We are about to redirect the user to the CDA application,
# dismiss any previously stored redirections (#1650)
delete $req->{pdata}->{_url};
$req->{urldc} .=
( $urldc =~ /\?/ ? '&' : '?' )
. $self->{conf}->{cookieName} . "cda="
. $cdaSession->id;
$self->logger->debug( "CDA redirection to " . $req->{urldc} );
} }
PE_OK; PE_OK;
} }

View File

@ -55,8 +55,10 @@ sub init {
sub run { sub run {
my ( $self, $req ) = @_; my ( $self, $req ) = @_;
my $savedHttpSession = $req->{sessionInfo}->{_httpSession} //= '';
my $spoofId = $req->param('spoofId') || $req->{user}; my $spoofId = $req->param('spoofId') || $req->{user};
$self->logger->debug("No impersonation required") if ( $spoofId eq $req->{user} ); $self->logger->debug("No impersonation required")
if ( $spoofId eq $req->{user} );
my $statut = PE_OK; my $statut = PE_OK;
if ( $spoofId !~ /$self->{conf}->{userControl}/o ) { if ( $spoofId !~ /$self->{conf}->{userControl}/o ) {
@ -139,6 +141,9 @@ sub run {
$self->p->updateSession( $req, $spoofSession ); $self->p->updateSession( $req, $spoofSession );
$req->steps( [ $self->p->validSession, @{ $self->p->endAuth } ] ); $req->steps( [ $self->p->validSession, @{ $self->p->endAuth } ] );
# Restore _httpSession for double Cookies
$req->{sessionInfo}->{_httpSession} = $savedHttpSession
if $savedHttpSession;
return $statut; return $statut;
} }

View File

@ -165,7 +165,7 @@ sub _register {
and and
!$self->getRegisterSession( $req->data->{registerInfo}->{mail} ) ) !$self->getRegisterSession( $req->data->{registerInfo}->{mail} ) )
{ {
# Check if token exists # Check if token exists
my $token; my $token;
if ( $self->ottRule->( $req, {} ) or $self->captcha ) { if ( $self->ottRule->( $req, {} ) or $self->captcha ) {

View File

@ -272,7 +272,7 @@ sub getAttributes {
my ( $self, $req, $id ) = @_; my ( $self, $req, $id ) = @_;
die 'id is required' unless ($id); die 'id is required' unless ($id);
my $session = $self->p->getApacheSession($id); my $session = $self->p->getApacheSession( $id, kind => '' );
my @tmp = (); my @tmp = ();
unless ($session) { unless ($session) {

View File

@ -158,4 +158,8 @@ div.oidc_consent_message > ul {
.fa.icon-blue { .fa.icon-blue {
color: blue; color: blue;
}
.progress-bar-animated {
width: 100%;
} }

View File

@ -1 +1 @@
html,body{height:100%;background:radial-gradient(circle at 50% 0,#fff 0,#ddd 100%) no-repeat scroll 0 0 #ddd}#wrap{min-height:100%;height:auto;margin:0 auto -80px;padding:20px 0 80px}#footer{height:80px;background-color:#fff;background-color:rgba(255,255,255,0.9);text-align:center;padding-top:10px;overflow:hidden}#header img{background-color:#fff;background-color:rgba(255,255,255,0.8);margin-bottom:20px}.card,.navbar-light{background-color:#fff;background-color:rgba(255,255,255,0.9);background-image:none}.login,.password{text-align:center;padding:20px}div.form{margin:0 auto;max-width:330px}div.actions{margin:10px 0 0 0}div.actions a{margin-top:10px}.buttons{text-align:center;margin:10px 0 0 0;cursor:pointer}.btn{white-space:normal}.btn span.fa{padding-right:8px}li.ui-state-active{background-color:#fafafa;background-color:rgba(250,250,250,0.9)}#appslist,#password,#loginHistory,#logout,#oidcConsents{margin-top:20px}div.category{margin:10px 0;cursor:grab}div.application{margin:5px 0;overflow:hidden}div.application a,div.application a:hover{text-decoration:none}p.notifCheck label{margin-left:5px;margin-top:3px;display:inline-block}img.langicon{cursor:pointer}button.idploop{max-width:300px}button.idploop img{max-height:30px}div.oidc_consent_message>ul{text-align:left;list-style:circle}@media(min-width:768px){div.application{height:80px}div.application h4.appname{margin:0}#wrap{margin:0 auto -60px}#footer{height:60px}}.hiddenFrame{border:0;display:hidden;margin:0}.noborder{border:0}.max{width:100%}.link{cursor:pointer}.nodecor:hover,.nodecor:active.nodecor:focus{text-decoration:none}.fa.icon-blue{color:blue} html,body{height:100%;background:radial-gradient(circle at 50% 0,#fff 0,#ddd 100%) no-repeat scroll 0 0 #ddd}#wrap{min-height:100%;height:auto;margin:0 auto -80px;padding:20px 0 80px}#footer{height:80px;background-color:#fff;background-color:rgba(255,255,255,0.9);text-align:center;padding-top:10px;overflow:hidden}#header img{background-color:#fff;background-color:rgba(255,255,255,0.8);margin-bottom:20px}.card,.navbar-light{background-color:#fff;background-color:rgba(255,255,255,0.9);background-image:none}.login,.password{text-align:center;padding:20px}div.form{margin:0 auto;max-width:330px}div.actions{margin:10px 0 0 0}div.actions a{margin-top:10px}.buttons{text-align:center;margin:10px 0 0 0;cursor:pointer}.btn{white-space:normal}.btn span.fa{padding-right:8px}li.ui-state-active{background-color:#fafafa;background-color:rgba(250,250,250,0.9)}#appslist,#password,#loginHistory,#logout,#oidcConsents{margin-top:20px}div.category{margin:10px 0;cursor:grab}div.application{margin:5px 0;overflow:hidden}div.application a,div.application a:hover{text-decoration:none}p.notifCheck label{margin-left:5px;margin-top:3px;display:inline-block}img.langicon{cursor:pointer}button.idploop{max-width:300px}button.idploop img{max-height:30px}div.oidc_consent_message>ul{text-align:left;list-style:circle}@media(min-width:768px){div.application{height:80px}div.application h4.appname{margin:0}#wrap{margin:0 auto -60px}#footer{height:60px}}.hiddenFrame{border:0;display:hidden;margin:0}.noborder{border:0}.max{width:100%}.link{cursor:pointer}.nodecor:hover,.nodecor:active.nodecor:focus{text-decoration:none}.fa.icon-blue{color:blue}.progress-bar-animated{width:100%}

View File

@ -172,7 +172,7 @@
"noU2FKeyFound":"No U2F key found", "noU2FKeyFound":"No U2F key found",
"oidcConsent":"التطبيق ٪s هل ترغب في معرفة:", "oidcConsent":"التطبيق ٪s هل ترغب في معرفة:",
"oidcConsents":"OIDC consents", "oidcConsents":"OIDC consents",
"oidcConsentsFull":"OpenID-Connect consents", "oidcConsentsFull":"OpenID Connect consents",
"openidAp":"هل توافق على تقديم الإعدادات التالية؟", "openidAp":"هل توافق على تقديم الإعدادات التالية؟",
"openIdExample":"فمثلا:http://myopenid.org/toto", "openIdExample":"فمثلا:http://myopenid.org/toto",
"openidExchange":"هل تريد مصادقة نفسك على٪ s؟", "openidExchange":"هل تريد مصادقة نفسك على٪ s؟",

View File

@ -172,7 +172,7 @@
"noU2FKeyFound":"Kein U2F Schlüssel gefunden", "noU2FKeyFound":"Kein U2F Schlüssel gefunden",
"oidcConsent":"Die Anwendung %s möchte wissen:", "oidcConsent":"Die Anwendung %s möchte wissen:",
"oidcConsents":"OIDC consents", "oidcConsents":"OIDC consents",
"oidcConsentsFull":"OpenID-Connect consents", "oidcConsentsFull":"OpenID Connect consents",
"openidAp":"Stimmst du folgenden Parametern zu ?", "openidAp":"Stimmst du folgenden Parametern zu ?",
"openIdExample":"zum Beispiel: http://myopenid.org/toto", "openIdExample":"zum Beispiel: http://myopenid.org/toto",
"openidExchange":"Willst du dich bei %s authentifizieren ?", "openidExchange":"Willst du dich bei %s authentifizieren ?",

View File

@ -45,12 +45,12 @@
"PE53":"SAML message destination is not correct", "PE53":"SAML message destination is not correct",
"PE54":"SAML message conditions are not respected", "PE54":"SAML message conditions are not respected",
"PE55":"Identity provider initiated single sign on is not authorized", "PE55":"Identity provider initiated single sign on is not authorized",
"PE56":"An error occured during SAML single logout", "PE56":"An error occurred during SAML single logout",
"PE57":"Error in SAML message signature management", "PE57":"Error in SAML message signature management",
"PE58":"An error occured during SAML artifact use", "PE58":"An error occurred during SAML artifact use",
"PE59":"Communication error with SAML sessions", "PE59":"Communication error with SAML sessions",
"PE60":"Problem when loading a service provider", "PE60":"Problem when loading a service provider",
"PE61":"An error occured during SAML attributes exchange", "PE61":"An error occurred during SAML attributes exchange",
"PE62":"This is an OpenID endpoint page", "PE62":"This is an OpenID endpoint page",
"PE63":"You try to use an OpenID identity which is not yours", "PE63":"You try to use an OpenID identity which is not yours",
"PE64":"A required attribute is not available", "PE64":"A required attribute is not available",
@ -172,13 +172,13 @@
"noU2FKeyFound": "No U2F key found", "noU2FKeyFound": "No U2F key found",
"oidcConsent":"The application %s would like to know:", "oidcConsent":"The application %s would like to know:",
"oidcConsents": "OIDC consents", "oidcConsents": "OIDC consents",
"oidcConsentsFull":"OpenID-Connect consents", "oidcConsentsFull":"OpenID Connect consents",
"openidAp":"Do you agree to provide the following parameters?", "openidAp":"Do you agree to provide the following parameters?",
"openIdExample":"for example:http://myopenid.org/toto", "openIdExample":"for example:http://myopenid.org/toto",
"openidExchange":"Do you want to authenticate yourself on %s ?", "openidExchange":"Do you want to authenticate yourself on %s ?",
"openidPA":"Data usage policy is available at", "openidPA":"Data usage policy is available at",
"openidRpns":"Parameter %s requested for federation isn't available", "openidRpns":"Parameter %s requested for federation isn't available",
"openSessionSpace":"This space allow you to open a SSO session. This will help you to securely access to all applications authorized by your profil.", "openSessionSpace":"This space allow you to open a SSO session. This will help you to securely access to all applications authorized by your profile.",
"openSSOSession":"Open your SSO session", "openSSOSession":"Open your SSO session",
"otherSessions":"Other active sessions", "otherSessions":"Other active sessions",
"password": "Password", "password": "Password",

View File

@ -172,13 +172,13 @@
"noU2FKeyFound":"No U2F key found", "noU2FKeyFound":"No U2F key found",
"oidcConsent":"The application %s would like to know:", "oidcConsent":"The application %s would like to know:",
"oidcConsents":"OIDC consents", "oidcConsents":"OIDC consents",
"oidcConsentsFull":"OpenID-Connect consents", "oidcConsentsFull":"OpenID Connect consents",
"openidAp":"Do you agree to provide the following parameters?", "openidAp":"Do you agree to provide the following parameters?",
"openIdExample":"for example:http://myopenid.org/toto", "openIdExample":"for example:http://myopenid.org/toto",
"openidExchange":"Do you want to authenticate yourself on %s ?", "openidExchange":"Do you want to authenticate yourself on %s ?",
"openidPA":"Data usage policy is available at", "openidPA":"Data usage policy is available at",
"openidRpns":"Parameter %s requested for federation isn't available", "openidRpns":"Parameter %s requested for federation isn't available",
"openSessionSpace":"This space allow you to open a SSO session. This will help you to securely access to all applications authorized by your profil.", "openSessionSpace":"This space allow you to open a SSO session. This will help you to securely access to all applications authorized by your profile.",
"openSSOSession":"Open your SSO session", "openSSOSession":"Open your SSO session",
"otherSessions":"Other active sessions", "otherSessions":"Other active sessions",
"password":"Password", "password":"Password",

View File

@ -45,12 +45,12 @@
"PE53":"SAML message destination is not correct", "PE53":"SAML message destination is not correct",
"PE54":"SAML message conditions are not respected", "PE54":"SAML message conditions are not respected",
"PE55":"Identity provider initiated single sign on is not authorized", "PE55":"Identity provider initiated single sign on is not authorized",
"PE56":"An error occured during SAML single logout", "PE56":"An error occurred during SAML single logout",
"PE57":"Error in SAML message signature management", "PE57":"Error in SAML message signature management",
"PE58":"An error occured during SAML artifact use", "PE58":"An error occurred during SAML artifact use",
"PE59":"Communication error with SAML sessions", "PE59":"Communication error with SAML sessions",
"PE60":"Problem when loading a service provider", "PE60":"Problem when loading a service provider",
"PE61":"An error occured during SAML attributes exchange", "PE61":"An error occurred during SAML attributes exchange",
"PE62":"This is an OpenID endpoint page", "PE62":"This is an OpenID endpoint page",
"PE63":"You try to use an OpenID identity which is not yours", "PE63":"You try to use an OpenID identity which is not yours",
"PE64":"A required attribute is not available", "PE64":"A required attribute is not available",
@ -172,13 +172,13 @@
"noU2FKeyFound":"No U2F key found", "noU2FKeyFound":"No U2F key found",
"oidcConsent":"The application %s would like to know:", "oidcConsent":"The application %s would like to know:",
"oidcConsents":"OIDC consents", "oidcConsents":"OIDC consents",
"oidcConsentsFull":"OpenID-Connect consents", "oidcConsentsFull":"OpenID Connect consents",
"openidAp":"Do you agree to provide the following parameters?", "openidAp":"Do you agree to provide the following parameters?",
"openIdExample":"for example:http://myopenid.org/toto", "openIdExample":"for example:http://myopenid.org/toto",
"openidExchange":"Do you want to authenticate yourself on %s ?", "openidExchange":"Do you want to authenticate yourself on %s ?",
"openidPA":"Data usage policy is available at", "openidPA":"Data usage policy is available at",
"openidRpns":"Parameter %s requested for federation isn't available", "openidRpns":"Parameter %s requested for federation isn't available",
"openSessionSpace":"This space allow you to open a SSO session. This will help you to securely access to all applications authorized by your profil.", "openSessionSpace":"This space allow you to open a SSO session. This will help you to securely access to all applications authorized by your profile.",
"openSSOSession":"Open your SSO session", "openSSOSession":"Open your SSO session",
"otherSessions":"Other active sessions", "otherSessions":"Other active sessions",
"password":"Salasana", "password":"Salasana",

View File

@ -77,7 +77,7 @@
"PE85":"Le site souhaite une authentification plus récente (et le plugin UpgradeSession n'est pas chargé). Déconnectez-vous et réessayez", "PE85":"Le site souhaite une authentification plus récente (et le plugin UpgradeSession n'est pas chargé). Déconnectez-vous et réessayez",
"PE86":"Votre compte est verrouillé. Vous devez attendre 30s avant de vous ré-authentifier.", "PE86":"Votre compte est verrouillé. Vous devez attendre 30s avant de vous ré-authentifier.",
"PE87":"Vous devez vous ré-authentifier pour pouvoir accéder au Portail", "PE87":"Vous devez vous ré-authentifier pour pouvoir accéder au Portail",
"PE88":"une addresse email doit être renseignée pour pouvoir utiliser l'authentification à double facteurs.", "PE88":"une adresse email doit être renseignée pour pouvoir utiliser l'authentification à double facteurs.",
"PE89":"Accès non autorisé au service SAML", "PE89":"Accès non autorisé au service SAML",
"PE90":"Accès non autorisé au service OIDC", "PE90":"Accès non autorisé au service OIDC",
"PE91":"Accès non autorisé au service OID", "PE91":"Accès non autorisé au service OID",
@ -172,7 +172,7 @@
"noU2FKeyFound": "Aucune clef U2F trouvée", "noU2FKeyFound": "Aucune clef U2F trouvée",
"oidcConsent":"L'application %s voudrait connaître :", "oidcConsent":"L'application %s voudrait connaître :",
"oidcConsents": "Accords OIDC", "oidcConsents": "Accords OIDC",
"oidcConsentsFull":"Accords OpenID-Connect", "oidcConsentsFull":"Accords OpenID Connect",
"openidAp":"Consentez-vous à communiquer les paramètres suivants ?", "openidAp":"Consentez-vous à communiquer les paramètres suivants ?",
"openIdExample":"par exemple : http://myopenid.org/toto", "openIdExample":"par exemple : http://myopenid.org/toto",
"openidExchange":"Souhaitez-vous vous identifier sur le site %s ?", "openidExchange":"Souhaitez-vous vous identifier sur le site %s ?",

View File

@ -172,7 +172,7 @@
"noU2FKeyFound":"Nessuna chiave U2F trovata", "noU2FKeyFound":"Nessuna chiave U2F trovata",
"oidcConsent":"L'applicazione %s vorrebbe sapere:", "oidcConsent":"L'applicazione %s vorrebbe sapere:",
"oidcConsents":"Consensi OIDC", "oidcConsents":"Consensi OIDC",
"oidcConsentsFull":"Consensi OpenID-Connect", "oidcConsentsFull":"Consensi OpenID Connect",
"openidAp":"Accetti di fornire i seguenti parametri?", "openidAp":"Accetti di fornire i seguenti parametri?",
"openIdExample":"per esempio:http://myopenid.org/toto", "openIdExample":"per esempio:http://myopenid.org/toto",
"openidExchange":"Vuoi autenticarti su% s?", "openidExchange":"Vuoi autenticarti su% s?",

View File

@ -172,13 +172,13 @@
"noU2FKeyFound":"No U2F key found", "noU2FKeyFound":"No U2F key found",
"oidcConsent":"The application %s would like to know:", "oidcConsent":"The application %s would like to know:",
"oidcConsents":"OIDC consents", "oidcConsents":"OIDC consents",
"oidcConsentsFull":"OpenID-Connect consents", "oidcConsentsFull":"OpenID Connect consents",
"openidAp":"Do you agree to provide the following parameters?", "openidAp":"Do you agree to provide the following parameters?",
"openIdExample":"for example:http://myopenid.org/toto", "openIdExample":"for example:http://myopenid.org/toto",
"openidExchange":"Do you want to authenticate yourself on %s ?", "openidExchange":"Do you want to authenticate yourself on %s ?",
"openidPA":"Data usage policy is available at", "openidPA":"Data usage policy is available at",
"openidRpns":"Parameter %s requested for federation isn't available", "openidRpns":"Parameter %s requested for federation isn't available",
"openSessionSpace":"This space allow you to open a SSO session. This will help you to securely access to all applications authorized by your profil.", "openSessionSpace":"This space allow you to open a SSO session. This will help you to securely access to all applications authorized by your profile.",
"openSSOSession":"Open your SSO session", "openSSOSession":"Open your SSO session",
"otherSessions":"Other active sessions", "otherSessions":"Other active sessions",
"password":"Password", "password":"Password",

View File

@ -172,13 +172,13 @@
"noU2FKeyFound":"No U2F key found", "noU2FKeyFound":"No U2F key found",
"oidcConsent":"The application %s would like to know:", "oidcConsent":"The application %s would like to know:",
"oidcConsents":"OIDC consents", "oidcConsents":"OIDC consents",
"oidcConsentsFull":"OpenID-Connect consents", "oidcConsentsFull":"OpenID Connect consents",
"openidAp":"Do you agree to provide the following parameters?", "openidAp":"Do you agree to provide the following parameters?",
"openIdExample":"for example:http://myopenid.org/toto", "openIdExample":"for example:http://myopenid.org/toto",
"openidExchange":"Do you want to authenticate yourself on %s ?", "openidExchange":"Do you want to authenticate yourself on %s ?",
"openidPA":"Data usage policy is available at", "openidPA":"Data usage policy is available at",
"openidRpns":"Parameter %s requested for federation isn't available", "openidRpns":"Parameter %s requested for federation isn't available",
"openSessionSpace":"This space allow you to open a SSO session. This will help you to securely access to all applications authorized by your profil.", "openSessionSpace":"This space allow you to open a SSO session. This will help you to securely access to all applications authorized by your profile.",
"openSSOSession":"Open your SSO session", "openSSOSession":"Open your SSO session",
"otherSessions":"Other active sessions", "otherSessions":"Other active sessions",
"password":"Password", "password":"Password",

View File

@ -172,13 +172,13 @@
"noU2FKeyFound":"No U2F key found", "noU2FKeyFound":"No U2F key found",
"oidcConsent":"The application %s would like to know:", "oidcConsent":"The application %s would like to know:",
"oidcConsents":"OIDC consents", "oidcConsents":"OIDC consents",
"oidcConsentsFull":"OpenID-Connect consents", "oidcConsentsFull":"OpenID Connect consents",
"openidAp":"Do you agree to provide the following parameters?", "openidAp":"Do you agree to provide the following parameters?",
"openIdExample":"for example:http://myopenid.org/toto", "openIdExample":"for example:http://myopenid.org/toto",
"openidExchange":"Do you want to authenticate yourself on %s ?", "openidExchange":"Do you want to authenticate yourself on %s ?",
"openidPA":"Data usage policy is available at", "openidPA":"Data usage policy is available at",
"openidRpns":"Parameter %s requested for federation isn't available", "openidRpns":"Parameter %s requested for federation isn't available",
"openSessionSpace":"This space allow you to open a SSO session. This will help you to securely access to all applications authorized by your profil.", "openSessionSpace":"This space allow you to open a SSO session. This will help you to securely access to all applications authorized by your profile.",
"openSSOSession":"Open your SSO session", "openSSOSession":"Open your SSO session",
"otherSessions":"Other active sessions", "otherSessions":"Other active sessions",
"password":"Password", "password":"Password",

View File

@ -172,7 +172,7 @@
"noU2FKeyFound":"No U2F key found", "noU2FKeyFound":"No U2F key found",
"oidcConsent":"Ứng dụng %s muốn biết:", "oidcConsent":"Ứng dụng %s muốn biết:",
"oidcConsents":"OIDC consents", "oidcConsents":"OIDC consents",
"oidcConsentsFull":"OpenID-Connect consents", "oidcConsentsFull":"OpenID Connect consents",
"openidAp":"Bạn đồng ý cung cấp các thông số sau?", "openidAp":"Bạn đồng ý cung cấp các thông số sau?",
"openIdExample":"ví dụ: http: //myopenid.org/toto", "openIdExample":"ví dụ: http: //myopenid.org/toto",
"openidExchange":"Bạn có muốn chứng thực mình trên%s không?", "openidExchange":"Bạn có muốn chứng thực mình trên%s không?",

View File

@ -45,12 +45,12 @@
"PE53":"SAML message destination is not correct", "PE53":"SAML message destination is not correct",
"PE54":"SAML message conditions are not respected", "PE54":"SAML message conditions are not respected",
"PE55":"Identity provider initiated single sign on is not authorized", "PE55":"Identity provider initiated single sign on is not authorized",
"PE56":"An error occured during SAML single logout", "PE56":"An error occurred during SAML single logout",
"PE57":"Error in SAML message signature management", "PE57":"Error in SAML message signature management",
"PE58":"An error occured during SAML artifact use", "PE58":"An error occurred during SAML artifact use",
"PE59":"Communication error with SAML sessions", "PE59":"Communication error with SAML sessions",
"PE60":"Problem when loading a service provider", "PE60":"Problem when loading a service provider",
"PE61":"An error occured during SAML attributes exchange", "PE61":"An error occurred during SAML attributes exchange",
"PE62":"This is an OpenID endpoint page", "PE62":"This is an OpenID endpoint page",
"PE63":"You try to use an OpenID identity which is not yours", "PE63":"You try to use an OpenID identity which is not yours",
"PE64":"所需 attribute 不可用", "PE64":"所需 attribute 不可用",
@ -172,13 +172,13 @@
"noU2FKeyFound":"No U2F key found", "noU2FKeyFound":"No U2F key found",
"oidcConsent":"The application %s would like to know:", "oidcConsent":"The application %s would like to know:",
"oidcConsents":"OIDC consents", "oidcConsents":"OIDC consents",
"oidcConsentsFull":"OpenID-Connect consents", "oidcConsentsFull":"OpenID Connect consents",
"openidAp":"您是否同意提供以下参数?", "openidAp":"您是否同意提供以下参数?",
"openIdExample":"例如http://myopenid.org/toto", "openIdExample":"例如http://myopenid.org/toto",
"openidExchange":"Do you want to authenticate yourself on %s ?", "openidExchange":"Do you want to authenticate yourself on %s ?",
"openidPA":"数据使用条约可在此处了解", "openidPA":"数据使用条约可在此处了解",
"openidRpns":"Parameter %s requested for federation isn't available", "openidRpns":"Parameter %s requested for federation isn't available",
"openSessionSpace":"This space allow you to open a SSO session. This will help you to securely access to all applications authorized by your profil.", "openSessionSpace":"This space allow you to open a SSO session. This will help you to securely access to all applications authorized by your profile.",
"openSSOSession":"Open your SSO session", "openSSOSession":"Open your SSO session",
"otherSessions":"Other active sessions", "otherSessions":"Other active sessions",
"password":"密码", "password":"密码",

View File

@ -16,7 +16,7 @@ form
</div> </div>
<div class="card-body"> <div class="card-body">
<div class="progress"> <div class="progress">
<div class="progress-bar progress-bar-striped progress-bar-animated" role="progressbar" aria-valuenow="100" aria-valuemin="0" aria-valuemax="100" style="width: 100%"></div> <div class="progress-bar progress-bar-striped progress-bar-animated" role="progressbar" aria-valuenow="100" aria-valuemin="0" aria-valuemax="100"></div>
</div> </div>
<noscript> <noscript>
<div class="message message-warning alert">It appears that your browser does not support Javascript.</div> <div class="message message-warning alert">It appears that your browser does not support Javascript.</div>

View File

@ -41,10 +41,9 @@ ok(
'Auth query' 'Auth query'
); );
count(1); count(1);
ok( ok( $res->[2]->[0] =~ /<span trmsg="5"><\/span><\/div>/,
$res->[2]->[0] =~ /<span trmsg="5"><\/span><\/div>/, 'jdoe rejected with PE_BADCREDENTIALS' )
'jdoe rejected with PE_BADCREDENTIALS' or print STDERR Dumper( $res->[2]->[0] );
) or print STDERR Dumper( $res->[2]->[0] );
count(1); count(1);
ok( $res->[2]->[0] =~ m%<span trspan="connect">Connect</span>%, ok( $res->[2]->[0] =~ m%<span trspan="connect">Connect</span>%,
'Found connect button' ) 'Found connect button' )
@ -63,17 +62,15 @@ ok(
'Auth query' 'Auth query'
); );
count(1); count(1);
ok( ok( $res->[2]->[0] =~ /<span trmsg="5"><\/span><\/div>/,
$res->[2]->[0] =~ /<span trmsg="5"><\/span><\/div>/, 'dwho rejected with PE_BADCREDENTIALS' )
'dwho rejected with PE_BADCREDENTIALS' or print STDERR Dumper( $res->[2]->[0] );
) or print STDERR Dumper( $res->[2]->[0] );
count(1); count(1);
ok( $res->[2]->[0] =~ m%<span trspan="connect">Connect</span>%, ok( $res->[2]->[0] =~ m%<span trspan="connect">Connect</span>%,
'Found connect button' ) 'Found connect button' )
or print STDERR Dumper( $res->[2]->[0] ); or print STDERR Dumper( $res->[2]->[0] );
count(1); count(1);
# Try to authenticate with good password # Try to authenticate with good password
# -------------------------------------- # --------------------------------------
ok( ok(

View File

@ -106,8 +106,7 @@ SKIP: {
$dbh->do( $dbh->do(
"INSERT INTO users VALUES ('jsmith','{ssha512}wr0zU/I6f7U4bVoeOlJnNFbhF0a9np59LUeNnhokohVI/wiNzt8Y4JujfOfNQiGuiVgY+xrYggfmgpke6KdjxKS7W0GR1ZCe','John Smith')" "INSERT INTO users VALUES ('jsmith','{ssha512}wr0zU/I6f7U4bVoeOlJnNFbhF0a9np59LUeNnhokohVI/wiNzt8Y4JujfOfNQiGuiVgY+xrYggfmgpke6KdjxKS7W0GR1ZCe','John Smith')"
); );
my $client = LLNG::Manager::Test->new( my $client = LLNG::Manager::Test->new( {
{
ini => { ini => {
logLevel => 'error', logLevel => 'error',
useSafeJail => 1, useSafeJail => 1,

View File

@ -7,7 +7,7 @@ require 't/test-lib.pm';
my $mainTests = 5; my $mainTests = 5;
SKIP: { SKIP: {
skip "Manual skip of GPG test", $mainTests if ($ENV{LLNG_SKIP_GPG_TEST}); skip "Manual skip of GPG test", $mainTests if ( $ENV{LLNG_SKIP_GPG_TEST} );
eval "use IPC::Run 'run',"; eval "use IPC::Run 'run',";
skip "Missing dependency", $mainTests if ($@); skip "Missing dependency", $mainTests if ($@);
my $gpg = `which gpg`; my $gpg = `which gpg`;

View File

@ -67,10 +67,13 @@ SKIP: {
# IDP must be sorted # IDP must be sorted
my @idp = map /val="http:\/\/(.+?)\/saml\/metadata">/g, $res->[2]->[0]; my @idp = map /val="http:\/\/(.+?)\/saml\/metadata">/g, $res->[2]->[0];
ok( $idp[0] eq 'auth.idp2.com', '1st = idp2' ) or print STDERR Dumper( \@idp ); ok( $idp[0] eq 'auth.idp2.com', '1st = idp2' )
ok( $idp[1] eq 'auth.idp2_z.com', '2nd = idp2_z' ) or print STDERR Dumper( \@idp ); or print STDERR Dumper( \@idp );
ok( $idp[2] eq 'auth.idp3.com', '3rd = idp3' ) or print STDERR Dumper( \@idp ); ok( $idp[1] eq 'auth.idp2_z.com', '2nd = idp2_z' )
ok( $idp[3] eq 'auth.idp.com', '4th= idp' ) or print STDERR Dumper( \@idp ); or print STDERR Dumper( \@idp );
ok( $idp[2] eq 'auth.idp3.com', '3rd = idp3' )
or print STDERR Dumper( \@idp );
ok( $idp[3] eq 'auth.idp.com', '4th= idp' ) or print STDERR Dumper( \@idp );
ok( ok(
$res->[2]->[0] =~ $res->[2]->[0] =~

View File

@ -132,7 +132,7 @@ m#img src="http://auth.idp.com(/saml/relaySingleLogoutSOAP)\?(relay=.*?)"#s,
), ),
'Get image' 'Get image'
); );
expectRedirection( $res, "http://auth.idp.com/static/common/icons/ok.png"); expectRedirection( $res, "http://auth.idp.com/static/common/icons/ok.png" );
# Test if logout is done # Test if logout is done
switch ('issuer'); switch ('issuer');

View File

@ -27,12 +27,19 @@ SKIP: {
ok( $res = $issuer->_get('/saml/metadata/idp'), 'Get IDP metadata' ); ok( $res = $issuer->_get('/saml/metadata/idp'), 'Get IDP metadata' );
ok( $res->[2]->[0] =~ m#^<\?xml version="1.0"\?>#s, 'Metadata is XML' ); ok( $res->[2]->[0] =~ m#^<\?xml version="1.0"\?>#s, 'Metadata is XML' );
ok( $res->[2]->[0] !~ m#<SPSSODescriptor#s, 'Metadata does not contain SP information' ); ok(
ok( $res->[2]->[0] =~ m#entityID="urn:example\.com"#s, 'IDP EntityID is overriden' ); $res->[2]->[0] !~ m#<SPSSODescriptor#s,
'Metadata does not contain SP information'
);
ok( $res->[2]->[0] =~ m#entityID="urn:example\.com"#s,
'IDP EntityID is overriden' );
ok( $res = $issuer->_get('/saml/metadata/sp'), 'Get SP metadata' ); ok( $res = $issuer->_get('/saml/metadata/sp'), 'Get SP metadata' );
ok( $res->[2]->[0] =~ m#^<\?xml version="1.0"\?>#s, 'Metadata is XML' ); ok( $res->[2]->[0] =~ m#^<\?xml version="1.0"\?>#s, 'Metadata is XML' );
ok( $res->[2]->[0] !~ m#<IDPSSODescriptor#s, 'Metadata does not contain IDP information' ); ok(
$res->[2]->[0] !~ m#<IDPSSODescriptor#s,
'Metadata does not contain IDP information'
);
#print STDERR Dumper($res); #print STDERR Dumper($res);
} }
@ -44,14 +51,14 @@ done_testing( count() );
sub issuer { sub issuer {
return LLNG::Manager::Test->new( { return LLNG::Manager::Test->new( {
ini => { ini => {
logLevel => $debug, logLevel => $debug,
domain => 'idp.com', domain => 'idp.com',
portal => 'http://auth.idp.com', portal => 'http://auth.idp.com',
authentication => 'Demo', authentication => 'Demo',
userDB => 'Same', userDB => 'Same',
issuerDBSAMLActivation => 1, issuerDBSAMLActivation => 1,
samlOverrideIDPEntityID => 'urn:example.com', samlOverrideIDPEntityID => 'urn:example.com',
samlSPMetaDataOptions => { samlSPMetaDataOptions => {
'sp.com' => { 'sp.com' => {
samlSPMetaDataOptionsEncryptionMode => 'none', samlSPMetaDataOptionsEncryptionMode => 'none',
samlSPMetaDataOptionsSignSSOMessage => 1, samlSPMetaDataOptionsSignSSOMessage => 1,

View File

@ -141,7 +141,7 @@ m#iframe src="http://auth.sp.com(/saml/proxySingleLogout)\?(SAMLRequest=.*?)"#,
switch ('issuer'); switch ('issuer');
ok( $res = $issuer->_get( $url, query => $query, accept => 'text/html' ), ok( $res = $issuer->_get( $url, query => $query, accept => 'text/html' ),
'Push SAML response to IdP' ); 'Push SAML response to IdP' );
expectRedirection($res, 'http://auth.idp.com/static/common/icons/ok.png'); expectRedirection( $res, 'http://auth.idp.com/static/common/icons/ok.png' );
ok( getHeader( $res, 'Content-Security-Policy' ) !~ /frame-ancestors/, ok( getHeader( $res, 'Content-Security-Policy' ) !~ /frame-ancestors/,
' Frame can be embedded' ) ' Frame can be embedded' )
or explain( $res->[1], or explain( $res->[1],

View File

@ -341,13 +341,13 @@ sub op {
oidcServiceAllowAuthorizationCodeFlow => 1, oidcServiceAllowAuthorizationCodeFlow => 1,
oidcRPMetaDataOptions => { oidcRPMetaDataOptions => {
rp => { rp => {
oidcRPMetaDataOptionsDisplayName => "RP", oidcRPMetaDataOptionsDisplayName => "RP",
oidcRPMetaDataOptionsIDTokenExpiration => 3600, oidcRPMetaDataOptionsIDTokenExpiration => 3600,
oidcRPMetaDataOptionsClientID => "rpid", oidcRPMetaDataOptionsClientID => "rpid",
oidcRPMetaDataOptionsIDTokenSignAlg => "RS512", oidcRPMetaDataOptionsIDTokenSignAlg => "RS512",
oidcRPMetaDataOptionsBypassConsent => 0, oidcRPMetaDataOptionsBypassConsent => 0,
oidcRPMetaDataOptionsPublic => 1, oidcRPMetaDataOptionsPublic => 1,
oidcRPMetaDataOptionsUserIDAttr => "", oidcRPMetaDataOptionsUserIDAttr => "",
oidcRPMetaDataOptionsAccessTokenExpiration => 3600, oidcRPMetaDataOptionsAccessTokenExpiration => 3600,
oidcRPMetaDataOptionsPostLogoutRedirectUris => oidcRPMetaDataOptionsPostLogoutRedirectUris =>
"http://auth.rp.com/?logout=1" "http://auth.rp.com/?logout=1"

View File

@ -80,7 +80,7 @@ expectOK($res);
my $metadata = $res->[2]->[0]; my $metadata = $res->[2]->[0];
count(3); count(3);
switch('rp'); switch ('rp');
&Lemonldap::NG::Handler::Main::cfgNum( 0, 0 ); &Lemonldap::NG::Handler::Main::cfgNum( 0, 0 );
ok( $rp = rp( $jwks, $metadata ), 'RP portal' ); ok( $rp = rp( $jwks, $metadata ), 'RP portal' );
count(1); count(1);

View File

@ -76,7 +76,7 @@ sub iniCmb {
useSafeJail => 1, useSafeJail => 1,
authentication => 'Combination', authentication => 'Combination',
userDB => 'Same', userDB => 'Same',
combination => $expr, combination => $expr,
combModules => { combModules => {
DB => { DB => {

View File

@ -116,7 +116,7 @@ SKIP: {
query => $query, query => $query,
accept => 'text/html', accept => 'text/html',
# cookie => 'lemonldapidp=http://auth.idp.com/saml/metadata' # cookie => 'lemonldapidp=http://auth.idp.com/saml/metadata'
), ),
"Push request to OP, endpoint $url" "Push request to OP, endpoint $url"
); );
@ -129,7 +129,7 @@ SKIP: {
ok( ok(
$res = $sp->_get( $res = $sp->_get(
"/", "/",
query => "idp=".uri_escape("http://auth.idp.com/saml/metadata"), query => "idp=" . uri_escape("http://auth.idp.com/saml/metadata"),
accept => 'text/html', accept => 'text/html',
cookie => $spPdata, cookie => $spPdata,
), ),
@ -138,9 +138,6 @@ SKIP: {
$spPdata = 'lemonldappdata=' . expectCookie( $res, 'lemonldappdata' ); $spPdata = 'lemonldappdata=' . expectCookie( $res, 'lemonldappdata' );
my ( $host, $tmp ); my ( $host, $tmp );
( $url, $query ) = expectRedirection( $res, ( $url, $query ) = expectRedirection( $res,
qr#^http://auth.idp.com(/saml/singleSignOn)\?(SAMLRequest=.+)# ); qr#^http://auth.idp.com(/saml/singleSignOn)\?(SAMLRequest=.+)# );
@ -433,10 +430,10 @@ sub sp {
userDB => 'Same', userDB => 'Same',
issuerDBSAMLActivation => 0, issuerDBSAMLActivation => 0,
issuerDBOpenIDConnectActivation => 1, issuerDBOpenIDConnectActivation => 1,
samlDiscoveryProtocolURL => 'http://discovery.example.com/', samlDiscoveryProtocolURL => 'http://discovery.example.com/',
samlDiscoveryProtocolActivation => 1, samlDiscoveryProtocolActivation => 1,
oidcRPMetaDataExportedVars => { oidcRPMetaDataExportedVars => {
rp => { rp => {
email => "mail", email => "mail",
family_name => "cn", family_name => "cn",

View File

@ -0,0 +1,84 @@
use Test::More;
use strict;
use IO::String;
require 't/test-lib.pm';
my $res;
my $client = LLNG::Manager::Test->new( {
ini => {
logLevel => 'error',
useSafeJail => 1,
requireToken => '"Bad rule"',
tokenUseGlobalStorage => 1,
}
}
);
# Test normal first access
# ------------------------
ok( $res = $client->_get( '/', accept => 'text/html' ), 'Unauth request' );
count(1);
my ( $host, $url, $query ) = expectForm( $res, '#', undef, 'token' );
ok( $query =~ /token=([^&]+)/, 'Token value' );
count(1);
my $token = $1;
$query =~ "token=$token";
# Try to auth without token
ok(
$res = $client->_post(
'/',
IO::String->new('user=dwho&password=dwho'),
length => 23
),
'Try to auth without token'
);
count(1);
expectReject($res);
# Try token as cookie value
ok( $res = $client->_get( '/', cookie => "lemonldap=$token" ),
'Try token as cookie' );
count(1);
expectReject($res);
# Try to auth with token
$query .= '&user=dwho&password=dwho';
ok(
$res =
$client->_post( '/', IO::String->new($query), length => length($query) ),
'Try to auth with token'
);
count(1);
expectOK($res);
my $id = expectCookie($res);
# Verify auth
ok( $res = $client->_get( '/', cookie => "lemonldap=$id" ), 'Verify auth' );
count(1);
expectOK($res);
# Try to reuse the same token
ok(
$res =
$client->_post( '/', IO::String->new($query), length => length($query) ),
'Try to reuse the same token'
);
expectReject($res);
ok(
$res = $client->_post(
'/', IO::String->new($query),
length => length($query),
accept => 'text/html'
),
'Verify that there is a new token'
);
expectForm( $res, '#', undef, 'token' );
count(2);
clean_sessions();
done_testing( count() );

View File

@ -25,7 +25,8 @@ SKIP: {
portalDisplayRegister => 1, portalDisplayRegister => 1,
registerDB => 'Demo', registerDB => 'Demo',
captcha_register_enabled => 0, captcha_register_enabled => 0,
requireToken => '!$env->{ipAddr} || $env->{ipAddr} ne "127.1.1.1"', requireToken =>
'!$env->{ipAddr} || $env->{ipAddr} ne "127.1.1.1"',
} }
} }
); );

View File

@ -0,0 +1,78 @@
use Test::More;
use strict;
use IO::String;
BEGIN {
eval {
require 't/test-lib.pm';
require 't/smtp.pm';
};
}
my $maintests = 5;
my ( $res, $user, $pwd );
SKIP: {
eval 'require Email::Sender::Simple';
if ($@) {
skip 'Missing dependencies', $maintests;
}
my $client = LLNG::Manager::Test->new( {
ini => {
logLevel => 'error',
useSafeJail => 1,
portalDisplayRegister => 1,
authentication => 'Demo',
userDB => 'Same',
registerDB => 'Demo',
captcha_register_enabled => 0,
tokenUseGlobalStorage => 1,
}
}
);
# Test normal first access
# ------------------------
ok(
$res = $client->_get( '/register', accept => 'text/html' ),
'Unauth request',
);
my ( $host, $url, $query ) =
expectForm( $res, '#', undef, 'firstname', 'lastname', 'mail' );
ok(
$res = $client->_post(
'/register',
IO::String->new(
'firstname=fôo&lastname=bar&mail=foobar%40badwolf.org'),
length => 53,
accept => 'text/html'
),
'Ask to create account'
);
expectOK($res);
my $mail = mail();
ok( $mail =~ m#a href="http://auth.example.com/register\?(.*?)"#,
'Found register token' );
$query = $1;
ok( $query =~ /register_token=([^&]+)/, 'Found register_token' );
my $token = $1;
ok(
$res = $client->_get(
'/',
length => 23,
cookie => "lemonldap=$token",
),
'Try to authenticate'
);
expectReject($res);
}
count($maintests);
clean_sessions();
done_testing( count() );

View File

@ -24,14 +24,14 @@ SKIP: {
my $client = LLNG::Manager::Test->new( { my $client = LLNG::Manager::Test->new( {
ini => { ini => {
logLevel => 'error', logLevel => 'error',
useSafeJail => 1, useSafeJail => 1,
portalDisplayRegister => 1, portalDisplayRegister => 1,
authentication => 'Demo', authentication => 'Demo',
userDB => 'Same', userDB => 'Same',
passwordDB => 'Demo', passwordDB => 'Demo',
captcha_mail_enabled => 0, captcha_mail_enabled => 0,
requireToken => '$env->{ipAddr} !~ /127\.0\.[1-3]\.1/', requireToken => '$env->{ipAddr} !~ /127\.0\.[1-3]\.1/',
portalDisplayResetPassword => 1, portalDisplayResetPassword => 1,
portalMainLogo => 'common/logos/logo_llng_old.png', portalMainLogo => 'common/logos/logo_llng_old.png',
} }

View File

@ -95,8 +95,7 @@ count(1);
ok( $res->[2]->[0] =~ m%<td class="text-left">_user</td>%, ok( $res->[2]->[0] =~ m%<td class="text-left">_user</td>%,
'Found attribute _user' ) 'Found attribute _user' )
or explain( $res->[2]->[0], 'Attribute _user' ); or explain( $res->[2]->[0], 'Attribute _user' );
ok( $res->[2]->[0] =~ m%<td class="text-left">dwho</td>%, ok( $res->[2]->[0] =~ m%<td class="text-left">dwho</td>%, 'Found value dwho' )
'Found value dwho' )
or explain( $res->[2]->[0], 'Value dwho' ); or explain( $res->[2]->[0], 'Value dwho' );
count(2); count(2);
@ -123,7 +122,7 @@ count(1);
# Request with good VH & user # Request with good VH & user
$query =~ $query =~
s#url=http%3A%2F%2Ftry.example.com#url=hTTp%3A%2F%2FTest1.exAmple.cOm/UriTesT#; s#url=http%3A%2F%2Ftry.example.com#url=hTTp%3A%2F%2FTest1.exAmple.cOm/UriTesT#;
ok( ok(
$res = $client->_post( $res = $client->_post(
@ -141,7 +140,8 @@ count(1);
expectForm( $res, undef, '/checkuser', 'user', 'url' ); expectForm( $res, undef, '/checkuser', 'user', 'url' );
ok( $res->[2]->[0] =~ m%<span trspan="checkUser">%, 'Found trspan="checkUser"' ) ok( $res->[2]->[0] =~ m%<span trspan="checkUser">%, 'Found trspan="checkUser"' )
or explain( $res->[2]->[0], 'trspan="checkUser"' ); or explain( $res->[2]->[0], 'trspan="checkUser"' );
ok( $res->[2]->[0] =~ m%value="http://test1.example.com/UriTesT"%, 'Found well formatted url' ) ok( $res->[2]->[0] =~ m%value="http://test1.example.com/UriTesT"%,
'Found well formatted url' )
or explain( $res->[2]->[0], 'Well formatted url' ); or explain( $res->[2]->[0], 'Well formatted url' );
count(2); count(2);
@ -196,7 +196,8 @@ count(1);
expectForm( $res, undef, '/checkuser', 'user', 'url' ); expectForm( $res, undef, '/checkuser', 'user', 'url' );
ok( $res->[2]->[0] =~ m%<span trspan="checkUser">%, 'Found trspan="checkUser"' ) ok( $res->[2]->[0] =~ m%<span trspan="checkUser">%, 'Found trspan="checkUser"' )
or explain( $res->[2]->[0], 'trspan="checkUser"' ); or explain( $res->[2]->[0], 'trspan="checkUser"' );
ok( $res->[2]->[0] =~ m%value="http://test1.example.com:1234"%, 'Found well formatted url' ) ok( $res->[2]->[0] =~ m%value="http://test1.example.com:1234"%,
'Found well formatted url' )
or explain( $res->[2]->[0], 'Well formatted url' ); or explain( $res->[2]->[0], 'Well formatted url' );
count(2); count(2);

View File

@ -269,7 +269,8 @@ ok( $res->[2]->[0] =~ m%<td class="text-left">testPrefix_groups</td>%,
or explain( $res->[2]->[0], 'testPrefix_groups' ); or explain( $res->[2]->[0], 'testPrefix_groups' );
ok( $res->[2]->[0] =~ m%<td class="text-left">su</td>%, 'Found su' ) ok( $res->[2]->[0] =~ m%<td class="text-left">su</td>%, 'Found su' )
or explain( $res->[2]->[0], 'su' ); or explain( $res->[2]->[0], 'su' );
ok( $res->[2]->[0] =~ m%<td class="text-left">testPrefix_uid</td>%, 'Found testPrefix_uid' ) ok( $res->[2]->[0] =~ m%<td class="text-left">testPrefix_uid</td>%,
'Found testPrefix_uid' )
or explain( $res->[2]->[0], 'testPrefix_groups' ); or explain( $res->[2]->[0], 'testPrefix_groups' );
ok( $res->[2]->[0] =~ m%<td class="text-left">rtyler</td>%, 'Found rtyler' ) ok( $res->[2]->[0] =~ m%<td class="text-left">rtyler</td>%, 'Found rtyler' )
or explain( $res->[2]->[0], 'su' ); or explain( $res->[2]->[0], 'su' );

View File

@ -269,11 +269,12 @@ JjTJecOOS+88fK8qL1TrYv5rapIdqUI7aQ==
or print STDERR Dumper($res); or print STDERR Dumper($res);
# Two 2F devices must be registered # Two 2F devices must be registered
my @sf = map m%<span device=\'(TOTP|U2F)\' epoch=\'\d{10}\'%g, $res->[2]->[0]; my @sf = map m%<span device=\'(TOTP|U2F)\' epoch=\'\d{10}\'%g,
$res->[2]->[0];
ok( scalar @sf == 2, 'Two 2F devices found' ) ok( scalar @sf == 2, 'Two 2F devices found' )
or print STDERR Dumper($res); or print STDERR Dumper($res);
ok( $sf[0] eq 'TOTP', 'TOTP device found' ) or print STDERR Dumper( \@sf ); ok( $sf[0] eq 'TOTP', 'TOTP device found' ) or print STDERR Dumper( \@sf );
ok( $sf[1] eq 'U2F', 'U2F device found' ) or print STDERR Dumper( \@sf ); ok( $sf[1] eq 'U2F', 'U2F device found' ) or print STDERR Dumper( \@sf );
# Unregister TOTP # Unregister TOTP
ok( $res->[2]->[0] =~ qr%TOTP.*epoch.*(\d{10})%m, "TOTP epoch $1 found" ) ok( $res->[2]->[0] =~ qr%TOTP.*epoch.*(\d{10})%m, "TOTP epoch $1 found" )

View File

@ -1,6 +1,6 @@
use IO::Pipe; use IO::Pipe;
use IO::Select; use IO::Select;
our ( $in, $out ) = ( IO::Pipe->new, IO::Pipe->new ); our ( $in, $out ) = ( IO::Pipe->new, IO::Pipe->new );
our ( $rin, $rout ) = ( IO::Pipe->new, IO::Pipe->new ); our ( $rin, $rout ) = ( IO::Pipe->new, IO::Pipe->new );
my $pid = fork; my $pid = fork;
@ -38,20 +38,21 @@ $s->add($rin);
sub handler { sub handler {
my (%args) = @_; my (%args) = @_;
print $in JSON::to_json( $args{req} ) . "\n"; print $in JSON::to_json( $args{req} ) . "\n";
while(my @ready = $s->can_read) { while ( my @ready = $s->can_read ) {
foreach $fh (@ready) { foreach $fh (@ready) {
if($fh == $out) { if ( $fh == $out ) {
my $res = <$out>; my $res = <$out>;
return JSON::from_json($res); return JSON::from_json($res);
} }
else { else {
my $res = <$rin>; my $res = <$rin>;
$res = $args{sub}->(JSON::from_json($res)); $res = $args{sub}->( JSON::from_json($res) );
print $rout JSON::to_json($res)."\n"; print $rout JSON::to_json($res) . "\n";
} }
} }
} }
} }
sub end_handler { sub end_handler {
print $in "END\n"; print $in "END\n";
} }

View File

@ -12,7 +12,7 @@
use LWP::UserAgent; use LWP::UserAgent;
use JSON; use JSON;
my $milestone = '2.0.3'; my $milestone = '2.1.0';
my @cat = ( 'Bug', 'New feature', 'Improvement' ); my @cat = ( 'Bug', 'New feature', 'Improvement' );
open F, "$ENV{HOME}/.ow2-token" or die "Unable to get OW2 token ($!)"; open F, "$ENV{HOME}/.ow2-token" or die "Unable to get OW2 token ($!)";