/** * CheckPassword does all of the password checking and * returns a user record object, or false if it all ends in tears. */ function CheckPassword($username, $password) { $qry = new PgQuery("SELECT * FROM usr WHERE lower(username) = ? ", $username); if ($qry->Exec('BasicAuthSession', __LINE, __FILE__) && $qry->rows == 1) { $usr = $qry->Fetch(); dbg_error_log("BasicAuthSession", "Name:%s, Pass:%s, File:%s", $username, $password, $usr->password); if (session_validate_password($password, $usr->password)) { return $usr; } } return false; }
/** * Authenticate against a different PostgreSQL database which contains a usr table in * the AWL format. * * @package awl */ function auth_other_awl($username, $password) { global $c; $authconn = pg_Connect($c->authenticate_hook['config']['connection']); if (!$authconn) { echo <<<EOERRMSG <html><head><title>Database Connection Failure</title></head><body> <h1>Database Error</h1> <h3>Could not connect to PostgreSQL database</h3> </body> </html> EOERRMSG; exit(1); } if (isset($c->authenticate_hook['config']['columns'])) { $cols = $c->authenticate_hook['config']['columns']; } else { $cols = "*"; } if (isset($c->authenticate_hook['config']['where'])) { $andwhere = " AND " . $c->authenticate_hook['config']['where']; } else { $andwhere = ""; } $qry = new AwlQuery("SELECT {$cols} FROM usr WHERE lower(username) = ? {$andwhere}", strtolower($username)); $qry->SetConnection($authconn); if ($qry->Exec('Login', __LINE, __FILE__) && $qry->rows() == 1) { $usr = $qry->Fetch(); if (session_validate_password($password, $usr->password)) { $qry = new AwlQuery("SELECT * FROM usr WHERE user_no = {$usr->user_no};"); if ($qry->Exec('Login', __LINE, __FILE__) && $qry->rows() == 1) { $type = "UPDATE"; } else { $type = "INSERT"; } $qry = new AwlQuery(sql_from_object($usr, $type, 'usr', "WHERE user_no={$usr->user_no}")); $qry->Exec('Login', __LINE, __FILE__); /** * We disallow login by inactive users _after_ we have updated the local copy */ if (isset($usr->active) && $usr->active == 'f') { return false; } return $usr; } } return false; }
/** * Authenticate against a different PostgreSQL database which contains a usr table in * the AWL format. * * Use this as in the following example config snippet: * * require_once('auth-functions.php'); * $c->authenticate_hook = array( * 'call' => 'AuthExternalAwl', * 'config' => array( * // A PgSQL database connection string for the database containing user records * 'connection[]' => 'dbname=wrms host=otherhost port=5433 user=general', * // Which columns should be fetched from the database * 'columns' => "user_no, active, email_ok, joined, last_update AS updated, last_used, username, password, fullname, email", * // a WHERE clause to limit the records returned. * 'where' => "active AND org_code=7" * ) * ); * */ function AuthExternalAWL($username, $password) { global $c; $persistent = isset($c->authenticate_hook['config']['use_persistent']) && $c->authenticate_hook['config']['use_persistent']; if (isset($c->authenticate_hook['config']['columns'])) { $cols = $c->authenticate_hook['config']['columns']; } else { $cols = '*'; } if (isset($c->authenticate_hook['config']['where'])) { $andwhere = ' AND ' . $c->authenticate_hook['config']['where']; } else { $andwhere = ''; } $qry = new AwlQuery('SELECT ' . $cols . ' FROM usr WHERE lower(username) = :username ' . $andwhere, array(':username' => strtolower($username))); $authconn = $qry->SetConnection($c->authenticate_hook['config']['connection'], $persistent ? array(PDO::ATTR_PERSISTENT => true) : null); if (!$authconn) { echo <<<EOERRMSG <html><head><title>Database Connection Failure</title></head><body> <h1>Database Error</h1> <h3>Could not connect to PostgreSQL database</h3> </body> </html> EOERRMSG; exit(1); } if ($qry->Exec('Login', __LINE__, __FILE__) && $qry->rows() == 1) { $usr = $qry->Fetch(); if (session_validate_password($password, $usr->password)) { UpdateUserFromExternal($usr); /** * We disallow login by inactive users _after_ we have updated the local copy */ if (isset($usr->active) && $usr->active == 'f') { return false; } $qry = new AwlQuery('SELECT * FROM dav_principal WHERE username = :username', array(':username' => $usr->username)); if ($qry->Exec() && $qry->rows() == 1) { $principal = $qry->Fetch(); return $principal; } return $usr; // Somewhat optimistically } } return false; }
/** * CheckPassword does all of the password checking and * returns a user record object, or false if it all ends in tears. */ function CheckPassword($username, $password) { global $c; if (isset($c->authenticate_hook) && isset($c->authenticate_hook['call']) && function_exists($c->authenticate_hook['call'])) { /** * The authenticate hook needs to: * - Accept a username / password * - Confirm the username / password are correct * - Create (or update) a 'usr' record in our database * - Return the 'usr' record as an object * - Return === false when authentication fails * * It can expect that: * - Configuration data will be in $c->authenticate_hook['config'], which might be an array, or whatever is needed. */ $hook_response = call_user_func($c->authenticate_hook['call'], $username, $password); /** * make the authentication hook optional: if the flag is set, ignore a return value of 'false' */ if (isset($c->authenticate_hook['optional']) && $c->authenticate_hook['optional']) { if ($hook_response !== false) { return $hook_response; } } else { return $hook_response; } } if ($usr = getUserByName($username)) { dbg_error_log("BasicAuth", ":CheckPassword: Name:%s, Pass:%s, File:%s, Active:%s", $username, $password, $usr->password, $usr->active ? 'Yes' : 'No'); if ($usr->active && session_validate_password($password, $usr->password)) { return $usr; } } return false; }
/** * CheckPassword does all of the password checking and * returns a user record object, or false if it all ends in tears. */ function CheckPassword($username, $password) { global $c; if (isset($c->login_append_domain_if_missing) && $c->login_append_domain_if_missing && !preg_match('/@/', $username)) { $username .= '@' . $c->domain_name; } if (!isset($c->authenticate_hook) || !isset($c->authenticate_hook['call']) || !function_exists($c->authenticate_hook['call']) || isset($c->authenticate_hook['optional']) && $c->authenticate_hook['optional']) { if ($principal = new Principal('username', $username)) { if (isset($c->dbg['password'])) { dbg_error_log("password", ":CheckPassword: Name:%s, Pass:%s, File:%s, Active:%s", $username, $password, $principal->password, $principal->user_active ? 'Yes' : 'No'); } if ($principal->user_active && session_validate_password($password, $principal->password)) { return $principal; } } } if (isset($c->authenticate_hook) && isset($c->authenticate_hook['call']) && function_exists($c->authenticate_hook['call'])) { /** * The authenticate hook needs to: * - Accept a username / password * - Confirm the username / password are correct * - Create (or update) a 'usr' record in our database * - Return the 'usr' record as an object * - Return === false when authentication fails * * It can expect that: * - Configuration data will be in $c->authenticate_hook['config'], which might be an array, or whatever is needed. */ $principal = call_user_func($c->authenticate_hook['call'], $username, $password); if ($principal !== false && !$principal instanceof Principal) { $principal = new Principal('username', $username); } return $principal; } return false; }
/** * Attempt to perform a login action. * * This will validate the user's username and password. If they are OK then a new * session id will be created and the user will be cookied with it for subsequent * pages. A logged in session will be created, and the $_POST array will be cleared * of the username, password and submit values. submit will also be cleared from * $_GET and $GLOBALS, just in case. * * @param string $username The user's login name, or at least what they entered it as. * @param string $password The user's password, or at least what they entered it as. * @param string $authenticated If true, then authentication has already happened and the password is not checked, though the user must still exist. * @return boolean Whether or not the user correctly guessed a temporary password within the necessary window of opportunity. */ function Login($username, $password, $authenticated = false) { global $c; $rc = false; dbg_error_log("Login", " Login: Attempting login for {$username}"); if (isset($usr)) { unset($usr); } /** In case someone is running with register_globals on */ /** * @todo In here we will need to put code to call the auth plugin, in order to * ensure the 'usr' table has current valid data. At this stage we are just * thinking it through... like ... * */ if (!$authenticated && isset($c->authenticate_hook) && isset($c->authenticate_hook['call']) && function_exists($c->authenticate_hook['call'])) { /** * The authenticate hook needs to: * - Accept a username / password * - Confirm the username / password are correct * - Create (or update) a 'usr' record in our database * - Return the 'usr' record as an object * - Return === false when authentication fails * It can expect that: * - Configuration data will be in $c->authenticate_hook['config'], which might be an array, or whatever is needed. */ $usr = call_user_func($c->authenticate_hook['call'], $username, $password); if ($usr === false) { unset($usr); } else { $authenticated = true; } } $sql = "SELECT * FROM usr WHERE lower(username) = ? AND active"; $qry = new AwlQuery($sql, strtolower($username)); if (isset($usr) || $qry->Exec('Login', __LINE__, __FILE__) && $qry->rows() == 1 && ($usr = $qry->Fetch())) { if ($authenticated || session_validate_password($password, $usr->password) || check_temporary_passwords($password, $usr->user_no)) { // Now get the next session ID to create one from... $qry = new AwlQuery("SELECT nextval('session_session_id_seq')"); if ($qry->Exec('Login') && $qry->rows() == 1) { $seq = $qry->Fetch(); $session_id = $seq->nextval; $session_key = md5(rand(1010101, 1999999999) . microtime()); // just some random s***e dbg_error_log("Login", " Login: Valid username/password for {$username} ({$usr->user_no})"); // Set the last_used timestamp to match the previous login. $qry = new AwlQuery('UPDATE usr SET last_used = (SELECT session_start FROM session WHERE session.user_no = ? ORDER BY session_id DESC LIMIT 1) WHERE user_no = ?;', $usr->user_no, $usr->user_no); $qry->Exec('Session'); // And create a session $sql = "INSERT INTO session (session_id, user_no, session_key) VALUES( ?, ?, ? )"; $qry = new AwlQuery($sql, $session_id, $usr->user_no, $session_key); if ($qry->Exec('Login')) { // Assign our session ID variable $sid = "{$session_id};{$session_key}"; // Create a cookie for the sesssion setcookie('sid', $sid, 0, '/'); // Recognise that we have started a session now too... $this->Session($sid); dbg_error_log("Login", " Login: New session {$session_id} started for {$username} ({$usr->user_no})"); if (isset($_POST['remember']) && intval($_POST['remember']) > 0) { $cookie = md5($usr->user_no) . ";"; $cookie .= session_salted_md5($usr->user_no . $usr->username . $usr->password); $GLOBALS['lsid'] = $cookie; setcookie("lsid", $cookie, time() + 86400 * 3600, "/"); // will expire in ten or so years } $this->just_logged_in = true; // Unset all of the submitted values, so we don't accidentally submit an unexpected form. unset($_POST['username']); unset($_POST['password']); unset($_POST['submit']); unset($_GET['submit']); unset($GLOBALS['submit']); if (function_exists('local_session_sql')) { $sql = local_session_sql(); } else { $sql = "SELECT session.*, usr.* FROM session JOIN usr USING ( user_no )"; } $sql .= " WHERE session.session_id = ? AND (md5(session.session_start::text) = ? OR session.session_key = ?) ORDER BY session.session_start DESC LIMIT 2"; $qry = new AwlQuery($sql, $session_id, $session_key, $session_key); if ($qry->Exec('Session') && 1 == $qry->rows()) { $this->AssignSessionDetails($qry->Fetch()); } $rc = true; return $rc; } // else ... $this->cause = 'ERR: Could not create new session.'; } else { $this->cause = 'ERR: Could not increment session sequence.'; } } else { $c->messages[] = i18n('Invalid username or password.'); if (isset($c->dbg['Login']) || isset($c->dbg['ALL'])) { $this->cause = 'WARN: Invalid password.'; } else { $this->cause = 'WARN: Invalid username or password.'; } } } else { $c->messages[] = i18n('Invalid username or password.'); if (isset($c->dbg['Login']) || isset($c->dbg['ALL'])) { $this->cause = 'WARN: Invalid username.'; } else { $this->cause = 'WARN: Invalid username or password.'; } } $this->Log("Login failure: {$this->cause}"); $this->login_failed = true; $rc = false; return $rc; }