Ticket #20276: 20276.2.diff
File 20276.2.diff, 7.5 KB (added by , 11 years ago) |
---|
-
src/wp-includes/pluggable.php
494 494 * @since 2.5.0 495 495 */ 496 496 function wp_logout() { 497 wp_destroy_current_session(); 497 498 wp_clear_auth_cookie(); 498 499 do_action('wp_logout'); 499 500 } … … 543 544 544 545 $pass_frag = substr($user->user_pass, 8, 4); 545 546 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); 548 549 549 550 if ( $hmac != $hash ) { 550 551 do_action('auth_cookie_bad_hash', $cookie_elements); … … 551 552 return false; 552 553 } 553 554 555 if ( ! wp_verify_session_token( $user->ID, $token ) ) { 556 return false; 557 } 558 554 559 if ( $expiration < time() ) // AJAX/POST grace period set above 555 560 $GLOBALS['login_grace_period'] = 1; 556 561 … … 571 576 * @param int $user_id User ID 572 577 * @param int $expiration Cookie expiration in seconds 573 578 * @param string $scheme Optional. The cookie scheme to use: auth, secure_auth, or logged_in 579 * @param string $token User's session token to use for this cookie 574 580 * @return string Authentication cookie contents 575 581 */ 576 function wp_generate_auth_cookie($user_id, $expiration, $scheme = 'auth') { 577 $user = get_userdata($user_id); 582 function wp_generate_auth_cookie($user_id, $expiration, $scheme = 'auth', $token = '') { 583 $user = new WP_User($user_id); 584 if ( ! $user->exists() ) 585 return ''; 578 586 587 if (empty($token)) 588 $token = wp_create_session_token( $user_id, $expiration ); 589 579 590 $pass_frag = substr($user->user_pass, 8, 4); 580 591 581 $key = wp_hash($user->user_login . $pass_frag . '|' . $expiration, $scheme);582 $hash = hash_hmac('md5', $user->user_login . '|' . $expiration , $key);592 $key = wp_hash($user->user_login . '|' . $pass_frag . '|' . $expiration . '|' . $token, $scheme); 593 $hash = hash_hmac('md5', $user->user_login . '|' . $expiration . '|' . $token, $key); 583 594 584 $cookie = $user->user_login . '|' . $expiration . '|' . $ hash;595 $cookie = $user->user_login . '|' . $expiration . '|' . $token . '|' . $hash; 585 596 586 597 return apply_filters('auth_cookie', $cookie, $user_id, $expiration, $scheme); 587 598 } … … 625 636 } 626 637 627 638 $cookie_elements = explode('|', $cookie); 628 if ( count($cookie_elements) != 3)639 if ( count($cookie_elements) != 4 ) 629 640 return false; 630 641 631 list($username, $expiration, $ hmac) = $cookie_elements;642 list($username, $expiration, $token, $hmac) = $cookie_elements; 632 643 633 return compact('username', 'expiration', ' hmac', 'scheme');644 return compact('username', 'expiration', 'token', 'hmac', 'scheme'); 634 645 } 635 646 endif; 636 647 … … 646 657 * 647 658 * @param int $user_id User ID 648 659 * @param bool $remember Whether to remember the user 660 * @param mixed $secure Whether the admin cookies should only be sent over HTTPS (defaults to is_ssl()) 649 661 */ 650 662 function wp_set_auth_cookie($user_id, $remember = false, $secure = '') { 651 663 if ( $remember ) { … … 669 681 $scheme = 'auth'; 670 682 } 671 683 672 $auth_cookie = wp_generate_auth_cookie($user_id, $expiration, $scheme); 673 $logged_in_cookie = wp_generate_auth_cookie($user_id, $expiration, 'logged_in'); 684 $token = wp_create_session_token( $user_id, $expiration ); 674 685 686 $auth_cookie = wp_generate_auth_cookie( $user_id, $expiration, $scheme, $token ); 687 $logged_in_cookie = wp_generate_auth_cookie( $user_id, $expiration, 'logged_in', $token ); 688 675 689 do_action('set_auth_cookie', $auth_cookie, $expire, $expiration, $user_id, $scheme); 676 690 do_action('set_logged_in_cookie', $logged_in_cookie, $expire, $expiration, $user_id, 'logged_in'); 677 691 … … 1258 1272 $uid = (int) $user->ID; 1259 1273 if ( ! $uid ) 1260 1274 $uid = apply_filters( 'nonce_user_logged_out', $uid, $action ); 1261 1275 $token = wp_get_session_token(); 1262 1276 $i = wp_nonce_tick(); 1263 1277 1264 1278 // Nonce generated 0-12 hours ago 1265 if ( substr(wp_hash($i . $action . $uid, 'nonce'), -12, 10) === $nonce )1279 if ( substr(wp_hash($i . '|' . $action . '|' . $uid . '|' . $token, 'nonce'), -12, 10) === $nonce ) 1266 1280 return 1; 1267 1281 // Nonce generated 12-24 hours ago 1268 if ( substr(wp_hash(($i - 1) . $action . $uid, 'nonce'), -12, 10) === $nonce )1282 if ( substr(wp_hash(($i - 1) . '|' . $action . '|' . $uid . '|' . $token, 'nonce'), -12, 10) === $nonce ) 1269 1283 return 2; 1270 1284 // Invalid nonce 1271 1285 return false; … … 1286 1300 $uid = (int) $user->ID; 1287 1301 if ( ! $uid ) 1288 1302 $uid = apply_filters( 'nonce_user_logged_out', $uid, $action ); 1289 1303 $token = wp_get_session_token(); 1290 1304 $i = wp_nonce_tick(); 1291 1305 1292 return substr(wp_hash($i . $action . $uid, 'nonce'), -12, 10);1306 return substr(wp_hash($i . '|' . $action . '|' . $uid . '|' . $token, 'nonce'), -12, 10); 1293 1307 } 1294 1308 endif; 1295 1309 -
src/wp-includes/user.php
1550 1550 } 1551 1551 return apply_filters( 'user_contactmethods', $user_contactmethods, $user ); 1552 1552 } 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 */ 1570 function 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 */ 1596 function 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 */ 1609 function wp_destroy_current_session() { 1610 $token = wp_get_session_token(); 1611 if ( ! empty( $token ) ) { 1612 $user_id = get_current_user_id(); 1613 $verifier = hash( 'sha256', $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 */ 1626 function _session_not_expired( $expiry ) { 1627 return $expiry >= time(); 1628 } 1629 1630 /** 1631 * Retrieve the current session token from the logged_in cookie. 1632 * 1633 * @since 3.7.0 1634 * 1635 * @return string 1636 */ 1637 function wp_get_session_token() { 1638 $cookie = wp_parse_auth_cookie( '', 'logged_in' ); 1639 return ! empty( $cookie['token'] ) ? $cookie['token'] : ''; 1640 }