WordPress.org

Make WordPress Core

Ticket #20276: 20276.diff

File 20276.diff, 6.2 KB (added by duck_, 6 years ago)
  • src/wp-includes/pluggable.php

     
    494494 * @since 2.5.0
    495495 */
    496496function wp_logout() {
     497        wp_destroy_current_session();
    497498        wp_clear_auth_cookie();
    498499        do_action('wp_logout');
    499500}
     
    543544
    544545        $pass_frag = substr($user->user_pass, 8, 4);
    545546
    546         $key = wp_hash($username . $pass_frag . '|' . $expiration, $scheme);
    547         $hash = hash_hmac('md5', $username . '|' . $expiration, $key);
     547        $key = wp_hash($username . '|' . $pass_frag . '|' . $expiration . '|' . $token, $scheme);
     548        $hash = hash_hmac('md5', $username . '|' . $expiration . '|' . $token, $key);
    548549
    549550        if ( $hmac != $hash ) {
    550551                do_action('auth_cookie_bad_hash', $cookie_elements);
     
    551552                return false;
    552553        }
    553554
     555        if ( ! wp_verify_session_token( $user->ID, $token ) ) {
     556                return false;
     557        }
     558
    554559        if ( $expiration < time() ) // AJAX/POST grace period set above
    555560                $GLOBALS['login_grace_period'] = 1;
    556561
     
    569574 *              and expiration of cookie.
    570575 *
    571576 * @param int $user_id User ID
     577 * @param string $token User's session token to use for this cookie
    572578 * @param int $expiration Cookie expiration in seconds
    573579 * @param string $scheme Optional. The cookie scheme to use: auth, secure_auth, or logged_in
    574580 * @return string Authentication cookie contents
    575581 */
    576 function wp_generate_auth_cookie($user_id, $expiration, $scheme = 'auth') {
    577         $user = get_userdata($user_id);
     582function wp_generate_auth_cookie($user_id, $token, $expiration, $scheme = 'auth') {
     583        $user = new WP_User($user_id);
     584        if ( ! $user->exists() )
     585                return '';
    578586
    579587        $pass_frag = substr($user->user_pass, 8, 4);
    580588
    581         $key = wp_hash($user->user_login . $pass_frag . '|' . $expiration, $scheme);
    582         $hash = hash_hmac('md5', $user->user_login . '|' . $expiration, $key);
     589        $key = wp_hash($user->user_login . '|' . $pass_frag . '|' . $expiration . '|' . $token, $scheme);
     590        $hash = hash_hmac('md5', $user->user_login . '|' . $expiration . '|' . $token, $key);
    583591
    584         $cookie = $user->user_login . '|' . $expiration . '|' . $hash;
     592        $cookie = $user->user_login . '|' . $expiration . '|' . $token . '|' . $hash;
    585593
    586594        return apply_filters('auth_cookie', $cookie, $user_id, $expiration, $scheme);
    587595}
     
    625633        }
    626634
    627635        $cookie_elements = explode('|', $cookie);
    628         if ( count($cookie_elements) != 3 )
     636        if ( count($cookie_elements) != 4 )
    629637                return false;
    630638
    631         list($username, $expiration, $hmac) = $cookie_elements;
     639        list($username, $expiration, $token, $hmac) = $cookie_elements;
    632640
    633         return compact('username', 'expiration', 'hmac', 'scheme');
     641        return compact('username', 'expiration', 'token', 'hmac', 'scheme');
    634642}
    635643endif;
    636644
     
    646654 *
    647655 * @param int $user_id User ID
    648656 * @param bool $remember Whether to remember the user
     657 * @param mixed $secure Whether the admin cookies should only be sent over HTTPS (defaults to is_ssl())
    649658 */
    650659function wp_set_auth_cookie($user_id, $remember = false, $secure = '') {
    651660        if ( $remember ) {
     
    669678                $scheme = 'auth';
    670679        }
    671680
    672         $auth_cookie = wp_generate_auth_cookie($user_id, $expiration, $scheme);
    673         $logged_in_cookie = wp_generate_auth_cookie($user_id, $expiration, 'logged_in');
     681        $token = wp_create_session_token( $user_id, $expiration );
    674682
     683        $auth_cookie = wp_generate_auth_cookie($user_id, $token, $expiration, $scheme);
     684        $logged_in_cookie = wp_generate_auth_cookie($user_id, $token, $expiration, 'logged_in');
     685
    675686        do_action('set_auth_cookie', $auth_cookie, $expire, $expiration, $user_id, $scheme);
    676687        do_action('set_logged_in_cookie', $logged_in_cookie, $expire, $expiration, $user_id, 'logged_in');
    677688
  • src/wp-includes/user.php

     
    15501550        }
    15511551        return apply_filters( 'user_contactmethods', $user_contactmethods, $user );
    15521552}
     1553
     1554/**
     1555 * Generate a cookie session identification token.
     1556 *
     1557 * A session identification token is a long, random string. It is used to
     1558 * link a cookie to an expiration time and to ensure that cookies become
     1559 * invalidated upon logout. This function generates a token and stores it
     1560 * as user meta with the associated expiration time.
     1561 *
     1562 * Will also remove any expired tokens from the database.
     1563 *
     1564 * @since 3.7.0
     1565 *
     1566 * @param int $user_id User to create a token for.
     1567 * @param int $expiration Session expiration timestamp.
     1568 * @return string Session identification token.
     1569 */
     1570function wp_create_session_token( $user_id, $expiration ) {
     1571        $sessions = get_user_meta( $user_id, 'session_tokens', true );
     1572        if ( ! $sessions )
     1573                $sessions = array();
     1574        $sessions = array_filter( $sessions, '_session_not_expired' );
     1575
     1576        $token = wp_generate_password( 40, false, false );
     1577        $verifier = hash( 'sha256', $token );
     1578        $sessions[$verifier] = $expiration;
     1579
     1580        update_user_meta( $user_id, 'session_tokens', $sessions );
     1581
     1582        return $token;
     1583}
     1584
     1585/**
     1586 * Validate a user's session token as authentic.
     1587 *
     1588 * Checks that the given token is present in the database and hasn't expired.
     1589 *
     1590 * @since 3.7.0
     1591 *
     1592 * @param int $user_id User to verify against.
     1593 * @param string $token Token to verify.
     1594 * @return bool Whether the token is valid for the given user.
     1595 */
     1596function wp_verify_session_token( $user_id, $token ) {
     1597        $sessions = get_user_meta( $user_id, 'session_tokens', true );
     1598        $verifier = hash( 'sha256', $token );
     1599        return isset( $sessions[$verifier] ) && $sessions[$verifier] >= time();
     1600}
     1601
     1602/**
     1603 * Remove the current session token from the database.
     1604 *
     1605 * Will also remove any expired tokens from the database.
     1606 *
     1607 * @since 3.7.0
     1608 */
     1609function wp_destroy_current_session() {
     1610        $user_id = get_current_user_id();
     1611        $cookie = wp_parse_auth_cookie( '', 'logged_in' );
     1612        if ( ! empty( $cookie['token'] ) ) {
     1613                $verifier = hash( 'sha256', $cookie['token'] );
     1614                $sessions = get_user_meta( $user_id, 'session_tokens', true );
     1615                unset( $sessions[$verifier] );
     1616                $sessions = array_filter( $sessions, '_session_not_expired' );
     1617                update_user_meta( $user_id, 'session_tokens', $sessions );
     1618        }
     1619}
     1620
     1621/**
     1622 * @access private
     1623 * @since 3.7.0
     1624 * @param int $expiry
     1625 */
     1626function _session_not_expired( $expiry ) {
     1627        return $expiry >= time();
     1628}