This commit is contained in:
Yadd 2022-02-16 17:43:29 +01:00
parent c0472d41db
commit b88a72c267
245 changed files with 1173 additions and 1101 deletions

View File

@ -1176,15 +1176,14 @@ test-diff:
done
tidy: clean
@if perltidy -v|grep v20181120 >/dev/null; then \
find lemon*/ -type f \( -name '*.pm' -or -name '*.pl' -or -name '*.fcgi' -or -name '*.t' \) -print -exec perltidy -se -b {} \; ; \
else echo "Wrong perltidy version, please install Perl::Tidy@20181120" ; exit 1 ;\
@if perltidy -v|grep v20210717 >/dev/null; then \
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; \
else echo "Wrong perltidy version, please install Perl::Tidy@20210717" ; exit 1 ;\
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
$(MAKE) json

View File

@ -63,10 +63,11 @@ sub testEmail {
eval {
Lemonldap::NG::Common::EmailTransport::sendTestMail( $conf, $dest );
};
my $error = $@;
my $error = $@;
if ($error) {
die $error;
} else {
}
else {
print STDERR "Test email successfully sent to $dest\n";
}
}

View File

@ -190,7 +190,7 @@ sub getConf {
eval { $r = $self->{refLocalStorage}->get('conf') }
if ( $> and not $args->{noCache} );
$msg .= "Warn: $@" if ($@);
if ( ref($r)
and $r->{cfgNum}
and $args->{cfgNum}

View File

@ -7,9 +7,9 @@ use Mouse;
use Lemonldap::NG::Common::Conf;
has '_confAcc' => ( is => 'rw', isa => 'Lemonldap::NG::Common::Conf' );
has 'configStorage' => ( is => 'rw', isa => 'HashRef', default => sub { {} } );
has 'currentConf' => ( is => 'rw', required => 1, default => sub { {} } );
has 'protection' => ( is => 'rw', isa => 'Str', default => 'manager' );
has 'configStorage' => ( is => 'rw', isa => 'HashRef', default => sub { {} } );
has 'currentConf' => ( is => 'rw', required => 1, default => sub { {} } );
has 'protection' => ( is => 'rw', isa => 'Str', default => 'manager' );
our $VERSION = '2.0.11';

View File

@ -194,8 +194,8 @@ sub store {
$operation = $self->ldap->add(
$confDN,
attrs => [
objectClass => [ 'top', $self->{ldapObjectClass} ],
$self->{ldapAttributeId} => $confName,
objectClass => [ 'top', $self->{ldapObjectClass} ],
$self->{ldapAttributeId} => $confName,
$self->{ldapAttributeContent} => \@confValues,
]
);

View File

@ -35,7 +35,7 @@ sub load {
cfgNum => 1,
cfgDate => time,
cfgAuthor => 'LLNG Team',
cfgLog =>
cfgLog =>
q"Do not edit this configuration, Null backend uses lemonldap-ng.ini values only",
};
}

View File

@ -19,7 +19,7 @@ sub store {
$req = $self->_dbh->prepare(
"INSERT INTO $self->{dbiTable} (cfgNum,field,value) VALUES (?,?,?)");
_delete($self,$cfgNum) if $lastCfg == $cfgNum;
_delete( $self, $cfgNum ) if $lastCfg == $cfgNum;
unless ($req) {
$self->logError;
return UNKNOWN_ERROR;

View File

@ -36,7 +36,8 @@ sub available {
my $sth =
$self->_dbh->prepare( "SELECT DISTINCT cfgNum from "
. $self->{dbiTable}
. " order by cfgNum" ) or $self->logError;
. " order by cfgNum" )
or $self->logError;
$sth->execute() or $self->logError;
my @conf;
while ( my @row = $sth->fetchrow_array ) {
@ -105,8 +106,8 @@ sub unlock {
sub delete {
my ( $self, $cfgNum ) = @_;
my $req =
$self->_dbh->prepare("DELETE FROM $self->{dbiTable} WHERE cfgNum=?")
or $self->logError;
$self->_dbh->prepare("DELETE FROM $self->{dbiTable} WHERE cfgNum=?")
or $self->logError;
my $res = $req->execute($cfgNum) or $self->logError;
$Lemonldap::NG::Common::Conf::msg .=
"Unable to find conf $cfgNum (" . $self->_dbh->errstr . ")"

View File

@ -17,7 +17,7 @@ sub defaultValues {
},
'authChoiceParam' => 'lmAuth',
'authentication' => 'Demo',
'available2F' =>
'available2F' =>
'UTOTP,TOTP,U2F,REST,Mail2F,Ext2F,WebAuthn,Yubikey,Radius',
'available2FSelfRegistration' => 'TOTP,U2F,WebAuthn,Yubikey',
'bruteForceProtectionLockTimes' => '15, 30, 60, 300, 600',
@ -102,7 +102,7 @@ sub defaultValues {
'globalLogoutTimer' => 1,
'globalStorage' => 'Apache::Session::File',
'globalStorageOptions' => {
'Directory' => '/var/lib/lemonldap-ng/sessions/',
'Directory' => '/var/lib/lemonldap-ng/sessions/',
'generateModule' =>
'Lemonldap::NG::Common::Apache::Session::Generate::SHA256',
'LockDirectory' => '/var/lib/lemonldap-ng/sessions/lock/'
@ -175,20 +175,20 @@ sub defaultValues {
'locationRules' => {
'default' => 'deny'
},
'logoutServices' => {},
'macros' => {},
'mail2fActivation' => 0,
'mail2fCodeRegex' => '\\d{6}',
'mailCharset' => 'utf-8',
'mailFrom' => 'noreply@example.com',
'mailSessionKey' => 'mail',
'mailTimeout' => 0,
'mailUrl' => 'http://auth.example.com/resetpwd',
'managerDn' => '',
'managerPassword' => '',
'max2FDevices' => 10,
'max2FDevicesNameLength' => 20,
'multiValuesSeparator' => '; ',
'logoutServices' => {},
'macros' => {},
'mail2fActivation' => 0,
'mail2fCodeRegex' => '\\d{6}',
'mailCharset' => 'utf-8',
'mailFrom' => 'noreply@example.com',
'mailSessionKey' => 'mail',
'mailTimeout' => 0,
'mailUrl' => 'http://auth.example.com/resetpwd',
'managerDn' => '',
'managerPassword' => '',
'max2FDevices' => 10,
'max2FDevicesNameLength' => 20,
'multiValuesSeparator' => '; ',
'mySessionAuthorizedRWKeys' =>
[ '_appsListOrder', '_oidcConnectedRP', '_oidcConsents' ],
'newLocationWarningLocationAttribute' => 'ipAddr',
@ -196,7 +196,7 @@ sub defaultValues {
'newLocationWarningMaxValues' => '0',
'notificationDefaultCond' => '',
'notificationServerPOST' => 1,
'notificationServerSentAttributes' =>
'notificationServerSentAttributes' =>
'uid reference date title subtitle text check',
'notificationsMaxRetrieve' => 3,
'notificationStorage' => 'File',
@ -250,7 +250,7 @@ sub defaultValues {
'passwordPolicyMinUpper' => 0,
'passwordPolicySpecialChar' => '__ALL__',
'passwordResetAllowedRetries' => 3,
'persistentSessionAttributes' =>
'persistentSessionAttributes' =>
'_loginHistory _2fDevices notification_',
'port' => -1,
'portal' => 'http://auth.example.com/',
@ -261,7 +261,7 @@ sub defaultValues {
'portalDisplayGeneratePassword' => 1,
'portalDisplayLoginHistory' => 1,
'portalDisplayLogout' => 1,
'portalDisplayOidcConsents' =>
'portalDisplayOidcConsents' =>
'$_oidcConsents && $_oidcConsents =~ /\\w+/',
'portalDisplayRefreshMyRights' => 1,
'portalDisplayRegister' => 1,
@ -289,11 +289,11 @@ sub defaultValues {
'http://auth.example.com/Lemonldap/NG/Common/PSGI/SOAPService',
'proxy' => 'http://auth.example.com/sessions'
},
'requireToken' => 1,
'rest2fActivation' => 0,
'restAuthnLevel' => 2,
'restClockTolerance' => 15,
'sameSite' => '',
'requireToken' => 1,
'rest2fActivation' => 0,
'restAuthnLevel' => 2,
'restClockTolerance' => 15,
'sameSite' => '',
'samlAttributeAuthorityDescriptorAttributeServiceSOAP' =>
'urn:oasis:names:tc:SAML:2.0:bindings:SOAP;#PORTAL#/saml/AA/SOAP;',
'samlAuthnContextMapKerberos' => 4,
@ -333,7 +333,7 @@ sub defaultValues {
'0;1;urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact;#PORTAL#/saml/proxySingleSignOnArtifact',
'samlSPSSODescriptorAssertionConsumerServiceHTTPPost' =>
'1;0;urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST;#PORTAL#/saml/proxySingleSignOnPost',
'samlSPSSODescriptorAuthnRequestsSigned' => 1,
'samlSPSSODescriptorAuthnRequestsSigned' => 1,
'samlSPSSODescriptorSingleLogoutServiceHTTPPost' =>
'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST;#PORTAL#/saml/proxySingleLogout;#PORTAL#/saml/proxySingleLogoutReturn',
'samlSPSSODescriptorSingleLogoutServiceHTTPRedirect' =>
@ -345,7 +345,7 @@ sub defaultValues {
'sfEngine' => '::2F::Engines::Default',
'sfManagerRule' => 1,
'sfRemovedMsgRule' => 0,
'sfRemovedNotifMsg' =>
'sfRemovedNotifMsg' =>
'_removedSF_ expired second factor(s) has/have been removed (_nameSF_)!',
'sfRemovedNotifRef' => 'RemoveSF',
'sfRemovedNotifTitle' => 'Second factor notification',

View File

@ -394,16 +394,17 @@ sub _oidcMetaDataNodes {
my ( $id, $resp ) = ( 1, [] );
# Handle RP Attributes
if ($query eq "oidcRPMetaDataExportedVars") {
if ( $query eq "oidcRPMetaDataExportedVars" ) {
my $pk = eval { $self->getConfKey( $req, $query )->{$partner} } // {};
return $self->sendError( $req, undef, 400 ) if ( $req->error );
foreach my $h ( sort keys %$pk ) {
# Set default values for type and array
my $data = [ split /;/, $pk->{$h} ];
unless ( $data->[1]) {
unless ( $data->[1] ) {
$data->[1] = "string";
}
unless ( $data->[2]) {
unless ( $data->[2] ) {
$data->[2] = "auto";
}
push @$resp,
@ -416,6 +417,7 @@ sub _oidcMetaDataNodes {
}
return $self->sendJSONresponse( $req, $resp );
}
# Return all exported attributes if asked
elsif ( $query =~
/^(?:oidc${type}MetaDataExportedVars|oidcRPMetaDataOptionsExtraClaims|oidcRPMetaDataMacros|oidcRPMetaDataScopeRules)$/
@ -733,9 +735,9 @@ sub combModules {
my $res = [];
foreach my $mod ( keys %$val ) {
my $tmp;
$tmp->{title} = $mod;
$tmp->{id} = "combModules/$mod";
$tmp->{type} = 'cmbModule';
$tmp->{title} = $mod;
$tmp->{id} = "combModules/$mod";
$tmp->{type} = 'cmbModule';
$tmp->{data}->{$_} = $val->{$mod}->{$_} foreach (qw(type for));
my $over = $val->{$mod}->{over} // {};
$tmp->{data}->{over} = [ map { [ $_, $over->{$_} ] } keys %$over ];
@ -809,8 +811,8 @@ sub metadata {
}
# Find next and previous conf
my @a = $self->confAcc->available;
my $id = -1;
my @a = $self->confAcc->available;
my $id = -1;
my ($ind) = map { $id++; $_ == $res->{cfgNum} ? ($id) : () } @a;
if ($ind) { $res->{prev} = $a[ $ind - 1 ]; }
if ( defined $ind and $ind < $#a ) {

View File

@ -26,7 +26,7 @@ sub serviceToXML {
my ( $self, $conf, $type ) = @_;
seek DATA, $dataStart, 0;
my $s = join '', <DATA>;
my $s = join '', <DATA>;
my $template = HTML::Template->new(
scalarref => \$s,
die_on_bad_params => 0,

View File

@ -95,7 +95,7 @@ sub configTest {
}
sub sendTestMail {
my ($conf, $dest) = @_;
my ( $conf, $dest ) = @_;
my $transport = Lemonldap::NG::Common::EmailTransport->new($conf);
my $message = MIME::Entity->build(
From => $conf->{mailFrom},
@ -110,7 +110,7 @@ sub sendTestMail {
# Send the mail
eval { sendmail( $message->stringify, { transport => $transport } ); };
if ($@) {
my $error = ( $@->isa('Throwable::Error') ? $@->message : $@ );
my $error = ( $@->isa('Throwable::Error') ? $@->message : $@ );
die $error;
}
}

View File

@ -4,7 +4,7 @@ use strict;
use base 'Exporter';
our $VERSION = '2.0.10';
our @EXPORT = qw(&isIPv6 &net6 &expand6);
our @EXPORT = qw(&isIPv6 &net6 &expand6);
sub isIPv6 {
my ($ip) = @_;

View File

@ -58,12 +58,12 @@ sub new {
}
sub setRequestObj {
my ($self, $req) = @_;
my ( $self, $req ) = @_;
Log::Log4perl::MDC->put( "req", $req );
}
sub clearRequestObj {
my ($self, $req) = @_;
my ( $self, $req ) = @_;
my $text = Log::Log4perl::MDC->remove();
}

View File

@ -13,9 +13,9 @@ use Sentry::Raven;
our $VERSION = '2.0.14';
sub new {
my $self = bless {}, shift;
my $self = bless {}, shift;
my ($conf) = @_;
my $show = 1;
my $show = 1;
$self->{raven} = Sentry::Raven->new( sentry_dsn => $conf->{sentryDsn} );
foreach (qw(error warn notice info debug)) {
my $rl = $_;

View File

@ -356,7 +356,8 @@ sub _logAndHandle {
if ( ref( $self->logger ) and $self->logger->can('setRequestObj') ) {
$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);
}
@ -367,7 +368,9 @@ sub _logAndHandle {
if ( ref( $self->logger ) and $self->logger->can('clearRequestObj') ) {
$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);
}

View File

@ -27,7 +27,7 @@ sub _get {
'REQUEST_URI' => $path . ( $query ? "?$query" : '' ),
'SERVER_PORT' => '8002',
'SERVER_PROTOCOL' => 'HTTP/1.1',
'HTTP_USER_AGENT' =>
'HTTP_USER_AGENT' =>
'Mozilla/5.0 (VAX-4000; rv:36.0) Gecko/20350101 Firefox',
'REMOTE_ADDR' => '127.0.0.1',
'HTTP_HOST' => '127.0.0.1:8002'
@ -52,7 +52,7 @@ sub _post {
'REQUEST_URI' => $path . ( $query ? "?$query" : '' ),
'SERVER_PORT' => '8002',
'SERVER_PROTOCOL' => 'HTTP/1.1',
'HTTP_USER_AGENT' =>
'HTTP_USER_AGENT' =>
'Mozilla/5.0 (VAX-4000; rv:36.0) Gecko/20350101 Firefox',
'REMOTE_ADDR' => '127.0.0.1',
'HTTP_HOST' => '127.0.0.1:8002',
@ -81,7 +81,7 @@ sub _put {
'REQUEST_URI' => $path . ( $query ? "?$query" : '' ),
'SERVER_PORT' => '8002',
'SERVER_PROTOCOL' => 'HTTP/1.1',
'HTTP_USER_AGENT' =>
'HTTP_USER_AGENT' =>
'Mozilla/5.0 (VAX-4000; rv:36.0) Gecko/20350101 Firefox',
'REMOTE_ADDR' => '127.0.0.1',
'HTTP_HOST' => '127.0.0.1:8002',
@ -110,7 +110,7 @@ sub _patch {
'REQUEST_URI' => $path . ( $query ? "?$query" : '' ),
'SERVER_PORT' => '8002',
'SERVER_PROTOCOL' => 'HTTP/1.1',
'HTTP_USER_AGENT' =>
'HTTP_USER_AGENT' =>
'Mozilla/5.0 (VAX-4000; rv:36.0) Gecko/20350101 Firefox',
'REMOTE_ADDR' => '127.0.0.1',
'HTTP_HOST' => '127.0.0.1:8002',
@ -137,7 +137,7 @@ sub _del {
'REQUEST_URI' => $path . ( $query ? "?$query" : '' ),
'SERVER_PORT' => '8002',
'SERVER_PROTOCOL' => 'HTTP/1.1',
'HTTP_USER_AGENT' =>
'HTTP_USER_AGENT' =>
'Mozilla/5.0 (VAX-4000; rv:36.0) Gecko/20350101 Firefox',
'REMOTE_ADDR' => '127.0.0.1',
'HTTP_HOST' => '127.0.0.1:8002',

View File

@ -48,8 +48,7 @@ sub userData {
return $self->{userData}
|| {
( $Lemonldap::NG::Handler::Main::tsv->{whatToTrace}
|| '_whatToTrace' ) => $self->{user},
};
|| '_whatToTrace' ) => $self->{user}, };
}
sub respHeaders {

View File

@ -11,8 +11,8 @@ extends 'Lemonldap::NG::Common::PSGI';
# Properties
has 'routes' => (
is => 'rw',
isa => 'HashRef',
is => 'rw',
isa => 'HashRef',
default =>
sub { { GET => {}, POST => {}, PUT => {}, PATCH => {}, DELETE => {} } }
);

View File

@ -121,20 +121,29 @@ sub date {
return $year . $mon . $mday . $hour . $min . $sec;
}
## @function integer dateToTime(string date)
# 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
# @return Date converted to time
sub dateToTime {
my $date = shift;
return undef unless ( $date );
return undef unless ($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
return str2time( $year . "-" . $month . "-" . $day . "T" . $hour . ":" . $min . ":" . $sec . $zone, "GMT" );
# 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"
);
}
## @function boolean checkDate(string start, string end, boolean default_access)
@ -158,10 +167,10 @@ sub checkDate {
# Convert dates to epoch time
my $starttime = &dateToTime($start);
my $endtime = &dateToTime($end);
my $endtime = &dateToTime($end);
# 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 0;

View File

@ -126,8 +126,8 @@ sub BUILD {
if ( $self->{info} ) {
foreach ( keys %{ $self->{info} } ) {
next if ( $_ eq "_session_id" and $data->{_session_id} );
next if ( $_ eq "_session_kind" and $data->{_session_kind});
next if ( $_ eq "_session_id" and $data->{_session_id} );
next if ( $_ eq "_session_kind" and $data->{_session_kind} );
if ( defined $self->{info}->{$_} ) {
$data->{$_} = $self->{info}->{$_};
}

View File

@ -258,13 +258,13 @@ sub getApacheSession {
my $apacheSession = Lemonldap::NG::Common::Session->new( {
storageModule => $mod->{module},
storageModuleOptions => $mod->{options},
cacheModule =>
cacheModule =>
Lemonldap::NG::Handler::PSGI::Main->tsv->{sessionCacheModule},
cacheModuleOptions =>
Lemonldap::NG::Handler::PSGI::Main->tsv->{sessionCacheOptions},
id => $id,
force => $force,
( $id ? () : ( kind => $mod->{kind} ) ),
( $id ? () : ( kind => $mod->{kind} ) ),
( $info ? ( info => $info ) : () ),
}
);
@ -294,7 +294,7 @@ sub getMod {
}
sub getGlobal {
my ( $self ) = @_;
my ($self) = @_;
return $self->sessionTypes->{global};
}

View File

@ -55,8 +55,11 @@ ok(
# Test "and"
@tests = ( '[A and B, A]', '[A,B] and [B,C]',
'if(0) then [A,B] else [A,B] and [B,C]' );
@tests = (
'[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 ) {
ok( [ getok($expr) ]->[0] == 0, qq{"$expr" returns PE_OK as auth result} )

View File

@ -240,7 +240,7 @@ is( @{$res}, 2, "Found 2 psessions" );
# Test search with where
$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" );
# Test search with where and field selection
@ -259,7 +259,7 @@ is(
);
# Delete session
$cli->run( 'delete', {}, "9684dd2a6489bf2be2fbdd799a8028e3" );
$cli->run( 'delete', {}, "9684dd2a6489bf2be2fbdd799a8028e3" );
$cli->run( 'delete', { persistent => 1 }, "rtyler" );
$res = getJson( "get", {}, "9684dd2a6489bf2be2fbdd799a8028e3" );
@ -348,7 +348,7 @@ is( ( keys %{$res} ), 2, "Found two consents" );
$cli->run( "consents", {}, "delete", "dwho", "rp-example" );
$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" );
ok( $res->{'rp-example2'}, "Consent for test-rp2 still present" );

View File

@ -72,18 +72,18 @@ SKIP: {
'name' => 'Imported automatically'
},
{
'name' => 'U2F-1',
'type' => 'U2F',
'epoch' => 1588691728,
'name' => 'U2F-1',
'type' => 'U2F',
'epoch' => 1588691728,
'_keyHandle' =>
'4aS6vXlFQpG5XZSoad6auM9fFu7Q1wazQYwfPtPKN_Hll6Up_ceeWkOgqxm49swWq4Vvcg5UlX0sQQhuRe8heA',
'_userKey' =>
'BMgMqKPL2PhsjCNW78UEQyNF8zlJtrAAPtWMUDBp9VfDRF5oL2xkwFuyXRMPtRZ7lNfGijDrMc06bDNfp478sQQ',
},
{
'name' => 'U2F-2',
'type' => 'U2F',
'epoch' => 1588691730,
'name' => 'U2F-2',
'type' => 'U2F',
'epoch' => 1588691730,
'_keyHandle' =>
'F1Kk9V_O7KDPIx-mqp6CIjbz7ljA-ihWVWyoP1xYBe_HPLHR74aTLanmn0b4vI8DumiBWO1DAle3k6N55cXreg',
'_userKey' =>
@ -128,9 +128,9 @@ SKIP: {
'name' => 'Imported automatically'
},
{
'name' => 'U2F-3',
'type' => 'U2F',
'epoch' => 1588691734,
'name' => 'U2F-3',
'type' => 'U2F',
'epoch' => 1588691734,
'_keyHandle' =>
'4suXv5Cf10vbJEP72mVkLpBjhSqy5niOgfc0X_MjdxZ_g2e-V8biC6WyCTpF_kGV1FCa06YlcryPCtWUuUST_g',
'_userKey' =>

View File

@ -48,7 +48,9 @@ sub launch {
if ( ref( $class->logger ) and $class->logger->can('setRequestObj') ) {
$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);
}
@ -58,7 +60,9 @@ sub launch {
if ( ref( $class->logger ) and $class->logger->can('clearRequestObj') ) {
$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);
}
return $res;

View File

@ -53,8 +53,7 @@ sub _loadVhostConfig {
my $resp = $class->ua->request($get);
if ( $resp->is_success ) {
$class->logger->debug('Response is success');
eval {
$json = from_json( $resp->content, { allow_nonref => 1 } ); };
eval { $json = from_json( $resp->content, { allow_nonref => 1 } ); };
if ($@) {
$class->logger->debug('Bad json file received');
$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->locationRulesInit( undef, { $vhost => $json->{rules} } );
$class->headersInit( undef, { $vhost => $json->{headers} } );
$class->headersInit( undef, { $vhost => $json->{headers} } );
$class->tsv->{lastVhostUpdate}->{$vhost} = time;
$class->tsv->{https}->{$vhost} = uc $req->env->{HTTPS_REDIRECT} eq 'ON'
if exists $req->env->{HTTPS_REDIRECT};

View File

@ -118,7 +118,8 @@ sub _logAuthTrace {
if ( ref( $self->logger ) and $self->logger->can('setRequestObj') ) {
$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);
}
@ -129,7 +130,9 @@ sub _logAuthTrace {
if ( ref( $self->logger ) and $self->logger->can('clearRequestObj') ) {
$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);
}

View File

@ -7,7 +7,8 @@ our $VERSION = '2.0.9';
sub fetchId {
my ( $class, $req ) = @_;
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");
# Decrypt token

View File

@ -29,10 +29,10 @@ sub run {
my $localConfig = $class->localConfig;
my $zimbraPreAuthKey = $localConfig->{zimbraPreAuthKey};
my $zimbraAccountKey = $localConfig->{zimbraAccountKey} || 'uid';
my $zimbraBy = $localConfig->{zimbraBy} || 'id';
my $zimbraUrl = $localConfig->{zimbraUrl} || '/service/preauth';
my $zimbraBy = $localConfig->{zimbraBy} || 'id';
my $zimbraUrl = $localConfig->{zimbraUrl} || '/service/preauth';
my $zimbraSsoUrl = $localConfig->{zimbraSsoUrl} || '^/zimbrasso$';
my $timeout = $localConfig->{'timeout'} || '0';
my $timeout = $localConfig->{'timeout'} || '0';
# Remove trailing white-spaces
$zimbraAccountKey =~ s/\s+$//;

View File

@ -63,7 +63,9 @@ sub build_jail {
if ($build) {
@builtCustomFunctions =
$self->customFunctions ? split( /[,\s]+/, $self->customFunctions ) : ();
$self->customFunctions
? split( /[,\s]+/, $self->customFunctions )
: ();
foreach (@builtCustomFunctions) {
no warnings 'redefine';
$api->logger->debug("Custom function: $_");

View File

@ -65,7 +65,8 @@ sub checkConf {
or $class->cfgNum != $conf->{cfgNum}
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} )
&& $class->cfgDate( $conf->{cfgDate} ) )
{

View File

@ -504,7 +504,7 @@ sub fetchId {
if $class->_isHttps( $req, $vhost );
my $lookForHttpCookie = ( $class->tsv->{securedCookie} =~ /^(2|3)$/
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)
? ( $t =~ /(?<![-.~])\b${cn}http=([^,; ]+)/o ? $1 : 0 )
: ( $t =~ /(?<![-.~])\b$cn=([^,; ]+)/o ? $1 : 0 );
@ -536,8 +536,8 @@ sub retrieveSession {
# (15 seconds)
if ( defined $class->data->{_session_id}
and $id eq $class->data->{_session_id}
and
( $now - $class->dataUpdate < $class->tsv->{handlerInternalCache} ) )
and ( $now - $class->dataUpdate < $class->tsv->{handlerInternalCache} )
)
{
$class->logger->debug("Get session $id from Handler internal cache");
return $class->data;
@ -898,8 +898,9 @@ sub postJavascript {
my $filler;
foreach my $name ( keys %$data ) {
use bytes;
my @characterSet = ( '0' ..'9', 'A' .. 'Z', 'a' .. 'z' );
my $value = join '' => map $characterSet[ rand @characterSet ], 1 .. bytes::length( $data->{$name} );
my @characterSet = ( '0' .. '9', 'A' .. 'Z', 'a' .. 'z' );
my $value = join '' => map $characterSet[ rand @characterSet ],
1 .. bytes::length( $data->{$name} );
$filler .=
"form.find('input[name=\"$name\"], select[name=\"$name\"], textarea[name=\"$name\"]').val('$value')\n";
}

View File

@ -36,7 +36,7 @@ ok(
( defined($code) and ref($code) eq 'CODE' ),
'encode_base64 function is defined'
);
ok( $res = &$code, "Function works" );
ok( $res = &$code, "Function works" );
ok( $res eq 'dGVzdA==', 'Get good result' );
$sub = "sub { return ( listMatch('ABC; DEF; GHI','abc',1) ) }";
@ -58,7 +58,7 @@ ok(
'checkDate extended function is defined'
);
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')) }";
$code = $jail->jail_reval($sub);
@ -67,7 +67,7 @@ ok(
'checkDate extended function is defined'
);
ok( $res = &$code, "Function works" );
ok( $res == 1, 'Get good result' );
ok( $res == 1, 'Get good result' );
$sub = "sub { return(has2f_internal(\$_[0],\$_[1])) }";
$code = $jail->jail_reval($sub);

View File

@ -15,7 +15,7 @@ my $SKIPUSER = 0;
# --------------------
ok( $res = $client->_get('/'), 'Unauthentified query' );
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] };
ok(
$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);
# Forged headers
ok( $res = $client->_get( '/skipif/zz', undef, 'test1.example.com', undef, HTTP_AUTH_USER => 'rtyler' ),
'Test skip() with forged header' );
ok(
$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 );
count(2);

View File

@ -13,7 +13,7 @@ my $res;
# --------------------
ok( $res = $client->_get('/'), 'Unauthentified query' );
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] };
ok(
$h{Location} eq 'http://auth.example.com/?url='

View File

@ -16,7 +16,7 @@ my $res;
# Unauthentified query
ok( $res = $client->_get('/'), 'Unauthentified query' );
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] };
ok(
$h{Location} eq 'http://auth.example.com/?url='

View File

@ -39,7 +39,7 @@ my $res;
# Unauth tests
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";
ok( $res->[2]->[0] eq 'Unauth', 'Get unauth result' )
or print "Expect Unauth, got $res->[2]->[0]\n";
@ -64,7 +64,7 @@ count(3);
# Bad path test
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);
clean();

View File

@ -82,12 +82,12 @@ no warnings 'redefine';
sub LWP::UserAgent::request {
my ( $self, $req ) = @_;
ok( $req->header('host') eq 'devops.example.com',
'Host header found' )
ok( $req->header('host') eq 'devops.example.com', 'Host header found' )
or explain( $req->headers(), 'devops.example.com' );
ok( $req->as_string() =~ m#http://devops.example.com/myfile.json#,
'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);
my $httpResp;
my $s = '{

View File

@ -14,8 +14,8 @@ init(
#logLevel => 'debug',
vhostOptions => {
'test3.example.com' => {
vhostHttps => 0,
vhostPort => 80,
vhostHttps => 0,
vhostPort => 80,
vhostDevOpsRulesUrl =>
'http://donotuse.example.com/myfile.json',
},

View File

@ -73,8 +73,7 @@ no warnings 'redefine';
sub LWP::UserAgent::request {
my ( $self, $req ) = @_;
ok( $req->header('host') eq 'test3.example.com',
'Host header found' )
ok( $req->header('host') eq 'test3.example.com', 'Host header found' )
or explain( $req->headers(), 'test3.example.com' );
ok( $req->as_string() =~ m#http://127.0.0.1:80/rules.json#,
'Rules file URL found' )

View File

@ -15,7 +15,7 @@ my $res;
ok( $res = $client->_get( '/', undef, 'test.example.org' ),
'Unauthentified query' );
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] };
ok(
$h{Location} eq 'http://auth.example.com/?url='

View File

@ -21,7 +21,7 @@ my $res;
ok( $res = $client->_get('/'), 'Unauthentified query' );
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;
eval {
@ -41,7 +41,7 @@ Lemonldap::NG::Handler::Main->configReload($conf);
fail $@ if $@;
ok( $res = $client->_get('/'), 'Unauthentified query' );
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] };
ok(
$h{Location} eq 'http://auth.example.com/?url='

View File

@ -27,7 +27,7 @@ my $res;
ok( $res = $client->_get('/'), 'Unauthentified query' );
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] };
ok(
$h{Location} eq 'http://auth.example.com/?url='

View File

@ -50,7 +50,7 @@ init(
Lemonldap::NG::Common::Session->new( {
storageModule => 'Apache::Session::File',
storageModuleOptions => { Directory => 't/sessions' },
id =>
id =>
'f0fd4e85000ce35d062f97f5b466fc00abc2fad0406e03e086605f929ec4a249',
force => 1,
kind => 'OIDCI',
@ -144,7 +144,7 @@ ok(
$res = $client->_get(
'/read', undef,
'test1.example.com', '',
VHOSTTYPE => 'OAuth2',
VHOSTTYPE => 'OAuth2',
HTTP_AUTHORIZATION =>
'Bearer f0fd4e85000ce35d062f97f5b466fc00abc2fad0406e03e086605f929ec4a249',
),
@ -165,7 +165,7 @@ ok(
$res = $client->_get(
'/write', undef,
'test1.example.com', '',
VHOSTTYPE => 'OAuth2',
VHOSTTYPE => 'OAuth2',
HTTP_AUTHORIZATION =>
'Bearer f0fd4e85000ce35d062f97f5b466fc00abc2fad0406e03e086605f929ec4a249',
),
@ -178,7 +178,7 @@ ok(
$res = $client->_get(
'/test', undef,
'test1.example.com', '',
VHOSTTYPE => 'OAuth2',
VHOSTTYPE => 'OAuth2',
HTTP_AUTHORIZATION =>
'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwianRpIjoiZjBmZDRlODUwMDBjZTM1ZDA2MmY5N2Y1YjQ2NmZjMDBhYmMyZmFkMDQwNmUwM2UwODY2MDVmOTI5ZWM0YTI0OSJ9.h0RDBLo5Vy8lqbltEP2L496KOzJLhLCIRZZmEqcPuN8',
),

View File

@ -75,7 +75,7 @@ sub init {
'_utime' => $now,
'_passwordDB' => 'Demo',
'_auth' => 'Demo',
'UA' =>
'UA' =>
'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" : '' ),
'SERVER_PORT' => '80',
'SERVER_PROTOCOL' => 'HTTP/1.1',
'HTTP_USER_AGENT' =>
'HTTP_USER_AGENT' =>
'Mozilla/5.0 (VAX-4000; rv:36.0) Gecko/20350101 Firefox',
'REMOTE_ADDR' => '127.0.0.1',
'HTTP_HOST' => $host,

View File

@ -24,7 +24,7 @@ extends qw(
Lemonldap::NG::Common::Conf::AccessLib
);
has csp => ( is => 'rw' );
has csp => ( is => 'rw' );
has loadedPlugins => ( is => 'rw', default => sub { [] } );
has hLoadedPlugins => ( is => 'rw', default => sub { {} } );

View File

@ -47,7 +47,8 @@ sub init {
$self->{hiddenAttributes} //= "_password";
$self->{hiddenAttributes} .= ' _session_id'
unless $conf->{displaySessionId};
$self->{TOTPCheck} = $self->{U2FCheck} = $self->{UBKCheck} = $self->{WebAuthnCheck} = '1';
$self->{TOTPCheck} = $self->{U2FCheck} = $self->{UBKCheck} =
$self->{WebAuthnCheck} = '1';
return 1;
}
@ -68,7 +69,7 @@ sub del2F {
my $epoch = $params->{epoch}
or return $self->sendError( $req, 'Missing "epoch" parameter', 400 );
if ( grep { $_ eq $type } @{_2FTYPES()} ) {
if ( grep { $_ eq $type } @{ _2FTYPES() } ) {
$self->logger->debug(
"Call procedure delete2F with type=$type and epoch=$epoch");
return $self->delete2F( $req, $session, $skey );
@ -118,7 +119,7 @@ sub sfa {
$moduleOptions->{backend} = $mod->{module};
# Select 2FA sessions to display
foreach (@{_2FTYPES()}) {
foreach ( @{ _2FTYPES() } ) {
$self->{ $_ . 'Check' } = delete $params->{ $_ . 'Check' }
if ( defined $params->{ $_ . 'Check' } );
}
@ -189,7 +190,7 @@ sub sfa {
# Remove sessions without at least one 2F device(s)
$self->logger->debug(
"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 ) {
delete $res->{$session}
unless ( defined $res->{$session}->{_2fDevices}
@ -200,7 +201,7 @@ sub sfa {
# Filter 2FA sessions if needed
$self->logger->debug("Filtering 2F sessions...");
my $all = ( keys %$res );
foreach (@{_2FTYPES()}) {
foreach ( @{ _2FTYPES() } ) {
if ( $self->{ $_ . 'Check' } eq '2' ) {
foreach my $session ( keys %$res ) {
delete $res->{$session}
@ -268,7 +269,7 @@ qq{Use of an uninitialized attribute "$group" to group sessions},
# { session => <sessionId>, userId => <_session_uid> }
else {
$res = [
sort { $a->{date} <=> $b->{date} }
sort { $a->{date} <=> $b->{date} }
map { { session => $_, userId => $res->{$_}->{_session_uid} } }
keys %$res
];

View File

@ -337,7 +337,7 @@ sub _checkType {
return {
res => "ko",
code => 400,
msg =>
msg =>
"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 );

View File

@ -312,8 +312,8 @@ sub _isNewCasAppServiceUrlUnique {
# Check service paramater
unless ( ref $casApp->{options}->{service} eq "ARRAY" ) {
return {
res => 'ko',
msg => "The parameter 'service' must be an array",
res => 'ko',
msg => "The parameter 'service' must be an array",
};
}

View File

@ -140,7 +140,7 @@ sub addOidcRp {
409
) 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}->{redirectUris} = $add->{redirectUris};
@ -246,8 +246,8 @@ sub replaceOidcRp {
return $self->sendError( $req, $res->{msg}, 409 )
unless ( $res->{res} eq 'ok' );
$replace->{options} = {} unless ( defined $replace->{options} );
$replace->{options}->{clientId} = $replace->{clientId};
$replace->{options} = {} unless ( defined $replace->{options} );
$replace->{options}->{clientId} = $replace->{clientId};
$replace->{options}->{redirectUris} = $replace->{redirectUris};
$res = $self->_pushOidcRp( $conf, $confKey, $replace, 1 );

View File

@ -67,7 +67,7 @@ sub types {
'hostname' => {
'form' => 'text',
'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]+)))?$/
},
'int' => {
@ -257,7 +257,7 @@ m[^(?:(?:\-+\s*BEGIN\s+(?:PUBLIC\s+KEY|CERTIFICATE)\s*\-+\r?\n)?[a-zA-Z0-9/\+\r\
'url' => {
'form' => 'text',
'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]))*)))?))?))/
}
};
@ -802,7 +802,7 @@ sub attributes {
},
'casSrvMetaDataOptionsUrl' => {
'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]))*)))?))?)/,
'type' => 'text'
},
@ -1341,7 +1341,7 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.]
'domain' => {
'default' => 'example.com',
'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])[.]?))?$/,
'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' => {
'default' => {
'Directory' => '/var/lib/lemonldap-ng/sessions/',
'Directory' => '/var/lib/lemonldap-ng/sessions/',
'generateModule' =>
'Lemonldap::NG::Common::Apache::Session::Generate::SHA256',
'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' => {
'default' => {},
'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])[.]?)$/,
'test' => {
'keyMsgFail' => '__badKeyName__',
@ -2808,7 +2808,7 @@ m[^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
'pdataDomain' => {
'default' => '',
'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])[.]?))?$/,
'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' => {
'default' => 'http://auth.example.com/',
'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]))*)))?))?)/,
'type' => 'url'
},
@ -3136,7 +3136,7 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.]
'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+)?$/,
'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]))*)))?))?)/,
'type' => 'keyTextContainer'
},
@ -3288,19 +3288,19 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.]
},
'samlCommonDomainCookieDomain' => {
'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])[.]?)$/,
'type' => 'text'
},
'samlCommonDomainCookieReader' => {
'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]))*)))?))?)/,
'type' => 'text'
},
'samlCommonDomainCookieWriter' => {
'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]))*)))?))?)/,
'type' => 'text'
},
@ -3317,7 +3317,7 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.]
},
'samlDiscoveryProtocolURL' => {
'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]))*)))?))?)/,
'type' => 'text'
},
@ -4110,7 +4110,7 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.]
},
'SMTPServer' => {
'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+)?)?$/,
'type' => 'text'
},

View File

@ -207,7 +207,8 @@ EOF
foreach (@simpleHashKeys) {
$ra->add($_);
}
print F "our \$simpleHashKeys = '" . $ra->as_string . "';\n"
print F "our \$simpleHashKeys = '"
. $ra->as_string . "';\n"
. "our \$specialNodeKeys = '${ignoreKeys}s';\n";
foreach ( sort keys %cnodesRe ) {
print F "our \$${_}Keys = '$cnodesRe{$_}';\n";
@ -467,7 +468,7 @@ sub buildPortalConstants() {
printf STDERR $format, $self->portalConstantsFile;
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;
my $content = <<EOF;
# This file is generated by $module. Don't modify it by hand
@ -596,7 +597,7 @@ sub scanTree {
# Subnode
elsif ( ref($leaf) ) {
$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$/ ) {
no strict 'refs';
my @tmp = $self->scanLeaf( $leaf->{nodes} );
@ -677,6 +678,7 @@ sub scanTree {
my $type = $attr->{type};
$type =~ s/Container//;
foreach my $k ( sort keys( %{ $attr->{default} } ) ) {
# Special handling for oidcAttribute
my $default = $attr->{default}->{$k};
if ( $attr->{type} eq 'oidcAttributeContainer' ) {
@ -703,9 +705,9 @@ sub scanTree {
push @cnodesKeys, $leaf;
}
# issue 2439
# FIXME: in future versions, oidcOPMetaDataJSON and samlIDPMetaDataXML shoud
# behave the same
# issue 2439
# FIXME: in future versions, oidcOPMetaDataJSON and samlIDPMetaDataXML shoud
# behave the same
if ( $leaf =~ /^oidcOPMetaData(?:JSON|JWKS)$/ ) {
push @simpleHashKeys, $leaf;
}

View File

@ -239,7 +239,7 @@ sub attributes {
# Other
checkTime => {
type => 'int',
type => 'int',
documentation =>
'Timeout to check new configuration in local cache',
default => 600,
@ -248,7 +248,7 @@ sub attributes {
mySessionAuthorizedRWKeys => {
type => 'array',
documentation => 'Alterable session keys by user itself',
default =>
default =>
[ '_appsListOrder', '_oidcConnectedRP', '_oidcConsents' ],
},
configStorage => {
@ -297,7 +297,7 @@ sub attributes {
flags => 'h',
},
confirmFormMethod => {
type => "select",
type => "select",
select =>
[ { k => 'get', v => 'GET' }, { k => 'post', v => 'POST' }, ],
default => 'post',
@ -318,7 +318,7 @@ sub attributes {
flags => 'h',
},
infoFormMethod => {
type => "select",
type => "select",
select =>
[ { k => 'get', v => 'GET' }, { k => 'post', v => 'POST' }, ],
default => 'get',
@ -379,13 +379,13 @@ sub attributes {
documentation => 'Enable portal status',
},
portalUserAttr => {
type => 'text',
default => '_user',
type => 'text',
default => '_user',
documentation =>
'Session parameter to display connected user in portal',
},
redirectFormMethod => {
type => "select",
type => "select",
select =>
[ { k => 'get', v => 'GET' }, { k => 'post', v => 'POST' }, ],
default => 'get',
@ -446,8 +446,8 @@ sub attributes {
documentation => 'Disable fingerprint checkng',
},
stayConnectedTimeout => {
type => 'int',
default => 2592000,
type => 'int',
default => 2592000,
documentation =>
'StayConnected persistent connexion session timeout',
flags => 'm',
@ -518,7 +518,7 @@ sub attributes {
flags => 'p',
},
checkUserSearchAttributes => {
type => 'text',
type => 'text',
documentation =>
'Attributes used for retrieving sessions in user DataBase',
flags => 'p',
@ -745,14 +745,14 @@ sub attributes {
flags => 'p',
},
skipRenewConfirmation => {
type => 'bool',
default => 0,
type => 'bool',
default => 0,
documentation =>
'Avoid asking confirmation when an Issuer asks to renew auth',
},
skipUpgradeConfirmation => {
type => 'bool',
default => 0,
type => 'bool',
default => 0,
documentation =>
'Avoid asking confirmation during a session upgrade',
},
@ -761,7 +761,7 @@ sub attributes {
documentation => 'Refresh sessions plugin',
},
forceGlobalStorageIssuerOTT => {
type => 'bool',
type => 'bool',
documentation =>
'Force Issuer tokens to be stored into Global Storage',
},
@ -845,8 +845,8 @@ sub attributes {
documentation => 'Show error if session is expired',
},
portalErrorOnMailNotFound => {
type => 'bool',
default => 0,
type => 'bool',
default => 0,
documentation =>
'Show error if mail is not found in password reset process',
},
@ -938,15 +938,15 @@ sub attributes {
documentation => 'Check XSS',
},
portalForceAuthn => {
default => 0,
help => 'forcereauthn.html',
type => 'bool',
default => 0,
help => 'forcereauthn.html',
type => 'bool',
documentation =>
'Enable force to authenticate when displaying portal',
},
portalForceAuthnInterval => {
default => 5,
type => 'int',
default => 5,
type => 'int',
documentation =>
'Maximum interval in seconds since last authentication to force reauthentication',
},
@ -977,15 +977,15 @@ sub attributes {
documentation => 'Max lock time',
},
bruteForceProtectionIncrementalTempo => {
default => 0,
help => 'bruteforceprotection.html',
type => 'bool',
default => 0,
help => 'bruteforceprotection.html',
type => 'bool',
documentation =>
'Enable incremental lock time for brute force attack protection',
},
bruteForceProtectionLockTimes => {
type => 'text',
default => '15, 30, 60, 300, 600',
type => 'text',
default => '15, 30, 60, 300, 600',
documentation =>
'Incremental lock time values for brute force attack protection',
},
@ -1021,38 +1021,38 @@ sub attributes {
documentation => 'Enable Cross-Origin Resource Sharing',
},
corsAllow_Credentials => {
type => 'text',
default => 'true',
type => 'text',
default => 'true',
documentation =>
'Allow credentials for Cross-Origin Resource Sharing',
},
corsAllow_Headers => {
type => 'text',
default => '*',
type => 'text',
default => '*',
documentation =>
'Allowed headers for Cross-Origin Resource Sharing',
},
corsAllow_Methods => {
type => 'text',
default => 'POST,GET',
type => 'text',
default => 'POST,GET',
documentation =>
'Allowed methods for Cross-Origin Resource Sharing',
},
corsAllow_Origin => {
type => 'text',
default => '*',
type => 'text',
default => '*',
documentation =>
'Allowed origine for Cross-Origin Resource Sharing',
},
corsExpose_Headers => {
type => 'text',
default => '*',
type => 'text',
default => '*',
documentation =>
'Exposed headers for Cross-Origin Resource Sharing',
},
corsMax_Age => {
type => 'text',
default => '86400', # 24 hours
type => 'text',
default => '86400', # 24 hours
documentation => 'MAx-age for Cross-Origin Resource Sharing',
},
cspDefault => {
@ -1061,8 +1061,8 @@ sub attributes {
documentation => 'Default value for Content-Security-Policy',
},
cspFormAction => {
type => 'text',
default => "*",
type => 'text',
default => "*",
documentation =>
'Form action destination for Content-Security-Policy',
},
@ -1082,8 +1082,8 @@ sub attributes {
documentation => 'Style source for Content-Security-Policy',
},
cspConnect => {
type => 'text',
default => "'self'",
type => 'text',
default => "'self'",
documentation =>
'Authorized Ajax destination for Content-Security-Policy',
},
@ -1254,8 +1254,8 @@ sub attributes {
documentation => 'Display logout tab in portal',
},
portalDisplayCertificateResetByMail => {
type => 'bool',
default => 0,
type => 'bool',
default => 0,
documentation =>
'Display certificate reset by mail button in portal',
},
@ -1280,8 +1280,8 @@ sub attributes {
documentation => 'Display OIDC consent tab in portal',
},
portalDisplayGeneratePassword => {
default => 1,
type => 'bool',
default => 1,
type => 'bool',
documentation =>
'Display password generate box in reset password form',
},
@ -1431,8 +1431,8 @@ sub attributes {
documentation => 'Notification server activation',
},
notificationServerSentAttributes => {
type => 'text',
default => 'uid reference date title subtitle text check',
type => 'text',
default => 'uid reference date title subtitle text check',
documentation =>
'Prameters to send with notification server GET method',
flags => 'p',
@ -1510,8 +1510,8 @@ sub attributes {
globalStorageOptions => {
type => 'keyTextContainer',
default => {
'Directory' => '/var/lib/lemonldap-ng/sessions/',
'LockDirectory' => '/var/lib/lemonldap-ng/sessions/lock/',
'Directory' => '/var/lib/lemonldap-ng/sessions/',
'LockDirectory' => '/var/lib/lemonldap-ng/sessions/lock/',
'generateModule' =>
'Lemonldap::NG::Common::Apache::Session::Generate::SHA256',
},
@ -1637,8 +1637,8 @@ sub attributes {
documentation => 'Send a mail when password is changed',
},
portalRequireOldPassword => {
default => 1,
type => 'boolOrExpr',
default => 1,
type => 'boolOrExpr',
documentation =>
'Rule to require old password to change the password',
},
@ -1853,7 +1853,7 @@ sub attributes {
documentation => 'Upgrade session activation',
},
forceGlobalStorageUpgradeOTT => {
type => 'bool',
type => 'bool',
documentation =>
'Force Upgrade tokens be stored into Global Storage',
},
@ -1882,7 +1882,7 @@ sub attributes {
documentation => 'U2F self registration activation',
},
u2fAuthnLevel => {
type => 'int',
type => 'int',
documentation =>
'Authentication level for users authentified by password+U2F'
},
@ -1916,7 +1916,7 @@ sub attributes {
documentation => 'TOTP self registration activation',
},
totp2fAuthnLevel => {
type => 'int',
type => 'int',
documentation =>
'Authentication level for users authentified by password+TOTP'
},
@ -1969,7 +1969,7 @@ sub attributes {
documentation => 'UTOTP activation (mixed U2F/TOTP module)',
},
utotp2fAuthnLevel => {
type => 'int',
type => 'int',
documentation =>
'Authentication level for users authentified by password+(U2F or TOTP)'
},
@ -2006,7 +2006,7 @@ sub attributes {
documentation => 'Second factor code timeout',
},
mail2fAuthnLevel => {
type => 'int',
type => 'int',
documentation =>
'Authentication level for users authenticated by Mail second factor'
},
@ -2043,7 +2043,7 @@ sub attributes {
documentation => 'Validation command of External second factor',
},
ext2fAuthnLevel => {
type => 'int',
type => 'int',
documentation =>
'Authentication level for users authentified by External second factor'
},
@ -2074,7 +2074,7 @@ sub attributes {
documentation => 'Radius 2f verification timeout',
},
radius2fAuthnLevel => {
type => 'int',
type => 'int',
documentation =>
'Authentication level for users authenticated by Radius second factor'
},
@ -2118,7 +2118,7 @@ sub attributes {
documentation => 'Args for REST 2F init',
},
rest2fAuthnLevel => {
type => 'int',
type => 'int',
documentation =>
'Authentication level for users authentified by REST second factor'
},
@ -2143,7 +2143,7 @@ sub attributes {
documentation => 'Yubikey self registration activation',
},
yubikey2fAuthnLevel => {
type => 'int',
type => 'int',
documentation =>
'Authentication level for users authentified by Yubikey second factor'
},
@ -2182,7 +2182,7 @@ sub attributes {
documentation => 'Authorize users to remove existing Yubikey',
},
yubikey2fFromSessionAttribute => {
type => 'text',
type => 'text',
documentation =>
'Provision yubikey from the given session variable',
},
@ -2203,9 +2203,9 @@ sub attributes {
documentation => 'WebAuthn self registration activation',
},
webauthn2fAuthnLevel => {
type => 'int',
type => 'int',
documentation =>
'Authentication level for users authentified by WebAuthn second factor'
'Authentication level for users authentified by WebAuthn second factor'
},
webauthn2fLabel => {
type => 'text',
@ -2218,11 +2218,11 @@ sub attributes {
webauthn2fUserVerification => {
type => 'select',
select => [
{ k => 'discouraged', v => 'Discouraged' },
{ k => 'discouraged', v => 'Discouraged' },
{ k => 'preferred', v => 'Preferred' },
{ k => 'required', v => 'Required' },
{ k => 'required', v => 'Required' },
],
default => 'preferred',
default => 'preferred',
documentation => 'Verify user during registration and login',
},
webauthn2fUserCanRemoveKey => {
@ -2239,7 +2239,6 @@ sub attributes {
documentation => 'WebAuthn Relying Party display name',
},
# Single session
notifyDeleted => {
default => 1,
@ -2284,14 +2283,14 @@ sub attributes {
documentation => 'Enable REST password reset server',
},
restExportSecretKeys => {
default => 0,
type => 'bool',
default => 0,
type => 'bool',
documentation =>
'Allow to export secret keys in REST session server',
},
restClockTolerance => {
default => 15,
type => 'int',
default => 15,
type => 'int',
documentation =>
'How tolerant the REST session server will be to clock dift',
},
@ -2320,7 +2319,7 @@ sub attributes {
documentation => 'Enable SOAP config server',
},
exportedAttr => {
type => 'text',
type => 'text',
documentation =>
'List of attributes to export by SOAP or REST servers',
},
@ -2583,7 +2582,7 @@ sub attributes {
documentation => 'CAS User attribute',
},
casAppMetaDataOptionsAuthnLevel => {
type => 'int',
type => 'int',
documentation =>
'Authentication level requires to access to this CAS application',
},
@ -2745,8 +2744,8 @@ sub attributes {
default => 'RSA_SHA256',
},
samlServiceUseCertificateInResponse => {
type => 'bool',
default => 0,
type => 'bool',
default => 0,
documentation =>
'Use certificate instead of public key in SAML responses',
},
@ -2769,8 +2768,8 @@ sub attributes {
documentation => 'SAML authn context password level',
},
samlAuthnContextMapPasswordProtectedTransport => {
type => 'int',
default => 3,
type => 'int',
default => 3,
documentation =>
'SAML authn context password protected transport level',
},
@ -3131,7 +3130,7 @@ sub attributes {
documentation => 'SAML SP SLO SOAP',
},
samlSPSSODescriptorAssertionConsumerServiceHTTPArtifact => {
type => 'samlAssertion',
type => 'samlAssertion',
default =>
'0;1;urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact;'
. '#PORTAL#/saml/proxySingleSignOnArtifact',
@ -3223,7 +3222,7 @@ sub attributes {
default => 1,
},
samlSPMetaDataOptionsAuthnLevel => {
type => 'int',
type => 'int',
documentation =>
'Authentication level requires to access to this SP',
},
@ -3335,9 +3334,9 @@ sub attributes {
documentation => 'Rule to display second factor Manager link',
},
sfRemovedMsgRule => {
type => 'boolOrExpr',
default => 0,
help => 'secondfactor.html',
type => 'boolOrExpr',
default => 0,
help => 'secondfactor.html',
documentation =>
'Display a message if at leat one expired SF has been removed',
},
@ -3359,7 +3358,7 @@ sub attributes {
documentation => 'Notification title',
},
sfRemovedNotifMsg => {
type => 'text',
type => 'text',
default =>
'_removedSF_ expired second factor(s) has/have been removed (_nameSF_)!',
help => 'secondfactor.html',
@ -3370,13 +3369,14 @@ sub attributes {
documentation => 'Timeout for 2F registration process',
},
available2F => {
type => 'text',
default => 'UTOTP,TOTP,U2F,REST,Mail2F,Ext2F,WebAuthn,Yubikey,Radius',
type => 'text',
default =>
'UTOTP,TOTP,U2F,REST,Mail2F,Ext2F,WebAuthn,Yubikey,Radius',
documentation => 'Available second factor modules',
},
available2FSelfRegistration => {
type => 'text',
default => 'TOTP,U2F,WebAuthn,Yubikey',
type => 'text',
default => 'TOTP,U2F,WebAuthn,Yubikey',
documentation =>
'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',
},
ldapGroupAttributeNameUser => {
type => 'text',
default => 'dn',
type => 'text',
default => 'dn',
documentation =>
'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',
},
ldapGroupAttributeNameGroup => {
type => 'text',
default => 'dn',
type => 'text',
default => 'dn',
documentation =>
'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',
},
ldapCAFile => {
type => 'text',
type => 'text',
documentation =>
'Location of the certificate file for LDAP connections',
},
ldapCAPath => {
type => 'text',
type => 'text',
documentation =>
'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',
default => {
proxy => 'http://auth.example.com/sessions',
ns =>
ns =>
'http://auth.example.com/Lemonldap/NG/Common/PSGI/SOAPService',
},
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'
},
linkedInUserField => { type => 'text', default => 'emailAddress' },
linkedInScope =>
linkedInScope =>
{ type => 'text', default => 'r_liteprofile r_emailaddress' },
# GitHub
@ -3881,10 +3881,10 @@ m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
dbiUserTable => { type => 'text', },
# TODO: add dbiMailCol
dbiAuthLoginCol => { type => 'text', },
dbiAuthPasswordCol => { type => 'text', },
dbiPasswordMailCol => { type => 'text', },
userPivot => { type => 'text', },
dbiAuthLoginCol => { type => 'text', },
dbiAuthPasswordCol => { type => 'text', },
dbiPasswordMailCol => { type => 'text', },
userPivot => { type => 'text', },
dbiAuthPasswordHash =>
{ type => 'text', help => 'authdbi.html#password', },
dbiDynamicHashEnabled =>
@ -4269,13 +4269,13 @@ m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
documentation => 'OpenID Connect global access token TTL',
},
oidcServiceDynamicRegistrationExportedVars => {
type => 'keyTextContainer',
type => 'keyTextContainer',
documentation =>
'OpenID Connect exported variables for dynamic registration',
},
oidcServiceDynamicRegistrationExtraClaims => {
type => 'keyTextContainer',
keyTest => qr/^[\x21\x23-\x5B\x5D-\x7E]+$/,
type => 'keyTextContainer',
keyTest => qr/^[\x21\x23-\x5B\x5D-\x7E]+$/,
documentation =>
'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 },
oidcOPMetaDataOptionsClientID => { type => 'text', },
oidcOPMetaDataOptionsClientSecret => { type => 'password', },
oidcOPMetaDataOptionsScope =>
oidcOPMetaDataOptionsScope =>
{ type => 'text', default => 'openid profile' },
oidcOPMetaDataOptionsDisplay => {
type => 'select',
@ -4363,10 +4363,10 @@ m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
{ type => 'bool', default => 1 },
oidcOPMetaDataOptionsIDTokenMaxAge => { type => 'int', default => 30 },
oidcOPMetaDataOptionsUseNonce => { type => 'bool', default => 1 },
oidcOPMetaDataOptionsDisplayName => { type => 'text', },
oidcOPMetaDataOptionsIcon => { type => 'text', },
oidcOPMetaDataOptionsStoreIDToken => { type => 'bool', default => 0 },
oidcOPMetaDataOptionsSortNumber => { type => 'int', },
oidcOPMetaDataOptionsDisplayName => { type => 'text', },
oidcOPMetaDataOptionsIcon => { type => 'text', },
oidcOPMetaDataOptionsStoreIDToken => { type => 'bool', default => 0 },
oidcOPMetaDataOptionsSortNumber => { type => 'int', },
# OpenID Connect relying parties
oidcRPMetaDataExportedVars => {
@ -4398,7 +4398,7 @@ m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
],
default => 'HS512',
},
oidcRPMetaDataOptionsIDTokenExpiration => { type => 'int' },
oidcRPMetaDataOptionsIDTokenExpiration => { type => 'int' },
oidcRPMetaDataOptionsIDTokenForceClaims =>
{ type => 'bool', default => 0 },
oidcRPMetaDataOptionsAccessTokenSignAlg => {
@ -4480,8 +4480,8 @@ m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
documentation => 'Allow offline access',
},
oidcRPMetaDataOptionsAllowPasswordGrant => {
type => 'bool',
default => 0,
type => 'bool',
default => 0,
documentation =>
'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',
},
oidcRPMetaDataOptionsAuthnLevel => {
type => 'int',
type => 'int',
documentation =>
'Authentication level requires to access to this RP',
},

View File

@ -72,7 +72,7 @@ sub tree {
},
{
title => 'passwordManagement',
help =>
help =>
'portalcustom.html#password-management',
form => 'simpleInputContainer',
nodes => [
@ -99,7 +99,7 @@ sub tree {
},
{
title => 'portalOther',
help =>
help =>
'portalcustom.html#other-parameters',
form => 'simpleInputContainer',
nodes => [
@ -129,7 +129,7 @@ sub tree {
},
{
title => 'authParams',
help =>
help =>
'start.html#authentication-users-and-password-databases',
form => 'authParams',
nodes => [
@ -650,7 +650,7 @@ sub tree {
},
{
title => 'soapServices',
help =>
help =>
'portalservers.html#SOAP_(deprecated)',
form => 'simpleInputContainer',
nodes => [
@ -684,7 +684,7 @@ sub tree {
'notificationStorageOptions',
{
title => 'serverNotification',
help =>
help =>
'notifications.html#notification-server',
nodes => [
'notificationServer',

View File

@ -24,8 +24,8 @@ has cfgNum => (
has log => ( is => 'rw' );
has req => ( is => 'ro' );
has sep => ( is => 'rw', isa => 'Str', default => '/' );
has format => ( is => 'rw', isa => 'Str', default => "%-25s | %-25s | %-25s" );
has sep => ( is => 'rw', isa => 'Str', default => '/' );
has format => ( is => 'rw', isa => 'Str', default => "%-25s | %-25s | %-25s" );
has yes => ( is => 'rw', isa => 'Bool', default => 0 );
has safe => ( is => 'rw', isa => 'Bool', default => 0 );
has force => ( is => 'rw', isa => 'Bool', default => 0 );
@ -317,8 +317,8 @@ sub lastCfg {
sub save {
my ($self) = @_;
my $conf = $self->jsonResponse( '/confs/' . $self->cfgNum, 'full=1' );
my $json = JSON->new->indent->canonical;
my $conf = $self->jsonResponse( '/confs/' . $self->cfgNum, 'full=1' );
my $json = JSON->new->indent->canonical;
print $json->encode($conf);
}
@ -404,9 +404,9 @@ sub _getKey {
sub _setKey {
my ( $self, $conf, $key, $value ) = @_;
my $sep = $self->sep;
my $sep = $self->sep;
my (@path) = split $sep, $key;
my $last = pop @path;
my $last = pop @path;
while ( my $next = shift @path ) {
$conf = $conf->{$next};
}

View File

@ -20,9 +20,10 @@ sub diff {
$res[$i]->{$key} = $tmp[$i] if ( $tmp[$i] );
}
}
elsif ( $key =~ $hashParameters
or
( ref( $conf[0]->{$key} ) and ref( $conf[0]->{$key} ) eq 'HASH' ) )
elsif (
$key =~ $hashParameters
or ( ref( $conf[0]->{$key} ) and ref( $conf[0]->{$key} ) eq 'HASH' )
)
{
if ( ref $conf[1]->{$key} ) {
my @tmp =

View File

@ -438,8 +438,8 @@ sub _scanNodes {
$self->_scanNodes($subNodes);
}
}
elsif (
$target =~ /^oidc(?:O|R)PMetaData(?:ExportedVars|Macros|ScopeRules)$/ )
elsif ( $target =~
/^oidc(?:O|R)PMetaData(?:ExportedVars|Macros|ScopeRules)$/ )
{
hdebug(" $target");
if ( $leaf->{cnodes} ) {

View File

@ -106,7 +106,7 @@ sub zeroConf {
},
'cfgNum' => 0,
'globalStorageOptions' => {
'Directory' => $sessionDir,
'Directory' => $sessionDir,
'generateModule' =>
'Lemonldap::NG::Common::Apache::Session::Generate::SHA256',
'LockDirectory' => "$sessionDir/lock"
@ -177,14 +177,14 @@ sub zeroConf {
'inGroup("timelords") or $uid eq "rtyler"',
}
},
'whatToTrace' => '_whatToTrace',
'securedCookie' => 0,
'cookieName' => 'lemonldap',
'cfgAuthor' => 'The LemonLDAP::NG team',
'cfgDate' => '1627287638',
'cfgVersion' => $VERSION,
'exportedVars' => {},
'portalSkin' => 'bootstrap',
'whatToTrace' => '_whatToTrace',
'securedCookie' => 0,
'cookieName' => 'lemonldap',
'cfgAuthor' => 'The LemonLDAP::NG team',
'cfgDate' => '1627287638',
'cfgVersion' => $VERSION,
'exportedVars' => {},
'portalSkin' => 'bootstrap',
'portalSkinBackground' =>
'1280px-Cedar_Breaks_National_Monument_partially.jpg',
'mailUrl' => "http://auth.$domain/resetpwd",

View File

@ -248,7 +248,8 @@ sub sessions {
value => $uid,
count => scalar( @{ $r->{$uid} } ),
sessions => [
map { {
map {
{
session =>
$self->_maybeEncryptSessionId( $_->{_sessionId} ),
date => $_->{_utime}
@ -399,7 +400,8 @@ qq{Use of an uninitialized attribute "$group" to group sessions},
else {
$res = [
sort { $a->{date} <=> $b->{date} }
map { {
map {
{
session => $self->_maybeEncryptSessionId($_),
date => $res->{$_}->{_utime}
}
@ -459,8 +461,8 @@ sub delSession {
}
sub cmpIPv4 {
my @a = split /\./, $_[0];
my @b = split /\./, $_[1];
my @a = split /\./, $_[0];
my @b = split /\./, $_[1];
my $cmp = 0;
F: for ( my $i = 0 ; $i < 4 ; $i++ ) {
if ( $a[$i] != $b[$i] ) {

View File

@ -20,9 +20,9 @@ sub newSession {
$tmp = Lemonldap::NG::Common::Session->new( {
storageModule => 'Apache::Session::File',
storageModuleOptions => {
Directory => 't/sessions',
LockDirectory => 't/sessions',
backend => 'Apache::Session::File',
Directory => 't/sessions',
LockDirectory => 't/sessions',
backend => 'Apache::Session::File',
generateModule =>
'Lemonldap::NG::Common::Apache::Session::Generate::SHA256',
},

View File

@ -129,7 +129,7 @@ sub checkGet {
my $res = get( $test, $type, $confKey );
check200( $test, $res );
my @path = split '/', $attrPath;
my $key = from_json( $res->[2]->[0] );
my $key = from_json( $res->[2]->[0] );
for (@path) {
if ( ref($key) eq 'ARRAY' ) {
$key = $key->[$_];
@ -326,7 +326,7 @@ checkAddFailsOnInvalidConfkey( $test, 'cat', $cat3 );
checkAddFailsOnInvalidConfkey
$test = "Cat - Update should succeed and keep existing values";
$test = "Cat - Update should succeed and keep existing values";
$cat1->{order} = 3;
delete $cat1->{catname};
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' );
$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";
checkAdd( $test, 'app/mycat1', $app1 );

View File

@ -23,10 +23,10 @@ is( $brokenconfig->{status}, 'ko', 'Got expected global status' );
is( $brokenconfig->{status_config}, 'ko', 'Got expected config status' );
rename 't/conf/lmConf-1.json.broken', 't/conf/lmConf-1.json';
my $allfine = getStatus( "Back to normal" );
is( $allfine->{status}, 'ok', 'Got expected global status' );
is( $allfine->{status_config}, 'ok', 'Got expected config status' );
is( $allfine->{status_sessions}, 'unknown', 'Not implemented yet' );
my $allfine = getStatus("Back to normal");
is( $allfine->{status}, 'ok', 'Got expected global status' );
is( $allfine->{status_config}, 'ok', 'Got expected config status' );
is( $allfine->{status_sessions}, 'unknown', 'Not implemented yet' );
is( $allfine->{status_psessions}, 'unknown', 'Not implemented yet' );
# Clean up generated files, except for "lmConf-1.json"

View File

@ -276,7 +276,7 @@ sub checkFindByProviderId {
($gotProviderId) = $result->{metadata} =~ m/entityID=['"](.+?)['"]/i;
}
elsif ( $providerIdName eq 'serviceUrl' ) {
$gotProviderId = shift @{$result->{options}->{service}};
$gotProviderId = shift @{ $result->{options}->{service} };
}
else {
$gotProviderId = $result->{$providerIdName};
@ -337,8 +337,8 @@ my $oidcRp = {
email => 'mail',
},
options => {
clientSecret => 'secret',
icon => 'web.png',
clientSecret => 'secret',
icon => 'web.png',
postLogoutRedirectUris =>
[ "http://url/logout1", "http://url/logout2" ],
}
@ -534,7 +534,7 @@ $samlSp->{options}->{checkSLOMessageSignature} = 1;
$samlSp->{options}->{encryptionMode} = 'nameid';
delete $samlSp->{options}->{sessionNotOnOrAfterTimeout};
delete $samlSp->{exportedAttributes};
$samlSp->{macros}->{family_name} = '$sn',
$samlSp->{macros}->{family_name} = '$sn',
$samlSp->{exportedAttributes}->{cn}->{name} = "cn",
$samlSp->{exportedAttributes}->{cn}->{friendlyName} = "common_name",
$samlSp->{exportedAttributes}->{cn}->{mandatory} = "false",
@ -646,7 +646,9 @@ my $casApp = {
given_name => '$firstName',
},
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\'',
userAttribute => 'uid'
}
@ -663,7 +665,7 @@ $test = "CasApp - Add should fail on duplicate confKey";
checkAddFailsIfExists( $test, 'cas/app', $casApp );
$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';
delete $casApp->{options}->{rule};
delete $casApp->{macros};
@ -672,7 +674,7 @@ $casApp->{macros}->{given_name} = '$givenName';
$casApp->{exportedVars}->{cn} = 'uid';
checkUpdate( $test, 'cas/app', 'myCasApp1', $casApp );
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/rule', '$uid eq \'dwho\'' );
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";
$casApp->{confKey} = 'myCasApp2';
$casApp->{options}->{service} = [ 'http://mycasapp.skynet.com' ];
$casApp->{options}->{service} = ['http://mycasapp.skynet.com'];
$casApp->{options}->{playingPossum} = 'ElephantInTheRoom';
checkAddWithUnknownAttributes( $test, 'cas/app', $casApp );
delete $casApp->{options}->{playingPossum};
$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 );
$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 );
$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';
checkReplaceWithInvalidAttribute( $test, 'cas/app', 'myCasApp2', $casApp );
delete $casApp->{options}->{playingPossum};
$casApp->{options}->{service} = [ "XXX" ];
$casApp->{options}->{service} = ["XXX"];
checkReplaceWithInvalidAttribute( $test, 'cas/app', 'myCasApp2', $casApp );
$test = "CasApp - Replace should fail if service is not an array";

View File

@ -58,7 +58,7 @@ while (<F>) {
close F;
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";
count(2);

View File

@ -15,7 +15,7 @@ sub checkResult {
like( $key->{private}, qr/BEGIN/, "is PEM formatted" );
like( $key->{public}, qr/BEGIN/, "is PEM formatted" );
ok( $key->{hash}, "hash is non empty" ) if $expecthash;
count(1) if $expecthash;
count(1) if $expecthash;
count(4);
}
@ -53,7 +53,7 @@ checkResult($res);
ok(
$res = &client->_post(
'/confs/newCertificate', '', IO::String->new('{"password":"hello"}'),
'application/json', 20,
'application/json', 20,
),
"Request succeed"
);

View File

@ -20,7 +20,7 @@ mkdir 't/sessions';
my ( $res, $resBody );
ok( $res = &client->_post( '/confs/', 'cfgNum=1', &body, 'application/json' ),
"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->{result} == 0, "JSON response contains \"result:0\"" )
@ -36,7 +36,7 @@ count(6);
foreach my $i ( 0 .. 3 ) {
ok(
$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"
) or print STDERR Dumper($resBody);
count(1);

View File

@ -20,7 +20,7 @@ mkdir 't/sessions';
my ( $res, $resBody );
ok( $res = &client->_post( '/confs/', 'cfgNum=1', &body, 'application/json' ),
"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->{result} == 1, "JSON response contains \"result:1\"" )
or print STDERR Dumper($resBody);

View File

@ -16,7 +16,7 @@ unlink 't/conf/lmConf-2.json';
my ( $res, $resBody );
ok( $res = &client->_post( '/confs/', 'cfgNum=1', &body, 'application/json' ),
"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->{result} == 0, "JSON response contains \"result:0\"" )
or print STDERR Dumper($res);

View File

@ -17,7 +17,7 @@ mkdir 't/sessions';
my ( $res, $resBody );
ok( $res = &client->_post( '/confs/', 'cfgNum=1', &body, 'application/json' ),
"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->{result} == 1, "JSON response contains \"result:1\"" )
or print STDERR Dumper($res);

View File

@ -17,7 +17,7 @@ mkdir 't/sessions';
my ( $res, $resBody );
ok( $res = &client->_post( '/confs/', 'cfgNum=1', &body, 'application/json' ),
"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->{result} == 1, "JSON response contains \"result:1\"" )
or print STDERR Dumper($res);

View File

@ -63,7 +63,7 @@ SKIP: {
Lemonldap::NG::Manager::Cli->run(@args);
my $res = $dbh->selectrow_hashref(
"SELECT * FROM lmConfig WHERE field='ldapSetPassword'");
ok( $res, 'Key inserted' );
ok( $res, 'Key inserted' );
ok( $res and $res->{value} == '0', 'Value is 0' );
}

View File

@ -16,8 +16,8 @@ sub newSession {
$tmp = Lemonldap::NG::Common::Session->new( {
storageModule => 'Apache::Session::File',
storageModuleOptions => {
Directory => 't/sessions',
LockDirectory => 't/sessions',
Directory => 't/sessions',
LockDirectory => 't/sessions',
generateModule =>
'Lemonldap::NG::Common::Apache::Session::Generate::SHA256',
},
@ -148,7 +148,7 @@ count(5);
foreach (@ids) {
my $res;
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,
'Body is JSON and result==1' );
count(3);

View File

@ -86,7 +86,7 @@ SKIP: {
$notif = '{"done":1}';
$res = $client->jsonPutResponse(
'notifications/actives/dwho_Test',
'', IO::String->new($notif),
'', IO::String->new($notif),
'application/json', length($notif)
);
ok( $res->{result} == 1, 'Result = 1' );

View File

@ -56,7 +56,7 @@ displayTests('actives');
$notif = '{"done":1}';
$res = &client->jsonPutResponse(
'notifications/actives/dwho_Test',
'', IO::String->new($notif),
'', IO::String->new($notif),
'application/json', length($notif)
);
ok( $res->{result} == 1, 'Result = 1' );
@ -137,7 +137,7 @@ sub displayTests {
) or diag Dumper($res);
my $internal_ref = $res->{values}->[0]->{notification};
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' )
or diag Dumper($res);
ok( $res = eval { from_json( $res->{notifications}->[0] ) },

View File

@ -16,8 +16,8 @@ sub newSession {
$tmp = Lemonldap::NG::Common::Session->new( {
storageModule => 'Apache::Session::File',
storageModuleOptions => {
Directory => 't/sessions',
LockDirectory => 't/sessions',
Directory => 't/sessions',
LockDirectory => 't/sessions',
generateModule =>
'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' );
ok( $res->{result} == 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}->[0]->{value} && $res->{values}->[0]->{value} eq 'd',
'Result match "uid=d"' )

View File

@ -18,7 +18,8 @@ sub body {
# Test that key value is sent
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);
# Test that hidden key values are NOT sent

View File

@ -38,14 +38,14 @@ my @notManagedAttributes = (
'syslogFacility', 'userLogger', 'logLevel',
# Plugins parameters
'notificationsMaxRetrieve', 'persistentSessionAttributes',
'notificationsMaxRetrieve', 'persistentSessionAttributes',
# PSGI/CGI protection (must be set in lemonldap-ng.ini)
'protection',
# SecureToken handler
'secureTokenAllowOnError', 'secureTokenAttribute', 'secureTokenExpiration',
'secureTokenHeader', 'secureTokenMemcachedServers', 'secureTokenUrls',
'secureTokenHeader', 'secureTokenMemcachedServers', 'secureTokenUrls',
# Sessions and OTT storage
'configStorage', 'localStorageOptions', 'localStorage',
@ -157,7 +157,7 @@ sub scanTree {
# Nodes must have a title
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
ok( (

View File

@ -385,7 +385,8 @@ sub run {
MSG => $self->canUpdateSfa($req) || 'choose2f',
ALERT => ( $self->canUpdateSfa($req) ? 'warning' : 'positive' ),
MODULES => [
map { {
map {
{
CODE => $_->prefix,
LOGO => $_->logo,
LABEL => $_->label
@ -440,7 +441,7 @@ sub _choice {
return $self->p->do(
$req,
[
sub { $res }, 'controlUrl',
sub { $res }, 'controlUrl',
'buildCookie', @{ $self->p->endAuth },
]
);

View File

@ -180,7 +180,7 @@ sub _registration {
if (
$self->find2fByKey(
$req, $req->userData, $self->type,
$req, $req->userData, $self->type,
"_credentialId", $credential_id
)
)

View File

@ -255,8 +255,7 @@ sub authenticate {
sub setAuthSessionInfo {
my ( $self, $req ) = @_;
$req->{sessionInfo}->{authenticationLevel} = $self->conf->{casAuthnLevel};
$req->{sessionInfo}->{_casSrv}
= $req->data->{_casSrvCurrent};
$req->{sessionInfo}->{_casSrv} = $req->data->{_casSrvCurrent};
return PE_OK;
}

View File

@ -155,8 +155,7 @@ sub extractFormInfo {
$self->logger->debug("Response from GitHub User API: $user_content");
eval {
$json_hash = from_json( $user_content, { allow_nonref => 1 } ); };
eval { $json_hash = from_json( $user_content, { allow_nonref => 1 } ); };
if ($@) {
$self->logger->error("Unable to decode JSON $user_content");
return PE_ERROR;

View File

@ -33,7 +33,7 @@ has reWebIDWhitelist => ( is => 'rw' );
sub init {
my ($self) = @_;
my @hosts = split /\s+/, $self->{conf}->{webIDWhitelist};
my @hosts = split /\s+/, $self->{conf}->{webIDWhitelist};
unless (@hosts) {
$self->error(
'WebID white list is empty. Set it in manager, use * to accept all FOAF providers'

View File

@ -90,11 +90,13 @@ sub extractFormInfo {
# 3. If user and oldpassword defined -> password form
elsif ( $defUser and $defOldPassword ) {
$res = PE_PASSWORDFORMEMPTY
unless ( ( $req->{user} = $req->param('user') )
unless (
( $req->{user} = $req->param('user') )
&& ( $req->data->{oldpassword} = $req->param('oldpassword') )
&& ( $req->data->{newpassword} = $req->param('newpassword') )
&& ( $req->data->{confirmpassword} =
$req->param('confirmpassword') ) );
$req->param('confirmpassword') )
);
}
# If form seems empty

View File

@ -703,7 +703,7 @@ sub run {
# Store data in session
my $code_payload = {
code_challenge => $oidc_request->{'code_challenge'},
code_challenge => $oidc_request->{'code_challenge'},
code_challenge_method =>
$oidc_request->{'code_challenge_method'},
nonce => $oidc_request->{'nonce'},
@ -765,7 +765,7 @@ sub run {
$self->logger->error("Unable to create Access Token");
$self->returnRedirectError( $req,
$oidc_request->{'redirect_uri'},
"server_error", undef, undef,
"server_error", undef, undef,
$oidc_request->{'state'}, 1 );
}
@ -873,7 +873,7 @@ sub run {
$self->logger->error("Unable to create Access Token");
return $self->returnRedirectError( $req,
$oidc_request->{'redirect_uri'},
"server_error", undef, undef,
"server_error", undef, undef,
$oidc_request->{'state'}, 1 );
}
@ -1328,7 +1328,7 @@ sub _handlePasswordGrant {
access_token => "$access_token",
token_type => 'Bearer',
expires_in => $expires_in + 0,
( ( $scope ne $req_scope ) ? ( scope => "$scope" ) : () ),
( ( $scope ne $req_scope ) ? ( scope => "$scope" ) : () ),
( $refresh_token ? ( refresh_token => "$refresh_token" ) : () ),
( $id_token ? ( id_token => "$id_token" ) : () ),
};
@ -1526,7 +1526,7 @@ sub _handleAuthorizationCodeGrant {
expires_in => $expires_in + 0,
id_token => "$id_token",
( $refresh_token ? ( refresh_token => "$refresh_token" ) : () ),
( ( $req_scope ne $scope ) ? ( scope => "$scope" ) : () ),
( ( $req_scope ne $scope ) ? ( scope => "$scope" ) : () ),
};
my $cRP = $apacheSession->data->{_oidcConnectedRP} || '';
@ -2195,10 +2195,10 @@ sub metadata {
# Scopes
scopes_supported => [qw/openid profile email address phone/],
response_types_supported => $response_types,
grant_types_supported => $grant_types,
acr_values_supported => \@acr,
subject_types_supported => ["public"],
response_types_supported => $response_types,
grant_types_supported => $grant_types,
acr_values_supported => \@acr,
subject_types_supported => ["public"],
token_endpoint_auth_methods_supported =>
[qw/client_secret_post client_secret_basic/],
introspection_endpoint_auth_methods_supported =>
@ -2380,9 +2380,9 @@ sub _generateIDToken {
exp => $id_token_exp, # expiration
iat => time, # Issued time
auth_time => $sessionInfo->{_lastAuthnUTime}, # Authentication time
acr => $id_token_acr, # Authentication Context Class Reference
azp => $client_id, # Authorized party
# TODO amr
acr => $id_token_acr, # Authentication Context Class Reference
azp => $client_id, # Authorized party
# TODO amr
};
for ( keys %{$extra_claims} ) {

View File

@ -281,7 +281,7 @@ sub run {
$req->data->{_proxiedRequest} = $request;
$req->data->{_proxiedMethod} = $method;
$req->data->{_proxiedRelayState} = $relaystate,
$req->data->{_proxiedArtifact} = $artifact;
$req->data->{_proxiedArtifact} = $artifact;
}
# Process the request or use IDP initiated mode
@ -597,8 +597,8 @@ sub run {
# Get session key associated with NameIDFormat
# Not for unspecified, transient, persistent, entity, encrypted
my $nameIDFormatConfiguration = {
$self->getNameIDFormat("email") => 'samlNameIDFormatMapEmail',
$self->getNameIDFormat("x509") => 'samlNameIDFormatMapX509',
$self->getNameIDFormat("email") => 'samlNameIDFormatMapEmail',
$self->getNameIDFormat("x509") => 'samlNameIDFormatMapX509',
$self->getNameIDFormat("windows") =>
'samlNameIDFormatMapWindows',
$self->getNameIDFormat("kerberos") =>

View File

@ -9,10 +9,10 @@ with 'Lemonldap::NG::Portal::Lib::OverConf';
our $VERSION = '2.0.14';
has modules => ( is => 'rw', default => sub { {} } );
has rules => ( is => 'rw', default => sub { {} } );
has type => ( is => 'rw' );
has catch => ( is => 'rw', default => sub { {} } );
has modules => ( is => 'rw', default => sub { {} } );
has rules => ( is => 'rw', default => sub { {} } );
has type => ( is => 'rw' );
has catch => ( is => 'rw', default => sub { {} } );
has sessionKey => ( is => 'ro', default => '_choice' );
my $_choiceRules;

View File

@ -72,8 +72,8 @@ has findUserFilter => (
is => 'ro',
lazy => 1,
builder => sub {
$_[0]->conf->{AuthLDAPFilter} ||
$_[0]->conf->{LDAPFilter}
$_[0]->conf->{AuthLDAPFilter}
|| $_[0]->conf->{LDAPFilter}
|| '(&(uid=$user)(objectClass=inetOrgPerson))';
}
);

View File

@ -52,7 +52,7 @@ sub new {
( $conf->{ldapVerify} ? ( verify => $conf->{ldapVerify} ) : () ),
);
unless ($self) {
$portal->logger->error("LDAP initialization error: ". $@);
$portal->logger->error( "LDAP initialization error: " . $@ );
return 0;
}
elsif ( $Net::LDAP::VERSION < '0.64' ) {

View File

@ -69,7 +69,7 @@ sub checkForNotifications {
}
# Transform notifications
my $i = 0; # Files count
my $i = 0; # Files count
my $now = strftime "%Y-%m-%d", localtime;
foreach my $file ( values %$notifs ) {

View File

@ -29,7 +29,7 @@ use constant PROFILE => [
qw/name family_name given_name middle_name nickname preferred_username
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 =>
[qw/formatted street_address locality region postal_code country/];
use constant PHONE => [qw/phone_number phone_number_verified/];
@ -1031,7 +1031,7 @@ sub storeState {
# check if there are data to store
my $infos;
foreach (@data) {
$infos->{$_} = $req->{$_} if $req->{$_};
$infos->{$_} = $req->{$_} if $req->{$_};
$infos->{"data_$_"} = $req->data->{$_} if $req->data->{$_};
}
return unless ($infos);

View File

@ -59,7 +59,7 @@ sub checkRemoteId {
# Trying to recover session from global session storage
my $remoteSession = Lemonldap::NG::Common::Session->new( {
storageModule => $self->conf->{remoteGlobalStorage},
storageModule => $self->conf->{remoteGlobalStorage},
storageModuleOptions =>
$self->conf->{remoteGlobalStorageOptions},
cacheModule => $self->conf->{localSessionStorage},

View File

@ -1888,7 +1888,8 @@ sub resolveArtifact {
$self->logger->debug("Get message $message");
}
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
$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");
# SAML2 attribute value

View File

@ -47,7 +47,7 @@ sub loadMailTemplate {
my ( $self, $req, $name, %prm ) = @_;
# 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}->{MAIN_LOGO} = $self->conf->{portalMainLogo};
my %extra =

View File

@ -10,8 +10,8 @@ use Carp;
our $VERSION = '2.0.12';
has rp_id => ( is => 'rw', lazy => 1, builder => "_build_rp_id" );
has origin => ( is => 'rw', lazy => 1, builder => "_build_origin" );
has rp_id => ( is => 'rw', lazy => 1, builder => "_build_rp_id" );
has origin => ( is => 'rw', lazy => 1, builder => "_build_origin" );
has type => ( is => 'ro', default => 'WebAuthn' );
has verifier => ( is => 'rw', lazy => 1, builder => "_build_verifier" );

View File

@ -32,7 +32,7 @@ sub authCancel { '_authCancel' }
sub _betweenAuthAndData { _wrapEntryPoint( @_, 'betweenAuthAndData' ); }
sub _afterData { _wrapEntryPoint( @_, 'afterData' ); }
sub _endAuth { _wrapEntryPoint( @_, 'endAuth' ); }
sub _forAuthUser { _wrapEntryPoint( @_, 'forAuthUser', 1 ); }
sub _forAuthUser { _wrapEntryPoint( @_, 'forAuthUser', 1 ); }
sub _beforeLogout { _wrapEntryPoint( @_, 'beforeLogout', 1 ); }
sub _authCancel { _wrapEntryPoint( @_, 'authCancel' ); }

View File

@ -11,6 +11,6 @@ extends 'Lemonldap::NG::Portal::Main::Plugin';
has authnLevel => ( is => 'rw' );
sub stop {0}
sub stop { 0 }
1;

View File

@ -7,7 +7,7 @@ use Exporter 'import';
our $VERSION = '2.0.14';
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]))*)))?))?)};
use constant {
PE_IDPCHOICE => -5,

View File

@ -29,7 +29,8 @@ sub displayInit {
else {
$self->logger->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} ) );
unless ($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);
$rule =
HANDLER->buildSub( HANDLER->substitute( $self->conf->{stayConnected} ) );
unless ($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);

View File

@ -128,9 +128,9 @@ sub init {
# Purge loaded module list
$self->loadedModules( {} );
$self->afterSub( {} );
$self->aroundSub( {} );
$self->hook( {} );
$self->afterSub( {} );
$self->aroundSub( {} );
$self->hook( {} );
# Insert `reloadConf` in handler reload stack
Lemonldap::NG::Handler::Main->onReload( $self, 'reloadConf' );
@ -228,10 +228,10 @@ sub reloadConf {
foreach ( qw(_macros _groups), @entryPoints ) {
$self->{$_} = [];
}
$self->afterSub( {} );
$self->afterSub( {} );
$self->aroundSub( {} );
$self->spRules( {} );
$self->hook( {} );
$self->spRules( {} );
$self->hook( {} );
# Plugin history fields
$self->pluginSessionDataToRemember( {} );

Some files were not shown because too many files have changed in this diff Show More