2 if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
3 /*********************************************************************************
4 * SugarCRM Community Edition is a customer relationship management program developed by
5 * SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
7 * This program is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU Affero General Public License version 3 as published by the
9 * Free Software Foundation with the addition of the following permission added
10 * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
11 * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
12 * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
19 * You should have received a copy of the GNU Affero General Public License along with
20 * this program; if not, see http://www.gnu.org/licenses or write to the Free
21 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24 * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
25 * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
27 * The interactive user interfaces in modified source and object code versions
28 * of this program must display Appropriate Legal Notices, as required under
29 * Section 5 of the GNU Affero General Public License version 3.
31 * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
32 * these Appropriate Legal Notices must retain the display of the "Powered by
33 * SugarCRM" logo. If the display of the logo is not reasonably feasible for
34 * technical reasons, the Appropriate Legal Notices must display the words
35 * "Powered by SugarCRM".
36 ********************************************************************************/
40 class AuthenticationController
42 public $loggedIn = false; //if a user has attempted to login
43 public $authenticated = false;
44 public $loginSuccess = false;// if a user has successfully logged in
46 protected static $authcontrollerinstance = null;
49 * @var SugarAuthenticate
51 public $authController;
54 * Creates an instance of the authentication controller and loads it
56 * @param STRING $type - the authentication Controller
57 * @return AuthenticationController -
59 public function __construct($type = null)
61 $this->authController = $this->getAuthController($type);
65 * Get auth controller object
67 * @return SugarAuthenticate
69 protected function getAuthController($type)
72 $type = !empty($GLOBALS['sugar_config']['authenticationClass'])
73 ? $GLOBALS['sugar_config']['authenticationClass'] : 'SugarAuthenticate';
76 if ($type == 'SugarAuthenticate' && !empty($GLOBALS['system_config']->settings['system_ldap_enabled']) && empty($_SESSION['sugar_user'])) {
77 $type = 'LDAPAuthenticate';
80 // check in custom dir first, in case someone want's to override an auth controller
81 if (file_exists('custom/modules/Users/authentication/'.$type.'/' . $type . '.php')) {
82 require_once('custom/modules/Users/authentication/'.$type.'/' . $type . '.php');
83 } elseif (file_exists('modules/Users/authentication/'.$type.'/' . $type . '.php')) {
84 require_once('modules/Users/authentication/'.$type.'/' . $type . '.php');
86 require_once('modules/Users/authentication/SugarAuthenticate/SugarAuthenticate.php');
87 $type = 'SugarAuthenticate';
90 if (!empty($_REQUEST['no_saml'])
91 && (is_subclass_of($type, 'SAMLAuthenticate') || 'SAMLAuthenticate' == $type)) {
92 $type = 'SugarAuthenticate';
99 * Returns an instance of the authentication controller
101 * @param string $type this is the type of authetnication you want to use default is SugarAuthenticate
102 * @return an instance of the authetnciation controller
104 public static function getInstance($type = null)
106 if (empty(self::$authcontrollerinstance)) {
107 self::$authcontrollerinstance = new AuthenticationController($type);
110 return self::$authcontrollerinstance;
114 * This function is called when a user initially tries to login.
116 * @param string $username
117 * @param string $password
118 * @param array $PARAMS
119 * @return boolean true if the user successfully logs in or false otherwise.
121 public function login($username, $password, $PARAMS = array())
124 $_SESSION['loginAttempts'] = (isset($_SESSION['loginAttempts']))? $_SESSION['loginAttempts'] + 1: 1;
125 unset($GLOBALS['login_error']);
127 if($this->loggedIn)return $this->loginSuccess;
128 LogicHook::initialize()->call_custom_logic('Users', 'before_login');
130 $this->loginSuccess = $this->authController->loginAuthenticate($username, $password, false, $PARAMS);
131 $this->loggedIn = true;
133 if($this->loginSuccess){
134 //Ensure the user is authorized
135 checkAuthUserStatus();
138 if(!empty($GLOBALS['login_error'])){
139 unset($_SESSION['authenticated_user_id']);
140 $GLOBALS['log']->fatal('FAILED LOGIN: potential hack attempt:'.$GLOBALS['login_error']);
141 $this->loginSuccess = false;
145 //call business logic hook
146 if(isset($GLOBALS['current_user']))
147 $GLOBALS['current_user']->call_custom_logic('after_login');
149 // Check for running Admin Wizard
150 $config = new Administration();
151 $config->retrieveSettings();
152 if ( is_admin($GLOBALS['current_user']) && empty($config->settings['system_adminwizard']) && $_REQUEST['action'] != 'AdminWizard' ) {
153 $GLOBALS['module'] = 'Configurator';
154 $GLOBALS['action'] = 'AdminWizard';
156 header("Location: index.php?module=Configurator&action=AdminWizard");
160 $ut = $GLOBALS['current_user']->getPreference('ut');
161 $checkTimeZone = true;
162 if (is_array($PARAMS) && !empty($PARAMS) && isset($PARAMS['passwordEncrypted'])) {
163 $checkTimeZone = false;
165 if(empty($ut) && $checkTimeZone && $_REQUEST['action'] != 'SetTimezone' && $_REQUEST['action'] != 'SaveTimezone' ) {
166 $GLOBALS['module'] = 'Users';
167 $GLOBALS['action'] = 'Wizard';
169 header("Location: index.php?module=Users&action=Wizard");
174 LogicHook::initialize();
175 $GLOBALS['logic_hook']->call_custom_logic('Users', 'login_failed');
176 $GLOBALS['log']->fatal('FAILED LOGIN:attempts[' .$_SESSION['loginAttempts'] .'] - '. $username);
178 // if password has expired, set a session variable
180 return $this->loginSuccess;
184 * This is called on every page hit.
185 * It returns true if the current session is authenticated or false otherwise
189 public function sessionAuthenticate()
191 if(!$this->authenticated){
192 $this->authenticated = $this->authController->sessionAuthenticate();
194 if($this->authenticated){
195 if(!isset($_SESSION['userStats']['pages'])){
196 $_SESSION['userStats']['loginTime'] = time();
197 $_SESSION['userStats']['pages'] = 0;
199 $_SESSION['userStats']['lastTime'] = time();
200 $_SESSION['userStats']['pages']++;
203 return $this->authenticated;
207 * Called when a user requests to logout. Should invalidate the session and redirect
210 public function logout()
212 $GLOBALS['current_user']->call_custom_logic('before_logout');
213 $this->authController->logout();
214 LogicHook::initialize();
215 $GLOBALS['logic_hook']->call_custom_logic('Users', 'after_logout');