PageRenderTime 27ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/auth.php

https://bitbucket.org/minaco2/pukiwiki
PHP | 228 lines | 159 code | 33 blank | 36 comment | 34 complexity | c5bc071f7e0a2555618165e7de46f546 MD5 | raw file
  1. <?php
  2. // PukiWiki - Yet another WikiWikiWeb clone
  3. // $Id: auth.php,v 1.22 2011/01/25 15:01:01 henoheno Exp $
  4. // Copyright (C) 2003-2005, 2007 PukiWiki Developers Team
  5. // License: GPL v2 or (at your option) any later version
  6. //
  7. // Authentication related functions
  8. define('PKWK_PASSPHRASE_LIMIT_LENGTH', 512);
  9. // Passwd-auth related ----
  10. function pkwk_login($pass = '')
  11. {
  12. global $adminpass;
  13. if (! PKWK_READONLY && isset($adminpass) &&
  14. pkwk_hash_compute($pass, $adminpass) === $adminpass) {
  15. return TRUE;
  16. } else {
  17. sleep(2); // Blocking brute force attack
  18. return FALSE;
  19. }
  20. }
  21. // Compute RFC2307 'userPassword' value, like slappasswd (OpenLDAP)
  22. // $phrase : Pass-phrase
  23. // $scheme : Specify '{scheme}' or '{scheme}salt'
  24. // $prefix : Output with a scheme-prefix or not
  25. // $canonical : Correct or Preserve $scheme prefix
  26. function pkwk_hash_compute($phrase = '', $scheme = '{x-php-md5}', $prefix = TRUE, $canonical = FALSE)
  27. {
  28. if (! is_string($phrase) || ! is_string($scheme)) return FALSE;
  29. if (strlen($phrase) > PKWK_PASSPHRASE_LIMIT_LENGTH)
  30. die('pkwk_hash_compute(): malicious message length');
  31. // With a {scheme}salt or not
  32. $matches = array();
  33. if (preg_match('/^(\{.+\})(.*)$/', $scheme, $matches)) {
  34. $scheme = & $matches[1];
  35. $salt = & $matches[2];
  36. } else if ($scheme != '') {
  37. $scheme = ''; // Cleartext
  38. $salt = '';
  39. }
  40. // Compute and add a scheme-prefix
  41. switch (strtolower($scheme)) {
  42. // PHP crypt()
  43. case '{x-php-crypt}' :
  44. $hash = ($prefix ? ($canonical ? '{x-php-crypt}' : $scheme) : '') .
  45. ($salt != '' ? crypt($phrase, $salt) : crypt($phrase));
  46. break;
  47. // PHP md5()
  48. case '{x-php-md5}' :
  49. $hash = ($prefix ? ($canonical ? '{x-php-md5}' : $scheme) : '') .
  50. md5($phrase);
  51. break;
  52. // PHP sha1()
  53. case '{x-php-sha1}' :
  54. $hash = ($prefix ? ($canonical ? '{x-php-sha1}' : $scheme) : '') .
  55. sha1($phrase);
  56. break;
  57. // LDAP CRYPT
  58. case '{crypt}' :
  59. $hash = ($prefix ? ($canonical ? '{CRYPT}' : $scheme) : '') .
  60. ($salt != '' ? crypt($phrase, $salt) : crypt($phrase));
  61. break;
  62. // LDAP MD5
  63. case '{md5}' :
  64. $hash = ($prefix ? ($canonical ? '{MD5}' : $scheme) : '') .
  65. base64_encode(hex2bin(md5($phrase)));
  66. break;
  67. // LDAP SMD5
  68. case '{smd5}' :
  69. // MD5 Key length = 128bits = 16bytes
  70. $salt = ($salt != '' ? substr(base64_decode($salt), 16) : substr(crypt(''), -8));
  71. $hash = ($prefix ? ($canonical ? '{SMD5}' : $scheme) : '') .
  72. base64_encode(hex2bin(md5($phrase . $salt)) . $salt);
  73. break;
  74. // LDAP SHA
  75. case '{sha}' :
  76. $hash = ($prefix ? ($canonical ? '{SHA}' : $scheme) : '') .
  77. base64_encode(hex2bin(sha1($phrase)));
  78. break;
  79. // LDAP SSHA
  80. case '{ssha}' :
  81. // SHA-1 Key length = 160bits = 20bytes
  82. $salt = ($salt != '' ? substr(base64_decode($salt), 20) : substr(crypt(''), -8));
  83. $hash = ($prefix ? ($canonical ? '{SSHA}' : $scheme) : '') .
  84. base64_encode(hex2bin(sha1($phrase . $salt)) . $salt);
  85. break;
  86. // LDAP CLEARTEXT and just cleartext
  87. case '{cleartext}' : /* FALLTHROUGH */
  88. case '' :
  89. $hash = ($prefix ? ($canonical ? '{CLEARTEXT}' : $scheme) : '') .
  90. $phrase;
  91. break;
  92. // Invalid scheme
  93. default:
  94. $hash = FALSE;
  95. break;
  96. }
  97. return $hash;
  98. }
  99. // Basic-auth related ----
  100. // Check edit-permission
  101. function check_editable($page, $auth_flag = TRUE, $exit_flag = TRUE)
  102. {
  103. global $script, $_title_cannotedit, $_msg_unfreeze;
  104. if (edit_auth($page, $auth_flag, $exit_flag) && is_editable($page)) {
  105. // Editable
  106. return TRUE;
  107. } else {
  108. // Not editable
  109. if ($exit_flag === FALSE) {
  110. return FALSE; // Without exit
  111. } else {
  112. // With exit
  113. $body = $title = str_replace('$1',
  114. htmlsc(strip_bracket($page)), $_title_cannotedit);
  115. if (! is_cantedit($page) && is_freeze($page)) {
  116. $body .= '(<a href="' . $script . '?cmd=unfreeze&amp;page=' .
  117. rawurlencode($page) . '">' . $_msg_unfreeze . '</a>)';
  118. }
  119. $page = str_replace('$1', make_search($page), $_title_cannotedit);
  120. catbody($title, $page, $body);
  121. exit;
  122. }
  123. }
  124. }
  125. // Check read-permission
  126. function check_readable($page, $auth_flag = TRUE, $exit_flag = TRUE)
  127. {
  128. return read_auth($page, $auth_flag, $exit_flag);
  129. }
  130. function edit_auth($page, $auth_flag = TRUE, $exit_flag = TRUE)
  131. {
  132. global $edit_auth, $edit_auth_pages, $_title_cannotedit;
  133. return $edit_auth ? basic_auth($page, $auth_flag, $exit_flag,
  134. $edit_auth_pages, $_title_cannotedit) : TRUE;
  135. }
  136. function read_auth($page, $auth_flag = TRUE, $exit_flag = TRUE)
  137. {
  138. global $read_auth, $read_auth_pages, $_title_cannotread;
  139. return $read_auth ? basic_auth($page, $auth_flag, $exit_flag,
  140. $read_auth_pages, $_title_cannotread) : TRUE;
  141. }
  142. // Basic authentication
  143. function basic_auth($page, $auth_flag, $exit_flag, $auth_pages, $title_cannot)
  144. {
  145. global $auth_method_type, $auth_users, $_msg_auth;
  146. // Checked by:
  147. $target_str = '';
  148. if ($auth_method_type == 'pagename') {
  149. $target_str = $page; // Page name
  150. } else if ($auth_method_type == 'contents') {
  151. $target_str = get_source($page, TRUE, TRUE); // Its contents
  152. }
  153. $user_list = array();
  154. foreach($auth_pages as $key=>$val)
  155. if (preg_match($key, $target_str))
  156. $user_list = array_merge($user_list, explode(',', $val));
  157. if (empty($user_list)) return TRUE; // No limit
  158. $matches = array();
  159. if (! isset($_SERVER['PHP_AUTH_USER']) &&
  160. ! isset($_SERVER ['PHP_AUTH_PW']) &&
  161. isset($_SERVER['HTTP_AUTHORIZATION']) &&
  162. preg_match('/^Basic (.*)$/', $_SERVER['HTTP_AUTHORIZATION'], $matches))
  163. {
  164. // Basic-auth with $_SERVER['HTTP_AUTHORIZATION']
  165. list($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']) =
  166. explode(':', base64_decode($matches[1]));
  167. }
  168. if (PKWK_READONLY ||
  169. ! isset($_SERVER['PHP_AUTH_USER']) ||
  170. ! in_array($_SERVER['PHP_AUTH_USER'], $user_list) ||
  171. ! isset($auth_users[$_SERVER['PHP_AUTH_USER']]) ||
  172. pkwk_hash_compute(
  173. $_SERVER['PHP_AUTH_PW'],
  174. $auth_users[$_SERVER['PHP_AUTH_USER']]
  175. ) !== $auth_users[$_SERVER['PHP_AUTH_USER']])
  176. {
  177. // Auth failed
  178. pkwk_common_headers();
  179. if ($auth_flag) {
  180. header('WWW-Authenticate: Basic realm="' . $_msg_auth . '"');
  181. header('HTTP/1.0 401 Unauthorized');
  182. }
  183. if ($exit_flag) {
  184. $body = $title = str_replace('$1',
  185. htmlsc(strip_bracket($page)), $title_cannot);
  186. $page = str_replace('$1', make_search($page), $title_cannot);
  187. catbody($title, $page, $body);
  188. exit;
  189. }
  190. return FALSE;
  191. } else {
  192. return TRUE;
  193. }
  194. }
  195. ?>