make tidy
This commit is contained in:
parent
f43139321c
commit
c5f9a7f95b
|
@ -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,
|
||||||
{
|
{
|
||||||
|
|
|
@ -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()',
|
||||||
|
|
|
@ -21,7 +21,7 @@ ok(
|
||||||
cookieName => 'lemonldap',
|
cookieName => 'lemonldap',
|
||||||
securedCookie => 0,
|
securedCookie => 0,
|
||||||
https => 0,
|
https => 0,
|
||||||
userLogger => 'Lemonldap::NG::Common::Logger::Null',
|
userLogger => 'Lemonldap::NG::Common::Logger::Null',
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
'initialization'
|
'initialization'
|
||||||
|
|
|
@ -29,7 +29,7 @@ sub init {
|
||||||
cookieName => 'lemonldap',
|
cookieName => 'lemonldap',
|
||||||
securedCookie => 0,
|
securedCookie => 0,
|
||||||
https => 0,
|
https => 0,
|
||||||
logger => 'Lemonldap::NG::Common::Logger::Std',
|
logger => 'Lemonldap::NG::Common::Logger::Std',
|
||||||
%$prms
|
%$prms
|
||||||
);
|
);
|
||||||
ok(
|
ok(
|
||||||
|
|
|
@ -8,17 +8,17 @@ sub types {
|
||||||
'array' => {
|
'array' => {
|
||||||
'test' => sub {
|
'test' => sub {
|
||||||
1;
|
1;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'authParamsText' => {
|
'authParamsText' => {
|
||||||
'test' => sub {
|
'test' => sub {
|
||||||
1;
|
1;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'blackWhiteList' => {
|
'blackWhiteList' => {
|
||||||
'test' => sub {
|
'test' => sub {
|
||||||
1;
|
1;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'bool' => {
|
'bool' => {
|
||||||
'msgFail' => '__notABoolean__',
|
'msgFail' => '__notABoolean__',
|
||||||
|
@ -36,17 +36,17 @@ sub types {
|
||||||
split( /\n/, $@, 0 ) )
|
split( /\n/, $@, 0 ) )
|
||||||
);
|
);
|
||||||
return $err ? ( 1, "__badExpression__: $err" ) : 1;
|
return $err ? ( 1, "__badExpression__: $err" ) : 1;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'catAndAppList' => {
|
'catAndAppList' => {
|
||||||
'test' => sub {
|
'test' => sub {
|
||||||
1;
|
1;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'file' => {
|
'file' => {
|
||||||
'test' => sub {
|
'test' => sub {
|
||||||
1;
|
1;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'hostname' => {
|
'hostname' => {
|
||||||
'form' => 'text',
|
'form' => 'text',
|
||||||
|
@ -80,48 +80,48 @@ qr/^(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-
|
||||||
if $_ =~ /exportedvars$/i and defined $conf->{$_}{$val};
|
if $_ =~ /exportedvars$/i and defined $conf->{$_}{$val};
|
||||||
}
|
}
|
||||||
return 1, "__unknownAttrOrMacro__: $val";
|
return 1, "__unknownAttrOrMacro__: $val";
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'longtext' => {
|
'longtext' => {
|
||||||
'test' => sub {
|
'test' => sub {
|
||||||
1;
|
1;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'menuApp' => {
|
'menuApp' => {
|
||||||
'test' => sub {
|
'test' => sub {
|
||||||
1;
|
1;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'menuCat' => {
|
'menuCat' => {
|
||||||
'test' => sub {
|
'test' => sub {
|
||||||
1;
|
1;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'oidcmetadatajson' => {
|
'oidcmetadatajson' => {
|
||||||
'test' => sub {
|
'test' => sub {
|
||||||
1;
|
1;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'oidcmetadatajwks' => {
|
'oidcmetadatajwks' => {
|
||||||
'test' => sub {
|
'test' => sub {
|
||||||
1;
|
1;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'oidcOPMetaDataNode' => {
|
'oidcOPMetaDataNode' => {
|
||||||
'test' => sub {
|
'test' => sub {
|
||||||
1;
|
1;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'oidcRPMetaDataNode' => {
|
'oidcRPMetaDataNode' => {
|
||||||
'test' => sub {
|
'test' => sub {
|
||||||
1;
|
1;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'password' => {
|
'password' => {
|
||||||
'msgFail' => '__malformedValue__',
|
'msgFail' => '__malformedValue__',
|
||||||
'test' => sub {
|
'test' => sub {
|
||||||
1;
|
1;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'pcre' => {
|
'pcre' => {
|
||||||
'form' => 'text',
|
'form' => 'text',
|
||||||
|
@ -132,7 +132,7 @@ qr/^(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return $@ ? ( 0, "__badRegexp__: $@" ) : 1;
|
return $@ ? ( 0, "__badRegexp__: $@" ) : 1;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'PerlModule' => {
|
'PerlModule' => {
|
||||||
'form' => 'text',
|
'form' => 'text',
|
||||||
|
@ -142,17 +142,17 @@ qr/^(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-
|
||||||
'portalskin' => {
|
'portalskin' => {
|
||||||
'test' => sub {
|
'test' => sub {
|
||||||
1;
|
1;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'portalskinbackground' => {
|
'portalskinbackground' => {
|
||||||
'test' => sub {
|
'test' => sub {
|
||||||
1;
|
1;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'post' => {
|
'post' => {
|
||||||
'test' => sub {
|
'test' => sub {
|
||||||
1;
|
1;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'RSAPrivateKey' => {
|
'RSAPrivateKey' => {
|
||||||
'test' => sub {
|
'test' => sub {
|
||||||
|
@ -160,7 +160,7 @@ qr/^(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-
|
||||||
m[^(?:(?:\-+\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
|
m[^(?:(?:\-+\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__' );
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'RSAPublicKey' => {
|
'RSAPublicKey' => {
|
||||||
'test' => sub {
|
'test' => sub {
|
||||||
|
@ -168,7 +168,7 @@ m[^(?:(?:\-+\s*BEGIN\s+(?:RSA\s+)?PRIVATE\s+KEY\s*\-+\r?\n)?(?:Proc-Type:.*\r?\n
|
||||||
m[^(?:(?:\-+\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
|
m[^(?:(?:\-+\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__' );
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'RSAPublicKeyOrCertificate' => {
|
'RSAPublicKeyOrCertificate' => {
|
||||||
'test' => sub {
|
'test' => sub {
|
||||||
|
@ -176,37 +176,37 @@ m[^(?:(?:\-+\s*BEGIN\s+PUBLIC\s+KEY\s*\-+\r?\n)?[a-zA-Z0-9/\+\r\n]+={0,2}(?:\r?\
|
||||||
m[^(?:(?:\-+\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
|
m[^(?:(?:\-+\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__' );
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'rule' => {
|
'rule' => {
|
||||||
'test' => sub {
|
'test' => sub {
|
||||||
1;
|
1;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'samlAssertion' => {
|
'samlAssertion' => {
|
||||||
'test' => sub {
|
'test' => sub {
|
||||||
1;
|
1;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'samlAttribute' => {
|
'samlAttribute' => {
|
||||||
'test' => sub {
|
'test' => sub {
|
||||||
1;
|
1;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'samlIDPMetaDataNode' => {
|
'samlIDPMetaDataNode' => {
|
||||||
'test' => sub {
|
'test' => sub {
|
||||||
1;
|
1;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'samlService' => {
|
'samlService' => {
|
||||||
'test' => sub {
|
'test' => sub {
|
||||||
1;
|
1;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'samlSPMetaDataNode' => {
|
'samlSPMetaDataNode' => {
|
||||||
'test' => sub {
|
'test' => sub {
|
||||||
1;
|
1;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'select' => {
|
'select' => {
|
||||||
'test' => sub {
|
'test' => sub {
|
||||||
|
@ -216,19 +216,19 @@ m[^(?:(?:\-+\s*BEGIN\s+(?:PUBLIC\s+KEY|CERTIFICATE)\s*\-+\r?\n)?[a-zA-Z0-9/\+\r\
|
||||||
return $test
|
return $test
|
||||||
? 1
|
? 1
|
||||||
: ( 1, "Invalid value '$_[0]' for this select" );
|
: ( 1, "Invalid value '$_[0]' for this select" );
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'subContainer' => {
|
'subContainer' => {
|
||||||
'keyTest' => qr/\w/,
|
'keyTest' => qr/\w/,
|
||||||
'test' => sub {
|
'test' => sub {
|
||||||
1;
|
1;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'text' => {
|
'text' => {
|
||||||
'msgFail' => '__malformedValue__',
|
'msgFail' => '__malformedValue__',
|
||||||
'test' => sub {
|
'test' => sub {
|
||||||
1;
|
1;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'trool' => {
|
'trool' => {
|
||||||
'msgFail' => '__authorizedValues__: -1, 0, 1',
|
'msgFail' => '__authorizedValues__: -1, 0, 1',
|
||||||
|
@ -1050,7 +1050,7 @@ qr/^(?:\*\.)?(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][
|
||||||
split( /\n/, $@, 0 ) )
|
split( /\n/, $@, 0 ) )
|
||||||
);
|
);
|
||||||
return $err ? ( 1, "__badExpression__: $err" ) : 1;
|
return $err ? ( 1, "__badExpression__: $err" ) : 1;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'type' => 'keyTextContainer'
|
'type' => 'keyTextContainer'
|
||||||
},
|
},
|
||||||
|
@ -1219,7 +1219,7 @@ qr/^(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-
|
||||||
and defined $conf->{$_}{$val};
|
and defined $conf->{$_}{$val};
|
||||||
}
|
}
|
||||||
return 1, "__unknownAttrOrMacro__: $val";
|
return 1, "__unknownAttrOrMacro__: $val";
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'type' => 'doubleHash'
|
'type' => 'doubleHash'
|
||||||
},
|
},
|
||||||
|
@ -1502,7 +1502,7 @@ qr/^(?:\*\.)?(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][
|
||||||
split( /\n/, $@, 0 ) )
|
split( /\n/, $@, 0 ) )
|
||||||
);
|
);
|
||||||
return $err ? ( 1, "__badExpression__: $err" ) : 1;
|
return $err ? ( 1, "__badExpression__: $err" ) : 1;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'type' => 'ruleContainer'
|
'type' => 'ruleContainer'
|
||||||
},
|
},
|
||||||
|
|
|
@ -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);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -66,11 +66,11 @@ sub types {
|
||||||
test => sub {
|
test => sub {
|
||||||
my ( $val, $conf ) = @_;
|
my ( $val, $conf ) = @_;
|
||||||
return 1
|
return 1
|
||||||
if ( defined $conf->{macros}->{$val}
|
if ( defined $conf->{macros}->{$val}
|
||||||
or $val eq '_timezone' );
|
or $val eq '_timezone' );
|
||||||
foreach ( keys %$conf ) {
|
foreach ( keys %$conf ) {
|
||||||
return 1
|
return 1
|
||||||
if ( $_ =~ /exportedvars$/i
|
if ( $_ =~ /exportedvars$/i
|
||||||
and defined $conf->{$_}->{$val} );
|
and defined $conf->{$_}->{$val} );
|
||||||
}
|
}
|
||||||
return ( 1, "__unknownAttrOrMacro__: $val" );
|
return ( 1, "__unknownAttrOrMacro__: $val" );
|
||||||
|
@ -102,27 +102,27 @@ sub types {
|
||||||
},
|
},
|
||||||
subContainer => {
|
subContainer => {
|
||||||
keyTest => qr/\w/,
|
keyTest => qr/\w/,
|
||||||
test => sub {1},
|
test => sub { 1 },
|
||||||
},
|
},
|
||||||
select => {
|
select => {
|
||||||
test => sub {
|
test => sub {
|
||||||
my $test = grep ( { $_ eq $_[0] }
|
my $test = grep ( { $_ eq $_[0] }
|
||||||
map ( { $_->{k} } @{ $_[2]->{select} } ) );
|
map ( { $_->{k} } @{ $_[2]->{select} } ) );
|
||||||
return $test
|
return $test
|
||||||
? 1
|
? 1
|
||||||
: ( 1, "Invalid value '$_[0]' for this select" );
|
: ( 1, "Invalid value '$_[0]' for this select" );
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
# 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 }
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -221,7 +221,7 @@ sub attributes {
|
||||||
checkTime => {
|
checkTime => {
|
||||||
type => 'int',
|
type => 'int',
|
||||||
documentation =>
|
documentation =>
|
||||||
'Timeout to check new configuration in local cache',
|
'Timeout to check new configuration in local cache',
|
||||||
default => 600,
|
default => 600,
|
||||||
flags => 'hp',
|
flags => 'hp',
|
||||||
},
|
},
|
||||||
|
@ -229,7 +229,7 @@ sub attributes {
|
||||||
type => 'array',
|
type => 'array',
|
||||||
documentation => 'Alterable session keys by user itself',
|
documentation => 'Alterable session keys by user itself',
|
||||||
default =>
|
default =>
|
||||||
[ '_appsListOrder', '_oidcConnectedRP', '_oidcConsents' ],
|
[ '_appsListOrder', '_oidcConnectedRP', '_oidcConsents' ],
|
||||||
},
|
},
|
||||||
configStorage => {
|
configStorage => {
|
||||||
type => 'text',
|
type => 'text',
|
||||||
|
@ -252,14 +252,12 @@ sub attributes {
|
||||||
documentation => 'Enable Cross Domain Authentication',
|
documentation => 'Enable Cross Domain Authentication',
|
||||||
},
|
},
|
||||||
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',
|
||||||
|
@ -281,7 +279,7 @@ sub attributes {
|
||||||
confirmFormMethod => {
|
confirmFormMethod => {
|
||||||
type => "select",
|
type => "select",
|
||||||
select =>
|
select =>
|
||||||
[ { k => 'get', v => 'GET' }, { k => 'post', v => 'POST' }, ],
|
[ { k => 'get', v => 'GET' }, { k => 'post', v => 'POST' }, ],
|
||||||
default => 'post',
|
default => 'post',
|
||||||
documentation => 'HTTP method for confirm page form',
|
documentation => 'HTTP method for confirm page form',
|
||||||
},
|
},
|
||||||
|
@ -301,7 +299,7 @@ sub attributes {
|
||||||
infoFormMethod => {
|
infoFormMethod => {
|
||||||
type => "select",
|
type => "select",
|
||||||
select =>
|
select =>
|
||||||
[ { k => 'get', v => 'GET' }, { k => 'post', v => 'POST' }, ],
|
[ { k => 'get', v => 'GET' }, { k => 'post', v => 'POST' }, ],
|
||||||
default => 'get',
|
default => 'get',
|
||||||
documentation => 'HTTP method for info page form',
|
documentation => 'HTTP method for info page form',
|
||||||
},
|
},
|
||||||
|
@ -316,11 +314,10 @@ sub attributes {
|
||||||
documentation => 'Use javascript for redirections',
|
documentation => 'Use javascript for redirections',
|
||||||
},
|
},
|
||||||
logoutServices => {
|
logoutServices => {
|
||||||
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,
|
||||||
|
@ -358,24 +355,24 @@ sub attributes {
|
||||||
default => '_user',
|
default => '_user',
|
||||||
help => 'monitoring.html',
|
help => 'monitoring.html',
|
||||||
documentation =>
|
documentation =>
|
||||||
'Session parameter to display connected user in portal',
|
'Session parameter to display connected user in portal',
|
||||||
},
|
},
|
||||||
redirectFormMethod => {
|
redirectFormMethod => {
|
||||||
type => "select",
|
type => "select",
|
||||||
select =>
|
select =>
|
||||||
[ { k => 'get', v => 'GET' }, { k => 'post', v => 'POST' }, ],
|
[ { k => 'get', v => 'GET' }, { k => 'post', v => 'POST' }, ],
|
||||||
default => 'get',
|
default => 'get',
|
||||||
documentation => 'HTTP method for redirect page form',
|
documentation => 'HTTP method for redirect page form',
|
||||||
},
|
},
|
||||||
reloadUrls => {
|
reloadUrls => {
|
||||||
type => 'keyTextContainer',
|
type => 'keyTextContainer',
|
||||||
help => 'configlocation.html#configuration_reload',
|
help => 'configlocation.html#configuration_reload',
|
||||||
keyTest => qr/^$Regexp::Common::URI::RFC2396::host(?::\d+)?$/,
|
keyTest => qr/^$Regexp::Common::URI::RFC2396::host(?::\d+)?$/,
|
||||||
test => $url,
|
test => $url,
|
||||||
msgFail => '__badUrl__',
|
msgFail => '__badUrl__',
|
||||||
documentation => 'URL to call on reload',
|
documentation => 'URL to call on reload',
|
||||||
},
|
},
|
||||||
portalMainLogo => {
|
portalMainLogo => {
|
||||||
type => 'text',
|
type => 'text',
|
||||||
default => 'common/logos/logo_llng_400px.png',
|
default => 'common/logos/logo_llng_400px.png',
|
||||||
documentation => 'Portal main logo path',
|
documentation => 'Portal main logo path',
|
||||||
|
@ -407,7 +404,7 @@ sub attributes {
|
||||||
skipRenewConfirmation => {
|
skipRenewConfirmation => {
|
||||||
type => 'bool',
|
type => 'bool',
|
||||||
documentation =>
|
documentation =>
|
||||||
'Avoid asking confirmation when an Issuer asks to renew auth',
|
'Avoid asking confirmation when an Issuer asks to renew auth',
|
||||||
},
|
},
|
||||||
|
|
||||||
# Loggers (ini only)
|
# Loggers (ini only)
|
||||||
|
@ -449,9 +446,9 @@ sub attributes {
|
||||||
|
|
||||||
# Manager or PSGI protected apps
|
# Manager or PSGI protected apps
|
||||||
protection => {
|
protection => {
|
||||||
type => 'text',
|
type => 'text',
|
||||||
test => qr/^(?:none|authenticate|manager|)$/,
|
test => qr/^(?:none|authenticate|manager|)$/,
|
||||||
msgFail => '__authorizedValues__: none authenticate manager',
|
msgFail => '__authorizedValues__: none authenticate manager',
|
||||||
documentation => 'Manager protection method',
|
documentation => 'Manager protection method',
|
||||||
flags => 'hm',
|
flags => 'hm',
|
||||||
},
|
},
|
||||||
|
@ -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',
|
||||||
},
|
},
|
||||||
|
@ -481,7 +477,7 @@ sub attributes {
|
||||||
type => 'bool',
|
type => 'bool',
|
||||||
default => 0,
|
default => 0,
|
||||||
documentation =>
|
documentation =>
|
||||||
'Show error if mail is not found in password reset process',
|
'Show error if mail is not found in password reset process',
|
||||||
},
|
},
|
||||||
portalOpenLinkInNewWindow => {
|
portalOpenLinkInNewWindow => {
|
||||||
type => 'bool',
|
type => 'bool',
|
||||||
|
@ -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'
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -565,13 +565,13 @@ sub attributes {
|
||||||
default => 0,
|
default => 0,
|
||||||
type => 'bool',
|
type => 'bool',
|
||||||
documentation =>
|
documentation =>
|
||||||
'Enable force to authenticate when displaying portal',
|
'Enable force to authenticate when displaying portal',
|
||||||
},
|
},
|
||||||
portalForceAuthnInterval => {
|
portalForceAuthnInterval => {
|
||||||
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,
|
||||||
|
@ -582,18 +582,18 @@ sub attributes {
|
||||||
default => 30,
|
default => 30,
|
||||||
type => 'int',
|
type => 'int',
|
||||||
documentation =>
|
documentation =>
|
||||||
'Brute force attack protection -> Tempo before try again',
|
'Brute force attack protection -> Tempo before try again',
|
||||||
},
|
},
|
||||||
bruteForceProtectionMaxAge => {
|
bruteForceProtectionMaxAge => {
|
||||||
default => 300,
|
default => 300,
|
||||||
type => 'int',
|
type => 'int',
|
||||||
documentation =>
|
documentation =>
|
||||||
'Brute force attack protection -> Max age third failed login',
|
'Brute force attack protection -> Max age third failed login',
|
||||||
},
|
},
|
||||||
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 => {
|
||||||
|
@ -629,7 +629,7 @@ sub attributes {
|
||||||
type => 'text',
|
type => 'text',
|
||||||
default => "'self'",
|
default => "'self'",
|
||||||
documentation =>
|
documentation =>
|
||||||
'Authorizated Ajax destination for Content-Security-Policy',
|
'Authorizated Ajax destination for Content-Security-Policy',
|
||||||
},
|
},
|
||||||
cspFont => {
|
cspFont => {
|
||||||
type => 'text',
|
type => 'text',
|
||||||
|
@ -652,7 +652,7 @@ sub attributes {
|
||||||
documentation => 'Regular expression to create a random password',
|
documentation => 'Regular expression to create a random password',
|
||||||
},
|
},
|
||||||
trustedDomains =>
|
trustedDomains =>
|
||||||
{ type => 'text', documentation => 'Trusted domains', },
|
{ type => 'text', documentation => 'Trusted domains', },
|
||||||
storePassword => {
|
storePassword => {
|
||||||
default => 0,
|
default => 0,
|
||||||
type => 'bool',
|
type => 'bool',
|
||||||
|
@ -788,10 +788,10 @@ sub attributes {
|
||||||
flags => 'hp',
|
flags => 'hp',
|
||||||
},
|
},
|
||||||
domain => {
|
domain => {
|
||||||
type => 'text',
|
type => 'text',
|
||||||
test => qr/^(?:$Regexp::Common::URI::RFC2396::hostname)?$/,
|
test => qr/^(?:$Regexp::Common::URI::RFC2396::hostname)?$/,
|
||||||
msgFail => '__badDomainName__',
|
msgFail => '__badDomainName__',
|
||||||
default => 'example.com',
|
default => 'example.com',
|
||||||
documentation => 'DNS domain',
|
documentation => 'DNS domain',
|
||||||
flags => 'hp',
|
flags => 'hp',
|
||||||
},
|
},
|
||||||
|
@ -886,7 +886,7 @@ sub attributes {
|
||||||
groups => {
|
groups => {
|
||||||
type => 'keyTextContainer',
|
type => 'keyTextContainer',
|
||||||
help =>
|
help =>
|
||||||
'exportedvars.html#extend_variables_using_macros_and_groups',
|
'exportedvars.html#extend_variables_using_macros_and_groups',
|
||||||
test => $perlExpr,
|
test => $perlExpr,
|
||||||
default => {},
|
default => {},
|
||||||
documentation => 'Groups',
|
documentation => 'Groups',
|
||||||
|
@ -894,7 +894,7 @@ sub attributes {
|
||||||
macros => {
|
macros => {
|
||||||
type => 'keyTextContainer',
|
type => 'keyTextContainer',
|
||||||
help =>
|
help =>
|
||||||
'exportedvars.html#extend_variables_using_macros_and_groups',
|
'exportedvars.html#extend_variables_using_macros_and_groups',
|
||||||
keyTest => qr/^[_a-zA-Z][a-zA-Z0-9_]*$/,
|
keyTest => qr/^[_a-zA-Z][a-zA-Z0-9_]*$/,
|
||||||
keyMsgFail => '__badMacroName__',
|
keyMsgFail => '__badMacroName__',
|
||||||
test => $perlExpr,
|
test => $perlExpr,
|
||||||
|
@ -915,7 +915,7 @@ sub attributes {
|
||||||
'Directory' => '/var/lib/lemonldap-ng/sessions/',
|
'Directory' => '/var/lib/lemonldap-ng/sessions/',
|
||||||
'LockDirectory' => '/var/lib/lemonldap-ng/sessions/lock/',
|
'LockDirectory' => '/var/lib/lemonldap-ng/sessions/lock/',
|
||||||
'generateModule' =>
|
'generateModule' =>
|
||||||
'Lemonldap::NG::Common::Apache::Session::Generate::SHA256',
|
'Lemonldap::NG::Common::Apache::Session::Generate::SHA256',
|
||||||
},
|
},
|
||||||
documentation => 'Session backend module options',
|
documentation => 'Session backend module options',
|
||||||
flags => 'hp',
|
flags => 'hp',
|
||||||
|
@ -1014,11 +1014,11 @@ sub attributes {
|
||||||
test => sub {
|
test => sub {
|
||||||
my ( $val, $conf ) = @_;
|
my ( $val, $conf ) = @_;
|
||||||
return 1
|
return 1
|
||||||
if ( defined $conf->{macros}->{$val}
|
if ( defined $conf->{macros}->{$val}
|
||||||
or $val eq '_timezone' );
|
or $val eq '_timezone' );
|
||||||
foreach ( keys %$conf ) {
|
foreach ( keys %$conf ) {
|
||||||
return 1
|
return 1
|
||||||
if ( $_ =~ /exportedvars$/i
|
if ( $_ =~ /exportedvars$/i
|
||||||
and defined $conf->{$_}->{$val} );
|
and defined $conf->{$_}->{$val} );
|
||||||
}
|
}
|
||||||
return ( 1, "__unknownAttrOrMacro__: $val" );
|
return ( 1, "__unknownAttrOrMacro__: $val" );
|
||||||
|
@ -1034,10 +1034,9 @@ sub attributes {
|
||||||
documentation => 'Send a mail when password is changed',
|
documentation => 'Send a mail when password is changed',
|
||||||
},
|
},
|
||||||
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,
|
||||||
|
@ -1047,7 +1046,7 @@ sub attributes {
|
||||||
|
|
||||||
# Mails
|
# Mails
|
||||||
mailBody =>
|
mailBody =>
|
||||||
{ type => 'longtext', documentation => 'Custom mail body', },
|
{ type => 'longtext', documentation => 'Custom mail body', },
|
||||||
mailCharset => {
|
mailCharset => {
|
||||||
type => 'text',
|
type => 'text',
|
||||||
default => 'utf-8',
|
default => 'utf-8',
|
||||||
|
@ -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',
|
||||||
|
@ -1090,7 +1088,7 @@ sub attributes {
|
||||||
SMTPServer => {
|
SMTPServer => {
|
||||||
type => 'text',
|
type => 'text',
|
||||||
default => '',
|
default => '',
|
||||||
test => qr/^(?:$Regexp::Common::URI::RFC2396::host(?::\d+)?)?$/,
|
test => qr/^(?:$Regexp::Common::URI::RFC2396::host(?::\d+)?)?$/,
|
||||||
documentation => 'SMTP Server',
|
documentation => 'SMTP Server',
|
||||||
},
|
},
|
||||||
SMTPPort => {
|
SMTPPort => {
|
||||||
|
@ -1185,7 +1183,7 @@ sub attributes {
|
||||||
u2fAuthnLevel => {
|
u2fAuthnLevel => {
|
||||||
type => 'int',
|
type => 'int',
|
||||||
documentation =>
|
documentation =>
|
||||||
'Authentication level for users authentified by password+U2F'
|
'Authentication level for users authentified by password+U2F'
|
||||||
},
|
},
|
||||||
u2fUserCanRemoveKey => {
|
u2fUserCanRemoveKey => {
|
||||||
type => 'bool',
|
type => 'bool',
|
||||||
|
@ -1207,7 +1205,7 @@ sub attributes {
|
||||||
totp2fAuthnLevel => {
|
totp2fAuthnLevel => {
|
||||||
type => 'int',
|
type => 'int',
|
||||||
documentation =>
|
documentation =>
|
||||||
'Authentication level for users authentified by password+TOTP'
|
'Authentication level for users authentified by password+TOTP'
|
||||||
},
|
},
|
||||||
totp2fIssuer => {
|
totp2fIssuer => {
|
||||||
type => 'text',
|
type => 'text',
|
||||||
|
@ -1232,7 +1230,7 @@ sub attributes {
|
||||||
type => 'bool',
|
type => 'bool',
|
||||||
default => 0,
|
default => 0,
|
||||||
documentation =>
|
documentation =>
|
||||||
'Display existing TOTP secret in registration form',
|
'Display existing TOTP secret in registration form',
|
||||||
},
|
},
|
||||||
totp2fUserCanChangeKey => {
|
totp2fUserCanChangeKey => {
|
||||||
type => 'bool',
|
type => 'bool',
|
||||||
|
@ -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',
|
||||||
|
@ -1424,7 +1422,7 @@ sub attributes {
|
||||||
exportedAttr => {
|
exportedAttr => {
|
||||||
type => 'text',
|
type => 'text',
|
||||||
documentation =>
|
documentation =>
|
||||||
'List of attributes to export by SOAP or REST servers',
|
'List of attributes to export by SOAP or REST servers',
|
||||||
},
|
},
|
||||||
wsdlServer => {
|
wsdlServer => {
|
||||||
type => 'bool',
|
type => 'bool',
|
||||||
|
@ -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__',
|
||||||
|
@ -1461,15 +1459,15 @@ sub attributes {
|
||||||
my $s = $val;
|
my $s = $val;
|
||||||
if ( $s =~ s/^logout(?:_(?:sso|app(?:_sso)?))?\s*// ) {
|
if ( $s =~ s/^logout(?:_(?:sso|app(?:_sso)?))?\s*// ) {
|
||||||
return $s =~ m{^(?:https?://.*)?$}
|
return $s =~ m{^(?:https?://.*)?$}
|
||||||
? (1)
|
? (1)
|
||||||
: ( 0, '__badUrl__' );
|
: ( 0, '__badUrl__' );
|
||||||
}
|
}
|
||||||
$s =~ s/\b(accept|deny|unprotect|skip)\b/1/g;
|
$s =~ s/\b(accept|deny|unprotect|skip)\b/1/g;
|
||||||
no warnings( 'redefine', 'uninitialized' );
|
no warnings( 'redefine', 'uninitialized' );
|
||||||
eval $s;
|
eval $s;
|
||||||
my $err = join( '',
|
my $err = join( '',
|
||||||
grep { $_ =~ /Undefined subroutine/ ? () : $_ }
|
grep { $_ =~ /Undefined subroutine/ ? () : $_ }
|
||||||
split( /\n/, $@ ) );
|
split( /\n/, $@ ) );
|
||||||
return $err ? ( 1, "__badExpression__: $err" ) : (1);
|
return $err ? ( 1, "__badExpression__: $err" ) : (1);
|
||||||
},
|
},
|
||||||
msgFail => '__badExpression__',
|
msgFail => '__badExpression__',
|
||||||
|
@ -1495,9 +1493,9 @@ sub attributes {
|
||||||
eval $s;
|
eval $s;
|
||||||
my $err = join( '',
|
my $err = join( '',
|
||||||
grep { $_ =~ /Undefined subroutine/ ? () : $_ }
|
grep { $_ =~ /Undefined subroutine/ ? () : $_ }
|
||||||
split( /\n/, $@ ) );
|
split( /\n/, $@ ) );
|
||||||
return $err ? ( 1, "__badExpression__: $err" ) : (1);
|
return $err ? ( 1, "__badExpression__: $err" ) : (1);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
documentation => 'Virtualhost headers',
|
documentation => 'Virtualhost headers',
|
||||||
flags => 'h',
|
flags => 'h',
|
||||||
|
@ -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',
|
||||||
|
@ -1603,7 +1601,7 @@ sub attributes {
|
||||||
|
|
||||||
# CAS IDP
|
# CAS IDP
|
||||||
casAttr =>
|
casAttr =>
|
||||||
{ type => 'text', documentation => 'Pivot attribute for CAS', },
|
{ type => 'text', documentation => 'Pivot attribute for CAS', },
|
||||||
casAttributes => {
|
casAttributes => {
|
||||||
type => 'keyTextContainer',
|
type => 'keyTextContainer',
|
||||||
documentation => 'CAS exported attributes',
|
documentation => 'CAS exported attributes',
|
||||||
|
@ -1762,7 +1760,7 @@ sub attributes {
|
||||||
samlAttributeAuthorityDescriptorAttributeServiceSOAP => {
|
samlAttributeAuthorityDescriptorAttributeServiceSOAP => {
|
||||||
type => 'samlService',
|
type => 'samlService',
|
||||||
default => 'urn:oasis:names:tc:SAML:2.0:bindings:SOAP;'
|
default => 'urn:oasis:names:tc:SAML:2.0:bindings:SOAP;'
|
||||||
. '#PORTAL#/saml/AA/SOAP;',
|
. '#PORTAL#/saml/AA/SOAP;',
|
||||||
documentation => 'SAML Attribute Authority SOAP',
|
documentation => 'SAML Attribute Authority SOAP',
|
||||||
},
|
},
|
||||||
samlServicePrivateKeySig => {
|
samlServicePrivateKeySig => {
|
||||||
|
@ -1803,7 +1801,7 @@ sub attributes {
|
||||||
type => 'bool',
|
type => 'bool',
|
||||||
default => 0,
|
default => 0,
|
||||||
documentation =>
|
documentation =>
|
||||||
'Use certificate instead of public key in SAML responses',
|
'Use certificate instead of public key in SAML responses',
|
||||||
},
|
},
|
||||||
samlIdPResolveCookie => {
|
samlIdPResolveCookie => {
|
||||||
type => 'text',
|
type => 'text',
|
||||||
|
@ -1832,7 +1830,7 @@ sub attributes {
|
||||||
type => 'int',
|
type => 'int',
|
||||||
default => 3,
|
default => 3,
|
||||||
documentation =>
|
documentation =>
|
||||||
'SAML authn context password protected transport level',
|
'SAML authn context password protected transport level',
|
||||||
},
|
},
|
||||||
samlAuthnContextMapTLSClient => {
|
samlAuthnContextMapTLSClient => {
|
||||||
type => 'int',
|
type => 'int',
|
||||||
|
@ -1901,45 +1899,45 @@ sub attributes {
|
||||||
samlIDPSSODescriptorSingleSignOnServiceHTTPRedirect => {
|
samlIDPSSODescriptorSingleSignOnServiceHTTPRedirect => {
|
||||||
type => 'samlService',
|
type => 'samlService',
|
||||||
default => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect;'
|
default => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect;'
|
||||||
. '#PORTAL#/saml/singleSignOn;',
|
. '#PORTAL#/saml/singleSignOn;',
|
||||||
documentation => 'SAML IDP SSO HTTP Redirect',
|
documentation => 'SAML IDP SSO HTTP Redirect',
|
||||||
},
|
},
|
||||||
samlIDPSSODescriptorSingleSignOnServiceHTTPPost => {
|
samlIDPSSODescriptorSingleSignOnServiceHTTPPost => {
|
||||||
type => 'samlService',
|
type => 'samlService',
|
||||||
default => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST;'
|
default => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST;'
|
||||||
. '#PORTAL#/saml/singleSignOn;',
|
. '#PORTAL#/saml/singleSignOn;',
|
||||||
documentation => 'SAML IDP SSO HTTP POST',
|
documentation => 'SAML IDP SSO HTTP POST',
|
||||||
},
|
},
|
||||||
samlIDPSSODescriptorSingleSignOnServiceHTTPArtifact => {
|
samlIDPSSODescriptorSingleSignOnServiceHTTPArtifact => {
|
||||||
type => 'samlService',
|
type => 'samlService',
|
||||||
default => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact;'
|
default => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact;'
|
||||||
. '#PORTAL#/saml/singleSignOnArtifact;',
|
. '#PORTAL#/saml/singleSignOnArtifact;',
|
||||||
documentation => 'SAML IDP SSO HTTP Artifact',
|
documentation => 'SAML IDP SSO HTTP Artifact',
|
||||||
},
|
},
|
||||||
samlIDPSSODescriptorSingleLogoutServiceHTTPRedirect => {
|
samlIDPSSODescriptorSingleLogoutServiceHTTPRedirect => {
|
||||||
type => 'samlService',
|
type => 'samlService',
|
||||||
default => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect;'
|
default => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect;'
|
||||||
. '#PORTAL#/saml/singleLogout;'
|
. '#PORTAL#/saml/singleLogout;'
|
||||||
. '#PORTAL#/saml/singleLogoutReturn',
|
. '#PORTAL#/saml/singleLogoutReturn',
|
||||||
documentation => 'SAML IDP SLO HTTP Redirect',
|
documentation => 'SAML IDP SLO HTTP Redirect',
|
||||||
},
|
},
|
||||||
samlIDPSSODescriptorSingleLogoutServiceHTTPPost => {
|
samlIDPSSODescriptorSingleLogoutServiceHTTPPost => {
|
||||||
type => 'samlService',
|
type => 'samlService',
|
||||||
default => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST;'
|
default => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST;'
|
||||||
. '#PORTAL#/saml/singleLogout;'
|
. '#PORTAL#/saml/singleLogout;'
|
||||||
. '#PORTAL#/saml/singleLogoutReturn',
|
. '#PORTAL#/saml/singleLogoutReturn',
|
||||||
documentation => 'SAML IDP SLO HTTP POST',
|
documentation => 'SAML IDP SLO HTTP POST',
|
||||||
},
|
},
|
||||||
samlIDPSSODescriptorSingleLogoutServiceSOAP => {
|
samlIDPSSODescriptorSingleLogoutServiceSOAP => {
|
||||||
type => 'samlService',
|
type => 'samlService',
|
||||||
default => 'urn:oasis:names:tc:SAML:2.0:bindings:SOAP;'
|
default => 'urn:oasis:names:tc:SAML:2.0:bindings:SOAP;'
|
||||||
. '#PORTAL#/saml/singleLogoutSOAP;',
|
. '#PORTAL#/saml/singleLogoutSOAP;',
|
||||||
documentation => 'SAML IDP SLO SOAP',
|
documentation => 'SAML IDP SLO SOAP',
|
||||||
},
|
},
|
||||||
samlIDPSSODescriptorArtifactResolutionServiceArtifact => {
|
samlIDPSSODescriptorArtifactResolutionServiceArtifact => {
|
||||||
type => 'samlAssertion',
|
type => 'samlAssertion',
|
||||||
default => '1;0;urn:oasis:names:tc:SAML:2.0:bindings:SOAP;'
|
default => '1;0;urn:oasis:names:tc:SAML:2.0:bindings:SOAP;'
|
||||||
. '#PORTAL#/saml/artifact',
|
. '#PORTAL#/saml/artifact',
|
||||||
documentation => 'SAML IDP artifact resolution service',
|
documentation => 'SAML IDP artifact resolution service',
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -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' },
|
||||||
|
@ -2152,40 +2151,40 @@ sub attributes {
|
||||||
samlSPSSODescriptorSingleLogoutServiceHTTPRedirect => {
|
samlSPSSODescriptorSingleLogoutServiceHTTPRedirect => {
|
||||||
type => 'samlService',
|
type => 'samlService',
|
||||||
default => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect;'
|
default => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect;'
|
||||||
. '#PORTAL#/saml/proxySingleLogout;'
|
. '#PORTAL#/saml/proxySingleLogout;'
|
||||||
. '#PORTAL#/saml/proxySingleLogoutReturn',
|
. '#PORTAL#/saml/proxySingleLogoutReturn',
|
||||||
documentation => 'SAML SP SLO HTTP Redirect',
|
documentation => 'SAML SP SLO HTTP Redirect',
|
||||||
},
|
},
|
||||||
samlSPSSODescriptorSingleLogoutServiceHTTPPost => {
|
samlSPSSODescriptorSingleLogoutServiceHTTPPost => {
|
||||||
type => 'samlService',
|
type => 'samlService',
|
||||||
default => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST;'
|
default => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST;'
|
||||||
. '#PORTAL#/saml/proxySingleLogout;'
|
. '#PORTAL#/saml/proxySingleLogout;'
|
||||||
. '#PORTAL#/saml/proxySingleLogoutReturn',
|
. '#PORTAL#/saml/proxySingleLogoutReturn',
|
||||||
documentation => 'SAML SP SLO HTTP POST',
|
documentation => 'SAML SP SLO HTTP POST',
|
||||||
},
|
},
|
||||||
samlSPSSODescriptorSingleLogoutServiceSOAP => {
|
samlSPSSODescriptorSingleLogoutServiceSOAP => {
|
||||||
type => 'samlService',
|
type => 'samlService',
|
||||||
default => 'urn:oasis:names:tc:SAML:2.0:bindings:SOAP;'
|
default => 'urn:oasis:names:tc:SAML:2.0:bindings:SOAP;'
|
||||||
. '#PORTAL#/saml/proxySingleLogoutSOAP;',
|
. '#PORTAL#/saml/proxySingleLogoutSOAP;',
|
||||||
documentation => 'SAML SP SLO SOAP',
|
documentation => 'SAML SP SLO SOAP',
|
||||||
},
|
},
|
||||||
samlSPSSODescriptorAssertionConsumerServiceHTTPArtifact => {
|
samlSPSSODescriptorAssertionConsumerServiceHTTPArtifact => {
|
||||||
type => 'samlAssertion',
|
type => 'samlAssertion',
|
||||||
default =>
|
default =>
|
||||||
'1;0;urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact;'
|
'1;0;urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact;'
|
||||||
. '#PORTAL#/saml/proxySingleSignOnArtifact',
|
. '#PORTAL#/saml/proxySingleSignOnArtifact',
|
||||||
documentation => 'SAML SP ACS HTTP artifact',
|
documentation => 'SAML SP ACS HTTP artifact',
|
||||||
},
|
},
|
||||||
samlSPSSODescriptorAssertionConsumerServiceHTTPPost => {
|
samlSPSSODescriptorAssertionConsumerServiceHTTPPost => {
|
||||||
type => 'samlAssertion',
|
type => 'samlAssertion',
|
||||||
default => '0;1;urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST;'
|
default => '0;1;urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST;'
|
||||||
. '#PORTAL#/saml/proxySingleSignOnPost',
|
. '#PORTAL#/saml/proxySingleSignOnPost',
|
||||||
documentation => 'SAML SP ACS HTTP POST',
|
documentation => 'SAML SP ACS HTTP POST',
|
||||||
},
|
},
|
||||||
samlSPSSODescriptorArtifactResolutionServiceArtifact => {
|
samlSPSSODescriptorArtifactResolutionServiceArtifact => {
|
||||||
type => 'samlAssertion',
|
type => 'samlAssertion',
|
||||||
default => '1;0;urn:oasis:names:tc:SAML:2.0:bindings:SOAP;'
|
default => '1;0;urn:oasis:names:tc:SAML:2.0:bindings:SOAP;'
|
||||||
. '#PORTAL#/saml/artifact',
|
. '#PORTAL#/saml/artifact',
|
||||||
documentation => 'SAML SP artifact resolution service ',
|
documentation => 'SAML SP artifact resolution service ',
|
||||||
},
|
},
|
||||||
samlSPMetaDataOptionsNameIDFormat => {
|
samlSPMetaDataOptionsNameIDFormat => {
|
||||||
|
@ -2277,8 +2276,8 @@ sub attributes {
|
||||||
{ k => 'Demo', v => 'Demonstration' },
|
{ k => 'Demo', v => 'Demonstration' },
|
||||||
{ k => 'Choice', v => 'authChoice' },
|
{ k => 'Choice', v => 'authChoice' },
|
||||||
{ k => 'Combination', v => 'combineMods' },
|
{ k => 'Combination', v => 'combineMods' },
|
||||||
{ k => 'CAS', v => 'Central Authentication Service (CAS)' },
|
{ k => 'CAS', v => 'Central Authentication Service (CAS)' },
|
||||||
{ k => 'OpenID', v => 'OpenID' },
|
{ k => 'OpenID', v => 'OpenID' },
|
||||||
{ k => 'OpenIDConnect', v => 'OpenID Connect' },
|
{ k => 'OpenIDConnect', v => 'OpenID Connect' },
|
||||||
{ k => 'SAML', v => 'SAML v2' },
|
{ k => 'SAML', v => 'SAML v2' },
|
||||||
{ k => 'Proxy', v => 'Proxy' },
|
{ k => 'Proxy', v => 'Proxy' },
|
||||||
|
@ -2341,7 +2340,7 @@ sub attributes {
|
||||||
type => 'text',
|
type => 'text',
|
||||||
default => 'TOTP,U2F,Yubikey',
|
default => 'TOTP,U2F,Yubikey',
|
||||||
documentation =>
|
documentation =>
|
||||||
'Available self-registration modules for second factor',
|
'Available self-registration modules for second factor',
|
||||||
},
|
},
|
||||||
|
|
||||||
# DEMO
|
# DEMO
|
||||||
|
@ -2414,9 +2413,9 @@ 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;
|
||||||
},
|
},
|
||||||
|
@ -2474,7 +2473,7 @@ sub attributes {
|
||||||
documentation => 'LDAP filter for mail search'
|
documentation => 'LDAP filter for mail search'
|
||||||
},
|
},
|
||||||
LDAPFilter =>
|
LDAPFilter =>
|
||||||
{ type => 'text', documentation => 'Default LDAP filter' },
|
{ type => 'text', documentation => 'Default LDAP filter' },
|
||||||
AuthLDAPFilter => {
|
AuthLDAPFilter => {
|
||||||
type => 'text',
|
type => 'text',
|
||||||
documentation => 'LDAP filter for auth search'
|
documentation => 'LDAP filter for auth search'
|
||||||
|
@ -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',
|
||||||
},
|
},
|
||||||
|
@ -2719,7 +2718,7 @@ sub attributes {
|
||||||
},
|
},
|
||||||
linkedInUserField => { type => 'text', default => 'emailAddress' },
|
linkedInUserField => { type => 'text', default => 'emailAddress' },
|
||||||
linkedInScope =>
|
linkedInScope =>
|
||||||
{ type => 'text', default => 'r_basicprofile r_emailaddress' },
|
{ type => 'text', default => 'r_basicprofile r_emailaddress' },
|
||||||
|
|
||||||
# WebID
|
# WebID
|
||||||
webIDAuthnLevel => {
|
webIDAuthnLevel => {
|
||||||
|
@ -2759,15 +2758,15 @@ sub attributes {
|
||||||
dbiPasswordMailCol => { type => 'text', },
|
dbiPasswordMailCol => { type => 'text', },
|
||||||
userPivot => { type => 'text', },
|
userPivot => { type => 'text', },
|
||||||
dbiAuthPasswordHash =>
|
dbiAuthPasswordHash =>
|
||||||
{ type => 'text', help => 'authdbi.html#password', },
|
{ type => 'text', help => 'authdbi.html#password', },
|
||||||
dbiDynamicHashEnabled =>
|
dbiDynamicHashEnabled =>
|
||||||
{ type => 'bool', help => 'authdbi.html#password', },
|
{ type => 'bool', help => 'authdbi.html#password', },
|
||||||
dbiDynamicHashValidSchemes =>
|
dbiDynamicHashValidSchemes =>
|
||||||
{ type => 'text', help => 'authdbi.html#password', },
|
{ type => 'text', help => 'authdbi.html#password', },
|
||||||
dbiDynamicHashValidSaltedSchemes =>
|
dbiDynamicHashValidSaltedSchemes =>
|
||||||
{ type => 'text', help => 'authdbi.html#password', },
|
{ type => 'text', help => 'authdbi.html#password', },
|
||||||
dbiDynamicHashNewPasswordScheme =>
|
dbiDynamicHashNewPasswordScheme =>
|
||||||
{ type => 'text', help => 'authdbi.html#password', },
|
{ type => 'text', help => 'authdbi.html#password', },
|
||||||
dbiExportedVars => {
|
dbiExportedVars => {
|
||||||
type => 'keyTextContainer',
|
type => 'keyTextContainer',
|
||||||
keyTest => qr/^!?[a-zA-Z][a-zA-Z0-9_-]*$/,
|
keyTest => qr/^!?[a-zA-Z][a-zA-Z0-9_-]*$/,
|
||||||
|
@ -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' },
|
||||||
|
@ -2933,8 +2937,8 @@ sub attributes {
|
||||||
{ k => 'Twitter', v => 'Twitter' },
|
{ k => 'Twitter', v => 'Twitter' },
|
||||||
{ k => 'WebID', v => 'WebID' },
|
{ k => 'WebID', v => 'WebID' },
|
||||||
{ k => 'Demo', v => 'Demonstration' },
|
{ k => 'Demo', v => 'Demonstration' },
|
||||||
{ k => 'CAS', v => 'Central Authentication Service (CAS)' },
|
{ k => 'CAS', v => 'Central Authentication Service (CAS)' },
|
||||||
{ k => 'OpenID', v => 'OpenID' },
|
{ k => 'OpenID', v => 'OpenID' },
|
||||||
{ k => 'OpenIDConnect', v => 'OpenID Connect' },
|
{ k => 'OpenIDConnect', v => 'OpenID Connect' },
|
||||||
{ k => 'SAML', v => 'SAML v2' },
|
{ k => 'SAML', v => 'SAML v2' },
|
||||||
{ k => 'Proxy', v => 'Proxy' },
|
{ k => 'Proxy', v => 'Proxy' },
|
||||||
|
@ -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', },
|
||||||
|
@ -3055,10 +3058,9 @@ sub attributes {
|
||||||
documentation => 'OpenID Connect Signature Key ID',
|
documentation => 'OpenID Connect Signature Key ID',
|
||||||
},
|
},
|
||||||
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,12 +3090,12 @@ 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',
|
||||||
help =>
|
help =>
|
||||||
'idpopenidconnect.html#configuration_of_relying_party_in_llng',
|
'idpopenidconnect.html#configuration_of_relying_party_in_llng',
|
||||||
},
|
},
|
||||||
oidcOPMetaDataOptions => { type => 'subContainer', },
|
oidcOPMetaDataOptions => { type => 'subContainer', },
|
||||||
oidcRPMetaDataOptions => { type => 'subContainer', },
|
oidcRPMetaDataOptions => { type => 'subContainer', },
|
||||||
|
@ -3115,7 +3117,7 @@ sub attributes {
|
||||||
oidcOPMetaDataOptionsClientID => { type => 'text', },
|
oidcOPMetaDataOptionsClientID => { type => 'text', },
|
||||||
oidcOPMetaDataOptionsClientSecret => { type => 'password', },
|
oidcOPMetaDataOptionsClientSecret => { type => 'password', },
|
||||||
oidcOPMetaDataOptionsScope =>
|
oidcOPMetaDataOptionsScope =>
|
||||||
{ type => 'text', default => 'openid profile' },
|
{ type => 'text', default => 'openid profile' },
|
||||||
oidcOPMetaDataOptionsDisplay => {
|
oidcOPMetaDataOptionsDisplay => {
|
||||||
type => 'select',
|
type => 'select',
|
||||||
select => [
|
select => [
|
||||||
|
@ -3140,10 +3142,9 @@ sub attributes {
|
||||||
default => 'client_secret_post',
|
default => 'client_secret_post',
|
||||||
},
|
},
|
||||||
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', },
|
||||||
oidcOPMetaDataOptionsStoreIDToken => { type => 'bool', default => 0 },
|
oidcOPMetaDataOptionsStoreIDToken => { type => 'bool', default => 0 },
|
||||||
|
@ -3182,12 +3183,12 @@ sub attributes {
|
||||||
default => 'HS512',
|
default => 'HS512',
|
||||||
},
|
},
|
||||||
oidcRPMetaDataOptionsIDTokenExpiration =>
|
oidcRPMetaDataOptionsIDTokenExpiration =>
|
||||||
{ type => 'int', default => 3600 },
|
{ type => 'int', default => 3600 },
|
||||||
oidcRPMetaDataOptionsAccessTokenExpiration =>
|
oidcRPMetaDataOptionsAccessTokenExpiration =>
|
||||||
{ type => 'int', default => 3600 },
|
{ type => 'int', default => 3600 },
|
||||||
oidcRPMetaDataOptionsRedirectUris => { type => 'text', },
|
oidcRPMetaDataOptionsRedirectUris => { type => 'text', },
|
||||||
oidcRPMetaDataOptionsExtraClaims =>
|
oidcRPMetaDataOptionsExtraClaims =>
|
||||||
{ type => 'keyTextContainer', default => {} },
|
{ type => 'keyTextContainer', default => {} },
|
||||||
oidcRPMetaDataOptionsBypassConsent => {
|
oidcRPMetaDataOptionsBypassConsent => {
|
||||||
type => 'bool',
|
type => 'bool',
|
||||||
help => 'openidconnectclaims.html',
|
help => 'openidconnectclaims.html',
|
||||||
|
|
|
@ -69,7 +69,7 @@ has confChanged => (
|
||||||
);
|
);
|
||||||
|
|
||||||
# Properties required during build
|
# Properties required during build
|
||||||
has refConf => ( is => 'ro', isa => 'HashRef', required => 1 );
|
has refConf => ( is => 'ro', isa => 'HashRef', required => 1 );
|
||||||
has req => ( is => 'ro', required => 1 );
|
has req => ( is => 'ro', required => 1 );
|
||||||
has newConf => ( is => 'rw', isa => 'HashRef' );
|
has newConf => ( is => 'rw', isa => 'HashRef' );
|
||||||
has tree => ( is => 'rw', isa => 'ArrayRef' );
|
has tree => ( is => 'rw', isa => 'ArrayRef' );
|
||||||
|
@ -158,7 +158,7 @@ sub _scanNodes {
|
||||||
hdebug("Looking to $name");
|
hdebug("Looking to $name");
|
||||||
|
|
||||||
# subnode
|
# subnode
|
||||||
my $subNodes = $leaf->{nodes} // $leaf->{_nodes};
|
my $subNodes = $leaf->{nodes} // $leaf->{_nodes};
|
||||||
my $subNodesCond = $leaf->{nodes_cond} // $leaf->{_nodes_cond};
|
my $subNodesCond = $leaf->{nodes_cond} // $leaf->{_nodes_cond};
|
||||||
|
|
||||||
##################################
|
##################################
|
||||||
|
@ -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} };
|
||||||
|
@ -1059,15 +1060,15 @@ sub _unitTest {
|
||||||
or $attr->{type} =~ /Container$/ )
|
or $attr->{type} =~ /Container$/ )
|
||||||
{
|
{
|
||||||
my $keyMsg = $attr->{keyMsgFail} // $type->{keyMsgFail};
|
my $keyMsg = $attr->{keyMsgFail} // $type->{keyMsgFail};
|
||||||
my $msg = $attr->{msgFail} // $type->{msgFail};
|
my $msg = $attr->{msgFail} // $type->{msgFail};
|
||||||
$res = 0
|
$res = 0
|
||||||
unless (
|
unless (
|
||||||
$self->_execTest(
|
$self->_execTest(
|
||||||
{
|
{
|
||||||
keyTest => $attr->{keyTest} // $type->{keyTest},
|
keyTest => $attr->{keyTest} // $type->{keyTest},
|
||||||
keyMsgFail => $attr->{keyMsgFail}
|
keyMsgFail => $attr->{keyMsgFail}
|
||||||
// $type->{keyMsgFail},
|
// $type->{keyMsgFail},
|
||||||
test => $attr->{test} // $type->{test},
|
test => $attr->{test} // $type->{test},
|
||||||
msgFail => $attr->{msgFail} // $type->{msgFail},
|
msgFail => $attr->{msgFail} // $type->{msgFail},
|
||||||
},
|
},
|
||||||
$conf->{$key},
|
$conf->{$key},
|
||||||
|
|
|
@ -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}"
|
||||||
)
|
)
|
||||||
|
@ -42,7 +43,7 @@ sub tests {
|
||||||
|
|
||||||
# Checking for ending slash
|
# Checking for ending slash
|
||||||
$conf->{portal} .= '/'
|
$conf->{portal} .= '/'
|
||||||
unless ( $conf->{portal} =~ qr#/$# );
|
unless ( $conf->{portal} =~ qr#/$# );
|
||||||
|
|
||||||
# Deleting trailing ending slash
|
# Deleting trailing ending slash
|
||||||
my $regex = qr#/+$#;
|
my $regex = qr#/+$#;
|
||||||
|
@ -60,10 +61,11 @@ 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"
|
||||||
: undef
|
: undef
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@ -77,9 +79,9 @@ sub tests {
|
||||||
}
|
}
|
||||||
if (@pb) {
|
if (@pb) {
|
||||||
return ( 0,
|
return ( 0,
|
||||||
'Virtual hosts '
|
'Virtual hosts '
|
||||||
. join( ', ', @pb )
|
. join( ', ', @pb )
|
||||||
. " contain a port, this is not allowed" );
|
. " contain a port, this is not allowed" );
|
||||||
}
|
}
|
||||||
else { return 1; }
|
else { return 1; }
|
||||||
},
|
},
|
||||||
|
@ -92,9 +94,9 @@ sub tests {
|
||||||
}
|
}
|
||||||
if (@pb) {
|
if (@pb) {
|
||||||
return ( 0,
|
return ( 0,
|
||||||
'Virtual hosts '
|
'Virtual hosts '
|
||||||
. join( ', ', @pb )
|
. join( ', ', @pb )
|
||||||
. " must be in lower case" );
|
. " must be in lower case" );
|
||||||
}
|
}
|
||||||
else { return 1; }
|
else { return 1; }
|
||||||
},
|
},
|
||||||
|
@ -102,12 +104,12 @@ sub tests {
|
||||||
# Check if "userDB" and "authentication" are consistent
|
# Check if "userDB" and "authentication" are consistent
|
||||||
authAndUserDBConsistency => sub {
|
authAndUserDBConsistency => sub {
|
||||||
foreach
|
foreach
|
||||||
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,29 +119,30 @@ 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};
|
||||||
$v =~ s/^$//;
|
$v =~ s/^$//;
|
||||||
next if ( $v =~ /^_/ );
|
next if ( $v =~ /^_/ );
|
||||||
push @tmp,
|
push @tmp,
|
||||||
$k
|
$k
|
||||||
unless (
|
unless (
|
||||||
defined(
|
defined(
|
||||||
$conf->{exportedVars}->{$v}
|
$conf->{exportedVars}->{$v}
|
||||||
or defined( $conf->{macros}->{$v} )
|
or defined( $conf->{macros}->{$v} )
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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,18 +154,18 @@ 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,10 +185,11 @@ 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,40 +198,40 @@ 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 {
|
||||||
tie %h, 'Lemonldap::NG::Common::Apache::Session', undef,
|
tie %h, 'Lemonldap::NG::Common::Apache::Session', undef,
|
||||||
{
|
{
|
||||||
%{ $conf->{globalStorageOptions} },
|
%{ $conf->{globalStorageOptions} },
|
||||||
backend => $conf->{globalStorage}
|
backend => $conf->{globalStorage}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
return ( -1, "Unable to create a session ($@)" )
|
return ( -1, "Unable to create a session ($@)" )
|
||||||
if ( $@ or not tied(%h) );
|
if ( $@ or not tied(%h) );
|
||||||
eval {
|
eval {
|
||||||
$h{a} = 1;
|
$h{a} = 1;
|
||||||
$id = $h{_session_id} or return ( -1, 'No _session_id' );
|
$id = $h{_session_id} or return ( -1, 'No _session_id' );
|
||||||
untie(%h);
|
untie(%h);
|
||||||
tie %h, 'Lemonldap::NG::Common::Apache::Session', $id,
|
tie %h, 'Lemonldap::NG::Common::Apache::Session', $id,
|
||||||
{
|
{
|
||||||
%{ $conf->{globalStorageOptions} },
|
%{ $conf->{globalStorageOptions} },
|
||||||
backend => $conf->{globalStorage}
|
backend => $conf->{globalStorage}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
return ( -1, "Unable to insert data ($@)" ) if ($@);
|
return ( -1, "Unable to insert data ($@)" ) if ($@);
|
||||||
return ( -1, "Unable to recover data stored" )
|
return ( -1, "Unable to recover data stored" )
|
||||||
unless ( $h{a} == 1 );
|
unless ( $h{a} == 1 );
|
||||||
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,8 +241,9 @@ 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
|
(
|
||||||
and $cn ne $conf->{cookieName}
|
$cn
|
||||||
|
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'
|
||||||
: ()
|
: ()
|
||||||
)
|
)
|
||||||
|
@ -250,9 +254,9 @@ sub tests {
|
||||||
cookieTTL => sub {
|
cookieTTL => sub {
|
||||||
return 1 unless ( defined $conf->{cookieExpiration} );
|
return 1 unless ( defined $conf->{cookieExpiration} );
|
||||||
return ( 0, "Cookie TTL must be higher than one minute" )
|
return ( 0, "Cookie TTL must be higher than one minute" )
|
||||||
unless ( $conf->{cookieExpiration} > 60 );
|
unless ( $conf->{cookieExpiration} > 60 );
|
||||||
return ( 1, "Cookie TTL should be higher or equal than one hour" )
|
return ( 1, "Cookie TTL should be higher or equal than one hour" )
|
||||||
unless ( $conf->{cookieExpiration} >= 3600
|
unless ( $conf->{cookieExpiration} >= 3600
|
||||||
|| $conf->{cookieExpiration} == 0 );
|
|| $conf->{cookieExpiration} == 0 );
|
||||||
|
|
||||||
# Return
|
# Return
|
||||||
|
@ -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'
|
||||||
: ''
|
: ''
|
||||||
)
|
)
|
||||||
|
@ -279,21 +284,21 @@ sub tests {
|
||||||
# Use SMTP
|
# Use SMTP
|
||||||
eval "use Net::SMTP";
|
eval "use Net::SMTP";
|
||||||
return ( 1, "Net::SMTP module is required to use SMTP server" )
|
return ( 1, "Net::SMTP module is required to use SMTP server" )
|
||||||
if ($@);
|
if ($@);
|
||||||
|
|
||||||
# Create SMTP object
|
# Create SMTP object
|
||||||
my $smtp = Net::SMTP->new( $conf->{SMTPServer}, Timeout => 5 );
|
my $smtp = Net::SMTP->new( $conf->{SMTPServer}, Timeout => 5 );
|
||||||
return ( 1,
|
return ( 1,
|
||||||
"SMTP connection to " . $conf->{SMTPServer} . " failed" )
|
"SMTP connection to " . $conf->{SMTPServer} . " failed" )
|
||||||
unless ($smtp);
|
unless ($smtp);
|
||||||
|
|
||||||
# Skip other tests if no authentication
|
# Skip other tests if no authentication
|
||||||
return 1
|
return 1
|
||||||
unless ( $conf->{SMTPAuthUser} and $conf->{SMTPAuthPass} );
|
unless ( $conf->{SMTPAuthUser} and $conf->{SMTPAuthPass} );
|
||||||
|
|
||||||
# Try authentication
|
# Try authentication
|
||||||
return ( 1, "SMTP authentication failed" )
|
return ( 1, "SMTP authentication failed" )
|
||||||
unless $smtp->auth( $conf->{SMTPAuthUser},
|
unless $smtp->auth( $conf->{SMTPAuthUser},
|
||||||
$conf->{SMTPAuthPass} );
|
$conf->{SMTPAuthPass} );
|
||||||
|
|
||||||
# Return
|
# Return
|
||||||
|
@ -303,14 +308,15 @@ sub tests {
|
||||||
# SAML entity ID must be uniq
|
# SAML entity ID must be uniq
|
||||||
samlIDPEntityIdUniqueness => sub {
|
samlIDPEntityIdUniqueness => sub {
|
||||||
return 1
|
return 1
|
||||||
unless ( $conf->{samlIDPMetaDataXML}
|
unless ( $conf->{samlIDPMetaDataXML}
|
||||||
and %{ $conf->{samlIDPMetaDataXML} } );
|
and %{ $conf->{samlIDPMetaDataXML} } );
|
||||||
my @msg;
|
my @msg;
|
||||||
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;
|
||||||
|
@ -319,7 +325,7 @@ sub tests {
|
||||||
my $eid = $2;
|
my $eid = $2;
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
@ -329,15 +335,15 @@ sub tests {
|
||||||
},
|
},
|
||||||
samlSPEntityIdUniqueness => sub {
|
samlSPEntityIdUniqueness => sub {
|
||||||
return 1
|
return 1
|
||||||
unless ( $conf->{samlSPMetaDataXML}
|
unless ( $conf->{samlSPMetaDataXML}
|
||||||
and %{ $conf->{samlSPMetaDataXML} } );
|
and %{ $conf->{samlSPMetaDataXML} } );
|
||||||
my @msg;
|
my @msg;
|
||||||
my $res = 1;
|
my $res = 1;
|
||||||
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;
|
||||||
|
@ -346,7 +352,7 @@ sub tests {
|
||||||
my $eid = $2;
|
my $eid = $2;
|
||||||
if ( defined $entityIds{$eid} ) {
|
if ( defined $entityIds{$eid} ) {
|
||||||
push @msg,
|
push @msg,
|
||||||
"$spId and $entityIds{$eid} have the same SAML EntityID";
|
"$spId and $entityIds{$eid} have the same SAML EntityID";
|
||||||
$res = 0;
|
$res = 0;
|
||||||
next;
|
next;
|
||||||
}
|
}
|
||||||
|
@ -360,7 +366,7 @@ sub tests {
|
||||||
return 1 unless ( $conf->{authentication} eq 'Combination' );
|
return 1 unless ( $conf->{authentication} eq 'Combination' );
|
||||||
require Lemonldap::NG::Common::Combination::Parser;
|
require Lemonldap::NG::Common::Combination::Parser;
|
||||||
return ( 0, 'No module declared for combination' )
|
return ( 0, 'No module declared for combination' )
|
||||||
unless ( $conf->{combModules} and %{ $conf->{combModules} } );
|
unless ( $conf->{combModules} and %{ $conf->{combModules} } );
|
||||||
my $moduleList;
|
my $moduleList;
|
||||||
foreach my $md ( keys %{ $conf->{combModules} } ) {
|
foreach my $md ( keys %{ $conf->{combModules} } ) {
|
||||||
my $entry = $conf->{combModules}->{$md};
|
my $entry = $conf->{combModules}->{$md};
|
||||||
|
@ -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 ($@);
|
||||||
|
|
||||||
|
@ -397,7 +403,7 @@ sub tests {
|
||||||
eval "use Convert::Base32";
|
eval "use Convert::Base32";
|
||||||
return ( 1,
|
return ( 1,
|
||||||
"Convert::Base32 module is required to enable TOTP" )
|
"Convert::Base32 module is required to enable TOTP" )
|
||||||
if ($@);
|
if ($@);
|
||||||
}
|
}
|
||||||
|
|
||||||
# Use U2F
|
# Use U2F
|
||||||
|
@ -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 ($@);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -428,7 +434,7 @@ sub tests {
|
||||||
my $w = "";
|
my $w = "";
|
||||||
foreach ( 'totp', 'u' ) {
|
foreach ( 'totp', 'u' ) {
|
||||||
$w .= uc($_) . "2F is activated twice \n"
|
$w .= uc($_) . "2F is activated twice \n"
|
||||||
if ( $conf->{ $_ . '2fActivation' } eq '1' );
|
if ( $conf->{ $_ . '2fActivation' } eq '1' );
|
||||||
}
|
}
|
||||||
return ( 1, ( $w ? $w : () ) );
|
return ( 1, ( $w ? $w : () ) );
|
||||||
},
|
},
|
||||||
|
@ -439,8 +445,10 @@ sub tests {
|
||||||
return 1 unless ( defined $conf->{totp2fDigits} );
|
return 1 unless ( defined $conf->{totp2fDigits} );
|
||||||
return (
|
return (
|
||||||
1,
|
1,
|
||||||
( ( $conf->{totp2fDigits} == 6
|
(
|
||||||
or $conf->{totp2fDigits} == 8
|
(
|
||||||
|
$conf->{totp2fDigits} == 6
|
||||||
|
or $conf->{totp2fDigits} == 8
|
||||||
)
|
)
|
||||||
? ''
|
? ''
|
||||||
: 'TOTP should be 6 or 8 digits long'
|
: 'TOTP should be 6 or 8 digits long'
|
||||||
|
@ -452,9 +460,9 @@ sub tests {
|
||||||
totp2fParams => sub {
|
totp2fParams => sub {
|
||||||
return 1 unless ( $conf->{totp2fActivation} );
|
return 1 unless ( $conf->{totp2fActivation} );
|
||||||
return ( 0, 'TOTP range must be defined' )
|
return ( 0, 'TOTP range must be defined' )
|
||||||
unless ( $conf->{totp2fRange} );
|
unless ( $conf->{totp2fRange} );
|
||||||
return ( 1, "TOTP interval should be higher than 10s" )
|
return ( 1, "TOTP interval should be higher than 10s" )
|
||||||
unless ( $conf->{totp2fInterval} > 10 );
|
unless ( $conf->{totp2fInterval} > 10 );
|
||||||
|
|
||||||
# Return
|
# Return
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -465,11 +473,12 @@ sub tests {
|
||||||
yubikey2fParams => sub {
|
yubikey2fParams => sub {
|
||||||
return 1 unless ( $conf->{yubikey2fActivation} );
|
return 1 unless ( $conf->{yubikey2fActivation} );
|
||||||
return ( 0, "Yubikey client ID and secret key must be set" )
|
return ( 0, "Yubikey client ID and secret key must be set" )
|
||||||
unless ( defined $conf->{yubikey2fSecretKey}
|
unless ( defined $conf->{yubikey2fSecretKey}
|
||||||
&& 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'
|
||||||
)
|
)
|
||||||
|
@ -480,7 +489,7 @@ sub tests {
|
||||||
rest2fVerifyUrl => sub {
|
rest2fVerifyUrl => sub {
|
||||||
return 1 unless ( $conf->{rest2fActivation} );
|
return 1 unless ( $conf->{rest2fActivation} );
|
||||||
return ( 0, "REST 2F Verify URL must be set" )
|
return ( 0, "REST 2F Verify URL must be set" )
|
||||||
unless ( defined $conf->{rest2fVerifyUrl} );
|
unless ( defined $conf->{rest2fVerifyUrl} );
|
||||||
|
|
||||||
# Return
|
# Return
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -494,16 +503,15 @@ sub tests {
|
||||||
my $ok = 0;
|
my $ok = 0;
|
||||||
foreach (qw(u totp yubikey)) {
|
foreach (qw(u totp yubikey)) {
|
||||||
$ok ||= $conf->{ $_ . '2fActivation' }
|
$ok ||= $conf->{ $_ . '2fActivation' }
|
||||||
&& $conf->{ $_ . '2fSelfRegistration' };
|
&& $conf->{ $_ . '2fSelfRegistration' };
|
||||||
last if ($ok);
|
last if ($ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
$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 );
|
||||||
},
|
},
|
||||||
|
@ -512,7 +520,7 @@ sub tests {
|
||||||
ext2fCommands => sub {
|
ext2fCommands => sub {
|
||||||
return 1 unless ( $conf->{ext2fActivation} );
|
return 1 unless ( $conf->{ext2fActivation} );
|
||||||
return ( 0, "External 2F Send or Validate command must be set" )
|
return ( 0, "External 2F Send or Validate command must be set" )
|
||||||
unless ( defined $conf->{ext2FSendCommand}
|
unless ( defined $conf->{ext2FSendCommand}
|
||||||
&& defined $conf->{ext2FValidateCommand} );
|
&& defined $conf->{ext2FValidateCommand} );
|
||||||
|
|
||||||
# Return
|
# Return
|
||||||
|
@ -523,9 +531,9 @@ sub tests {
|
||||||
formTimeout => sub {
|
formTimeout => sub {
|
||||||
return 1 unless ( defined $conf->{formTimeout} );
|
return 1 unless ( defined $conf->{formTimeout} );
|
||||||
return ( 0, "XSRF form token TTL must be higher than 30s" )
|
return ( 0, "XSRF form token TTL must be higher than 30s" )
|
||||||
unless ( $conf->{formTimeout} > 30 );
|
unless ( $conf->{formTimeout} > 30 );
|
||||||
return ( 1, "XSRF form token TTL should not be higher than 2mn" )
|
return ( 1, "XSRF form token TTL should not be higher than 2mn" )
|
||||||
if ( $conf->{formTimeout} > 120 );
|
if ( $conf->{formTimeout} > 120 );
|
||||||
|
|
||||||
# Return
|
# Return
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -24,7 +24,7 @@ delete $forms{restore};
|
||||||
my ( @types, $attr, $tree, $ctrees );
|
my ( @types, $attr, $tree, $ctrees );
|
||||||
ok( $tree = Lemonldap::NG::Manager::Build::Tree::tree(), 'Get tree' );
|
ok( $tree = Lemonldap::NG::Manager::Build::Tree::tree(), 'Get tree' );
|
||||||
ok( $ctrees = Lemonldap::NG::Manager::Build::CTrees::cTrees(), 'Get cTrees' );
|
ok( $ctrees = Lemonldap::NG::Manager::Build::CTrees::cTrees(), 'Get cTrees' );
|
||||||
ok( $attr = Lemonldap::NG::Manager::Build::Attributes::attributes(),
|
ok( $attr = Lemonldap::NG::Manager::Build::Attributes::attributes(),
|
||||||
'Get attributes' );
|
'Get attributes' );
|
||||||
$count += 4;
|
$count += 4;
|
||||||
|
|
||||||
|
|
|
@ -13,11 +13,11 @@ use strict;
|
||||||
use Mouse;
|
use Mouse;
|
||||||
use JSON qw(from_json to_json);
|
use JSON qw(from_json to_json);
|
||||||
use Lemonldap::NG::Portal::Main::Constants qw(
|
use Lemonldap::NG::Portal::Main::Constants qw(
|
||||||
PE_ERROR
|
PE_ERROR
|
||||||
PE_NOTOKEN
|
PE_NOTOKEN
|
||||||
PE_OK
|
PE_OK
|
||||||
PE_SENDRESPONSE
|
PE_SENDRESPONSE
|
||||||
PE_TOKENEXPIRED
|
PE_TOKENEXPIRED
|
||||||
);
|
);
|
||||||
|
|
||||||
our $VERSION = '2.0.0';
|
our $VERSION = '2.0.0';
|
||||||
|
@ -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,10 +49,12 @@ 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($_);
|
||||||
$prefix =~ s/2f$//i;
|
$prefix =~ s/2f$//i;
|
||||||
|
@ -64,10 +66,9 @@ 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
|
||||||
my $rule = $self->conf->{$ap};
|
my $rule = $self->conf->{$ap};
|
||||||
|
@ -77,13 +78,13 @@ sub init {
|
||||||
$rule = $self->p->HANDLER->substitute($rule);
|
$rule = $self->p->HANDLER->substitute($rule);
|
||||||
unless ( $rule = $self->p->HANDLER->buildSub($rule) ) {
|
unless ( $rule = $self->p->HANDLER->buildSub($rule) ) {
|
||||||
$self->error( 'External 2F rule error: '
|
$self->error( 'External 2F rule error: '
|
||||||
. $self->p->HANDLER->tsv->{jail}->error );
|
. $self->p->HANDLER->tsv->{jail}->error );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Store module
|
# Store module
|
||||||
push @{ $self->{ $i ? 'sfRModules' : 'sfModules' } },
|
push @{ $self->{ $i ? 'sfRModules' : 'sfModules' } },
|
||||||
{ p => $prefix, m => $m, r => $rule };
|
{ p => $prefix, m => $m, r => $rule };
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$self->logger->debug(' -> not enabled');
|
$self->logger->debug(' -> not enabled');
|
||||||
|
@ -97,10 +98,10 @@ sub init {
|
||||||
$self->p->HANDLER->substitute( $self->conf->{sfRequired} )
|
$self->p->HANDLER->substitute( $self->conf->{sfRequired} )
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
$self->error( 'Error in sfRequired rule'
|
$self->error( 'Error in sfRequired rule'
|
||||||
. $self->p->HANDLER->tsv->{jail}->error );
|
. $self->p->HANDLER->tsv->{jail}->error );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -179,7 +180,7 @@ sub run {
|
||||||
}
|
}
|
||||||
|
|
||||||
$self->userLogger->info( 'Second factor required for '
|
$self->userLogger->info( 'Second factor required for '
|
||||||
. $req->sessionInfo->{ $self->conf->{whatToTrace} } );
|
. $req->sessionInfo->{ $self->conf->{whatToTrace} } );
|
||||||
|
|
||||||
# Store user data in a token
|
# Store user data in a token
|
||||||
$req->sessionInfo->{_2fRealSession} = $req->id;
|
$req->sessionInfo->{_2fRealSession} = $req->id;
|
||||||
|
@ -201,10 +202,9 @@ sub run {
|
||||||
$req,
|
$req,
|
||||||
'2fchoice',
|
'2fchoice',
|
||||||
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" : '' ) ], []
|
||||||
[]
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,26 +299,25 @@ sub _displayRegister {
|
||||||
'Looking if ' . $m->{m}->prefix . '2F register is available' );
|
'Looking if ' . $m->{m}->prefix . '2F register is available' );
|
||||||
if ( $m->{r}->( $req, $req->userData ) ) {
|
if ( $m->{r}->( $req, $req->userData ) ) {
|
||||||
push @am,
|
push @am,
|
||||||
{
|
{
|
||||||
CODE => $m->{m}->prefix,
|
CODE => $m->{m}->prefix,
|
||||||
URL => '/2fregisters/' . $m->{m}->prefix,
|
URL => '/2fregisters/' . $m->{m}->prefix,
|
||||||
LOGO => $m->{m}->logo,
|
LOGO => $m->{m}->logo,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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 =
|
||||||
? eval {
|
$req->userData->{_2fDevices}
|
||||||
from_json( $req->userData->{_2fDevices}, { allow_nonref => 1 } );
|
? eval {
|
||||||
}
|
from_json( $req->userData->{_2fDevices}, { allow_nonref => 1 } ); }
|
||||||
: undef;
|
: undef;
|
||||||
|
|
||||||
unless ($_2fDevices) {
|
unless ($_2fDevices) {
|
||||||
$self->logger->debug("No 2F Device found");
|
$self->logger->debug("No 2F Device found");
|
||||||
|
@ -365,11 +363,11 @@ sub register {
|
||||||
$self->logger->debug(' -> OK');
|
$self->logger->debug(' -> OK');
|
||||||
my $name = $m->{m}->prefix;
|
my $name = $m->{m}->prefix;
|
||||||
push @am,
|
push @am,
|
||||||
{
|
{
|
||||||
name => $name,
|
name => $name,
|
||||||
logo => $m->{m}->logo,
|
logo => $m->{m}->logo,
|
||||||
url => "/2fregisters/$name"
|
url => "/2fregisters/$name"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $self->p->sendJSONresponse( $req, \@am );
|
return $self->p->sendJSONresponse( $req, \@am );
|
||||||
|
@ -378,12 +376,12 @@ sub register {
|
||||||
sub restoreSession {
|
sub restoreSession {
|
||||||
my ( $self, $req, @path ) = @_;
|
my ( $self, $req, @path ) = @_;
|
||||||
my $token = $req->pdata->{sfRegToken}
|
my $token = $req->pdata->{sfRegToken}
|
||||||
or return [ 302, [ Location => $self->conf->{portal} ], [] ];
|
or return [ 302, [ Location => $self->conf->{portal} ], [] ];
|
||||||
$req->userData( $self->ott->getToken( $token, 1 ) );
|
$req->userData( $self->ott->getToken( $token, 1 ) );
|
||||||
$req->data->{sfRegRequired} = 1;
|
$req->data->{sfRegRequired} = 1;
|
||||||
return $req->method eq 'POST'
|
return $req->method eq 'POST'
|
||||||
? $self->register( $req, @path )
|
? $self->register( $req, @path )
|
||||||
: $self->_displayRegister( $req, @path );
|
: $self->_displayRegister( $req, @path );
|
||||||
}
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|
|
@ -39,11 +39,12 @@ 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} ) )
|
||||||
{
|
{
|
||||||
$self->logger->error("External send command failed (code $c)");
|
$self->logger->error("External send command failed (code $c)");
|
||||||
return $self->p->do( $req, [ sub { PE_ERROR } ] );
|
return $self->p->do( $req, [ sub { PE_ERROR } ] );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 ) )
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ extends 'Lemonldap::NG::Portal::Main::Auth',
|
||||||
|
|
||||||
# INTERFACE
|
# INTERFACE
|
||||||
|
|
||||||
has opList => ( is => 'rw', default => sub { [] } );
|
has opList => ( is => 'rw', default => sub { [] } );
|
||||||
has opNumber => ( is => 'rw', default => 0 );
|
has opNumber => ( is => 'rw', default => 0 );
|
||||||
has path => ( is => 'rw', default => 'oauth2' );
|
has path => ( is => 'rw', default => 'oauth2' );
|
||||||
|
|
||||||
|
|
|
@ -174,7 +174,7 @@ sub send_mail {
|
||||||
foreach ( keys %cid ) {
|
foreach ( keys %cid ) {
|
||||||
$message->attach(
|
$message->attach(
|
||||||
Type => "image/" . ( $cid{$_} =~ m/\.(\w+)/ )[0],
|
Type => "image/" . ( $cid{$_} =~ m/\.(\w+)/ )[0],
|
||||||
Id => $_,
|
Id => $_,
|
||||||
Path => $self->p->{templateDir} . "/" . $cid{$_},
|
Path => $self->p->{templateDir} . "/" . $cid{$_},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,17 +16,16 @@ 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 },
|
||||||
[ $self->conf->{portalSkinRules}->{$skinRule}, $sub ];
|
[ $self->conf->{portalSkinRules}->{$skinRule}, $sub ];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$self->logger->error(
|
$self->logger->error(
|
||||||
qq(Skin rule "$skinRule" returns an error: )
|
qq(Skin rule "$skinRule" returns an error: )
|
||||||
. HANDLER->tsv->{jail}->error );
|
. HANDLER->tsv->{jail}->error );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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} )
|
||||||
: ()
|
: ()
|
||||||
),
|
),
|
||||||
|
@ -79,11 +79,12 @@ sub display {
|
||||||
CHOICE_PARAM => $self->conf->{authChoiceParam},
|
CHOICE_PARAM => $self->conf->{authChoiceParam},
|
||||||
CHOICE_VALUE => $req->data->{_authChoice},
|
CHOICE_VALUE => $req->data->{_authChoice},
|
||||||
CHECK_LOGINS => $self->conf->{portalCheckLogins}
|
CHECK_LOGINS => $self->conf->{portalCheckLogins}
|
||||||
&& $req->data->{login},
|
&& $req->data->{login},
|
||||||
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} )
|
||||||
: ()
|
: ()
|
||||||
),
|
),
|
||||||
|
@ -106,12 +107,13 @@ sub display {
|
||||||
CHOICE_PARAM => $self->conf->{authChoiceParam},
|
CHOICE_PARAM => $self->conf->{authChoiceParam},
|
||||||
CHOICE_VALUE => $req->data->{_authChoice},
|
CHOICE_VALUE => $req->data->{_authChoice},
|
||||||
CHECK_LOGINS => $self->conf->{portalCheckLogins}
|
CHECK_LOGINS => $self->conf->{portalCheckLogins}
|
||||||
&& $req->data->{login},
|
&& $req->data->{login},
|
||||||
ASK_LOGINS => $req->param('checkLogins') || 0,
|
ASK_LOGINS => $req->param('checkLogins') || 0,
|
||||||
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} )
|
||||||
: ()
|
: ()
|
||||||
),
|
),
|
||||||
|
@ -150,14 +153,15 @@ sub display {
|
||||||
my $p = $self->conf->{portal} . $self->conf->{issuerDBOpenIDPath};
|
my $p = $self->conf->{portal} . $self->conf->{issuerDBOpenIDPath};
|
||||||
$p =~ s#(?<!:)/?\^?/#/#g;
|
$p =~ s#(?<!:)/?\^?/#/#g;
|
||||||
my $id = $req->{sessionInfo}
|
my $id = $req->{sessionInfo}
|
||||||
->{ $self->conf->{openIdAttr} || $self->conf->{whatToTrace} };
|
->{ $self->conf->{openIdAttr} || $self->conf->{whatToTrace} };
|
||||||
%templateParams = (
|
%templateParams = (
|
||||||
MAIN_LOGO => $self->conf->{portalMainLogo},
|
MAIN_LOGO => $self->conf->{portalMainLogo},
|
||||||
AUTH_ERROR => $self->error,
|
AUTH_ERROR => $self->error,
|
||||||
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,16 +193,16 @@ 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'},
|
||||||
PING => $self->conf->{portalPingInterval},
|
PING => $self->conf->{portalPingInterval},
|
||||||
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} )
|
||||||
: ()
|
: ()
|
||||||
),
|
),
|
||||||
|
@ -240,14 +247,15 @@ sub display {
|
||||||
or ( not $req->data->{noerror}
|
or ( not $req->data->{noerror}
|
||||||
and $req->userData
|
and $req->userData
|
||||||
and %{ $req->userData } )
|
and %{ $req->userData } )
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
$skinfile = 'error';
|
$skinfile = 'error';
|
||||||
%templateParams = (
|
%templateParams = (
|
||||||
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} )
|
||||||
: ()
|
: ()
|
||||||
),
|
),
|
||||||
|
@ -260,21 +268,21 @@ sub display {
|
||||||
my $login = $self->userId($req);
|
my $login = $self->userId($req);
|
||||||
$login = '' if ( $login eq 'anonymous' );
|
$login = '' if ( $login eq 'anonymous' );
|
||||||
%templateParams = (
|
%templateParams = (
|
||||||
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,
|
||||||
AUTH_URL => $req->{data}->{_url},
|
AUTH_URL => $req->{data}->{_url},
|
||||||
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} )
|
||||||
: ()
|
: ()
|
||||||
),
|
),
|
||||||
|
@ -306,12 +314,12 @@ sub display {
|
||||||
or $req->{error} == PE_PASSWORDFORMEMPTY
|
or $req->{error} == PE_PASSWORDFORMEMPTY
|
||||||
or ( $req->{error} == PE_PP_PASSWORD_EXPIRED
|
or ( $req->{error} == PE_PP_PASSWORD_EXPIRED
|
||||||
and $self->conf->{ldapAllowResetExpiredPassword} )
|
and $self->conf->{ldapAllowResetExpiredPassword} )
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
%templateParams = (
|
%templateParams = (
|
||||||
%templateParams,
|
%templateParams,
|
||||||
REQUIRE_OLDPASSWORD =>
|
REQUIRE_OLDPASSWORD =>
|
||||||
1, # Old password is required to check user credentials
|
1, # Old password is required to check user credentials
|
||||||
DISPLAY_FORM => 0,
|
DISPLAY_FORM => 0,
|
||||||
DISPLAY_OPENID_FORM => 0,
|
DISPLAY_OPENID_FORM => 0,
|
||||||
DISPLAY_YUBIKEY_FORM => 0,
|
DISPLAY_YUBIKEY_FORM => 0,
|
||||||
|
@ -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
|
||||||
|
@ -388,10 +395,9 @@ sub display {
|
||||||
module => $displayType eq "logo"
|
module => $displayType eq "logo"
|
||||||
? $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}
|
or return $self->sendError( $req,
|
||||||
. "/$file"
|
|
||||||
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,12 +450,11 @@ 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="}
|
||||||
. $req->{portalHiddenFormValues}->{$_} . '" />';
|
. $req->{portalHiddenFormValues}->{$_} . '" />';
|
||||||
}
|
}
|
||||||
|
|
||||||
return $val;
|
return $val;
|
||||||
|
@ -521,12 +525,13 @@ sub mkSessionArray {
|
||||||
displayError => $displayError,
|
displayError => $displayError,
|
||||||
fields => [
|
fields => [
|
||||||
map { { name => $self->conf->{sessionDataToRemember}->{$_} } }
|
map { { name => $self->conf->{sessionDataToRemember}->{$_} } }
|
||||||
@fields
|
@fields
|
||||||
],
|
],
|
||||||
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 ],
|
||||||
|
@ -548,7 +553,7 @@ sub mkOidcConsent {
|
||||||
# Set default RP displayname
|
# Set default RP displayname
|
||||||
foreach my $oidc ( keys %{ $self->conf->{oidcRPMetaDataOptions} } ) {
|
foreach my $oidc ( keys %{ $self->conf->{oidcRPMetaDataOptions} } ) {
|
||||||
$self->conf->{oidcRPMetaDataOptions}->{$oidc}
|
$self->conf->{oidcRPMetaDataOptions}->{$oidc}
|
||||||
->{oidcRPMetaDataOptionsDisplayName} ||= $oidc;
|
->{oidcRPMetaDataOptionsDisplayName} ||= $oidc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -574,9 +579,9 @@ 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}
|
||||||
|
|
|
@ -84,8 +84,9 @@ sub init {
|
||||||
my ( $self, $args ) = @_;
|
my ( $self, $args ) = @_;
|
||||||
$args ||= {};
|
$args ||= {};
|
||||||
$self->localConfig(
|
$self->localConfig(
|
||||||
{ %{ Lemonldap::NG::Common::Conf->new( $args->{configStorage} )
|
{
|
||||||
->getLocalConf('portal')
|
%{ Lemonldap::NG::Common::Conf->new( $args->{configStorage} )
|
||||||
|
->getLocalConf('portal')
|
||||||
},
|
},
|
||||||
%$args
|
%$args
|
||||||
}
|
}
|
||||||
|
@ -109,33 +110,33 @@ sub init {
|
||||||
# Handle requests (other path may be declared in enabled plugins)
|
# Handle requests (other path may be declared in enabled plugins)
|
||||||
$self
|
$self
|
||||||
|
|
||||||
# "/" or undeclared paths
|
# "/" or undeclared paths
|
||||||
->addUnauthRoute( '*' => 'login', ['GET'] )
|
->addUnauthRoute( '*' => 'login', ['GET'] )
|
||||||
->addUnauthRoute( '*' => 'postLogin', ['POST'] )
|
->addUnauthRoute( '*' => 'postLogin', ['POST'] )
|
||||||
->addAuthRoute( '*' => 'authenticatedRequest', ['GET'] )
|
->addAuthRoute( '*' => 'authenticatedRequest', ['GET'] )
|
||||||
->addAuthRoute( '*' => 'postAuthenticatedRequest', ['POST'] )
|
->addAuthRoute( '*' => 'postAuthenticatedRequest', ['POST'] )
|
||||||
|
|
||||||
# psgi.js
|
# psgi.js
|
||||||
->addUnauthRoute( 'psgi.js' => 'sendJs', ['GET'] )
|
->addUnauthRoute( 'psgi.js' => 'sendJs', ['GET'] )
|
||||||
->addAuthRoute( 'psgi.js' => 'sendJs', ['GET'] )
|
->addAuthRoute( 'psgi.js' => 'sendJs', ['GET'] )
|
||||||
|
|
||||||
# portal.css
|
# portal.css
|
||||||
->addUnauthRoute( 'portal.css' => 'sendCss', ['GET'] )
|
->addUnauthRoute( 'portal.css' => 'sendCss', ['GET'] )
|
||||||
->addAuthRoute( 'portal.css' => 'sendCss', ['GET'] )
|
->addAuthRoute( 'portal.css' => 'sendCss', ['GET'] )
|
||||||
|
|
||||||
# lmerror
|
# lmerror
|
||||||
->addUnauthRoute( lmerror => { ':code' => 'lmError' }, ['GET'] )
|
->addUnauthRoute( lmerror => { ':code' => 'lmError' }, ['GET'] )
|
||||||
->addAuthRoute( lmerror => { ':code' => 'lmError' }, ['GET'] )
|
->addAuthRoute( lmerror => { ':code' => 'lmError' }, ['GET'] )
|
||||||
|
|
||||||
# Core REST API
|
# Core REST API
|
||||||
->addUnauthRoute( ping => 'pleaseAuth', ['GET'] )
|
->addUnauthRoute( ping => 'pleaseAuth', ['GET'] )
|
||||||
->addAuthRoute( ping => 'authenticated', ['GET'] )
|
->addAuthRoute( ping => 'authenticated', ['GET'] )
|
||||||
|
|
||||||
# Refresh session
|
# Refresh session
|
||||||
->addAuthRoute( refresh => 'refresh', ['GET'] )
|
->addAuthRoute( refresh => 'refresh', ['GET'] )
|
||||||
|
|
||||||
# Logout
|
# Logout
|
||||||
->addAuthRoute( logout => 'logout', ['GET'] );
|
->addAuthRoute( logout => 'logout', ['GET'] );
|
||||||
|
|
||||||
# Default routes must point to routines declared above
|
# Default routes must point to routines declared above
|
||||||
$self->defaultAuthRoute('');
|
$self->defaultAuthRoute('');
|
||||||
|
@ -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
|
||||||
|
@ -215,19 +216,19 @@ sub reloadConf {
|
||||||
return $self->fail;
|
return $self->fail;
|
||||||
}
|
}
|
||||||
$mod = $self->conf->{$type}
|
$mod = $self->conf->{$type}
|
||||||
unless ( $self->conf->{$type} eq 'Same' );
|
unless ( $self->conf->{$type} eq 'Same' );
|
||||||
my $module = '::' . ucfirst($type) . '::' . $mod;
|
my $module = '::' . ucfirst($type) . '::' . $mod;
|
||||||
$module =~ s/Authentication/Auth/;
|
$module =~ s/Authentication/Auth/;
|
||||||
|
|
||||||
# Launch and initialize module
|
# Launch and initialize module
|
||||||
return $self->fail
|
return $self->fail
|
||||||
unless ( $self->{"_$type"} = $self->loadPlugin($module) );
|
unless ( $self->{"_$type"} = $self->loadPlugin($module) );
|
||||||
}
|
}
|
||||||
|
|
||||||
# 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,22 +282,22 @@ 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;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$self->logger->error( "$type $name returns an error: "
|
$self->logger->error( "$type $name returns an error: "
|
||||||
. HANDLER->tsv->{jail}->error );
|
. HANDLER->tsv->{jail}->error );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$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 );
|
||||||
|
|
||||||
# Load plugins
|
# Load plugins
|
||||||
|
@ -332,7 +333,7 @@ sub loadPlugin {
|
||||||
}
|
}
|
||||||
my $obj;
|
my $obj;
|
||||||
return 0
|
return 0
|
||||||
unless ( $obj = $self->loadModule("$plugin") );
|
unless ( $obj = $self->loadModule("$plugin") );
|
||||||
return $self->findEP( $plugin, $obj );
|
return $self->findEP( $plugin, $obj );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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};
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,7 +111,7 @@ sub _redirect {
|
||||||
# Restore urldc if auth doesn't need to dial with browser
|
# Restore urldc if auth doesn't need to dial with browser
|
||||||
$self->restoreRequest( $req, $ir );
|
$self->restoreRequest( $req, $ir );
|
||||||
return $self->run( @_, @path );
|
return $self->run( @_, @path );
|
||||||
}
|
}
|
||||||
: ()
|
: ()
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
|
@ -17,11 +17,11 @@ 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
|
||||||
setLocalGroups store secondFactor);
|
setLocalGroups store secondFactor);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub validSession {
|
sub validSession {
|
||||||
|
@ -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,9 +201,9 @@ 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" );
|
||||||
}
|
}
|
||||||
|
|
||||||
# Update history
|
# Update history
|
||||||
|
@ -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
|
||||||
|
@ -240,7 +250,7 @@ sub do {
|
||||||
and $req->data->{redirectFormMethod} eq 'post' )
|
and $req->data->{redirectFormMethod} eq 'post' )
|
||||||
or $req->info
|
or $req->info
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
my ( $tpl, $prms ) = $self->display($req);
|
my ( $tpl, $prms ) = $self->display($req);
|
||||||
$self->logger->debug("Calling sendHtml with template $tpl");
|
$self->logger->debug("Calling sendHtml with template $tpl");
|
||||||
|
@ -258,20 +268,21 @@ 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'
|
||||||
}->{$type}
|
}->{$type}
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if ( my $sub = $self->$mod->can('name') ) {
|
if ( my $sub = $self->$mod->can('name') ) {
|
||||||
return $sub->( $self->$mod, $req, $type );
|
return $sub->( $self->$mod, $req, $type );
|
||||||
}
|
}
|
||||||
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -288,7 +299,7 @@ sub autoRedirect {
|
||||||
|
|
||||||
# Set redirection URL if needed
|
# Set redirection URL if needed
|
||||||
$req->{urldc} ||= $self->conf->{portal}
|
$req->{urldc} ||= $self->conf->{portal}
|
||||||
if ( $req->mustRedirect and not( $req->info ) );
|
if ( $req->mustRedirect and not( $req->info ) );
|
||||||
|
|
||||||
# Redirection should be made if urldc defined
|
# Redirection should be made if urldc defined
|
||||||
if ( $req->{urldc} ) {
|
if ( $req->{urldc} ) {
|
||||||
|
@ -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,16 +362,17 @@ 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} )
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
$self->logger->debug("Session $args{kind} $id expired");
|
$self->logger->debug("Session $args{kind} $id expired");
|
||||||
return;
|
return;
|
||||||
|
@ -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,
|
||||||
|
@ -423,11 +437,10 @@ sub updatePersistentSession {
|
||||||
# Return if no infos to update
|
# Return if no infos to update
|
||||||
return () unless ( ref $infos eq 'HASH' and %$infos );
|
return () unless ( ref $infos eq 'HASH' and %$infos );
|
||||||
$uid ||= $req->{sessionInfo}->{ $self->conf->{whatToTrace} }
|
$uid ||= $req->{sessionInfo}->{ $self->conf->{whatToTrace} }
|
||||||
|| $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,10 +572,10 @@ 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;
|
||||||
return $res;
|
return $res;
|
||||||
}
|
}
|
||||||
|
@ -694,7 +707,7 @@ sub cookie {
|
||||||
$h{path} ||= '/';
|
$h{path} ||= '/';
|
||||||
$h{HttpOnly} //= $self->conf->{httpOnly};
|
$h{HttpOnly} //= $self->conf->{httpOnly};
|
||||||
$h{max_age} //= $self->conf->{cookieExpiration}
|
$h{max_age} //= $self->conf->{cookieExpiration}
|
||||||
if ( $self->conf->{cookieExpiration} );
|
if ( $self->conf->{cookieExpiration} );
|
||||||
foreach (qw(domain path expires max_age HttpOnly)) {
|
foreach (qw(domain path expires max_age HttpOnly)) {
|
||||||
my $f = $_;
|
my $f = $_;
|
||||||
$f =~ s/_/-/g;
|
$f =~ s/_/-/g;
|
||||||
|
@ -717,8 +730,8 @@ sub sendHtml {
|
||||||
my ( $self, $req, $template, %args ) = @_;
|
my ( $self, $req, $template, %args ) = @_;
|
||||||
my $res = $self->SUPER::sendHtml( $req, $template, %args );
|
my $res = $self->SUPER::sendHtml( $req, $template, %args );
|
||||||
push @{ $res->[1] },
|
push @{ $res->[1] },
|
||||||
'X-XSS-Protection' => '1; mode=block',
|
'X-XSS-Protection' => '1; mode=block',
|
||||||
'X-Content-Type-Options' => 'nosniff';
|
'X-Content-Type-Options' => 'nosniff';
|
||||||
|
|
||||||
# Set authorized URL for POST
|
# Set authorized URL for POST
|
||||||
my $csp = $self->csp . "form-action 'self'";
|
my $csp = $self->csp . "form-action 'self'";
|
||||||
|
@ -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 .= ';';
|
||||||
|
@ -754,7 +766,7 @@ sub sendHtml {
|
||||||
my @url;
|
my @url;
|
||||||
if ( $req->info ) {
|
if ( $req->info ) {
|
||||||
@url = map { s#https?://([^/]+).*#$1#; $_ }
|
@url = map { s#https?://([^/]+).*#$1#; $_ }
|
||||||
( $req->info =~ /<iframe.*?src="(.*?)"/sg );
|
( $req->info =~ /<iframe.*?src="(.*?)"/sg );
|
||||||
}
|
}
|
||||||
if (@url) {
|
if (@url) {
|
||||||
$csp .= join( ' ', 'child-src', @url ) . ';';
|
$csp .= join( ' ', 'child-src', @url ) . ';';
|
||||||
|
@ -768,16 +780,17 @@ 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}
|
||||||
. '") no-repeat center fixed;'
|
. '") no-repeat center fixed;'
|
||||||
. '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',
|
||||||
],
|
],
|
||||||
|
@ -799,16 +812,16 @@ sub lmError {
|
||||||
|
|
||||||
# Error code
|
# Error code
|
||||||
$templateParams{"ERROR$_"} = ( $httpError == $_ ? 1 : 0 )
|
$templateParams{"ERROR$_"} = ( $httpError == $_ ? 1 : 0 )
|
||||||
foreach ( 403, 404, 500, 502, 503 );
|
foreach ( 403, 404, 500, 502, 503 );
|
||||||
return $self->sendHtml( $req, 'error', params => \%templateParams );
|
return $self->sendHtml( $req, 'error', params => \%templateParams );
|
||||||
}
|
}
|
||||||
|
|
||||||
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' );
|
||||||
}
|
}
|
||||||
$req->{respHeaders} = \@tmp;
|
$req->{respHeaders} = \@tmp;
|
||||||
$self->buildCookie($req);
|
$self->buildCookie($req);
|
||||||
|
@ -831,7 +844,7 @@ sub tplParams {
|
||||||
sub registerLogin {
|
sub registerLogin {
|
||||||
my ( $self, $req ) = @_;
|
my ( $self, $req ) = @_;
|
||||||
return
|
return
|
||||||
unless ( $self->conf->{loginHistoryEnabled}
|
unless ( $self->conf->{loginHistoryEnabled}
|
||||||
and defined $req->authResult );
|
and defined $req->authResult );
|
||||||
my $history = $req->sessionInfo->{_loginHistory} ||= {};
|
my $history = $req->sessionInfo->{_loginHistory} ||= {};
|
||||||
my $type = ( $req->authResult > 0 ? 'failed' : 'success' ) . 'Login';
|
my $type = ( $req->authResult > 0 ? 'failed' : 'success' ) . 'Login';
|
||||||
|
@ -841,17 +854,17 @@ sub registerLogin {
|
||||||
# Gather current login's parameters
|
# Gather current login's parameters
|
||||||
my $login = $self->_sumUpSession( $req->{sessionInfo}, 1 );
|
my $login = $self->_sumUpSession( $req->{sessionInfo}, 1 );
|
||||||
$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,12 +875,12 @@ 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->{$_}
|
||||||
foreach ( "_utime", "ipAddr",
|
foreach ( "_utime", "ipAddr",
|
||||||
keys %{ $self->conf->{sessionDataToRemember} } );
|
keys %{ $self->conf->{sessionDataToRemember} } );
|
||||||
return $res;
|
return $res;
|
||||||
}
|
}
|
||||||
|
@ -876,12 +889,12 @@ 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
|
||||||
unless ( -e $file );
|
unless ( -e $file );
|
||||||
unless ( -e $file ) {
|
unless ( -e $file ) {
|
||||||
die "Unable to find $name in $self->conf->{templateDir}";
|
die "Unable to find $name in $self->conf->{templateDir}";
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,11 +3,11 @@ package Lemonldap::NG::Portal::Main::SecondFactor;
|
||||||
use strict;
|
use strict;
|
||||||
use Mouse;
|
use Mouse;
|
||||||
use Lemonldap::NG::Portal::Main::Constants qw(
|
use Lemonldap::NG::Portal::Main::Constants qw(
|
||||||
PE_SENDRESPONSE
|
PE_SENDRESPONSE
|
||||||
PE_OK
|
PE_OK
|
||||||
PE_NOTOKEN
|
PE_NOTOKEN
|
||||||
PE_TOKENEXPIRED
|
PE_TOKENEXPIRED
|
||||||
PE_BADCREDENTIALS
|
PE_BADCREDENTIALS
|
||||||
);
|
);
|
||||||
|
|
||||||
our $VERSION = '2.0.0';
|
our $VERSION = '2.0.0';
|
||||||
|
@ -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
|
||||||
|
@ -101,15 +99,22 @@ sub _verify {
|
||||||
$self->p->rebuildCookies($req);
|
$self->p->rebuildCookies($req);
|
||||||
$req->mustRedirect(1);
|
$req->mustRedirect(1);
|
||||||
$self->userLogger->notice( $self->prefix
|
$self->userLogger->notice( $self->prefix
|
||||||
. '2F verification for '
|
. '2F verification for '
|
||||||
. $req->sessionInfo->{ $self->conf->{whatToTrace} } );
|
. $req->sessionInfo->{ $self->conf->{whatToTrace} } );
|
||||||
|
|
||||||
if ( my $l = $self->conf->{ $self->prefix . '2fAuthnLevel' } ) {
|
if ( my $l = $self->conf->{ $self->prefix . '2fAuthnLevel' } ) {
|
||||||
$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;
|
||||||
|
|
|
@ -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");
|
||||||
|
@ -53,7 +51,7 @@ sub run {
|
||||||
$MaxAge = $lastFailedLoginEpoch[0] - $lastFailedLoginEpoch[2];
|
$MaxAge = $lastFailedLoginEpoch[0] - $lastFailedLoginEpoch[2];
|
||||||
$self->logger->debug(" -> MaxAge = $MaxAge");
|
$self->logger->debug(" -> MaxAge = $MaxAge");
|
||||||
return PE_OK
|
return PE_OK
|
||||||
if ( $MaxAge > $self->conf->{bruteForceProtectionMaxAge} );
|
if ( $MaxAge > $self->conf->{bruteForceProtectionMaxAge} );
|
||||||
|
|
||||||
# Delta between the two last failed logins -> Auth_N - Auth_N-1
|
# Delta between the two last failed logins -> Auth_N - Auth_N-1
|
||||||
my $delta = time - $lastFailedLoginEpoch[1];
|
my $delta = time - $lastFailedLoginEpoch[1];
|
||||||
|
@ -61,7 +59,7 @@ sub run {
|
||||||
|
|
||||||
# Delta between the two last failed logins < 30s => wait
|
# Delta between the two last failed logins < 30s => wait
|
||||||
return PE_OK
|
return PE_OK
|
||||||
unless ( $delta <= $self->conf->{bruteForceProtectionTempo} );
|
unless ( $delta <= $self->conf->{bruteForceProtectionTempo} );
|
||||||
|
|
||||||
# Account locked
|
# Account locked
|
||||||
#shift @{ $req->sessionInfo->{_loginHistory}->{failedLogin} };
|
#shift @{ $req->sessionInfo->{_loginHistory}->{failedLogin} };
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
@ -25,8 +25,8 @@ sub run {
|
||||||
$self->logger->debug( "Delta with last Authn -> " . $delta );
|
$self->logger->debug( "Delta with last Authn -> " . $delta );
|
||||||
|
|
||||||
$delta <= $self->conf->{portalForceAuthnInterval}
|
$delta <= $self->conf->{portalForceAuthnInterval}
|
||||||
? return PE_OK
|
? return PE_OK
|
||||||
: return PE_MUSTAUTHN;
|
: return PE_MUSTAUTHN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,8 @@ package Lemonldap::NG::Portal::Plugins::GrantSession;
|
||||||
use strict;
|
use strict;
|
||||||
use Mouse;
|
use Mouse;
|
||||||
use Lemonldap::NG::Portal::Main::Constants qw(
|
use Lemonldap::NG::Portal::Main::Constants qw(
|
||||||
PE_OK
|
PE_OK
|
||||||
PE_SESSIONNOTGRANTED
|
PE_SESSIONNOTGRANTED
|
||||||
);
|
);
|
||||||
|
|
||||||
our $VERSION = '2.0.0';
|
our $VERSION = '2.0.0';
|
||||||
|
@ -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;
|
||||||
|
@ -45,7 +45,7 @@ sub run {
|
||||||
|
|
||||||
foreach ( sort sortByComment keys %{ $self->rules } ) {
|
foreach ( sort sortByComment keys %{ $self->rules } ) {
|
||||||
$self->logger->debug( "Grant session condition -> "
|
$self->logger->debug( "Grant session condition -> "
|
||||||
. $self->conf->{grantSessionRules}->{$_} );
|
. $self->conf->{grantSessionRules}->{$_} );
|
||||||
unless ( $self->rules->{$_}->( $req, $req->sessionInfo ) ) {
|
unless ( $self->rules->{$_}->( $req, $req->sessionInfo ) ) {
|
||||||
$req->userData( {} );
|
$req->userData( {} );
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ sub run {
|
||||||
if ($1) {
|
if ($1) {
|
||||||
$self->logger->debug("Message -> $1");
|
$self->logger->debug("Message -> $1");
|
||||||
|
|
||||||
# Message can contain session data as user attributes or macros
|
# Message can contain session data as user attributes or macros
|
||||||
my $hd = $self->p->HANDLER;
|
my $hd = $self->p->HANDLER;
|
||||||
my $msg = $hd->substitute($1);
|
my $msg = $hd->substitute($1);
|
||||||
unless ( $msg = $hd->buildSub($msg) ) {
|
unless ( $msg = $hd->buildSub($msg) ) {
|
||||||
|
@ -68,17 +68,17 @@ sub run {
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
$self->userLogger->error( 'User '
|
$self->userLogger->error( 'User '
|
||||||
. $req->sessionInfo->{uid}
|
. $req->sessionInfo->{uid}
|
||||||
. " was not granted to open session (rule -> $msg)" );
|
. " was not granted to open session (rule -> $msg)" );
|
||||||
$req->urldc( $self->conf->{portal} );
|
$req->urldc( $self->conf->{portal} );
|
||||||
return $req->authResult(PE_SESSIONNOTGRANTED);
|
return $req->authResult(PE_SESSIONNOTGRANTED);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$self->userLogger->error( 'User '
|
$self->userLogger->error( 'User '
|
||||||
. $req->sessionInfo->{uid}
|
. $req->sessionInfo->{uid}
|
||||||
. " was not granted to open session (rule -> "
|
. " was not granted to open session (rule -> "
|
||||||
. $self->conf->{grantSessionRules}->{$_}
|
. $self->conf->{grantSessionRules}->{$_}
|
||||||
. ")" );
|
. ")" );
|
||||||
$req->urldc( $self->conf->{portal} );
|
$req->urldc( $self->conf->{portal} );
|
||||||
return $req->authResult(PE_SESSIONNOTGRANTED);
|
return $req->authResult(PE_SESSIONNOTGRANTED);
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,15 +28,15 @@ sub run {
|
||||||
$req->sessionInfo->{_loginHistory}->{successLogin},
|
$req->sessionInfo->{_loginHistory}->{successLogin},
|
||||||
'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},
|
||||||
'lastFailedLogins', 0, 1 )
|
'lastFailedLogins', 0, 1 )
|
||||||
: ""
|
: ""
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
unless ( $req->info ) {
|
unless ( $req->info ) {
|
||||||
$req->info( $self->loadTemplate('noHistory') );
|
$req->info( $self->loadTemplate('noHistory') );
|
||||||
|
|
|
@ -32,7 +32,7 @@ sub createUser {
|
||||||
givenName => $gn,
|
givenName => $gn,
|
||||||
unicodePwd => utf8(
|
unicodePwd => utf8(
|
||||||
chr(34) . $req->data->{registerInfo}->{password} . chr(34)
|
chr(34) . $req->data->{registerInfo}->{password} . chr(34)
|
||||||
)->utf16le(),
|
)->utf16le(),
|
||||||
mail => $req->data->{registerInfo}->{mail},
|
mail => $req->data->{registerInfo}->{mail},
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -20,7 +20,7 @@ SKIP: {
|
||||||
);
|
);
|
||||||
$dbh->prepare(
|
$dbh->prepare(
|
||||||
q{INSERT INTO notifications VALUES ('dwho','testref','2016-05-30 00:00:00',?,null,null)}
|
q{INSERT INTO notifications VALUES ('dwho','testref','2016-05-30 00:00:00',?,null,null)}
|
||||||
)->execute(
|
)->execute(
|
||||||
'[
|
'[
|
||||||
{
|
{
|
||||||
"uid": "dwho",
|
"uid": "dwho",
|
||||||
|
@ -32,7 +32,7 @@ q{INSERT INTO notifications VALUES ('dwho','testref','2016-05-30 00:00:00',?,nul
|
||||||
"check": ["Accept test"]
|
"check": ["Accept test"]
|
||||||
}
|
}
|
||||||
]'
|
]'
|
||||||
);
|
);
|
||||||
|
|
||||||
my $client = LLNG::Manager::Test->new(
|
my $client = LLNG::Manager::Test->new(
|
||||||
{
|
{
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;';
|
||||||
|
|
|
@ -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,
|
||||||
|
@ -131,7 +140,7 @@ count(1);
|
||||||
$id1 = expectCookie($res);
|
$id1 = 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 );
|
||||||
my @cf = ( $res->[2]->[0] =~ /PE5<\/td>/gs );
|
my @cf = ( $res->[2]->[0] =~ /PE5<\/td>/gs );
|
||||||
|
|
|
@ -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',
|
||||||
|
@ -41,10 +44,11 @@ ok( $res = $client->_get(
|
||||||
'Form ReAuthentification'
|
'Form ReAuthentification'
|
||||||
);
|
);
|
||||||
ok( $res->[2]->[0] =~ qr%<span trspan="PE87"></span>%, 'Found PE87 code' )
|
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',
|
||||||
|
@ -65,7 +70,7 @@ ok( $res = $client->_get(
|
||||||
);
|
);
|
||||||
ok( $res->[2]->[0] =~ qr%<span trspan="yourApps">Your applications</span>%,
|
ok( $res->[2]->[0] =~ qr%<span trspan="yourApps">Your applications</span>%,
|
||||||
'Found applications list' )
|
'Found applications list' )
|
||||||
or print STDERR Dumper( $res->[2]->[0] );
|
or print STDERR Dumper( $res->[2]->[0] );
|
||||||
count(1);
|
count(1);
|
||||||
|
|
||||||
$client->logout($id1);
|
$client->logout($id1);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
@ -32,7 +34,7 @@ count(1);
|
||||||
expectOK($res);
|
expectOK($res);
|
||||||
my $id1 = expectCookie($res);
|
my $id1 = expectCookie($res);
|
||||||
ok( $res->[2]->[0] =~ /trspan="lastLogins"/, 'History found' )
|
ok( $res->[2]->[0] =~ /trspan="lastLogins"/, 'History found' )
|
||||||
or explain( $res->[2]->[0], 'trspan="noHistory"' );
|
or explain( $res->[2]->[0], 'trspan="noHistory"' );
|
||||||
my @c = ( $res->[2]->[0] =~ /<td>127.0.0.1/gs );
|
my @c = ( $res->[2]->[0] =~ /<td>127.0.0.1/gs );
|
||||||
|
|
||||||
# History with 1 successLogin
|
# History with 1 successLogin
|
||||||
|
@ -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,
|
||||||
|
|
|
@ -34,13 +34,13 @@ LWP::Protocol::PSGI->register(
|
||||||
my $client = LLNG::Manager::Test->new(
|
my $client = LLNG::Manager::Test->new(
|
||||||
{
|
{
|
||||||
ini => {
|
ini => {
|
||||||
logLevel => 'error',
|
logLevel => 'error',
|
||||||
rest2fActivation => 1,
|
rest2fActivation => 1,
|
||||||
rest2fInitUrl => 'http://auth.example.com/init',
|
rest2fInitUrl => 'http://auth.example.com/init',
|
||||||
rest2fInitArgs => { name => 'uid' },
|
rest2fInitArgs => { name => 'uid' },
|
||||||
rest2fVerifyUrl => 'http://auth.example.com/vrfy',
|
rest2fVerifyUrl => 'http://auth.example.com/vrfy',
|
||||||
rest2fVerifyArgs => { code => 'code' },
|
rest2fVerifyArgs => { code => 'code' },
|
||||||
loginHistoryEnabled => 1,
|
loginHistoryEnabled => 1,
|
||||||
authentication => 'Demo',
|
authentication => 'Demo',
|
||||||
userDB => 'Same',
|
userDB => 'Same',
|
||||||
}
|
}
|
||||||
|
@ -74,9 +74,8 @@ 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 );
|
||||||
ok( @c == 1, 'One entry found' );
|
ok( @c == 1, 'One entry found' );
|
||||||
|
|
||||||
|
|
|
@ -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),
|
||||||
|
@ -136,11 +144,11 @@ count(1);
|
||||||
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] );
|
||||||
count(1);
|
count(1);
|
||||||
my @c = ( $res->[2]->[0] =~ /<td>127.0.0.1/gs );
|
my @c = ( $res->[2]->[0] =~ /<td>127.0.0.1/gs );
|
||||||
ok( @c == 4, 'Four entries found' )
|
ok( @c == 4, 'Four entries found' )
|
||||||
or print STDERR Dumper( $res->[2]->[0] );
|
or print STDERR Dumper( $res->[2]->[0] );
|
||||||
count(1);
|
count(1);
|
||||||
|
|
||||||
$client->logout($id);
|
$client->logout($id);
|
||||||
|
|
|
@ -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),
|
||||||
|
@ -58,12 +61,12 @@ count(1);
|
||||||
|
|
||||||
ok( $res->[2]->[0] =~ /<h3 trspan="Dwho_notAllowed">Dwho_notAllowed<\/h3>/,
|
ok( $res->[2]->[0] =~ /<h3 trspan="Dwho_notAllowed">Dwho_notAllowed<\/h3>/,
|
||||||
'dwho rejected with custom message' )
|
'dwho rejected with custom message' )
|
||||||
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);
|
||||||
|
|
||||||
clean_sessions();
|
clean_sessions();
|
||||||
|
|
|
@ -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' );
|
||||||
|
|
|
@ -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';
|
||||||
|
@ -625,7 +626,7 @@ sub _get {
|
||||||
: ()
|
: ()
|
||||||
),
|
),
|
||||||
'REQUEST_METHOD' => $args{method} || 'GET',
|
'REQUEST_METHOD' => $args{method} || 'GET',
|
||||||
'REQUEST_URI' => $path . ( $args{query} ? "?$args{query}" : '' ),
|
'REQUEST_URI' => $path . ( $args{query} ? "?$args{query}" : '' ),
|
||||||
( $args{query} ? ( QUERY_STRING => $args{query} ) : () ),
|
( $args{query} ? ( QUERY_STRING => $args{query} ) : () ),
|
||||||
'SCRIPT_NAME' => '',
|
'SCRIPT_NAME' => '',
|
||||||
'SERVER_NAME' => 'auth.example.com',
|
'SERVER_NAME' => 'auth.example.com',
|
||||||
|
@ -677,10 +678,10 @@ sub _post {
|
||||||
: ()
|
: ()
|
||||||
),
|
),
|
||||||
'REQUEST_METHOD' => $args{method} || 'POST',
|
'REQUEST_METHOD' => $args{method} || 'POST',
|
||||||
'REQUEST_URI' => $path . ( $args{query} ? "?$args{query}" : '' ),
|
'REQUEST_URI' => $path . ( $args{query} ? "?$args{query}" : '' ),
|
||||||
'SCRIPT_NAME' => '',
|
'SCRIPT_NAME' => '',
|
||||||
'SERVER_NAME' => 'auth.example.com',
|
'SERVER_NAME' => 'auth.example.com',
|
||||||
'SERVER_PORT' => '80',
|
'SERVER_PORT' => '80',
|
||||||
'SERVER_PROTOCOL' => 'HTTP/1.1',
|
'SERVER_PROTOCOL' => 'HTTP/1.1',
|
||||||
( $args{custom} ? %{ $args{custom} } : () ),
|
( $args{custom} ? %{ $args{custom} } : () ),
|
||||||
'psgix.input.buffered' => 0,
|
'psgix.input.buffered' => 0,
|
||||||
|
|
|
@ -53,7 +53,7 @@ sub mirror {
|
||||||
: ()
|
: ()
|
||||||
),
|
),
|
||||||
'REQUEST_METHOD' => $args{method} || 'GET',
|
'REQUEST_METHOD' => $args{method} || 'GET',
|
||||||
'REQUEST_URI' => ( $args{path} || '/' )
|
'REQUEST_URI' => ( $args{path} || '/' )
|
||||||
. ( $args{query} ? "?$args{query}" : '' ),
|
. ( $args{query} ? "?$args{query}" : '' ),
|
||||||
( $args{query} ? ( QUERY_STRING => $args{query} ) : () ),
|
( $args{query} ? ( QUERY_STRING => $args{query} ) : () ),
|
||||||
'SCRIPT_NAME' => '',
|
'SCRIPT_NAME' => '',
|
||||||
|
|
|
@ -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' );
|
||||||
|
|
Loading…
Reference in New Issue
Block a user