PHP session cookies : A global Drupal login problem fix
Drupal has made it to 5.1 without dealing with one serious PHP problem of handling session cookies, causing various Drupal login problems in different configurations. I've been following Drupal forums for a long time and I've never seen a more wide-spread annoying bug. Myself, I've faced this bug on more than one occasion and can honestly say it's extremely frustrating. Definitely a critical bug.
For example, I was getting the following error when trying to log in:
PHP Warning: session_start() [<a href='function.session-start'>function.session-start</a>]: Cannot send session cache limiter - headers already sent (output started at /includes/bootstrap.inc:760) in /includes/bootstrap.inc on line 760
Seemed like a session cookie problem.
Hoping that I'll save some time for those facing this issue, here's the short description of the problem from John Albin:
This bug is more pernicious than originally thought. There’s a critical bug with an edge-case configuration. Here’s a not-so-unusual situation:
If a user goes to a PHP-based site at http://example.com (it doesn’t even have to be running Drupal, just some PHP code that uses sessions), by default PHP sets a cookie named PHPSESSID for .example.com.
If that user then goes to a Drupal site at http://intranet.example.com and attempts to login, Drupal sets a cookie named PHPSESSID for .intranet.example.com with authenticated permissions. BUT, the user’s browser sends both the .example.com and the .intranet.example.com cookies back to the intranet Drupal site and when Drupal tries to access the
$_COOKIE['PHPSESSID']value via PHP’s session functions, it gets the .example.com value; the wrong session id!From the user’s point of view, the user sees no “Unrecognized username or password” message (Drupal does enter a “session opened” watchdog entry), but because Drupal can’t access the correct cookie, the user keeps seeing the login screen. If the .example.com cookie is set to expire in 2037 (some PHP apps do that) and the user doesn’t think to delete cookies for a completely different web server, the user will NEVER be able to log into intranet.example.com!
From the cookie spec:
When sending cookies to a server, all cookies with a more specific path mapping should be sent before cookies with less specific path mappings. For example, a cookie "name1=foo" with a path mapping of "/" should be sent after a cookie "name1=foo2" with a path mapping of "/bar" if they are both to be sent.
Even though both cookies are submitted by the browser, PHP clobbers the value of the more-specific cookie with the less-specific cookie that follows. So there’s no way that Drupal could try to differentiate the two cookies.
I believe this is rightly a PHP bug and have submitted a bug report with PHP. But Drupal has to have a work-around. I verified this affects both 5.1 and 4.7.6.
After trying almost everything, I've finally found John's patch on #64 and it worked okay for my configurations. Unbelievable. Thanks John.
