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;
foreach my $k ( sort keys %$value ) {
my $data = [ split /;/, $value->{$k} ];
eval {$data->[5] = from_json($data->[5]) if $data->[5] };
if($@){
$self->logger->error("Bad value in choice over parameters, deleted ($@)");
eval { $data->[5] = from_json( $data->[5] ) if $data->[5] };
if ($@) {
$self->logger->error(
"Bad value in choice over parameters, deleted ($@)");
}
push @res,
{

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -39,7 +39,8 @@ sub run {
$self->logger->debug("Ext2F checkLogins set") if ($checkLogins);
# 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 =
$self->launch( $req->sessionInfo, $self->conf->{ext2FSendCommand} ) )
{
@ -72,7 +73,8 @@ sub verify {
}
# 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");
if ( my $c =
$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';
extends 'Lemonldap::NG::Portal::Main::Plugin', 'Lemonldap::NG::Portal::Lib::U2F';
extends 'Lemonldap::NG::Portal::Main::Plugin',
'Lemonldap::NG::Portal::Lib::U2F';
# INITIALIZATION

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -10,7 +10,8 @@ BEGIN {
my $res;
my $client = LLNG::Manager::Test->new(
{ ini => {
{
ini => {
authentication => 'Demo',
userdb => 'Same',
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'),
length => 23
@ -33,7 +35,8 @@ count(1);
sleep 3;
ok( $res = $client->_get(
ok(
$res = $client->_get(
'/',
cookie => "lemonldap=$id1",
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] );
count(1);
ok( $res = $client->_post(
ok(
$res = $client->_post(
'/',
IO::String->new('user=dwho&password=dwho'),
length => 23,
@ -56,7 +60,8 @@ expectOK($res);
$id1 = expectCookie($res);
count(1);
ok( $res = $client->_get(
ok(
$res = $client->_get(
'/',
cookie => "lemonldap=$id1",
accept => 'text/html',

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -2,6 +2,9 @@
use strict;
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' );