PageRenderTime 49ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/textpattern/include/txp_auth.php

http://textpattern.googlecode.com/
PHP | 276 lines | 172 code | 51 blank | 53 comment | 20 complexity | 0386a09136d06e415ada971689c4b561 MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.1, GPL-2.0
  1. <?php
  2. /*
  3. * Textpattern Content Management System
  4. * http://textpattern.com
  5. *
  6. * Copyright (C) 2005 Dean Allen
  7. * Copyright (C) 2014 The Textpattern Development Team
  8. *
  9. * This file is part of Textpattern.
  10. *
  11. * Textpattern is free software; you can redistribute it and/or
  12. * modify it under the terms of the GNU General Public License
  13. * as published by the Free Software Foundation, version 2.
  14. *
  15. * Textpattern is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with Textpattern. If not, see <http://www.gnu.org/licenses/>.
  22. */
  23. /**
  24. * Login panel.
  25. *
  26. * @package Admin\Auth
  27. */
  28. if (!defined('txpinterface')) {
  29. die('txpinterface is undefined.');
  30. }
  31. /**
  32. * Renders a login panel if necessary.
  33. *
  34. * If the current visitor isn't authenticated,
  35. * terminates the script and instead renders
  36. * a login page.
  37. *
  38. * @access private
  39. */
  40. function doAuth()
  41. {
  42. global $txp_user;
  43. $txp_user = null;
  44. $message = doTxpValidate();
  45. if (!$txp_user) {
  46. doLoginForm($message);
  47. }
  48. ob_start();
  49. }
  50. /**
  51. * Renders and outputs a login form.
  52. *
  53. * This function outputs a full HTML document,
  54. * including &lt;head&gt; and footer.
  55. *
  56. * @param string|array $message The activity message
  57. */
  58. function doLoginForm($message)
  59. {
  60. global $textarray_script, $event, $step;
  61. include txpath.'/lib/txplib_head.php';
  62. $event = 'login';
  63. if (gps('logout')) {
  64. $step = 'logout';
  65. } elseif (gps('reset')) {
  66. $step = 'reset';
  67. }
  68. pagetop(gTxt('login'), $message);
  69. $stay = (cs('txp_login') and !gps('logout') ? 1 : 0);
  70. $reset = gps('reset');
  71. $name = join(',', array_slice(explode(',', cs('txp_login')), 0, -1));
  72. $out = array();
  73. if ($reset) {
  74. $out[] = hed(gTxt('password_reset'), 2, array('id' => 'txp-login-heading')).
  75. graf(
  76. n.span(tag(gTxt('name'), 'label', array('for' => 'login_name')), array('class' => 'txp-label')).
  77. n.span(fInput('text', 'p_userid', $name, '', '', '', INPUT_REGULAR, '', 'login_name'), array('class' => 'txp-value'))
  78. , ' class="login-name"').
  79. graf(
  80. fInput('submit', '', gTxt('password_reset_button'), 'publish').n
  81. ).
  82. graf(
  83. href(gTxt('back_to_login'), 'index.php')
  84. , array('class' => 'login-return')).
  85. hInput('p_reset', 1);
  86. } else {
  87. $out[] = hed(gTxt('login_to_textpattern'), 2, array('id' => 'txp-login-heading')).
  88. graf(
  89. n.span(tag(gTxt('name'), 'label', array('for' => 'login_name')), array('class' => 'txp-label')).
  90. n.span(fInput('text', 'p_userid', $name, '', '', '', INPUT_REGULAR, '', 'login_name'), array('class' => 'txp-value'))
  91. , array('class' => 'login-name')).
  92. graf(
  93. n.span(tag(gTxt('password'), 'label', array('for' => 'login_password')), array('class' => 'txp-label')).
  94. n.span(fInput('password', 'p_password', '', '', '', '', INPUT_REGULAR, '', 'login_password'), array('class' => 'txp-value'))
  95. , array('class' => 'login-password')).
  96. graf(
  97. checkbox('stay', 1, $stay, '', 'login_stay').n.
  98. tag(gTxt('stay_logged_in'), 'label', array('for' => 'login_stay')).
  99. popHelp('remember_login').n
  100. , array('class' => 'login-stay')).
  101. graf(
  102. fInput('submit', '', gTxt('log_in_button'), 'publish').n
  103. ).
  104. graf(
  105. href(gTxt('password_forgotten'), '?reset=1')
  106. , array('class' => 'login-forgot'));
  107. if (gps('event')) {
  108. $out[] = eInput(gps('event'));
  109. }
  110. }
  111. echo form(
  112. tag(join('', $out), 'section', array(
  113. 'role' => 'region',
  114. 'class' => 'txp-login',
  115. 'aria-labelledby' => 'txp-login-heading',
  116. ))
  117. , '', '', 'post', '', '', 'login_form').
  118. script_js('textpattern.textarray = '.json_encode($textarray_script)).
  119. n.'</main><!-- /txp-body -->'.n.'</body>'.n.'</html>';
  120. exit(0);
  121. }
  122. /**
  123. * Validates the sent login form and creates a session.
  124. *
  125. * @return string A localised feedback message
  126. * @see doLoginForm()
  127. */
  128. function doTxpValidate()
  129. {
  130. global $logout, $txp_user;
  131. $p_userid = ps('p_userid');
  132. $p_password = ps('p_password');
  133. $p_reset = ps('p_reset');
  134. $stay = ps('stay');
  135. $logout = gps('logout');
  136. $message = '';
  137. $pub_path = preg_replace('|//$|','/', rhu.'/');
  138. if (cs('txp_login') and strpos(cs('txp_login'), ',')) {
  139. $txp_login = explode(',', cs('txp_login'));
  140. $c_hash = end($txp_login);
  141. $c_userid = join(',', array_slice($txp_login, 0, -1));
  142. } else {
  143. $c_hash = '';
  144. $c_userid = '';
  145. }
  146. if ($logout) {
  147. setcookie('txp_login', '', time() - 3600);
  148. setcookie('txp_login_public', '', time() - 3600, $pub_path);
  149. }
  150. if ($c_userid and strlen($c_hash) == 32) { // Cookie exists.
  151. $r = safe_row(
  152. 'name, nonce',
  153. 'txp_users',
  154. "name='".doSlash($c_userid)."' AND last_access > DATE_SUB(NOW(), INTERVAL 30 DAY)"
  155. );
  156. if ($r && $r['nonce'] && $r['nonce'] === md5($c_userid.pack('H*', $c_hash))) {
  157. // Cookie is good.
  158. if ($logout) {
  159. // Destroy nonce.
  160. safe_update(
  161. 'txp_users',
  162. "nonce = '".doSlash(md5(uniqid(mt_rand(), true)))."'",
  163. "name = '".doSlash($c_userid)."'"
  164. );
  165. } else {
  166. // Create $txp_user.
  167. $txp_user = $r['name'];
  168. }
  169. return $message;
  170. } else {
  171. setcookie('txp_login', $c_userid, time() + 3600 * 24 * 365);
  172. setcookie('txp_login_public', '', time() - 3600, $pub_path);
  173. $message = array(gTxt('bad_cookie'), E_ERROR);
  174. }
  175. } elseif ($p_userid and $p_password) { // Incoming login vars.
  176. $name = txp_validate($p_userid, $p_password);
  177. if ($name !== false) {
  178. $c_hash = md5(uniqid(mt_rand(), true));
  179. $nonce = md5($name.pack('H*', $c_hash));
  180. safe_update(
  181. 'txp_users',
  182. "nonce = '".doSlash($nonce)."'",
  183. "name = '".doSlash($name)."'"
  184. );
  185. setcookie(
  186. 'txp_login',
  187. $name.','.$c_hash,
  188. ($stay ? time()+3600*24*365 : 0),
  189. null,
  190. null,
  191. null,
  192. LOGIN_COOKIE_HTTP_ONLY
  193. );
  194. setcookie(
  195. 'txp_login_public',
  196. substr(md5($nonce), -10).$name,
  197. ($stay ? time()+3600*24*30 : 0),
  198. $pub_path
  199. );
  200. // Login is good, create $txp_user.
  201. $txp_user = $name;
  202. return '';
  203. } else {
  204. sleep(3);
  205. $message = array(gTxt('could_not_log_in'), E_ERROR);
  206. }
  207. } elseif ($p_reset) { // Reset request.
  208. sleep(3);
  209. include_once txpath.'/lib/txplib_admin.php';
  210. $message = ($p_userid) ? send_reset_confirmation_request($p_userid) : '';
  211. } elseif (gps('reset')) {
  212. $message = '';
  213. } elseif (gps('confirm')) {
  214. sleep(3);
  215. $confirm = pack('H*', gps('confirm'));
  216. $name = substr($confirm, 5);
  217. $nonce = safe_field('nonce', 'txp_users', "name = '".doSlash($name)."'");
  218. if ($nonce and $confirm === pack('H*', substr(md5($nonce), 0, 10)).$name) {
  219. include_once txpath.'/lib/txplib_admin.php';
  220. $message = reset_author_pass($name);
  221. }
  222. }
  223. $txp_user = '';
  224. return $message;
  225. }