Commit a81dbb10 authored by Christophe Maudoux's avatar Christophe Maudoux 🐛

Merge branch 'v2.0'

parents d67f32d2 fab25530
Pipeline #7990 failed with stages
in 22 minutes and 35 seconds
LemonLDAP::NG Core team:
* Maxime BESSON
* David COUTADEUR
* Xavier GUIMARD
* Christophe MAUDOUX
......@@ -9,17 +10,21 @@ Past and present contributors:
* Casimir ANTUNES
* Sébastien BAHLOUL
* Oliver BOIREAU
* Sandro CAZZANIGA
* Jean-Thomas CHECCO
* Sandro CAZZANIGA
* Thomas CHEMINEAU
* François-Xavier DELTOMBE
* Sebastien DIAZ
* Hubert GAULTIER
* Soisik FROGIER
* Gaultier HUBERT
* Eric GERMAN
* Mounir GZADY
* Jérémy KESPITE
* Erwan LEGALL
* Pascal PEJAC
* Daniel RIVIERE
* Antoine ROSIER
* Mame Dieynaba SENE
* Habib ZITOUNI
See http://lemonldap-ng.org/contact#the_team
......@@ -4,18 +4,22 @@ Upstream-Contact: https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/issues
Source: https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/tags?sort=updated_desc
Files: *
Copyright: 2005-2019, Xavier Guimard <yadd@debian.org>
2006-2019, Clement Oudot <clem.oudot@gmail.com>
Copyright: 2005-2020, Xavier Guimard <yadd@debian.org>
2006-2020, Clement Oudot <clem.oudot@gmail.com>
2008, Mikael Ates <mikael.ates@univ-st-etienne.fr>
2008-2011, Thomas Chemineau <thomas.chemineau@gmail.com>
2012-2013, Sandro Cazzaniga <cazzaniga.sandro@gmail.com>
2012-2015, François-Xavier Deltombe <fxdeltombe@gmail.com>
2012-2015, David Coutadeur <david.coutadeur@gmail.com>
2018-2019, Christophe Maudoux <chrmdx@gmail.com>
2005-2019, Gendarmerie nationale <https://www.gendarmerie.interieur.gouv.fr>
2006-2015, LINAGORA <info@linagora.com>
2012-2019, David Coutadeur <david.coutadeur@gmail.com>
2018-2020, Christophe Maudoux <chrmdx@gmail.com>
2019-2020, Maxime Besson <maxime.besson@worteks.com>
2019, Soisik Frogier <soisik.froger@worteks.com>
2019, Mame Dieynaba Sene <msene@linagora.com>
2019, Antoine Rosier <lemonldap@mon-refuge.fr>
2005-2020, Gendarmerie nationale <https://www.gendarmerie.interieur.gouv.fr>
2006-2019, LINAGORA <info@linagora.com>
2015-2018, Savoir-faire Linux <contact@savoirfairelinux.com>
2018-2019, Worteks <info@worteks.com>
2018-2020, Worteks <info@worteks.com>
License: GPL-2+
Files: lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Auth/PAM.pm
......
......@@ -92,6 +92,10 @@ print
print "<li>Connected user: <ul>\n";
print "<li><tt>\$ENV{HTTP_AUTH_USER}</tt>: $ENV{HTTP_AUTH_USER}</li>\n";
print "<li><tt>\$ENV{REMOTE_USER}</tt>: $ENV{REMOTE_USER}</li>\n";
print "</ul><li>Groups: <ul>\n";
for my $grp (split /; /, $ENV{HTTP_AUTH_GROUPS}) {
print "<li>$grp</li>\n";
}
print "</ul></li>\n";
print "</ul>\n";
print
......
......@@ -129,7 +129,7 @@
.\" ========================================================================
.\"
.IX Title "llng-fastcgi-server 8"
.TH llng-fastcgi-server 8 "2020-01-24" "perl v5.26.1" "User Contributed Perl Documentation"
.TH llng-fastcgi-server 8 "2020-03-02" "perl v5.26.1" "User Contributed Perl Documentation"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
......@@ -178,16 +178,10 @@ file to load for custom functions
Plack::Handler engine, default to \s-1FCGI\s0 (see below)
.IP "\-\-plackOptions:" 4
.IX Item "--plackOptions:"
other options to pass to Plack. This multi-valued parameter must have
\&\*(L"key=value\*(R" values.
other options to pass to the Plack handler. This multi-valued parameter must
have \*(L"key=value\*(R" values.
.Sp
Example to use FCGI::ProcManager::Constrained instead of default \s-1FCGI\s0 manager
(FCGI::ProcManager):
.Sp
.Vb 2
\& llng\-fastcgi\-server \-u nobody \-g nobody \-s /run/llng.sock \-e FCGI \-n 10 \e
\& \-\-plackOptions manager=FCGI::ProcManager::Constrained
.Ve
See Plack::Handler::FCGI for a list of options for the default \s-1FCGI\s0 engine
.SH "ENGINES"
.IX Header "ENGINES"
By default, llng-fastcgi-server uses \s-1FCGI\s0 (= Plack::Handler::FCGI). Some
......@@ -195,23 +189,6 @@ other engines can be used:
.SS "\s-1FCGI\s0 (default)"
.IX Subsection "FCGI (default)"
It uses FCGI::ProcManager as manager. Other managers:
.IP "FCGI::ProcManager::Constrained" 4
.IX Item "FCGI::ProcManager::Constrained"
Example to launch it:
.Sp
.Vb 2
\& llng\-fastcgi\-server \-u nobody \-g nobody \-s /run/llng.sock \-e FCGI \-n 10 \e
\& \-\-plackOptions manager=FCGI::ProcManager::Constrained
.Ve
.Sp
You can then set environment values (in /etc/default/llng\-fastcgi\-server file
for example):
.Sp
.Vb 3
\& PM_MAX_REQUESTS=10000
\& PM_SIZECHECK_NUM_REQUESTS=100
\& PM_MAX_SIZE=300000
.Ve
.IP "FCGI::ProcManager::Dynamic" 4
.IX Item "FCGI::ProcManager::Dynamic"
.Vb 2
......
......@@ -24,7 +24,7 @@ use constant MANAGERSECTION => "manager";
use constant SESSIONSEXPLORERSECTION => "sessionsExplorer";
use constant APPLYSECTION => "apply";
our $hashParameters = qr/^(?:(?:l(?:o(?:ca(?:lSessionStorageOption|tionRule)|goutService)|dapExportedVar|wp(?:Ssl)?Opt)|(?:(?:d(?:emo|bi)|facebook|webID)ExportedVa|exported(?:Heade|Va)|issuerDBGetParamete)r|re(?:moteGlobalStorageOption|st2f(?:Verify|Init)Arg|loadUrl)|g(?:r(?:antSessionRule|oup)|lobalStorageOption)|n(?:otificationStorageOption|ginxCustomHandler)|macro)s|o(?:idc(?:S(?:ervice(?:DynamicRegistrationEx(?:portedVar|traClaim)s|MetaDataAuthnContext)|torageOptions)|RPMetaData(?:(?:Option(?:sExtraClaim)?|ExportedVar|Macro)s|Node)|OPMetaData(?:(?:ExportedVar|Option)s|J(?:SON|WKS)|Node))|penIdExportedVars)|s(?:aml(?:S(?:PMetaData(?:(?:ExportedAttribute|Option|Macro)s|Node|XML)|torageOptions)|IDPMetaData(?:(?:ExportedAttribute|Option)s|Node|XML))|essionDataToRemember|laveExportedVars|fExtra)|c(?:as(?:A(?:ppMetaData(?:(?:ExportedVar|Option|Macro)s|Node)|ttributes)|S(?:rvMetaData(?:(?:ExportedVar|Option)s|Node)|torageOptions))|(?:ustom(?:Plugins|Add)Param|ombModule)s)|p(?:ersistentStorageOptions|o(?:rtalSkinRules|st))|a(?:ut(?:hChoiceMod|oSigninR)ules|pplicationList)|v(?:hostOptions|irtualHost)|S(?:MTPTLSOpts|SLVarIf))$/;
our $boolKeys = qr/^(?:s(?:aml(?:IDP(?:MetaDataOptions(?:(?:Check(?:S[LS]OMessageSignatur|Audienc|Tim)|IsPassiv)e|A(?:llow(?:LoginFromIDP|ProxiedAuthn)|daptSessionUtime)|Force(?:Authn|UTF8)|StoreSAMLToken|RelayStateURL)|SSODescriptorWantAuthnRequestsSigned)|S(?:P(?:MetaDataOptions(?:(?:CheckS[LS]OMessageSignatur|OneTimeUs)e|EnableIDPInitiatedURL|ForceUTF8)|SSODescriptor(?:WantAssertion|AuthnRequest)sSigned)|erviceUseCertificateInResponse)|DiscoveryProtocol(?:Activation|IsPassive)|CommonDomainCookieActivation|UseQueryStringSpecific|MetadataForceUTF8)|ingle(?:Session(?:UserByIP)?|(?:UserBy)?IP)|oap(?:Session|Config)Server|t(?:ayConnecte|orePasswor)d|kipRenewConfirmation|fRemovedUseNotif|laveDisplayLogo|howLanguages|slByAjax)|o(?:idc(?:RPMetaDataOptions(?:Re(?:freshToken|quirePKCE)|LogoutSessionRequired|IDTokenForceClaims|BypassConsent|AllowOffline|Public)|ServiceAllow(?:(?:AuthorizationCode|Implicit|Hybrid)Flow|DynamicRegistration)|OPMetaDataOptions(?:(?:CheckJWTSignatur|UseNonc)e|StoreIDToken))|ldNotifFormat)|p(?:ortal(?:Display(?:Re(?:setPassword|gister)|GeneratePassword|PasswordPolicy)|ErrorOn(?:ExpiredSession|MailNotFound)|(?:CheckLogin|Statu)s|OpenLinkInNewWindow|RequireOldPassword|ForceAuthn|AntiFrame)|roxyUseSoap)|c(?:a(?:ptcha_(?:register|login|mail)_enabled|sSrvMetaDataOptions(?:Gateway|Renew))|heck(?:User(?:Display(?:PersistentInfo|EmptyValues))?|State|XSS)|o(?:ntextSwitchingStopWithLogout|mpactConf|rsEnabled)|da)|l(?:dap(?:(?:Group(?:DecodeSearchedValu|Recursiv)|UsePasswordResetAttribut)e|(?:AllowResetExpired|Set)Password|ChangePasswordAsUser|PpolicyControl|ITDS)|oginHistoryEnabled)|no(?:tif(?:ication(?:Server(?:(?:POS|GE)T|DELETE)?|sExplorer)?|y(?:Deleted|Other))|AjaxHook)|i(?:ssuerDB(?:OpenID(?:Connect)?|SAML|CAS|Get)Activation|mpersonationSkipEmptyValues)|to(?:tp2f(?:UserCan(?:Chang|Remov)eKey|DisplayExistingSecret)|kenUseGlobalStorage)|u(?:se(?:RedirectOn(?:Forbidden|Error)|SafeJail)|2fUserCanRemoveKey|pgradeSession)|br(?:uteForceProtection(?:IncrementalTempo)?|owsersDontStorePassword)|re(?:st(?:(?:Session|Config)Server|ExportSecretKeys)|freshSessions)|(?:mai(?:lOnPasswordChang|ntenanc)|vhostMaintenanc)e|d(?:isablePersistentStorage|biDynamicHashEnabled)|g(?:roupsBeforeMacros|lobalLogoutTimer)|h(?:ideOldPassword|ttpOnly)|yubikey2fUserCanRemoveKey|(?:activeTim|wsdlServ)er|krb(?:RemoveDomain|ByJs))$/;
our $boolKeys = qr/^(?:s(?:aml(?:IDP(?:MetaDataOptions(?:(?:Check(?:S[LS]OMessageSignatur|Audienc|Tim)|IsPassiv)e|A(?:llow(?:LoginFromIDP|ProxiedAuthn)|daptSessionUtime)|Force(?:Authn|UTF8)|StoreSAMLToken|RelayStateURL)|SSODescriptorWantAuthnRequestsSigned)|S(?:P(?:MetaDataOptions(?:(?:CheckS[LS]OMessageSignatur|OneTimeUs)e|EnableIDPInitiatedURL|ForceUTF8)|SSODescriptor(?:WantAssertion|AuthnRequest)sSigned)|erviceUseCertificateInResponse)|DiscoveryProtocol(?:Activation|IsPassive)|CommonDomainCookieActivation|UseQueryStringSpecific|MetadataForceUTF8)|ingle(?:Session(?:UserByIP)?|(?:UserBy)?IP)|oap(?:Session|Config)Server|t(?:ayConnecte|orePasswor)d|kipRenewConfirmation|fRemovedUseNotif|laveDisplayLogo|howLanguages|slByAjax)|o(?:idc(?:RPMetaDataOptions(?:Re(?:freshToken|quirePKCE)|LogoutSessionRequired|IDTokenForceClaims|BypassConsent|AllowOffline|Public)|ServiceAllow(?:(?:AuthorizationCode|Implicit|Hybrid)Flow|DynamicRegistration)|OPMetaDataOptions(?:(?:CheckJWTSignatur|UseNonc)e|StoreIDToken))|ldNotifFormat)|c(?:a(?:ptcha_(?:register|login|mail)_enabled|sSrvMetaDataOptions(?:Gateway|Renew))|heck(?:User(?:Display(?:Empty(?:Header|Value)s|PersistentInfo))?|State|XSS)|o(?:ntextSwitchingStopWithLogout|mpactConf|rsEnabled)|da)|p(?:ortal(?:Display(?:Re(?:setPassword|gister)|GeneratePassword|PasswordPolicy)|ErrorOn(?:ExpiredSession|MailNotFound)|(?:CheckLogin|Statu)s|OpenLinkInNewWindow|RequireOldPassword|ForceAuthn|AntiFrame)|roxyUseSoap)|l(?:dap(?:(?:Group(?:DecodeSearchedValu|Recursiv)|UsePasswordResetAttribut)e|(?:AllowResetExpired|Set)Password|ChangePasswordAsUser|PpolicyControl|ITDS)|oginHistoryEnabled)|no(?:tif(?:ication(?:Server(?:(?:POS|GE)T|DELETE)?|sExplorer)?|y(?:Deleted|Other))|AjaxHook)|i(?:ssuerDB(?:OpenID(?:Connect)?|SAML|CAS|Get)Activation|mpersonationSkipEmptyValues)|to(?:tp2f(?:UserCan(?:Chang|Remov)eKey|DisplayExistingSecret)|kenUseGlobalStorage)|u(?:se(?:RedirectOn(?:Forbidden|Error)|SafeJail)|2fUserCanRemoveKey|pgradeSession)|br(?:uteForceProtection(?:IncrementalTempo)?|owsersDontStorePassword)|re(?:st(?:(?:Session|Config)Server|ExportSecretKeys)|freshSessions)|(?:mai(?:lOnPasswordChang|ntenanc)|vhostMaintenanc)e|d(?:isablePersistentStorage|biDynamicHashEnabled)|g(?:roupsBeforeMacros|lobalLogoutTimer)|h(?:ideOldPassword|ttpOnly)|yubikey2fUserCanRemoveKey|(?:activeTim|wsdlServ)er|krb(?:RemoveDomain|ByJs))$/;
our @sessionTypes = ( 'remoteGlobal', 'global', 'localSession', 'persistent', 'saml', 'oidc', 'cas' );
......
......@@ -108,7 +108,7 @@ sub portalConsts {
}
# EXPORTER PARAMETERS
our @EXPORT_OK = ('portalConsts');
our @EXPORT_OK = ('portalConsts');
our %EXPORT_TAGS = ( 'all' => [ @EXPORT_OK, 'import' ], );
1;
......@@ -596,6 +596,9 @@ sub substitute {
$expr =~ s/\$_rulematch\[/\$m->\[/g;
$expr =~ s/\bskip\b/q\{999_SKIP\}/g;
# handle inGroup
$expr =~ s/\binGroup\(([^)]*)\)/listMatch(\$s->{'hGroups'},\1,1),/g;
return $expr;
}
......
......@@ -90,6 +90,23 @@ ok( $res = $client->_get( '/deny', undef, undef, "lemonldap=$sessionId" ),
ok( $res->[0] == 403, 'Code is 403' ) or explain( $res->[0], 403 );
count(2);
# Required "timelords" group
ok(
$res =
$client->_get( '/fortimelords', undef, undef, "lemonldap=$sessionId" ),
'Require Timelords group'
);
ok( $res->[0] == 200, 'Code is 200' ) or explain( $res, 200 );
count(2);
# Required "dalek" group
ok(
$res = $client->_get( '/fordaleks', undef, undef, "lemonldap=$sessionId" ),
'Require Dalek group'
);
ok( $res->[0] == 403, 'Code is 403' ) or explain( $res, 403 );
count(2);
# Required AuthnLevel = 1
ok( $res = $client->_get( '/AuthWeak', undef, undef, "lemonldap=$sessionId" ),
'Weak Authentified query' );
......
......@@ -47,6 +47,8 @@
"^/test-uri2": "varIsInUri($ENV{REQUEST_URI}, '/test-uri2/', $uid)",
"^/test-restricted_uri": "varIsInUri($ENV{REQUEST_URI}, '/test-restricted_uri/', \"$uid/\", 1)",
"^/skipif": "$ENV{REQUEST_URI} =~ /zz/ ? skip : 1",
"^/fortimelords": "inGroup('timelords')",
"^/fordaleks": "inGroup('daleks')",
"^/logout": "logout_sso",
"^/deny": "deny",
"^/user_(\\w+)/": "$uid eq $_rulematch[1]",
......
......@@ -46,17 +46,42 @@ sub init {
my $now = time;
my $ts = strftime "%Y%m%d%H%M%S", localtime;
print F '{"_updateTime":"'
. $ts
. '","_timezone":"1","_session_kind":"SSO","_passwordDB":"Demo","_startTime":"'
. $ts
. '","ipAddr":"127.0.0.1","UA":"Mozilla/5.0 (X11; VAX4000; rv:43.0) Gecko/20100101 Firefox/143.0 Iceweasel/143.0.1","_user":"dwho","_userDB":"Demo","_lastAuthnUTime":'
. $now
. ',"uid":"dwho","_issuerDB":"Null","_session_id":"f5eec18ebb9bc96352595e2d8ce962e8ecf7af7c9a98cb9a43f9cd181cf4b545","authenticationLevel":1,"_whatToTrace":"dwho","_auth":"Demo","_utime":'
. $now
. ',"_loginHistory":{"successLogin":[{"ipAddr":"127.0.0.1","_utime":'
. $now
. '}]},"cn":"Doctor Who","mail":"dwho@badwolf.org"}';
print F <<EOF;
{
"_startTime" : "$ts",
"_session_kind" : "SSO",
"UA" : "Mozilla/5.0 (X11; VAX4000; rv:43.0) Gecko/20100101 Firefox/143.0 Iceweasel/143.0.1",
"cn" : "Doctor Who",
"_utime" : $now,
"_whatToTrace" : "dwho",
"mail" : "dwho\@badwolf.org",
"_passwordDB" : "Demo",
"_lastAuthnUTime" : $now,
"uid" : "dwho",
"_issuerDB" : "Null",
"_userDB" : "Demo",
"_user" : "dwho",
"_session_id" : "f5eec18ebb9bc96352595e2d8ce962e8ecf7af7c9a98cb9a43f9cd181cf4b545",
"authenticationLevel" : 1,
"_auth" : "Demo",
"_updateTime" : "$ts",
"_loginHistory" : {
"successLogin" : [
{
"ipAddr" : "127.0.0.1",
"_utime" : $now
}
]
},
"ipAddr" : "127.0.0.1",
"_timezone" : "1",
"groups" : "users; timelords",
"hGroups" : {
"users" : {},
"timelords" : {}
}
}
EOF
close F;
}
......
......@@ -142,7 +142,7 @@ qr/^(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-
eval {
do {
qr/$_[0]/;
}
}
};
return $@ ? ( 0, "__badRegexp__: $@" ) : 1;
}
......@@ -223,7 +223,8 @@ m[^(?:(?:\-+\s*BEGIN\s+(?:PUBLIC\s+KEY|CERTIFICATE)\s*\-+\r?\n)?[a-zA-Z0-9/\+\r\
},
'select' => {
'test' => sub {
my $test = grep( { $_ eq $_[0]; }
my $test =
grep( { $_ eq $_[0]; }
map( { $_->{'k'}; } @{ $_[2]{'select'}; } ) );
return $test
? 1
......@@ -839,6 +840,10 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.]
'default' => 0,
'type' => 'bool'
},
'checkUserDisplayEmptyHeaders' => {
'default' => 0,
'type' => 'bool'
},
'checkUserDisplayEmptyValues' => {
'default' => 0,
'type' => 'bool'
......@@ -1709,7 +1714,7 @@ qr/^(?:\*\.)?(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][
eval {
do {
qr/$_[0]/;
}
}
};
return $@ ? 0 : 1;
},
......
......@@ -476,6 +476,12 @@ sub attributes {
documentation => 'Display session empty values',
flags => 'p',
},
checkUserDisplayEmptyHeaders => {
default => 0,
type => 'bool',
documentation => 'Display empty headers',
flags => 'p',
},
globalLogoutRule => {
type => 'boolOrExpr',
default => 0,
......
......@@ -736,8 +736,9 @@ sub tree {
'checkUserIdRule',
'checkUserHiddenAttributes',
'checkUserSearchAttributes',
'checkUserDisplayPersistentInfo',
'checkUserDisplayEmptyHeaders',
'checkUserDisplayEmptyValues',
'checkUserDisplayPersistentInfo',
]
},
{
......
......@@ -188,6 +188,7 @@
"checkUserIdRule":"Identities use rule",
"checkUserHiddenAttributes":"السمات المخفية",
"checkUserDisplayPersistentInfo":"Display persistent session",
"checkUserDisplayEmptyHeaders":"Display empty headers",
"checkUserDisplayEmptyValues":"Display empty values",
"checkUserSearchAttributes":"Attributes used for searching sessions",
"choiceParams":"اختيارالإعدادات",
......
......@@ -188,6 +188,7 @@
"checkUserIdRule":"Identities use rule",
"checkUserHiddenAttributes":"Hidden attributes",
"checkUserDisplayPersistentInfo":"Display persistent session",
"checkUserDisplayEmptyHeaders":"Display empty headers",
"checkUserDisplayEmptyValues":"Display empty values",
"checkUserSearchAttributes":"Attributes used for searching sessions",
"choiceParams":"Choice parameters",
......
......@@ -188,6 +188,7 @@
"checkUserIdRule":"Identities use rule",
"checkUserHiddenAttributes":"Hidden attributes",
"checkUserDisplayPersistentInfo":"Display persistent session",
"checkUserDisplayEmptyHeaders":"Display empty headers",
"checkUserDisplayEmptyValues":"Display empty values",
"checkUserSearchAttributes":"Attributes used for searching sessions",
"choiceParams":"Choice parameters",
......
......@@ -188,6 +188,7 @@
"checkUserIdRule":"Règle d'utilisation des identités",
"checkUserHiddenAttributes":"Attributs masqués",
"checkUserDisplayPersistentInfo":"Afficher les données de session persistante",
"checkUserDisplayEmptyHeaders":"Afficher les entêtes nuls",
"checkUserDisplayEmptyValues":"Afficher les valeurs nulles",
"checkUserSearchAttributes":"Attributs utilisés pour rechercher les sessions",
"choiceParams":"Paramètres des choix",
......
......@@ -188,6 +188,7 @@
"checkUserIdRule":"Uso della regola delle identità",
"checkUserHiddenAttributes":"Attributi nascosti",
"checkUserDisplayPersistentInfo":"Mostra sessione persistente",
"checkUserDisplayEmptyHeaders":"Display empty headers",
"checkUserDisplayEmptyValues":"Mostra valori vuoti",
"checkUserSearchAttributes":"Attributes used for searching sessions",
"choiceParams":"Scelta parametri",
......
......@@ -104,8 +104,8 @@
"browserIdSiteName":"Site adı",
"browserIdVerificationURL":"Doğrulama URL'i",
"browseTree":"Ağaca göz at",
"bruteForceProtection":"Activation",
"bruteForceAttackProtection":"Brute-force attack protection",
"bruteForceProtection":"Aktivasyon",
"bruteForceAttackProtection":"Kaba kuvvet saldırı koruması",
"bruteForceProtectionIncrementalTempo":"Incremental lock times",
"cancel":"İptal Et",
"captcha_login_enabled":"Giriş formunda aktivasyon",
......@@ -188,6 +188,7 @@
"checkUserIdRule":"Kimlik kullanım kuralı",
"checkUserHiddenAttributes":"Gizli nitelikler",
"checkUserDisplayPersistentInfo":"Kalıcı oturumu görüntüle",
"checkUserDisplayEmptyHeaders":"Display empty headers",
"checkUserDisplayEmptyValues":"Boş değerleri görüntüle",
"checkUserSearchAttributes":"Arama oturumlarında kullanılan nitelikler",
"choiceParams":"Tercih parametreleri",
......
......@@ -188,6 +188,7 @@
"checkUserIdRule":"Identities use rule",
"checkUserHiddenAttributes":"Thuộc tính ẩn",
"checkUserDisplayPersistentInfo":"Display persistent session",
"checkUserDisplayEmptyHeaders":"Display empty headers",
"checkUserDisplayEmptyValues":"Display empty values",
"checkUserSearchAttributes":"Attributes used for searching sessions",
"choiceParams":"Các tham số lựa chọn",
......
......@@ -188,6 +188,7 @@
"checkUserIdRule":"Identities use rule",
"checkUserHiddenAttributes":"Hidden attributes",
"checkUserDisplayPersistentInfo":"Display persistent session",
"checkUserDisplayEmptyHeaders":"Display empty headers",
"checkUserDisplayEmptyValues":"Display empty values",
"checkUserSearchAttributes":"Attributes used for searching sessions",
"choiceParams":"Choice parameters",
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -618,6 +618,7 @@ t/59-Double-cookies-for-Double-sessions.t
t/59-Double-cookies-Refresh-and-Logout.t
t/59-Secured-cookie-Refresh-and-Logout.t
t/60-Status.t
t/61-BruteForceProtection-with-Incremental-lockTimes-and-TOTP.t
t/61-BruteForceProtection-with-Incremental-lockTimes.t
t/61-BruteForceProtection.t
t/61-ForceAuthn.t
......@@ -641,6 +642,7 @@ t/67-CheckUser-with-issuer-SAML-POST.t
t/67-CheckUser-with-token.t
t/67-CheckUser.t
t/68-ContextSwitching-with-Logout.t
t/68-ContextSwitching-with-TOTP-and-Notification.t
t/68-ContextSwitching.t
t/68-Impersonation-with-doubleCookies.t
t/68-Impersonation-with-filtered-merge.t
......
......@@ -14,7 +14,7 @@ use constant CommonPrms => {
LANGS => 'showLanguages',
};
has skinRules => ( is => 'rw' );
has skinRules => ( is => 'rw' );
has favAppsRule => ( is => 'rw', default => sub { 1 } );
sub displayInit {
......@@ -124,7 +124,7 @@ sub display {
&& $req->data->{login},
ASK_LOGINS => $req->param('checkLogins') || 0,
CONFIRMKEY => $self->stamp(),
LIST => $req->data->{list} || [],
LIST => $req->data->{list} || [],
(
$req->data->{customScript}
? ( CUSTOM_SCRIPT => $req->data->{customScript} )
......@@ -194,6 +194,7 @@ sub display {
$skinfile = "redirect";
%templateParams = (
MAIN_LOGO => $self->conf->{portalMainLogo},
LANGS => $self->conf->{showLanguages},
URL => $req->{urldc},
HIDDEN_INPUTS => $self->buildHiddenForm($req),
FORM_METHOD => $req->data->{redirectFormMethod} || 'get',
......@@ -312,14 +313,15 @@ sub display {
ASK_LOGINS => $req->param('checkLogins') || 0,
DISPLAY_RESETPASSWORD => $self->conf->{portalDisplayResetPassword},
DISPLAY_REGISTER => $self->conf->{portalDisplayRegister},
DISPLAY_UPDATECERTIF => $self->conf->{portalDisplayCertificateResetByMail},
MAILCERTIF_URL => $self->conf->{certificateResetByMailURL},
MAIL_URL => $self->conf->{mailUrl},
REGISTER_URL => $self->conf->{registerUrl},
HIDDEN_INPUTS => $self->buildHiddenForm($req),
STAYCONNECTED => $self->conf->{stayConnected},
REQUIRE_OLDPASSWORD => $self->conf->{portalRequireOldPassword},
SPOOFID => $self->conf->{impersonationRule},
DISPLAY_UPDATECERTIF =>
$self->conf->{portalDisplayCertificateResetByMail},
MAILCERTIF_URL => $self->conf->{certificateResetByMailURL},
MAIL_URL => $self->conf->{mailUrl},
REGISTER_URL => $self->conf->{registerUrl},
HIDDEN_INPUTS => $self->buildHiddenForm($req),
STAYCONNECTED => $self->conf->{stayConnected},
REQUIRE_OLDPASSWORD => $self->conf->{portalRequireOldPassword},
SPOOFID => $self->conf->{impersonationRule},
(
$req->data->{customScript}
? ( CUSTOM_SCRIPT => $req->data->{customScript} )
......@@ -338,7 +340,11 @@ sub display {
or $req->{error} == PE_BADURL )
{
$skinfile = 'error';
%templateParams = ( %templateParams, MSG => $req->info(), );
%templateParams = (
%templateParams,
MSG => $req->info(),
LOCKTIME => $req->lockTime()
);
}
else {
......
......@@ -9,8 +9,7 @@ our $VERSION = '2.1.0';
extends 'Lemonldap::NG::Portal::Main::Plugin';
# INITIALIZATION
use constant afterData => 'run';
use constant afterSub => { storeHistory => 'run' };
has lockTimes => (
is => 'rw',
......@@ -53,15 +52,21 @@ sub init {
grep { /\d+/ }
split /\s+/, $self->conf->{bruteForceProtectionLockTimes};
@{ $self->lockTimes } = ( 5, 15, 60, 300, 600 )
unless $lockTimes;
$self->logger->warn( 'Number of incremental lock time values ('
. "$lockTimes) is higher than failed logins history ("
. $self->conf->{failedLoginNumber}
. ')' )
if ( $lockTimes > $self->conf->{failedLoginNumber} );
unless ($lockTimes) {
@{ $self->lockTimes } = ( 5, 15, 60, 300, 600 );
$lockTimes = 5;
}
if ( $lockTimes > $self->conf->{failedLoginNumber} ) {
$self->logger->warn( 'Number of incremental lock time values ('
. "$lockTimes) is higher than failed logins history ("
. $self->conf->{failedLoginNumber}
. ')' );
splice @{ $self->lockTimes }, $self->conf->{failedLoginNumber};
$lockTimes = $self->conf->{failedLoginNumber};
}
my $sum = $self->conf->{bruteForceProtectionMaxAge};
my $sum = $self->conf->{bruteForceProtectionMaxAge} * ( 1 + $self->conf->{failedLoginNumber} - $lockTimes );
$sum += $_ foreach @{ $self->lockTimes };
$self->maxAge($sum);
}
......
......@@ -60,7 +60,7 @@ sub changeUrldc {
$self->logger->debug( "CDA redirection to " . $req->{urldc} );
}
PE_OK;
return PE_OK;
}
1;
......@@ -22,23 +22,22 @@ sub init {
return 0;
}
$self->addUnauthRoute( checkstate => 'check', ['GET'] );
$self->addAuthRoute( checkstate => 'check', ['GET'] );
$self->addAuthRoute( checkstate => 'check', ['GET'] );
return 1;
}
sub check {
my ( $self, $req ) = @_;
my @rep;
unless ($req->param('secret')
and $req->param('secret') eq $self->conf->{checkStateSecret} )
{
return $self->p->sendError( $req, 'Bad secret' );
}
return $self->p->sendError( $req, 'Bad secret' )
unless ( $req->param('secret')
and $req->param('secret') eq $self->conf->{checkStateSecret} );
$req->steps( [ 'controlUrl', @{ $self->p->beforeAuth } ] );
my $res = $self->p->process($req);
if ( $res > 0 ) {
push @rep, "Bad result before auth: $res";
}
if ( my $user = $req->param('user') and my $pwd = $req->param('password') )
{
$req->user($user);
......@@ -59,12 +58,9 @@ sub check {
}
$self->p->deleteSession($req);
}
if (@rep) {
return $self->p->sendError( $req, join( ",\n", @rep ), 500 );
}
else {
return $self->p->sendJSONresponse( $req, { result => 1 } );
}
return $self->p->sendError( $req, join( ",\n", @rep ), 500 ) if (@rep);
return $self->p->sendJSONresponse( $req, { result => 1 } );
}
1;
......@@ -440,7 +440,14 @@ sub _headers {
$self->p->HANDLER->headersInit( $self->{conf} );
$self->logger->debug(
"Return \"$attrs->{ $self->{conf}->{whatToTrace} }\" headers");
return $self->p->HANDLER->checkHeaders( $req, $attrs );
return $self->p->HANDLER->checkHeaders( $req, $attrs )
if ( $self->conf->{checkUserDisplayEmptyHeaders} );
$self->logger->debug("Remove empty headers");
my @headers = grep $_->{value} =~ /.+/,
@{ $self->p->HANDLER->checkHeaders( $req, $attrs ) };
return \@headers;
}
sub _splitAttributes {
......@@ -456,7 +463,7 @@ sub _splitAttributes {
if ( $element->{key} eq 'groups' ) {
$self->logger->debug('Key "groups" found');
my $separator = $self->{conf}->{multiValuesSeparator};
my @tmp = split /\Q$separator/, $element->{value};
my @tmp = split /\Q$separator/, $element->{value};
$grps = [ map { { value => $_ } } sort @tmp ];
next;
}
......@@ -499,8 +506,8 @@ sub _splitAttributes {
sub _removePersistentAttributes {
my ( $self, $attrs ) = @_;
my $regex = join '|', split /\s+/, $self->persistentAttrs;
my @keys = grep /$regex/, keys %$attrs;
my $regex = join '|', split /\s+/, $self->persistentAttrs;
my @keys = grep /$regex/, keys %$attrs;
$self->logger->debug("Remove persistent session attributes");
delete @$attrs{@keys};
......
......@@ -81,7 +81,7 @@ sub display {
sub run {
my ( $self, $req ) = @_;
my ( $msg, $decryptedValue ) = ( '', '' );
my $msg = my $decryptedValue = '';
# Check access rules
unless ( $self->rule->( $req, $req->userData ) ) {
......
......@@ -21,12 +21,12 @@ sub run {
if ( $req->env->{HTTP_HOST}
and $self->conf->{portal} =~ /\Q$req->{env}->{HTTP_HOST}/ )
{
my $delta = time() - $req->{sessionInfo}->{_utime};
my $delta = time - $req->{sessionInfo}->{_utime};
$self->logger->debug( "Delta with last Authn -> " . $delta );
$delta <= $self->conf->{portalForceAuthnInterval}
? return PE_OK
: return PE_MUSTAUTHN;
return $delta <= $self->conf->{portalForceAuthnInterval}
? PE_OK
: PE_MUSTAUTHN;
}
}
......