Use password_hash() for passwords

- Use legacy_password to update double-hashed passwords
This commit is contained in:
Hypolite Petovan 2018-01-20 22:29:03 -05:00
parent c53c2fffa5
commit b0a764b14c
2 changed files with 36 additions and 12 deletions

View file

@ -112,7 +112,7 @@ class User
if (is_object($user_info)) { if (is_object($user_info)) {
$user = (array) $user_info; $user = (array) $user_info;
} elseif (is_int($user_info)) { } elseif (is_int($user_info)) {
$user = dba::selectFirst('user', ['uid', 'password'], $user = dba::selectFirst('user', ['uid', 'password', 'legacy_password'],
[ [
'uid' => $user_info, 'uid' => $user_info,
'blocked' => 0, 'blocked' => 0,
@ -122,7 +122,7 @@ class User
] ]
); );
} elseif (is_string($user_info)) { } elseif (is_string($user_info)) {
$user = dba::fetch_first('SELECT `uid`, `password` $user = dba::fetch_first('SELECT `uid`, `password`, `legacy_password`
FROM `user` FROM `user`
WHERE (`email` = ? OR `username` = ? OR `nickname` = ?) WHERE (`email` = ? OR `username` = ? OR `nickname` = ?)
AND `blocked` = 0 AND `blocked` = 0
@ -138,17 +138,29 @@ class User
$user = $user_info; $user = $user_info;
} }
if (!DBM::is_result($user) || !isset($user['uid']) || !isset($user['password'])) { if (!DBM::is_result($user)
return false; || !isset($user['uid'])
|| !isset($user['password'])
|| !isset($user['legacy_password'])
) {
throw new Exception('Not enough information to authenticate');
} }
$password_hashed = self::hashPassword($password); if ($user['legacy_password']) {
if (password_verify(self::hashPasswordLegacy($password), $user['password'])) {
self::updatePassword($user['uid'], $password);
if ($password_hashed !== $user['password']) { return $user['uid'];
return false; }
} elseif (password_verify($password, $user['password'])) {
if (password_needs_rehash($user['password'], PASSWORD_DEFAULT)) {
self::updatePassword($user['uid'], $password);
}
return $user['uid'];
} }
return $user['uid']; return false;
} }
/** /**
@ -161,15 +173,26 @@ class User
return autoname(6) . mt_rand(100, 9999); return autoname(6) . mt_rand(100, 9999);
} }
/**
* Legacy hashing function, kept for password migration purposes
*
* @param string $password
* @return string
*/
private static function hashPasswordLegacy($password)
{
return hash('whirlpool', $password);
}
/** /**
* Global user password hashing function * Global user password hashing function
* *
* @param string $password * @param string $password
* @return string * @return string
*/ */
private static function hashPassword($password) public static function hashPassword($password)
{ {
return hash('whirlpool', $password); return password_hash($password, PASSWORD_DEFAULT);
} }
/** /**
@ -197,7 +220,8 @@ class User
$fields = [ $fields = [
'password' => $pasword_hashed, 'password' => $pasword_hashed,
'pwdreset' => null, 'pwdreset' => null,
'pwdreset_time' => null 'pwdreset_time' => null,
'legacy_password' => false
]; ];
return dba::update('user', $fields, ['uid' => $uid]); return dba::update('user', $fields, ['uid' => $uid]);
} }

View file

@ -226,7 +226,7 @@ class ExAuth
if ($a->get_hostname() == $aCommand[2]) { if ($a->get_hostname() == $aCommand[2]) {
$this->writeLog(LOG_INFO, 'internal auth for ' . $sUser . '@' . $aCommand[2]); $this->writeLog(LOG_INFO, 'internal auth for ' . $sUser . '@' . $aCommand[2]);
$aUser = dba::selectFirst('user', ['uid', 'password'], ['nickname' => $sUser]); $aUser = dba::selectFirst('user', ['uid', 'password', 'legacy_password'], ['nickname' => $sUser]);
if (DBM::is_result($aUser)) { if (DBM::is_result($aUser)) {
$uid = $aUser['uid']; $uid = $aUser['uid'];
$success = User::authenticate($aUser, $aCommand[3]); $success = User::authenticate($aUser, $aCommand[3]);