#29156 closed defect (bug) (fixed)
$rp_path does not respect SITECOOKIEPATH/COOKIEPATH
Reported by: |
|
Owned by: |
|
---|---|---|---|
Milestone: | 4.0 | Priority: | high |
Severity: | major | Version: | 4.0 |
Component: | Login and Registration | Keywords: | has-patch needs-testing |
Focuses: | administration | Cc: |
Description
In wp-login.php
The wp-resetpass- cookie is set if a user hits with a key. This value is then transitioned to a cookie written with a path.
list( $rp_path ) = explode( '?', wp_unslash( $_SERVER['REQUEST_URI'] ) );
setcookie( $rp_cookie, $value, 0, $rp_path, COOKIE_DOMAIN, is_ssl(), true );
In my installation with siteurl and home set to www.mydomain.com/blog this results in a cookie with a path of /wp-login.php instead of /blog/wp-login.php, as a result the user can never reset their password.
Attachments (2)
Change History (27)
#1
@
9 years ago
- Focuses administration added
- Milestone changed from Awaiting Review to Future Release
This code was introduced in 3.9.2 (r29327) and backported to 3.8.4 and 3.7.4. I'll run some tests to confirm the bug shortly.
#3
@
9 years ago
- Milestone changed from Future Release to 4.0
- Version changed from 3.9.2 to trunk
This was technically introduced in trunk and backported to 3.9.2, 3.8.4, and 3.7.4.
Moving to 4.0 to get more eyes on this.
#4
@
9 years ago
I'm also experiencing this on a Multisite install with WordPress in a subdirectory. The cookie's path is set to /wp-login.php, and the form submits to /subdirectory/wp-login.php as described, making the cookie inaccessible.
I'm handling password resets manually for the time being.
#5
@
9 years ago
I don't understand this one, unfortunately.
If wp-login.php is at /blog/wp-login.php, then that would be the value of $_SERVER['REQUEST_URI']
, and it would be the path that would get set.
Can you describe the actual steps? You start on X URL, it posts to Y URL, the email contains Z URL, which takes you to W URL, etc... What's the actual configuration of your network as a subdirectory install, rewrite rules, and such?
#7
@
9 years ago
For me, it's as follows:
- Request lost password link at http://domain.com/wp-login.php?action=lostpassword
- Receive email; contains link to http://domain.com/wp-login.php?action=rp&key=<key>&login=<username>
- Click link; 301 redirect to http://domain.com/wp-login.php?action=rp
At this point the cookie is set, but the form on that page has as its action:
http://domain.com/subdirectory/wp-login.php?action=resetpass
Submitting the form results in, "Sorry, that key does not appear to be valid."
#8
@
9 years ago
Can you check the value of $_SERVER['REQUEST_URI']
when visiting http://domain.com/wp-login.php? If it's anything other than /wp-login.php then this is a server configuration issue (or possibly a bug in wp_fix_server_vars(), but unlikely).
#9
@
9 years ago
At login_head
, $_SERVER['REQUEST_URI']
has a value of /wp-login.php
when going directly to the login form.
As of step three in the steps above, the value is /wp-login.php?action=rp
The only rewrite rule that looks relevant is this one:
RewriteRule ^([_0-9a-zA-Z-]+/)?(.*\.php)$ subdirectory/$2 [L]
(As supplied by My Sites > Settings > Network Setup.)
#10
@
9 years ago
Okay, I misread, but I don't fully understand your setup. Could you give me a better idea of what's going on here? Do you have sites at domain.com, domain.com/subdirectory, domain.com/blog, etc.? Which is the main site on the network?
#11
@
9 years ago
I followed these instructions for installation:
http://codex.wordpress.org/Giving_WordPress_Its_Own_Directory
Then followed the usual instructions for creating a network.
The network uses subdirectories. So domain.com is the main site, WordPress is installed at domain.com/subdirectory, and sites exist at domain.com/site2, domain.com/site3, etc.
#12
@
9 years ago
Is it possible that this line in wp-login.php:
<form name="lostpasswordform" id="lostpasswordform" action="<?php echo esc_url( site_url( 'wp-login.php?action=lostpassword', 'login_post' ) ); ?>" method="post">
is causing the problem? Could home_url
be used instead of site_url
?
Alternatively, would it make sense to take site_url
into account when setting the cookie?
#13
@
9 years ago
I attempted to reproduce this issue on a fresh subdirectory network install of 4.0 and did not get the same behavior when following the same steps.
#14
@
9 years ago
Roughly, home_url() is wherever the homepage is located, while site_url() is wherever the site's files are located.
If you had example.com with WordPress at example.com/wordpress, then home_url() would return the former and site_url() would return the latter. site_url() is thus used whenever we're targeting a particular file, whether that's wp-login.php or in something like includes_url() for example.com/wordpress/wp-includes.
I'd be curious to know what the home and siteurl option values are for the various sites. For a post-3.5 multisite setup that puts WP into a subdirectory, it should look like this:
- main site: home url is domain.com, siteurl is domain.com/wordpress
- additional sites: home url and siteurl are both domain.com/sitename (since we require rewrite rules for multisite, we can dynamically rewrite things and don't require home url and siteurl to be different)
siteurl *is* taken to account when setting the cookie because wp-login.php would be located at site_url( 'wp-login.php' ). Using REQUEST_URI was a matter of not wreaking havoc when someone was doing crazy/weird filtering of URLs or whatever.
#15
follow-up:
↓ 18
@
9 years ago
- Keywords reporter-feedback removed
- Priority changed from normal to high
- Severity changed from normal to major
Okay, I could see how this could go wrong.
You're going to http://domain.com/wp-login.php. This is the network site url, but not the site url for the main site. That'd be http://domain.com/wordpress/wp-login.php. http://domain.com/wp-login.php isn't actually the site url for any site in this setup.
When you submit, you're actually submitting to http://domain.com/wordpress/wp-login.php, since the form actions are site_url() throughout this process. The email uses network_site_url() though, which links you back to http://domain.com/wp-login.php. At that point, you then get redirected (after the key and username is stripped from the URL) to http://domain.com/wp-login.php again. But the form action submits to site_url(), which is http://domain.com/wordpress/wp-login.php.
Two possible solutions:
- Always post to network_site_url().
- Link to site_url() in the email.
I like the first one, since for whatever reason we already seem to want it to go through the central location.
#16
@
9 years ago
To work around this (and to confirm it's a problem), when visiting a password reset link, change its path to http://domain.com/wordpress/wp-login.php. Or, change siteurl for the main site to http://domain.com (could have other side effects but rewrite rules should cover it).
#17
@
9 years ago
I attempted to reproduce this issue on a fresh subdirectory network install of 4.0 and did not get the same behavior when following the same steps.
I went through the subdirectory installation instructions on a clean install and confirmed that the bug is not present outside of Multisite; then, I converted to a network, and the bug is present in 3.9.2.
I then upgraded to the latest nightly, and the bug is present there as well.
To work around this (and to confirm it's a problem), when visiting a password reset link, change its path to http://domain.com/wordpress/wp-login.php.
This works. If you have any interest in trying it, I can create an account for you on my test installation.
Or, change siteurl for the main site to http://domain.com (could have other side effects but rewrite rules should cover it).
This also works; I didn't check for further side effects, but the password change was successful.
#18
in reply to:
↑ 15
;
follow-up:
↓ 19
@
9 years ago
Replying to nacin:
- Always post to network_site_url().
For all forms on wp-login.php or just the reset one? This seems better to me too, but I wonder if it's more likely to break something else.
#19
in reply to:
↑ 18
@
9 years ago
Replying to mdawaffe:
Replying to nacin:
- Always post to network_site_url().
For all forms on wp-login.php or just the reset one? This seems better to me too, but I wonder if it's more likely to break something else.
Just for reset, which is already attempting to only go through the main site, so we're only trying to further handle this as it was intended. For everything else, we'd probably break things. The most obvious example is logging in to a particular site and getting redirected to that site's dashboard.)
#20
@
9 years ago
- Keywords has-patch needs-testing added
Use network_site_url()
for the lostpasswordform (I don't think this is strictly necessary) and the resetpassform (this is necessary).
Simple patch, may not cover all cases.