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 # Purpose of file: Global Makefile
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
MAJOR=$(shell sed -ne 's/^[^(]*(\([^)]*\)).*/\1/;1p' debian/changelog) MAJOR=$(shell sed -ne 's/^[^(]*(\([^)]*\)).*/\1/;1p' debian/changelog)
VERSION=$MAJOR VERSION=$(MAJOR)
export VERSION export VERSION
build: build:

View File

@ -541,7 +541,6 @@ function _md5cr($pass, $salt = "") {
return crypt($pass, $salt); return crypt($pass, $salt);
} }
/** split mysql database name between username and custom database name /** split mysql database name between username and custom database name
* @param string $dbname database name * @param string $dbname database name
* @return array returns username as first element, custom name as second * @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);"); $db->exec("DELETE FROM csrf WHERE created<DATE_SUB(NOW(), INTERVAL 1 DAY);");
return 1; 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 -")); $msg->raise("ERROR", "admin", _("Login can only contains characters a-z, 0-9 and -"));
return false; return false;
} }
$pass = _md5cr($pass); $pass = password_hash($pass, PASSWORD_BCRYPT);
$db = new DB_System(); $db = new DB_System();
// Already exist? // Already exist?
$db->query("SELECT count(*) AS cnt FROM membres WHERE login= ?;", array($login)); $db->query("SELECT count(*) AS cnt FROM membres WHERE login= ?;", array($login));
@ -772,7 +772,7 @@ class m_admin {
$db = new DB_System(); $db = new DB_System();
if ($pass) { 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 = "UPDATE membres SET mail= ?, canpass= ?, enabled= ?, `type`= ?, notes= ? , pass = ? WHERE uid= ?;";
$second_query_args = array($mail, $canpass, $enabled, $type, $notes, $pass, $uid); $second_query_args = array($mail, $canpass, $enabled, $type, $notes, $pass, $uid);
} else { } else {

View File

@ -321,7 +321,7 @@ class m_ftp {
return false; // The error has been raised by checkPolicy() 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)); $db->query("UPDATE ftpusers SET name= ? , password='', encrypted_password= ?, homedir= ?, uid= ? WHERE id= ?;", array($full_login, $encrypted_password, $absolute, $cuid, $id));
} else { } else {
$db->query("UPDATE ftpusers SET name= ? , homedir= ? , uid= ? WHERE id= ? ;", array($full_login, $absolute, $cuid, $id)); $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")) { 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)); $db->query("INSERT INTO ftpusers (name,password, encrypted_password,homedir,uid) VALUES ( ?, '', ?, ?, ?)", array($full_login, $encrypted_password, $absolute, $cuid));
return true; return true;
} else { } else {

View File

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

View File

@ -93,7 +93,7 @@ class m_mem {
return false; return false;
} }
$db->next_record(); $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"))); $db->query("UPDATE membres SET lastfail=lastfail+1 WHERE uid= ? ;", array($db->f("uid")));
$msg->raise("ERROR", "mem", _("User or password incorrect")); $msg->raise("ERROR", "mem", _("User or password incorrect"));
return false; return false;
@ -104,6 +104,12 @@ class m_mem {
} }
$this->user = $db->Record; $this->user = $db->Record;
$cuid = $db->f("uid"); $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) { if (panel_islocked() && $cuid != 2000) {
$msg->raise("ALERT", "mem", _("This website is currently under maintenance, login is currently disabled.")); $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.")); $msg->raise("ERROR", "mem", _("You are not allowed to change your password."));
return false; 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")); $msg->raise("ERROR", "mem", _("The old password is incorrect"));
return false; return false;
} }
@ -410,7 +416,7 @@ class m_mem {
if (!$admin->checkPolicy("mem", $login, $newpass)) { if (!$admin->checkPolicy("mem", $login, $newpass)) {
return false; // The error has been raised by checkPolicy() 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)); $db->query("UPDATE membres SET pass= ? WHERE uid= ?;", array($newpass, $cuid));
$msg->init_msgs(); $msg->init_msgs();
return true; return true;

View File

@ -129,7 +129,7 @@ CREATE TABLE IF NOT EXISTS ftpusers (
id int(10) unsigned NOT NULL auto_increment, id int(10) unsigned NOT NULL auto_increment,
name varchar(64) NOT NULL default '', name varchar(64) NOT NULL default '',
password varchar(32) 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 '', homedir varchar(128) NOT NULL default '',
uid int(10) unsigned NOT NULL default '0', uid int(10) unsigned NOT NULL default '0',
enabled boolean NOT NULL DEFAULT TRUE, enabled boolean NOT NULL DEFAULT TRUE,
@ -159,7 +159,7 @@ CREATE TABLE IF NOT EXISTS local (
CREATE TABLE IF NOT EXISTS membres ( CREATE TABLE IF NOT EXISTS membres (
uid int(10) unsigned NOT NULL auto_increment, -- Numéro du membre (GID) uid int(10) unsigned NOT NULL auto_increment, -- Numéro du membre (GID)
login varchar(128) NOT NULL default '', -- Nom d`utilisateur 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 ? 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 ? su tinyint(4) NOT NULL default '0', -- Le compte est-il super-admin ?
mail varchar(128) NOT NULL default '', -- Adresse email du possesseur 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);