| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453 | 
							- <?php
 
- /**
 
-  * Elgg session management
 
-  * Functions to manage logins
 
-  *
 
-  * @package    Elgg.Core
 
-  * @subpackage Session
 
-  */
 
- /**
 
-  * Elgg magic session
 
-  * @deprecated 1.9
 
-  */
 
- global $SESSION;
 
- /**
 
-  * Gets Elgg's session object
 
-  *
 
-  * @return \ElggSession
 
-  * @since 1.9
 
-  */
 
- function elgg_get_session() {
 
- 	return _elgg_services()->session;
 
- }
 
- /**
 
-  * Return the current logged in user, or null if no user is logged in.
 
-  *
 
-  * @return \ElggUser
 
-  */
 
- function elgg_get_logged_in_user_entity() {
 
- 	return _elgg_services()->session->getLoggedInUser();
 
- }
 
- /**
 
-  * Return the current logged in user by guid.
 
-  *
 
-  * @see elgg_get_logged_in_user_entity()
 
-  * @return int
 
-  */
 
- function elgg_get_logged_in_user_guid() {
 
- 	return _elgg_services()->session->getLoggedInUserGuid();
 
- }
 
- /**
 
-  * Returns whether or not the user is currently logged in
 
-  *
 
-  * @return bool
 
-  */
 
- function elgg_is_logged_in() {
 
- 	return _elgg_services()->session->isLoggedIn();
 
- }
 
- /**
 
-  * Returns whether or not the viewer is currently logged in and an admin user.
 
-  *
 
-  * @return bool
 
-  */
 
- function elgg_is_admin_logged_in() {
 
- 	return _elgg_services()->session->isAdminLoggedIn();
 
- }
 
- /**
 
-  * Check if the given user has full access.
 
-  *
 
-  * @todo: Will always return full access if the user is an admin.
 
-  *
 
-  * @param int $user_guid The user to check
 
-  *
 
-  * @return bool
 
-  * @since 1.7.1
 
-  */
 
- function elgg_is_admin_user($user_guid) {
 
- 	global $CONFIG;
 
- 	$user_guid = (int)$user_guid;
 
- 	$current_user = elgg_get_logged_in_user_entity();
 
- 	if ($current_user && $current_user->guid == $user_guid) {
 
- 		return $current_user->isAdmin();
 
- 	}
 
- 	// cannot use magic metadata here because of recursion
 
- 	// must support the old way of getting admin from metadata
 
- 	// in order to run the upgrade to move it into the users table.
 
- 	$version = (int) datalist_get('version');
 
- 	if ($version < 2010040201) {
 
- 		$admin = elgg_get_metastring_id('admin');
 
- 		$yes = elgg_get_metastring_id('yes');
 
- 		$one = elgg_get_metastring_id('1');
 
- 		$query = "SELECT 1 FROM {$CONFIG->dbprefix}users_entity as e,
 
- 			{$CONFIG->dbprefix}metadata as md
 
- 			WHERE (
 
- 				md.name_id = '$admin'
 
- 				AND md.value_id IN ('$yes', '$one')
 
- 				AND e.guid = md.entity_guid
 
- 				AND e.guid = {$user_guid}
 
- 				AND e.banned = 'no'
 
- 			)";
 
- 	} else {
 
- 		$query = "SELECT 1 FROM {$CONFIG->dbprefix}users_entity as e
 
- 			WHERE (
 
- 				e.guid = {$user_guid}
 
- 				AND e.admin = 'yes'
 
- 			)";
 
- 	}
 
- 	// normalizing the results from get_data()
 
- 	// See #1242
 
- 	$info = get_data($query);
 
- 	if (!((is_array($info) && count($info) < 1) || $info === false)) {
 
- 		return true;
 
- 	}
 
- 	return false;
 
- }
 
