tidy
This commit is contained in:
parent
c0472d41db
commit
b88a72c267
15
Makefile
15
Makefile
|
@ -1176,15 +1176,14 @@ test-diff:
|
||||||
done
|
done
|
||||||
|
|
||||||
tidy: clean
|
tidy: clean
|
||||||
@if perltidy -v|grep v20181120 >/dev/null; then \
|
@if perltidy -v|grep v20210717 >/dev/null; then \
|
||||||
find lemon*/ -type f \( -name '*.pm' -or -name '*.pl' -or -name '*.fcgi' -or -name '*.t' \) -print -exec perltidy -se -b {} \; ; \
|
for f in `find lemon*/ -type f \( -name '*.pm' -or -name '*.pl' -or -name '*.fcgi' -or -name '*.t' \)`; do \
|
||||||
else echo "Wrong perltidy version, please install Perl::Tidy@20181120" ; exit 1 ;\
|
echo -n $$f; \
|
||||||
|
perltidy -se -b $$f; \
|
||||||
|
echo; \
|
||||||
|
done; \
|
||||||
|
else echo "Wrong perltidy version, please install Perl::Tidy@20210717" ; exit 1 ;\
|
||||||
fi
|
fi
|
||||||
for f in `find lemon*/ -type f \( -name '*.pm' -or -name '*.pl' -or -name '*.fcgi' -or -name '*.t' \)`; do \
|
|
||||||
echo -n $$f; \
|
|
||||||
perltidy -se -b $$f; \
|
|
||||||
echo; \
|
|
||||||
done
|
|
||||||
find lemon*/ -name '*.bak' -delete
|
find lemon*/ -name '*.bak' -delete
|
||||||
$(MAKE) json
|
$(MAKE) json
|
||||||
|
|
||||||
|
|
|
@ -63,10 +63,11 @@ sub testEmail {
|
||||||
eval {
|
eval {
|
||||||
Lemonldap::NG::Common::EmailTransport::sendTestMail( $conf, $dest );
|
Lemonldap::NG::Common::EmailTransport::sendTestMail( $conf, $dest );
|
||||||
};
|
};
|
||||||
my $error = $@;
|
my $error = $@;
|
||||||
if ($error) {
|
if ($error) {
|
||||||
die $error;
|
die $error;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
print STDERR "Test email successfully sent to $dest\n";
|
print STDERR "Test email successfully sent to $dest\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -190,7 +190,7 @@ sub getConf {
|
||||||
eval { $r = $self->{refLocalStorage}->get('conf') }
|
eval { $r = $self->{refLocalStorage}->get('conf') }
|
||||||
if ( $> and not $args->{noCache} );
|
if ( $> and not $args->{noCache} );
|
||||||
$msg .= "Warn: $@" if ($@);
|
$msg .= "Warn: $@" if ($@);
|
||||||
|
|
||||||
if ( ref($r)
|
if ( ref($r)
|
||||||
and $r->{cfgNum}
|
and $r->{cfgNum}
|
||||||
and $args->{cfgNum}
|
and $args->{cfgNum}
|
||||||
|
|
|
@ -7,9 +7,9 @@ use Mouse;
|
||||||
use Lemonldap::NG::Common::Conf;
|
use Lemonldap::NG::Common::Conf;
|
||||||
|
|
||||||
has '_confAcc' => ( is => 'rw', isa => 'Lemonldap::NG::Common::Conf' );
|
has '_confAcc' => ( is => 'rw', isa => 'Lemonldap::NG::Common::Conf' );
|
||||||
has 'configStorage' => ( is => 'rw', isa => 'HashRef', default => sub { {} } );
|
has 'configStorage' => ( is => 'rw', isa => 'HashRef', default => sub { {} } );
|
||||||
has 'currentConf' => ( is => 'rw', required => 1, default => sub { {} } );
|
has 'currentConf' => ( is => 'rw', required => 1, default => sub { {} } );
|
||||||
has 'protection' => ( is => 'rw', isa => 'Str', default => 'manager' );
|
has 'protection' => ( is => 'rw', isa => 'Str', default => 'manager' );
|
||||||
|
|
||||||
our $VERSION = '2.0.11';
|
our $VERSION = '2.0.11';
|
||||||
|
|
||||||
|
|
|
@ -194,8 +194,8 @@ sub store {
|
||||||
$operation = $self->ldap->add(
|
$operation = $self->ldap->add(
|
||||||
$confDN,
|
$confDN,
|
||||||
attrs => [
|
attrs => [
|
||||||
objectClass => [ 'top', $self->{ldapObjectClass} ],
|
objectClass => [ 'top', $self->{ldapObjectClass} ],
|
||||||
$self->{ldapAttributeId} => $confName,
|
$self->{ldapAttributeId} => $confName,
|
||||||
$self->{ldapAttributeContent} => \@confValues,
|
$self->{ldapAttributeContent} => \@confValues,
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
|
@ -35,7 +35,7 @@ sub load {
|
||||||
cfgNum => 1,
|
cfgNum => 1,
|
||||||
cfgDate => time,
|
cfgDate => time,
|
||||||
cfgAuthor => 'LLNG Team',
|
cfgAuthor => 'LLNG Team',
|
||||||
cfgLog =>
|
cfgLog =>
|
||||||
q"Do not edit this configuration, Null backend uses lemonldap-ng.ini values only",
|
q"Do not edit this configuration, Null backend uses lemonldap-ng.ini values only",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ sub store {
|
||||||
$req = $self->_dbh->prepare(
|
$req = $self->_dbh->prepare(
|
||||||
"INSERT INTO $self->{dbiTable} (cfgNum,field,value) VALUES (?,?,?)");
|
"INSERT INTO $self->{dbiTable} (cfgNum,field,value) VALUES (?,?,?)");
|
||||||
|
|
||||||
_delete($self,$cfgNum) if $lastCfg == $cfgNum;
|
_delete( $self, $cfgNum ) if $lastCfg == $cfgNum;
|
||||||
unless ($req) {
|
unless ($req) {
|
||||||
$self->logError;
|
$self->logError;
|
||||||
return UNKNOWN_ERROR;
|
return UNKNOWN_ERROR;
|
||||||
|
|
|
@ -36,7 +36,8 @@ sub available {
|
||||||
my $sth =
|
my $sth =
|
||||||
$self->_dbh->prepare( "SELECT DISTINCT cfgNum from "
|
$self->_dbh->prepare( "SELECT DISTINCT cfgNum from "
|
||||||
. $self->{dbiTable}
|
. $self->{dbiTable}
|
||||||
. " order by cfgNum" ) or $self->logError;
|
. " order by cfgNum" )
|
||||||
|
or $self->logError;
|
||||||
$sth->execute() or $self->logError;
|
$sth->execute() or $self->logError;
|
||||||
my @conf;
|
my @conf;
|
||||||
while ( my @row = $sth->fetchrow_array ) {
|
while ( my @row = $sth->fetchrow_array ) {
|
||||||
|
@ -105,8 +106,8 @@ sub unlock {
|
||||||
sub delete {
|
sub delete {
|
||||||
my ( $self, $cfgNum ) = @_;
|
my ( $self, $cfgNum ) = @_;
|
||||||
my $req =
|
my $req =
|
||||||
$self->_dbh->prepare("DELETE FROM $self->{dbiTable} WHERE cfgNum=?")
|
$self->_dbh->prepare("DELETE FROM $self->{dbiTable} WHERE cfgNum=?")
|
||||||
or $self->logError;
|
or $self->logError;
|
||||||
my $res = $req->execute($cfgNum) or $self->logError;
|
my $res = $req->execute($cfgNum) or $self->logError;
|
||||||
$Lemonldap::NG::Common::Conf::msg .=
|
$Lemonldap::NG::Common::Conf::msg .=
|
||||||
"Unable to find conf $cfgNum (" . $self->_dbh->errstr . ")"
|
"Unable to find conf $cfgNum (" . $self->_dbh->errstr . ")"
|
||||||
|
|
|
@ -17,7 +17,7 @@ sub defaultValues {
|
||||||
},
|
},
|
||||||
'authChoiceParam' => 'lmAuth',
|
'authChoiceParam' => 'lmAuth',
|
||||||
'authentication' => 'Demo',
|
'authentication' => 'Demo',
|
||||||
'available2F' =>
|
'available2F' =>
|
||||||
'UTOTP,TOTP,U2F,REST,Mail2F,Ext2F,WebAuthn,Yubikey,Radius',
|
'UTOTP,TOTP,U2F,REST,Mail2F,Ext2F,WebAuthn,Yubikey,Radius',
|
||||||
'available2FSelfRegistration' => 'TOTP,U2F,WebAuthn,Yubikey',
|
'available2FSelfRegistration' => 'TOTP,U2F,WebAuthn,Yubikey',
|
||||||
'bruteForceProtectionLockTimes' => '15, 30, 60, 300, 600',
|
'bruteForceProtectionLockTimes' => '15, 30, 60, 300, 600',
|
||||||
|
@ -102,7 +102,7 @@ sub defaultValues {
|
||||||
'globalLogoutTimer' => 1,
|
'globalLogoutTimer' => 1,
|
||||||
'globalStorage' => 'Apache::Session::File',
|
'globalStorage' => 'Apache::Session::File',
|
||||||
'globalStorageOptions' => {
|
'globalStorageOptions' => {
|
||||||
'Directory' => '/var/lib/lemonldap-ng/sessions/',
|
'Directory' => '/var/lib/lemonldap-ng/sessions/',
|
||||||
'generateModule' =>
|
'generateModule' =>
|
||||||
'Lemonldap::NG::Common::Apache::Session::Generate::SHA256',
|
'Lemonldap::NG::Common::Apache::Session::Generate::SHA256',
|
||||||
'LockDirectory' => '/var/lib/lemonldap-ng/sessions/lock/'
|
'LockDirectory' => '/var/lib/lemonldap-ng/sessions/lock/'
|
||||||
|
@ -175,20 +175,20 @@ sub defaultValues {
|
||||||
'locationRules' => {
|
'locationRules' => {
|
||||||
'default' => 'deny'
|
'default' => 'deny'
|
||||||
},
|
},
|
||||||
'logoutServices' => {},
|
'logoutServices' => {},
|
||||||
'macros' => {},
|
'macros' => {},
|
||||||
'mail2fActivation' => 0,
|
'mail2fActivation' => 0,
|
||||||
'mail2fCodeRegex' => '\\d{6}',
|
'mail2fCodeRegex' => '\\d{6}',
|
||||||
'mailCharset' => 'utf-8',
|
'mailCharset' => 'utf-8',
|
||||||
'mailFrom' => 'noreply@example.com',
|
'mailFrom' => 'noreply@example.com',
|
||||||
'mailSessionKey' => 'mail',
|
'mailSessionKey' => 'mail',
|
||||||
'mailTimeout' => 0,
|
'mailTimeout' => 0,
|
||||||
'mailUrl' => 'http://auth.example.com/resetpwd',
|
'mailUrl' => 'http://auth.example.com/resetpwd',
|
||||||
'managerDn' => '',
|
'managerDn' => '',
|
||||||
'managerPassword' => '',
|
'managerPassword' => '',
|
||||||
'max2FDevices' => 10,
|
'max2FDevices' => 10,
|
||||||
'max2FDevicesNameLength' => 20,
|
'max2FDevicesNameLength' => 20,
|
||||||
'multiValuesSeparator' => '; ',
|
'multiValuesSeparator' => '; ',
|
||||||
'mySessionAuthorizedRWKeys' =>
|
'mySessionAuthorizedRWKeys' =>
|
||||||
[ '_appsListOrder', '_oidcConnectedRP', '_oidcConsents' ],
|
[ '_appsListOrder', '_oidcConnectedRP', '_oidcConsents' ],
|
||||||
'newLocationWarningLocationAttribute' => 'ipAddr',
|
'newLocationWarningLocationAttribute' => 'ipAddr',
|
||||||
|
@ -196,7 +196,7 @@ sub defaultValues {
|
||||||
'newLocationWarningMaxValues' => '0',
|
'newLocationWarningMaxValues' => '0',
|
||||||
'notificationDefaultCond' => '',
|
'notificationDefaultCond' => '',
|
||||||
'notificationServerPOST' => 1,
|
'notificationServerPOST' => 1,
|
||||||
'notificationServerSentAttributes' =>
|
'notificationServerSentAttributes' =>
|
||||||
'uid reference date title subtitle text check',
|
'uid reference date title subtitle text check',
|
||||||
'notificationsMaxRetrieve' => 3,
|
'notificationsMaxRetrieve' => 3,
|
||||||
'notificationStorage' => 'File',
|
'notificationStorage' => 'File',
|
||||||
|
@ -250,7 +250,7 @@ sub defaultValues {
|
||||||
'passwordPolicyMinUpper' => 0,
|
'passwordPolicyMinUpper' => 0,
|
||||||
'passwordPolicySpecialChar' => '__ALL__',
|
'passwordPolicySpecialChar' => '__ALL__',
|
||||||
'passwordResetAllowedRetries' => 3,
|
'passwordResetAllowedRetries' => 3,
|
||||||
'persistentSessionAttributes' =>
|
'persistentSessionAttributes' =>
|
||||||
'_loginHistory _2fDevices notification_',
|
'_loginHistory _2fDevices notification_',
|
||||||
'port' => -1,
|
'port' => -1,
|
||||||
'portal' => 'http://auth.example.com/',
|
'portal' => 'http://auth.example.com/',
|
||||||
|
@ -261,7 +261,7 @@ sub defaultValues {
|
||||||
'portalDisplayGeneratePassword' => 1,
|
'portalDisplayGeneratePassword' => 1,
|
||||||
'portalDisplayLoginHistory' => 1,
|
'portalDisplayLoginHistory' => 1,
|
||||||
'portalDisplayLogout' => 1,
|
'portalDisplayLogout' => 1,
|
||||||
'portalDisplayOidcConsents' =>
|
'portalDisplayOidcConsents' =>
|
||||||
'$_oidcConsents && $_oidcConsents =~ /\\w+/',
|
'$_oidcConsents && $_oidcConsents =~ /\\w+/',
|
||||||
'portalDisplayRefreshMyRights' => 1,
|
'portalDisplayRefreshMyRights' => 1,
|
||||||
'portalDisplayRegister' => 1,
|
'portalDisplayRegister' => 1,
|
||||||
|
@ -289,11 +289,11 @@ sub defaultValues {
|
||||||
'http://auth.example.com/Lemonldap/NG/Common/PSGI/SOAPService',
|
'http://auth.example.com/Lemonldap/NG/Common/PSGI/SOAPService',
|
||||||
'proxy' => 'http://auth.example.com/sessions'
|
'proxy' => 'http://auth.example.com/sessions'
|
||||||
},
|
},
|
||||||
'requireToken' => 1,
|
'requireToken' => 1,
|
||||||
'rest2fActivation' => 0,
|
'rest2fActivation' => 0,
|
||||||
'restAuthnLevel' => 2,
|
'restAuthnLevel' => 2,
|
||||||
'restClockTolerance' => 15,
|
'restClockTolerance' => 15,
|
||||||
'sameSite' => '',
|
'sameSite' => '',
|
||||||
'samlAttributeAuthorityDescriptorAttributeServiceSOAP' =>
|
'samlAttributeAuthorityDescriptorAttributeServiceSOAP' =>
|
||||||
'urn:oasis:names:tc:SAML:2.0:bindings:SOAP;#PORTAL#/saml/AA/SOAP;',
|
'urn:oasis:names:tc:SAML:2.0:bindings:SOAP;#PORTAL#/saml/AA/SOAP;',
|
||||||
'samlAuthnContextMapKerberos' => 4,
|
'samlAuthnContextMapKerberos' => 4,
|
||||||
|
@ -333,7 +333,7 @@ sub defaultValues {
|
||||||
'0;1;urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact;#PORTAL#/saml/proxySingleSignOnArtifact',
|
'0;1;urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact;#PORTAL#/saml/proxySingleSignOnArtifact',
|
||||||
'samlSPSSODescriptorAssertionConsumerServiceHTTPPost' =>
|
'samlSPSSODescriptorAssertionConsumerServiceHTTPPost' =>
|
||||||
'1;0;urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST;#PORTAL#/saml/proxySingleSignOnPost',
|
'1;0;urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST;#PORTAL#/saml/proxySingleSignOnPost',
|
||||||
'samlSPSSODescriptorAuthnRequestsSigned' => 1,
|
'samlSPSSODescriptorAuthnRequestsSigned' => 1,
|
||||||
'samlSPSSODescriptorSingleLogoutServiceHTTPPost' =>
|
'samlSPSSODescriptorSingleLogoutServiceHTTPPost' =>
|
||||||
'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST;#PORTAL#/saml/proxySingleLogout;#PORTAL#/saml/proxySingleLogoutReturn',
|
'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST;#PORTAL#/saml/proxySingleLogout;#PORTAL#/saml/proxySingleLogoutReturn',
|
||||||
'samlSPSSODescriptorSingleLogoutServiceHTTPRedirect' =>
|
'samlSPSSODescriptorSingleLogoutServiceHTTPRedirect' =>
|
||||||
|
@ -345,7 +345,7 @@ sub defaultValues {
|
||||||
'sfEngine' => '::2F::Engines::Default',
|
'sfEngine' => '::2F::Engines::Default',
|
||||||
'sfManagerRule' => 1,
|
'sfManagerRule' => 1,
|
||||||
'sfRemovedMsgRule' => 0,
|
'sfRemovedMsgRule' => 0,
|
||||||
'sfRemovedNotifMsg' =>
|
'sfRemovedNotifMsg' =>
|
||||||
'_removedSF_ expired second factor(s) has/have been removed (_nameSF_)!',
|
'_removedSF_ expired second factor(s) has/have been removed (_nameSF_)!',
|
||||||
'sfRemovedNotifRef' => 'RemoveSF',
|
'sfRemovedNotifRef' => 'RemoveSF',
|
||||||
'sfRemovedNotifTitle' => 'Second factor notification',
|
'sfRemovedNotifTitle' => 'Second factor notification',
|
||||||
|
|
|
@ -394,16 +394,17 @@ sub _oidcMetaDataNodes {
|
||||||
my ( $id, $resp ) = ( 1, [] );
|
my ( $id, $resp ) = ( 1, [] );
|
||||||
|
|
||||||
# Handle RP Attributes
|
# Handle RP Attributes
|
||||||
if ($query eq "oidcRPMetaDataExportedVars") {
|
if ( $query eq "oidcRPMetaDataExportedVars" ) {
|
||||||
my $pk = eval { $self->getConfKey( $req, $query )->{$partner} } // {};
|
my $pk = eval { $self->getConfKey( $req, $query )->{$partner} } // {};
|
||||||
return $self->sendError( $req, undef, 400 ) if ( $req->error );
|
return $self->sendError( $req, undef, 400 ) if ( $req->error );
|
||||||
foreach my $h ( sort keys %$pk ) {
|
foreach my $h ( sort keys %$pk ) {
|
||||||
|
|
||||||
# Set default values for type and array
|
# Set default values for type and array
|
||||||
my $data = [ split /;/, $pk->{$h} ];
|
my $data = [ split /;/, $pk->{$h} ];
|
||||||
unless ( $data->[1]) {
|
unless ( $data->[1] ) {
|
||||||
$data->[1] = "string";
|
$data->[1] = "string";
|
||||||
}
|
}
|
||||||
unless ( $data->[2]) {
|
unless ( $data->[2] ) {
|
||||||
$data->[2] = "auto";
|
$data->[2] = "auto";
|
||||||
}
|
}
|
||||||
push @$resp,
|
push @$resp,
|
||||||
|
@ -416,6 +417,7 @@ sub _oidcMetaDataNodes {
|
||||||
}
|
}
|
||||||
return $self->sendJSONresponse( $req, $resp );
|
return $self->sendJSONresponse( $req, $resp );
|
||||||
}
|
}
|
||||||
|
|
||||||
# Return all exported attributes if asked
|
# Return all exported attributes if asked
|
||||||
elsif ( $query =~
|
elsif ( $query =~
|
||||||
/^(?:oidc${type}MetaDataExportedVars|oidcRPMetaDataOptionsExtraClaims|oidcRPMetaDataMacros|oidcRPMetaDataScopeRules)$/
|
/^(?:oidc${type}MetaDataExportedVars|oidcRPMetaDataOptionsExtraClaims|oidcRPMetaDataMacros|oidcRPMetaDataScopeRules)$/
|
||||||
|
@ -733,9 +735,9 @@ sub combModules {
|
||||||
my $res = [];
|
my $res = [];
|
||||||
foreach my $mod ( keys %$val ) {
|
foreach my $mod ( keys %$val ) {
|
||||||
my $tmp;
|
my $tmp;
|
||||||
$tmp->{title} = $mod;
|
$tmp->{title} = $mod;
|
||||||
$tmp->{id} = "combModules/$mod";
|
$tmp->{id} = "combModules/$mod";
|
||||||
$tmp->{type} = 'cmbModule';
|
$tmp->{type} = 'cmbModule';
|
||||||
$tmp->{data}->{$_} = $val->{$mod}->{$_} foreach (qw(type for));
|
$tmp->{data}->{$_} = $val->{$mod}->{$_} foreach (qw(type for));
|
||||||
my $over = $val->{$mod}->{over} // {};
|
my $over = $val->{$mod}->{over} // {};
|
||||||
$tmp->{data}->{over} = [ map { [ $_, $over->{$_} ] } keys %$over ];
|
$tmp->{data}->{over} = [ map { [ $_, $over->{$_} ] } keys %$over ];
|
||||||
|
@ -809,8 +811,8 @@ sub metadata {
|
||||||
}
|
}
|
||||||
|
|
||||||
# Find next and previous conf
|
# Find next and previous conf
|
||||||
my @a = $self->confAcc->available;
|
my @a = $self->confAcc->available;
|
||||||
my $id = -1;
|
my $id = -1;
|
||||||
my ($ind) = map { $id++; $_ == $res->{cfgNum} ? ($id) : () } @a;
|
my ($ind) = map { $id++; $_ == $res->{cfgNum} ? ($id) : () } @a;
|
||||||
if ($ind) { $res->{prev} = $a[ $ind - 1 ]; }
|
if ($ind) { $res->{prev} = $a[ $ind - 1 ]; }
|
||||||
if ( defined $ind and $ind < $#a ) {
|
if ( defined $ind and $ind < $#a ) {
|
||||||
|
|
|
@ -26,7 +26,7 @@ sub serviceToXML {
|
||||||
my ( $self, $conf, $type ) = @_;
|
my ( $self, $conf, $type ) = @_;
|
||||||
|
|
||||||
seek DATA, $dataStart, 0;
|
seek DATA, $dataStart, 0;
|
||||||
my $s = join '', <DATA>;
|
my $s = join '', <DATA>;
|
||||||
my $template = HTML::Template->new(
|
my $template = HTML::Template->new(
|
||||||
scalarref => \$s,
|
scalarref => \$s,
|
||||||
die_on_bad_params => 0,
|
die_on_bad_params => 0,
|
||||||
|
|
|
@ -95,7 +95,7 @@ sub configTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
sub sendTestMail {
|
sub sendTestMail {
|
||||||
my ($conf, $dest) = @_;
|
my ( $conf, $dest ) = @_;
|
||||||
my $transport = Lemonldap::NG::Common::EmailTransport->new($conf);
|
my $transport = Lemonldap::NG::Common::EmailTransport->new($conf);
|
||||||
my $message = MIME::Entity->build(
|
my $message = MIME::Entity->build(
|
||||||
From => $conf->{mailFrom},
|
From => $conf->{mailFrom},
|
||||||
|
@ -110,7 +110,7 @@ sub sendTestMail {
|
||||||
# Send the mail
|
# Send the mail
|
||||||
eval { sendmail( $message->stringify, { transport => $transport } ); };
|
eval { sendmail( $message->stringify, { transport => $transport } ); };
|
||||||
if ($@) {
|
if ($@) {
|
||||||
my $error = ( $@->isa('Throwable::Error') ? $@->message : $@ );
|
my $error = ( $@->isa('Throwable::Error') ? $@->message : $@ );
|
||||||
die $error;
|
die $error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ use strict;
|
||||||
use base 'Exporter';
|
use base 'Exporter';
|
||||||
|
|
||||||
our $VERSION = '2.0.10';
|
our $VERSION = '2.0.10';
|
||||||
our @EXPORT = qw(&isIPv6 &net6 &expand6);
|
our @EXPORT = qw(&isIPv6 &net6 &expand6);
|
||||||
|
|
||||||
sub isIPv6 {
|
sub isIPv6 {
|
||||||
my ($ip) = @_;
|
my ($ip) = @_;
|
||||||
|
|
|
@ -58,12 +58,12 @@ sub new {
|
||||||
}
|
}
|
||||||
|
|
||||||
sub setRequestObj {
|
sub setRequestObj {
|
||||||
my ($self, $req) = @_;
|
my ( $self, $req ) = @_;
|
||||||
Log::Log4perl::MDC->put( "req", $req );
|
Log::Log4perl::MDC->put( "req", $req );
|
||||||
}
|
}
|
||||||
|
|
||||||
sub clearRequestObj {
|
sub clearRequestObj {
|
||||||
my ($self, $req) = @_;
|
my ( $self, $req ) = @_;
|
||||||
my $text = Log::Log4perl::MDC->remove();
|
my $text = Log::Log4perl::MDC->remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,9 +13,9 @@ use Sentry::Raven;
|
||||||
our $VERSION = '2.0.14';
|
our $VERSION = '2.0.14';
|
||||||
|
|
||||||
sub new {
|
sub new {
|
||||||
my $self = bless {}, shift;
|
my $self = bless {}, shift;
|
||||||
my ($conf) = @_;
|
my ($conf) = @_;
|
||||||
my $show = 1;
|
my $show = 1;
|
||||||
$self->{raven} = Sentry::Raven->new( sentry_dsn => $conf->{sentryDsn} );
|
$self->{raven} = Sentry::Raven->new( sentry_dsn => $conf->{sentryDsn} );
|
||||||
foreach (qw(error warn notice info debug)) {
|
foreach (qw(error warn notice info debug)) {
|
||||||
my $rl = $_;
|
my $rl = $_;
|
||||||
|
|
|
@ -356,7 +356,8 @@ sub _logAndHandle {
|
||||||
if ( ref( $self->logger ) and $self->logger->can('setRequestObj') ) {
|
if ( ref( $self->logger ) and $self->logger->can('setRequestObj') ) {
|
||||||
$self->logger->setRequestObj($req);
|
$self->logger->setRequestObj($req);
|
||||||
}
|
}
|
||||||
if ( ref( $self->userLogger ) and $self->userLogger->can('setRequestObj') ) {
|
if ( ref( $self->userLogger ) and $self->userLogger->can('setRequestObj') )
|
||||||
|
{
|
||||||
$self->userLogger->setRequestObj($req);
|
$self->userLogger->setRequestObj($req);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -367,7 +368,9 @@ sub _logAndHandle {
|
||||||
if ( ref( $self->logger ) and $self->logger->can('clearRequestObj') ) {
|
if ( ref( $self->logger ) and $self->logger->can('clearRequestObj') ) {
|
||||||
$self->logger->clearRequestObj($req);
|
$self->logger->clearRequestObj($req);
|
||||||
}
|
}
|
||||||
if ( ref( $self->userLogger ) and $self->userLogger->can('clearRequestObj') ) {
|
if ( ref( $self->userLogger )
|
||||||
|
and $self->userLogger->can('clearRequestObj') )
|
||||||
|
{
|
||||||
$self->userLogger->clearRequestObj($req);
|
$self->userLogger->clearRequestObj($req);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ sub _get {
|
||||||
'REQUEST_URI' => $path . ( $query ? "?$query" : '' ),
|
'REQUEST_URI' => $path . ( $query ? "?$query" : '' ),
|
||||||
'SERVER_PORT' => '8002',
|
'SERVER_PORT' => '8002',
|
||||||
'SERVER_PROTOCOL' => 'HTTP/1.1',
|
'SERVER_PROTOCOL' => 'HTTP/1.1',
|
||||||
'HTTP_USER_AGENT' =>
|
'HTTP_USER_AGENT' =>
|
||||||
'Mozilla/5.0 (VAX-4000; rv:36.0) Gecko/20350101 Firefox',
|
'Mozilla/5.0 (VAX-4000; rv:36.0) Gecko/20350101 Firefox',
|
||||||
'REMOTE_ADDR' => '127.0.0.1',
|
'REMOTE_ADDR' => '127.0.0.1',
|
||||||
'HTTP_HOST' => '127.0.0.1:8002'
|
'HTTP_HOST' => '127.0.0.1:8002'
|
||||||
|
@ -52,7 +52,7 @@ sub _post {
|
||||||
'REQUEST_URI' => $path . ( $query ? "?$query" : '' ),
|
'REQUEST_URI' => $path . ( $query ? "?$query" : '' ),
|
||||||
'SERVER_PORT' => '8002',
|
'SERVER_PORT' => '8002',
|
||||||
'SERVER_PROTOCOL' => 'HTTP/1.1',
|
'SERVER_PROTOCOL' => 'HTTP/1.1',
|
||||||
'HTTP_USER_AGENT' =>
|
'HTTP_USER_AGENT' =>
|
||||||
'Mozilla/5.0 (VAX-4000; rv:36.0) Gecko/20350101 Firefox',
|
'Mozilla/5.0 (VAX-4000; rv:36.0) Gecko/20350101 Firefox',
|
||||||
'REMOTE_ADDR' => '127.0.0.1',
|
'REMOTE_ADDR' => '127.0.0.1',
|
||||||
'HTTP_HOST' => '127.0.0.1:8002',
|
'HTTP_HOST' => '127.0.0.1:8002',
|
||||||
|
@ -81,7 +81,7 @@ sub _put {
|
||||||
'REQUEST_URI' => $path . ( $query ? "?$query" : '' ),
|
'REQUEST_URI' => $path . ( $query ? "?$query" : '' ),
|
||||||
'SERVER_PORT' => '8002',
|
'SERVER_PORT' => '8002',
|
||||||
'SERVER_PROTOCOL' => 'HTTP/1.1',
|
'SERVER_PROTOCOL' => 'HTTP/1.1',
|
||||||
'HTTP_USER_AGENT' =>
|
'HTTP_USER_AGENT' =>
|
||||||
'Mozilla/5.0 (VAX-4000; rv:36.0) Gecko/20350101 Firefox',
|
'Mozilla/5.0 (VAX-4000; rv:36.0) Gecko/20350101 Firefox',
|
||||||
'REMOTE_ADDR' => '127.0.0.1',
|
'REMOTE_ADDR' => '127.0.0.1',
|
||||||
'HTTP_HOST' => '127.0.0.1:8002',
|
'HTTP_HOST' => '127.0.0.1:8002',
|
||||||
|
@ -110,7 +110,7 @@ sub _patch {
|
||||||
'REQUEST_URI' => $path . ( $query ? "?$query" : '' ),
|
'REQUEST_URI' => $path . ( $query ? "?$query" : '' ),
|
||||||
'SERVER_PORT' => '8002',
|
'SERVER_PORT' => '8002',
|
||||||
'SERVER_PROTOCOL' => 'HTTP/1.1',
|
'SERVER_PROTOCOL' => 'HTTP/1.1',
|
||||||
'HTTP_USER_AGENT' =>
|
'HTTP_USER_AGENT' =>
|
||||||
'Mozilla/5.0 (VAX-4000; rv:36.0) Gecko/20350101 Firefox',
|
'Mozilla/5.0 (VAX-4000; rv:36.0) Gecko/20350101 Firefox',
|
||||||
'REMOTE_ADDR' => '127.0.0.1',
|
'REMOTE_ADDR' => '127.0.0.1',
|
||||||
'HTTP_HOST' => '127.0.0.1:8002',
|
'HTTP_HOST' => '127.0.0.1:8002',
|
||||||
|
@ -137,7 +137,7 @@ sub _del {
|
||||||
'REQUEST_URI' => $path . ( $query ? "?$query" : '' ),
|
'REQUEST_URI' => $path . ( $query ? "?$query" : '' ),
|
||||||
'SERVER_PORT' => '8002',
|
'SERVER_PORT' => '8002',
|
||||||
'SERVER_PROTOCOL' => 'HTTP/1.1',
|
'SERVER_PROTOCOL' => 'HTTP/1.1',
|
||||||
'HTTP_USER_AGENT' =>
|
'HTTP_USER_AGENT' =>
|
||||||
'Mozilla/5.0 (VAX-4000; rv:36.0) Gecko/20350101 Firefox',
|
'Mozilla/5.0 (VAX-4000; rv:36.0) Gecko/20350101 Firefox',
|
||||||
'REMOTE_ADDR' => '127.0.0.1',
|
'REMOTE_ADDR' => '127.0.0.1',
|
||||||
'HTTP_HOST' => '127.0.0.1:8002',
|
'HTTP_HOST' => '127.0.0.1:8002',
|
||||||
|
|
|
@ -48,8 +48,7 @@ sub userData {
|
||||||
return $self->{userData}
|
return $self->{userData}
|
||||||
|| {
|
|| {
|
||||||
( $Lemonldap::NG::Handler::Main::tsv->{whatToTrace}
|
( $Lemonldap::NG::Handler::Main::tsv->{whatToTrace}
|
||||||
|| '_whatToTrace' ) => $self->{user},
|
|| '_whatToTrace' ) => $self->{user}, };
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub respHeaders {
|
sub respHeaders {
|
||||||
|
|
|
@ -11,8 +11,8 @@ extends 'Lemonldap::NG::Common::PSGI';
|
||||||
|
|
||||||
# Properties
|
# Properties
|
||||||
has 'routes' => (
|
has 'routes' => (
|
||||||
is => 'rw',
|
is => 'rw',
|
||||||
isa => 'HashRef',
|
isa => 'HashRef',
|
||||||
default =>
|
default =>
|
||||||
sub { { GET => {}, POST => {}, PUT => {}, PATCH => {}, DELETE => {} } }
|
sub { { GET => {}, POST => {}, PUT => {}, PATCH => {}, DELETE => {} } }
|
||||||
);
|
);
|
||||||
|
|
|
@ -121,20 +121,29 @@ sub date {
|
||||||
return $year . $mon . $mday . $hour . $min . $sec;
|
return $year . $mon . $mday . $hour . $min . $sec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
## @function integer dateToTime(string date)
|
## @function integer dateToTime(string date)
|
||||||
# Converts a LDAP date into epoch time or returns undef upon failure.
|
# Converts a LDAP date into epoch time or returns undef upon failure.
|
||||||
# @param $date string Date in YYYYMMDDHHMMSS[+/-0000] format. It may contain a differential timezone, otherwise default TZ is GMT
|
# @param $date string Date in YYYYMMDDHHMMSS[+/-0000] format. It may contain a differential timezone, otherwise default TZ is GMT
|
||||||
# @return Date converted to time
|
# @return Date converted to time
|
||||||
sub dateToTime {
|
sub dateToTime {
|
||||||
my $date = shift;
|
my $date = shift;
|
||||||
return undef unless ( $date );
|
return undef unless ($date);
|
||||||
|
|
||||||
# Parse date
|
# Parse date
|
||||||
my ( $year, $month, $day, $hour, $min, $sec, $zone ) = ( $date =~ /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})([-+\w]*)/ );
|
my ( $year, $month, $day, $hour, $min, $sec, $zone ) =
|
||||||
|
( $date =~ /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})([-+\w]*)/ );
|
||||||
|
|
||||||
# Convert date to epoch time with GMT as default timezone if date contains none
|
# Convert date to epoch time with GMT as default timezone if date contains none
|
||||||
return str2time( $year . "-" . $month . "-" . $day . "T" . $hour . ":" . $min . ":" . $sec . $zone, "GMT" );
|
return str2time(
|
||||||
|
$year . "-"
|
||||||
|
. $month . "-"
|
||||||
|
. $day . "T"
|
||||||
|
. $hour . ":"
|
||||||
|
. $min . ":"
|
||||||
|
. $sec
|
||||||
|
. $zone,
|
||||||
|
"GMT"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
## @function boolean checkDate(string start, string end, boolean default_access)
|
## @function boolean checkDate(string start, string end, boolean default_access)
|
||||||
|
@ -158,10 +167,10 @@ sub checkDate {
|
||||||
|
|
||||||
# Convert dates to epoch time
|
# Convert dates to epoch time
|
||||||
my $starttime = &dateToTime($start);
|
my $starttime = &dateToTime($start);
|
||||||
my $endtime = &dateToTime($end);
|
my $endtime = &dateToTime($end);
|
||||||
|
|
||||||
# Convert current GMT date to epoch time
|
# Convert current GMT date to epoch time
|
||||||
my $datetime = &dateToTime(&date(1));
|
my $datetime = &dateToTime( &date(1) );
|
||||||
|
|
||||||
return 1 if ( ( $datetime >= $starttime ) and ( $datetime <= $endtime ) );
|
return 1 if ( ( $datetime >= $starttime ) and ( $datetime <= $endtime ) );
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -126,8 +126,8 @@ sub BUILD {
|
||||||
|
|
||||||
if ( $self->{info} ) {
|
if ( $self->{info} ) {
|
||||||
foreach ( keys %{ $self->{info} } ) {
|
foreach ( keys %{ $self->{info} } ) {
|
||||||
next if ( $_ eq "_session_id" and $data->{_session_id} );
|
next if ( $_ eq "_session_id" and $data->{_session_id} );
|
||||||
next if ( $_ eq "_session_kind" and $data->{_session_kind});
|
next if ( $_ eq "_session_kind" and $data->{_session_kind} );
|
||||||
if ( defined $self->{info}->{$_} ) {
|
if ( defined $self->{info}->{$_} ) {
|
||||||
$data->{$_} = $self->{info}->{$_};
|
$data->{$_} = $self->{info}->{$_};
|
||||||
}
|
}
|
||||||
|
|
|
@ -258,13 +258,13 @@ sub getApacheSession {
|
||||||
my $apacheSession = Lemonldap::NG::Common::Session->new( {
|
my $apacheSession = Lemonldap::NG::Common::Session->new( {
|
||||||
storageModule => $mod->{module},
|
storageModule => $mod->{module},
|
||||||
storageModuleOptions => $mod->{options},
|
storageModuleOptions => $mod->{options},
|
||||||
cacheModule =>
|
cacheModule =>
|
||||||
Lemonldap::NG::Handler::PSGI::Main->tsv->{sessionCacheModule},
|
Lemonldap::NG::Handler::PSGI::Main->tsv->{sessionCacheModule},
|
||||||
cacheModuleOptions =>
|
cacheModuleOptions =>
|
||||||
Lemonldap::NG::Handler::PSGI::Main->tsv->{sessionCacheOptions},
|
Lemonldap::NG::Handler::PSGI::Main->tsv->{sessionCacheOptions},
|
||||||
id => $id,
|
id => $id,
|
||||||
force => $force,
|
force => $force,
|
||||||
( $id ? () : ( kind => $mod->{kind} ) ),
|
( $id ? () : ( kind => $mod->{kind} ) ),
|
||||||
( $info ? ( info => $info ) : () ),
|
( $info ? ( info => $info ) : () ),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -294,7 +294,7 @@ sub getMod {
|
||||||
}
|
}
|
||||||
|
|
||||||
sub getGlobal {
|
sub getGlobal {
|
||||||
my ( $self ) = @_;
|
my ($self) = @_;
|
||||||
return $self->sessionTypes->{global};
|
return $self->sessionTypes->{global};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,8 +55,11 @@ ok(
|
||||||
|
|
||||||
# Test "and"
|
# Test "and"
|
||||||
|
|
||||||
@tests = ( '[A and B, A]', '[A,B] and [B,C]',
|
@tests = (
|
||||||
'if(0) then [A,B] else [A,B] and [B,C]' );
|
'[A and B, A]',
|
||||||
|
'[A,B] and [B,C]',
|
||||||
|
'if(0) then [A,B] else [A,B] and [B,C]'
|
||||||
|
);
|
||||||
|
|
||||||
while ( my $expr = shift @tests ) {
|
while ( my $expr = shift @tests ) {
|
||||||
ok( [ getok($expr) ]->[0] == 0, qq{"$expr" returns PE_OK as auth result} )
|
ok( [ getok($expr) ]->[0] == 0, qq{"$expr" returns PE_OK as auth result} )
|
||||||
|
|
|
@ -240,7 +240,7 @@ is( @{$res}, 2, "Found 2 psessions" );
|
||||||
|
|
||||||
# Test search with where
|
# Test search with where
|
||||||
$res = getJson( "search", { where => "uid=dwho" } );
|
$res = getJson( "search", { where => "uid=dwho" } );
|
||||||
is( @{$res}, 2, "Found 2 sessions" );
|
is( @{$res}, 2, "Found 2 sessions" );
|
||||||
is( ( grep { $_->{uid} eq "dwho" } @{$res} ), 2, "Both sessions are dwho" );
|
is( ( grep { $_->{uid} eq "dwho" } @{$res} ), 2, "Both sessions are dwho" );
|
||||||
|
|
||||||
# Test search with where and field selection
|
# Test search with where and field selection
|
||||||
|
@ -259,7 +259,7 @@ is(
|
||||||
);
|
);
|
||||||
|
|
||||||
# Delete session
|
# Delete session
|
||||||
$cli->run( 'delete', {}, "9684dd2a6489bf2be2fbdd799a8028e3" );
|
$cli->run( 'delete', {}, "9684dd2a6489bf2be2fbdd799a8028e3" );
|
||||||
$cli->run( 'delete', { persistent => 1 }, "rtyler" );
|
$cli->run( 'delete', { persistent => 1 }, "rtyler" );
|
||||||
|
|
||||||
$res = getJson( "get", {}, "9684dd2a6489bf2be2fbdd799a8028e3" );
|
$res = getJson( "get", {}, "9684dd2a6489bf2be2fbdd799a8028e3" );
|
||||||
|
@ -348,7 +348,7 @@ is( ( keys %{$res} ), 2, "Found two consents" );
|
||||||
|
|
||||||
$cli->run( "consents", {}, "delete", "dwho", "rp-example" );
|
$cli->run( "consents", {}, "delete", "dwho", "rp-example" );
|
||||||
$res = getJson( "consents", {}, "get", "dwho" );
|
$res = getJson( "consents", {}, "get", "dwho" );
|
||||||
is( ( keys %{$res} ), 1, "Found one consent" );
|
is( ( keys %{$res} ), 1, "Found one consent" );
|
||||||
is( $res->{'rp-example'}, undef, "Consent for test-rp removed" );
|
is( $res->{'rp-example'}, undef, "Consent for test-rp removed" );
|
||||||
ok( $res->{'rp-example2'}, "Consent for test-rp2 still present" );
|
ok( $res->{'rp-example2'}, "Consent for test-rp2 still present" );
|
||||||
|
|
||||||
|
|
|
@ -72,18 +72,18 @@ SKIP: {
|
||||||
'name' => 'Imported automatically'
|
'name' => 'Imported automatically'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'name' => 'U2F-1',
|
'name' => 'U2F-1',
|
||||||
'type' => 'U2F',
|
'type' => 'U2F',
|
||||||
'epoch' => 1588691728,
|
'epoch' => 1588691728,
|
||||||
'_keyHandle' =>
|
'_keyHandle' =>
|
||||||
'4aS6vXlFQpG5XZSoad6auM9fFu7Q1wazQYwfPtPKN_Hll6Up_ceeWkOgqxm49swWq4Vvcg5UlX0sQQhuRe8heA',
|
'4aS6vXlFQpG5XZSoad6auM9fFu7Q1wazQYwfPtPKN_Hll6Up_ceeWkOgqxm49swWq4Vvcg5UlX0sQQhuRe8heA',
|
||||||
'_userKey' =>
|
'_userKey' =>
|
||||||
'BMgMqKPL2PhsjCNW78UEQyNF8zlJtrAAPtWMUDBp9VfDRF5oL2xkwFuyXRMPtRZ7lNfGijDrMc06bDNfp478sQQ',
|
'BMgMqKPL2PhsjCNW78UEQyNF8zlJtrAAPtWMUDBp9VfDRF5oL2xkwFuyXRMPtRZ7lNfGijDrMc06bDNfp478sQQ',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'name' => 'U2F-2',
|
'name' => 'U2F-2',
|
||||||
'type' => 'U2F',
|
'type' => 'U2F',
|
||||||
'epoch' => 1588691730,
|
'epoch' => 1588691730,
|
||||||
'_keyHandle' =>
|
'_keyHandle' =>
|
||||||
'F1Kk9V_O7KDPIx-mqp6CIjbz7ljA-ihWVWyoP1xYBe_HPLHR74aTLanmn0b4vI8DumiBWO1DAle3k6N55cXreg',
|
'F1Kk9V_O7KDPIx-mqp6CIjbz7ljA-ihWVWyoP1xYBe_HPLHR74aTLanmn0b4vI8DumiBWO1DAle3k6N55cXreg',
|
||||||
'_userKey' =>
|
'_userKey' =>
|
||||||
|
@ -128,9 +128,9 @@ SKIP: {
|
||||||
'name' => 'Imported automatically'
|
'name' => 'Imported automatically'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'name' => 'U2F-3',
|
'name' => 'U2F-3',
|
||||||
'type' => 'U2F',
|
'type' => 'U2F',
|
||||||
'epoch' => 1588691734,
|
'epoch' => 1588691734,
|
||||||
'_keyHandle' =>
|
'_keyHandle' =>
|
||||||
'4suXv5Cf10vbJEP72mVkLpBjhSqy5niOgfc0X_MjdxZ_g2e-V8biC6WyCTpF_kGV1FCa06YlcryPCtWUuUST_g',
|
'4suXv5Cf10vbJEP72mVkLpBjhSqy5niOgfc0X_MjdxZ_g2e-V8biC6WyCTpF_kGV1FCa06YlcryPCtWUuUST_g',
|
||||||
'_userKey' =>
|
'_userKey' =>
|
||||||
|
|
|
@ -48,7 +48,9 @@ sub launch {
|
||||||
if ( ref( $class->logger ) and $class->logger->can('setRequestObj') ) {
|
if ( ref( $class->logger ) and $class->logger->can('setRequestObj') ) {
|
||||||
$class->logger->setRequestObj($req);
|
$class->logger->setRequestObj($req);
|
||||||
}
|
}
|
||||||
if ( ref( $class->userLogger ) and $class->userLogger->can('setRequestObj') ) {
|
if ( ref( $class->userLogger )
|
||||||
|
and $class->userLogger->can('setRequestObj') )
|
||||||
|
{
|
||||||
$class->userLogger->setRequestObj($req);
|
$class->userLogger->setRequestObj($req);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +60,9 @@ sub launch {
|
||||||
if ( ref( $class->logger ) and $class->logger->can('clearRequestObj') ) {
|
if ( ref( $class->logger ) and $class->logger->can('clearRequestObj') ) {
|
||||||
$class->logger->clearRequestObj($req);
|
$class->logger->clearRequestObj($req);
|
||||||
}
|
}
|
||||||
if ( ref( $class->userLogger ) and $class->userLogger->can('clearRequestObj') ) {
|
if ( ref( $class->userLogger )
|
||||||
|
and $class->userLogger->can('clearRequestObj') )
|
||||||
|
{
|
||||||
$class->userLogger->clearRequestObj($req);
|
$class->userLogger->clearRequestObj($req);
|
||||||
}
|
}
|
||||||
return $res;
|
return $res;
|
||||||
|
|
|
@ -53,8 +53,7 @@ sub _loadVhostConfig {
|
||||||
my $resp = $class->ua->request($get);
|
my $resp = $class->ua->request($get);
|
||||||
if ( $resp->is_success ) {
|
if ( $resp->is_success ) {
|
||||||
$class->logger->debug('Response is success');
|
$class->logger->debug('Response is success');
|
||||||
eval {
|
eval { $json = from_json( $resp->content, { allow_nonref => 1 } ); };
|
||||||
$json = from_json( $resp->content, { allow_nonref => 1 } ); };
|
|
||||||
if ($@) {
|
if ($@) {
|
||||||
$class->logger->debug('Bad json file received');
|
$class->logger->debug('Bad json file received');
|
||||||
$class->logger->error(
|
$class->logger->error(
|
||||||
|
@ -92,7 +91,7 @@ q"I refuse to compile 'rules.json' when useSafeJail isn't activated! Yes I know,
|
||||||
|
|
||||||
$class->logger->debug("DevOps handler called by $vhost");
|
$class->logger->debug("DevOps handler called by $vhost");
|
||||||
$class->locationRulesInit( undef, { $vhost => $json->{rules} } );
|
$class->locationRulesInit( undef, { $vhost => $json->{rules} } );
|
||||||
$class->headersInit( undef, { $vhost => $json->{headers} } );
|
$class->headersInit( undef, { $vhost => $json->{headers} } );
|
||||||
$class->tsv->{lastVhostUpdate}->{$vhost} = time;
|
$class->tsv->{lastVhostUpdate}->{$vhost} = time;
|
||||||
$class->tsv->{https}->{$vhost} = uc $req->env->{HTTPS_REDIRECT} eq 'ON'
|
$class->tsv->{https}->{$vhost} = uc $req->env->{HTTPS_REDIRECT} eq 'ON'
|
||||||
if exists $req->env->{HTTPS_REDIRECT};
|
if exists $req->env->{HTTPS_REDIRECT};
|
||||||
|
|
|
@ -118,7 +118,8 @@ sub _logAuthTrace {
|
||||||
if ( ref( $self->logger ) and $self->logger->can('setRequestObj') ) {
|
if ( ref( $self->logger ) and $self->logger->can('setRequestObj') ) {
|
||||||
$self->logger->setRequestObj($req);
|
$self->logger->setRequestObj($req);
|
||||||
}
|
}
|
||||||
if ( ref( $self->userLogger ) and $self->userLogger->can('setRequestObj') ) {
|
if ( ref( $self->userLogger ) and $self->userLogger->can('setRequestObj') )
|
||||||
|
{
|
||||||
$self->userLogger->setRequestObj($req);
|
$self->userLogger->setRequestObj($req);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,7 +130,9 @@ sub _logAuthTrace {
|
||||||
if ( ref( $self->logger ) and $self->logger->can('clearRequestObj') ) {
|
if ( ref( $self->logger ) and $self->logger->can('clearRequestObj') ) {
|
||||||
$self->logger->clearRequestObj($req);
|
$self->logger->clearRequestObj($req);
|
||||||
}
|
}
|
||||||
if ( ref( $self->userLogger ) and $self->userLogger->can('clearRequestObj') ) {
|
if ( ref( $self->userLogger )
|
||||||
|
and $self->userLogger->can('clearRequestObj') )
|
||||||
|
{
|
||||||
$self->userLogger->clearRequestObj($req);
|
$self->userLogger->clearRequestObj($req);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,8 @@ our $VERSION = '2.0.9';
|
||||||
sub fetchId {
|
sub fetchId {
|
||||||
my ( $class, $req ) = @_;
|
my ( $class, $req ) = @_;
|
||||||
my $token = $req->{env}->{HTTP_X_LLNG_TOKEN};
|
my $token = $req->{env}->{HTTP_X_LLNG_TOKEN};
|
||||||
return $class->Lemonldap::NG::Handler::Main::fetchId($req) unless ($token =~ /\w+/);
|
return $class->Lemonldap::NG::Handler::Main::fetchId($req)
|
||||||
|
unless ( $token =~ /\w+/ );
|
||||||
$class->logger->debug("Found token: $token");
|
$class->logger->debug("Found token: $token");
|
||||||
|
|
||||||
# Decrypt token
|
# Decrypt token
|
||||||
|
|
|
@ -29,10 +29,10 @@ sub run {
|
||||||
my $localConfig = $class->localConfig;
|
my $localConfig = $class->localConfig;
|
||||||
my $zimbraPreAuthKey = $localConfig->{zimbraPreAuthKey};
|
my $zimbraPreAuthKey = $localConfig->{zimbraPreAuthKey};
|
||||||
my $zimbraAccountKey = $localConfig->{zimbraAccountKey} || 'uid';
|
my $zimbraAccountKey = $localConfig->{zimbraAccountKey} || 'uid';
|
||||||
my $zimbraBy = $localConfig->{zimbraBy} || 'id';
|
my $zimbraBy = $localConfig->{zimbraBy} || 'id';
|
||||||
my $zimbraUrl = $localConfig->{zimbraUrl} || '/service/preauth';
|
my $zimbraUrl = $localConfig->{zimbraUrl} || '/service/preauth';
|
||||||
my $zimbraSsoUrl = $localConfig->{zimbraSsoUrl} || '^/zimbrasso$';
|
my $zimbraSsoUrl = $localConfig->{zimbraSsoUrl} || '^/zimbrasso$';
|
||||||
my $timeout = $localConfig->{'timeout'} || '0';
|
my $timeout = $localConfig->{'timeout'} || '0';
|
||||||
|
|
||||||
# Remove trailing white-spaces
|
# Remove trailing white-spaces
|
||||||
$zimbraAccountKey =~ s/\s+$//;
|
$zimbraAccountKey =~ s/\s+$//;
|
||||||
|
|
|
@ -63,7 +63,9 @@ sub build_jail {
|
||||||
|
|
||||||
if ($build) {
|
if ($build) {
|
||||||
@builtCustomFunctions =
|
@builtCustomFunctions =
|
||||||
$self->customFunctions ? split( /[,\s]+/, $self->customFunctions ) : ();
|
$self->customFunctions
|
||||||
|
? split( /[,\s]+/, $self->customFunctions )
|
||||||
|
: ();
|
||||||
foreach (@builtCustomFunctions) {
|
foreach (@builtCustomFunctions) {
|
||||||
no warnings 'redefine';
|
no warnings 'redefine';
|
||||||
$api->logger->debug("Custom function: $_");
|
$api->logger->debug("Custom function: $_");
|
||||||
|
|
|
@ -65,7 +65,8 @@ sub checkConf {
|
||||||
or $class->cfgNum != $conf->{cfgNum}
|
or $class->cfgNum != $conf->{cfgNum}
|
||||||
or $class->cfgDate != $conf->{cfgDate} )
|
or $class->cfgDate != $conf->{cfgDate} )
|
||||||
{
|
{
|
||||||
$class->logger->debug("Get configuration $conf->{cfgNum} aged $conf->{cfgDate}");
|
$class->logger->debug(
|
||||||
|
"Get configuration $conf->{cfgNum} aged $conf->{cfgDate}");
|
||||||
unless ( $class->cfgNum( $conf->{cfgNum} )
|
unless ( $class->cfgNum( $conf->{cfgNum} )
|
||||||
&& $class->cfgDate( $conf->{cfgDate} ) )
|
&& $class->cfgDate( $conf->{cfgDate} ) )
|
||||||
{
|
{
|
||||||
|
|
|
@ -504,7 +504,7 @@ sub fetchId {
|
||||||
if $class->_isHttps( $req, $vhost );
|
if $class->_isHttps( $req, $vhost );
|
||||||
my $lookForHttpCookie = ( $class->tsv->{securedCookie} =~ /^(2|3)$/
|
my $lookForHttpCookie = ( $class->tsv->{securedCookie} =~ /^(2|3)$/
|
||||||
and not $class->_isHttps( $req, $vhost ) );
|
and not $class->_isHttps( $req, $vhost ) );
|
||||||
my $cn = $class->tsv->{cookieName};
|
my $cn = $class->tsv->{cookieName};
|
||||||
my $value = $lookForHttpCookie # Avoid prefix and bad cookie name (#2417)
|
my $value = $lookForHttpCookie # Avoid prefix and bad cookie name (#2417)
|
||||||
? ( $t =~ /(?<![-.~])\b${cn}http=([^,; ]+)/o ? $1 : 0 )
|
? ( $t =~ /(?<![-.~])\b${cn}http=([^,; ]+)/o ? $1 : 0 )
|
||||||
: ( $t =~ /(?<![-.~])\b$cn=([^,; ]+)/o ? $1 : 0 );
|
: ( $t =~ /(?<![-.~])\b$cn=([^,; ]+)/o ? $1 : 0 );
|
||||||
|
@ -536,8 +536,8 @@ sub retrieveSession {
|
||||||
# (15 seconds)
|
# (15 seconds)
|
||||||
if ( defined $class->data->{_session_id}
|
if ( defined $class->data->{_session_id}
|
||||||
and $id eq $class->data->{_session_id}
|
and $id eq $class->data->{_session_id}
|
||||||
and
|
and ( $now - $class->dataUpdate < $class->tsv->{handlerInternalCache} )
|
||||||
( $now - $class->dataUpdate < $class->tsv->{handlerInternalCache} ) )
|
)
|
||||||
{
|
{
|
||||||
$class->logger->debug("Get session $id from Handler internal cache");
|
$class->logger->debug("Get session $id from Handler internal cache");
|
||||||
return $class->data;
|
return $class->data;
|
||||||
|
@ -898,8 +898,9 @@ sub postJavascript {
|
||||||
my $filler;
|
my $filler;
|
||||||
foreach my $name ( keys %$data ) {
|
foreach my $name ( keys %$data ) {
|
||||||
use bytes;
|
use bytes;
|
||||||
my @characterSet = ( '0' ..'9', 'A' .. 'Z', 'a' .. 'z' );
|
my @characterSet = ( '0' .. '9', 'A' .. 'Z', 'a' .. 'z' );
|
||||||
my $value = join '' => map $characterSet[ rand @characterSet ], 1 .. bytes::length( $data->{$name} );
|
my $value = join '' => map $characterSet[ rand @characterSet ],
|
||||||
|
1 .. bytes::length( $data->{$name} );
|
||||||
$filler .=
|
$filler .=
|
||||||
"form.find('input[name=\"$name\"], select[name=\"$name\"], textarea[name=\"$name\"]').val('$value')\n";
|
"form.find('input[name=\"$name\"], select[name=\"$name\"], textarea[name=\"$name\"]').val('$value')\n";
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ ok(
|
||||||
( defined($code) and ref($code) eq 'CODE' ),
|
( defined($code) and ref($code) eq 'CODE' ),
|
||||||
'encode_base64 function is defined'
|
'encode_base64 function is defined'
|
||||||
);
|
);
|
||||||
ok( $res = &$code, "Function works" );
|
ok( $res = &$code, "Function works" );
|
||||||
ok( $res eq 'dGVzdA==', 'Get good result' );
|
ok( $res eq 'dGVzdA==', 'Get good result' );
|
||||||
|
|
||||||
$sub = "sub { return ( listMatch('ABC; DEF; GHI','abc',1) ) }";
|
$sub = "sub { return ( listMatch('ABC; DEF; GHI','abc',1) ) }";
|
||||||
|
@ -58,7 +58,7 @@ ok(
|
||||||
'checkDate extended function is defined'
|
'checkDate extended function is defined'
|
||||||
);
|
);
|
||||||
ok( $res = &$code, "Function works" );
|
ok( $res = &$code, "Function works" );
|
||||||
ok( $res == 1, 'Get good result' );
|
ok( $res == 1, 'Get good result' );
|
||||||
|
|
||||||
$sub = "sub { return(checkDate('20000101000000+0100','21000101000000+0100')) }";
|
$sub = "sub { return(checkDate('20000101000000+0100','21000101000000+0100')) }";
|
||||||
$code = $jail->jail_reval($sub);
|
$code = $jail->jail_reval($sub);
|
||||||
|
@ -67,7 +67,7 @@ ok(
|
||||||
'checkDate extended function is defined'
|
'checkDate extended function is defined'
|
||||||
);
|
);
|
||||||
ok( $res = &$code, "Function works" );
|
ok( $res = &$code, "Function works" );
|
||||||
ok( $res == 1, 'Get good result' );
|
ok( $res == 1, 'Get good result' );
|
||||||
|
|
||||||
$sub = "sub { return(has2f_internal(\$_[0],\$_[1])) }";
|
$sub = "sub { return(has2f_internal(\$_[0],\$_[1])) }";
|
||||||
$code = $jail->jail_reval($sub);
|
$code = $jail->jail_reval($sub);
|
||||||
|
|
|
@ -15,7 +15,7 @@ my $SKIPUSER = 0;
|
||||||
# --------------------
|
# --------------------
|
||||||
ok( $res = $client->_get('/'), 'Unauthentified query' );
|
ok( $res = $client->_get('/'), 'Unauthentified query' );
|
||||||
ok( ref($res) eq 'ARRAY', 'Response is an array' ) or explain( $res, 'array' );
|
ok( ref($res) eq 'ARRAY', 'Response is an array' ) or explain( $res, 'array' );
|
||||||
ok( $res->[0] == 302, ' Code is 302' ) or explain( $res->[0], 302 );
|
ok( $res->[0] == 302, ' Code is 302' ) or explain( $res->[0], 302 );
|
||||||
my %h = @{ $res->[1] };
|
my %h = @{ $res->[1] };
|
||||||
ok(
|
ok(
|
||||||
$h{Location} eq 'http://auth.example.com/?url='
|
$h{Location} eq 'http://auth.example.com/?url='
|
||||||
|
@ -224,8 +224,13 @@ ok( $res->[0] == 200, ' Code is 200' ) or explain( $res, 200 );
|
||||||
count(2);
|
count(2);
|
||||||
|
|
||||||
# Forged headers
|
# Forged headers
|
||||||
ok( $res = $client->_get( '/skipif/zz', undef, 'test1.example.com', undef, HTTP_AUTH_USER => 'rtyler' ),
|
ok(
|
||||||
'Test skip() with forged header' );
|
$res = $client->_get(
|
||||||
|
'/skipif/zz', undef, 'test1.example.com', undef,
|
||||||
|
HTTP_AUTH_USER => 'rtyler'
|
||||||
|
),
|
||||||
|
'Test skip() with forged header'
|
||||||
|
);
|
||||||
ok( $res->[0] == 200, ' Code is 200' ) or explain( $res, 200 );
|
ok( $res->[0] == 200, ' Code is 200' ) or explain( $res, 200 );
|
||||||
count(2);
|
count(2);
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ my $res;
|
||||||
# --------------------
|
# --------------------
|
||||||
ok( $res = $client->_get('/'), 'Unauthentified query' );
|
ok( $res = $client->_get('/'), 'Unauthentified query' );
|
||||||
ok( ref($res) eq 'ARRAY', 'Response is an array' ) or explain( $res, 'array' );
|
ok( ref($res) eq 'ARRAY', 'Response is an array' ) or explain( $res, 'array' );
|
||||||
ok( $res->[0] == 302, 'Code is 302' ) or explain( $res->[0], 302 );
|
ok( $res->[0] == 302, 'Code is 302' ) or explain( $res->[0], 302 );
|
||||||
my %h = @{ $res->[1] };
|
my %h = @{ $res->[1] };
|
||||||
ok(
|
ok(
|
||||||
$h{Location} eq 'http://auth.example.com/?url='
|
$h{Location} eq 'http://auth.example.com/?url='
|
||||||
|
|
|
@ -16,7 +16,7 @@ my $res;
|
||||||
# Unauthentified query
|
# Unauthentified query
|
||||||
ok( $res = $client->_get('/'), 'Unauthentified query' );
|
ok( $res = $client->_get('/'), 'Unauthentified query' );
|
||||||
ok( ref($res) eq 'ARRAY', 'Response is an array' ) or explain( $res, 'array' );
|
ok( ref($res) eq 'ARRAY', 'Response is an array' ) or explain( $res, 'array' );
|
||||||
ok( $res->[0] == 401, 'Code is 401' ) or explain( $res->[0], 401 );
|
ok( $res->[0] == 401, 'Code is 401' ) or explain( $res->[0], 401 );
|
||||||
my %h = @{ $res->[1] };
|
my %h = @{ $res->[1] };
|
||||||
ok(
|
ok(
|
||||||
$h{Location} eq 'http://auth.example.com/?url='
|
$h{Location} eq 'http://auth.example.com/?url='
|
||||||
|
|
|
@ -39,7 +39,7 @@ my $res;
|
||||||
|
|
||||||
# Unauth tests
|
# Unauth tests
|
||||||
ok( $res = $client->_get('/test'), 'Get response' );
|
ok( $res = $client->_get('/test'), 'Get response' );
|
||||||
ok( $res->[0] == 200, 'Response code is 200' )
|
ok( $res->[0] == 200, 'Response code is 200' )
|
||||||
or print "Expect 200, got $res->[0]\n";
|
or print "Expect 200, got $res->[0]\n";
|
||||||
ok( $res->[2]->[0] eq 'Unauth', 'Get unauth result' )
|
ok( $res->[2]->[0] eq 'Unauth', 'Get unauth result' )
|
||||||
or print "Expect Unauth, got $res->[2]->[0]\n";
|
or print "Expect Unauth, got $res->[2]->[0]\n";
|
||||||
|
@ -64,7 +64,7 @@ count(3);
|
||||||
# Bad path test
|
# Bad path test
|
||||||
|
|
||||||
ok( $res = $client->_get('/[]/test'), 'Try a bad path' );
|
ok( $res = $client->_get('/[]/test'), 'Try a bad path' );
|
||||||
ok( $res->[0] == 400, 'Response is 400' );
|
ok( $res->[0] == 400, 'Response is 400' );
|
||||||
count(2);
|
count(2);
|
||||||
|
|
||||||
clean();
|
clean();
|
||||||
|
|
|
@ -82,12 +82,12 @@ no warnings 'redefine';
|
||||||
|
|
||||||
sub LWP::UserAgent::request {
|
sub LWP::UserAgent::request {
|
||||||
my ( $self, $req ) = @_;
|
my ( $self, $req ) = @_;
|
||||||
ok( $req->header('host') eq 'devops.example.com',
|
ok( $req->header('host') eq 'devops.example.com', 'Host header found' )
|
||||||
'Host header found' )
|
|
||||||
or explain( $req->headers(), 'devops.example.com' );
|
or explain( $req->headers(), 'devops.example.com' );
|
||||||
ok( $req->as_string() =~ m#http://devops.example.com/myfile.json#,
|
ok( $req->as_string() =~ m#http://devops.example.com/myfile.json#,
|
||||||
'Rules file URL found' )
|
'Rules file URL found' )
|
||||||
or explain( $req->as_string(), 'GET http://devops.example.com/myfile.json' );
|
or
|
||||||
|
explain( $req->as_string(), 'GET http://devops.example.com/myfile.json' );
|
||||||
count(2);
|
count(2);
|
||||||
my $httpResp;
|
my $httpResp;
|
||||||
my $s = '{
|
my $s = '{
|
||||||
|
|
|
@ -14,8 +14,8 @@ init(
|
||||||
#logLevel => 'debug',
|
#logLevel => 'debug',
|
||||||
vhostOptions => {
|
vhostOptions => {
|
||||||
'test3.example.com' => {
|
'test3.example.com' => {
|
||||||
vhostHttps => 0,
|
vhostHttps => 0,
|
||||||
vhostPort => 80,
|
vhostPort => 80,
|
||||||
vhostDevOpsRulesUrl =>
|
vhostDevOpsRulesUrl =>
|
||||||
'http://donotuse.example.com/myfile.json',
|
'http://donotuse.example.com/myfile.json',
|
||||||
},
|
},
|
||||||
|
|
|
@ -73,8 +73,7 @@ no warnings 'redefine';
|
||||||
|
|
||||||
sub LWP::UserAgent::request {
|
sub LWP::UserAgent::request {
|
||||||
my ( $self, $req ) = @_;
|
my ( $self, $req ) = @_;
|
||||||
ok( $req->header('host') eq 'test3.example.com',
|
ok( $req->header('host') eq 'test3.example.com', 'Host header found' )
|
||||||
'Host header found' )
|
|
||||||
or explain( $req->headers(), 'test3.example.com' );
|
or explain( $req->headers(), 'test3.example.com' );
|
||||||
ok( $req->as_string() =~ m#http://127.0.0.1:80/rules.json#,
|
ok( $req->as_string() =~ m#http://127.0.0.1:80/rules.json#,
|
||||||
'Rules file URL found' )
|
'Rules file URL found' )
|
||||||
|
|
|
@ -15,7 +15,7 @@ my $res;
|
||||||
ok( $res = $client->_get( '/', undef, 'test.example.org' ),
|
ok( $res = $client->_get( '/', undef, 'test.example.org' ),
|
||||||
'Unauthentified query' );
|
'Unauthentified query' );
|
||||||
ok( ref($res) eq 'ARRAY', 'Response is an array' ) or explain( $res, 'array' );
|
ok( ref($res) eq 'ARRAY', 'Response is an array' ) or explain( $res, 'array' );
|
||||||
ok( $res->[0] == 302, 'Code is 302' ) or explain( $res->[0], 302 );
|
ok( $res->[0] == 302, 'Code is 302' ) or explain( $res->[0], 302 );
|
||||||
my %h = @{ $res->[1] };
|
my %h = @{ $res->[1] };
|
||||||
ok(
|
ok(
|
||||||
$h{Location} eq 'http://auth.example.com/?url='
|
$h{Location} eq 'http://auth.example.com/?url='
|
||||||
|
|
|
@ -21,7 +21,7 @@ my $res;
|
||||||
|
|
||||||
ok( $res = $client->_get('/'), 'Unauthentified query' );
|
ok( $res = $client->_get('/'), 'Unauthentified query' );
|
||||||
ok( ref($res) eq 'ARRAY', 'Response is an array' ) or explain( $res, 'array' );
|
ok( ref($res) eq 'ARRAY', 'Response is an array' ) or explain( $res, 'array' );
|
||||||
ok( $res->[0] == 302, 'Code is 302' ) or explain( $res->[0], 302 );
|
ok( $res->[0] == 302, 'Code is 302' ) or explain( $res->[0], 302 );
|
||||||
|
|
||||||
my $conf;
|
my $conf;
|
||||||
eval {
|
eval {
|
||||||
|
@ -41,7 +41,7 @@ Lemonldap::NG::Handler::Main->configReload($conf);
|
||||||
fail $@ if $@;
|
fail $@ if $@;
|
||||||
ok( $res = $client->_get('/'), 'Unauthentified query' );
|
ok( $res = $client->_get('/'), 'Unauthentified query' );
|
||||||
ok( ref($res) eq 'ARRAY', 'Response is an array' ) or explain( $res, 'array' );
|
ok( ref($res) eq 'ARRAY', 'Response is an array' ) or explain( $res, 'array' );
|
||||||
ok( $res->[0] == 302, 'Code is 302' ) or explain( $res->[0], 302 );
|
ok( $res->[0] == 302, 'Code is 302' ) or explain( $res->[0], 302 );
|
||||||
my %h = @{ $res->[1] };
|
my %h = @{ $res->[1] };
|
||||||
ok(
|
ok(
|
||||||
$h{Location} eq 'http://auth.example.com/?url='
|
$h{Location} eq 'http://auth.example.com/?url='
|
||||||
|
|
|
@ -27,7 +27,7 @@ my $res;
|
||||||
|
|
||||||
ok( $res = $client->_get('/'), 'Unauthentified query' );
|
ok( $res = $client->_get('/'), 'Unauthentified query' );
|
||||||
ok( ref($res) eq 'ARRAY', 'Response is an array' ) or explain( $res, 'array' );
|
ok( ref($res) eq 'ARRAY', 'Response is an array' ) or explain( $res, 'array' );
|
||||||
ok( $res->[0] == 302, 'Code is 302' ) or explain( $res->[0], 302 );
|
ok( $res->[0] == 302, 'Code is 302' ) or explain( $res->[0], 302 );
|
||||||
my %h = @{ $res->[1] };
|
my %h = @{ $res->[1] };
|
||||||
ok(
|
ok(
|
||||||
$h{Location} eq 'http://auth.example.com/?url='
|
$h{Location} eq 'http://auth.example.com/?url='
|
||||||
|
|
|
@ -50,7 +50,7 @@ init(
|
||||||
Lemonldap::NG::Common::Session->new( {
|
Lemonldap::NG::Common::Session->new( {
|
||||||
storageModule => 'Apache::Session::File',
|
storageModule => 'Apache::Session::File',
|
||||||
storageModuleOptions => { Directory => 't/sessions' },
|
storageModuleOptions => { Directory => 't/sessions' },
|
||||||
id =>
|
id =>
|
||||||
'f0fd4e85000ce35d062f97f5b466fc00abc2fad0406e03e086605f929ec4a249',
|
'f0fd4e85000ce35d062f97f5b466fc00abc2fad0406e03e086605f929ec4a249',
|
||||||
force => 1,
|
force => 1,
|
||||||
kind => 'OIDCI',
|
kind => 'OIDCI',
|
||||||
|
@ -144,7 +144,7 @@ ok(
|
||||||
$res = $client->_get(
|
$res = $client->_get(
|
||||||
'/read', undef,
|
'/read', undef,
|
||||||
'test1.example.com', '',
|
'test1.example.com', '',
|
||||||
VHOSTTYPE => 'OAuth2',
|
VHOSTTYPE => 'OAuth2',
|
||||||
HTTP_AUTHORIZATION =>
|
HTTP_AUTHORIZATION =>
|
||||||
'Bearer f0fd4e85000ce35d062f97f5b466fc00abc2fad0406e03e086605f929ec4a249',
|
'Bearer f0fd4e85000ce35d062f97f5b466fc00abc2fad0406e03e086605f929ec4a249',
|
||||||
),
|
),
|
||||||
|
@ -165,7 +165,7 @@ ok(
|
||||||
$res = $client->_get(
|
$res = $client->_get(
|
||||||
'/write', undef,
|
'/write', undef,
|
||||||
'test1.example.com', '',
|
'test1.example.com', '',
|
||||||
VHOSTTYPE => 'OAuth2',
|
VHOSTTYPE => 'OAuth2',
|
||||||
HTTP_AUTHORIZATION =>
|
HTTP_AUTHORIZATION =>
|
||||||
'Bearer f0fd4e85000ce35d062f97f5b466fc00abc2fad0406e03e086605f929ec4a249',
|
'Bearer f0fd4e85000ce35d062f97f5b466fc00abc2fad0406e03e086605f929ec4a249',
|
||||||
),
|
),
|
||||||
|
@ -178,7 +178,7 @@ ok(
|
||||||
$res = $client->_get(
|
$res = $client->_get(
|
||||||
'/test', undef,
|
'/test', undef,
|
||||||
'test1.example.com', '',
|
'test1.example.com', '',
|
||||||
VHOSTTYPE => 'OAuth2',
|
VHOSTTYPE => 'OAuth2',
|
||||||
HTTP_AUTHORIZATION =>
|
HTTP_AUTHORIZATION =>
|
||||||
'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwianRpIjoiZjBmZDRlODUwMDBjZTM1ZDA2MmY5N2Y1YjQ2NmZjMDBhYmMyZmFkMDQwNmUwM2UwODY2MDVmOTI5ZWM0YTI0OSJ9.h0RDBLo5Vy8lqbltEP2L496KOzJLhLCIRZZmEqcPuN8',
|
'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwianRpIjoiZjBmZDRlODUwMDBjZTM1ZDA2MmY5N2Y1YjQ2NmZjMDBhYmMyZmFkMDQwNmUwM2UwODY2MDVmOTI5ZWM0YTI0OSJ9.h0RDBLo5Vy8lqbltEP2L496KOzJLhLCIRZZmEqcPuN8',
|
||||||
),
|
),
|
||||||
|
|
|
@ -75,7 +75,7 @@ sub init {
|
||||||
'_utime' => $now,
|
'_utime' => $now,
|
||||||
'_passwordDB' => 'Demo',
|
'_passwordDB' => 'Demo',
|
||||||
'_auth' => 'Demo',
|
'_auth' => 'Demo',
|
||||||
'UA' =>
|
'UA' =>
|
||||||
'Mozilla/5.0 (X11; VAX4000; rv:43.0) Gecko/20100101 Firefox/143.0 Iceweasel/143.0.1'
|
'Mozilla/5.0 (X11; VAX4000; rv:43.0) Gecko/20100101 Firefox/143.0 Iceweasel/143.0.1'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -152,7 +152,7 @@ sub _get {
|
||||||
'X_ORIGINAL_URI' => $path . ( $query ? "?$query" : '' ),
|
'X_ORIGINAL_URI' => $path . ( $query ? "?$query" : '' ),
|
||||||
'SERVER_PORT' => '80',
|
'SERVER_PORT' => '80',
|
||||||
'SERVER_PROTOCOL' => 'HTTP/1.1',
|
'SERVER_PROTOCOL' => 'HTTP/1.1',
|
||||||
'HTTP_USER_AGENT' =>
|
'HTTP_USER_AGENT' =>
|
||||||
'Mozilla/5.0 (VAX-4000; rv:36.0) Gecko/20350101 Firefox',
|
'Mozilla/5.0 (VAX-4000; rv:36.0) Gecko/20350101 Firefox',
|
||||||
'REMOTE_ADDR' => '127.0.0.1',
|
'REMOTE_ADDR' => '127.0.0.1',
|
||||||
'HTTP_HOST' => $host,
|
'HTTP_HOST' => $host,
|
||||||
|
|
|
@ -24,7 +24,7 @@ extends qw(
|
||||||
Lemonldap::NG::Common::Conf::AccessLib
|
Lemonldap::NG::Common::Conf::AccessLib
|
||||||
);
|
);
|
||||||
|
|
||||||
has csp => ( is => 'rw' );
|
has csp => ( is => 'rw' );
|
||||||
has loadedPlugins => ( is => 'rw', default => sub { [] } );
|
has loadedPlugins => ( is => 'rw', default => sub { [] } );
|
||||||
has hLoadedPlugins => ( is => 'rw', default => sub { {} } );
|
has hLoadedPlugins => ( is => 'rw', default => sub { {} } );
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,8 @@ sub init {
|
||||||
$self->{hiddenAttributes} //= "_password";
|
$self->{hiddenAttributes} //= "_password";
|
||||||
$self->{hiddenAttributes} .= ' _session_id'
|
$self->{hiddenAttributes} .= ' _session_id'
|
||||||
unless $conf->{displaySessionId};
|
unless $conf->{displaySessionId};
|
||||||
$self->{TOTPCheck} = $self->{U2FCheck} = $self->{UBKCheck} = $self->{WebAuthnCheck} = '1';
|
$self->{TOTPCheck} = $self->{U2FCheck} = $self->{UBKCheck} =
|
||||||
|
$self->{WebAuthnCheck} = '1';
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,7 +69,7 @@ sub del2F {
|
||||||
my $epoch = $params->{epoch}
|
my $epoch = $params->{epoch}
|
||||||
or return $self->sendError( $req, 'Missing "epoch" parameter', 400 );
|
or return $self->sendError( $req, 'Missing "epoch" parameter', 400 );
|
||||||
|
|
||||||
if ( grep { $_ eq $type } @{_2FTYPES()} ) {
|
if ( grep { $_ eq $type } @{ _2FTYPES() } ) {
|
||||||
$self->logger->debug(
|
$self->logger->debug(
|
||||||
"Call procedure delete2F with type=$type and epoch=$epoch");
|
"Call procedure delete2F with type=$type and epoch=$epoch");
|
||||||
return $self->delete2F( $req, $session, $skey );
|
return $self->delete2F( $req, $session, $skey );
|
||||||
|
@ -118,7 +119,7 @@ sub sfa {
|
||||||
$moduleOptions->{backend} = $mod->{module};
|
$moduleOptions->{backend} = $mod->{module};
|
||||||
|
|
||||||
# Select 2FA sessions to display
|
# Select 2FA sessions to display
|
||||||
foreach (@{_2FTYPES()}) {
|
foreach ( @{ _2FTYPES() } ) {
|
||||||
$self->{ $_ . 'Check' } = delete $params->{ $_ . 'Check' }
|
$self->{ $_ . 'Check' } = delete $params->{ $_ . 'Check' }
|
||||||
if ( defined $params->{ $_ . 'Check' } );
|
if ( defined $params->{ $_ . 'Check' } );
|
||||||
}
|
}
|
||||||
|
@ -189,7 +190,7 @@ sub sfa {
|
||||||
# Remove sessions without at least one 2F device(s)
|
# Remove sessions without at least one 2F device(s)
|
||||||
$self->logger->debug(
|
$self->logger->debug(
|
||||||
"Removing sessions without at least one 2F device(s)...");
|
"Removing sessions without at least one 2F device(s)...");
|
||||||
my $_2f_types_re = join ('|', @{_2FTYPES()});
|
my $_2f_types_re = join( '|', @{ _2FTYPES() } );
|
||||||
foreach my $session ( keys %$res ) {
|
foreach my $session ( keys %$res ) {
|
||||||
delete $res->{$session}
|
delete $res->{$session}
|
||||||
unless ( defined $res->{$session}->{_2fDevices}
|
unless ( defined $res->{$session}->{_2fDevices}
|
||||||
|
@ -200,7 +201,7 @@ sub sfa {
|
||||||
# Filter 2FA sessions if needed
|
# Filter 2FA sessions if needed
|
||||||
$self->logger->debug("Filtering 2F sessions...");
|
$self->logger->debug("Filtering 2F sessions...");
|
||||||
my $all = ( keys %$res );
|
my $all = ( keys %$res );
|
||||||
foreach (@{_2FTYPES()}) {
|
foreach ( @{ _2FTYPES() } ) {
|
||||||
if ( $self->{ $_ . 'Check' } eq '2' ) {
|
if ( $self->{ $_ . 'Check' } eq '2' ) {
|
||||||
foreach my $session ( keys %$res ) {
|
foreach my $session ( keys %$res ) {
|
||||||
delete $res->{$session}
|
delete $res->{$session}
|
||||||
|
@ -268,7 +269,7 @@ qq{Use of an uninitialized attribute "$group" to group sessions},
|
||||||
# { session => <sessionId>, userId => <_session_uid> }
|
# { session => <sessionId>, userId => <_session_uid> }
|
||||||
else {
|
else {
|
||||||
$res = [
|
$res = [
|
||||||
sort { $a->{date} <=> $b->{date} }
|
sort { $a->{date} <=> $b->{date} }
|
||||||
map { { session => $_, userId => $res->{$_}->{_session_uid} } }
|
map { { session => $_, userId => $res->{$_}->{_session_uid} } }
|
||||||
keys %$res
|
keys %$res
|
||||||
];
|
];
|
||||||
|
|
|
@ -337,7 +337,7 @@ sub _checkType {
|
||||||
return {
|
return {
|
||||||
res => "ko",
|
res => "ko",
|
||||||
code => 400,
|
code => 400,
|
||||||
msg =>
|
msg =>
|
||||||
"Invalid input: Type \"$type\" does not exist. Allowed values for type are: \"U2F\", \"TOTP\", \"WebAuthn\" or \"UBK\""
|
"Invalid input: Type \"$type\" does not exist. Allowed values for type are: \"U2F\", \"TOTP\", \"WebAuthn\" or \"UBK\""
|
||||||
}
|
}
|
||||||
unless ( $type =~ /\b(?:U2F|TOTP|UBK|WebAuthn)\b/i );
|
unless ( $type =~ /\b(?:U2F|TOTP|UBK|WebAuthn)\b/i );
|
||||||
|
|
|
@ -312,8 +312,8 @@ sub _isNewCasAppServiceUrlUnique {
|
||||||
# Check service paramater
|
# Check service paramater
|
||||||
unless ( ref $casApp->{options}->{service} eq "ARRAY" ) {
|
unless ( ref $casApp->{options}->{service} eq "ARRAY" ) {
|
||||||
return {
|
return {
|
||||||
res => 'ko',
|
res => 'ko',
|
||||||
msg => "The parameter 'service' must be an array",
|
msg => "The parameter 'service' must be an array",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -140,7 +140,7 @@ sub addOidcRp {
|
||||||
409
|
409
|
||||||
) if ( defined $self->_getOidcRpByClientId( $conf, $add->{clientId} ) );
|
) if ( defined $self->_getOidcRpByClientId( $conf, $add->{clientId} ) );
|
||||||
|
|
||||||
$add->{options} = {} unless ( defined $add->{options} );
|
$add->{options} = {} unless ( defined $add->{options} );
|
||||||
$add->{options}->{clientId} = $add->{clientId};
|
$add->{options}->{clientId} = $add->{clientId};
|
||||||
$add->{options}->{redirectUris} = $add->{redirectUris};
|
$add->{options}->{redirectUris} = $add->{redirectUris};
|
||||||
|
|
||||||
|
@ -246,8 +246,8 @@ sub replaceOidcRp {
|
||||||
return $self->sendError( $req, $res->{msg}, 409 )
|
return $self->sendError( $req, $res->{msg}, 409 )
|
||||||
unless ( $res->{res} eq 'ok' );
|
unless ( $res->{res} eq 'ok' );
|
||||||
|
|
||||||
$replace->{options} = {} unless ( defined $replace->{options} );
|
$replace->{options} = {} unless ( defined $replace->{options} );
|
||||||
$replace->{options}->{clientId} = $replace->{clientId};
|
$replace->{options}->{clientId} = $replace->{clientId};
|
||||||
$replace->{options}->{redirectUris} = $replace->{redirectUris};
|
$replace->{options}->{redirectUris} = $replace->{redirectUris};
|
||||||
|
|
||||||
$res = $self->_pushOidcRp( $conf, $confKey, $replace, 1 );
|
$res = $self->_pushOidcRp( $conf, $confKey, $replace, 1 );
|
||||||
|
|
|
@ -67,7 +67,7 @@ sub types {
|
||||||
'hostname' => {
|
'hostname' => {
|
||||||
'form' => 'text',
|
'form' => 'text',
|
||||||
'msgFail' => '__badHostname__',
|
'msgFail' => '__badHostname__',
|
||||||
'test' =>
|
'test' =>
|
||||||
qr/^(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)|(?:[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+)))?$/
|
qr/^(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)|(?:[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+)))?$/
|
||||||
},
|
},
|
||||||
'int' => {
|
'int' => {
|
||||||
|
@ -257,7 +257,7 @@ m[^(?:(?:\-+\s*BEGIN\s+(?:PUBLIC\s+KEY|CERTIFICATE)\s*\-+\r?\n)?[a-zA-Z0-9/\+\r\
|
||||||
'url' => {
|
'url' => {
|
||||||
'form' => 'text',
|
'form' => 'text',
|
||||||
'msgFail' => '__badUrl__',
|
'msgFail' => '__badUrl__',
|
||||||
'test' =>
|
'test' =>
|
||||||
qr/(?:^$|(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)|(?:[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+)))(?::(?:(?:[0-9]*)))?(?:\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*)(?:\/(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*))*))(?:[?](?:(?:(?:[;\/?:@&=+\$,a-zA-Z0-9\-_.!~*'()]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)))?))?))/
|
qr/(?:^$|(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)|(?:[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+)))(?::(?:(?:[0-9]*)))?(?:\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*)(?:\/(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*))*))(?:[?](?:(?:(?:[;\/?:@&=+\$,a-zA-Z0-9\-_.!~*'()]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)))?))?))/
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -802,7 +802,7 @@ sub attributes {
|
||||||
},
|
},
|
||||||
'casSrvMetaDataOptionsUrl' => {
|
'casSrvMetaDataOptionsUrl' => {
|
||||||
'msgFail' => '__badUrl__',
|
'msgFail' => '__badUrl__',
|
||||||
'test' =>
|
'test' =>
|
||||||
qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)|(?:[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+)))(?::(?:(?:[0-9]*)))?(?:\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*)(?:\/(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*))*))(?:[?](?:(?:(?:[;\/?:@&=+\$,a-zA-Z0-9\-_.!~*'()]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)))?))?)/,
|
qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)|(?:[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+)))(?::(?:(?:[0-9]*)))?(?:\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*)(?:\/(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*))*))(?:[?](?:(?:(?:[;\/?:@&=+\$,a-zA-Z0-9\-_.!~*'()]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)))?))?)/,
|
||||||
'type' => 'text'
|
'type' => 'text'
|
||||||
},
|
},
|
||||||
|
@ -1341,7 +1341,7 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.]
|
||||||
'domain' => {
|
'domain' => {
|
||||||
'default' => 'example.com',
|
'default' => 'example.com',
|
||||||
'msgFail' => '__badDomainName__',
|
'msgFail' => '__badDomainName__',
|
||||||
'test' =>
|
'test' =>
|
||||||
qr/^(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?))?$/,
|
qr/^(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?))?$/,
|
||||||
'type' => 'text'
|
'type' => 'text'
|
||||||
},
|
},
|
||||||
|
@ -1484,7 +1484,7 @@ qr/^(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-
|
||||||
},
|
},
|
||||||
'globalStorageOptions' => {
|
'globalStorageOptions' => {
|
||||||
'default' => {
|
'default' => {
|
||||||
'Directory' => '/var/lib/lemonldap-ng/sessions/',
|
'Directory' => '/var/lib/lemonldap-ng/sessions/',
|
||||||
'generateModule' =>
|
'generateModule' =>
|
||||||
'Lemonldap::NG::Common::Apache::Session::Generate::SHA256',
|
'Lemonldap::NG::Common::Apache::Session::Generate::SHA256',
|
||||||
'LockDirectory' => '/var/lib/lemonldap-ng/sessions/lock/'
|
'LockDirectory' => '/var/lib/lemonldap-ng/sessions/lock/'
|
||||||
|
@ -1609,7 +1609,7 @@ qr/^(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-
|
||||||
'issuerDBGetParameters' => {
|
'issuerDBGetParameters' => {
|
||||||
'default' => {},
|
'default' => {},
|
||||||
'keyMsgFail' => '__badHostname__',
|
'keyMsgFail' => '__badHostname__',
|
||||||
'keyTest' =>
|
'keyTest' =>
|
||||||
qr/^(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)$/,
|
qr/^(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)$/,
|
||||||
'test' => {
|
'test' => {
|
||||||
'keyMsgFail' => '__badKeyName__',
|
'keyMsgFail' => '__badKeyName__',
|
||||||
|
@ -2808,7 +2808,7 @@ m[^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
|
||||||
'pdataDomain' => {
|
'pdataDomain' => {
|
||||||
'default' => '',
|
'default' => '',
|
||||||
'msgFail' => '__badDomainName__',
|
'msgFail' => '__badDomainName__',
|
||||||
'test' =>
|
'test' =>
|
||||||
qr/^(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?))?$/,
|
qr/^(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?))?$/,
|
||||||
'type' => 'text'
|
'type' => 'text'
|
||||||
},
|
},
|
||||||
|
@ -2829,7 +2829,7 @@ qr/^(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-
|
||||||
'portal' => {
|
'portal' => {
|
||||||
'default' => 'http://auth.example.com/',
|
'default' => 'http://auth.example.com/',
|
||||||
'msgFail' => '__badUrl__',
|
'msgFail' => '__badUrl__',
|
||||||
'test' =>
|
'test' =>
|
||||||
qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)|(?:[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+)))(?::(?:(?:[0-9]*)))?(?:\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*)(?:\/(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*))*))(?:[?](?:(?:(?:[;\/?:@&=+\$,a-zA-Z0-9\-_.!~*'()]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)))?))?)/,
|
qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)|(?:[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+)))(?::(?:(?:[0-9]*)))?(?:\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*)(?:\/(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*))*))(?:[?](?:(?:(?:[;\/?:@&=+\$,a-zA-Z0-9\-_.!~*'()]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)))?))?)/,
|
||||||
'type' => 'url'
|
'type' => 'url'
|
||||||
},
|
},
|
||||||
|
@ -3136,7 +3136,7 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.]
|
||||||
'keyTest' =>
|
'keyTest' =>
|
||||||
qr/^(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)|(?:[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+))(?::\d+)?$/,
|
qr/^(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)|(?:[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+))(?::\d+)?$/,
|
||||||
'msgFail' => '__badUrl__',
|
'msgFail' => '__badUrl__',
|
||||||
'test' =>
|
'test' =>
|
||||||
qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)|(?:[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+)))(?::(?:(?:[0-9]*)))?(?:\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*)(?:\/(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*))*))(?:[?](?:(?:(?:[;\/?:@&=+\$,a-zA-Z0-9\-_.!~*'()]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)))?))?)/,
|
qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)|(?:[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+)))(?::(?:(?:[0-9]*)))?(?:\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*)(?:\/(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*))*))(?:[?](?:(?:(?:[;\/?:@&=+\$,a-zA-Z0-9\-_.!~*'()]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)))?))?)/,
|
||||||
'type' => 'keyTextContainer'
|
'type' => 'keyTextContainer'
|
||||||
},
|
},
|
||||||
|
@ -3288,19 +3288,19 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.]
|
||||||
},
|
},
|
||||||
'samlCommonDomainCookieDomain' => {
|
'samlCommonDomainCookieDomain' => {
|
||||||
'msgFail' => '__badDomainName__',
|
'msgFail' => '__badDomainName__',
|
||||||
'test' =>
|
'test' =>
|
||||||
qr/^(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)$/,
|
qr/^(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)$/,
|
||||||
'type' => 'text'
|
'type' => 'text'
|
||||||
},
|
},
|
||||||
'samlCommonDomainCookieReader' => {
|
'samlCommonDomainCookieReader' => {
|
||||||
'msgFail' => '__badUrl__',
|
'msgFail' => '__badUrl__',
|
||||||
'test' =>
|
'test' =>
|
||||||
qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)|(?:[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+)))(?::(?:(?:[0-9]*)))?(?:\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*)(?:\/(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*))*))(?:[?](?:(?:(?:[;\/?:@&=+\$,a-zA-Z0-9\-_.!~*'()]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)))?))?)/,
|
qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)|(?:[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+)))(?::(?:(?:[0-9]*)))?(?:\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*)(?:\/(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*))*))(?:[?](?:(?:(?:[;\/?:@&=+\$,a-zA-Z0-9\-_.!~*'()]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)))?))?)/,
|
||||||
'type' => 'text'
|
'type' => 'text'
|
||||||
},
|
},
|
||||||
'samlCommonDomainCookieWriter' => {
|
'samlCommonDomainCookieWriter' => {
|
||||||
'msgFail' => '__badUrl__',
|
'msgFail' => '__badUrl__',
|
||||||
'test' =>
|
'test' =>
|
||||||
qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)|(?:[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+)))(?::(?:(?:[0-9]*)))?(?:\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*)(?:\/(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*))*))(?:[?](?:(?:(?:[;\/?:@&=+\$,a-zA-Z0-9\-_.!~*'()]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)))?))?)/,
|
qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)|(?:[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+)))(?::(?:(?:[0-9]*)))?(?:\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*)(?:\/(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*))*))(?:[?](?:(?:(?:[;\/?:@&=+\$,a-zA-Z0-9\-_.!~*'()]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)))?))?)/,
|
||||||
'type' => 'text'
|
'type' => 'text'
|
||||||
},
|
},
|
||||||
|
@ -3317,7 +3317,7 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.]
|
||||||
},
|
},
|
||||||
'samlDiscoveryProtocolURL' => {
|
'samlDiscoveryProtocolURL' => {
|
||||||
'msgFail' => '__badUrl__',
|
'msgFail' => '__badUrl__',
|
||||||
'test' =>
|
'test' =>
|
||||||
qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)|(?:[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+)))(?::(?:(?:[0-9]*)))?(?:\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*)(?:\/(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*))*))(?:[?](?:(?:(?:[;\/?:@&=+\$,a-zA-Z0-9\-_.!~*'()]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)))?))?)/,
|
qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)|(?:[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+)))(?::(?:(?:[0-9]*)))?(?:\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*)(?:\/(?:(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*))*))(?:[?](?:(?:(?:[;\/?:@&=+\$,a-zA-Z0-9\-_.!~*'()]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)))?))?)/,
|
||||||
'type' => 'text'
|
'type' => 'text'
|
||||||
},
|
},
|
||||||
|
@ -4110,7 +4110,7 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.]
|
||||||
},
|
},
|
||||||
'SMTPServer' => {
|
'SMTPServer' => {
|
||||||
'default' => '',
|
'default' => '',
|
||||||
'test' =>
|
'test' =>
|
||||||
qr/^(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)|(?:[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+))(?::\d+)?)?$/,
|
qr/^(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)|(?:[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+))(?::\d+)?)?$/,
|
||||||
'type' => 'text'
|
'type' => 'text'
|
||||||
},
|
},
|
||||||
|
|
|
@ -207,7 +207,8 @@ EOF
|
||||||
foreach (@simpleHashKeys) {
|
foreach (@simpleHashKeys) {
|
||||||
$ra->add($_);
|
$ra->add($_);
|
||||||
}
|
}
|
||||||
print F "our \$simpleHashKeys = '" . $ra->as_string . "';\n"
|
print F "our \$simpleHashKeys = '"
|
||||||
|
. $ra->as_string . "';\n"
|
||||||
. "our \$specialNodeKeys = '${ignoreKeys}s';\n";
|
. "our \$specialNodeKeys = '${ignoreKeys}s';\n";
|
||||||
foreach ( sort keys %cnodesRe ) {
|
foreach ( sort keys %cnodesRe ) {
|
||||||
print F "our \$${_}Keys = '$cnodesRe{$_}';\n";
|
print F "our \$${_}Keys = '$cnodesRe{$_}';\n";
|
||||||
|
@ -467,7 +468,7 @@ sub buildPortalConstants() {
|
||||||
|
|
||||||
printf STDERR $format, $self->portalConstantsFile;
|
printf STDERR $format, $self->portalConstantsFile;
|
||||||
open( F, '>', $self->portalConstantsFile ) or die($!);
|
open( F, '>', $self->portalConstantsFile ) or die($!);
|
||||||
my $urire = $RE{URI}{HTTP}{ -scheme=>qr/https?/ }{-keep};
|
my $urire = $RE{URI}{HTTP}{ -scheme => qr/https?/ }{-keep};
|
||||||
$urire =~ s/([\$\@])/\\$1/g;
|
$urire =~ s/([\$\@])/\\$1/g;
|
||||||
my $content = <<EOF;
|
my $content = <<EOF;
|
||||||
# This file is generated by $module. Don't modify it by hand
|
# This file is generated by $module. Don't modify it by hand
|
||||||
|
@ -596,7 +597,7 @@ sub scanTree {
|
||||||
# Subnode
|
# Subnode
|
||||||
elsif ( ref($leaf) ) {
|
elsif ( ref($leaf) ) {
|
||||||
$jleaf->{title} = $jleaf->{id} = $leaf->{title};
|
$jleaf->{title} = $jleaf->{id} = $leaf->{title};
|
||||||
$jleaf->{type} = $leaf->{form} if ( $leaf->{form} );
|
$jleaf->{type} = $leaf->{form} if ( $leaf->{form} );
|
||||||
if ( $leaf->{title} =~ /^((?:oidc|saml|cas)Service)MetaData$/ ) {
|
if ( $leaf->{title} =~ /^((?:oidc|saml|cas)Service)MetaData$/ ) {
|
||||||
no strict 'refs';
|
no strict 'refs';
|
||||||
my @tmp = $self->scanLeaf( $leaf->{nodes} );
|
my @tmp = $self->scanLeaf( $leaf->{nodes} );
|
||||||
|
@ -677,6 +678,7 @@ sub scanTree {
|
||||||
my $type = $attr->{type};
|
my $type = $attr->{type};
|
||||||
$type =~ s/Container//;
|
$type =~ s/Container//;
|
||||||
foreach my $k ( sort keys( %{ $attr->{default} } ) ) {
|
foreach my $k ( sort keys( %{ $attr->{default} } ) ) {
|
||||||
|
|
||||||
# Special handling for oidcAttribute
|
# Special handling for oidcAttribute
|
||||||
my $default = $attr->{default}->{$k};
|
my $default = $attr->{default}->{$k};
|
||||||
if ( $attr->{type} eq 'oidcAttributeContainer' ) {
|
if ( $attr->{type} eq 'oidcAttributeContainer' ) {
|
||||||
|
@ -703,9 +705,9 @@ sub scanTree {
|
||||||
push @cnodesKeys, $leaf;
|
push @cnodesKeys, $leaf;
|
||||||
}
|
}
|
||||||
|
|
||||||
# issue 2439
|
# issue 2439
|
||||||
# FIXME: in future versions, oidcOPMetaDataJSON and samlIDPMetaDataXML shoud
|
# FIXME: in future versions, oidcOPMetaDataJSON and samlIDPMetaDataXML shoud
|
||||||
# behave the same
|
# behave the same
|
||||||
if ( $leaf =~ /^oidcOPMetaData(?:JSON|JWKS)$/ ) {
|
if ( $leaf =~ /^oidcOPMetaData(?:JSON|JWKS)$/ ) {
|
||||||
push @simpleHashKeys, $leaf;
|
push @simpleHashKeys, $leaf;
|
||||||
}
|
}
|
||||||
|
|
|
@ -239,7 +239,7 @@ sub attributes {
|
||||||
|
|
||||||
# Other
|
# Other
|
||||||
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,
|
||||||
|
@ -248,7 +248,7 @@ sub attributes {
|
||||||
mySessionAuthorizedRWKeys => {
|
mySessionAuthorizedRWKeys => {
|
||||||
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 => {
|
||||||
|
@ -297,7 +297,7 @@ sub attributes {
|
||||||
flags => 'h',
|
flags => 'h',
|
||||||
},
|
},
|
||||||
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',
|
||||||
|
@ -318,7 +318,7 @@ sub attributes {
|
||||||
flags => 'h',
|
flags => 'h',
|
||||||
},
|
},
|
||||||
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',
|
||||||
|
@ -379,13 +379,13 @@ sub attributes {
|
||||||
documentation => 'Enable portal status',
|
documentation => 'Enable portal status',
|
||||||
},
|
},
|
||||||
portalUserAttr => {
|
portalUserAttr => {
|
||||||
type => 'text',
|
type => 'text',
|
||||||
default => '_user',
|
default => '_user',
|
||||||
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',
|
||||||
|
@ -446,8 +446,8 @@ sub attributes {
|
||||||
documentation => 'Disable fingerprint checkng',
|
documentation => 'Disable fingerprint checkng',
|
||||||
},
|
},
|
||||||
stayConnectedTimeout => {
|
stayConnectedTimeout => {
|
||||||
type => 'int',
|
type => 'int',
|
||||||
default => 2592000,
|
default => 2592000,
|
||||||
documentation =>
|
documentation =>
|
||||||
'StayConnected persistent connexion session timeout',
|
'StayConnected persistent connexion session timeout',
|
||||||
flags => 'm',
|
flags => 'm',
|
||||||
|
@ -518,7 +518,7 @@ sub attributes {
|
||||||
flags => 'p',
|
flags => 'p',
|
||||||
},
|
},
|
||||||
checkUserSearchAttributes => {
|
checkUserSearchAttributes => {
|
||||||
type => 'text',
|
type => 'text',
|
||||||
documentation =>
|
documentation =>
|
||||||
'Attributes used for retrieving sessions in user DataBase',
|
'Attributes used for retrieving sessions in user DataBase',
|
||||||
flags => 'p',
|
flags => 'p',
|
||||||
|
@ -745,14 +745,14 @@ sub attributes {
|
||||||
flags => 'p',
|
flags => 'p',
|
||||||
},
|
},
|
||||||
skipRenewConfirmation => {
|
skipRenewConfirmation => {
|
||||||
type => 'bool',
|
type => 'bool',
|
||||||
default => 0,
|
default => 0,
|
||||||
documentation =>
|
documentation =>
|
||||||
'Avoid asking confirmation when an Issuer asks to renew auth',
|
'Avoid asking confirmation when an Issuer asks to renew auth',
|
||||||
},
|
},
|
||||||
skipUpgradeConfirmation => {
|
skipUpgradeConfirmation => {
|
||||||
type => 'bool',
|
type => 'bool',
|
||||||
default => 0,
|
default => 0,
|
||||||
documentation =>
|
documentation =>
|
||||||
'Avoid asking confirmation during a session upgrade',
|
'Avoid asking confirmation during a session upgrade',
|
||||||
},
|
},
|
||||||
|
@ -761,7 +761,7 @@ sub attributes {
|
||||||
documentation => 'Refresh sessions plugin',
|
documentation => 'Refresh sessions plugin',
|
||||||
},
|
},
|
||||||
forceGlobalStorageIssuerOTT => {
|
forceGlobalStorageIssuerOTT => {
|
||||||
type => 'bool',
|
type => 'bool',
|
||||||
documentation =>
|
documentation =>
|
||||||
'Force Issuer tokens to be stored into Global Storage',
|
'Force Issuer tokens to be stored into Global Storage',
|
||||||
},
|
},
|
||||||
|
@ -845,8 +845,8 @@ sub attributes {
|
||||||
documentation => 'Show error if session is expired',
|
documentation => 'Show error if session is expired',
|
||||||
},
|
},
|
||||||
portalErrorOnMailNotFound => {
|
portalErrorOnMailNotFound => {
|
||||||
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',
|
||||||
},
|
},
|
||||||
|
@ -938,15 +938,15 @@ sub attributes {
|
||||||
documentation => 'Check XSS',
|
documentation => 'Check XSS',
|
||||||
},
|
},
|
||||||
portalForceAuthn => {
|
portalForceAuthn => {
|
||||||
default => 0,
|
default => 0,
|
||||||
help => 'forcereauthn.html',
|
help => 'forcereauthn.html',
|
||||||
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 =>
|
||||||
'Maximum interval in seconds since last authentication to force reauthentication',
|
'Maximum interval in seconds since last authentication to force reauthentication',
|
||||||
},
|
},
|
||||||
|
@ -977,15 +977,15 @@ sub attributes {
|
||||||
documentation => 'Max lock time',
|
documentation => 'Max lock time',
|
||||||
},
|
},
|
||||||
bruteForceProtectionIncrementalTempo => {
|
bruteForceProtectionIncrementalTempo => {
|
||||||
default => 0,
|
default => 0,
|
||||||
help => 'bruteforceprotection.html',
|
help => 'bruteforceprotection.html',
|
||||||
type => 'bool',
|
type => 'bool',
|
||||||
documentation =>
|
documentation =>
|
||||||
'Enable incremental lock time for brute force attack protection',
|
'Enable incremental lock time for brute force attack protection',
|
||||||
},
|
},
|
||||||
bruteForceProtectionLockTimes => {
|
bruteForceProtectionLockTimes => {
|
||||||
type => 'text',
|
type => 'text',
|
||||||
default => '15, 30, 60, 300, 600',
|
default => '15, 30, 60, 300, 600',
|
||||||
documentation =>
|
documentation =>
|
||||||
'Incremental lock time values for brute force attack protection',
|
'Incremental lock time values for brute force attack protection',
|
||||||
},
|
},
|
||||||
|
@ -1021,38 +1021,38 @@ sub attributes {
|
||||||
documentation => 'Enable Cross-Origin Resource Sharing',
|
documentation => 'Enable Cross-Origin Resource Sharing',
|
||||||
},
|
},
|
||||||
corsAllow_Credentials => {
|
corsAllow_Credentials => {
|
||||||
type => 'text',
|
type => 'text',
|
||||||
default => 'true',
|
default => 'true',
|
||||||
documentation =>
|
documentation =>
|
||||||
'Allow credentials for Cross-Origin Resource Sharing',
|
'Allow credentials for Cross-Origin Resource Sharing',
|
||||||
},
|
},
|
||||||
corsAllow_Headers => {
|
corsAllow_Headers => {
|
||||||
type => 'text',
|
type => 'text',
|
||||||
default => '*',
|
default => '*',
|
||||||
documentation =>
|
documentation =>
|
||||||
'Allowed headers for Cross-Origin Resource Sharing',
|
'Allowed headers for Cross-Origin Resource Sharing',
|
||||||
},
|
},
|
||||||
corsAllow_Methods => {
|
corsAllow_Methods => {
|
||||||
type => 'text',
|
type => 'text',
|
||||||
default => 'POST,GET',
|
default => 'POST,GET',
|
||||||
documentation =>
|
documentation =>
|
||||||
'Allowed methods for Cross-Origin Resource Sharing',
|
'Allowed methods for Cross-Origin Resource Sharing',
|
||||||
},
|
},
|
||||||
corsAllow_Origin => {
|
corsAllow_Origin => {
|
||||||
type => 'text',
|
type => 'text',
|
||||||
default => '*',
|
default => '*',
|
||||||
documentation =>
|
documentation =>
|
||||||
'Allowed origine for Cross-Origin Resource Sharing',
|
'Allowed origine for Cross-Origin Resource Sharing',
|
||||||
},
|
},
|
||||||
corsExpose_Headers => {
|
corsExpose_Headers => {
|
||||||
type => 'text',
|
type => 'text',
|
||||||
default => '*',
|
default => '*',
|
||||||
documentation =>
|
documentation =>
|
||||||
'Exposed headers for Cross-Origin Resource Sharing',
|
'Exposed headers for Cross-Origin Resource Sharing',
|
||||||
},
|
},
|
||||||
corsMax_Age => {
|
corsMax_Age => {
|
||||||
type => 'text',
|
type => 'text',
|
||||||
default => '86400', # 24 hours
|
default => '86400', # 24 hours
|
||||||
documentation => 'MAx-age for Cross-Origin Resource Sharing',
|
documentation => 'MAx-age for Cross-Origin Resource Sharing',
|
||||||
},
|
},
|
||||||
cspDefault => {
|
cspDefault => {
|
||||||
|
@ -1061,8 +1061,8 @@ sub attributes {
|
||||||
documentation => 'Default value for Content-Security-Policy',
|
documentation => 'Default value for Content-Security-Policy',
|
||||||
},
|
},
|
||||||
cspFormAction => {
|
cspFormAction => {
|
||||||
type => 'text',
|
type => 'text',
|
||||||
default => "*",
|
default => "*",
|
||||||
documentation =>
|
documentation =>
|
||||||
'Form action destination for Content-Security-Policy',
|
'Form action destination for Content-Security-Policy',
|
||||||
},
|
},
|
||||||
|
@ -1082,8 +1082,8 @@ sub attributes {
|
||||||
documentation => 'Style source for Content-Security-Policy',
|
documentation => 'Style source for Content-Security-Policy',
|
||||||
},
|
},
|
||||||
cspConnect => {
|
cspConnect => {
|
||||||
type => 'text',
|
type => 'text',
|
||||||
default => "'self'",
|
default => "'self'",
|
||||||
documentation =>
|
documentation =>
|
||||||
'Authorized Ajax destination for Content-Security-Policy',
|
'Authorized Ajax destination for Content-Security-Policy',
|
||||||
},
|
},
|
||||||
|
@ -1254,8 +1254,8 @@ sub attributes {
|
||||||
documentation => 'Display logout tab in portal',
|
documentation => 'Display logout tab in portal',
|
||||||
},
|
},
|
||||||
portalDisplayCertificateResetByMail => {
|
portalDisplayCertificateResetByMail => {
|
||||||
type => 'bool',
|
type => 'bool',
|
||||||
default => 0,
|
default => 0,
|
||||||
documentation =>
|
documentation =>
|
||||||
'Display certificate reset by mail button in portal',
|
'Display certificate reset by mail button in portal',
|
||||||
},
|
},
|
||||||
|
@ -1280,8 +1280,8 @@ sub attributes {
|
||||||
documentation => 'Display OIDC consent tab in portal',
|
documentation => 'Display OIDC consent tab in portal',
|
||||||
},
|
},
|
||||||
portalDisplayGeneratePassword => {
|
portalDisplayGeneratePassword => {
|
||||||
default => 1,
|
default => 1,
|
||||||
type => 'bool',
|
type => 'bool',
|
||||||
documentation =>
|
documentation =>
|
||||||
'Display password generate box in reset password form',
|
'Display password generate box in reset password form',
|
||||||
},
|
},
|
||||||
|
@ -1431,8 +1431,8 @@ sub attributes {
|
||||||
documentation => 'Notification server activation',
|
documentation => 'Notification server activation',
|
||||||
},
|
},
|
||||||
notificationServerSentAttributes => {
|
notificationServerSentAttributes => {
|
||||||
type => 'text',
|
type => 'text',
|
||||||
default => 'uid reference date title subtitle text check',
|
default => 'uid reference date title subtitle text check',
|
||||||
documentation =>
|
documentation =>
|
||||||
'Prameters to send with notification server GET method',
|
'Prameters to send with notification server GET method',
|
||||||
flags => 'p',
|
flags => 'p',
|
||||||
|
@ -1510,8 +1510,8 @@ sub attributes {
|
||||||
globalStorageOptions => {
|
globalStorageOptions => {
|
||||||
type => 'keyTextContainer',
|
type => 'keyTextContainer',
|
||||||
default => {
|
default => {
|
||||||
'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',
|
||||||
},
|
},
|
||||||
|
@ -1637,8 +1637,8 @@ 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 => 'boolOrExpr',
|
type => 'boolOrExpr',
|
||||||
documentation =>
|
documentation =>
|
||||||
'Rule to require old password to change the password',
|
'Rule to require old password to change the password',
|
||||||
},
|
},
|
||||||
|
@ -1853,7 +1853,7 @@ sub attributes {
|
||||||
documentation => 'Upgrade session activation',
|
documentation => 'Upgrade session activation',
|
||||||
},
|
},
|
||||||
forceGlobalStorageUpgradeOTT => {
|
forceGlobalStorageUpgradeOTT => {
|
||||||
type => 'bool',
|
type => 'bool',
|
||||||
documentation =>
|
documentation =>
|
||||||
'Force Upgrade tokens be stored into Global Storage',
|
'Force Upgrade tokens be stored into Global Storage',
|
||||||
},
|
},
|
||||||
|
@ -1882,7 +1882,7 @@ sub attributes {
|
||||||
documentation => 'U2F self registration activation',
|
documentation => 'U2F self registration activation',
|
||||||
},
|
},
|
||||||
u2fAuthnLevel => {
|
u2fAuthnLevel => {
|
||||||
type => 'int',
|
type => 'int',
|
||||||
documentation =>
|
documentation =>
|
||||||
'Authentication level for users authentified by password+U2F'
|
'Authentication level for users authentified by password+U2F'
|
||||||
},
|
},
|
||||||
|
@ -1916,7 +1916,7 @@ sub attributes {
|
||||||
documentation => 'TOTP self registration activation',
|
documentation => 'TOTP self registration activation',
|
||||||
},
|
},
|
||||||
totp2fAuthnLevel => {
|
totp2fAuthnLevel => {
|
||||||
type => 'int',
|
type => 'int',
|
||||||
documentation =>
|
documentation =>
|
||||||
'Authentication level for users authentified by password+TOTP'
|
'Authentication level for users authentified by password+TOTP'
|
||||||
},
|
},
|
||||||
|
@ -1969,7 +1969,7 @@ sub attributes {
|
||||||
documentation => 'UTOTP activation (mixed U2F/TOTP module)',
|
documentation => 'UTOTP activation (mixed U2F/TOTP module)',
|
||||||
},
|
},
|
||||||
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)'
|
||||||
},
|
},
|
||||||
|
@ -2006,7 +2006,7 @@ sub attributes {
|
||||||
documentation => 'Second factor code timeout',
|
documentation => 'Second factor code timeout',
|
||||||
},
|
},
|
||||||
mail2fAuthnLevel => {
|
mail2fAuthnLevel => {
|
||||||
type => 'int',
|
type => 'int',
|
||||||
documentation =>
|
documentation =>
|
||||||
'Authentication level for users authenticated by Mail second factor'
|
'Authentication level for users authenticated by Mail second factor'
|
||||||
},
|
},
|
||||||
|
@ -2043,7 +2043,7 @@ sub attributes {
|
||||||
documentation => 'Validation command of External second factor',
|
documentation => 'Validation command of External second factor',
|
||||||
},
|
},
|
||||||
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'
|
||||||
},
|
},
|
||||||
|
@ -2074,7 +2074,7 @@ sub attributes {
|
||||||
documentation => 'Radius 2f verification timeout',
|
documentation => 'Radius 2f verification timeout',
|
||||||
},
|
},
|
||||||
radius2fAuthnLevel => {
|
radius2fAuthnLevel => {
|
||||||
type => 'int',
|
type => 'int',
|
||||||
documentation =>
|
documentation =>
|
||||||
'Authentication level for users authenticated by Radius second factor'
|
'Authentication level for users authenticated by Radius second factor'
|
||||||
},
|
},
|
||||||
|
@ -2118,7 +2118,7 @@ sub attributes {
|
||||||
documentation => 'Args for REST 2F init',
|
documentation => 'Args for REST 2F init',
|
||||||
},
|
},
|
||||||
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'
|
||||||
},
|
},
|
||||||
|
@ -2143,7 +2143,7 @@ sub attributes {
|
||||||
documentation => 'Yubikey self registration activation',
|
documentation => 'Yubikey self registration activation',
|
||||||
},
|
},
|
||||||
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'
|
||||||
},
|
},
|
||||||
|
@ -2182,7 +2182,7 @@ sub attributes {
|
||||||
documentation => 'Authorize users to remove existing Yubikey',
|
documentation => 'Authorize users to remove existing Yubikey',
|
||||||
},
|
},
|
||||||
yubikey2fFromSessionAttribute => {
|
yubikey2fFromSessionAttribute => {
|
||||||
type => 'text',
|
type => 'text',
|
||||||
documentation =>
|
documentation =>
|
||||||
'Provision yubikey from the given session variable',
|
'Provision yubikey from the given session variable',
|
||||||
},
|
},
|
||||||
|
@ -2203,9 +2203,9 @@ sub attributes {
|
||||||
documentation => 'WebAuthn self registration activation',
|
documentation => 'WebAuthn self registration activation',
|
||||||
},
|
},
|
||||||
webauthn2fAuthnLevel => {
|
webauthn2fAuthnLevel => {
|
||||||
type => 'int',
|
type => 'int',
|
||||||
documentation =>
|
documentation =>
|
||||||
'Authentication level for users authentified by WebAuthn second factor'
|
'Authentication level for users authentified by WebAuthn second factor'
|
||||||
},
|
},
|
||||||
webauthn2fLabel => {
|
webauthn2fLabel => {
|
||||||
type => 'text',
|
type => 'text',
|
||||||
|
@ -2218,11 +2218,11 @@ sub attributes {
|
||||||
webauthn2fUserVerification => {
|
webauthn2fUserVerification => {
|
||||||
type => 'select',
|
type => 'select',
|
||||||
select => [
|
select => [
|
||||||
{ k => 'discouraged', v => 'Discouraged' },
|
{ k => 'discouraged', v => 'Discouraged' },
|
||||||
{ k => 'preferred', v => 'Preferred' },
|
{ k => 'preferred', v => 'Preferred' },
|
||||||
{ k => 'required', v => 'Required' },
|
{ k => 'required', v => 'Required' },
|
||||||
],
|
],
|
||||||
default => 'preferred',
|
default => 'preferred',
|
||||||
documentation => 'Verify user during registration and login',
|
documentation => 'Verify user during registration and login',
|
||||||
},
|
},
|
||||||
webauthn2fUserCanRemoveKey => {
|
webauthn2fUserCanRemoveKey => {
|
||||||
|
@ -2239,7 +2239,6 @@ sub attributes {
|
||||||
documentation => 'WebAuthn Relying Party display name',
|
documentation => 'WebAuthn Relying Party display name',
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
# Single session
|
# Single session
|
||||||
notifyDeleted => {
|
notifyDeleted => {
|
||||||
default => 1,
|
default => 1,
|
||||||
|
@ -2284,14 +2283,14 @@ sub attributes {
|
||||||
documentation => 'Enable REST password reset server',
|
documentation => 'Enable REST password reset server',
|
||||||
},
|
},
|
||||||
restExportSecretKeys => {
|
restExportSecretKeys => {
|
||||||
default => 0,
|
default => 0,
|
||||||
type => 'bool',
|
type => 'bool',
|
||||||
documentation =>
|
documentation =>
|
||||||
'Allow to export secret keys in REST session server',
|
'Allow to export secret keys in REST session server',
|
||||||
},
|
},
|
||||||
restClockTolerance => {
|
restClockTolerance => {
|
||||||
default => 15,
|
default => 15,
|
||||||
type => 'int',
|
type => 'int',
|
||||||
documentation =>
|
documentation =>
|
||||||
'How tolerant the REST session server will be to clock dift',
|
'How tolerant the REST session server will be to clock dift',
|
||||||
},
|
},
|
||||||
|
@ -2320,7 +2319,7 @@ sub attributes {
|
||||||
documentation => 'Enable SOAP config server',
|
documentation => 'Enable SOAP config server',
|
||||||
},
|
},
|
||||||
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',
|
||||||
},
|
},
|
||||||
|
@ -2583,7 +2582,7 @@ sub attributes {
|
||||||
documentation => 'CAS User attribute',
|
documentation => 'CAS User attribute',
|
||||||
},
|
},
|
||||||
casAppMetaDataOptionsAuthnLevel => {
|
casAppMetaDataOptionsAuthnLevel => {
|
||||||
type => 'int',
|
type => 'int',
|
||||||
documentation =>
|
documentation =>
|
||||||
'Authentication level requires to access to this CAS application',
|
'Authentication level requires to access to this CAS application',
|
||||||
},
|
},
|
||||||
|
@ -2745,8 +2744,8 @@ sub attributes {
|
||||||
default => 'RSA_SHA256',
|
default => 'RSA_SHA256',
|
||||||
},
|
},
|
||||||
samlServiceUseCertificateInResponse => {
|
samlServiceUseCertificateInResponse => {
|
||||||
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',
|
||||||
},
|
},
|
||||||
|
@ -2769,8 +2768,8 @@ sub attributes {
|
||||||
documentation => 'SAML authn context password level',
|
documentation => 'SAML authn context password level',
|
||||||
},
|
},
|
||||||
samlAuthnContextMapPasswordProtectedTransport => {
|
samlAuthnContextMapPasswordProtectedTransport => {
|
||||||
type => 'int',
|
type => 'int',
|
||||||
default => 3,
|
default => 3,
|
||||||
documentation =>
|
documentation =>
|
||||||
'SAML authn context password protected transport level',
|
'SAML authn context password protected transport level',
|
||||||
},
|
},
|
||||||
|
@ -3131,7 +3130,7 @@ sub attributes {
|
||||||
documentation => 'SAML SP SLO SOAP',
|
documentation => 'SAML SP SLO SOAP',
|
||||||
},
|
},
|
||||||
samlSPSSODescriptorAssertionConsumerServiceHTTPArtifact => {
|
samlSPSSODescriptorAssertionConsumerServiceHTTPArtifact => {
|
||||||
type => 'samlAssertion',
|
type => 'samlAssertion',
|
||||||
default =>
|
default =>
|
||||||
'0;1;urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact;'
|
'0;1;urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact;'
|
||||||
. '#PORTAL#/saml/proxySingleSignOnArtifact',
|
. '#PORTAL#/saml/proxySingleSignOnArtifact',
|
||||||
|
@ -3223,7 +3222,7 @@ sub attributes {
|
||||||
default => 1,
|
default => 1,
|
||||||
},
|
},
|
||||||
samlSPMetaDataOptionsAuthnLevel => {
|
samlSPMetaDataOptionsAuthnLevel => {
|
||||||
type => 'int',
|
type => 'int',
|
||||||
documentation =>
|
documentation =>
|
||||||
'Authentication level requires to access to this SP',
|
'Authentication level requires to access to this SP',
|
||||||
},
|
},
|
||||||
|
@ -3335,9 +3334,9 @@ sub attributes {
|
||||||
documentation => 'Rule to display second factor Manager link',
|
documentation => 'Rule to display second factor Manager link',
|
||||||
},
|
},
|
||||||
sfRemovedMsgRule => {
|
sfRemovedMsgRule => {
|
||||||
type => 'boolOrExpr',
|
type => 'boolOrExpr',
|
||||||
default => 0,
|
default => 0,
|
||||||
help => 'secondfactor.html',
|
help => 'secondfactor.html',
|
||||||
documentation =>
|
documentation =>
|
||||||
'Display a message if at leat one expired SF has been removed',
|
'Display a message if at leat one expired SF has been removed',
|
||||||
},
|
},
|
||||||
|
@ -3359,7 +3358,7 @@ sub attributes {
|
||||||
documentation => 'Notification title',
|
documentation => 'Notification title',
|
||||||
},
|
},
|
||||||
sfRemovedNotifMsg => {
|
sfRemovedNotifMsg => {
|
||||||
type => 'text',
|
type => 'text',
|
||||||
default =>
|
default =>
|
||||||
'_removedSF_ expired second factor(s) has/have been removed (_nameSF_)!',
|
'_removedSF_ expired second factor(s) has/have been removed (_nameSF_)!',
|
||||||
help => 'secondfactor.html',
|
help => 'secondfactor.html',
|
||||||
|
@ -3370,13 +3369,14 @@ sub attributes {
|
||||||
documentation => 'Timeout for 2F registration process',
|
documentation => 'Timeout for 2F registration process',
|
||||||
},
|
},
|
||||||
available2F => {
|
available2F => {
|
||||||
type => 'text',
|
type => 'text',
|
||||||
default => 'UTOTP,TOTP,U2F,REST,Mail2F,Ext2F,WebAuthn,Yubikey,Radius',
|
default =>
|
||||||
|
'UTOTP,TOTP,U2F,REST,Mail2F,Ext2F,WebAuthn,Yubikey,Radius',
|
||||||
documentation => 'Available second factor modules',
|
documentation => 'Available second factor modules',
|
||||||
},
|
},
|
||||||
available2FSelfRegistration => {
|
available2FSelfRegistration => {
|
||||||
type => 'text',
|
type => 'text',
|
||||||
default => 'TOTP,U2F,WebAuthn,Yubikey',
|
default => 'TOTP,U2F,WebAuthn,Yubikey',
|
||||||
documentation =>
|
documentation =>
|
||||||
'Available self-registration modules for second factor',
|
'Available self-registration modules for second factor',
|
||||||
},
|
},
|
||||||
|
@ -3540,8 +3540,8 @@ m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
|
||||||
documentation => 'LDAP attribute name for member in groups',
|
documentation => 'LDAP attribute name for member in groups',
|
||||||
},
|
},
|
||||||
ldapGroupAttributeNameUser => {
|
ldapGroupAttributeNameUser => {
|
||||||
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',
|
||||||
},
|
},
|
||||||
|
@ -3551,8 +3551,8 @@ m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
|
||||||
documentation => 'LDAP attributes to search in groups',
|
documentation => 'LDAP attributes to search in groups',
|
||||||
},
|
},
|
||||||
ldapGroupAttributeNameGroup => {
|
ldapGroupAttributeNameGroup => {
|
||||||
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',
|
||||||
},
|
},
|
||||||
|
@ -3594,12 +3594,12 @@ m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
|
||||||
default => 'require',
|
default => 'require',
|
||||||
},
|
},
|
||||||
ldapCAFile => {
|
ldapCAFile => {
|
||||||
type => 'text',
|
type => 'text',
|
||||||
documentation =>
|
documentation =>
|
||||||
'Location of the certificate file for LDAP connections',
|
'Location of the certificate file for LDAP connections',
|
||||||
},
|
},
|
||||||
ldapCAPath => {
|
ldapCAPath => {
|
||||||
type => 'text',
|
type => 'text',
|
||||||
documentation =>
|
documentation =>
|
||||||
'Location of the CA directory for LDAP connections',
|
'Location of the CA directory for LDAP connections',
|
||||||
},
|
},
|
||||||
|
@ -3736,7 +3736,7 @@ m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
|
||||||
type => 'keyTextContainer',
|
type => 'keyTextContainer',
|
||||||
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',
|
||||||
|
@ -3834,7 +3834,7 @@ m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
|
||||||
default => 'id,first-name,last-name,email-address'
|
default => 'id,first-name,last-name,email-address'
|
||||||
},
|
},
|
||||||
linkedInUserField => { type => 'text', default => 'emailAddress' },
|
linkedInUserField => { type => 'text', default => 'emailAddress' },
|
||||||
linkedInScope =>
|
linkedInScope =>
|
||||||
{ type => 'text', default => 'r_liteprofile r_emailaddress' },
|
{ type => 'text', default => 'r_liteprofile r_emailaddress' },
|
||||||
|
|
||||||
# GitHub
|
# GitHub
|
||||||
|
@ -3881,10 +3881,10 @@ m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
|
||||||
dbiUserTable => { type => 'text', },
|
dbiUserTable => { type => 'text', },
|
||||||
|
|
||||||
# TODO: add dbiMailCol
|
# TODO: add dbiMailCol
|
||||||
dbiAuthLoginCol => { type => 'text', },
|
dbiAuthLoginCol => { type => 'text', },
|
||||||
dbiAuthPasswordCol => { type => 'text', },
|
dbiAuthPasswordCol => { type => 'text', },
|
||||||
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 =>
|
||||||
|
@ -4269,13 +4269,13 @@ m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
|
||||||
documentation => 'OpenID Connect global access token TTL',
|
documentation => 'OpenID Connect global access token TTL',
|
||||||
},
|
},
|
||||||
oidcServiceDynamicRegistrationExportedVars => {
|
oidcServiceDynamicRegistrationExportedVars => {
|
||||||
type => 'keyTextContainer',
|
type => 'keyTextContainer',
|
||||||
documentation =>
|
documentation =>
|
||||||
'OpenID Connect exported variables for dynamic registration',
|
'OpenID Connect exported variables for dynamic registration',
|
||||||
},
|
},
|
||||||
oidcServiceDynamicRegistrationExtraClaims => {
|
oidcServiceDynamicRegistrationExtraClaims => {
|
||||||
type => 'keyTextContainer',
|
type => 'keyTextContainer',
|
||||||
keyTest => qr/^[\x21\x23-\x5B\x5D-\x7E]+$/,
|
keyTest => qr/^[\x21\x23-\x5B\x5D-\x7E]+$/,
|
||||||
documentation =>
|
documentation =>
|
||||||
'OpenID Connect extra claims for dynamic registration',
|
'OpenID Connect extra claims for dynamic registration',
|
||||||
},
|
},
|
||||||
|
@ -4334,7 +4334,7 @@ m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
|
||||||
oidcOPMetaDataOptionsJWKSTimeout => { type => 'int', default => 0 },
|
oidcOPMetaDataOptionsJWKSTimeout => { type => 'int', default => 0 },
|
||||||
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',
|
||||||
|
@ -4363,10 +4363,10 @@ m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
|
||||||
{ type => 'bool', default => 1 },
|
{ type => 'bool', default => 1 },
|
||||||
oidcOPMetaDataOptionsIDTokenMaxAge => { type => 'int', default => 30 },
|
oidcOPMetaDataOptionsIDTokenMaxAge => { 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 },
|
||||||
oidcOPMetaDataOptionsSortNumber => { type => 'int', },
|
oidcOPMetaDataOptionsSortNumber => { type => 'int', },
|
||||||
|
|
||||||
# OpenID Connect relying parties
|
# OpenID Connect relying parties
|
||||||
oidcRPMetaDataExportedVars => {
|
oidcRPMetaDataExportedVars => {
|
||||||
|
@ -4398,7 +4398,7 @@ m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
|
||||||
],
|
],
|
||||||
default => 'HS512',
|
default => 'HS512',
|
||||||
},
|
},
|
||||||
oidcRPMetaDataOptionsIDTokenExpiration => { type => 'int' },
|
oidcRPMetaDataOptionsIDTokenExpiration => { type => 'int' },
|
||||||
oidcRPMetaDataOptionsIDTokenForceClaims =>
|
oidcRPMetaDataOptionsIDTokenForceClaims =>
|
||||||
{ type => 'bool', default => 0 },
|
{ type => 'bool', default => 0 },
|
||||||
oidcRPMetaDataOptionsAccessTokenSignAlg => {
|
oidcRPMetaDataOptionsAccessTokenSignAlg => {
|
||||||
|
@ -4480,8 +4480,8 @@ m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
|
||||||
documentation => 'Allow offline access',
|
documentation => 'Allow offline access',
|
||||||
},
|
},
|
||||||
oidcRPMetaDataOptionsAllowPasswordGrant => {
|
oidcRPMetaDataOptionsAllowPasswordGrant => {
|
||||||
type => 'bool',
|
type => 'bool',
|
||||||
default => 0,
|
default => 0,
|
||||||
documentation =>
|
documentation =>
|
||||||
'Allow OAuth2 Resource Owner Password Credentials Grant',
|
'Allow OAuth2 Resource Owner Password Credentials Grant',
|
||||||
},
|
},
|
||||||
|
@ -4496,7 +4496,7 @@ m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
|
||||||
documentation => 'Issue refresh tokens',
|
documentation => 'Issue refresh tokens',
|
||||||
},
|
},
|
||||||
oidcRPMetaDataOptionsAuthnLevel => {
|
oidcRPMetaDataOptionsAuthnLevel => {
|
||||||
type => 'int',
|
type => 'int',
|
||||||
documentation =>
|
documentation =>
|
||||||
'Authentication level requires to access to this RP',
|
'Authentication level requires to access to this RP',
|
||||||
},
|
},
|
||||||
|
|
|
@ -72,7 +72,7 @@ sub tree {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title => 'passwordManagement',
|
title => 'passwordManagement',
|
||||||
help =>
|
help =>
|
||||||
'portalcustom.html#password-management',
|
'portalcustom.html#password-management',
|
||||||
form => 'simpleInputContainer',
|
form => 'simpleInputContainer',
|
||||||
nodes => [
|
nodes => [
|
||||||
|
@ -99,7 +99,7 @@ sub tree {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title => 'portalOther',
|
title => 'portalOther',
|
||||||
help =>
|
help =>
|
||||||
'portalcustom.html#other-parameters',
|
'portalcustom.html#other-parameters',
|
||||||
form => 'simpleInputContainer',
|
form => 'simpleInputContainer',
|
||||||
nodes => [
|
nodes => [
|
||||||
|
@ -129,7 +129,7 @@ sub tree {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title => 'authParams',
|
title => 'authParams',
|
||||||
help =>
|
help =>
|
||||||
'start.html#authentication-users-and-password-databases',
|
'start.html#authentication-users-and-password-databases',
|
||||||
form => 'authParams',
|
form => 'authParams',
|
||||||
nodes => [
|
nodes => [
|
||||||
|
@ -650,7 +650,7 @@ sub tree {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title => 'soapServices',
|
title => 'soapServices',
|
||||||
help =>
|
help =>
|
||||||
'portalservers.html#SOAP_(deprecated)',
|
'portalservers.html#SOAP_(deprecated)',
|
||||||
form => 'simpleInputContainer',
|
form => 'simpleInputContainer',
|
||||||
nodes => [
|
nodes => [
|
||||||
|
@ -684,7 +684,7 @@ sub tree {
|
||||||
'notificationStorageOptions',
|
'notificationStorageOptions',
|
||||||
{
|
{
|
||||||
title => 'serverNotification',
|
title => 'serverNotification',
|
||||||
help =>
|
help =>
|
||||||
'notifications.html#notification-server',
|
'notifications.html#notification-server',
|
||||||
nodes => [
|
nodes => [
|
||||||
'notificationServer',
|
'notificationServer',
|
||||||
|
|
|
@ -24,8 +24,8 @@ has cfgNum => (
|
||||||
|
|
||||||
has log => ( is => 'rw' );
|
has log => ( is => 'rw' );
|
||||||
has req => ( is => 'ro' );
|
has req => ( is => 'ro' );
|
||||||
has sep => ( is => 'rw', isa => 'Str', default => '/' );
|
has sep => ( is => 'rw', isa => 'Str', default => '/' );
|
||||||
has format => ( is => 'rw', isa => 'Str', default => "%-25s | %-25s | %-25s" );
|
has format => ( is => 'rw', isa => 'Str', default => "%-25s | %-25s | %-25s" );
|
||||||
has yes => ( is => 'rw', isa => 'Bool', default => 0 );
|
has yes => ( is => 'rw', isa => 'Bool', default => 0 );
|
||||||
has safe => ( is => 'rw', isa => 'Bool', default => 0 );
|
has safe => ( is => 'rw', isa => 'Bool', default => 0 );
|
||||||
has force => ( is => 'rw', isa => 'Bool', default => 0 );
|
has force => ( is => 'rw', isa => 'Bool', default => 0 );
|
||||||
|
@ -317,8 +317,8 @@ sub lastCfg {
|
||||||
|
|
||||||
sub save {
|
sub save {
|
||||||
my ($self) = @_;
|
my ($self) = @_;
|
||||||
my $conf = $self->jsonResponse( '/confs/' . $self->cfgNum, 'full=1' );
|
my $conf = $self->jsonResponse( '/confs/' . $self->cfgNum, 'full=1' );
|
||||||
my $json = JSON->new->indent->canonical;
|
my $json = JSON->new->indent->canonical;
|
||||||
print $json->encode($conf);
|
print $json->encode($conf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -404,9 +404,9 @@ sub _getKey {
|
||||||
|
|
||||||
sub _setKey {
|
sub _setKey {
|
||||||
my ( $self, $conf, $key, $value ) = @_;
|
my ( $self, $conf, $key, $value ) = @_;
|
||||||
my $sep = $self->sep;
|
my $sep = $self->sep;
|
||||||
my (@path) = split $sep, $key;
|
my (@path) = split $sep, $key;
|
||||||
my $last = pop @path;
|
my $last = pop @path;
|
||||||
while ( my $next = shift @path ) {
|
while ( my $next = shift @path ) {
|
||||||
$conf = $conf->{$next};
|
$conf = $conf->{$next};
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,9 +20,10 @@ sub diff {
|
||||||
$res[$i]->{$key} = $tmp[$i] if ( $tmp[$i] );
|
$res[$i]->{$key} = $tmp[$i] if ( $tmp[$i] );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
elsif ( $key =~ $hashParameters
|
elsif (
|
||||||
or
|
$key =~ $hashParameters
|
||||||
( ref( $conf[0]->{$key} ) and ref( $conf[0]->{$key} ) eq 'HASH' ) )
|
or ( ref( $conf[0]->{$key} ) and ref( $conf[0]->{$key} ) eq 'HASH' )
|
||||||
|
)
|
||||||
{
|
{
|
||||||
if ( ref $conf[1]->{$key} ) {
|
if ( ref $conf[1]->{$key} ) {
|
||||||
my @tmp =
|
my @tmp =
|
||||||
|
|
|
@ -438,8 +438,8 @@ sub _scanNodes {
|
||||||
$self->_scanNodes($subNodes);
|
$self->_scanNodes($subNodes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
elsif (
|
elsif ( $target =~
|
||||||
$target =~ /^oidc(?:O|R)PMetaData(?:ExportedVars|Macros|ScopeRules)$/ )
|
/^oidc(?:O|R)PMetaData(?:ExportedVars|Macros|ScopeRules)$/ )
|
||||||
{
|
{
|
||||||
hdebug(" $target");
|
hdebug(" $target");
|
||||||
if ( $leaf->{cnodes} ) {
|
if ( $leaf->{cnodes} ) {
|
||||||
|
|
|
@ -106,7 +106,7 @@ sub zeroConf {
|
||||||
},
|
},
|
||||||
'cfgNum' => 0,
|
'cfgNum' => 0,
|
||||||
'globalStorageOptions' => {
|
'globalStorageOptions' => {
|
||||||
'Directory' => $sessionDir,
|
'Directory' => $sessionDir,
|
||||||
'generateModule' =>
|
'generateModule' =>
|
||||||
'Lemonldap::NG::Common::Apache::Session::Generate::SHA256',
|
'Lemonldap::NG::Common::Apache::Session::Generate::SHA256',
|
||||||
'LockDirectory' => "$sessionDir/lock"
|
'LockDirectory' => "$sessionDir/lock"
|
||||||
|
@ -177,14 +177,14 @@ sub zeroConf {
|
||||||
'inGroup("timelords") or $uid eq "rtyler"',
|
'inGroup("timelords") or $uid eq "rtyler"',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'whatToTrace' => '_whatToTrace',
|
'whatToTrace' => '_whatToTrace',
|
||||||
'securedCookie' => 0,
|
'securedCookie' => 0,
|
||||||
'cookieName' => 'lemonldap',
|
'cookieName' => 'lemonldap',
|
||||||
'cfgAuthor' => 'The LemonLDAP::NG team',
|
'cfgAuthor' => 'The LemonLDAP::NG team',
|
||||||
'cfgDate' => '1627287638',
|
'cfgDate' => '1627287638',
|
||||||
'cfgVersion' => $VERSION,
|
'cfgVersion' => $VERSION,
|
||||||
'exportedVars' => {},
|
'exportedVars' => {},
|
||||||
'portalSkin' => 'bootstrap',
|
'portalSkin' => 'bootstrap',
|
||||||
'portalSkinBackground' =>
|
'portalSkinBackground' =>
|
||||||
'1280px-Cedar_Breaks_National_Monument_partially.jpg',
|
'1280px-Cedar_Breaks_National_Monument_partially.jpg',
|
||||||
'mailUrl' => "http://auth.$domain/resetpwd",
|
'mailUrl' => "http://auth.$domain/resetpwd",
|
||||||
|
|
|
@ -248,7 +248,8 @@ sub sessions {
|
||||||
value => $uid,
|
value => $uid,
|
||||||
count => scalar( @{ $r->{$uid} } ),
|
count => scalar( @{ $r->{$uid} } ),
|
||||||
sessions => [
|
sessions => [
|
||||||
map { {
|
map {
|
||||||
|
{
|
||||||
session =>
|
session =>
|
||||||
$self->_maybeEncryptSessionId( $_->{_sessionId} ),
|
$self->_maybeEncryptSessionId( $_->{_sessionId} ),
|
||||||
date => $_->{_utime}
|
date => $_->{_utime}
|
||||||
|
@ -399,7 +400,8 @@ qq{Use of an uninitialized attribute "$group" to group sessions},
|
||||||
else {
|
else {
|
||||||
$res = [
|
$res = [
|
||||||
sort { $a->{date} <=> $b->{date} }
|
sort { $a->{date} <=> $b->{date} }
|
||||||
map { {
|
map {
|
||||||
|
{
|
||||||
session => $self->_maybeEncryptSessionId($_),
|
session => $self->_maybeEncryptSessionId($_),
|
||||||
date => $res->{$_}->{_utime}
|
date => $res->{$_}->{_utime}
|
||||||
}
|
}
|
||||||
|
@ -459,8 +461,8 @@ sub delSession {
|
||||||
}
|
}
|
||||||
|
|
||||||
sub cmpIPv4 {
|
sub cmpIPv4 {
|
||||||
my @a = split /\./, $_[0];
|
my @a = split /\./, $_[0];
|
||||||
my @b = split /\./, $_[1];
|
my @b = split /\./, $_[1];
|
||||||
my $cmp = 0;
|
my $cmp = 0;
|
||||||
F: for ( my $i = 0 ; $i < 4 ; $i++ ) {
|
F: for ( my $i = 0 ; $i < 4 ; $i++ ) {
|
||||||
if ( $a[$i] != $b[$i] ) {
|
if ( $a[$i] != $b[$i] ) {
|
||||||
|
|
|
@ -20,9 +20,9 @@ sub newSession {
|
||||||
$tmp = Lemonldap::NG::Common::Session->new( {
|
$tmp = Lemonldap::NG::Common::Session->new( {
|
||||||
storageModule => 'Apache::Session::File',
|
storageModule => 'Apache::Session::File',
|
||||||
storageModuleOptions => {
|
storageModuleOptions => {
|
||||||
Directory => 't/sessions',
|
Directory => 't/sessions',
|
||||||
LockDirectory => 't/sessions',
|
LockDirectory => 't/sessions',
|
||||||
backend => 'Apache::Session::File',
|
backend => 'Apache::Session::File',
|
||||||
generateModule =>
|
generateModule =>
|
||||||
'Lemonldap::NG::Common::Apache::Session::Generate::SHA256',
|
'Lemonldap::NG::Common::Apache::Session::Generate::SHA256',
|
||||||
},
|
},
|
||||||
|
|
|
@ -129,7 +129,7 @@ sub checkGet {
|
||||||
my $res = get( $test, $type, $confKey );
|
my $res = get( $test, $type, $confKey );
|
||||||
check200( $test, $res );
|
check200( $test, $res );
|
||||||
my @path = split '/', $attrPath;
|
my @path = split '/', $attrPath;
|
||||||
my $key = from_json( $res->[2]->[0] );
|
my $key = from_json( $res->[2]->[0] );
|
||||||
for (@path) {
|
for (@path) {
|
||||||
if ( ref($key) eq 'ARRAY' ) {
|
if ( ref($key) eq 'ARRAY' ) {
|
||||||
$key = $key->[$_];
|
$key = $key->[$_];
|
||||||
|
@ -326,7 +326,7 @@ checkAddFailsOnInvalidConfkey( $test, 'cat', $cat3 );
|
||||||
|
|
||||||
checkAddFailsOnInvalidConfkey
|
checkAddFailsOnInvalidConfkey
|
||||||
|
|
||||||
$test = "Cat - Update should succeed and keep existing values";
|
$test = "Cat - Update should succeed and keep existing values";
|
||||||
$cat1->{order} = 3;
|
$cat1->{order} = 3;
|
||||||
delete $cat1->{catname};
|
delete $cat1->{catname};
|
||||||
checkUpdate( $test, 'cat', 'mycat1', $cat1 );
|
checkUpdate( $test, 'cat', 'mycat1', $cat1 );
|
||||||
|
@ -419,7 +419,7 @@ $test = "App - Get app myapp1 from mycat3 should err on not found";
|
||||||
checkGetNotFound( $test, 'app/mycat3', 'myapp1' );
|
checkGetNotFound( $test, 'app/mycat3', 'myapp1' );
|
||||||
|
|
||||||
$test = "App - Add app myapp1 to mycat3 should err on not found";
|
$test = "App - Add app myapp1 to mycat3 should err on not found";
|
||||||
checkAddNotFound( $test, 'app/mycat3', $app1);
|
checkAddNotFound( $test, 'app/mycat3', $app1 );
|
||||||
|
|
||||||
$test = "App - Add app1 to cat1 should succeed";
|
$test = "App - Add app1 to cat1 should succeed";
|
||||||
checkAdd( $test, 'app/mycat1', $app1 );
|
checkAdd( $test, 'app/mycat1', $app1 );
|
||||||
|
|
|
@ -23,10 +23,10 @@ is( $brokenconfig->{status}, 'ko', 'Got expected global status' );
|
||||||
is( $brokenconfig->{status_config}, 'ko', 'Got expected config status' );
|
is( $brokenconfig->{status_config}, 'ko', 'Got expected config status' );
|
||||||
rename 't/conf/lmConf-1.json.broken', 't/conf/lmConf-1.json';
|
rename 't/conf/lmConf-1.json.broken', 't/conf/lmConf-1.json';
|
||||||
|
|
||||||
my $allfine = getStatus( "Back to normal" );
|
my $allfine = getStatus("Back to normal");
|
||||||
is( $allfine->{status}, 'ok', 'Got expected global status' );
|
is( $allfine->{status}, 'ok', 'Got expected global status' );
|
||||||
is( $allfine->{status_config}, 'ok', 'Got expected config status' );
|
is( $allfine->{status_config}, 'ok', 'Got expected config status' );
|
||||||
is( $allfine->{status_sessions}, 'unknown', 'Not implemented yet' );
|
is( $allfine->{status_sessions}, 'unknown', 'Not implemented yet' );
|
||||||
is( $allfine->{status_psessions}, 'unknown', 'Not implemented yet' );
|
is( $allfine->{status_psessions}, 'unknown', 'Not implemented yet' );
|
||||||
|
|
||||||
# Clean up generated files, except for "lmConf-1.json"
|
# Clean up generated files, except for "lmConf-1.json"
|
||||||
|
|
|
@ -276,7 +276,7 @@ sub checkFindByProviderId {
|
||||||
($gotProviderId) = $result->{metadata} =~ m/entityID=['"](.+?)['"]/i;
|
($gotProviderId) = $result->{metadata} =~ m/entityID=['"](.+?)['"]/i;
|
||||||
}
|
}
|
||||||
elsif ( $providerIdName eq 'serviceUrl' ) {
|
elsif ( $providerIdName eq 'serviceUrl' ) {
|
||||||
$gotProviderId = shift @{$result->{options}->{service}};
|
$gotProviderId = shift @{ $result->{options}->{service} };
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$gotProviderId = $result->{$providerIdName};
|
$gotProviderId = $result->{$providerIdName};
|
||||||
|
@ -337,8 +337,8 @@ my $oidcRp = {
|
||||||
email => 'mail',
|
email => 'mail',
|
||||||
},
|
},
|
||||||
options => {
|
options => {
|
||||||
clientSecret => 'secret',
|
clientSecret => 'secret',
|
||||||
icon => 'web.png',
|
icon => 'web.png',
|
||||||
postLogoutRedirectUris =>
|
postLogoutRedirectUris =>
|
||||||
[ "http://url/logout1", "http://url/logout2" ],
|
[ "http://url/logout1", "http://url/logout2" ],
|
||||||
}
|
}
|
||||||
|
@ -534,7 +534,7 @@ $samlSp->{options}->{checkSLOMessageSignature} = 1;
|
||||||
$samlSp->{options}->{encryptionMode} = 'nameid';
|
$samlSp->{options}->{encryptionMode} = 'nameid';
|
||||||
delete $samlSp->{options}->{sessionNotOnOrAfterTimeout};
|
delete $samlSp->{options}->{sessionNotOnOrAfterTimeout};
|
||||||
delete $samlSp->{exportedAttributes};
|
delete $samlSp->{exportedAttributes};
|
||||||
$samlSp->{macros}->{family_name} = '$sn',
|
$samlSp->{macros}->{family_name} = '$sn',
|
||||||
$samlSp->{exportedAttributes}->{cn}->{name} = "cn",
|
$samlSp->{exportedAttributes}->{cn}->{name} = "cn",
|
||||||
$samlSp->{exportedAttributes}->{cn}->{friendlyName} = "common_name",
|
$samlSp->{exportedAttributes}->{cn}->{friendlyName} = "common_name",
|
||||||
$samlSp->{exportedAttributes}->{cn}->{mandatory} = "false",
|
$samlSp->{exportedAttributes}->{cn}->{mandatory} = "false",
|
||||||
|
@ -646,7 +646,9 @@ my $casApp = {
|
||||||
given_name => '$firstName',
|
given_name => '$firstName',
|
||||||
},
|
},
|
||||||
options => {
|
options => {
|
||||||
service => [ 'http://mycasapp.example.com', 'http://mycasapp2.example.com/test' ],
|
service => [
|
||||||
|
'http://mycasapp.example.com', 'http://mycasapp2.example.com/test'
|
||||||
|
],
|
||||||
rule => '$uid eq \'dwho\'',
|
rule => '$uid eq \'dwho\'',
|
||||||
userAttribute => 'uid'
|
userAttribute => 'uid'
|
||||||
}
|
}
|
||||||
|
@ -663,7 +665,7 @@ $test = "CasApp - Add should fail on duplicate confKey";
|
||||||
checkAddFailsIfExists( $test, 'cas/app', $casApp );
|
checkAddFailsIfExists( $test, 'cas/app', $casApp );
|
||||||
|
|
||||||
$test = "CasApp - Update should succeed and keep existing values";
|
$test = "CasApp - Update should succeed and keep existing values";
|
||||||
$casApp->{options}->{service} = [ 'http://mycasapp.acme.com' ];
|
$casApp->{options}->{service} = ['http://mycasapp.acme.com'];
|
||||||
$casApp->{options}->{userAttribute} = 'cn';
|
$casApp->{options}->{userAttribute} = 'cn';
|
||||||
delete $casApp->{options}->{rule};
|
delete $casApp->{options}->{rule};
|
||||||
delete $casApp->{macros};
|
delete $casApp->{macros};
|
||||||
|
@ -672,7 +674,7 @@ $casApp->{macros}->{given_name} = '$givenName';
|
||||||
$casApp->{exportedVars}->{cn} = 'uid';
|
$casApp->{exportedVars}->{cn} = 'uid';
|
||||||
checkUpdate( $test, 'cas/app', 'myCasApp1', $casApp );
|
checkUpdate( $test, 'cas/app', 'myCasApp1', $casApp );
|
||||||
checkGet( $test, 'cas/app', 'myCasApp1', 'options/service/0',
|
checkGet( $test, 'cas/app', 'myCasApp1', 'options/service/0',
|
||||||
'http://mycasapp.acme.com');
|
'http://mycasapp.acme.com' );
|
||||||
checkGet( $test, 'cas/app', 'myCasApp1', 'options/userAttribute', 'cn' );
|
checkGet( $test, 'cas/app', 'myCasApp1', 'options/userAttribute', 'cn' );
|
||||||
checkGet( $test, 'cas/app', 'myCasApp1', 'options/rule', '$uid eq \'dwho\'' );
|
checkGet( $test, 'cas/app', 'myCasApp1', 'options/rule', '$uid eq \'dwho\'' );
|
||||||
checkGet( $test, 'cas/app', 'myCasApp1', 'exportedVars/cn', 'uid' );
|
checkGet( $test, 'cas/app', 'myCasApp1', 'exportedVars/cn', 'uid' );
|
||||||
|
@ -686,17 +688,17 @@ delete $casApp->{options}->{playingPossum};
|
||||||
|
|
||||||
$test = "CasApp - Add should fail on non existing options";
|
$test = "CasApp - Add should fail on non existing options";
|
||||||
$casApp->{confKey} = 'myCasApp2';
|
$casApp->{confKey} = 'myCasApp2';
|
||||||
$casApp->{options}->{service} = [ 'http://mycasapp.skynet.com' ];
|
$casApp->{options}->{service} = ['http://mycasapp.skynet.com'];
|
||||||
$casApp->{options}->{playingPossum} = 'ElephantInTheRoom';
|
$casApp->{options}->{playingPossum} = 'ElephantInTheRoom';
|
||||||
checkAddWithUnknownAttributes( $test, 'cas/app', $casApp );
|
checkAddWithUnknownAttributes( $test, 'cas/app', $casApp );
|
||||||
delete $casApp->{options}->{playingPossum};
|
delete $casApp->{options}->{playingPossum};
|
||||||
|
|
||||||
$test = "CasApp - Add should fail because service host already exists";
|
$test = "CasApp - Add should fail because service host already exists";
|
||||||
$casApp->{options}->{service} = [ 'http://mycasapp.acme.com/ignoredbyissuer' ];
|
$casApp->{options}->{service} = ['http://mycasapp.acme.com/ignoredbyissuer'];
|
||||||
checkAddFailsIfExists( $test, 'cas/app', $casApp );
|
checkAddFailsIfExists( $test, 'cas/app', $casApp );
|
||||||
|
|
||||||
$test = "CasApp - 2nd add should succeed";
|
$test = "CasApp - 2nd add should succeed";
|
||||||
$casApp->{options}->{service} = [ 'http://mycasapp.skynet.com' ];
|
$casApp->{options}->{service} = ['http://mycasapp.skynet.com'];
|
||||||
checkAdd( $test, 'cas/app', $casApp );
|
checkAdd( $test, 'cas/app', $casApp );
|
||||||
|
|
||||||
$test = "CasApp - Update should fail if confKey not found";
|
$test = "CasApp - Update should fail if confKey not found";
|
||||||
|
@ -714,7 +716,7 @@ $test = "CasApp - Replace should fail on non existing or invalid options";
|
||||||
$casApp->{options}->{playingPossum} = 'elephant';
|
$casApp->{options}->{playingPossum} = 'elephant';
|
||||||
checkReplaceWithInvalidAttribute( $test, 'cas/app', 'myCasApp2', $casApp );
|
checkReplaceWithInvalidAttribute( $test, 'cas/app', 'myCasApp2', $casApp );
|
||||||
delete $casApp->{options}->{playingPossum};
|
delete $casApp->{options}->{playingPossum};
|
||||||
$casApp->{options}->{service} = [ "XXX" ];
|
$casApp->{options}->{service} = ["XXX"];
|
||||||
checkReplaceWithInvalidAttribute( $test, 'cas/app', 'myCasApp2', $casApp );
|
checkReplaceWithInvalidAttribute( $test, 'cas/app', 'myCasApp2', $casApp );
|
||||||
|
|
||||||
$test = "CasApp - Replace should fail if service is not an array";
|
$test = "CasApp - Replace should fail if service is not an array";
|
||||||
|
|
|
@ -58,7 +58,7 @@ while (<F>) {
|
||||||
close F;
|
close F;
|
||||||
|
|
||||||
ok( $hstruct = from_json($hstruct), 'struct.json is JSON' );
|
ok( $hstruct = from_json($hstruct), 'struct.json is JSON' );
|
||||||
ok( ref $hstruct eq 'ARRAY', 'struct.json is an array' )
|
ok( ref $hstruct eq 'ARRAY', 'struct.json is an array' )
|
||||||
or print STDERR "Expected: ARRAY, got: " . ( ref $hstruct ) . "\n";
|
or print STDERR "Expected: ARRAY, got: " . ( ref $hstruct ) . "\n";
|
||||||
count(2);
|
count(2);
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ sub checkResult {
|
||||||
like( $key->{private}, qr/BEGIN/, "is PEM formatted" );
|
like( $key->{private}, qr/BEGIN/, "is PEM formatted" );
|
||||||
like( $key->{public}, qr/BEGIN/, "is PEM formatted" );
|
like( $key->{public}, qr/BEGIN/, "is PEM formatted" );
|
||||||
ok( $key->{hash}, "hash is non empty" ) if $expecthash;
|
ok( $key->{hash}, "hash is non empty" ) if $expecthash;
|
||||||
count(1) if $expecthash;
|
count(1) if $expecthash;
|
||||||
count(4);
|
count(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ checkResult($res);
|
||||||
ok(
|
ok(
|
||||||
$res = &client->_post(
|
$res = &client->_post(
|
||||||
'/confs/newCertificate', '', IO::String->new('{"password":"hello"}'),
|
'/confs/newCertificate', '', IO::String->new('{"password":"hello"}'),
|
||||||
'application/json', 20,
|
'application/json', 20,
|
||||||
),
|
),
|
||||||
"Request succeed"
|
"Request succeed"
|
||||||
);
|
);
|
||||||
|
|
|
@ -20,7 +20,7 @@ mkdir 't/sessions';
|
||||||
my ( $res, $resBody );
|
my ( $res, $resBody );
|
||||||
ok( $res = &client->_post( '/confs/', 'cfgNum=1', &body, 'application/json' ),
|
ok( $res = &client->_post( '/confs/', 'cfgNum=1', &body, 'application/json' ),
|
||||||
"Request succeed" );
|
"Request succeed" );
|
||||||
ok( $res->[0] == 200, "Result code is 200" );
|
ok( $res->[0] == 200, "Result code is 200" );
|
||||||
ok( $resBody = from_json( $res->[2]->[0] ), "Result body contains JSON text" );
|
ok( $resBody = from_json( $res->[2]->[0] ), "Result body contains JSON text" );
|
||||||
|
|
||||||
ok( $resBody->{result} == 0, "JSON response contains \"result:0\"" )
|
ok( $resBody->{result} == 0, "JSON response contains \"result:0\"" )
|
||||||
|
@ -36,7 +36,7 @@ count(6);
|
||||||
foreach my $i ( 0 .. 3 ) {
|
foreach my $i ( 0 .. 3 ) {
|
||||||
ok(
|
ok(
|
||||||
$resBody->{details}->{__warnings__}->[$i]->{message} =~
|
$resBody->{details}->{__warnings__}->[$i]->{message} =~
|
||||||
/\b(unprotected|cross-domain-authentication|retries|__badExpressionAssignment__)\b/,
|
/\b(unprotected|cross-domain-authentication|retries|__badExpressionAssignment__)\b/,
|
||||||
"Warning with 'unprotect', 'CDA', 'assignment' or 'retries' found"
|
"Warning with 'unprotect', 'CDA', 'assignment' or 'retries' found"
|
||||||
) or print STDERR Dumper($resBody);
|
) or print STDERR Dumper($resBody);
|
||||||
count(1);
|
count(1);
|
||||||
|
|
|
@ -20,7 +20,7 @@ mkdir 't/sessions';
|
||||||
my ( $res, $resBody );
|
my ( $res, $resBody );
|
||||||
ok( $res = &client->_post( '/confs/', 'cfgNum=1', &body, 'application/json' ),
|
ok( $res = &client->_post( '/confs/', 'cfgNum=1', &body, 'application/json' ),
|
||||||
"Request succeed" );
|
"Request succeed" );
|
||||||
ok( $res->[0] == 200, "Result code is 200" );
|
ok( $res->[0] == 200, "Result code is 200" );
|
||||||
ok( $resBody = from_json( $res->[2]->[0] ), "Result body contains JSON text" );
|
ok( $resBody = from_json( $res->[2]->[0] ), "Result body contains JSON text" );
|
||||||
ok( $resBody->{result} == 1, "JSON response contains \"result:1\"" )
|
ok( $resBody->{result} == 1, "JSON response contains \"result:1\"" )
|
||||||
or print STDERR Dumper($resBody);
|
or print STDERR Dumper($resBody);
|
||||||
|
|
|
@ -16,7 +16,7 @@ unlink 't/conf/lmConf-2.json';
|
||||||
my ( $res, $resBody );
|
my ( $res, $resBody );
|
||||||
ok( $res = &client->_post( '/confs/', 'cfgNum=1', &body, 'application/json' ),
|
ok( $res = &client->_post( '/confs/', 'cfgNum=1', &body, 'application/json' ),
|
||||||
"Request succeed" );
|
"Request succeed" );
|
||||||
ok( $res->[0] == 200, "Result code is 200" );
|
ok( $res->[0] == 200, "Result code is 200" );
|
||||||
ok( $resBody = from_json( $res->[2]->[0] ), "Result body contains JSON text" );
|
ok( $resBody = from_json( $res->[2]->[0] ), "Result body contains JSON text" );
|
||||||
ok( $resBody->{result} == 0, "JSON response contains \"result:0\"" )
|
ok( $resBody->{result} == 0, "JSON response contains \"result:0\"" )
|
||||||
or print STDERR Dumper($res);
|
or print STDERR Dumper($res);
|
||||||
|
|
|
@ -17,7 +17,7 @@ mkdir 't/sessions';
|
||||||
my ( $res, $resBody );
|
my ( $res, $resBody );
|
||||||
ok( $res = &client->_post( '/confs/', 'cfgNum=1', &body, 'application/json' ),
|
ok( $res = &client->_post( '/confs/', 'cfgNum=1', &body, 'application/json' ),
|
||||||
"Request succeed" );
|
"Request succeed" );
|
||||||
ok( $res->[0] == 200, "Result code is 200" );
|
ok( $res->[0] == 200, "Result code is 200" );
|
||||||
ok( $resBody = from_json( $res->[2]->[0] ), "Result body contains JSON text" );
|
ok( $resBody = from_json( $res->[2]->[0] ), "Result body contains JSON text" );
|
||||||
ok( $resBody->{result} == 1, "JSON response contains \"result:1\"" )
|
ok( $resBody->{result} == 1, "JSON response contains \"result:1\"" )
|
||||||
or print STDERR Dumper($res);
|
or print STDERR Dumper($res);
|
||||||
|
|
|
@ -17,7 +17,7 @@ mkdir 't/sessions';
|
||||||
my ( $res, $resBody );
|
my ( $res, $resBody );
|
||||||
ok( $res = &client->_post( '/confs/', 'cfgNum=1', &body, 'application/json' ),
|
ok( $res = &client->_post( '/confs/', 'cfgNum=1', &body, 'application/json' ),
|
||||||
"Request succeed" );
|
"Request succeed" );
|
||||||
ok( $res->[0] == 200, "Result code is 200" );
|
ok( $res->[0] == 200, "Result code is 200" );
|
||||||
ok( $resBody = from_json( $res->[2]->[0] ), "Result body contains JSON text" );
|
ok( $resBody = from_json( $res->[2]->[0] ), "Result body contains JSON text" );
|
||||||
ok( $resBody->{result} == 1, "JSON response contains \"result:1\"" )
|
ok( $resBody->{result} == 1, "JSON response contains \"result:1\"" )
|
||||||
or print STDERR Dumper($res);
|
or print STDERR Dumper($res);
|
||||||
|
|
|
@ -63,7 +63,7 @@ SKIP: {
|
||||||
Lemonldap::NG::Manager::Cli->run(@args);
|
Lemonldap::NG::Manager::Cli->run(@args);
|
||||||
my $res = $dbh->selectrow_hashref(
|
my $res = $dbh->selectrow_hashref(
|
||||||
"SELECT * FROM lmConfig WHERE field='ldapSetPassword'");
|
"SELECT * FROM lmConfig WHERE field='ldapSetPassword'");
|
||||||
ok( $res, 'Key inserted' );
|
ok( $res, 'Key inserted' );
|
||||||
ok( $res and $res->{value} == '0', 'Value is 0' );
|
ok( $res and $res->{value} == '0', 'Value is 0' );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,8 +16,8 @@ sub newSession {
|
||||||
$tmp = Lemonldap::NG::Common::Session->new( {
|
$tmp = Lemonldap::NG::Common::Session->new( {
|
||||||
storageModule => 'Apache::Session::File',
|
storageModule => 'Apache::Session::File',
|
||||||
storageModuleOptions => {
|
storageModuleOptions => {
|
||||||
Directory => 't/sessions',
|
Directory => 't/sessions',
|
||||||
LockDirectory => 't/sessions',
|
LockDirectory => 't/sessions',
|
||||||
generateModule =>
|
generateModule =>
|
||||||
'Lemonldap::NG::Common::Apache::Session::Generate::SHA256',
|
'Lemonldap::NG::Common::Apache::Session::Generate::SHA256',
|
||||||
},
|
},
|
||||||
|
@ -148,7 +148,7 @@ count(5);
|
||||||
foreach (@ids) {
|
foreach (@ids) {
|
||||||
my $res;
|
my $res;
|
||||||
ok( $res = &client->_del("/sessions/global/$_"), "Delete $_" );
|
ok( $res = &client->_del("/sessions/global/$_"), "Delete $_" );
|
||||||
ok( $res->[0] == 200, 'Result code is 200' );
|
ok( $res->[0] == 200, 'Result code is 200' );
|
||||||
ok( from_json( $res->[2]->[0] )->{result} == 1,
|
ok( from_json( $res->[2]->[0] )->{result} == 1,
|
||||||
'Body is JSON and result==1' );
|
'Body is JSON and result==1' );
|
||||||
count(3);
|
count(3);
|
||||||
|
|
|
@ -86,7 +86,7 @@ SKIP: {
|
||||||
$notif = '{"done":1}';
|
$notif = '{"done":1}';
|
||||||
$res = $client->jsonPutResponse(
|
$res = $client->jsonPutResponse(
|
||||||
'notifications/actives/dwho_Test',
|
'notifications/actives/dwho_Test',
|
||||||
'', IO::String->new($notif),
|
'', IO::String->new($notif),
|
||||||
'application/json', length($notif)
|
'application/json', length($notif)
|
||||||
);
|
);
|
||||||
ok( $res->{result} == 1, 'Result = 1' );
|
ok( $res->{result} == 1, 'Result = 1' );
|
||||||
|
|
|
@ -56,7 +56,7 @@ displayTests('actives');
|
||||||
$notif = '{"done":1}';
|
$notif = '{"done":1}';
|
||||||
$res = &client->jsonPutResponse(
|
$res = &client->jsonPutResponse(
|
||||||
'notifications/actives/dwho_Test',
|
'notifications/actives/dwho_Test',
|
||||||
'', IO::String->new($notif),
|
'', IO::String->new($notif),
|
||||||
'application/json', length($notif)
|
'application/json', length($notif)
|
||||||
);
|
);
|
||||||
ok( $res->{result} == 1, 'Result = 1' );
|
ok( $res->{result} == 1, 'Result = 1' );
|
||||||
|
@ -137,7 +137,7 @@ sub displayTests {
|
||||||
) or diag Dumper($res);
|
) or diag Dumper($res);
|
||||||
my $internal_ref = $res->{values}->[0]->{notification};
|
my $internal_ref = $res->{values}->[0]->{notification};
|
||||||
my $ref = $res->{values}->[0]->{reference};
|
my $ref = $res->{values}->[0]->{reference};
|
||||||
$res = &client->jsonResponse( "notifications/$type/$internal_ref" );
|
$res = &client->jsonResponse("notifications/$type/$internal_ref");
|
||||||
ok( $res->{done} eq $internal_ref, 'Internal reference found' )
|
ok( $res->{done} eq $internal_ref, 'Internal reference found' )
|
||||||
or diag Dumper($res);
|
or diag Dumper($res);
|
||||||
ok( $res = eval { from_json( $res->{notifications}->[0] ) },
|
ok( $res = eval { from_json( $res->{notifications}->[0] ) },
|
||||||
|
|
|
@ -16,8 +16,8 @@ sub newSession {
|
||||||
$tmp = Lemonldap::NG::Common::Session->new( {
|
$tmp = Lemonldap::NG::Common::Session->new( {
|
||||||
storageModule => 'Apache::Session::File',
|
storageModule => 'Apache::Session::File',
|
||||||
storageModuleOptions => {
|
storageModuleOptions => {
|
||||||
Directory => 't/sessions',
|
Directory => 't/sessions',
|
||||||
LockDirectory => 't/sessions',
|
LockDirectory => 't/sessions',
|
||||||
generateModule =>
|
generateModule =>
|
||||||
'Lemonldap::NG::Common::Apache::Session::Generate::SHA256',
|
'Lemonldap::NG::Common::Apache::Session::Generate::SHA256',
|
||||||
},
|
},
|
||||||
|
@ -277,7 +277,7 @@ $res = &client->jsonResponse( '/sfa/persistent',
|
||||||
'uid=*&groupBy=substr(uid,0)&U2FCheck=2&TOTPCheck=2&UBKCheck=2' );
|
'uid=*&groupBy=substr(uid,0)&U2FCheck=2&TOTPCheck=2&UBKCheck=2' );
|
||||||
ok( $res->{result} == 1,
|
ok( $res->{result} == 1,
|
||||||
'Search "uid"=* & UBK & TOTP & UBK - Result code = 1' );
|
'Search "uid"=* & UBK & TOTP & UBK - Result code = 1' );
|
||||||
ok( $res->{count} == 1, 'Found 1 result' ) or print STDERR Dumper($res);
|
ok( $res->{count} == 1, 'Found 1 result' ) or print STDERR Dumper($res);
|
||||||
ok( @{ $res->{values} } == 1, 'List 1 result' );
|
ok( @{ $res->{values} } == 1, 'List 1 result' );
|
||||||
ok( $res->{values}->[0]->{value} && $res->{values}->[0]->{value} eq 'd',
|
ok( $res->{values}->[0]->{value} && $res->{values}->[0]->{value} eq 'd',
|
||||||
'Result match "uid=d"' )
|
'Result match "uid=d"' )
|
||||||
|
|
|
@ -18,7 +18,8 @@ sub body {
|
||||||
|
|
||||||
# Test that key value is sent
|
# Test that key value is sent
|
||||||
my $res = &client->jsonResponse('/view/1/portalDisplayOidcConsents');
|
my $res = &client->jsonResponse('/view/1/portalDisplayOidcConsents');
|
||||||
ok( $res->{value} eq '$_oidcConsents && $_oidcConsents =~ /\\w+/', 'Key found' );
|
ok( $res->{value} eq '$_oidcConsents && $_oidcConsents =~ /\\w+/',
|
||||||
|
'Key found' );
|
||||||
count(1);
|
count(1);
|
||||||
|
|
||||||
# Test that hidden key values are NOT sent
|
# Test that hidden key values are NOT sent
|
||||||
|
|
|
@ -38,14 +38,14 @@ my @notManagedAttributes = (
|
||||||
'syslogFacility', 'userLogger', 'logLevel',
|
'syslogFacility', 'userLogger', 'logLevel',
|
||||||
|
|
||||||
# Plugins parameters
|
# Plugins parameters
|
||||||
'notificationsMaxRetrieve', 'persistentSessionAttributes',
|
'notificationsMaxRetrieve', 'persistentSessionAttributes',
|
||||||
|
|
||||||
# PSGI/CGI protection (must be set in lemonldap-ng.ini)
|
# PSGI/CGI protection (must be set in lemonldap-ng.ini)
|
||||||
'protection',
|
'protection',
|
||||||
|
|
||||||
# SecureToken handler
|
# SecureToken handler
|
||||||
'secureTokenAllowOnError', 'secureTokenAttribute', 'secureTokenExpiration',
|
'secureTokenAllowOnError', 'secureTokenAttribute', 'secureTokenExpiration',
|
||||||
'secureTokenHeader', 'secureTokenMemcachedServers', 'secureTokenUrls',
|
'secureTokenHeader', 'secureTokenMemcachedServers', 'secureTokenUrls',
|
||||||
|
|
||||||
# Sessions and OTT storage
|
# Sessions and OTT storage
|
||||||
'configStorage', 'localStorageOptions', 'localStorage',
|
'configStorage', 'localStorageOptions', 'localStorage',
|
||||||
|
@ -157,7 +157,7 @@ sub scanTree {
|
||||||
|
|
||||||
# Nodes must have a title
|
# Nodes must have a title
|
||||||
ok( $name = $leaf->{title}, "Node has a name" );
|
ok( $name = $leaf->{title}, "Node has a name" );
|
||||||
ok( $name =~ /^\w+$/, "Name is a string" );
|
ok( $name =~ /^\w+$/, "Name is a string" );
|
||||||
|
|
||||||
# Nodes must have leafs or subnodes
|
# Nodes must have leafs or subnodes
|
||||||
ok( (
|
ok( (
|
||||||
|
|
|
@ -385,7 +385,8 @@ sub run {
|
||||||
MSG => $self->canUpdateSfa($req) || 'choose2f',
|
MSG => $self->canUpdateSfa($req) || 'choose2f',
|
||||||
ALERT => ( $self->canUpdateSfa($req) ? 'warning' : 'positive' ),
|
ALERT => ( $self->canUpdateSfa($req) ? 'warning' : 'positive' ),
|
||||||
MODULES => [
|
MODULES => [
|
||||||
map { {
|
map {
|
||||||
|
{
|
||||||
CODE => $_->prefix,
|
CODE => $_->prefix,
|
||||||
LOGO => $_->logo,
|
LOGO => $_->logo,
|
||||||
LABEL => $_->label
|
LABEL => $_->label
|
||||||
|
@ -440,7 +441,7 @@ sub _choice {
|
||||||
return $self->p->do(
|
return $self->p->do(
|
||||||
$req,
|
$req,
|
||||||
[
|
[
|
||||||
sub { $res }, 'controlUrl',
|
sub { $res }, 'controlUrl',
|
||||||
'buildCookie', @{ $self->p->endAuth },
|
'buildCookie', @{ $self->p->endAuth },
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
|
@ -180,7 +180,7 @@ sub _registration {
|
||||||
|
|
||||||
if (
|
if (
|
||||||
$self->find2fByKey(
|
$self->find2fByKey(
|
||||||
$req, $req->userData, $self->type,
|
$req, $req->userData, $self->type,
|
||||||
"_credentialId", $credential_id
|
"_credentialId", $credential_id
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
@ -255,8 +255,7 @@ sub authenticate {
|
||||||
sub setAuthSessionInfo {
|
sub setAuthSessionInfo {
|
||||||
my ( $self, $req ) = @_;
|
my ( $self, $req ) = @_;
|
||||||
$req->{sessionInfo}->{authenticationLevel} = $self->conf->{casAuthnLevel};
|
$req->{sessionInfo}->{authenticationLevel} = $self->conf->{casAuthnLevel};
|
||||||
$req->{sessionInfo}->{_casSrv}
|
$req->{sessionInfo}->{_casSrv} = $req->data->{_casSrvCurrent};
|
||||||
= $req->data->{_casSrvCurrent};
|
|
||||||
return PE_OK;
|
return PE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -155,8 +155,7 @@ sub extractFormInfo {
|
||||||
|
|
||||||
$self->logger->debug("Response from GitHub User API: $user_content");
|
$self->logger->debug("Response from GitHub User API: $user_content");
|
||||||
|
|
||||||
eval {
|
eval { $json_hash = from_json( $user_content, { allow_nonref => 1 } ); };
|
||||||
$json_hash = from_json( $user_content, { allow_nonref => 1 } ); };
|
|
||||||
if ($@) {
|
if ($@) {
|
||||||
$self->logger->error("Unable to decode JSON $user_content");
|
$self->logger->error("Unable to decode JSON $user_content");
|
||||||
return PE_ERROR;
|
return PE_ERROR;
|
||||||
|
|
|
@ -33,7 +33,7 @@ has reWebIDWhitelist => ( is => 'rw' );
|
||||||
|
|
||||||
sub init {
|
sub init {
|
||||||
my ($self) = @_;
|
my ($self) = @_;
|
||||||
my @hosts = split /\s+/, $self->{conf}->{webIDWhitelist};
|
my @hosts = split /\s+/, $self->{conf}->{webIDWhitelist};
|
||||||
unless (@hosts) {
|
unless (@hosts) {
|
||||||
$self->error(
|
$self->error(
|
||||||
'WebID white list is empty. Set it in manager, use * to accept all FOAF providers'
|
'WebID white list is empty. Set it in manager, use * to accept all FOAF providers'
|
||||||
|
|
|
@ -90,11 +90,13 @@ sub extractFormInfo {
|
||||||
# 3. If user and oldpassword defined -> password form
|
# 3. If user and oldpassword defined -> password form
|
||||||
elsif ( $defUser and $defOldPassword ) {
|
elsif ( $defUser and $defOldPassword ) {
|
||||||
$res = PE_PASSWORDFORMEMPTY
|
$res = PE_PASSWORDFORMEMPTY
|
||||||
unless ( ( $req->{user} = $req->param('user') )
|
unless (
|
||||||
|
( $req->{user} = $req->param('user') )
|
||||||
&& ( $req->data->{oldpassword} = $req->param('oldpassword') )
|
&& ( $req->data->{oldpassword} = $req->param('oldpassword') )
|
||||||
&& ( $req->data->{newpassword} = $req->param('newpassword') )
|
&& ( $req->data->{newpassword} = $req->param('newpassword') )
|
||||||
&& ( $req->data->{confirmpassword} =
|
&& ( $req->data->{confirmpassword} =
|
||||||
$req->param('confirmpassword') ) );
|
$req->param('confirmpassword') )
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
# If form seems empty
|
# If form seems empty
|
||||||
|
|
|
@ -703,7 +703,7 @@ sub run {
|
||||||
|
|
||||||
# Store data in session
|
# Store data in session
|
||||||
my $code_payload = {
|
my $code_payload = {
|
||||||
code_challenge => $oidc_request->{'code_challenge'},
|
code_challenge => $oidc_request->{'code_challenge'},
|
||||||
code_challenge_method =>
|
code_challenge_method =>
|
||||||
$oidc_request->{'code_challenge_method'},
|
$oidc_request->{'code_challenge_method'},
|
||||||
nonce => $oidc_request->{'nonce'},
|
nonce => $oidc_request->{'nonce'},
|
||||||
|
@ -765,7 +765,7 @@ sub run {
|
||||||
$self->logger->error("Unable to create Access Token");
|
$self->logger->error("Unable to create Access Token");
|
||||||
$self->returnRedirectError( $req,
|
$self->returnRedirectError( $req,
|
||||||
$oidc_request->{'redirect_uri'},
|
$oidc_request->{'redirect_uri'},
|
||||||
"server_error", undef, undef,
|
"server_error", undef, undef,
|
||||||
$oidc_request->{'state'}, 1 );
|
$oidc_request->{'state'}, 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -873,7 +873,7 @@ sub run {
|
||||||
$self->logger->error("Unable to create Access Token");
|
$self->logger->error("Unable to create Access Token");
|
||||||
return $self->returnRedirectError( $req,
|
return $self->returnRedirectError( $req,
|
||||||
$oidc_request->{'redirect_uri'},
|
$oidc_request->{'redirect_uri'},
|
||||||
"server_error", undef, undef,
|
"server_error", undef, undef,
|
||||||
$oidc_request->{'state'}, 1 );
|
$oidc_request->{'state'}, 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1328,7 +1328,7 @@ sub _handlePasswordGrant {
|
||||||
access_token => "$access_token",
|
access_token => "$access_token",
|
||||||
token_type => 'Bearer',
|
token_type => 'Bearer',
|
||||||
expires_in => $expires_in + 0,
|
expires_in => $expires_in + 0,
|
||||||
( ( $scope ne $req_scope ) ? ( scope => "$scope" ) : () ),
|
( ( $scope ne $req_scope ) ? ( scope => "$scope" ) : () ),
|
||||||
( $refresh_token ? ( refresh_token => "$refresh_token" ) : () ),
|
( $refresh_token ? ( refresh_token => "$refresh_token" ) : () ),
|
||||||
( $id_token ? ( id_token => "$id_token" ) : () ),
|
( $id_token ? ( id_token => "$id_token" ) : () ),
|
||||||
};
|
};
|
||||||
|
@ -1526,7 +1526,7 @@ sub _handleAuthorizationCodeGrant {
|
||||||
expires_in => $expires_in + 0,
|
expires_in => $expires_in + 0,
|
||||||
id_token => "$id_token",
|
id_token => "$id_token",
|
||||||
( $refresh_token ? ( refresh_token => "$refresh_token" ) : () ),
|
( $refresh_token ? ( refresh_token => "$refresh_token" ) : () ),
|
||||||
( ( $req_scope ne $scope ) ? ( scope => "$scope" ) : () ),
|
( ( $req_scope ne $scope ) ? ( scope => "$scope" ) : () ),
|
||||||
};
|
};
|
||||||
|
|
||||||
my $cRP = $apacheSession->data->{_oidcConnectedRP} || '';
|
my $cRP = $apacheSession->data->{_oidcConnectedRP} || '';
|
||||||
|
@ -2195,10 +2195,10 @@ sub metadata {
|
||||||
|
|
||||||
# Scopes
|
# Scopes
|
||||||
scopes_supported => [qw/openid profile email address phone/],
|
scopes_supported => [qw/openid profile email address phone/],
|
||||||
response_types_supported => $response_types,
|
response_types_supported => $response_types,
|
||||||
grant_types_supported => $grant_types,
|
grant_types_supported => $grant_types,
|
||||||
acr_values_supported => \@acr,
|
acr_values_supported => \@acr,
|
||||||
subject_types_supported => ["public"],
|
subject_types_supported => ["public"],
|
||||||
token_endpoint_auth_methods_supported =>
|
token_endpoint_auth_methods_supported =>
|
||||||
[qw/client_secret_post client_secret_basic/],
|
[qw/client_secret_post client_secret_basic/],
|
||||||
introspection_endpoint_auth_methods_supported =>
|
introspection_endpoint_auth_methods_supported =>
|
||||||
|
@ -2380,9 +2380,9 @@ sub _generateIDToken {
|
||||||
exp => $id_token_exp, # expiration
|
exp => $id_token_exp, # expiration
|
||||||
iat => time, # Issued time
|
iat => time, # Issued time
|
||||||
auth_time => $sessionInfo->{_lastAuthnUTime}, # Authentication time
|
auth_time => $sessionInfo->{_lastAuthnUTime}, # Authentication time
|
||||||
acr => $id_token_acr, # Authentication Context Class Reference
|
acr => $id_token_acr, # Authentication Context Class Reference
|
||||||
azp => $client_id, # Authorized party
|
azp => $client_id, # Authorized party
|
||||||
# TODO amr
|
# TODO amr
|
||||||
};
|
};
|
||||||
|
|
||||||
for ( keys %{$extra_claims} ) {
|
for ( keys %{$extra_claims} ) {
|
||||||
|
|
|
@ -281,7 +281,7 @@ sub run {
|
||||||
$req->data->{_proxiedRequest} = $request;
|
$req->data->{_proxiedRequest} = $request;
|
||||||
$req->data->{_proxiedMethod} = $method;
|
$req->data->{_proxiedMethod} = $method;
|
||||||
$req->data->{_proxiedRelayState} = $relaystate,
|
$req->data->{_proxiedRelayState} = $relaystate,
|
||||||
$req->data->{_proxiedArtifact} = $artifact;
|
$req->data->{_proxiedArtifact} = $artifact;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Process the request or use IDP initiated mode
|
# Process the request or use IDP initiated mode
|
||||||
|
@ -597,8 +597,8 @@ sub run {
|
||||||
# Get session key associated with NameIDFormat
|
# Get session key associated with NameIDFormat
|
||||||
# Not for unspecified, transient, persistent, entity, encrypted
|
# Not for unspecified, transient, persistent, entity, encrypted
|
||||||
my $nameIDFormatConfiguration = {
|
my $nameIDFormatConfiguration = {
|
||||||
$self->getNameIDFormat("email") => 'samlNameIDFormatMapEmail',
|
$self->getNameIDFormat("email") => 'samlNameIDFormatMapEmail',
|
||||||
$self->getNameIDFormat("x509") => 'samlNameIDFormatMapX509',
|
$self->getNameIDFormat("x509") => 'samlNameIDFormatMapX509',
|
||||||
$self->getNameIDFormat("windows") =>
|
$self->getNameIDFormat("windows") =>
|
||||||
'samlNameIDFormatMapWindows',
|
'samlNameIDFormatMapWindows',
|
||||||
$self->getNameIDFormat("kerberos") =>
|
$self->getNameIDFormat("kerberos") =>
|
||||||
|
|
|
@ -9,10 +9,10 @@ with 'Lemonldap::NG::Portal::Lib::OverConf';
|
||||||
|
|
||||||
our $VERSION = '2.0.14';
|
our $VERSION = '2.0.14';
|
||||||
|
|
||||||
has modules => ( is => 'rw', default => sub { {} } );
|
has modules => ( is => 'rw', default => sub { {} } );
|
||||||
has rules => ( is => 'rw', default => sub { {} } );
|
has rules => ( is => 'rw', default => sub { {} } );
|
||||||
has type => ( is => 'rw' );
|
has type => ( is => 'rw' );
|
||||||
has catch => ( is => 'rw', default => sub { {} } );
|
has catch => ( is => 'rw', default => sub { {} } );
|
||||||
has sessionKey => ( is => 'ro', default => '_choice' );
|
has sessionKey => ( is => 'ro', default => '_choice' );
|
||||||
|
|
||||||
my $_choiceRules;
|
my $_choiceRules;
|
||||||
|
|
|
@ -72,8 +72,8 @@ has findUserFilter => (
|
||||||
is => 'ro',
|
is => 'ro',
|
||||||
lazy => 1,
|
lazy => 1,
|
||||||
builder => sub {
|
builder => sub {
|
||||||
$_[0]->conf->{AuthLDAPFilter} ||
|
$_[0]->conf->{AuthLDAPFilter}
|
||||||
$_[0]->conf->{LDAPFilter}
|
|| $_[0]->conf->{LDAPFilter}
|
||||||
|| '(&(uid=$user)(objectClass=inetOrgPerson))';
|
|| '(&(uid=$user)(objectClass=inetOrgPerson))';
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -52,7 +52,7 @@ sub new {
|
||||||
( $conf->{ldapVerify} ? ( verify => $conf->{ldapVerify} ) : () ),
|
( $conf->{ldapVerify} ? ( verify => $conf->{ldapVerify} ) : () ),
|
||||||
);
|
);
|
||||||
unless ($self) {
|
unless ($self) {
|
||||||
$portal->logger->error("LDAP initialization error: ". $@);
|
$portal->logger->error( "LDAP initialization error: " . $@ );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
elsif ( $Net::LDAP::VERSION < '0.64' ) {
|
elsif ( $Net::LDAP::VERSION < '0.64' ) {
|
||||||
|
|
|
@ -69,7 +69,7 @@ sub checkForNotifications {
|
||||||
}
|
}
|
||||||
|
|
||||||
# Transform notifications
|
# Transform notifications
|
||||||
my $i = 0; # Files count
|
my $i = 0; # Files count
|
||||||
my $now = strftime "%Y-%m-%d", localtime;
|
my $now = strftime "%Y-%m-%d", localtime;
|
||||||
|
|
||||||
foreach my $file ( values %$notifs ) {
|
foreach my $file ( values %$notifs ) {
|
||||||
|
|
|
@ -29,7 +29,7 @@ use constant PROFILE => [
|
||||||
qw/name family_name given_name middle_name nickname preferred_username
|
qw/name family_name given_name middle_name nickname preferred_username
|
||||||
profile picture website gender birthdate zoneinfo locale updated_at/
|
profile picture website gender birthdate zoneinfo locale updated_at/
|
||||||
];
|
];
|
||||||
use constant EMAIL => [qw/email email_verified/];
|
use constant EMAIL => [qw/email email_verified/];
|
||||||
use constant ADDRESS =>
|
use constant ADDRESS =>
|
||||||
[qw/formatted street_address locality region postal_code country/];
|
[qw/formatted street_address locality region postal_code country/];
|
||||||
use constant PHONE => [qw/phone_number phone_number_verified/];
|
use constant PHONE => [qw/phone_number phone_number_verified/];
|
||||||
|
@ -1031,7 +1031,7 @@ sub storeState {
|
||||||
# check if there are data to store
|
# check if there are data to store
|
||||||
my $infos;
|
my $infos;
|
||||||
foreach (@data) {
|
foreach (@data) {
|
||||||
$infos->{$_} = $req->{$_} if $req->{$_};
|
$infos->{$_} = $req->{$_} if $req->{$_};
|
||||||
$infos->{"data_$_"} = $req->data->{$_} if $req->data->{$_};
|
$infos->{"data_$_"} = $req->data->{$_} if $req->data->{$_};
|
||||||
}
|
}
|
||||||
return unless ($infos);
|
return unless ($infos);
|
||||||
|
|
|
@ -59,7 +59,7 @@ sub checkRemoteId {
|
||||||
|
|
||||||
# Trying to recover session from global session storage
|
# Trying to recover session from global session storage
|
||||||
my $remoteSession = Lemonldap::NG::Common::Session->new( {
|
my $remoteSession = Lemonldap::NG::Common::Session->new( {
|
||||||
storageModule => $self->conf->{remoteGlobalStorage},
|
storageModule => $self->conf->{remoteGlobalStorage},
|
||||||
storageModuleOptions =>
|
storageModuleOptions =>
|
||||||
$self->conf->{remoteGlobalStorageOptions},
|
$self->conf->{remoteGlobalStorageOptions},
|
||||||
cacheModule => $self->conf->{localSessionStorage},
|
cacheModule => $self->conf->{localSessionStorage},
|
||||||
|
|
|
@ -1888,7 +1888,8 @@ sub resolveArtifact {
|
||||||
$self->logger->debug("Get message $message");
|
$self->logger->debug("Get message $message");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$self->logger->error("Error while sending message: ".$soap_answer->status_line);
|
$self->logger->error(
|
||||||
|
"Error while sending message: " . $soap_answer->status_line );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3039,7 +3040,7 @@ sub createAttributeValue {
|
||||||
|
|
||||||
# Decode UTF-8
|
# Decode UTF-8
|
||||||
$self->logger->debug("Decode UTF8 value $value") if $force_utf8;
|
$self->logger->debug("Decode UTF8 value $value") if $force_utf8;
|
||||||
$value = decode( "utf8", $value ) if $force_utf8;
|
$value = decode( "utf8", $value ) if $force_utf8;
|
||||||
$self->logger->debug("Create attribute value $value");
|
$self->logger->debug("Create attribute value $value");
|
||||||
|
|
||||||
# SAML2 attribute value
|
# SAML2 attribute value
|
||||||
|
|
|
@ -47,7 +47,7 @@ sub loadMailTemplate {
|
||||||
my ( $self, $req, $name, %prm ) = @_;
|
my ( $self, $req, $name, %prm ) = @_;
|
||||||
|
|
||||||
# HTML::Template cache interferes with email translation (#1897)
|
# HTML::Template cache interferes with email translation (#1897)
|
||||||
$prm{cache} = 0 unless defined $prm{cache};
|
$prm{cache} = 0 unless defined $prm{cache};
|
||||||
$prm{params}->{STATIC_PREFIX} = $self->p->staticPrefix;
|
$prm{params}->{STATIC_PREFIX} = $self->p->staticPrefix;
|
||||||
$prm{params}->{MAIN_LOGO} = $self->conf->{portalMainLogo};
|
$prm{params}->{MAIN_LOGO} = $self->conf->{portalMainLogo};
|
||||||
my %extra =
|
my %extra =
|
||||||
|
|
|
@ -10,8 +10,8 @@ use Carp;
|
||||||
|
|
||||||
our $VERSION = '2.0.12';
|
our $VERSION = '2.0.12';
|
||||||
|
|
||||||
has rp_id => ( is => 'rw', lazy => 1, builder => "_build_rp_id" );
|
has rp_id => ( is => 'rw', lazy => 1, builder => "_build_rp_id" );
|
||||||
has origin => ( is => 'rw', lazy => 1, builder => "_build_origin" );
|
has origin => ( is => 'rw', lazy => 1, builder => "_build_origin" );
|
||||||
has type => ( is => 'ro', default => 'WebAuthn' );
|
has type => ( is => 'ro', default => 'WebAuthn' );
|
||||||
has verifier => ( is => 'rw', lazy => 1, builder => "_build_verifier" );
|
has verifier => ( is => 'rw', lazy => 1, builder => "_build_verifier" );
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ sub authCancel { '_authCancel' }
|
||||||
sub _betweenAuthAndData { _wrapEntryPoint( @_, 'betweenAuthAndData' ); }
|
sub _betweenAuthAndData { _wrapEntryPoint( @_, 'betweenAuthAndData' ); }
|
||||||
sub _afterData { _wrapEntryPoint( @_, 'afterData' ); }
|
sub _afterData { _wrapEntryPoint( @_, 'afterData' ); }
|
||||||
sub _endAuth { _wrapEntryPoint( @_, 'endAuth' ); }
|
sub _endAuth { _wrapEntryPoint( @_, 'endAuth' ); }
|
||||||
sub _forAuthUser { _wrapEntryPoint( @_, 'forAuthUser', 1 ); }
|
sub _forAuthUser { _wrapEntryPoint( @_, 'forAuthUser', 1 ); }
|
||||||
sub _beforeLogout { _wrapEntryPoint( @_, 'beforeLogout', 1 ); }
|
sub _beforeLogout { _wrapEntryPoint( @_, 'beforeLogout', 1 ); }
|
||||||
sub _authCancel { _wrapEntryPoint( @_, 'authCancel' ); }
|
sub _authCancel { _wrapEntryPoint( @_, 'authCancel' ); }
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,6 @@ extends 'Lemonldap::NG::Portal::Main::Plugin';
|
||||||
|
|
||||||
has authnLevel => ( is => 'rw' );
|
has authnLevel => ( is => 'rw' );
|
||||||
|
|
||||||
sub stop {0}
|
sub stop { 0 }
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|
|
@ -7,7 +7,7 @@ use Exporter 'import';
|
||||||
our $VERSION = '2.0.14';
|
our $VERSION = '2.0.14';
|
||||||
|
|
||||||
use constant HANDLER => 'Lemonldap::NG::Handler::PSGI::Main';
|
use constant HANDLER => 'Lemonldap::NG::Handler::PSGI::Main';
|
||||||
use constant URIRE =>
|
use constant URIRE =>
|
||||||
qr{(((?^:https?))://((?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)|(?:[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+)))(?::((?:[0-9]*)))?(/(((?:(?:(?:(?:[a-zA-Z0-9\-_.!~*'():\@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():\@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*)(?:/(?:(?:(?:[a-zA-Z0-9\-_.!~*'():\@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():\@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*))*))(?:[?]((?:(?:[;/?:\@&=+\$,a-zA-Z0-9\-_.!~*'()]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)))?))?)};
|
qr{(((?^:https?))://((?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-9]*[a-zA-Z0-9]|[a-zA-Z])[.]?)|(?:[0-9]+[.][0-9]+[.][0-9]+[.][0-9]+)))(?::((?:[0-9]*)))?(/(((?:(?:(?:(?:[a-zA-Z0-9\-_.!~*'():\@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():\@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*)(?:/(?:(?:(?:[a-zA-Z0-9\-_.!~*'():\@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)(?:;(?:(?:[a-zA-Z0-9\-_.!~*'():\@&=+\$,]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*))*))*))(?:[?]((?:(?:[;/?:\@&=+\$,a-zA-Z0-9\-_.!~*'()]+|(?:%[a-fA-F0-9][a-fA-F0-9]))*)))?))?)};
|
||||||
use constant {
|
use constant {
|
||||||
PE_IDPCHOICE => -5,
|
PE_IDPCHOICE => -5,
|
||||||
|
|
|
@ -29,7 +29,8 @@ sub displayInit {
|
||||||
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 || 'Unable to compile rule' );
|
. HANDLER->tsv->{jail}->error
|
||||||
|
|| 'Unable to compile rule' );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,14 +38,14 @@ sub displayInit {
|
||||||
HANDLER->substitute( $self->conf->{portalRequireOldPassword} ) );
|
HANDLER->substitute( $self->conf->{portalRequireOldPassword} ) );
|
||||||
unless ($rule) {
|
unless ($rule) {
|
||||||
my $error = HANDLER->tsv->{jail}->error || 'Unable to compile rule';
|
my $error = HANDLER->tsv->{jail}->error || 'Unable to compile rule';
|
||||||
$self->logger->error( "Bad requireOldPwd rule: $error" );
|
$self->logger->error("Bad requireOldPwd rule: $error");
|
||||||
}
|
}
|
||||||
$self->requireOldPwd($rule);
|
$self->requireOldPwd($rule);
|
||||||
$rule =
|
$rule =
|
||||||
HANDLER->buildSub( HANDLER->substitute( $self->conf->{stayConnected} ) );
|
HANDLER->buildSub( HANDLER->substitute( $self->conf->{stayConnected} ) );
|
||||||
unless ($rule) {
|
unless ($rule) {
|
||||||
my $error = HANDLER->tsv->{jail}->error || 'Unable to compile rule';
|
my $error = HANDLER->tsv->{jail}->error || 'Unable to compile rule';
|
||||||
$self->logger->error( "Bad stayConnected rule: $error" );
|
$self->logger->error("Bad stayConnected rule: $error");
|
||||||
}
|
}
|
||||||
$self->stayConnected($rule);
|
$self->stayConnected($rule);
|
||||||
|
|
||||||
|
|
|
@ -128,9 +128,9 @@ sub init {
|
||||||
|
|
||||||
# Purge loaded module list
|
# Purge loaded module list
|
||||||
$self->loadedModules( {} );
|
$self->loadedModules( {} );
|
||||||
$self->afterSub( {} );
|
$self->afterSub( {} );
|
||||||
$self->aroundSub( {} );
|
$self->aroundSub( {} );
|
||||||
$self->hook( {} );
|
$self->hook( {} );
|
||||||
|
|
||||||
# Insert `reloadConf` in handler reload stack
|
# Insert `reloadConf` in handler reload stack
|
||||||
Lemonldap::NG::Handler::Main->onReload( $self, 'reloadConf' );
|
Lemonldap::NG::Handler::Main->onReload( $self, 'reloadConf' );
|
||||||
|
@ -228,10 +228,10 @@ sub reloadConf {
|
||||||
foreach ( qw(_macros _groups), @entryPoints ) {
|
foreach ( qw(_macros _groups), @entryPoints ) {
|
||||||
$self->{$_} = [];
|
$self->{$_} = [];
|
||||||
}
|
}
|
||||||
$self->afterSub( {} );
|
$self->afterSub( {} );
|
||||||
$self->aroundSub( {} );
|
$self->aroundSub( {} );
|
||||||
$self->spRules( {} );
|
$self->spRules( {} );
|
||||||
$self->hook( {} );
|
$self->hook( {} );
|
||||||
|
|
||||||
# Plugin history fields
|
# Plugin history fields
|
||||||
$self->pluginSessionDataToRemember( {} );
|
$self->pluginSessionDataToRemember( {} );
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue