PageRenderTime 50ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/application/controllers/admin/authentication.php

https://bitbucket.org/sammousa/valuematchbv-ls2
PHP | 379 lines | 244 code | 44 blank | 91 comment | 26 complexity | 2ef35bf0fe5da15163edbb707c58ffba MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, BSD-3-Clause, GPL-3.0, LGPL-3.0
  1. <?php
  2. if (!defined('BASEPATH'))
  3. exit('No direct script access allowed');
  4. /*
  5. * LimeSurvey
  6. * Copyright (C) 2007-2011 The LimeSurvey Project Team / Carsten Schmitz
  7. * All rights reserved.
  8. * License: GNU/GPL License v2 or later, see LICENSE.php
  9. * LimeSurvey is free software. This version may have been modified pursuant
  10. * to the GNU General Public License, and as distributed it includes or
  11. * is derivative of works licensed under the GNU General Public License or
  12. * other free or open source software licenses.
  13. * See COPYRIGHT.php for copyright notices and details.
  14. *
  15. * $Id$
  16. */
  17. /**
  18. * Authentication Controller
  19. *
  20. * This controller performs authentication
  21. *
  22. * @package LimeSurvey
  23. * @subpackage Backend
  24. */
  25. class Authentication extends Survey_Common_Action
  26. {
  27. /**
  28. * Show login screen and parse login data
  29. */
  30. public function index()
  31. {
  32. $this->_redirectIfLoggedIn();
  33. $bCanLogin = $this->_userCanLogin();
  34. if ($bCanLogin && !is_array($bCanLogin))
  35. {
  36. if (Yii::app()->request->getPost('action') || !is_null(Yii::app()->request->getQuery('onepass')) || Yii::app()->getConfig('auth_webserver') === true)
  37. {
  38. $aData = $this->_doLogin(Yii::app()->request->getParam('user'), Yii::app()->request->getPost('password'),Yii::app()->request->getQuery('onepass',''));
  39. if (!isset($aData['errormsg']))
  40. {
  41. Failed_login_attempts::model()->deleteAttempts();
  42. $this->getController()->_GetSessionUserRights(Yii::app()->session['loginID']);
  43. Yii::app()->session['just_logged_in'] = true;
  44. Yii::app()->session['loginsummary'] = $this->_getSummary();
  45. $this->_doRedirect();
  46. die();
  47. }
  48. else
  49. {
  50. $this->_renderWrappedTemplate('authentication', 'error', $aData);
  51. }
  52. }
  53. else
  54. {
  55. $this->_showLoginForm();
  56. }
  57. }
  58. else
  59. {
  60. $this->_renderWrappedTemplate('authentication', 'error', $bCanLogin);
  61. }
  62. }
  63. /**
  64. * Logout user
  65. */
  66. public function logout()
  67. {
  68. Yii::app()->user->logout();
  69. $this->_showLoginForm($this->getController()->lang->gT('Logout successful.'));
  70. }
  71. /**
  72. * Forgot Password screen
  73. */
  74. public function forgotpassword()
  75. {
  76. $this->_redirectIfLoggedIn();
  77. if (!Yii::app()->request->getPost('action'))
  78. {
  79. $this->_renderWrappedTemplate('authentication', 'forgotpassword');
  80. }
  81. else
  82. {
  83. $sUserName = Yii::app()->request->getPost('user');
  84. $sEmailAddr = Yii::app()->request->getPost('email');
  85. $aFields = User::model()->findAllByAttributes(array('users_name' => $sUserName, 'email' => $sEmailAddr));
  86. if (count($aFields) < 1)
  87. {
  88. // wrong or unknown username and/or email
  89. $aData['errormsg'] = $this->getController()->lang->gT('User name and/or email not found!');
  90. $aData['maxattempts'] = '';
  91. $this->_renderWrappedTemplate('authentication', 'error', $aData);
  92. }
  93. else
  94. {
  95. $aData['message'] = $this->_sendPasswordEmail($sEmailAddr, $aFields);
  96. $this->_renderWrappedTemplate('authentication', 'message', $aData);
  97. }
  98. }
  99. }
  100. /**
  101. * Send the forgot password email
  102. *
  103. * @param string $sEmailAddr
  104. * @param array $aFields
  105. */
  106. private function _sendPasswordEmail($sEmailAddr, $aFields)
  107. {
  108. $clang = $this->getController()->lang;
  109. $sFrom = Yii::app()->getConfig('siteadminemail');
  110. $sTo = $sEmailAddr;
  111. $sSubject = $clang->gT('User data');
  112. $sNewPass = createPassword();
  113. $sSiteName = Yii::app()->getConfig('sitename');
  114. $sSiteAdminBounce = Yii::app()->getConfig('siteadminbounce');
  115. $username = sprintf($clang->gT('Username: %s'), $aFields[0]['users_name']);
  116. $email = sprintf($clang->gT('Email: %s'), $sEmailAddr);
  117. $password = sprintf($clang->gT('New password: %s'), $sNewPass);
  118. $body = array();
  119. $body[] = sprintf($clang->gT('Your user data for accessing %s'), Yii::app()->getConfig('sitename'));
  120. $body[] = $username;
  121. $body[] = $password;
  122. $body = implode("\n", $body);
  123. if (SendEmailMessage($body, $sSubject, $sTo, $sFrom, $sSiteName, false, $sSiteAdminBounce))
  124. {
  125. User::model()->updatePassword($aFields[0]['uid'], hash('sha256', $sNewPass));
  126. $sMessage = $username . '<br />' . $email . '<br /><br />' . $clang->gT('An email with your login data was sent to you.');
  127. }
  128. else
  129. {
  130. $sTmp = str_replace("{NAME}", '<strong>' . $aFields[0]['users_name'] . '</strong>', $clang->gT("Email to {NAME} ({EMAIL}) failed."));
  131. $sMessage = str_replace("{EMAIL}", $sEmailAddr, $sTmp) . '<br />';
  132. }
  133. return $sMessage;
  134. }
  135. /**
  136. * Show login screen
  137. * @param optional message
  138. */
  139. protected function _showLoginForm($sLogoutSummary = '')
  140. {
  141. $aData['summary'] = $this->_getSummary('logout', $sLogoutSummary);
  142. $this->_renderWrappedTemplate('authentication', 'login', $aData);
  143. }
  144. /**
  145. * Get's the summary
  146. * @param string $sMethod login|logout
  147. * @param string $sSummary Default summary
  148. * @return string Summary
  149. */
  150. private function _getSummary($sMethod = 'login', $sSummary = '')
  151. {
  152. if (!empty($sSummary))
  153. {
  154. return $sSummary;
  155. }
  156. $clang = $this->getController()->lang;
  157. switch ($sMethod) {
  158. case 'logout' :
  159. $sSummary = $clang->gT('Please log in first.');
  160. break;
  161. case 'login' :
  162. default :
  163. $sSummary = '<br />' . sprintf($clang->gT('Welcome %s!'), Yii::app()->session['full_name']) . '<br />&nbsp;';
  164. if (!empty(Yii::app()->session['redirect_after_login']) && strpos(Yii::app()->session['redirect_after_login'], 'logout') === FALSE)
  165. {
  166. Yii::app()->session['metaHeader'] = '<meta http-equiv="refresh"'
  167. . ' content="1;URL=' . Yii::app()->session['redirect_after_login'] . '" />';
  168. $sSummary = '<p><font size="1"><i>' . $clang->gT('Reloading screen. Please wait.') . '</i></font>';
  169. unset(Yii::app()->session['redirect_after_login']);
  170. }
  171. break;
  172. }
  173. return $sSummary;
  174. }
  175. /**
  176. * Redirects a logged in user to the administration page
  177. */
  178. private function _redirectIfLoggedIn()
  179. {
  180. if (!Yii::app()->user->getIsGuest())
  181. {
  182. Yii::app()->request->redirect($this->getController()->createUrl('/admin'));
  183. }
  184. }
  185. /**
  186. * Check if a user can log in
  187. * @return bool|array
  188. */
  189. private function _userCanLogin()
  190. {
  191. $failed_login_attempts = Failed_login_attempts::model();
  192. $failed_login_attempts->cleanOutOldAttempts();
  193. if ($failed_login_attempts->isLockedOut())
  194. {
  195. return $this->_getAuthenticationFailedErrorMessage();
  196. }
  197. else
  198. {
  199. return true;
  200. }
  201. }
  202. /**
  203. * Redirect after login
  204. */
  205. private function _doRedirect()
  206. {
  207. if (strlen(Yii::app()->session['redirectopage']) > 1)
  208. {
  209. Yii::app()->request->redirect(Yii::app()->session['redirectopage']);
  210. }
  211. else
  212. {
  213. Yii::app()->request->redirect($this->getController()->createUrl('/admin'));
  214. }
  215. }
  216. /**
  217. * Do the actual login work
  218. * Note: This function is replicated in parts in remotecontrol.php controller - if you change this don't forget to make according changes there, too (which is why we should make a login helper)
  219. * @param string $sUsername The username to login with
  220. * @param string $sPassword The password to login with
  221. * @return Array of data containing errors for the view
  222. */
  223. private function _doLogin($sUsername, $sPassword, $sOneTimePassword)
  224. {
  225. $identity = new UserIdentity(sanitize_user($sUsername), $sPassword);
  226. if (!$identity->authenticate($sOneTimePassword))
  227. {
  228. return $this->_getAuthenticationFailedErrorMessage();
  229. }
  230. @session_regenerate_id(); // Prevent session fixation
  231. return $this->_setLoginSessions($identity);
  232. }
  233. /**
  234. * Sets the login sessions
  235. * @param UserIdentity $identity
  236. * @return bool True
  237. */
  238. private function _setLoginSessions($identity)
  239. {
  240. $user = $identity->getUser();
  241. Yii::app()->user->login($identity);
  242. $this->_checkForUsageOfDefaultPassword();
  243. $this->_setSessionData($user);
  244. $this->_setLanguageSettings($user);
  245. return true;
  246. }
  247. /**
  248. * Sets the session data
  249. * @param CActiveRecord $user
  250. */
  251. private function _setSessionData($user)
  252. {
  253. Yii::app()->session['loginID'] = (int) $user->uid;
  254. Yii::app()->session['user'] = $user->users_name;
  255. Yii::app()->session['full_name'] = $user->full_name;
  256. Yii::app()->session['htmleditormode'] = $user->htmleditormode;
  257. Yii::app()->session['templateeditormode'] = $user->templateeditormode;
  258. Yii::app()->session['questionselectormode'] = $user->questionselectormode;
  259. Yii::app()->session['dateformat'] = $user->dateformat;
  260. Yii::app()->session['session_hash'] = hash('sha256',getGlobalSetting('SessionName').$user->users_name.$user->uid);
  261. }
  262. /**
  263. * Sets the language settings for the user
  264. * @param CActiveRecord $user
  265. */
  266. private function _setLanguageSettings($user)
  267. {
  268. if (Yii::app()->request->getPost('loginlang','default') != 'default')
  269. {
  270. $user->lang = sanitize_languagecode(Yii::app()->request->getPost('loginlang'));
  271. $user->save();
  272. $sLanguage=$user->lang;
  273. }
  274. else if ($user->lang=='auto' || $user->lang=='')
  275. {
  276. $sLanguage= getBrowserLanguage();
  277. }
  278. else
  279. {
  280. $sLanguage=$user->lang;
  281. }
  282. Yii::app()->session['adminlang'] = $sLanguage;
  283. $this->getController()->lang= new limesurvey_lang($sLanguage);
  284. }
  285. /**
  286. * Checks if the user is using default password
  287. */
  288. private function _checkForUsageOfDefaultPassword()
  289. {
  290. $clang = $this->getController()->lang;
  291. Yii::app()->session['pw_notify'] = false;
  292. if (strtolower(Yii::app()->request->getPost('password','') ) === 'password')
  293. {
  294. Yii::app()->session['pw_notify'] = true;
  295. Yii::app()->session['flashmessage'] = $clang->gT('Warning: You are still using the default password (\'password\'). Please change your password and re-login again.');
  296. }
  297. }
  298. /**
  299. * Get the authentication failed error messages
  300. * @return array Data
  301. */
  302. private function _getAuthenticationFailedErrorMessage()
  303. {
  304. $clang = $this->getController()->lang;
  305. $aData = array();
  306. $userHostAddress = Yii::app()->request->getUserHostAddress();
  307. $bUserNotFound = Failed_login_attempts::model()->addAttempt($userHostAddress);
  308. if ($bUserNotFound)
  309. {
  310. $aData['errormsg'] = $clang->gT('Incorrect username and/or password!');
  311. $aData['maxattempts'] = '';
  312. }
  313. $bLockedOut = Failed_login_attempts::model()->isLockedOut($userHostAddress);
  314. if ($bLockedOut)
  315. {
  316. $aData['maxattempts'] = sprintf(
  317. $clang->gT('You have exceeded the number of maximum login attempts. Please wait %d minutes before trying again.'),
  318. Yii::app()->getConfig('timeOutTime') / 60
  319. );
  320. }
  321. return $aData;
  322. }
  323. /**
  324. * Renders template(s) wrapped in header and footer
  325. *
  326. * @param string $sAction Current action, the folder to fetch views from
  327. * @param string|array $aViewUrls View url(s)
  328. * @param array $aData Data to be passed on. Optional.
  329. */
  330. protected function _renderWrappedTemplate($sAction = 'authentication', $aViewUrls = array(), $aData = array())
  331. {
  332. $aData['display']['menu_bars'] = false;
  333. parent::_renderWrappedTemplate($sAction, $aViewUrls, $aData);
  334. }
  335. }