The fix for issue 56357 was meant to ensure that each Drupal site in a domain has a unique session name, but it causes multiple session names to be used for the same site. The problem is that it creates a session name from $base_url, which changes depending on whether HTTP or HTTPS is being used and whether the script is in the site's root directory or in a subdirectory.

This patch ensures that only one unique session name is used for each site by ignoring the $base_root and working up the directory tree until it finds index.php.

Comments

drumm’s picture

Version: 5.x-dev » 6.x-dev
Status: Needs review » Needs work

This code in question is a backport from Drupal HEAD, so any issues need to be fixed there first.

Using multisite hosting, there can be many sites with different users and different sessions, for one index.php. This is not an acceptable algorithm for determining what is a site. Maybe conf_path() could be used.

johnalbin’s picture

Title: Multiple cookies for same site » Different cookies for http and https access
Status: Needs work » Needs review
StatusFileSize
new701 bytes

I’ve confirmed that https and http accesses will have different session names. So that does need to be fixed. But…

The problem is that it creates a session name from $base_url, which changes depending on … whether the script is in the site's root directory or in a subdirectory.

That’s the desired behavior. A Drupal site installed at $base_url = http://example.com/ and a site at $base_url = http://example.com/myothersite/ will have different session names. If you want to share session cookies between the 2 separate Drupal installs, you’ll need to configure the sites to use the same user tables and to change the settings.php file’s $cookie_domain variable.

New patch fixes http/https issue for HEAD.

darren oh’s picture

Title: Different cookies for http and https access » Multiple cookies for same site
Assigned: Unassigned » darren oh
Status: Needs review » Needs work

Actually, the desired behavior is for the session name to depend on the directory the site is installed in, not on the directory the script is installed in. The modular design of Drupal would lose a major advantage if scripts had to be copied from the module's directory to the site's root directory.

I realize my patch does not satisfactorily identify the site directory and am working on a revision.

moshe weitzman’s picture

Title: Multiple cookies for same site » Different cookies for http and https access
Assigned: darren oh » Unassigned
Status: Needs work » Reviewed & tested by the community

good catch. RTBC for the most recent patch.

johnalbin’s picture

Darren, I understand your $base_url problem now. Please see chatroom issue #160068 for the fix.

And I agree with Moshe, good catch on the http/https bug. I want to get this backported to 5.x ASAP!

darren oh’s picture

Title: Different cookies for http and https access » Multiple cookies for same site
Assigned: Unassigned » darren oh
Status: Reviewed & tested by the community » Needs review
StatusFileSize
new1.33 KB

