Support for storing salted passwords

To upgrade existing databases:

ALTER TABLE Users ADD Salt CHAR(32) NOT NULL DEFAULT '';

Signed-off-by: Loui Chang <louipc.ist@gmail.com>
This commit is contained in:
Denis 2010-04-05 09:41:30 -04:00 committed by Loui Chang
parent 5b8b0757f4
commit 290c436046
4 changed files with 74 additions and 21 deletions

View file

@ -26,6 +26,7 @@ CREATE TABLE Users (
Username CHAR(32) NOT NULL,
Email CHAR(64) NOT NULL,
Passwd CHAR(32) NOT NULL,
Salt CHAR(32) NOT NULL DEFAULT '',
ResetKey CHAR(32) NOT NULL DEFAULT '',
RealName CHAR(64) NOT NULL DEFAULT '',
LangPreference CHAR(5) NOT NULL DEFAULT 'en',

View file

@ -31,10 +31,13 @@ if (isset($_GET['resetkey'], $_POST['email'], $_POST['password'], $_POST['confir
if (empty($error)) {
$dbh = db_connect();
$salt = generate_salt();
$hash = salted_hash($password, $salt);
# The query below won't affect any records unless the ResetKey
# and Email combination is correct and ResetKey is nonempty
$q = "UPDATE Users
SET Passwd = '".md5($password)."',
SET Passwd = '$hash',
Salt = '$salt',
ResetKey = ''
WHERE ResetKey != ''
AND ResetKey = '".mysql_real_escape_string($resetkey)."'

View file

@ -265,17 +265,14 @@ function process_account_form($UTYPE,$TYPE,$A,$U="",$T="",$S="",$E="",
} else {
if ($TYPE == "new") {
# no errors, go ahead and create the unprivileged user
# md5hash the password
$P = md5($P);
$q = "INSERT INTO Users (AccountTypeID, Suspended, Username, Email, ";
$q.= "Passwd, RealName, LangPreference, IRCNick, NewPkgNotify) ";
$q.= "VALUES (1, 0, '".mysql_real_escape_string($U)."'";
$q.= ", '".mysql_real_escape_string($E)."'";
$q.= ", '".mysql_real_escape_string($P)."'";
$q.= ", '".mysql_real_escape_string($R)."'";
$q.= ", '".mysql_real_escape_string($L)."'";
$q.= ", '".mysql_real_escape_string($I)."'";
$salt = generate_salt();
$P = salted_hash($P, $salt);
$escaped = array_map(mysql_real_escape_string,
array($U, $E, $P, $salt, $R, $L, $I));
$q = "INSERT INTO Users (" .
"AccountTypeID, Suspended, Username, Email, Passwd, Salt" .
", RealName, LangPreference, IRCNick, NewPkgNotify) " .
"VALUES (1, 0, '" . implode("', '", $escaped) . "'";
if ($N) {
$q.= ", 1)";
} else {
@ -298,7 +295,6 @@ function process_account_form($UTYPE,$TYPE,$A,$U="",$T="",$S="",$E="",
} else {
# no errors, go ahead and modify the user account
# md5 hash the password
$q = "UPDATE Users SET ";
$q.= "Username = '".mysql_real_escape_string($U)."'";
if ($T) {
@ -311,7 +307,9 @@ function process_account_form($UTYPE,$TYPE,$A,$U="",$T="",$S="",$E="",
}
$q.= ", Email = '".mysql_real_escape_string($E)."'";
if ($P) {
$q.= ", Passwd = '".mysql_real_escape_string(md5($P))."'";
$salt = generate_salt();
$hash = salted_hash($P, $salt);
$q .= ", Passwd = '$hash', Salt = '$salt'";
}
$q.= ", RealName = '".mysql_real_escape_string($R)."'";
$q.= ", LangPreference = '".mysql_real_escape_string($L)."'";
@ -738,16 +736,36 @@ function valid_passwd( $userID, $passwd )
{
if ( strlen($passwd) > 0 ) {
$dbh = db_connect();
$q = "SELECT ID FROM Users".
# get salt for this user
$salt = get_salt($userID);
if ($salt) {
# use salt
$passwd_q = "SELECT ID FROM Users" .
" WHERE ID = '$userID' AND Passwd = '" .
salted_hash($passwd, $salt) . "'";
$passwd_result = mysql_fetch_row(db_query($passwd_q, $dbh));
if ($passwd_result[0]) {
return true;
}
} else {
# check without salt
$nosalt_q = "SELECT ID FROM Users".
" WHERE ID = '$userID'" .
" AND Passwd = '" . md5($passwd) . "'";
$nosalt_result = mysql_fetch_row(db_query($nosalt_q, $dbh));
if ($nosalt_result[0]) {
# password correct, but salt it first
if (!save_salt($userID, $passwd)) {
trigger_error("Unable to salt user's password;" .
" ID $userID", E_USER_WARNING);
return false;
}
$result = mysql_fetch_row(db_query($q, $dbh));
if ($result[0]) {
# Is it the right password?
return true;
}
}
}
return false;
}

View file

@ -455,3 +455,34 @@ function mkurl($append) {
return substr($out, 5);
}
function get_salt($user_id)
{
$dbh = db_connect();
$salt_q = "SELECT Salt FROM Users WHERE ID = '$user_id'";
$salt_result = mysql_fetch_row(db_query($salt_q, $dbh));
return $salt_result[0];
}
function save_salt($user_id, $passwd)
{
$dbh = db_connect();
$salt = generate_salt();
$hash = salted_hash($passwd, $salt);
$salting_q = "UPDATE Users SET Salt = '$salt'" .
", Passwd = '$hash' WHERE ID = '$user_id'";
return db_query($salting_q, $dbh);
}
function generate_salt()
{
return md5(uniqid(rand(), true));
}
function salted_hash($passwd, $salt)
{
if (strlen($salt) != 32) {
trigger_error('Salt does not look like an md5 hash', E_USER_WARNING);
}
return md5($salt . $passwd);
}