* @inspiration Horde's Auth class * @version 1.0 */ class AuthFile { var $_params = array(); var $_users = array(); var $login_timeout = 21600; // 6 hours var $idle_timeout = 3600; // 1 hour /** * Constructs a new htpasswd authentication object. * * @access public * * @param optional array $params A hash containing parameters. */ function AuthFile($params = array()) { $this->_params = $params; setDefault($this->_params['htpasswd_file'], CODE_BASE . '/config/ht_auth'); setDefault($this->_params['encryption_type'], 'des'); if (!empty($this->_params['htpasswd_file'])) { if (false === ($users = @file($this->_params['htpasswd_file']))) { logMsg(sprintf(_("Could not read htpasswd file: %s"), $this->_params['htpasswd_file']), LOG_ERR, __FILE__, __LINE__); } if (is_array($users)) { foreach ($users as $line) { list($user, $pass) = explode(':', $line, 2); $this->_users[trim($user)] = trim($pass); } } } } /** * Find out if a set of login credentials are valid. Only supports * htpasswd files with DES passwords right now. * * @access private * * @param string $user_id The user_id to check. * @param array $password The password to compare to user_id. * * @return boolean Whether or not the credentials are valid. */ function authenticate($user_id, $password) { if (empty($password)) { logMsg(_("No password provided for htpasswd authentication."), LOG_NOTICE, __FILE__, __LINE__); return false; } if (empty($this->_users[$user_id])) { logMsg(_("User ID provided does not exist."), LOG_NOTICE, __FILE__, __LINE__); return false; } $hash = $this->_encrypt($password, $this->_salt($user_id)); if ($hash == $this->_users[$user_id]) { return true; } else { logMsg(_("Provided password hash does not match stored hash."), LOG_NOTICE, __FILE__, __LINE__); return false; } } /** * If user passes authentication create authenticated session. * * @access private * * @param string $user_id The user_id to check. * @param array $password The password to compare to user_id. * * @return boolean Whether or not the credentials are valid. */ function login($user_id, $password) { $user_id = trim($user_id); $this->clearAuth(); if ($this->authenticate($user_id, $password)) { $_SESSION['_auth'] = array( 'authenticated' => true, 'user_id' => $user_id, 'user_type' => 'admin', 'priv' => 'editor', 'login_datetime' => date('Y-m-d H:i:s'), 'last_access_datetime' => date('Y-m-d H:i:s'), 'remote_addr' => getRemoteAddr() ); return true; } return false; } /** * Clear any authentication tokens in the current session. A.K.A. logout. * * @access public */ function clearAuth() { $_SESSION['_auth'] = array(); $_SESSION['_auth']['authenticated'] = false; } /** * Test if user has a currently logged-in session. * - authentication flag set to true * - user_id not empty * - total logged-in time is not greater than login_timeout * - idle time is not greater than idle_timeout * - remote address is the same as the login remote address. * * @access public */ function isLoggedIn() { if (isset($_SESSION['_auth'])) { if (true === $_SESSION['_auth']['authenticated'] && !empty($_SESSION['_auth']['user_id']) && strtotime($_SESSION['_auth']['login_datetime']) > time() - $this->login_timeout && strtotime($_SESSION['_auth']['last_access_datetime']) > time() - $this->idle_timeout && $_SESSION['_auth']['remote_addr'] == getRemoteAddr() ) { $_SESSION['_auth']['last_access_datetime'] = date('Y-m-d H:i:s'); return true; } else if (true === $_SESSION['_auth']['authenticated']) { raiseMsg(_("Your session has closed. You need to log-in again."), MSG_NOTICE, __FILE__, __LINE__); $this->clearAuth(); } } return false; } /** * Test if user is of user_type 'admin'. * * @access public */ function isAdmin() { if ($_SESSION['_auth']['user_type'] == 'admin') { return true; } return false; } /** * Redirect user to login page if they are not logged in. * * @access public */ function requireAdminLogin() { if (!$this->isLoggedIn() || !$this->isAdmin()) { setBoomerangURL(absoluteMe()); dieURL("$CFG->admin_url/login.php"); } } /** * Hash a given password according to the configured encryption * type. * * @param string $password The password to encrypt. * @param string $salt The salt to use, if needed. * * @return string The hashed password. */ function _encrypt($password, $salt=null) { switch ($this->_params['encryption_type']) { case 'des' : if (isset($salt)) { return crypt($password, $salt); } else { return crypt($password); } break; default : logMsg('Encryption type not found.', LOG_ERR, __FILE__, __LINE__); } return false; } /** * Get a salt for $user_id, or generate a new one. * * @return string The salt. */ function _salt($user_id) { switch ($this->_params['encryption_type']) { case 'des': if (!empty($this->_users[$user_id])) { return substr($this->_users[$user_id], 0, 2); } break; default : logMsg('Encryption type not found.', LOG_ERR, __FILE__, __LINE__); } return ''; } } ?>