Merge remote-tracking branch 'origin/pr-235'

Fix #227: Use stronger password hashes #235
This commit is contained in:
Benjamin Sonntag 2018-06-21 17:44:53 +02:00
commit f48618d0e5
8 changed files with 61 additions and 13 deletions

View File

@ -21,7 +21,7 @@
# Purpose of file: Global Makefile
# ----------------------------------------------------------------------
MAJOR=$(shell sed -ne 's/^[^(]*(\([^)]*\)).*/\1/;1p' debian/changelog)
VERSION=$MAJOR
VERSION=$(MAJOR)
export VERSION
build:

View File

@ -541,7 +541,6 @@ function _md5cr($pass, $salt = "") {
return crypt($pass, $salt);
}
/** split mysql database name between username and custom database name
* @param string $dbname database name
* @return array returns username as first element, custom name as second
@ -1204,3 +1203,42 @@ function csrf_check($token=null) {
$db->exec("DELETE FROM csrf WHERE created<DATE_SUB(NOW(), INTERVAL 1 DAY);");
return 1;
}
/**
* Create a SHA512-CRYPT hash of a string.
*/
function _sha512cr($password, $salt = NULL) {
if (!$salt) {
// Aim to have a 16 character salt for SHA-512 crypt.
// @see https://secure.php.net/manual/en/function.crypt.php
if (function_exists('random_bytes')) {
// PHP >= 7.0
$salt = base64_encode(random_bytes(12));
}
else if (function_exists('mcrypt_create_iv')) {
$salt = base64_encode(mcrypt_create_iv(12, MCRYPT_DEV_URANDOM));
}
else if (function_exists('')) {
$salt = base64_encode(openssl_random_pseudo_bytes(12));
}
if (!$salt) {
throw Error('Unable to generate salt');
}
}
$salt = '$6$rounds=20000$' . $salt;
$hash = crypt($password, $salt);
return $hash;
}
/**
* Create a password hash for use with dovecot.
*/
function _dovecot_hash($password) {
// In any case the final password saved for dovecot can store the
// scheme to override the default on a per-account basis.
// Ideally this is updated to bcrypt or argon2 when those become
// available in dovecot.
// @see https://wiki.dovecot.org/Authentication/PasswordSchemes
$hash = _sha512cr($password);
return '{SHA512-CRYPT}' . $hash;
}

View File

