[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-includes/ -> class-wp-recovery-mode-key-service.php (source)

   1  <?php
   2  /**
   3   * Error Protection API: WP_Recovery_Mode_Key_Service class
   4   *
   5   * @package WordPress
   6   * @since 5.2.0
   7   */
   8  
   9  /**
  10   * Core class used to generate and validate keys used to enter Recovery Mode.
  11   *
  12   * @since 5.2.0
  13   */
  14  #[AllowDynamicProperties]
  15  final class WP_Recovery_Mode_Key_Service {
  16  
  17      /**
  18       * The option name used to store the keys.
  19       *
  20       * @since 5.2.0
  21       * @var string
  22       */
  23      private $option_name = 'recovery_keys';
  24  
  25      /**
  26       * Creates a recovery mode token.
  27       *
  28       * @since 5.2.0
  29       *
  30       * @return string A random string to identify its associated key in storage.
  31       */
  32  	public function generate_recovery_mode_token() {
  33          return wp_generate_password( 22, false );
  34      }
  35  
  36      /**
  37       * Creates a recovery mode key.
  38       *
  39       * @since 5.2.0
  40       * @since 6.8.0 The stored key is now hashed using wp_fast_hash() instead of phpass.
  41       *
  42       * @param string $token A token generated by {@see generate_recovery_mode_token()}.
  43       * @return string Recovery mode key.
  44       */
  45  	public function generate_and_store_recovery_mode_key( $token ) {
  46          $key = wp_generate_password( 22, false );
  47  
  48          $records = $this->get_keys();
  49  
  50          $records[ $token ] = array(
  51              'hashed_key' => wp_fast_hash( $key ),
  52              'created_at' => time(),
  53          );
  54  
  55          $this->update_keys( $records );
  56  
  57          /**
  58           * Fires when a recovery mode key is generated.
  59           *
  60           * @since 5.2.0
  61           *
  62           * @param string $token The recovery data token.
  63           * @param string $key   The recovery mode key.
  64           */
  65          do_action( 'generate_recovery_mode_key', $token, $key );
  66  
  67          return $key;
  68      }
  69  
  70      /**
  71       * Verifies if the recovery mode key is correct.
  72       *
  73       * Recovery mode keys can only be used once; the key will be consumed in the process.
  74       *
  75       * @since 5.2.0
  76       *
  77       * @param string $token The token used when generating the given key.
  78       * @param string $key   The plain text key.
  79       * @param int    $ttl   Time in seconds for the key to be valid for.
  80       * @return true|WP_Error True on success, error object on failure.
  81       */
  82  	public function validate_recovery_mode_key( $token, $key, $ttl ) {
  83          $records = $this->get_keys();
  84  
  85          if ( ! isset( $records[ $token ] ) ) {
  86              return new WP_Error( 'token_not_found', __( 'Recovery Mode not initialized.' ) );
  87          }
  88  
  89          $record = $records[ $token ];
  90  
  91          $this->remove_key( $token );
  92  
  93          if ( ! is_array( $record ) || ! isset( $record['hashed_key'], $record['created_at'] ) ) {
  94              return new WP_Error( 'invalid_recovery_key_format', __( 'Invalid recovery key format.' ) );
  95          }
  96  
  97          if ( ! wp_verify_fast_hash( $key, $record['hashed_key'] ) ) {
  98              return new WP_Error( 'hash_mismatch', __( 'Invalid recovery key.' ) );
  99          }
 100  
 101          if ( time() > $record['created_at'] + $ttl ) {
 102              return new WP_Error( 'key_expired', __( 'Recovery key expired.' ) );
 103          }
 104  
 105          return true;
 106      }
 107  
 108      /**
 109       * Removes expired recovery mode keys.
 110       *
 111       * @since 5.2.0
 112       *
 113       * @param int $ttl Time in seconds for the keys to be valid for.
 114       */
 115  	public function clean_expired_keys( $ttl ) {
 116  
 117          $records = $this->get_keys();
 118  
 119          foreach ( $records as $key => $record ) {
 120              if ( ! isset( $record['created_at'] ) || time() > $record['created_at'] + $ttl ) {
 121                  unset( $records[ $key ] );
 122              }
 123          }
 124  
 125          $this->update_keys( $records );
 126      }
 127  
 128      /**
 129       * Removes a used recovery key.
 130       *
 131       * @since 5.2.0
 132       *
 133       * @param string $token The token used when generating a recovery mode key.
 134       */
 135  	private function remove_key( $token ) {
 136  
 137          $records = $this->get_keys();
 138  
 139          if ( ! isset( $records[ $token ] ) ) {
 140              return;
 141          }
 142  
 143          unset( $records[ $token ] );
 144  
 145          $this->update_keys( $records );
 146      }
 147  
 148      /**
 149       * Gets the recovery key records.
 150       *
 151       * @since 5.2.0
 152       * @since 6.8.0 Each key is now hashed using wp_fast_hash() instead of phpass.
 153       *              Existing keys may still be hashed using phpass.
 154       *
 155       * @return array {
 156       *     Associative array of token => data pairs, where the data is an associative
 157       *     array of information about the key.
 158       *
 159       *     @type array ...$0 {
 160       *         Information about the key.
 161       *
 162       *         @type string $hashed_key The hashed value of the key.
 163       *         @type int    $created_at The timestamp when the key was created.
 164       *     }
 165       * }
 166       */
 167  	private function get_keys() {
 168          return (array) get_option( $this->option_name, array() );
 169      }
 170  
 171      /**
 172       * Updates the recovery key records.
 173       *
 174       * @since 5.2.0
 175       * @since 6.8.0 Each key should now be hashed using wp_fast_hash() instead of phpass.
 176       *
 177       * @param array $keys {
 178       *     Associative array of token => data pairs, where the data is an associative
 179       *     array of information about the key.
 180       *
 181       *     @type array ...$0 {
 182       *         Information about the key.
 183       *
 184       *         @type string $hashed_key The hashed value of the key.
 185       *         @type int    $created_at The timestamp when the key was created.
 186       *     }
 187       * }
 188       * @return bool True on success, false on failure.
 189       */
 190  	private function update_keys( array $keys ) {
 191          return update_option( $this->option_name, $keys, false );
 192      }
 193  }


Generated : Sat Feb 22 08:20:01 2025 Cross-referenced by PHPXref