Merge branch '2276' into 'v2.0'
2276 See merge request lemonldap-ng/lemonldap-ng!159
This commit is contained in:
commit
5d056699c4
|
@ -20,6 +20,15 @@ Go in Manager, ``General Parameters`` » ``Advanced Parameters`` »
|
|||
``Security`` » ``Brute-force attack protection`` » ``Activation``\ and
|
||||
set to ``On``.
|
||||
|
||||
- **Parameters**:
|
||||
|
||||
- **Activation**: Enable/disable brute force attack protection
|
||||
- **Lock time**: Waiting time before another login attempt
|
||||
- **Allowed failed login**: Number of failed login attempts allowed before account is locked
|
||||
- **Incremental lock**: Enable/disable incremental lock times
|
||||
- **Incremental lock times**: List of comma separated lock time values in seconds
|
||||
|
||||
|
||||
Incremental lock time enabled
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -35,33 +44,29 @@ in ``lemonldap-ng.ini`` [portal] section:
|
|||
[portal]
|
||||
bruteForceProtectionIncrementalTempo = 1
|
||||
|
||||
Lock time increases between each failed login attempt. To modify lock
|
||||
time values ('5 15 60 300 600' seconds by default) or max lock time
|
||||
value (900 seconds by default) edit ``lemonldap-ng.ini`` in [portal]
|
||||
section:
|
||||
Lock time increases between each failed login attempt after allowed failed logins.
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[portal]
|
||||
bruteForceProtectionLockTimes = '5 15 60 300 600'
|
||||
bruteForceProtectionLockTimes = 5, 15, 60, 300, 600
|
||||
bruteForceProtectionMaxLockTime = 900
|
||||
|
||||
|
||||
.. note::
|
||||
|
||||
Max lock time value is used by this plugin if a lock time is
|
||||
missing (number of failed logins higher than listed lock time values).
|
||||
Max lock time value is used if a lock time is missing
|
||||
(number of failed logins higher than listed lock time values).
|
||||
Lock time values can not be higher than max lock time.
|
||||
|
||||
|
||||
Incremental lock time disabled
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
After ``bruteForceProtectionMaxFailed`` failed login attempts, user must
|
||||
wait ``bruteForceProtectionTempo`` seconds before trying to log in
|
||||
again. To modify waiting time (30 seconds by default), MaxAge between
|
||||
current and last stored failed login (300 seconds by default) or number
|
||||
of allowed failed login attempts (3 by default) edit
|
||||
``lemonldap-ng.ini`` in [portal] section:
|
||||
After allowed failed login attempts, user must
|
||||
wait the lock time before trying to log in again.
|
||||
To modify delta (MaxAge) between current and last stored
|
||||
failed login (300 seconds by default) edit ``lemonldap-ng.ini`` in [portal] section:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
|
@ -72,7 +77,12 @@ of allowed failed login attempts (3 by default) edit
|
|||
|
||||
|
||||
.. attention::
|
||||
Number of failed login attempts history might be also higher than
|
||||
number of incremental lock time value plus allowed failed login attempts.
|
||||
Incremental lock time values list will be truncated if not.
|
||||
|
||||
|
||||
.. danger::
|
||||
Number of failed login attempts stored in history MUST
|
||||
be higher than allowed failed logins for this plugin takes effect.
|
||||
See :doc:`History plugin<loginhistory>`
|
|
@ -19,7 +19,7 @@ sub defaultValues {
|
|||
'authentication' => 'Demo',
|
||||
'available2F' => 'UTOTP,TOTP,U2F,REST,Mail2F,Ext2F,Yubikey,Radius',
|
||||
'available2FSelfRegistration' => 'TOTP,U2F,Yubikey',
|
||||
'bruteForceProtectionLockTimes' => '5 15 60 300 600',
|
||||
'bruteForceProtectionLockTimes' => '5, 15, 60, 300, 600',
|
||||
'bruteForceProtectionMaxAge' => 300,
|
||||
'bruteForceProtectionMaxFailed' => 3,
|
||||
'bruteForceProtectionMaxLockTime' => 900,
|
||||
|
|
|
@ -636,7 +636,7 @@ sub attributes {
|
|||
'type' => 'bool'
|
||||
},
|
||||
'bruteForceProtectionLockTimes' => {
|
||||
'default' => '5 15 60 300 600',
|
||||
'default' => '5, 15, 60, 300, 600',
|
||||
'type' => 'text'
|
||||
},
|
||||
'bruteForceProtectionMaxAge' => {
|
||||
|
|
|
@ -833,7 +833,7 @@ sub attributes {
|
|||
},
|
||||
bruteForceProtectionLockTimes => {
|
||||
type => 'text',
|
||||
default => '5 15 60 300 600',
|
||||
default => '5, 15, 60, 300, 600',
|
||||
documentation =>
|
||||
'Incremental lock time values for brute force attack protection',
|
||||
},
|
||||
|
|
|
@ -630,7 +630,8 @@ sub tree {
|
|||
'notificationStorageOptions',
|
||||
{
|
||||
title => 'serverNotification',
|
||||
help => 'notifications.html#notification-server',
|
||||
help =>
|
||||
'notifications.html#notification-server',
|
||||
nodes => [
|
||||
'notificationServer',
|
||||
'notificationDefaultCond',
|
||||
|
@ -959,7 +960,10 @@ sub tree {
|
|||
form => 'simpleInputContainer',
|
||||
nodes => [
|
||||
'bruteForceProtection',
|
||||
'bruteForceProtectionTempo',
|
||||
'bruteForceProtectionMaxFailed',
|
||||
'bruteForceProtectionIncrementalTempo',
|
||||
'bruteForceProtectionLockTimes',
|
||||
]
|
||||
},
|
||||
'lwpOpts',
|
||||
|
|
|
@ -254,8 +254,6 @@ sub tests {
|
|||
return ( 1, "Cookie TTL should be higher or equal than one hour" )
|
||||
unless ( $conf->{cookieExpiration} >= 3600
|
||||
|| $conf->{cookieExpiration} == 0 );
|
||||
|
||||
# Return
|
||||
return 1;
|
||||
},
|
||||
|
||||
|
@ -265,8 +263,6 @@ sub tests {
|
|||
return ( -1, "Session timeout should be higher than ten minutes" )
|
||||
unless ( $conf->{timeout} > 600
|
||||
|| $conf->{timeout} == 0 );
|
||||
|
||||
# Return
|
||||
return 1;
|
||||
},
|
||||
|
||||
|
@ -278,8 +274,6 @@ sub tests {
|
|||
)
|
||||
unless ( $conf->{timeoutActivity} > 59
|
||||
|| $conf->{timeoutActivity} == 0 );
|
||||
|
||||
# Return
|
||||
return 1;
|
||||
},
|
||||
|
||||
|
@ -292,8 +286,6 @@ sub tests {
|
|||
if ( $conf->{timeoutActivity}
|
||||
and $conf->{timeoutActivity} <=
|
||||
$conf->{timeoutActivityInterval} );
|
||||
|
||||
# Return
|
||||
return 1;
|
||||
},
|
||||
|
||||
|
@ -338,8 +330,6 @@ sub tests {
|
|||
return ( 1, "SMTP authentication failed" )
|
||||
unless $smtp->auth( $conf->{SMTPAuthUser},
|
||||
$conf->{SMTPAuthPass} );
|
||||
|
||||
# Return
|
||||
return 1;
|
||||
},
|
||||
|
||||
|
@ -441,8 +431,6 @@ sub tests {
|
|||
unless ( $conf->{combination} );
|
||||
return ( 0, 'userDB must be set to "Same" to enable Combination' )
|
||||
unless ( $conf->{userDB} eq "Same" );
|
||||
|
||||
# Return
|
||||
return 1;
|
||||
},
|
||||
|
||||
|
@ -482,8 +470,6 @@ sub tests {
|
|||
"Auth::Yubikey_WebClient module is required to enable Yubikey"
|
||||
) if ($@);
|
||||
}
|
||||
|
||||
# Return
|
||||
return 1;
|
||||
},
|
||||
|
||||
|
@ -521,8 +507,6 @@ sub tests {
|
|||
unless ( $conf->{totp2fRange} );
|
||||
return ( 1, "TOTP interval should be higher than 10s" )
|
||||
unless ( $conf->{totp2fInterval} > 10 );
|
||||
|
||||
# Return
|
||||
return 1;
|
||||
},
|
||||
|
||||
|
@ -570,7 +554,6 @@ sub tests {
|
|||
|| $conf->{'totp2fSelfRegistration'} );
|
||||
$msg = "A self registrable module should be enabled to require 2FA"
|
||||
unless ($ok);
|
||||
|
||||
return ( 1, $msg );
|
||||
},
|
||||
|
||||
|
@ -583,8 +566,6 @@ sub tests {
|
|||
return ( 0, "External 2F Validate command must be set" )
|
||||
unless ( defined $conf->{ext2FValidateCommand} );
|
||||
}
|
||||
|
||||
# Return
|
||||
return 1;
|
||||
},
|
||||
|
||||
|
@ -595,8 +576,6 @@ sub tests {
|
|||
unless ( $conf->{formTimeout} > 30 );
|
||||
return ( 1, "XSRF form token TTL should not be higher than 2mn" )
|
||||
if ( $conf->{formTimeout} > 120 );
|
||||
|
||||
# Return
|
||||
return 1;
|
||||
},
|
||||
|
||||
|
@ -607,8 +586,6 @@ sub tests {
|
|||
unless ( $conf->{issuersTimeout} > 30 );
|
||||
return ( 1, "Issuers token TTL should not be higher than 2mn" )
|
||||
if ( $conf->{issuersTimeout} > 120 );
|
||||
|
||||
# Return
|
||||
return 1;
|
||||
},
|
||||
|
||||
|
@ -617,8 +594,6 @@ sub tests {
|
|||
return 1 unless ( $conf->{portalDisplayResetPassword} );
|
||||
return ( 1, "Number of reset password retries should not be null" )
|
||||
unless ( $conf->{passwordResetAllowedRetries} );
|
||||
|
||||
# Return
|
||||
return 1;
|
||||
},
|
||||
|
||||
|
@ -641,8 +616,18 @@ sub tests {
|
|||
return ( 1,
|
||||
'Number of failed logins must be higher than 2 to enable "BruteForceProtection" plugin'
|
||||
) unless ( $conf->{failedLoginNumber} > 2 );
|
||||
|
||||
# Return
|
||||
return ( 1,
|
||||
'Number of failed logins history must be higher than allowed failed logins plus lock time values'
|
||||
)
|
||||
if ( $conf->{bruteForceProtectionIncrementalTempo}
|
||||
&& $conf->{failedLoginNumber} <=
|
||||
$conf->{bruteForceProtectionMaxFailed} +
|
||||
$conf->{bruteForceProtectionLockTimes} );
|
||||
return ( 1,
|
||||
'Number of failed logins history must be higher than allowed failed logins'
|
||||
)
|
||||
unless ( $conf->{failedLoginNumber} >
|
||||
$conf->{bruteForceProtectionMaxFailed} );
|
||||
return 1;
|
||||
},
|
||||
|
||||
|
@ -654,8 +639,6 @@ sub tests {
|
|||
)
|
||||
unless ( $conf->{requireToken}
|
||||
or $conf->{captcha_mail_enabled} );
|
||||
|
||||
# Return
|
||||
return 1;
|
||||
},
|
||||
|
||||
|
@ -666,8 +649,6 @@ sub tests {
|
|||
)
|
||||
if ( $conf->{impersonationRule}
|
||||
&& $conf->{contextSwitchingRule} );
|
||||
|
||||
# Return
|
||||
return 1;
|
||||
},
|
||||
|
||||
|
@ -691,8 +672,6 @@ sub tests {
|
|||
return ( 1,
|
||||
"BruteForceProtection plugin enabled WITHOUT persistent session storage"
|
||||
) if ( $conf->{bruteForceProtection} );
|
||||
|
||||
# Return
|
||||
return 1;
|
||||
},
|
||||
|
||||
|
@ -707,8 +686,6 @@ sub tests {
|
|||
return ( 1,
|
||||
"XML::LibXSLT module is required to enable old format notifications"
|
||||
) if ($@);
|
||||
|
||||
# Return
|
||||
return 1;
|
||||
},
|
||||
|
||||
|
@ -722,8 +699,6 @@ sub tests {
|
|||
return ( 1,
|
||||
"DateTime::Format::RFC3339 module is required to enable CertificateResetByMail plugin"
|
||||
) if ($@);
|
||||
|
||||
# Return
|
||||
return 1;
|
||||
},
|
||||
|
||||
|
@ -867,7 +842,6 @@ sub tests {
|
|||
and $conf->{portal} !~ /^https:/ );
|
||||
return 1;
|
||||
},
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -106,7 +106,10 @@
|
|||
"browseTree":"تصفح الهيكل",
|
||||
"bruteForceProtection":"تفعيل",
|
||||
"bruteForceAttackProtection":"Brute-force attack protection",
|
||||
"bruteForceProtectionIncrementalTempo":"Incremental lock times",
|
||||
"bruteForceProtectionIncrementalTempo":"Incremental lock",
|
||||
"bruteForceProtectionLockTimes":"Incremental lock times",
|
||||
"bruteForceProtectionMaxFailed":"Allowed failed logins",
|
||||
"bruteForceProtectionTempo":"Lock time",
|
||||
"cancel":"إلغاء",
|
||||
"captcha_login_enabled":"التفعيل في استمارة تسجيل الدخول",
|
||||
"captcha_mail_enabled":"التفعيل في إعادة تعيين كلمة المرور بواسطة استمارة البريد",
|
||||
|
|
|
@ -106,7 +106,10 @@
|
|||
"browseTree":"Browse tree",
|
||||
"bruteForceProtection":"Activation",
|
||||
"bruteForceAttackProtection":"Brute-force attack protection",
|
||||
"bruteForceProtectionIncrementalTempo":"Incremental lock times",
|
||||
"bruteForceProtectionIncrementalTempo":"Incremental lock",
|
||||
"bruteForceProtectionLockTimes":"Incremental lock times",
|
||||
"bruteForceProtectionMaxFailed":"Allowed failed logins",
|
||||
"bruteForceProtectionTempo":"Lock time",
|
||||
"cancel":"Abbrechen",
|
||||
"captcha_login_enabled":"Activation in login form",
|
||||
"captcha_mail_enabled":"Activation in password reset by mail form",
|
||||
|
|
|
@ -106,7 +106,10 @@
|
|||
"browseTree":"Browse tree",
|
||||
"bruteForceProtection":"Activation",
|
||||
"bruteForceAttackProtection":"Brute-force attack protection",
|
||||
"bruteForceProtectionIncrementalTempo":"Incremental lock times",
|
||||
"bruteForceProtectionIncrementalTempo":"Incremental lock",
|
||||
"bruteForceProtectionLockTimes":"Incremental lock times",
|
||||
"bruteForceProtectionMaxFailed":"Allowed failed logins",
|
||||
"bruteForceProtectionTempo":"Lock time",
|
||||
"cancel":"Cancel",
|
||||
"captcha_login_enabled":"Activation in login form",
|
||||
"captcha_mail_enabled":"Activation in password reset by mail form",
|
||||
|
|
|
@ -106,7 +106,10 @@
|
|||
"browseTree":"Parcourir l'arbre",
|
||||
"bruteForceProtection":"Activation",
|
||||
"bruteForceAttackProtection":"Protection contre les attaques par force brute",
|
||||
"bruteForceProtectionIncrementalTempo":"Temps de verrouillage incrémentiels",
|
||||
"bruteForceProtectionIncrementalTempo":"Verrouillage incrémentiel",
|
||||
"bruteForceProtectionLockTimes":"Temps de verrouillage incrémentiel",
|
||||
"bruteForceProtectionMaxFailed":"Nombre d'échecs de connexion autorisés",
|
||||
"bruteForceProtectionTempo":"Temps de verrouillage",
|
||||
"cancel":"Annuler",
|
||||
"captcha_login_enabled":"Activation dans le formulaire d'authentification",
|
||||
"captcha_mail_enabled":"Activation dans le formulaire de réinitialisation par mail",
|
||||
|
|
|
@ -106,7 +106,10 @@
|
|||
"browseTree":"Naviga albero",
|
||||
"bruteForceProtection":"Attivazione",
|
||||
"bruteForceAttackProtection":"Brute-force attack protection",
|
||||
"bruteForceProtectionIncrementalTempo":"Incremental lock times",
|
||||
"bruteForceProtectionIncrementalTempo":"Incremental lock",
|
||||
"bruteForceProtectionLockTimes":"Incremental lock times",
|
||||
"bruteForceProtectionMaxFailed":"Allowed failed logins",
|
||||
"bruteForceProtectionTempo":"Lock time",
|
||||
"cancel":"Cancella",
|
||||
"captcha_login_enabled":"Attivazione nel modulo di login",
|
||||
"captcha_mail_enabled":"Attivazione della reimpostazione della password tramite modulo di posta",
|
||||
|
|
|
@ -106,7 +106,10 @@
|
|||
"browseTree":"Przeglądaj drzewo",
|
||||
"bruteForceProtection":"Aktywacja",
|
||||
"bruteForceAttackProtection":"Ochrona przed atakiem siłowym",
|
||||
"bruteForceProtectionIncrementalTempo":"Przyrostowe czasy blokady",
|
||||
"bruteForceProtectionIncrementalTempo":"Incremental lock",
|
||||
"bruteForceProtectionLockTimes":"Incremental lock times",
|
||||
"bruteForceProtectionMaxFailed":"Allowed failed logins",
|
||||
"bruteForceProtectionTempo":"Lock time",
|
||||
"cancel":"Anuluj",
|
||||
"captcha_login_enabled":"Aktywacja w formularzu logowania",
|
||||
"captcha_mail_enabled":"Aktywacja przy resetowaniu hasła za pomocą formularza pocztowego",
|
||||
|
|
|
@ -106,7 +106,10 @@
|
|||
"browseTree":"Ağaca göz at",
|
||||
"bruteForceProtection":"Aktivasyon",
|
||||
"bruteForceAttackProtection":"Kaba kuvvet saldırı koruması",
|
||||
"bruteForceProtectionIncrementalTempo":"Artan gecikme zamanı",
|
||||
"bruteForceProtectionIncrementalTempo":"Incremental lock",
|
||||
"bruteForceProtectionLockTimes":"Incremental lock times",
|
||||
"bruteForceProtectionMaxFailed":"Allowed failed logins",
|
||||
"bruteForceProtectionTempo":"Lock time",
|
||||
"cancel":"İptal Et",
|
||||
"captcha_login_enabled":"Giriş formunda aktivasyon",
|
||||
"captcha_mail_enabled":"E-posta formu tarafından parola sıfırlamada aktivasyon",
|
||||
|
|
|
@ -106,7 +106,10 @@
|
|||
"browseTree":"Duyệt cây",
|
||||
"bruteForceProtection":"Kích hoạt",
|
||||
"bruteForceAttackProtection":"Brute-force attack protection",
|
||||
"bruteForceProtectionIncrementalTempo":"Incremental lock times",
|
||||
"bruteForceProtectionIncrementalTempo":"Incremental lock",
|
||||
"bruteForceProtectionLockTimes":"Incremental lock times",
|
||||
"bruteForceProtectionMaxFailed":"Allowed failed logins",
|
||||
"bruteForceProtectionTempo":"Lock time",
|
||||
"cancel":"Hủy",
|
||||
"captcha_login_enabled":"Kích hoạt ở dạng đăng nhập",
|
||||
"captcha_mail_enabled":"Kích hoạt đặt lại mật khẩu bằng biểu mẫu thư",
|
||||
|
|
|
@ -106,7 +106,10 @@
|
|||
"browseTree":"浏览树",
|
||||
"bruteForceProtection":"激活",
|
||||
"bruteForceAttackProtection":"Brute-force attack protection",
|
||||
"bruteForceProtectionIncrementalTempo":"Incremental lock times",
|
||||
"bruteForceProtectionIncrementalTempo":"Incremental lock",
|
||||
"bruteForceProtectionLockTimes":"Incremental lock times",
|
||||
"bruteForceProtectionMaxFailed":"Allowed failed logins",
|
||||
"bruteForceProtectionTempo":"Lock time",
|
||||
"cancel":"取消",
|
||||
"captcha_login_enabled":" 登录激活",
|
||||
"captcha_mail_enabled":"通过邮件进行密码重置 激活",
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -24,10 +24,6 @@ my @notManagedAttributes = (
|
|||
'sfEngine', 'available2FSelfRegistration', 'available2F', 'max2FDevices',
|
||||
'max2FDevicesNameLength',
|
||||
|
||||
# Brute force attack protection parameters
|
||||
'bruteForceProtectionMaxAge', 'bruteForceProtectionTempo',
|
||||
'bruteForceProtectionMaxFailed',
|
||||
|
||||
# Handlers
|
||||
'handlerInternalCache', 'handlerServiceTokenTTL',
|
||||
|
||||
|
@ -42,8 +38,8 @@ my @notManagedAttributes = (
|
|||
'syslogFacility', 'userLogger', 'logLevel',
|
||||
|
||||
# Plugins parameters
|
||||
'notificationsMaxRetrieve', 'persistentSessionAttributes',
|
||||
'bruteForceProtectionLockTimes', 'bruteForceProtectionMaxLockTime',
|
||||
'notificationsMaxRetrieve', 'persistentSessionAttributes',
|
||||
'bruteForceProtectionMaxAge', 'bruteForceProtectionMaxLockTime',
|
||||
|
||||
# PSGI/CGI protection (must be set in lemonldap-ng.ini)
|
||||
'protection',
|
||||
|
|
|
@ -4,7 +4,7 @@ use strict;
|
|||
use Mouse;
|
||||
use Lemonldap::NG::Portal::Main::Constants qw(PE_OK PE_WAIT);
|
||||
|
||||
our $VERSION = '2.0.8';
|
||||
our $VERSION = '2.0.9';
|
||||
|
||||
extends 'Lemonldap::NG::Portal::Main::Plugin';
|
||||
|
||||
|
@ -38,9 +38,9 @@ sub init {
|
|||
unless ( $self->conf->{failedLoginNumber} >
|
||||
$self->conf->{bruteForceProtectionMaxFailed} )
|
||||
{
|
||||
$self->logger->error( 'failedLoginNumber('
|
||||
$self->logger->error( 'Number of failed logins history ('
|
||||
. $self->conf->{failedLoginNumber}
|
||||
. ') must be higher than bruteForceProtectionMaxFailed('
|
||||
. ') must be higher than allowed failed logins attempt ('
|
||||
. $self->conf->{bruteForceProtectionMaxFailed}
|
||||
. ')' );
|
||||
return 0;
|
||||
|
@ -48,20 +48,33 @@ sub init {
|
|||
if ( $self->conf->{bruteForceProtectionIncrementalTempo} ) {
|
||||
my $lockTimes = @{ $self->lockTimes } =
|
||||
sort { $a <=> $b }
|
||||
map { $_ < $self->conf->{bruteForceProtectionMaxLockTime} ? $_ : () }
|
||||
map {
|
||||
$_ =~ s/\D//;
|
||||
$_ < $self->conf->{bruteForceProtectionMaxLockTime} ? $_ : ()
|
||||
}
|
||||
grep { /\d+/ }
|
||||
split /\s+/, $self->conf->{bruteForceProtectionLockTimes};
|
||||
split /\s*,\s*/, $self->conf->{bruteForceProtectionLockTimes};
|
||||
|
||||
unless ($lockTimes) {
|
||||
@{ $self->lockTimes } = ( 5, 15, 60, 300, 600 );
|
||||
$lockTimes = 5;
|
||||
}
|
||||
|
||||
if ( $lockTimes > $self->conf->{failedLoginNumber} ) {
|
||||
$self->logger->warn( 'Number of incremental lock time values ('
|
||||
. "$lockTimes) is higher than failed logins history ("
|
||||
for (
|
||||
my $i = 1 ;
|
||||
$i <= $self->conf->{bruteForceProtectionMaxFailed} ;
|
||||
$i++
|
||||
)
|
||||
{
|
||||
unshift @{ $self->lockTimes }, 0;
|
||||
$lockTimes++;
|
||||
}
|
||||
|
||||
unless ( $lockTimes < $self->conf->{failedLoginNumber} ) {
|
||||
$self->logger->warn( 'Number failed logins history ('
|
||||
. $self->conf->{failedLoginNumber}
|
||||
. ')' );
|
||||
. ') must be higher than incremental lock time values plus allowed failed logins attempt ('
|
||||
. "$lockTimes)" );
|
||||
splice @{ $self->lockTimes }, $self->conf->{failedLoginNumber};
|
||||
$lockTimes = $self->conf->{failedLoginNumber};
|
||||
}
|
||||
|
@ -96,9 +109,9 @@ sub run {
|
|||
my $delta = $now - $lastFailedLoginEpoch;
|
||||
$self->logger->debug(" -> Delta = $delta");
|
||||
my $waitingTime = $self->lockTimes->[ $countFailed - 1 ]
|
||||
|| $self->conf->{bruteForceProtectionMaxLockTime};
|
||||
// $self->conf->{bruteForceProtectionMaxLockTime};
|
||||
$self->logger->debug(" -> Waiting time = $waitingTime");
|
||||
unless ( $delta > $waitingTime ) {
|
||||
if ( $waitingTime && $delta <= $waitingTime ) {
|
||||
$self->logger->debug("BruteForceProtection enabled");
|
||||
$req->lockTime($waitingTime);
|
||||
return PE_WAIT;
|
||||
|
|
|
@ -26,6 +26,7 @@ SKIP: {
|
|||
totp2fSelfRegistration => 1,
|
||||
totp2fActivation => 1,
|
||||
failedLoginNumber => 4,
|
||||
bruteForceProtectionMaxFailed => 0,
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
|
@ -16,9 +16,10 @@ my $client = LLNG::Manager::Test->new( {
|
|||
loginHistoryEnabled => 1,
|
||||
bruteForceProtection => 1,
|
||||
bruteForceProtectionIncrementalTempo => 1,
|
||||
failedLoginNumber => 4,
|
||||
failedLoginNumber => 6,
|
||||
bruteForceProtectionMaxLockTime => 300,
|
||||
bruteForceProtectionLockTimes => '5 500 bad 20 10 ',
|
||||
bruteForceProtectionLockTimes => '5 , 500, bad ,20, 10 ',
|
||||
bruteForceProtectionMaxFailed => 2,
|
||||
}
|
||||
}
|
||||
);
|
||||
|
@ -38,6 +39,36 @@ my $id = expectCookie($res);
|
|||
expectRedirection( $res, 'http://auth.example.com/' );
|
||||
$client->logout($id);
|
||||
|
||||
## First allowed failed login
|
||||
ok(
|
||||
$res = $client->_post(
|
||||
'/',
|
||||
IO::String->new('user=dwho&password=ohwd'),
|
||||
length => 23,
|
||||
accept => 'text/html',
|
||||
),
|
||||
'1st allowed Bad Auth query'
|
||||
);
|
||||
ok( $res->[2]->[0] =~ /<span trmsg="5"><\/span>/,
|
||||
'Bad credential' )
|
||||
or print STDERR Dumper( $res->[2]->[0] );
|
||||
count(2);
|
||||
|
||||
## Second allowed failed login
|
||||
ok(
|
||||
$res = $client->_post(
|
||||
'/',
|
||||
IO::String->new('user=dwho&password=ohwd'),
|
||||
length => 23,
|
||||
accept => 'text/html',
|
||||
),
|
||||
'2nd allowed Bad Auth query'
|
||||
);
|
||||
ok( $res->[2]->[0] =~ /<span trmsg="5"><\/span>/,
|
||||
'Bad credential' )
|
||||
or print STDERR Dumper( $res->[2]->[0] );
|
||||
count(2);
|
||||
|
||||
## First failed connection
|
||||
ok(
|
||||
$res = $client->_post(
|
||||
|
|
Loading…
Reference in New Issue
Block a user