This commit is contained in:
Christophe Maudoux 2020-05-23 23:52:09 +02:00
parent 279538613f
commit 79246c8da9
102 changed files with 464 additions and 1427 deletions

View File

@ -40,7 +40,7 @@ sub available {
closedir D;
@conf =
sort { $a <=> $b }
map { /lmConf-(\d+)(?:\.js(?:on))?/ ? ( $1 + 0 ) : () } @conf;
map { /lmConf-(\d+)(?:\.js(?:on))?/ ? ( $1 + 0 ) : () } @conf;
return @conf;
}

View File

@ -41,7 +41,7 @@ sub available {
closedir D;
@conf =
sort { $a <=> $b }
map { /lmConf-(\d+)\.yaml/ ? ( $1 + 0 ) : () } @conf;
map { /lmConf-(\d+)\.yaml/ ? ( $1 + 0 ) : () } @conf;
return @conf;
}

View File

@ -23,16 +23,20 @@ use constant HANDLERSECTION => "handler";
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)|oap(?:Session|Config)Server|t(?:ayConnecte|orePasswor)d|kipRenewConfirmation|fRemovedUseNotif|laveDisplayLogo|howLanguages|slByAjax)|o(?:idc(?:RPMetaDataOptions(?:Allow(?:PasswordGrant|Offline)|Re(?:freshToken|quirePKCE)|LogoutSessionRequired|IDTokenForceClaims|BypassConsent|Public)|ServiceAllow(?:(?:AuthorizationCode|Implicit|Hybrid)Flow|DynamicRegistration)|OPMetaDataOptions(?:(?:CheckJWTSignatur|UseNonc)e|StoreIDToken))|ldNotifFormat)|p(?:ortal(?:Display(?:Re(?:freshMyRights|setPassword|gister)|GeneratePassword|PasswordPolicy)|ErrorOn(?:ExpiredSession|MailNotFound)|(?:CheckLogin|Statu)s|OpenLinkInNewWindow|ForceAuthn|AntiFrame)|roxyUseSoap)|l(?:dap(?:(?:Group(?:DecodeSearchedValu|Recursiv)|UsePasswordResetAttribut)e|(?:AllowResetExpired|Set)Password|ChangePasswordAsUser|PpolicyControl|ITDS)|oginHistoryEnabled)|c(?:a(?:ptcha_(?:register|login|mail)_enabled|sSrvMetaDataOptions(?:Gateway|Renew))|o(?:ntextSwitchingStopWithLogout|mpactConf|rsEnabled)|heck(?:State|User|XSS)|da)|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)|re(?:st(?:(?:Password|Session|Config|Auth)Server|ExportSecretKeys)|freshSessions)|br(?:uteForceProtection(?:IncrementalTempo)?|owsersDontStorePassword)|(?:mai(?:lOnPasswordChang|ntenanc)|vhostMaintenanc)e|d(?:isablePersistentStorage|biDynamicHashEnabled)|g(?:roupsBeforeMacros|lobalLogoutTimer)|h(?:ideOldPassword|ttpOnly)|yubikey2fUserCanRemoveKey|(?:activeTim|wsdlServ)er|krb(?:RemoveDomain|ByJs))$/;
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)|oap(?:Session|Config)Server|t(?:ayConnecte|orePasswor)d|kipRenewConfirmation|fRemovedUseNotif|laveDisplayLogo|howLanguages|slByAjax)|o(?:idc(?:RPMetaDataOptions(?:Allow(?:PasswordGrant|Offline)|Re(?:freshToken|quirePKCE)|LogoutSessionRequired|IDTokenForceClaims|BypassConsent|Public)|ServiceAllow(?:(?:AuthorizationCode|Implicit|Hybrid)Flow|DynamicRegistration)|OPMetaDataOptions(?:(?:CheckJWTSignatur|UseNonc)e|StoreIDToken))|ldNotifFormat)|p(?:ortal(?:Display(?:Re(?:freshMyRights|setPassword|gister)|GeneratePassword|PasswordPolicy)|ErrorOn(?:ExpiredSession|MailNotFound)|(?:CheckLogin|Statu)s|OpenLinkInNewWindow|ForceAuthn|AntiFrame)|roxyUseSoap)|l(?:dap(?:(?:Group(?:DecodeSearchedValu|Recursiv)|UsePasswordResetAttribut)e|(?:AllowResetExpired|Set)Password|ChangePasswordAsUser|PpolicyControl|ITDS)|oginHistoryEnabled)|c(?:a(?:ptcha_(?:register|login|mail)_enabled|sSrvMetaDataOptions(?:Gateway|Renew))|o(?:ntextSwitchingStopWithLogout|mpactConf|rsEnabled)|heck(?:State|User|XSS)|da)|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)|re(?:st(?:(?:Password|Session|Config|Auth)Server|ExportSecretKeys)|freshSessions)|br(?:uteForceProtection(?:IncrementalTempo)?|owsersDontStorePassword)|(?: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' );
our @sessionTypes = (
'remoteGlobal', 'global', 'localSession', 'persistent',
'saml', 'oidc', 'cas'
);
sub NO {qr/^(?:off|no|0)?$/i}
sub NO { qr/^(?:off|no|0)?$/i }
our %EXPORT_TAGS = (
'all' => [
qw(
'all' => [ qw(
CONFIG_WAS_CHANGED
UNKNOWN_ERROR
DATABASE_LOCKED
@ -54,7 +58,7 @@ our %EXPORT_TAGS = (
)
]
);
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
our @EXPORT = ( @{ $EXPORT_TAGS{'all'} } );
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
our @EXPORT = ( @{ $EXPORT_TAGS{'all'} } );
1;

View File

@ -710,9 +710,9 @@ sub combModules {
my $res = [];
foreach my $mod ( keys %$val ) {
my $tmp;
$tmp->{title} = $mod;
$tmp->{id} = "combModules/$mod";
$tmp->{type} = 'cmbModule';
$tmp->{title} = $mod;
$tmp->{id} = "combModules/$mod";
$tmp->{type} = 'cmbModule';
$tmp->{data}->{$_} = $val->{$mod}->{$_} foreach (qw(type for));
my $over = $val->{$mod}->{over} // {};
$tmp->{data}->{over} = [ map { [ $_, $over->{$_} ] } keys %$over ];
@ -786,8 +786,8 @@ sub metadata {
}
# Find next and previous conf
my @a = $self->confAcc->available;
my $id = -1;
my @a = $self->confAcc->available;
my $id = -1;
my ($ind) = map { $id++; $_ == $res->{cfgNum} ? ($id) : () } @a;
if ($ind) { $res->{prev} = $a[ $ind - 1 ]; }
if ( defined $ind and $ind < $#a ) {

View File

@ -7,68 +7,127 @@ use base qw(Exporter);
our $VERSION = '2.1.0';
our %EXPORT_TAGS = ( 'all' => [qw($simpleHashKeys $doubleHashKeys $specialNodeKeys $casAppMetaDataNodeKeys $casSrvMetaDataNodeKeys $oidcOPMetaDataNodeKeys $oidcRPMetaDataNodeKeys $samlIDPMetaDataNodeKeys $samlSPMetaDataNodeKeys $virtualHostKeys $specialNodeHash $authParameters $issuerParameters $samlServiceParameters $oidcServiceParameters $casServiceParameters)] );
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
our @EXPORT = ( @{ $EXPORT_TAGS{'all'} } );
our %EXPORT_TAGS = (
'all' => [
qw($simpleHashKeys $doubleHashKeys $specialNodeKeys $casAppMetaDataNodeKeys $casSrvMetaDataNodeKeys $oidcOPMetaDataNodeKeys $oidcRPMetaDataNodeKeys $samlIDPMetaDataNodeKeys $samlSPMetaDataNodeKeys $virtualHostKeys $specialNodeHash $authParameters $issuerParameters $samlServiceParameters $oidcServiceParameters $casServiceParameters)
]
);
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
our @EXPORT = ( @{ $EXPORT_TAGS{'all'} } );
our $specialNodeHash = {
virtualHosts => [qw(exportedHeaders locationRules post vhostOptions)],
samlIDPMetaDataNodes => [qw(samlIDPMetaDataXML samlIDPMetaDataExportedAttributes samlIDPMetaDataOptions)],
samlSPMetaDataNodes => [qw(samlSPMetaDataXML samlSPMetaDataExportedAttributes samlSPMetaDataOptions samlSPMetaDataMacros)],
oidcOPMetaDataNodes => [qw(oidcOPMetaDataJSON oidcOPMetaDataJWKS oidcOPMetaDataOptions oidcOPMetaDataExportedVars)],
oidcRPMetaDataNodes => [qw(oidcRPMetaDataOptions oidcRPMetaDataExportedVars oidcRPMetaDataOptionsExtraClaims oidcRPMetaDataMacros)],
casSrvMetaDataNodes => [qw(casSrvMetaDataOptions casSrvMetaDataExportedVars)],
casAppMetaDataNodes => [qw(casAppMetaDataOptions casAppMetaDataExportedVars casAppMetaDataMacros)],
virtualHosts => [qw(exportedHeaders locationRules post vhostOptions)],
samlIDPMetaDataNodes => [
qw(samlIDPMetaDataXML samlIDPMetaDataExportedAttributes samlIDPMetaDataOptions)
],
samlSPMetaDataNodes => [
qw(samlSPMetaDataXML samlSPMetaDataExportedAttributes samlSPMetaDataOptions samlSPMetaDataMacros)
],
oidcOPMetaDataNodes => [
qw(oidcOPMetaDataJSON oidcOPMetaDataJWKS oidcOPMetaDataOptions oidcOPMetaDataExportedVars)
],
oidcRPMetaDataNodes => [
qw(oidcRPMetaDataOptions oidcRPMetaDataExportedVars oidcRPMetaDataOptionsExtraClaims oidcRPMetaDataMacros)
],
casSrvMetaDataNodes =>
[qw(casSrvMetaDataOptions casSrvMetaDataExportedVars)],
casAppMetaDataNodes => [
qw(casAppMetaDataOptions casAppMetaDataExportedVars casAppMetaDataMacros)
],
};
our $doubleHashKeys = 'issuerDBGetParameters';
our $simpleHashKeys = '(?:(?:l(?:o(?:calSessionStorageOption|goutService)|dapExportedVar|wp(?:Ssl)?Opt)|c(?:as(?:StorageOption|Attribute)|ustom(?:Plugins|Add)Param|ombModule)|re(?:moteGlobalStorageOption|st2f(?:Verify|Init)Arg|loadUrl)|(?:(?:d(?:emo|bi)|facebook|webID)E|e)xportedVar|g(?:r(?:antSessionRule|oup)|lobalStorageOption)|n(?:otificationStorageOption|ginxCustomHandler)|p(?:ersistentStorageOption|ortalSkinRule)|macro)s|o(?:idcS(?:ervice(?:DynamicRegistrationEx(?:portedVar|traClaim)s|MetaDataAuthnContext)|torageOptions)|penIdExportedVars)|s(?:(?:amlStorageOption|laveExportedVar)s|essionDataToRemember|fExtra)|a(?:ut(?:hChoiceMod|oSigninR)ules|pplicationList)|S(?:MTPTLSOpts|SLVarIf))';
our $specialNodeKeys = '(?:(?:(?:saml(?:ID|S)|oidc[OR])P|cas(?:App|Srv))MetaDataNode|virtualHost)s';
our $casAppMetaDataNodeKeys = 'casAppMetaData(?:Options(?:UserAttribut|Servic|Rul)e|(?:ExportedVar|Macro)s)';
our $casSrvMetaDataNodeKeys = 'casSrvMetaData(?:Options(?:ProxiedServices|DisplayName|SortNumber|Gateway|Renew|Icon|Url)|ExportedVars)';
our $oidcOPMetaDataNodeKeys = 'oidcOPMetaData(?:Options(?:C(?:lient(?:Secret|ID)|heckJWTSignature|onfigurationURI)|S(?:toreIDToken|ortNumber|cope)|TokenEndpointAuthMethod|(?:JWKSTimeou|Promp)t|I(?:DTokenMaxAge|con)|U(?:iLocales|seNonce)|Display(?:Name)?|AcrValues|MaxAge)|ExportedVars|J(?:SON|WKS))';
our $oidcRPMetaDataNodeKeys = 'oidcRPMetaData(?:Options(?:A(?:(?:uthorizationCode|ccessToken)Expiration|llow(?:PasswordGrant|Offline)|dditionalAudiences)|I(?:DToken(?:ForceClaims|Expiration|SignAlg)|con)|R(?:e(?:directUris|freshToken|quirePKCE)|ule)|Logout(?:SessionRequired|Type|Url)|P(?:ostLogoutRedirectUris|ublic)|OfflineSessionExpiration|Client(?:Secret|ID)|BypassConsent|DisplayName|ExtraClaims|UserIDAttr)|(?:ExportedVar|Macro)s)';
our $samlIDPMetaDataNodeKeys = 'samlIDPMetaData(?:Options(?:(?:Check(?:S[LS]OMessageSignatur|Audienc|Tim)|EncryptionMod|UserAttribut|DisplayNam)e|S(?:ignS[LS]OMessage|toreSAMLToken|[LS]OBinding|ortNumber)|A(?:llow(?:LoginFromIDP|ProxiedAuthn)|daptSessionUtime)|Re(?:questedAuthnContext|solutionRule|layStateURL)|Force(?:Authn|UTF8)|I(?:sPassive|con)|NameIDFormat)|ExportedAttributes|XML)';
our $samlSPMetaDataNodeKeys = 'samlSPMetaData(?:Options(?:N(?:ameID(?:SessionKey|Format)|otOnOrAfterTimeout)|S(?:essionNotOnOrAfterTimeout|ignS[LS]OMessage)|(?:CheckS[LS]OMessageSignatur|OneTimeUs|Rul)e|En(?:ableIDPInitiatedURL|cryptionMode)|ForceUTF8)|(?:ExportedAttribute|Macro)s|XML)';
our $virtualHostKeys = '(?:vhost(?:A(?:uthnLevel|liases)|(?:Maintenanc|Typ)e|ServiceTokenTTL|Https|Port)|(?:exportedHeader|locationRule)s|post)';
our $simpleHashKeys =
'(?:(?:l(?:o(?:calSessionStorageOption|goutService)|dapExportedVar|wp(?:Ssl)?Opt)|c(?:as(?:StorageOption|Attribute)|ustom(?:Plugins|Add)Param|ombModule)|re(?:moteGlobalStorageOption|st2f(?:Verify|Init)Arg|loadUrl)|(?:(?:d(?:emo|bi)|facebook|webID)E|e)xportedVar|g(?:r(?:antSessionRule|oup)|lobalStorageOption)|n(?:otificationStorageOption|ginxCustomHandler)|p(?:ersistentStorageOption|ortalSkinRule)|macro)s|o(?:idcS(?:ervice(?:DynamicRegistrationEx(?:portedVar|traClaim)s|MetaDataAuthnContext)|torageOptions)|penIdExportedVars)|s(?:(?:amlStorageOption|laveExportedVar)s|essionDataToRemember|fExtra)|a(?:ut(?:hChoiceMod|oSigninR)ules|pplicationList)|S(?:MTPTLSOpts|SLVarIf))';
our $specialNodeKeys =
'(?:(?:(?:saml(?:ID|S)|oidc[OR])P|cas(?:App|Srv))MetaDataNode|virtualHost)s';
our $casAppMetaDataNodeKeys =
'casAppMetaData(?:Options(?:UserAttribut|Servic|Rul)e|(?:ExportedVar|Macro)s)';
our $casSrvMetaDataNodeKeys =
'casSrvMetaData(?:Options(?:ProxiedServices|DisplayName|SortNumber|Gateway|Renew|Icon|Url)|ExportedVars)';
our $oidcOPMetaDataNodeKeys =
'oidcOPMetaData(?:Options(?:C(?:lient(?:Secret|ID)|heckJWTSignature|onfigurationURI)|S(?:toreIDToken|ortNumber|cope)|TokenEndpointAuthMethod|(?:JWKSTimeou|Promp)t|I(?:DTokenMaxAge|con)|U(?:iLocales|seNonce)|Display(?:Name)?|AcrValues|MaxAge)|ExportedVars|J(?:SON|WKS))';
our $oidcRPMetaDataNodeKeys =
'oidcRPMetaData(?:Options(?:A(?:(?:uthorizationCode|ccessToken)Expiration|llow(?:PasswordGrant|Offline)|dditionalAudiences)|I(?:DToken(?:ForceClaims|Expiration|SignAlg)|con)|R(?:e(?:directUris|freshToken|quirePKCE)|ule)|Logout(?:SessionRequired|Type|Url)|P(?:ostLogoutRedirectUris|ublic)|OfflineSessionExpiration|Client(?:Secret|ID)|BypassConsent|DisplayName|ExtraClaims|UserIDAttr)|(?:ExportedVar|Macro)s)';
our $samlIDPMetaDataNodeKeys =
'samlIDPMetaData(?:Options(?:(?:Check(?:S[LS]OMessageSignatur|Audienc|Tim)|EncryptionMod|UserAttribut|DisplayNam)e|S(?:ignS[LS]OMessage|toreSAMLToken|[LS]OBinding|ortNumber)|A(?:llow(?:LoginFromIDP|ProxiedAuthn)|daptSessionUtime)|Re(?:questedAuthnContext|solutionRule|layStateURL)|Force(?:Authn|UTF8)|I(?:sPassive|con)|NameIDFormat)|ExportedAttributes|XML)';
our $samlSPMetaDataNodeKeys =
'samlSPMetaData(?:Options(?:N(?:ameID(?:SessionKey|Format)|otOnOrAfterTimeout)|S(?:essionNotOnOrAfterTimeout|ignS[LS]OMessage)|(?:CheckS[LS]OMessageSignatur|OneTimeUs|Rul)e|En(?:ableIDPInitiatedURL|cryptionMode)|ForceUTF8)|(?:ExportedAttribute|Macro)s|XML)';
our $virtualHostKeys =
'(?:vhost(?:A(?:uthnLevel|liases)|(?:Maintenanc|Typ)e|ServiceTokenTTL|Https|Port)|(?:exportedHeader|locationRule)s|post)';
our $authParameters = {
adParams => [qw(ADPwdMaxAge ADPwdExpireWarning)],
apacheParams => [qw(apacheAuthnLevel)],
casParams => [qw(casAuthnLevel)],
choiceParams => [qw(authChoiceParam authChoiceModules authChoiceAuthBasic)],
combinationParams => [qw(combination combModules combinationForms)],
customParams => [qw(customAuth customUserDB customPassword customRegister customResetCertByMail customAddParams)],
dbiParams => [qw(dbiAuthnLevel dbiExportedVars dbiAuthChain dbiAuthUser dbiAuthPassword dbiUserChain dbiUserUser dbiUserPassword dbiAuthTable dbiUserTable dbiAuthLoginCol dbiAuthPasswordCol dbiPasswordMailCol userPivot dbiAuthPasswordHash dbiDynamicHashEnabled dbiDynamicHashValidSchemes dbiDynamicHashValidSaltedSchemes dbiDynamicHashNewPasswordScheme)],
demoParams => [qw(demoExportedVars)],
facebookParams => [qw(facebookAuthnLevel facebookExportedVars facebookAppId facebookAppSecret facebookUserField)],
githubParams => [qw(githubAuthnLevel githubClientID githubClientSecret githubUserField githubScope)],
gpgParams => [qw(gpgAuthnLevel gpgDb)],
kerberosParams => [qw(krbAuthnLevel krbKeytab krbByJs krbRemoveDomain)],
ldapParams => [qw(ldapAuthnLevel ldapExportedVars ldapServer ldapPort ldapBase managerDn managerPassword ldapTimeout ldapVersion ldapRaw LDAPFilter AuthLDAPFilter mailLDAPFilter ldapSearchDeref ldapGroupBase ldapGroupObjectClass ldapGroupAttributeName ldapGroupAttributeNameUser ldapGroupAttributeNameSearch ldapGroupDecodeSearchedValue ldapGroupRecursive ldapGroupAttributeNameGroup ldapPpolicyControl ldapSetPassword ldapChangePasswordAsUser ldapPwdEnc ldapUsePasswordResetAttribute ldapPasswordResetAttribute ldapPasswordResetAttributeValue ldapAllowResetExpiredPassword ldapITDS)],
linkedinParams => [qw(linkedInAuthnLevel linkedInClientID linkedInClientSecret linkedInUserField linkedInScope)],
nullParams => [qw(nullAuthnLevel)],
oidcParams => [qw(oidcAuthnLevel oidcRPCallbackGetParam oidcRPStateTimeout)],
openidParams => [qw(openIdAuthnLevel openIdExportedVars openIdSecret openIdIDPList)],
pamParams => [qw(pamAuthnLevel pamService)],
proxyParams => [qw(proxyAuthnLevel proxyAuthService proxySessionService remoteCookieName proxyUseSoap)],
radiusParams => [qw(radiusAuthnLevel radiusSecret radiusServer)],
remoteParams => [qw(remotePortal remoteCookieName remoteGlobalStorage remoteGlobalStorageOptions)],
restParams => [qw(restAuthnLevel restAuthUrl restUserDBUrl restPwdConfirmUrl restPwdModifyUrl)],
slaveParams => [qw(slaveAuthnLevel slaveUserHeader slaveMasterIP slaveHeaderName slaveHeaderContent slaveDisplayLogo slaveExportedVars)],
sslParams => [qw(SSLAuthnLevel SSLVar SSLVarIf sslByAjax sslHost)],
twitterParams => [qw(twitterAuthnLevel twitterKey twitterSecret twitterAppName twitterUserField)],
webidParams => [qw(webIDAuthnLevel webIDExportedVars webIDWhitelist)],
adParams => [qw(ADPwdMaxAge ADPwdExpireWarning)],
apacheParams => [qw(apacheAuthnLevel)],
casParams => [qw(casAuthnLevel)],
choiceParams => [qw(authChoiceParam authChoiceModules authChoiceAuthBasic)],
combinationParams => [qw(combination combModules combinationForms)],
customParams => [
qw(customAuth customUserDB customPassword customRegister customResetCertByMail customAddParams)
],
dbiParams => [
qw(dbiAuthnLevel dbiExportedVars dbiAuthChain dbiAuthUser dbiAuthPassword dbiUserChain dbiUserUser dbiUserPassword dbiAuthTable dbiUserTable dbiAuthLoginCol dbiAuthPasswordCol dbiPasswordMailCol userPivot dbiAuthPasswordHash dbiDynamicHashEnabled dbiDynamicHashValidSchemes dbiDynamicHashValidSaltedSchemes dbiDynamicHashNewPasswordScheme)
],
demoParams => [qw(demoExportedVars)],
facebookParams => [
qw(facebookAuthnLevel facebookExportedVars facebookAppId facebookAppSecret facebookUserField)
],
githubParams => [
qw(githubAuthnLevel githubClientID githubClientSecret githubUserField githubScope)
],
gpgParams => [qw(gpgAuthnLevel gpgDb)],
kerberosParams => [qw(krbAuthnLevel krbKeytab krbByJs krbRemoveDomain)],
ldapParams => [
qw(ldapAuthnLevel ldapExportedVars ldapServer ldapPort ldapBase managerDn managerPassword ldapTimeout ldapVersion ldapRaw LDAPFilter AuthLDAPFilter mailLDAPFilter ldapSearchDeref ldapGroupBase ldapGroupObjectClass ldapGroupAttributeName ldapGroupAttributeNameUser ldapGroupAttributeNameSearch ldapGroupDecodeSearchedValue ldapGroupRecursive ldapGroupAttributeNameGroup ldapPpolicyControl ldapSetPassword ldapChangePasswordAsUser ldapPwdEnc ldapUsePasswordResetAttribute ldapPasswordResetAttribute ldapPasswordResetAttributeValue ldapAllowResetExpiredPassword ldapITDS)
],
linkedinParams => [
qw(linkedInAuthnLevel linkedInClientID linkedInClientSecret linkedInUserField linkedInScope)
],
nullParams => [qw(nullAuthnLevel)],
oidcParams =>
[qw(oidcAuthnLevel oidcRPCallbackGetParam oidcRPStateTimeout)],
openidParams =>
[qw(openIdAuthnLevel openIdExportedVars openIdSecret openIdIDPList)],
pamParams => [qw(pamAuthnLevel pamService)],
proxyParams => [
qw(proxyAuthnLevel proxyAuthService proxySessionService remoteCookieName proxyUseSoap)
],
radiusParams => [qw(radiusAuthnLevel radiusSecret radiusServer)],
remoteParams => [
qw(remotePortal remoteCookieName remoteGlobalStorage remoteGlobalStorageOptions)
],
restParams => [
qw(restAuthnLevel restAuthUrl restUserDBUrl restPwdConfirmUrl restPwdModifyUrl)
],
slaveParams => [
qw(slaveAuthnLevel slaveUserHeader slaveMasterIP slaveHeaderName slaveHeaderContent slaveDisplayLogo slaveExportedVars)
],
sslParams => [qw(SSLAuthnLevel SSLVar SSLVarIf sslByAjax sslHost)],
twitterParams => [
qw(twitterAuthnLevel twitterKey twitterSecret twitterAppName twitterUserField)
],
webidParams => [qw(webIDAuthnLevel webIDExportedVars webIDWhitelist)],
};
our $issuerParameters = {
issuerDBCAS => [qw(issuerDBCASActivation issuerDBCASPath issuerDBCASRule)],
issuerDBGet => [qw(issuerDBGetActivation issuerDBGetPath issuerDBGetRule issuerDBGetParameters)],
issuerDBOpenID => [qw(issuerDBOpenIDActivation issuerDBOpenIDPath issuerDBOpenIDRule openIdIssuerSecret openIdAttr openIdSPList openIdSreg_fullname openIdSreg_nickname openIdSreg_language openIdSreg_postcode openIdSreg_timezone openIdSreg_country openIdSreg_gender openIdSreg_email openIdSreg_dob)],
issuerDBOpenIDConnect => [qw(issuerDBOpenIDConnectActivation issuerDBOpenIDConnectPath issuerDBOpenIDConnectRule)],
issuerDBSAML => [qw(issuerDBSAMLActivation issuerDBSAMLPath issuerDBSAMLRule)],
issuerOptions => [qw(issuersTimeout)],
issuerDBCAS => [qw(issuerDBCASActivation issuerDBCASPath issuerDBCASRule)],
issuerDBGet => [
qw(issuerDBGetActivation issuerDBGetPath issuerDBGetRule issuerDBGetParameters)
],
issuerDBOpenID => [
qw(issuerDBOpenIDActivation issuerDBOpenIDPath issuerDBOpenIDRule openIdIssuerSecret openIdAttr openIdSPList openIdSreg_fullname openIdSreg_nickname openIdSreg_language openIdSreg_postcode openIdSreg_timezone openIdSreg_country openIdSreg_gender openIdSreg_email openIdSreg_dob)
],
issuerDBOpenIDConnect => [
qw(issuerDBOpenIDConnectActivation issuerDBOpenIDConnectPath issuerDBOpenIDConnectRule)
],
issuerDBSAML =>
[qw(issuerDBSAMLActivation issuerDBSAMLPath issuerDBSAMLRule)],
issuerOptions => [qw(issuersTimeout)],
};
our $samlServiceParameters = [qw(samlEntityID samlServicePrivateKeySig samlServicePrivateKeySigPwd samlServicePublicKeySig samlServicePrivateKeyEnc samlServicePrivateKeyEncPwd samlServicePublicKeyEnc samlServiceUseCertificateInResponse samlServiceSignatureMethod samlNameIDFormatMapEmail samlNameIDFormatMapX509 samlNameIDFormatMapWindows samlNameIDFormatMapKerberos samlAuthnContextMapPassword samlAuthnContextMapPasswordProtectedTransport samlAuthnContextMapTLSClient samlAuthnContextMapKerberos samlOrganizationDisplayName samlOrganizationName samlOrganizationURL samlSPSSODescriptorAuthnRequestsSigned samlSPSSODescriptorWantAssertionsSigned samlSPSSODescriptorSingleLogoutServiceHTTPRedirect samlSPSSODescriptorSingleLogoutServiceHTTPPost samlSPSSODescriptorSingleLogoutServiceSOAP samlSPSSODescriptorAssertionConsumerServiceHTTPArtifact samlSPSSODescriptorAssertionConsumerServiceHTTPPost samlSPSSODescriptorArtifactResolutionServiceArtifact samlIDPSSODescriptorWantAuthnRequestsSigned samlIDPSSODescriptorSingleSignOnServiceHTTPRedirect samlIDPSSODescriptorSingleSignOnServiceHTTPPost samlIDPSSODescriptorSingleSignOnServiceHTTPArtifact samlIDPSSODescriptorSingleLogoutServiceHTTPRedirect samlIDPSSODescriptorSingleLogoutServiceHTTPPost samlIDPSSODescriptorSingleLogoutServiceSOAP samlIDPSSODescriptorArtifactResolutionServiceArtifact samlAttributeAuthorityDescriptorAttributeServiceSOAP samlMetadataForceUTF8 samlRelayStateTimeout samlUseQueryStringSpecific samlOverrideIDPEntityID samlStorage samlStorageOptions samlCommonDomainCookieActivation samlCommonDomainCookieDomain samlCommonDomainCookieReader samlCommonDomainCookieWriter samlDiscoveryProtocolActivation samlDiscoveryProtocolURL samlDiscoveryProtocolPolicy samlDiscoveryProtocolIsPassive)];
our $oidcServiceParameters = [qw(oidcServiceMetaDataAuthorizeURI oidcServiceMetaDataTokenURI oidcServiceMetaDataUserInfoURI oidcServiceMetaDataJWKSURI oidcServiceMetaDataRegistrationURI oidcServiceMetaDataIntrospectionURI oidcServiceMetaDataEndSessionURI oidcServiceMetaDataCheckSessionURI oidcServiceMetaDataFrontChannelURI oidcServiceMetaDataBackChannelURI oidcServiceMetaDataAuthnContext oidcServicePrivateKeySig oidcServicePublicKeySig oidcServiceKeyIdSig oidcServiceAllowDynamicRegistration oidcServiceAllowAuthorizationCodeFlow oidcServiceAllowImplicitFlow oidcServiceAllowHybridFlow oidcServiceAuthorizationCodeExpiration oidcServiceAccessTokenExpiration oidcServiceIDTokenExpiration oidcServiceOfflineSessionExpiration oidcStorage oidcStorageOptions oidcServiceDynamicRegistrationExportedVars oidcServiceDynamicRegistrationExtraClaims)];
our $samlServiceParameters = [
qw(samlEntityID samlServicePrivateKeySig samlServicePrivateKeySigPwd samlServicePublicKeySig samlServicePrivateKeyEnc samlServicePrivateKeyEncPwd samlServicePublicKeyEnc samlServiceUseCertificateInResponse samlServiceSignatureMethod samlNameIDFormatMapEmail samlNameIDFormatMapX509 samlNameIDFormatMapWindows samlNameIDFormatMapKerberos samlAuthnContextMapPassword samlAuthnContextMapPasswordProtectedTransport samlAuthnContextMapTLSClient samlAuthnContextMapKerberos samlOrganizationDisplayName samlOrganizationName samlOrganizationURL samlSPSSODescriptorAuthnRequestsSigned samlSPSSODescriptorWantAssertionsSigned samlSPSSODescriptorSingleLogoutServiceHTTPRedirect samlSPSSODescriptorSingleLogoutServiceHTTPPost samlSPSSODescriptorSingleLogoutServiceSOAP samlSPSSODescriptorAssertionConsumerServiceHTTPArtifact samlSPSSODescriptorAssertionConsumerServiceHTTPPost samlSPSSODescriptorArtifactResolutionServiceArtifact samlIDPSSODescriptorWantAuthnRequestsSigned samlIDPSSODescriptorSingleSignOnServiceHTTPRedirect samlIDPSSODescriptorSingleSignOnServiceHTTPPost samlIDPSSODescriptorSingleSignOnServiceHTTPArtifact samlIDPSSODescriptorSingleLogoutServiceHTTPRedirect samlIDPSSODescriptorSingleLogoutServiceHTTPPost samlIDPSSODescriptorSingleLogoutServiceSOAP samlIDPSSODescriptorArtifactResolutionServiceArtifact samlAttributeAuthorityDescriptorAttributeServiceSOAP samlMetadataForceUTF8 samlRelayStateTimeout samlUseQueryStringSpecific samlOverrideIDPEntityID samlStorage samlStorageOptions samlCommonDomainCookieActivation samlCommonDomainCookieDomain samlCommonDomainCookieReader samlCommonDomainCookieWriter samlDiscoveryProtocolActivation samlDiscoveryProtocolURL samlDiscoveryProtocolPolicy samlDiscoveryProtocolIsPassive)
];
our $oidcServiceParameters = [
qw(oidcServiceMetaDataAuthorizeURI oidcServiceMetaDataTokenURI oidcServiceMetaDataUserInfoURI oidcServiceMetaDataJWKSURI oidcServiceMetaDataRegistrationURI oidcServiceMetaDataIntrospectionURI oidcServiceMetaDataEndSessionURI oidcServiceMetaDataCheckSessionURI oidcServiceMetaDataFrontChannelURI oidcServiceMetaDataBackChannelURI oidcServiceMetaDataAuthnContext oidcServicePrivateKeySig oidcServicePublicKeySig oidcServiceKeyIdSig oidcServiceAllowDynamicRegistration oidcServiceAllowAuthorizationCodeFlow oidcServiceAllowImplicitFlow oidcServiceAllowHybridFlow oidcServiceAuthorizationCodeExpiration oidcServiceAccessTokenExpiration oidcServiceIDTokenExpiration oidcServiceOfflineSessionExpiration oidcStorage oidcStorageOptions oidcServiceDynamicRegistrationExportedVars oidcServiceDynamicRegistrationExtraClaims)
];
1;

View File

@ -166,9 +166,9 @@ sub serviceToXML {
foreach (@param_assertion) {
my @_tab = split( /;/, $self->getValue( $_, $conf ) );
$template->param( $_ . 'Default', $_tab[0] ? 'true' : 'false' );
$template->param( $_ . 'Index', $_tab[1] );
$template->param( $_ . 'Binding', $_tab[2] );
$template->param( $_ . 'Default', $_tab[0] ? 'true' : 'false' );
$template->param( $_ . 'Index', $_tab[1] );
$template->param( $_ . 'Binding', $_tab[2] );
$template->param( $_ . 'Location', $_tab[3] );
}

View File

@ -36,7 +36,7 @@ has fileNameSeparator => ( is => 'rw', default => '_' );
sub get {
my ( $self, $uid, $ref ) = @_;
return () unless ($uid);
my $ext = $self->extension;
my $ext = $self->extension;
my $fns = $self->{fileNameSeparator};
my $identifier = &getIdentifier( $self, $uid, $ref );
@ -61,7 +61,7 @@ sub get {
sub getAccepted {
my ( $self, $uid, $ref ) = @_;
return () unless ($uid);
my $ext = $self->extension;
my $ext = $self->extension;
my $fns = $self->{fileNameSeparator};
my $identifier = &getIdentifier( $self, $uid, $ref );

View File

@ -21,7 +21,7 @@ sub newNotification {
foreach my $notif (@$json) {
my @data;
$notif->{reference} =~ s/_/-/g; # Remove underscores (#2135)
$notif->{reference} =~ s/_/-/g; # Remove underscores (#2135)
# Mandatory information
foreach (qw(date uid reference)) {

View File

@ -33,7 +33,7 @@ sub newNotification {
my $notif ( $xml->documentElement->getElementsByTagName('notification') )
{
my @data = ();
$notif->{reference} =~ s/_/-/g; # Remove underscores (#2135)
$notif->{reference} =~ s/_/-/g; # Remove underscores (#2135)
# Mandatory information
foreach (qw(date uid reference)) {

View File

@ -64,8 +64,8 @@ sub checkLogonHours {
# Use time_correction
if ($time_correction) {
my ( $sign, $time ) = ( $time_correction =~ /([+|-]?)(\d+)/ );
if ( $sign =~ /-/ ) { $hourpos -= $time; }
else { $hourpos += $time; }
if ( $sign =~ /-/ ) { $hourpos -= $time; }
else { $hourpos += $time; }
}
# Get the corresponding byte

View File

@ -66,7 +66,7 @@ q"I refuse to compile rules.json when useSafeJail isn't activated! Yes I know, I
$json->{rules} ||= { default => 1 };
$json->{headers} //= { 'Auth-User' => '$uid' };
$class->locationRulesInit( undef, { $vhost => $json->{rules} } );
$class->headersInit( undef, { $vhost => $json->{headers} } );
$class->headersInit( undef, { $vhost => $json->{headers} } );
$class->tsv->{lastVhostUpdate}->{$vhost} = time;
return;
}

View File

@ -36,7 +36,7 @@ our @builtCustomFunctions;
sub build_jail {
my ( $self, $api, $require, $dontDie ) = @_;
my $build = 1;
return $self->jail
if ( $self->jail
and $self->jail->useSafeJail

View File

@ -452,7 +452,7 @@ sub fetchId {
my $value =
$lookForHttpCookie
? ( $t =~ /${cn}http=([^,; ]+)/o ? $1 : 0 )
: ( $t =~ /$cn=([^,; ]+)/o ? $1 : 0 );
: ( $t =~ /$cn=([^,; ]+)/o ? $1 : 0 );
if ( $value && $lookForHttpCookie && $class->tsv->{securedCookie} == 3 ) {
$value = $class->tsv->{cipher}->decryptHex( $value, "http" );

View File

@ -1,7 +1,7 @@
package Plack::Middleware::Auth::LemonldapNG;
our $AUTHORITY = 'cpan:GUIMARD';
our $VERSION = '2.1.0';
our $VERSION = '2.1.0';
our $llclass = 'Lemonldap::NG::Handler::Server';
use strict;

View File

@ -36,7 +36,7 @@ ok(
( defined($code) and ref($code) eq 'CODE' ),
'encode_base64 function is defined'
);
ok( $res = &$code, "Function works" );
ok( $res = &$code, "Function works" );
ok( $res eq 'dGVzdA==', 'Get good result' );
$sub = "sub { return ( listMatch('ABC; DEF; GHI','abc',1) ) }";
@ -58,5 +58,5 @@ ok(
'checkDate extended function is defined'
);
ok( $res = &$code, "Function works" );
ok( $res == 1, 'Get good result' );
ok( $res == 1, 'Get good result' );

View File

@ -37,14 +37,17 @@ ok( $res = $client->_get( '/', undef, undef, "lemonldap=$sessionId" ),
ok( $res->[0] == 200, ' Code is 200' ) or explain( $res, 200 );
count(2);
SKIP: {
skip "Regexp match in rules only supported in recent Perl", 0 unless $^V ge v5.25.7;
ok( $res = $client->_get( '/user_dwho/', undef, undef, "lemonldap=$sessionId" ),
'Regexp query' );
ok( $res->[0] == 200, 'Code is 200' ) or explain( $res, 200 );
count(2);
};
skip "Regexp match in rules only supported in recent Perl", 0
unless $^V ge v5.25.7;
ok(
$res =
$client->_get( '/user_dwho/', undef, undef, "lemonldap=$sessionId" ),
'Regexp query'
);
ok( $res->[0] == 200, 'Code is 200' ) or explain( $res, 200 );
count(2);
}
# Request an URI protected by custom function -> allowed
ok(
@ -115,14 +118,18 @@ ok( $res->[0] == 200, ' Code is 200' ) or explain( $res, 200 );
count(2);
SKIP: {
skip "Regexp match in rules only supported in recent Perl", 0 unless $^V ge v5.25.7;
ok( $res = $client->_get( '/user_rtyler/', undef, undef, "lemonldap=$sessionId" ),
'Regexp deny query' );
skip "Regexp match in rules only supported in recent Perl", 0
unless $^V ge v5.25.7;
ok(
$res = $client->_get(
'/user_rtyler/', undef, undef, "lemonldap=$sessionId"
),
'Regexp deny query'
);
ok( $res->[0] == 403, 'Code is 403' ) or explain( $res, 403 );
count(2);
}
# Required AuthnLevel = 5
ok(
$res = $client->_get( '/AuthStrong', undef, undef, "lemonldap=$sessionId" ),

View File

@ -39,7 +39,7 @@ my $res;
# Unauth tests
ok( $res = $client->_get('/test'), 'Get response' );
ok( $res->[0] == 200, 'Response code is 200' )
ok( $res->[0] == 200, 'Response code is 200' )
or print "Expect 200, got $res->[0]\n";
ok( $res->[2]->[0] eq 'Unauth', 'Get unauth result' )
or print "Expect Unauth, got $res->[2]->[0]\n";
@ -64,7 +64,7 @@ count(3);
# Bad path test
ok( $res = $client->_get('/[]/test'), 'Try a bad path' );
ok( $res->[0] == 400, 'Response is 400' );
ok( $res->[0] == 400, 'Response is 400' );
count(2);
clean();

View File

@ -570,7 +570,7 @@ sub scanTree {
# Subnode
elsif ( ref($leaf) ) {
$jleaf->{title} = $jleaf->{id} = $leaf->{title};
$jleaf->{type} = $leaf->{form} if ( $leaf->{form} );
$jleaf->{type} = $leaf->{form} if ( $leaf->{form} );
if ( $leaf->{title} =~ /^((?:oidc|saml|cas)Service)MetaData$/ ) {
no strict 'refs';
my @tmp = $self->scanLeaf( $leaf->{nodes} );

View File

@ -1454,9 +1454,10 @@ sub attributes {
documentation => 'Send a mail when password is changed',
},
portalRequireOldPassword => {
default => 1,
type => 'boolOrExpr',
documentation => 'Rule to require old password to change the password',
default => 1,
type => 'boolOrExpr',
documentation =>
'Rule to require old password to change the password',
},
hideOldPassword => {
default => 0,
@ -2126,16 +2127,16 @@ sub attributes {
},
msgFail => '__badExpression__',
},
keyTest => qr/^\S+$/,
keyTest => qr/^\S+$/,
keyMsgFail => '__badHostname__',
default => { default => 'deny', },
documentation => 'Virtualhost rules',
flags => 'h',
},
exportedHeaders => {
type => 'keyTextContainer',
help => 'writingrulesand_headers.html#headers',
keyTest => qr/^\S+$/,
type => 'keyTextContainer',
help => 'writingrulesand_headers.html#headers',
keyTest => qr/^\S+$/,
keyMsgFail => '__badHostname__',
test => {
keyTest => qr/^(?=[^\-])[\w\-]+(?<=[^-])$/,
@ -2146,10 +2147,10 @@ sub attributes {
flags => 'h',
},
post => {
type => 'postContainer',
help => 'formreplay.html',
test => sub { 1 },
keyTest => qr/^\S+$/,
type => 'postContainer',
help => 'formreplay.html',
test => sub { 1 },
keyTest => qr/^\S+$/,
keyMsgFail => '__badHostname__',
documentation => 'Virtualhost urls/Data to post',
},
@ -3015,11 +3016,10 @@ sub attributes {
documentation => 'Second factor required',
},
sfManagerRule => {
type => 'boolOrExpr',
default => 1,
help => 'secondfactor.html',
documentation =>
'Rule to display second factor Manager link',
type => 'boolOrExpr',
default => 1,
help => 'secondfactor.html',
documentation => 'Rule to display second factor Manager link',
},
sfRemovedMsgRule => {
type => 'boolOrExpr',
@ -4029,6 +4029,7 @@ m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
type => 'select',
select => [
{ k => 'front', v => 'Front Channel' },
#TODO #1194
# { k => 'back', v => 'Back Channel' },
],

View File

@ -11,7 +11,7 @@ sub portalConstants {
return {
# Portal errors
# Developers warning, do not use PE_INFO, it's reserved to autoRedirect.
# Developers warning, do not use PE_INFO, it's reserved to autoRedirect.
PE_LOGOUT_OK => -7,
PE_PASSWORD_OK => -6,
PE_IDPCHOICE => -5,

View File

@ -580,8 +580,8 @@ sub tree {
form => 'simpleInputContainer',
nodes => [
'singleSession', 'singleIP',
'singleUserByIP',
'notifyDeleted', 'notifyOther'
'singleUserByIP', 'notifyDeleted',
'notifyOther'
]
},
{

View File

@ -58,7 +58,7 @@ while (<F>) {
close F;
ok( $hstruct = from_json($hstruct), 'struct.json is JSON' );
ok( ref $hstruct eq 'ARRAY', 'struct.json is an array' )
ok( ref $hstruct eq 'ARRAY', 'struct.json is an array' )
or print STDERR "Expected: ARRAY, got: " . ( ref $hstruct ) . "\n";
count(2);

View File

@ -25,7 +25,7 @@ ok(
),
"Request succeed"
);
ok( $res->[0] == 200, "Result code is 200" );
ok( $res->[0] == 200, "Result code is 200" );
ok( $key = from_json( $res->[2]->[0] ), 'Response is JSON' );
count(3);

View File

@ -20,7 +20,7 @@ mkdir 't/sessions';
my ( $res, $resBody );
ok( $res = &client->_post( '/confs/', 'cfgNum=1', &body, 'application/json' ),
"Request succeed" );
ok( $res->[0] == 200, "Result code is 200" );
ok( $res->[0] == 200, "Result code is 200" );
ok( $resBody = from_json( $res->[2]->[0] ), "Result body contains JSON text" );
ok( $resBody->{result} == 0, "JSON response contains \"result:0\"" )

View File

@ -20,7 +20,7 @@ mkdir 't/sessions';
my ( $res, $resBody );
ok( $res = &client->_post( '/confs/', 'cfgNum=1', &body, 'application/json' ),
"Request succeed" );
ok( $res->[0] == 200, "Result code is 200" );
ok( $res->[0] == 200, "Result code is 200" );
ok( $resBody = from_json( $res->[2]->[0] ), "Result body contains JSON text" );
ok( $resBody->{result} == 1, "JSON response contains \"result:1\"" )
or print STDERR Dumper($resBody);

View File

@ -16,7 +16,7 @@ unlink 't/conf/lmConf-2.json';
my ( $res, $resBody );
ok( $res = &client->_post( '/confs/', 'cfgNum=1', &body, 'application/json' ),
"Request succeed" );
ok( $res->[0] == 200, "Result code is 200" );
ok( $res->[0] == 200, "Result code is 200" );
ok( $resBody = from_json( $res->[2]->[0] ), "Result body contains JSON text" );
ok( $resBody->{result} == 0, "JSON response contains \"result:0\"" )
or print STDERR Dumper($res);

View File

@ -17,7 +17,7 @@ mkdir 't/sessions';
my ( $res, $resBody );
ok( $res = &client->_post( '/confs/', 'cfgNum=1', &body, 'application/json' ),
"Request succeed" );
ok( $res->[0] == 200, "Result code is 200" );
ok( $res->[0] == 200, "Result code is 200" );
ok( $resBody = from_json( $res->[2]->[0] ), "Result body contains JSON text" );
ok( $resBody->{result} == 1, "JSON response contains \"result:1\"" )
or print STDERR Dumper($res);

View File

@ -23,11 +23,7 @@ my $res;
# Test 'set' command
@cmd = qw(-yes 1 set notification 1);
combined_like(
sub { llclient->run(@cmd) },
qr/Saved under/,
'"addKey" OK'
);
combined_like( sub { llclient->run(@cmd) }, qr/Saved under/, '"addKey" OK' );
# Test 'get' command
@cmd = qw(get notification);
@ -37,11 +33,7 @@ ok( $res =~ /^notification\s+=\s+1$/, '"get notification" OK' )
# Test 'addKey' command
@cmd = qw(-yes 1 addKey locationRules/test1.example.com ^/reject deny);
combined_like(
sub { llclient->run(@cmd) },
qr/Saved under/,
'"addKey" OK'
);
combined_like( sub { llclient->run(@cmd) }, qr/Saved under/, '"addKey" OK' );
# Test 'delKey' command
@cmd = qw(-yes 1 delKey locationRules/test1.example.com ^/reject);
@ -59,11 +51,7 @@ ok( $res =~ m#accept#, '"get key/subkey" OK' )
# Test 'set' command with key/subkey
@cmd = qw(-yes 1 set locationRules/test1.example.com/default deny);
combined_like(
sub { llclient->run(@cmd) },
qr/Saved under/,
'"addKey" OK'
);
combined_like( sub { llclient->run(@cmd) }, qr/Saved under/, '"addKey" OK' );
# Test 'save' command
@cmd = qw(-cfgNum 1 save);
@ -96,8 +84,7 @@ combined_like(
qr#\bAuthor IP\b#s,
'"Author IP" OK'
);
combined_like( sub { llcommonClient->run(@cmd) },
qr#\bLog\b#s, '"Log" OK' );
combined_like( sub { llcommonClient->run(@cmd) }, qr#\bLog\b#s, '"Log" OK' );
combined_like( sub { llcommonClient->run(@cmd) },
qr#\bVersion\b#s, '"Version" OK' );

View File

@ -17,7 +17,7 @@ mkdir 't/sessions';
my ( $res, $resBody );
ok( $res = &client->_post( '/confs/', 'cfgNum=1', &body, 'application/json' ),
"Request succeed" );
ok( $res->[0] == 200, "Result code is 200" );
ok( $res->[0] == 200, "Result code is 200" );
ok( $resBody = from_json( $res->[2]->[0] ), "Result body contains JSON text" );
ok( $resBody->{result} == 1, "JSON response contains \"result:1\"" )
or print STDERR Dumper($res);

View File

@ -148,7 +148,7 @@ count(5);
foreach (@ids) {
my $res;
ok( $res = &client->_del("/sessions/global/$_"), "Delete $_" );
ok( $res->[0] == 200, 'Result code is 200' );
ok( $res->[0] == 200, 'Result code is 200' );
ok( from_json( $res->[2]->[0] )->{result} == 1,
'Body is JSON and result==1' );
count(3);

View File

@ -100,7 +100,7 @@ SKIP: {
$res =
$client->jsonResponse( 'notifications/done', 'groupBy=substr(uid,1)' );
ok( $res->{result} == 1, 'Result = 1' );
ok( $res->{count} == 0, 'Count = 0' ) or diag Dumper($res);
ok( $res->{count} == 0, 'Count = 0' ) or diag Dumper($res);
#print STDERR Dumper($res);
}

View File

@ -277,7 +277,7 @@ $res = &client->jsonResponse( '/sfa/persistent',
'uid=*&groupBy=substr(uid,0)&U2FCheck=2&TOTPCheck=2&UBKCheck=2' );
ok( $res->{result} == 1,
'Search "uid"=* & UBK & TOTP & UBK - Result code = 1' );
ok( $res->{count} == 1, 'Found 1 result' ) or print STDERR Dumper($res);
ok( $res->{count} == 1, 'Found 1 result' ) or print STDERR Dumper($res);
ok( @{ $res->{values} } == 1, 'List 1 result' );
ok( $res->{values}->[0]->{value} && $res->{values}->[0]->{value} eq 'd',
'Result match "uid=d"' )

View File

@ -64,8 +64,8 @@ my @notManagedAttributes = (
'zimbraUrl',
# Other ini-only prms
'checkTime', 'status', 'soapProxyUrn',
'impersonationPrefix', 'pdataDomain',
'checkTime', 'status', 'soapProxyUrn',
'impersonationPrefix', 'pdataDomain',
'mySessionAuthorizedRWKeys', 'contextSwitchingPrefix'
);

View File

@ -111,8 +111,8 @@ sub verify {
return PE_OK;
}
else {
$self->userLogger->notice( 'Invalid TOTP for '
. $session->{ $self->conf->{whatToTrace} } );
$self->userLogger->notice(
'Invalid TOTP for ' . $session->{ $self->conf->{whatToTrace} } );
return PE_BADOTP;
}
}

View File

@ -25,7 +25,7 @@ sub init {
$hd->buildSub( $hd->substitute( $self->conf->{issuerDBGetRule} ) );
unless ($rule) {
my $error = $hd->tsv->{jail}->error || '???';
$self->error( "Bad GET activation rule -> $error" );
$self->error("Bad GET activation rule -> $error");
return 0;
}
$self->{rule} = $rule;

View File

@ -65,7 +65,7 @@ sub init {
$hd->buildSub( $hd->substitute( $self->conf->{issuerDBOpenIDRule} ) );
unless ($rule) {
my $error = $hd->tsv->{jail}->error || '???';
$self->error( "Bad OpenID activation rule -> $error" );
$self->error("Bad OpenID activation rule -> $error");
return 0;
}
$self->{rule} = $rule;

View File

@ -76,7 +76,7 @@ sub getCaptcha {
$image->random;
$image->create( 'normal', 'default', $self->fgColor, $self->bgColor );
my ( $imageData, $mimeType, $rdm ) = $image->out( force => 'png' );
my $img = 'data:image/png;base64,' . encode_base64( $imageData, '' );
my $img = 'data:image/png;base64,' . encode_base64( $imageData, '' );
my $token = $self->ott->createToken( { captcha => $rdm } );
return ( $token, $img );
}

View File

@ -1,307 +0,0 @@
package Lemonldap::NG::Portal::Lib::Choice;
use strict;
use Mouse;
use Safe;
use IO::String;
extends 'Lemonldap::NG::Portal::Lib::Wrapper';
with 'Lemonldap::NG::Portal::Lib::OverConf';
our $VERSION = '2.1.0';
has modules => ( is => 'rw', default => sub { {} } );
has rules => ( is => 'rw', default => sub { {} } );
has type => ( is => 'rw' );
has catch => ( is => 'rw', default => sub { {} } );
has sessionKey => ( is => 'ro', default => '_choice' );
my $_choiceRules;
# INITIALIZATION
# init() must be called by module::init() with a number:
# - 0 for auth
# - 1 for userDB
# - 2 for passwordDB ?
sub init {
my ( $self, $type ) = @_;
$self->type($type);
unless ( $self->conf->{authChoiceModules}
and %{ $self->conf->{authChoiceModules} } )
{
$self->error("'authChoiceModules' is empty");
return 0;
}
foreach my $name ( keys %{ $self->conf->{authChoiceModules} } ) {
my @mods =
split( /[;\|]/, $self->conf->{authChoiceModules}->{$name} );
my $module = '::'
. [ 'Auth', 'UserDB', 'Password' ]->[$type] . '::'
. $mods[$type];
my $over;
if ( $mods[5] ) {
eval { $over = JSON::from_json( $mods[5] ) };
if ($@) {
$self->logger->error("Bad over value ($@), skipped");
}
}
if ( $module = $self->loadModule( $module, $over ) ) {
$self->modules->{$name} = $module;
$self->logger->debug(
[qw(Authentication User Password)]->[$type]
. " module $name selected" );
}
else {
$self->logger->error(
"Choice: unable to load $name, disabling it: " . $self->error );
$self->error('');
}
# Test if auth module wants to catch some path
unless ($type) {
if ( $module->can('catch') ) {
$self->catch->{$name} = $module->catch;
}
}
# Display conditions
my $safe = Safe->new;
my $cond = $mods[4];
if ( defined $cond and $cond !~ /^$/ ) {
$self->logger->debug("Found rule $cond for $name");
$_choiceRules->{$name} =
$safe->reval("sub{my(\$env)=\@_;return ($cond)}");
if ($@) {
$self->logger->error("Bad condition $cond: $@");
return 0;
}
}
else {
$self->logger->debug("No rule for $name");
$_choiceRules->{$name} = sub { 1 };
}
}
unless ( keys %{ $self->modules } ) {
$self->error('Choice: no available modules found, aborting');
return 0;
}
return 1;
}
# RUNNING METHODS
sub checkChoice {
my ( $self, $req ) = @_;
my $name;
# Check Choice from pdata
if ( defined $req->pdata->{_choice} ) {
$name = $req->pdata->{_choice};
$self->logger->debug("Choice $name selected from pdata");
}
unless ($name) {
# Check with catch method
foreach ( keys %{ $self->catch } ) {
if ( $req->path_info =~ $self->catch->{$_} ) {
$name = $_;
$self->logger->debug(
"Choice $name selected from " . $req->path_info );
last;
}
}
}
unless ($name) {
# Check with other methods
$name ||=
$req->param( $self->conf->{authChoiceParam} )
|| $req->userData->{_choice}
|| $req->sessionInfo->{_choice}
or return 0;
$self->logger->debug("Choice $name selected");
}
unless ( defined $self->modules->{$name} ) {
$self->logger->error("Unknown choice '$name'");
return 0;
}
# Store choice if module loops
$req->pdata->{_choice} = $name;
$req->data->{_authChoice} = $name;
return $name if ( $req->data->{ "enabledMods" . $self->type } );
$req->sessionInfo->{_choice} = $name;
$req->data->{ "enabledMods" . $self->type } = [ $self->modules->{$name} ];
$self->p->_authentication->authnLevel("${name}AuthnLevel");
return $name;
}
sub name {
my ( $self, $req, $type ) = @_;
unless ($req) {
return 'Choice';
}
my $n = ref( $req->data->{ "enabledMods" . $self->type }->[0] );
$n =~ s/^Lemonldap::NG::Portal::(?:(?:UserDB|Auth)::)?//;
return $n;
}
sub getForm {
my ( $self, $req ) = @_;
my @authLoop;
# Test authentication choices
unless ( ref $self->conf->{authChoiceModules} eq 'HASH' ) {
$self->logger->warn("No authentication choices defined");
return [];
}
foreach ( sort keys %{ $self->conf->{authChoiceModules} } ) {
my $name = $_;
# Name can have a digit as first character
# for sorting purpose
# Remove it in displayed name
$name =~ s/^(\d*)?(\s*)?//;
# Replace also _ by space for a nice display
$name =~ s/\_/ /g;
# Find modules associated to authChoice
my ( $auth, $userDB, $passwordDB, $url, $condition ) =
split( /[;\|]/, $self->conf->{authChoiceModules}->{$_} );
unless ( $_choiceRules->{$_} ) {
$self->logger->error("$_ has no rule");
$_choiceRules->{$_} = sub { 1 };
}
unless ( $_choiceRules->{$_}->( $req->env ) ) {
$self->logger->debug(
"Condition returns false, authentication choice $_ will not be displayed"
);
}
else {
$self->logger->debug("Displaying authentication choice $_");
if ( $auth and $userDB and $passwordDB ) {
# Default URL
$req->{cspFormAction} ||= '';
if (
defined $url
and not $self->checkXSSAttack( 'URI',
$req->env->{'REQUEST_URI'} )
and $url =~
q%^(https?://)?[^\s/.?#$].[^\s]+$% # URL must be well formatted
)
{
#$url .= $req->env->{'REQUEST_URI'};
# Avoid append same URL
$req->{cspFormAction} .= " $url"
unless $req->{cspFormAction} =~ qr%\b$url\b%;
}
else {
$url .= '#';
}
$self->logger->debug("Use URL $url");
# Options to store in the loop
my $optionsLoop = {
name => $name,
key => $_,
module => $auth,
url => $url,
CHOICE_VALUE => $req->data->{_authChoice},
CHOICE_PARAM => $self->conf->{authChoiceParam},
};
# Get displayType for this module
no strict 'refs';
my $displayType = eval {
"Lemonldap::NG::Portal::Auth::${auth}"
->can('getForm')->( $self, $req );
} || 'logo';
$self->logger->debug( 'Display type '
. ( ref $displayType ? '[ref]' : $displayType )
. ' for module $auth' );
#$optionsLoop->{$displayType} = 1 unless(ref $displayType);
$optionsLoop->{form} = $displayType;
my $logo = $_;
if ( $auth eq 'Custom' ) {
$logo =
( $self->{conf}->{customAuth} =~ /::(\w+)$/ )[0];
}
# If displayType is logo, check if key.png is available
if ( -e $self->conf->{templateDir}
. "/../htdocs/static/common/modules/"
. $logo
. ".png" )
{
$optionsLoop->{logoFile} = $logo . ".png";
}
else {
$optionsLoop->{logoFile} = $auth . ".png";
}
# Register item in loop
push @authLoop, $optionsLoop;
$self->logger->debug(
"Authentication choice $name will be displayed");
}
else {
$req->error("Authentication choice $_ value is invalid");
return 0;
}
}
}
open my $fh,
$self->conf->{templateDir} . '/'
. $self->p->getSkin($req)
. "/choice.tpl"
or die $!;
my $res;
{
local $/ = undef;
$res = readline $fh;
}
close $fh;
while ( $res =~ m#<TMPL_LOOP NAME="AUTH_LOOP">(.*?)</TMPL_LOOP>#s ) {
my $content = $1;
my $new = '';
foreach (@authLoop) {
my $tmp = $content;
if ( my @match = ( $tmp =~ m#<TMPL_VAR NAME="(\w+)">#gs ) ) {
foreach my $key (@match) {
$tmp =~ s#<TMPL_VAR NAME="$key">#$_->{$key}#gs
if defined $_->{$key};
}
}
$tmp =~ s#__LLNG_FORM__#<TMPL_INCLUDE NAME="$_->{form}.tpl">#gs;
$new .= $tmp;
}
$res =~ s#<TMPL_LOOP NAME="AUTH_LOOP">.*?</TMPL_LOOP>#$new#s;
}
$req->tplParams->{CHOICE_PARAM} = $self->conf->{authChoiceParam};
return IO::String->new($res);
}
1;

View File

@ -1,181 +0,0 @@
package Lemonldap::NG::Portal::Lib::LDAP;
use strict;
use Mouse;
use Lemonldap::NG::Portal::Lib::Net::LDAP;
use Lemonldap::NG::Portal::Main::Constants
qw(PE_OK PE_LDAPCONNECTFAILED PE_LDAPERROR PE_BADCREDENTIALS);
extends 'Lemonldap::NG::Common::Module';
our $VERSION = '2.1.0';
# PROPERTIES
has ldap => (
is => 'rw',
lazy => 1,
builder => 'newLdap',
);
has attrs => (
is => 'rw',
lazy => 1,
builder => sub {
return [
values %{ $_[0]->{conf}->{exportedVars} },
values %{ $_[0]->{conf}->{ldapExportedVars} }
];
}
);
sub newLdap {
my $self = $_[0];
my $ldap;
# Build object and test LDAP connexion
unless (
$ldap = Lemonldap::NG::Portal::Lib::Net::LDAP->new(
{ p => $self->{p}, conf => $self->{conf} }
)
)
{
$self->logger->error("LDAP initialization error: $@");
return undef;
}
# Test connection
my $msg = $ldap->bind;
if ( $msg->code ) {
$self->logger->error( 'LDAP test has failed: ' . $msg->error );
}
elsif ( $self->{conf}->{ldapPpolicyControl} and not $ldap->loadPP() ) {
$self->logger->error("LDAP password policy error");
}
return $ldap;
}
has filter => (
is => 'rw',
lazy => 1,
builder => 'buildFilter',
);
has mailFilter => (
is => 'rw',
lazy => 1,
builder => 'buildMailFilter',
);
sub buildFilter {
return $_[0]->_buildFilter( $_[0]->conf->{AuthLDAPFilter}
|| $_[0]->conf->{LDAPFilter}
|| '(&(uid=$user)(objectClass=inetOrgPerson))' );
}
sub buildMailFilter {
my $f = $_[0]->conf->{mailLDAPFilter}
|| '(&(mail=$user)(objectClass=inetOrgPerson))';
$f =~ s/\$mail\b/\$user/g;
return $_[0]->_buildFilter($f);
}
sub _buildFilter {
my ( $self, $filter ) = @_;
my $conf = $self->{conf};
$self->{p}->logger->debug("LDAP Search base: $_[0]->{conf}->{ldapBase}");
$filter =~ s/"/\\"/g;
$filter =~ s/\$(\w+)/".\$req->{sessionInfo}->{$1}."/g;
$filter =~ s/\$req->\{sessionInfo\}->\{user\}/\$req->{user}/g;
$filter =~
s/\$req->\{sessionInfo\}->\{(_?password|mail)\}/\$req->{data}->{$1}/g;
$self->{p}->logger->debug("LDAP transformed filter: $filter");
$filter = "sub{my(\$req)=\$_[0];return \"$filter\";}";
my $res = eval $filter;
if ($@) {
$self->error("Unable to build fiter: $@");
}
return $res;
}
# INITIALIZATION
sub init {
my ($self) = @_;
$self->ldap
or $self->logger->error(
"LDAP initialization has failed, but let's continue");
$self->filter;
}
# RUNNING METHODS
sub getUser {
my ( $self, $req, %args ) = @_;
$self->validateLdap;
unless ( $self->ldap ) {
return PE_LDAPCONNECTFAILED;
}
$self->bind();
my $mesg = $self->ldap->search(
base => $self->conf->{ldapBase},
scope => 'sub',
filter => (
$args{useMail}
? $self->mailFilter->($req)
: $self->filter->($req)
),
defer => $self->conf->{ldapSearchDeref} || 'find',
attrs => $self->attrs,
);
if ( $mesg->code() != 0 ) {
$self->logger->error(
'LDAP Search error ' . $mesg->code . ": " . $mesg->error );
return PE_LDAPERROR;
}
if ( $mesg->count() > 1 ) {
$self->logger->error('More than one entry returned by LDAP directory');
eval { $self->p->_authentication->setSecurity($req) };
return PE_BADCREDENTIALS;
}
unless ( $req->data->{ldapentry} = $mesg->entry(0) ) {
$self->userLogger->warn("$req->{user} was not found in LDAP directory");
eval { $self->p->_authentication->setSecurity($req) };
return PE_BADCREDENTIALS;
}
$req->data->{dn} = $req->data->{ldapentry}->dn();
PE_OK;
}
# Validate LDAP connection before use
sub validateLdap {
my ($self) = @_;
unless ($self->ldap
and $self->ldap->root_dse( attrs => ['supportedLDAPVersion'] ) )
{
$self->ldap->DESTROY if ( $self->ldap );
$self->ldap( $self->newLdap );
}
}
# Bind
sub bind {
my $self = shift;
$self->validateLdap;
return undef unless ( $self->ldap );
my $msg = $self->ldap->bind(@_);
if ( $msg->code ) {
$self->logger->error( $msg->error );
return undef;
}
return 1;
}
1;

View File

@ -12,7 +12,7 @@ use Unicode::String qw(utf8);
use Scalar::Util 'weaken';
use utf8;
our $VERSION = '2.1.0';
our $VERSION = '2.1.0';
our $ppLoaded = 0;
BEGIN {

View File

@ -35,7 +35,7 @@ sub checkForNotifications {
unless ($notifs) {
$self->logger->info("No notification found");
return 0;
};
}
# Transform notifications
my $i = 0; # Files count
@ -125,7 +125,7 @@ sub viewNotification {
unless ($notifs) {
$self->logger->info("No accepted notification found");
return 0;
};
}
# Transform notifications
my $i = 0; # Files count

View File

@ -66,7 +66,7 @@ sub checkForNotifications {
unless ($notifs) {
$self->logger->info("No notification found");
return 0;
};
}
# Transform notifications
my $i = 0; # Files count
@ -173,7 +173,7 @@ sub viewNotification {
unless ($notifs) {
$self->logger->info("No accepted notification found");
return 0;
};
}
# Transform notifications
my $i = 0; # Files count

View File

@ -1,248 +0,0 @@
## @file
# OpenID SREG extension for Lemonldap::NG::Portal::Issuer::OpenID class
## @class
# OpenID SREG extension for Lemonldap::NG::Portal::Issuer::OpenID class
package Lemonldap::NG::Portal::Lib::OpenID::SREG;
use strict;
use Lemonldap::NG::Common::Regexp;
our $VERSION = '2.1.0';
## @method protected hash sregHook(hash prm)
# Hook called to add SREG parameters to the OpenID response
# @return Hash containing wanted parameters
sub sregHook {
my ( $self, $req, $u, $trust_root, $is_id, $is_trusted, $prm ) = @_;
my ( @req, @opt );
# Refuse federation if rejected by user
if ( $req->param('confirm') and $req->param('confirm') == -1 ) {
my %h;
$h{$_} = undef foreach (
qw(fullname nickname language postcode timezone country gender email dob)
);
$self->p->updatePersistentSession( $req, \%h );
return 0;
}
# If identity is not trusted, does nothing
return ( 0, $prm ) unless ( $is_id and $is_trusted );
$self->logger->debug("SREG start");
my $accepted = 1;
# Check all parameters
my @pol;
while ( my ( $k, $v ) = each %$prm ) {
# Store policy if provided
if ( $k eq 'policy_url' ) {
if ( $v =~ Lemonldap::NG::Common::Regexp::HTTP_URI ) {
push @pol, { url => $v };
# Question: is it important to notify policy changes ?
# if yes, uncomment this
#my $p =
# $req->{sessionInfo}->{"_openidTrust$trust_root\_Policy"};
#$accepted = 0 unless ( $p and $p eq $v );
}
else {
$self->logger->error("Bad policy url");
}
}
# Parse required attributes
elsif ( $k eq 'required' ) {
$self->logger->debug("Required attr $v");
push @req, split( /,/, $v );
}
# Parse optional attributes
elsif ( $k eq 'optional' ) {
$self->logger->debug("Optional attr $v");
push @opt,
grep { defined $self->conf->{"openIdSreg_$trust_root$_"} }
split( /,/, $v );
}
else {
$self->logger->error("Unknown OpenID SREG request $k");
}
}
$req->data->{_openIdTrustExtMsg} .= $self->loadTemplate(
$req,
'openIdPol',
params => {
policies => \@pol,
}
) if (@pol);
# Check if required keys are valid SREG requests
# Question: reject bad SREG request ? Not done yet
@req = sregfilter( $self, @req );
@opt = sregfilter( $self, @opt );
# Return if nothing is asked
return ( 1, {} ) unless ( @req or @opt );
# If a required data is not available, returns nothing
foreach my $k (@req) {
unless ( $self->conf->{"openIdSreg_$k"} ) {
$self->logger->notice(
"Parameter $k is required by $trust_root but not defined in configuration"
);
$req->info(
$self->loadTemplate(
$req, 'simpleInfo',
params => { trspan => "openidRpns,$k" }
)
);
return ( 0, {} );
}
}
# Now set data
my ( %r, %msg, %ag, %toStore );
# Requested parameters: check if already agreed or confirm is set
foreach my $k (@req) {
my $agree = $req->{sessionInfo}->{"_openidTrust$trust_root\_$k"};
if ($accepted) {
unless ( $req->param('confirm') or $agree ) {
$accepted = 0;
}
elsif ( !$agree ) {
$toStore{"_openidTrust$trust_root\_$k"} = 1;
}
}
my $tmp = $self->conf->{"openIdSreg_$k"};
$tmp =~ s/^\$//;
$msg{req}->{$k} = $r{$k} =
$req->{sessionInfo}->{ $self->{"openIdSreg_$k"} } || '';
}
# Optional parameters:
foreach my $k (@opt) {
my $tmp = $self->conf->{"openIdSreg_$k"};
$tmp =~ s/^\$//;
my $agree = $req->{sessionInfo}->{"_openidTrust$trust_root\_$k"};
if ($accepted) {
# First, check if already accepted
unless ( $req->param('confirm') or defined($agree) ) {
$accepted = 0;
$r{$k} = $req->{sessionInfo}->{$tmp}
|| '';
}
# If confirmation is returned, check the value for this field
elsif ( $req->param('confirm') == 1 ) {
my $ck = 0;
if ( defined( $req->param("sreg_$k") ) ) {
$ck = ( $req->param("sreg_$k") eq 'OK' ) || 0;
}
# Store the value returned
if ( !defined($agree) or $agree != $ck ) {
$toStore{"_openidTrust$trust_root\_$k"} = $ck;
$agree = $ck;
}
}
}
$msg{opt}->{$k} = $req->{sessionInfo}->{$tmp} || '';
# Store the value only if user agree it
if ($agree) {
$r{$k} = $msg{opt}->{$k};
$ag{$k} = 1;
}
elsif ( !defined($agree) ) {
$ag{$k} = 1;
}
else {
$ag{$k} = 0;
}
}
$self->p->updatePersistentSession( $req, \%toStore ) if (%toStore);
# Check if user has agreed request
if ($accepted) {
$self->userLogger->info(
$req->{sessionInfo}->{ $self->conf->{whatToTrace} }
. " has accepted OpenID SREG exchange with $trust_root" );
return ( 1, \%r );
}
# else build message and return 0
else {
my ( @mopt, @mreq );
# No choice for requested parameters: just an information
foreach my $k (@req) {
utf8::decode( $msg{req}->{$k} );
push @mreq, { k => $k, m => $msg{req}->{$k} };
}
# For optional parameters: checkboxes are displayed
foreach my $k (@opt) {
utf8::decode( $msg{opt}->{$k} );
push @mopt,
{
k => $k,
m => $msg{opt}->{$k},
c => ( $ag{$k} ? 'checked' : '' )
};
}
$req->data->{_openIdTrustExtMsg} .= $self->loadTemplate(
$req,
'openIdTrust',
params => {
required => \@mreq,
optional => \@mopt,
}
);
$self->logger->debug('Building validation form');
return ( 0, $prm );
}
}
## @method private array sregfilter(array attr)
# Filter the arguments passed as parameters by checking their compliance with
# SREG.
# @return fitered data
sub sregfilter {
my ( $self, @attr ) = @_;
my ( @ret, @rej );
# Browse attributes
foreach my $s (@attr) {
if ( $s =~
/^(?:(?:(?:full|nick)nam|languag|postcod|timezon)e|country|gender|email|dob)$/
)
{
push @ret, $s;
}
else {
$s =~ s/\W/\./sg;
push @rej, $s;
}
}
# Warn if some parameters are rejected
if (@rej) {
$self->logger->warn( "Requested parameter(s) "
. join( ',', @rej )
. "is(are) not valid OpenID SREG parameter(s)" );
}
# Return valid SREG parameters
return @ret;
}
1;

View File

@ -1,232 +0,0 @@
## @file
# Subclass of Net::OpenID::Server that manage OpenID extensions
## @class
# Subclass of Net::OpenID::Server that manage OpenID extensions
package Lemonldap::NG::Portal::Lib::OpenID::Server;
use strict;
use base qw(Net::OpenID::Server);
use fields qw(_extensions);
use Net::OpenID::Server;
use Lemonldap::NG::Common::Regexp;
use constant DEBUG => 0;
our $VERSION = '2.1.0';
use constant OPENID2_NS => 'http://specs.openid.net/auth/2.0';
use constant OPENID2_ID_SELECT =>
'http://specs.openid.net/auth/2.0/identifier_select';
*_push_url_arg =
( $Net::OpenID::Server::VERSION >= 1.09 )
? *OpenID::util::push_url_arg
: *Net::OpenID::Server::_push_url_arg;
## @cmethod Lemonldap::NG::Portal::Lib::OpenID::Server new(hash opts)
# Call Net::OpenID::Server::new() and store extensions
# @param %opts Net::OpenID::Server options
# @return Lemonldap::NG::Portal::Lib::OpenID::Server new object
sub new {
my $class = shift;
my $self = fields::new($class);
my %opts = @_;
$self->$_( delete $opts{$_} ) foreach (qw(extensions));
$self->SUPER::new(%opts);
#$self->{get_args} = sub { $self->param(@_) };
}
## @method protected void extensions()
# Manage "extensions" constructor parameter
sub extensions {
my $self = shift;
$self->{_extensions} = shift;
}
## @method protected list _mode_checkid(string mode, boolean redirect_for_setup)
# Overload Net::OpenID::Server::_mode_checkid to call extensions hook
# @param $mode OpenID mode
# @param $redirect_for_setup indicates that user must be redirected or not for
# setup
# @return (string $type, hashref parameters)
sub _mode_checkid {
my Lemonldap::NG::Portal::Lib::OpenID::Server $self = shift;
my ( $mode, $redirect_for_setup ) = @_;
my $return_to = $self->args("openid.return_to");
return $self->_fail("no_return_to")
unless ( $return_to
and $return_to =~ m!^https?://! );
my $trust_root = $self->args("openid.trust_root") || $return_to;
$trust_root = $self->args("openid.realm")
if $self->args('openid.ns') eq OPENID2_NS;
return $self->_fail("invalid_trust_root")
unless ( $trust_root =~ Lemonldap::NG::Common::Regexp::HTTP_URI
and Net::OpenID::Server::_url_is_under( $trust_root, $return_to ) );
my $identity = $self->args("openid.identity");
# chop off the query string, in case our trust_root came from the return_to URL
$trust_root =~ s/\?.*//;
my $u = $self->_proxy("get_user");
if ( $self->args('openid.ns') eq OPENID2_NS
&& $identity eq OPENID2_ID_SELECT )
{
$identity = $self->_proxy( "get_identity", $u, $identity );
}
my $is_identity = $self->_proxy( "is_identity", $u, $identity );
my $is_trusted =
$self->_proxy( "is_trusted", $u, $trust_root, $is_identity );
my ( %extVars, %is_ext_trusted );
my $is_exts_trusted = 1;
if ( ref( $self->{_extensions} ) ) {
my @list = $self->args->();
my %extArgs;
foreach my $arg (@list) {
next unless ( $arg =~ /^openid\.(\w+)\.([\w\.]+)?/ );
my $tmp = $1;
my $val = $2;
$extArgs{$tmp}->{$val} = scalar $self->args->($arg);
}
foreach my $ns ( keys %{ $self->{_extensions} } ) {
print STDERR "Launching OpenIP $ns hook\n" if (DEBUG);
my $h;
( $is_ext_trusted{$ns}, $h ) = $self->{_extensions}->{$ns}->(
$u, $trust_root, $is_identity, $is_trusted,
delete( $extArgs{$ns} ) || {}
);
if ($h) {
while ( my ( $k, $v ) = each %$h ) {
print STDERR "$ns returned data: $k => $v\n" if (DEBUG);
$extVars{"$ns.$k"} = $v;
}
}
$is_exts_trusted &&= $is_ext_trusted{$ns};
}
# TODO: warn if keys(%extArgs)
}
# assertion path:
if ( $is_identity && $is_trusted && $is_exts_trusted ) {
my %sArgs = (
identity => $identity,
claimed_id => $self->args('openid.claimed_id'),
return_to => $return_to,
assoc_handle => $self->args("openid.assoc_handle"),
ns => $self->args('openid.ns'),
);
$sArgs{additional_fields} = \%extVars if (%extVars);
my $ret_url = $self->signed_return_url(%sArgs);
return ( "redirect", $ret_url );
}
# Assertion could not be made, so user requires setup (login/trust...
# something). Two ways that can happen: caller might have asked us for an
# immediate return with a setup URL (the default), or explictly said that
# we're in control of the user-agent's full window, and we can do whatever
# we want with them now.
# TODO: call extension sub for setup
my %setup_args = (
$self->_setup_map("trust_root"), $trust_root,
$self->_setup_map("realm"), $trust_root,
$self->_setup_map("return_to"), $return_to,
$self->_setup_map("identity"), $identity,
$self->_setup_map("assoc_handle"), $self->args("openid.assoc_handle"),
%extVars,
);
$setup_args{ $self->_setup_map('ns') } = $self->args('openid.ns')
if $self->args('openid.ns');
my $setup_url = $self->{setup_url}
or Carp::croak("No setup_url defined.");
_push_url_arg( \$setup_url, %setup_args );
if ( $mode eq "checkid_immediate" ) {
my $ret_url = $return_to;
if ( $self->args('openid.ns') eq OPENID2_NS ) {
_push_url_arg( \$ret_url, "openid.ns", $self->args('openid.ns') );
_push_url_arg( \$ret_url, "openid.mode", "setup_needed" );
}
else {
_push_url_arg( \$ret_url, "openid.mode", "id_res" );
_push_url_arg( \$ret_url, "openid.user_setup_url", $setup_url );
}
return ( "redirect", $ret_url );
}
else {
# the "checkid_setup" mode, where we take control of the user-agent
# and return to their return_to URL later.
if ($redirect_for_setup) {
return ( "redirect", $setup_url );
}
else {
return ( "setup", \%setup_args );
}
}
}
1;
__END__
=encoding utf8
=head1 NAME
Lemonldap::NG::Portal::Lib::OpenID::Server - Add capability to manage extensions to
Net::OpenID::Server
=head1 DESCRIPTION
Lemonldap::NG::Portal::Lib::OpenID::Server adds capability to manage extensions to
Net::OpenID::Server.
=head1 SEE ALSO
L<http://lemonldap-ng.org>, L<Net::OpenID::Server>
=head1 AUTHORS
=over
=item LemonLDAP::NG team L<http://lemonldap-ng.org/team>
=back
=head1 BUG REPORT
Use OW2 system to report bug or ask for features:
L<https://gitlab.ow2.org/lemonldap-ng/lemonldap-ng/issues>
=head1 DOWNLOAD
Lemonldap::NG is available at
L<http://forge.objectweb.org/project/showfiles.php?group_id=274>
=head1 COPYRIGHT AND LICENSE
See COPYING file for details.
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see L<http://www.gnu.org/licenses/>.
=cut

View File

@ -1743,8 +1743,10 @@ sub replayProtection {
return 0;
}
}
} else {
$self->logger->warn( "No assertion session found for request ID ".$samlID);
}
else {
$self->logger->warn(
"No assertion session found for request ID " . $samlID );
}
return 0;

View File

@ -1,52 +0,0 @@
##@file
# Slave common functions
##@class
# Slave common functions
package Lemonldap::NG::Portal::Lib::Slave;
use Exporter;
use base qw(Exporter);
use strict;
our @EXPORT = qw(checkIP checkHeader);
our $VERSION = '2.1.0';
# RUNNING METHODS
## @method Lemonldap::NG::Portal::_Slave checkIP()
# @return true if remote IP is accredited in LL::NG conf
sub checkIP {
my ( $self, $req ) = @_;
my $remoteIP = $req->address;
return 1
if (!$self->conf->{slaveMasterIP}
|| $self->conf->{slaveMasterIP} =~ /\b$remoteIP\b/ );
$self->userLogger->warn('Client IP not accredited for Slave module');
return 0;
}
## @method Lemonldap::NG::Portal::_Slave checkHeader()
# @return true if header content matches LL::NG conf
sub checkHeader {
my ( $self, $req ) = @_;
return 1
unless ( $self->conf->{slaveHeaderName}
and $self->conf->{slaveHeaderContent} );
my $slave_header = 'HTTP_' . uc( $self->{conf}->{slaveHeaderName} );
$slave_header =~ s/\-/_/g;
my $headerContent = $req->env->{$slave_header};
$self->logger->debug(
"Required Slave header => $self->{conf}->{slaveHeaderName}");
$self->logger->debug("Received Slave header content => $headerContent");
return 1
if ( $headerContent
and $self->conf->{slaveHeaderContent} =~ /\b$headerContent\b/ );
$self->userLogger->warn('Matching header not found for Slave module ');
return 0;
}
1;

View File

@ -1,26 +0,0 @@
package Lemonldap::NG::Portal::Lib::_tokenRule;
use strict;
use Mouse;
our $VERSION = '2.1.0';
has ottRule => (
is => 'rw',
lazy => 1,
default => sub {
my $rule = $_[0]->conf->{requireToken};
my $hd = $_[0]->p->HANDLER;
$rule = $hd->buildSub( $hd->substitute($rule) );
unless ($rule) {
$_[0]->logger->error(
'Unable to compile "requireToken" rule => Forcing token');
$rule = sub { 1 };
}
return $rule;
}
);
sub init { 1 }
1;

View File

@ -15,9 +15,9 @@ use constant CommonPrms => {
LANGS => 'showLanguages',
};
has skinRules => ( is => 'rw' );
has skinRules => ( is => 'rw' );
has requireOldPwd => ( is => 'rw', default => sub { 1 } );
has favAppsRule => ( is => 'rw', default => sub { 1 } );
has favAppsRule => ( is => 'rw', default => sub { 1 } );
sub displayInit {
my ($self) = @_;
@ -45,8 +45,7 @@ sub displayInit {
HANDLER->substitute( $self->conf->{portalDisplayFavApps} ) );
unless ($rule) {
my $error = HANDLER->tsv->{jail}->error || '???';
$self->error(
"Bad FavApps activation rule -> " . $error );
$self->error( "Bad FavApps activation rule -> " . $error );
return 0;
}
$self->favAppsRule($rule);
@ -135,7 +134,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} )
@ -157,12 +156,12 @@ sub display {
AUTH_ERROR => $self->error,
AUTH_ERROR_TYPE => $req->error_type,
MSG => $info,
URL => $req->{urldc} || $self->conf->{portal}, # Fix 2158
HIDDEN_INPUTS => $self->buildOutgoingHiddenForm( $req, $method ),
ACTIVE_TIMER => $req->data->{activeTimer},
CHOICE_PARAM => $self->conf->{authChoiceParam},
CHOICE_VALUE => $req->data->{_authChoice},
FORM_METHOD => $method,
URL => $req->{urldc} || $self->conf->{portal}, # Fix 2158
HIDDEN_INPUTS => $self->buildOutgoingHiddenForm( $req, $method ),
ACTIVE_TIMER => $req->data->{activeTimer},
CHOICE_PARAM => $self->conf->{authChoiceParam},
CHOICE_VALUE => $req->data->{_authChoice},
FORM_METHOD => $method,
(
( not $req->{urldc} ) ? ( SEND_PARAMS => 1 )
: ()
@ -236,18 +235,19 @@ sub display {
%templateParams = (
AUTH_USER => $req->{sessionInfo}->{ $self->conf->{portalUserAttr} },
NEWWINDOW => $self->conf->{portalOpenLinkInNewWindow},
LOGOUT_URL => $self->conf->{portal} . "?logout=1",
APPSLIST_ORDER => $req->{sessionInfo}->{'_appsListOrder'},
PING => $self->conf->{portalPingInterval},
REQUIRE_OLDPASSWORD => $self->requireOldPwd->($req, $req->userData),
HIDE_OLDPASSWORD => 0,
STARS => $self->favAppsRule->( $req, $req->userData ),
DISPLAY_PPOLICY => $self->conf->{portalDisplayPasswordPolicy},
PPOLICY_MINSIZE => $self->conf->{passwordPolicyMinSize},
PPOLICY_MINLOWER => $self->conf->{passwordPolicyMinLower},
PPOLICY_MINUPPER => $self->conf->{passwordPolicyMinUpper},
PPOLICY_MINDIGIT => $self->conf->{passwordPolicyMinDigit},
PPOLICY_NOPOLICY => !$isPP,
LOGOUT_URL => $self->conf->{portal} . "?logout=1",
APPSLIST_ORDER => $req->{sessionInfo}->{'_appsListOrder'},
PING => $self->conf->{portalPingInterval},
REQUIRE_OLDPASSWORD =>
$self->requireOldPwd->( $req, $req->userData ),
HIDE_OLDPASSWORD => 0,
STARS => $self->favAppsRule->( $req, $req->userData ),
DISPLAY_PPOLICY => $self->conf->{portalDisplayPasswordPolicy},
PPOLICY_MINSIZE => $self->conf->{passwordPolicyMinSize},
PPOLICY_MINLOWER => $self->conf->{passwordPolicyMinLower},
PPOLICY_MINUPPER => $self->conf->{passwordPolicyMinUpper},
PPOLICY_MINDIGIT => $self->conf->{passwordPolicyMinDigit},
PPOLICY_NOPOLICY => !$isPP,
PPOLICY_ALLOWEDSPECHAR => $speChars,
(
$speChars

View File

@ -99,7 +99,7 @@ sub _redirect {
$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;
$req->{urldc} = $self->conf->{portal} . '/' . $self->path;
$req->pdata->{_url} = encode_base64( $req->urldc, '' );
$req->pdata->{issuerTs} = time;
}
@ -152,7 +152,7 @@ sub _forAuthUser {
# In case a confirm form is shown, we need it to POST on the
# current Path
$req->data->{confirmFormAction} = URI->new($req->uri)->path;
$req->data->{confirmFormAction} = URI->new( $req->uri )->path;
}
# Clean pdata: keepPdata has been set, so pdata must be cleaned here

View File

@ -339,11 +339,11 @@ sub _buildApplicationHash {
my $applications;
# Get application items
my $appname = $apphash->{options}->{name} || $appid;
my $appuri = $apphash->{options}->{uri} || "";
my $appdesc = $apphash->{options}->{description};
my $applogo = $apphash->{options}->{logo};
my $apptip = $apphash->{options}->{tooltip} || $appname;
my $appname = $apphash->{options}->{name} || $appid;
my $appuri = $apphash->{options}->{uri} || "";
my $appdesc = $apphash->{options}->{description};
my $applogo = $apphash->{options}->{logo};
my $apptip = $apphash->{options}->{tooltip} || $appname;
my $appIsFavApp = $apphash->{options}->{isFavApp} || "0";
# Detect sub applications

View File

@ -14,26 +14,26 @@ use Mouse;
# Developers: 2FA must be loaded before Notifications
# Developers: GlobalLogout must be the last loaded plugin
our @pList = (
portalDisplayResetPassword => '::Plugins::MailPasswordReset',
portalDisplayResetPassword => '::Plugins::MailPasswordReset',
portalDisplayCertificateResetByMail => '::Plugins::CertificateResetByMail',
portalStatus => '::Plugins::Status',
cda => '::Plugins::CDA',
notification => '::Plugins::Notifications',
portalCheckLogins => '::Plugins::History',
stayConnected => '::Plugins::StayConnected',
bruteForceProtection => '::Plugins::BruteForceProtection',
grantSessionRules => '::Plugins::GrantSession',
upgradeSession => '::Plugins::Upgrade',
autoSigninRules => '::Plugins::AutoSignin',
checkState => '::Plugins::CheckState',
portalForceAuthn => '::Plugins::ForceAuthn',
checkUser => '::Plugins::CheckUser',
impersonationRule => '::Plugins::Impersonation',
portalDisplayFavApps => '::Plugins::FavApps',
contextSwitchingRule => '::Plugins::ContextSwitching',
decryptValueRule => '::Plugins::DecryptValue',
globalLogoutRule => '::Plugins::GlobalLogout',
refreshSessions => '::Plugins::Refresh',
portalStatus => '::Plugins::Status',
cda => '::Plugins::CDA',
notification => '::Plugins::Notifications',
portalCheckLogins => '::Plugins::History',
stayConnected => '::Plugins::StayConnected',
bruteForceProtection => '::Plugins::BruteForceProtection',
grantSessionRules => '::Plugins::GrantSession',
upgradeSession => '::Plugins::Upgrade',
autoSigninRules => '::Plugins::AutoSignin',
checkState => '::Plugins::CheckState',
portalForceAuthn => '::Plugins::ForceAuthn',
checkUser => '::Plugins::CheckUser',
impersonationRule => '::Plugins::Impersonation',
portalDisplayFavApps => '::Plugins::FavApps',
contextSwitchingRule => '::Plugins::ContextSwitching',
decryptValueRule => '::Plugins::DecryptValue',
globalLogoutRule => '::Plugins::GlobalLogout',
refreshSessions => '::Plugins::Refresh',
);
##@method list enabledPlugins

View File

@ -42,14 +42,17 @@ sub _modifyPassword {
return PE_PASSWORD_MISMATCH
unless ( $req->data->{newpassword} eq $req->param('confirmpassword') );
my $rule =
$self->p->HANDLER->buildSub( $self->p->HANDLER->substitute( $self->conf->{portalRequireOldPassword} ) );
my $rule = $self->p->HANDLER->buildSub(
$self->p->HANDLER->substitute(
$self->conf->{portalRequireOldPassword}
)
);
unless ($rule) {
my $error = $self->p->HANDLER->tsv->{jail}->error || '???';
}
# Check if portal require old password
if ( $rule->($req, $req->userData) or $requireOldPwd ) {
if ( $rule->( $req, $req->userData ) or $requireOldPwd ) {
# TODO: verify oldpassword
unless ( $req->data->{oldpassword} = $req->param('oldpassword') ) {
@ -157,9 +160,13 @@ sub checkPasswordQuality {
# Fobidden special characters
$password =~ s/[\Q$speChars\E\w]//g;
if ($password) {
$self->logger->error(
'Password contains ' . length($password) . " forbidden character(s): $password");
return length($password) > 1 ? PE_PP_NOT_ALLOWED_CHARACTERS : PE_PP_NOT_ALLOWED_CHARACTER;
$self->logger->error( 'Password contains '
. length($password)
. " forbidden character(s): $password" );
return
length($password) > 1
? PE_PP_NOT_ALLOWED_CHARACTERS
: PE_PP_NOT_ALLOWED_CHARACTER;
}
return PE_OK;

View File

@ -39,12 +39,12 @@ sub modifyPassword {
my $error = $self->p->HANDLER->tsv->{jail}->error || '???';
}
if ( $req->data->{dn} ) {
$dn = $req->data->{dn};
$dn = $req->data->{dn};
$requireOldPassword = $rule->( $req, $req->userData );
$self->logger->debug("Get DN from request data: $dn");
}
else {
$dn = $req->sessionInfo->{_dn};
$dn = $req->sessionInfo->{_dn};
$requireOldPassword = $rule->( $req, $req->sessionInfo );
$self->logger->debug("Get DN from session data: $dn");
}
@ -59,7 +59,8 @@ sub modifyPassword {
# Call the modify password method
my $code =
$self->ldap->userModifyPassword( $dn, $pwd, $req->data->{oldpassword}, 0 , $requireOldPassword );
$self->ldap->userModifyPassword( $dn, $pwd, $req->data->{oldpassword},
0, $requireOldPassword );
unless ( $code == PE_PASSWORD_OK ) {
return $code;

View File

@ -46,7 +46,7 @@ sub modifyPassword {
$self->conf->{restPwdModifyUrl},
{
( $useMail ? 'mail' : 'user' ) => $req->user,
useMail => ( $useMail ? JSON::true : JSON::false ),
useMail => ( $useMail ? JSON::true : JSON::false ),
password => $pwd,
}
);

View File

@ -56,7 +56,7 @@ sub init {
@{ $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 ("
@ -66,7 +66,8 @@ sub init {
$lockTimes = $self->conf->{failedLoginNumber};
}
my $sum = $self->conf->{bruteForceProtectionMaxAge} * ( 1 + $self->conf->{failedLoginNumber} - $lockTimes );
my $sum = $self->conf->{bruteForceProtectionMaxAge} *
( 1 + $self->conf->{failedLoginNumber} - $lockTimes );
$sum += $_ foreach @{ $self->lockTimes };
$self->maxAge($sum);
}

View File

@ -716,7 +716,7 @@ sub checkCertificateValidity {
my ( $self, $notAfter, $delay ) = @_;
my $dtNow; # now in format DateTime
my $days; # difference between NotAfter and now
my $f = DateTime::Format::RFC3339->new();
my $f = DateTime::Format::RFC3339->new();
my $dtNotAfter = $f->parse_datetime($notAfter);
$self->userLogger->debug("Not After Date: $dtNotAfter");

View File

@ -37,7 +37,7 @@ sub check {
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);

View File

@ -276,7 +276,8 @@ sub check {
"checkUser requested for an unvalid user ($user)");
$req->{sessionInfo} = {};
$self->logger->debug('Identity not authorized');
$req->error(PE_BADCREDENTIALS); # Catch error to preserve protected Id
$req->error(PE_BADCREDENTIALS)
; # Catch error to preserve protected Id
}
}

View File

@ -34,9 +34,9 @@ has ott => (
return $ott;
}
);
has rule => ( is => 'rw', default => sub { 0 } );
has idRule => ( is => 'rw', default => sub { 1 } );
has unrestrictedUsersRule => ( is => 'rw', default => sub { 0 } );
has rule => ( is => 'rw', default => sub { 0 } );
has idRule => ( is => 'rw', default => sub { 1 } );
has unrestrictedUsersRule => ( is => 'rw', default => sub { 0 } );
sub init {
my ($self) = @_;
@ -191,7 +191,8 @@ sub run {
# Main session
$self->p->updateSession( $req, $req->sessionInfo );
$self->userLogger->notice(
"ContextSwitching: Update \"$realId\" session with \"$spoofId\" session data");
"ContextSwitching: Update \"$realId\" session with \"$spoofId\" session data"
);
return $self->p->do( $req, [ sub { $statut } ] );
}

View File

@ -19,7 +19,7 @@ sub init { 1 }
sub run {
my ( $self, $req ) = @_;
if ( $req->param('checkLogins') ) {
$self->logger->debug('History asked');
$req->info( (

View File

@ -131,7 +131,7 @@ sub run {
if ( $req->error ) {
$self->setSecurity($req);
if ( $req->error == PE_BADCREDENTIALS ) {
$statut = PE_BADCREDENTIALS; # Catch error to preserve protected Id
$statut = PE_BADCREDENTIALS; # Catch error to preserve protected Id
}
else {
return $req->error;
@ -200,7 +200,7 @@ sub run {
sub _userData {
my ( $self, $req, $spoofId, $realSession, $unUser ) = @_;
my $realId = $req->{user};
my $raz = 0;
my $raz = 0;
$req->{user} = $spoofId;
# Compute Macros and Groups with real and spoof sessions

View File

@ -529,7 +529,7 @@ sub display {
$speChars =~ s/\s+/ /g;
$speChars =~ s/(?:^\s|\s$)//g;
$self->logger->debug( 'Display called with code: ' . $req->error );
my %tplPrm = (
SKIN_PATH => $self->conf->{staticPrefix},
SKIN => $self->p->getSkin($req),

View File

@ -167,7 +167,8 @@ sub myNotifs {
my ( $self, $req, $ref ) = @_;
if ($ref) {
return $self->sendJSONresponse( $req, { error => 'Missing epoch parameter' } )
return $self->sendJSONresponse( $req,
{ error => 'Missing epoch parameter' } )
unless $req->param('epoch');
# Retrieve notification reference=$ref with epoch
@ -212,14 +213,14 @@ sub retrieveNotifs {
my @_notifications = sort {
$b->{epoch} <=> $a->{epoch}
or $a->{reference} cmp $b->{reference}
} (
} (
map {
/^notification_(.+)$/
? { reference => $1, epoch => $req->{userData}->{$_} }
: ()
}
keys %{ $req->{userData} }
);
);
splice @_notifications, $self->conf->{notificationsMaxRetrieve};
return \@_notifications;
@ -228,10 +229,11 @@ sub retrieveNotifs {
sub _viewNotif {
my ( $self, $req, $ref, $epoch ) = @_;
$self->logger->debug( "Retrieve notification with reference: \"$ref\" and epoch: \"$epoch\"" );
$self->logger->debug(
"Retrieve notification with reference: \"$ref\" and epoch: \"$epoch\"");
my $notif = eval { $self->module->viewNotification( $req, $ref, $epoch ); };
if ($@) {
$self->logger->debug( "Notification not found" );
$self->logger->debug("Notification not found");
$self->logger->error($@);
return '';
}

View File

@ -9,7 +9,7 @@ our $VERSION = '2.1.0';
sub init {
my ($self) = @_;
$self->addAuthRoute( public => { ':tpl' => 'run' }, ['GET'] );
$self->addAuthRoute( public => { ':tpl' => 'run' }, ['GET'] );
$self->addUnauthRoute( public => { ':tpl' => 'run' }, ['GET'] );
return 1;
}

View File

@ -132,7 +132,7 @@ sub init {
}
if ( $self->conf->{wsdlServer} ) {
$self->addUnauthRoute( 'portal.wsdl' => 'getWsdl', ['GET'] );
$self->addAuthRoute( 'portal.wsdl' => 'getWsdl', ['GET'] );
$self->addAuthRoute( 'portal.wsdl' => 'getWsdl', ['GET'] );
}
1;
}

View File

@ -133,7 +133,7 @@ sub run {
sub removeOther {
my ( $self, $req ) = @_;
my $res = PE_OK;
my $res = PE_OK;
my $count = 0;
$req->{urldc} = decode_base64( $req->param('url') );

View File

@ -89,8 +89,8 @@ sub setSessionInfo {
# @return Lemonldap::NG::Portal constant
sub setGroups {
my ( $self, $req ) = @_;
my $user = $req->user;
my $groups = $req->sessionInfo->{groups} || '';
my $user = $req->user;
my $groups = $req->sessionInfo->{groups} || '';
my $hGroups = $req->sessionInfo->{hGroups} || {};
for my $grp ( keys %demoGroups ) {
if ( grep { $_ eq $user } @{ $demoGroups{$grp} } ) {

View File

@ -25,8 +25,7 @@ ok(
),
'Get Menu'
);
ok( $res->[2]->[0] =~ m%<span trmsg="37">%,
'Rejected with PE_BADURL' )
ok( $res->[2]->[0] =~ m%<span trmsg="37">%, 'Rejected with PE_BADURL' )
or print STDERR Dumper( $res->[2]->[0] );
ok( $res->[2]->[0] =~ m%<span id="languages"></span>%, ' Language icons found' )
or print STDERR Dumper( $res->[2]->[0] );
@ -41,8 +40,7 @@ ok(
),
'Get Menu'
);
ok( $res->[2]->[0] =~ /<span trmsg="9">/,
'Rejected with PE_FIRSTACCESS' )
ok( $res->[2]->[0] =~ /<span trmsg="9">/, 'Rejected with PE_FIRSTACCESS' )
or print STDERR Dumper( $res->[2]->[0] );
ok( $res->[2]->[0] =~ m%<span id="languages"></span>%, ' Language icons found' )
or print STDERR Dumper( $res->[2]->[0] );
@ -73,9 +71,10 @@ ok(
),
'Auth query'
);
ok( $res->[2]->[0] =~ /<span trmsg="5">/,
'jdoe rejected with PE_BADCREDENTIALS' )
or print STDERR Dumper( $res->[2]->[0] );
ok(
$res->[2]->[0] =~ /<span trmsg="5">/,
'jdoe rejected with PE_BADCREDENTIALS'
) or print STDERR Dumper( $res->[2]->[0] );
ok( $res->[2]->[0] =~ m%<span trspan="connect">Connect</span>%,
'Found connect button' )
or print STDERR Dumper( $res->[2]->[0] );
@ -93,9 +92,10 @@ ok(
'Auth query'
);
count(1);
ok( $res->[2]->[0] =~ /<span trmsg="5">/,
'dwho rejected with PE_BADCREDENTIALS' )
or print STDERR Dumper( $res->[2]->[0] );
ok(
$res->[2]->[0] =~ /<span trmsg="5">/,
'dwho rejected with PE_BADCREDENTIALS'
) or print STDERR Dumper( $res->[2]->[0] );
count(1);
ok( $res->[2]->[0] =~ m%<span trspan="connect">Connect</span>%,
'Found connect button' )

View File

@ -10,8 +10,7 @@ require 't/test-lib.pm';
my $res;
my $client = LLNG::Manager::Test->new(
{
my $client = LLNG::Manager::Test->new( {
ini => {
logLevel => 'error',
useSafeJail => 1,
@ -31,8 +30,7 @@ ok( $app = Lemonldap::NG::Handler::Server->run( $client->ini ), 'App' );
count(1);
ok(
$res = $app->(
{
$res = $app->( {
'HTTP_ACCEPT' => 'text/html',
'SCRIPT_NAME' => '/',
'SERVER_NAME' => '127.0.0.1',
@ -69,8 +67,7 @@ expectForm( $res, undef, undef, 'url' );
count(1);
ok(
$res = $app->(
{
$res = $app->( {
'HTTP_ACCEPT' => 'text/html',
'SCRIPT_NAME' => '/',
'SERVER_NAME' => '127.0.0.1',
@ -88,7 +85,7 @@ ok(
'HTTP_HOST' => 'courriel.example.com',
}
),
'Standard Handler with host value that contains a + character after base64 encoding'
'Standard Handler with host value that contains a + character after base64 encoding'
);
count(1);

View File

@ -300,7 +300,7 @@ ok(
$res->[2]->[0] =~
m%<li><span trspan="passwordPolicyMinSize">Minimal size:</span> 6</li>%,
' passwordPolicyMinSize'
) or print STDERR Dumper( $res->[2]->[0], 'passwordPolicyMinSize');
) or print STDERR Dumper( $res->[2]->[0], 'passwordPolicyMinSize' );
ok(
$res->[2]->[0] =~
m%<li><span trspan="passwordPolicyMinLower">Minimal lower characters:</span> 3</li>%,
@ -320,7 +320,7 @@ ok(
$res->[2]->[0] =~
m%<li><span trspan="passwordPolicyMinSpeChar">Minimal special characters:</span> 2</li>%,
' passwordPolicyMinSpeChar'
) or print STDERR Dumper( $res->[2]->[0], 'passwordPolicyMinSpeChar');
) or print STDERR Dumper( $res->[2]->[0], 'passwordPolicyMinSpeChar' );
ok(
$res->[2]->[0] =~
m%\Q<li><span trspan="passwordPolicySpecialChar">Allowed special characters:</span> [ } \</li>\E%,
@ -328,7 +328,7 @@ m%\Q<li><span trspan="passwordPolicySpecialChar">Allowed special characters:</sp
) or print STDERR Dumper( $res->[2]->[0], 'passwordPolicySpecialChar' );
ok(
$res->[2]->[0] =~
m%<span id=\'show-hide-icon-button\' class="fa fa-eye"></span>%,
m%<span id=\'show-hide-icon-button\' class="fa fa-eye"></span>%,
'Show/Hide toogle button'
) or print STDERR Dumper( $res->[2]->[0], 'Toogle button' );
count(8);

View File

@ -72,9 +72,10 @@ m#<img class="renewcaptchaclick" src="/static/common/icons/arrow_refresh.png" al
( $host, $url, $query ) =
expectForm( $res, '#', undef, 'user', 'password', 'token' );
ok( $res->[2]->[0] =~ /<span trmsg="5">/,
'dalek rejected with PE_BADCREDENTIALS' )
or print STDERR Dumper( $res->[2]->[0] );
ok(
$res->[2]->[0] =~ /<span trmsg="5">/,
'dalek rejected with PE_BADCREDENTIALS'
) or print STDERR Dumper( $res->[2]->[0] );
# Try to authenticate
# -------------------

View File

@ -52,9 +52,10 @@ ok(
( $host, $url, $query ) =
expectForm( $res, '#', undef, 'user', 'password', 'token' );
ok( $res->[2]->[0] =~ /<span trmsg="5">/,
'dalek rejected with PE_BADCREDENTIALS' )
or print STDERR Dumper( $res->[2]->[0] );
ok(
$res->[2]->[0] =~ /<span trmsg="5">/,
'dalek rejected with PE_BADCREDENTIALS'
) or print STDERR Dumper( $res->[2]->[0] );
# Try to authenticate
# -------------------

View File

@ -21,10 +21,10 @@ SKIP: {
# Initialization
$issuer = register( 'issuer', \&issuer );
ok( $res = $issuer->_get('/saml/metadata'), 'Get metadata' );
ok( $res = $issuer->_get('/saml/metadata'), 'Get metadata' );
ok( $res->[2]->[0] =~ m#^<\?xml version="1.0"\?>#s, 'Metadata is XML' );
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#<SPSSODescriptor#s,
@ -33,7 +33,7 @@ SKIP: {
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#<IDPSSODescriptor#s,

View File

@ -198,16 +198,16 @@ ok( $prms{state}, ' state found' );
ok( $prms{session_state}, ' session_state found' );
count(6);
my $id_token_payload = id_token_payload($prms{id_token});
ok( $id_token_payload->{c_hash}, "ID token contains c_hash");
ok( $id_token_payload->{at_hash}, "ID token contains at_hash");
is( $id_token_payload->{nonce}, "qwerty", "ID token contains nonce");
my $id_token_payload = id_token_payload( $prms{id_token} );
ok( $id_token_payload->{c_hash}, "ID token contains c_hash" );
ok( $id_token_payload->{at_hash}, "ID token contains at_hash" );
is( $id_token_payload->{nonce}, "qwerty", "ID token contains nonce" );
count(3);
my $at;
ok( $at = $rp->p->_userDB->getUserInfo( 'op', $prms{access_token} ),
'Get access token' );
ok( $at = JSON::from_json($at), ' Decode JSON' );
ok( $at = JSON::from_json($at), ' Decode JSON' );
ok( $at->{name} eq 'Doctor Who', ' Get name' );
ok( $at->{family_name} eq 'Doctor Who', ' Get family_name' );
ok( $at->{sub} eq 'dwho', ' Get sub' );

View File

@ -144,7 +144,7 @@ ok( $prms{state}, ' state found' );
count(5);
# Check attributes in ID Token
my $id_token_decoded = id_token_payload($prms{id_token});
my $id_token_decoded = id_token_payload( $prms{id_token} );
ok( $id_token_decoded->{sub} eq "dwho", 'Check sub value' );
ok( $id_token_decoded->{name} eq "Doctor Who", 'Check name value' );
count(2);

View File

@ -126,7 +126,7 @@ my $newId = $res->{session}->{_session_id};
# Verify a key
ok( $res = $issuer->_get("/sessions/global/$newId/uid"), 'Verify uid' );
ok( $res->[2]->[0] eq 'zz', ' Uid is good' );
ok( $res->[2]->[0] eq 'zz', ' Uid is good' );
count(4);
# Update a key
@ -159,7 +159,7 @@ count(3);
# Verify new key
ok( $res = $issuer->_get("/sessions/global/$newId/cn"), 'Verify cn' );
ok( $res->[2]->[0] eq 'CN', ' CN is good' );
ok( $res->[2]->[0] eq 'CN', ' CN is good' );
count(2);
use_ok('Lemonldap::NG::Common::Apache::Session::REST');

View File

@ -144,11 +144,11 @@ sub sp {
portal => 'http://auth.sp.com',
authentication => 'Proxy',
userDB => 'Same',
secret => 'abc',
secret => 'abc',
proxyAuthService => 'http://auth.idp.com',
proxyUseSoap => 0,
whatToTrace => '_whatToTrace',
globalStorage => 'Lemonldap::NG::Common::Apache::Session::REST',
globalStorage => 'Lemonldap::NG::Common::Apache::Session::REST',
globalStorageOptions => {
'baseUrl' => 'http://auth.idp.com/sessions/global',
}

View File

@ -63,7 +63,7 @@ SKIP: {
my $res;
ok( $res = $soap->call('getConfig')->result(), 'Get configuration' );
ok( $res->{cfgNum} == 1, 'cfgNum is 1' );
ok( $res->{cfgNum} == 1, 'cfgNum is 1' );
$sp = register( 'sp', \&sp );

View File

@ -235,7 +235,8 @@ m%<span notif=\'testref\' epoch=\'(\d{10})\' class="btn btn-success" role="butto
);
ok( $json = eval { from_json( $res->[2]->[0] ) }, 'Response is JSON' )
or print STDERR "$@\n" . Dumper($res);
ok( $json->{error} eq 'Missing epoch parameter', ' Missing epoch parameter' )
ok( $json->{error} eq 'Missing epoch parameter',
' Missing epoch parameter' )
or explain( $json, "Missing epoch parameter" );
# Bad request

View File

@ -183,7 +183,7 @@ ok(
'List all pending notifications'
);
ok( $json = eval { from_json( $res->[2]->[0] ) }, 'Response is JSON' );
ok( scalar @{ $json->{result} } == 3, 'Three notifications found' )
ok( scalar @{ $json->{result} } == 3, 'Three notifications found' )
or print STDERR Dumper($json);
foreach ( @{ $json->{result} } ) {
@ -341,7 +341,7 @@ ok(
'List all existing notifications'
);
ok( $json = eval { from_json( $res->[2]->[0] ) }, 'Response is JSON' );
ok( scalar @{ $json->{result} } == 5, 'Five notifications found' )
ok( scalar @{ $json->{result} } == 5, 'Five notifications found' )
or print STDERR Dumper($json);
count(3);
@ -454,7 +454,7 @@ ok(
'List all pending notifications'
);
ok( $json = eval { from_json( $res->[2]->[0] ) }, 'Response is JSON' );
ok( scalar @{ $json->{result} } == 3, 'Three notifications found' )
ok( scalar @{ $json->{result} } == 3, 'Three notifications found' )
or print STDERR Dumper($json);
count(3);

View File

@ -13,15 +13,15 @@ my $res;
my $client = LLNG::Manager::Test->new( {
ini => {
logLevel => 'error',
authentication => 'Demo',
userDB => 'Same',
loginHistoryEnabled => 0,
bruteForceProtection => 0,
requireToken => 0,
securedCookie => 3,
restSessionServer => 1,
globalLogoutRule => 1,
logLevel => 'error',
authentication => 'Demo',
userDB => 'Same',
loginHistoryEnabled => 0,
bruteForceProtection => 0,
requireToken => 0,
securedCookie => 3,
restSessionServer => 1,
globalLogoutRule => 1,
}
}
);
@ -38,7 +38,7 @@ ok(
);
count(1);
expectCookie($res);
my $id = expectCookie($res, 'lemonldaphttp');
my $id = expectCookie( $res, 'lemonldaphttp' );
expectRedirection( $res, 'http://auth.example.com/' );
## Second successful connection for "dwho"
@ -53,7 +53,7 @@ ok(
);
count(1);
expectCookie($res);
expectCookie($res, 'lemonldaphttp');
expectCookie( $res, 'lemonldaphttp' );
expectRedirection( $res, 'http://auth.example.com/' );
## Third successful connection for 'dwho'
@ -68,7 +68,7 @@ ok(
);
count(1);
expectCookie($res);
expectCookie($res, 'lemonldaphttp');
expectCookie( $res, 'lemonldaphttp' );
expectRedirection( $res, 'http://auth.example.com/' );
## Logout request for 'dwho'

View File

@ -13,15 +13,15 @@ my $res;
my $client = LLNG::Manager::Test->new( {
ini => {
logLevel => 'error',
authentication => 'Demo',
userDB => 'Same',
loginHistoryEnabled => 0,
bruteForceProtection => 0,
requireToken => 0,
securedCookie => 2,
restSessionServer => 1,
globalLogoutRule => 1,
logLevel => 'error',
authentication => 'Demo',
userDB => 'Same',
loginHistoryEnabled => 0,
bruteForceProtection => 0,
requireToken => 0,
securedCookie => 2,
restSessionServer => 1,
globalLogoutRule => 1,
}
}
);
@ -38,7 +38,7 @@ ok(
);
count(1);
expectCookie($res);
my $id = expectCookie($res, 'lemonldaphttp');
my $id = expectCookie( $res, 'lemonldaphttp' );
expectRedirection( $res, 'http://auth.example.com/' );
## Second successful connection for "dwho"
@ -53,7 +53,7 @@ ok(
);
count(1);
expectCookie($res);
expectCookie($res, 'lemonldaphttp');
expectCookie( $res, 'lemonldaphttp' );
expectRedirection( $res, 'http://auth.example.com/' );
## Third successful connection for 'dwho'
@ -68,7 +68,7 @@ ok(
);
count(1);
expectCookie($res);
expectCookie($res, 'lemonldaphttp');
expectCookie( $res, 'lemonldaphttp' );
expectRedirection( $res, 'http://auth.example.com/' );
## Logout request for 'dwho'

View File

@ -11,14 +11,14 @@ my $res;
my $client = LLNG::Manager::Test->new( {
ini => {
logLevel => 'error',
authentication => 'Demo',
userDB => 'Same',
loginHistoryEnabled => 0,
bruteForceProtection => 0,
requireToken => 0,
restSessionServer => 1,
logoutServices => { 'mytest' => 'http://auth.example.com/' }
logLevel => 'error',
authentication => 'Demo',
userDB => 'Same',
loginHistoryEnabled => 0,
bruteForceProtection => 0,
requireToken => 0,
restSessionServer => 1,
logoutServices => { 'mytest' => 'http://auth.example.com/' }
}
}
);
@ -50,8 +50,11 @@ ok(
);
count(1);
ok( $res->[2]->[0] =~ m%<h3 trspan="logoutFromOtherApp">logoutFromOtherApp</h3>%, 'Found Logout Forward page' )
or explain( $res->[2]->[0], "PE_LOGOUT_OK" );
ok(
$res->[2]->[0] =~
m%<h3 trspan="logoutFromOtherApp">logoutFromOtherApp</h3>%,
'Found Logout Forward page'
) or explain( $res->[2]->[0], "PE_LOGOUT_OK" );
count(1);
$client->logout( $idd[0] );

View File

@ -211,7 +211,7 @@ expectOK($res);
ok(
$res->[2]->[0] =~
m%<div class="message message-positive alert"><span trmsg="-7"></span>%,
m%<div class="message message-positive alert"><span trmsg="-7"></span>%,
'Dwho has been well disconnected'
) or print STDERR Dumper( $res->[2]->[0] );
count(1);

View File

@ -121,7 +121,7 @@ expectOK($res);
ok(
$res->[2]->[0] =~
m%<div class="message message-positive alert"><span trmsg="-7"></span>%,
m%<div class="message message-positive alert"><span trmsg="-7"></span>%,
'Dwho has been well disconnected'
) or print STDERR Dumper( $res->[2]->[0] );
count(1);

View File

@ -113,9 +113,8 @@ SKIP: {
accept => 'text/html',
),
'Auth query'
);
ok( $res->[2]->[0] =~ /<span trspan="enterTotpCode">/,
'Enter TOTP code' )
);
ok( $res->[2]->[0] =~ /<span trspan="enterTotpCode">/, 'Enter TOTP code' )
or print STDERR Dumper( $res->[2]->[0] );
count(2);
@ -170,8 +169,7 @@ SKIP: {
),
'Auth query'
);
ok( $res->[2]->[0] =~ /<span trspan="enterTotpCode">/,
'Enter TOTP code' )
ok( $res->[2]->[0] =~ /<span trspan="enterTotpCode">/, 'Enter TOTP code' )
or print STDERR Dumper( $res->[2]->[0] );
count(2);

View File

@ -51,9 +51,10 @@ ok(
'Auth query'
);
count(1);
ok( $res->[2]->[0] =~ /<span trmsg="5">/,
'dwho rejected with PE_BADCREDENTIALS' )
or print STDERR Dumper( $res->[2]->[0] );
ok(
$res->[2]->[0] =~ /<span trmsg="5">/,
'dwho rejected with PE_BADCREDENTIALS'
) or print STDERR Dumper( $res->[2]->[0] );
count(1);
ok( $res->[2]->[0] =~ m%<span trspan="connect">Connect</span>%,
'Found connect button' )

View File

@ -62,7 +62,7 @@ ok(
);
ok(
$res->[2]->[0] =~
m%<div class="message message-warning alert"><span trmsg="1">%,
m%<div class="message message-warning alert"><span trmsg="1">%,
'Found PE_SESSIONEXPIRED code'
) or print STDERR Dumper( $res->[2]->[0] );
count(2);

View File

@ -61,7 +61,7 @@ ok(
);
ok(
$res->[2]->[0] =~
m%<div class="message message-warning alert"><span trmsg="1">%,
m%<div class="message message-warning alert"><span trmsg="1">%,
'Found PE_SESSIONEXPIRED code'
) or print STDERR Dumper( $res->[2]->[0] );
count(2);

View File

@ -51,7 +51,7 @@ count(1);
foreach (@ids) {
ok( $res = $client->_get("/sessions/global/$_"), 'Get session content' );
ok( $res->[2]->[0] =~ /"uid":"Dr Who"/, ' Content is updated' );
ok( $res->[2]->[0] =~ /"uid":"Dr Who"/, ' Content is updated' );
count(2);
}

View File

@ -204,10 +204,8 @@ ok(
m%<a href="http://auth.example.com/removeOther\?token=\d{10}_\d+" onclick="_go=0" trspan="removeOtherSessions"></a>%,
'Link found'
) or explain( $res->[2]->[0], 'Link found' );
ok(
$res->[2]->[0] =~ m%action="http://test1.example.com/"%,
'action found'
) or explain( $res->[2]->[0], 'action found' );
ok( $res->[2]->[0] =~ m%action="http://test1.example.com/"%, 'action found' )
or explain( $res->[2]->[0], 'action found' );
count(4);
clean_sessions();

View File

@ -26,13 +26,13 @@ my $client = LLNG::Manager::Test->new( {
userControl => '^[\w\.\-/\s]+$',
whatToTrace => '_whatToTrace',
macros => {
authLevel => '"Macro_$authenticationLevel"',
authLevel => '"Macro_$authenticationLevel"',
realAuthLevel => '"realMacro_$real_authenticationLevel"',
_whatToTrace =>
'$real__user ? "$_user / $real__user" : "$_user / $_user"',
},
groups => {
authGroup => '$authenticationLevel == 1',
groups => {
authGroup => '$authenticationLevel == 1',
realAuthGroup => '$real_authenticationLevel == 1',
},
}
@ -177,9 +177,11 @@ ok( $res->[2]->[0] =~ m%<td scope="row">Macro_1</td>%, 'Found uid' )
ok( $nbr = ( $res->[2]->[0] =~ s%<td scope="row">Macro_1</td>%%g ),
'Found two well computed macros' )
or explain( $res->[2]->[0], 'Macros not well computed' );
ok( $res->[2]->[0] =~ m%<div class="col">authGroup</div>%, 'Found group "authGroup"' )
ok( $res->[2]->[0] =~ m%<div class="col">authGroup</div>%,
'Found group "authGroup"' )
or explain( $res->[2]->[0], 'Group "authgroup"' );
ok( $res->[2]->[0] =~ m%<div class="col">realAuthGroup</div>%, 'Found group "realAuthGroup"' )
ok( $res->[2]->[0] =~ m%<div class="col">realAuthGroup</div>%,
'Found group "realAuthGroup"' )
or explain( $res->[2]->[0], 'Found group "realAuthGroup"' );
count(7);

View File

@ -253,7 +253,8 @@ ok( $res->[2]->[0] =~ m%<td scope="row">dwho</td>%, 'Found dwho' )
or explain( $res->[2]->[0], 'Macro Value dwho' );
ok( $res->[2]->[0] =~ m%<td scope="row">array</td>%, 'Found empty macro' )
or explain( $res->[2]->[0], 'Macro: empty' );
ok( $res->[2]->[0] =~ m%<td scope="row">real_array</td>%, 'Found empty real_macro' )
ok( $res->[2]->[0] =~ m%<td scope="row">real_array</td>%,
'Found empty real_macro' )
or explain( $res->[2]->[0], 'Macro: empty real' );
count(9);

View File

@ -61,13 +61,19 @@ ok( $res->[2]->[0] =~ qr%<span id="languages"></span>%, 'Found language flags' )
expectAuthenticatedAs( $res, 'rtyler' );
ok( $res->[2]->[0] !~ m%contextSwitching_ON%, 'Connected as dwho' )
or print STDERR Dumper( $res->[2]->[0] );
ok( $res->[2]->[0] =~ qr%href="http://test1\.example\.com/" title="Application Test 1"%, 'Found test1 & title' )
or print STDERR Dumper( $res->[2]->[0] );
ok( $res->[2]->[0] =~ qr%href="http://test2\.example\.com/" title="A nice application!"%, 'Found test2 & title' )
or print STDERR Dumper( $res->[2]->[0] );
ok(
$res->[2]->[0] =~
qr%href="http://test1\.example\.com/" title="Application Test 1"%,
'Found test1 & title'
) or print STDERR Dumper( $res->[2]->[0] );
ok(
$res->[2]->[0] =~
qr%href="http://test2\.example\.com/" title="A nice application!"%,
'Found test2 & title'
) or print STDERR Dumper( $res->[2]->[0] );
my @appdesc = ($res->[2]->[0] =~ qr%class="appdesc%);
ok( @appdesc == 1 , 'Found only one description' )
my @appdesc = ( $res->[2]->[0] =~ qr%class="appdesc% );
ok( @appdesc == 1, 'Found only one description' )
or print STDERR Dumper( $res->[2]->[0] );
count(6);
@ -406,7 +412,7 @@ expectOK($res);
ok(
$res->[2]->[0] =~
m%<div class="message message-positive alert"><span trmsg="-7"></span>%,
m%<div class="message message-positive alert"><span trmsg="-7"></span>%,
'Dwho has been well disconnected'
) or print STDERR Dumper( $res->[2]->[0] );
count(2);

View File

@ -77,7 +77,7 @@ ok(
);
ok(
$res->[2]->[0] =~
m%<div class="message message-negative alert"><span trmsg="5">%,
m%<div class="message message-negative alert"><span trmsg="5">%,
' PE5 found'
) or explain( $res->[2]->[0], "PE5 - Forbidden identity" );
count(2);

View File

@ -83,7 +83,7 @@ ok(
);
ok(
$res->[2]->[0] =~
m%<div class="message message-negative alert"><span trmsg="5">%,
m%<div class="message message-negative alert"><span trmsg="5">%,
' PE5 found'
) or explain( $res->[2]->[0], "PE5 - Forbidden identity" );
count(2);
@ -112,7 +112,7 @@ ok(
);
ok(
$res->[2]->[0] =~
m%<div class="message message-negative alert"><span trmsg="93">%,
m%<div class="message message-negative alert"><span trmsg="93">%,
' PE93 found'
) or explain( $res->[2]->[0], "PE93 - Impersonation service not allowed" );
count(2);

View File

@ -83,7 +83,7 @@ ok(
);
ok(
$res->[2]->[0] =~
m%<div class="message message-negative alert"><span trmsg="5">%,
m%<div class="message message-negative alert"><span trmsg="5">%,
' PE5 found'
) or explain( $res->[2]->[0], "PE5 - Forbidden identity" );
count(2);
@ -112,7 +112,7 @@ ok(
);
ok(
$res->[2]->[0] =~
m%<div class="message message-negative alert"><span trmsg="93">%,
m%<div class="message message-negative alert"><span trmsg="93">%,
' PE93 found'
) or explain( $res->[2]->[0], "PE93 - Impersonation service not allowed" );
count(2);
@ -329,8 +329,8 @@ count(17);
my %attributes = map /<td scope="row">(.+)?<\/td>/g, $res->[2]->[0];
ok( keys %attributes == 34, 'Found 34 attributes' )
or print STDERR ( keys %attributes < 34 )
? "Missing attributes -> " . scalar keys (%attributes) . "\n"
: "Too much attributes -> " . scalar keys (%attributes). "\n";
? "Missing attributes -> " . scalar keys(%attributes) . "\n"
: "Too much attributes -> " . scalar keys(%attributes) . "\n";
ok( $attributes{'_auth'} eq 'Demo', '_auth' )
or print STDERR Dumper( \%attributes );
ok( $attributes{'uid'}, 'uid' ) or print STDERR Dumper( \%attributes );

View File

@ -137,7 +137,7 @@ SKIP: {
# Generate TOTP with an external application to validate LLNG TOTP formula
my $oath = Authen::OATH->new( digits => 8 );
ok( $code = $oath->totp($key), 'Ext. App Code' );
ok( $code == $totp, 'Both TOTP match' )
ok( $code == $totp, 'Both TOTP match' )
or explain( [ $code, $totp ], 'LLNG and Ext. App TOTP mismatch' );
$query =~ s/code=/code=$code/;

View File

@ -160,7 +160,7 @@ SKIP: {
);
expectRedirection( $res, 'http://auth.example.com/' );
Time::Fake->offset("+20s"); # Go through handler internal cache
Time::Fake->offset("+20s"); # Go through handler internal cache
ok(
$res = $client->_post(

View File

@ -32,6 +32,7 @@ TODO: {
local $TODO = "Not yet fully cleaned";
fail "Unable to really destroy a portal object for now";
# Test with initialization
#my $p = Lemonldap::NG::Portal::Main->new();
#$p->init($ini);
@ -45,6 +46,6 @@ TODO: {
my $p = Lemonldap::NG::Portal::Main->new();
$p->init($ini);
leaks_cmp_ok {
$p->reloadConf($p->conf);
$p->reloadConf( $p->conf );
}
'<', 1;

Some files were not shown because too many files have changed in this diff Show More