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