|
|
|
@ -31,7 +31,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}" |
|
|
|
|
) |
|
|
|
@ -61,7 +62,8 @@ sub tests { |
|
|
|
|
} |
|
|
|
|
return ( |
|
|
|
|
1, |
|
|
|
|
( @pb |
|
|
|
|
( |
|
|
|
|
@pb |
|
|
|
|
? 'Virtual hosts ' |
|
|
|
|
. join( ', ', @pb ) |
|
|
|
|
. " are not in $conf->{domain} and cross-domain-authentication is not set" |
|
|
|
@ -106,9 +108,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; |
|
|
|
@ -118,8 +120,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}; |
|
|
|
@ -137,7 +139,8 @@ sub tests { |
|
|
|
|
} |
|
|
|
|
return ( |
|
|
|
|
1, |
|
|
|
|
( @tmp |
|
|
|
|
( |
|
|
|
|
@tmp |
|
|
|
|
? 'Values of parameter(s) "' |
|
|
|
|
. join( ', ', @tmp ) |
|
|
|
|
. '" are not defined in exported attributes or macros' |
|
|
|
@ -152,15 +155,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' |
|
|
|
@ -175,8 +178,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; |
|
|
|
|
} |
|
|
|
@ -184,7 +186,8 @@ sub tests { |
|
|
|
|
} |
|
|
|
|
return ( |
|
|
|
|
1, |
|
|
|
|
( @tmp |
|
|
|
|
( |
|
|
|
|
@tmp |
|
|
|
|
? 'Values of parameter(s) "' |
|
|
|
|
. join( ', ', @tmp ) |
|
|
|
|
. '" are not exported by OpenID SREG' |
|
|
|
@ -196,12 +199,11 @@ sub tests { |
|
|
|
|
# Try to use Apache::Session module |
|
|
|
|
testApacheSession => sub { |
|
|
|
|
my ( $id, %h ); |
|
|
|
|
my $gc |
|
|
|
|
= Lemonldap::NG::Handler::Main->tsv->{sessionStorageModule}; |
|
|
|
|
my $gc = Lemonldap::NG::Handler::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 { |
|
|
|
@ -229,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; |
|
|
|
|
}, |
|
|
|
@ -239,7 +241,8 @@ sub tests { |
|
|
|
|
my $cn = Lemonldap::NG::Handler::Main->tsv->{cookieName}; |
|
|
|
|
return ( |
|
|
|
|
1, |
|
|
|
|
( $cn |
|
|
|
|
( |
|
|
|
|
$cn |
|
|
|
|
and $cn ne $conf->{cookieName} |
|
|
|
|
? 'Cookie name has changed, you must restart all your web servers' |
|
|
|
|
: () |
|
|
|
@ -276,7 +279,7 @@ sub tests { |
|
|
|
|
sessionTimeoutActivity => sub { |
|
|
|
|
return 1 unless ( defined $conf->{timeoutActivity} ); |
|
|
|
|
return ( 0, |
|
|
|
|
"Session activity timeout must be higher or equal than one minute" |
|
|
|
|
"Session activity timeout must be higher or equal than one minute" |
|
|
|
|
) |
|
|
|
|
unless ( $conf->{timeoutActivity} > 59 |
|
|
|
|
|| $conf->{timeoutActivity} == 0 ); |
|
|
|
@ -289,11 +292,11 @@ sub tests { |
|
|
|
|
timeoutActivityInterval => sub { |
|
|
|
|
return 1 unless ( defined $conf->{timeoutActivityInterval} ); |
|
|
|
|
return ( 0, |
|
|
|
|
"Activity timeout interval must be lower than session activity timeout" |
|
|
|
|
"Activity timeout interval must be lower than session activity timeout" |
|
|
|
|
) |
|
|
|
|
if ($conf->{timeoutActivity} |
|
|
|
|
and $conf->{timeoutActivity} |
|
|
|
|
<= $conf->{timeoutActivityInterval} ); |
|
|
|
|
if ( $conf->{timeoutActivity} |
|
|
|
|
and $conf->{timeoutActivity} <= |
|
|
|
|
$conf->{timeoutActivityInterval} ); |
|
|
|
|
|
|
|
|
|
# Return |
|
|
|
|
return 1; |
|
|
|
@ -303,7 +306,8 @@ sub tests { |
|
|
|
|
managerProtection => sub { |
|
|
|
|
return ( |
|
|
|
|
1, |
|
|
|
|
( $conf->{cfgAuthor} eq 'anonymous' |
|
|
|
|
( |
|
|
|
|
$conf->{cfgAuthor} eq 'anonymous' |
|
|
|
|
? 'Your manager seems to be unprotected' |
|
|
|
|
: '' |
|
|
|
|
) |
|
|
|
@ -353,8 +357,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; |
|
|
|
@ -380,8 +385,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; |
|
|
|
@ -415,8 +420,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 ($@); |
|
|
|
|
|
|
|
|
@ -462,7 +467,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 ($@); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -470,7 +475,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 ($@); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -495,8 +500,8 @@ sub tests { |
|
|
|
|
return 1 unless ( defined $conf->{totp2fDigits} ); |
|
|
|
|
return ( |
|
|
|
|
1, |
|
|
|
|
( |
|
|
|
|
( $conf->{totp2fDigits} == 6 |
|
|
|
|
( ( |
|
|
|
|
$conf->{totp2fDigits} == 6 |
|
|
|
|
or $conf->{totp2fDigits} == 8 |
|
|
|
|
) |
|
|
|
|
? '' |
|
|
|
@ -526,7 +531,8 @@ sub tests { |
|
|
|
|
&& defined $conf->{yubikey2fClientID} ); |
|
|
|
|
return ( |
|
|
|
|
1, |
|
|
|
|
( ( $conf->{yubikey2fPublicIDSize} == 12 ) |
|
|
|
|
( |
|
|
|
|
( $conf->{yubikey2fPublicIDSize} == 12 ) |
|
|
|
|
? '' |
|
|
|
|
: 'Yubikey public ID size should be 12 digits long' |
|
|
|
|
) |
|
|
|
@ -558,8 +564,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 ); |
|
|
|
@ -594,8 +599,7 @@ sub tests { |
|
|
|
|
# Warn if number of password reset retries is null |
|
|
|
|
passwordResetRetries => sub { |
|
|
|
|
return 1 unless ( $conf->{portalDisplayResetPassword} ); |
|
|
|
|
return ( 1, |
|
|
|
|
"Number of reset password retries should not be null" ) |
|
|
|
|
return ( 1, "Number of reset password retries should not be null" ) |
|
|
|
|
unless ( $conf->{passwordResetAllowedRetries} ); |
|
|
|
|
|
|
|
|
|
# Return |
|
|
|
@ -606,10 +610,10 @@ sub tests { |
|
|
|
|
bruteForceProtection => sub { |
|
|
|
|
return 1 unless ( $conf->{bruteForceProtection} ); |
|
|
|
|
return ( 1, |
|
|
|
|
'"History" plugin is required to enable "BruteForceProtection" plugin' |
|
|
|
|
'"History" plugin is required to enable "BruteForceProtection" plugin' |
|
|
|
|
) unless ( $conf->{loginHistoryEnabled} ); |
|
|
|
|
return ( 1, |
|
|
|
|
'Number of failed logins must be higher than 2 to enable "BruteForceProtection" plugin' |
|
|
|
|
'Number of failed logins must be higher than 2 to enable "BruteForceProtection" plugin' |
|
|
|
|
) unless ( $conf->{failedLoginNumber} > 2 ); |
|
|
|
|
|
|
|
|
|
# Return |
|
|
|
@ -620,7 +624,7 @@ sub tests { |
|
|
|
|
checkMailResetSecurity => sub { |
|
|
|
|
return 1 unless ( $conf->{portalDisplayResetPassword} ); |
|
|
|
|
return ( -1, |
|
|
|
|
'"passwordMailReset" plugin is enabled without CSRF Token neither Captcha required !!!' |
|
|
|
|
'"passwordMailReset" plugin is enabled without CSRF Token neither Captcha required !!!' |
|
|
|
|
) |
|
|
|
|
unless ( $conf->{requireToken} |
|
|
|
|
or $conf->{captcha_mail_enabled} ); |
|
|
|
|