Tidy
This commit is contained in:
parent
279538613f
commit
79246c8da9
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 ) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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] );
|
||||
}
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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" );
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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' );
|
||||
|
||||
|
|
|
@ -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" ),
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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} );
|
||||
|
|
|
@ -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' },
|
||||
],
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -580,8 +580,8 @@ sub tree {
|
|||
form => 'simpleInputContainer',
|
||||
nodes => [
|
||||
'singleSession', 'singleIP',
|
||||
'singleUserByIP',
|
||||
'notifyDeleted', 'notifyOther'
|
||||
'singleUserByIP', 'notifyDeleted',
|
||||
'notifyOther'
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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\"" )
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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' );
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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"' )
|
||||
|
|
|
@ -64,8 +64,8 @@ my @notManagedAttributes = (
|
|||
'zimbraUrl',
|
||||
|
||||
# Other ini-only prms
|
||||
'checkTime', 'status', 'soapProxyUrn',
|
||||
'impersonationPrefix', 'pdataDomain',
|
||||
'checkTime', 'status', 'soapProxyUrn',
|
||||
'impersonationPrefix', 'pdataDomain',
|
||||
'mySessionAuthorizedRWKeys', 'contextSwitchingPrefix'
|
||||
);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -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;
|
|
@ -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;
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
|
@ -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;
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 } ] );
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ sub init { 1 }
|
|||
|
||||
sub run {
|
||||
my ( $self, $req ) = @_;
|
||||
|
||||
|
||||
if ( $req->param('checkLogins') ) {
|
||||
$self->logger->debug('History asked');
|
||||
$req->info( (
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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 '';
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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') );
|
||||
|
||||
|
|
|
@ -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} } ) {
|
||||
|
|
|
@ -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' )
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
# -------------------
|
||||
|
|
|
@ -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
|
||||
# -------------------
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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' );
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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');
|
||||
|
|
|
@ -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',
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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] );
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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' )
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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/;
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue