Merge branch 'v2.0'

This commit is contained in:
Xavier 2019-09-30 23:20:12 +02:00
commit 2323c031ec
54 changed files with 744 additions and 173 deletions

View File

@ -60,6 +60,7 @@ sub defaultValues {
'cspStyle' => '\'self\'',
'dbiAuthnLevel' => 2,
'dbiExportedVars' => {},
'decryptValueRule' => 0,
'demoExportedVars' => {
'cn' => 'cn',
'mail' => 'mail',

View File

@ -800,8 +800,13 @@ sub getKey {
unless ($key) {
return $self->metadata($req);
}
$self->userLogger->info(
'User ' . $self->userId($req) . " asks for key $key" );
if ( $self->can('userId') ) {
$self->userLogger->info(
'User ' . $self->userId($req) . " asks for key $key" );
}
else {
$self->logger->info("REST request to get configuration key $key");
}
my $value = $self->getConfKey( $req, $key );
return $self->sendError( $req, undef, 400 ) if ( $req->error );

View File

@ -55,6 +55,9 @@ t/64-Lemonldap-NG-Handler-PSGI-DevOps.t
t/65-Lemonldap-NG-Handler-PSGI-ServiceToken.t
t/66-Lemonldap-NG-Handler-PSGI-wildcard.t
t/67-Lemonldap-NG-Handler-PSGI-vhostoptions.t
t/68-Lemonldap-NG-Handler-PSGI-Zimbra.t
t/69-Lemonldap-NG-Handler-PSGI-SecureToken.t
t/70-Lemonldap-NG-Handler-PSGI-AuthBasic.t
t/99-pod.t
t/lmConf-1.json
t/sessions/lock/Apache-Session-f5eec18ebb9bc96352595e2d8ce962e8ecf7af7c9a98cb9a43f9cd181cf4b545.lock

View File

@ -15,6 +15,7 @@ our $VERSION = '2.1.0';
our @ISA = ('Exporter');
our @EXPORT = qw(fetchId retrieveSession createSession hideCookie goToPortal);
our @EXPORT_OK = @EXPORT;
our $_ua;
## @rmethod protected fetchId
# Get user session id from Authorization header
@ -162,8 +163,6 @@ sub goToPortal {
}
}
our $_ua;
sub ua {
my ($class) = @_;
return $_ua if ($_ua);
@ -173,7 +172,6 @@ sub ua {
}
);
# TODO: auth basic
return $_ua;
}

View File

@ -8,7 +8,7 @@ sub run {
my ( $class, $req, $rule, $protection ) = @_;
my $uri = $req->{env}->{REQUEST_URI};
my $cn = $class->tsv->{cookieName};
my ( $id, $session );
my ( $id, $ret, $session );
if ( $uri =~ s/[\?&;]${cn}cda=(\w+)$//oi ) {
if ( $id = $class->fetchId($req)
and $session = $class->retrieveSession( $req, $id ) )
@ -48,8 +48,10 @@ sub run {
return $class->REDIRECT;
}
}
return $class->Lemonldap::NG::Handler::Main::run( $req, $rule,
$protection );
( $ret, $session ) =
$class->Lemonldap::NG::Handler::Main::run( $req, $rule, $protection );
return $ret;
}
## @rmethod protected hash getCDAInfos(id)

View File

@ -32,7 +32,7 @@ BEGIN {
# @return Apache2::Const value ($class->OK, $class->FORBIDDEN, $class->REDIRECT or $class->SERVER_ERROR)
sub run {
my $class = shift;
my $r = $_[0];
my $r = shift;
my ( $ret, $session ) = $class->Lemonldap::NG::Handler::Main::run($r);
# Continue only if user is authorized
@ -106,7 +106,7 @@ sub run {
# Remove token
eval 'use Apache2::Filter' unless ( $INC{"Apache2/Filter.pm"} );
if ( $INC{"Apache2/Filter.pm"} ) {
if ( $INC{"Apache2/Filter.pm"} and defined $r->{env}->{'psgi.r'} ) {
$r->{env}->{'psgi.r'}->add_output_filter(
sub {
my $f = shift;
@ -121,7 +121,6 @@ sub run {
);
}
# Return $class->OK
return $class->OK;
}
@ -150,9 +149,7 @@ sub _createMemcachedConnection {
# @return Token key
sub _setToken {
my ( $class, $value, $secureTokenExpiration ) = @_;
my $key = Apache::Session::Generate::MD5::generate();
my $res =
$secureTokenMemcachedConnection->set( $key, $value,
$secureTokenExpiration );
@ -173,7 +170,6 @@ sub _setToken {
# @return result
sub _deleteToken {
my ( $class, $key ) = @_;
my $res = $secureTokenMemcachedConnection->delete($key);
unless ($res) {
@ -192,16 +188,13 @@ sub _deleteToken {
# @return result
sub _isAlive {
my ($class) = @_;
return 0 unless defined $secureTokenMemcachedConnection;
my $stats = $secureTokenMemcachedConnection->stats();
if ( $stats and defined $stats->{'total'} ) {
my $total_c = $stats->{'total'}->{'connection_structures'};
my $total_i = $stats->{'total'}->{'total_items'};
$class->logger->debug->(
$class->logger->debug(
"Memcached connection is alive ($total_c connections / $total_i items)"
);

View File

@ -98,9 +98,10 @@ sub portalConsts {
'92' => 'PE_GET_SERVICE_NOT_ALLOWED',
'93' => 'PE_IMPERSONATION_SERVICE_NOT_ALLOWED',
'94' => 'PE_ISSUERMISSINGREQATTR',
'95' => 'PE_RESETCERTIFICATE_INVALID',
'96' => 'PE_RESETCERTIFICATE_FORMEMPTY',
'97' => 'PE_RESETCERTIFICATE_FIRSTACCESS'
'95' => 'PE_DECRYPTVALUE_SERVICE_NOT_ALLOWED',
'96' => 'PE_RESETCERTIFICATE_INVALID',
'97' => 'PE_RESETCERTIFICATE_FORMEMPTY',
'98' => 'PE_RESETCERTIFICATE_FIRSTACCESS'
};
}

View File

@ -15,7 +15,7 @@ my $dir = dirname( abs_path($0) );
print $ini "[all]
logger = Lemonldap::NG::Common::Logger::Std
logLeval = error
logLevel = error
[configuration]
type=File
dirName=$dir
@ -32,7 +32,6 @@ open STDERR, '>/dev/null';
# Insert your test code below, the Test::More module is used here so read
# its man page ( perldoc Test::More ) for help writing this test script.
SKIP: {
eval { require Cache::Memcached };
skip

View File

@ -15,6 +15,7 @@ my $dir = dirname( abs_path($0) );
print $ini "[all]
logger = Lemonldap::NG::Common::Logger::Std
logLevel = error
[configuration]
type=File
dirName=$dir

View File

@ -0,0 +1,82 @@
use Test::More;
BEGIN {
require 't/test-psgi-lib.pm';
}
my $maintests = 8;
SKIP: {
eval { require Digest::HMAC_SHA1; };
if ($@) {
skip 'Digest::HMAC_SHA1 not found', $maintests;
}
init(
'Lemonldap::NG::Handler::Server',
{
logLevel => 'error',
zimbraPreAuthKey => '1234567890',
zimbraUrl => '/service/preauthtest',
zimbraSsoUrl => '^/testsso',
vhostOptions => {
'test1.example.com' => {
vhostHttps => 0,
vhostPort => 80,
vhostMaintenance => 0,
vhostServiceTokenTTL => -1,
},
},
exportedHeaders => {
'test1.example.com' => {
'Auth-User' => '$uid',
},
}
}
);
# Request a non-Zimbra URL
ok(
$res = $client->_get(
'/test', undef,
'test1.example.com', "lemonldap=$sessionId",
VHOSTTYPE => 'ZimbraPreAuth',
),
'Non-Zimbra URL Query'
);
ok( $res->[0] == 200, 'Code is 200' ) or explain( $res->[0], 200 );
# Check headers
%h = @{ $res->[1] };
ok( !defined $h{'Location'}, 'Location is undefined' )
or explain( \%h, 'Location => "URL"' );
ok( $h{'Auth-User'} eq 'dwho', 'Header Auth-User is set to "dwho"' )
or explain( \%h, 'Auth-User => "dwho"' );
# Request Zimbra URL
my $timestamp = time() * 1000;
my $value =
Digest::HMAC_SHA1::hmac_sha1_hex( "dwho|id|0|$timestamp", '1234567890' );
ok(
$res = $client->_get(
'/testsso', undef,
'test1.example.com', "lemonldap=$sessionId",
VHOSTTYPE => 'ZimbraPreAuth',
),
'Zimbra URL Query'
);
ok( $res->[0] == 302, 'Code is 302' ) or explain( $res->[0], 302 );
# Check headers
%h = @{ $res->[1] };
ok(
$h{'Location'} =~
m%^/service/preauthtest\?account=dwho&by=id&timestamp=$timestamp&expires=0&preauth=$value$%,
'Header Location is set to Zimbra URL'
) or explain( \%h, 'Location => "Zimbra URL"' );
ok( $h{'Auth-User'} eq 'dwho', 'Header Auth-User is set to "dwho"' )
or explain( \%h, 'Auth-User => "dwho"' );
}
count($maintests);
done_testing( count() );
clean();

View File

@ -0,0 +1,99 @@
use Test::More;
BEGIN {
require 't/test-psgi-lib.pm';
}
my $maintests = 12;
SKIP: {
eval { require Cache::Memcached; };
if ($@) {
skip 'Cache::Memcached not found', $maintests;
}
eval { require Apache::Session::Generate::MD5; };
if ($@) {
skip 'Apache::Session::Generate::MD5 not found', $maintests;
}
init(
'Lemonldap::NG::Handler::Server',
{
logLevel => 'error',
secureTokenUrls => [ '^/secured$', '/test$' ],
secureTokenHeader => 'AuthToken',
vhostOptions => {
'test1.example.com' => {
vhostHttps => 0,
vhostPort => 80,
vhostMaintenance => 0,
vhostServiceTokenTTL => -1,
},
},
exportedHeaders => {
'test1.example.com' => {
'Auth-User' => '$uid',
},
}
}
);
## Request secured URLs
# First URL
ok(
$res = $client->_get(
'/secured', undef,
'test1.example.com', "lemonldap=$sessionId",
VHOSTTYPE => 'SecureToken',
),
'Auth secured URL query 1'
);
ok( $res->[0] == 200, 'Code is 200' ) or explain( $res->[0], 200 );
# Check headers
%h = @{ $res->[1] };
ok( $h{'AuthToken'} =~ m%[0-9a-f]{32}%, 'Header "AuthToken" found' )
or explain( \%h, 'AuthToken => "md5 value"' );
ok( $h{'Auth-User'} eq 'dwho', 'Header Auth-User is set to "dwho"' )
or explain( \%h, 'Auth-User => "dwho"' );
# Second URL
ok(
$res = $client->_get(
'/try/test', undef,
'test1.example.com', "lemonldap=$sessionId",
VHOSTTYPE => 'SecureToken',
),
'Auth secured URL query 2'
);
ok( $res->[0] == 200, 'Code is 200' ) or explain( $res->[0], 200 );
# Check headers
%h = @{ $res->[1] };
ok( $h{'AuthToken'} =~ m%[0-9a-f]{32}%, 'Header "AuthToken" found' )
or explain( \%h, 'AuthToken => "md5 value"' );
ok( $h{'Auth-User'} eq 'dwho', 'Header Auth-User is set to "dwho"' )
or explain( \%h, 'Auth-User => "dwho"' );
## Request an unsecured URL
ok(
$res = $client->_get(
'/try', undef,
'test1.example.com', "lemonldap=$sessionId",
VHOSTTYPE => 'SecureToken',
),
'Auth unsecured URL query'
);
ok( $res->[0] == 200, 'Code is 200' ) or explain( $res->[0], 200 );
# Check headers
%h = @{ $res->[1] };
ok( !defined $h{'AuthToken'}, 'Header "AuthToken" not found' )
or explain( \%h, 'AuthToken => "md5 value"' );
ok( $h{'Auth-User'} eq 'dwho', 'Header Auth-User is set to "dwho"' )
or explain( \%h, 'Auth-User => "dwho"' );
}
count($maintests);
done_testing( count() );
clean();

View File

@ -0,0 +1,68 @@
use Test::More;
use MIME::Base64;
BEGIN {
require 't/test-psgi-lib.pm';
}
my $maintests = 3;
init(
'Lemonldap::NG::Handler::Server',
{
# authentication => 'Demo',
# userDB => 'Same',
# restSessionServer => 1,
logLevel => 'error',
vhostOptions => {
'test1.example.com' => {
vhostHttps => 0,
vhostPort => 80,
vhostMaintenance => 0,
vhostServiceTokenTTL => -1,
},
},
exportedHeaders => {
'test1.example.com' => {
'Auth-User' => '$uid',
},
}
}
);
ok(
$res = $client->_get(
'/', undef, 'test1.example.com', undef, VHOSTTYPE => 'AuthBasic',
),
'Query'
);
ok( $res->[0] == 401, 'Code is 401' ) or explain( $res->[0], 302 );
# Check headers
%h = @{ $res->[1] };
ok(
$h{'WWW-Authenticate'} =~ m%^Basic realm="LemonLDAP::NG"$%,
'Header WWW-Authenticate is set to Basic realm="LemonLDAP::NG"'
) or explain( \%h, 'WWW-Authenticate => realm' );
# my $login = encode_base64("dwho:dwho");
# ok(
# $res = $client->_get(
# '/', undef, 'test1.example.com', undef,
# VHOSTTYPE => 'AuthBasic',
# HTTP_X_FORWARDED_FOR => '127.0.0.1',
# HTTP_AUTHORIZATION => "Basic $login"
# ),
# 'AuthBasic query'
# );
#
# print STDERR Data::Dumper::Dumper($res);
#
# # Check headers
# %h = @{ $res->[1] };
# ok( $h{'Auth-User'} eq 'dwho', 'Header Auth-User is set to "dwho"' )
# or explain( \%h, 'Auth-User => "dwho"' );
count($maintests);
done_testing( count() );
clean();

View File

@ -1139,6 +1139,10 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.]
'dbiUserUser' => {
'type' => 'text'
},
'decryptValueRule' => {
'default' => 0,
'type' => 'boolOrExpr'
},
'demoExportedVars' => {
'default' => {
'cn' => 'cn',

View File

@ -534,6 +534,12 @@ sub attributes {
documentation => 'Stop context switching by logout',
flags => 'p',
},
decryptValueRule => {
type => 'boolOrExpr',
default => 0,
documentation => 'Decrypt value activation rule',
flags => 'p',
},
skipRenewConfirmation => {
type => 'bool',
default => 0,

View File

@ -102,9 +102,10 @@ sub portalConstants {
PE_GET_SERVICE_NOT_ALLOWED => 92,
PE_IMPERSONATION_SERVICE_NOT_ALLOWED => 93,
PE_ISSUERMISSINGREQATTR => 94,
PE_RESETCERTIFICATE_INVALID => 95,
PE_RESETCERTIFICATE_FORMEMPTY => 96,
PE_RESETCERTIFICATE_FIRSTACCESS => 97,
PE_DECRYPTVALUE_SERVICE_NOT_ALLOWED => 95,
PE_RESETCERTIFICATE_INVALID => 96,
PE_RESETCERTIFICATE_FORMEMPTY => 97,
PE_RESETCERTIFICATE_FIRSTACCESS => 98,
};
}

View File

@ -753,6 +753,14 @@ sub tree {
'contextSwitchingStopWithLogout',
]
},
{
title => 'decryptValue',
help => 'decryptValueRule.html',
form => 'simpleInputContainer',
nodes => [
'decryptValueRule',
]
},
]
},
{

View File

@ -245,6 +245,8 @@
"dbiPasswordMailCol":"اسم حقل البريد",
"dbiSchema":"مخطط",
"dbiUserTable":"جدول المستخدم",
"decryptValue":"Decrypt value",
"decryptValueRule":"Use rule",
"default":"الاعْتيادي",
"defaultRule":"القاعدة الاعتيادية ",
"demoModeOn":"هذا المدير يعمل في طريقة العرض",

View File

@ -244,6 +244,8 @@
"dbiPasswordMailCol":"Mail field name",
"dbiSchema":"Schema",
"dbiUserTable":"User table",
"decryptValue":"Decrypt value",
"decryptValueRule":"Use rule",
"default":"Default",
"defaultRule":"Default rule",
"demoModeOn":"This manager runs in demo mode",

View File

@ -244,6 +244,8 @@
"dbiPasswordMailCol":"Mail field name",
"dbiSchema":"Schema",
"dbiUserTable":"User table",
"decryptValue":"Decrypt value",
"decryptValueRule":"Use rule",
"default":"Default",
"defaultRule":"Default rule",
"demoModeOn":"This manager runs in demo mode",

View File

@ -244,6 +244,8 @@
"dbiPasswordMailCol":"Champ mail",
"dbiSchema":"Schéma",
"dbiUserTable":"Table des utilisateurs",
"decryptValue":"Déchiffrement",
"decryptValueRule":"Règle d'utilisation",
"default":"Défaut",
"defaultRule":"Règle par défaut",
"demoModeOn":"Ce manager fonctionne en mode Demo",

View File

@ -244,6 +244,8 @@
"dbiPasswordMailCol":"Nome del campo di posta",
"dbiSchema":"Schema",
"dbiUserTable":"Tabella utente",
"decryptValue":"Decrypt value",
"decryptValueRule":"Use rule",
"default":"Predefinito",
"defaultRule":"Regola predefinita",
"demoModeOn":"Questo gestore viene eseguito in modalità demo",

View File

@ -244,6 +244,8 @@
"dbiPasswordMailCol":"Tên trường thư",
"dbiSchema":"Giản đồ",
"dbiUserTable":"Bảng người dùng",
"decryptValue":"Decrypt value",
"decryptValueRule":"Use rule",
"default":"Mặc định",
"defaultRule":"Quy tắc mặc định",
"demoModeOn":"Trình quản lý này chạy ở chế độ demo",

View File

@ -244,6 +244,8 @@
"dbiPasswordMailCol":"Mail field name",
"dbiSchema":"Schema",
"dbiUserTable":"用户表",
"decryptValue":"Decrypt value",
"decryptValueRule":"Use rule",
"default":"默认",
"defaultRule":"默认规则",
"demoModeOn":"This manager runs in demo mode",

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -106,6 +106,7 @@ lib/Lemonldap/NG/Portal/Plugins/CertificateResetByMail.pm
lib/Lemonldap/NG/Portal/Plugins/CheckState.pm
lib/Lemonldap/NG/Portal/Plugins/CheckUser.pm
lib/Lemonldap/NG/Portal/Plugins/ContextSwitching.pm
lib/Lemonldap/NG/Portal/Plugins/DecryptValue.pm
lib/Lemonldap/NG/Portal/Plugins/FavApps.pm
lib/Lemonldap/NG/Portal/Plugins/ForceAuthn.pm
lib/Lemonldap/NG/Portal/Plugins/GrantSession.pm
@ -377,6 +378,7 @@ site/templates/bootstrap/customhead.tpl
site/templates/bootstrap/customheader.tpl
site/templates/bootstrap/customLoginFooter.tpl
site/templates/bootstrap/customLoginHeader.tpl
site/templates/bootstrap/decryptvalue.tpl
site/templates/bootstrap/error.tpl
site/templates/bootstrap/ext2fcheck.tpl
site/templates/bootstrap/footer.tpl
@ -431,6 +433,7 @@ site/templates/common/mail/en.json
site/templates/common/mail/fi.json
site/templates/common/mail/fr.json
site/templates/common/mail/it.json
site/templates/common/mail/ms.json
site/templates/common/mail/vi.json
site/templates/common/mail/zh_CN.json
site/templates/common/mail_2fcode.tpl

View File

@ -1510,7 +1510,7 @@ sub getIDP {
if ( $idpName eq $idpConfKey ) {
$idp = $_;
$self->logger->debug(
"IDP $idp found from idpName URL Parameter ($idpName)");
"IDP $idp selected from idpName URL Parameter ($idpName)");
last;
}
}
@ -1518,7 +1518,7 @@ sub getIDP {
# Case 3: Recover IDP from cookie
if ( !$idp and $idp = $idp_cookie ) {
$self->logger->debug("IDP $idp found in IDP resolution cookie");
$self->logger->debug("IDP $idp selected from IDP resolution cookie");
}
# Case 4: check all IDP resolution rules
@ -1526,19 +1526,19 @@ sub getIDP {
else {
foreach ( keys %{ $self->idpList } ) {
my $idpConfKey = $self->idpList->{$_}->{confKey};
my $cond = $self->idpRules->{$idpConfKey} or next;
my $cond = $self->idpRules->{$_} or next;
if ( $cond->( $req, $req->sessionInfo ) ) {
$self->logger->debug(
"IDP $idpConfKey resolution rule match");
"IDP $idpConfKey selected from resolution rule");
$idp = $_;
last;
}
}
}
$self->logger->debug('No IDP found') unless ($idp);
$self->logger->debug('No IDP selected') unless ($idp);
}
else {
$self->logger->debug("IDP $idp found from idp URL Parameter");
$self->logger->debug("IDP $idp selected from idp URL Parameter");
}
# Case 6: auto select IDP if only one IDP defined

View File

@ -85,7 +85,11 @@ sub storeEnvAndCheckGateway {
$self->logger->debug(
"Gateway mode requested, redirect without authentication");
$req->response( [ 302, [ Location => $service ], [] ] );
$req->pdata( {} );
for my $s ( $self->ipath, $self->ipath . 'Path' ) {
$self->logger->debug("Removing $s from pdata")
if delete $req->pdata->{$s};
}
return PE_SENDRESPONSE;
}

View File

@ -98,9 +98,10 @@ use constant {
PE_GET_SERVICE_NOT_ALLOWED => 92,
PE_IMPERSONATION_SERVICE_NOT_ALLOWED => 93,
PE_ISSUERMISSINGREQATTR => 94,
PE_RESETCERTIFICATE_INVALID => 95,
PE_RESETCERTIFICATE_FORMEMPTY => 96,
PE_RESETCERTIFICATE_FIRSTACCESS => 97,
PE_DECRYPTVALUE_SERVICE_NOT_ALLOWED => 95,
PE_RESETCERTIFICATE_INVALID => 96,
PE_RESETCERTIFICATE_FORMEMPTY => 97,
PE_RESETCERTIFICATE_FIRSTACCESS => 98,
};
sub portalConsts {
@ -195,9 +196,10 @@ sub portalConsts {
'92' => 'PE_GET_SERVICE_NOT_ALLOWED',
'93' => 'PE_IMPERSONATION_SERVICE_NOT_ALLOWED',
'94' => 'PE_ISSUERMISSINGREQATTR',
'95' => 'PE_RESETCERTIFICATE_INVALID',
'96' => 'PE_RESETCERTIFICATE_FORMEMPTY',
'97' => 'PE_RESETCERTIFICATE_FIRSTACCESS'
'95' => 'PE_DECRYPTVALUE_SERVICE_NOT_ALLOWED',
'96' => 'PE_RESETCERTIFICATE_INVALID',
'97' => 'PE_RESETCERTIFICATE_FORMEMPTY',
'98' => 'PE_RESETCERTIFICATE_FIRSTACCESS'
};
}
@ -296,6 +298,7 @@ our @EXPORT_OK = (
'PE_GET_SERVICE_NOT_ALLOWED',
'PE_IMPERSONATION_SERVICE_NOT_ALLOWED',
'PE_ISSUERMISSINGREQATTR',
'PE_DECRYPTVALUE_SERVICE_NOT_ALLOWED',
'PE_RESETCERTIFICATE_INVALID',
'PE_RESETCERTIFICATE_FORMEMPTY',
'PE_RESETCERTIFICATE_FIRSTACCESS'

View File

@ -140,24 +140,24 @@ sub init {
# psgi.js
->addUnauthRoute( 'psgi.js' => 'sendJs', ['GET'] )
->addAuthRoute( 'psgi.js' => 'sendJs', ['GET'] )
->addAuthRoute( 'psgi.js' => 'sendJs', ['GET'] )
# portal.css
->addUnauthRoute( 'portal.css' => 'sendCss', ['GET'] )
->addAuthRoute( 'portal.css' => 'sendCss', ['GET'] )
->addAuthRoute( 'portal.css' => 'sendCss', ['GET'] )
# lmerror
->addUnauthRoute( lmerror => { ':code' => 'lmError' }, ['GET'] )
->addAuthRoute( lmerror => { ':code' => 'lmError' }, ['GET'] )
->addAuthRoute( lmerror => { ':code' => 'lmError' }, ['GET'] )
# Core REST API
->addUnauthRoute( ping => 'pleaseAuth', ['GET'] )
->addUnauthRoute( ping => 'pleaseAuth', ['GET'] )
->addAuthRoute( ping => 'authenticated', ['GET'] )
# Refresh session
->addAuthRoute( refresh => 'refresh', ['GET'] )
->addAuthRoute( '*' => 'corsPreflight', ['OPTIONS'] )
->addAuthRoute( '*' => 'corsPreflight', ['OPTIONS'] )
->addUnauthRoute( '*' => 'corsPreflight', ['OPTIONS'] )
# Logout
@ -356,11 +356,18 @@ sub reloadConf {
# Clean $req->pdata after authentication
push @{ $self->endAuth }, sub {
unless ( $_[0]->pdata->{keepPdata} ) {
$self->logger->debug('Cleaning pdata');
$_[0]->pdata( {} );
$self->userLogger->notice( $_[0]->user . ' connected' )
if $_[0]->user;
my $tmp = $_[0]->pdata->{keepPdata} //= [];
foreach my $k ( keys %{ $_[0]->pdata } ) {
unless ( grep { $_ eq $k } @$tmp ) {
$self->logger->debug("Removing $k from pdata");
delete $_[0]->pdata->{$k};
}
}
$self->userLogger->notice( $_[0]->user . ' connected' ) if $_[0]->user;
if (@$tmp) {
$self->logger->debug(
'Add ' . join( ',', @$tmp ) . ' in keepPdata' );
$_[0]->pdata->{keepPdata} = $tmp;
}
return PE_OK;
};

View File

@ -34,9 +34,10 @@ has _ott => (
is => 'rw',
lazy => 1,
default => sub {
my $ott = $_[0]->{p}->loadModule('::Lib::OneTimeToken');
my $timeout = $_[0]->{conf}->{issuersTimeout} // $_[0]->{conf}->{formTimeout};
$ott->timeout( $timeout );
my $ott = $_[0]->{p}->loadModule('::Lib::OneTimeToken');
my $timeout = $_[0]->{conf}->{issuersTimeout}
// $_[0]->{conf}->{formTimeout};
$ott->timeout($timeout);
return $ott;
}
);
@ -86,7 +87,9 @@ sub _redirect {
$self->logger->debug('Processing _redirect');
$ir = $req->pdata->{ $self->ipath } ||= $self->storeRequest($req);
$req->pdata->{ $self->ipath . 'Path' } = \@path;
$req->pdata->{keepPdata} = 1;
$self->logger->debug(
'Add ' . $self->ipath . ', ' . $self->ipath . 'Path in keepPdata' );
push @{ $req->pdata->{keepPdata} }, $self->ipath, $self->ipath . 'Path';
$req->{urldc} = $self->conf->{portal} . '/' . $self->path;
}
else {
@ -111,8 +114,7 @@ sub _redirect {
# Restore urldc if auth doesn't need to dial with browser
$self->restoreRequest( $req, $ir );
delete $req->pdata->{ $self->ipath };
delete $req->pdata->{ $self->ipath . 'Path' };
$self->cleanPdata($req);
return $self->run( @_, @path );
}
: ()
@ -135,8 +137,9 @@ sub _forAuthUser {
# Clean pdata: keepPdata has been set, so pdata must be cleaned here
$self->logger->debug('Cleaning pdata');
$req->pdata( {} );
$req->urlNotBase64(1) if ( ref($self) =~ /::CAS$/ );
$self->cleanPdata($req);
$req->maybeNotBase64(1) if ( ref($self) =~ /::CAS$/ );
$req->mustRedirect(1);
return $self->p->do(
$req,
@ -151,6 +154,27 @@ sub _forAuthUser {
);
}
sub cleanPdata {
my ( $self, $req ) = @_;
for my $s ( $self->ipath, $self->ipath . 'Path' ) {
if ( $req->pdata->{$s} ) {
$self->logger->debug("Removing $s key from pdata");
delete $req->pdata->{$s};
}
}
if ( $req->pdata->{keepPdata} and ref $req->pdata->{keepPdata} ) {
@{ $req->pdata->{keepPdata} } =
grep {
$_ ne $self->ipath
and $_ ne $self->ipath . 'Path'
? 1
: ( $self->logger->debug("Removing $_ from keepPdata") and 0 )
} @{ $req->pdata->{keepPdata} };
delete $req->pdata->{keepPdata}
unless ( @{ $req->pdata->{keepPdata} } );
}
}
sub storeRequest {
my ( $self, $req ) = @_;
$self->logger->debug('Store issuer request');
@ -191,7 +215,7 @@ qq'<script type="text/javascript" src="$self->{p}->{staticPrefix}/common/js/auto
$req->data->{_url} =
encode_base64( $self->conf->{portal} . $req->path_info, '' );
$req->pdata->{ $self->ipath } = $self->storeRequest($req);
$req->pdata->{keepPdata} = 1;
push @{ $req->pdata->{keepPdata} }, $self->ipath, $self->ipath . 'Path';
return PE_RENEWSESSION;
}

View File

@ -159,7 +159,7 @@ Custom plugins can be inserted in portal by declaring them in
C<lemonldap-ng.ini> file, section C<[portal]>, key C<customPlugins>:
[portal]
customPlugins = My::Plugin1, My::Plugin2
customPlugins = ::My::Plugin1, ::My::Plugin2
Plugins must be valid packages well found in C<@INC>.

View File

@ -29,6 +29,7 @@ our @pList = (
impersonationRule => '::Plugins::Impersonation',
portalDisplayFavApps => '::Plugins::FavApps',
contextSwitchingRule => '::Plugins::ContextSwitching',
decryptValueRule => '::Plugins::DecryptValue'
);
##@method list enabledPlugins

View File

@ -95,12 +95,18 @@ sub controlUrl {
}
else {
if ( $url =~ m#[^A-Za-z0-9\+/=]# ) {
$self->userLogger->error(
"Value must be BASE64 encoded (param: url | value: $url)");
return PE_BADURL;
unless ( $req->maybeNotBase64 ) {
$self->userLogger->error(
"Value must be BASE64 encoded (param: url | value: $url)"
);
return PE_BADURL;
}
$req->{urldc} = $url;
}
else {
$req->{urldc} = decode_base64($url);
$req->{urldc} =~ s/[\r\n]//sg;
}
$req->{urldc} = decode_base64($url);
$req->{urldc} =~ s/[\r\n]//sg;
}
# For logout request, test if Referer comes from an authorized site
@ -153,10 +159,12 @@ sub checkLogout {
sub authLogout {
my ( $self, $req ) = @_;
my $res = $self->_authentication->authLogout($req);
unless ( $res or $req->pdata->{keepPdata} ) {
$self->logger->debug('Cleaning pdata');
$req->pdata( {} );
$self->logger->debug('Cleaning pdata');
my $tmp = $req->pdata->{keepPdata} //= [];
foreach my $k ( keys %{ $req->pdata } ) {
delete $req->pdata->{$k} unless ( grep { $_ eq $k } @$tmp );
}
$req->pdata->{keepPdata} = $tmp if @$tmp;
return $res;
}
@ -309,7 +317,7 @@ sub authenticate {
$req->steps( [
'setSessionInfo', 'setMacros',
'setPersistentSessionInfo', 'storeHistory',
@{ $self->afterData }, sub { PE_BADCREDENTIALS }
@{ $self->afterData }, sub { PE_BADCREDENTIALS }
]
);

View File

@ -57,7 +57,8 @@ has continue => ( is => 'rw' );
has checkLogins => ( is => 'rw' );
# Boolean to indicate that url isn't Base64 encoded
has urlNotBase64 => ( is => 'rw' );
has urlNotBase64 => ( is => 'rw' );
has maybeNotBase64 => ( is => 'rw' );
# Menu error
has menuError => ( is => 'rw' );

View File

@ -59,6 +59,66 @@ sub init {
}
# RUNNING METHODS
sub display {
my ( $self, $req ) = @_;
my ( $attrs, $array_attrs ) = ( {}, [] );
$self->logger->debug("Display current session data...");
$self->userLogger->info("Using spoofed SSO groups if exist")
if ( $self->conf->{impersonationRule} );
$attrs = $req->userData;
# Create an array of hashes for template loop
$self->logger->debug("Delete hidden or empty attributes");
if ( $self->conf->{checkUserDisplayEmptyValues} ) {
foreach my $k ( sort keys %$attrs ) {
# Ignore hidden attributes
push @$array_attrs, { key => $k, value => $attrs->{$k} }
unless ( $self->hAttr =~ /\b$k\b/ );
}
}
else {
foreach my $k ( sort keys %$attrs ) {
# Ignore hidden attributes and empty values
push @$array_attrs, { key => $k, value => $attrs->{$k} }
unless ( $self->hAttr =~ /\b$k\b/ or !$attrs->{$k} );
}
}
# ARRAY_REF = [ A_REF GROUPS, A_REF MACROS, A_REF OTHERS ]
$array_attrs = $self->_splitAttributes($array_attrs);
# Display form
my $params = {
PORTAL => $self->conf->{portal},
MAIN_LOGO => $self->conf->{portalMainLogo},
SKIN => $self->p->getSkin($req),
LANGS => $self->conf->{showLanguages},
MSG => (
$self->{conf}->{impersonationMergeSSOgroups} ? 'checkUserMerged'
: 'checkUser'
),
ALERTE => (
$self->{conf}->{impersonationMergeSSOgroups} ? 'alert-warning'
: 'alert-info'
),
LOGIN => $req->{userData}->{ $self->conf->{whatToTrace} },
ATTRIBUTES => $array_attrs->[2],
MACROS => $array_attrs->[1],
GROUPS => $array_attrs->[0],
TOKEN => (
$self->ottRule->( $req, {} ) ? $self->ott->createToken()
: ''
)
};
return $self->sendJSONresponse( $req, $params ) if ( $req->wantJSON );
# Display form
return $self->p->sendHtml( $req, 'checkuser', params => $params, );
}
sub check {
my ( $self, $req ) = @_;
my ( $attrs, $array_attrs, $array_hdrs ) = ( {}, [], [] );
@ -93,7 +153,7 @@ sub check {
};
return $self->p->sendJSONresponse( $req, $params )
if ( $req->wantJSON );
return $self->p->sendHtml( $req, 'checkuser', params => $params, )
return $self->p->sendHtml( $req, 'checkuser', params => $params )
if $msg;
}
@ -274,65 +334,7 @@ sub check {
return $self->p->sendJSONresponse( $req, $params ) if ( $req->wantJSON );
# Display form
return $self->p->sendHtml( $req, 'checkuser', params => $params, );
}
sub display {
my ( $self, $req ) = @_;
my ( $attrs, $array_attrs ) = ( {}, [] );
$self->logger->debug("Display current session data...");
$self->userLogger->info("Using spoofed SSO groups if exist")
if ( $self->conf->{impersonationRule} );
$attrs = $req->userData;
# Create an array of hashes for template loop
$self->logger->debug("Delete hidden or empty attributes");
if ( $self->conf->{checkUserDisplayEmptyValues} ) {
foreach my $k ( sort keys %$attrs ) {
# Ignore hidden attributes
push @$array_attrs, { key => $k, value => $attrs->{$k} }
unless ( $self->hAttr =~ /\b$k\b/ );
}
}
else {
foreach my $k ( sort keys %$attrs ) {
# Ignore hidden attributes and empty values
push @$array_attrs, { key => $k, value => $attrs->{$k} }
unless ( $self->hAttr =~ /\b$k\b/ or !$attrs->{$k} );
}
}
# ARRAY_REF = [ A_REF GROUPS, A_REF MACROS, A_REF OTHERS ]
$array_attrs = $self->_splitAttributes($array_attrs);
# Display form
my $params = {
PORTAL => $self->conf->{portal},
MAIN_LOGO => $self->conf->{portalMainLogo},
SKIN => $self->p->getSkin($req),
LANGS => $self->conf->{showLanguages},
MSG => (
$self->{conf}->{impersonationMergeSSOgroups} ? 'checkUserMerged'
: 'checkUser'
),
ALERTE => (
$self->{conf}->{impersonationMergeSSOgroups} ? 'alert-warning'
: 'alert-info'
),
LOGIN => $req->{userData}->{ $self->conf->{whatToTrace} },
ATTRIBUTES => $array_attrs->[2],
MACROS => $array_attrs->[1],
GROUPS => $array_attrs->[0],
TOKEN => (
$self->ottRule->( $req, {} ) ? $self->ott->createToken()
: ''
)
};
return $self->sendJSONresponse( $req, $params ) if ( $req->wantJSON );
return $self->p->sendHtml( $req, 'checkuser', params => $params, );
return $self->p->sendHtml( $req, 'checkuser', params => $params );
}
sub _urlFormat {

View File

@ -32,7 +32,7 @@ has ott => (
return $ott;
}
);
has rule => ( is => 'rw', default => sub { 1 } );
has rule => ( is => 'rw', default => sub { 0 } );
has idRule => ( is => 'rw', default => sub { 1 } );
sub init {

View File

@ -0,0 +1,158 @@
package Lemonldap::NG::Portal::Plugins::DecryptValue;
use strict;
use Mouse;
use Lemonldap::NG::Portal::Main::Constants qw(
PE_TOKENEXPIRED
PE_NOTOKEN
PE_DECRYPTVALUE_SERVICE_NOT_ALLOWED
);
our $VERSION = '2.0.7';
extends qw(
Lemonldap::NG::Portal::Main::Plugin
Lemonldap::NG::Portal::Lib::_tokenRule
);
# INITIALIZATION
has rule => ( is => 'rw', default => sub { 0 } );
has ott => (
is => 'rw',
lazy => 1,
default => sub {
my $ott =
$_[0]->{p}->loadModule('Lemonldap::NG::Portal::Lib::OneTimeToken');
$ott->timeout( $_[0]->{conf}->{formTimeout} );
return $ott;
}
);
sub init {
my ($self) = @_;
my $hd = $self->p->HANDLER;
$self->addAuthRoute( decryptvalue => 'run', ['POST'] )
->addAuthRouteWithRedirect( decryptvalue => 'display', ['GET'] );
# Parse activation rule
$self->logger->debug(
'DecryptValue rule -> ' . $self->conf->{decryptValueRule} );
my $rule =
$hd->buildSub( $hd->substitute( $self->conf->{decryptValueRule} ) );
unless ($rule) {
$self->error( 'Bad decryptValue rule -> ' . $hd->tsv->{jail}->error );
return 0;
}
$self->rule($rule);
return 1;
}
# RUNNING METHOD
sub display {
my ( $self, $req ) = @_;
# Check access rules
unless ( $self->rule->( $req, $req->userData ) ) {
$self->userLogger->warn('decryptValue service NOT authorized');
return $self->p->do( $req,
[ sub { PE_DECRYPTVALUE_SERVICE_NOT_ALLOWED } ] );
}
# Display form
my $params = {
PORTAL => $self->conf->{portal},
MAIN_LOGO => $self->conf->{portalMainLogo},
SKIN => $self->p->getSkin($req),
LANGS => $self->conf->{showLanguages},
MSG => 'decryptCipheredValue',
ALERTE => 'alert-warning',
TOKEN => (
$self->ottRule->( $req, {} )
? $self->ott->createToken()
: ''
)
};
return $self->sendJSONresponse( $req, $params ) if ( $req->wantJSON );
# Display form
return $self->p->sendHtml( $req, 'decryptvalue', params => $params );
}
sub run {
my ( $self, $req ) = @_;
my $msg = '';
# Check access rules
unless ( $self->rule->( $req, $req->userData ) ) {
$self->userLogger->warn('decryptValue service NOT authorized');
return $self->p->do( $req,
[ sub { PE_DECRYPTVALUE_SERVICE_NOT_ALLOWED } ] );
}
# Check token
if ( $self->ottRule->( $req, {} ) ) {
my $token = $req->param('token');
unless ($token) {
$self->userLogger->warn('decryptValue try without token');
$msg = PE_NOTOKEN;
$token = $self->ott->createToken();
}
unless ( $self->ott->getToken($token) ) {
$self->userLogger->warn('decryptValue try with expired/bad token');
$msg = PE_TOKENEXPIRED;
$token = $self->ott->createToken();
}
my $params = {
PORTAL => $self->conf->{portal},
MAIN_LOGO => $self->conf->{portalMainLogo},
SKIN => $self->p->getSkin($req),
LANGS => $self->conf->{showLanguages},
MSG => "PE$msg",
ALERTE => 'alert-warning',
TOKEN => $token,
};
return $self->p->sendJSONresponse( $req, $params )
if ( $req->wantJSON );
return $self->p->sendHtml( $req, 'decryptvalue', params => $params )
if $msg;
}
my $cipheredValue = $req->param('cipheredValue') || '';
my $decryptedValue =
$self->p->HANDLER->tsv->{cipher}->decrypt($cipheredValue)
if $cipheredValue;
$self->logger->debug("decryptValue try with : $cipheredValue");
$self->logger->debug("Decrypted value = $decryptedValue") if $decryptedValue;
# Display form
my $params = {
PORTAL => $self->conf->{portal},
MAIN_LOGO => $self->conf->{portalMainLogo},
SKIN => $self->p->getSkin($req),
LANGS => $self->conf->{showLanguages},
MSG => 'decryptCipheredValue',
DECRYPTED => (
$decryptedValue ? $decryptedValue
: 'notAnEncryptedValue'
),
DALERTE => (
$decryptedValue ? 'alert-info'
: 'alert-danger'
),
ALERTE => 'alert-warning',
TOKEN => (
$self->ottRule->( $req, {} ) ? $self->ott->createToken()
: ''
)
};
return $self->p->sendJSONresponse( $req, $params ) if ( $req->wantJSON );
# Display form
return $self->p->sendHtml( $req, 'decryptvalue', params => $params );
}
1;

View File

@ -85,10 +85,10 @@
"PE92":"Access not granted on GET service",
"PE93":"Access not granted on IMPERSONATION service",
"PE94":"A required attribute is not available",
"PE95":"Your certificate is invalid or expires soon",
"PE96":"Please select your new certificate",
"PE95":"Access not granted on DECRYPT service",
"PE96":"Your certificate is invalid or expires soon",
"PE97":"Please select your new certificate",
"PE98":"Please select your new certificate",
"2fRegRequired":"This service requires a double factor authentication. Register a device now, then go back to the portal.",
"accept":"قبول",
"accessDenied":"ليس لديك إذن بالدخول لهذا التطبيق",
@ -118,6 +118,7 @@
"checkUserComputeSession":"Computed session data!",
"choose2f":"Choose your second factor",
"chooseApp":"اختر أحد التطبيقات المسموح لك بالدخول إليها",
"cipheredValue":"Ciphered value",
"clickHere":"الرجاء الضغط هنا",
"clickOnYubikey":"Click on your Yubikey",
"closeSSO":"أغلق جلسة الدخول الموحد (سسو)",
@ -131,6 +132,7 @@
"createAccount":"انشئ حساب",
"currentPwd":"كلمة المرور الحالية",
"date":"تاريخ",
"decryptCipheredValue":"Decrypt a ciphered value",
"enterCred":"الرجاء إدخال بيانات الاعتماد الخاصة بك",
"enterExt2fCode":"تم إرسال رمز إليك. الرجاء إدخاله",
"enterMail2fCode":"A code has been sent to your email address. Please enter it",
@ -181,6 +183,7 @@
"newPassword":"كلمة مرور جديدة",
"newPwdSentTo":"تم إرسال تأكيد إلى عنوان بريدك الإلكتروني.",
"noHistory":"هذا هو أول اتصال، مرحبا بك!",
"notAnEncryptedValue":"It is not an encrypted value",
"notAuthorized":"You're not authorized to do this",
"notFound":"لم يتم العثور: محاولة الدخول إلى صفحة غير متوفرة",
"noTOTPFound":"No TOTP found",

View File

@ -84,10 +84,10 @@
"PE92":"Zugang zum GET-Service nicht genehmigt",
"PE93":"Access not granted on IMPERSONATION service",
"PE94":"A required attribute is not available",
"PE95":"Your certificate is invalid or expires soon",
"PE96":"Please select your new certificate",
"PE95":"Access not granted on DECRYPT service",
"PE96":"Your certificate is invalid or expires soon",
"PE97":"Please select your new certificate",
"PE98":"Please select your new certificate",
"2fRegRequired":"Dieser Dienst benötigt Zwei-Faktor-Authentifizierung. Bitte legen Sie ein Gerät an und gehen dann zum Portal zurück.",
"accept":"Akzeptieren",
"accessDenied":"Sie haben keine Zugriffsberechtigung für diese Anwendung",
@ -117,6 +117,7 @@
"checkUserComputeSession":"Computed session data!",
"choose2f":"Wählen deinen Ihren zweiten Faktor",
"chooseApp":"Wählen Sie eine Anwendung aus, auf die du zugreifen darfst",
"cipheredValue":"Ciphered value",
"clickHere":"Bitte hier klicken",
"clickOnYubikey":"Klicke auf deinen Yubikey",
"closeSSO":"Schließe deine SSO-Sitzung",
@ -130,6 +131,7 @@
"createAccount":"Konto erstellen",
"currentPwd":"Aktuelles Passwort",
"date":"Datum",
"decryptCipheredValue":"Decrypt a ciphered value",
"enterCred":"Bitte geben deine Zugangsdaten ein",
"enterExt2fCode":"Ein Code wurde an dich gesendet. Bitte gebe diesen ein",
"enterMail2fCode":"A code has been sent to your email address. Please enter it",
@ -180,6 +182,7 @@
"newPassword":"Neues Passwort",
"newPwdSentTo":"Eine Bestätigung wurde an deine E-Mail Adresse gesendet.",
"noHistory":"Das ist deine erste Verbindung, willkommen!",
"notAnEncryptedValue":"It is not an encrypted value",
"notAuthorized":"Du bist nicht dazu berechtigt",
"notFound":"Nicht gefunden: Du versuchst, auf eine nicht verfügbare Seite zuzugreifen",
"noTOTPFound":"Kein TOTP gefunden",

View File

@ -84,9 +84,10 @@
"PE92":"Access not granted on GET service",
"PE93":"Access not granted on IMPERSONATION service",
"PE94":"A required attribute is not available",
"PE95":"Your certificate is invalid or expires soon",
"PE96":"Please select your new certificate",
"PE95":"Access not granted on DECRYPT service",
"PE96":"Your certificate is invalid or expires soon",
"PE97":"Please select your new certificate",
"PE98":"Please select your new certificate",
"2fRegRequired":"This service requires a double factor authentication. Register a device now, then go back to the portal.",
"accept":"Accept",
"accessDenied":"You have no access authorization for this application",
@ -117,6 +118,7 @@
"certificateReset":"Reset my certificate",
"choose2f":"Choose your second factor",
"chooseApp":"Choose an application your are allowed to access to",
"cipheredValue":"Ciphered value",
"clickHere":"Please click here",
"clickOnYubikey":"Click on your Yubikey",
"closeSSO":"Close your SSO session",
@ -130,6 +132,7 @@
"createAccount":"Create an account",
"currentPwd":"Current password",
"date":"Date",
"decryptCipheredValue":"Decrypt a ciphered value",
"enterCred":"Please enter your credentials",
"enterExt2fCode":"A code has been sent to you. Please enter it",
"enterMail2fCode":"A code has been sent to your email address. Please enter it",
@ -181,6 +184,7 @@
"newPassword":"New password",
"newPwdSentTo":"A confirmation has been sent to your mail address.",
"noHistory":"This is your first connection, welcome!",
"notAnEncryptedValue":"It is not an encrypted value",
"notAuthorized":"You're not authorized to do this",
"notFound": "Not found: you try to access to an unavailable page",
"noTOTPFound":"No TOTP found",

View File

@ -84,9 +84,10 @@
"PE92":"Acceso no autorizado al servicio GET",
"PE93":"Acceso no concedido al servicio de SUPLANTACIÓN",
"PE94":"Un atributo obligatorio no está presente",
"PE95":"Your certificate is invalid or expires soon",
"PE96":"Please select your new certificate",
"PE95":"Access not granted on DECRYPT service",
"PE96":"Your certificate is invalid or expires soon",
"PE97":"Please select your new certificate",
"PE98":"Please select your new certificate",
"2fRegRequired":"Este servicio necesita la autenticación de dos factores. Registre un dispositivo ahora, luego reingrese al portal.",
"accept":"Aceptar",
"accessDenied":"No está autorizado a acceder a esta aplicación",
@ -116,6 +117,7 @@
"checkUserComputeSession":"¡Datos de sesión calculados!",
"choose2f":"Seleccione su segundo factor",
"chooseApp":"Elija una aplicación a la cual se le está permitido acceder",
"cipheredValue":"Ciphered value",
"clickHere":"Por favor haga clic aquí",
"clickOnYubikey":"Haga clic en su Yubikey",
"closeSSO":"Cierre su sesión SSO",
@ -129,6 +131,7 @@
"createAccount":"Crear una cuenta",
"currentPwd":"Contraseña actual",
"date":"Fecha",
"decryptCipheredValue":"Decrypt a ciphered value",
"enterCred":"Por favor ingrese sus credenciales",
"enterExt2fCode":"Un código le ha sido enviado. Por favor ingréselo ",
"enterMail2fCode":"Un código le ha sido enviado a dirección de e-mail. Por favor ingréselo",
@ -179,6 +182,7 @@
"newPassword":"Contraseña nueva",
"newPwdSentTo":"Una confirmación ha sido enviada a su dirección de e-mail.",
"noHistory":"Esta es su primera conexión, bienvenido.",
"notAnEncryptedValue":"It is not an encrypted value",
"notAuthorized":"Usted no está autorizado a hacer esto",
"notFound":"No encontrado: página no disponible",
"noTOTPFound":"TOTP no encontrado",

View File

@ -84,9 +84,10 @@
"PE92":"Access not granted on GET service",
"PE93":"Access not granted on IMPERSONATION service",
"PE94":"A required attribute is not available",
"PE95":"Your certificate is invalid or expires soon",
"PE96":"Please select your new certificate",
"PE95":"Access not granted on DECRYPT service",
"PE96":"Your certificate is invalid or expires soon",
"PE97":"Please select your new certificate",
"PE98":"Please select your new certificate",
"2fRegRequired":"This service requires a double factor authentication. Register a device now, then go back to the portal.",
"accept":"Hyväksy",
"accessDenied":"Sinulla ei ole käyttöoikeutta tähän sovellukseen",
@ -116,6 +117,7 @@
"checkUserComputeSession":"Computed session data!",
"choose2f":"Choose your second factor",
"chooseApp":"Choose an application your are allowed to access to",
"cipheredValue":"Ciphered value",
"clickHere":"Please click here",
"clickOnYubikey":"Click on your Yubikey",
"closeSSO":"Sulje SSO istuntosi",
@ -129,6 +131,7 @@
"createAccount":"Rekisteröidy",
"currentPwd":"Nykyinen salasana",
"date":"Päivämäärä",
"decryptCipheredValue":"Decrypt a ciphered value",
"enterCred":"Syötä käyttäjätietosi",
"enterExt2fCode":"A code has been sent to you. Please enter it",
"enterMail2fCode":"A code has been sent to your email address. Please enter it",
@ -179,6 +182,7 @@
"newPassword":"Uusi salasana",
"newPwdSentTo":"A confirmation has been sent to your mail address.",
"noHistory":"This is your first connection, welcome!",
"notAnEncryptedValue":"It is not an encrypted value",
"notAuthorized":"You're not authorized to do this",
"notFound":"Not found: you try to access to an unavailable page",
"noTOTPFound":"No TOTP found",

View File

@ -84,9 +84,10 @@
"PE92":"Accès non autorisé au service GET",
"PE93":"Accès non autorisé au service d'Usurpation d'Identité",
"PE94":"Un attribut exigé n'est pas disponible",
"PE95":"votre certificat est invalid ou expire bientot.Veuillez contacter votre administrateur",
"PE96":"Veuillez selectionner votre nouveau certificat",
"PE95":"Accès non autorisé au service de déchiffrement",
"PE96":"votre certificat est invalid ou expire bientot.Veuillez contacter votre administrateur",
"PE97":"Veuillez selectionner votre nouveau certificat",
"PE98":"Veuillez selectionner votre nouveau certificat",
"2fRegRequired":"Ce service requiert une authentification à deux facteurs. Enregistrez un équipement ici et retournez au portail.",
"accept":"Accepter",
"accessDenied":"Vous n'avez pas les droits d'accès à cette application",
@ -116,6 +117,7 @@
"checkUserComputeSession":"Données de session issues d'une évaluation !",
"choose2f":"Choisissez votre second facteur",
"chooseApp":"Choisissez une application à laquelle vous êtes autorisé à accéder",
"cipheredValue":"Valeur cryptée",
"clickHere":"Cliquez ici",
"clickOnYubikey":"Cliquez sur votre Yubikey",
"closeSSO":"Fermer votre Session SSO",
@ -129,6 +131,7 @@
"createAccount":"Créer un compte",
"currentPwd":"Mot de passe actuel",
"date":"Date",
"decryptCipheredValue":"Déchiffrer une valeur cryptée",
"enterCred":"Merci de vous authentifier",
"enterExt2fCode":"Un code vous a été envoyé, entrez-le ici",
"enterMail2fCode":"Un code vous a été envoyé par mail, entrez-le ici",
@ -179,6 +182,7 @@
"newPassword":"Nouveau mot de passe",
"newPwdSentTo":"Une confirmation a été envoyée à votre adresse mail.",
"noHistory":"Ceci est votre première connexion. Bienvenue !",
"notAnEncryptedValue":"Ce n'est pas une valeur cryptée",
"notAuthorized":"Vous n'êtes pas autorisé à faire cette requête",
"notFound": "Non trouvé : vous tentez d'accéder à une page non disponible",
"noTOTPFound":"Aucun secret TOTP trouvé",

View File

@ -84,9 +84,10 @@
"PE92":"Accesso non concesso sul servizio GET",
"PE93":"Accesso non concesso sul servizio IMPERSONATION",
"PE94":"A required attribute is not available",
"PE95":"Your certificate is invalid or expires soon",
"PE96":"Please select your new certificate",
"PE95":"Access not granted on DECRYPT service",
"PE96":"Your certificate is invalid or expires soon",
"PE97":"Please select your new certificate",
"PE98":"Please select your new certificate",
"2fRegRequired":"Questo servizio richiede un'autenticazione a doppio fattore. Registrare un dispositivo ora, quindi tornare al portale.",
"accept":"Accetta",
"accessDenied":"Non hai un'autorizzazione di accesso per questa applicazione",
@ -116,6 +117,7 @@
"checkUserComputeSession":"Computed session data!",
"choose2f":"Scegli il tuo secondo fattore",
"chooseApp":"Scegli un'applicazione alla quale ti è consentito l'accesso",
"cipheredValue":"Ciphered value",
"clickHere":"Per favore clicka qui",
"clickOnYubikey":"Clicca sulla tua Yubikey",
"closeSSO":"Chiudi la sessione SSO",
@ -129,6 +131,7 @@
"createAccount":"Crea un account",
"currentPwd":"Password attuale",
"date":"Data",
"decryptCipheredValue":"Decrypt a ciphered value",
"enterCred":"Inserisci le tue credenziali",
"enterExt2fCode":"Un codice vi é stato inviato. Inseritelo",
"enterMail2fCode":"A code has been sent to your email address. Please enter it",
@ -179,6 +182,7 @@
"newPassword":"Nuova password",
"newPwdSentTo":"Una conferma è stata inviata all'indirizzo di posta elettronica.",
"noHistory":"Questa è la tua prima connessione, benvenuto!",
"notAnEncryptedValue":"It is not an encrypted value",
"notAuthorized":"Non sei autorizzato a farlo",
"notFound":"Non trovato: si tenta di accedere ad una pagina non disponibile",
"noTOTPFound":"Nessun TOTP trovato",

View File

@ -84,9 +84,10 @@
"PE92":"Onbevoegde toegang tot de GET-service",
"PE93":"Access not granted on IMPERSONATION service",
"PE94":"A required attribute is not available",
"PE95":"Your certificate is invalid or expires soon",
"PE96":"Please select your new certificate",
"PE95":"Access not granted on DECRYPT service",
"PE96":"Your certificate is invalid or expires soon",
"PE97":"Please select your new certificate",
"PE98":"Please select your new certificate",
"2fRegRequired":"This service requires a double factor authentication. Register a device now, then go back to the portal.",
"accept":"Accept",
"accessDenied":"You have no access authorization for this application",
@ -116,6 +117,7 @@
"checkUserComputeSession":"Computed session data!",
"choose2f":"Choose your second factor",
"chooseApp":"Choose an application your are allowed to access to",
"cipheredValue":"Ciphered value",
"clickHere":"Please click here",
"clickOnYubikey":"Click on your Yubikey",
"closeSSO":"Close your SSO session",
@ -129,6 +131,7 @@
"createAccount":"Create an account",
"currentPwd":"Current password",
"date":"Date",
"decryptCipheredValue":"Decrypt a ciphered value",
"enterCred":"Please enter your credentials",
"enterExt2fCode":"A code has been sent to you. Please enter it",
"enterMail2fCode":"A code has been sent to your email address. Please enter it",
@ -179,6 +182,7 @@
"newPassword":"New password",
"newPwdSentTo":"A confirmation has been sent to your mail address.",
"noHistory":"This is your first connection, welcome!",
"notAnEncryptedValue":"It is not an encrypted value",
"notAuthorized":"You're not authorized to do this",
"notFound":"Not found: you try to access to an unavailable page",
"noTOTPFound":"No TOTP found",

View File

@ -84,9 +84,10 @@
"PE92":"Acesso não autorizado ao serviço GET",
"PE93":"Access not granted on IMPERSONATION service",
"PE94":"Um atributo exigido não está disponível",
"PE95":"Your certificate is invalid or expires soon",
"PE96":"Please select your new certificate",
"PE95":"Access not granted on DECRYPT service",
"PE96":"Your certificate is invalid or expires soon",
"PE97":"Please select your new certificate",
"PE98":"Please select your new certificate",
"2fRegRequired":"This service requires a double factor authentication. Register a device now, then go back to the portal.",
"accept":"Accept",
"accessDenied":"You have no access authorization for this application",
@ -116,6 +117,7 @@
"checkUserComputeSession":"Computed session data!",
"choose2f":"Choose your second factor",
"chooseApp":"Choose an application your are allowed to access to",
"cipheredValue":"Ciphered value",
"clickHere":"Please click here",
"clickOnYubikey":"Click on your Yubikey",
"closeSSO":"Close your SSO session",
@ -129,6 +131,7 @@
"createAccount":"Create an account",
"currentPwd":"Current password",
"date":"Date",
"decryptCipheredValue":"Decrypt a ciphered value",
"enterCred":"Please enter your credentials",
"enterExt2fCode":"A code has been sent to you. Please enter it",
"enterMail2fCode":"A code has been sent to your email address. Please enter it",
@ -179,6 +182,7 @@
"newPassword":"New password",
"newPwdSentTo":"A confirmation has been sent to your mail address.",
"noHistory":"This is your first connection, welcome!",
"notAnEncryptedValue":"It is not an encrypted value",
"notAuthorized":"You're not authorized to do this",
"notFound":"Not found: you try to access to an unavailable page",
"noTOTPFound":"No TOTP found",

View File

@ -84,9 +84,10 @@
"PE92":"Access not granted on GET service",
"PE93":"Access not granted on IMPERSONATION service",
"PE94":"A required attribute is not available",
"PE95":"Your certificate is invalid or expires soon",
"PE96":"Please select your new certificate",
"PE95":"Access not granted on DECRYPT service",
"PE96":"Your certificate is invalid or expires soon",
"PE97":"Please select your new certificate",
"PE98":"Please select your new certificate",
"2fRegRequired":"This service requires a double factor authentication. Register a device now, then go back to the portal.",
"accept":"Accept",
"accessDenied":"You have no access authorization for this application",
@ -116,6 +117,7 @@
"checkUserComputeSession":"Computed session data!",
"choose2f":"Choose your second factor",
"chooseApp":"Choose an application your are allowed to access to",
"cipheredValue":"Ciphered value",
"clickHere":"Please click here",
"clickOnYubikey":"Click on your Yubikey",
"closeSSO":"Close your SSO session",
@ -129,6 +131,7 @@
"createAccount":"Create an account",
"currentPwd":"Current password",
"date":"Date",
"decryptCipheredValue":"Decrypt a ciphered value",
"enterCred":"Please enter your credentials",
"enterExt2fCode":"A code has been sent to you. Please enter it",
"enterMail2fCode":"A code has been sent to your email address. Please enter it",
@ -179,6 +182,7 @@
"newPassword":"New password",
"newPwdSentTo":"A confirmation has been sent to your mail address.",
"noHistory":"This is your first connection, welcome!",
"notAnEncryptedValue":"It is not an encrypted value",
"notAuthorized":"You're not authorized to do this",
"notFound":"Not found: you try to access to an unavailable page",
"noTOTPFound":"No TOTP found",

View File

@ -84,9 +84,10 @@
"PE92":"Truy cập không được cấp trên dịch vụ GET",
"PE93":"Access not granted on IMPERSONATION service",
"PE94":"Một thuộc tính bắt buộc không có sẵn",
"PE95":"Your certificate is invalid or expires soon",
"PE96":"Please select your new certificate",
"PE95":"Access not granted on DECRYPT service",
"PE96":"Your certificate is invalid or expires soon",
"PE97":"Please select your new certificate",
"PE98":"Please select your new certificate",
"2fRegRequired":"This service requires a double factor authentication. Register a device now, then go back to the portal.",
"accept":"Chấp nhận",
"accessDenied":"Bạn không có quyền truy cập vào ứng dụng này",
@ -116,6 +117,7 @@
"checkUserComputeSession":"Computed session data!",
"choose2f":"Choose your second factor",
"chooseApp":"Chọn một ứng dụng bạn được phép truy cập vào",
"cipheredValue":"Ciphered value",
"clickHere":"Vui lòng nhấp vào đây",
"clickOnYubikey":"Click on your Yubikey",
"closeSSO":"Đóng phiên SSO của bạn",
@ -129,6 +131,7 @@
"createAccount":"Tạo một tài khoản",
"currentPwd":"Mật khẩu hiện tại",
"date":"Ngày",
"decryptCipheredValue":"Decrypt a ciphered value",
"enterCred":"Vui lòng nhập thông tin đăng nhập của bạn",
"enterExt2fCode":"Một mã đã được gửi cho bạn. Hãy nhập nó",
"enterMail2fCode":"A code has been sent to your email address. Please enter it",
@ -179,6 +182,7 @@
"newPassword":"Mật khẩu mới",
"newPwdSentTo":"Một xác nhận đã được gửi đến địa chỉ thư của bạn.",
"noHistory":"Đây là kết nối đầu tiên của bạn, chào mừng!",
"notAnEncryptedValue":"It is not an encrypted value",
"notAuthorized":"You're not authorized to do this",
"notFound":"Không tìm thấy: bạn cố gắng truy cập vào một trang không có sẵn",
"noTOTPFound":"Đăng xuất khỏi các ứng dụng khác",

View File

@ -84,9 +84,10 @@
"PE92":"Access not granted on GET service",
"PE93":"Access not granted on IMPERSONATION service",
"PE94":"A required attribute is not available",
"PE95":"Your certificate is invalid or expires soon",
"PE96":"Please select your new certificate",
"PE95":"Access not granted on DECRYPT service",
"PE96":"Your certificate is invalid or expires soon",
"PE97":"Please select your new certificate",
"PE98":"Please select your new certificate",
"2fRegRequired":"This service requires a double factor authentication. Register a device now, then go back to the portal.",
"accept":"Accept 方法",
"accessDenied":"您无权访问此应用",
@ -116,6 +117,7 @@
"checkUserComputeSession":"Computed session data!",
"choose2f":"Choose your second factor",
"chooseApp":"Choose an application your are allowed to access to",
"cipheredValue":"Ciphered value",
"clickHere":"请点击这里",
"clickOnYubikey":"Click on your Yubikey",
"closeSSO":"Close your SSO session",
@ -129,6 +131,7 @@
"createAccount":"创建账户",
"currentPwd":"当前密码",
"date":"日期",
"decryptCipheredValue":"Decrypt a ciphered value",
"enterCred":"请输入您的认证信息",
"enterExt2fCode":"验证法已发送,请输入",
"enterMail2fCode":"A code has been sent to your email address. Please enter it",
@ -179,6 +182,7 @@
"newPassword":"新密码",
"newPwdSentTo":"确认邮件已发送至您的邮箱",
"noHistory":"欢迎,这是您的首次登陆",
"notAnEncryptedValue":"It is not an encrypted value",
"notAuthorized":"您没有权限进行该项操作",
"notFound":"无法找到:您请求的网页不存在。",
"noTOTPFound":"No TOTP found",

View File

@ -1,9 +1,6 @@
<TMPL_INCLUDE NAME="header.tpl">
<div id="errorcontent" class="container">
<!--
<div class="message message-positive alert"><span trspan="<TMPL_VAR NAME="MSG">"></span></div>
-->
<div class="alert <TMPL_VAR NAME="ALERTE"> alert"><div class="text-center"><span trspan="<TMPL_VAR NAME="MSG">"></span></div></div>
<form id="contextSwitching" action="/switchcontext" method="post" class="password" role="form">
<div class="buttons">
@ -11,7 +8,7 @@
<input type="hidden" name="token" value="<TMPL_VAR NAME="TOKEN">" />
</TMPL_IF>
<TMPL_INCLUDE NAME="impersonation.tpl">
<TMPL_INCLUDE NAME="impersonation.tpl">
<button type="submit" class="btn btn-success">
<span class="fa fa-random"></span>
@ -19,14 +16,7 @@
</button>
</div>
</form>
<div class="buttons">
<!--
<button type="submit" class="btn btn-success">
<span class="fa fa-sign-in"></span>
<span trspan="search">Search</span>
</button>
-->
<a href="<TMPL_VAR NAME="PORTAL_URL">" class="btn btn-primary" role="button">
<span class="fa fa-home"></span>
<span trspan="goToPortal">Go to portal</span>

View File

@ -0,0 +1,38 @@
<TMPL_INCLUDE NAME="header.tpl">
<div id="errorcontent" class="container">
<div class="alert <TMPL_VAR NAME="ALERTE"> alert"><div class="text-center"><span trspan="<TMPL_VAR NAME="MSG">"></span></div></div>
<TMPL_IF NAME="DECRYPTED">
<div class="alert <TMPL_VAR NAME="DALERTE"> alert"><div class="text-center"><span trspan="<TMPL_VAR NAME="DECRYPTED">"></span></div></div>
</TMPL_IF>
<form id="findUser" action="/decryptvalue" method="post" class="password" role="form">
<div class="buttons">
<TMPL_IF NAME="TOKEN">
<input type="hidden" name="token" value="<TMPL_VAR NAME="TOKEN">" />
</TMPL_IF>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-random icon-blue"></i> </span>
</div>
<input name="cipheredValue" type="text" class="form-control" trplaceholder="cipheredValue" autocomplete="off" aria-required="false"/>
</div>
<button type="submit" class="btn btn-success">
<span class="fa fa-search"></span>
<span trspan="search">Search</span>
</button>
</div>
</form>
<div class="buttons">
<a href="<TMPL_VAR NAME="PORTAL_URL">" class="btn btn-primary" role="button">
<span class="fa fa-home"></span>
<span trspan="goToPortal">Go to portal</span>
</a>
</div>
</div>
</div>
<TMPL_INCLUDE NAME="footer.tpl">

View File

@ -1,8 +1,8 @@
<TMPL_IF NAME="SPOOFID">
<div class="input-group mb-3">
<div class="input-group-prepend">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-user icon-blue"></i> </span>
</div>
<input name="spoofId" type="text" class="form-control" trplaceholder="spoofId" aria-required="false"/>
</div>
<input name="spoofId" type="text" class="form-control" trplaceholder="spoofId" aria-required="false"/>
</div>
</TMPL_IF>

View File

@ -134,7 +134,8 @@ SKIP: {
# Expect pdata to be cleared
$pdata = expectCookie( $res, 'lemonldappdata' );
ok( $pdata !~ 'issuerRequestsaml', 'SAML request cleared from pdata' );
ok( $pdata !~ 'issuerRequestsaml', 'SAML request cleared from pdata' )
or explain( $pdata, 'not issuerRequestsaml' );
( $host, $url, $s ) =
expectAutoPost( $res, 'auth.sp.com', '/saml/proxySingleSignOnPost',