/** * Validate a password for this account * * Updated to use PHP 5.5's password_hash(), password_verify() and password_needs_rehash() functions * @since Version 3.8.7 * * @param string $password * * @return boolean */ public function validatePassword($password = false, $username = false) { Utility\PasswordUtility::validateParameters($password, $username, $this); /** * Create a temporary instance of the requested user for logging purposes */ try { $TmpUser = Factory::CreateUserFromUsername($username); } catch (Exception $e) { if ($e->getMessage() == "Could not find user ID from given username") { $TmpUser = new User($this->id); } } /** * Get the stored password for this username */ if ($username && !empty($username) && empty($this->username)) { $query = "SELECT user_id, user_password, user_password_bcrypt FROM nuke_users WHERE username = ?"; $row = $this->db->fetchRow($query, $username); $stored_user_id = $row['user_id']; $stored_pass = $row['user_password']; $stored_pass_bcrypt = $row['user_password_bcrypt']; } elseif (!empty($this->password)) { $stored_user_id = $this->id; $stored_pass = $this->password; $stored_pass_bcrypt = $this->password_bcrypt; } /** * Check if the invalid auth timeout is in effect */ if (isset($TmpUser->meta['InvalidAuthTimeout'])) { if ($TmpUser->meta['InvalidAuthTimeout'] <= time()) { unset($TmpUser->meta['InvalidAuthTimeout']); unset($TmpUser->meta['InvalidAuthCounter']); $TmpUser->commit(); $this->refresh(); } else { $TmpUser->addNote("Login attempt while InvalidAuthTimeout is in effect"); throw new Exception("You've attempted to log in with the wrong password too many times. We've temporarily disabled your account to protect it against hackers. Please try again soon. <a href='/account/resetpassword'>Can't remember your password?</a>"); } } /** * Verify the password */ if (Utility\PasswordUtility::validatePassword($password, $stored_pass, $stored_pass_bcrypt)) { $this->load($stored_user_id); /** * Check if the password needs rehashing */ if (password_needs_rehash($stored_pass, PASSWORD_DEFAULT) || password_needs_rehash($stored_pass_bcrypt, PASSWORD_DEFAULT)) { $this->setPassword($password); } /** * Reset the InvalidAuthCounter */ if (isset($this->meta['InvalidAuthCounter'])) { unset($this->meta['InvalidAuthCounter']); } if (isset($this->meta['InvalidAuthTimeout'])) { unset($this->meta['InvalidAuthTimeout']); } $this->commit(); return true; } /** * Unsuccessful login attempt - bump up the invalid auth counter */ $TmpUser->meta['InvalidAuthCounter'] = !isset($TmpUser->meta['InvalidAuthCounter']) ? 1 : $TmpUser->meta['InvalidAuthCounter']++; $TmpUser->addNote(sprintf("Invalid login attempt %d", $TmpUser->meta['InvalidAuthCounter'])); $TmpUser->commit(); $this->refresh(); if ($TmpUser->meta['InvalidAuthCounter'] === 3) { $TmpUser->meta['InvalidAuthTimeout'] = strtotime("+10 minutes"); $TmpUser->addNote("Too many invalid login attempts - account disabled for ten minutes"); $TmpUser->commit(); $this->refresh(); throw new Exception("You've attempted to log in with the wrong password too many times. As a result, we're disabling this account for the next ten minutes. <a href='/account/resetpassword'>Can't remember your password?</a>"); } $this->reset(); return false; }