This patch deals with the whole problem by leaving out the base root (http:// or https://) and accurately identifying the root directory of the site. (conf_path() didn't work because it is relative to the script's directory and doesn't identify the site's root directory.)

johnalbin’s picture

Status: Needs review » Needs work

Drupal, by design, assumes that $_SERVER['PHP_SELF'] will be in the root directory of the Drupal install. You can see that assumption/design in the way $base_url is calculated in conf_init(). If you’d like to argue that point, your patch will need to address how $base_url is created.

I‘m moving the http/https bug fix to issue #160107.

darren oh’s picture

StatusFileSize
new1.46 KB

You are right. This patch fixes $base_url and eliminates http:// and https:// from the session name.

darren oh’s picture

Status: Needs work » Needs review
johnalbin’s picture

Title: Multiple cookies for same site » cookie name is wrong when accessing Drupal from subdir of install
Status: Needs review » Needs work

You can’t use PATH_TRANSLATED to get the file path to the current script, because it can be empty. See http://us.php.net/reserved.variables

Also, I don’t think it’s a good idea to calculate the $base_path on each request into Drupal. Since $base_url doesn’t change after installation, it would be much faster if the $base_url was specified in the settings.php file. The best thing would be for the installer to calculate it and add it to settings.php.

darren oh’s picture

My patch does not interfere with the $base_url in settings.php. It simply ensures that it is correctly calculated if it is missing from settings.php. The speed issue is more than made up for by the advantage of enabling modules to avoid loading all of Drupal on each AJAX request.

darren oh’s picture

Status: Needs work » Needs review

Replaced PATH_TRANSLATED with SCRIPT_FILENAME. If the test fails, $base_url and $base_path are set in the same way as before. As I pointed out, this code will not be run at all if $base_url is specified in settings.php.

If this patch is not committed, all scripts outside the Drupal root directory will be unable to use Drupal's session management. Even though only one of the modules I maintain is affected, this is a critical bug that has the potential to break any module.

darren oh’s picture

StatusFileSize
new1.46 KB

Patch attached.

johnalbin’s picture

Status: Needs review » Needs work

Are there any core modules that use AJAX requests in this way?

By default $base_url is not set in $settings, so the patch fixes an edge case (which may or may not be in core), but negatively affects all page requests.

If this is to get into core, one of two things must happen:

  1. show an example of a core AJAX request getting a cookie with the wrong name (a critical bug), or
  2. in addition to your current patch, update the installation process to save $base_url in settings.php file, so that, by default, the code that your current patch adds to conf_init() isn‘t run. I.e. update drupal_rewrite_settings(). Rather than negatively affecting the default case, this would actually improve the performance of the default case.
darren oh’s picture

Version: 6.x-dev » 5.x-dev

Wrong version. This was a change to Drupal 5 that breaks contributed modules.

darren oh’s picture

Status: Needs work » Needs review

Code works. Just needs an independent review. In response to #14, I recommend opening a feature request for Drupal 6.

drumm’s picture

Version: 5.x-dev » 6.x-dev
Status: Needs review » Needs work

On the version number- this code should be the same for Drupal 5.x and 6.x, so the fix will hopefully be the same in both versions. In this situation, we should fix this in Drupal 6.x and then backport to 5.x, as I mentioned in update #1.

On splitting this patch into two parts- yes, this is a perfectly reasonable patch to split. If one chunk of code is ready to go, there is no reason to hold it back by tying it to another chunk of code.

On taking out the protocol, http or https- this looks like a good idea, but it needs a code comment.

On the rest, the directory traversal- I am a bit confused on what exactly this is doing. Could you either
1. Put in more code comments.
2. Summarize a sample configuration which triggers the bug in an update to this issue?

I have another idea for avoiding the directory traversal- use something based on drupal_get_private_key(). This will of course have to be hashed sufficiently to not reveal it. It does provide a unique value for each variables table, and there is almost always only one of those per-site, crazy shared-table installations excluded. I am not sure how this would affect install.php since there is not a database available at that point.

darren oh’s picture

Version: 6.x-dev » 5.x-dev
Status: Needs work » Needs review

As long as it is properly documented, this is not a bug for Drupal 6. We expect to have to re-design our modules to work with new versions. It is a bug for Drupal 5 because it's an API change that breaks existing modules.

I first discovered this when working with Chat Room. In order to avoid loading all of Drupal on each AJAX update, Chat Room calls a script in its own directory that partially boots Drupal. $_SERVER[PHP_SELF] points to the script's directory rather than the Drupal directory. Since $_SERVER[PHP_SELF] is one of the values from which the session name is derived, this generates the wrong session name.

My patch uses the file system path to find the directory containing index.php and trims the directories below it off the path given by $_SERVER[PHP_SELF] so that Drupal will always use the same value to generate the session name.

drumm’s picture

Status: Needs review » Needs work

This should be fixed in both Drupal 5.x and 6.x. In this case, the version number of the issue should be the highest available. 6.x has a better chance of getting reviews since more developers are looking at it now. However, arguing this point is pointless if the reasons are ignored and I will leave this at the incorrect version.

Thanks for the explanation, this patch makes sense now.

As mentioned in follow-ups #1 and #2, you can have two URLs pointing to the same Drupal install and have two separate sites which should have separate cookies. $_SERVER['SCRIPT_FILENAME'] is be the same if two Apache virtual hosts point at the same filesystem path. This approach would break the intended behavior of having one cookie per site.

I did further research on my proposed alternative using Drupal's private key. Installation of Drupal doesn't actually seem to use cookies, which makes sense, since we don't have the sessions table either, so I think using Drupal's private key as a seed would be an effective way of ensuring we have one cookie per site.

johnalbin’s picture

I’m not sure this is a bug. It seems that the method Darren is describing (bypassing index.php and accessing a module’s file directly) is incompatible with multi-site configurations. For example:

If you have Drupal installed at / but your only configured sites are at /subsite1 and /subsite2 and then accessing /modules/example/ajax-connect.php directly, will mean that the ajax-connect.php file won’t know what subsite or what session cookie it should be using.

Since multi-site configurations are a supported part of the API, and I don’t see any docs to the contrary, this AJAX method can’t be supported. I’m in favor of marking this “by design” or “won't fix.”

darren oh’s picture

Status: Needs work » Needs review

What are you talking about? Did you look at the patch? It's completely compatible with multisite set-ups (which I use myself). Say the site is at http://www.example.com/sub1/sub2/sub3 and script.php is in the directory sites/modules/example. The URL will be http://www.example.com/sub1/sub2/sub3/sites/modules/example/script.php. My patch strips off sites/modules/example, leaving http://www.example.com/sub1/sub2/sub3.

darren oh’s picture

I think drumm misunderstood the purpose of $_SERVER[SCRIPT_FILENAME] in the patch. It is not used to generate the session name; it is used to find index.php so directories below it can be stripped from the URL before the session name is generated. The site URL will thus always be used to generate the session name.

darren oh’s picture

And in case it wasn't clear, each site will have exactly one session name. Try the patch.

manimal’s picture

tried the patch, and recieved this error:
patching file bootstrap.inc
Hunk #1 succeeded at 253 (offset -5 lines).
Hunk #2 FAILED at 283.
1 out of 2 hunks FAILED -- saving rejects to file bootstrap.inc.rej

how do I fix this?

johnalbin’s picture

Darren, of course I read your patch. But it’s immaterial, since it’s the described AJAX method which I’m arguing against being supported in core.

There are lots of possible multi-site configs. One of which is:

  1. installing Drupal in the root of web accessible directory ( http://example.com/ )
  2. But only configuring Drupal sites in sub-directories ( http://example.com/subsite1/ and http://example.com/subsite2/ ) i.e. http://example.com/ is not Drupal site.

In other words, any request outside of /subsite1 and /subsite2 are NOT handled by Drupal, but instead by real files (if anyone is unfamiliar with how this works, see the default /.htaccess file.) So a request to /modules/example/ajax-request.php gets the REAL file. And a request to /subsite1/modules/example/ajax-request.php won’t work because Drupal isn’t physically installed in /subsite1/.

So there‘s no patch you could add to core that would help the ajax-request.php to know which site config to use.

darren oh’s picture

Read the documentation for conf_path(). There is no problem determining which configuration to use.

I have no problem with your arguing against this being supported, but that's a discussion for the next version of Drupal. Changing the API of the current version in such a way that modules break is against policy.

darren oh’s picture

By the way, I'm assuming that the module script does a chdir() to the Drupal root directory before loading Drupal, as chatroomread.php does.

drumm’s picture

Priority: Critical » Normal
Status: Needs review » Needs work

http://drupal.org/node/160107 has been committed to both 6.x and 5.x, in that order. This patch no longer applies cleanly.

At this point I have spent multiple hours reviewing this patch, including testing it.

There are two design problems with the approach in this patch:

1. The code is not obvious. I do agree that it does seem to get one session name per site, however the code does not readily explain this. At least, an additional comment is required.
2. This potentially generates plenty of calls to file_exists() and adds complex array manipulation. I am concerned about the speed of this approach.

This is why I have offered two separate alternatives which I am not fully convinced won't work and both will be faster since they both are a single function call which get a value from a static variable. Both are calls to existing APIs which are designed to uniquely identify sites.

darren oh’s picture

StatusFileSize
new1.07 KB

I'm attaching an updated patch. However, my effort to maintain API compatibility between Drupal 5 releases has failed with the release of version 5.2.

In response to Drumm's concerns

  1. I'd be happy to add whatever comments are required if it will immediately result in a new release to fix the compatibility problem.
  2. If Drupal is loaded by a script in the site root (index.php, update.php, cron.php, or install.php), my patch calls file_exists() only once (conf_path() calls it many times more).

The function drupal_get_private_key() (suggested in #17) is not available at this point in the boot process.

darren oh’s picture

StatusFileSize
new1.85 KB

I didn't get a promise to fix the broken Drupal 5 API, but I couldn't resist updating the patch anyway. The added comments should make the code blindingly obvious.

Drumm's alternative methods for generating a unique session name would require a reworking of the entire boot process, which should not be done for a stable release.

darren oh’s picture

Status: Needs work » Needs review
heine’s picture

Status: Needs review » Reviewed & tested by the community

I didn't get a promise to fix the broken Drupal 5 API,

Sorry, what API do you mean? Something 'that used to work' is not immediately an API.

Setting to 'needs review'

heine’s picture

Status: Reviewed & tested by the community » Needs review

weird. Setting to need review for real.

darren oh’s picture

Heine, I am referring to the bootstrap API. There have been comments on this issue claiming that it doesn't have to work for modules. That's a change that shouldn't be made in a stable release.

darren oh’s picture

Version: 5.x-dev » 5.2
Priority: Normal » Critical
Scott Reynolds’s picture

Subscribing

I hope this gets resolved. A point release probably shouldn't break contrib modules unless unavoidable

keesje’s picture

Drupals name for stability is on the line here, it's against Drupals own principles to release a minor-version update that fixes bugs but potentially totally breaks 3th party modules!! This cannot be true, please fix.

johnalbin’s picture

Priority: Critical » Normal
Status: Needs review » Closed (won't fix)

Drupal current bootstrap API is designed to work from scripts residing in the root of the Drupal install. You can see that both in the way files are included via include("./filepath") and in the way $base_url is calculated.

If a module’s script attempted to startup by using the Drupal bootstrap API, it wouldn’t work. This is true for Drupal 5.0, 5.1, and 5.2.

The chatroom module gets around this limitation by using a custom startup in chatroomread.php. (BTW, there is a module-side patch to get chatroom to work with Drupal 5.2 at http://drupal.org/node/160068)

Yes, the bootstrap API changed in Drupal 5.2, but the inability to use it in a module was true for 5.1 as well.

Could the bootstrap API be changed to allow easy usage by a module? Sure, but that’s a feature request, not a bug report.

This is not going to get changed in 5.x.

Scott and Kees, the change in the API was unavoidable; see issue 56357 for the critical bugs it fixed. Are there modules besides Darren’s chatroom breaking?

darren oh’s picture

Priority: Normal » Critical
Status: Closed (won't fix) » Needs review

If a module’s script attempted to startup by using the Drupal bootstrap API, it wouldn’t work. This is true for Drupal 5.0, 5.1, and 5.2.

This is false. There was no "workaround". Please stop trying to defend an inexcusable break. I have answered all concerns about the patch, and they are completely groundless.

moshe weitzman@drupal.org’s picture

Status: Needs review » Closed (won't fix)

just because something unusual happenned to work in drupal5, does not mean it was supported. where does it say that we support scripts run from random subdirs of drupal? i agree with won't fix here. furthermore, the workaround is trivial. just symlink or copy to root, and make some minor tweaks to the script. With such an easy workaround available, I feel that Darren is just (vehemently) making a point and others are free to agree or disagree with him. In any case, the status of this issue doesn't really matter. Noone is working on restoring that capability and such a patch is not likely to garner attention and support.

darren oh’s picture

The workaround is not acceptable for end users. It makes it impossible to separate modules from core. Any time Drupal core is updated, those symlinks will be lost. By the way, moshe, you were the one who modified chatroomread.php so that it would not have to be copied to the root directory.

yngens’s picture

subscribe