diff --git a/wp-admin/includes/misc.php b/wp-admin/includes/misc.php index 5902c4e8b..24a4c063c 100644 --- a/wp-admin/includes/misc.php +++ b/wp-admin/includes/misc.php @@ -128,7 +128,7 @@ function update_recently_edited( $file ) { update_option( 'recently_edited', $oldfiles ); } -// If siteurl or home changed, reset cookies and flush rewrite rules. +// If siteurl or home changed, flush rewrite rules. function update_home_siteurl( $old_value, $value ) { global $wp_rewrite, $user_login, $user_pass_md5; @@ -137,10 +137,6 @@ function update_home_siteurl( $old_value, $value ) { // If home changed, write rewrite rules to new location. $wp_rewrite->flush_rules(); - // Clear cookies for old paths. - wp_clearcookie(); - // Set cookies for new paths. - wp_setcookie( $user_login, $user_pass_md5, true, get_option( 'home' ), get_option( 'siteurl' )); } add_action( 'update_option_home', 'update_home_siteurl', 10, 2 ); diff --git a/wp-config-sample.php b/wp-config-sample.php index 26bf086f5..6b9956745 100644 --- a/wp-config-sample.php +++ b/wp-config-sample.php @@ -6,6 +6,7 @@ define('DB_PASSWORD', 'yourpasswordhere'); // ...and password define('DB_HOST', 'localhost'); // 99% chance you won't need to change this value define('DB_CHARSET', 'utf8'); define('DB_COLLATE', ''); +define('SECRET_KEY', ''); // Change this to a unique phrase. // You can have multiple installations in one database if you give each a unique prefix $table_prefix = 'wp_'; // Only numbers, letters, and underscores please! diff --git a/wp-includes/compat.php b/wp-includes/compat.php index 0573c4a5b..88d1751e7 100644 --- a/wp-includes/compat.php +++ b/wp-includes/compat.php @@ -147,6 +147,27 @@ if (!function_exists('stripos')) { } } +if ( ! function_exists('hash_hmac') ): +function hash_hmac($algo, $data, $key, $raw_output = false) { + $packs = array('md5' => 'H32', 'sha1' => 'H40'); + + if ( !isset($packs[$algo]) ) + return false; + + $pack = $packs[$algo]; + + if (strlen($key) > 64) + $key = pack($pack, $algo($key)); + else if (strlen($key) < 64) + $key = str_pad($key, 64, chr(0)); + + $ipad = (substr($key, 0, 64) ^ str_repeat(chr(0x36), 64)); + $opad = (substr($key, 0, 64) ^ str_repeat(chr(0x5C), 64)); + + return $algo($opad . pack($pack, $algo($ipad . $data))); +} +endif; + // Added in PHP 4.3.0? if (!defined('IMAGETYPE_GIF')) define('IMAGETYPE_GIF', 1); diff --git a/wp-includes/pluggable.php b/wp-includes/pluggable.php index b628e9e7a..46b877d42 100644 --- a/wp-includes/pluggable.php +++ b/wp-includes/pluggable.php @@ -46,14 +46,12 @@ function get_currentuserinfo() { if ( ! empty($current_user) ) return; - if ( empty($_COOKIE[USER_COOKIE]) || empty($_COOKIE[PASS_COOKIE]) || - !wp_login($_COOKIE[USER_COOKIE], $_COOKIE[PASS_COOKIE], true) ) { + if ( ! $user = wp_validate_auth_cookie() ) { wp_set_current_user(0); return false; } - $user_login = $_COOKIE[USER_COOKIE]; - wp_set_current_user(0, $user_login); + wp_set_current_user($user); } endif; @@ -293,7 +291,7 @@ function wp_mail( $to, $subject, $message, $headers = '' ) { endif; if ( !function_exists('wp_login') ) : -function wp_login($username, $password, $already_md5 = false) { +function wp_login($username, $password, $deprecated = false) { global $wpdb, $error; $username = sanitize_user($username); @@ -313,26 +311,87 @@ function wp_login($username, $password, $already_md5 = false) { return false; } - // If the password is already_md5, it has been double hashed. - // Otherwise, it is plain text. - if ( !$already_md5 ) { - if ( wp_check_password($password, $login->user_pass) ) { - // If using old md5 password, rehash. - if ( strlen($login->user_pass) <= 32 ) { - $hash = wp_hash_password($password); - $wpdb->query("UPDATE $wpdb->users SET user_pass = '$hash', user_activation_key = '' WHERE ID = '$login->ID'"); - wp_cache_delete($login->ID, 'users'); - } - - return true; - } - } else { - if ( md5($login->user_pass) == $password ) - return true; + if ( !wp_check_password($password, $login->user_pass) ) { + $error = __('ERROR: Incorrect password.'); + return false; } - $error = __('ERROR: Incorrect password.'); - return false; + // If using old md5 password, rehash. + if ( strlen($login->user_pass) <= 32 ) { + $hash = wp_hash_password($password); + $wpdb->query("UPDATE $wpdb->users SET user_pass = '$hash', user_activation_key = '' WHERE ID = '$login->ID'"); + wp_cache_delete($login->ID, 'users'); + } + + return true; +} +endif; + +if ( !function_exists('wp_validate_auth_cookie') ) : +function wp_validate_auth_cookie($cookie = '') { + if ( empty($cookie) ) { + if ( empty($_COOKIE[AUTH_COOKIE]) ) + return false; + $cookie = $_COOKIE[AUTH_COOKIE]; + } + + list($username, $expiration, $hmac) = explode('|', $cookie); + + $expired = $expiration; + + // Allow a grace period for POST requests + if ( 'POST' == $_SERVER['REQUEST_METHOD'] ) + $expired += 3600; + + if ( $expired < time() ) + return false; + + $key = wp_hash($username . $expiration); + $hash = hash_hmac('md5', $username . $expiration, $key); + + if ( $hmac != $hash ) + return false; + + $user = get_userdatabylogin($username); + if ( ! $user ) + return false; + + return $user->ID; +} +endif; + +if ( !function_exists('wp_set_auth_cookie') ) : +function wp_set_auth_cookie($user_id, $remember = false) { + $user = get_userdata($user_id); + + if ( $remember ) { + $expiration = $expire = time() + 1209600; + } else { + $expiration = time() + 172800; + $expire = 0; + } + + $key = wp_hash($user->user_login . $expiration); + $hash = hash_hmac('md5', $user->user_login . $expiration, $key); + + $cookie = $user->user_login . '|' . $expiration . '|' . $hash; + + setcookie(AUTH_COOKIE, $cookie, $expire, COOKIEPATH, COOKIE_DOMAIN); + if ( COOKIEPATH != SITECOOKIEPATH ) + setcookie(AUTH_COOKIE, $cookie, $expire, SITECOOKIEPATH, COOKIE_DOMAIN); +} +endif; + +if ( !function_exists('wp_clear_auth_cookie') ) : +function wp_clear_auth_cookie() { + setcookie(AUTH_COOKIE, ' ', time() - 31536000, COOKIEPATH, COOKIE_DOMAIN); + setcookie(AUTH_COOKIE, ' ', time() - 31536000, SITECOOKIEPATH, COOKIE_DOMAIN); + + // Old cookies + setcookie(USER_COOKIE, ' ', time() - 31536000, COOKIEPATH, COOKIE_DOMAIN); + setcookie(PASS_COOKIE, ' ', time() - 31536000, COOKIEPATH, COOKIE_DOMAIN); + setcookie(USER_COOKIE, ' ', time() - 31536000, SITECOOKIEPATH, COOKIE_DOMAIN); + setcookie(PASS_COOKIE, ' ', time() - 31536000, SITECOOKIEPATH, COOKIE_DOMAIN); } endif; @@ -350,9 +409,9 @@ endif; if ( !function_exists('auth_redirect') ) : function auth_redirect() { // Checks if a user is logged in, if not redirects them to the login page - if ( (!empty($_COOKIE[USER_COOKIE]) && - !wp_login($_COOKIE[USER_COOKIE], $_COOKIE[PASS_COOKIE], true)) || - (empty($_COOKIE[USER_COOKIE])) ) { + if ( (!empty($_COOKIE[AUTH_COOKIE]) && + !wp_validate_auth_cookie($_COOKIE[AUTH_COOKIE])) || + (empty($_COOKIE[AUTH_COOKIE])) ) { nocache_headers(); wp_redirect(get_option('siteurl') . '/wp-login.php?redirect_to=' . urlencode($_SERVER['REQUEST_URI'])); @@ -379,19 +438,18 @@ function check_ajax_referer( $action = -1 ) { if ( !wp_verify_nonce( $nonce, $action ) ) { $current_name = ''; if ( ( $current = wp_get_current_user() ) && $current->ID ) - $current_name = $current->data->user_login; + $current_name = $current->user_login; if ( !$current_name ) die('-1'); + $auth_cookie = ''; $cookie = explode('; ', urldecode(empty($_POST['cookie']) ? $_GET['cookie'] : $_POST['cookie'])); // AJAX scripts must pass cookie=document.cookie foreach ( $cookie as $tasty ) { - if ( false !== strpos($tasty, USER_COOKIE) ) - $user = substr(strstr($tasty, '='), 1); - if ( false !== strpos($tasty, PASS_COOKIE) ) - $pass = substr(strstr($tasty, '='), 1); + if ( false !== strpos($tasty, AUTH_COOKIE) ) + $auth_cookie = substr(strstr($tasty, '='), 1); } - if ( $current_name != $user || !wp_login( $user, $pass, true ) ) + if ( $current_name != $user || empty($auth_cookie) || !wp_validate_auth_cookie( $auth_cookie ) ) die('-1'); } do_action('check_ajax_referer'); @@ -472,60 +530,6 @@ function wp_safe_redirect($location, $status = 302) { } endif; -if ( !function_exists('wp_get_cookie_login') ): -function wp_get_cookie_login() { - if ( empty($_COOKIE[USER_COOKIE]) || empty($_COOKIE[PASS_COOKIE]) ) - return false; - - return array('login' => $_COOKIE[USER_COOKIE], 'password' => $_COOKIE[PASS_COOKIE]); -} - -endif; - -if ( !function_exists('wp_setcookie') ) : -function wp_setcookie($username, $password, $already_md5 = false, $home = '', $siteurl = '', $remember = false) { - $user = get_userdatabylogin($username); - if ( !$already_md5) { - $password = md5($user->user_pass); // Double hash the password in the cookie. - } - - if ( empty($home) ) - $cookiepath = COOKIEPATH; - else - $cookiepath = preg_replace('|https?://[^/]+|i', '', $home . '/' ); - - if ( empty($siteurl) ) { - $sitecookiepath = SITECOOKIEPATH; - $cookiehash = COOKIEHASH; - } else { - $sitecookiepath = preg_replace('|https?://[^/]+|i', '', $siteurl . '/' ); - $cookiehash = md5($siteurl); - } - - if ( $remember ) - $expire = time() + 31536000; - else - $expire = 0; - - setcookie(USER_COOKIE, $username, $expire, $cookiepath, COOKIE_DOMAIN); - setcookie(PASS_COOKIE, $password, $expire, $cookiepath, COOKIE_DOMAIN); - - if ( $cookiepath != $sitecookiepath ) { - setcookie(USER_COOKIE, $username, $expire, $sitecookiepath, COOKIE_DOMAIN); - setcookie(PASS_COOKIE, $password, $expire, $sitecookiepath, COOKIE_DOMAIN); - } -} -endif; - -if ( !function_exists('wp_clearcookie') ) : -function wp_clearcookie() { - setcookie(USER_COOKIE, ' ', time() - 31536000, COOKIEPATH, COOKIE_DOMAIN); - setcookie(PASS_COOKIE, ' ', time() - 31536000, COOKIEPATH, COOKIE_DOMAIN); - setcookie(USER_COOKIE, ' ', time() - 31536000, SITECOOKIEPATH, COOKIE_DOMAIN); - setcookie(PASS_COOKIE, ' ', time() - 31536000, SITECOOKIEPATH, COOKIE_DOMAIN); -} -endif; - if ( ! function_exists('wp_notify_postauthor') ) : function wp_notify_postauthor($comment_id, $comment_type='') { $comment = get_comment($comment_id); @@ -692,10 +696,17 @@ endif; if ( !function_exists('wp_salt') ) : function wp_salt() { $salt = get_option('secret'); - if ( empty($salt) ) - $salt = DB_PASSWORD . DB_USER . DB_NAME . DB_HOST . ABSPATH; + if ( empty($salt) ) { + $salt = wp_generate_password(); + update_option('secret', $salt); + } - return $salt; + if ( !defined('SECRET_KEY') || '' == SECRET_KEY ) + $secret_key = DB_PASSWORD . DB_USER . DB_NAME . DB_HOST . ABSPATH; + else + $secret_key = SECRET_KEY; + + return $salt . $secret_key; } endif; @@ -758,4 +769,27 @@ function wp_generate_password() { return $password; } endif; + +// Deprecated. Use wp_set_auth_cookie() +if ( !function_exists('wp_setcookie') ) : +function wp_setcookie($username, $password = '', $already_md5 = false, $home = '', $siteurl = '', $remember = false) { + $user = get_userdatabylogin($username); + wp_set_auth_cookie($user->ID, $remember); +} +endif; + +// Deprecated. Use wp_clear_auth_cookie() +if ( !function_exists('wp_clearcookie') ) : +function wp_clearcookie() { + wp_clear_auth_cookie(); +} +endif; + +// Deprecated. No alternative. +if ( !function_exists('wp_get_cookie_login') ): +function wp_get_cookie_login() { + return false; +} +endif; + ?> diff --git a/wp-includes/registration.php b/wp-includes/registration.php index 7f7b7d2a3..769f0a588 100644 --- a/wp-includes/registration.php +++ b/wp-includes/registration.php @@ -167,8 +167,8 @@ function wp_update_user($userdata) { $current_user = wp_get_current_user(); if ( $current_user->id == $ID ) { if ( isset($plaintext_pass) ) { - wp_clearcookie(); - wp_setcookie($userdata['user_login'], $plaintext_pass); + wp_clear_auth_cookie(); + wp_set_auth_cookie($ID); } } diff --git a/wp-login.php b/wp-login.php index 645447546..20945281f 100644 --- a/wp-login.php +++ b/wp-login.php @@ -288,7 +288,6 @@ case 'login' : default: $user_login = ''; $user_pass = ''; - $using_cookie = FALSE; if ( !isset( $_REQUEST['redirect_to'] ) || is_user_logged_in() ) $redirect_to = 'wp-admin/'; @@ -296,25 +295,31 @@ default: $redirect_to = $_REQUEST['redirect_to']; if ( $http_post ) { + // If cookies are disabled we can't log in even with a valid user+pass + if ( empty($_COOKIE[TEST_COOKIE]) ) + $errors['test_cookie'] = __('ERROR: WordPress requires Cookies but your browser does not support them or they are blocked.'); + $user_login = $_POST['log']; $user_login = sanitize_user( $user_login ); $user_pass = $_POST['pwd']; $rememberme = $_POST['rememberme']; + + do_action_ref_array('wp_authenticate', array(&$user_login, &$user_pass)); } else { - $cookie_login = wp_get_cookie_login(); - if ( ! empty($cookie_login) ) { - $using_cookie = true; - $user_login = $cookie_login['login']; - $user_pass = $cookie_login['password']; + $user = wp_validate_auth_cookie(); + if ( !$user ) { + $errors['expiredsession'] = __('Your session has expired.'); + } else { + $user = new WP_User($user); + + // If the user can't edit posts, send them to their profile. + if ( !$user->has_cap('edit_posts') && ( empty( $redirect_to ) || $redirect_to == 'wp-admin/' ) ) + $redirect_to = get_option('siteurl') . '/wp-admin/profile.php'; + wp_safe_redirect($redirect_to); + exit(); } } - do_action_ref_array('wp_authenticate', array(&$user_login, &$user_pass)); - - // If cookies are disabled we can't log in even with a valid user+pass - if ( $http_post && empty($_COOKIE[TEST_COOKIE]) ) - $errors['test_cookie'] = __('ERROR: WordPress requires Cookies but your browser does not support them or they are blocked.'); - if ( $user_login && $user_pass && empty( $errors ) ) { $user = new WP_User(0, $user_login); @@ -322,15 +327,11 @@ default: if ( !$user->has_cap('edit_posts') && ( empty( $redirect_to ) || $redirect_to == 'wp-admin/' ) ) $redirect_to = get_option('siteurl') . '/wp-admin/profile.php'; - if ( wp_login($user_login, $user_pass, $using_cookie) ) { - if ( !$using_cookie ) - wp_setcookie($user_login, $user_pass, false, '', '', $rememberme); + if ( wp_login($user_login, $user_pass) ) { + wp_set_auth_cookie($user->ID, $rememberme); do_action('wp_login', $user_login); wp_safe_redirect($redirect_to); exit(); - } else { - if ( $using_cookie ) - $errors['expiredsession'] = __('Your session has expired.'); } } diff --git a/wp-settings.php b/wp-settings.php index 0672536c8..d3ae5d526 100644 --- a/wp-settings.php +++ b/wp-settings.php @@ -186,9 +186,11 @@ if (strpos($_SERVER['PHP_SELF'], 'install.php') === false) { } if ( !defined('USER_COOKIE') ) - define('USER_COOKIE', 'wordpressuser_'. COOKIEHASH); + define('USER_COOKIE', 'wordpressuser_' . COOKIEHASH); if ( !defined('PASS_COOKIE') ) - define('PASS_COOKIE', 'wordpresspass_'. COOKIEHASH); + define('PASS_COOKIE', 'wordpresspass_' . COOKIEHASH); +if ( !defined('AUTH_COOKIE') ) + define('AUTH_COOKIE', 'wordpress_' . COOKIEHASH); if ( !defined('TEST_COOKIE') ) define('TEST_COOKIE', 'wordpress_test_cookie'); if ( !defined('COOKIEPATH') )