make tidy

This commit is contained in:
Clément OUDOT 2018-10-12 10:04:03 +02:00
parent f43139321c
commit c5f9a7f95b
39 changed files with 765 additions and 690 deletions

View File

@ -541,9 +541,10 @@ sub authChoiceModules {
my @res; my @res;
foreach my $k ( sort keys %$value ) { foreach my $k ( sort keys %$value ) {
my $data = [ split /;/, $value->{$k} ]; my $data = [ split /;/, $value->{$k} ];
eval {$data->[5] = from_json($data->[5]) if $data->[5] }; eval { $data->[5] = from_json( $data->[5] ) if $data->[5] };
if($@){ if ($@) {
$self->logger->error("Bad value in choice over parameters, deleted ($@)"); $self->logger->error(
"Bad value in choice over parameters, deleted ($@)");
} }
push @res, push @res,
{ {

View File

@ -107,7 +107,7 @@ sub statusInit {
exec $perl_exec, '-MLemonldap::NG::Handler::Lib::Status', exec $perl_exec, '-MLemonldap::NG::Handler::Lib::Status',
# Insert @INC in Perl path # Insert @INC in Perl path
map( { "-I$_" } @INC ), map( {"-I$_"} @INC ),
# Command to launch # Command to launch
'-e', '&Lemonldap::NG::Handler::Lib::Status::run()', '-e', '&Lemonldap::NG::Handler::Lib::Status::run()',

View File

@ -29,15 +29,15 @@ sub types {
# Simple text types # Simple text types
text => { text => {
test => sub {1}, test => sub { 1 },
msgFail => '__malformedValue__', msgFail => '__malformedValue__',
}, },
password => { password => {
test => sub {1}, test => sub { 1 },
msgFail => '__malformedValue__', msgFail => '__malformedValue__',
}, },
longtext => { longtext => {
test => sub {1} test => sub { 1 }
}, },
url => { url => {
form => 'text', form => 'text',
@ -57,7 +57,7 @@ sub types {
pcre => { pcre => {
form => 'text', form => 'text',
test => sub { test => sub {
eval {qr/$_[0]/}; eval { qr/$_[0]/ };
return $@ ? ( 0, "__badRegexp__: $@" ) : (1); return $@ ? ( 0, "__badRegexp__: $@" ) : (1);
}, },
}, },
@ -102,7 +102,7 @@ sub types {
}, },
subContainer => { subContainer => {
keyTest => qr/\w/, keyTest => qr/\w/,
test => sub {1}, test => sub { 1 },
}, },
select => { select => {
test => sub { test => sub {
@ -116,13 +116,13 @@ sub types {
# Files type (long text) # Files type (long text)
file => { file => {
test => sub {1} test => sub { 1 }
}, },
RSAPublicKey => { RSAPublicKey => {
test => sub { test => sub {
return ( return (
$_[0] $_[0] =~
=~ /^(?:(?:\-+\s*BEGIN\s+PUBLIC\s+KEY\s*\-+\r?\n)?[a-zA-Z0-9\/\+\r\n]+={0,2}(?:\r?\n\-+\s*END\s+PUBLIC\s+KEY\s*\-+)?[\r\n]*)?$/s /^(?:(?:\-+\s*BEGIN\s+PUBLIC\s+KEY\s*\-+\r?\n)?[a-zA-Z0-9\/\+\r\n]+={0,2}(?:\r?\n\-+\s*END\s+PUBLIC\s+KEY\s*\-+)?[\r\n]*)?$/s
? (1) ? (1)
: ( 1, '__badPemEncoding__' ) : ( 1, '__badPemEncoding__' )
); );
@ -131,8 +131,8 @@ sub types {
'RSAPublicKeyOrCertificate' => { 'RSAPublicKeyOrCertificate' => {
'test' => sub { 'test' => sub {
return ( return (
$_[0] $_[0] =~
=~ /^(?:(?:\-+\s*BEGIN\s+(?:PUBLIC\s+KEY|CERTIFICATE)\s*\-+\r?\n)?[a-zA-Z0-9\/\+\r\n]+={0,2}(?:\r?\n\-+\s*END\s+(?:PUBLIC\s+KEY|CERTIFICATE)\s*\-+)?[\r\n]*)?$/s /^(?:(?:\-+\s*BEGIN\s+(?:PUBLIC\s+KEY|CERTIFICATE)\s*\-+\r?\n)?[a-zA-Z0-9\/\+\r\n]+={0,2}(?:\r?\n\-+\s*END\s+(?:PUBLIC\s+KEY|CERTIFICATE)\s*\-+)?[\r\n]*)?$/s
? (1) ? (1)
: ( 1, '__badPemEncoding__' ) : ( 1, '__badPemEncoding__' )
); );
@ -141,8 +141,8 @@ sub types {
RSAPrivateKey => { RSAPrivateKey => {
test => sub { test => sub {
return ( return (
$_[0] $_[0] =~
=~ /^(?:(?:\-+\s*BEGIN\s+(?:RSA\s+)?PRIVATE\s+KEY\s*\-+\r?\n)?(?:Proc-Type:.*\r?\nDEK-Info:.*\r?\n[\r\n]*)?[a-zA-Z0-9\/\+\r\n]+={0,2}(?:\r?\n\-+\s*END\s+(?:RSA\s+)PRIVATE\s+KEY\s*\-+)?[\r\n]*)?$/s /^(?:(?:\-+\s*BEGIN\s+(?:RSA\s+)?PRIVATE\s+KEY\s*\-+\r?\n)?(?:Proc-Type:.*\r?\nDEK-Info:.*\r?\n[\r\n]*)?[a-zA-Z0-9\/\+\r\n]+={0,2}(?:\r?\n\-+\s*END\s+(?:RSA\s+)PRIVATE\s+KEY\s*\-+)?[\r\n]*)?$/s
? (1) ? (1)
: ( 1, '__badPemEncoding__' ) : ( 1, '__badPemEncoding__' )
); );
@ -150,13 +150,13 @@ sub types {
}, },
authParamsText => { authParamsText => {
test => sub {1} test => sub { 1 }
}, },
blackWhiteList => { blackWhiteList => {
test => sub {1} test => sub { 1 }
}, },
catAndAppList => { catAndAppList => {
test => sub {1} test => sub { 1 }
}, },
keyText => { keyText => {
keyTest => qr/^[a-zA-Z0-9_]+$/, keyTest => qr/^[a-zA-Z0-9_]+$/,
@ -164,52 +164,52 @@ sub types {
msgFail => '__badValue__', msgFail => '__badValue__',
}, },
menuApp => { menuApp => {
test => sub {1} test => sub { 1 }
}, },
menuCat => { menuCat => {
test => sub {1} test => sub { 1 }
}, },
oidcOPMetaDataNode => { oidcOPMetaDataNode => {
test => sub {1} test => sub { 1 }
}, },
oidcRPMetaDataNode => { oidcRPMetaDataNode => {
test => sub {1} test => sub { 1 }
}, },
oidcmetadatajson => { oidcmetadatajson => {
test => sub {1} test => sub { 1 }
}, },
oidcmetadatajwks => { oidcmetadatajwks => {
test => sub {1} test => sub { 1 }
}, },
portalskin => { portalskin => {
test => sub {1} test => sub { 1 }
}, },
portalskinbackground => { portalskinbackground => {
test => sub {1} test => sub { 1 }
}, },
post => { post => {
test => sub {1} test => sub { 1 }
}, },
rule => { rule => {
test => sub {1} test => sub { 1 }
}, },
samlAssertion => { samlAssertion => {
test => sub {1} test => sub { 1 }
}, },
samlAttribute => { samlAttribute => {
test => sub {1} test => sub { 1 }
}, },
samlIDPMetaDataNode => { samlIDPMetaDataNode => {
test => sub {1} test => sub { 1 }
}, },
samlSPMetaDataNode => { samlSPMetaDataNode => {
test => sub {1} test => sub { 1 }
}, },
samlService => { samlService => {
test => sub {1} test => sub { 1 }
}, },
array => { array => {
test => sub {1} test => sub { 1 }
}, },
}; };
} }
@ -253,13 +253,11 @@ sub attributes {
}, },
cfgAuthor => { cfgAuthor => {
type => 'text', type => 'text',
documentation => documentation => 'Name of the author of the current configuration',
'Name of the author of the current configuration',
}, },
cfgAuthorIP => { cfgAuthorIP => {
type => 'text', type => 'text',
documentation => documentation => 'Uploader IP address of the current configuration',
'Uploader IP address of the current configuration',
}, },
cfgDate => { cfgDate => {
type => 'int', type => 'int',
@ -319,8 +317,7 @@ sub attributes {
type => 'keyTextContainer', type => 'keyTextContainer',
help => 'logoutforward.html', help => 'logoutforward.html',
default => {}, default => {},
documentation => documentation => 'Send logout trough GET request to these services',
'Send logout trough GET request to these services',
}, },
maintenance => { maintenance => {
default => 0, default => 0,
@ -467,8 +464,7 @@ sub attributes {
keyTest => qr/\w/, keyTest => qr/\w/,
help => 'portalmenu.html#categories_and_applications', help => 'portalmenu.html#categories_and_applications',
default => { default => {
default => default => { catname => 'Default category', type => "category" }
{ catname => 'Default category', type => "category" }
}, },
documentation => 'Applications list', documentation => 'Applications list',
}, },
@ -504,22 +500,26 @@ sub attributes {
documentation => 'Background image of portal skin', documentation => 'Background image of portal skin',
select => [ select => [
{ k => "", v => 'None' }, { k => "", v => 'None' },
{ k => "1280px-Anse_Source_d'Argent_2-La_Digue.jpg", {
k => "1280px-Anse_Source_d'Argent_2-La_Digue.jpg",
v => 'Anse' v => 'Anse'
}, },
{ k => {
"1280px-Autumn-clear-water-waterfall-landscape_-_Virginia_-_ForestWander.jpg", k =>
"1280px-Autumn-clear-water-waterfall-landscape_-_Virginia_-_ForestWander.jpg",
v => 'Waterfall' v => 'Waterfall'
}, },
{ k => "1280px-BrockenSnowedTrees.jpg", v => 'Snowed Trees' }, { k => "1280px-BrockenSnowedTrees.jpg", v => 'Snowed Trees' },
{ k => {
"1280px-Cedar_Breaks_National_Monument_partially.jpg", k => "1280px-Cedar_Breaks_National_Monument_partially.jpg",
v => 'National Monument' v => 'National Monument'
}, },
{ k => "1280px-Parry_Peak_from_Winter_Park.jpg", {
k => "1280px-Parry_Peak_from_Winter_Park.jpg",
v => 'Winter' v => 'Winter'
}, },
{ k => "Aletschgletscher_mit_Pinus_cembra1.jpg", {
k => "Aletschgletscher_mit_Pinus_cembra1.jpg",
v => 'Pinus' v => 'Pinus'
}, },
], ],
@ -571,7 +571,7 @@ sub attributes {
default => 5, default => 5,
type => 'int', type => 'int',
documentation => documentation =>
'Maximun interval in seconds since last authentifcation to force reauthentication', 'Maximun interval in seconds since last authentifcation to force reauthentication',
}, },
bruteForceProtection => { bruteForceProtection => {
default => 0, default => 0,
@ -593,7 +593,7 @@ sub attributes {
grantSessionRules => { grantSessionRules => {
type => 'grantContainer', type => 'grantContainer',
keyTest => $perlExpr, keyTest => $perlExpr,
test => sub {1}, test => sub { 1 },
documentation => 'Rules to grant sessions', documentation => 'Rules to grant sessions',
}, },
hiddenAttributes => { hiddenAttributes => {
@ -1036,8 +1036,7 @@ sub attributes {
portalRequireOldPassword => { portalRequireOldPassword => {
default => 1, default => 1,
type => 'bool', type => 'bool',
documentation => documentation => 'Old password is required to change the password',
'Old password is required to change the password',
}, },
hideOldPassword => { hideOldPassword => {
default => 0, default => 0,
@ -1066,8 +1065,7 @@ sub attributes {
default => 'noreply@example.com', default => 'noreply@example.com',
documentation => 'Sender email', documentation => 'Sender email',
}, },
mailReplyTo => mailReplyTo => { type => 'text', documentation => 'Reply-To address' },
{ type => 'text', documentation => 'Reply-To address' },
mailSessionKey => { mailSessionKey => {
type => 'text', type => 'text',
default => 'mail', default => 'mail',
@ -1254,7 +1252,7 @@ sub attributes {
utotp2fAuthnLevel => { utotp2fAuthnLevel => {
type => 'int', type => 'int',
documentation => documentation =>
'Authentication level for users authentified by password+(U2F or TOTP)' 'Authentication level for users authentified by password+(U2F or TOTP)'
}, },
# External second factor # External second factor
@ -1274,7 +1272,7 @@ sub attributes {
ext2fAuthnLevel => { ext2fAuthnLevel => {
type => 'int', type => 'int',
documentation => documentation =>
'Authentication level for users authentified by External second factor' 'Authentication level for users authentified by External second factor'
}, },
ext2fLogo => { ext2fLogo => {
type => 'text', type => 'text',
@ -1314,7 +1312,7 @@ sub attributes {
rest2fAuthnLevel => { rest2fAuthnLevel => {
type => 'int', type => 'int',
documentation => documentation =>
'Authentication level for users authentified by REST second factor' 'Authentication level for users authentified by REST second factor'
}, },
rest2fLogo => { rest2fLogo => {
type => 'text', type => 'text',
@ -1335,7 +1333,7 @@ sub attributes {
yubikey2fAuthnLevel => { yubikey2fAuthnLevel => {
type => 'int', type => 'int',
documentation => documentation =>
'Authentication level for users authentified by Yubikey second factor' 'Authentication level for users authentified by Yubikey second factor'
}, },
yubikey2fClientID => { yubikey2fClientID => {
type => 'text', type => 'text',
@ -1452,7 +1450,7 @@ sub attributes {
help => 'writingrulesand_headers.html#rules', help => 'writingrulesand_headers.html#rules',
test => { test => {
keyTest => sub { keyTest => sub {
eval {qr/$_[0]/}; eval { qr/$_[0]/ };
return $@ ? 0 : 1; return $@ ? 0 : 1;
}, },
keyMsgFail => '__badRegexp__', keyMsgFail => '__badRegexp__',
@ -1505,7 +1503,7 @@ sub attributes {
post => { post => {
type => 'postContainer', type => 'postContainer',
help => 'formreplay.html', help => 'formreplay.html',
test => sub {1}, test => sub { 1 },
keyTest => qr/^(?:\*\.)?$Regexp::Common::URI::RFC2396::hostname$/, keyTest => qr/^(?:\*\.)?$Regexp::Common::URI::RFC2396::hostname$/,
keyMsgFail => '__badHostname__', keyMsgFail => '__badHostname__',
documentation => 'Virtualhost urls/Data to post', documentation => 'Virtualhost urls/Data to post',
@ -1979,8 +1977,8 @@ sub attributes {
my $res = 1; my $res = 1;
my %entityIds; my %entityIds;
foreach my $idpId ( keys %$v ) { foreach my $idpId ( keys %$v ) {
unless ( $v->{$idpId}->{samlIDPMetaDataXML} unless ( $v->{$idpId}->{samlIDPMetaDataXML} =~
=~ /entityID="(.+?)"/si ) /entityID="(.+?)"/si )
{ {
push @msg, "$idpId SAML metadata has ne EntityID"; push @msg, "$idpId SAML metadata has ne EntityID";
$res = 0; $res = 0;
@ -1989,7 +1987,7 @@ sub attributes {
my $eid = $1; my $eid = $1;
if ( defined $entityIds{$eid} ) { if ( defined $entityIds{$eid} ) {
push @msg, push @msg,
"$idpId and $entityIds{$eid} have the same SAML EntityID"; "$idpId and $entityIds{$eid} have the same SAML EntityID";
$res = 0; $res = 0;
next; next;
} }
@ -2040,7 +2038,8 @@ sub attributes {
select => [ select => [
{ k => '', v => '' }, { k => '', v => '' },
{ k => 'kerberos', v => 'Kerberos' }, { k => 'kerberos', v => 'Kerberos' },
{ k => 'password-protected-transport', {
k => 'password-protected-transport',
v => 'Password protected transport' v => 'Password protected transport'
}, },
{ k => 'password', v => 'Password' }, { k => 'password', v => 'Password' },
@ -2414,8 +2413,8 @@ sub attributes {
my $l = shift; my $l = shift;
my (@s) = split( /[\s,]+/, $l ); my (@s) = split( /[\s,]+/, $l );
foreach my $s (@s) { foreach my $s (@s) {
$s $s =~
=~ m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?::\d{1,5})?/?.*)$}o m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?::\d{1,5})?/?.*)$}o
or return ( 0, "__badLdapUri__: \"$s\"" ); or return ( 0, "__badLdapUri__: \"$s\"" );
} }
return 1; return 1;
@ -2499,7 +2498,7 @@ sub attributes {
type => 'text', type => 'text',
default => 'dn', default => 'dn',
documentation => documentation =>
'LDAP attribute name in user entry referenced as member in groups', 'LDAP attribute name in user entry referenced as member in groups',
}, },
ldapGroupAttributeNameSearch => { ldapGroupAttributeNameSearch => {
type => 'text', type => 'text',
@ -2510,7 +2509,7 @@ sub attributes {
type => 'text', type => 'text',
default => 'dn', default => 'dn',
documentation => documentation =>
'LDAP attribute name in group entry referenced as member in groups', 'LDAP attribute name in group entry referenced as member in groups',
}, },
ldapTimeout => { ldapTimeout => {
type => 'int', type => 'int',
@ -2637,7 +2636,7 @@ sub attributes {
default => { default => {
proxy => 'http://auth.example.com/sessions', proxy => 'http://auth.example.com/sessions',
ns => ns =>
'http://auth.example.com/Lemonldap/NG/Common/PSGI/SOAPService', 'http://auth.example.com/Lemonldap/NG/Common/PSGI/SOAPService',
}, },
documentation => 'Apache::Session module parameters', documentation => 'Apache::Session module parameters',
}, },
@ -2847,11 +2846,13 @@ sub attributes {
type => 'authChoiceContainer', type => 'authChoiceContainer',
keyTest => qr/^(\d*)?[a-zA-Z0-9_]+$/, keyTest => qr/^(\d*)?[a-zA-Z0-9_]+$/,
keyMsgFail => '__badChoiceKey__', keyMsgFail => '__badChoiceKey__',
test => sub {1}, test => sub { 1 },
select => [ select => [
[ { k => 'Apache', v => 'Apache' }, [
{ k => 'Apache', v => 'Apache' },
{ k => 'AD', v => 'Active Directory' }, { k => 'AD', v => 'Active Directory' },
{ k => 'CAS', {
k => 'CAS',
v => 'Central Authentication Service (CAS)' v => 'Central Authentication Service (CAS)'
}, },
{ k => 'DBI', v => 'Database (DBI)' }, { k => 'DBI', v => 'Database (DBI)' },
@ -2876,8 +2877,10 @@ sub attributes {
{ k => 'WebID', v => 'WebID' }, { k => 'WebID', v => 'WebID' },
{ k => 'Custom', v => 'customModule' }, { k => 'Custom', v => 'customModule' },
], ],
[ { k => 'AD', v => 'Active Directory' }, [
{ k => 'CAS', { k => 'AD', v => 'Active Directory' },
{
k => 'CAS',
v => 'Central Authentication Service (CAS)' v => 'Central Authentication Service (CAS)'
}, },
{ k => 'DBI', v => 'Database (DBI)' }, { k => 'DBI', v => 'Database (DBI)' },
@ -2896,7 +2899,8 @@ sub attributes {
{ k => 'WebID', v => 'WebID' }, { k => 'WebID', v => 'WebID' },
{ k => 'Custom', v => 'customModule' }, { k => 'Custom', v => 'customModule' },
], ],
[ { k => 'AD', v => 'Active Directory' }, [
{ k => 'AD', v => 'Active Directory' },
{ k => 'DBI', v => 'Database (DBI)' }, { k => 'DBI', v => 'Database (DBI)' },
{ k => 'Demo', v => 'Demo' }, { k => 'Demo', v => 'Demo' },
{ k => 'LDAP', v => 'LDAP' }, { k => 'LDAP', v => 'LDAP' },
@ -2916,7 +2920,7 @@ sub attributes {
combModules => { combModules => {
type => 'cmbModuleContainer', type => 'cmbModuleContainer',
keyTest => qr/^\w+$/, keyTest => qr/^\w+$/,
test => sub {1}, test => sub { 1 },
documentation => 'Combination module description', documentation => 'Combination module description',
select => [ select => [
{ k => 'Apache', v => 'Apache' }, { k => 'Apache', v => 'Apache' },
@ -3045,8 +3049,7 @@ sub attributes {
'loa-4' => 4, 'loa-4' => 4,
'loa-5' => 5, 'loa-5' => 5,
}, },
documentation => documentation => 'OpenID Connect Authentication Context Class Ref',
'OpenID Connect Authentication Context Class Ref',
}, },
oidcServicePrivateKeySig => { type => 'RSAPrivateKey', }, oidcServicePrivateKeySig => { type => 'RSAPrivateKey', },
oidcServicePublicKeySig => { type => 'RSAPublicKey', }, oidcServicePublicKeySig => { type => 'RSAPublicKey', },
@ -3057,8 +3060,7 @@ sub attributes {
oidcServiceAllowDynamicRegistration => { oidcServiceAllowDynamicRegistration => {
type => 'bool', type => 'bool',
default => 0, default => 0,
documentation => documentation => 'OpenID Connect allow dynamic client registration',
'OpenID Connect allow dynamic client registration',
}, },
oidcServiceAllowAuthorizationCodeFlow => { oidcServiceAllowAuthorizationCodeFlow => {
type => 'bool', type => 'bool',
@ -3088,7 +3090,7 @@ sub attributes {
oidcOPMetaDataNodes => { oidcOPMetaDataNodes => {
type => 'oidcOPMetaDataNodeContainer', type => 'oidcOPMetaDataNodeContainer',
help => help =>
'authopenidconnect.html#declare_the_openid_connect_provider_in_llng', 'authopenidconnect.html#declare_the_openid_connect_provider_in_llng',
}, },
oidcRPMetaDataNodes => { oidcRPMetaDataNodes => {
type => 'oidcRPMetaDataNodeContainer', type => 'oidcRPMetaDataNodeContainer',
@ -3141,8 +3143,7 @@ sub attributes {
}, },
oidcOPMetaDataOptionsCheckJWTSignature => oidcOPMetaDataOptionsCheckJWTSignature =>
{ type => 'bool', default => 1 }, { type => 'bool', default => 1 },
oidcOPMetaDataOptionsIDTokenMaxAge => oidcOPMetaDataOptionsIDTokenMaxAge => { type => 'int', default => 30 },
{ type => 'int', default => 30 },
oidcOPMetaDataOptionsUseNonce => { type => 'bool', default => 1 }, oidcOPMetaDataOptionsUseNonce => { type => 'bool', default => 1 },
oidcOPMetaDataOptionsDisplayName => { type => 'text', }, oidcOPMetaDataOptionsDisplayName => { type => 'text', },
oidcOPMetaDataOptionsIcon => { type => 'text', }, oidcOPMetaDataOptionsIcon => { type => 'text', },

View File

@ -763,11 +763,12 @@ sub _scanNodes {
foreach my $n (@$subNodes) { foreach my $n (@$subNodes) {
hdebug(" looking at $n subnode"); hdebug(" looking at $n subnode");
if ( ref $n->{data} and ref $n->{data} eq 'ARRAY' ) { if ( ref $n->{data} and ref $n->{data} eq 'ARRAY' ) {
# authChoiceModules # authChoiceModules
if ( $name eq 'authChoiceModules' ) { if ( $name eq 'authChoiceModules' ) {
hdebug(' combModules'); hdebug(' combModules');
$n->{data}->[5] ||= {}; $n->{data}->[5] ||= {};
$n->{data}->[5] = to_json($n->{data}->[5]); $n->{data}->[5] = to_json( $n->{data}->[5] );
} }
$n->{data} = join ';', @{ $n->{data} }; $n->{data} = join ';', @{ $n->{data} };

View File

@ -30,7 +30,8 @@ sub tests {
portalIsInDomain => sub { portalIsInDomain => sub {
return ( return (
1, 1,
( index( $conf->{portal}, $conf->{domain} ) > 0 (
index( $conf->{portal}, $conf->{domain} ) > 0
? '' ? ''
: "Portal seems not to be in the domain $conf->{domain}" : "Portal seems not to be in the domain $conf->{domain}"
) )
@ -60,7 +61,8 @@ sub tests {
} }
return ( return (
1, 1,
( @pb (
@pb
? 'Virtual hosts ' ? 'Virtual hosts '
. join( ', ', @pb ) . join( ', ', @pb )
. " are not in $conf->{domain} and cross-domain-authentication is not set" . " are not in $conf->{domain} and cross-domain-authentication is not set"
@ -105,9 +107,9 @@ sub tests {
my $type (qw(Facebook Google OpenID OpenIDConnect SAML WebID)) my $type (qw(Facebook Google OpenID OpenIDConnect SAML WebID))
{ {
return ( 0, return ( 0,
"\"$type\" can not be used as user database without using \"$type\" for authentication" "\"$type\" can not be used as user database without using \"$type\" for authentication"
) )
if ($conf->{userDB} =~ /$type/ if ( $conf->{userDB} =~ /$type/
and $conf->{authentication} !~ /$type/ ); and $conf->{authentication} !~ /$type/ );
} }
return 1; return 1;
@ -117,8 +119,8 @@ sub tests {
checkAttrAndMacros => sub { checkAttrAndMacros => sub {
my @tmp; my @tmp;
foreach my $k ( keys %$conf ) { foreach my $k ( keys %$conf ) {
if ( $k if ( $k =~
=~ /^(?:openIdSreg_(?:(?:(?:full|nick)nam|languag|postcod|timezon)e|country|gender|email|dob)|whatToTrace)$/ /^(?:openIdSreg_(?:(?:(?:full|nick)nam|languag|postcod|timezon)e|country|gender|email|dob)|whatToTrace)$/
) )
{ {
my $v = $conf->{$k}; my $v = $conf->{$k};
@ -136,7 +138,8 @@ sub tests {
} }
return ( return (
1, 1,
( @tmp (
@tmp
? 'Values of parameter(s) "' ? 'Values of parameter(s) "'
. join( ', ', @tmp ) . join( ', ', @tmp )
. '" are not defined in exported attributes or macros' . '" are not defined in exported attributes or macros'
@ -151,15 +154,15 @@ sub tests {
if ( $conf->{userDB} =~ /^Google$/ ) { if ( $conf->{userDB} =~ /^Google$/ ) {
foreach my $k ( keys %{ $conf->{exportedVars} } ) { foreach my $k ( keys %{ $conf->{exportedVars} } ) {
my $v = $conf->{exportedVars}->{$k}; my $v = $conf->{exportedVars}->{$k};
if ( $v !~ Lemonldap::NG::Common::Regexp::GOOGLEAXATTR() ) if ( $v !~ Lemonldap::NG::Common::Regexp::GOOGLEAXATTR() ) {
{
push @tmp, $v; push @tmp, $v;
} }
} }
} }
return ( return (
1, 1,
( @tmp (
@tmp
? 'Values of parameter(s) "' ? 'Values of parameter(s) "'
. join( ', ', @tmp ) . join( ', ', @tmp )
. '" are not exported by Google' . '" are not exported by Google'
@ -174,8 +177,7 @@ sub tests {
if ( $conf->{userDB} =~ /^OpenID$/ ) { if ( $conf->{userDB} =~ /^OpenID$/ ) {
foreach my $k ( keys %{ $conf->{exportedVars} } ) { foreach my $k ( keys %{ $conf->{exportedVars} } ) {
my $v = $conf->{exportedVars}->{$k}; my $v = $conf->{exportedVars}->{$k};
if ( $v if ( $v !~ Lemonldap::NG::Common::Regexp::OPENIDSREGATTR() )
!~ Lemonldap::NG::Common::Regexp::OPENIDSREGATTR() )
{ {
push @tmp, $v; push @tmp, $v;
} }
@ -183,7 +185,8 @@ sub tests {
} }
return ( return (
1, 1,
( @tmp (
@tmp
? 'Values of parameter(s) "' ? 'Values of parameter(s) "'
. join( ', ', @tmp ) . join( ', ', @tmp )
. '" are not exported by OpenID SREG' . '" are not exported by OpenID SREG'
@ -195,12 +198,12 @@ sub tests {
# Try to use Apache::Session module # Try to use Apache::Session module
testApacheSession => sub { testApacheSession => sub {
my ( $id, %h ); my ( $id, %h );
my $gc = $Lemonldap::NG::Handler::PSGI::Main::tsv my $gc =
->{sessionStorageModule}; $Lemonldap::NG::Handler::PSGI::Main::tsv->{sessionStorageModule};
return 1 return 1
if ( ( $gc and $gc eq $conf->{globalStorage} ) if ( ( $gc and $gc eq $conf->{globalStorage} )
or $conf->{globalStorage} or $conf->{globalStorage} =~
=~ /^Lemonldap::NG::Common::Apache::Session::/ ); /^Lemonldap::NG::Common::Apache::Session::/ );
eval "use $conf->{globalStorage}"; eval "use $conf->{globalStorage}";
return ( -1, "Unknown package $conf->{globalStorage}" ) if ($@); return ( -1, "Unknown package $conf->{globalStorage}" ) if ($@);
eval { eval {
@ -228,7 +231,7 @@ sub tests {
eval { tied(%h)->delete; }; eval { tied(%h)->delete; };
return ( -1, "Unable to delete session ($@)" ) if ($@); return ( -1, "Unable to delete session ($@)" ) if ($@);
return ( -1, return ( -1,
'All sessions may be lost and you must restart all your Apache servers' 'All sessions may be lost and you must restart all your Apache servers'
) if ( $gc and $conf->{globalStorage} ne $gc ); ) if ( $gc and $conf->{globalStorage} ne $gc );
return 1; return 1;
}, },
@ -238,7 +241,8 @@ sub tests {
my $cn = $Lemonldap::NG::Handler::PSGI::API::tsv->{cookieName}; my $cn = $Lemonldap::NG::Handler::PSGI::API::tsv->{cookieName};
return ( return (
1, 1,
( $cn (
$cn
and $cn ne $conf->{cookieName} and $cn ne $conf->{cookieName}
? 'Cookie name has changed, you must restart all your web servers' ? 'Cookie name has changed, you must restart all your web servers'
: () : ()
@ -263,7 +267,8 @@ sub tests {
managerProtection => sub { managerProtection => sub {
return ( return (
1, 1,
( $conf->{cfgAuthor} eq 'anonymous' (
$conf->{cfgAuthor} eq 'anonymous'
? 'Your manager seems to be unprotected' ? 'Your manager seems to be unprotected'
: '' : ''
) )
@ -309,8 +314,9 @@ sub tests {
my $res = 1; my $res = 1;
my %entityIds; my %entityIds;
foreach my $idpId ( keys %{ $conf->{samlIDPMetaDataXML} } ) { foreach my $idpId ( keys %{ $conf->{samlIDPMetaDataXML} } ) {
unless ( $conf->{samlIDPMetaDataXML}->{$idpId} unless (
->{samlIDPMetaDataXML} =~ /entityID=(['"])(.+?)\1/si ) $conf->{samlIDPMetaDataXML}->{$idpId}->{samlIDPMetaDataXML}
=~ /entityID=(['"])(.+?)\1/si )
{ {
push @msg, "$idpId SAML metadata has no EntityID"; push @msg, "$idpId SAML metadata has no EntityID";
$res = 0; $res = 0;
@ -336,8 +342,8 @@ sub tests {
my %entityIds; my %entityIds;
foreach my $spId ( keys %{ $conf->{samlSPMetaDataXML} } ) { foreach my $spId ( keys %{ $conf->{samlSPMetaDataXML} } ) {
unless ( unless (
$conf->{samlSPMetaDataXML}->{$spId}->{samlSPMetaDataXML} $conf->{samlSPMetaDataXML}->{$spId}->{samlSPMetaDataXML} =~
=~ /entityID=(['"])(.+?)\1/si ) /entityID=(['"])(.+?)\1/si )
{ {
push @msg, "$spId SAML metadata has no EntityID"; push @msg, "$spId SAML metadata has no EntityID";
$res = 0; $res = 0;
@ -371,8 +377,8 @@ sub tests {
); );
} }
eval { eval {
Lemonldap::NG::Common::Combination::Parser->parse( Lemonldap::NG::Common::Combination::Parser->parse( $moduleList,
$moduleList, $conf->{combination} ); $conf->{combination} );
}; };
return ( 0, $@ ) if ($@); return ( 0, $@ ) if ($@);
@ -406,7 +412,7 @@ sub tests {
{ {
eval "use Crypt::U2F::Server::Simple"; eval "use Crypt::U2F::Server::Simple";
return ( 1, return ( 1,
"Crypt::U2F::Server::Simple module is required to enable U2F" "Crypt::U2F::Server::Simple module is required to enable U2F"
) if ($@); ) if ($@);
} }
@ -414,7 +420,7 @@ sub tests {
if ( $conf->{yubikey2fActivation} ) { if ( $conf->{yubikey2fActivation} ) {
eval "use Auth::Yubikey_WebClient"; eval "use Auth::Yubikey_WebClient";
return ( 1, return ( 1,
"Auth::Yubikey_WebClient module is required to enable Yubikey" "Auth::Yubikey_WebClient module is required to enable Yubikey"
) if ($@); ) if ($@);
} }
@ -439,7 +445,9 @@ sub tests {
return 1 unless ( defined $conf->{totp2fDigits} ); return 1 unless ( defined $conf->{totp2fDigits} );
return ( return (
1, 1,
( ( $conf->{totp2fDigits} == 6 (
(
$conf->{totp2fDigits} == 6
or $conf->{totp2fDigits} == 8 or $conf->{totp2fDigits} == 8
) )
? '' ? ''
@ -469,7 +477,8 @@ sub tests {
&& defined $conf->{yubikey2fClientID} ); && defined $conf->{yubikey2fClientID} );
return ( return (
1, 1,
( ( $conf->{yubikey2fPublicIDSize} == 12 ) (
( $conf->{yubikey2fPublicIDSize} == 12 )
? '' ? ''
: 'Yubikey public ID size should be 12 digits long' : 'Yubikey public ID size should be 12 digits long'
) )
@ -501,8 +510,7 @@ sub tests {
$ok ||= $conf->{'utotp2fActivation'} $ok ||= $conf->{'utotp2fActivation'}
&& ( $conf->{'u2fSelfRegistration'} && ( $conf->{'u2fSelfRegistration'}
|| $conf->{'totp2fSelfRegistration'} ); || $conf->{'totp2fSelfRegistration'} );
$msg $msg = "A self registrable module should be enabled to require 2FA"
= "A self registrable module should be enabled to require 2FA"
unless ($ok); unless ($ok);
return ( 1, $msg ); return ( 1, $msg );

View File

@ -35,8 +35,8 @@ has sfReq => ( is => 'rw' );
has ott => ( has ott => (
is => 'rw', is => 'rw',
default => sub { default => sub {
my $ott = $_[0]->{p} my $ott =
->loadModule('Lemonldap::NG::Portal::Lib::OneTimeToken'); $_[0]->{p}->loadModule('Lemonldap::NG::Portal::Lib::OneTimeToken');
$ott->timeout( $_[0]->{conf}->{formTimeout} ); $ott->timeout( $_[0]->{conf}->{formTimeout} );
return $ott; return $ott;
} }
@ -49,9 +49,11 @@ sub init {
for my $i ( 0 .. 1 ) { for my $i ( 0 .. 1 ) {
foreach ( foreach (
split /,\s*/, split /,\s*/,
$self->conf->{ $i $self->conf->{
$i
? 'available2FSelfRegistration' ? 'available2FSelfRegistration'
: 'available2F' } : 'available2F'
}
) )
{ {
my $prefix = lc($_); my $prefix = lc($_);
@ -64,9 +66,8 @@ sub init {
# Unless $rule, skip loading # Unless $rule, skip loading
if ( $self->conf->{$ap} ) { if ( $self->conf->{$ap} ) {
$self->logger->debug("Trying to load $_ 2F"); $self->logger->debug("Trying to load $_ 2F");
my $m my $m =
= $self->p->loadPlugin( $self->p->loadPlugin( $i ? "::2F::Register::$_" : "::2F::$_" )
$i ? "::2F::Register::$_" : "::2F::$_" )
or return 0; or return 0;
# Rule and prefix may be modified by 2F module, reread them # Rule and prefix may be modified by 2F module, reread them
@ -161,14 +162,14 @@ sub run {
if ( $self->sfReq->( $req, $req->sessionInfo ) ) { if ( $self->sfReq->( $req, $req->sessionInfo ) ) {
$self->logger->debug("2F is required..."); $self->logger->debug("2F is required...");
$self->logger->debug(" -> Register 2F"); $self->logger->debug(" -> Register 2F");
$req->pdata->{sfRegToken} $req->pdata->{sfRegToken} =
= $self->ott->createToken( $req->sessionInfo ); $self->ott->createToken( $req->sessionInfo );
$self->logger->debug("Just one 2F is enabled"); $self->logger->debug("Just one 2F is enabled");
$self->logger->debug(" -> Redirect to /2fregisters/"); $self->logger->debug(" -> Redirect to /2fregisters/");
$req->response( $req->response(
[ 302, [
[ Location => $self->conf->{portal} . '/2fregisters/' ], 302,
[] [ Location => $self->conf->{portal} . '/2fregisters/' ], []
] ]
); );
return PE_SENDRESPONSE; return PE_SENDRESPONSE;
@ -203,8 +204,7 @@ sub run {
params => { params => {
SKIN => $self->conf->{portalSkin}, SKIN => $self->conf->{portalSkin},
TOKEN => $token, TOKEN => $token,
MODULES => MODULES => [ map { { CODE => $_->prefix, LOGO => $_->logo } } @am ],
[ map { { CODE => $_->prefix, LOGO => $_->logo } } @am ],
CHECKLOGINS => $checkLogins CHECKLOGINS => $checkLogins
} }
); );
@ -230,16 +230,15 @@ sub _choice {
# Restore session # Restore session
unless ( $token = $req->param('token') ) { unless ( $token = $req->param('token') ) {
$self->userLogger->error( $self->userLogger->error( $self->prefix . ' 2F access without token' );
$self->prefix . ' 2F access without token' );
$req->mustRedirect(1); $req->mustRedirect(1);
return $self->p->do( $req, [ sub {PE_NOTOKEN} ] ); return $self->p->do( $req, [ sub { PE_NOTOKEN } ] );
} }
my $session; my $session;
unless ( $session = $self->ott->getToken($token) ) { unless ( $session = $self->ott->getToken($token) ) {
$self->userLogger->info('Token expired'); $self->userLogger->info('Token expired');
return $self->p->do( $req, [ sub {PE_TOKENEXPIRED} ] ); return $self->p->do( $req, [ sub { PE_TOKENEXPIRED } ] );
} }
$req->sessionInfo($session); $req->sessionInfo($session);
@ -254,7 +253,8 @@ sub _choice {
$req->authResult($res); $req->authResult($res);
return $self->p->do( return $self->p->do(
$req, $req,
[ sub {$res}, 'controlUrl', [
sub { $res }, 'controlUrl',
'buildCookie', @{ $self->p->endAuth }, 'buildCookie', @{ $self->p->endAuth },
] ]
); );
@ -269,8 +269,7 @@ sub _redirect {
my $arg = $req->env->{QUERY_STRING}; my $arg = $req->env->{QUERY_STRING};
$self->logger->debug('Call sfEngine _redirect method'); $self->logger->debug('Call sfEngine _redirect method');
return [ return [
302, [ Location => $self->conf->{portal} . ( $arg ? "?$arg" : '' ) ], 302, [ Location => $self->conf->{portal} . ( $arg ? "?$arg" : '' ) ], []
[]
]; ];
} }
@ -308,17 +307,16 @@ sub _displayRegister {
} }
} }
if ( @am == 1 if ( @am == 1
and and not( $req->userData->{_2fDevices} or $req->data->{sfRegRequired} ) )
not( $req->userData->{_2fDevices} or $req->data->{sfRegRequired} ) )
{ {
return [ 302, [ Location => $self->conf->{portal} . $am[0]->{URL} ], return [ 302, [ Location => $self->conf->{portal} . $am[0]->{URL} ],
[] ]; [] ];
} }
my $_2fDevices = $req->userData->{_2fDevices} my $_2fDevices =
$req->userData->{_2fDevices}
? eval { ? eval {
from_json( $req->userData->{_2fDevices}, { allow_nonref => 1 } ); from_json( $req->userData->{_2fDevices}, { allow_nonref => 1 } ); }
}
: undef; : undef;
unless ($_2fDevices) { unless ($_2fDevices) {

View File

@ -39,7 +39,8 @@ sub run {
$self->logger->debug("Ext2F checkLogins set") if ($checkLogins); $self->logger->debug("Ext2F checkLogins set") if ($checkLogins);
# Prepare command and launch it # Prepare command and launch it
$self->logger->debug('Launching "Send" external 2F command -> ' . $self->conf->{ext2FSendCommand}); $self->logger->debug( 'Launching "Send" external 2F command -> '
. $self->conf->{ext2FSendCommand} );
if ( my $c = if ( my $c =
$self->launch( $req->sessionInfo, $self->conf->{ext2FSendCommand} ) ) $self->launch( $req->sessionInfo, $self->conf->{ext2FSendCommand} ) )
{ {
@ -72,7 +73,8 @@ sub verify {
} }
# Prepare command and launch it # Prepare command and launch it
$self->logger->debug('Launching "Validate" external 2F command -> ' . $self->conf->{ext2FValidateCommand}); $self->logger->debug( 'Launching "Validate" external 2F command -> '
. $self->conf->{ext2FValidateCommand} );
$self->logger->debug(" code -> $code"); $self->logger->debug(" code -> $code");
if ( my $c = if ( my $c =
$self->launch( $session, $self->conf->{ext2FValidateCommand}, $code ) ) $self->launch( $session, $self->conf->{ext2FValidateCommand}, $code ) )

View File

@ -7,7 +7,8 @@ use JSON qw(from_json to_json);
our $VERSION = '2.0.0'; our $VERSION = '2.0.0';
extends 'Lemonldap::NG::Portal::Main::Plugin', 'Lemonldap::NG::Portal::Lib::U2F'; extends 'Lemonldap::NG::Portal::Main::Plugin',
'Lemonldap::NG::Portal::Lib::U2F';
# INITIALIZATION # INITIALIZATION

View File

@ -16,8 +16,7 @@ sub displayInit {
my ($self) = @_; my ($self) = @_;
$self->skinRules( [] ); $self->skinRules( [] );
if ( $self->conf->{portalSkinRules} ) { if ( $self->conf->{portalSkinRules} ) {
foreach my $skinRule ( sort keys %{ $self->conf->{portalSkinRules} } ) foreach my $skinRule ( sort keys %{ $self->conf->{portalSkinRules} } ) {
{
my $sub = HANDLER->buildSub( HANDLER->substitute($skinRule) ); my $sub = HANDLER->buildSub( HANDLER->substitute($skinRule) );
if ($sub) { if ($sub) {
push @{ $self->skinRules }, push @{ $self->skinRules },
@ -55,7 +54,8 @@ sub display {
AUTH_URL => $req->{data}->{_url}, AUTH_URL => $req->{data}->{_url},
CHOICE_PARAM => $self->conf->{authChoiceParam}, CHOICE_PARAM => $self->conf->{authChoiceParam},
CHOICE_VALUE => $req->data->{_authChoice}, CHOICE_VALUE => $req->data->{_authChoice},
( $req->data->{customScript} (
$req->data->{customScript}
? ( CUSTOM_SCRIPT => $req->data->{customScript} ) ? ( CUSTOM_SCRIPT => $req->data->{customScript} )
: () : ()
), ),
@ -83,7 +83,8 @@ sub display {
ASK_LOGINS => $req->param('checkLogins') || 0, ASK_LOGINS => $req->param('checkLogins') || 0,
CONFIRMKEY => $self->stamp(), CONFIRMKEY => $self->stamp(),
REMEMBER => $req->data->{confirmRemember}, REMEMBER => $req->data->{confirmRemember},
( $req->data->{customScript} (
$req->data->{customScript}
? ( CUSTOM_SCRIPT => $req->data->{customScript} ) ? ( CUSTOM_SCRIPT => $req->data->{customScript} )
: () : ()
), ),
@ -111,7 +112,8 @@ sub display {
CONFIRMKEY => $self->stamp(), CONFIRMKEY => $self->stamp(),
LIST => $req->data->{list} || [], LIST => $req->data->{list} || [],
REMEMBER => $req->data->{confirmRemember}, REMEMBER => $req->data->{confirmRemember},
( $req->data->{customScript} (
$req->data->{customScript}
? ( CUSTOM_SCRIPT => $req->data->{customScript} ) ? ( CUSTOM_SCRIPT => $req->data->{customScript} )
: () : ()
), ),
@ -135,7 +137,8 @@ sub display {
FORM_METHOD => $self->conf->{infoFormMethod}, FORM_METHOD => $self->conf->{infoFormMethod},
CHOICE_PARAM => $self->conf->{authChoiceParam}, CHOICE_PARAM => $self->conf->{authChoiceParam},
CHOICE_VALUE => $req->data->{_authChoice}, CHOICE_VALUE => $req->data->{_authChoice},
( $req->data->{customScript} (
$req->data->{customScript}
? ( CUSTOM_SCRIPT => $req->data->{customScript} ) ? ( CUSTOM_SCRIPT => $req->data->{customScript} )
: () : ()
), ),
@ -157,7 +160,8 @@ sub display {
AUTH_ERROR_TYPE => $req->error_type, AUTH_ERROR_TYPE => $req->error_type,
PROVIDERURI => $p, PROVIDERURI => $p,
MSG => $req->info(), MSG => $req->info(),
( $req->data->{customScript} (
$req->data->{customScript}
? ( CUSTOM_SCRIPT => $req->data->{customScript} ) ? ( CUSTOM_SCRIPT => $req->data->{customScript} )
: () : ()
), ),
@ -174,7 +178,8 @@ sub display {
URL => $req->{urldc}, URL => $req->{urldc},
HIDDEN_INPUTS => $self->buildHiddenForm($req), HIDDEN_INPUTS => $self->buildHiddenForm($req),
FORM_METHOD => $req->data->{redirectFormMethod} || 'get', FORM_METHOD => $req->data->{redirectFormMethod} || 'get',
( $req->data->{customScript} (
$req->data->{customScript}
? ( CUSTOM_SCRIPT => $req->data->{customScript} ) ? ( CUSTOM_SCRIPT => $req->data->{customScript} )
: () : ()
), ),
@ -188,8 +193,7 @@ sub display {
#utf8::decode($auth_user); #utf8::decode($auth_user);
%templateParams = ( %templateParams = (
MAIN_LOGO => $self->conf->{portalMainLogo}, MAIN_LOGO => $self->conf->{portalMainLogo},
AUTH_USER => AUTH_USER => $req->{sessionInfo}->{ $self->conf->{portalUserAttr} },
$req->{sessionInfo}->{ $self->conf->{portalUserAttr} },
NEWWINDOW => $self->conf->{portalOpenLinkInNewWindow}, NEWWINDOW => $self->conf->{portalOpenLinkInNewWindow},
LOGOUT_URL => $self->conf->{portal} . "?logout=1", LOGOUT_URL => $self->conf->{portal} . "?logout=1",
APPSLIST_ORDER => $req->{sessionInfo}->{'_appsListOrder'}, APPSLIST_ORDER => $req->{sessionInfo}->{'_appsListOrder'},
@ -197,7 +201,8 @@ sub display {
REQUIRE_OLDPASSWORD => $self->conf->{portalRequireOldPassword}, REQUIRE_OLDPASSWORD => $self->conf->{portalRequireOldPassword},
HIDE_OLDPASSWORD => 0, HIDE_OLDPASSWORD => 0,
$self->menu->params($req), $self->menu->params($req),
( $req->data->{customScript} (
$req->data->{customScript}
? ( CUSTOM_SCRIPT => $req->data->{customScript} ) ? ( CUSTOM_SCRIPT => $req->data->{customScript} )
: () : ()
), ),
@ -212,7 +217,8 @@ sub display {
CONFIRMKEY => $self->stamp, CONFIRMKEY => $self->stamp,
PORTAL => $self->conf->{portal}, PORTAL => $self->conf->{portal},
URL => $req->data->{_url}, URL => $req->data->{_url},
( $req->data->{customScript} (
$req->data->{customScript}
? ( CUSTOM_SCRIPT => $req->data->{customScript} ) ? ( CUSTOM_SCRIPT => $req->data->{customScript} )
: () : ()
), ),
@ -227,7 +233,8 @@ sub display {
CONFIRMKEY => $self->stamp, CONFIRMKEY => $self->stamp,
PORTAL => $self->conf->{portal}, PORTAL => $self->conf->{portal},
URL => $req->data->{_url}, URL => $req->data->{_url},
( $req->data->{customScript} (
$req->data->{customScript}
? ( CUSTOM_SCRIPT => $req->data->{customScript} ) ? ( CUSTOM_SCRIPT => $req->data->{customScript} )
: () : ()
), ),
@ -247,7 +254,8 @@ sub display {
MAIN_LOGO => $self->conf->{portalMainLogo}, MAIN_LOGO => $self->conf->{portalMainLogo},
AUTH_ERROR => $req->error, AUTH_ERROR => $req->error,
AUTH_ERROR_TYPE => $req->error_type, AUTH_ERROR_TYPE => $req->error_type,
( $req->data->{customScript} (
$req->data->{customScript}
? ( CUSTOM_SCRIPT => $req->data->{customScript} ) ? ( CUSTOM_SCRIPT => $req->data->{customScript} )
: () : ()
), ),
@ -267,14 +275,14 @@ sub display {
LOGIN => $login, LOGIN => $login,
CHECK_LOGINS => $self->conf->{portalCheckLogins}, CHECK_LOGINS => $self->conf->{portalCheckLogins},
ASK_LOGINS => $req->param('checkLogins') || 0, ASK_LOGINS => $req->param('checkLogins') || 0,
DISPLAY_RESETPASSWORD => DISPLAY_RESETPASSWORD => $self->conf->{portalDisplayResetPassword},
$self->conf->{portalDisplayResetPassword},
DISPLAY_REGISTER => $self->conf->{portalDisplayRegister}, DISPLAY_REGISTER => $self->conf->{portalDisplayRegister},
MAIL_URL => $self->conf->{mailUrl}, MAIL_URL => $self->conf->{mailUrl},
REGISTER_URL => $self->conf->{registerUrl}, REGISTER_URL => $self->conf->{registerUrl},
HIDDEN_INPUTS => $self->buildHiddenForm($req), HIDDEN_INPUTS => $self->buildHiddenForm($req),
STAYCONNECTED => $self->conf->{stayConnected}, STAYCONNECTED => $self->conf->{stayConnected},
( $req->data->{customScript} (
$req->data->{customScript}
? ( CUSTOM_SCRIPT => $req->data->{customScript} ) ? ( CUSTOM_SCRIPT => $req->data->{customScript} )
: () : ()
), ),
@ -368,8 +376,8 @@ sub display {
# Choose what form to display if not in a loop # Choose what form to display if not in a loop
else { else {
my $displayType my $displayType =
= eval { $self->_authentication->getDisplayType($req) }; eval { $self->_authentication->getDisplayType($req) };
$self->logger->debug("Display type $displayType "); $self->logger->debug("Display type $displayType ");
@ -377,8 +385,7 @@ sub display {
%templateParams, %templateParams,
DISPLAY_FORM => $displayType =~ /\bstandardform\b/ ? 1 DISPLAY_FORM => $displayType =~ /\bstandardform\b/ ? 1
: 0, : 0,
DISPLAY_OPENID_FORM => $displayType =~ /\bopenidform\b/ DISPLAY_OPENID_FORM => $displayType =~ /\bopenidform\b/ ? 1
? 1
: 0, : 0,
DISPLAY_YUBIKEY_FORM => $displayType =~ /\byubikeyform\b/ DISPLAY_YUBIKEY_FORM => $displayType =~ /\byubikeyform\b/
? 1 ? 1
@ -389,9 +396,8 @@ sub display {
? $self->getModule( $req, 'auth' ) ? $self->getModule( $req, 'auth' )
: "", : "",
AUTH_LOOP => [], AUTH_LOOP => [],
PORTAL_URL => ( PORTAL_URL =>
$displayType eq "logo" ? $self->conf->{portal} : 0 ( $displayType eq "logo" ? $self->conf->{portal} : 0 ),
),
MSG => $req->info(), MSG => $req->info(),
); );
@ -402,8 +408,8 @@ sub display {
} }
# Additional $req param # Additional $req param
%templateParams %templateParams =
= ( %templateParams, %{ $req->{customParameters} // {} }, ); ( %templateParams, %{ $req->{customParameters} // {} }, );
$self->logger->debug("Skin returned: $skinfile"); $self->logger->debug("Skin returned: $skinfile");
return ( $skinfile, \%templateParams ); return ( $skinfile, \%templateParams );
@ -419,16 +425,15 @@ sub staticFile {
require Plack::Util; require Plack::Util;
require Cwd; require Cwd;
require HTTP::Date; require HTTP::Date;
open my $fh, '<:raw', open my $fh, '<:raw', $self->conf->{templatesDir} . "/$file"
$self->conf->{templatesDir}
. "/$file"
or return $self->sendError( $req, or return $self->sendError( $req,
$self->conf->{templatesDir} . "/$file: $!", 403 ); $self->conf->{templatesDir} . "/$file: $!", 403 );
my @stat = stat $file; my @stat = stat $file;
Plack::Util::set_io_path( $fh, Cwd::realpath($file) ); Plack::Util::set_io_path( $fh, Cwd::realpath($file) );
return [ return [
200, 200,
[ 'Content-Type' => $type, [
'Content-Type' => $type,
'Content-Length' => $stat[7], 'Content-Length' => $stat[7],
'Last-Modified' => HTTP::Date::time2str( $stat[9] ) 'Last-Modified' => HTTP::Date::time2str( $stat[9] )
], ],
@ -445,8 +450,7 @@ sub buildHiddenForm {
# Check XSS attacks # Check XSS attacks
next next
if $self->checkXSSAttack( $_, if $self->checkXSSAttack( $_, $req->{portalHiddenFormValues}->{$_} );
$req->{portalHiddenFormValues}->{$_} );
# Build hidden input HTML code # Build hidden input HTML code
$val .= qq{<input type="hidden" name="$_" id="$_" value="} $val .= qq{<input type="hidden" name="$_" id="$_" value="}
@ -526,7 +530,8 @@ sub mkSessionArray {
sessions => [ sessions => [
map { map {
my $session = $_; my $session = $_;
{ user => $session->{user}, {
user => $session->{user},
utime => $session->{_utime}, utime => $session->{_utime},
ip => $session->{ipAddr}, ip => $session->{ipAddr},
values => [ map { { v => $session->{$_} } } @fields ], values => [ map { { v => $session->{$_} } } @fields ],
@ -574,8 +579,8 @@ sub mkOidcConsent {
$self->logger->debug("RP { $rp } Consent found"); $self->logger->debug("RP { $rp } Consent found");
$consents->{$rp}->{epoch} = $_->{epoch}; $consents->{$rp}->{epoch} = $_->{epoch};
$consents->{$rp}->{scope} = $_->{scope}; $consents->{$rp}->{scope} = $_->{scope};
$consents->{$rp}->{displayName} $consents->{$rp}->{displayName} =
= $self->conf->{oidcRPMetaDataOptions}->{$rp} $self->conf->{oidcRPMetaDataOptions}->{$rp}
->{oidcRPMetaDataOptionsDisplayName}; ->{oidcRPMetaDataOptionsDisplayName};
} }
} }
@ -586,7 +591,8 @@ sub mkOidcConsent {
params => { params => {
partners => [ partners => [
map { map {
{ name => $_, {
name => $_,
epoch => $consents->{$_}->{epoch}, epoch => $consents->{$_}->{epoch},
scope => $consents->{$_}->{scope}, scope => $consents->{$_}->{scope},
displayName => $consents->{$_}->{displayName} displayName => $consents->{$_}->{displayName}

View File

@ -84,7 +84,8 @@ sub init {
my ( $self, $args ) = @_; my ( $self, $args ) = @_;
$args ||= {}; $args ||= {};
$self->localConfig( $self->localConfig(
{ %{ Lemonldap::NG::Common::Conf->new( $args->{configStorage} ) {
%{ Lemonldap::NG::Common::Conf->new( $args->{configStorage} )
->getLocalConf('portal') ->getLocalConf('portal')
}, },
%$args %$args
@ -169,8 +170,8 @@ sub reloadConf {
$self->csp($csp); $self->csp($csp);
# Initialize templateDir # Initialize templateDir
$self->{templateDir} $self->{templateDir} =
= $self->conf->{templateDir} . '/' . $self->conf->{portalSkin}; $self->conf->{templateDir} . '/' . $self->conf->{portalSkin};
unless ( -d $self->{templateDir} ) { unless ( -d $self->{templateDir} ) {
$self->error("Template dir $self->{templateDir} doesn't exist"); $self->error("Template dir $self->{templateDir} doesn't exist");
return $self->fail; return $self->fail;
@ -190,8 +191,8 @@ sub reloadConf {
# Initialize persistent session DB # Initialize persistent session DB
unless ( $self->conf->{persistentStorage} ) { unless ( $self->conf->{persistentStorage} ) {
$self->conf->{persistentStorage} = $self->conf->{globalStorage}; $self->conf->{persistentStorage} = $self->conf->{globalStorage};
$self->conf->{persistentStorageOptions} $self->conf->{persistentStorageOptions} =
= $self->conf->{globalStorageOptions}; $self->conf->{globalStorageOptions};
} }
# Initialize cookie domain # Initialize cookie domain
@ -226,8 +227,8 @@ sub reloadConf {
# Load second-factor engine # Load second-factor engine
return $self->fail return $self->fail
unless $self->{_sfEngine} unless $self->{_sfEngine} =
= $self->loadPlugin( $self->conf->{'sfEngine'} ); $self->loadPlugin( $self->conf->{'sfEngine'} );
# Initialize trusted domain regexp # Initialize trusted domain regexp
if ( $self->conf->{trustedDomains} if ( $self->conf->{trustedDomains}
@ -250,8 +251,8 @@ sub reloadConf {
# - $domainlabel.$td # - $domainlabel.$td
# $domainlabel is build looking RFC2396 # $domainlabel is build looking RFC2396
# (see Regexp::Common::URI::RFC2396) # (see Regexp::Common::URI::RFC2396)
$_ $_ =~
=~ s/\*\\\./(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9]\\.)*/g; s/\*\\\./(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9]\\.)*/g;
$re->add("$_"); $re->add("$_");
} }
} }
@ -262,8 +263,8 @@ sub reloadConf {
$self->logger->debug("Vhost $vhost added in trusted domains"); $self->logger->debug("Vhost $vhost added in trusted domains");
$re->add( quotemeta($vhost) ); $re->add( quotemeta($vhost) );
$self->conf->{vhostOptions} ||= {}; $self->conf->{vhostOptions} ||= {};
if ( my $tmp if ( my $tmp =
= $self->conf->{vhostOptions}->{$vhost}->{vhostAliases} ) $self->conf->{vhostOptions}->{$vhost}->{vhostAliases} )
{ {
foreach my $alias ( split /\s+/, $tmp ) { foreach my $alias ( split /\s+/, $tmp ) {
$self->logger->debug( $self->logger->debug(
@ -281,7 +282,8 @@ sub reloadConf {
$self->{"_$type"} = {}; $self->{"_$type"} = {};
if ( $self->conf->{$type} ) { if ( $self->conf->{$type} ) {
for my $name ( sort keys %{ $self->conf->{$type} } ) { for my $name ( sort keys %{ $self->conf->{$type} } ) {
my $sub = HANDLER->buildSub( my $sub =
HANDLER->buildSub(
HANDLER->substitute( $self->conf->{$type}->{$name} ) ); HANDLER->substitute( $self->conf->{$type}->{$name} ) );
if ($sub) { if ($sub) {
$self->{"_$type"}->{$name} = $sub; $self->{"_$type"}->{$name} = $sub;
@ -293,9 +295,8 @@ sub reloadConf {
} }
} }
} }
$self->{_jsRedirect} $self->{_jsRedirect} =
= HANDLER->buildSub( HANDLER->buildSub( HANDLER->substitute( $self->conf->{jsRedirect} ) )
HANDLER->substitute( $self->conf->{jsRedirect} ) )
or $self->logger->error( or $self->logger->error(
'jsRedirect returns an error: ' . HANDLER->tsv->{jail}->error ); 'jsRedirect returns an error: ' . HANDLER->tsv->{jail}->error );
@ -361,7 +362,7 @@ sub findEP {
if ( $obj->can('spRules') ) { if ( $obj->can('spRules') ) {
foreach my $k ( keys %{ $obj->{spRules} } ) { foreach my $k ( keys %{ $obj->{spRules} } ) {
$self->logger->info( $self->logger->info(
"$k is defined more than one time, it can have some bad effect on Menu display" "$k is defined more than one time, it can have some bad effect on Menu display"
) if ( $self->spRules->{$k} ); ) if ( $self->spRules->{$k} );
$self->spRules->{$k} = $obj->{spRules}->{$k}; $self->spRules->{$k} = $obj->{spRules}->{$k};
} }

View File

@ -17,7 +17,7 @@ use strict;
use URI::Escape; use URI::Escape;
# List constants # List constants
sub authProcess {qw(extractFormInfo getUser authenticate)} sub authProcess { qw(extractFormInfo getUser authenticate) }
sub sessionData { sub sessionData {
qw(setAuthSessionInfo setSessionInfo setMacros setGroups setPersistentSessionInfo qw(setAuthSessionInfo setSessionInfo setMacros setGroups setPersistentSessionInfo
@ -56,9 +56,11 @@ sub handler {
if ( $sp or %{ $req->pdata } ) { if ( $sp or %{ $req->pdata } ) {
my %v = ( my %v = (
name => $self->conf->{cookieName} . 'pdata', name => $self->conf->{cookieName} . 'pdata',
( %{ $req->pdata } (
%{ $req->pdata }
? ( value => uri_escape( JSON::to_json( $req->pdata ) ) ) ? ( value => uri_escape( JSON::to_json( $req->pdata ) ) )
: ( value => '', : (
value => '',
expires => 'Wed, 21 Oct 2015 00:00:00 GMT' expires => 'Wed, 21 Oct 2015 00:00:00 GMT'
) )
) )
@ -92,7 +94,8 @@ sub login {
my ( $self, $req ) = @_; my ( $self, $req ) = @_;
return $self->do( return $self->do(
$req, $req,
[ 'controlUrl', @{ $self->beforeAuth }, [
'controlUrl', @{ $self->beforeAuth },
$self->authProcess, @{ $self->betweenAuthAndData }, $self->authProcess, @{ $self->betweenAuthAndData },
$self->sessionData, @{ $self->afterData }, $self->sessionData, @{ $self->afterData },
$self->validSession, @{ $self->endAuth }, $self->validSession, @{ $self->endAuth },
@ -104,7 +107,8 @@ sub postLogin {
my ( $self, $req ) = @_; my ( $self, $req ) = @_;
return $self->do( return $self->do(
$req, $req,
[ 'restoreArgs', 'controlUrl', [
'restoreArgs', 'controlUrl',
@{ $self->beforeAuth }, $self->authProcess, @{ $self->beforeAuth }, $self->authProcess,
@{ $self->betweenAuthAndData }, $self->sessionData, @{ $self->betweenAuthAndData }, $self->sessionData,
@{ $self->afterData }, $self->validSession, @{ $self->afterData }, $self->validSession,
@ -117,7 +121,8 @@ sub authenticatedRequest {
my ( $self, $req ) = @_; my ( $self, $req ) = @_;
return $self->do( return $self->do(
$req, $req,
[ 'importHandlerData', 'controlUrl', [
'importHandlerData', 'controlUrl',
'checkLogout', @{ $self->forAuthUser } 'checkLogout', @{ $self->forAuthUser }
] ]
); );
@ -127,7 +132,8 @@ sub postAuthenticatedRequest {
my ( $self, $req ) = @_; my ( $self, $req ) = @_;
return $self->do( return $self->do(
$req, $req,
[ 'importHandlerData', 'restoreArgs', [
'importHandlerData', 'restoreArgs',
'controlUrl', 'checkLogout', 'controlUrl', 'checkLogout',
@{ $self->forAuthUser } @{ $self->forAuthUser }
] ]
@ -145,7 +151,8 @@ sub refresh {
delete $data{$_} unless ( /^_/ or /^(?:startTime)$/ ); delete $data{$_} unless ( /^_/ or /^(?:startTime)$/ );
} }
$req->steps( $req->steps(
[ 'getUser', [
'getUser',
@{ $self->betweenAuthAndData }, @{ $self->betweenAuthAndData },
'setAuthSessionInfo', 'setAuthSessionInfo',
'setSessionInfo', 'setSessionInfo',
@ -163,21 +170,21 @@ sub refresh {
if ($res) { if ($res) {
$req->info( $req->info(
$self->loadTemplate( $self->loadTemplate(
'simpleInfo', 'simpleInfo', params => { trspan => 'rightsReloadNeedsLogout' }
params => { trspan => 'rightsReloadNeedsLogout' }
) )
); );
$req->urldc( $self->conf->{portal} ); $req->urldc( $self->conf->{portal} );
return $self->do( $req, [ sub {PE_INFO} ] ); return $self->do( $req, [ sub { PE_INFO } ] );
} }
return $self->do( $req, [ sub {PE_OK} ] ); return $self->do( $req, [ sub { PE_OK } ] );
} }
sub logout { sub logout {
my ( $self, $req ) = @_; my ( $self, $req ) = @_;
return $self->do( return $self->do(
$req, $req,
[ 'controlUrl', @{ $self->beforeLogout }, [
'controlUrl', @{ $self->beforeLogout },
'authLogout', 'deleteSession' 'authLogout', 'deleteSession'
] ]
); );
@ -194,7 +201,7 @@ sub do {
# Update status # Update status
if ( my $p = $self->HANDLER->tsv->{statusPipe} ) { if ( my $p = $self->HANDLER->tsv->{statusPipe} ) {
$p->print(( $req->user ? $req->user : $req->address ) . ' => ' $p->print( ( $req->user ? $req->user : $req->address ) . ' => '
. $req->uri . $req->uri
. " $err\n" ); . " $err\n" );
} }
@ -208,7 +215,8 @@ sub do {
if ( ( $err > 0 and !$req->id ) or $err eq PE_SESSIONNOTGRANTED ) { if ( ( $err > 0 and !$req->id ) or $err eq PE_SESSIONNOTGRANTED ) {
return [ return [
401, 401,
[ 'WWW-Authenticate' => "SSO " . $self->conf->{portal}, [
'WWW-Authenticate' => "SSO " . $self->conf->{portal},
'Access-Control-Allow-Origin' => '*' 'Access-Control-Allow-Origin' => '*'
], ],
[qq'{"result":0,"error":$err}'] [qq'{"result":0,"error":$err}']
@ -224,14 +232,16 @@ sub do {
else { else {
return $self->sendJSONresponse( return $self->sendJSONresponse(
$req, $req,
{ result => 1, {
result => 1,
code => $err code => $err
} }
); );
} }
} }
else { else {
if ( $err if (
$err
and $err != PE_LOGOUT_OK and $err != PE_LOGOUT_OK
and ( and (
$err != PE_REDIRECT $err != PE_REDIRECT
@ -258,7 +268,8 @@ sub do {
sub getModule { sub getModule {
my ( $self, $req, $type ) = @_; my ( $self, $req, $type ) = @_;
if (my $mod = { if (
my $mod = {
auth => '_authentication', auth => '_authentication',
user => '_userDB', user => '_userDB',
password => '_passwordDB' password => '_passwordDB'
@ -270,8 +281,8 @@ sub getModule {
} }
else { else {
my $s = ref( $self->$mod ); my $s = ref( $self->$mod );
$s $s =~
=~ s/^Lemonldap::NG::Portal::(?:(?:Issuer|UserDB|Auth|Password)::)?//; s/^Lemonldap::NG::Portal::(?:(?:Issuer|UserDB|Auth|Password)::)?//;
return $s; return $s;
} }
} }
@ -298,9 +309,8 @@ sub autoRedirect {
$req->data->{redirectFormMethod} = "get"; $req->data->{redirectFormMethod} = "get";
} }
else { else {
return [ return [ 302,
302, [ Location => $req->{urldc}, @{ $req->respHeaders } ], [] [ Location => $req->{urldc}, @{ $req->respHeaders } ], [] ];
];
} }
} }
my ( $tpl, $prms ) = $self->display($req); my ( $tpl, $prms ) = $self->display($req);
@ -322,7 +332,8 @@ sub getApacheSession {
} }
my $as = Lemonldap::NG::Common::Session->new( my $as = Lemonldap::NG::Common::Session->new(
{ storageModule => $self->conf->{globalStorage}, {
storageModule => $self->conf->{globalStorage},
storageModuleOptions => $self->conf->{globalStorageOptions}, storageModuleOptions => $self->conf->{globalStorageOptions},
cacheModule => $self->conf->{localSessionStorage}, cacheModule => $self->conf->{localSessionStorage},
cacheModuleOptions => $self->conf->{localSessionStorageOptions}, cacheModuleOptions => $self->conf->{localSessionStorageOptions},
@ -336,7 +347,8 @@ sub getApacheSession {
if ( my $err = $as->error ) { if ( my $err = $as->error ) {
$self->lmLog( $self->lmLog(
$err, $err,
( $err =~ /(?:Object does not exist|Invalid session ID)/ (
$err =~ /(?:Object does not exist|Invalid session ID)/
? 'notice' ? 'notice'
: 'error' : 'error'
) )
@ -350,14 +362,15 @@ sub getApacheSession {
} }
my $now = time; my $now = time;
if ( $id if (
$id
and defined $as->data->{_utime} and defined $as->data->{_utime}
and ( and (
$now - $as->data->{_utime} > $self->conf->{timeout} $now - $as->data->{_utime} > $self->conf->{timeout}
or ( $self->conf->{timeoutActivity} or ( $self->conf->{timeoutActivity}
and $as->data->{_lastSeen} and $as->data->{_lastSeen}
and $now - $as->data->{_lastSeen} and $now - $as->data->{_lastSeen} >
> $self->conf->{timeoutActivity} ) $self->conf->{timeoutActivity} )
) )
) )
{ {
@ -382,7 +395,8 @@ sub getPersistentSession {
$info->{_session_uid} = $uid; $info->{_session_uid} = $uid;
my $ps = Lemonldap::NG::Common::Session->new( my $ps = Lemonldap::NG::Common::Session->new(
{ storageModule => $self->conf->{persistentStorage}, {
storageModule => $self->conf->{persistentStorage},
storageModuleOptions => $self->conf->{persistentStorageOptions}, storageModuleOptions => $self->conf->{persistentStorageOptions},
id => $pid, id => $pid,
force => 1, force => 1,
@ -426,8 +440,7 @@ sub updatePersistentSession {
|| $req->userData->{ $self->conf->{whatToTrace} }; || $req->userData->{ $self->conf->{whatToTrace} };
$self->logger->debug("Found 'whatToTrace' -> $uid"); $self->logger->debug("Found 'whatToTrace' -> $uid");
unless ($uid) { unless ($uid) {
$self->logger->debug( $self->logger->debug('No uid found, skipping updatePersistentSession');
'No uid found, skipping updatePersistentSession');
return (); return ();
} }
$self->logger->debug("Update $uid persistent session"); $self->logger->debug("Update $uid persistent session");
@ -469,14 +482,14 @@ sub updateSession {
foreach ( keys %$infos ) { foreach ( keys %$infos ) {
$self->logger->debug( $self->logger->debug(
"Update sessionInfo $_ with " . $infos->{$_} ); "Update sessionInfo $_ with " . $infos->{$_} );
$req->{sessionInfo}->{$_} = $self->HANDLER->data->{$_} $req->{sessionInfo}->{$_} = $self->HANDLER->data->{$_} =
= $infos->{$_}; $infos->{$_};
} }
# Update session in global storage with _updateTime # Update session in global storage with _updateTime
$infos->{_updateTime} = strftime( "%Y%m%d%H%M%S", localtime() ); $infos->{_updateTime} = strftime( "%Y%m%d%H%M%S", localtime() );
if ( my $apacheSession if ( my $apacheSession =
= $self->getApacheSession( $id, info => $infos ) ) $self->getApacheSession( $id, info => $infos ) )
{ {
if ( $apacheSession->error ) { if ( $apacheSession->error ) {
$self->logger->error("Cannot update session $id"); $self->logger->error("Cannot update session $id");
@ -559,8 +572,8 @@ sub isTrustedUrl {
sub stamp { sub stamp {
my $self = shift; my $self = shift;
my $res my $res =
= $self->conf->{cipher} $self->conf->{cipher}
? $self->conf->{cipher}->encrypt( time() ) ? $self->conf->{cipher}->encrypt( time() )
: 1; : 1;
$res =~ s/\+/%2B/g; $res =~ s/\+/%2B/g;
@ -732,14 +745,13 @@ sub sendHtml {
if ( defined $url ) { if ( defined $url ) {
$self->logger->debug("Required Params URL : $url"); $self->logger->debug("Required Params URL : $url");
if ( $url =~ s#(https?://[^/]+).*#$1# ) { if ( $url =~ s#(https?://[^/]+).*#$1# ) {
$self->logger->debug( $self->logger->debug("Set CSP form-action with Params URL : $url");
"Set CSP form-action with Params URL : $url");
$csp .= " $url"; $csp .= " $url";
} }
} }
if ( defined $req->{cspFormAction} ) { if ( defined $req->{cspFormAction} ) {
$self->logger->debug( "Set CSP form-action with request URL: " $self->logger->debug(
. $req->{cspFormAction} ); "Set CSP form-action with request URL: " . $req->{cspFormAction} );
$csp .= " " . $req->{cspFormAction}; $csp .= " " . $req->{cspFormAction};
} }
$csp .= ';'; $csp .= ';';
@ -768,8 +780,8 @@ sub sendHtml {
sub sendCss { sub sendCss {
my ( $self, $req ) = @_; my ( $self, $req ) = @_;
my $s my $s =
= 'html,body{background:url("' 'html,body{background:url("'
. $self->staticPrefix . $self->staticPrefix
. '/common/backgrounds/' . '/common/backgrounds/'
. $self->conf->{portalSkinBackground} . $self->conf->{portalSkinBackground}
@ -777,7 +789,8 @@ sub sendCss {
. 'background-size:cover;}'; . 'background-size:cover;}';
return [ return [
200, 200,
[ 'Content-Type' => 'text/css', [
'Content-Type' => 'text/css',
'Content-Length' => length($s), 'Content-Length' => length($s),
'Cache-Control' => 'public,max-age=3600', 'Cache-Control' => 'public,max-age=3600',
], ],
@ -806,7 +819,7 @@ sub lmError {
sub rebuildCookies { sub rebuildCookies {
my ( $self, $req ) = @_; my ( $self, $req ) = @_;
my @tmp; my @tmp;
for ( my $i = 0; $i < @{ $req->{respHeaders} }; $i += 2 ) { for ( my $i = 0 ; $i < @{ $req->{respHeaders} } ; $i += 2 ) {
push @tmp, $req->respHeaders->[0], $req->respHeaders->[1] push @tmp, $req->respHeaders->[0], $req->respHeaders->[1]
unless ( $req->respHeaders->[0] eq 'Set-Cookie' ); unless ( $req->respHeaders->[0] eq 'Set-Cookie' );
} }
@ -843,15 +856,15 @@ sub registerLogin {
$login->{error} = $self->error( $req->authResult ) $login->{error} = $self->error( $req->authResult )
if ( $req->authResult ); if ( $req->authResult );
$self->logger->debug(" Current login -> " . $login->{error}) if ( $login->{error} ); $self->logger->debug( " Current login -> " . $login->{error} )
if ( $login->{error} );
# Add current login into history # Add current login into history
unshift @{ $history->{$type} }, $login; unshift @{ $history->{$type} }, $login;
# Forget oldest logins # Forget oldest logins
splice @{ $history->{$type} }, $self->conf->{ $type . "Number" } splice @{ $history->{$type} }, $self->conf->{ $type . "Number" }
if ( if ( scalar @{ $history->{$type} } > $self->conf->{ $type . "Number" } );
scalar @{ $history->{$type} } > $self->conf->{ $type . "Number" } );
# Save into persistent session # Save into persistent session
$self->updatePersistentSession( $req, { _loginHistory => $history, } ); $self->updatePersistentSession( $req, { _loginHistory => $history, } );
@ -862,8 +875,8 @@ sub registerLogin {
# @return hashref # @return hashref
sub _sumUpSession { sub _sumUpSession {
my ( $self, $session, $withoutUser ) = @_; my ( $self, $session, $withoutUser ) = @_;
my $res my $res =
= $withoutUser $withoutUser
? {} ? {}
: { user => $session->{ $self->conf->{whatToTrace} } }; : { user => $session->{ $self->conf->{whatToTrace} } };
$res->{$_} = $session->{$_} $res->{$_} = $session->{$_}
@ -876,8 +889,8 @@ sub _sumUpSession {
sub loadTemplate { sub loadTemplate {
my ( $self, $name, %prm ) = @_; my ( $self, $name, %prm ) = @_;
$name .= '.tpl'; $name .= '.tpl';
my $file my $file =
= $self->conf->{templateDir} . '/' $self->conf->{templateDir} . '/'
. $self->conf->{portalSkin} . '/' . $self->conf->{portalSkin} . '/'
. $name; . $name;
$file = $self->conf->{templateDir} . '/common/' . $name $file = $self->conf->{templateDir} . '/common/' . $name

View File

@ -19,8 +19,8 @@ extends 'Lemonldap::NG::Portal::Main::Plugin';
has ott => ( has ott => (
is => 'rw', is => 'rw',
default => sub { default => sub {
my $ott = $_[0]->{p} my $ott =
->loadModule('Lemonldap::NG::Portal::Lib::OneTimeToken'); $_[0]->{p}->loadModule('Lemonldap::NG::Portal::Lib::OneTimeToken');
$ott->timeout( $_[0]->{conf}->{formTimeout} ); $ott->timeout( $_[0]->{conf}->{formTimeout} );
return $ott; return $ott;
} }
@ -52,8 +52,7 @@ sub _redirect {
my ( $self, $req ) = @_; my ( $self, $req ) = @_;
my $arg = $req->env->{QUERY_STRING}; my $arg = $req->env->{QUERY_STRING};
return [ return [
302, [ Location => $self->conf->{portal} . ( $arg ? "?$arg" : '' ) ], 302, [ Location => $self->conf->{portal} . ( $arg ? "?$arg" : '' ) ], []
[]
]; ];
} }
@ -66,16 +65,15 @@ sub _verify {
# Check token # Check token
my $token; my $token;
unless ( $token = $req->param('token') ) { unless ( $token = $req->param('token') ) {
$self->userLogger->error( $self->userLogger->error( $self->prefix . ' 2F access without token' );
$self->prefix . ' 2F access without token' );
$req->mustRedirect(1); $req->mustRedirect(1);
return $self->p->do( $req, [ sub {PE_NOTOKEN} ] ); return $self->p->do( $req, [ sub { PE_NOTOKEN } ] );
} }
my $session; my $session;
unless ( $session = $self->ott->getToken($token) ) { unless ( $session = $self->ott->getToken($token) ) {
$self->userLogger->info('Token expired'); $self->userLogger->info('Token expired');
return $self->p->do( $req, [ sub {PE_TOKENEXPIRED} ] ); return $self->p->do( $req, [ sub { PE_TOKENEXPIRED } ] );
} }
# Launch second factor verification # Launch second factor verification
@ -90,7 +88,7 @@ sub _verify {
$req->{sessionInfo}->{_utime} = delete $req->{sessionInfo}->{_2fUtime}; $req->{sessionInfo}->{_utime} = delete $req->{sessionInfo}->{_2fUtime};
$req->authResult(PE_BADCREDENTIALS); $req->authResult(PE_BADCREDENTIALS);
return $self->p->do( $req, return $self->p->do( $req,
[ $self->p->storeHistory($req), sub {$res} ] ); [ $self->p->storeHistory($req), sub { $res } ] );
} }
# Else restore session # Else restore session
@ -108,8 +106,15 @@ sub _verify {
$self->p->updateSession( $req, { authenticationLevel => $l } ); $self->p->updateSession( $req, { authenticationLevel => $l } );
} }
$req->authResult(PE_SENDRESPONSE); $req->authResult(PE_SENDRESPONSE);
return $self->p->do( $req, return $self->p->do(
[ @{ $self->p->afterData }, $self->p->validSession, @{ $self->p->endAuth }, sub {PE_OK} ] ); $req,
[
@{ $self->p->afterData },
$self->p->validSession,
@{ $self->p->endAuth },
sub { PE_OK }
]
);
} }
1; 1;

View File

@ -40,11 +40,9 @@ sub run {
return PE_OK if ( $countFailed < 3 ); return PE_OK if ( $countFailed < 3 );
foreach ( 0 .. 2 ) { foreach ( 0 .. 2 ) {
if ( defined $req->sessionInfo->{_loginHistory}->{failedLogin}->[$_] ) if ( defined $req->sessionInfo->{_loginHistory}->{failedLogin}->[$_] ) {
{
push @lastFailedLoginEpoch, push @lastFailedLoginEpoch,
$req->sessionInfo->{_loginHistory}->{failedLogin}->[$_] $req->sessionInfo->{_loginHistory}->{failedLogin}->[$_]->{_utime};
->{_utime};
} }
} }
$self->logger->debug("BruteForceProtection enabled"); $self->logger->debug("BruteForceProtection enabled");

View File

@ -12,7 +12,7 @@ extends 'Lemonldap::NG::Portal::Main::Plugin';
use constant forAuthUser => 'run'; use constant forAuthUser => 'run';
sub init {1} sub init { 1 }
# RUNNING METHOD # RUNNING METHOD

View File

@ -22,11 +22,11 @@ sub init {
$self->logger->debug("GrantRule key -> $_"); $self->logger->debug("GrantRule key -> $_");
$self->logger->debug( $self->logger->debug(
"GrantRule value -> " . $self->conf->{grantSessionRules}->{$_} ); "GrantRule value -> " . $self->conf->{grantSessionRules}->{$_} );
my $rule = $hd->buildSub( my $rule =
$hd->buildSub(
$hd->substitute( $self->conf->{grantSessionRules}->{$_} ) ); $hd->substitute( $self->conf->{grantSessionRules}->{$_} ) );
unless ($rule) { unless ($rule) {
$self->error( $self->error( "Bad grantSession rule " . $hd->tsv->{jail}->error );
"Bad grantSession rule " . $hd->tsv->{jail}->error );
return 0; return 0;
} }
$self->rules->{$_} = $rule; $self->rules->{$_} = $rule;

View File

@ -29,8 +29,8 @@ sub run {
'lastLogins', 0, 0 ) 'lastLogins', 0, 0 )
: "" : ""
) )
. ("<hr>") . . ("<hr>")
( . (
$req->sessionInfo->{_loginHistory}->{failedLogin} $req->sessionInfo->{_loginHistory}->{failedLogin}
? $self->p->mkSessionArray( ? $self->p->mkSessionArray(
$req->sessionInfo->{_loginHistory}->{failedLogin}, $req->sessionInfo->{_loginHistory}->{failedLogin},

View File

@ -9,7 +9,7 @@ sub new {
} }
my $res = $self->{p}->loadModule( $self->{conf}->{customRegister} ); my $res = $self->{p}->loadModule( $self->{conf}->{customRegister} );
unless($res) { unless ($res) {
die 'Unable to load register module ' . $self->{conf}->{customRegister}; die 'Unable to load register module ' . $self->{conf}->{customRegister};
} }
return $res; return $res;

View File

@ -111,8 +111,8 @@ ok(
), ),
'New auth query' 'New auth query'
); );
expectAuthenticatedAs($res,'dwho'); expectAuthenticatedAs( $res, 'dwho' );
ok($res->[2]->[0] =~ /yourApp/s, 'Menu displayed'); ok( $res->[2]->[0] =~ /yourApp/s, 'Menu displayed' );
count(2); count(2);
clean_sessions(); clean_sessions();

View File

@ -16,7 +16,6 @@ my $mailSend = 0;
my $mail2 = 0; my $mail2 = 0;
SKIP: { SKIP: {
eval eval
'require Email::Sender::Simple;use GD::SecurityImage;use Image::Magick;'; 'require Email::Sender::Simple;use GD::SecurityImage;use Image::Magick;';

View File

@ -10,7 +10,8 @@ BEGIN {
my $res; my $res;
my $client = LLNG::Manager::Test->new( my $client = LLNG::Manager::Test->new(
{ ini => { {
ini => {
logLevel => 'error', logLevel => 'error',
authentication => 'Demo', authentication => 'Demo',
userDB => 'Same', userDB => 'Same',
@ -22,7 +23,8 @@ my $client = LLNG::Manager::Test->new(
); );
## First successful connection ## First successful connection
ok( $res = $client->_post( ok(
$res = $client->_post(
'/', '/',
IO::String->new('user=dwho&password=dwho'), IO::String->new('user=dwho&password=dwho'),
length => 23, length => 23,
@ -37,7 +39,8 @@ expectRedirection( $res, 'http://auth.example.com/' );
$client->logout($id1); $client->logout($id1);
## Second successful connection ## Second successful connection
ok( $res = $client->_post( ok(
$res = $client->_post(
'/', '/',
IO::String->new('user=dwho&password=dwho'), IO::String->new('user=dwho&password=dwho'),
length => 23, length => 23,
@ -52,7 +55,8 @@ expectRedirection( $res, 'http://auth.example.com/' );
$client->logout($id1); $client->logout($id1);
## First failed connection ## First failed connection
ok( $res = $client->_post( ok(
$res = $client->_post(
'/', '/',
IO::String->new('user=dwho&password=ohwd'), IO::String->new('user=dwho&password=ohwd'),
length => 23 length => 23
@ -63,7 +67,8 @@ count(1);
expectReject($res); expectReject($res);
## Second failed connection ## Second failed connection
ok( $res = $client->_post( ok(
$res = $client->_post(
'/', '/',
IO::String->new('user=dwho&password=ohwd'), IO::String->new('user=dwho&password=ohwd'),
length => 23 length => 23
@ -74,7 +79,8 @@ count(1);
expectReject($res); expectReject($res);
## Third failed connection -> rejected ## Third failed connection -> rejected
ok( $res = $client->_post( ok(
$res = $client->_post(
'/', '/',
IO::String->new('user=dwho&password=ohwd'), IO::String->new('user=dwho&password=ohwd'),
length => 23, length => 23,
@ -89,7 +95,8 @@ count(1);
sleep 1; sleep 1;
## Fourth failed connection -> Rejected ## Fourth failed connection -> Rejected
ok( $res = $client->_post( ok(
$res = $client->_post(
'/', '/',
IO::String->new('user=dwho&password=ohwd'), IO::String->new('user=dwho&password=ohwd'),
length => 23, length => 23,
@ -104,7 +111,8 @@ count(1);
sleep 2; sleep 2;
## Third successful connection -> Rejected ## Third successful connection -> Rejected
ok( $res = $client->_post( ok(
$res = $client->_post(
'/', '/',
IO::String->new('user=dwho&password=dwho'), IO::String->new('user=dwho&password=dwho'),
length => 23, length => 23,
@ -119,7 +127,8 @@ count(1);
sleep 3; sleep 3;
## Fourth successful connection -> Accepted ## Fourth successful connection -> Accepted
ok( $res = $client->_post( ok(
$res = $client->_post(
'/', '/',
IO::String->new('user=dwho&password=dwho&checkLogins=1'), IO::String->new('user=dwho&password=dwho&checkLogins=1'),
length => 37, length => 37,

View File

@ -10,7 +10,8 @@ BEGIN {
my $res; my $res;
my $client = LLNG::Manager::Test->new( my $client = LLNG::Manager::Test->new(
{ ini => { {
ini => {
authentication => 'Demo', authentication => 'Demo',
userdb => 'Same', userdb => 'Same',
portalForceAuthn => 1, portalForceAuthn => 1,
@ -19,7 +20,8 @@ my $client = LLNG::Manager::Test->new(
} }
); );
ok( $res = $client->_post( ok(
$res = $client->_post(
'/', '/',
IO::String->new('user=dwho&password=dwho'), IO::String->new('user=dwho&password=dwho'),
length => 23 length => 23
@ -33,7 +35,8 @@ count(1);
sleep 3; sleep 3;
ok( $res = $client->_get( ok(
$res = $client->_get(
'/', '/',
cookie => "lemonldap=$id1", cookie => "lemonldap=$id1",
accept => 'text/html', accept => 'text/html',
@ -44,7 +47,8 @@ ok( $res->[2]->[0] =~ qr%<span trspan="PE87"></span>%, 'Found PE87 code' )
or print STDERR Dumper( $res->[2]->[0] ); or print STDERR Dumper( $res->[2]->[0] );
count(1); count(1);
ok( $res = $client->_post( ok(
$res = $client->_post(
'/', '/',
IO::String->new('user=dwho&password=dwho'), IO::String->new('user=dwho&password=dwho'),
length => 23, length => 23,
@ -56,7 +60,8 @@ expectOK($res);
$id1 = expectCookie($res); $id1 = expectCookie($res);
count(1); count(1);
ok( $res = $client->_get( ok(
$res = $client->_get(
'/', '/',
cookie => "lemonldap=$id1", cookie => "lemonldap=$id1",
accept => 'text/html', accept => 'text/html',

View File

@ -10,7 +10,8 @@ BEGIN {
my $res; my $res;
my $client = LLNG::Manager::Test->new( my $client = LLNG::Manager::Test->new(
{ ini => { {
ini => {
logLevel => 'error', logLevel => 'error',
authentication => 'Demo', authentication => 'Demo',
userdb => 'Same', userdb => 'Same',
@ -23,7 +24,8 @@ my $client = LLNG::Manager::Test->new(
} }
); );
ok( $res = $client->_post( ok(
$res = $client->_post(
'/', '/',
IO::String->new('user=dwho&password=dwho'), IO::String->new('user=dwho&password=dwho'),
accept => 'text/html', accept => 'text/html',
@ -33,15 +35,16 @@ ok( $res = $client->_post(
); );
count(1); count(1);
ok( $res->[2]->[0] =~ /<h3 trspan="dwho not allowed">dwho not allowed<\/h3>/, ok( $res->[2]->[0] =~ /<h3 trspan="dwho not allowed">dwho not allowed<\/h3>/,
'dwho rejected with custom message and session data' 'dwho rejected with custom message and session data' )
) or print STDERR Dumper( $res->[2]->[0] ); or print STDERR Dumper( $res->[2]->[0] );
count(1); count(1);
ok( $res->[2]->[0] =~ qr%src="/static/common/js/info.(?:min\.)?js"></script>%, ok( $res->[2]->[0] =~ qr%src="/static/common/js/info.(?:min\.)?js"></script>%,
'Found INFO js' 'Found INFO js' )
) or print STDERR Dumper( $res->[2]->[0] ); or print STDERR Dumper( $res->[2]->[0] );
count(1); count(1);
ok( $res = $client->_post( ok(
$res = $client->_post(
'/', '/',
IO::String->new('user=rtyler&password=rtyler'), IO::String->new('user=rtyler&password=rtyler'),
length => 27 length => 27
@ -52,7 +55,8 @@ count(1);
expectOK($res); expectOK($res);
expectCookie($res); expectCookie($res);
ok( $res = $client->_post( ok(
$res = $client->_post(
'/', '/',
IO::String->new('user=mrsmith&password=mrsmith'), IO::String->new('user=mrsmith&password=mrsmith'),
accept => 'text/html', accept => 'text/html',
@ -61,7 +65,8 @@ ok( $res = $client->_post(
'Auth query' 'Auth query'
); );
count(1); count(1);
ok( $res->[2]->[0] =~ /<span trmsg="4"><\/span><\/div>/, ok(
$res->[2]->[0] =~ /<span trmsg="4"><\/span><\/div>/,
'rtyler rejected with PE_SESSIONNOTGRANTED' 'rtyler rejected with PE_SESSIONNOTGRANTED'
) or print STDERR Dumper( $res->[2]->[0] ); ) or print STDERR Dumper( $res->[2]->[0] );
count(1); count(1);
@ -72,7 +77,8 @@ count(1);
&Lemonldap::NG::Handler::Main::cfgNum( 0, 0 ); &Lemonldap::NG::Handler::Main::cfgNum( 0, 0 );
$client = LLNG::Manager::Test->new( $client = LLNG::Manager::Test->new(
{ ini => { {
ini => {
authentication => 'Demo', authentication => 'Demo',
userdb => 'Same', userdb => 'Same',
grantSessionRules => { '' => '$uid eq "dwho"', } grantSessionRules => { '' => '$uid eq "dwho"', }
@ -80,7 +86,8 @@ $client = LLNG::Manager::Test->new(
} }
); );
ok( $res = $client->_post( ok(
$res = $client->_post(
'/', '/',
IO::String->new('user=dwho&password=dwho'), IO::String->new('user=dwho&password=dwho'),
length => 23 length => 23

View File

@ -9,7 +9,8 @@ BEGIN {
my $res; my $res;
my $client = LLNG::Manager::Test->new( my $client = LLNG::Manager::Test->new(
{ ini => { {
ini => {
logLevel => 'error', logLevel => 'error',
authentication => 'Demo', authentication => 'Demo',
userDB => 'Same', userDB => 'Same',
@ -20,7 +21,8 @@ my $client = LLNG::Manager::Test->new(
); );
## First successful connection ## First successful connection
ok( $res = $client->_post( ok(
$res = $client->_post(
'/', '/',
IO::String->new('user=dwho&password=dwho&checkLogins=1'), IO::String->new('user=dwho&password=dwho&checkLogins=1'),
length => 37, length => 37,
@ -47,7 +49,8 @@ expectOK($res);
$client->logout($id1); $client->logout($id1);
## Second successful connection ## Second successful connection
ok( $res = $client->_post( ok(
$res = $client->_post(
'/', '/',
IO::String->new('user=dwho&password=dwho&checkLogins=1'), IO::String->new('user=dwho&password=dwho&checkLogins=1'),
length => 37, length => 37,
@ -69,7 +72,8 @@ count(2);
$client->logout($id1); $client->logout($id1);
## First failed connection ## First failed connection
ok( $res = $client->_post( ok(
$res = $client->_post(
'/', '/',
IO::String->new('user=dwho&password=ohwd'), IO::String->new('user=dwho&password=ohwd'),
length => 23 length => 23
@ -80,7 +84,8 @@ count(1);
expectReject($res); expectReject($res);
## Second failed connection ## Second failed connection
ok( $res = $client->_post( ok(
$res = $client->_post(
'/', '/',
IO::String->new('user=dwho&password=ohwd'), IO::String->new('user=dwho&password=ohwd'),
length => 23 length => 23
@ -91,7 +96,8 @@ count(1);
expectReject($res); expectReject($res);
## Third successful connection ## Third successful connection
ok( $res = $client->_post( ok(
$res = $client->_post(
'/', '/',
IO::String->new('user=dwho&password=dwho&checkLogins=1'), IO::String->new('user=dwho&password=dwho&checkLogins=1'),
length => 37, length => 37,

View File

@ -74,7 +74,6 @@ ok(
); );
my $id = expectCookie($res); my $id = expectCookie($res);
ok( $res->[2]->[0] =~ /trspan="lastLogins"/, 'History found' ) ok( $res->[2]->[0] =~ /trspan="lastLogins"/, 'History found' )
or print STDERR Dumper( $res->[2]->[0] ); or print STDERR Dumper( $res->[2]->[0] );
my @c = ( $res->[2]->[0] =~ /<td>127.0.0.1/gs ); my @c = ( $res->[2]->[0] =~ /<td>127.0.0.1/gs );

View File

@ -9,7 +9,8 @@ use_ok('Lemonldap::NG::Common::FormEncode');
count(1); count(1);
my $client = LLNG::Manager::Test->new( my $client = LLNG::Manager::Test->new(
{ ini => { {
ini => {
logLevel => 'error', logLevel => 'error',
ext2fActivation => 1, ext2fActivation => 1,
ext2FSendCommand => 't/sendOTP.pl -uid $uid', ext2FSendCommand => 't/sendOTP.pl -uid $uid',
@ -26,7 +27,8 @@ my $client = LLNG::Manager::Test->new(
my $res; my $res;
## First failed connection ## First failed connection
ok( $res = $client->_post( ok(
$res = $client->_post(
'/', '/',
IO::String->new('user=dwho&password=ohwd'), IO::String->new('user=dwho&password=ohwd'),
length => 23 length => 23
@ -37,7 +39,8 @@ count(1);
expectReject($res); expectReject($res);
## Second failed connection ## Second failed connection
ok( $res = $client->_post( ok(
$res = $client->_post(
'/', '/',
IO::String->new('user=dwho&password=ohwd'), IO::String->new('user=dwho&password=ohwd'),
length => 23 length => 23
@ -48,7 +51,8 @@ count(1);
expectReject($res); expectReject($res);
## Third failed connection -> rejected ## Third failed connection -> rejected
ok( $res = $client->_post( ok(
$res = $client->_post(
'/', '/',
IO::String->new('user=dwho&password=ohwd'), IO::String->new('user=dwho&password=ohwd'),
length => 23, length => 23,
@ -64,7 +68,8 @@ sleep 2;
# Try to authenticate # Try to authenticate
# ------------------- # -------------------
ok( $res = $client->_post( ok(
$res = $client->_post(
'/', '/',
IO::String->new('user=dwho&password=dwho&checkLogins=1'), IO::String->new('user=dwho&password=dwho&checkLogins=1'),
length => 37, length => 37,
@ -74,18 +79,19 @@ ok( $res = $client->_post(
); );
count(1); count(1);
my ( $host, $url, $query ) my ( $host, $url, $query ) =
= expectForm( $res, undef, '/ext2fcheck', 'token', 'code', expectForm( $res, undef, '/ext2fcheck', 'token', 'code', 'checkLogins' );
'checkLogins' );
ok( $res->[2]->[0] ok(
=~ qr%<input name="code" value="" class="form-control" id="extcode" trplaceholder="code">%, $res->[2]->[0] =~
qr%<input name="code" value="" class="form-control" id="extcode" trplaceholder="code">%,
'Found EXTCODE input' 'Found EXTCODE input'
) or print STDERR Dumper( $res->[2]->[0] ); ) or print STDERR Dumper( $res->[2]->[0] );
count(1); count(1);
$query =~ s/code=/code=123456/; $query =~ s/code=/code=123456/;
ok( $res = $client->_post( ok(
$res = $client->_post(
'/ext2fcheck', '/ext2fcheck',
IO::String->new($query), IO::String->new($query),
length => length($query), length => length($query),
@ -102,7 +108,8 @@ sleep 4;
# Try to authenticate again # Try to authenticate again
# ------------------------- # -------------------------
ok( $res = $client->_post( ok(
$res = $client->_post(
'/', '/',
IO::String->new('user=dwho&password=dwho&checkLogins=1'), IO::String->new('user=dwho&password=dwho&checkLogins=1'),
length => 37, length => 37,
@ -112,18 +119,19 @@ ok( $res = $client->_post(
); );
count(1); count(1);
( $host, $url, $query ) ( $host, $url, $query ) =
= expectForm( $res, undef, '/ext2fcheck', 'token', 'code', expectForm( $res, undef, '/ext2fcheck', 'token', 'code', 'checkLogins' );
'checkLogins' );
ok( $res->[2]->[0] ok(
=~ qr%<input name="code" value="" class="form-control" id="extcode" trplaceholder="code">%, $res->[2]->[0] =~
qr%<input name="code" value="" class="form-control" id="extcode" trplaceholder="code">%,
'Found EXTCODE input' 'Found EXTCODE input'
) or print STDERR Dumper( $res->[2]->[0] ); ) or print STDERR Dumper( $res->[2]->[0] );
count(1); count(1);
$query =~ s/code=/code=123456/; $query =~ s/code=/code=123456/;
ok( $res = $client->_post( ok(
$res = $client->_post(
'/ext2fcheck', '/ext2fcheck',
IO::String->new($query), IO::String->new($query),
length => length($query), length => length($query),

View File

@ -9,15 +9,15 @@ use_ok('Lemonldap::NG::Common::FormEncode');
count(1); count(1);
my $client = LLNG::Manager::Test->new( my $client = LLNG::Manager::Test->new(
{ ini => { {
ini => {
logLevel => 'error', logLevel => 'error',
ext2fActivation => 1, ext2fActivation => 1,
ext2FSendCommand => 't/sendOTP.pl -uid $uid', ext2FSendCommand => 't/sendOTP.pl -uid $uid',
ext2FValidateCommand => 't/vrfyOTP.pl -uid $uid -code $code', ext2FValidateCommand => 't/vrfyOTP.pl -uid $uid -code $code',
authentication => 'Demo', authentication => 'Demo',
userDB => 'Same', userDB => 'Same',
grantSessionRules => grantSessionRules => { 'Dwho_notAllowed##Test' => '$uid ne "dwho"' }
{ 'Dwho_notAllowed##Test' => '$uid ne "dwho"' }
} }
} }
); );
@ -26,7 +26,8 @@ my $res;
# Try to authenticate # Try to authenticate
# ------------------- # -------------------
ok( $res = $client->_post( ok(
$res = $client->_post(
'/', '/',
IO::String->new('user=dwho&password=dwho'), IO::String->new('user=dwho&password=dwho'),
length => 23, length => 23,
@ -36,17 +37,19 @@ ok( $res = $client->_post(
); );
count(1); count(1);
my ( $host, $url, $query ) my ( $host, $url, $query ) =
= expectForm( $res, undef, '/ext2fcheck', 'token', 'code' ); expectForm( $res, undef, '/ext2fcheck', 'token', 'code' );
ok( $res->[2]->[0] ok(
=~ qr%<input name="code" value="" class="form-control" id="extcode" trplaceholder="code">%, $res->[2]->[0] =~
qr%<input name="code" value="" class="form-control" id="extcode" trplaceholder="code">%,
'Found EXTCODE input' 'Found EXTCODE input'
) or print STDERR Dumper( $res->[2]->[0] ); ) or print STDERR Dumper( $res->[2]->[0] );
count(1); count(1);
$query =~ s/code=/code=123456/; $query =~ s/code=/code=123456/;
ok( $res = $client->_post( ok(
$res = $client->_post(
'/ext2fcheck', '/ext2fcheck',
IO::String->new($query), IO::String->new($query),
length => length($query), length => length($query),
@ -62,8 +65,8 @@ ok( $res->[2]->[0] =~ /<h3 trspan="Dwho_notAllowed">Dwho_notAllowed<\/h3>/,
count(1); count(1);
ok( $res->[2]->[0] =~ qr%src="/static/common/js/info.(?:min\.)?js"></script>%, ok( $res->[2]->[0] =~ qr%src="/static/common/js/info.(?:min\.)?js"></script>%,
'Found INFO js' 'Found INFO js' )
) or print STDERR Dumper( $res->[2]->[0] ); or print STDERR Dumper( $res->[2]->[0] );
count(1); count(1);
clean_sessions(); clean_sessions();

View File

@ -2,6 +2,6 @@
use strict; use strict;
use warnings; use warnings;
my ($swt, $user) = @ARGV; my ( $swt, $user ) = @ARGV;
exit !( $swt eq '-uid' && $user eq 'dwho' ); exit !( $swt eq '-uid' && $user eq 'dwho' );

View File

@ -58,6 +58,7 @@ use Data::Dumper;
use LWP::UserAgent; use LWP::UserAgent;
use URI::Escape; use URI::Escape;
use Lemonldap::NG::Common::FormEncode; use Lemonldap::NG::Common::FormEncode;
#use 5.10.0; #use 5.10.0;
no warnings 'redefine'; no warnings 'redefine';

View File

@ -2,6 +2,9 @@
use strict; use strict;
use warnings; use warnings;
my ($swt1, $user, $swt2, $code) = @ARGV; my ( $swt1, $user, $swt2, $code ) = @ARGV;
exit !( $swt1 eq '-uid' && $user eq 'dwho' && $swt2 eq '-code' && $code eq '123456' ); exit !($swt1 eq '-uid'
&& $user eq 'dwho'
&& $swt2 eq '-code'
&& $code eq '123456' );