WordPress.org

Make WordPress Core

Ticket #5367: secure_cookie.3.diff

File secure_cookie.3.diff, 11.6 KB (added by ryan, 10 years ago)

Allow POST requests a grace period

  • wp-login.php

     
    288288default:
    289289        $user_login = '';
    290290        $user_pass = '';
    291         $using_cookie = FALSE;
    292291
    293292        if ( !isset( $_REQUEST['redirect_to'] ) || is_user_logged_in() )
    294293                $redirect_to = 'wp-admin/';
     
    296295                $redirect_to = $_REQUEST['redirect_to'];
    297296
    298297        if ( $http_post ) {
     298                // If cookies are disabled we can't log in even with a valid user+pass
     299                if ( empty($_COOKIE[TEST_COOKIE]) )
     300                        $errors['test_cookie'] = __('<strong>ERROR</strong>: WordPress requires Cookies but your browser does not support them or they are blocked.');
     301               
    299302                $user_login = $_POST['log'];
    300303                $user_login = sanitize_user( $user_login );
    301304                $user_pass  = $_POST['pwd'];
    302305                $rememberme = $_POST['rememberme'];
     306
     307                do_action_ref_array('wp_authenticate', array(&$user_login, &$user_pass));
    303308        } else {
    304                 $cookie_login = wp_get_cookie_login();
    305                 if ( ! empty($cookie_login) ) {
    306                         $using_cookie = true;
    307                         $user_login = $cookie_login['login'];
    308                         $user_pass = $cookie_login['password'];
     309                $user = wp_validate_auth_cookie();
     310                if ( !$user ) {
     311                        $errors['expiredsession'] = __('Your session has expired.');
     312                } else {
     313                        $user = new WP_User($user);
     314
     315                        // If the user can't edit posts, send them to their profile.
     316                        if ( !$user->has_cap('edit_posts') && ( empty( $redirect_to ) || $redirect_to == 'wp-admin/' ) )
     317                                $redirect_to = get_option('siteurl') . '/wp-admin/profile.php';
     318                        wp_safe_redirect($redirect_to);
     319                        exit();
    309320                }
    310321        }
    311322
    312         do_action_ref_array('wp_authenticate', array(&$user_login, &$user_pass));
    313 
    314         // If cookies are disabled we can't log in even with a valid user+pass
    315         if ( $http_post && empty($_COOKIE[TEST_COOKIE]) )
    316                 $errors['test_cookie'] = __('<strong>ERROR</strong>: WordPress requires Cookies but your browser does not support them or they are blocked.');
    317 
    318323        if ( $user_login && $user_pass && empty( $errors ) ) {
    319324                $user = new WP_User(0, $user_login);
    320325
     
    322327                if ( !$user->has_cap('edit_posts') && ( empty( $redirect_to ) || $redirect_to == 'wp-admin/' ) )
    323328                        $redirect_to = get_option('siteurl') . '/wp-admin/profile.php';
    324329
    325                 if ( wp_login($user_login, $user_pass, $using_cookie) ) {
    326                         if ( !$using_cookie )
    327                                 wp_setcookie($user_login, $user_pass, false, '', '', $rememberme);
     330                if ( wp_login($user_login, $user_pass) ) {
     331                        wp_setcookie($user_login, $user_pass, false, '', '', $rememberme);
    328332                        do_action('wp_login', $user_login);
    329333                        wp_safe_redirect($redirect_to);
    330334                        exit();
    331                 } else {
    332                         if ( $using_cookie )
    333                                 $errors['expiredsession'] = __('Your session has expired.');
    334335                }
    335336        }
    336337
  • wp-includes/compat.php

     
    147147        }
    148148}
    149149
     150if ( ! function_exists('hash_hmac') ):
     151function hash_hmac($algo, $data, $key, $raw_output = false) {
     152        $packs = array('md5' => 'H32', 'sha1' => 'H40');
     153
     154        if ( !isset($packs[$algo]) )
     155                return false;
     156
     157        $pack = $packs[$algo];
     158
     159        if (strlen($key) > 64)
     160                $key = pack($pack, $algo($key));
     161        else if (strlen($key) < 64)
     162                $key = str_pad($key, 64, chr(0));
     163       
     164        $ipad = (substr($key, 0, 64) ^ str_repeat(chr(0x36), 64));
     165        $opad = (substr($key, 0, 64) ^ str_repeat(chr(0x5C), 64));
     166
     167        return $algo($opad . pack($pack, $algo($ipad . $data)));
     168}
     169endif;
     170
    150171// Added in PHP 4.3.0?
    151172if (!defined('IMAGETYPE_GIF'))
    152173    define('IMAGETYPE_GIF', 1);
  • wp-includes/pluggable.php

     
    4646        if ( ! empty($current_user) )
    4747                return;
    4848
    49         if ( empty($_COOKIE[USER_COOKIE]) || empty($_COOKIE[PASS_COOKIE]) ||
    50                 !wp_login($_COOKIE[USER_COOKIE], $_COOKIE[PASS_COOKIE], true) ) {
     49        if ( ! $user = wp_validate_auth_cookie() ) {
    5150                wp_set_current_user(0);
    5251                return false;
    5352        }
    5453
    55         $user_login = $_COOKIE[USER_COOKIE];
    56         wp_set_current_user(0, $user_login);
     54        wp_set_current_user($user);
    5755}
    5856endif;
    5957
     
    293291endif;
    294292
    295293if ( !function_exists('wp_login') ) :
    296 function wp_login($username, $password, $already_md5 = false) {
     294function wp_login($username, $password, $deprecated = false) {
    297295        global $wpdb, $error;
    298296
    299297        $username = sanitize_user($username);
     
    313311                return false;
    314312        }
    315313
    316         // If the password is already_md5, it has been double hashed.
    317         // Otherwise, it is plain text.
    318         if ( !$already_md5 ) {
    319                 if ( wp_check_password($password, $login->user_pass) ) {
    320                         // If using old md5 password, rehash.
    321                         if ( strlen($login->user_pass) <= 32 ) {
    322                                 $hash = wp_hash_password($password);
    323                                 $wpdb->query("UPDATE $wpdb->users SET user_pass = '$hash', user_activation_key = '' WHERE ID = '$login->ID'");
    324                                 wp_cache_delete($login->ID, 'users');
    325                         }
     314        if ( !wp_check_password($password, $login->user_pass) ) {
     315                $error = __('<strong>ERROR</strong>: Incorrect password.');
     316                return false;
     317        }
    326318
    327                         return true;
    328                 }
     319        // If using old md5 password, rehash.
     320        if ( strlen($login->user_pass) <= 32 ) {
     321                $hash = wp_hash_password($password);
     322                $wpdb->query("UPDATE $wpdb->users SET user_pass = '$hash', user_activation_key = '' WHERE ID = '$login->ID'");
     323                wp_cache_delete($login->ID, 'users');
     324        }
     325
     326        return true;
     327}
     328endif;
     329
     330if ( !function_exists('wp_validate_auth_cookie') ) :
     331function wp_validate_auth_cookie($cookie = '') {
     332        if ( empty($cookie) ) {
     333                if ( empty($_COOKIE[AUTH_COOKIE]) )
     334                        return false;
     335                $cookie = $_COOKIE[AUTH_COOKIE];
     336        }
     337
     338        list($username, $expiration, $hmac) = explode('|', $cookie);
     339
     340        // Allow a grace period for POST requests
     341        if ( 'POST' == $_SERVER['REQUEST_METHOD'] )
     342                $expiration += 3600;
     343
     344        if ( $expiration < time() )
     345                return false;
     346
     347        $key = wp_hash($username . $expiration);
     348        $hash = hash_hmac('md5', $username . $expiration, $key);
     349       
     350        if ( $hmac != $hash )
     351                return false;
     352
     353        $user = get_userdatabylogin($username);
     354        if ( ! $user )
     355                return false;
     356
     357        return $user->ID;
     358}
     359endif;
     360
     361if ( !function_exists('wp_set_auth_cookie') ) :
     362function wp_set_auth_cookie($user_id, $remember = false) {
     363        $user = get_userdata($user_id);
     364
     365        if ( $remember ) {
     366                $expiration = $expire = time() + 1209600;
    329367        } else {
    330                 if ( md5($login->user_pass) == $password )
    331                         return true;
     368                $expiration = time() + 172800;
     369                $expire = 0;
    332370        }
    333371
    334         $error = __('<strong>ERROR</strong>: Incorrect password.');
    335         return false;
     372        $key = wp_hash($user->user_login . $expiration);
     373        $hash = hash_hmac('md5', $user->user_login . $expiration, $key);
     374
     375        $cookie = $user->user_login . '|' . $expiration . '|' . $hash;
     376
     377        setcookie(AUTH_COOKIE, $cookie, $expire, COOKIEPATH, COOKIE_DOMAIN);
     378        if ( COOKIEPATH != SITECOOKIEPATH )
     379                setcookie(AUTH_COOKIE, $cookie, $expire, SITECOOKIEPATH, COOKIE_DOMAIN);
    336380}
    337381endif;
    338382
     
    350394if ( !function_exists('auth_redirect') ) :
    351395function auth_redirect() {
    352396        // Checks if a user is logged in, if not redirects them to the login page
    353         if ( (!empty($_COOKIE[USER_COOKIE]) &&
    354                                 !wp_login($_COOKIE[USER_COOKIE], $_COOKIE[PASS_COOKIE], true)) ||
    355                          (empty($_COOKIE[USER_COOKIE])) ) {
     397        if ( (!empty($_COOKIE[AUTH_COOKIE]) &&
     398                                !wp_validate_auth_cookie($_COOKIE[AUTH_COOKIE])) ||
     399                         (empty($_COOKIE[AUTH_COOKIE])) ) {
    356400                nocache_headers();
    357401
    358402                wp_redirect(get_option('siteurl') . '/wp-login.php?redirect_to=' . urlencode($_SERVER['REQUEST_URI']));
     
    379423        if ( !wp_verify_nonce( $nonce, $action ) ) {
    380424                $current_name = '';
    381425                if ( ( $current = wp_get_current_user() ) && $current->ID )
    382                         $current_name = $current->data->user_login;
     426                        $current_name = $current->user_login;
    383427                if ( !$current_name )
    384428                        die('-1');
    385429
     430                $auth_cookie = '';
    386431                $cookie = explode('; ', urldecode(empty($_POST['cookie']) ? $_GET['cookie'] : $_POST['cookie'])); // AJAX scripts must pass cookie=document.cookie
    387432                foreach ( $cookie as $tasty ) {
    388                         if ( false !== strpos($tasty, USER_COOKIE) )
    389                                 $user = substr(strstr($tasty, '='), 1);
    390                         if ( false !== strpos($tasty, PASS_COOKIE) )
    391                                 $pass = substr(strstr($tasty, '='), 1);
     433                        if ( false !== strpos($tasty, AUTH_COOKIE) )
     434                                $auth_cookie = substr(strstr($tasty, '='), 1);
    392435                }
    393436
    394                 if ( $current_name != $user || !wp_login( $user, $pass, true ) )
     437                if ( $current_name != $user || empty($auth_cookie) || !wp_validate_auth_cookie( $auth_cookie ) )
    395438                        die('-1');
    396439        }
    397440        do_action('check_ajax_referer');
     
    483526endif;
    484527
    485528if ( !function_exists('wp_setcookie') ) :
    486 function wp_setcookie($username, $password, $already_md5 = false, $home = '', $siteurl = '', $remember = false) {
     529function wp_setcookie($username, $password = '', $already_md5 = false, $home = '', $siteurl = '', $remember = false) {
    487530        $user = get_userdatabylogin($username);
    488         if ( !$already_md5) {
    489                 $password = md5($user->user_pass); // Double hash the password in the cookie.
    490         }
    491 
    492         if ( empty($home) )
    493                 $cookiepath = COOKIEPATH;
    494         else
    495                 $cookiepath = preg_replace('|https?://[^/]+|i', '', $home . '/' );
    496 
    497         if ( empty($siteurl) ) {
    498                 $sitecookiepath = SITECOOKIEPATH;
    499                 $cookiehash = COOKIEHASH;
    500         } else {
    501                 $sitecookiepath = preg_replace('|https?://[^/]+|i', '', $siteurl . '/' );
    502                 $cookiehash = md5($siteurl);
    503         }
    504 
    505         if ( $remember )
    506                 $expire = time() + 31536000;
    507         else
    508                 $expire = 0;
    509 
    510         setcookie(USER_COOKIE, $username, $expire, $cookiepath, COOKIE_DOMAIN);
    511         setcookie(PASS_COOKIE, $password, $expire, $cookiepath, COOKIE_DOMAIN);
    512 
    513         if ( $cookiepath != $sitecookiepath ) {
    514                 setcookie(USER_COOKIE, $username, $expire, $sitecookiepath, COOKIE_DOMAIN);
    515                 setcookie(PASS_COOKIE, $password, $expire, $sitecookiepath, COOKIE_DOMAIN);
    516         }
     531        wp_set_auth_cookie($user->ID, $remember);
    517532}
    518533endif;
    519534
    520535if ( !function_exists('wp_clearcookie') ) :
    521536function wp_clearcookie() {
     537        setcookie(AUTH_COOKIE, ' ', time() - 31536000, COOKIEPATH, COOKIE_DOMAIN);
     538        setcookie(AUTH_COOKIE, ' ', time() - 31536000, SITECOOKIEPATH, COOKIE_DOMAIN);
     539
     540        // Old cookies
    522541        setcookie(USER_COOKIE, ' ', time() - 31536000, COOKIEPATH, COOKIE_DOMAIN);
    523542        setcookie(PASS_COOKIE, ' ', time() - 31536000, COOKIEPATH, COOKIE_DOMAIN);
    524543        setcookie(USER_COOKIE, ' ', time() - 31536000, SITECOOKIEPATH, COOKIE_DOMAIN);
     
    695714        if ( empty($salt) )
    696715                $salt = DB_PASSWORD . DB_USER . DB_NAME . DB_HOST . ABSPATH;
    697716
    698         return $salt;
     717        if ( ! defined('SECRET_KEY') )
     718                $secret_key = 'shhhh';
     719        else
     720                $secret_key = SECRET_KEY;
     721               
     722        return $salt . $secret_key;
    699723}
    700724endif;
    701725
  • wp-config-sample.php

     
    66define('DB_HOST', 'localhost');    // 99% chance you won't need to change this value
    77define('DB_CHARSET', 'utf8');
    88define('DB_COLLATE', '');
     9define('SECRET_KEY', 'shhhh'); // Change this to something unique
    910
    1011// You can have multiple installations in one database if you give each a unique prefix
    1112$table_prefix  = 'wp_';   // Only numbers, letters, and underscores please!
  • wp-settings.php

     
    186186}
    187187
    188188if ( !defined('USER_COOKIE') )
    189         define('USER_COOKIE', 'wordpressuser_'. COOKIEHASH);
     189        define('USER_COOKIE', 'wordpressuser_' . COOKIEHASH);
    190190if ( !defined('PASS_COOKIE') )
    191         define('PASS_COOKIE', 'wordpresspass_'. COOKIEHASH);
     191        define('PASS_COOKIE', 'wordpresspass_' . COOKIEHASH);
     192if ( !defined('AUTH_COOKIE') )
     193        define('AUTH_COOKIE', 'wordpress_' . COOKIEHASH);
    192194if ( !defined('TEST_COOKIE') )
    193195        define('TEST_COOKIE', 'wordpress_test_cookie');
    194196if ( !defined('COOKIEPATH') )