Ticket #5367: secure_cookie.4.diff

File secure_cookie.4.diff, 14.4 KB (added by ryan, 5 years ago)
Line 
1Index: wp-login.php
2===================================================================
3--- wp-login.php        (revision 6364)
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 6360)
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 6364)
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,88 @@
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+       // Allow a grace period for POST requests
179+       if ( 'POST' == $_SERVER['REQUEST_METHOD'] )
180+               $expiration += 3600;
181+
182+       if ( $expiration < time() )
183+               return false;
184+
185+       $key = wp_hash($username . $expiration);
186+       $hash = hash_hmac('md5', $username . $expiration, $key);
187+       
188+       if ( $hmac != $hash )
189+               return false;
190+
191+       $user = get_userdatabylogin($username);
192+       if ( ! $user )
193+               return false;
194+
195+       return $user->ID;
196+}
197+endif;
198+
199+if ( !function_exists('wp_set_auth_cookie') ) :
200+function wp_set_auth_cookie($user_id, $remember = false) {
201+       $user = get_userdata($user_id);
202+
203+       if ( $remember ) {
204+               $expiration = $expire = time() + 1209600;
205        } else {
206-               if ( md5($login->user_pass) == $password )
207-                       return true;
208+               $expiration = time() + 172800;
209+               $expire = 0;
210        }
211 
212-       $error = __('<strong>ERROR</strong>: Incorrect password.');
213-       return false;
214+       $key = wp_hash($user->user_login . $expiration);
215+       $hash = hash_hmac('md5', $user->user_login . $expiration, $key);
216+
217+       $cookie = $user->user_login . '|' . $expiration . '|' . $hash;
218+
219+       setcookie(AUTH_COOKIE, $cookie, $expire, COOKIEPATH, COOKIE_DOMAIN);
220+       if ( COOKIEPATH != SITECOOKIEPATH )
221+               setcookie(AUTH_COOKIE, $cookie, $expire, SITECOOKIEPATH, COOKIE_DOMAIN);
222 }
223 endif;
224 
225+if ( !function_exists('wp_clear_auth_cookie') ) :
226+function wp_clear_auth_cookie() {
227+       setcookie(AUTH_COOKIE, ' ', time() - 31536000, COOKIEPATH, COOKIE_DOMAIN);
228+       setcookie(AUTH_COOKIE, ' ', time() - 31536000, SITECOOKIEPATH, COOKIE_DOMAIN);
229+
230+       // Old cookies
231+       setcookie(USER_COOKIE, ' ', time() - 31536000, COOKIEPATH, COOKIE_DOMAIN);
232+       setcookie(PASS_COOKIE, ' ', time() - 31536000, COOKIEPATH, COOKIE_DOMAIN);
233+       setcookie(USER_COOKIE, ' ', time() - 31536000, SITECOOKIEPATH, COOKIE_DOMAIN);
234+       setcookie(PASS_COOKIE, ' ', time() - 31536000, SITECOOKIEPATH, COOKIE_DOMAIN); 
235+}
236+endif;
237+
238 if ( !function_exists('is_user_logged_in') ) :
239 function is_user_logged_in() {
240        $user = wp_get_current_user();
241@@ -350,9 +407,9 @@
242 if ( !function_exists('auth_redirect') ) :
243 function auth_redirect() {
244        // Checks if a user is logged in, if not redirects them to the login page
245-       if ( (!empty($_COOKIE[USER_COOKIE]) &&
246-                               !wp_login($_COOKIE[USER_COOKIE], $_COOKIE[PASS_COOKIE], true)) ||
247-                        (empty($_COOKIE[USER_COOKIE])) ) {
248+       if ( (!empty($_COOKIE[AUTH_COOKIE]) &&
249+                               !wp_validate_auth_cookie($_COOKIE[AUTH_COOKIE])) ||
250+                        (empty($_COOKIE[AUTH_COOKIE])) ) {
251                nocache_headers();
252 
253                wp_redirect(get_option('siteurl') . '/wp-login.php?redirect_to=' . urlencode($_SERVER['REQUEST_URI']));
254@@ -379,19 +436,18 @@
255        if ( !wp_verify_nonce( $nonce, $action ) ) {
256                $current_name = '';
257                if ( ( $current = wp_get_current_user() ) && $current->ID )
258-                       $current_name = $current->data->user_login;
259+                       $current_name = $current->user_login;
260                if ( !$current_name )
261                        die('-1');
262 
263+               $auth_cookie = '';
264                $cookie = explode('; ', urldecode(empty($_POST['cookie']) ? $_GET['cookie'] : $_POST['cookie'])); // AJAX scripts must pass cookie=document.cookie
265                foreach ( $cookie as $tasty ) {
266-                       if ( false !== strpos($tasty, USER_COOKIE) )
267-                               $user = substr(strstr($tasty, '='), 1);
268-                       if ( false !== strpos($tasty, PASS_COOKIE) )
269-                               $pass = substr(strstr($tasty, '='), 1);
270+                       if ( false !== strpos($tasty, AUTH_COOKIE) )
271+                               $auth_cookie = substr(strstr($tasty, '='), 1);
272                }
273 
274-               if ( $current_name != $user || !wp_login( $user, $pass, true ) )
275+               if ( $current_name != $user || empty($auth_cookie) || !wp_validate_auth_cookie( $auth_cookie ) )
276                        die('-1');
277        }
278        do_action('check_ajax_referer');
279@@ -472,60 +528,6 @@
280 }
281 endif;
282 
283-if ( !function_exists('wp_get_cookie_login') ):
284-function wp_get_cookie_login() {
285-       if ( empty($_COOKIE[USER_COOKIE]) || empty($_COOKIE[PASS_COOKIE]) )
286-               return false;
287-
288-       return array('login' => $_COOKIE[USER_COOKIE],  'password' => $_COOKIE[PASS_COOKIE]);
289-}
290-
291-endif;
292-
293-if ( !function_exists('wp_setcookie') ) :
294-function wp_setcookie($username, $password, $already_md5 = false, $home = '', $siteurl = '', $remember = false) {
295-       $user = get_userdatabylogin($username);
296-       if ( !$already_md5) {
297-               $password = md5($user->user_pass); // Double hash the password in the cookie.
298-       }
299-
300-       if ( empty($home) )
301-               $cookiepath = COOKIEPATH;
302-       else
303-               $cookiepath = preg_replace('|https?://[^/]+|i', '', $home . '/' );
304-
305-       if ( empty($siteurl) ) {
306-               $sitecookiepath = SITECOOKIEPATH;
307-               $cookiehash = COOKIEHASH;
308-       } else {
309-               $sitecookiepath = preg_replace('|https?://[^/]+|i', '', $siteurl . '/' );
310-               $cookiehash = md5($siteurl);
311-       }
312-
313-       if ( $remember )
314-               $expire = time() + 31536000;
315-       else
316-               $expire = 0;
317-
318-       setcookie(USER_COOKIE, $username, $expire, $cookiepath, COOKIE_DOMAIN);
319-       setcookie(PASS_COOKIE, $password, $expire, $cookiepath, COOKIE_DOMAIN);
320-
321-       if ( $cookiepath != $sitecookiepath ) {
322-               setcookie(USER_COOKIE, $username, $expire, $sitecookiepath, COOKIE_DOMAIN);
323-               setcookie(PASS_COOKIE, $password, $expire, $sitecookiepath, COOKIE_DOMAIN);
324-       }
325-}
326-endif;
327-
328-if ( !function_exists('wp_clearcookie') ) :
329-function wp_clearcookie() {
330-       setcookie(USER_COOKIE, ' ', time() - 31536000, COOKIEPATH, COOKIE_DOMAIN);
331-       setcookie(PASS_COOKIE, ' ', time() - 31536000, COOKIEPATH, COOKIE_DOMAIN);
332-       setcookie(USER_COOKIE, ' ', time() - 31536000, SITECOOKIEPATH, COOKIE_DOMAIN);
333-       setcookie(PASS_COOKIE, ' ', time() - 31536000, SITECOOKIEPATH, COOKIE_DOMAIN);
334-}
335-endif;
336-
337 if ( ! function_exists('wp_notify_postauthor') ) :
338 function wp_notify_postauthor($comment_id, $comment_type='') {
339        $comment = get_comment($comment_id);
340@@ -695,7 +697,12 @@
341        if ( empty($salt) )
342                $salt = DB_PASSWORD . DB_USER . DB_NAME . DB_HOST . ABSPATH;
343 
344-       return $salt;
345+       if ( ! defined('SECRET_KEY') )
346+               $secret_key = 'shhhh';
347+       else
348+               $secret_key = SECRET_KEY;
349+               
350+       return $salt . $secret_key;
351 }
352 endif;
353 
354@@ -744,4 +751,26 @@
355 }
356 endif;
357 
358+// Deprecated. Use wp_set_auth_cookie()
359+if ( !function_exists('wp_setcookie') ) :
360+function wp_setcookie($username, $password = '', $already_md5 = false, $home = '', $siteurl = '', $remember = false) {
361+       $user = get_userdatabylogin($username);
362+       wp_set_auth_cookie($user->ID, $remember);
363+}
364+endif;
365+
366+// Deprecated. Use wp_clear_auth_cookie()
367+if ( !function_exists('wp_clearcookie') ) :
368+function wp_clearcookie() {
369+       wp_clear_auth_cookie();
370+}
371+endif;
372+
373+// Deprecated.  No alternative.
374+if ( !function_exists('wp_get_cookie_login') ):
375+function wp_get_cookie_login() {
376+       return false;
377+}
378+endif;
379+
380 ?>
381Index: wp-includes/registration.php
382===================================================================
383--- wp-includes/registration.php        (revision 6360)
384+++ wp-includes/registration.php        (working copy)
385@@ -167,8 +167,8 @@
386        $current_user = wp_get_current_user();
387        if ( $current_user->id == $ID ) {
388                if ( isset($plaintext_pass) ) {
389-                       wp_clearcookie();
390-                       wp_setcookie($userdata['user_login'], $plaintext_pass);
391+                       wp_clear_auth_cookie();
392+                       wp_set_auth_cookie($ID);
393                }
394        }
395 
396Index: wp-config-sample.php
397===================================================================
398--- wp-config-sample.php        (revision 6360)
399+++ wp-config-sample.php        (working copy)
400@@ -6,6 +6,7 @@
401 define('DB_HOST', 'localhost');    // 99% chance you won't need to change this value
402 define('DB_CHARSET', 'utf8');
403 define('DB_COLLATE', '');
404+define('SECRET_KEY', 'shhhh'); // Change this to something unique
405 
406 // You can have multiple installations in one database if you give each a unique prefix
407 $table_prefix  = 'wp_';   // Only numbers, letters, and underscores please!
408Index: wp-settings.php
409===================================================================
410--- wp-settings.php     (revision 6360)
411+++ wp-settings.php     (working copy)
412@@ -186,9 +186,11 @@
413 }
414 
415 if ( !defined('USER_COOKIE') )
416-       define('USER_COOKIE', 'wordpressuser_'. COOKIEHASH);
417+       define('USER_COOKIE', 'wordpressuser_' . COOKIEHASH);
418 if ( !defined('PASS_COOKIE') )
419-       define('PASS_COOKIE', 'wordpresspass_'. COOKIEHASH);
420+       define('PASS_COOKIE', 'wordpresspass_' . COOKIEHASH);
421+if ( !defined('AUTH_COOKIE') )
422+       define('AUTH_COOKIE', 'wordpress_' . COOKIEHASH);
423 if ( !defined('TEST_COOKIE') )
424        define('TEST_COOKIE', 'wordpress_test_cookie');
425 if ( !defined('COOKIEPATH') )
426Index: wp-admin/includes/misc.php
427===================================================================
428--- wp-admin/includes/misc.php  (revision 6360)
429+++ wp-admin/includes/misc.php  (working copy)
430@@ -128,7 +128,7 @@
431        update_option( 'recently_edited', $oldfiles );
432 }
433 
434-// If siteurl or home changed, reset cookies and flush rewrite rules.
435+// If siteurl or home changed, flush rewrite rules.
436 function update_home_siteurl( $old_value, $value ) {
437        global $wp_rewrite, $user_login, $user_pass_md5;
438 
439@@ -137,10 +137,6 @@
440 
441        // If home changed, write rewrite rules to new location.
442        $wp_rewrite->flush_rules();
443-       // Clear cookies for old paths.
444-       wp_clearcookie();
445-       // Set cookies for new paths.
446-       wp_setcookie( $user_login, $user_pass_md5, true, get_option( 'home' ), get_option( 'siteurl' ));
447 }
448 
449 add_action( 'update_option_home', 'update_home_siteurl', 10, 2 );