Skip Menu |

This queue is for tickets about the Apache2-Controller CPAN distribution.

Report information
The Basics
Id: 61744
Status: resolved
Priority: 0/
Queue: Apache2-Controller

People
Owner: MARKLE [...] cpan.org
Requestors: arkadius.litwinczuk [...] gmail.com
Cc: scott [...] hnsc.de
AdminCc:

Bug Information
Severity: Normal
Broken in:
  • 1.000.000
  • 1.000.001
  • 1.000.010
  • 1.000.011
  • 1.000.100
  • v1.0.101
  • v1.0.110
  • v1.0.110+b
  • v1.0.110+c
  • v1.0.110+d
Fixed in: (no value)



Subject: Coockie caching bug
Hi, we use A2C for a application, and I noted a strange behavior. The IE under some of our win 7 Builds seem to send expired cookies to the server in some cases. We use file as storage for the Session data, and it looks to me that a expired cookie results in a Internal Server Error of the Apache. In my eyes this is not really a A2C bug but it would be great to fix it so a new session is started, in this case and not an Internal Server Error occurs. Kind Regards, Arkadius
Wow, someone uses it for a real live application? I'm so stoked. You've made my day. I don't have any Windows instance that I can use to test this. If you can duplicate the problem, can you init Log::Log4perl in apache startup and look at the debugging log? See the startup settings in t/conf for how to do this. Thanks! --mark--
From: arkadius.litwinczuk [...] gmail.com
Hi Mark, sorry can't get you the logfiles but i know the problem by now :). Take a look at http://comments.gmane.org/gmane.comp.apache.apreq/4477 . The fix should look like this: my $cookies; eval { $cookies = Apache2::Cookie->fetch($r) } if ($ <at> ) { $cookies = $ <at> ->jar; $cookies->cookie_class('Apache2::Cookie'); } apperently apreq or rather Apache2::Cookie generates a cookie header that contains "1;" and this causes a Apache2::Cookie parser error. The eval above should at least fix the internal server error problem. And yeah it's a real life application, that might end up in a Opensource project. Right now this is all internal =) but i can't tell you what I use it for. Still it's light waight and was my choice for this project :). Kind regards, Arkadius
$<at> s/b $@ i.e. $EVAL_ERROR ... that is incredibly strange that Apache2::Cookie would be putting itself into $@ in the event of an error.... On Mon Oct 04 06:58:12 2010, rad1us wrote: Show quoted text
> apperently apreq or rather Apache2::Cookie generates a cookie header > that contains "1;" and this causes a Apache2::Cookie parser error. The > eval above should at least fix the internal server error problem.
From http://comments.gmane.org/gmane.comp.apache.apreq/4477 : Show quoted text
> Apreq doesn't generate cookies that would create a "1" in > the client's Cookie header. It's some other application that > did that, but you can tell apreq to ignore the 1 by using eval:
I'm hesitant to slap in a workaround for a buggy client, if that's the reason it doesn't work. I'd like to figure out what the actual problem is and fix that, if it is a problem in A2C. I'm going to have a hard time debugging this without knowing the details of the internal server error. When you get that error, what gets reported in the error log? A2C should log at least part of the exception via Apache2::Log::log_reason(). Are you sure you can't install Log::Log4perl and at least get me the A2C exception and stack trace? Mark
From: arkadius.litwinczuk [...] gmail.com
Hi Mark, now I finally do have some details for you. The Problem is coused by a invalid cookie, a single sign on system is bugged and writes a empty cookie with only a ';' if there is not login at the time. libapreq2 correctly throws a parsing error "TOKEN NOT PRESENT" in the Apache error.log when the invalid cookie is recieved, cousing then an internal server error. So it is not really a problem with a2c but it could be prevented with an eval for the cookie parsing, there is no need for an internal Server error, only the cookie is invalid and should be droped. Would be very cool if you could patch this :). Kind regards from Germany, - Arkadius Am Mo 04. Okt 2010, 18:46:51, MARKLE schrieb: Show quoted text
> > $<at> s/b $@ i.e. $EVAL_ERROR ... that is incredibly strange that > Apache2::Cookie would be putting itself into $@ in the event of an
error.... Show quoted text
> > On Mon Oct 04 06:58:12 2010, rad1us wrote:
> > apperently apreq or rather Apache2::Cookie generates a cookie header > > that contains "1;" and this causes a Apache2::Cookie parser error. The > > eval above should at least fix the internal server error problem.
> > From http://comments.gmane.org/gmane.comp.apache.apreq/4477 :
> > Apreq doesn't generate cookies that would create a "1" in > > the client's Cookie header. It's some other application that > > did that, but you can tell apreq to ignore the 1 by using eval:
> > I'm hesitant to slap in a workaround for a buggy client, if that's the > reason it doesn't work. > > I'd like to figure out what the actual problem is and fix that, if it is > a problem in A2C. > > I'm going to have a hard time debugging this without knowing the details > of the internal server error. When you get that error, what gets > reported in the error log? A2C should log at least part of the > exception via Apache2::Log::log_reason(). > > Are you sure you can't install Log::Log4perl and at least get me the A2C > exception and stack trace? > > Mark
Yargh, I haven't had time to finish the OpenID redirect layer, but I'll disable that and release a bugfix version today.
Show quoted text
> Yargh, I haven't had time to figure out the OpenID redirect layer yet, > but this has stalled too long. I'll disable that module and release a > bugfix version today.
Today meaning 10 days later.... I think the solution I am uploading now will work, but I do not have a test for it. I also put in some Log::Log4perl statements to dump more details about the error. I was conservative and only skip errors when the code is NOTOKEN. It would be nice to have a test script that issues a request with a bad cookie line... unfortunately Apache::Test uses LWP::UserAgent and I'm not sure how to trick HTTP::Cookies into sending a malformed cookie. Maybe setting the header in the $ua just before the request. I am going to go ahead and release 1.0.101, please let me know if it works. --mark--
Someone on apreq-dev mentioned that this is usually a buggy app, not a browser, that sends a bogus cookie, and that sometimes it is a good idea to know this is happening. I decided I would release another version 1.000.110 that does the cookie eval ONLY if new directive A2C_Skip_Bogus_Cookies IS set.
From: arkadius.litwinczuk [...] gmail.com
Hi, yeah it is a buggy app, RSA clear trust to be exact, but I can#t get a test script sorry. I'll be able to test it in January, thank you very much and I let you know how it goes :). Kind regards and merry christmas already! :) - Arkadius Am Di 21. Dez 2010, 19:40:15, MARKLE schrieb: Show quoted text
> Someone on apreq-dev mentioned that this is usually a buggy app, not a > browser, that sends a bogus cookie, and that sometimes it is a good idea > to know this is happening. I decided I would release another version > 1.000.110 that does the cookie eval ONLY if new directive > A2C_Skip_Bogus_Cookies IS set.
Subject: Cookie caching bug
From: Scott Hardin <...> Cc: Arkadius Litwinczuk <...> Subject: Bogus cookies and uncaught exceptions Hi Mark, regarding the new A2C_Skip_Bogus_Cookies option you added, I've stumbled across the problem that the one eval isn't enough when dealing with these bogus cookies. I've added a couple more that I need for my situation to work properly. Attached is a patch file of the changes I made. With best regards, Scott From: Scott T. Hardin <...> Date: Wed, 23 Feb 2011 10:39:47 +0100 Subject: [PATCH] added more evals for bad cookies The initial eval for bad cookies wasn't enough because there are a couple of other spots that throw exceptions when bad cookies were received. --- lib/Apache2/Controller/Methods.pm | 3 ++- lib/Apache2/Controller/Session/Cookie.pm | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/Apache2/Controller/Methods.pm b/lib/Apache2/Controller/Methods.pm index 5746fb2..6fe0a8b 100644 --- a/lib/Apache2/Controller/Methods.pm +++ b/lib/Apache2/Controller/Methods.pm @@ -202,7 +202,8 @@ sub _cookie_jar_debug_sub { my $r = $self->{r}; my $cookie = $r->headers_in->{Cookie}; $cookie = $cookie ? qq{$cookie} : '[no raw cookie string]'; - my @cookie_names = map qq{$_}, $jar->cookies; + my @cookie_names; + eval { @cookie_names = map qq{$_}, $jar->cookies; }; return sub { "raw cookie header: $cookie\n" ."cookie names in jar:\n" diff --git a/lib/Apache2/Controller/Session/Cookie.pm b/lib/Apache2/Controller/Session/Cookie.pm index 7cfafe7..98583dc 100644 --- a/lib/Apache2/Controller/Session/Cookie.pm +++ b/lib/Apache2/Controller/Session/Cookie.pm @@ -83,7 +83,8 @@ sub get_session_id { my $jar = $self->get_cookie_jar(); DEBUG "looking for cookie name '$cookie_name'"; - my $cookie = $jar->cookies($cookie_name); + my $cookie; + eval { $cookie = $jar->cookies($cookie_name); }; DEBUG $cookie ? "found cookie!" : "did not find cookie."; @@ -97,7 +98,8 @@ sub get_session_id { }) }; # if the session_id does not pass signature, return nothing - my $valid_sig = $self->signature($sid); + my $valid_sig; + eval { $valid_sig = $self->signature($sid); }; if ($valid_sig ne $sig) { WARN "signature validation failed"; -- 1.7.3
Subject: Cookie caching bug
Thank you! I will release a fix shortly.
Does this attached source archive work for you? I refactored a few things. I should really write a test for this condition, when client sends a bogus cookie header, with the directive set and not. --mark--
Subject: Apache2-Controller-v1.0.111+beta1.tar.gz

Message body not shown because it is not plain text.

Duh... I think I see how I can test this. I just have to create a cookie jar object that I plug in for LWP, then set the bogus value. I should be able to get to it this weekend.
Hrmm, I can't reproduce this in 1.0.100 - doesn't it seem like this test script should reproduce the bug? --mark--
Subject: session.t
use strict; use warnings FATAL => 'all'; use Apache::Test; use Apache::TestUtil; use Apache::TestRequest qw( GET_BODY GET_STR GET_HEAD ); use FindBin; use Apache2::Const -compile => qw( HTTP_OK ); use lib "$FindBin::Bin/lib"; use Apache2::Controller::Test::Funk qw( diag ); use YAML::Syck; use URI::Escape; my $cookie_name = 'testapp_sessid'; my $cookie_path = '/session'; my @CHARS = ('A'..'Z', 'a'..'z', 0 .. 9); my %TD = ( foo => { boz => [qw( noz schnoz )] }, bar => 'biz', floobie => join('', map $CHARS[int(rand @CHARS)], 1 .. 50), ); my $testdata_dump = Dump(\%TD); use HTTP::Cookies; my $jar = HTTP::Cookies->new(); plan tests => 12, need_lwp; my $ua = Apache::TestRequest::user_agent( cookie_jar => $jar, requests_redirectable => 0, ); Apache::TestRequest::lwp_debug(2); use TestApp::Session::Controller; my $url = "/session"; my $get = "$url/set?data=".uri_escape($testdata_dump); my $response = GET_BODY $get; ok t_cmp($response, "Set session data.\n", "Set data."); $response = GET_BODY "$url/read"; my $session = Load($response); my $response_testdata = $session->{testdata}; ok t_cmp(Dump($response_testdata), $testdata_dump, "Read data."); # what about a redirect? if i save something in a controller # that returns redirect, does it actually get saved? my $redirect = GET_HEAD "$url/redirect"; ok t_cmp($redirect, qr{ ^ \# Location: \s+ \Q$url\E/read }mxs, 'Redirect ok'); my $redirect_set_data = GET_BODY "$url/read"; $session = Load($redirect_set_data); $response_testdata = Dump($session->{testdata}); ok t_cmp($response_testdata, $testdata_dump, "Read data after redirect - did not save."); my $error = GET_HEAD "$url/server_error"; ok t_cmp($error, qr{ ^ \# Title: \s+ 500 \s+ Internal \s+ Server \s+ Error }mxs, 'error page ok' ); # check to make sure the forced-save flag works my $redirect_force_save = GET_HEAD "$url/redirect_force_save"; ok t_cmp($redirect, qr{ ^ \# Location: \s+ \Q$url\E/read }mxs, 'Redirect (force save) ok'); $TD{redirect_data} = 'redirect data test'; $testdata_dump = Dump(\%TD); my $redirect_forced_data = GET_BODY "$url/read"; $session = Load($redirect_forced_data); $response_testdata = Dump($session->{testdata}); ok t_cmp($response_testdata, $testdata_dump, "Read data after redirect with forced save - saved data."); diag("HORTA: jar is '$jar':\n".Dump($jar).$jar->as_string); my $error_data_set = GET_BODY "$url/read"; $session = Load($error_data_set); $response_testdata = Dump($session->{testdata}); #diag($response_testdata); ok t_cmp($response_testdata, $testdata_dump, "Read data after error unchanged."); my $old_sess_id = q{}; $jar->scan(sub { diag("lame:\n".Dump(\@_)); $old_sess_id ||= $_[2]; }); # See HTTP::Cookie diag("session id was '$old_sess_id'"); diag("set raw cookie val to 1 in headers_out (invalid cookie freeze/thaw bug)"); my ($cookie_domain) = keys %{$jar->{COOKIES}}; # ('highlander.therecanbeonly1.com') diag("cookie domain is '$cookie_domain'"); my $full_url = Apache::TestRequest::module2url('', { path => "$url/read" }); diag("full_url: '$full_url'"); $response = $ua->get($full_url); ok t_cmp($response->code, Apache2::Const::HTTP_OK, '2xcheck response is HTTP_OK'); my $doublecheck_sess_id = q{}; $jar->scan(sub { $doublecheck_sess_id ||= $_[2] }); diag('double-check'); ok t_cmp($old_sess_id, $doublecheck_sess_id, 'double-check sess id is the same across requests', ); diag("SPOCK: '$ua'"); $jar->clear(); diag("KIRK: ".Dump($jar)); $response = $ua->get($full_url, 'Set-Cookie3' => qq{1; path="$cookie_path"; domain=$cookie_domain; discard; version=0}); diag("response code:\n".$response->code); diag("as_string:\n".$response->as_string); diag("UHURA: ".Dump($jar)); my $new_sess_id = q{}; $jar->scan(sub { $new_sess_id ||= $_[2] }); ok t_cmp($response->code, Apache2::Const::HTTP_OK, 'response after bad cookie is HTTP_OK', ); ok !t_cmp($new_sess_id, $old_sess_id, 'new sess id is different after bad cookie');
Should be fixed in 1.0.111 uploading now. Not sure the test actually covers the case in question. If you have any trouble please let me know.