- /**
 
-  * Perform user authentication with a given username and password.
 
-  *
 
-  * @warning This returns an error message on failure. Use the identical operator to check
 
-  * for access: if (true === elgg_authenticate()) { ... }.
 
-  *
 
-  *
 
-  * @see login
 
-  *
 
-  * @param string $username The username
 
-  * @param string $password The password
 
-  *
 
-  * @return true|string True or an error message on failure
 
-  * @access private
 
-  */
 
- function elgg_authenticate($username, $password) {
 
- 	$pam = new \ElggPAM('user');
 
- 	$credentials = array('username' => $username, 'password' => $password);
 
- 	$result = $pam->authenticate($credentials);
 
- 	if (!$result) {
 
- 		return $pam->getFailureMessage();
 
- 	}
 
- 	return true;
 
- }
 
- /**
 
-  * Hook into the PAM system which accepts a username and password and attempts to authenticate
 
-  * it against a known user.
 
-  *
 
-  * @param array $credentials Associated array of credentials passed to
 
-  *                           Elgg's PAM system. This function expects
 
-  *                           'username' and 'password' (cleartext).
 
-  *
 
-  * @return bool
 
-  * @throws LoginException
 
-  * @access private
 
-  */
 
- function pam_auth_userpass(array $credentials = array()) {
 
- 	if (!isset($credentials['username']) || !isset($credentials['password'])) {
 
- 		return false;
 
- 	}
 
- 	$user = get_user_by_username($credentials['username']);
 
- 	if (!$user) {
 
- 		throw new \LoginException(_elgg_services()->translator->translate('LoginException:UsernameFailure'));
 
- 	}
 
- 	if (check_rate_limit_exceeded($user->guid)) {
 
- 		throw new \LoginException(_elgg_services()->translator->translate('LoginException:AccountLocked'));
 
- 	}
 
- 	$password_svc = _elgg_services()->passwords;
 
- 	$password = $credentials['password'];
 
- 	$hash = $user->password_hash;
 
- 	if (!$hash) {
 
- 		// try legacy hash
 
- 		$legacy_hash = $password_svc->generateLegacyHash($user, $password);
 
- 		if ($user->password !== $legacy_hash) {
 
- 			log_login_failure($user->guid);
 
- 			throw new \LoginException(_elgg_services()->translator->translate('LoginException:PasswordFailure'));
 
- 		}
 
- 		// migrate password
 
- 		$password_svc->forcePasswordReset($user, $password);
 
- 		return true;
 
- 	}
 
- 	if (!$password_svc->verify($password, $hash)) {
 
- 		log_login_failure($user->guid);
 
- 		throw new \LoginException(_elgg_services()->translator->translate('LoginException:PasswordFailure'));
 
- 	}
 
- 	if ($password_svc->needsRehash($hash)) {
 
- 		$password_svc->forcePasswordReset($user, $password);
 
- 	}
 
- 	return true;
 
- }
 
- /**
 
-  * Log a failed login for $user_guid
 
-  *
 
-  * @param int $user_guid User GUID
 
-  *
 
-  * @return bool
 
-  */
 
- function log_login_failure($user_guid) {
 
- 	$user_guid = (int)$user_guid;
 
- 	$user = get_entity($user_guid);
 
- 	if (($user_guid) && ($user) && ($user instanceof \ElggUser)) {
 
- 		$fails = (int)$user->getPrivateSetting("login_failures");
 
- 		$fails++;
 
- 		$user->setPrivateSetting("login_failures", $fails);
 
- 		$user->setPrivateSetting("login_failure_$fails", time());
 
- 		return true;
 
- 	}
 
- 	return false;
 
- }
 
- /**
 
-  * Resets the fail login count for $user_guid
 
-  *
 
-  * @param int $user_guid User GUID
 
-  *
 
-  * @return bool true on success (success = user has no logged failed attempts)
 
-  */
 
