* @version 1.1 */ // Available encryption types for class Auth_SQL. define('AUTH_ENCRYPT_MD5', 'md5'); define('AUTH_ENCRYPT_CRYPT', 'crypt'); define('AUTH_ENCRYPT_SHA1', 'sha1'); define('AUTH_ENCRYPT_PLAINTEXT', 'plaintext'); class Auth_File { var $_params = array( 'encryption_type' => AUTH_ENCRYPT_CRYPT, 'htpasswd_file' => null, 'login_timeout' => 21600, // 6 hours. 'idle_timeout' => 3600, // 1 hour. 'login_url' => '/login.php', ); var $_users = array(); /** * Constructs a new htpasswd authentication object. * * @access public * * @param optional array $params A hash containing parameters. */ function Auth_File($params = array()) { $this->_params = array_merge($this->_params, $params); if (!empty($this->_params['htpasswd_file'])) { if (false === ($users = file($this->_params['htpasswd_file']))) { App::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); } } } } /** * Set the params of an auth object. * * @param array $params Array of parameter keys and value to set. * @return bool true on success, false on failure */ function setParam($params) { if (isset($params) && is_array($params)) { // Merge new parameters with old overriding only those passed. $this->_params = array_merge($this->_params, $params); } } /** * Return the value of a parameter, if it exists. * * @access public * @param string $param Which parameter to return. * @return mixed Configured parameter value. */ function getParam($param) { if (isset($this->_params[$param])) { return $this->_params[$param]; } else { App::logMsg(sprintf('Parameter is not set: %s', $param), LOG_DEBUG, __FILE__, __LINE__); return null; } } /** * Clear any authentication tokens in the current session. A.K.A. logout. * * @access public */ function clearAuth() { $_SESSION['_auth_file'] = array('authenticated' => false); } /** * Find out if a set of login credentials are valid. Only supports * htpasswd files with DES passwords right now. * * @access public * * @param string $username The username to check. * @param array $password The password to compare to username. * * @return boolean Whether or not the credentials are valid. */ function authenticate($username, $password) { if ('' == trim($password)) { App::logMsg(_("No password provided for htpasswd authentication."), LOG_INFO, __FILE__, __LINE__); return false; } if (!isset($this->_users[$username])) { App::logMsg(_("User ID provided does not exist."), LOG_INFO, __FILE__, __LINE__); return false; } if ($this->_encrypt($password, $this->_users[$username]) == $this->_users[$username]) { return true; } else { App::logMsg(sprintf('Authentication failed for user %s', $username), LOG_INFO, __FILE__, __LINE__); return false; } } /** * If user passes authentication create authenticated session. * * @access public * * @param string $username The username to check. * @param array $password The password to compare to username. * * @return boolean Whether or not the credentials are valid. */ function login($username, $password) { $username = strtolower(trim($username)); $this->clearAuth(); if ($this->authenticate($username, $password)) { $_SESSION['_auth_file'] = array( 'authenticated' => true, 'username' => $username, '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; } /** * Test if user has a currently logged-in session. * - authentication flag set to true * - username 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_file'])) { if (true === $_SESSION['_auth_file']['authenticated'] && !empty($_SESSION['_auth_file']['username']) && strtotime($_SESSION['_auth_file']['login_datetime']) > time() - $this->_params['login_timeout'] && strtotime($_SESSION['_auth_file']['last_access_datetime']) > time() - $this->_params['idle_timeout'] && $_SESSION['_auth_file']['remote_addr'] == getRemoteAddr() ) { $_SESSION['_auth_file']['last_access_datetime'] = date('Y-m-d H:i:s'); return true; } else if (true === $_SESSION['_auth_file']['authenticated']) { App::raiseMsg(_("Your session has closed. You need to log-in again."), MSG_NOTICE, __FILE__, __LINE__); $this->clearAuth(); return false; } } return false; } /** * Redirect user to login page if they are not logged in. * * @param string $message The text description of a message to raise. * @param int $type The type of message: MSG_NOTICE, * MSG_SUCCESS, MSG_WARNING, or MSG_ERR. * @param string $file __FILE__. * @param string $line __LINE__. * @access public */ function requireLogin($message='', $type=MSG_NOTICE, $file=null, $line=null) { if (!$this->isLoggedIn()) { // Display message for requiring login. App::raiseMsg($message, $type, $file, $line); // Login scripts must have the same 'login' tag for boomerangURL verification/manipulation. App::setBoomerangURL(absoluteMe(), 'login'); App::dieURL($this->_params['login_url']); } } /** * Hash a given password according to the configured encryption * type. * * @param string $password The password to encrypt. * @param string $encrypted_password The currently encrypted password to use as salt, if needed. * * @return string The hashed password. */ function _encrypt($password, $encrypted_password=null) { switch ($this->_params['encryption_type']) { case AUTH_ENCRYPT_PLAINTEXT : return $password; break; case AUTH_ENCRYPT_SHA1 : return sha1($password); break; case AUTH_ENCRYPT_MD5 : return md5($password); break; case AUTH_ENCRYPT_CRYPT : default : return crypt($password, $encrypted_password); break; } } } // end class ?>