Ticket #20276: 20276.4.diff
File 20276.4.diff, 7.9 KB (added by , 11 years ago) |
---|
-
src/wp-includes/pluggable.php
586 586 * @since 2.5.0 587 587 */ 588 588 function wp_logout() { 589 wp_destroy_current_session(); 589 590 wp_clear_auth_cookie(); 590 591 591 592 /** … … 631 632 $scheme = $cookie_elements['scheme']; 632 633 $username = $cookie_elements['username']; 633 634 $hmac = $cookie_elements['hmac']; 635 $token = $cookie_elements['token']; 634 636 $expired = $expiration = $cookie_elements['expiration']; 635 637 636 638 // Allow a grace period for POST and AJAX requests … … 666 668 667 669 $pass_frag = substr($user->user_pass, 8, 4); 668 670 669 $key = wp_hash( $username . $pass_frag . '|' . $expiration, $scheme);670 $hash = hash_hmac( 'md5', $username . '|' . $expiration, $key);671 $key = wp_hash( $username . '|' . $pass_frag . '|' . $expiration . '|' . $token, $scheme ); 672 $hash = hash_hmac( 'md5', $username . '|' . $expiration . '|' . $token, $key ); 671 673 672 674 if ( hash_hmac( 'md5', $hmac, $key ) !== hash_hmac( 'md5', $hash, $key ) ) { 673 675 /** … … 681 683 return false; 682 684 } 683 685 684 if ( $expiration < time() ) {// AJAX/POST grace period set above 686 if ( ! wp_verify_session_token( $user->ID, $token ) ) { 687 do_action( 'auth_cookie_bad_session_token', $cookie_elements ); 688 return false; 689 } 690 691 if ( $expiration < time() ) { // AJAX/POST grace period set above 685 692 $GLOBALS['login_grace_period'] = 1; 686 693 } 687 694 … … 708 715 * @param int $user_id User ID 709 716 * @param int $expiration Cookie expiration in seconds 710 717 * @param string $scheme Optional. The cookie scheme to use: auth, secure_auth, or logged_in 711 * @return string Authentication cookie contents 718 * @param string $token User's session token to use for this cookie 719 * @return string Authentication cookie contents. Empty string if user does not exist. 712 720 */ 713 function wp_generate_auth_cookie( $user_id, $expiration, $scheme = 'auth') {721 function wp_generate_auth_cookie( $user_id, $expiration, $scheme = 'auth', $token = '' ) { 714 722 $user = get_userdata($user_id); 723 if ( ! $user ) { 724 return ''; 725 } 715 726 727 if ( ! $token ) { 728 $token = wp_create_session_token( $user_id, $expiration ); 729 } 730 716 731 $pass_frag = substr($user->user_pass, 8, 4); 717 732 718 $key = wp_hash( $user->user_login . $pass_frag . '|' . $expiration, $scheme);719 $hash = hash_hmac( 'md5', $user->user_login . '|' . $expiration, $key);733 $key = wp_hash( $user->user_login . '|' . $pass_frag . '|' . $expiration . '|' . $token, $scheme ); 734 $hash = hash_hmac( 'md5', $user->user_login . '|' . $expiration . '|' . $token, $key ); 720 735 721 $cookie = $user->user_login . '|' . $expiration . '|' . $ hash;736 $cookie = $user->user_login . '|' . $expiration . '|' . $token . '|' . $hash; 722 737 723 738 /** 724 739 * Filter the authentication cookie. … … 772 787 } 773 788 774 789 $cookie_elements = explode('|', $cookie); 775 if ( count( $cookie_elements) != 3 )790 if ( count( $cookie_elements ) !== 4 ) { 776 791 return false; 792 } 777 793 778 list( $username, $expiration, $hmac) = $cookie_elements;794 list( $username, $expiration, $token, $hmac ) = $cookie_elements; 779 795 780 return compact( 'username', 'expiration', 'hmac', 'scheme');796 return compact( 'username', 'expiration', 'token', 'hmac', 'scheme' ); 781 797 } 782 798 endif; 783 799 … … 793 809 * 794 810 * @param int $user_id User ID 795 811 * @param bool $remember Whether to remember the user 812 * @param mixed $secure Whether the admin cookies should only be sent over HTTPS. 813 * Default is_ssl(). 796 814 */ 797 815 function wp_set_auth_cookie($user_id, $remember = false, $secure = '') { 798 816 if ( $remember ) { … … 850 868 $scheme = 'auth'; 851 869 } 852 870 853 $auth_cookie = wp_generate_auth_cookie($user_id, $expiration, $scheme); 854 $logged_in_cookie = wp_generate_auth_cookie($user_id, $expiration, 'logged_in'); 871 $token = wp_create_session_token( $user_id, $expiration ); 872 $auth_cookie = wp_generate_auth_cookie( $user_id, $expiration, $scheme, $token ); 873 $logged_in_cookie = wp_generate_auth_cookie( $user_id, $expiration, 'logged_in', $token ); 855 874 856 875 /** 857 876 * Fires immediately before the authentication cookie is set. … … 1678 1697 $uid = apply_filters( 'nonce_user_logged_out', $uid, $action ); 1679 1698 } 1680 1699 1700 $token = wp_get_session_token(); 1681 1701 $i = wp_nonce_tick(); 1682 1702 1683 1703 // Nonce generated 0-12 hours ago 1684 if ( substr(wp_hash($i . $action . $uid, 'nonce'), -12, 10) === $nonce )1704 if ( $nonce === substr( wp_hash( $i . '|' . $action . '|' . $uid . '|' . $token, 'nonce'), -12, 10 ) ) { 1685 1705 return 1; 1706 } 1707 1686 1708 // Nonce generated 12-24 hours ago 1687 if ( substr(wp_hash(($i - 1) . $action . $uid, 'nonce'), -12, 10) === $nonce )1709 if ( $nonce === substr( wp_hash( ( $i - 1 ) . '|' . $action . '|' . $uid . '|' . $token, 'nonce' ), -12, 10 ) ) { 1688 1710 return 2; 1711 } 1712 1689 1713 // Invalid nonce 1690 1714 return false; 1691 1715 } … … 1708 1732 $uid = apply_filters( 'nonce_user_logged_out', $uid, $action ); 1709 1733 } 1710 1734 1735 $token = wp_get_session_token(); 1711 1736 $i = wp_nonce_tick(); 1712 1737 1713 return substr( wp_hash($i . $action . $uid, 'nonce'), -12, 10);1738 return substr( wp_hash( $i . '|' . $action . '|' . $uid . '|' . $token, 'nonce' ), -12, 10 ); 1714 1739 } 1715 1740 endif; 1716 1741 -
src/wp-includes/user.php
2127 2127 2128 2128 return $user_id; 2129 2129 } 2130 2131 /** 2132 * Generate a cookie session identification token. 2133 * 2134 * A session identification token is a long, random string. It is used to 2135 * link a cookie to an expiration time and to ensure that cookies become 2136 * invalidated upon logout. This function generates a token and stores it 2137 * as user meta with the associated expiration time. 2138 * 2139 * Will also remove any expired tokens from the database. 2140 * 2141 * @since 4.0.0 2142 * 2143 * @param int $user_id User to create a token for. 2144 * @param int $expiration Session expiration timestamp. 2145 * @return string Session identification token. 2146 */ 2147 function wp_create_session_token( $user_id, $expiration ) { 2148 $sessions = get_user_meta( $user_id, 'session_tokens', true ); 2149 if ( ! $sessions ) 2150 $sessions = array(); 2151 // Expire old sessions 2152 $time = time(); 2153 foreach ( $sessions as $v => $e ) { 2154 if ( $e < $time ) { 2155 unset( $sessions[ $v ] ); 2156 } 2157 } 2158 2159 $token = wp_generate_password( 40, false, false ); 2160 $verifier = hash( 'sha256', $token ); 2161 $sessions[ $verifier ] = $expiration; 2162 2163 update_user_meta( $user_id, 'session_tokens', $sessions ); 2164 2165 return $token; 2166 } 2167 2168 /** 2169 * Validate a user's session token as authentic. 2170 * 2171 * Checks that the given token is present in the database and hasn't expired. 2172 * 2173 * @since 4.0.0 2174 * 2175 * @param int $user_id User to verify against. 2176 * @param string $token Token to verify. 2177 * @return bool Whether the token is valid for the given user. 2178 */ 2179 function wp_verify_session_token( $user_id, $token ) { 2180 $sessions = get_user_meta( $user_id, 'session_tokens', true ); 2181 $verifier = hash( 'sha256', $token ); 2182 return isset( $sessions[ $verifier ] ) && $sessions[ $verifier ] >= time(); 2183 } 2184 2185 /** 2186 * Remove the current session token from the database. 2187 * 2188 * Will also remove any expired tokens from the database. 2189 * 2190 * @since 4.0.0 2191 */ 2192 function wp_destroy_current_session() { 2193 $token = wp_get_session_token(); 2194 if ( ! empty( $token ) ) { 2195 $user_id = get_current_user_id(); 2196 $verifier = hash( 'sha256', $token ); 2197 $sessions = get_user_meta( $user_id, 'session_tokens', true ); 2198 unset( $sessions[ $verifier ] ); 2199 2200 // Expire old sessions 2201 $time = time(); 2202 foreach ( $sessions as $v => $e ) { 2203 if ( $e < $time ) { 2204 unset( $sessions[ $v ] ); 2205 } 2206 } 2207 2208 if ( $sessions ) { 2209 update_user_meta( $user_id, 'session_tokens', $sessions ); 2210 } else { 2211 delete_user_meta( $user_id, 'session_tokens' ); 2212 } 2213 } 2214 } 2215 2216 /** 2217 * Retrieve the current session token from the logged_in cookie. 2218 * 2219 * @since 4.0.0 2220 * 2221 * @return string 2222 */ 2223 function wp_get_session_token() { 2224 $cookie = wp_parse_auth_cookie( '', 'logged_in' ); 2225 return ! empty( $cookie['token'] ) ? $cookie['token'] : ''; 2226 }