Ticket #5367: secure_cookie.5.diff

File secure_cookie.5.diff, 14.7 KB (added by ryan, 5 years ago)
Line 
1Index: wp-login.php
2===================================================================
3--- wp-login.php        (revision 6385)
4+++ wp-login.php        (working copy)
5@@ -288,7 +288,6 @@
6 default:
7        $user_login = '';
8        $user_pass = '';
9-       $using_cookie = FALSE;
10 
11        if ( !isset( $_REQUEST['redirect_to'] ) || is_user_logged_in() )
12                $redirect_to = 'wp-admin/';
13@@ -296,25 +295,31 @@
14                $redirect_to = $_REQUEST['redirect_to'];
15 
16        if ( $http_post ) {
17+               // If cookies are disabled we can't log in even with a valid user+pass
18+               if ( empty($_COOKIE[TEST_COOKIE]) )
19+                       $errors['test_cookie'] = __('<strong>ERROR</strong>: WordPress requires Cookies but your browser does not support them or they are blocked.');
20+               
21                $user_login = $_POST['log'];
22                $user_login = sanitize_user( $user_login );
23                $user_pass  = $_POST['pwd'];
24                $rememberme = $_POST['rememberme'];
25+
26+               do_action_ref_array('wp_authenticate', array(&$user_login, &$user_pass));
27        } else {
28-               $cookie_login = wp_get_cookie_login();
29-               if ( ! empty($cookie_login) ) {
30-                       $using_cookie = true;
31-                       $user_login = $cookie_login['login'];
32-                       $user_pass = $cookie_login['password'];
33+               $user = wp_validate_auth_cookie();
34+               if ( !$user ) {
35+                       $errors['expiredsession'] = __('Your session has expired.');
36+               } else {
37+                       $user = new WP_User($user);
38+
39+                       // If the user can't edit posts, send them to their profile.
40+                       if ( !$user->has_cap('edit_posts') && ( empty( $redirect_to ) || $redirect_to == 'wp-admin/' ) )
41+                               $redirect_to = get_option('siteurl') . '/wp-admin/profile.php';
42+                       wp_safe_redirect($redirect_to);
43+                       exit();
44                }
45        }
46 
47-       do_action_ref_array('wp_authenticate', array(&$user_login, &$user_pass));
48-
49-       // If cookies are disabled we can't log in even with a valid user+pass
50-       if ( $http_post && empty($_COOKIE[TEST_COOKIE]) )
51-               $errors['test_cookie'] = __('<strong>ERROR</strong>: WordPress requires Cookies but your browser does not support them or they are blocked.');
52-
53        if ( $user_login && $user_pass && empty( $errors ) ) {
54                $user = new WP_User(0, $user_login);
55 
56@@ -322,15 +327,11 @@
57                if ( !$user->has_cap('edit_posts') && ( empty( $redirect_to ) || $redirect_to == 'wp-admin/' ) )
58                        $redirect_to = get_option('siteurl') . '/wp-admin/profile.php';
59 
60-               if ( wp_login($user_login, $user_pass, $using_cookie) ) {
61-                       if ( !$using_cookie )
62-                               wp_setcookie($user_login, $user_pass, false, '', '', $rememberme);
63+               if ( wp_login($user_login, $user_pass) ) {
64+                       wp_set_auth_cookie($user->ID, $rememberme);
65                        do_action('wp_login', $user_login);
66                        wp_safe_redirect($redirect_to);
67                        exit();
68-               } else {
69-                       if ( $using_cookie )
70-                               $errors['expiredsession'] = __('Your session has expired.');
71                }
72        }
73 
74Index: wp-includes/compat.php
75===================================================================
76--- wp-includes/compat.php      (revision 6385)
77+++ wp-includes/compat.php      (working copy)
78@@ -147,6 +147,27 @@
79        }
80 }
81 
82+if ( ! function_exists('hash_hmac') ):
83+function hash_hmac($algo, $data, $key, $raw_output = false) {
84+       $packs = array('md5' => 'H32', 'sha1' => 'H40');
85+
86+       if ( !isset($packs[$algo]) )
87+               return false;
88+
89+       $pack = $packs[$algo];
90+
91+       if (strlen($key) > 64)
92+               $key = pack($pack, $algo($key));
93+       else if (strlen($key) < 64)
94+               $key = str_pad($key, 64, chr(0));
95+       
96+       $ipad = (substr($key, 0, 64) ^ str_repeat(chr(0x36), 64));
97+       $opad = (substr($key, 0, 64) ^ str_repeat(chr(0x5C), 64));
98+
99+       return $algo($opad . pack($pack, $algo($ipad . $data)));
100+}
101+endif;
102+
103 // Added in PHP 4.3.0?
104 if (!defined('IMAGETYPE_GIF'))
105     define('IMAGETYPE_GIF', 1);
106Index: wp-includes/pluggable.php
107===================================================================
108--- wp-includes/pluggable.php   (revision 6385)
109+++ wp-includes/pluggable.php   (working copy)
110@@ -46,14 +46,12 @@
111        if ( ! empty($current_user) )
112                return;
113 
114-       if ( empty($_COOKIE[USER_COOKIE]) || empty($_COOKIE[PASS_COOKIE]) ||
115-               !wp_login($_COOKIE[USER_COOKIE], $_COOKIE[PASS_COOKIE], true) ) {
116+       if ( ! $user = wp_validate_auth_cookie() ) {
117                wp_set_current_user(0);
118                return false;
119        }
120 
121-       $user_login = $_COOKIE[USER_COOKIE];
122-       wp_set_current_user(0, $user_login);
123+       wp_set_current_user($user);
124 }
125 endif;
126 
127@@ -293,7 +291,7 @@
128 endif;
129 
130 if ( !function_exists('wp_login') ) :
131-function wp_login($username, $password, $already_md5 = false) {
132+function wp_login($username, $password, $deprecated = false) {
133        global $wpdb, $error;
134 
135        $username = sanitize_user($username);
136@@ -313,29 +311,90 @@
137                return false;
138        }
139 
140-       // If the password is already_md5, it has been double hashed.
141-       // Otherwise, it is plain text.
142-       if ( !$already_md5 ) {
143-               if ( wp_check_password($password, $login->user_pass) ) {
144-                       // If using old md5 password, rehash.
145-                       if ( strlen($login->user_pass) <= 32 ) {
146-                               $hash = wp_hash_password($password);
147-                               $wpdb->query("UPDATE $wpdb->users SET user_pass = '$hash', user_activation_key = '' WHERE ID = '$login->ID'");
148-                               wp_cache_delete($login->ID, 'users');
149-                       }
150+       if ( !wp_check_password($password, $login->user_pass) ) {
151+               $error = __('<strong>ERROR</strong>: Incorrect password.');
152+               return false;
153+       }
154 
155-                       return true;
156-               }
157+       // If using old md5 password, rehash.
158+       if ( strlen($login->user_pass) <= 32 ) {
159+               $hash = wp_hash_password($password);
160+               $wpdb->query("UPDATE $wpdb->users SET user_pass = '$hash', user_activation_key = '' WHERE ID = '$login->ID'");
161+               wp_cache_delete($login->ID, 'users');
162+       }
163+
164+       return true;
165+}
166+endif;
167+
168+if ( !function_exists('wp_validate_auth_cookie') ) :
169+function wp_validate_auth_cookie($cookie = '') {
170+       if ( empty($cookie) ) {
171+               if ( empty($_COOKIE[AUTH_COOKIE]) )
172+                       return false;
173+               $cookie = $_COOKIE[AUTH_COOKIE];
174+       }
175+
176+       list($username, $expiration, $hmac) = explode('|', $cookie);
177+
178+       $expired = $expiration;
179+
180+       // Allow a grace period for POST requests
181+       if ( 'POST' == $_SERVER['REQUEST_METHOD'] )
182+               $expired += 3600;
183+
184+       if ( $expired < time() )
185+               return false;
186+
187+       $key = wp_hash($username . $expiration);
188+       $hash = hash_hmac('md5', $username . $expiration, $key);
189+       
190+       if ( $hmac != $hash )
191+               return false;
192+
193+       $user = get_userdatabylogin($username);
194+       if ( ! $user )
195+               return false;
196+
197+       return $user->ID;
198+}
199+endif;
200+
201+if ( !function_exists('wp_set_auth_cookie') ) :
202+function wp_set_auth_cookie($user_id, $remember = false) {
203+       $user = get_userdata($user_id);
204+
205+       if ( $remember ) {
206+               $expiration = $expire = time() + 1209600;
207        } else {
208-               if ( md5($login->user_pass) == $password )
209-                       return true;
210+               $expiration = time() + 172800;
211+               $expire = 0;
212        }
213 
214-       $error = __('<strong>ERROR</strong>: Incorrect password.');
215-       return false;
216+       $key = wp_hash($user->user_login . $expiration);
217+       $hash = hash_hmac('md5', $user->user_login . $expiration, $key);
218+
219+       $cookie = $user->user_login . '|' . $expiration . '|' . $hash;
220+
221+       setcookie(AUTH_COOKIE, $cookie, $expire, COOKIEPATH, COOKIE_DOMAIN);
222+       if ( COOKIEPATH != SITECOOKIEPATH )
223+               setcookie(AUTH_COOKIE, $cookie, $expire, SITECOOKIEPATH, COOKIE_DOMAIN);
224 }
225 endif;
226 
227+if ( !function_exists('wp_clear_auth_cookie') ) :
228+function wp_clear_auth_cookie() {
229+       setcookie(AUTH_COOKIE, ' ', time() - 31536000, COOKIEPATH, COOKIE_DOMAIN);
230+       setcookie(AUTH_COOKIE, ' ', time() - 31536000, SITECOOKIEPATH, COOKIE_DOMAIN);
231+
232+       // Old cookies
233+       setcookie(USER_COOKIE, ' ', time() - 31536000, COOKIEPATH, COOKIE_DOMAIN);
234+       setcookie(PASS_COOKIE, ' ', time() - 31536000, COOKIEPATH, COOKIE_DOMAIN);
235+       setcookie(USER_COOKIE, ' ', time() - 31536000, SITECOOKIEPATH, COOKIE_DOMAIN);
236+       setcookie(PASS_COOKIE, ' ', time() - 31536000, SITECOOKIEPATH, COOKIE_DOMAIN); 
237+}
238+endif;
239+
240 if ( !function_exists('is_user_logged_in') ) :
241 function is_user_logged_in() {
242        $user = wp_get_current_user();
243@@ -350,9 +409,9 @@
244 if ( !function_exists('auth_redirect') ) :
245 function auth_redirect() {
246        // Checks if a user is logged in, if not redirects them to the login page
247-       if ( (!empty($_COOKIE[USER_COOKIE]) &&
248-                               !wp_login($_COOKIE[USER_COOKIE], $_COOKIE[PASS_COOKIE], true)) ||
249-                        (empty($_COOKIE[USER_COOKIE])) ) {
250+       if ( (!empty($_COOKIE[AUTH_COOKIE]) &&
251+                               !wp_validate_auth_cookie($_COOKIE[AUTH_COOKIE])) ||
252+                        (empty($_COOKIE[AUTH_COOKIE])) ) {
253                nocache_headers();
254 
255                wp_redirect(get_option('siteurl') . '/wp-login.php?redirect_to=' . urlencode($_SERVER['REQUEST_URI']));
256@@ -379,19 +438,18 @@
257        if ( !wp_verify_nonce( $nonce, $action ) ) {
258                $current_name = '';
259                if ( ( $current = wp_get_current_user() ) && $current->ID )
260-                       $current_name = $current->data->user_login;
261+                       $current_name = $current->user_login;
262                if ( !$current_name )
263                        die('-1');
264 
265+               $auth_cookie = '';
266                $cookie = explode('; ', urldecode(empty($_POST['cookie']) ? $_GET['cookie'] : $_POST['cookie'])); // AJAX scripts must pass cookie=document.cookie
267                foreach ( $cookie as $tasty ) {
268-                       if ( false !== strpos($tasty, USER_COOKIE) )
269-                               $user = substr(strstr($tasty, '='), 1);
270-                       if ( false !== strpos($tasty, PASS_COOKIE) )
271-                               $pass = substr(strstr($tasty, '='), 1);
272+                       if ( false !== strpos($tasty, AUTH_COOKIE) )
273+                               $auth_cookie = substr(strstr($tasty, '='), 1);
274                }
275 
276-               if ( $current_name != $user || !wp_login( $user, $pass, true ) )
277+               if ( $current_name != $user || empty($auth_cookie) || !wp_validate_auth_cookie( $auth_cookie ) )
278                        die('-1');
279        }
280        do_action('check_ajax_referer');
281@@ -472,60 +530,6 @@
282 }
283 endif;
284 
285-if ( !function_exists('wp_get_cookie_login') ):
286-function wp_get_cookie_login() {
287-       if ( empty($_COOKIE[USER_COOKIE]) || empty($_COOKIE[PASS_COOKIE]) )
288-               return false;
289-
290-       return array('login' => $_COOKIE[USER_COOKIE],  'password' => $_COOKIE[PASS_COOKIE]);
291-}
292-
293-endif;
294-
295-if ( !function_exists('wp_setcookie') ) :
296-function wp_setcookie($username, $password, $already_md5 = false, $home = '', $siteurl = '', $remember = false) {
297-       $user = get_userdatabylogin($username);
298-       if ( !$already_md5) {
299-               $password = md5($user->user_pass); // Double hash the password in the cookie.
300-       }
301-
302-       if ( empty($home) )
303-               $cookiepath = COOKIEPATH;
304-       else
305-               $cookiepath = preg_replace('|https?://[^/]+|i', '', $home . '/' );
306-
307-       if ( empty($siteurl) ) {
308-               $sitecookiepath = SITECOOKIEPATH;
309-               $cookiehash = COOKIEHASH;
310-       } else {
311-               $sitecookiepath = preg_replace('|https?://[^/]+|i', '', $siteurl . '/' );
312-               $cookiehash = md5($siteurl);
313-       }
314-
315-       if ( $remember )
316-               $expire = time() + 31536000;
317-       else
318-               $expire = 0;
319-
320-       setcookie(USER_COOKIE, $username, $expire, $cookiepath, COOKIE_DOMAIN);
321-       setcookie(PASS_COOKIE, $password, $expire, $cookiepath, COOKIE_DOMAIN);
322-
323-       if ( $cookiepath != $sitecookiepath ) {
324-               setcookie(USER_COOKIE, $username, $expire, $sitecookiepath, COOKIE_DOMAIN);
325-               setcookie(PASS_COOKIE, $password, $expire, $sitecookiepath, COOKIE_DOMAIN);
326-       }
327-}
328-endif;
329-
330-if ( !function_exists('wp_clearcookie') ) :
331-function wp_clearcookie() {
332-       setcookie(USER_COOKIE, ' ', time() - 31536000, COOKIEPATH, COOKIE_DOMAIN);
333-       setcookie(PASS_COOKIE, ' ', time() - 31536000, COOKIEPATH, COOKIE_DOMAIN);
334-       setcookie(USER_COOKIE, ' ', time() - 31536000, SITECOOKIEPATH, COOKIE_DOMAIN);
335-       setcookie(PASS_COOKIE, ' ', time() - 31536000, SITECOOKIEPATH, COOKIE_DOMAIN);
336-}
337-endif;
338-
339 if ( ! function_exists('wp_notify_postauthor') ) :
340 function wp_notify_postauthor($comment_id, $comment_type='') {
341        $comment = get_comment($comment_id);
342@@ -692,10 +696,17 @@
343 if ( !function_exists('wp_salt') ) :
344 function wp_salt() {
345        $salt = get_option('secret');
346-       if ( empty($salt) )
347-               $salt = DB_PASSWORD . DB_USER . DB_NAME . DB_HOST . ABSPATH;
348+       if ( empty($salt) ) {
349+               $salt = wp_generate_password();
350+               update_option('secret', $salt);
351+       }
352 
353-       return $salt;
354+       if ( !defined('SECRET_KEY') || '' == SECRET_KEY )
355+               $secret_key = DB_PASSWORD . DB_USER . DB_NAME . DB_HOST . ABSPATH;
356+       else
357+               $secret_key = SECRET_KEY;
358+               
359+       return $salt . $secret_key;
360 }
361 endif;
362 
363@@ -758,4 +769,27 @@
364        return $password;
365 }
366 endif;
367+
368+// Deprecated. Use wp_set_auth_cookie()
369+if ( !function_exists('wp_setcookie') ) :
370+function wp_setcookie($username, $password = '', $already_md5 = false, $home = '', $siteurl = '', $remember = false) {
371+       $user = get_userdatabylogin($username);
372+       wp_set_auth_cookie($user->ID, $remember);
373+}
374+endif;
375+
376+// Deprecated. Use wp_clear_auth_cookie()
377+if ( !function_exists('wp_clearcookie') ) :
378+function wp_clearcookie() {
379+       wp_clear_auth_cookie();
380+}
381+endif;
382+
383+// Deprecated.  No alternative.
384+if ( !function_exists('wp_get_cookie_login') ):
385+function wp_get_cookie_login() {
386+       return false;
387+}
388+endif;
389+
390 ?>
391Index: wp-includes/registration.php
392===================================================================
393--- wp-includes/registration.php        (revision 6385)
394+++ wp-includes/registration.php        (working copy)
395@@ -167,8 +167,8 @@
396        $current_user = wp_get_current_user();
397        if ( $current_user->id == $ID ) {
398                if ( isset($plaintext_pass) ) {
399-                       wp_clearcookie();
400-                       wp_setcookie($userdata['user_login'], $plaintext_pass);
401+                       wp_clear_auth_cookie();
402+                       wp_set_auth_cookie($ID);
403                }
404        }
405 
406Index: wp-config-sample.php
407===================================================================
408--- wp-config-sample.php        (revision 6385)
409+++ wp-config-sample.php        (working copy)
410@@ -6,6 +6,7 @@
411 define('DB_HOST', 'localhost');    // 99% chance you won't need to change this value
412 define('DB_CHARSET', 'utf8');
413 define('DB_COLLATE', '');
414+define('SECRET_KEY', ''); // Change this to a unique phrase.
415 
416 // You can have multiple installations in one database if you give each a unique prefix
417 $table_prefix  = 'wp_';   // Only numbers, letters, and underscores please!
418Index: wp-settings.php
419===================================================================
420--- wp-settings.php     (revision 6385)
421+++ wp-settings.php     (working copy)
422@@ -186,9 +186,11 @@
423 }
424 
425 if ( !defined('USER_COOKIE') )
426-       define('USER_COOKIE', 'wordpressuser_'. COOKIEHASH);
427+       define('USER_COOKIE', 'wordpressuser_' . COOKIEHASH);
428 if ( !defined('PASS_COOKIE') )
429-       define('PASS_COOKIE', 'wordpresspass_'. COOKIEHASH);
430+       define('PASS_COOKIE', 'wordpresspass_' . COOKIEHASH);
431+if ( !defined('AUTH_COOKIE') )
432+       define('AUTH_COOKIE', 'wordpress_' . COOKIEHASH);
433 if ( !defined('TEST_COOKIE') )
434        define('TEST_COOKIE', 'wordpress_test_cookie');
435 if ( !defined('COOKIEPATH') )
436Index: wp-admin/includes/misc.php
437===================================================================
438--- wp-admin/includes/misc.php  (revision 6385)
439+++ wp-admin/includes/misc.php  (working copy)
440@@ -128,7 +128,7 @@
441        update_option( 'recently_edited', $oldfiles );
442 }
443 
444-// If siteurl or home changed, reset cookies and flush rewrite rules.
445+// If siteurl or home changed, flush rewrite rules.
446 function update_home_siteurl( $old_value, $value ) {
447        global $wp_rewrite, $user_login, $user_pass_md5;
448 
449@@ -137,10 +137,6 @@
450 
451        // If home changed, write rewrite rules to new location.
452        $wp_rewrite->flush_rules();
453-       // Clear cookies for old paths.
454-       wp_clearcookie();
455-       // Set cookies for new paths.
456-       wp_setcookie( $user_login, $user_pass_md5, true, get_option( 'home' ), get_option( 'siteurl' ));
457 }
458 
459 add_action( 'update_option_home', 'update_home_siteurl', 10, 2 );