- function reset_login_failure_count($user_guid) {
 
- 	$user_guid = (int)$user_guid;
 
- 	$user = get_entity($user_guid);
 
- 	if (($user_guid) && ($user) && ($user instanceof \ElggUser)) {
 
- 		$fails = (int)$user->getPrivateSetting("login_failures");
 
- 		if ($fails) {
 
- 			for ($n = 1; $n <= $fails; $n++) {
 
- 				$user->removePrivateSetting("login_failure_$n");
 
- 			}
 
- 			$user->removePrivateSetting("login_failures");
 
- 			return true;
 
- 		}
 
- 		// nothing to reset
 
- 		return true;
 
- 	}
 
- 	return false;
 
- }
 
- /**
 
-  * Checks if the rate limit of failed logins has been exceeded for $user_guid.
 
-  *
 
-  * @param int $user_guid User GUID
 
-  *
 
-  * @return bool on exceeded limit.
 
-  */
 
- function check_rate_limit_exceeded($user_guid) {
 
- 	// 5 failures in 5 minutes causes temporary block on logins
 
- 	$limit = 5;
 
- 	$user_guid = (int)$user_guid;
 
- 	$user = get_entity($user_guid);
 
- 	if (($user_guid) && ($user) && ($user instanceof \ElggUser)) {
 
- 		$fails = (int)$user->getPrivateSetting("login_failures");
 
- 		if ($fails >= $limit) {
 
- 			$cnt = 0;
 
- 			$time = time();
 
- 			for ($n = $fails; $n > 0; $n--) {
 
- 				$f = $user->getPrivateSetting("login_failure_$n");
 
- 				if ($f > $time - (60 * 5)) {
 
- 					$cnt++;
 
- 				}
 
- 				if ($cnt == $limit) {
 
- 					// Limit reached
 
- 					return true;
 
- 				}
 
- 			}
 
- 		}
 
- 	}
 
- 	return false;
 
- }
 
- /**
 
-  * Set a cookie, but allow plugins to customize it first.
 
-  *
 
-  * To customize all cookies, register for the 'init:cookie', 'all' event.
 
-  *
 
-  * @param \ElggCookie $cookie The cookie that is being set
 
-  * @return bool
 
-  * @since 1.9
 
-  */
 
- function elgg_set_cookie(\ElggCookie $cookie) {
 
- 	if (elgg_trigger_event('init:cookie', $cookie->name, $cookie)) {
 
- 		return setcookie($cookie->name, $cookie->value, $cookie->expire, $cookie->path,
 
- 						$cookie->domain, $cookie->secure, $cookie->httpOnly);
 
- 	}
 
- 	return false;
 
- }
 
- /**
 
-  * Logs in a specified \ElggUser. For standard registration, use in conjunction
 
-  * with elgg_authenticate.
 
-  *
 
-  * @see elgg_authenticate
 
-  *
 
-  * @param \ElggUser $user       A valid Elgg user object
 
-  * @param boolean   $persistent Should this be a persistent login?
 
-  *
 
-  * @return true or throws exception
 
-  * @throws LoginException
 
-  */
 
