Commit 4663186f authored by Reed Loden's avatar Reed Loden

Bug 785283 - Support increased values for PASSWORD_SALT_LENGTH without breaking…

Bug 785283 - Support increased values for PASSWORD_SALT_LENGTH without breaking compat with old hashes [r=LpSolit a=LpSolit]
parent a9fb9c4b
...@@ -66,11 +66,22 @@ sub check_credentials { ...@@ -66,11 +66,22 @@ sub check_credentials {
Bugzilla::Token::DeletePasswordTokens($user->id, "user_logged_in"); Bugzilla::Token::DeletePasswordTokens($user->id, "user_logged_in");
$user->clear_login_failures(); $user->clear_login_failures();
my $update_password = 0;
# If their old password was using crypt() or some different hash # If their old password was using crypt() or some different hash
# than we're using now, convert the stored password to using # than we're using now, convert the stored password to using
# whatever hashing system we're using now. # whatever hashing system we're using now.
my $current_algorithm = PASSWORD_DIGEST_ALGORITHM; my $current_algorithm = PASSWORD_DIGEST_ALGORITHM;
if ($real_password_crypted !~ /{\Q$current_algorithm\E}$/) { $update_password = 1 if ($real_password_crypted !~ /{\Q$current_algorithm\E}$/);
# If their old password was using a different length salt than what
# we're using now, update the password to use the new salt length.
if ($real_password_crypted =~ /^([^,]+),/) {
$update_password = 1 if (length($1) != PASSWORD_SALT_LENGTH);
}
# If needed, update the user's password.
if ($update_password) {
$user->set_password($password); $user->set_password($password);
$user->update(); $user->update();
} }
......
...@@ -567,10 +567,10 @@ use constant MAX_QUIP_LENGTH => 512; ...@@ -567,10 +567,10 @@ use constant MAX_QUIP_LENGTH => 512;
# This is the name of the algorithm used to hash passwords before storing # This is the name of the algorithm used to hash passwords before storing
# them in the database. This can be any string that is valid to pass to # them in the database. This can be any string that is valid to pass to
# Perl's "Digest" module. Note that if you change this, it won't take # Perl's "Digest" module. Note that if you change this, it won't take
# effect until a user changes his password. # effect until a user logs in or changes his password.
use constant PASSWORD_DIGEST_ALGORITHM => 'SHA-256'; use constant PASSWORD_DIGEST_ALGORITHM => 'SHA-256';
# How long of a salt should we use? Note that if you change this, none # How long of a salt should we use? Note that if you change this, it
# of your users will be able to log in until they reset their passwords. # won't take effect until a user logs in or changes his password.
use constant PASSWORD_SALT_LENGTH => 8; use constant PASSWORD_SALT_LENGTH => 8;
# Certain scripts redirect to GET even if the form was submitted originally # Certain scripts redirect to GET even if the form was submitted originally
......
...@@ -24,6 +24,7 @@ use Bugzilla::Field; ...@@ -24,6 +24,7 @@ use Bugzilla::Field;
use Date::Parse; use Date::Parse;
use Date::Format; use Date::Format;
use Digest;
use IO::File; use IO::File;
use List::MoreUtils qw(uniq); use List::MoreUtils qw(uniq);
use URI; use URI;
...@@ -701,6 +702,9 @@ sub update_table_definitions { ...@@ -701,6 +702,9 @@ sub update_table_definitions {
# 2012-08-01 koosha.khajeh@gmail.com - Bug 187753 # 2012-08-01 koosha.khajeh@gmail.com - Bug 187753
_shorten_long_quips(); _shorten_long_quips();
# 2012-12-29 reed@reedloden.com - Bug 785283
_add_password_salt_separator();
################################################################ ################################################################
# New --TABLE-- changes should go *** A B O V E *** this point # # New --TABLE-- changes should go *** A B O V E *** this point #
################################################################ ################################################################
...@@ -3776,6 +3780,39 @@ sub _shorten_long_quips { ...@@ -3776,6 +3780,39 @@ sub _shorten_long_quips {
$dbh->bz_alter_column('quips', 'quip', { TYPE => 'varchar(512)', NOTNULL => 1}); $dbh->bz_alter_column('quips', 'quip', { TYPE => 'varchar(512)', NOTNULL => 1});
} }
sub _add_password_salt_separator {
my $dbh = Bugzilla->dbh;
$dbh->bz_start_transaction();
my $profiles = $dbh->selectall_arrayref("SELECT userid, cryptpassword FROM profiles WHERE ("
. $dbh->sql_regexp("cryptpassword", "'^[^,]+{'") . ")");
if (@$profiles) {
say "Adding salt separator to password hashes...";
my $query = $dbh->prepare("UPDATE profiles SET cryptpassword = ? WHERE userid = ?");
my %algo_sizes;
foreach my $profile (@$profiles) {
my ($userid, $hash) = @$profile;
my ($algorithm) = $hash =~ /{([^}]+)}$/;
$algo_sizes{$algorithm} ||= length(Digest->new($algorithm)->b64digest);
# Calculate the salt length by taking the stored hash and
# subtracting the combined lengths of the hash size, the
# algorithm name, and 2 for the {} surrounding the name.
my $not_salt_len = $algo_sizes{$algorithm} + length($algorithm) + 2;
my $salt_len = length($hash) - $not_salt_len;
substr($hash, $salt_len, 0, ',');
$query->execute($hash, $userid);
}
}
$dbh->bz_commit_transaction();
}
1; 1;
__END__ __END__
......
...@@ -591,11 +591,10 @@ sub bz_crypt { ...@@ -591,11 +591,10 @@ sub bz_crypt {
} }
else { else {
my $hasher = Digest->new($algorithm); my $hasher = Digest->new($algorithm);
# We only want to use the first characters of the salt, no # Newly created salts won't yet have a comma.
# matter how long of a salt we may have been passed. ($salt) = $salt =~ /^([^,]+),?/;
$salt = substr($salt, 0, PASSWORD_SALT_LENGTH);
$hasher->add($password, $salt); $hasher->add($password, $salt);
$crypted_password = $salt . $hasher->b64digest . "{$algorithm}"; $crypted_password = $salt . ',' . $hasher->b64digest . "{$algorithm}";
} }
# Return the crypted password. # Return the crypted password.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment