Bug 10722 - ProxyPassReverse doesn't change cookie paths
Summary: ProxyPassReverse doesn't change cookie paths
Status: RESOLVED FIXED
Alias: None
Product: Apache httpd-2
Classification: Unclassified
Component: mod_proxy (show other bugs)
Version: 2.0.58
Hardware: Other other
: P3 normal with 11 votes (vote)
Target Milestone: ---
Assignee: Apache HTTPD Bugs Mailing List
URL:
Keywords: PatchAvailable
Depends on:
Blocks:
 
Reported: 2002-07-12 04:31 UTC by Dan Sandberg
Modified: 2009-05-06 12:25 UTC (History)
5 users (show)



Attachments
Against 1.3.26, uses ProxyReversePass setting to rewrite cookies (4.75 KB, patch)
2002-10-07 13:17 UTC, Matthew Stevenson
Details | Diff
Patch against 1.3.27 not great but actually works (touch wood) (7.45 KB, patch)
2002-10-14 13:24 UTC, Matthew Stevenson
Details | Diff
Patch against httpd-2.0.49 (8.33 KB, patch)
2004-06-19 03:32 UTC, Nick Kew
Details | Diff
Corrected (deals with multiple cookies) patch against 2.0.49 (14.92 KB, patch)
2004-06-23 09:21 UTC, Nick Kew
Details | Diff
Documentation patch (URLMapping guide) (1.94 KB, patch)
2004-06-23 10:24 UTC, Nick Kew
Details | Diff
Documentation patch (mod_proxy) (2.42 KB, patch)
2004-06-23 10:25 UTC, Nick Kew
Details | Diff
2.0.53, mult cookie plus location aware (16.50 KB, patch)
2005-06-28 12:33 UTC, Graham Collinson
Details | Diff
Updated patch for "2.0.53, mult cookie plus location aware" to 2.0.55 (24.06 KB, application/octet-stream)
2006-01-16 11:36 UTC, Adam Retter
Details
diff -ur patch for Adam's 2.0.55 update (17.16 KB, patch)
2006-01-16 19:13 UTC, Bill McGonigle
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Dan Sandberg 2002-07-12 04:31:50 UTC
If I have a reverse proxy setup like:

ProxyPassReverse /foo/ http://mononoke/bar/

Then if the mononoke server returns a cookie with path /bar, then it will be
passed back to the client as /bar.  On the next request to /foo, the cookie will
not be sent by the client, and state tracking through cookies will fail.

mod_proxy should convert the cookie path from /bar to /foo, just as it changes
Location and other headers.
Comment 1 Matthew Stevenson 2002-10-07 13:17:09 UTC
Created attachment 3373 [details]
Against 1.3.26, uses ProxyReversePass setting to rewrite cookies
Comment 2 Matthew Stevenson 2002-10-14 13:24:54 UTC
Created attachment 3456 [details]
Patch against 1.3.27 not great but actually works (touch wood)
Comment 3 Graham Leggett 2003-01-08 10:17:17 UTC
Cookie path variables do not necessarily have anything to do with the current
URL, which is why modifying them along with Location is not necessarily what the
administrator might want. (example: the admin might specify path '/' meaning "be
sitewide", and proxy might change "/" to "/bar" in the case of ProxyPassReverse
/bar http://backend/ where the admin did not want this to happen)

A separate configuration parameter is needed for cookies to be modified correctly.
Comment 4 Bill McGonigle 2004-05-13 06:14:40 UTC
One might want to modify both the domain and the path, so you'd need two
directives, right?  For instance:

ProxyPassReverseCookieDomain foo.com bar.com
ProxyPassReverseCookiePath /mailprog /

I'm assuming it's original->new, like most apache directives.

You'd want to be able to set this on a per-url basis, perhaps in a <Directory
proxy:foo> block?

This seems pretty essential for flexible proxy/load balancer setup, so if I
missed an obvious better implementation, please comment.
Comment 5 Graham Leggett 2004-05-21 22:13:56 UTC
ProxyPassReverseCookieDomain and ProxyPassReverseCookiePath seem the right thing
to do. I tend to want to limit the creation of new directives if at all
possible, but here we specifically need to specify behavior for cookie domains
and path.

Now all we need is a patch :)
Comment 6 Nick Kew 2004-06-18 21:15:15 UTC
I've just tried porting this for Apache 2.  It ports just fine, but it's not
adequate: it leaves "domain=foo" strings in a cookie untouched.

Is anyone actually using this?
Comment 7 Nick Kew 2004-06-19 03:30:16 UTC
I've created a patch for this against 2.0.49 - testing encouraged.

I'll port this (with any bugfixes that turn out necessary) to HEAD in the next
few days - someone bug me if I don't:-)
Comment 8 Nick Kew 2004-06-19 03:32:51 UTC
Created attachment 11886 [details]
Patch against httpd-2.0.49
Comment 9 Bill McGonigle 2004-06-19 14:48:16 UTC
Nick, does your patch address Graham's issues?
Comment 10 Nick Kew 2004-06-19 15:32:44 UTC
Bill, yes, it implements ProxyPassReverseCookieDomain and ProxyPassReverseCookiePath

Implementation is in line with the ProxyPassReverse stuff, though I was strongly
tempted to use a regexp instead (and implement regexps in ProxyPassReverse too).
Comment 11 Nick Kew 2004-06-22 14:23:52 UTC
OK, scrub my patch.  It's fine for one cookie, but fails for two or more.
Update to follow.
Comment 12 Nick Kew 2004-06-23 09:21:25 UTC
Created attachment 11915 [details]
Corrected (deals with multiple cookies) patch against 2.0.49
Comment 13 Nick Kew 2004-06-23 10:24:45 UTC
Created attachment 11916 [details]
Documentation patch (URLMapping guide)
Comment 14 Nick Kew 2004-06-23 10:25:32 UTC
Created attachment 11917 [details]
Documentation patch (mod_proxy)
Comment 15 Nick Kew 2004-06-29 06:44:25 UTC
Patch available for 2.0.49; fix now committed to HEAD
Comment 16 Torsten Schlabach 2005-02-26 20:58:54 UTC
(In reply to comment #15)
> Patch available for 2.0.49; fix now committed to HEAD

Why is this still not in, even not in 2.0.53 if it was committed to HEAD?
Comment 17 Graham Collinson 2005-06-28 12:33:18 UTC
Created attachment 15543 [details]
2.0.53, mult cookie plus location aware

patch to check request uri against location ProxyPassReverseCookiePath/Domain
is configured in.  This works for me with 2 different java servlet application
servers behind the proxy each setting jsessionid with path=/
Comment 18 Tony Fogle 2005-08-09 19:35:23 UTC
(In reply to comment #17)
> Created an attachment (id=15543) [edit]
> 2.0.53, mult cookie plus location aware
> 
> patch to check request uri against location ProxyPassReverseCookiePath/Domain
> is configured in.  This works for me with 2 different java servlet application
> servers behind the proxy each setting jsessionid with path=/

My production server is running Fedora Core 2 with the latest available Apache 
available, httpd-2.0.51-2.9.i386.rpm.  Is there a way I can get a patch for this 
version or a patched mod_proxy module to drop in as a replacement for the one from the 
rpm?

I've tested your patch on a test FC4 system with 2.0.53 and was able to get perfect 
results; the persistent login cookie was sent and allowed me to "hide" the dynamic 
pages from the backend server and virtualize them on my public server.

Thanks,
Tony
Comment 19 Bill McGonigle 2005-08-09 21:34:54 UTC
As far as I can tell, this made it to the trunk for Apache 2.1 but not to the 2.0 branch.

http://svn.apache.org/viewcvs.cgi/httpd/httpd/trunk/modules/proxy/mod_proxy.c?
rev=151248&view=markup
http://svn.apache.org/viewcvs.cgi/httpd/httpd/branches/2.0.x/modules/proxy/mod_proxy.c?
rev=151405&view=markup

It went in here:
http://svn.apache.org/viewcvs.cgi?rev=104070&view=rev
Comment 20 Nick Kew 2005-08-11 12:21:48 UTC
I've just posted to dev@httpd.apache.org in support of backporting a fix for 
this so it actually makes it into future 2.0 releases.  So there's an active 
thread now if anyone wants to discuss it. 
Comment 21 cyber 2005-08-22 12:02:10 UTC
Comment on attachment 3373 [details]
Against 1.3.26, uses ProxyReversePass setting to rewrite cookies

*** proxy_http.c	Tue Jun 18 01:59:59 2002
--- proxy_http.c_clean_new	Mon Oct  7 12:33:03 2002
***************
*** 137,142 ****
--- 137,198 ----
      return url;
  }

+ /* Take a cooke value and rewrite the path as required by ProxyPassReverse
setting.
+  * Written for tomcat apps that add cookie path by default. NOT heavily
tested.
+  */
+ 
+ static const char *proxy_cookie_reverse_map(request_rec *r, const char
*cookie_val)
+ {
+   proxy_server_conf *conf;
+   struct proxy_alias *ent;
+   int i, l1, l2, l3, lreal, lrest;
+   char *u;
+   char *real_path;
+   char *ctmp1,*ctmp2,*ctmp3,*fixed = NULL;
+ 
+   conf = (proxy_server_conf *)ap_get_module_config(r->server->module_config,
&proxy_module);
+   l1 = strlen(cookie_val);
+   ent = (struct proxy_alias *)conf->raliases->elts;
+   ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server,
+	       "ProxyPassReverse Original cookie = %s", cookie_val);
+   for (i = 0; i < conf->raliases->nelts; i++) {
+     /* Find just the proxy reverse paths for cookie remapping */
+     ctmp1 = strstr(ent[i].real, "//");
+     /* go passed //, could do this above but simpler here */
+     ctmp1 = ctmp1 + 2;
+     /* find / which should be start of path. We have only a very
+      *	    simple url to parse */
+     real_path = strstr(ctmp1, "/");
+     /*  real_path now has real path so swap real in for fake */
+     if( ctmp1 = strstr(cookie_val, "path=") ){
+	ctmp2 = strstr(ctmp1, ent[i].fake);
+	if ( !ctmp2 ) continue;
+	/* go passed path= */
+	ctmp1 += 5;
+	/* go passed fake entry (bit we are rewriting)*/
+	ctmp2 += strlen(ent[i].fake);
+	/*
+	 * ctmp1 is just passed path= and ctmp2 at end of fake bit,
+	 * now add bits together
+	 * l3 = bit up to end "path=" + lenght real + bit at end fake + \0
+	 */
+	lreal = strlen(real_path);
+	lrest = strlen(ctmp2);
+	l3 = ((int) (ctmp1 - cookie_val)) + lreal + lrest + 1;
+	fixed = ap_palloc(r->pool, l3);
+	strncpy(fixed, cookie_val, (int) (ctmp1 - cookie_val));
+	strncpy(&fixed[(int) (ctmp1 - cookie_val)], ctmp1, lreal);
+	strncpy(&fixed[(int) (ctmp1 - cookie_val + lreal)], ctmp2, lrest);
+	/* strncpy(&fixed[(int) (ctmp1 - a + lreal + lrest)], '\0', 1); */
+	ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server,
+		   "ProxyPassReverse Fixed cookie = %s", fixed);
+     }
+   }
+   if( fixed ) return fixed;
+   return cookie_val;
+ }
+ 
+ 
  /*
   * This handles http:// URLs, and other URLs using a remote proxy over http
   * If proxyhost is NULL, then contact the server directly, otherwise
***************
*** 153,161 ****
      char *strp2;
      const char *err, *desthost;
      int i, j, sock,/* len,*/ backasswards;
!     table *req_hdrs, *resp_hdrs;
!     array_header *reqhdrs_arr;
!     table_entry *reqhdrs_elts;
      struct sockaddr_in server;
      struct in_addr destaddr;
      struct hostent server_hp;
--- 209,217 ----
      char *strp2;
      const char *err, *desthost;
      int i, j, sock,/* len,*/ backasswards;
!     table *req_hdrs, *resp_hdrs, *cookie_temp;
!     array_header *reqhdrs_arr, *resphdrs_arr;
!     table_entry *reqhdrs_elts, *resphdrs_elts;
      struct sockaddr_in server;
      struct in_addr destaddr;
      struct hostent server_hp;
***************
*** 555,560 ****
--- 611,638 ----
      if ((urlstr = ap_table_get(resp_hdrs, "Content-Location")) != NULL)
	  ap_table_set(resp_hdrs, "Content-Location",
proxy_location_reverse_map(r, urlstr));

+     cookie_temp = ap_make_table( r->pool, 2);
+     resphdrs_arr = ap_table_elts(resp_hdrs);
+     resphdrs_elts = (table_entry *)resphdrs_arr->elts;
+     for (i = 0; i < resphdrs_arr->nelts; i++) {
+	if ( strcmp(resphdrs_elts[i].key, "Set-Cookie") == 0 ){
+	ap_table_add( cookie_temp, "Set-Cookie", proxy_cookie_reverse_map(r,
resphdrs_elts[i].val) );
+	ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server,
+		 "Added cookie Set-Cookie to cookie_temp = %s",
proxy_cookie_reverse_map(r, resphdrs_elts[i].val) );
+	}
+     }
+ 
+     if( ! ap_is_empty_table( cookie_temp ) ){
+	ap_table_unset(resp_hdrs, "Set-Cookie");
+	resphdrs_arr = ap_table_elts(cookie_temp);
+	resphdrs_elts = (table_entry *)resphdrs_arr->elts;
+	for (i = 0; i < resphdrs_arr->nelts; i++) {
+	ap_table_add(resp_hdrs, "Set-Cookie", resphdrs_elts[i].val);
+	ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server,
+		     "Added cookie Set-Cookie to resp_hdrs = %s",
resphdrs_elts[i].val);
+	}
+     }
+ 
  /* check if NoCache directive on this host */
      if (nocache == 0) {
	  for (i = 0; i < conf->nocaches->nelts; i++) {
Comment 22 cyber 2005-08-22 12:02:32 UTC
*** proxy_http.c	Tue Jun 18 01:59:59 2002
--- proxy_http.c_clean_new	Mon Oct  7 12:33:03 2002
***************
*** 137,142 ****
--- 137,198 ----
      return url;
  }
  
+ /* Take a cooke value and rewrite the path as required by ProxyPassReverse 
setting.
+  * Written for tomcat apps that add cookie path by default. NOT heavily 
tested.
+  */
+ 
+ static const char *proxy_cookie_reverse_map(request_rec *r, const char 
*cookie_val)
+ {
+   proxy_server_conf *conf;
+   struct proxy_alias *ent;
+   int i, l1, l2, l3, lreal, lrest;
+   char *u;
+   char *real_path;
+   char *ctmp1,*ctmp2,*ctmp3,*fixed = NULL;
+ 
+   conf = (proxy_server_conf *)ap_get_module_config(r->server->module_config, 
&proxy_module);
+   l1 = strlen(cookie_val);
+   ent = (struct proxy_alias *)conf->raliases->elts;
+   ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server,
+ 	       "ProxyPassReverse Original cookie = %s", cookie_val);
+   for (i = 0; i < conf->raliases->nelts; i++) {
+     /* Find just the proxy reverse paths for cookie remapping */
+     ctmp1 = strstr(ent[i].real, "//");
+     /* go passed //, could do this above but simpler here */
+     ctmp1 = ctmp1 + 2;
+     /* find / which should be start of path. We have only a very
+      *            simple url to parse */
+     real_path = strstr(ctmp1, "/");
+     /*  real_path now has real path so swap real in for fake */
+     if( ctmp1 = strstr(cookie_val, "path=") ){
+       ctmp2 = strstr(ctmp1, ent[i].fake);
+       if ( !ctmp2 ) continue;
+       /* go passed path= */
+       ctmp1 += 5;
+       /* go passed fake entry (bit we are rewriting)*/
+       ctmp2 += strlen(ent[i].fake);
+       /*
+        * ctmp1 is just passed path= and ctmp2 at end of fake bit,
+        * now add bits together
+        * l3 = bit up to end "path=" + lenght real + bit at end fake + \0
+        */
+       lreal = strlen(real_path);
+       lrest = strlen(ctmp2);
+       l3 = ((int) (ctmp1 - cookie_val)) + lreal + lrest + 1;
+       fixed = ap_palloc(r->pool, l3);
+       strncpy(fixed, cookie_val, (int) (ctmp1 - cookie_val));
+       strncpy(&fixed[(int) (ctmp1 - cookie_val)], ctmp1, lreal);
+       strncpy(&fixed[(int) (ctmp1 - cookie_val + lreal)], ctmp2, lrest);
+       /* strncpy(&fixed[(int) (ctmp1 - a + lreal + lrest)], '\0', 1); */
+       ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server,
+ 		   "ProxyPassReverse Fixed cookie = %s", fixed);
+     }
+   }
+   if( fixed ) return fixed;
+   return cookie_val;
+ }
+ 
+ 
  /*
   * This handles http:// URLs, and other URLs using a remote proxy over http
   * If proxyhost is NULL, then contact the server directly, otherwise
***************
*** 153,161 ****
      char *strp2;
      const char *err, *desthost;
      int i, j, sock,/* len,*/ backasswards;
!     table *req_hdrs, *resp_hdrs;
!     array_header *reqhdrs_arr;
!     table_entry *reqhdrs_elts;
      struct sockaddr_in server;
      struct in_addr destaddr;
      struct hostent server_hp;
--- 209,217 ----
      char *strp2;
      const char *err, *desthost;
      int i, j, sock,/* len,*/ backasswards;
!     table *req_hdrs, *resp_hdrs, *cookie_temp;
!     array_header *reqhdrs_arr, *resphdrs_arr;
!     table_entry *reqhdrs_elts, *resphdrs_elts;
      struct sockaddr_in server;
      struct in_addr destaddr;
      struct hostent server_hp;
***************
*** 555,560 ****
--- 611,638 ----
      if ((urlstr = ap_table_get(resp_hdrs, "Content-Location")) != NULL)
          ap_table_set(resp_hdrs, "Content-Location", proxy_location_reverse_map
(r, urlstr));
  
+     cookie_temp = ap_make_table( r->pool, 2);
+     resphdrs_arr = ap_table_elts(resp_hdrs);
+     resphdrs_elts = (table_entry *)resphdrs_arr->elts;
+     for (i = 0; i < resphdrs_arr->nelts; i++) {
+       if ( strcmp(resphdrs_elts[i].key, "Set-Cookie") == 0 ){
+ 	ap_table_add( cookie_temp, "Set-Cookie", proxy_cookie_reverse_map(r, 
resphdrs_elts[i].val) );
+ 	ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server,
+ 		 "Added cookie Set-Cookie to cookie_temp = %s", 
proxy_cookie_reverse_map(r, resphdrs_elts[i].val) );
+       }
+     }
+ 
+     if( ! ap_is_empty_table( cookie_temp ) ){
+       ap_table_unset(resp_hdrs, "Set-Cookie");
+       resphdrs_arr = ap_table_elts(cookie_temp);
+       resphdrs_elts = (table_entry *)resphdrs_arr->elts;
+       for (i = 0; i < resphdrs_arr->nelts; i++) {
+ 	ap_table_add(resp_hdrs, "Set-Cookie", resphdrs_elts[i].val);
+ 	ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server,
+ 		     "Added cookie Set-Cookie to resp_hdrs = %s", resphdrs_elts
[i].val);
+       }
+     }
+ 
  /* check if NoCache directive on this host */
      if (nocache == 0) {
          for (i = 0; i < conf->nocaches->nelts; i++) {

Comment 23 Adam Retter 2006-01-16 11:36:34 UTC
Created attachment 17430 [details]
Updated patch for "2.0.53, mult cookie plus location aware" to 2.0.55

Updated the patch for 2.0.53 so that it applies to 2.0.55, wasnt sure how to
produce a patch file so have attached the updated mod_proxy.c mod_proxy.h and
proxy_http.c files for mod_proxy 2.0.55.

Would be great if this could make it back into the source tree, im sure other
users out there need this as well as me...
Comment 24 Bill McGonigle 2006-01-16 19:13:15 UTC
Created attachment 17438 [details]
diff -ur patch for Adam's 2.0.55 update

This is just a diff -ur format patch for Adam's update work. This should make
it fit the Apache process better and hopefully increase odds of landing.  This
is still Adam's work, not mine, all I did was run diff.
Comment 25 Francisco Gimeno 2006-04-20 19:49:34 UTC
The 2.0.55 Adam's patch doesn't work Right.

I really haven't studied the case. But one of my customers complained about some
header variables not propagated to the real server.

I know it was with a very large HTTP Header variable. I have made the test by
myself today and I could see cleanly that it failed just by being compiled. I
tried an unpatched Apache an it worked pretty fine.

I think I can make more tests but not today.. This comments is to say to you:
don't put that patch in a production environment. ;)

Thx
Comment 26 Nick Kew 2006-04-20 20:37:50 UTC
(In reply to comment #25) 
> The 2.0.55 Adam's patch doesn't work Right. 
 
2.0.55 has new proxy problems (see bug 37145).  Upgrade to 2.2 if you want 
this functionality.  Other 2.0 variants (eg 2.0.54) are an option if you want 
the proxy but don't care about proxied cookies. 
 
There's also a patch for 2.0-trunk at 
http://people.apache.org/~colm/httpd-2.0-reverse-proxy-cookie.patch 
Comment 27 Francisco Gimeno 2006-04-20 23:01:00 UTC
Please, forget my previous message 
(http://issues.apache.org/bugzilla/show_bug.cgi?id=10722#c25). As I have read 
the #c26, I realize that I didn't include the #37145 patch at the same time 
that this patch. So, finally, it was failing because the lack of #37145. As I 
restored a previous package with it enable, I got it working again.

This patch could work perfectly, but I didn't tested it well. No conclusion for 
me yet.
Comment 28 Nick Kew 2006-09-14 13:42:19 UTC
*** Bug 40492 has been marked as a duplicate of this bug. ***
Comment 29 Tige Chastain 2006-11-02 10:54:42 UTC
Is anyone updating patches for the new 2.0 releases for this?  I have a case 
where I need to utilize the ProxyPassReverseCookieDomain and 
ProxyPassReverseCookiePath in the latest 2.0 tree.

Comment 30 Davi Arnaut 2007-06-08 06:31:12 UTC
Closing, as this has been fixed in the stable 2.2.x branch. A updated patch for the 2.0.x branch
can be found at http://people.apache.org/~colm/httpd-2.0-reverse-proxy-cookie.patch
Also, the 2.0.x patch is up for vote and should be committed soon (missing just one vote).
Comment 31 Thomas Blick 2008-02-21 01:28:05 UTC
Is there a patch available for v2.0.61 or v2.0.63?
Moving to httpd v2.2.x unfortunately is no option in the environment where I 
need the patch. 
Could you help please?

http://people.apache.org/~colm/httpd-2.0-reverse-proxy-cookie.patch
only works up to v2.0.59
Comment 32 William A. Rowe Jr. 2009-05-06 12:25:51 UTC
Do not reopen to request backports.  This is an issues tracking database for
the code development, not a user support forum