- function login(\ElggUser $user, $persistent = false) {
 
- 	if ($user->isBanned()) {
 
- 		throw new \LoginException(elgg_echo('LoginException:BannedUser'));
 
- 	}
 
- 	$session = _elgg_services()->session;
 
- 	// give plugins a chance to reject the login of this user (no user in session!)
 
- 	if (!elgg_trigger_before_event('login', 'user', $user)) {
 
- 		throw new \LoginException(elgg_echo('LoginException:Unknown'));
 
- 	}
 
- 	// #5933: set logged in user early so code in login event will be able to
 
- 	// use elgg_get_logged_in_user_entity().
 
- 	$session->setLoggedInUser($user);
 
- 	// deprecate event
 
- 	$message = "The 'login' event was deprecated. Register for 'login:before' or 'login:after'";
 
- 	$version = "1.9";
 
- 	if (!elgg_trigger_deprecated_event('login', 'user', $user, $message, $version)) {
 
- 		$session->removeLoggedInUser();
 
- 		throw new \LoginException(elgg_echo('LoginException:Unknown'));
 
- 	}
 
- 	// if remember me checked, set cookie with token and store hash(token) for user
 
- 	if ($persistent) {
 
- 		_elgg_services()->persistentLogin->makeLoginPersistent($user);
 
- 	}
 
- 	// User's privilege has been elevated, so change the session id (prevents session fixation)
 
- 	$session->migrate();
 
- 	set_last_login($user->guid);
 
- 	reset_login_failure_count($user->guid);
 
- 	elgg_trigger_after_event('login', 'user', $user);
 
- 	// if memcache is enabled, invalidate the user in memcache @see https://github.com/Elgg/Elgg/issues/3143
 
- 	if (is_memcache_available()) {
 
- 		$guid = $user->getGUID();
 
- 		// this needs to happen with a shutdown function because of the timing with set_last_login()
 
- 		register_shutdown_function("_elgg_invalidate_memcache_for_entity", $guid);
 
- 	}
 
- 	return true;
 
- }
 
- /**
 
-  * Log the current user out
 
-  *
 
-  * @return bool
 
-  */
 
- function logout() {
 
- 	$session = _elgg_services()->session;
 
- 	$user = $session->getLoggedInUser();
 
- 	if (!$user) {
 
- 		return false;
 
- 	}
 
- 	if (!elgg_trigger_before_event('logout', 'user', $user)) {
 
- 		return false;
 
- 	}
 
- 	// deprecate event
 
- 	$message = "The 'logout' event was deprecated. Register for 'logout:before' or 'logout:after'";
 
- 	$version = "1.9";
 
- 	if (!elgg_trigger_deprecated_event('logout', 'user', $user, $message, $version)) {
 
- 		return false;
 
- 	}
 
- 	_elgg_services()->persistentLogin->removePersistentLogin();
 
- 	// pass along any messages into new session
 
- 	$old_msg = $session->get('msg');
 
- 	$session->invalidate();
 
- 	$session->set('msg', $old_msg);
 
- 	elgg_trigger_after_event('logout', 'user', $user);
 
- 	return true;
 
- }
 
- /**
 
-  * Initializes the session and checks for the remember me cookie
 
-  *
 
-  * @return bool
 
-  * @access private
 
-  */
 
- function _elgg_session_boot() {
 
- 	elgg_register_action('login', '', 'public');
 
- 	elgg_register_action('logout');
 
- 	register_pam_handler('pam_auth_userpass');
 
- 	$session = _elgg_services()->session;
 
- 	$session->start();
 
- 	// test whether we have a user session
 
- 	if ($session->has('guid')) {
 
- 		$user = _elgg_services()->entityTable->get($session->get('guid'), 'user');
 
- 		if (!$user) {
 
- 			// OMG user has been deleted.
 
- 			$session->invalidate();
 
- 			forward('');
 
- 		}
 
- 		$session->setLoggedInUser($user);
 
- 		_elgg_services()->persistentLogin->replaceLegacyToken($user);
 
- 	} else {
 
- 		$user = _elgg_services()->persistentLogin->bootSession();
 
- 		if ($user) {
 
- 			$session->setLoggedInUser($user);
 
- 		}
 
- 	}
 
- 	if ($session->has('guid')) {
 
- 		set_last_action($session->get('guid'));
 
- 	}
 
- 	// initialize the deprecated global session wrapper
 
- 	global $SESSION;
 
- 	$SESSION = new \Elgg\DeprecationWrapper($session, "\$SESSION is deprecated", 1.9);
 
- 	// logout a user with open session who has been banned
 
- 	$user = $session->getLoggedInUser();
 
- 	if ($user && $user->isBanned()) {
 
- 		logout();
 
- 		return false;
 
- 	}
 
- 	return true;
 
- }
 
 
  |