@ -634,7 +634,7 @@ class m_admin {
$msg->raise("ERROR", "admin", _("Login can only contains characters a-z, 0-9 and -"));
return false;
}
$pass = _md5cr($pass);
$pass = password_hash($pass, PASSWORD_BCRYPT);
$db = new DB_System();
// Already exist?
$db->query("SELECT count(*) AS cnt FROM membres WHERE login= ?;", array($login));
@ -772,7 +772,7 @@ class m_admin {
$db = new DB_System();
if ($pass) {
$pass = _md5cr($pass);
$pass = password_hash($pass, PASSWORD_BCRYPT);
$second_query = "UPDATE membres SET mail= ?, canpass= ?, enabled= ?, `type`= ?, notes= ? , pass = ? WHERE uid= ?;";
$second_query_args = array($mail, $canpass, $enabled, $type, $notes, $pass, $uid);
} else {

View File

@ -321,7 +321,7 @@ class m_ftp {
return false; // The error has been raised by checkPolicy()
}
}
$encrypted_password = _md5cr($pass, strrev(microtime(true)));
$encrypted_password = _sha512cr($pass);
$db->query("UPDATE ftpusers SET name= ? , password='', encrypted_password= ?, homedir= ?, uid= ? WHERE id= ?;", array($full_login, $encrypted_password, $absolute, $cuid, $id));
} else {
$db->query("UPDATE ftpusers SET name= ? , homedir= ? , uid= ? WHERE id= ? ;", array($full_login, $absolute, $cuid, $id));
@ -406,7 +406,7 @@ class m_ftp {
}
if ($quota->cancreate("ftp")) {
$encrypted_password = _md5cr($pass, strrev(microtime(true)));
$encrypted_password = _sha512cr($pass);
$db->query("INSERT INTO ftpusers (name,password, encrypted_password,homedir,uid) VALUES ( ?, '', ?, ?, ?)", array($full_login, $encrypted_password, $absolute, $cuid));
return true;
} else {

View File

@ -620,8 +620,10 @@ ORDER BY
return false;
}
if ($canbeempty && empty($pass)) {
return $db->query("UPDATE address SET password= ? where id = ? ;", array(null, $mail_id ));
} else if (!$db->query("UPDATE address SET password= ? where id = ? ;", array(_md5cr($pass), $mail_id ))) {
return $db->query("UPDATE address SET password= ? where id = ? ;",
array(null, $mail_id ));
} else if (!$db->query("UPDATE address SET password= ? where id = ? ;",
array(_dovecot_hash($pass), $mail_id ))) {
return false;
}
return true;

View File

@ -93,7 +93,7 @@ class m_mem {
return false;
}
$db->next_record();
if (_md5cr($password, $db->f("pass")) != $db->f("pass")) {
if (!password_verify($password, $db->f('pass'))) {
$db->query("UPDATE membres SET lastfail=lastfail+1 WHERE uid= ? ;", array($db->f("uid")));
$msg->raise("ERROR", "mem", _("User or password incorrect"));
return false;
@ -104,6 +104,12 @@ class m_mem {
}
$this->user = $db->Record;
$cuid = $db->f("uid");
// Transitional code to update md5 hashed passwords to those created
// with password_hash().
if (strncmp($db->f('pass'), '$1$', 3) == 0) {
$db->query("update membres set pass = ? where uid = ?",
array(password_hash($password, PASSWORD_BCRYPT), $cuid));
}
if (panel_islocked() && $cuid != 2000) {
$msg->raise("ALERT", "mem", _("This website is currently under maintenance, login is currently disabled."));
@ -396,7 +402,7 @@ class m_mem {
$msg->raise("ERROR", "mem", _("You are not allowed to change your password."));
return false;
}
if ($this->user["pass"] != _md5cr($oldpass, $this->user["pass"])) {
if (!password_verify($oldpass, $this->user['pass'])) {
$msg->raise("ERROR", "mem", _("The old password is incorrect"));
return false;
}
@ -410,7 +416,7 @@ class m_mem {
if (!$admin->checkPolicy("mem", $login, $newpass)) {
return false; // The error has been raised by checkPolicy()
}
$newpass = _md5cr($newpass);
$newpass = password_hash($newpass, PASSWORD_BCRYPT);
$db->query("UPDATE membres SET pass= ? WHERE uid= ?;", array($newpass, $cuid));
$msg->init_msgs();
return true;

View File

@ -129,7 +129,7 @@ CREATE TABLE IF NOT EXISTS ftpusers (
id int(10) unsigned NOT NULL auto_increment,
name varchar(64) NOT NULL default '',
password varchar(32) NOT NULL default '',
encrypted_password VARCHAR(32) default NULL,
encrypted_password VARCHAR(255) default NULL,
homedir varchar(128) NOT NULL default '',
uid int(10) unsigned NOT NULL default '0',
enabled boolean NOT NULL DEFAULT TRUE,
@ -159,7 +159,7 @@ CREATE TABLE IF NOT EXISTS local (
CREATE TABLE IF NOT EXISTS membres (
uid int(10) unsigned NOT NULL auto_increment, -- Numéro du membre (GID)
login varchar(128) NOT NULL default '', -- Nom d`utilisateur
pass varchar(64) NOT NULL default '', -- Mot de passe
pass varchar(255) NOT NULL default '', -- Mot de passe
enabled tinyint(4) NOT NULL default '1', -- Le compte est-il actif ?
su tinyint(4) NOT NULL default '0', -- Le compte est-il super-admin ?
mail varchar(128) NOT NULL default '', -- Adresse email du possesseur

View File

@ -0,0 +1,2 @@
ALTER TABLE `membres` MODIFY `pass` varchar(255);
ALTER TABLE `ftpusers` MODIFY `encrypted_password` varchar(255);