wp/wp-includes/class-wp-application-passwords.php
changeset 22 8c2e4d02f4ef
parent 21 48c4eec2b7e6
equal deleted inserted replaced
21:48c4eec2b7e6 22:8c2e4d02f4ef
    58 	/**
    58 	/**
    59 	 * Creates a new application password.
    59 	 * Creates a new application password.
    60 	 *
    60 	 *
    61 	 * @since 5.6.0
    61 	 * @since 5.6.0
    62 	 * @since 5.7.0 Returns WP_Error if application name already exists.
    62 	 * @since 5.7.0 Returns WP_Error if application name already exists.
       
    63 	 * @since 6.8.0 The hashed password value now uses wp_fast_hash() instead of phpass.
    63 	 *
    64 	 *
    64 	 * @param int   $user_id  User ID.
    65 	 * @param int   $user_id  User ID.
    65 	 * @param array $args     {
    66 	 * @param array $args     {
    66 	 *     Arguments used to create the application password.
    67 	 *     Arguments used to create the application password.
    67 	 *
    68 	 *
    69 	 *     @type string $app_id A UUID provided by the application to uniquely identify it.
    70 	 *     @type string $app_id A UUID provided by the application to uniquely identify it.
    70 	 * }
    71 	 * }
    71 	 * @return array|WP_Error {
    72 	 * @return array|WP_Error {
    72 	 *     Application password details, or a WP_Error instance if an error occurs.
    73 	 *     Application password details, or a WP_Error instance if an error occurs.
    73 	 *
    74 	 *
    74 	 *     @type string $0 The unhashed generated application password.
    75 	 *     @type string $0 The generated application password in plain text.
    75 	 *     @type array  $1 {
    76 	 *     @type array  $1 {
    76 	 *         The details about the created password.
    77 	 *         The details about the created password.
    77 	 *
    78 	 *
    78 	 *         @type string $uuid      The unique identifier for the application password.
    79 	 *         @type string $uuid      The unique identifier for the application password.
    79 	 *         @type string $app_id    A UUID provided by the application to uniquely identify it.
    80 	 *         @type string $app_id    A UUID provided by the application to uniquely identify it.
    92 
    93 
    93 		if ( empty( $args['name'] ) ) {
    94 		if ( empty( $args['name'] ) ) {
    94 			return new WP_Error( 'application_password_empty_name', __( 'An application name is required to create an application password.' ), array( 'status' => 400 ) );
    95 			return new WP_Error( 'application_password_empty_name', __( 'An application name is required to create an application password.' ), array( 'status' => 400 ) );
    95 		}
    96 		}
    96 
    97 
    97 		if ( self::application_name_exists_for_user( $user_id, $args['name'] ) ) {
       
    98 			return new WP_Error( 'application_password_duplicate_name', __( 'Each application name should be unique.' ), array( 'status' => 409 ) );
       
    99 		}
       
   100 
       
   101 		$new_password    = wp_generate_password( static::PW_LENGTH, false );
    98 		$new_password    = wp_generate_password( static::PW_LENGTH, false );
   102 		$hashed_password = wp_hash_password( $new_password );
    99 		$hashed_password = self::hash_password( $new_password );
   103 
   100 
   104 		$new_item = array(
   101 		$new_item = array(
   105 			'uuid'      => wp_generate_uuid4(),
   102 			'uuid'      => wp_generate_uuid4(),
   106 			'app_id'    => empty( $args['app_id'] ) ? '' : $args['app_id'],
   103 			'app_id'    => empty( $args['app_id'] ) ? '' : $args['app_id'],
   107 			'name'      => $args['name'],
   104 			'name'      => $args['name'],
   126 
   123 
   127 		/**
   124 		/**
   128 		 * Fires when an application password is created.
   125 		 * Fires when an application password is created.
   129 		 *
   126 		 *
   130 		 * @since 5.6.0
   127 		 * @since 5.6.0
       
   128 		 * @since 6.8.0 The hashed password value now uses wp_fast_hash() instead of phpass.
   131 		 *
   129 		 *
   132 		 * @param int    $user_id      The user ID.
   130 		 * @param int    $user_id      The user ID.
   133 		 * @param array  $new_item     {
   131 		 * @param array  $new_item     {
   134 		 *     The details about the created password.
   132 		 *     The details about the created password.
   135 		 *
   133 		 *
   139 		 *     @type string $password  A one-way hash of the password.
   137 		 *     @type string $password  A one-way hash of the password.
   140 		 *     @type int    $created   Unix timestamp of when the password was created.
   138 		 *     @type int    $created   Unix timestamp of when the password was created.
   141 		 *     @type null   $last_used Null.
   139 		 *     @type null   $last_used Null.
   142 		 *     @type null   $last_ip   Null.
   140 		 *     @type null   $last_ip   Null.
   143 		 * }
   141 		 * }
   144 		 * @param string $new_password The unhashed generated application password.
   142 		 * @param string $new_password The generated application password in plain text.
   145 		 * @param array  $args         {
   143 		 * @param array  $args         {
   146 		 *     Arguments used to create the application password.
   144 		 *     Arguments used to create the application password.
   147 		 *
   145 		 *
   148 		 *     @type string $name   The name of the application password.
   146 		 *     @type string $name   The name of the application password.
   149 		 *     @type string $app_id A UUID provided by the application to uniquely identify it.
   147 		 *     @type string $app_id A UUID provided by the application to uniquely identify it.
   159 	 *
   157 	 *
   160 	 * @since 5.6.0
   158 	 * @since 5.6.0
   161 	 *
   159 	 *
   162 	 * @param int $user_id User ID.
   160 	 * @param int $user_id User ID.
   163 	 * @return array {
   161 	 * @return array {
   164 	 *     The list of app passwords.
   162 	 *     The list of application passwords.
   165 	 *
   163 	 *
   166 	 *     @type array ...$0 {
   164 	 *     @type array ...$0 {
   167 	 *         @type string      $uuid      The unique identifier for the application password.
   165 	 *         @type string      $uuid      The unique identifier for the application password.
   168 	 *         @type string      $app_id    A UUID provided by the application to uniquely identify it.
   166 	 *         @type string      $app_id    A UUID provided by the application to uniquely identify it.
   169 	 *         @type string      $name      The name of the application password.
   167 	 *         @type string      $name      The name of the application password.
   202 	 *
   200 	 *
   203 	 * @since 5.6.0
   201 	 * @since 5.6.0
   204 	 *
   202 	 *
   205 	 * @param int    $user_id User ID.
   203 	 * @param int    $user_id User ID.
   206 	 * @param string $uuid    The password's UUID.
   204 	 * @param string $uuid    The password's UUID.
   207 	 * @return array|null The application password if found, null otherwise.
   205 	 * @return array|null {
       
   206 	 *     The application password if found, null otherwise.
       
   207 	 *
       
   208 	 *     @type string      $uuid      The unique identifier for the application password.
       
   209 	 *     @type string      $app_id    A UUID provided by the application to uniquely identify it.
       
   210 	 *     @type string      $name      The name of the application password.
       
   211 	 *     @type string      $password  A one-way hash of the password.
       
   212 	 *     @type int         $created   Unix timestamp of when the password was created.
       
   213 	 *     @type int|null    $last_used The Unix timestamp of the GMT date the application password was last used.
       
   214 	 *     @type string|null $last_ip   The IP address the application password was last used by.
       
   215 	 * }
   208 	 */
   216 	 */
   209 	public static function get_user_application_password( $user_id, $uuid ) {
   217 	public static function get_user_application_password( $user_id, $uuid ) {
   210 		$passwords = static::get_user_application_passwords( $user_id );
   218 		$passwords = static::get_user_application_passwords( $user_id );
   211 
   219 
   212 		foreach ( $passwords as $password ) {
   220 		foreach ( $passwords as $password ) {
   241 
   249 
   242 	/**
   250 	/**
   243 	 * Updates an application password.
   251 	 * Updates an application password.
   244 	 *
   252 	 *
   245 	 * @since 5.6.0
   253 	 * @since 5.6.0
       
   254 	 * @since 6.8.0 The actual password should now be hashed using wp_fast_hash().
   246 	 *
   255 	 *
   247 	 * @param int    $user_id User ID.
   256 	 * @param int    $user_id User ID.
   248 	 * @param string $uuid    The password's UUID.
   257 	 * @param string $uuid    The password's UUID.
   249 	 * @param array  $update  Information about the application password to update.
   258 	 * @param array  $update  {
       
   259 	 *     Information about the application password to update.
       
   260 	 *
       
   261 	 *     @type string      $uuid      The unique identifier for the application password.
       
   262 	 *     @type string      $app_id    A UUID provided by the application to uniquely identify it.
       
   263 	 *     @type string      $name      The name of the application password.
       
   264 	 *     @type string      $password  A one-way hash of the password.
       
   265 	 *     @type int         $created   Unix timestamp of when the password was created.
       
   266 	 *     @type int|null    $last_used The Unix timestamp of the GMT date the application password was last used.
       
   267 	 *     @type string|null $last_ip   The IP address the application password was last used by.
       
   268 	 * }
   250 	 * @return true|WP_Error True if successful, otherwise a WP_Error instance is returned on error.
   269 	 * @return true|WP_Error True if successful, otherwise a WP_Error instance is returned on error.
   251 	 */
   270 	 */
   252 	public static function update_application_password( $user_id, $uuid, $update = array() ) {
   271 	public static function update_application_password( $user_id, $uuid, $update = array() ) {
   253 		$passwords = static::get_user_application_passwords( $user_id );
   272 		$passwords = static::get_user_application_passwords( $user_id );
   254 
   273 
   278 
   297 
   279 			/**
   298 			/**
   280 			 * Fires when an application password is updated.
   299 			 * Fires when an application password is updated.
   281 			 *
   300 			 *
   282 			 * @since 5.6.0
   301 			 * @since 5.6.0
       
   302 			 * @since 6.8.0 The password is now hashed using wp_fast_hash() instead of phpass.
       
   303 			 *              Existing passwords may still be hashed using phpass.
   283 			 *
   304 			 *
   284 			 * @param int   $user_id The user ID.
   305 			 * @param int   $user_id The user ID.
   285 			 * @param array $item    The updated app password details.
   306 			 * @param array $item    {
       
   307 			 *     The updated application password details.
       
   308 			 *
       
   309 			 *     @type string      $uuid      The unique identifier for the application password.
       
   310 			 *     @type string      $app_id    A UUID provided by the application to uniquely identify it.
       
   311 			 *     @type string      $name      The name of the application password.
       
   312 			 *     @type string      $password  A one-way hash of the password.
       
   313 			 *     @type int         $created   Unix timestamp of when the password was created.
       
   314 			 *     @type int|null    $last_used The Unix timestamp of the GMT date the application password was last used.
       
   315 			 *     @type string|null $last_ip   The IP address the application password was last used by.
       
   316 			 * }
   286 			 * @param array $update  The information to update.
   317 			 * @param array $update  The information to update.
   287 			 */
   318 			 */
   288 			do_action( 'wp_update_application_password', $user_id, $item, $update );
   319 			do_action( 'wp_update_application_password', $user_id, $item, $update );
   289 
   320 
   290 			return true;
   321 			return true;
   402 	 * Sets a user's application passwords.
   433 	 * Sets a user's application passwords.
   403 	 *
   434 	 *
   404 	 * @since 5.6.0
   435 	 * @since 5.6.0
   405 	 *
   436 	 *
   406 	 * @param int   $user_id   User ID.
   437 	 * @param int   $user_id   User ID.
   407 	 * @param array $passwords Application passwords.
   438 	 * @param array $passwords {
   408 	 *
   439 	 *     The list of application passwords.
   409 	 * @return bool
   440 	 *
       
   441 	 *     @type array ...$0 {
       
   442 	 *         @type string      $uuid      The unique identifier for the application password.
       
   443 	 *         @type string      $app_id    A UUID provided by the application to uniquely identify it.
       
   444 	 *         @type string      $name      The name of the application password.
       
   445 	 *         @type string      $password  A one-way hash of the password.
       
   446 	 *         @type int         $created   Unix timestamp of when the password was created.
       
   447 	 *         @type int|null    $last_used The Unix timestamp of the GMT date the application password was last used.
       
   448 	 *         @type string|null $last_ip   The IP address the application password was last used by.
       
   449 	 *     }
       
   450 	 * }
       
   451 	 * @return int|bool User meta ID if the key didn't exist (ie. this is the first time that an application password
       
   452 	 *                  has been saved for the user), true on successful update, false on failure or if the value passed
       
   453 	 *                  is the same as the one that is already in the database.
   410 	 */
   454 	 */
   411 	protected static function set_user_application_passwords( $user_id, $passwords ) {
   455 	protected static function set_user_application_passwords( $user_id, $passwords ) {
   412 		return update_user_meta( $user_id, static::USERMETA_KEY_APPLICATION_PASSWORDS, $passwords );
   456 		return update_user_meta( $user_id, static::USERMETA_KEY_APPLICATION_PASSWORDS, $passwords );
   413 	}
   457 	}
   414 
   458 
   418 	 * @since 5.6.0
   462 	 * @since 5.6.0
   419 	 *
   463 	 *
   420 	 * @param string $raw_password The raw application password.
   464 	 * @param string $raw_password The raw application password.
   421 	 * @return string The chunked password.
   465 	 * @return string The chunked password.
   422 	 */
   466 	 */
   423 	public static function chunk_password( $raw_password ) {
   467 	public static function chunk_password(
       
   468 		#[\SensitiveParameter]
       
   469 		$raw_password
       
   470 	) {
   424 		$raw_password = preg_replace( '/[^a-z\d]/i', '', $raw_password );
   471 		$raw_password = preg_replace( '/[^a-z\d]/i', '', $raw_password );
   425 
   472 
   426 		return trim( chunk_split( $raw_password, 4, ' ' ) );
   473 		return trim( chunk_split( $raw_password, 4, ' ' ) );
   427 	}
   474 	}
       
   475 
       
   476 	/**
       
   477 	 * Hashes a plaintext application password.
       
   478 	 *
       
   479 	 * @since 6.8.0
       
   480 	 *
       
   481 	 * @param string $password Plaintext password.
       
   482 	 * @return string Hashed password.
       
   483 	 */
       
   484 	public static function hash_password(
       
   485 		#[\SensitiveParameter]
       
   486 		string $password
       
   487 	): string {
       
   488 		return wp_fast_hash( $password );
       
   489 	}
       
   490 
       
   491 	/**
       
   492 	 * Checks a plaintext application password against a hashed password.
       
   493 	 *
       
   494 	 * @since 6.8.0
       
   495 	 *
       
   496 	 * @param string $password Plaintext password.
       
   497 	 * @param string $hash     Hash of the password to check against.
       
   498 	 * @return bool Whether the password matches the hashed password.
       
   499 	 */
       
   500 	public static function check_password(
       
   501 		#[\SensitiveParameter]
       
   502 		string $password,
       
   503 		string $hash
       
   504 	): bool {
       
   505 		if ( ! str_starts_with( $hash, '$generic$' ) ) {
       
   506 			/*
       
   507 			 * If the hash doesn't start with `$generic$`, it is a hash created with `wp_hash_password()`.
       
   508 			 * This is the case for application passwords created before 6.8.0.
       
   509 			 */
       
   510 			return wp_check_password( $password, $hash );
       
   511 		}
       
   512 
       
   513 		return wp_verify_fast_hash( $password, $hash );
       
   514 	}
   428 }
   515 }