From 72cb2bc73e71f54c2223bb78af29fee888590b53 Mon Sep 17 00:00:00 2001 From: "mkanat%bugzilla.org" <> Date: Sun, 13 Dec 2009 20:46:24 +0000 Subject: Bug 355283: Lock out a user account on a particular IP for 30 minutes if they fail to log in 5 times from that IP. Patch by Max Kanat-Alexander r=LpSolit, a=LpSolit --- Bugzilla/Auth/Verify/DB.pm | 46 ++++++++++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 16 deletions(-) (limited to 'Bugzilla/Auth') diff --git a/Bugzilla/Auth/Verify/DB.pm b/Bugzilla/Auth/Verify/DB.pm index 695671a31..d8794472e 100644 --- a/Bugzilla/Auth/Verify/DB.pm +++ b/Bugzilla/Auth/Verify/DB.pm @@ -41,37 +41,51 @@ sub check_credentials { my $dbh = Bugzilla->dbh; my $username = $login_data->{username}; - my $user_id = login_to_id($username); + my $user = new Bugzilla::User({ name => $username }); - return { failure => AUTH_NO_SUCH_USER } unless $user_id; + return { failure => AUTH_NO_SUCH_USER } unless $user; - $login_data->{bz_username} = $username; - my $password = $login_data->{password}; + $login_data->{user} = $user; + $login_data->{bz_username} = $user->login; + + if ($user->account_is_locked_out) { + return { failure => AUTH_LOCKOUT, user => $user }; + } - trick_taint($username); - my ($real_password_crypted) = $dbh->selectrow_array( - "SELECT cryptpassword FROM profiles WHERE userid = ?", - undef, $user_id); + my $password = $login_data->{password}; + my $real_password_crypted = $user->cryptpassword; # Using the internal crypted password as the salt, # crypt the password the user entered. my $entered_password_crypted = bz_crypt($password, $real_password_crypted); - - return { failure => AUTH_LOGINFAILED } - if $entered_password_crypted ne $real_password_crypted; + + if ($entered_password_crypted ne $real_password_crypted) { + # Record the login failure + $user->note_login_failure(); + + # Immediately check if we are locked out + if ($user->account_is_locked_out) { + return { failure => AUTH_LOCKOUT, user => $user, + just_locked_out => 1 }; + } + + return { failure => AUTH_LOGINFAILED, + failure_count => scalar(@{ $user->account_ip_login_failures }), + }; + } # The user's credentials are okay, so delete any outstanding - # password tokens they may have generated. - Bugzilla::Token::DeletePasswordTokens($user_id, "user_logged_in"); + # password tokens or login failures they may have generated. + Bugzilla::Token::DeletePasswordTokens($user->id, "user_logged_in"); + $user->clear_login_failures(); # If their old password was using crypt() or some different hash # than we're using now, convert the stored password to using # whatever hashing system we're using now. my $current_algorithm = PASSWORD_DIGEST_ALGORITHM; if ($real_password_crypted !~ /{\Q$current_algorithm\E}$/) { - my $new_crypted = bz_crypt($password); - $dbh->do('UPDATE profiles SET cryptpassword = ? WHERE userid = ?', - undef, $new_crypted, $user_id); + $user->set_password($password); + $user->update(); } return $login_data; -- cgit v1.2.3-24-g4f1b