All session related code has now been moved to horde/Core.
Horde_Auth no longer depends on horde/Core.
Authentication for each application is handled entirely by the
Horde_Core_Auth_Application driver.
Removed registry functions:
getProvider()
requireAuth()
isAuthenticated() now has a new option - 'notransparent'
Removed the recently added clearAuth() call to isAuthenticated() -
isAuthenticated() is meant solely for determining whether the given app
is authenticated. Code to invalidate a session (for example, if a
checkExistingAuth() call fails) MUST go elsewhere.
Moved last login display to a Horde LoginTask.
// reset credentials so user is not forced to relogin
if ($registry->getAuthCredential('password') == $info['old']) {
$registry->setAuthCredential('password', $info['new']);
- $secret = $injector->getInstance('Horde_Secret');
- if ($registry->getProvider() == 'imp' ||
- !empty($_SESSION['imp']['pass'])) {
- $_SESSION['imp']['pass'] = $secret->write($secret->getKey('imp'), $info['new']);
- }
}
-
} while (false);
// update password reminder prefs
require_once dirname(__FILE__) . '/base.php';
$GLOBALS['folks_driver'] = Folks_Driver::factory();
if ($_COOKIE['folks_login_code'] == $GLOBALS['folks_driver']->getCookie($_COOKIE['folks_login_user'])) {
- Horde_Auth::setAuth($_COOKIE['folks_login_user'], array(), array('transparent' => true, 'nologin' => true));
+ $GLOBALS['registry']->setAuth($_COOKIE['folks_login_user']);
$auth_ob->setCredential('userId', $_COOKIE['folks_login_user']);
$GLOBALS['folks_driver']->resetOnlineUsers();
return true;
<?php
/**
- * The Horde_Auth:: class provides a common abstracted interface into the
- * various backends for the Horde authentication system.
- *
- * Horde authentication data is stored in the session in the 'horde_auth'
- * array key. That key has the following structure:
- * <pre>
- * 'app' - (array) Application-specific authentication. Keys are the
- * app names, values are an array containing credentials. If true,
- * application does not require any specific credentials.
- * 'authId' - (string) The username used during the original authentication.
- * 'browser' - (string) The remote browser string.
- * 'change' - (boolean) Is a password change requested?
- * 'credentials' - (string) The 'app' entry that contains the Horde
- * credentials.
- * 'driver' - (string) The driver used for base horde auth.
- * 'remoteAddr' - (string) The remote IP address of the user.
- * 'timestamp' - (integer) The login time.
- * 'userId' - (string) The unique Horde username.
- * </pre>
+ * The Horde_Auth:: class provides a common abstracted interface for various
+ * authentication backends. It also provides some useful
+ * authentication-related utilities.
*
* Copyright 1999-2010 The Horde Project (http://www.horde.org/)
*
class Horde_Auth
{
/**
- * The parameter name for the logout reason.
- */
- const REASON_PARAM = 'logout_reason';
-
- /**
- * The parameter name for the logout message used with type
- * REASON_MESSAGE.
- */
- const REASON_MSG_PARAM = 'logout_msg';
-
- /**
- * The 'badlogin' reason.
+ * Authentication failure reasons.
*
- * The following 'reasons' for the logout screen are recognized:
* <pre>
* REASON_BADLOGIN - Bad username and/or password
- * REASON_BROWSER - A browser change was detected
* REASON_FAILED - Login failed
* REASON_EXPIRED - Password has expired
* REASON_LOGOUT - Logout due to user request
- * REASON_MESSAGE - Logout with custom message in REASON_MSG_PARAM
+ * REASON_MESSAGE - Logout with custom message
* REASON_SESSION - Logout due to session expiration
- * REASON_SESSIONIP - Logout due to change of IP address during session
* </pre>
*/
const REASON_BADLOGIN = 1;
- const REASON_BROWSER = 2;
- const REASON_FAILED = 3;
- const REASON_EXPIRED = 4;
- const REASON_LOGOUT = 5;
- const REASON_MESSAGE = 6;
- const REASON_SESSION = 7;
- const REASON_SESSIONIP = 8;
+ const REASON_FAILED = 2;
+ const REASON_EXPIRED = 3;
+ const REASON_LOGOUT = 4;
+ const REASON_MESSAGE = 5;
+ const REASON_SESSION = 6;
/**
* 64 characters that are valid for APRMD5 passwords.
const NUMBERS = '0123456789';
/**
- * A Net_DNS_Resolver object to use to determine hostnames.
- *
- * @var Net_DNS_Resolver
- */
- static public $dnsResolver;
-
- /**
- * The logout reason information.
- *
- * @var array
- */
- static protected $_reason = array();
-
- /**
* Attempts to return a concrete Horde_Auth_Base instance based on
* $driver.
*
}
/**
- * Generates a random, hopefully pronounceable, password. This can be used
- * when resetting automatically a user's password.
- *
- * @return string A random password
- */
- static public function genRandomPassword()
- {
- /* Alternate consonant and vowel random chars with two random numbers
- * at the end. This should produce a fairly pronounceable password. */
- return substr(self::CONSONANTS, mt_rand(0, strlen(self::CONSONANTS) - 1), 1) .
- substr(self::VOWELS, mt_rand(0, strlen(self::VOWELS) - 1), 1) .
- substr(self::CONSONANTS, mt_rand(0, strlen(self::CONSONANTS) - 1), 1) .
- substr(self::VOWELS, mt_rand(0, strlen(self::VOWELS) - 1), 1) .
- substr(self::CONSONANTS, mt_rand(0, strlen(self::CONSONANTS) - 1), 1) .
- substr(self::NUMBERS, mt_rand(0, strlen(self::NUMBERS) - 1), 1) .
- substr(self::NUMBERS, mt_rand(0, strlen(self::NUMBERS) - 1), 1);
- }
-
- /**
- * Calls all applications' removeUser API methods.
- *
- * @param string $userId The userId to delete.
- *
- * @throws Horde_Auth_Exception
- */
- static public function removeUserData($userId)
- {
- $errApps = array();
-
- foreach ($GLOBALS['registry']->listApps(array('notoolbar', 'hidden', 'active', 'admin')) as $app) {
- try {
- $GLOBALS['registry']->callByPackage($app, 'removeUserData', array($userId));
- } catch (Horde_Auth_Exception $e) {
- Horde::logMessage($e, 'ERR');
- $errApps[] = $app;
- }
- }
-
- if (count($errApps)) {
- throw new Horde_Auth_Exception(sprintf(_("The following applications encountered errors removing user data: %s"), implode(', ', $errApps)));
- }
- }
-
- /**
- * Check existing auth for triggers that might invalidate it.
- *
- * @return boolean Is existing auth valid?
- */
- static public function checkExistingAuth()
- {
- if (!empty($GLOBALS['conf']['auth']['checkip']) &&
- !empty($_SESSION['horde_auth']['remoteAddr']) &&
- ($_SESSION['horde_auth']['remoteAddr'] != $_SERVER['REMOTE_ADDR'])) {
- self::setAuthError(self::REASON_SESSIONIP);
- return false;
- }
-
- if (!empty($GLOBALS['conf']['auth']['checkbrowser'])) {
- if ($_SESSION['horde_auth']['browser'] != $GLOBALS['injector']->getInstance('Horde_Browser')->getAgentString()) {
- self::setAuthError(self::REASON_BROWSER);
- return false;
- }
- }
-
- return $GLOBALS['injector']->getInstance('Horde_Auth')->getAuth()->checkExistingAuth();
- }
-
- /**
- * Sets a variable in the session saying that authorization has succeeded,
- * note which userId was authorized, and note when the login took place.
- *
- * If a user name hook was defined in the configuration, it gets applied
- * to the $userId at this point.
- *
- * @param string $authId The userId that has been authorized.
- * @param array $credentials The credentials of the user.
- * @param array $options Additional options:
- * <pre>
- * 'app' - (string) The app to set authentication credentials for.
- * DEFAULT: Set horde authentication
- * 'change' - (boolean) Whether to request that the user change their
- * password.
- * DEFAULT: No
- * 'nologin' - (boolean) Don't do login tasks?
- * DEFAULT: Perform login tasks
- * </pre>
- *
- * @return boolean Whether authentication was successful.
- */
- static public function setAuth($authId, $credentials, $options = array())
- {
- $app = empty($options['app']) ? 'horde' : $options['app'];
- $authId = $userId = trim($authId);
- $is_auth = $GLOBALS['registry']->getAuth();
-
- try {
- if (!$is_auth) {
- $userId = $GLOBALS['registry']->convertUserName($userId, true);
- }
- list(,$credentials) = self::runHook($userId, $credentials, $app, 'postauthenticate');
- } catch (Horde_Auth_Exception $e) {
- return false;
- }
-
- $app_array = $is_auth
- ? $_SESSION['horde_auth']['app']
- : array();
-
- $secret = $GLOBALS['injector']->getInstance('Horde_Secret');
- $app_array[$app] = $secret->write($secret->getKey('auth'), serialize($credentials));
-
- if ($is_auth) {
- /* Store app credentials. */
- $_SESSION['horde_auth']['app'] = $app_array;
- return true;
- }
-
- /* Clear any existing info. */
- $GLOBALS['registry']->clearAuth(false);
-
- $_SESSION['horde_auth'] = array(
- 'app' => $app_array,
- 'authId' => $authId,
- 'browser' => $GLOBALS['injector']->getInstance('Horde_Browser')->getAgentString(),
- 'change' => !empty($options['change']),
- 'credentials' => $app,
- 'driver' => $GLOBALS['conf']['auth']['driver'],
- 'remoteAddr' => isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : null,
- 'timestamp' => time(),
- 'userId' => $userId
- );
-
- /* Reload preferences for the new user. */
- $GLOBALS['registry']->loadPrefs();
- Horde_Nls::setLanguageEnvironment($GLOBALS['prefs']->getValue('language'), $app);
-
- if (!empty($options['nologin'])) {
- return true;
- }
-
- /* Fetch the user's last login time. */
- $old_login = @unserialize($GLOBALS['prefs']->getValue('last_login'));
-
- /* Display it, if we have a notification object and the
- * show_last_login preference is active. */
- if (isset($GLOBALS['notification']) &&
- $GLOBALS['prefs']->getValue('show_last_login')) {
- if (empty($old_login['time'])) {
- $GLOBALS['notification']->push(_("Last login: Never"), 'horde.message');
- } else {
- if (empty($old_login['host'])) {
- $GLOBALS['notification']->push(sprintf(_("Last login: %s"), strftime('%c', $old_login['time'])), 'horde.message');
- } else {
- $GLOBALS['notification']->push(sprintf(_("Last login: %s from %s"), strftime('%c', $old_login['time']), $old_login['host']), 'horde.message');
- }
- }
- }
-
- /* Set the user's last_login information. */
- $host = empty($_SERVER['HTTP_X_FORWARDED_FOR'])
- ? $_SERVER['REMOTE_ADDR']
- : $_SERVER['HTTP_X_FORWARDED_FOR'];
-
- if (!empty(self::$dnsResolver)) {
- $ptrdname = $host;
- if ($response = self::$dnsResolver->query($host, 'PTR')) {
- foreach ($response->answer as $val) {
- if (isset($val->ptrdname)) {
- $ptrdname = $val->ptrdname;
- break;
- }
- }
- }
- } else {
- $ptrdname = @gethostbyaddr($host);
- }
-
- $last_login = array('time' => time(), 'host' => $ptrdname);
- $GLOBALS['prefs']->setValue('last_login', serialize($last_login));
-
- return true;
- }
-
- /**
- * Runs the pre/post-authenticate hook and parses the result.
- *
- * @param string $userId The userId who has been authorized.
- * @param array $credentials The credentials of the user.
- * @param string $app The app currently being authenticated.
- * @param string $type Either 'preauthenticate' or
- * 'postauthenticate'.
- * @param string $method The triggering method (preauthenticate only).
- * Either 'authenticate', 'transparent', or
- * 'admin'
- *
- * @return array Two element array, $userId and $credentials.
- * @throws Horde_Auth_Exception
- */
- static public function runHook($userId, $credentials, $app, $type,
- $method = null)
- {
- $ret_array = array($userId, $credentials);
-
- if ($type == 'preauthenticate') {
- $credentials['authMethod'] = $method;
- }
-
- try {
- $result = Horde::callHook($type, array($userId, $credentials), $app);
- } catch (Horde_Exception $e) {
- throw new Horde_Auth_Exception($e->getMessage());
- } catch (Horde_Exception_HookNotSet $e) {
- return $ret_array;
- }
-
- unset($credentials['authMethod']);
-
- if ($result === false) {
- if (self::getAuthError() != self::REASON_MESSAGE) {
- self::setAuthError(self::REASON_FAILED);
- }
- throw new Horde_Auth_Exception($type . ' hook failed');
- }
-
- if (is_array($result)) {
- if ($type == 'postauthenticate') {
- $ret_array[1] = $result;
- } else {
- if (isset($result['userId'])) {
- $ret_array[0] = $result['userId'];
- }
-
- if (isset($result['credentials'])) {
- $ret_array[1] = $result['credentials'];
- }
- }
- }
-
- return $ret_array;
- }
-
- /**
- * Sets the error message for an invalid authentication.
- *
- * @param string $type The type of error (self::REASON_* constant).
- * @param string $msg The error message/reason for invalid
- * authentication.
- */
- static public function setAuthError($type, $msg = null)
- {
- self::$_reason = array(
- 'msg' => $msg,
- 'type' => $type
- );
- }
-
- /**
- * Returns the error type or message for an invalid authentication.
- *
- * @param boolean $msg If true, returns the message string (if set).
- *
- * @return mixed Error type, error message (if $msg is true) or false
- * if entry doesn't exist.
- */
- static public function getAuthError($msg = false)
- {
- return isset(self::$_reason['type'])
- ? ($msg ? self::$_reason['msg'] : self::$_reason['type'])
- : false;
- }
-
- /**
* Converts to allowed 64 characters for APRMD5 passwords.
*
* @param string $value TODO
return $aprmd5;
}
+ /**
+ * Generates a random, hopefully pronounceable, password. This can be used
+ * when resetting automatically a user's password.
+ *
+ * @return string A random password
+ */
+ static public function genRandomPassword()
+ {
+ /* Alternate consonant and vowel random chars with two random numbers
+ * at the end. This should produce a fairly pronounceable password. */
+ return substr(self::CONSONANTS, mt_rand(0, strlen(self::CONSONANTS) - 1), 1) .
+ substr(self::VOWELS, mt_rand(0, strlen(self::VOWELS) - 1), 1) .
+ substr(self::CONSONANTS, mt_rand(0, strlen(self::CONSONANTS) - 1), 1) .
+ substr(self::VOWELS, mt_rand(0, strlen(self::VOWELS) - 1), 1) .
+ substr(self::CONSONANTS, mt_rand(0, strlen(self::CONSONANTS) - 1), 1) .
+ substr(self::NUMBERS, mt_rand(0, strlen(self::NUMBERS) - 1), 1) .
+ substr(self::NUMBERS, mt_rand(0, strlen(self::NUMBERS) - 1), 1);
+ }
+
}
*
* @return boolean Whether or not the client is allowed.
*/
- protected function _transparent()
+ public function transparent()
{
$this->_credentials['userId'] = (!empty($this->_params['requestuser']) && isset($_REQUEST['username']))
? $_REQUEST['username']
* @var array
*/
protected $_credentials = array(
+ 'change' => false,
'credentials' => array(),
- 'params' => array('change' => false),
+ 'expire' => null,
'userId' => ''
);
/**
- * Current application for authentication.
+ * Logger object.
*
- * @var string
+ * @var Horde_Log_Logger
*/
- protected $_app = 'horde';
+ protected $_logger;
/**
- * Logger object.
+ * Authentication error information.
*
- * @var Horde_Log_Logger
+ * @var array
*/
- protected $_logger;
+ protected $_error;
/**
* Constructor.
* <pre>
* 'default_user' - (string) The default user.
* 'logger' - (Horde_Log_Logger) A logger object.
- * 'notify_expire' - (callback) Callback function to output notification
- * when password is about to expire. Passed one
- * argument: UNIX timestamp of when password expires.
* </pre>
*/
public function __construct(array $params = array())
*/
public function authenticate($userId, $credentials, $login = true)
{
- $auth = false;
$userId = trim($userId);
try {
- list($userId, $credentials) = Horde_Auth::runHook($userId, $credentials, $this->_app, 'preauthenticate', 'authenticate');
- } catch (Horde_Auth_Exception $e) {
- return false;
- }
-
- /* Store the credentials being checked so that subclasses can modify
- * them if necessary. */
- $this->_credentials['credentials'] = $credentials;
- $this->_credentials['userId'] = $userId;
- $this->_credentials['params']['app'] = $this->_app;
-
- try {
$this->_authenticate($userId, $credentials);
-
- if ($login) {
- $auth = Horde_Auth::setAuth(
- $this->_credentials['userId'],
- $this->_credentials['credentials'],
- $this->_credentials['params']
- );
- } else {
- $auth = Horde_Auth::checkExistingAuth();
- }
+ $this->setCredential('userId', $userId);
+ $this->setCredential('credentials', $credentials);
+ return true;
} catch (Horde_Auth_Exception $e) {
if ($e->getCode()) {
- Horde_Auth::setAuthError($e->getCode());
+ $this->setError($e->getCode());
} else {
- Horde_Auth::setAuthError(Horde_Auth::REASON_MESSAGE, $e->getMessage());
+ $this->setError(Horde_Auth::REASON_MESSAGE, $e->getMessage());
}
+ return false;
}
-
- return $auth;
}
/**
abstract protected function _authenticate($userId, $credentials);
/**
- * Check existing auth for triggers that might invalidate it.
+ * Checks for triggers that may invalidate the current auth.
+ * These triggers are independent of the credentials.
*
- * @return boolean Is existing auth valid?
+ * @return boolean True if the results of authenticate() are still valid.
*/
- public function checkExistingAuth()
+ public function validateAuth()
{
return true;
}
/**
* Automatic authentication.
*
- * @return boolean Whether or not the user is authenticated
- * automatically.
- * @throws Horde_Auth_Exception
- */
- public function transparent()
- {
- $userId = empty($this->_credentials['userId'])
- ? $this->_params['default_user']
- : $this->_credentials['userId'];
- $credentials = empty($this->_credentials['credentials'])
- ? $GLOBALS['registry']->getAuthCredential()
- : $this->_credentials['credentials'];
-
- list($this->_credentials['userId'], $this->_credentials['credentials']) = Horde_Auth::runHook($userId, $credentials, $this->_app, 'preauthenticate', 'transparent');
- $this->_credentials['params']['app'] = $this->_app;
-
- if ($this->_transparent()) {
- return Horde_Auth::setAuth(
- $this->_credentials['userId'],
- $this->_credentials['credentials'],
- $this->_credentials['params']
- );
- }
-
- return false;
- }
-
- /**
- * Transparent authentication stub.
- *
* Transparent authentication should set 'userId', 'credentials', or
* 'params' in $this->_credentials as needed - these values will be used
* to set the credentials in the session.
* @return boolean Whether transparent login is supported.
* @throws Horde_Auth_Exception
*/
- protected function _transparent()
+ public function transparent()
{
return false;
}
}
/**
- * Returns information on what login parameters to display on the login
- * screen. If not defined, will display the default (username, password).
+ * Retrieve internal credential value(s).
*
- * @return array An array with the following elements:
+ * @param mixed $name The credential value to get. If null, will return
+ * the entire credential list. Valid names:
* <pre>
- * 'js_code' - (array) A list of javascript code to output to the login
- * page.
- * 'js_files' - (array) A list of javascript files to include in the login
- * page.
- * 'params' - (array) TODO
+ * 'change' - (boolean) Do credentials need to be changed?
+ * 'credentials' - (array) The credentials needed to authenticate.
+ * 'expire' - (integer) UNIX timestamp of the credential expiration date.
+ * 'userId' - (string) The user ID.
* </pre>
- * @throws Horde_Exception
+ *
+ * @return mixed Return the credential information, or null if the
+ * credential doesn't exist.
*/
- public function getLoginParams()
+ public function getCredential($name = null)
{
- return array(
- 'js_code' => array(),
- 'js_files' => array(),
- 'params' => array()
+ if (is_null($name)) {
+ return $this->_credentials;
+ }
+
+ return isset($this->_credentials[$name])
+ ? $this->_credentials[$name]
+ : null;
+ }
+
+ /**
+ * Set internal credential value.
+ *
+ * @param string $name The credential name to set.
+ * @param mixed $value The credential value to set. See getCredential()
+ * for the list of valid credentials/types.
+ */
+ public function setCredential($type, $value)
+ {
+ switch ($type) {
+ case 'change':
+ $this->_credentials['change'] = (bool)$value;
+ break;
+
+ case 'credentials':
+ $this->_credentials['credentials'] = array_filter(array_merge($this->_credentials['credentials'], $value));
+ break;
+
+ case 'expire':
+ $this->_credentials['expire'] = intval($value);
+ break;
+
+ case 'userId':
+ $this->_credentials['userId'] = strval($value);
+ break;
+ }
+ }
+
+ /**
+ * Sets the error message for an invalid authentication.
+ *
+ * @param string $type The type of error (Horde_Auth::REASON_* constant).
+ * @param string $msg The error message/reason for invalid
+ * authentication.
+ */
+ public function setError($type, $msg = null)
+ {
+ $this->_error = array(
+ 'msg' => $msg,
+ 'type' => $type
);
}
+ /**
+ * Returns the error type or message for an invalid authentication.
+ *
+ * @param boolean $msg If true, returns the message string (if set).
+ *
+ * @return mixed Error type, error message (if $msg is true) or false
+ * if entry doesn't exist.
+ */
+ public function getError($msg = false)
+ {
+ return isset($this->_error['type'])
+ ? ($msg ? $this->_error['msg'] : $this->_error['type'])
+ : false;
+ }
+
}
*/
protected function _authenticate($userId, $credentials)
{
- return $this->_params['auth_driver']->authenticate($userId, $credentials, false);
+ return $this->_params['auth_driver']->authenticate($userId, $credentials);
}
/**
*
* @return boolean Whether or not the client is allowed.
*/
- protected function _transparent()
+ public function transparent()
{
try {
return $this->_params['auth_driver']->transparent();
if (!empty($this->_params['soft_expiration_field']) &&
!empty($row[$this->_params['soft_expiration_field']]) &&
($now > $row[$this->_params['soft_expiration_field']])) {
- $this->_credentials['params']['change'] = true;
+ $this->setCredential('change', true);
}
}
*
* @return boolean Whether or not the client is allowed.
*/
- protected function _transparent()
+ public function transparent()
{
return $this->_backend->transparent();
}
*
* @return boolean Whether or not the client is allowed.
*/
- protected function _transparent()
+ public function transparent()
{
if (empty($_SERVER['PHP_AUTH_USER']) ||
empty($_SERVER['PHP_AUTH_PW'])) {
*
* @return boolean Whether or not the client is allowed.
*/
- protected function _transparent()
+ public function transparent()
{
if (isset($_SERVER['REMOTE_ADDR'])) {
foreach ($this->_params['blocks'] as $cidr) {
public function __construct(array $params = array())
{
if (!isset($params['kolab'])) {
- throw new InvalidArgumentException('Missing ' . $params . ' parameter.');
+ throw new InvalidArgumentException('Missing kolab parameter.');
}
parent::__construct($params);
$toexpire = $shadow['shadowlastchange'] +
$shadow['shadowmax'] - $today;
- if ($this->_params['notify_expire']) {
- $warnday = $shadow['shadowlastchange'] +
- $shadow['shadowmax'] - $shadow['shadowwarning'];
- if ($today >= $warnday) {
- call_user_func($this->_params['notify_expire'], $toexpire);
- }
+ $warnday = $shadow['shadowlastchange'] + $shadow['shadowmax'] - $shadow['shadowwarning'];
+ if ($today >= $warnday) {
+ $this->setCredential('expire', $toexpire);
}
if ($toexpire == 0) {
- $this->_credentials['params']['change'] = true;
+ $this->setCredential('change', true);
} elseif ($toexpire < 0) {
throw new Horde_Auth_Exception('', Horde_Auth::REASON_EXPIRED);
}
throw new Horde_Auth_Exception(__CLASS__ . ': Adding users is not supported for Active Directory.');
}
- list($userId, $credentials) = Horde_Auth::runHook($userId, $credentials, $this->_app, 'preauthenticate', 'admin');
if (isset($credentials['ldap'])) {
$entry = $credentials['ldap'];
$dn = $entry['dn'];
* Remove a set of authentication credentials.
*
* @param string $userId The userId to add.
+ * @param string $dn TODO
*
* @throws Horde_Auth_Exception
*/
- public function removeUser($userId)
+ public function removeUser($userId, $dn = null)
{
if ($this->_params['ad']) {
throw new Horde_Auth_Exception(__CLASS__ . ': Removing users is not supported for Active Directory');
}
- list($userId, $credentials) = Horde_Auth::runHook($userId, array(), $this->_app, 'preauthenticate', 'admin');
- if (isset($credentials['ldap'])) {
- $dn = $credentials['ldap']['dn'];
- } else {
+ if (is_null($dn)) {
/* Search for the user's full DN. */
$dn = $this->_findDN($userId);
}
* @param string $oldID The old userId.
* @param string $newID The new userId.
* @param array $credentials The new credentials
+ * @param string $olddn TODO
+ * @param string $newdn TODO
*
* @throws Horde_Auth_Exception
*/
- public function updateUser($oldID, $newID, $credentials)
+ public function updateUser($oldID, $newID, $credentials, $olddn = null,
+ $newdn = null)
{
if ($this->_params['ad']) {
throw new Horde_Auth_Exception(__CLASS__ . ': Updating users is not supported for Active Directory.');
}
- list($oldID, $old_credentials) = Horde_Auth::runHook($oldID, $credentials, $this->_app, 'preauthenticate', 'admin');
- if (isset($old_credentials['ldap'])) {
- $olddn = $old_credentials['ldap']['dn'];
- list($newID, $new_credentials) = Horde_Auth::runHook($newID, $credentials, $this->_app, 'preauthenticate', 'admin');
- $newdn = $new_credentials['ldap']['dn'];
- unset($new_credentials['ldap']['dn']);
- } else {
+ if (is_null($olddn)) {
/* Search for the user's full DN. */
$dn = $this->_findDN($oldID);
/* Connect to the MSAD server. */
$this->_connect();
- list($accountName, $credentials) = Horde_Auth::runHook($accountName, $credentials, $this->_app, 'preauthenticate', 'admin');
if (isset($credentials['ldap'])) {
$dn = $credentials['ldap']['dn'];
} else {
* Remove a set of authentication credentials.
*
* @param string $accountName The user sAMAccountName to remove.
+ * @param string $dn TODO
*
* @throws Horde_Auth_Exception
*/
- public function removeUser($accountName)
+ public function removeUser($accountName, $dn = null)
{
/* Connect to the MSAD server. */
$this->_connect();
- list($accountName, $credentials) = Horde_Auth::runHook($accountName, $credentials, $this->_app, 'preauthenticate', 'admin');
- if (isset($credentials['ldap'])) {
- $dn = $credentials['ldap']['dn'];
- } else {
+ if (is_null($dn)) {
/* Search for the user's full DN. */
$dn = $this->_findDN($accountName);
}
/* Connect to the MSAD server. */
$this->_connect();
- list($oldId, $credentials) = Horde_Auth::runHook($oldId, $credentials, $this->_app, 'preauthenticate', 'admin');
if (isset($credentials['ldap'])) {
$olddn = $credentials['ldap']['dn'];
} else {
}
/**
- * Check existing auth for triggers that might invalidate it.
- *
- * @return boolean Is existing auth valid?
- */
- public function checkExistingAuth()
- {
- return !empty($_SERVER[$this->_params['username_header']]) &&
- ($this->_removeScope($_SERVER[$this->_params['username_header']]) == $this->_params['default_user']);
- }
-
- /**
* Automatic authentication: check if the username is set in the
* configured header.
*
* @return boolean Whether or not the client is allowed.
*/
- protected function _transparent()
+ public function transparent()
{
if (empty($_SERVER[$this->_params['username_header']])) {
return false;
$username = $_SERVER[$this->_params['username_header']];
// Remove scope from username, if present.
- $this->_credentials['userId'] = $this->_removeScope($username);
+ $this->setCredential('userId', $this->_removeScope($username));
// Set password for hordeauth login.
switch ($this->_params['password_holder']) {
case 'header':
- $this->_credentials['credentials'] = array(
+ $this->setCredential('credentials', array(
'password' => $_SERVER[$this->_params['password_header']]
- );
+ ));
break;
case 'preferences':
- $this->_credentials['credentials'] = array(
+ $this->setCredential('credentials', array(
'password' => $_SERVER[$this->_params['password_preference']]
- );
+ ));
+ break;
}
return true;
protected function _removeScope($username)
{
$pos = strrpos($username, '@');
-
return ($pos !== false)
? substr($username, 0, $pos)
: $username;
if (!empty($this->_params['soft_expiration_field']) &&
!empty($row[$this->_params['soft_expiration_field']]) &&
($now > $row[$this->_params['soft_expiration_field']])) {
- $this->_credentials['params']['change'] = true;
+ $this->setCredential('change', true);
+ $this->setCredential('expire', $date);
}
}
$query .= ', ' . $this->_params['soft_expiration_field'] . ' = ?';
$values[] = $date;
- if ($this->_params['notify_expire']) {
- call_user_func($this->_params['notify_expire'], $date);
- }
-
- $query .= ', ' . $this->_params['soft_expiration_field'] . ' = ?';
-
if (empty($this->_params['hard_expiration_window'])) {
$values[] = null;
} else {
<api>beta</api>
</stability>
<license uri="http://opensource.org/licenses/lgpl-2.1.php">LGPL</license>
- <notes>* Removed Krb5 driver.
+ <notes>* Remove dependency on horde/Core.
+ * Remove all non-authentication backend related code.
+ * Removed Krb5 driver.
* Moved signup code to horde/Core.
* Split Horde_Auth:: into Horde_Auth:: and Horde_Auth_Base:: components.
* Initial Horde 4 package.
<min>1.5.4</min>
</pearinstaller>
<package>
- <name>Core</name>
- <channel>pear.horde.org</channel>
- </package>
- <package>
<name>Exception</name>
<channel>pear.horde.org</channel>
</package>
<package>
- <name>Secret</name>
- <channel>pear.horde.org</channel>
- </package>
- <package>
<name>Util</name>
<channel>pear.horde.org</channel>
</package>
<channel>pear.horde.org</channel>
</package>
<package>
- <name>Form</name>
- <channel>pear.horde.org</channel>
- </package>
- <package>
- <name>History</name>
- <channel>pear.horde.org</channel>
- </package>
- <package>
<name>Imap_Client</name>
<channel>pear.horde.org</channel>
</package>
<channel>pear.horde.org</channel>
</package>
<extension>
- <name>gettext</name>
- </extension>
- <extension>
<name>pam_auth</name>
</extension>
<extension>
<?php
require_once dirname(__FILE__) . '/../../../lib/Horde/Auth.php';
-require_once dirname(__FILE__) . '/../../../lib/Horde/Auth/Driver.php';
+require_once dirname(__FILE__) . '/../../../lib/Horde/Auth/Base.php';
require_once dirname(__FILE__) . '/../../../lib/Horde/Auth/Passwd.php';
$auth = Horde_Auth::factory('passwd', array('filename' => dirname(__FILE__) . '/test.passwd'));
var_dump($auth->listUsers());
// Authenticate
-var_dump($auth->authenticate('user', array('password' => 'password'), false));
+var_dump($auth->authenticate('user', array('password' => 'password')));
?>
--EXPECT--
<?php
/**
- * The Horde_Core_Auth_Application class provides a wrapper around
- * application-provided Horde authentication which fits inside the
- * Horde_Auth:: API.
+ * The Horde_Core_Auth_Application class provides application-specific
+ * authentication built on top of the Horde_Auth:: API.
*
* Copyright 2002-2010 The Horde Project (http://www.horde.org/)
*
* not receive this file, see http://opensource.org/licenses/lgpl-2.1.php
*
* @author Chuck Hagenbuch <chuck@horde.org>
+ * @author Michael Slusarz <slusarz@horde.org>
* @category Horde
* @license http://opensource.org/licenses/lgpl-2.1.php LGPL
* @package Core
class Horde_Core_Auth_Application extends Horde_Auth_Base
{
/**
+ * Authentication failure reasons (additions to Horde_Auth:: reasons).
+ *
+ * <pre>
+ * REASON_BROWSER - A browser change was detected
+ * REASON_SESSIONIP - Logout due to change of IP address during session
+ * </pre>
+ */
+ const REASON_BROWSER = 100;
+ const REASON_SESSIONIP = 101;
+
+ /**
+ * The base auth driver, used for horde authentication.
+ *
+ * @var Horde_Auth_Base
+ */
+ protected $_base;
+
+ /**
+ * Application for authentication.
+ *
+ * @var string
+ */
+ protected $_app = 'horde';
+
+ /**
* Cache for hasCapability().
*
* @var array
* @param array $params Required parameters:
* <pre>
* 'app' - (string) The application which is providing authentication.
+ * 'base' - (Horde_Auth_Base) The base Horde_Auth driver. Only needed if
+ 'app' is 'horde'.
* </pre>
*
* @throws InvalidArgumentException
if (!isset($params['app'])) {
throw new InvalidArgumentException('Missing app parameter.');
}
-
$this->_app = $params['app'];
+ unset($params['app']);
- parent::__construct($params);
- }
-
- /**
- * Queries the current Auth object to find out if it supports the given
- * capability.
- *
- * @param string $capability The capability to test for.
- *
- * @return boolean Whether or not the capability is supported.
- */
- public function hasCapability($capability)
- {
- $capability = strtolower($capability);
+ if ($this->_app == 'horde') {
+ if (!isset($params['base'])) {
+ throw new InvalidArgumentException('Missing base parameter.');
+ }
- if (!in_array($capability, $this->_loaded) &&
- isset($this->_apiMethods[$capability])) {
- $this->_capabilities[$capability] = $GLOBALS['registry']->hasAppMethod($this->_app, $this->_apiMethods[$capability]);
- $this->_loaded[] = $capability;
+ $this->_base = $params['base'];
+ unset($params['base']);
}
- return parent::hasCapability($capability);
+ parent::__construct($params);
}
/**
* Finds out if a set of login credentials are valid, and if requested,
* mark the user as logged in in the current session.
*
- * @param string $userId The userId to check.
+ * @param string $userId The user ID to check.
* @param array $credentials The credentials to check.
- * @param boolean $login Whether to log the user in. If false, we'll
- * only test the credentials and won't modify
- * the current session. Defaults to true.
*
* @return boolean Whether or not the credentials are valid.
*/
- public function authenticate($userId, $credentials, $login = true)
+ public function authenticate($userId, $credentials)
{
- if (!parent::authenticate($userId, $credentials, $login)) {
+ try {
+ list($userId, $credentials) = $this->runHook(trim($userId), $credentials, 'preauthenticate', 'authenticate');
+ } catch (Horde_Auth_Exception $e) {
return false;
}
- $this->_authCallback();
+ if ($this->_base) {
+ if (!$this->_base->authenticate($userId, $credentials)) {
+ return false;
+ }
+ } elseif (!parent::authenticate($userId, $credentials)) {
+ return false;
+ }
- return true;
+ return $this->_setAuth();
}
/**
* Find out if a set of login credentials are valid.
*
- * @param string $userId The userId to check.
+ * @param string $userId The user ID to check.
* @param array $credentials The credentials to use. This object will
* always be available in the 'auth_ob' key.
*
}
/**
- * List all users in the system.
+ * Checks for triggers that may invalidate the current auth.
+ * These triggers are independent of the credentials.
*
- * @return array The array of userIds.
- * @throws Horde_Auth_Exception
+ * @return boolean True if the results of authenticate() are still valid.
*/
- public function listUsers()
+ public function validateAuth()
{
- return $this->hasCapability('list')
- ? $GLOBALS['registry']->callAppMethod($this->_app, $this->_apiMethods['list'])
- : parent::listUsers();
- }
-
- /**
- * Checks if $userId exists in the system.
- *
- * @param string $userId User ID to check.
- *
- * @return boolean Whether or not $userId already exists.
- */
- public function exists($userId)
- {
- return $this->hasCapability('exists')
- ? $GLOBALS['registry']->callAppMethod($this->_app, $this->_apiMethods['exists'], array('args' => array($userId)))
- : parent::exists($userId);
+ return $this->_base
+ ? $this->_base->validateAuth()
+ : parent::validateAuth();
}
/**
* Add a set of authentication credentials.
*
- * @param string $userId The userId to add.
+ * @param string $userId The user ID to add.
* @param array $credentials The credentials to use.
*
* @throws Horde_Auth_Exception
*/
public function addUser($userId, $credentials)
{
+ if ($this->_base) {
+ $this->_base->addUser($userId, $credentials);
+ return;
+ }
+
if ($this->hasCapability('add')) {
$GLOBALS['registry']->callAppMethod($this->_app, $this->_apiMethods['add'], array('args' => array($userId, $credentials)));
} else {
/**
* Update a set of authentication credentials.
*
- * @param string $oldID The old userId.
- * @param string $newID The new userId.
+ * @param string $oldID The old user ID.
+ * @param string $newID The new user ID.
* @param array $credentials The new credentials
*
* @throws Horde_Auth_Exception
*/
public function updateUser($oldID, $newID, $credentials)
{
+ if ($this->_base) {
+ $this->_base->updateUser($oldID, $newID, $credentials);
+ return;
+ }
+
if ($this->hasCapability('update')) {
$GLOBALS['registry']->callAppMethod($this->_app, $this->_apiMethods['update'], array('args' => array($oldID, $newID, $credentials)));
} else {
}
/**
+ * Delete a set of authentication credentials.
+ *
+ * @param string $userId The user ID to delete.
+ *
+ * @throws Horde_Auth_Exception
+ */
+ public function removeUser($userId)
+ {
+ if ($this->_base) {
+ $this->_base->removeUser($userId);
+
+ try {
+ $GLOBALS['registry']->callAppMethod('horde', 'removeUserDataFromAllApplications', array('args' => array($userId)));
+ } catch (Horde_Exception $e) {
+ throw new Horde_Auth_Exception($e);
+ }
+ } else {
+ if ($this->hasCapability('remove')) {
+ $GLOBALS['registry']->callAppMethod($this->_app, $this->_apiMethods['remove'], array('args' => array($userId)));
+ } else {
+ parent::removeUser($userId);
+ }
+
+ try {
+ $GLOBALS['registry']->callAppMethod($this->_app, 'removeUserData', array('args' => array($userId)));
+ } catch (Horde_Exception $e) {
+ throw new Horde_Auth_Exception($e);
+ }
+ }
+ }
+
+ /**
+ * List all users in the system.
+ *
+ * @return array The array of user IDs.
+ * @throws Horde_Auth_Exception
+ */
+ public function listUsers()
+ {
+ if ($this->_base) {
+ return $this->_base->listUsers();
+ }
+
+ return $this->hasCapability('list')
+ ? $GLOBALS['registry']->callAppMethod($this->_app, $this->_apiMethods['list'])
+ : parent::listUsers();
+ }
+
+ /**
+ * Checks if a user ID exists in the system.
+ *
+ * @param string $userId User ID to check.
+ *
+ * @return boolean Whether or not the user ID already exists.
+ */
+ public function exists($userId)
+ {
+ if ($this->_base) {
+ return $this->_base->exists($userId);
+ }
+
+ return $this->hasCapability('exists')
+ ? $GLOBALS['registry']->callAppMethod($this->_app, $this->_apiMethods['exists'], array('args' => array($userId)))
+ : parent::exists($userId);
+ }
+
+ /**
+ * Automatic authentication.
+ *
+ * @return boolean Whether or not the client is allowed.
+ * @throws Horde_Auth_Exception
+ */
+ public function transparent()
+ {
+ global $registry;
+
+ if (!($userId = $this->getCredential('userId'))) {
+ $userId = $registry->getAuth();
+ }
+ if (!($credentials = $this->getCredential('credentials'))) {
+ $credentials = $registry->getAuthCredential();
+ }
+
+ list($userId, $credentials) = $this->runHook($userId, $credentials, 'preauthenticate', 'transparent');
+
+ $this->setCredential('userId', $userId);
+ $this->setCredential('credentials', $credentials);
+
+ if ($this->_base) {
+ $result = $this->_base->transparent();
+ } else {
+ $result = $this->hasCapability('transparent')
+ ? $registry->callAppMethod($this->_app, $this->_apiMethods['transparent'], array('args' => array($this), 'noperms' => true))
+ /* If this application contains neither transparent nor
+ * authenticate capabilities, it does not require any
+ * authentication if already authenticated to Horde. */
+ : ($registry->getAuth() && !$this->hasCapability('authenticate'));
+ }
+
+ return $result && $this->_setAuth();
+ }
+
+ /**
* Reset a user's password. Used for example when the user does not
* remember the existing password.
*
- * @param string $userId The userId for which to reset the password.
+ * @param string $userId The user ID for which to reset the password.
*
* @return string The new password on success.
* @throws Horde_Auth_Exception
*/
public function resetPassword($userId)
{
+ if ($this->_base) {
+ return $this->_base->resetPassword($userId);
+ }
+
return $this->hasCapability('resetpassword')
? $GLOBALS['registry']->callAppMethod($this->_app, $this->_apiMethods['resetpassword'], array('args' => array($userId)))
: parent::resetPassword();
}
/**
- * Delete a set of authentication credentials.
+ * Queries the current driver to find out if it supports the given
+ * capability.
*
- * @param string $userId The userId to delete.
+ * @param string $capability The capability to test for.
*
- * @throws Horde_Auth_Exception
+ * @return boolean Whether or not the capability is supported.
*/
- public function removeUser($userId)
+ public function hasCapability($capability)
{
- if ($this->hasCapability('remove')) {
- $GLOBALS['registry']->callAppMethod($this->_app, $this->_apiMethods['remove'], array('args' => array($userId)));
- Horde_Auth::removeUserData($userId);
- } else {
- parent::removeUser($userId);
+ if ($this->_base) {
+ return $this->_base->hasCapability($capability);
}
+
+ $capability = strtolower($capability);
+
+ if (!in_array($capability, $this->_loaded) &&
+ isset($this->_apiMethods[$capability])) {
+ $this->_capabilities[$capability] = $GLOBALS['registry']->hasAppMethod($this->_app, $this->_apiMethods[$capability]);
+ $this->_loaded[] = $capability;
+ }
+
+ return parent::hasCapability($capability);
}
/**
- * Automatic authentication.
+ * Returns the named parameter for the current auth driver.
*
- * @return boolean Whether or not the client is allowed.
- * @throws Horde_Auth_Exception
+ * @param string $param The parameter to fetch.
+ *
+ * @return string The parameter's value, or null if it doesn't exist.
*/
- public function transparent()
+ public function getParam($param)
{
- if (!parent::transparent()) {
- return false;
- }
+ return $this->_base
+ ? $this->_base->getParam($param)
+ : parent::getParam($param);
+ }
- $this->_authCallback();
+ /**
+ * Retrieve internal credential value(s).
+ *
+ * @param mixed $name The credential value to get. If null, will return
+ * the entire credential list. Valid names:
+ * <pre>
+ * 'change' - (boolean) Do credentials need to be changed?
+ * 'credentials' - (array) The credentials needed to authenticate.
+ * 'expire' - (integer) UNIX timestamp of the credential expiration date.
+ * 'userId' - (string) The user ID.
+ * </pre>
+ *
+ * @return mixed Return the credential information, or null if the
+ * credential doesn't exist.
+ */
+ public function getCredential($name = null)
+ {
+ return $this->_base
+ ? $this->_base->getCredential($name)
+ : parent::getCredential($name);
+ }
- return true;
+ /**
+ * Set internal credential value.
+ *
+ * @param string $name The credential name to set.
+ * @param mixed $value The credential value to set. See getCredential()
+ * for the list of valid credentials/types.
+ */
+ public function setCredential($type, $value)
+ {
+ if ($this->_base) {
+ $this->_base->setCredential($type, $value);
+ } else {
+ parent::setCredential($type, $value);
+ }
}
/**
- * Attempt transparent authentication. The application method is passed a
- * single parameter: the current class instance.
+ * Sets the error message for an invalid authentication.
*
- * @return boolean Whether transparent login is supported.
+ * @param string $type The type of error (Horde_Auth::REASON_* constant).
+ * @param string $msg The error message/reason for invalid
+ * authentication.
*/
- protected function _transparent()
+ public function setError($type, $msg = null)
{
- if (!$this->hasCapability('transparent')) {
- /* If this application contains neither transparent nor
- * authenticate capabilities, it does not require any
- * authentication if already authenticated to Horde. */
- return ($GLOBALS['registry']->getAuth() &&
- !$this->hasCapability('authenticate'));
+ if ($this->_base) {
+ $this->_base->setError($type, $msg);
+ } else {
+ parent::setError($type, $msg);
}
+ }
- return $GLOBALS['registry']->callAppMethod($this->_app, $this->_apiMethods['transparent'], array('args' => array($this), 'noperms' => true));
+ /**
+ * Returns the error type or message for an invalid authentication.
+ *
+ * @param boolean $msg If true, returns the message string (if set).
+ *
+ * @return mixed Error type, error message (if $msg is true) or false
+ * if entry doesn't exist.
+ */
+ public function getError($msg = false)
+ {
+ return $this->_base
+ ? $this->_base->getError($msg)
+ : parent::getError($msg);
}
/**
*/
public function getLoginParams()
{
- if (!$this->hasCapability('loginparams')) {
- return parent::getLoginParams();
+ if ($this->hasCapability('loginparams')) {
+ return $this->_base
+ ? $this->_base->getLoginParams()
+ : $GLOBALS['registry']->callAppMethod($this->_app, $this->_apiMethods['loginparams'], array('noperms' => true));
}
- return $GLOBALS['registry']->callAppMethod($this->_app, $this->_apiMethods['loginparams'], array('noperms' => true));
+ return array(
+ 'js_code' => array(),
+ 'js_files' => array(),
+ 'params' => array()
+ );
}
/**
- * Provide method to get internal credential values. Necessary as the
- * application API does not have direct access to the protected member
- * variables of this class.
- *
- * @param mixed $name The credential name to get. If null, will return
- * the entire credential list.
+ * Indicate whether the application requires authentication.
*
- * @return mixed Return the credential information, or null if the.
- * credential doesn't exist.
+ * @return boolean True if application requires authentication.
*/
- public function getCredential($name = null)
+ public function requireAuth()
{
- if (is_null($name)) {
- return $this->_credentials;
- }
-
- return isset($this->_credentials[$name])
- ? $this->_credentials[$name]
- : null;
+ return !$this->_base &&
+ ($this->hasCapability('authenticate') ||
+ $this->hasCapability('transparent'));
}
/**
- * Provide method to set internal credential values. Necessary as the
- * application API does not have direct access to the protected member
- * variables of this class.
+ * Runs the pre/post-authenticate hook and parses the result.
*
- * @param string $name The credential name to set.
- * @param mixed $value The credential value to set. If $name is 'userId',
- * this must be a text value. If $name is
- * 'credentials' or 'params', this is an array of
- * values to be merged in.
+ * @param string $userId The userId who has been authorized.
+ * @param array $credentials The credentials of the user.
+ * @param string $type Either 'preauthenticate' or
+ * 'postauthenticate'.
+ * @param string $method The triggering method (preauthenticate only).
+ * Either 'authenticate' or 'transparent'.
+ *
+ * @return array Two element array, $userId and $credentials.
+ * @throws Horde_Auth_Exception
*/
- public function setCredential($type, $value)
+ public function runHook($userId, $credentials, $type, $method = null)
{
- switch ($type) {
- case 'userId':
- $this->_credentials['userId'] = $value;
- break;
-
- case 'credentials':
- case 'params':
- $this->_credentials[$type] = array_merge($this->_credentials[$type], $value);
- break;
+ if (!is_array($credentials)) {
+ $credentials = empty($credentials)
+ ? array()
+ : array($credentials);
+ }
+
+ $ret_array = array($userId, $credentials);
+
+ if ($type == 'preauthenticate') {
+ $credentials['authMethod'] = $method;
+ }
+
+ try {
+ $result = Horde::callHook($type, array($userId, $credentials), $this->_app);
+ } catch (Horde_Exception $e) {
+ throw new Horde_Auth_Exception($e);
+ } catch (Horde_Exception_HookNotSet $e) {
+ return $ret_array;
+ }
+
+ unset($credentials['authMethod']);
+
+ if ($result === false) {
+ if ($this->getError() != Horde_Auth::REASON_MESSAGE) {
+ $this->setError(Horde_Auth::REASON_FAILED);
+ }
+ throw new Horde_Auth_Exception($type . ' hook failed');
+ }
+
+ if (is_array($result)) {
+ if ($type == 'postauthenticate') {
+ $ret_array[1] = $result;
+ } else {
+ if (isset($result['userId'])) {
+ $ret_array[0] = $result['userId'];
+ }
+
+ if (isset($result['credentials'])) {
+ $ret_array[1] = $result['credentials'];
+ }
+ }
}
}
/**
- * Provide way to finish authentication tasks in an application and ensure
- * that the full application environment is loaded.
+ * Set authentication credentials in the Horde session.
*
- * @throws Horde_Auth_Exception
+ * @return boolean True on success, false on failure.
*/
- protected function _authCallback()
+ protected function _setAuth()
{
+ if ($GLOBALS['registry']->isAuthenticated(array('app' => $this->_app, 'notransparent' => true))) {
+ return true;
+ }
+
+ $userId = $this->getCredential('userId');
+ $credentials = $this->getCredential('credentials');
+
+ try {
+ list(,$credentials) = $this->runHook($userId, $credentials, 'postauthenticate');
+ } catch (Horde_Auth_Exception $e) {
+ return false;
+ }
+
+ $GLOBALS['registry']->setAuth($userId, $credentials, array(
+ 'app' => $this->_app,
+ 'change' => $this->getCredential('change')
+ ));
+
+ if ($this->_base &&
+ isset($GLOBALS['notification']) &&
+ ($expire = $this->_base->getCredential('expire'))) {
+ $toexpire = ($expire - time()) / 86400;
+ $GLOBALS['notification']->push(sprintf(ngettext("%d day until your password expires.", "%d days until your password expires.", $toexpire), $toexpire), 'horde.warning');
+ }
+
if ($this->hasCapability('authenticatecallback')) {
$GLOBALS['registry']->callAppMethod($this->_app, $this->_apiMethods['authenticatecallback'], array('noperms' => true));
}
- }
- /**
- * Indicate whether the application requires authentication.
- *
- * @return boolean True if application requires authentication.
- */
- public function requireAuth()
- {
- return $this->hasCapability('authenticate') || $this->hasCapability('transparent');
+ return true;
}
}
--- /dev/null
+<?php
+/**
+ * The Horde_Core_Auth_Ldap class provides Horde-specific code that
+ * extends the base LDAP driver.
+ *
+ * Copyright 2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you did
+ * not receive this file, see http://opensource.org/licenses/lgpl-2.1.php
+ *
+ * @author Michael Slusarz <slusarz@horde.org>
+ * @category Horde
+ * @license http://opensource.org/licenses/lgpl-2.1.php LGPL
+ * @package Core
+ */
+class Horde_Core_Auth_Ldap extends Horde_Auth_Ldap
+{
+ /**
+ * Add a set of authentication credentials.
+ *
+ * @param string $userId The user ID to add.
+ * @param array $credentials The credentials to use.
+ *
+ * @throws Horde_Auth_Exception
+ */
+ public function addUser($userId, $credentials)
+ {
+ list($userId, $credentials) = $GLOBALS['injector']->getInstance('Horde_Auth')->getAuth()->runHook($userId, $credentials, 'preauthenticate', 'admin');
+
+ parent::addUser($userId, $credentials);
+ }
+
+ /**
+ * Update a set of authentication credentials.
+ *
+ * @param string $oldID The old user ID.
+ * @param string $newID The new user ID.
+ * @param array $credentials The new credentials
+ *
+ * @throws Horde_Auth_Exception
+ */
+ public function updateUser($oldID, $newID, $credentials)
+ {
+ $auth = $GLOBALS['injector']->getInstance('Horde_Auth')->getAuth();
+
+ list($oldID, $old_credentials) = $auth->runHook($oldID, $credentials, 'preauthenticate', 'admin');
+ if (isset($old_credentials['ldap'])) {
+ list($newID, $new_credentials) = $auth->runHook($newID, $credentials, 'preauthenticate', 'admin');
+ $olddn = $old_credentials['ldap']['dn'];
+ $newdn = $new_credentials['ldap']['dn'];
+ } else {
+ $olddn = $newdn = null;
+ }
+
+ parent::updateUser($oldID, $newID, $credentials, $olddn, $newdn);
+ }
+
+ /**
+ * Delete a set of authentication credentials.
+ *
+ * @param string $userId The user ID to delete.
+ *
+ * @throws Horde_Auth_Exception
+ */
+ public function removeUser($userId)
+ {
+ list($userId, $credentials) = $GLOBALS['injector']->getInstance('Horde_Auth')->getAuth()->runHook($userId, array(), 'preauthenticate', 'admin');
+
+ parent::removeUser($userId, isset($credentials['ldap']) ? $credentials['ldap']['dn'] : null);
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * The Horde_Core_Auth_Msad class provides Horde-specific code that
+ * extends the base LDAP driver.
+ *
+ * Copyright 2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you did
+ * not receive this file, see http://opensource.org/licenses/lgpl-2.1.php
+ *
+ * @author Michael Slusarz <slusarz@horde.org>
+ * @category Horde
+ * @license http://opensource.org/licenses/lgpl-2.1.php LGPL
+ * @package Core
+ */
+class Horde_Core_Auth_Msad extends Horde_Auth_Msad
+{
+ /**
+ * Add a set of authentication credentials.
+ *
+ * @param string $userId The user ID to add.
+ * @param array $credentials The credentials to use.
+ *
+ * @throws Horde_Auth_Exception
+ */
+ public function addUser($userId, $credentials)
+ {
+ list($userId, $credentials) = $GLOBALS['injector']->getInstance('Horde_Auth')->getAuth()->runHook($userId, $credentials, 'preauthenticate', 'admin');
+
+ parent::addUser($userId, $credentials);
+ }
+
+ /**
+ * Update a set of authentication credentials.
+ *
+ * @param string $oldID The old user ID.
+ * @param string $newID The new user ID.
+ * @param array $credentials The new credentials
+ *
+ * @throws Horde_Auth_Exception
+ */
+ public function updateUser($oldID, $newID, $credentials)
+ {
+ list($oldId, $credentials) = $GLOBALS['injector']->getInstance('Horde_Auth')->getAuth()->runHook($oldId, $credentials, 'preauthenticate', 'admin');
+
+ parent::updateUser($oldID, $newID, $credentials);
+ }
+
+ /**
+ * Delete a set of authentication credentials.
+ *
+ * @param string $userId The user ID to delete.
+ *
+ * @throws Horde_Auth_Exception
+ */
+ public function removeUser($userId)
+ {
+ list($userId, $credentials) = $GLOBALS['injector']->getInstance('Horde_Auth')->getAuth()->runHook($userId, array(), 'preauthenticate', 'admin');
+
+ parent::removeUser($userId, isset($credentials['ldap']) ? $credentials['ldap']['dn'] : null);
+ }
+
+}
--- /dev/null
+<?php
+/**
+ * The Horde_Core_Auth_Shibboleth class provides Horde-specific code that
+ * extends the base Shibboleth driver.
+ *
+ * Copyright 2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you did
+ * not receive this file, see http://opensource.org/licenses/lgpl-2.1.php
+ *
+ * @author Michael Slusarz <slusarz@horde.org>
+ * @category Horde
+ * @license http://opensource.org/licenses/lgpl-2.1.php LGPL
+ * @package Core
+ */
+class Horde_Core_Auth_Shibboleth extends Horde_Auth_Shibboleth
+{
+ /**
+ * Checks for triggers that may invalidate the current auth.
+ * These triggers are independent of the credentials.
+ *
+ * @return boolean True if the results of authenticate() are still valid.
+ */
+ public function validateAuth()
+ {
+ return !empty($_SERVER[$this->getParam('username_header')]) &&
+ ($this->_removeScope($_SERVER[$this->getParam('username_header')]) == $GLOBALS['registry']->getAuth());
+ }
+
+}
+++ /dev/null
-<?php
-/**
- * @category Horde
- * @package Core
- */
-class Horde_Core_Autoloader_Callback_Auth
-{
- /**
- * TODO
- */
- static public function callback()
- {
- Horde_Auth::$dnsResolver = $GLOBALS['injector']->getInstance('Net_DNS_Resolver');
- }
-
-}
/**
* Return the Horde_Auth:: instance.
*
- * @param string $driver The driver.
- * @param array $params Additional parameters to pass to the driver
- * (will override Horde defaults).
+ * @param string $app The application to authenticate to.
*
* @return Horde_Auth_Base The singleton instance.
* @throws Horde_Auth_Exception
*/
- public function getAuth($driver = null, array $params = array())
+ public function getAuth($app = null)
{
- if (is_null($driver)) {
- $driver = $GLOBALS['conf']['auth']['driver'];
+ if (is_null($app)) {
+ $app = 'horde';
}
- $params = array_merge(Horde::getDriverConfig('auth', $driver), $params);
- ksort($params);
-
- /* Get proper driver name now that we have grabbed the
- * configuration. */
- if (strcasecmp($driver, 'httpremote') === 0) {
- /* BC */
- $driver = 'Http_Remote';
- } elseif (strcasecmp($driver, 'application') === 0) {
- $driver = 'Horde_Core_Auth_Application';
- } else {
- $driver = Horde_String::ucfirst(Horde_String::lower(basename($driver)));
+ if (isset($this->_instances[$app])) {
+ return $this->_instances[$app];
}
- $sig = hash('md5', serialize(array($driver, $params)));
+ $base_params = array(
+ 'app' => $app,
+ 'logger' => $this->_injector->getInstance('Horde_Log_Logger')
+ );
+
+ if ($app == 'horde') {
+ $driver = $GLOBALS['conf']['auth']['driver'];
+ $params = Horde::getDriverConfig('auth', $driver);
+
+ /* Get proper driver name now that we have grabbed the
+ * configuration. */
+ if (strcasecmp($driver, 'application') === 0) {
+ $driver = 'Horde_Core_Auth_Application';
+ } elseif (strcasecmp($driver, 'httpremote') === 0) {
+ /* BC */
+ $driver = 'Http_Remote';
+ } elseif (strcasecmp($driver, 'ldap') === 0) {
+ $driver = 'Horde_Core_Auth_Ldap';
+ } elseif (strcasecmp($driver, 'msad') === 0) {
+ $driver = 'Horde_Core_Auth_Msad';
+ } elseif (strcasecmp($driver, 'shibboleth') === 0) {
+ $driver = 'Horde_Core_Auth_Shibboleth';
+ } else {
+ $driver = Horde_String::ucfirst(Horde_String::lower(basename($driver)));
+ }
- if (!isset($this->_instances[$sig])) {
$lc_driver = Horde_String::lower($driver);
switch ($lc_driver) {
case 'composite':
$params['kolab'] = $this->_injector->getInstance('Horde_Kolab_Session');
break;
- case 'ldap':
+ case 'horde_core_auth_ldap':
+ case 'horde_core_auth_msad':
$params['ldap'] = $this->_injector->getInstance('Horde_Ldap')->getLdap('horde', 'auth');
break;
$params['default_user'] = $GLOBALS['registry']->getAuth();
$params['logger'] = $this->_injector->getInstance('Horde_Log_Logger');
- $params['notify_expire'] = array($this, 'notifyExpire');
- $this->_instances[$sig] = Horde_Auth::factory($driver, $params);
+ $base_params['base'] = Horde_Auth::factory($driver, $params);
+ if ($driver == 'Horde_Core_Auth_Application') {
+ $this->_instances[$params['app']] = $base_params['base'];
+ }
}
- return $this->_instances[$sig];
- }
+ $this->_instances[$app] = Horde_Auth::factory('Horde_Core_Auth_Application', $base_params);
- /**
- * Expire notification callback.
- *
- * @param integer $date UNIX timestamp of password expiration.
- */
- public function notifyExpire($date)
- {
- if (isset($GLOBALS['notification'])) {
- $toexpire = ($date - time()) / 86400;
- $GLOBALS['notification']->push(sprintf(ngettext("%d day until your password expires.", "%d days until your password expires.", $toexpire), $toexpire), 'horde.warning');
- }
+ return $this->_instances[$app];
}
}
{
/* Define autoloader callbacks. */
$callbacks = array(
- 'Horde_Auth' => 'Horde_Core_Autoloader_Callback_Auth',
'Horde_Mime' => 'Horde_Core_Autoloader_Callback_Mime'
);
* - To all authenticated users if no permission is set on $app.
* - To anyone who is allowed by an explicit ACL on $app. */
if ($checkPerms) {
- if ($this->getAuth() && !Horde_Auth::checkExistingAuth()) {
+ if ($this->getAuth() && !$this->checkExistingAuth($app)) {
throw new Horde_Exception('User is not authorized', self::AUTH_FAILURE);
}
+
if (!$this->hasPermission($app, Horde_Perms::READ)) {
if (!$this->isAuthenticated(array('app' => $app))) {
throw new Horde_Exception('User is not authorized', self::AUTH_FAILURE);
* application auth != Horde admin auth. And there can *never* be
* non-SHOW access to an application that requires authentication. */
if (!$this->isAuthenticated(array('app' => $app)) &&
- $this->requireAuth($app) &&
+ $GLOBALS['injector']->getInstance('Horde_Auth')->getAuth($app)->requireAuth() &&
($perms != Horde_Perms::SHOW)) {
return false;
}
}
/**
- * Returns the name of the authentication provider.
- *
- * @return string The name of the driver currently providing
- * authentication, or false if not set.
- */
- public function getProvider()
- {
- return empty($_SESSION['horde_auth']['driver'])
- ? false
- : $_SESSION['horde_auth']['driver'];
- }
-
- /**
* Clears any authentication tokens in the current session.
*
* @param boolean $destroy Destroy the session?
}
/**
- * Checks if an application requires additional authentication above and
- * beyond Horde authentication.
- *
- * @params string $app The application to check.
- *
- * @return boolean Whether or not the application required additional
- * authentication.
- * @throws Horde_Exception
- */
- public function requireAuth($app)
- {
- return ($app == 'horde')
- ? false
- : $GLOBALS['injector']->getInstance('Horde_Auth')->getAuth('application', array('app' => $app))->requireAuth();
- }
-
- /**
* Checks if there is a session with valid auth information. If there
* isn't, but the configured Auth driver supports transparent
* authentication, then we try that.
* <pre>
* 'app' - (string) Check authentication for this app.
* DEFAULT: Checks horde-wide authentication.
+ * 'notransparent' - (boolean) Do not attempt transparent authentication.
+ * DEFAULT: false
* </pre>
*
* @return boolean Whether or not the user is authenticated.
*/
- public function isAuthenticated($options = array())
+ public function isAuthenticated(array $options = array())
{
+ $app = empty($options['app'])
+ ? 'horde'
+ : $options['app'];
+
/* Check for cached authentication results. */
- if ($GLOBALS['registry']->getAuth()) {
- $driver = (empty($options['app']) || ($options['app'] == 'horde'))
- ? $GLOBALS['conf']['auth']['driver']
- : $options['app'];
-
- if (($_SESSION['horde_auth']['driver'] == $driver) ||
- isset($_SESSION['horde_auth']['app'][$driver])) {
- if (Horde_Auth::checkExistingAuth()) {
- return true;
- }
- $this->clearAuth();
- return false;
+ if ($this->getAuth() &&
+ (($app == 'horde') ||
+ isset($_SESSION['horde_auth']['app'][$app]))) {
+ if ($this->checkExistingAuth($app)) {
+ return true;
}
+
+ return false;
}
/* Try transparent authentication. */
- $auth = (empty($options['app']) || ($options['app'] == 'horde'))
- ? $GLOBALS['injector']->getInstance('Horde_Auth')->getAuth()
- : $GLOBALS['injector']->getInstance('Horde_Auth')->getAuth('application', array('app' => $options['app']));
-
- return $auth->transparent();
+ return empty($options['notransparent'])
+ ? $GLOBALS['injector']->getInstance('Horde_Auth')->getAuth($app)->transparent()
+ : false;
}
/**
public function getLogoutUrl(array $options = array())
{
if (!isset($options['reason'])) {
- $options['reason'] = Horde_Auth::getAuthError();
+ // TODO: This only returns the error for Horde-wide
+ // authentication, not for application auth.
+ $options['reason'] = $GLOBALS['injector']->getInstance('Horde_Auth')->getAuth()->getError();
}
if (empty($options['app']) ||
}
if ($options['reason']) {
- $params[Horde_Auth::REASON_PARAM] = $options['reason'];
+ $params['logout_reason'] = $options['reason'];
if ($options['reason'] == Horde_Auth::REASON_MESSAGE) {
- $params[Horde_Auth::REASON_MSG_PARAM] = empty($options['msg'])
- ? Horde_Auth::getAuthError(true)
+ $params['logout_msg'] = empty($options['msg'])
+ ? $GLOBALS['injector']->getInstance('Horde_Auth')->getAuth()->getError(true)
: $options['msg'];
}
}
/**
* Sets the requested credential for the currently logged in user.
*
- * @param string $credential The credential to set.
- * @param string $value The value to set the credential to.
- * @param string $app The app to update. Defaults to Horde.
+ * @param mixed $credential The credential to set. If an array,
+ * overwrites the current credentials array.
+ * @param string $value The value to set the credential to. If
+ * $credential is an array, this value is
+ * ignored.
+ * @param string $app The app to update. Defaults to Horde.
*/
- public function setAuthCredential($credential, $value, $app = null)
+ public function setAuthCredential($credential, $value = null, $app = null)
{
if (!$this->getAuth()) {
return;
}
- $credentials = $this->_getAuthCredentials($app);
+ if (is_array($credential)) {
+ $credentials = $credential;
+ } else {
+ if (($credentials = $this->_getAuthCredentials($app)) === false) {
+ return;
+ }
- if ($credentials !== false) {
- if (is_array($credentials)) {
- $credentials[$credential] = $value;
- } else {
- $credentials = array($credential => $value);
+ if (!is_array($credentials)) {
+ $credentials = array();
}
- $secret = $GLOBALS['injector']->getInstance('Horde_Secret');
- $_SESSION['horde_auth']['app'][$app] = $secret->write($secret->getKey('auth'), serialize($credentials));
+ $credentials[$credential] = $value;
}
+
+ $secret = $GLOBALS['injector']->getInstance('Horde_Secret');
+ $_SESSION['horde_auth']['app'][$app] = $secret->write($secret->getKey('auth'), serialize($credentials));
}
/**
*/
protected function _getAuthCredentials($app)
{
+ if (!isset($_SESSION['horde_auth']['app'])) {
+ return false;
+ }
+
if (is_null($app)) {
$app = $_SESSION['horde_auth']['credentials'];
}
- if (!isset($_SESSION['horde_auth']['app'])) {
+ $secret = $GLOBALS['injector']->getInstance('Horde_Secret');
+ return @unserialize($secret->read($secret->getKey('auth'), $_SESSION['horde_auth']['app'][$app]));
+ }
+
+ /**
+ * Sets a variable in the session saying that authorization has succeeded,
+ * note which userId was authorized, and note when the login took place.
+ *
+ * If a user name hook was defined in the configuration, it gets applied
+ * to the $userId at this point.
+ *
+ * Horde authentication data is stored in the session in the 'horde_auth'
+ * array key. That key has the following structure:
+ * <pre>
+ * 'app' - (array) Application-specific authentication. Keys are the
+ * app names, values are an array containing credentials. If true,
+ * application does not require any specific credentials.
+ * 'authId' - (string) The username used during the original
+ authentication.
+ * 'browser' - (string) The remote browser string.
+ * 'change' - (boolean) Is a password change requested?
+ * 'credentials' - (string) The 'app' entry that contains the Horde
+ * credentials.
+ * 'remoteAddr' - (string) The remote IP address of the user.
+ * 'timestamp' - (integer) The login time.
+ * 'userId' - (string) The unique Horde username.
+ * </pre>
+ *
+ * @param string $authId The userId that has been authorized.
+ * @param array $credentials The credentials of the user.
+ * @param array $options Additional options:
+ * <pre>
+ * 'app' - (string) The app to set authentication credentials for.
+ * DEFAULT: 'horde'
+ * 'change' - (boolean) Whether to request that the user change their
+ * password.
+ * DEFAULT: No
+ * </pre>
+ */
+ public function setAuth($authId, $credentials, array $options = array())
+ {
+ $app = empty($options['app']) ? 'horde' : $options['app'];
+
+ if ($this->getAuth()) {
+ /* Store app credentials. */
+ $this->setAuthCredential($credentials, null, $app);
+ return;
+ }
+
+ /* Clear any existing info. */
+ $this->clearAuth(false);
+
+ $_SESSION['horde_auth'] = array(
+ 'app' => array(),
+ 'authId' => $authId,
+ 'browser' => $GLOBALS['injector']->getInstance('Horde_Browser')->getAgentString(),
+ 'change' => !empty($options['change']),
+ 'credentials' => $app,
+ 'remoteAddr' => isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : null,
+ 'timestamp' => time(),
+ 'userId' => $this->convertUsername(trim($authId), true)
+ );
+
+ $this->setAuthCredential($credentials, null, $app);
+
+ /* Reload preferences for the new user. */
+ $this->loadPrefs();
+ Horde_Nls::setLanguageEnvironment($GLOBALS['prefs']->getValue('language'), $app);
+ }
+
+ /**
+ * Check existing auth for triggers that might invalidate it.
+ *
+ * @param string $app Check authentication for this app.
+ *
+ * @return boolean Is existing auth valid?
+ */
+ public function checkExistingAuth($app)
+ {
+ if ($app != 'horde') {
+ return true;
+ }
+
+ $auth = $GLOBALS['injector']->getInstance('Horde_Auth')->getAuth();
+
+ if (!empty($GLOBALS['conf']['auth']['checkip']) &&
+ !empty($_SESSION['horde_auth']['remoteAddr']) &&
+ ($_SESSION['horde_auth']['remoteAddr'] != $_SERVER['REMOTE_ADDR'])) {
+ $auth->setError(Horde_Core_Auth_Application::REASON_SESSIONIP);
return false;
}
- $secret = $GLOBALS['injector']->getInstance('Horde_Secret');
- return @unserialize($secret->read($secret->getKey('auth'), $_SESSION['horde_auth']['app'][$app]));
+ if (!empty($GLOBALS['conf']['auth']['checkbrowser']) &&
+ ($_SESSION['horde_auth']['browser'] != $GLOBALS['injector']->getInstance('Horde_Browser')->getAgentString())) {
+ $auth->setError(Horde_Core_Auth_Application::REASON_BROWSER);
+ return false;
+ }
+
+ return $auth->validateAuth();
}
}
<dir name="Core">
<dir name="Auth">
<file name="Application.php" role="php" />
+ <file name="Ldap.php" role="php" />
+ <file name="Msad.php" role="php" />
+ <file name="Shibboleth.php" role="php" />
<dir name="Signup">
<file name="Base.php" role="php" />
<file name="Form.php" role="php" />
<file name="Autoloader.php" role="php" />
<dir name="Autoloader">
<dir name="Callback">
- <file name="Auth.php" role="php" />
<file name="Mime.php" role="php" />
</dir> <!-- /lib/Horde/Core/Autoloader/Callback -->
</dir> <!-- /lib/Horde/Core/Autoloader -->
<install name="lib/Horde/Config.php" as="Horde/Config.php" />
<install name="lib/Horde/Config/Form.php" as="Horde/Config/Form.php" />
<install name="lib/Horde/Core/Auth/Application.php" as="Horde/Core/Auth/Application.php" />
+ <install name="lib/Horde/Core/Auth/Ldap.php" as="Horde/Core/Auth/Ldap.php" />
+ <install name="lib/Horde/Core/Auth/Msad.php" as="Horde/Core/Auth/Msad.php" />
+ <install name="lib/Horde/Core/Auth/Shibboleth.php" as="Horde/Core/Auth/Shibboleth.php" />
<install name="lib/Horde/Core/Auth/Signup.php" as="Horde/Core/Auth/Signup.php" />
<install name="lib/Horde/Core/Auth/Signup/Base.php" as="Horde/Core/Auth/Signup/Base.php" />
<install name="lib/Horde/Core/Auth/Signup/Form.php" as="Horde/Core/Auth/Signup/Form.php" />
<install name="lib/Horde/Core/Auth/Signup/Sql.php" as="Horde/Core/Auth/Signup/Sql.php" />
<install name="lib/Horde/Core/Auth/Signup/SqlObject.php" as="Horde/Core/Auth/Signup/SqlObject.php" />
<install name="lib/Horde/Core/Autoloader.php" as="Horde/Core/Autoloader.php" />
- <install name="lib/Horde/Core/Autoloader/Callback/Auth.php" as="Horde/Core/Autoloader/Callback/Auth.php" />
<install name="lib/Horde/Core/Autoloader/Callback/Mime.php" as="Horde/Core/Autoloader/Callback/Mime.php" />
<install name="lib/Horde/Core/Binder/Alarm.php" as="Horde/Core/Binder/Alarm.php" />
<install name="lib/Horde/Core/Binder/Auth.php" as="Horde/Core/Binder/Auth.php" />
$credentials = array('password' => $secret->read($secret->getKey('gollem'), $GLOBALS['gollem_be']['params']['password']));
}
- $login = ($login && ($GLOBALS['registry']->getProvider() == 'gollem'));
+ //$login = ($login && ($GLOBALS['registry']->getProvider() == 'gollem'));
return parent::authenticate($userID, $credentials, $login);
}
--- /dev/null
+<?php
+/**
+ * Login task to output last login information.
+ *
+ * Copyright 2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file COPYING for license information (LGPL). If you
+ * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
+ *
+ * @author Michael Slusarz <slusarz@horde.org>
+ * @category Horde
+ * @license http://www.fsf.org/copyleft/lgpl.html LGPL
+ * @package Horde
+ */
+class Horde_LoginTasks_Task_LastLogin extends Horde_LoginTasks_Task
+{
+ /**
+ * The interval at which to run the task.
+ *
+ * @var integer
+ */
+ public $interval = Horde_LoginTasks::EVERY;
+
+ /**
+ * Display type.
+ *
+ * @var integer
+ */
+ public $display = Horde_LoginTasks::DISPLAY_NONE;
+
+ /**
+ * Perform all functions for this task.
+ */
+ public function execute()
+ {
+ /* Fetch the user's last login time. */
+ $old_login = @unserialize($GLOBALS['prefs']->getValue('last_login'));
+
+ /* Display it, if we have a notification object and the
+ * show_last_login preference is active. */
+ if (isset($GLOBALS['notification']) &&
+ $GLOBALS['prefs']->getValue('show_last_login')) {
+ if (empty($old_login['time'])) {
+ $GLOBALS['notification']->push(_("Last login: Never"), 'horde.message');
+ } elseif (empty($old_login['host'])) {
+ $GLOBALS['notification']->push(sprintf(_("Last login: %s"), strftime('%c', $old_login['time'])), 'horde.message');
+ } else {
+ $GLOBALS['notification']->push(sprintf(_("Last login: %s from %s"), strftime('%c', $old_login['time']), $old_login['host']), 'horde.message');
+ }
+ }
+
+ /* Set the user's last_login information. */
+ $host = empty($_SERVER['HTTP_X_FORWARDED_FOR'])
+ ? $_SERVER['REMOTE_ADDR']
+ : $_SERVER['HTTP_X_FORWARDED_FOR'];
+
+ if ($dns = $GLOBALS['injector']->getInstance('Net_DNS_Resolver')) {
+ $ptrdname = $host;
+ if ($response = $dns->query($host, 'PTR')) {
+ foreach ($response->answer as $val) {
+ if (isset($val->ptrdname)) {
+ $ptrdname = $val->ptrdname;
+ break;
+ }
+ }
+ }
+ } else {
+ $ptrdname = @gethostbyaddr($host);
+ }
+
+ $GLOBALS['prefs']->setValue('last_login', serialize(array(
+ 'host' => $ptrdname,
+ 'time' => time()
+ )));
+ }
+
+}
case Horde_Auth::REASON_SESSION:
return _("Your session has expired. Please login again.");
- case Horde_Auth::REASON_SESSIONIP:
+ case Horde_Core_Auth_Application::REASON_SESSIONIP:
return _("Your Internet Address has changed since the beginning of your session. To protect your security, you must login again.");
- case Horde_Auth::REASON_BROWSER:
+ case Horde_Core_Auth_Application::REASON_BROWSER:
return _("Your browser appears to have changed since the beginning of your session. To protect your security, you must login again.");
case Horde_Auth::REASON_LOGOUT:
}
/* Get an Auth object. */
-$auth = ($app && $is_auth)
- ? $injector->getInstance('Horde_Auth')->getAuth('application', array('app' => $app))
- : $injector->getInstance('Horde_Auth')->getAuth();
+$auth = $injector->getInstance('Horde_Auth')->getAuth(($is_auth && $vars->app) ? $vars->app : null);
/* Build the list of necessary login parameters. */
$loginparams = array(
{
if ($GLOBALS['registry']->getAuthCredential('password') == $old_password) {
$GLOBALS['registry']->setAuthCredential('password', $new_password);
- if ($GLOBALS['registry']->getProvider() == 'imp') {
- $_SESSION['imp']['pass'] = Secret::write(Secret::getKey('imp'),
- $new_password);
- }
}
}