diff --git a/inc/config.php b/inc/config.php index a4914252..adfaa5e8 100644 --- a/inc/config.php +++ b/inc/config.php @@ -906,8 +906,10 @@ // Check public ban message by default $config['mod']['check_ban_message'] = false; - // Default public ban message + // Default public ban message. + // In public ban messages, %length% is replaced with "for x days" or "permanently" (with %LENGTH% being the uppercase equivalent). $config['mod']['default_ban_message'] = 'USER WAS BANNED FOR THIS POST'; + // $config['mod']['default_ban_message'] = 'USER WAS BANNED %LENGTH% FOR THIS POST'; // Include length in ban message // What to append to the post for public bans ("%s" is the message) $config['mod']['ban_message'] = '(%s)'; diff --git a/inc/mod/auth.php b/inc/mod/auth.php index 173190ab..1bc27dff 100644 --- a/inc/mod/auth.php +++ b/inc/mod/auth.php @@ -29,6 +29,11 @@ function mkhash($username, $password, $salt = false) { return $hash; } +function generate_salt() { + mt_srand(microtime(true) * 100000 + memory_get_usage(true)); + return md5(uniqid(mt_rand(), true)); +} + function login($username, $password, $makehash=true) { global $mod; @@ -37,20 +42,23 @@ function login($username, $password, $makehash=true) { $password = sha1($password); } - $query = prepare("SELECT `id`,`type`,`boards` FROM `mods` WHERE `username` = :username AND `password` = :password LIMIT 1"); + $query = prepare("SELECT `id`, `type`, `boards`, `password`, `salt` FROM `mods` WHERE `username` = :username"); $query->bindValue(':username', $username); - $query->bindValue(':password', $password); $query->execute() or error(db_error($query)); - if ($user = $query->fetch()) { - return $mod = array( - 'id' => $user['id'], - 'type' => $user['type'], - 'username' => $username, - 'hash' => mkhash($username, $password), - 'boards' => explode(',', $user['boards']) - ); - } else return false; + if ($user = $query->fetch(PDO::FETCH_ASSOC)) { + if ($user['password'] === hash('sha256', $user['salt'] . $password)) { + return $mod = array( + 'id' => $user['id'], + 'type' => $user['type'], + 'username' => $username, + 'hash' => mkhash($username, $user['password']), + 'boards' => explode(',', $user['boards']) + ); + } + } + + return false; } function setCookies() { @@ -104,10 +112,10 @@ if (isset($_COOKIE[$config['cookies']['mod']])) { exit; } - $query = prepare("SELECT `id`, `type`, `boards`, `password` FROM `mods` WHERE `username` = :username LIMIT 1"); + $query = prepare("SELECT `id`, `type`, `boards`, `password` FROM `mods` WHERE `username` = :username"); $query->bindValue(':username', $cookie[0]); $query->execute() or error(db_error($query)); - $user = $query->fetch(); + $user = $query->fetch(PDO::FETCH_ASSOC); // validate password hash if ($cookie[1] !== mkhash($cookie[0], $user['password'], $cookie[2])) { diff --git a/inc/mod/pages.php b/inc/mod/pages.php index e1e8c88f..1e47ea21 100644 --- a/inc/mod/pages.php +++ b/inc/mod/pages.php @@ -1152,6 +1152,9 @@ function mod_ban_post($board, $delete, $post, $token = false) { if (isset($_POST['public_message'], $_POST['message'])) { // public ban message + $length_english = parse_time($_POST['length']) ? 'for ' . until(parse_time($_POST['length'])) : 'permanently'; + $_POST['message'] = str_replace('%length%', $length_english, $_POST['message']); + $_POST['message'] = str_replace('%LENGTH%', strtoupper($length_english), $_POST['message']); $query = prepare(sprintf('UPDATE `posts_%s` SET `body` = CONCAT(`body`, :body) WHERE `id` = :id', $board)); $query->bindValue(':id', $post); $query->bindValue(':body', sprintf($config['mod']['ban_message'], utf8tohtml($_POST['message']))); @@ -1407,9 +1410,13 @@ function mod_user($uid) { } if ($_POST['password'] != '') { - $query = prepare('UPDATE `mods` SET `password` = SHA1(:password) WHERE `id` = :id'); + $salt = generate_salt(); + $password = hash('sha256', $salt . sha1($_POST['password'])); + + $query = prepare('UPDATE `mods` SET `password` = :password, `salt` = :salt WHERE `id` = :id'); $query->bindValue(':id', $uid); - $query->bindValue(':password', $_POST['password']); + $query->bindValue(':password', $password); + $query->bindValue(':salt', $salt); $query->execute() or error(db_error($query)); modLog('Changed password for ' . utf8tohtml($_POST['username']) . ' (#' . $user['id'] . ')'); @@ -1430,9 +1437,13 @@ function mod_user($uid) { if (hasPermission($config['mod']['change_password']) && $uid == $mod['id'] && isset($_POST['password'])) { if ($_POST['password'] != '') { - $query = prepare('UPDATE `mods` SET `password` = SHA1(:password) WHERE `id` = :id'); + $salt = generate_salt(); + $password = hash('sha256', $salt . sha1($_POST['password'])); + + $query = prepare('UPDATE `mods` SET `password` = :password, `salt` = :salt WHERE `id` = :id'); $query->bindValue(':id', $uid); - $query->bindValue(':password', $_POST['password']); + $query->bindValue(':password', $password); + $query->bindValue(':salt', $salt); $query->execute() or error(db_error($query)); modLog('Changed own password'); @@ -1494,9 +1505,13 @@ function mod_user_new() { if ($_POST['type'] !== JANITOR && $_POST['type'] !== MOD && $_POST['type'] !== ADMIN) error(sprintf($config['error']['invalidfield'], 'type')); - $query = prepare('INSERT INTO `mods` VALUES (NULL, :username, SHA1(:password), :type, :boards)'); + $salt = generate_salt(); + $password = hash('sha256', $salt . sha1($_POST['password'])); + + $query = prepare('INSERT INTO `mods` VALUES (NULL, :username, :password, :salt, :type, :boards)'); $query->bindValue(':username', $_POST['username']); - $query->bindValue(':password', $_POST['password']); + $query->bindValue(':password', $password); + $query->bindValue(':salt', $salt); $query->bindValue(':type', $_POST['type']); $query->bindValue(':boards', implode(',', $boards)); $query->execute() or error(db_error($query)); diff --git a/install.php b/install.php index 542762ae..7c095c53 100644 --- a/install.php +++ b/install.php @@ -1,7 +1,7 @@ vichan-devel-4.0.2'); +define('VERSION', 'v0.9.6-dev-9 + vichan-devel-4.0.3'); require 'inc/functions.php'; @@ -233,6 +233,26 @@ if (file_exists($config['has_installed'])) { case 'v0.9.6-dev-8': case 'v0.9.6-dev-8 + vichan-devel-4.0.1': query("CREATE TABLE IF NOT EXISTS `search_queries` ( `ip` varchar(39) NOT NULL, `time` int(11) NOT NULL, `query` text NOT NULL) ENGINE=MyISAM DEFAULT CHARSET=utf8;") or error(db_error()); + case 'v0.9.6-dev-8 + vichan-devel-4.0.2': + query("ALTER TABLE `mods` CHANGE `password` `password` CHAR( 64 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'SHA256'") or error(db_error()); + query("ALTER TABLE `mods` ADD `salt` CHAR( 32 ) NOT NULL AFTER `password`") or error(db_error()); + $query = query("SELECT `id`,`password` FROM `mods`") or error(db_error()); + while ($user = $query->fetch(PDO::FETCH_ASSOC)) { + if (strlen($user['password']) == 40) { + mt_srand(microtime(true) * 100000 + memory_get_usage(true)); + $salt = md5(uniqid(mt_rand(), true)); + + $user['salt'] = $salt; + $user['password'] = hash('sha256', $user['salt'] . $user['password']); + + $_query = prepare("UPDATE `mods` SET `password` = :password, `salt` = :salt WHERE `id` = :id"); + $_query->bindValue(':id', $user['id']); + $_query->bindValue(':password', $user['password']); + $_query->bindValue(':salt', $user['salt']); + $_query->execute() or error(db_error($_query)); + } + } + case 'v0.9.6-dev-9': case false: // Update version number file_write($config['has_installed'], VERSION); diff --git a/install.sql b/install.sql index 9c6a0acd..10198ee2 100644 --- a/install.sql +++ b/install.sql @@ -129,9 +129,10 @@ CREATE TABLE IF NOT EXISTS `modlogs` ( -- CREATE TABLE IF NOT EXISTS `mods` ( - `id` smallint(6) UNSIGNED NOT NULL AUTO_INCREMENT, + `id` smallint(6) unsigned NOT NULL AUTO_INCREMENT, `username` varchar(30) NOT NULL, - `password` char(40) NOT NULL COMMENT 'SHA1', + `password` char(64) NOT NULL COMMENT 'SHA256', + `salt` char(32) NOT NULL, `type` smallint(1) NOT NULL COMMENT '0: janitor, 1: mod, 2: admin', `boards` text NOT NULL, PRIMARY KEY (`id`), @@ -143,7 +144,7 @@ CREATE TABLE IF NOT EXISTS `mods` ( -- INSERT INTO `mods` (`id`, `username`, `password`, `type`, `boards`) VALUES -(1, 'admin', '5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8', 2, '*'); +(1, 'admin', 'cedad442efeef7112fed0f50b011b2b9bf83f6898082f995f69dd7865ca19fb7', '4a44c6c55df862ae901b413feecb0d49', 2, '*'); -- --------------------------------------------------------