diff options
author | Yorhel <git@yorhel.nl> | 2019-05-15 20:48:53 +0200 |
---|---|---|
committer | Yorhel <git@yorhel.nl> | 2019-05-16 09:19:56 +0200 |
commit | 1cbc5107f32ec744d1834569f3885146d7282974 (patch) | |
tree | c7970b7815daf0c37db5baf6e6bb611b04759888 /lib/VNDB | |
parent | a193e240f5ea41509276ede529c68642af2ec656 (diff) |
Add password dictionary check
This affects the following:
- API login with a weak password is disallowed, affected users will have
to change their password through the website to continue using the API.
- Registration, password reset or password change forms require the new
password to not be in the dictionary.
- Attempting to log in to the website with a weak password will
force-redirect to a password change form, allowing a new password to
be set (using the weak-but-still-valid password as check).
Diffstat (limited to 'lib/VNDB')
-rw-r--r-- | lib/VNDB/Handler/Users.pm | 65 | ||||
-rw-r--r-- | lib/VNDB/Util/Auth.pm | 5 |
2 files changed, 55 insertions, 15 deletions
diff --git a/lib/VNDB/Handler/Users.pm b/lib/VNDB/Handler/Users.pm index 56664443..0177e4aa 100644 --- a/lib/VNDB/Handler/Users.pm +++ b/lib/VNDB/Handler/Users.pm @@ -6,6 +6,7 @@ use warnings; use TUWF ':html', 'xml_escape'; use VNDB::Func; use POSIX 'floor'; +use PWLookup; TUWF::register( @@ -142,11 +143,8 @@ sub userpage { } -sub login { +sub _check_throttle { my $self = shift; - - return $self->resRedirect('/', 'temp') if $self->authInfo->{id}; - my $tm = $self->dbThrottleGet(norm_ip($self->reqIP)); if($tm-time() > $self->{login_throttle}[1]) { $self->htmlHeader(title => 'Login'); @@ -165,8 +163,19 @@ sub login { end; end 'div'; $self->htmlFooter; - return; + return undef; } + $tm +} + + +sub login { + my $self = shift; + + return $self->resRedirect('/', 'temp') if $self->authInfo->{id}; + + my $tm = _check_throttle($self); + return if !defined $tm; my $ref = $self->formValidate({ param => 'ref', required => 0, default => '/'})->{ref}; @@ -180,7 +189,16 @@ sub login { if(!$frm->{_err}) { $frm->{usrname} = lc $frm->{usrname}; - return if $self->authLogin($frm->{usrname}, $frm->{usrpass}, $ref); + + my $ok = $self->authLogin($frm->{usrname}, $frm->{usrpass}, $ref); + + if($ok && $self->{password_db} && PWLookup::lookup($self->{password_db}, $frm->{usrpass})) { + my $u = $self->dbUserGet(username => $frm->{usrname})->[0]; + $self->dbUserLogout($u->{id}, $ok); # Make sure to throw away the session we just created + return $self->resRedirect("/u$u->{id}/setpass", 'post'); + } + return if $ok; + $frm->{_err} = [ 'Invalid username or password' ]; $self->dbThrottleSet(norm_ip($self->reqIP), $tm+$self->{login_throttle}[0]); } @@ -262,36 +280,55 @@ sub newpass_sent { } +# /u+/setpass has two modes: With a token (?t=xxx), to set the password after a +# 'register' or 'newpass', or without a token, after the user tried to log in +# with a weak password. sub setpass { my($self, $uid) = @_; return $self->resRedirect('/', 'temp') if $self->authInfo->{id}; - my $t = $self->formValidate({get => 't', regex => qr/^[a-f0-9]{40}$/i }); + my $t = $self->formValidate({param => 't', required => 0, regex => qr/^[a-f0-9]{40}$/i }); return $self->resNotFound if $t->{_err}; $t = $t->{t}; my $u = $self->dbUserGet(uid => $uid)->[0]; - return $self->resNotFound if !$u || !$self->authIsValidToken($u->{id}, $t); + return $self->resNotFound if !$u || ($t && !$self->authIsValidToken($u->{id}, $t)); + + my $tm = !$t && _check_throttle($self); + return if !$t && !defined $tm; my $frm; if($self->reqMethod eq 'POST') { - return if !$self->authCheckCode("/u$u->{id}/setpass?t=$t"); + return if !$self->authCheckCode("/u$u->{id}/setpass"); $frm = $self->formValidate( + $t ? () : ( + { post => 'curpass', minlength => 4, maxlength => 500 }, + ), { post => 'usrpass', minlength => 4, maxlength => 500 }, { post => 'usrpass2', minlength => 4, maxlength => 500 }, ); push @{$frm->{_err}}, 'Passwords do not match' if $frm->{usrpass} ne $frm->{usrpass2}; + push @{$frm->{_err}}, 'The chosen password is too weak, please choose a stronger password' + if $self->{password_db} && PWLookup::lookup($self->{password_db}, $frm->{usrpass}); if(!$frm->{_err}) { $self->dbUserEdit($uid, email_confirmed => 1); - return $self->authSetPass($uid, $frm->{usrpass}, "/u$uid", token => $t) + return if $self->authSetPass($uid, $frm->{usrpass}, "/u$uid", $t ? (token => $t) : (pass => $frm->{curpass})); + $self->dbThrottleSet(norm_ip($self->reqIP), $tm+$self->{login_throttle}[0]); + push @{$frm->{_err}}, 'Invalid password'; } } $self->htmlHeader(title => "Set password for $u->{username}", noindex => 1); - $self->htmlForm({ frm => $frm, action => "/u$u->{id}/setpass?t=$t" }, setpass => [ "Set password for $u->{username}", - [ static => nolabel => 1, content => 'Now you can set a password for your account.' - .' You will be logged in automatically after your password has been saved.' ], + $self->htmlForm({ frm => $frm, action => "/u$u->{id}/setpass" }, setpass => [ "Set password for $u->{username}", + [ hidden => short => 't', value => $t||'' ], + $t ? ( + [ static => nolabel => 1, content => 'Now you can set a password for your account.' + .' You will be logged in automatically after your password has been saved.' ], + ) : ( + [ static => nolabel => 1, content => "Your current password is too weak, please change your password to continue.<br><br>" ], + [ passwd => short => 'curpass', name => 'Current password' ], + ), [ passwd => short => 'usrpass', name => 'Password' ], [ passwd => short => 'usrpass2', name => 'Confirm password' ], ]); @@ -411,6 +448,8 @@ sub edit { ); push @{$frm->{_err}}, 'Passwords do not match' if ($frm->{usrpass} || $frm->{usrpass2}) && (!$frm->{usrpass} || !$frm->{usrpass2} || $frm->{usrpass} ne $frm->{usrpass2}); + push @{$frm->{_err}}, 'The chosen password is too weak, please choose a stronger password' + if $self->{password_db} && PWLookup::lookup($self->{password_db}, $frm->{usrpass}); if(!$frm->{_err}) { $frm->{skin} = '' if $frm->{skin} eq $self->{skin_default}; diff --git a/lib/VNDB/Util/Auth.pm b/lib/VNDB/Util/Auth.pm index e3ee20eb..bda13158 100644 --- a/lib/VNDB/Util/Auth.pm +++ b/lib/VNDB/Util/Auth.pm @@ -81,11 +81,12 @@ sub _createsession { my($self, $uid, $encpass, $url) = @_; my $token = urandom(20); - return 0 if !$self->dbUserLogin($uid, $encpass, sha1 $token); + my $token_e = sha1 $token; + return 0 if !$self->dbUserLogin($uid, $encpass, $token_e); $self->resRedirect($url, 'post'); $self->resCookie(auth => unpack('H*', $token).'.'.$uid, httponly => 1, expires => time + 31536000); # keep the cookie for 1 year - return 1; + return $token_e; } |