I've limited IP login pages at /admin/settings/ip_login by selecting "Login by IP only on the listed pages." and listing their paths.
Cleared all cookies, then went to a non-login page, but there were IP Login cookies as follows:
Array
(
[ip_login_as_different_user] =>
[ip_login_by_ip_complete] =>
[ip_login_checked] => 1
[ip_login_uid] => 0
)
Could you please make sure that if there are no cookies set, they should not be set unless the user goes to permitted login pages.
This is absolutely crucial for many sites that employ external caching, which is broken if there are session cookies. E.g. Varnish in Pressflow - see https://wiki.fourkitchens.com/display/PF/Modules+that+break+caching,+and...
Comments
Comment #1
vacilando commentedHere's a solution (sorry, no patch due to lack of time):
Make a new function ip_login_path() from the following code from ip_login_login():
but make it return
if (!$page_match) return FALSE;Then in ip_login_login() use
if (ip_login_path() === FALSE) return;And then -- here's the actual solution -- add
if (ip_login_path() === FALSE) return;as the first thing in ip_login_boot().
Works fine for me. Please test, apply to the release, and let me know.
Comment #2
jim kirkpatrick commentedOK, thanks Vacilando, I'll take a look later this week and post a new 6.x-2.x-beta2 release if your solution works as described.
Comment #3
jim kirkpatrick commentedExcept the code in #1 doesn't and cannot work because
drupal_get_path_alias()(or anything in path.inc) is not available during hook_boot, so the check cannot happen before more of the bootstrap process has happened. Presently I'm getting a 'Function not found' error when putting theip_login_check_path()(as I named it) in hook_boot.Your code makes sense in as far as that section of code should certainly be a separate function, but unfortunately it (on it's own) won't work.
It boils down to this: A path check is needed early to avoid cookie setting on every page, which messes up external caches like Varnish. BUT path checks can only safely/'properly' happen from hook_init() onwards, and most of IP Login's logic happens in hook_boot() to avoid the fact that hook_init() doesn't run on cached pages! Catch 22... See #509028: doesn't log in until after second page load and #791410: Improved: now supports logging in as alternate user plus comma separated values, IP ranges and wildcards for more background.
What might work is doing the preliminary checks in hook_boot, then storing the values in the global $user until hook_init is ready to use them and has path.inc available. BUT this means that we need another way to make sure we don't keep testing a user IP (with associated database query) every request AND a way to avoid caching skipping the hook_init() stuff altogether...
This may, because of the way Drupal's bootstrap process works, be impossible or at least very convoluted... I'll put my thinking cap on, but in the mean time I've committed the newer version to DEV without the call in hook_boot. It might be that path checking for IP login is just disabled when external caching is enabled, and your Varnish config will have to only allow cookies/pass through on the paths you would have put in the IP login path anyway... OR we need another - non-hacky! - way of checking paths that isn't reliant on path.inc...
Hmmm.... Ideas, anyone?
Comment #4
vacilando commentedInteresting. Function not found would return a fatal error, no? When I tested, it definitely worked -- I was logged in only on the pages I allowed for IP login and all other pages were nicely Varnished. Not having the time to re-test/debug right now, I quickly attach my version of ip_login.module as I had modified it.
A quick thought -- can't we just use $_GET['q'] in the path checking function and check it against path values saved at submitting the settings form? Might be a worthless idea -- really did not think it over.
Comment #5
jim kirkpatrick commented$_GET['q'] is the staring point, yes. But these functions in path.inc do some other nice things, which now I think about them, I'm not sure we particularly need.
Well we could drop the need for
drupal_get_path_alias()which callsdrupal_match_path()by just plain not caring about non-aliased pages... I.e. an admin setting IP Login to occur for 'about/cheese' would also need to enter it's non-aliased path too, e.g. 'node/123' into the IP login admin page... Then we'd just need a note in the help section of that field.That just leaves
drupal_match_path()which is quite a simple function we could just copy into IP Login and change the name, like so:It's all slightly hacky, but since external caching is a big deal for me as one of my Drupal sites uses it too, and it's kinda 'the future' of fast Drupal installations, I'm inclined to go with the above.
So I have! It's committed to DEV, have a play and let me know.
Comment #6
jim kirkpatrick commentedI've now also updated the admin page help text to explain all this...
Comment #7
vacilando commentedNice! And it seems to work, too -- no session set on pages other than the permitted one!
As for the permitted path -- I have the login form embedded in a node which is aliased. When I specify only the alias on the admin page, I do not get logged in. When I specify the system path (node/x) then it works. So perhaps the help text is wrong... instead of "you must also enter system paths" it should say "you must enter system paths"?
Comment #8
jim kirkpatrick commentedHmm... so close! OK, I'll take a look. Didn't realise $_GET['q'] would have the system path when requesting an alias... Will test and tweak accordingly later.
Comment #9
jim kirkpatrick commentedI've checked this and it works as expected. Arriving at www.example.com/this-page means $_GET['q'] == "this-page", while arriving at www.example.com/node/123 means $_GET['q'] == "node/123". That's what the admin screen says:
All done, closing.