Merge remote-tracking branch 'origin/v2.0'
This commit is contained in:
commit
aabb65629b
|
@ -133,7 +133,7 @@
|
|||
.\" ========================================================================
|
||||
.\"
|
||||
.IX Title "llng-fastcgi-server 1"
|
||||
.TH llng-fastcgi-server 1 "2019-04-23" "perl v5.28.1" "User Contributed Perl Documentation"
|
||||
.TH llng-fastcgi-server 1 "2019-06-06" "perl v5.28.1" "User Contributed Perl Documentation"
|
||||
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
|
||||
.\" way too many mistakes in technical documents.
|
||||
.if n .ad l
|
||||
|
|
|
@ -24,7 +24,7 @@ use constant MANAGERSECTION => "manager";
|
|||
use constant SESSIONSEXPLORERSECTION => "sessionsExplorer";
|
||||
use constant APPLYSECTION => "apply";
|
||||
our $hashParameters = qr/^(?:(?:l(?:o(?:ca(?:lSessionStorageOption|tionRule)|goutService)|dapExportedVar|wp(?:Ssl)?Opt)|(?:(?:d(?:emo|bi)|facebook|webID)ExportedVa|exported(?:Heade|Va)|issuerDBGetParamete)r|re(?:moteGlobalStorageOption|st2f(?:Verify|Init)Arg|loadUrl)|g(?:r(?:antSessionRule|oup)|lobalStorageOption)|n(?:otificationStorageOption|ginxCustomHandler)|macro)s|o(?:idc(?:RPMetaData(?:(?:Option(?:sExtraClaim)?|ExportedVar)s|Node)|OPMetaData(?:(?:ExportedVar|Option)s|J(?:SON|WKS)|Node)|S(?:erviceMetaDataAuthnContext|torageOptions))|penIdExportedVars)|s(?:aml(?:S(?:PMetaData(?:(?:ExportedAttribute|Option)s|Node|XML)|torageOptions)|IDPMetaData(?:(?:ExportedAttribute|Option)s|Node|XML))|essionDataToRemember|laveExportedVars)|c(?:as(?:S(?:rvMetaData(?:(?:ExportedVar|Option)s|Node)|torageOptions)|A(?:ppMetaData(?:(?:ExportedVar|Option)s|Node)|ttributes))|(?:ustomAddParam|ombModule)s)|p(?:ersistentStorageOptions|o(?:rtalSkinRules|st))|a(?:ut(?:hChoiceMod|oSigninR)ules|pplicationList)|v(?:hostOptions|irtualHost)|S(?:MTPTLSOpts|SLVarIf))$/;
|
||||
our $boolKeys = qr/^(?:s(?:aml(?:IDP(?:MetaDataOptions(?:(?:Check(?:S[LS]OMessageSignatur|Audienc|Tim)|IsPassiv)e|A(?:llow(?:LoginFromIDP|ProxiedAuthn)|daptSessionUtime)|Force(?:Authn|UTF8)|StoreSAMLToken|RelayStateURL)|SSODescriptorWantAuthnRequestsSigned)|S(?:P(?:MetaDataOptions(?:(?:CheckS[LS]OMessageSignatur|OneTimeUs)e|EnableIDPInitiatedURL|ForceUTF8)|SSODescriptor(?:WantAssertion|AuthnRequest)sSigned)|erviceUseCertificateInResponse)|DiscoveryProtocol(?:Activation|IsPassive)|CommonDomainCookieActivation|UseQueryStringSpecific|MetadataForceUTF8)|ingle(?:Session(?:UserByIP)?|(?:UserBy)?IP)|oap(?:Session|Config)Server|t(?:ayConnecte|orePasswor)d|kipRenewConfirmation|howLanguages|slByAjax)|o(?:idc(?:ServiceAllow(?:(?:AuthorizationCode|Implicit|Hybrid)Flow|DynamicRegistration)|RPMetaDataOptions(?:LogoutSessionRequired|BypassConsent|RequirePKCE|Public)|OPMetaDataOptions(?:(?:CheckJWTSignatur|UseNonc)e|StoreIDToken))|ldNotifFormat)|p(?:ortal(?:ErrorOn(?:ExpiredSession|MailNotFound)|DisplayRe(?:setPassword|gister)|(?:CheckLogin|Statu)s|OpenLinkInNewWindow|RequireOldPassword|ForceAuthn|AntiFrame)|roxyUseSoap)|l(?:dap(?:(?:Group(?:DecodeSearchedValu|Recursiv)|UsePasswordResetAttribut)e|(?:AllowResetExpired|Set)Password|ChangePasswordAsUser|PpolicyControl)|oginHistoryEnabled)|c(?:a(?:ptcha_(?:register|login|mail)_enabled|sSrvMetaDataOptions(?:Gateway|Renew))|heck(?:User(?:Display(?:PersistentInfo|EmptyValues))?|State|XSS)|orsEnabled|da)|i(?:ssuerDB(?:OpenID(?:Connect)?|SAML|CAS|Get)Activation|mpersonation(?:SkipEmptyValue|MergeSSOgroup)s)|to(?:tp2f(?:UserCan(?:Chang|Remov)eKey|DisplayExistingSecret)|kenUseGlobalStorage)|u(?:se(?:RedirectOn(?:Forbidden|Error)|SafeJail)|2fUserCanRemoveKey|pgradeSession)|no(?:tif(?:ication(?:Server)?|y(?:Deleted|Other))|AjaxHook)|(?:mai(?:lOnPasswordChang|ntenanc)|vhostMaintenanc)e|(?:(?:rest(?:Session|Config)|wsdl)Serv|activeTim)er|h(?:ideOldPassword|ttpOnly)|yubikey2fUserCanRemoveKey|krb(?:RemoveDomain|ByJs)|dbiDynamicHashEnabled|bruteForceProtection)$/;
|
||||
our $boolKeys = qr/^(?:s(?:aml(?:IDP(?:MetaDataOptions(?:(?:Check(?:S[LS]OMessageSignatur|Audienc|Tim)|IsPassiv)e|A(?:llow(?:LoginFromIDP|ProxiedAuthn)|daptSessionUtime)|Force(?:Authn|UTF8)|StoreSAMLToken|RelayStateURL)|SSODescriptorWantAuthnRequestsSigned)|S(?:P(?:MetaDataOptions(?:(?:CheckS[LS]OMessageSignatur|OneTimeUs)e|EnableIDPInitiatedURL|ForceUTF8)|SSODescriptor(?:WantAssertion|AuthnRequest)sSigned)|erviceUseCertificateInResponse)|DiscoveryProtocol(?:Activation|IsPassive)|CommonDomainCookieActivation|UseQueryStringSpecific|MetadataForceUTF8)|ingle(?:Session(?:UserByIP)?|(?:UserBy)?IP)|oap(?:Session|Config)Server|t(?:ayConnecte|orePasswor)d|kipRenewConfirmation|howLanguages|slByAjax)|o(?:idc(?:ServiceAllow(?:(?:AuthorizationCode|Implicit|Hybrid)Flow|DynamicRegistration)|RPMetaDataOptions(?:LogoutSessionRequired|BypassConsent|RequirePKCE|Public)|OPMetaDataOptions(?:(?:CheckJWTSignatur|UseNonc)e|StoreIDToken))|ldNotifFormat)|p(?:ortal(?:ErrorOn(?:ExpiredSession|MailNotFound)|DisplayRe(?:setPassword|gister)|(?:CheckLogin|Statu)s|OpenLinkInNewWindow|RequireOldPassword|ForceAuthn|AntiFrame)|roxyUseSoap)|l(?:dap(?:(?:Group(?:DecodeSearchedValu|Recursiv)|UsePasswordResetAttribut)e|(?:AllowResetExpired|Set)Password|ChangePasswordAsUser|PpolicyControl)|oginHistoryEnabled)|c(?:a(?:ptcha_(?:register|login|mail)_enabled|sSrvMetaDataOptions(?:Gateway|Renew))|heck(?:User(?:Display(?:PersistentInfo|EmptyValues))?|State|XSS)|orsEnabled|da)|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)|no(?:tif(?:ication(?:Server)?|y(?:Deleted|Other))|AjaxHook)|(?:mai(?:lOnPasswordChang|ntenanc)|vhostMaintenanc)e|(?:(?:rest(?:Session|Config)|wsdl)Serv|activeTim)er|h(?:ideOldPassword|ttpOnly)|yubikey2fUserCanRemoveKey|krb(?:RemoveDomain|ByJs)|dbiDynamicHashEnabled|bruteForceProtection)$/;
|
||||
|
||||
our @sessionTypes = ( 'remoteGlobal', 'global', 'localSession', 'persistent', 'saml', 'oidc', 'cas' );
|
||||
|
||||
|
|
|
@ -83,6 +83,7 @@ sub defaultValues {
|
|||
'https' => -1,
|
||||
'impersonationHiddenAttributes' => '_2fDevices _loginHistory',
|
||||
'impersonationIdRule' => 1,
|
||||
'impersonationMergeSSOgroups' => 0,
|
||||
'impersonationPrefix' => 'real_',
|
||||
'impersonationRule' => 0,
|
||||
'impersonationSkipEmptyValues' => 1,
|
||||
|
|
|
@ -3,6 +3,22 @@ package Lemonldap::NG::Manager::Attributes;
|
|||
|
||||
our $VERSION = '2.1.0';
|
||||
|
||||
sub perlExpr {
|
||||
my ( $val, $conf ) = @_;
|
||||
my $cpt = 'Safe'->new;
|
||||
$cpt->share_from( 'MIME::Base64', ['&encode_base64'] );
|
||||
$cpt->share_from( 'Lemonldap::NG::Handler::Main::Jail',
|
||||
[ '&encrypt', '&token' ] );
|
||||
$cpt->share_from( 'Lemonldap::NG::Common::Safelib',
|
||||
$Lemonldap::NG::Common::Safelib::functions );
|
||||
$cpt->reval("BEGIN { warnings->unimport; } $val");
|
||||
my $err = join(
|
||||
'',
|
||||
grep( { $_ =~ /Undefined subroutine/ ? () : $_; } split( /\n/, $@, 0 ) )
|
||||
);
|
||||
return $err ? ( 1, "__badExpression__: $err" ) : 1;
|
||||
}
|
||||
|
||||
sub types {
|
||||
return {
|
||||
'array' => {
|
||||
|
@ -27,21 +43,7 @@ sub types {
|
|||
'boolOrExpr' => {
|
||||
'msgFail' => '__notAValidPerlExpression__',
|
||||
'test' => sub {
|
||||
my ( $val, $conf ) = @_;
|
||||
my $s = '';
|
||||
my $cpt = 'Safe'->new;
|
||||
$cpt->share_from( 'MIME::Base64', ['&encode_base64'] );
|
||||
$cpt->share_from( 'Lemonldap::NG::Handler::Main::Jail',
|
||||
[ '&encrypt', '&token' ] );
|
||||
$cpt->share_from( 'Lemonldap::NG::Common::Safelib',
|
||||
$Lemonldap::NG::Common::Safelib::functions );
|
||||
$cpt->reval("BEGIN { warnings->unimport; } $s $val");
|
||||
my $err = join(
|
||||
'',
|
||||
grep( { $_ =~ /Undefined subroutine/ ? () : $_; }
|
||||
split( /\n/, $@, 0 ) )
|
||||
);
|
||||
return $err ? ( 1, "__badExpression__: $err" ) : 1;
|
||||
return perlExpr(@_);
|
||||
}
|
||||
},
|
||||
'catAndAppList' => {
|
||||
|
@ -669,21 +671,7 @@ sub attributes {
|
|||
},
|
||||
'casAppMetaDataOptionsRule' => {
|
||||
'test' => sub {
|
||||
my ( $val, $conf ) = @_;
|
||||
my $s = '';
|
||||
my $cpt = 'Safe'->new;
|
||||
$cpt->share_from( 'MIME::Base64', ['&encode_base64'] );
|
||||
$cpt->share_from( 'Lemonldap::NG::Handler::Main::Jail',
|
||||
[ '&encrypt', '&token' ] );
|
||||
$cpt->share_from( 'Lemonldap::NG::Common::Safelib',
|
||||
$Lemonldap::NG::Common::Safelib::functions );
|
||||
$cpt->reval("BEGIN { warnings->unimport; } $s $val");
|
||||
my $err = join(
|
||||
'',
|
||||
grep( { $_ =~ /Undefined subroutine/ ? () : $_; }
|
||||
split( /\n/, $@, 0 ) )
|
||||
);
|
||||
return $err ? ( 1, "__badExpression__: $err" ) : 1;
|
||||
return perlExpr(@_);
|
||||
},
|
||||
'type' => 'text'
|
||||
},
|
||||
|
@ -804,21 +792,7 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.]
|
|||
'checkUserIdRule' => {
|
||||
'default' => 1,
|
||||
'test' => sub {
|
||||
my ( $val, $conf ) = @_;
|
||||
my $s = '';
|
||||
my $cpt = 'Safe'->new;
|
||||
$cpt->share_from( 'MIME::Base64', ['&encode_base64'] );
|
||||
$cpt->share_from( 'Lemonldap::NG::Handler::Main::Jail',
|
||||
[ '&encrypt', '&token' ] );
|
||||
$cpt->share_from( 'Lemonldap::NG::Common::Safelib',
|
||||
$Lemonldap::NG::Common::Safelib::functions );
|
||||
$cpt->reval("BEGIN { warnings->unimport; } $s $val");
|
||||
my $err = join(
|
||||
'',
|
||||
grep( { $_ =~ /Undefined subroutine/ ? () : $_; }
|
||||
split( /\n/, $@, 0 ) )
|
||||
);
|
||||
return $err ? ( 1, "__badExpression__: $err" ) : 1;
|
||||
return perlExpr(@_);
|
||||
},
|
||||
'type' => 'text'
|
||||
},
|
||||
|
@ -1127,21 +1101,7 @@ qr/^(?:\*\.)?(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][
|
|||
'keyMsgFail' => '__badHeaderName__',
|
||||
'keyTest' => qr/^(?=[^\-])[\w\-]+(?<=[^-])$/,
|
||||
'test' => sub {
|
||||
my ( $val, $conf ) = @_;
|
||||
my $s = $val;
|
||||
my $cpt = 'Safe'->new;
|
||||
$cpt->share_from( 'MIME::Base64', ['&encode_base64'] );
|
||||
$cpt->share_from( 'Lemonldap::NG::Handler::Main::Jail',
|
||||
[ '&encrypt', '&token' ] );
|
||||
$cpt->share_from( 'Lemonldap::NG::Common::Safelib',
|
||||
$Lemonldap::NG::Common::Safelib::functions );
|
||||
$cpt->reval("BEGIN { warnings->unimport; } $s");
|
||||
my $err = join(
|
||||
'',
|
||||
grep( { $_ =~ /Undefined subroutine/ ? () : $_; }
|
||||
split( /\n/, $@, 0 ) )
|
||||
);
|
||||
return $err ? ( 1, "__badExpression__: $err" ) : 1;
|
||||
return perlExpr(@_);
|
||||
}
|
||||
},
|
||||
'type' => 'keyTextContainer'
|
||||
|
@ -1233,21 +1193,7 @@ qr/^(?:\*\.)?(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][
|
|||
},
|
||||
'grantSessionRules' => {
|
||||
'keyTest' => sub {
|
||||
my ( $val, $conf ) = @_;
|
||||
my $s = '';
|
||||
my $cpt = 'Safe'->new;
|
||||
$cpt->share_from( 'MIME::Base64', ['&encode_base64'] );
|
||||
$cpt->share_from( 'Lemonldap::NG::Handler::Main::Jail',
|
||||
[ '&encrypt', '&token' ] );
|
||||
$cpt->share_from( 'Lemonldap::NG::Common::Safelib',
|
||||
$Lemonldap::NG::Common::Safelib::functions );
|
||||
$cpt->reval("BEGIN { warnings->unimport; } $s $val");
|
||||
my $err = join(
|
||||
'',
|
||||
grep( { $_ =~ /Undefined subroutine/ ? () : $_; }
|
||||
split( /\n/, $@, 0 ) )
|
||||
);
|
||||
return $err ? ( 1, "__badExpression__: $err" ) : 1;
|
||||
return perlExpr(@_);
|
||||
},
|
||||
'test' => sub {
|
||||
1;
|
||||
|
@ -1257,21 +1203,7 @@ qr/^(?:\*\.)?(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][
|
|||
'groups' => {
|
||||
'default' => {},
|
||||
'test' => sub {
|
||||
my ( $val, $conf ) = @_;
|
||||
my $s = '';
|
||||
my $cpt = 'Safe'->new;
|
||||
$cpt->share_from( 'MIME::Base64', ['&encode_base64'] );
|
||||
$cpt->share_from( 'Lemonldap::NG::Handler::Main::Jail',
|
||||
[ '&encrypt', '&token' ] );
|
||||
$cpt->share_from( 'Lemonldap::NG::Common::Safelib',
|
||||
$Lemonldap::NG::Common::Safelib::functions );
|
||||
$cpt->reval("BEGIN { warnings->unimport; } $s $val");
|
||||
my $err = join(
|
||||
'',
|
||||
grep( { $_ =~ /Undefined subroutine/ ? () : $_; }
|
||||
split( /\n/, $@, 0 ) )
|
||||
);
|
||||
return $err ? ( 1, "__badExpression__: $err" ) : 1;
|
||||
return perlExpr(@_);
|
||||
},
|
||||
'type' => 'keyTextContainer'
|
||||
},
|
||||
|
@ -1306,27 +1238,13 @@ qr/^(?:\*\.)?(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][
|
|||
'impersonationIdRule' => {
|
||||
'default' => 1,
|
||||
'test' => sub {
|
||||
my ( $val, $conf ) = @_;
|
||||
my $s = '';
|
||||
my $cpt = 'Safe'->new;
|
||||
$cpt->share_from( 'MIME::Base64', ['&encode_base64'] );
|
||||
$cpt->share_from( 'Lemonldap::NG::Handler::Main::Jail',
|
||||
[ '&encrypt', '&token' ] );
|
||||
$cpt->share_from( 'Lemonldap::NG::Common::Safelib',
|
||||
$Lemonldap::NG::Common::Safelib::functions );
|
||||
$cpt->reval("BEGIN { warnings->unimport; } $s $val");
|
||||
my $err = join(
|
||||
'',
|
||||
grep( { $_ =~ /Undefined subroutine/ ? () : $_; }
|
||||
split( /\n/, $@, 0 ) )
|
||||
);
|
||||
return $err ? ( 1, "__badExpression__: $err" ) : 1;
|
||||
return perlExpr(@_);
|
||||
},
|
||||
'type' => 'text'
|
||||
},
|
||||
'impersonationMergeSSOgroups' => {
|
||||
'default' => 0,
|
||||
'type' => 'bool'
|
||||
'type' => 'boolOrExpr'
|
||||
},
|
||||
'impersonationPrefix' => {
|
||||
'default' => 'real_',
|
||||
|
@ -1666,19 +1584,7 @@ qr/^(?:\*\.)?(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][
|
|||
: ( 0, '__badUrl__' );
|
||||
}
|
||||
$s =~ s/\b(accept|deny|unprotect|skip)\b/1/g;
|
||||
my $cpt = 'Safe'->new;
|
||||
$cpt->share_from( 'MIME::Base64', ['&encode_base64'] );
|
||||
$cpt->share_from( 'Lemonldap::NG::Handler::Main::Jail',
|
||||
[ '&encrypt', '&token' ] );
|
||||
$cpt->share_from( 'Lemonldap::NG::Common::Safelib',
|
||||
$Lemonldap::NG::Common::Safelib::functions );
|
||||
$cpt->reval("BEGIN { warnings->unimport; } $s");
|
||||
my $err = join(
|
||||
'',
|
||||
grep( { $_ =~ /Undefined subroutine/ ? () : $_; }
|
||||
split( /\n/, $@, 0 ) )
|
||||
);
|
||||
return $err ? ( 1, "__badExpression__: $err" ) : 1;
|
||||
return &perlExpr( $s, $conf );
|
||||
}
|
||||
},
|
||||
'type' => 'ruleContainer'
|
||||
|
@ -1711,21 +1617,7 @@ qr/^(?:\*\.)?(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][
|
|||
'keyMsgFail' => '__badMacroName__',
|
||||
'keyTest' => qr/^[_a-zA-Z][a-zA-Z0-9_]*$/,
|
||||
'test' => sub {
|
||||
my ( $val, $conf ) = @_;
|
||||
my $s = '';
|
||||
my $cpt = 'Safe'->new;
|
||||
$cpt->share_from( 'MIME::Base64', ['&encode_base64'] );
|
||||
$cpt->share_from( 'Lemonldap::NG::Handler::Main::Jail',
|
||||
[ '&encrypt', '&token' ] );
|
||||
$cpt->share_from( 'Lemonldap::NG::Common::Safelib',
|
||||
$Lemonldap::NG::Common::Safelib::functions );
|
||||
$cpt->reval("BEGIN { warnings->unimport; } $s $val");
|
||||
my $err = join(
|
||||
'',
|
||||
grep( { $_ =~ /Undefined subroutine/ ? () : $_; }
|
||||
split( /\n/, $@, 0 ) )
|
||||
);
|
||||
return $err ? ( 1, "__badExpression__: $err" ) : 1;
|
||||
return perlExpr(@_);
|
||||
},
|
||||
'type' => 'keyTextContainer'
|
||||
},
|
||||
|
@ -2107,21 +1999,7 @@ qr/^(?:\*\.)?(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][
|
|||
},
|
||||
'oidcRPMetaDataOptionsRule' => {
|
||||
'test' => sub {
|
||||
my ( $val, $conf ) = @_;
|
||||
my $s = '';
|
||||
my $cpt = 'Safe'->new;
|
||||
$cpt->share_from( 'MIME::Base64', ['&encode_base64'] );
|
||||
$cpt->share_from( 'Lemonldap::NG::Handler::Main::Jail',
|
||||
[ '&encrypt', '&token' ] );
|
||||
$cpt->share_from( 'Lemonldap::NG::Common::Safelib',
|
||||
$Lemonldap::NG::Common::Safelib::functions );
|
||||
$cpt->reval("BEGIN { warnings->unimport; } $s $val");
|
||||
my $err = join(
|
||||
'',
|
||||
grep( { $_ =~ /Undefined subroutine/ ? () : $_; }
|
||||
split( /\n/, $@, 0 ) )
|
||||
);
|
||||
return $err ? ( 1, "__badExpression__: $err" ) : 1;
|
||||
return perlExpr(@_);
|
||||
},
|
||||
'type' => 'text'
|
||||
},
|
||||
|
@ -2462,21 +2340,7 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.]
|
|||
'portalSkinRules' => {
|
||||
'keyMsgFail' => '__badSkinRule__',
|
||||
'keyTest' => sub {
|
||||
my ( $val, $conf ) = @_;
|
||||
my $s = '';
|
||||
my $cpt = 'Safe'->new;
|
||||
$cpt->share_from( 'MIME::Base64', ['&encode_base64'] );
|
||||
$cpt->share_from( 'Lemonldap::NG::Handler::Main::Jail',
|
||||
[ '&encrypt', '&token' ] );
|
||||
$cpt->share_from( 'Lemonldap::NG::Common::Safelib',
|
||||
$Lemonldap::NG::Common::Safelib::functions );
|
||||
$cpt->reval("BEGIN { warnings->unimport; } $s $val");
|
||||
my $err = join(
|
||||
'',
|
||||
grep( { $_ =~ /Undefined subroutine/ ? () : $_; }
|
||||
split( /\n/, $@, 0 ) )
|
||||
);
|
||||
return $err ? ( 1, "__badExpression__: $err" ) : 1;
|
||||
return perlExpr(@_);
|
||||
},
|
||||
'msgFail' => '__badValue__',
|
||||
'test' => qr/^\w+$/,
|
||||
|
@ -3211,21 +3075,7 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.]
|
|||
},
|
||||
'samlSPMetaDataOptionsRule' => {
|
||||
'test' => sub {
|
||||
my ( $val, $conf ) = @_;
|
||||
my $s = '';
|
||||
my $cpt = 'Safe'->new;
|
||||
$cpt->share_from( 'MIME::Base64', ['&encode_base64'] );
|
||||
$cpt->share_from( 'Lemonldap::NG::Handler::Main::Jail',
|
||||
[ '&encrypt', '&token' ] );
|
||||
$cpt->share_from( 'Lemonldap::NG::Common::Safelib',
|
||||
$Lemonldap::NG::Common::Safelib::functions );
|
||||
$cpt->reval("BEGIN { warnings->unimport; } $s $val");
|
||||
my $err = join(
|
||||
'',
|
||||
grep( { $_ =~ /Undefined subroutine/ ? () : $_; }
|
||||
split( /\n/, $@, 0 ) )
|
||||
);
|
||||
return $err ? ( 1, "__badExpression__: $err" ) : 1;
|
||||
return perlExpr(@_);
|
||||
},
|
||||
'type' => 'text'
|
||||
},
|
||||
|
@ -3535,6 +3385,9 @@ qr/^(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-
|
|||
'default' => 0,
|
||||
'type' => 'boolOrExpr'
|
||||
},
|
||||
'totp2fTTL' => {
|
||||
'type' => 'int'
|
||||
},
|
||||
'totp2fUserCanChangeKey' => {
|
||||
'default' => 0,
|
||||
'type' => 'bool'
|
||||
|
@ -3574,6 +3427,9 @@ qr/^(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-
|
|||
'default' => 0,
|
||||
'type' => 'boolOrExpr'
|
||||
},
|
||||
'u2fTTL' => {
|
||||
'type' => 'int'
|
||||
},
|
||||
'u2fUserCanRemoveKey' => {
|
||||
'default' => 1,
|
||||
'type' => 'bool'
|
||||
|
@ -3775,6 +3631,9 @@ qr/^(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-
|
|||
'default' => 0,
|
||||
'type' => 'boolOrExpr'
|
||||
},
|
||||
'yubikey2fTTL' => {
|
||||
'type' => 'int'
|
||||
},
|
||||
'yubikey2fUrl' => {
|
||||
'type' => 'text'
|
||||
},
|
||||
|
|
|
@ -370,6 +370,9 @@ EOF
|
|||
} keys(%$attributes)
|
||||
};
|
||||
$managerAttr = mydump( $managerAttr, 'attributes' );
|
||||
my $managerSub = Dumper( \&Lemonldap::NG::Manager::Build::Attributes::perlExpr );
|
||||
$managerSub =~ s/\$VAR1 = sub/sub perlExpr/s;
|
||||
$managerSub =~ s/^\s*(?:use strict;|package .*?;|)\n//gm;
|
||||
my $managerTypes =
|
||||
mydump( Lemonldap::NG::Manager::Build::Attributes::types(), 'types' );
|
||||
$managerAttr = "# This file is generated by $module. Don't modify it by hand
|
||||
|
@ -377,6 +380,8 @@ package Lemonldap::NG::Manager::Attributes;
|
|||
|
||||
our \$VERSION = '$Lemonldap::NG::Manager::Build::Attributes::VERSION';
|
||||
|
||||
$managerSub
|
||||
|
||||
$managerTypes}
|
||||
|
||||
$managerAttr}
|
||||
|
|
|
@ -10,16 +10,15 @@ our $VERSION = '2.1.0';
|
|||
use strict;
|
||||
use Regexp::Common qw/URI/;
|
||||
|
||||
my $perlExpr = sub {
|
||||
sub perlExpr {
|
||||
my ( $val, $conf ) = @_;
|
||||
my $s = '';
|
||||
my $cpt = new Safe;
|
||||
$cpt->share_from( 'MIME::Base64', ['&encode_base64'] );
|
||||
$cpt->share_from( 'Lemonldap::NG::Handler::Main::Jail',
|
||||
[ '&encrypt', '&token' ] );
|
||||
$cpt->share_from( 'Lemonldap::NG::Common::Safelib',
|
||||
$Lemonldap::NG::Common::Safelib::functions );
|
||||
$cpt->reval("BEGIN { warnings->unimport; } $s $val");
|
||||
$cpt->reval("BEGIN { warnings->unimport; } $val");
|
||||
my $err = join( '',
|
||||
grep { $_ =~ /Undefined subroutine/ ? () : $_ } split( /\n/, $@ ) );
|
||||
return $err ? ( 1, "__badExpression__: $err" ) : (1);
|
||||
|
@ -96,7 +95,7 @@ sub types {
|
|||
msgFail => '__authorizedValues__: -1, 0, 1',
|
||||
},
|
||||
boolOrExpr => {
|
||||
test => $perlExpr,
|
||||
test => sub { return perlExpr(@_) },
|
||||
msgFail => '__notAValidPerlExpression__',
|
||||
},
|
||||
keyTextContainer => {
|
||||
|
@ -430,7 +429,7 @@ sub attributes {
|
|||
},
|
||||
checkUserIdRule => {
|
||||
type => 'text',
|
||||
test => $perlExpr,
|
||||
test => sub { return perlExpr(@_) },
|
||||
default => 1,
|
||||
documentation => 'checkUser identities rule',
|
||||
},
|
||||
|
@ -466,7 +465,7 @@ sub attributes {
|
|||
},
|
||||
impersonationMergeSSOgroups => {
|
||||
default => 0,
|
||||
type => 'bool',
|
||||
type => 'boolOrExpr',
|
||||
documentation => 'Merge spoofed and real SSO groups',
|
||||
flags => 'p',
|
||||
},
|
||||
|
@ -483,7 +482,7 @@ sub attributes {
|
|||
},
|
||||
impersonationIdRule => {
|
||||
type => 'text',
|
||||
test => $perlExpr,
|
||||
test => sub { return perlExpr(@_) },
|
||||
default => 1,
|
||||
documentation => 'Impersonation identities rule',
|
||||
},
|
||||
|
@ -638,7 +637,7 @@ sub attributes {
|
|||
portalSkinRules => {
|
||||
type => 'keyTextContainer',
|
||||
help => 'portalcustom.html',
|
||||
keyTest => $perlExpr,
|
||||
keyTest => sub { return perlExpr(@_) },
|
||||
keyMsgFail => '__badSkinRule__',
|
||||
test => qr/^\w+$/,
|
||||
msgFail => '__badValue__',
|
||||
|
@ -711,7 +710,7 @@ sub attributes {
|
|||
},
|
||||
grantSessionRules => {
|
||||
type => 'grantContainer',
|
||||
keyTest => $perlExpr,
|
||||
keyTest => sub { return perlExpr(@_) },
|
||||
test => sub { 1 },
|
||||
documentation => 'Rules to grant sessions',
|
||||
},
|
||||
|
@ -1070,7 +1069,7 @@ sub attributes {
|
|||
type => 'keyTextContainer',
|
||||
help =>
|
||||
'exportedvars.html#extend_variables_using_macros_and_groups',
|
||||
test => $perlExpr,
|
||||
test => sub { return perlExpr(@_) },
|
||||
default => {},
|
||||
documentation => 'Groups',
|
||||
},
|
||||
|
@ -1080,7 +1079,7 @@ sub attributes {
|
|||
'exportedvars.html#extend_variables_using_macros_and_groups',
|
||||
keyTest => qr/^[_a-zA-Z][a-zA-Z0-9_]*$/,
|
||||
keyMsgFail => '__badMacroName__',
|
||||
test => $perlExpr,
|
||||
test => sub { return perlExpr(@_) },
|
||||
default => {},
|
||||
documentation => 'Macros',
|
||||
},
|
||||
|
@ -1381,6 +1380,10 @@ sub attributes {
|
|||
default => 1,
|
||||
documentation => 'Authorize users to remove existing U2F key',
|
||||
},
|
||||
u2fTTL => {
|
||||
type => 'int',
|
||||
documentation => 'U2F device time to live',
|
||||
},
|
||||
|
||||
# TOTP second factor
|
||||
totp2fActivation => {
|
||||
|
@ -1433,6 +1436,10 @@ sub attributes {
|
|||
default => 1,
|
||||
documentation => 'Authorize users to remove existing TOTP secret',
|
||||
},
|
||||
totp2fTTL => {
|
||||
type => 'int',
|
||||
documentation => 'TOTP device time to live ',
|
||||
},
|
||||
|
||||
# UTOTP 2F
|
||||
utotp2fActivation => {
|
||||
|
@ -1590,6 +1597,10 @@ sub attributes {
|
|||
default => 1,
|
||||
documentation => 'Authorize users to remove existing Yubikey',
|
||||
},
|
||||
yubikey2fTTL => {
|
||||
type => 'int',
|
||||
documentation => 'Yubikey device time to live',
|
||||
},
|
||||
|
||||
# Single session
|
||||
notifyDeleted => {
|
||||
|
@ -1698,17 +1709,7 @@ sub attributes {
|
|||
: ( 0, '__badUrl__' );
|
||||
}
|
||||
$s =~ s/\b(accept|deny|unprotect|skip)\b/1/g;
|
||||
my $cpt = new Safe;
|
||||
$cpt->share_from( 'MIME::Base64', ['&encode_base64'] );
|
||||
$cpt->share_from( 'Lemonldap::NG::Handler::Main::Jail',
|
||||
[ '&encrypt', '&token' ] );
|
||||
$cpt->share_from( 'Lemonldap::NG::Common::Safelib',
|
||||
$Lemonldap::NG::Common::Safelib::functions );
|
||||
$cpt->reval("BEGIN { warnings->unimport; } $s");
|
||||
my $err = join( '',
|
||||
grep { $_ =~ /Undefined subroutine/ ? () : $_ }
|
||||
split( /\n/, $@ ) );
|
||||
return $err ? ( 1, "__badExpression__: $err" ) : (1);
|
||||
return &perlExpr( $s, $conf );
|
||||
},
|
||||
msgFail => '__badExpression__',
|
||||
},
|
||||
|
@ -1726,21 +1727,7 @@ sub attributes {
|
|||
test => {
|
||||
keyTest => qr/^(?=[^\-])[\w\-]+(?<=[^-])$/,
|
||||
keyMsgFail => '__badHeaderName__',
|
||||
test => sub {
|
||||
my ( $val, $conf ) = @_;
|
||||
my $s = $val;
|
||||
my $cpt = new Safe;
|
||||
$cpt->share_from( 'MIME::Base64', ['&encode_base64'] );
|
||||
$cpt->share_from( 'Lemonldap::NG::Handler::Main::Jail',
|
||||
[ '&encrypt', '&token' ] );
|
||||
$cpt->share_from( 'Lemonldap::NG::Common::Safelib',
|
||||
$Lemonldap::NG::Common::Safelib::functions );
|
||||
$cpt->reval("BEGIN { warnings->unimport; } $s");
|
||||
my $err = join( '',
|
||||
grep { $_ =~ /Undefined subroutine/ ? () : $_ }
|
||||
split( /\n/, $@ ) );
|
||||
return $err ? ( 1, "__badExpression__: $err" ) : (1);
|
||||
}
|
||||
test => sub { return perlExpr(@_) },
|
||||
},
|
||||
documentation => 'Virtualhost headers',
|
||||
flags => 'h',
|
||||
|
@ -1910,7 +1897,7 @@ sub attributes {
|
|||
},
|
||||
casAppMetaDataOptionsRule => {
|
||||
type => 'text',
|
||||
test => $perlExpr,
|
||||
test => sub { return perlExpr(@_) },
|
||||
documentation => 'CAS App rule',
|
||||
},
|
||||
|
||||
|
@ -2514,7 +2501,7 @@ sub attributes {
|
|||
},
|
||||
samlSPMetaDataOptionsRule => {
|
||||
type => 'text',
|
||||
test => $perlExpr,
|
||||
test => sub { return perlExpr(@_) },
|
||||
documentation => 'Rule to grant access to this SP',
|
||||
},
|
||||
|
||||
|
@ -3508,7 +3495,7 @@ m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
|
|||
},
|
||||
oidcRPMetaDataOptionsRule => {
|
||||
type => 'text',
|
||||
test => $perlExpr,
|
||||
test => sub { return perlExpr(@_) },
|
||||
documentation => 'Rule to grant access to this RP',
|
||||
},
|
||||
};
|
||||
|
|
|
@ -701,6 +701,7 @@ sub tree {
|
|||
'totp2fDisplayExistingSecret',
|
||||
'totp2fUserCanChangeKey',
|
||||
'totp2fUserCanRemoveKey',
|
||||
'totp2fTTL',
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -710,6 +711,7 @@ sub tree {
|
|||
nodes => [
|
||||
'u2fActivation', 'u2fSelfRegistration',
|
||||
'u2fAuthnLevel', 'u2fUserCanRemoveKey',
|
||||
'u2fTTL',
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -757,6 +759,7 @@ sub tree {
|
|||
'yubikey2fUrl',
|
||||
'yubikey2fPublicIDSize',
|
||||
'yubikey2fUserCanRemoveKey',
|
||||
'yubikey2fTTL',
|
||||
],
|
||||
},
|
||||
'sfRequired',
|
||||
|
|
|
@ -787,8 +787,9 @@
|
|||
"totp2fIssuer":"TOTP Issuer name",
|
||||
"totp2fRange":"Range of attempts",
|
||||
"totp2fSelfRegistration":"التسجيل الذاتي",
|
||||
"totp2fTTL":"Lifetime",
|
||||
"totp2fUserCanChangeKey":"Change existing secret",
|
||||
"totp2fUserCanRemoveKey":"Authorize user to remove TOTP",
|
||||
"totp2fUserCanRemoveKey":"Allow user to remove TOTP",
|
||||
"trustedDomains":"النطاقات الموثوق بها",
|
||||
"trustedProxies":"عناوين الآي بي البروكسي الموثوق بها",
|
||||
"twitterAppName":"اسم التطبيق",
|
||||
|
@ -801,8 +802,9 @@
|
|||
"u2f":"U2F",
|
||||
"u2fActivation":"تفعيل",
|
||||
"u2fAuthnLevel":"U2F مستوى إثبات الهوية",
|
||||
"u2fUserCanRemoveKey":"Authorize user to remove U2F key",
|
||||
"u2fSelfRegistration":"التسجيل الذاتي",
|
||||
"u2fTTL":"Lifetime",
|
||||
"u2fUserCanRemoveKey":"Allow user to remove U2F key",
|
||||
"uid":"المعرف",
|
||||
"unknownAttrOrMacro":"سمة غير معروفة أو ماكرو",
|
||||
"unknownError":"خطأ غير معروف",
|
||||
|
@ -865,8 +867,9 @@
|
|||
"yubikey2fPublicIDSize":"حجم الجزء العام لي OTP آي دي",
|
||||
"yubikey2fSecretKey":"مفتاح سرأل API",
|
||||
"yubikey2fSelfRegistration":"التسجيل الذاتي",
|
||||
"yubikey2fTTL":"Lifetime",
|
||||
"yubikey2fUrl":"خدمة أل يو أر ل",
|
||||
"yubikey2fUserCanRemoveKey":"Authorize user to remove Yubikey",
|
||||
"yubikey2fUserCanRemoveKey":"Allow user to remove Yubikey",
|
||||
"zeroConfExplanations":"لا يحتوي الخادم على إعدادات. استخدام قالب لحفظ الأول",
|
||||
|
||||
"saml":"SAML",
|
||||
|
|
|
@ -787,8 +787,9 @@
|
|||
"totp2fIssuer":"TOTP Issuer name",
|
||||
"totp2fRange":"Range of attempts",
|
||||
"totp2fSelfRegistration":"Self registration",
|
||||
"totp2fTTL":"Lifetime",
|
||||
"totp2fUserCanChangeKey":"Change existing secret",
|
||||
"totp2fUserCanRemoveKey":"Authorize user to remove TOTP",
|
||||
"totp2fUserCanRemoveKey":"Allow user to remove TOTP",
|
||||
"trustedDomains":"Trusted domains",
|
||||
"trustedProxies":"Trusted proxies IP",
|
||||
"twitterAppName":"Application name",
|
||||
|
@ -801,8 +802,9 @@
|
|||
"u2f":"U2F",
|
||||
"u2fActivation":"Activation",
|
||||
"u2fAuthnLevel":"U2F authentication level",
|
||||
"u2fUserCanRemoveKey":"Authorize user to remove U2F key",
|
||||
"u2fSelfRegistration":"Self registration",
|
||||
"u2fTTL":"Lifetime",
|
||||
"u2fUserCanRemoveKey":"Allow user to remove U2F key",
|
||||
"uid":"Identifier",
|
||||
"unknownAttrOrMacro":"Unknown attribute or macro",
|
||||
"unknownError":"Unknown error",
|
||||
|
@ -865,8 +867,9 @@
|
|||
"yubikey2fPublicIDSize":"OTP public ID part size",
|
||||
"yubikey2fSecretKey":"API secret key",
|
||||
"yubikey2fSelfRegistration":"Self registration",
|
||||
"yubikey2fTTL":"Lifetime",
|
||||
"yubikey2fUrl":"Service URL",
|
||||
"yubikey2fUserCanRemoveKey":"Authorize user to remove Yubikey",
|
||||
"yubikey2fUserCanRemoveKey":"Allow user to remove Yubikey",
|
||||
"zeroConfExplanations":"Server has no configuration. Use template to save the first.",
|
||||
|
||||
"saml":"SAML",
|
||||
|
|
|
@ -787,8 +787,9 @@
|
|||
"totp2fIssuer":"TOTP Issuer name",
|
||||
"totp2fRange":"Range of attempts",
|
||||
"totp2fSelfRegistration":"Self registration",
|
||||
"totp2fTTL":"Lifetime",
|
||||
"totp2fUserCanChangeKey":"Change existing secret",
|
||||
"totp2fUserCanRemoveKey":"Authorize user to remove TOTP",
|
||||
"totp2fUserCanRemoveKey":"Allow user to remove TOTP",
|
||||
"trustedDomains":"Trusted domains",
|
||||
"trustedProxies":"Trusted proxies IP",
|
||||
"twitterAppName":"Application name",
|
||||
|
@ -801,8 +802,9 @@
|
|||
"u2f":"U2F",
|
||||
"u2fActivation":"Activation",
|
||||
"u2fAuthnLevel":"U2F authentication level",
|
||||
"u2fUserCanRemoveKey":"Authorize user to remove U2F key",
|
||||
"u2fSelfRegistration":"Self registration",
|
||||
"u2fTTL":"Lifetime",
|
||||
"u2fUserCanRemoveKey":"Allow user to remove U2F key",
|
||||
"uid":"Identifier",
|
||||
"unknownAttrOrMacro":"Unknown attribute or macro",
|
||||
"unknownError":"Unknown error",
|
||||
|
@ -865,8 +867,9 @@
|
|||
"yubikey2fPublicIDSize":"OTP public ID part size",
|
||||
"yubikey2fSecretKey":"API secret key",
|
||||
"yubikey2fSelfRegistration":"Self registration",
|
||||
"yubikey2fTTL":"Lifetime",
|
||||
"yubikey2fUrl":"Service URL",
|
||||
"yubikey2fUserCanRemoveKey":"Authorize user to remove Yubikey",
|
||||
"yubikey2fUserCanRemoveKey":"Allow user to remove Yubikey",
|
||||
"zeroConfExplanations":"Server has no configuration. Use template to save the first.",
|
||||
|
||||
"saml":"SAML",
|
||||
|
|
|
@ -787,6 +787,7 @@
|
|||
"totp2fIssuer":"Nom du fournisseur TOTP",
|
||||
"totp2fRange":"Nombre d'intervalles à tester",
|
||||
"totp2fSelfRegistration":"Auto-enregistrement",
|
||||
"totp2fTTL":"Durée de vie",
|
||||
"totp2fUserCanChangeKey":"Changer une clef existante",
|
||||
"totp2fUserCanRemoveKey":"Autoriser les utilisateurs à effacer leur TOTP",
|
||||
"trustedDomains":"Domaines approuvés",
|
||||
|
@ -801,8 +802,9 @@
|
|||
"u2f":"U2F",
|
||||
"u2fActivation":"Activation",
|
||||
"u2fAuthnLevel":"Niveau d'authentification U2F",
|
||||
"u2fUserCanRemoveKey":"Autoriser les utilisateurs à effacer leur clef U2F",
|
||||
"u2fSelfRegistration":"Auto-enregistrement",
|
||||
"u2fTTL":"Durée de vie",
|
||||
"u2fUserCanRemoveKey":"Autoriser les utilisateurs à effacer leur clef U2F",
|
||||
"uid":"Identifiant",
|
||||
"unknownAttrOrMacro":"Attribut ou macro inconnu",
|
||||
"unknownError":"Erreur inconnue",
|
||||
|
@ -865,6 +867,7 @@
|
|||
"yubikey2fPublicIDSize":"Taille de la partie publique de l'OTP",
|
||||
"yubikey2fSecretKey":"Clef secrète de l'API",
|
||||
"yubikey2fSelfRegistration":"Auto-enregistrement",
|
||||
"yubikey2fTTL":"Durée de vie",
|
||||
"yubikey2fUrl":"URL du service",
|
||||
"yubikey2fUserCanRemoveKey":"Autoriser les utilisateurs à effacer leur Yubikey",
|
||||
"zeroConfExplanations":"Le serveur ne dispose pas de configuration. Cette configuration de base vous permet d'en initialiser une.",
|
||||
|
|
|
@ -787,6 +787,7 @@
|
|||
"totp2fIssuer":"Nome dell'emittente TOTP",
|
||||
"totp2fRange":"Gamma di tentativi",
|
||||
"totp2fSelfRegistration":"Auto-registrazione",
|
||||
"totp2fTTL":"Lifetime",
|
||||
"totp2fUserCanChangeKey":"Cambia segreto esistente",
|
||||
"totp2fUserCanRemoveKey":"Autorizza l'utente a rimuovere TOTP",
|
||||
"trustedDomains":"Domini attendibili",
|
||||
|
@ -801,8 +802,9 @@
|
|||
"u2f":"U2F",
|
||||
"u2fActivation":"Attivazione",
|
||||
"u2fAuthnLevel":"Livello di autenticazione U2F",
|
||||
"u2fUserCanRemoveKey":"Autorizza l'utente a rimuovere la chiave U2F",
|
||||
"u2fSelfRegistration":"Auto-registrazione",
|
||||
"u2fTTL":"Lifetime",
|
||||
"u2fUserCanRemoveKey":"Autorizza l'utente a rimuovere la chiave U2F",
|
||||
"uid":"Identificatore",
|
||||
"unknownAttrOrMacro":"Attributo o macro sconosciuti",
|
||||
"unknownError":"Errore sconosciuto",
|
||||
|
@ -865,6 +867,7 @@
|
|||
"yubikey2fPublicIDSize":"Dimensione della parte ID OTP pubblica",
|
||||
"yubikey2fSecretKey":"Chiave segreta API",
|
||||
"yubikey2fSelfRegistration":"Auto-registrazione",
|
||||
"yubikey2fTTL":"Lifetime",
|
||||
"yubikey2fUrl":"URL del servizio",
|
||||
"yubikey2fUserCanRemoveKey":"Autorizza l'utente a rimuovere la Yubikey",
|
||||
"zeroConfExplanations":"Il server non ha alcuna configurazione. Utilizza il modello per salvare il primo.",
|
||||
|
|
|
@ -787,8 +787,9 @@
|
|||
"totp2fIssuer":"TOTP Issuer name",
|
||||
"totp2fRange":"Range of attempts",
|
||||
"totp2fSelfRegistration":"Tự đăng ký",
|
||||
"totp2fTTL":"Lifetime",
|
||||
"totp2fUserCanChangeKey":"Change existing secret",
|
||||
"totp2fUserCanRemoveKey":"Authorize user to remove TOTP",
|
||||
"totp2fUserCanRemoveKey":"Allow user to remove TOTP",
|
||||
"trustedDomains":"Miền tin cậy",
|
||||
"trustedProxies":"proxies IP tin cậy",
|
||||
"twitterAppName":"Tên ứng dụng",
|
||||
|
@ -801,8 +802,9 @@
|
|||
"u2f":"U2F",
|
||||
"u2fActivation":"Kích hoạt",
|
||||
"u2fAuthnLevel":"Mức xác thực U2F",
|
||||
"u2fUserCanRemoveKey":"Authorize user to remove U2F key",
|
||||
"u2fSelfRegistration":"Tự đăng ký ",
|
||||
"u2fTTL":"Lifetime",
|
||||
"u2fUserCanRemoveKey":"Allow user to remove U2F key",
|
||||
"uid":"Trình định danh",
|
||||
"unknownAttrOrMacro":"Thuộc tính hoặc macro chưa xác định",
|
||||
"unknownError":"Lỗi không xác định",
|
||||
|
@ -865,8 +867,9 @@
|
|||
"yubikey2fPublicIDSize":"Kích thước phần tử công khai OTP",
|
||||
"yubikey2fSecretKey":"Khóa bí mật API",
|
||||
"yubikey2fSelfRegistration":"Tự đăng ký",
|
||||
"yubikey2fTTL":"Lifetime",
|
||||
"yubikey2fUrl":"Dịch vụ URL",
|
||||
"yubikey2fUserCanRemoveKey":"Authorize user to remove Yubikey",
|
||||
"yubikey2fUserCanRemoveKey":"Allow user to remove Yubikey",
|
||||
"zeroConfExplanations":"Máy chủ không có cấu hình. Sử dụng mẫu để lưu đầu tiên. ",
|
||||
|
||||
"saml":"SAML",
|
||||
|
|
|
@ -787,8 +787,9 @@
|
|||
"totp2fIssuer":"TOTP Issuer name",
|
||||
"totp2fRange":"Range of attempts",
|
||||
"totp2fSelfRegistration":"Self registration",
|
||||
"totp2fTTL":"Lifetime",
|
||||
"totp2fUserCanChangeKey":"Change existing secret",
|
||||
"totp2fUserCanRemoveKey":"Authorize user to remove TOTP",
|
||||
"totp2fUserCanRemoveKey":"Allow user to remove TOTP",
|
||||
"trustedDomains":"Trusted domains",
|
||||
"trustedProxies":"Trusted proxies IP",
|
||||
"twitterAppName":"Application name",
|
||||
|
@ -801,8 +802,9 @@
|
|||
"u2f":"U2F",
|
||||
"u2fActivation":"激活",
|
||||
"u2fAuthnLevel":"U2F authentication level",
|
||||
"u2fUserCanRemoveKey":"Authorize user to remove U2F key",
|
||||
"u2fSelfRegistration":"Self registration",
|
||||
"u2fTTL":"Lifetime",
|
||||
"u2fUserCanRemoveKey":"Allow user to remove U2F key",
|
||||
"uid":"Identifier",
|
||||
"unknownAttrOrMacro":"Unknown attribute or macro",
|
||||
"unknownError":"Unknown error",
|
||||
|
@ -865,8 +867,9 @@
|
|||
"yubikey2fPublicIDSize":"OTP public ID part size",
|
||||
"yubikey2fSecretKey":"API secret key",
|
||||
"yubikey2fSelfRegistration":"Self registration",
|
||||
"yubikey2fTTL":"Lifetime",
|
||||
"yubikey2fUrl":"Service URL",
|
||||
"yubikey2fUserCanRemoveKey":"Authorize user to remove Yubikey",
|
||||
"yubikey2fUserCanRemoveKey":"Allow user to remove Yubikey",
|
||||
"zeroConfExplanations":"Server has no configuration. Use template to save the first.",
|
||||
|
||||
"saml":"SAML",
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -126,7 +126,6 @@ sub init {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -137,7 +136,6 @@ sub init {
|
|||
# run() is called at each authentication, just after sessionInfo populated
|
||||
sub run {
|
||||
my ( $self, $req ) = @_;
|
||||
|
||||
my $checkLogins = $req->param('checkLogins');
|
||||
my $spoofId = $req->param('spoofId') || '';
|
||||
$self->logger->debug("2F checkLogins set") if ($checkLogins);
|
||||
|
@ -145,6 +143,65 @@ sub run {
|
|||
# Skip 2F unless a module has been registered
|
||||
return PE_OK unless ( @{ $self->sfModules } );
|
||||
|
||||
# Remove expired 2F devices
|
||||
my $session = $req->sessionInfo;
|
||||
if ( $session->{_2fDevices} ) {
|
||||
$self->logger->debug("Loading 2F Devices ...");
|
||||
|
||||
# Read existing 2FDevices
|
||||
my $_2fDevices =
|
||||
eval { from_json( $session->{_2fDevices}, { allow_nonref => 1 } ); };
|
||||
if ($@) {
|
||||
$self->logger->error("Bad encoding in _2fDevices: $@");
|
||||
return PE_ERROR;
|
||||
}
|
||||
$self->logger->debug(" -> 2F Device(s) found");
|
||||
|
||||
# Initialize 2FDevices TTL
|
||||
my $u2fTTL = $self->conf->{u2fTTL}
|
||||
&& $self->conf->{u2fTTL} > 0 ? $self->conf->{u2fTTL} : 0;
|
||||
my $totpTTL = $self->conf->{totp2fTTL}
|
||||
&& $self->conf->{totp2fTTL} > 0 ? $self->conf->{totp2fTTL} : 0;
|
||||
my $ubkTTL = $self->conf->{yubikey2fTTL}
|
||||
&& $self->conf->{yubikey2fTTL} > 0 ? $self->conf->{yubikey2fTTL} : 0;
|
||||
|
||||
# Processing if at least one TTL is set
|
||||
if ( $u2fTTL || $totpTTL || $ubkTTL ) {
|
||||
my $now = time();
|
||||
my $removed = 0;
|
||||
$self->logger->debug("Looking for expired 2F device(s)...");
|
||||
foreach my $device (@$_2fDevices) {
|
||||
foreach my $type (qw(TOTP U2F UBK)) {
|
||||
if ( $device->{type} eq $type ) {
|
||||
if ( eval( '$' . lc($type) . 'TTL' )
|
||||
&& $now - $device->{epoch} >
|
||||
eval( '$' . lc($type) . 'TTL' ) )
|
||||
{
|
||||
$self->logger->debug(
|
||||
"Remove $type -> $device->{name} / $device->{epoch}"
|
||||
);
|
||||
$self->userLogger->info("Remove expired $type");
|
||||
$device->{type} = 'EXPIRED';
|
||||
$removed++;
|
||||
last;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($removed) {
|
||||
$self->logger->debug(
|
||||
"Found $removed EXPIRED 2F device(s) => Update persistent session"
|
||||
);
|
||||
$self->userLogger->notice(
|
||||
" -> $removed EXPIRED 2F device(s) removed");
|
||||
@$_2fDevices =
|
||||
map { $_->{type} =~ /\bEXPIRED\b/ ? () : $_ } @$_2fDevices;
|
||||
$self->p->updatePersistentSession( $req,
|
||||
{ _2fDevices => to_json($_2fDevices) } );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Search for authorized modules for this user
|
||||
my @am;
|
||||
foreach my $m ( @{ $self->sfModules } ) {
|
||||
|
|
|
@ -166,7 +166,7 @@ sub check {
|
|||
}
|
||||
else {
|
||||
$msg =
|
||||
$self->{conf}->{impersonationMergeSSOgroups}
|
||||
$self->{conf}->{impersonationMergeSSOgroups} eq 1
|
||||
? 'checkUserMerged'
|
||||
: 'checkUser';
|
||||
$msg = 'checkUserComputeSession' if $compute;
|
||||
|
|
|
@ -55,7 +55,9 @@ sub init {
|
|||
sub run {
|
||||
my ( $self, $req ) = @_;
|
||||
|
||||
return $req->authResult if $req->authResult > PE_OK; # Skip Impersonation if error during Auth process
|
||||
return $req->authResult
|
||||
if $req->authResult >
|
||||
PE_OK; # Skip Impersonation if error during Auth process
|
||||
|
||||
my $statut = PE_OK;
|
||||
my $loginHistory =
|
||||
|
@ -124,24 +126,42 @@ sub run {
|
|||
|
||||
# Merging SSO Groups and hGroups & dedup
|
||||
$spoofSession->{groups} ||= '';
|
||||
$spoofSession->{hGroups} ||= {};
|
||||
if ( $self->{conf}->{impersonationMergeSSOgroups} ) {
|
||||
$self->userLogger->warn("MERGING SSO groups and hGroups...");
|
||||
my $spg = "$self->{conf}->{impersonationPrefix}groups";
|
||||
my $sphg = "$self->{conf}->{impersonationPrefix}hGroups";
|
||||
my $separator = $self->{conf}->{multiValuesSeparator};
|
||||
$realSession->{$spg} ||= '';
|
||||
|
||||
## GROUPS
|
||||
my @spoofGrps = split /\Q$separator/, $spoofSession->{groups};
|
||||
my @realGrps = split /\Q$separator/, $realSession->{$spg};
|
||||
|
||||
## hGROUPS
|
||||
$realSession->{$sphg} ||= {};
|
||||
|
||||
# Merge specified groups/hGroups only
|
||||
unless ( $self->{conf}->{impersonationMergeSSOgroups} eq 1 ) {
|
||||
my %SSOgroups = map { $_, 1 } split /\Q$separator/,
|
||||
$self->{conf}->{impersonationMergeSSOgroups};
|
||||
|
||||
$self->logger->debug("Filtering specified groups/hGroups...");
|
||||
@realGrps = grep { exists $SSOgroups{$_} } @realGrps;
|
||||
my %intersct =
|
||||
map {
|
||||
$realSession->{$sphg}->{$_}
|
||||
? ( $_, $realSession->{$sphg}->{$_} )
|
||||
: ()
|
||||
} keys %SSOgroups;
|
||||
$realSession->{$sphg} = \%intersct;
|
||||
}
|
||||
|
||||
$self->logger->debug("Processing groups...");
|
||||
my @spoofGrps = my @realGrps = ();
|
||||
@spoofGrps = split /\Q$separator/, $spoofSession->{groups};
|
||||
@realGrps = split /\Q$separator/, $realSession->{$spg};
|
||||
@spoofGrps = ( @spoofGrps, @realGrps );
|
||||
my %hash = map { $_, 1 } @spoofGrps;
|
||||
$spoofSession->{groups} = join $separator, sort keys %hash;
|
||||
|
||||
$self->logger->debug("Processing hGroups...");
|
||||
$spoofSession->{hGroups} ||= {};
|
||||
$realSession->{$sphg} ||= {};
|
||||
$spoofSession->{hGroups} =
|
||||
{ %{ $spoofSession->{hGroups} }, %{ $realSession->{$sphg} } };
|
||||
}
|
||||
|
|
|
@ -237,11 +237,9 @@ ok(
|
|||
);
|
||||
count(1);
|
||||
expectOK($res);
|
||||
ok(
|
||||
$res->[2]->[0] =~
|
||||
m%<span trspan="connectedAs">Connected as</span> dwho%,
|
||||
'Connected as dwho'
|
||||
) or print STDERR Dumper( $res->[2]->[0] );
|
||||
ok( $res->[2]->[0] =~ m%<span trspan="connectedAs">Connected as</span> dwho%,
|
||||
'Connected as dwho' )
|
||||
or print STDERR Dumper( $res->[2]->[0] );
|
||||
count(1);
|
||||
|
||||
# CheckUser form
|
||||
|
@ -310,7 +308,8 @@ ok( $res->[2]->[0] =~ m%<td class="align-middle">_whatToTrace</td>%,
|
|||
ok( $res->[2]->[0] =~ m%<td class="text-left">testPrefix_groups</td>%,
|
||||
'Found testPrefix_groups' )
|
||||
or explain( $res->[2]->[0], 'testPrefix_groups' );
|
||||
ok( $res->[2]->[0] =~ m%<td class="text-left">su</td>%, 'Found su' )
|
||||
ok( $res->[2]->[0] =~ m%<td class="text-left">su; su_test; test_su</td>%,
|
||||
'Found "su; su_test; test_su"' )
|
||||
or explain( $res->[2]->[0], 'su' );
|
||||
ok( $res->[2]->[0] =~ m%<td class="text-left">testPrefix_uid</td>%,
|
||||
'Found testPrefix_uid' )
|
||||
|
|
|
@ -0,0 +1,149 @@
|
|||
use Test::More;
|
||||
use strict;
|
||||
use IO::String;
|
||||
|
||||
BEGIN {
|
||||
require 't/test-lib.pm';
|
||||
}
|
||||
|
||||
my $res;
|
||||
|
||||
my $client = LLNG::Manager::Test->new( {
|
||||
ini => {
|
||||
logLevel => 'error',
|
||||
authentication => 'Demo',
|
||||
userDB => 'Same',
|
||||
loginHistoryEnabled => 0,
|
||||
brutForceProtection => 0,
|
||||
portalMainLogo => 'common/logos/logo_llng_old.png',
|
||||
requireToken => 0,
|
||||
checkUser => 1,
|
||||
impersonationRule => 1,
|
||||
checkUserDisplayPersistentInfo => 0,
|
||||
checkUserDisplayEmptyValues => 0,
|
||||
impersonationMergeSSOgroups => 'su; _test_; su_test; sutest',
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
## Try to authenticate
|
||||
ok( $res = $client->_get( '/', accept => 'text/html' ), 'Get Menu', );
|
||||
count(1);
|
||||
my ( $host, $url, $query ) =
|
||||
expectForm( $res, '#', undef, 'user', 'password', 'spoofId' );
|
||||
|
||||
$query =~ s/user=/user=rtyler/;
|
||||
$query =~ s/password=/password=rtyler/;
|
||||
$query =~ s/spoofId=/spoofId=dwho/;
|
||||
ok(
|
||||
$res = $client->_post(
|
||||
'/',
|
||||
IO::String->new($query),
|
||||
length => length($query),
|
||||
accept => 'text/html',
|
||||
),
|
||||
'Auth query'
|
||||
);
|
||||
count(1);
|
||||
|
||||
my $id = expectCookie($res);
|
||||
expectRedirection( $res, 'http://auth.example.com/' );
|
||||
|
||||
# Get Menu
|
||||
# ------------------------
|
||||
ok(
|
||||
$res = $client->_get(
|
||||
'/',
|
||||
cookie => "lemonldap=$id",
|
||||
accept => 'text/html'
|
||||
),
|
||||
'Get Menu',
|
||||
);
|
||||
count(1);
|
||||
expectOK($res);
|
||||
ok(
|
||||
$res->[2]->[0] =~
|
||||
m%<span trspan="connectedAs">Connected as</span> dwho%,
|
||||
'Connected as dwho'
|
||||
) or print STDERR Dumper( $res->[2]->[0] );
|
||||
expectAuthenticatedAs( $res, 'dwho' );
|
||||
count(1);
|
||||
|
||||
# CheckUser form
|
||||
# ------------------------
|
||||
ok(
|
||||
$res = $client->_get(
|
||||
'/checkuser',
|
||||
cookie => "lemonldap=$id",
|
||||
accept => 'text/html'
|
||||
),
|
||||
'CheckUser form',
|
||||
);
|
||||
count(1);
|
||||
( $host, $url, $query ) =
|
||||
expectForm( $res, undef, '/checkuser', 'user', 'url' );
|
||||
ok( $res->[2]->[0] =~ m%<span trspan="checkUserMerged">%,
|
||||
'Found trspan="checkUserMerged"' )
|
||||
or explain( $res->[2]->[0], 'trspan="checkUserMerged"' );
|
||||
count(1);
|
||||
|
||||
$query =~ s/url=/url=test1.example.com/;
|
||||
|
||||
ok(
|
||||
$res = $client->_post(
|
||||
'/checkuser',
|
||||
IO::String->new($query),
|
||||
cookie => "lemonldap=$id",
|
||||
length => length($query),
|
||||
accept => 'text/html',
|
||||
),
|
||||
'POST checkuser'
|
||||
);
|
||||
count(1);
|
||||
|
||||
( $host, $url, $query ) =
|
||||
expectForm( $res, undef, '/checkuser', 'user', 'url' );
|
||||
ok( $res->[2]->[0] =~ m%<span trspan="checkUser">%,
|
||||
'Found trspan="checkUser"' )
|
||||
or explain( $res->[2]->[0], 'trspan="checkUser"' );
|
||||
ok(
|
||||
$res->[2]->[0] =~
|
||||
m%<div class="alert alert-success"><b><span trspan="allowed"></span></b></div>%,
|
||||
'Found trspan="allowed"'
|
||||
) or explain( $res->[2]->[0], 'trspan="allowed"' );
|
||||
ok( $res->[2]->[0] =~ m%<span trspan="headers">%, 'Found trspan="headers"' )
|
||||
or explain( $res->[2]->[0], 'trspan="headers"' );
|
||||
ok( $res->[2]->[0] =~ m%<span trspan="groups_sso">%,
|
||||
'Found trspan="groups_sso"' )
|
||||
or explain( $res->[2]->[0], 'trspan="groups_sso"' );
|
||||
ok( $res->[2]->[0] =~ m%<span trspan="macros">%, 'Found trspan="macros"' )
|
||||
or explain( $res->[2]->[0], 'trspan="macros"' );
|
||||
ok( $res->[2]->[0] =~ m%<span trspan="attributes">%,
|
||||
'Found trspan="attributes"' )
|
||||
or explain( $res->[2]->[0], 'trspan="attributes"' );
|
||||
ok( $res->[2]->[0] =~ m%<td class="text-left">_userDB</td>%, 'Found _userDB' )
|
||||
or explain( $res->[2]->[0], '_userDB' );
|
||||
ok( $res->[2]->[0] =~ m%<td class="align-middle">Auth-User</td>%,
|
||||
'Found Auth-User' )
|
||||
or explain( $res->[2]->[0], 'Header Key: Auth-User' );
|
||||
ok( $res->[2]->[0] =~ m%<td class="align-middle">dwho</td>%, 'Found dwho' )
|
||||
or explain( $res->[2]->[0], 'Header Value: dwho' );
|
||||
ok( $res->[2]->[0] =~ m%<td class="align-middle">su</td>%, 'Found su' )
|
||||
or explain( $res->[2]->[0], 'SSO Groups: su' );
|
||||
ok( $res->[2]->[0] =~ m%<td class="align-middle">su_test</td>%, 'Found su_test' )
|
||||
or explain( $res->[2]->[0], 'SSO Groups: su_test' );
|
||||
ok( $res->[2]->[0] !~ m%<td class="align-middle">_test_</td>%, 'NOT found _test_' )
|
||||
or explain( $res->[2]->[0], 'SSO Groups: _test_' );
|
||||
ok( $res->[2]->[0] !~ m%<td class="align-middle">test_su</td>%, 'NOT found test_su' )
|
||||
or explain( $res->[2]->[0], 'SSO Groups: test_su' );
|
||||
ok( $res->[2]->[0] =~ m%<td class="align-middle">_whatToTrace</td>%,
|
||||
'Found _whatToTrace' )
|
||||
or explain( $res->[2]->[0], 'Macro Key _whatToTrace' );
|
||||
ok( $res->[2]->[0] =~ m%<td class="text-left">uid</td>%, 'Found uid' )
|
||||
or explain( $res->[2]->[0], 'Attribute Value uid' );
|
||||
count(15);
|
||||
|
||||
$client->logout($id);
|
||||
clean_sessions();
|
||||
|
||||
done_testing( count() );
|
|
@ -116,6 +116,15 @@ ok( $res->[2]->[0] =~ m%<span trspan="headers">%, 'Found trspan="headers"' )
|
|||
ok( $res->[2]->[0] =~ m%<span trspan="groups_sso">%,
|
||||
'Found trspan="groups_sso"' )
|
||||
or explain( $res->[2]->[0], 'trspan="groups_sso"' );
|
||||
ok( $res->[2]->[0] =~ m%<td class="align-middle">su</td>%,
|
||||
'Found SSO group "su"' )
|
||||
or explain( $res->[2]->[0], 'Found SSOO group "su"' );
|
||||
ok( $res->[2]->[0] =~ m%<td class="align-middle">su_test</td>%,
|
||||
'Found SSO group "su_test"' )
|
||||
or explain( $res->[2]->[0], 'Found SSO group "su_test"' );
|
||||
ok( $res->[2]->[0] =~ m%<td class="align-middle">test_su</td>%,
|
||||
'Found SSO group "test_su"' )
|
||||
or explain( $res->[2]->[0], 'Found SSO group "test_su"' );
|
||||
ok( $res->[2]->[0] =~ m%<span trspan="macros">%, 'Found trspan="macros"' )
|
||||
or explain( $res->[2]->[0], 'trspan="macros"' );
|
||||
ok( $res->[2]->[0] =~ m%<span trspan="attributes">%,
|
||||
|
@ -130,12 +139,18 @@ ok( $res->[2]->[0] =~ m%<td class="align-middle">dwho</td>%, 'Found dwho' )
|
|||
or explain( $res->[2]->[0], 'Header Value: dwho' );
|
||||
ok( $res->[2]->[0] =~ m%<td class="align-middle">su</td>%, 'Found su' )
|
||||
or explain( $res->[2]->[0], 'SSO Groups: su' );
|
||||
ok( $res->[2]->[0] =~ m%<td class="align-middle">su_test</td>%, 'Found su_test' )
|
||||
or explain( $res->[2]->[0], 'SSO Groups: su_test' );
|
||||
ok( $res->[2]->[0] !~ m%<td class="align-middle">_test_</td>%, 'NOT found _test_' )
|
||||
or explain( $res->[2]->[0], 'SSO Groups: _test_' );
|
||||
ok( $res->[2]->[0] =~ m%<td class="align-middle">test_su</td>%, 'Found test_su' )
|
||||
or explain( $res->[2]->[0], 'SSO Groups: test_su' );
|
||||
ok( $res->[2]->[0] =~ m%<td class="align-middle">_whatToTrace</td>%,
|
||||
'Found _whatToTrace' )
|
||||
or explain( $res->[2]->[0], 'Macro Key _whatToTrace' );
|
||||
ok( $res->[2]->[0] =~ m%<td class="text-left">uid</td>%, 'Found uid' )
|
||||
or explain( $res->[2]->[0], 'Attribute Value uid' );
|
||||
count(12);
|
||||
count(18);
|
||||
|
||||
$client->logout($id);
|
||||
clean_sessions();
|
||||
|
|
|
@ -154,8 +154,7 @@ ok(
|
|||
count(1);
|
||||
expectOK($res);
|
||||
ok(
|
||||
$res->[2]->[0] =~
|
||||
m%<span trspan="connectedAs">Connected as</span> msmith%,
|
||||
$res->[2]->[0] =~ m%<span trspan="connectedAs">Connected as</span> msmith%,
|
||||
'Connected as msmith'
|
||||
) or print STDERR Dumper( $res->[2]->[0] );
|
||||
expectAuthenticatedAs( $res, 'msmith' );
|
||||
|
@ -235,11 +234,9 @@ ok(
|
|||
);
|
||||
count(1);
|
||||
expectOK($res);
|
||||
ok(
|
||||
$res->[2]->[0] =~
|
||||
m%<span trspan="connectedAs">Connected as</span> dwho%,
|
||||
'Connected as dwho'
|
||||
) or print STDERR Dumper( $res->[2]->[0] );
|
||||
ok( $res->[2]->[0] =~ m%<span trspan="connectedAs">Connected as</span> dwho%,
|
||||
'Connected as dwho' )
|
||||
or print STDERR Dumper( $res->[2]->[0] );
|
||||
expectAuthenticatedAs( $res, 'dwho' );
|
||||
count(1);
|
||||
|
||||
|
@ -309,7 +306,8 @@ ok( $res->[2]->[0] =~ m%<td class="align-middle">_whatToTrace</td>%,
|
|||
ok( $res->[2]->[0] =~ m%<td class="text-left">testPrefix_groups</td>%,
|
||||
'Found testPrefix_groups' )
|
||||
or explain( $res->[2]->[0], 'testPrefix_groups' );
|
||||
ok( $res->[2]->[0] =~ m%<td class="text-left">su</td>%, 'Found su' )
|
||||
ok( $res->[2]->[0] =~ m%<td class="text-left">su; su_test; test_su</td>%,
|
||||
'Found "su; su_test; test_su"' )
|
||||
or explain( $res->[2]->[0], 'su' );
|
||||
ok( $res->[2]->[0] =~ m%<td class="text-left">testPrefix_uid</td>%,
|
||||
'Found testPrefix_uid' )
|
||||
|
|
|
@ -3,7 +3,7 @@ use strict;
|
|||
use IO::String;
|
||||
|
||||
require 't/test-lib.pm';
|
||||
my $maintests = 16;
|
||||
my $maintests = 17;
|
||||
|
||||
SKIP: {
|
||||
eval { require Convert::Base32 };
|
||||
|
@ -17,6 +17,7 @@ SKIP: {
|
|||
logLevel => 'error',
|
||||
totp2fSelfRegistration => 1,
|
||||
totp2fActivation => 1,
|
||||
totp2fTTL => 2,
|
||||
portalMainLogo => 'common/logos/logo_llng_old.png',
|
||||
}
|
||||
}
|
||||
|
@ -82,7 +83,7 @@ SKIP: {
|
|||
ok( $code = Lemonldap::NG::Common::TOTP::_code( undef, $key, 0, 30, 6 ),
|
||||
'Code' );
|
||||
ok( $code =~ /^\d{6}$/, 'Code contains 6 digits' );
|
||||
my $s = "code=$code&token=$token";
|
||||
my $s = "code=$code&token=$token&TOTPName=myTOTP";
|
||||
ok(
|
||||
$res = $client->_post(
|
||||
'/2fregisters/totp/verify',
|
||||
|
@ -122,6 +123,22 @@ SKIP: {
|
|||
);
|
||||
$id = expectCookie($res);
|
||||
$client->logout($id);
|
||||
|
||||
diag 'Waiting';
|
||||
sleep 3;
|
||||
|
||||
# Try to sign-in
|
||||
ok(
|
||||
$res = $client->_post(
|
||||
'/',
|
||||
IO::String->new('user=dwho&password=dwho'),
|
||||
length => 23,
|
||||
accept => 'text/html',
|
||||
),
|
||||
'Auth query'
|
||||
);
|
||||
$id = expectCookie($res);
|
||||
expectRedirection( $res, 'http://auth.example.com/' );
|
||||
}
|
||||
count($maintests);
|
||||
|
|
@ -4,7 +4,7 @@ use IO::String;
|
|||
use Data::Dumper;
|
||||
|
||||
require 't/test-lib.pm';
|
||||
my $maintests = 51;
|
||||
my $maintests = 52;
|
||||
|
||||
SKIP: {
|
||||
eval { require Convert::Base32 };
|
||||
|
@ -92,7 +92,7 @@ SKIP: {
|
|||
ok( $code = Lemonldap::NG::Common::TOTP::_code( undef, $key, 0, 30, 6 ),
|
||||
'Code' );
|
||||
ok( $code =~ /^\d{6}$/, 'Code contains 6 digits' );
|
||||
my $s = "code=$code&token=$token";
|
||||
my $s = "code=$code&token=$token&TOTPName=myTOTP";
|
||||
ok(
|
||||
$res = $client->_post(
|
||||
'/2fregisters/totp/verify',
|
||||
|
@ -276,6 +276,9 @@ JjTJecOOS+88fK8qL1TrYv5rapIdqUI7aQ==
|
|||
or print STDERR Dumper($res);
|
||||
ok( $sf[0] eq 'TOTP', 'TOTP device found' ) or print STDERR Dumper( \@sf );
|
||||
ok( $sf[1] eq 'U2F', 'U2F device found' ) or print STDERR Dumper( \@sf );
|
||||
ok( $res->[2]->[0] =~ qr%<td class="align-middle">myTOTP</td>%,
|
||||
'Found TOTP name' )
|
||||
or print STDERR Dumper($res);
|
||||
|
||||
# Unregister TOTP
|
||||
ok( $res->[2]->[0] =~ qr%TOTP.*epoch.*(\d{10})%m, "TOTP epoch $1 found" )
|
||||
|
|
|
@ -71,7 +71,7 @@
|
|||
"LockDirectory": "t/sessions/lock",
|
||||
"generateModule": "Lemonldap::NG::Common::Apache::Session::Generate::SHA256"
|
||||
},
|
||||
"groups": { "su":"$uid eq \"rtyler\"" },
|
||||
"groups": { "su":"$uid eq \"rtyler\"", "test_su": "$uid eq \"rtyler\"", "su_test": "$uid eq \"rtyler\"" },
|
||||
"key": "qwertyui",
|
||||
"locationRules": {
|
||||
"auth.example.com" : {
|
||||
|
|
Loading…
Reference in New Issue