Last active
March 24, 2017 10:38
-
-
Save AmauryCarrade/0a4abdaeaa0545e5ee02866759e2ef13 to your computer and use it in GitHub Desktop.
Migration de FluxBB vers BCrypt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/include/common.php b/include/common.php | |
index 1661f58..3af340a 100644 | |
--- a/include/common.php | |
+++ b/include/common.php | |
@@ -45,6 +45,16 @@ if (!defined('PUN')) | |
exit; | |
} | |
+// If the password config is missing, here are some default values | |
+if (!isset($password_hash_options) || empty($password_hash_options)) | |
+{ | |
+ $password_hash_options = | |
+ [ | |
+ 'algorithm' => PASSWORD_DEFAULT, | |
+ 'cost' => 12 | |
+ ]; | |
+} | |
+ | |
// Load the functions script | |
require PUN_ROOT.'include/functions.php'; | |
diff --git a/include/functions.php b/include/functions.php | |
index a014699..bfbc00a 100644 | |
--- a/include/functions.php | |
+++ b/include/functions.php | |
@@ -27,7 +27,7 @@ function check_cookie(&$pun_user) | |
$now = time(); | |
// If the cookie is set and it matches the correct pattern, then read the values from it | |
- if (isset($_COOKIE[$cookie_name]) && preg_match('%^(\d+)\|([0-9a-fA-F]+)\|(\d+)\|([0-9a-fA-F]+)$%', $_COOKIE[$cookie_name], $matches)) | |
+ if (isset($_COOKIE[$cookie_name]) && preg_match('%^(\d+)\|([^|]+)\|(\d+)\|([0-9a-fA-F]+)$%', $_COOKIE[$cookie_name], $matches)) | |
{ | |
$cookie = array( | |
'user_id' => intval($matches[1]), | |
@@ -163,8 +163,11 @@ function authenticate_user($user, $password, $password_is_hash = false) | |
$result = $db->query('SELECT u.*, g.*, o.logged, o.idle FROM '.$db->prefix.'users AS u INNER JOIN '.$db->prefix.'groups AS g ON g.g_id=u.group_id LEFT JOIN '.$db->prefix.'online AS o ON o.user_id=u.id WHERE '.(is_int($user) ? 'u.id='.intval($user) : 'u.username=\''.$db->escape($user).'\'')) or error('Unable to fetch user info', __FILE__, __LINE__, $db->error()); | |
$pun_user = $db->fetch_assoc($result); | |
- $is_password_authorized = pun_hash_equals($password, $pun_user['password']); | |
- $is_hash_authorized = pun_hash_equals(pun_hash($password), $pun_user['password']); | |
+ $is_password_authorized = check_password($password, $pun_user); | |
+ | |
+ // The PHP password hash functions (i.e. bcrypt) donesn't support hash comparison directly. | |
+ // Not a real problem—in the source code, $password_is_hash is always false. | |
+ $is_hash_authorized = false; //pun_hash_equals(pun_hash($password), $pun_user['password']); | |
if (!isset($pun_user['id']) || | |
($password_is_hash && !$is_password_authorized || | |
@@ -1209,6 +1212,91 @@ function check_csrf($token) | |
} | |
+ | |
+// | |
+// Hashes a password. | |
+// Never use pun_hash to hash passwords. Like, never. | |
+// | |
+function hash_password($plaintext_password) | |
+{ | |
+ global $password_hash_options; | |
+ return password_hash($plaintext_password, $password_hash_options['algorithm'], $password_hash_options); | |
+} | |
+ | |
+// | |
+// Checks if the given password is correct for an user. | |
+// This will also upgrade the password if needed on the fly, and update the hash in $user. | |
+// | |
+function check_password($plaintext_password, &$user) | |
+{ | |
+ if (empty($user['password'])) return false; | |
+ | |
+ global $password_hash_options; | |
+ | |
+ $authorized = false; | |
+ $need_rehash = false; | |
+ | |
+ // If there is a salt in the database we have upgraded from 1.3-legacy though haven't yet logged in | |
+ if (!empty($user['salt'])) | |
+ { | |
+ if (pun_hash_equals(sha1($user['salt'].sha1($plaintext_password)), $user['password'])) // 1.3 used sha1(salt.sha1(pass)) | |
+ { | |
+ $authorized = true; | |
+ $need_rehash = true; | |
+ } | |
+ } | |
+ | |
+ // It must be md5 from 1.2 | |
+ else if (strlen($user['password']) == 32) | |
+ { | |
+ if (pun_hash_equals(md5($plaintext_password), $user['password'])) | |
+ { | |
+ $authorized = true; | |
+ $need_rehash = true; | |
+ } | |
+ } | |
+ | |
+ // This must be SHA1 from the 1.4+ version | |
+ else if (strlen($user['password']) == 40) | |
+ { | |
+ if (pun_hash_equals($user['password'], pun_hash($plaintext_password))) | |
+ { | |
+ $authorized = true; | |
+ $need_rehash = true; | |
+ } | |
+ } | |
+ | |
+ // This is a good password hashed using password_hash from PHP 5.5+. | |
+ else | |
+ { | |
+ $authorized = password_verify($plaintext_password, $user['password']); | |
+ $need_rehash = password_needs_rehash($user['password'], $password_hash_options['algorithm'], $password_hash_options); | |
+ } | |
+ | |
+ // If the password should be re-hashed (and it was the good one, of course), we save a new one. | |
+ if ($authorized && $need_rehash) | |
+ { | |
+ update_password($plaintext_password, $user); | |
+ } | |
+ | |
+ return $authorized; | |
+} | |
+ | |
+// | |
+// Updates the password of the given user. | |
+// Updates the hash in $user too. | |
+// | |
+function update_password($plaintext_password, &$user) | |
+{ | |
+ $password_hash = hash_password($plaintext_password); | |
+ | |
+ global $db; | |
+ $db->query('UPDATE '.$db->prefix.'users SET password=\''.$db->escape($password_hash).'\''.((isset($user['salt']) && !empty($user['salt'])) ? ', salt=NULL' : '') . ' WHERE id='.$user['id']) or error('Unable to update user password', __FILE__, __LINE__, $db->error()); | |
+ | |
+ $user['password'] = $password_hash; | |
+} | |
+ | |
+ | |
// | |
// Try to determine the correct remote IP-address | |
// | |
diff --git a/lang/French/mail_templates/activate_password.tpl b/lang/French/mail_templates/activate_password.tpl | |
index 9a94c90..fc09206 100644 | |
--- a/lang/French/mail_templates/activate_password.tpl | |
+++ b/lang/French/mail_templates/activate_password.tpl | |
@@ -2,7 +2,7 @@ Subject: Demande de nouveau mot de passe | |
Bonjour <username>, | |
-Vous avez demandé un nouveau mot de passe associé à votre compte sur les forums de <base_url>. Si vous n'en avez pas fait la demande ou ne souhaitez finalement pas le modifier, veuillez ignorer ce message. Il ne sera changé que si vous vous rendez à la page d'activation ci-dessous. | |
+Vous avez demandé un nouveau mot de passe associé à votre compte sur les forums de <base_url>. Si vous n'en avez pas fait la demande ou ne souhaitez finalement pas le modifier, veuillez ignorer ce message. Il ne sera changé que si vous vous rendez à la page d'activation ci-dessous. | |
======================================================================= | |
Votre nouveau mot de passe est : <new_password> | |
======================================================================= | |
@@ -10,6 +10,8 @@ Votre nouveau mot de passe est : <new_password> | |
Afin de modifier votre mot de passe, merci de vous rendre à la page suivante : | |
<activation_url> | |
--- | |
+Nous vous recommandons vivement de changer ce nouveau mot de passe (dans « Mon profil », « Changer de mot de passe ») et de supprimer ce courriel, pour des raisons de sécurité. | |
+ | |
+-- | |
<board_mailer> | |
-(Veuillez ne pas répondre à ce message. Merci !) | |
\ No newline at end of file | |
+(Veuillez ne pas répondre à ce message. Merci !) | |
diff --git a/lang/French/mail_templates/welcome.tpl b/lang/French/mail_templates/welcome.tpl | |
index ec67f0b..24377a3 100644 | |
--- a/lang/French/mail_templates/welcome.tpl | |
+++ b/lang/French/mail_templates/welcome.tpl | |
@@ -8,6 +8,8 @@ Mot de passe : <password> | |
Veuillez vous rendre à <login_url> pour activer votre compte. | |
--- | |
+Nous vous recommandons vivement de changer le mot de passe qui a été généré (dans « Mon profil », « Changer de mot de passe ») par un mot de passe que vous seul(e) connaissez, et de supprimer ce courriel, pour des raisons de sécurité. | |
+ | |
+-- | |
<board_mailer> | |
-(Veuillez ne pas répondre à ce message. Merci !) | |
\ No newline at end of file | |
+(Veuillez ne pas répondre à ce message. Merci !) | |
diff --git a/login.php b/login.php | |
index 2d0aa80..c4d7c86 100644 | |
--- a/login.php | |
+++ b/login.php | |
@@ -32,38 +32,7 @@ if (isset($_POST['form_sent']) && $action == 'in') | |
$result = $db->query('SELECT * FROM '.$db->prefix.'users WHERE '.$username_sql) or error('Unable to fetch user info', __FILE__, __LINE__, $db->error()); | |
$cur_user = $db->fetch_assoc($result); | |
- $authorized = false; | |
- | |
- if (!empty($cur_user['password'])) | |
- { | |
- $form_password_hash = pun_hash($form_password); // Will result in a SHA-1 hash | |
- | |
- // If there is a salt in the database we have upgraded from 1.3-legacy though haven't yet logged in | |
- if (!empty($cur_user['salt'])) | |
- { | |
- $is_salt_authorized = pun_hash_equals(sha1($cur_user['salt'].sha1($form_password)), $cur_user['password']); | |
- if ($is_salt_authorized) // 1.3 used sha1(salt.sha1(pass)) | |
- { | |
- $authorized = true; | |
- | |
- $db->query('UPDATE '.$db->prefix.'users SET password=\''.$form_password_hash.'\', salt=NULL WHERE id='.$cur_user['id']) or error('Unable to update user password', __FILE__, __LINE__, $db->error()); | |
- } | |
- } | |
- // If the length isn't 40 then the password isn't using sha1, so it must be md5 from 1.2 | |
- else if (strlen($cur_user['password']) != 40) | |
- { | |
- $is_md5_authorized = pun_hash_equals(md5($form_password), $cur_user['password']); | |
- if ($is_md5_authorized) | |
- { | |
- $authorized = true; | |
- | |
- $db->query('UPDATE '.$db->prefix.'users SET password=\''.$form_password_hash.'\' WHERE id='.$cur_user['id']) or error('Unable to update user password', __FILE__, __LINE__, $db->error()); | |
- } | |
- } | |
- // Otherwise we should have a normal sha1 password | |
- else | |
- $authorized = pun_hash_equals($cur_user['password'], $form_password_hash); | |
- } | |
+ $authorized = check_password($form_password, $cur_user); | |
if (!$authorized) | |
$errors[] = $lang_login['Wrong user/pass']; | |
@@ -89,7 +58,7 @@ if (isset($_POST['form_sent']) && $action == 'in') | |
$db->query('DELETE FROM '.$db->prefix.'online WHERE ident=\''.$db->escape(get_remote_address()).'\'') or error('Unable to delete from online list', __FILE__, __LINE__, $db->error()); | |
$expire = ($save_pass == '1') ? time() + 1209600 : time() + $pun_config['o_timeout_visit']; | |
- pun_setcookie($cur_user['id'], $form_password_hash, $expire); | |
+ pun_setcookie($cur_user['id'], $cur_user['password'], $expire); | |
// Reset tracked topics | |
set_tracked_topics(null); | |
@@ -175,7 +144,7 @@ else if ($action == 'forget' || $action == 'forget_2') | |
$new_password = random_pass(12); | |
$new_password_key = random_pass(8); | |
- $db->query('UPDATE '.$db->prefix.'users SET activate_string=\''.pun_hash($new_password).'\', activate_key=\''.$new_password_key.'\', last_email_sent = '.time().' WHERE id='.$cur_hit['id']) or error('Unable to update activation data', __FILE__, __LINE__, $db->error()); | |
+ $db->query('UPDATE '.$db->prefix.'users SET activate_string=\''.hash_password($new_password).'\', activate_key=\''.$new_password_key.'\', last_email_sent = '.time().' WHERE id='.$cur_hit['id']) or error('Unable to update activation data', __FILE__, __LINE__, $db->error()); | |
// Do the user specific replacements to the template | |
$cur_mail_message = str_replace('<username>', $cur_hit['username'], $mail_message); | |
diff --git a/profile.php b/profile.php | |
index ee0e3c8..c3df5df 100644 | |
--- a/profile.php | |
+++ b/profile.php | |
@@ -96,25 +96,15 @@ if ($action == 'change_pass') | |
$result = $db->query('SELECT * FROM '.$db->prefix.'users WHERE id='.$id) or error('Unable to fetch password', __FILE__, __LINE__, $db->error()); | |
$cur_user = $db->fetch_assoc($result); | |
- $authorized = false; | |
- | |
- if (!empty($cur_user['password'])) | |
- { | |
- $old_password_hash = pun_hash($old_password); | |
- | |
- if ($cur_user['password'] == $old_password_hash || $pun_user['is_admmod']) | |
- $authorized = true; | |
- } | |
+ $authorized = $pun_user['is_admmod'] || check_password($old_password, $cur_user); | |
if (!$authorized) | |
message($lang_profile['Wrong pass']); | |
- $new_password_hash = pun_hash($new_password1); | |
- | |
- $db->query('UPDATE '.$db->prefix.'users SET password=\''.$new_password_hash.'\''.(!empty($cur_user['salt']) ? ', salt=NULL' : '').' WHERE id='.$id) or error('Unable to update password', __FILE__, __LINE__, $db->error()); | |
+ update_password($new_password1, $cur_user); | |
if ($pun_user['id'] == $id) | |
- pun_setcookie($pun_user['id'], $new_password_hash, time() + $pun_config['o_timeout_visit']); | |
+ pun_setcookie($pun_user['id'], $cur_user['password'], time() + $pun_config['o_timeout_visit']); | |
redirect('profile.php?section=essentials&id='.$id, $lang_profile['Pass updated redirect']); | |
} | |
@@ -193,7 +183,7 @@ else if ($action == 'change_email') | |
} | |
else if (isset($_POST['form_sent'])) | |
{ | |
- if (pun_hash($_POST['req_password']) !== $pun_user['password']) | |
+ if (!check_password($_POST['req_password'], $pun_user)) | |
message($lang_profile['Wrong pass']); | |
// Make sure they got here from the site | |
diff --git a/register.php b/register.php | |
index f7a0bbc..e433d73 100644 | |
--- a/register.php | |
+++ b/register.php | |
@@ -176,10 +176,11 @@ if (isset($_POST['form_sent'])) | |
$now = time(); | |
$intial_group_id = ($pun_config['o_regs_verify'] == '0') ? $pun_config['o_default_user_group'] : PUN_UNVERIFIED; | |
- $password_hash = pun_hash($password1); | |
+ $password_hash = hash_password($password1); | |
// Add the user | |
$db->query('INSERT INTO '.$db->prefix.'users (username, group_id, password, email, email_setting, timezone, dst, language, style, registered, registration_ip, last_visit) VALUES(\''.$db->escape($username).'\', '.$intial_group_id.', \''.$password_hash.'\', \''.$db->escape($email1).'\', '.$email_setting.', '.$timezone.' , '.$dst.', \''.$db->escape($language).'\', \''.$pun_config['o_default_style'].'\', '.$now.', \''.$db->escape(get_remote_address()).'\', '.$now.')') or error('Unable to create user', __FILE__, __LINE__, $db->error()); | |
+ //' | |
$new_uid = $db->insert_id(); | |
if ($pun_config['o_regs_verify'] == '0') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment