WordPress.org

Make WordPress Core

Ticket #24783: 24783.3.diff

File 24783.3.diff, 5.7 KB (added by nacin, 6 years ago)
  • src/wp-includes/user.php

     
    15681568/**
    15691569 * Retrieves a user row based on password reset key and login
    15701570 *
     1571 * A key is considered 'expired' if it exactly matches the value of the
     1572 * user_activation_key field, rather than being matched after going through the
     1573 * hashing process. This field is now hashed; old values are no longer accepted
     1574 * but have a different WP_Error code so good user feedback can be provided.
     1575 *
    15711576 * @uses $wpdb WordPress Database object
    15721577 *
    1573  * @param string $key Hash to validate sending user's password
    1574  * @param string $login The user login
    1575  * @return object|WP_Error User's database row on success, error object for invalid keys
     1578 * @param string $key       Hash to validate sending user's password.
     1579 * @param string $login     The user login.
     1580 * @return WP_User|WP_Error WP_User object on success, WP_Error object for invalid or expired keys.
    15761581 */
    1577 function check_password_reset_key( $key, $login ) {
    1578         global $wpdb;
     1582function check_password_reset_key($key, $login) {
     1583        global $wpdb, $wp_hasher;
    15791584
    1580         $key = preg_replace( '/[^a-z0-9]/i', '', $key );
     1585        $key = preg_replace('/[^a-z0-9]/i', '', $key);
    15811586
    1582         if ( empty( $key ) || ! is_string( $key ) )
    1583                 return new WP_Error( 'invalid_key', __( 'Invalid key' ) );
     1587        if ( empty( $key ) || !is_string( $key ) )
     1588                return new WP_Error('invalid_key', __('Invalid key'));
    15841589
    1585         if ( empty( $login ) || ! is_string( $login ) )
    1586                 return new WP_Error( 'invalid_key', __( 'Invalid key' ) );
     1590        if ( empty($login) || !is_string($login) )
     1591                return new WP_Error('invalid_key', __('Invalid key'));
    15871592
    1588         $user = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->users WHERE user_activation_key = %s AND user_login = %s", $key, $login ) );
     1593        $row = $wpdb->get_row( $wpdb->prepare( "SELECT ID, user_activation_key FROM $wpdb->users WHERE user_login = %s", $login ) );
     1594        if ( ! $row )
     1595                return new WP_Error('invalid_key', __('Invalid key'));
    15891596
    1590         if ( empty( $user ) )
    1591                 return new WP_Error( 'invalid_key', __( 'Invalid key' ) );
     1597        if ( empty( $wp_hasher ) ) {
     1598                require_once ABSPATH . 'wp-includes/class-phpass.php';
     1599                $wp_hasher = new PasswordHash( 8, true );
     1600        }
    15921601
    1593         return $user;
     1602        if ( $wp_hasher->CheckPassword( $key, $row->user_activation_key ) )
     1603                return get_userdata( $row->ID );
     1604
     1605        if ( $key === $row->user_activation_key ) {
     1606                $return = new WP_Error( 'expired_key', __( 'Invalid key' ) );
     1607                $user_id = $row->ID;
     1608
     1609                /**
     1610                 * Filter the return value of check_password_reset_key() when an
     1611                 * old-style key is used (plain-text key was stored in the database).
     1612                 *
     1613                 * @since 3.7.0
     1614                 *
     1615                 * @param WP_Error $return  A WP_Error object denoting an expired key.
     1616                 *                          Return a WP_User object to validate the key.
     1617                 * @param int      $user_id The matched user ID.
     1618                 */
     1619                return apply_filters( 'password_reset_key_expired', $return, $user_id );
     1620        }
     1621
     1622        return new WP_Error('invalid_key', __('Invalid key'));
    15941623}
    15951624
    15961625/**
  • src/wp-login.php

     
    197197 * @return bool|WP_Error True: when finish. WP_Error on error
    198198 */
    199199function retrieve_password() {
    200         global $wpdb, $current_site;
     200        global $wpdb, $current_site, $wp_hasher;
    201201
    202202        $errors = new WP_Error();
    203203
     
    236236        else if ( is_wp_error($allow) )
    237237                return $allow;
    238238
    239         $key = $wpdb->get_var($wpdb->prepare("SELECT user_activation_key FROM $wpdb->users WHERE user_login = %s", $user_login));
    240         if ( empty($key) ) {
    241                 // Generate something random for a key...
    242                 $key = wp_generate_password(20, false);
    243                 do_action('retrieve_password_key', $user_login, $key);
    244                 // Now insert the new md5 key into the db
    245                 $wpdb->update($wpdb->users, array('user_activation_key' => $key), array('user_login' => $user_login));
     239        // Generate something random for a key...
     240        $key = wp_generate_password(20, false);
     241        do_action('retrieve_password_key', $user_login, $key);
     242        // Now insert the key, hashed, into the db
     243        if ( empty( $wp_hasher ) ) {
     244                require_once ABSPATH . 'wp-includes/class-phpass.php';
     245                $wp_hasher = new PasswordHash( 8, true );
    246246        }
     247        $hashed = $wp_hasher->HashPassword( $key );
     248        $wpdb->update( $wpdb->users, array( 'user_activation_key' => $hashed ), array( 'user_login' => $user_login ) );
     249
    247250        $message = __('Someone requested that the password be reset for the following account:') . "\r\n\r\n";
    248251        $message .= network_home_url( '/' ) . "\r\n\r\n";
    249252        $message .= sprintf(__('Username: %s'), $user_login) . "\r\n\r\n";
     
    353356                }
    354357        }
    355358
    356         if ( isset($_GET['error']) && 'invalidkey' == $_GET['error'] ) $errors->add('invalidkey', __('Sorry, that key does not appear to be valid.'));
     359        if ( isset( $_GET['error'] ) ) {
     360                if ( 'invalidkey' == $_GET['error'] )
     361                        $errors->add( 'invalidkey', __( 'Sorry, that key does not appear to be valid.' ) );
     362                elseif ( 'expiredkey' == $_GET['error'] )
     363                        $errors->add( 'expiredkey', __( 'Sorry, that key has expired. Please try again.' ) );
     364        }
     365
    357366        $redirect_to = apply_filters( 'lostpassword_redirect', !empty( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : '' );
    358367
    359368        do_action('lost_password');
     
    389398        $user = check_password_reset_key($_GET['key'], $_GET['login']);
    390399
    391400        if ( is_wp_error($user) ) {
    392                 wp_redirect( site_url('wp-login.php?action=lostpassword&error=invalidkey') );
     401                if ( $user->get_error_code() === 'expired_key' )
     402                        wp_redirect( site_url( 'wp-login.php?action=lostpassword&error=expiredkey' ) );
     403                else
     404                        wp_redirect( site_url( 'wp-login.php?action=lostpassword&error=invalidkey' ) );
    393405                exit;
    394406        }
    395407