The version of vichan running on lainchan.org
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

216 lignes
6.3KB

  1. <?php
  2. /*
  3. * Copyright (c) 2010-2013 Tinyboard Development Group
  4. */
  5. defined('TINYBOARD') or exit;
  6. // create a hash/salt pair for validate logins
  7. function mkhash($username, $password, $salt = false) {
  8. global $config;
  9. if (!$salt) {
  10. // create some sort of salt for the hash
  11. $salt = substr(base64_encode(sha1(rand() . time(), true) . $config['cookies']['salt']), 0, 15);
  12. $generated_salt = true;
  13. }
  14. // generate hash (method is not important as long as it's strong)
  15. $hash = substr(
  16. base64_encode(
  17. md5(
  18. $username . $config['cookies']['salt'] . sha1(
  19. $username . $password . $salt . (
  20. $config['mod']['lock_ip'] ? $_SERVER['REMOTE_ADDR'] : ''
  21. ), true
  22. ) . sha1($config['password_crypt_version']) // Log out users being logged in with older password encryption schema
  23. , true
  24. )
  25. ), 0, 20
  26. );
  27. if (isset($generated_salt))
  28. return array($hash, $salt);
  29. else
  30. return $hash;
  31. }
  32. function crypt_password_old($password) {
  33. $salt = generate_salt();
  34. $password = hash('sha256', $salt . sha1($password));
  35. return array($salt, $password);
  36. }
  37. function crypt_password($password) {
  38. global $config;
  39. // `salt` database field is reused as a version value. We don't want it to be 0.
  40. $version = $config['password_crypt_version'] ? $config['password_crypt_version'] : 1;
  41. $new_salt = generate_salt();
  42. $password = crypt($password, $config['password_crypt'] . $new_salt . "$");
  43. return array($version, $password);
  44. }
  45. function test_password($password, $salt, $test) {
  46. global $config;
  47. // Version = 0 denotes an old password hashing schema. In the same column, the
  48. // password hash was kept previously
  49. $version = (strlen($salt) <= 8) ? (int) $salt : 0;
  50. if ($version == 0) {
  51. $comp = hash('sha256', $salt . sha1($test));
  52. }
  53. else {
  54. $comp = crypt($test, $password);
  55. }
  56. return array($version, hash_equals($password, $comp));
  57. }
  58. function generate_salt() {
  59. // 128 bits of entropy
  60. return strtr(base64_encode(mcrypt_create_iv(16, MCRYPT_DEV_URANDOM)), '+', '.');
  61. }
  62. function login($username, $password) {
  63. global $mod, $config;
  64. $query = prepare("SELECT `id`, `type`, `boards`, `password`, `version` FROM ``mods`` WHERE BINARY `username` = :username");
  65. $query->bindValue(':username', $username);
  66. $query->execute() or error(db_error($query));
  67. if ($user = $query->fetch(PDO::FETCH_ASSOC)) {
  68. list($version, $ok) = test_password($user['password'], $user['version'], $password);
  69. if ($ok) {
  70. if ($config['password_crypt_version'] > $version) {
  71. // It's time to upgrade the password hashing method!
  72. list ($user['version'], $user['password']) = crypt_password($password);
  73. $query = prepare("UPDATE ``mods`` SET `password` = :password, `version` = :version WHERE `id` = :id");
  74. $query->bindValue(':password', $user['password']);
  75. $query->bindValue(':version', $user['version']);
  76. $query->bindValue(':id', $user['id']);
  77. $query->execute() or error(db_error($query));
  78. }
  79. return $mod = array(
  80. 'id' => $user['id'],
  81. 'type' => $user['type'],
  82. 'username' => $username,
  83. 'hash' => mkhash($username, $user['password']),
  84. 'boards' => explode(',', $user['boards'])
  85. );
  86. }
  87. }
  88. return false;
  89. }
  90. function setCookies() {
  91. global $mod, $config;
  92. if (!$mod)
  93. error('setCookies() was called for a non-moderator!');
  94. setcookie($config['cookies']['mod'],
  95. $mod['username'] . // username
  96. ':' .
  97. $mod['hash'][0] . // password
  98. ':' .
  99. $mod['hash'][1], // salt
  100. time() + $config['cookies']['expire'], $config['cookies']['jail'] ? $config['cookies']['path'] : '/', null, !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off', $config['cookies']['httponly']);
  101. }
  102. function destroyCookies() {
  103. global $config;
  104. // Delete the cookies
  105. setcookie($config['cookies']['mod'], 'deleted', time() - $config['cookies']['expire'], $config['cookies']['jail']?$config['cookies']['path'] : '/', null, !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off', true);
  106. }
  107. function modLog($action, $_board=null) {
  108. global $mod, $board, $config;
  109. $query = prepare("INSERT INTO ``modlogs`` VALUES (:id, :ip, :board, :time, :text)");
  110. $query->bindValue(':id', (isset($mod['id']) ? $mod['id'] : -1), PDO::PARAM_INT);
  111. $query->bindValue(':ip', $_SERVER['REMOTE_ADDR']);
  112. $query->bindValue(':time', time(), PDO::PARAM_INT);
  113. $query->bindValue(':text', $action);
  114. if (isset($_board))
  115. $query->bindValue(':board', $_board);
  116. elseif (isset($board))
  117. $query->bindValue(':board', $board['uri']);
  118. else
  119. $query->bindValue(':board', null, PDO::PARAM_NULL);
  120. $query->execute() or error(db_error($query));
  121. if ($config['syslog'])
  122. _syslog(LOG_INFO, '[mod/' . $mod['username'] . ']: ' . $action);
  123. }
  124. function create_pm_header() {
  125. global $mod, $config;
  126. if ($config['cache']['enabled'] && ($header = cache::get('pm_unread_' . $mod['id'])) != false) {
  127. if ($header === true)
  128. return false;
  129. return $header;
  130. }
  131. $query = prepare("SELECT `id` FROM ``pms`` WHERE `to` = :id AND `unread` = 1");
  132. $query->bindValue(':id', $mod['id'], PDO::PARAM_INT);
  133. $query->execute() or error(db_error($query));
  134. if ($pm = $query->fetch(PDO::FETCH_ASSOC))
  135. $header = array('id' => $pm['id'], 'waiting' => $query->rowCount() - 1);
  136. else
  137. $header = true;
  138. if ($config['cache']['enabled'])
  139. cache::set('pm_unread_' . $mod['id'], $header);
  140. if ($header === true)
  141. return false;
  142. return $header;
  143. }
  144. function make_secure_link_token($uri) {
  145. global $mod, $config;
  146. return substr(sha1($config['cookies']['salt'] . '-' . $uri . '-' . $mod['id']), 0, 8);
  147. }
  148. function check_login($prompt = false) {
  149. global $config, $mod;
  150. // Validate session
  151. if (isset($_COOKIE[$config['cookies']['mod']])) {
  152. // Should be username:hash:salt
  153. $cookie = explode(':', $_COOKIE[$config['cookies']['mod']]);
  154. if (count($cookie) != 3) {
  155. // Malformed cookies
  156. destroyCookies();
  157. if ($prompt) mod_login();
  158. exit;
  159. }
  160. $query = prepare("SELECT `id`, `type`, `boards`, `password` FROM ``mods`` WHERE `username` = :username");
  161. $query->bindValue(':username', $cookie[0]);
  162. $query->execute() or error(db_error($query));
  163. $user = $query->fetch(PDO::FETCH_ASSOC);
  164. // validate password hash
  165. if ($cookie[1] !== mkhash($cookie[0], $user['password'], $cookie[2])) {
  166. // Malformed cookies
  167. destroyCookies();
  168. if ($prompt) mod_login();
  169. exit;
  170. }
  171. $mod = array(
  172. 'id' => $user['id'],
  173. 'type' => $user['type'],
  174. 'username' => $cookie[0],
  175. 'boards' => explode(',', $user['boards'])
  176. );
  177. }
  178. }