From a4a73ca90788c635edbfe34004062f85e201d122 Mon Sep 17 00:00:00 2001 From: Christophe Maudoux Date: Wed, 26 Feb 2020 22:31:22 +0100 Subject: [PATCH] Don t prompt second factor after a failed log in attempt (#2088) --- .../lib/Lemonldap/NG/Portal/Main/Display.pm | 1 + .../NG/Portal/Plugins/BruteForceProtection.pm | 25 +++++++++++-------- .../site/templates/bootstrap/login.tpl | 6 ++++- lemonldap-ng-portal/t/01-AuthDemo.t | 8 +++--- .../t/28-AuthChoice-with-captcha.t | 2 +- .../t/28-AuthChoice-with-token.t | 2 +- .../t/59-Double-cookies-Refresh-and-Logout.t | 2 +- .../t/59-Secured-cookie-Refresh-and-Logout.t | 2 +- lemonldap-ng-portal/t/61-GrantSession.t | 6 ++--- .../t/61-Session-ActivityTimeout.t | 2 +- lemonldap-ng-portal/t/61-Session-Timeout.t | 2 +- lemonldap-ng-portal/t/68-ContextSwitching.t | 4 +-- .../t/68-Impersonation-with-doubleCookies.t | 6 ++--- lemonldap-ng-portal/t/68-Impersonation.t | 6 ++--- .../t/76-2F-Ext-with-BruteForce.t | 21 ++++++---------- 15 files changed, 50 insertions(+), 45 deletions(-) diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Display.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Display.pm index 3587e463c..1e6bc059a 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Display.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Main/Display.pm @@ -395,6 +395,7 @@ sub display { DISPLAY_YUBIKEY_FORM => 0, AUTH_LOOP => [], MSG => $req->info(), + LOCKTIME => $req->lockTime(), ); } diff --git a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/BruteForceProtection.pm b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/BruteForceProtection.pm index da10aa94d..7cb8d3110 100644 --- a/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/BruteForceProtection.pm +++ b/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Plugins/BruteForceProtection.pm @@ -9,8 +9,7 @@ our $VERSION = '2.0.8'; extends 'Lemonldap::NG::Portal::Main::Plugin'; # INITIALIZATION - -use constant afterData => 'run'; +use constant afterSub => { storeHistory => 'run' }; has lockTimes => ( is => 'rw', @@ -53,15 +52,21 @@ sub init { grep { /\d+/ } split /\s+/, $self->conf->{bruteForceProtectionLockTimes}; - @{ $self->lockTimes } = ( 5, 15, 60, 300, 600 ) - unless $lockTimes; - $self->logger->warn( 'Number of incremental lock time values (' - . "$lockTimes) is higher than failed logins history (" - . $self->conf->{failedLoginNumber} - . ')' ) - if ( $lockTimes > $self->conf->{failedLoginNumber} ); + 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 (" + . $self->conf->{failedLoginNumber} + . ')' ); + splice @{ $self->lockTimes }, $self->conf->{failedLoginNumber}; + $lockTimes = $self->conf->{failedLoginNumber}; + } - my $sum = $self->conf->{bruteForceProtectionMaxAge}; + my $sum = $self->conf->{bruteForceProtectionMaxAge} * ( 1 + $self->conf->{failedLoginNumber} - $lockTimes ); $sum += $_ foreach @{ $self->lockTimes }; $self->maxAge($sum); } diff --git a/lemonldap-ng-portal/site/templates/bootstrap/login.tpl b/lemonldap-ng-portal/site/templates/bootstrap/login.tpl index 29c8ce4ed..ac03be8a9 100644 --- a/lemonldap-ng-portal/site/templates/bootstrap/login.tpl +++ b/lemonldap-ng-portal/site/templates/bootstrap/login.tpl @@ -5,7 +5,11 @@ -
alert">">
+
alert">"> + + seconds. + +
diff --git a/lemonldap-ng-portal/t/01-AuthDemo.t b/lemonldap-ng-portal/t/01-AuthDemo.t index 2c2e84f6e..6324ca5fa 100644 --- a/lemonldap-ng-portal/t/01-AuthDemo.t +++ b/lemonldap-ng-portal/t/01-AuthDemo.t @@ -25,7 +25,7 @@ ok( ), 'Get Menu' ); -ok( $res->[2]->[0] =~ /<\/span><\/div>/, +ok( $res->[2]->[0] =~ //, 'Rejected with PE_BADURL' ) or print STDERR Dumper( $res->[2]->[0] ); ok( $res->[2]->[0] =~ m%%, ' Language icons found' ) @@ -41,7 +41,7 @@ ok( ), 'Get Menu' ); -ok( $res->[2]->[0] =~ /<\/span><\/div>/, +ok( $res->[2]->[0] =~ //, 'Rejected with PE_FIRSTACCESS' ) or print STDERR Dumper( $res->[2]->[0] ); ok( $res->[2]->[0] =~ m%%, ' Language icons found' ) @@ -73,7 +73,7 @@ ok( ), 'Auth query' ); -ok( $res->[2]->[0] =~ /<\/span><\/div>/, +ok( $res->[2]->[0] =~ //, 'jdoe rejected with PE_BADCREDENTIALS' ) or print STDERR Dumper( $res->[2]->[0] ); ok( $res->[2]->[0] =~ m%Connect%, @@ -93,7 +93,7 @@ ok( 'Auth query' ); count(1); -ok( $res->[2]->[0] =~ /<\/span><\/div>/, +ok( $res->[2]->[0] =~ //, 'dwho rejected with PE_BADCREDENTIALS' ) or print STDERR Dumper( $res->[2]->[0] ); count(1); diff --git a/lemonldap-ng-portal/t/28-AuthChoice-with-captcha.t b/lemonldap-ng-portal/t/28-AuthChoice-with-captcha.t index d239c9fc4..9bc128587 100644 --- a/lemonldap-ng-portal/t/28-AuthChoice-with-captcha.t +++ b/lemonldap-ng-portal/t/28-AuthChoice-with-captcha.t @@ -70,7 +70,7 @@ m#[2]->[0] =~ /<\/span><\/div>/, + ok( $res->[2]->[0] =~ //, 'dalek rejected with PE_BADCREDENTIALS' ) or print STDERR Dumper( $res->[2]->[0] ); diff --git a/lemonldap-ng-portal/t/28-AuthChoice-with-token.t b/lemonldap-ng-portal/t/28-AuthChoice-with-token.t index c638b3ba8..300f6c819 100644 --- a/lemonldap-ng-portal/t/28-AuthChoice-with-token.t +++ b/lemonldap-ng-portal/t/28-AuthChoice-with-token.t @@ -50,7 +50,7 @@ ok( ( $host, $url, $query ) = expectForm( $res, '#', undef, 'user', 'password', 'token' ); -ok( $res->[2]->[0] =~ /<\/span><\/div>/, +ok( $res->[2]->[0] =~ //, 'dalek rejected with PE_BADCREDENTIALS' ) or print STDERR Dumper( $res->[2]->[0] ); diff --git a/lemonldap-ng-portal/t/59-Double-cookies-Refresh-and-Logout.t b/lemonldap-ng-portal/t/59-Double-cookies-Refresh-and-Logout.t index cd3130094..ed8e0cbba 100644 --- a/lemonldap-ng-portal/t/59-Double-cookies-Refresh-and-Logout.t +++ b/lemonldap-ng-portal/t/59-Double-cookies-Refresh-and-Logout.t @@ -211,7 +211,7 @@ expectOK($res); ok( $res->[2]->[0] =~ -m%
%, +m%
%, 'Dwho has been well disconnected' ) or print STDERR Dumper( $res->[2]->[0] ); count(1); diff --git a/lemonldap-ng-portal/t/59-Secured-cookie-Refresh-and-Logout.t b/lemonldap-ng-portal/t/59-Secured-cookie-Refresh-and-Logout.t index 8db638a02..e09bad7d4 100644 --- a/lemonldap-ng-portal/t/59-Secured-cookie-Refresh-and-Logout.t +++ b/lemonldap-ng-portal/t/59-Secured-cookie-Refresh-and-Logout.t @@ -121,7 +121,7 @@ expectOK($res); ok( $res->[2]->[0] =~ -m%
%, +m%
%, 'Dwho has been well disconnected' ) or print STDERR Dumper( $res->[2]->[0] ); count(1); diff --git a/lemonldap-ng-portal/t/61-GrantSession.t b/lemonldap-ng-portal/t/61-GrantSession.t index 84db1f5ed..657737183 100644 --- a/lemonldap-ng-portal/t/61-GrantSession.t +++ b/lemonldap-ng-portal/t/61-GrantSession.t @@ -50,7 +50,7 @@ ok( 'Auth query' ); count(1); -ok( $res->[2]->[0] =~ /<\/span><\/div>/, +ok( $res->[2]->[0] =~ //, 'dwho rejected with PE_BADCREDENTIALS' ) or print STDERR Dumper( $res->[2]->[0] ); count(1); @@ -105,7 +105,7 @@ ok( ); count(1); ok( - $res->[2]->[0] =~ /<\/span><\/div>/, + $res->[2]->[0] =~ //, 'rtyler rejected with PE_SESSIONNOTGRANTED' ) or print STDERR Dumper( $res->[2]->[0] ); count(1); @@ -121,7 +121,7 @@ ok( ); count(1); ok( - $res->[2]->[0] =~ /<\/span><\/div>/, + $res->[2]->[0] =~ //, 'rtyler rejected with PE_BADCREDENTIALS' ) or print STDERR Dumper( $res->[2]->[0] ); count(1); diff --git a/lemonldap-ng-portal/t/61-Session-ActivityTimeout.t b/lemonldap-ng-portal/t/61-Session-ActivityTimeout.t index 9ce10fdff..64a589da6 100644 --- a/lemonldap-ng-portal/t/61-Session-ActivityTimeout.t +++ b/lemonldap-ng-portal/t/61-Session-ActivityTimeout.t @@ -62,7 +62,7 @@ ok( ); ok( $res->[2]->[0] =~ -m%
%, +m%
%, 'Found PE_SESSIONEXPIRED code' ) or print STDERR Dumper( $res->[2]->[0] ); count(2); diff --git a/lemonldap-ng-portal/t/61-Session-Timeout.t b/lemonldap-ng-portal/t/61-Session-Timeout.t index 6515c9063..a8791b5c2 100644 --- a/lemonldap-ng-portal/t/61-Session-Timeout.t +++ b/lemonldap-ng-portal/t/61-Session-Timeout.t @@ -61,7 +61,7 @@ ok( ); ok( $res->[2]->[0] =~ -m%
%, +m%
%, 'Found PE_SESSIONEXPIRED code' ) or print STDERR Dumper( $res->[2]->[0] ); count(2); diff --git a/lemonldap-ng-portal/t/68-ContextSwitching.t b/lemonldap-ng-portal/t/68-ContextSwitching.t index 2f32cfd08..02694b9fc 100644 --- a/lemonldap-ng-portal/t/68-ContextSwitching.t +++ b/lemonldap-ng-portal/t/68-ContextSwitching.t @@ -375,7 +375,7 @@ ok( ); count(6); -ok( $res->[2]->[0] =~ m%%, 'Found PE_SESSIONEXPIRED' ) +ok( $res->[2]->[0] =~ m%%, 'Found PE_SESSIONEXPIRED' ) or explain( $res->[2]->[0], 'Sessuion expired' ); ok( $res = $client->_get( @@ -403,7 +403,7 @@ expectOK($res); ok( $res->[2]->[0] =~ -m%
%, +m%
%, 'Dwho has been well disconnected' ) or print STDERR Dumper( $res->[2]->[0] ); count(2); diff --git a/lemonldap-ng-portal/t/68-Impersonation-with-doubleCookies.t b/lemonldap-ng-portal/t/68-Impersonation-with-doubleCookies.t index 887a92fba..9784a3fa9 100644 --- a/lemonldap-ng-portal/t/68-Impersonation-with-doubleCookies.t +++ b/lemonldap-ng-portal/t/68-Impersonation-with-doubleCookies.t @@ -55,7 +55,7 @@ ok( ), 'Auth query' ); -ok( $res->[2]->[0] =~ m%%, ' PE40 found' ) +ok( $res->[2]->[0] =~ m%%, ' PE40 found' ) or explain( $res->[2]->[0], "PE40 - Bad formed user" ); count(2); @@ -83,7 +83,7 @@ ok( ); ok( $res->[2]->[0] =~ -m%
%, +m%
%, ' PE5 found' ) or explain( $res->[2]->[0], "PE5 - Forbidden identity" ); count(2); @@ -112,7 +112,7 @@ ok( ); ok( $res->[2]->[0] =~ -m%
%, +m%
%, ' PE93 found' ) or explain( $res->[2]->[0], "PE93 - Impersonation service not allowed" ); count(2); diff --git a/lemonldap-ng-portal/t/68-Impersonation.t b/lemonldap-ng-portal/t/68-Impersonation.t index eaebc6716..1d8d206e3 100644 --- a/lemonldap-ng-portal/t/68-Impersonation.t +++ b/lemonldap-ng-portal/t/68-Impersonation.t @@ -54,7 +54,7 @@ ok( ), 'Auth query' ); -ok( $res->[2]->[0] =~ m%%, ' PE40 found' ) +ok( $res->[2]->[0] =~ m%%, ' PE40 found' ) or explain( $res->[2]->[0], "PE40 - Bad formed user" ); count(2); @@ -82,7 +82,7 @@ ok( ); ok( $res->[2]->[0] =~ -m%
%, +m%
%, ' PE5 found' ) or explain( $res->[2]->[0], "PE5 - Forbidden identity" ); count(2); @@ -111,7 +111,7 @@ ok( ); ok( $res->[2]->[0] =~ -m%
%, +m%
%, ' PE93 found' ) or explain( $res->[2]->[0], "PE93 - Impersonation service not allowed" ); count(2); diff --git a/lemonldap-ng-portal/t/76-2F-Ext-with-BruteForce.t b/lemonldap-ng-portal/t/76-2F-Ext-with-BruteForce.t index 832698774..10502bc5e 100644 --- a/lemonldap-ng-portal/t/76-2F-Ext-with-BruteForce.t +++ b/lemonldap-ng-portal/t/76-2F-Ext-with-BruteForce.t @@ -72,11 +72,10 @@ ok( ), '4th Bad Auth query -> Rejected' ); -count(1); -ok( $res->[2]->[0] =~ /<\/span>/, 'Protection enabled' ); -count(1); +ok( $res->[2]->[0] =~ //, 'Protection enabled' ); +count(2); -# Cool down +# Count down Time::Fake->offset("+2s"); # Try to authenticate @@ -113,10 +112,8 @@ ok( ), 'Post code' ); -count(1); - -ok( $res->[2]->[0] =~ /<\/span>/, 'Protection enabled' ); -count(1); +ok( $res->[2]->[0] =~ //, 'Protection enabled' ); +count(2); # Cool down Time::Fake->offset("+6s"); @@ -143,7 +140,6 @@ ok( qr%%, 'Found EXTCODE input' ) or print STDERR Dumper( $res->[2]->[0] ); -count(1); $query =~ s/code=/code=123456/; ok( @@ -155,17 +151,16 @@ ok( ), 'Post code' ); -count(1); +count(2); my $id = expectCookie($res); ok( $res->[2]->[0] =~ /trspan="lastLogins"/, 'History found' ) or print STDERR Dumper( $res->[2]->[0] ); -count(1); my @c = ( $res->[2]->[0] =~ /127.0.0.1/gs ); -ok( @c == 5, 'Five entries found' ) +ok( @c == 6, 'Six entries found' ) or print STDERR Dumper( $res->[2]->[0] ); -count(1); +count(2); $client->logout($id); clean_sessions();