/** * Try to authenticate user from : * SSO * COOKIE * Given parameters * SESSION * * @return Zend_Auth_Result */ public function authenticate() { if (isset($this->_params['authType'])) { switch ($this->_params['authType']) { case 'credentials': if (isset($this->_params['login']) && isset($this->_params['password']) && $this->_params['login'] && $this->_params['password']) { //check token if (isset($this->_params['tokenName']) && $this->_params['tokenName'] && (!isset($this->_params['token']) || !$this->_params['token'] || !CMS_session::checkToken($this->_params['tokenName'], $this->_params['token']))) { $this->_messages[] = self::AUTH_INVALID_TOKEN; $this->_result = new Zend_Auth_Result(Zend_Auth_Result::FAILURE, null, $this->_messages); } else { //check user credentials from DB $sql = "\n\t\t\t\t\t\t\t\tselect\n\t\t\t\t\t\t\t\t\tid_pru\n\t\t\t\t\t\t\t\tfrom\n\t\t\t\t\t\t\t\t\tprofilesUsers\n\t\t\t\t\t\t\t\twhere\n\t\t\t\t\t\t\t\t\tlogin_pru = '" . SensitiveIO::sanitizeSQLString($this->_params['login']) . "'\n\t\t\t\t\t\t\t\t\tand (\n\t\t\t\t\t\t\t\t\t\tpassword_pru = '" . SensitiveIO::sanitizeSQLString(md5($this->_params['password'])) . "'\n\t\t\t\t\t\t\t\t\t\tor password_pru = '{sha}" . SensitiveIO::sanitizeSQLString(sha1($this->_params['password'])) . "'\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\tand password_pru != ''\n\t\t\t\t\t\t\t\t\tand active_pru = 1\n\t\t\t\t\t\t\t\t\tand deleted_pru = 0\n\t\t\t\t\t\t\t"; $q = new CMS_query($sql); if ($q->getNumRows()) { $userId = $q->getValue("id_pru"); $this->_user = CMS_profile_usersCatalog::getByID($userId); if ($this->_user && !$this->_user->hasError() && !$this->_user->isDeleted() && $this->_user->isActive()) { $this->_messages[] = self::AUTH_VALID_CREDENTIALS; $this->_result = new Zend_Auth_Result(Zend_Auth_Result::SUCCESS, $this->_user->getUserId(), $this->_messages); //remove previous autologin cookie if exists if (isset($_COOKIE[CMS_session::getAutoLoginCookieName()])) { CMS_session::setCookie(CMS_session::getAutoLoginCookieName()); } return $this->_result; } else { $this->_messages[] = self::AUTH_INVALID_USER; $this->_result = new Zend_Auth_Result(Zend_Auth_Result::FAILURE, null, $this->_messages); $this->raiseError("user_id found don't instanciate a valid user object. ID : " . $userId); } } else { $this->_messages[] = self::AUTH_INVALID_CREDENTIALS; $this->_result = new Zend_Auth_Result(Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID, null, $this->_messages); //wait a little (5 seconds) to avoid multiple simultaneous attempts sleep(5); } } } break; case 'session': $authStorage = new Zend_Auth_Storage_Session('atm-auth'); $userId = $authStorage->read(); if (io::isPositiveInteger($userId)) { if (!isset($this->_params['disconnect']) || !$this->_params['disconnect']) { //check user from session table if ($this->_checkSession($userId)) { $this->_user = CMS_profile_usersCatalog::getByID($userId); if ($this->_user && !$this->_user->hasError() && !$this->_user->isDeleted() && $this->_user->isActive()) { $this->_messages[] = self::AUTH_VALID_USER_SESSION; $this->_result = new Zend_Auth_Result(Zend_Auth_Result::SUCCESS, $this->_user->getUserId(), $this->_messages); return $this->_result; } else { $this->_messages[] = self::AUTH_INVALID_USER_SESSION; $this->_result = new Zend_Auth_Result(Zend_Auth_Result::FAILURE, null, $this->_messages); //clear session content CMS_session::deleteSession(true); } } else { //clear session content CMS_session::deleteSession(); } } } break; case 'cookie': if (isset($_COOKIE[CMS_session::getAutoLoginCookieName()])) { if (!isset($this->_params['disconnect']) || !$this->_params['disconnect']) { if (!$this->_autoLogin()) { //remove cookie CMS_session::setCookie(CMS_session::getAutoLoginCookieName()); } else { return $this->_result; } } } break; case 'sso': if (!(isset($this->_params['login']) && isset($this->_params['password']) && $this->_params['login'] && $this->_params['password'])) { if (defined('MOD_STANDARD_SSO_LOGIN') && MOD_STANDARD_SSO_LOGIN) { $this->_user = CMS_profile_usersCatalog::getByLogin(MOD_STANDARD_SSO_LOGIN); if ($this->_user && !$this->_user->hasError()) { $this->_messages[] = self::AUTH_SSOLOGIN_VALID; $this->_result = new Zend_Auth_Result(Zend_Auth_Result::SUCCESS, $this->_user->getUserId(), $this->_messages); return $this->_result; } else { $this->_messages[] = self::AUTH_SSOLOGIN_INVALID_USER; $this->_result = new Zend_Auth_Result(Zend_Auth_Result::FAILURE, null, $this->_messages); } } elseif (defined('MOD_STANDARD_SSO_FUNCTION') && MOD_STANDARD_SSO_FUNCTION) { if (is_callable(MOD_STANDARD_SSO_FUNCTION, false)) { //check if function/method name exists. $login = ''; if (io::strpos(MOD_STANDARD_SSO_FUNCTION, '::') !== false) { //static method call $method = explode('::', MOD_STANDARD_SSO_FUNCTION); $login = call_user_func(array($method[0], $method[1])); } else { //function call $login = call_user_func(MOD_STANDARD_SSO_FUNCTION); } if ($login) { $this->_user = CMS_profile_usersCatalog::getByLogin($login); if ($this->_user && !$this->_user->hasError()) { $this->_messages[] = self::AUTH_SSOLOGIN_VALID; $this->_result = new Zend_Auth_Result(Zend_Auth_Result::SUCCESS, $this->_user->getUserId(), $this->_messages); return $this->_result; } else { $this->_messages[] = self::AUTH_SSOLOGIN_INVALID_USER; $this->_result = new Zend_Auth_Result(Zend_Auth_Result::FAILURE, null, $this->_messages); } } } else { $this->raiseError('Cannot call SSO method/function: ' . MOD_STANDARD_SSO_FUNCTION); } } } break; default: CMS_grandFather::raiseError('Unknown authType: ' . $this->_params['authType']); break; } } //Nothing found if (!$this->_result) { $this->_messages[] = self::AUTH_MISSING_CREDENTIALS; $this->_result = new Zend_Auth_Result(Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND, null, $this->_messages); } return $this->_result; }
/** * Authenticate user * This method can * - authenticate user throught authentification process * - load already authenticated user in current session (or SSO) * - disconnect user * * @param array $params : indexed array of authentification parameters (default : nothing) * Accepted array keys are : * - authenticate : boolean : default true if disconnect is not set * - disconnect : boolean : default false * - login : string : user login to authenticate * - password : string : user password to authenticate * - remember : boolean : default false * - tokenName : string * - token : string * - type : string : type of authentification (admin|frontend) : default APPLICATION_USER_TYPE contant * - ... and any parameter needed by authentifications processes handled by modules * @return void * @access public * @static */ public static function authenticate($params = array()) { //first clean old sessions datas from database CMS_session::_cleanSessions(); // Get Zend Auth instance $auth = Zend_Auth::getInstance(); // Use CMS_auth as session storage space $auth->setStorage(new Zend_Auth_Storage_Session('atm-auth')); //set authentification type if (!isset($params['type'])) { $params['type'] = APPLICATION_USER_TYPE; } //set permanent auth status if (isset($params['remember']) && $params['remember']) { self::$_permanent = true; } else { $params['remember'] = false; } //clear auth storage if disconnection is queried and set default authenticate value if (isset($params['disconnect']) && $params['disconnect']) { //log disconection if user exists $storageValue = $auth->getStorage()->read(); if (io::isPositiveInteger($storageValue)) { //load user $user = CMS_profile_usersCatalog::getByID($storageValue); if ($user) { //log new session $log = new CMS_log(); $log->logMiscAction(CMS_log::LOG_ACTION_DISCONNECT, $user, 'IP: ' . @$_SERVER['REMOTE_ADDR'] . ', UA: ' . @$_SERVER['HTTP_USER_AGENT']); } } //clear session content CMS_session::deleteSession(true); if (!isset($params['authenticate'])) { $params['authenticate'] = false; } } else { $params['disconnect'] = false; if (!isset($params['authenticate'])) { $params['authenticate'] = true; } } //init authenticated boolean $authenticated = false; //keep old storage value, because storage will be reseted by each module authentification $storageValue = $auth->getStorage()->read(); //loop on each authentification types suupported foreach (array('credentials', 'session', 'cookie', 'sso') as $authType) { //load modules $modules = CMS_modulesCatalog::getAll('id'); //get last module $module = array_pop($modules); //set authentification type as param $params['authType'] = $authType; //then try it for each modules do { //if module has auth method, try it if (method_exists($module, 'getAuthAdapter')) { //overwrite auth storage value with old value $auth->getStorage()->write($storageValue); //get module auth adapter $authAdapter = $module->getAuthAdapter($params); //authenticate user self::$_result = $auth->authenticate($authAdapter); //To debug Auth process easily, discomment this line //CMS_grandFather::log($_SERVER['SCRIPT_NAME'].' - '.$module->getCodename().' - Auth type : '.$authType.'/'.$params['type'].' - Auth result : '.self::$_result->getCode().($auth->hasIdentity() ? ' - Identity : '.$auth->getIdentity() : '').' - Message : '.(sizeof(self::$_result->getMessages()) == 1 ? array_pop(self::$_result->getMessages()) : print_r(self::$_result->getMessages(), true))); switch (self::$_result->getCode()) { case Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND: //user crendentials does not exists (ex: no login/pass provided) //nothing for now break; case Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID: //invalid login/pass //nothing for now break; case Zend_Auth_Result::SUCCESS: if ($auth->hasIdentity()) { // get user from identity found $user = $authAdapter->getUser($auth->getIdentity()); //check if user is valid if (isset($user) && $user && !$user->hasError() && !$user->isDeleted() && $user->isActive()) { $authenticated = true; //overwrite auth identity with valid user Id $auth->getStorage()->write($user->getUserId()); } else { unset($user); } } break; case Zend_Auth_Result::FAILURE: //user found but has error during loading (user inactive or deleted) //nothing for now break; default: //other unidentified cases : thrown an error CMS_grandFather::raiseError('Authentification return code ' . self::$_result->getCode() . ' for module ' . $module->getCodename() . ' with parameters ' . print_r($params, true)); break; } } //get next last module $module = array_pop($modules); } while (!$authenticated && $module); //if user is authenticated, break authentification foreach if ($authenticated) { break; } } //if authenticated : set or refresh session datas in table, regenerate session Id if ($authenticated && $user) { $q = new CMS_query("\n\t\t\tselect \n\t\t\t\tid_ses, cookie_expire_ses\n\t\t\tfrom \n\t\t\t\tsessions \n\t\t\twhere \n\t\t\t\tphpid_ses='" . sensitiveIO::sanitizeSQLString(Zend_Session::getId()) . "' \n\t\t\t\tand user_ses='" . sensitiveIO::sanitizeSQLString($user->getUserId()) . "'"); //get old session Id $oldSessionId = Zend_Session::getId(); if ($q->getNumRows() > 0) { //if session already exists : update it //regenerate session Id randomly (arround 1/100 times) //removed : cause session instability /*if (!rand(0, 100)) { //session id should not be regenerated each times because in case of a lot of concurrent calls, session can be destroyed Zend_Session::regenerateId(); }*/ $r = $q->getArray(); $id = $r['id_ses']; //Cookie if (self::$_permanent || $r['cookie_expire_ses'] != '0000-00-00 00:00:00') { self::$_permanent = true; // Cookie expire in APPLICATION_COOKIE_EXPIRATION days $expires = time() + 60 * 60 * 24 * APPLICATION_COOKIE_EXPIRATION; CMS_session::setCookie(CMS_session::getAutoLoginCookieName(), base64_encode($id . '|' . Zend_Session::getId()), $expires); } //DB session $sql = "\n\t\t\t\t\tupdate \n\t\t\t\t\t\tsessions \n\t\t\t\t\tset\n\t\t\t\t\t\tlastTouch_ses=NOW(),\n\t\t\t\t\t\tuser_ses='" . sensitiveIO::sanitizeSQLString($user->getUserId()) . "',\n\t\t\t\t\t\tphpid_ses='" . sensitiveIO::sanitizeSQLString(Zend_Session::getId()) . "',\n\t\t\t\t\t\tremote_addr_ses='" . sensitiveIO::sanitizeSQLString(@$_SERVER['REMOTE_ADDR']) . "'"; if (self::$_permanent) { $sql .= ",\n\t\t\t\t\t\tcookie_expire_ses = DATE_ADD(NOW(), INTERVAL " . APPLICATION_COOKIE_EXPIRATION . " DAY)"; } $sql .= "\n\t\t\t\t\twhere\n\t\t\t\t\t \tid_ses='" . sensitiveIO::sanitizeSQLString($id) . "'"; $q = new CMS_query($sql); //if autologin : log it if (in_array(CMS_auth::AUTH_AUTOLOGIN_VALID, self::$_result->getMessages())) { //log autologin session $log = new CMS_log(); $log->logMiscAction(CMS_log::LOG_ACTION_AUTO_LOGIN, $user, 'IP: ' . @$_SERVER['REMOTE_ADDR'] . ', UA: ' . @$_SERVER['HTTP_USER_AGENT']); } } else { //otherwhise, create user session //regenerate session Id Zend_Session::regenerateId(); //delete old session record if any $q = new CMS_query("\n\t\t\t\t\tdelete\n\t\t\t\t\tfrom \n\t\t\t\t\t\tsessions \n\t\t\t\t\twhere \n\t\t\t\t\t\tphpid_ses='" . sensitiveIO::sanitizeSQLString($oldSessionId) . "'"); //insert new session record $sql = "\n\t\t\t\t\tinsert into\n\t\t\t\t\t\tsessions\n\t\t\t\t\tset\n\t\t\t\t\t\tlastTouch_ses=NOW(),\n\t\t\t\t\t\tphpid_ses='" . sensitiveIO::sanitizeSQLString(Zend_Session::getId()) . "',\n\t\t\t\t\t\tuser_ses='" . sensitiveIO::sanitizeSQLString($user->getUserId()) . "',\n\t\t\t\t\t\tremote_addr_ses='" . sensitiveIO::sanitizeSQLString(@$_SERVER['REMOTE_ADDR']) . "'\n\t\t\t\t"; if (self::$_permanent) { $sql .= ",\n\t\t\t\t\tcookie_expire_ses = DATE_ADD(NOW(), INTERVAL " . APPLICATION_COOKIE_EXPIRATION . " DAY)"; } $q = new CMS_query($sql); if (!$q->hasError() && self::$_permanent) { // Cookie expire in APPLICATION_COOKIE_EXPIRATION days $expires = time() + 60 * 60 * 24 * APPLICATION_COOKIE_EXPIRATION; CMS_session::setCookie(CMS_session::getAutoLoginCookieName(), base64_encode($q->getLastInsertedID() . '|' . Zend_Session::getId()), $expires); } //log new session $log = new CMS_log(); $log->logMiscAction(CMS_log::LOG_ACTION_LOGIN, $user, 'Permanent cookie: ' . (self::$_permanent ? 'Yes' : 'No') . ', IP: ' . @$_SERVER['REMOTE_ADDR'] . ', UA: ' . @$_SERVER['HTTP_USER_AGENT']); } //set user as currently logged user self::$_userID = $user->getUserId(); } else { if (APPLICATION_USER_TYPE == "frontend" && APPLICATION_ENFORCES_ACCESS_CONTROL) { //set public user as currently logged user self::$_userID = ANONYMOUS_PROFILEUSER_ID; } } //for backward compatibility $_SESSION["cms_context"] = new CMS_context(); }