diff --git a/core/core.services.yml b/core/core.services.yml index 2b240ee..796fdb7 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -663,10 +663,7 @@ services: # the speed and power of computers available to crack the hashes. password: class: Drupal\Core\Password\Password - arguments: [16, '@drupal7_password'] - drupal7_password: - class: Drupal\Core\Password\Drupal7Password - arguments: [16] + arguments: [10] accept_header_matcher: class: Drupal\Core\Routing\AcceptHeaderMatcher arguments: ['@content_negotiation'] diff --git a/core/lib/Drupal/Core/Password/Drupal7Password.php b/core/lib/Drupal/Core/Password/Drupal7Password.php index 5e46807..ba5e4cc 100644 --- a/core/lib/Drupal/Core/Password/Drupal7Password.php +++ b/core/lib/Drupal/Core/Password/Drupal7Password.php @@ -226,7 +226,34 @@ public function hash($password) { * {@inheritdoc} */ public function check($password, UserInterface $account) { - // Not used. + if (substr($account->getPassword(), 0, 2) == 'U$') { + // This may be an updated password from user_update_7000(). Such hashes + // have 'U' added as the first character and need an extra md5() (see the + // Drupal 7 documentation). + $stored_hash = substr($account->getPassword(), 1); + $password = md5($password); + } + else { + $stored_hash = $account->getPassword(); + } + + $type = substr($stored_hash, 0, 3); + switch ($type) { + case '$S$': + // A normal Drupal 7 password using sha512. + $hash = $this->crypt('sha512', $password, $stored_hash); + break; + case '$H$': + // phpBB3 uses "$H$" for the same thing as "$P$". + case '$P$': + // A phpass password generated using md5. This is an + // imported password or from an earlier Drupal version. + $hash = $this->crypt('md5', $password, $stored_hash); + break; + default: + return FALSE; + } + return ($hash && $stored_hash == $hash); } /** diff --git a/core/lib/Drupal/Core/Password/Password.php b/core/lib/Drupal/Core/Password/Password.php index 1be8d2b..86b6f46 100644 --- a/core/lib/Drupal/Core/Password/Password.php +++ b/core/lib/Drupal/Core/Password/Password.php @@ -12,8 +12,10 @@ /** * Secure password hashing functions based on PHP (>=5.5.0) password hashing * functions. + * + * @see http://php.net/manual/en/ref.password.php */ -class Password implements PasswordInterface { +class Password extends Drupal7Password { /** * The algorithmic cost that should be used. @@ -23,69 +25,52 @@ class Password implements PasswordInterface { protected $cost; /** - * The Drupal 7 password hashing service. - * - * @var \Drupal\Core\Password\PasswordInterface - */ - protected $drupal7Password; - - /** * Constructs a new password hashing instance. * * @param int $cost * The algorithmic cost that should be used. - * @param \Drupal\Core\Password\PasswordInterface - * The Drupal7 password hashing service. */ - function __construct($cost, PasswordInterface $drupal7_password) { + function __construct($cost) { + parent::__construct(16); $this->cost = $cost; - $this->drupal7Password = $drupal7_password; - - // Assure PHP 5.4 backward compatibility. - // @todo To be removed along with the 'ircmaxell/password-compat' library - // when Drupal will require PHP >= 5.5. - if (version_compare(PHP_VERSION, '5.5.0', '>=')) { - // @todo Is there a standard API to include such files? - require_once 'core/vendor/ircmaxell/password-compat/lib/password.php'; - } } /** * {@inheritdoc} */ public function hash($password) { - return password_hash($password, PASSWORD_DEFAULT, ['cost' => $this->cost]); + return password_hash($password, PASSWORD_DEFAULT, $this->getOptions()); } /** * {@inheritdoc} */ public function check($password, UserInterface $account) { - if (substr($account->getPassword(), 0, 2) == 'U$') { - // This may be an updated password from user_update_7000(). Such hashes - // have 'U' added as the first character and need an extra md5() (see the - // Drupal 7 documentation). - $stored_hash = substr($account->getPassword(), 1); - $password = md5($password); - } - elseif (substr($account->getPassword(), 0, 3) == 'D7$') { - $stored_hash = substr($account->getPassword(), 2); - $password = $this->drupal7Password->hash($password); - } - else { - $stored_hash = $account->getPassword(); + $info = password_get_info($account->getPassword()); + // If this the stored hash is not valid password_hash() hash, pass the check + // to Drupal 7 hash check. + if (!$info['algo']) { + return parent::check($password, $account); } - // Is this is a Drupal 8 password? - return password_verify($password, $stored_hash); + return password_verify($password, $account->getPassword()); } /** * {@inheritdoc} */ public function userNeedsNewHash(UserInterface $account) { - $info = password_get_info($account->getPassword()); - return (bool) $info['algo']; + return password_needs_rehash($account->getPassword(), PASSWORD_DEFAULT, $this->getOptions()); + } + + /** + * Returns password options. + * + * @return array + * Associative array with password options. + */ + protected function getOptions() { + return ['cost' => $this->cost]; } } diff --git a/core/modules/user/src/UserAuth.php b/core/modules/user/src/UserAuth.php index c1bf679..625b444 100644 --- a/core/modules/user/src/UserAuth.php +++ b/core/modules/user/src/UserAuth.php @@ -8,6 +8,7 @@ namespace Drupal\user; use Drupal\Core\Entity\EntityManagerInterface; +use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Password\PasswordInterface; /**