mirror of
git://develop.git.wordpress.org/
synced 2025-04-19 19:51:54 +02:00
Application Passwords: Correct the fallback behaviour for application passwords that don't use a generic hash.
Application passwords that aren't hashed using BLAKE2b should be checked using wp_check_password() rather than assuming they were hashed with phpass. This provides full back compat support for application passwords that were created via an overridden wp_hash_password() function that uses an alternative hashing algorithm. Reviewed by audrasjb. Merges [60123] into the 6.8 branch. Props snicco, debarghyabanerjee, peterwilsoncc, jorbin, johnbillion. Fixes #63203 git-svn-id: https://develop.svn.wordpress.org/branches/6.8@60125 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
parent
295bfbad4e
commit
0c56b81904
@ -502,6 +502,14 @@ class WP_Application_Passwords {
|
||||
string $password,
|
||||
string $hash
|
||||
): bool {
|
||||
if ( ! str_starts_with( $hash, '$generic$' ) ) {
|
||||
/*
|
||||
* If the hash doesn't start with `$generic$`, it is a hash created with `wp_hash_password()`.
|
||||
* This is the case for application passwords created before 6.8.0.
|
||||
*/
|
||||
return wp_check_password( $password, $hash );
|
||||
}
|
||||
|
||||
return wp_verify_fast_hash( $password, $hash );
|
||||
}
|
||||
}
|
||||
|
@ -9150,8 +9150,8 @@ function wp_fast_hash(
|
||||
* Checks whether a plaintext message matches the hashed value. Used to verify values hashed via wp_fast_hash().
|
||||
*
|
||||
* The function uses Sodium to hash the message and compare it to the hashed value. If the hash is not a generic hash,
|
||||
* the hash is treated as a phpass portable hash in order to provide backward compatibility for application passwords
|
||||
* which were hashed using phpass prior to WordPress 6.8.0.
|
||||
* the hash is treated as a phpass portable hash in order to provide backward compatibility for passwords and security
|
||||
* keys which were hashed using phpass prior to WordPress 6.8.0.
|
||||
*
|
||||
* @since 6.8.0
|
||||
*
|
||||
|
@ -1134,6 +1134,29 @@ class Tests_Auth extends WP_UnitTestCase {
|
||||
$this->assertSame( self::$user_id, $user->ID );
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 21022
|
||||
* @ticket 63203
|
||||
*/
|
||||
public function test_plain_bcrypt_application_password_is_accepted() {
|
||||
add_filter( 'application_password_is_api_request', '__return_true' );
|
||||
add_filter( 'wp_is_application_passwords_available', '__return_true' );
|
||||
|
||||
$password = 'password';
|
||||
|
||||
// Set an application password with plain bcrypt, which mimics a password that was hashed with
|
||||
// a custom `wp_hash_password()` in use.
|
||||
$uuid = self::set_application_password_with_plain_bcrypt( $password, self::$user_id );
|
||||
|
||||
// Authenticate.
|
||||
$user = wp_authenticate_application_password( null, self::USER_LOGIN, $password );
|
||||
|
||||
// Verify that the plain bcrypt hash for the application password was valid.
|
||||
$this->assertNotWPError( $user );
|
||||
$this->assertInstanceOf( 'WP_User', $user );
|
||||
$this->assertSame( self::$user_id, $user->ID );
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider data_usernames
|
||||
*
|
||||
@ -1591,6 +1614,19 @@ class Tests_Auth extends WP_UnitTestCase {
|
||||
$this->assertSame( $item['uuid'], rest_get_authenticated_app_password() );
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 21022
|
||||
* @ticket 63203
|
||||
*
|
||||
* @covers WP_Application_Passwords::create_new_application_password
|
||||
*/
|
||||
public function test_application_password_is_hashed_with_fast_hash() {
|
||||
// Create a new app-only password.
|
||||
list( , $item ) = WP_Application_Passwords::create_new_application_password( self::$user_id, array( 'name' => 'phpunit' ) );
|
||||
|
||||
$this->assertStringStartsWith( '$generic$', $item['password'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* @ticket 42790
|
||||
*/
|
||||
@ -1963,6 +1999,37 @@ class Tests_Auth extends WP_UnitTestCase {
|
||||
clean_user_cache( $user_id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the tests
|
||||
*
|
||||
* @covers Tests_Auth::set_application_password_with_plain_bcrypt
|
||||
*
|
||||
* @ticket 21022
|
||||
* @ticket 63203
|
||||
*/
|
||||
public function test_set_application_password_with_plain_bcrypt() {
|
||||
// Set an application password with the plain_bcrypt algorithm.
|
||||
$uuid = self::set_application_password_with_plain_bcrypt( 'password', self::$user_id );
|
||||
|
||||
// Ensure the password is hashed with plain_bcrypt.
|
||||
$hash = WP_Application_Passwords::get_user_application_password( self::$user_id, $uuid )['password'];
|
||||
$this->assertStringStartsWith( '$2y$', $hash );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an application password that is hashed using bcrypt instead of the generic algorithm.
|
||||
*
|
||||
* This is ultimately used to mimic a plugged version of `wp_hash_password()` that uses bcrypt and
|
||||
* facilitate backwards compatibility testing.
|
||||
*
|
||||
* @param string $password The password to hash.
|
||||
* @param int $user_id The user ID to associate the password with.
|
||||
* @return string The UUID of the application password.
|
||||
*/
|
||||
private static function set_application_password_with_plain_bcrypt( string $password, int $user_id ) {
|
||||
return self::set_application_password( password_hash( $password, PASSWORD_BCRYPT ), $user_id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the tests
|
||||
*
|
||||
@ -1979,13 +2046,33 @@ class Tests_Auth extends WP_UnitTestCase {
|
||||
$this->assertStringStartsWith( '$P$', $hash );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an application password that is hashed using a phpass portable hash instead of the generic algorithm.
|
||||
*
|
||||
* This facilitate backwards compatibility testing.
|
||||
*
|
||||
* @param string $password The password to hash.
|
||||
* @param int $user_id The user ID to associate the password with.
|
||||
* @return string The UUID of the application password.
|
||||
*/
|
||||
private static function set_application_password_with_phpass( string $password, int $user_id ) {
|
||||
return self::set_application_password( self::$wp_hasher->HashPassword( $password ), $user_id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an application password using the given password hash.
|
||||
*
|
||||
* @param string $hash The password hash.
|
||||
* @param int $user_id The user ID to associate the password with.
|
||||
* @return string The UUID of the application password.
|
||||
*/
|
||||
private static function set_application_password( string $hash, int $user_id ) {
|
||||
$uuid = wp_generate_uuid4();
|
||||
$item = array(
|
||||
'uuid' => $uuid,
|
||||
'app_id' => '',
|
||||
'name' => 'Test',
|
||||
'password' => self::$wp_hasher->HashPassword( $password ),
|
||||
'password' => $hash,
|
||||
'created' => time(),
|
||||
'last_used' => null,
|
||||
'last_ip' => null,
|
||||
|
Loading…
x
Reference in New Issue
Block a user