setStorage(new Zend_Auth_Storage_Session($this->getSessionNamespace())); Qs_Options::setConstructorOptions($this); } public static function addAuthCredentials($url) { if (defined('BASIC_AUTH_LOGIN') && BASIC_AUTH_LOGIN && defined('BASIC_AUTH_PASSWORD') && BASIC_AUTH_PASSWORD) { $url = str_replace('://', '://' . BASIC_AUTH_LOGIN . ':' . BASIC_AUTH_PASSWORD . '@', $url); } return $url; } public function getSessionNamespace() { if (null === $this->_sessionNamespace) { $this->_sessionNamespace = get_class($this); } return $this->_sessionNamespace; } public function authenticate(Zend_Auth_Adapter_Interface $adapter) { /** @var Qs_Auth_Adapter_DbTable $adapter */ if (method_exists($adapter, 'isRemoteAuthEnabled') && $adapter->isRemoteAuthEnabled() && $adapter->isRemoteUser() ) { if ($this->hasIdentity() && !$adapter->isRemoteUserPasswordExpired()) { if ($adapter->getAutologinCode()) { $identity = null; } else { $identity = $adapter->getIdentity(); } $result = $this->_getResultSuccess($identity); } else { try { $result = $this->_remoteAuthenticate($adapter); } catch (Exception $e) { $result = $this->_getResultFailed($adapter->getIdentity()); } } } else { $result = $adapter->authenticate(); } if ($result->isValid()) { $storageData = $this->getStorage()->read(); if (empty($storageData)) { $storageData = []; $storageData['startTimestamp'] = time(); $storageData['startTime'] = date('Y-m-d H:i:s', $storageData['startTimestamp']); } $storageData['identity'] = $result->getIdentity(); $storageData['credential'] = $adapter->getCredential(); $storageData['data'] = (array) $adapter->getResultRowObject(null, ['password']); if ($this->_autologin) { $code = md5('autologin' . time() . md5(rand(100, 1000))); $adapter->saveAutologinCode($code); setcookie($this->getAutologinVariable(), $code, strtotime('+2 years'), '/', $_SERVER['HTTP_HOST'], false, true); } $this->getStorage()->write($storageData); } return $result; } public function setBackUrl($url) { $this->setSessionValue('backUrl', $url); } public function getSessionValue($name) { $session = new Qs_Session_Namespace($this->getSessionNamespace()); if (isset($session->{$name})) { return $session->{$name}; } return null; } public function setSessionValue($name, $value) { $session = new Qs_Session_Namespace($this->getSessionNamespace()); $session->{$name} = $value; } public function clearBackUrl($session = null) { if (null === $session) { $session = new Qs_Session_Namespace($this->getSessionNamespace()); } if (!empty($session->backUrl)) { $session->__unset('backUrl'); } } public function getBackUrl($clear = false) { $session = new Qs_Session_Namespace($this->getSessionNamespace()); if (!empty($session->backUrl)) { $backUrl = $session->backUrl; if ($clear) { $session->__unset('backUrl'); } return $backUrl; } // fix for previous functionality if (null == $this->_defaultBackAlias && property_exists($this, '_defaultBackPage')) { $this->_defaultBackUrl = BASE_URL . '/' . $this->_defaultBackPage; } return $this->getDefaultBackUrl(); } public function getDefaultBackPageQuery() { } public function setDefaultBackPageQuery($query) { $this->_defaultBackPageQuery = $query; return $this; } public function setDefaultBackAlias($alias) { $this->_defaultBackAlias = $alias; return $this; } public function getDefaultBackAlias() { if (null === $this->_defaultBackAlias) { $this->_defaultBackAlias = $this->_findAlias($this->_defaultBackPageQuery); if (empty($this->_defaultBackAlias)) { $this->_defaultBackAlias = PARENT_PAGE; } } return $this->_defaultBackAlias; } public function getDefaultBackUrl() { if (null === $this->_defaultBackUrl) { $fullAlias = $this->getDefaultBackAlias(); $this->_defaultBackUrl = BASE_URL_LANGUAGE . ((empty($fullAlias)) ? '' : '/') . $fullAlias; } return $this->_defaultBackUrl; } public function setLoginUrl($url) { $this->_loginUrl = $url; return $this; } public function getLoginUrl() { if (null === $this->_loginUrl) { $loginAlias = $this->getLoginAlias(); $this->_loginUrl = BASE_URL_LANGUAGE . ((empty($loginAlias) ? '' : '/')) . $loginAlias; } return $this->_loginUrl; } public function setLoginAlias($alias) { $this->_loginAlias = $alias; return $this; } protected function _findAlias($query) { $params = (is_array($query) ? $query : [$query]); while (count($params) < 3) { $params[] = null; } $params[] = 'fullAlias'; return call_user_func_array('Qs_SiteMap::findFirst', $params); } public function getLoginAlias() { if (null === $this->_loginAlias) { if (!empty($this->_loginPageQuery)) { $this->_loginAlias = $this->_findAlias($this->_loginPageQuery); } // fix for previous functionality if (null === $this->_loginAlias && property_exists($this, '_loginPage')) { $this->_loginAlias = $this->_loginPage; } } return $this->_loginAlias; } public function setLoginPageQuery($query) { $this->_loginPageQuery = $query; return $this; } public function getLoginPageQuery() { return $this->_loginPageQuery; } public function autologin(Zend_Auth_Adapter_Interface $adapter) { $code = Qs_Request::getCookieValue($this->getAutologinVariable()); if ($code) { /** @var Qs_Auth_Adapter_DbTable $adapter */ if (false !== ($identity = $adapter->getAutologinIdentity($code))) { $adapter->setCredentialColumn('autologinCode'); $adapter->setCredentialTreatment('?'); } } } public function setAutologin($flag = true) { $this->_autologin = $flag; return $this; } public function getAutologinVariable() { if (null === $this->_autologinVariable) { $this->_autologinVariable = strtolower(get_class($this) . '_autologin'); $this->_autologinVariable = session_name() . '_' . substr($this->_autologinVariable, strpos($this->_autologinVariable, '_') + 1); } return $this->_autologinVariable; } public function hasIdentity() { $identity = $this->getIdentity(); if (!empty($identity) && !empty($identity['identity']) && !empty($identity['credential'])) { return true; } return (bool) (Qs_Request::getCookieValue($this->getAutologinVariable())); } public function getIdentity() { $identity = parent::getIdentity(); $code = Qs_Request::getCookieValue($this->getAutologinVariable()); if (null === $identity) { if ($code) { $identity = ['autologinCode' => $code]; } } else { if ($code) { $identity['autologinCode'] = $code; } } return $identity; } public function isLoggedIn() { $identity = $this->getIdentity(); return !empty($identity['data']); } public function getData($field = false, $default = null) { $identity = $this->getIdentity(); if ($identity) { return Qs_Array::get($identity['data'], $field, $default); } return $default; } public function clearIdentity() { $this->clearBackUrl(); parent::clearIdentity(); if (Qs_Request::getCookieValue($this->getAutologinVariable())) { setcookie($this->getAutologinVariable(), '', strtotime('-1 day'), '/', $_SERVER['HTTP_HOST'], false, true); } } public function setRemoteAuthUrl($url) { $this->_remoteAuthUrl = $url; return $this; } public function getRemoteAuthUrl() { if (null === $this->_remoteAuthUrl) { throw new Qs_Exception('Remote Auth Url is not defined'); } return $this->_remoteAuthUrl; } protected function _remoteAuthenticate(Qs_Auth_Adapter_DbTable $adapter) { $requestData = [ 'identity' => $adapter->getIdentity(), 'credential' => $adapter->getCredential(), 'clientIp' => $_SERVER['REMOTE_ADDR'], 'serverName' => $_SERVER['SERVER_NAME'], 'url' => Qs_Request::getUrl(), ]; $data = serialize($requestData); $config = [ 'keepalive' => true, ]; $client = new Zend_Http_Client($this->getRemoteAuthUrl(), $config); $client->setMethod('POST'); $client->setEncType(Zend_Http_Client::ENC_URLENCODED); $client->setCookieJar(); $client->setParameterPost('action', 'getPublicKey'); $response = $client->request(); if (200 != $response->getStatus()) { return $this->_getResultFailed($requestData['identity']); } $client->resetParameters(); $publicKeyResource = openssl_pkey_get_public($response->getBody()); $envelopeKeys = []; $sealed = ''; openssl_seal($data, $sealed, $envelopeKeys, [$publicKeyResource]); $encrypted = base64_encode($sealed); $envelopeKey = base64_encode(reset($envelopeKeys)); $client->setParameterPost('action', 'authenticate'); $client->setParameterPost('encrypted', $encrypted); $client->setParameterPost('envelopeKey', $envelopeKey); $response = $client->request('POST'); if (200 != $response->getStatus()) { return $this->_getResultFailed($requestData['identity']); } $body = unserialize($response->getBody()); if (openssl_verify($body['data'], $body['signature'], $publicKeyResource)) { $data = unserialize($body['data']); if (true === $data['isValid']) { $adapter->setRemoteUserExpiration( date('Y-m-d H:i:s', strtotime($this->_remoteAuthExpirationInterval)) ); if ($adapter->getAutologinCode()) { $identity = null; } else { $identity = $requestData['identity']; }; return $this->_getResultSuccess($identity); } } openssl_free_key($publicKeyResource); return $this->_getResultFailed($requestData['identity']); } protected function _getResultSuccess($identity) { return new Zend_Auth_Result( Zend_Auth_Result::SUCCESS, $identity, ['Authentication successful.'] ); } protected function _getResultFailed($identity) { return new Zend_Auth_Result( Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID, $identity, ['Supplied credential is invalid.'] ); } /* * $type can be one of these: * test always returns the same password = "test" * any returns a random password, which can contain strange characters * alphanum returns a random password containing alphanumerics only * standard same as alphanum, but not including l10O (lower L, one, zero, upper O) */ public static function generatePassword($length = 8, $type = 'standard') { $ranges = ''; if ('test' == $type) { return 'test'; } else if ('standard' == $type) { $ranges = '65-78,80-90,97-107,109-122,50-57'; } else if ('alphanum' == $type) { $ranges = '65-90,97-122,48-57'; } else if ('any' == $type) { $ranges = '40-59,61-91,93-126'; } if ($ranges != '') { $range = explode(',', $ranges); $numRanges = count($range); $password = ''; for ($i = 1; $i <= $length; $i++) { $r = mt_rand(0, $numRanges - 1); list($min, $max) = explode('-', $range[$r]); $password .= chr(mt_rand($min, $max)); } return $password; } return null; } public function getRole() { if (null === $this->_role) { $this->_role = $this->getData('role'); } return $this->_role; } }