protected function __construct($scheme) { //handle some stuff that only needs to happen the first time we access this algorithm. // if (!self::$initialized) { //if password hash doesn't exists (php version 5.5 or lower) then include compatibility library if (!function_exists('password_hash')) { //library also does this check but will trigger an error instead of throwing an exception if (!function_exists('crypt')) { throw new vB_Utility_Password_Exception_SchemeNotSupported(); } //the library requires a security fix that was made in 5.3.7. Apparently there exist specific //distributions of prior versions that have the patched that fix, but the specific check for //fix is more involved and we need to keep people from causing themselves problems. if (version_compare(PHP_VERSION, '5.3.7', '<')) { throw new vB_Utility_Password_Exception_SchemeNotSupported(); } require_once DIR . '/libraries/password_compat/lib/password.php'; } self::$initialized = true; } //scheme specific init, need to do this every time because it could change. //this algorithm expects exactly one parameter $params = explode(':', $scheme); if (count($params) != 2) { throw new vB_Utility_Password_Exception_SchemeNotSupported(); } $this->cost = (int) $params[1]; parent::__construct($scheme); }
/** * Checks to see if a password is in the user's password history * * Will also delete any expired records in the password history. * * @param integer $userid User ID * @param string $fe_password -- the frontend encoded password * @param integer $lookback The time period to look back for passwords in seconds * * @return boolean Returns true if password is in the history */ protected function checkPasswordHistory($userid, $fe_password, $lookback) { $db = vB::getDBAssertor(); // first delete old password history $db->delete('passwordhistory', array('userid' => $userid, array('field' => 'passworddate', 'value' => $lookback, 'operator' => vB_dB_Query::OPERATOR_LTE))); $old_passwords = $db->select('passwordhistory', array('userid' => $userid)); foreach ($old_passwords as $old_password) { //need to use the same scheme as when the history hash was created. If the front end scheme has changed //then we'll be unable to check -- we'll just have to pass it along. When we implement front end schemes //other than plain md5 we'll need to do something here to check if its changed. try { $verify = vB_Utility_Password_Algorithm::instance($old_password['scheme'])->verifyPassword($fe_password, $old_password['token']); } catch (Exception $e) { //if we fail to hash the password we'll just ignore that history record. Better than failing because of an old //record that has a now invalid scheme or something else equally silly. continue; } if ($verify) { return false; } } return true; }