Bug 56358 - Cookie manager supports cross port cookies and RFC6265
Summary: Cookie manager supports cross port cookies and RFC6265
Status: RESOLVED FIXED
Alias: None
Product: JMeter
Classification: Unclassified
Component: HTTP (show other bugs)
Version: 2.11
Hardware: All All
: P2 enhancement (vote)
Target Milestone: ---
Assignee: JMeter issues mailing list
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-04-07 18:32 UTC by Zach Calvert
Modified: 2015-12-27 21:12 UTC (History)
2 users (show)



Attachments
Test Plan showing there is no bug (13.47 KB, text/xml)
2014-04-07 20:10 UTC, Philippe Mouawad
Details
Updated Test plan showing it works fine (15.65 KB, application/xml)
2014-04-07 20:53 UTC, Philippe Mouawad
Details
The webapp that supports a servlet on path /ssc/* and /cookie/* (99.84 KB, application/octet-stream)
2014-04-08 03:10 UTC, Zach Calvert
Details
Jmeter script showing the problem (23.47 KB, text/plain)
2014-04-08 03:11 UTC, Zach Calvert
Details
Source code for creating WAR file (7.43 KB, application/octet-stream)
2014-04-08 03:12 UTC, Zach Calvert
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Zach Calvert 2014-04-07 18:32:23 UTC
If you run a ThreadGroup which hits the same server, same domain, different ports, the cookies generated on Port A (ie Set-Cookie header) will not be sent to port B.

Quote from RFC:
http://tools.ietf.org/html/rfc6265
Similarly, cookies for a given host are shared
   across all the ports on that host, even though the usual "same-origin
   policy" used by web browsers isolates content retrieved via different
   ports.
I have tested using IE and FireFox, and the expected behavior of cross-port cookie transfer is supported.

Test method:
Create a test thread group with a cookie manager and any configuration will fail (I have tried them all, all behave the same way)
Run an HTTP GET such as http://remote:10008/get/cookie
Service should set a cookie, such as 
Set-Cookie: test=value;Max-Age=120;Path=/;Version=1

Run another HTTP GET on a different port such as 
http://remote:10001/test/me

Expected behavior:
Cookie "test" should be provided to the server

Actual behavior:
Cookie is not provided to the server
Comment 1 Philippe Mouawad 2014-04-07 20:10:46 UTC
Created attachment 31486 [details]
Test Plan showing there is no bug

Hello,
To use this plan start the 2 mirror servers .
Run plan, you will see that Fist Request to localhost:8082 contains cookie.
Comment 2 Zach Calvert 2014-04-07 20:21:11 UTC
What value is the SetCookie coming back with?

It will work for "/", but not for anything where the port and path are specified, and this may be the difference.  I was under the impression the port was the problem, but perhaps it is because I'm setting the path.  

I'll try to specify the request ins and outs that I'm currently dealing with.

Request 1:
GET http://rhel55:10008/custom/simulated/1.0/sso?generate=true

Response:
Response headers:
HTTP/1.1 200 OK
Content-Type: text/xml
Set-Cookie: simulatedCookie=Tk9URk9SUFJPRFVDVElPTjEzOTY5MDE3NDE5MzF8MTIzNDU2Nzg5MA==;Max-Age=120;Path=/ssc;Version=1

Request 2:
POST http://rhel55:10001/ssc/auth/1.0/validate

The 2nd request matches the same domain, with the "/ssc" path as specified in the cookie.  Again, this works for browsers IE, FireFox, and Chrome, so I believe there is a problem to JMeter.

I can open a browser to 
http://rhel55:10008/custom/simulated/1.0/sso?generate=true
and then open the same browser to GET
http://rhel55:10001/ssc/auth/1.0/validate
and the cookie is sent. 

My differences in my actual code as listed above are 
a) the Path is specified, max-age is specified, and version is specified.
b) The path is a full path (I specify /ssc but the next request path is /ssc/auth/1.0/validate)
c) The second request is a POST, not a get in the jmeter script
Comment 3 Zach Calvert 2014-04-07 20:34:40 UTC
Also, could this be because the domain isn't specified in the result cookie?
Comment 4 Philippe Mouawad 2014-04-07 20:38:20 UTC
Possibly, try changing this in user.properties:
# CookieManager behaviour - check received cookies are valid before storing them?
# Default is true. Use false to revert to previous behaviour
CookieManager.check.cookies=false
Comment 5 Zach Calvert 2014-04-07 20:40:26 UTC
The more I play with it, the more I do believe this is more a problem with the path pattern matching than with the port.

GET:
http://rhel55:10008/custom/simulated/1.0/sso?generate=true
response:
Set-Cookie: simulatedSsoCookie=Tk9URk9SUFJPRFVDVElPTjEzOTY5MDI5NTMyMzN8MTIzNDU2Nzg5MA==;Max-Age=1;Path=/ssc;Version=1

GET: http://rhel55:10008/ssc

no cookie is delivered as part of the request

"/ssc" in the 2nd request should match the "Path=/ssc" listed in the first request.
Comment 6 Zach Calvert 2014-04-07 20:40:48 UTC
I tried your 

# CookieManager behaviour - check received cookies are valid before storing them?
# Default is true. Use false to revert to previous behaviour
CookieManager.check.cookies=false


to no avail
Comment 7 Philippe Mouawad 2014-04-07 20:45:46 UTC
Could you show your Test Plan structure ?
Comment 8 Zach Calvert 2014-04-07 20:50:37 UTC
The moment you said that I was reading again through the HTTP Cookie Manager docs and saw it required addition to the User Threads, not the Test Plan.  The moment I moved it into the User Threads, it started working correctly.

In this case, it seems RTFM is an appropriate request.  You are correct, this is an invalid ticket.
Comment 9 Philippe Mouawad 2014-04-07 20:53:21 UTC
Created attachment 31487 [details]
Updated Test plan showing it works fine
Comment 10 Philippe Mouawad 2014-04-07 20:53:49 UTC
Thanks for feedback.
Comment 11 Zach Calvert 2014-04-07 20:58:14 UTC
*sigh*
I'm making too many parallel movements and it is causing me to trip up and make a mess of this.  Let's try again.

The fix was 
# CookieManager behaviour - check received cookies are valid before storing them?
# Default is true. Use false to revert to previous behaviour
CookieManager.check.cookies=false
and it works.  I was working in the wrong jmeter window.

So now I believe you are correct in that JMeter is treating 
Set-Cookie: simulatedSsoCookie=Tk9URk9SUFJPRFVDVElPTjEzOTY5MDQxMjA3NzN8MTIzNDU2Nzg5MA==;Max-Age=120;Path=/ssc;Version=1
as an invalid cookie.

Browsers IE, Chrome, and FireFox treat this cookie as acceptable.

Is the filter killing it because I use Max-Age instead of expires, or is it due to lack of a domain?  I will try playing with both and report back.
Comment 12 Zach Calvert 2014-04-07 21:24:40 UTC
Alright, we will try this again.  I have modified my code to make this a bit easier to inspect.  I have put together two test cases and have proven that this is a path matching problem, not a port problem.  Note that the only difference of value in the response is the "/ssc" vs "/" in the Path of the Set-Cookie.

Request execution that fails:
GET http://rhel55:10008/custom/simulated/1.0/sso?generate=true

[no cookies]


POST http://rhel55:10001/ssc/auth/1.0/validate

POST data:


[no cookies]


Request execution that succeeds (in that the POST contains the cookie):
GET http://rhel55:10008/custom/simulated/1.0/sso?generate=true

[no cookies]

POST http://rhel55:10001/ssc/auth/1.0/validate

POST data:


Cookie Data:
simulatedCookie=testing
Comment 13 Zach Calvert 2014-04-07 21:26:10 UTC
Would help if I actually managed to specify the response.

Request execution that fails:
GET http://rhel55:10008/custom/simulated/1.0/sso?generate=true

[no cookies]


Response headers:
HTTP/1.1 200 OK
Content-Type: text/xml
Set-Cookie: simulatedCookie=testing;Domain=rhel55;Path=/ssc;Version=1
Transfer-Encoding: chunked
Server: Jetty(7.2.2.v20101205)


POST http://rhel55:10001/ssc/auth/1.0/validate

POST data:


[no cookies]


Request execution that succeeds (in that the POST contains the cookie):
GET http://rhel55:10008/custom/simulated/1.0/sso?generate=true

[no cookies]

Response headers:
HTTP/1.1 200 OK
Content-Type: text/xml
Set-Cookie: simulatedCookie=testing;Domain=rhel55;Path=/ssc;Version=1
Transfer-Encoding: chunked
Server: Jetty(7.2.2.v20101205)

POST http://rhel55:10001/ssc/auth/1.0/validate

POST data:


Cookie Data:
simulatedCookie=testing
Comment 14 Zach Calvert 2014-04-07 21:29:00 UTC
And the mistakes are just piling on.  Sorry, I'm working on a VM tied to a VPN and my copy paste is functioning only sometimes.

That should read that the first GET, in the failing request, results in 
Response headers:
HTTP/1.1 200 OK
Content-Type: text/xml
Set-Cookie: simulatedCookie=testing;Domain=rhel55;Path=/ssc;Version=1
Transfer-Encoding: chunked
Server: Jetty(7.2.2.v20101205)

The second GET that sets the cookie in the successful request results in
Response headers:
HTTP/1.1 200 OK
Content-Type: text/xml
Set-Cookie: simulatedCookie=testing;Domain=rhel55;Path=/;Version=1
Transfer-Encoding: chunked
Server: Jetty(7.2.2.v20101205)


The only change is the Path value.  The request will provide the cookie when the Path is "/" but not when it is "/ssc".  Note the request that will have/not have the cookie is consistent to 
POST http://rhel55:10001/ssc/auth/1.0/validate
Comment 15 Zach Calvert 2014-04-07 21:33:55 UTC
In other words, you should be able to update your code to where it will provide a "/ssc" in the path portion of the Set-Cookie, and your next request to localhost:8181/ssc/test/this/path should result in a cookie being sent, but it will not.

If I may ask, so I can set up an environment using your code base, what are you using to process the requests?
Comment 16 Zach Calvert 2014-04-07 21:44:16 UTC
In addition, I have confirmed (just to be sure)
CookieManager.check.cookies=false
flips the behavior.  So "CookieManager.check.cookies" doesn't seem to think that having "Path=/ssc" makes the cookie valid, but having "Path=/" is acceptable.
Comment 17 Zach Calvert 2014-04-08 03:07:36 UTC
Alright, went home and burned some of my personal time to figure this one out.  I will be attaching a WAR file, some code, and a jmeter script shortly.  

First, make sure you have commented out your cookie manager config:
# CookieManager.check.cookies=false

Key elements:
The request to get the cookie must be on a path not corresponding to the cookie.  
ie request to http://localhost:8080/cookie/get, and the Set-Cookie should have the path set like /ssc,  something NOT related to the request GET query string.

The next Jmeter request http://localhost:8080/ssc will not provide the cookie.  Browsers IE, FireFox, and Chrome support an unrelated path setting the cookie for another path.  I believe this is where the "check.cookies" filter comes into play. What I mean by this is JMeter will not allow http://localhost:8080/cookie to set a cookie with "/ssc" as the path.

So, example request sequence:
GET http://localhost:8080/ssc/somepath/cookie/test?cookieName=test&age=1&path=/cookie&version=1&value=sampleValue
Response cookie:
Set-Cookie: test=sampleValue;Max-Age=1;Path=/cookie;Version=1

Next:
POST http://localhost:8081/cookie/test
This SHOULD have the cookie, but it will not.  I will attach my WAR, my WAR code, and my jmeter script.
Comment 18 Zach Calvert 2014-04-08 03:07:46 UTC
Alright, went home and burned some of my personal time to figure this one out.  I will be attaching a WAR file, some code, and a jmeter script shortly.  

First, make sure you have commented out your cookie manager config:
# CookieManager.check.cookies=false

Key elements:
The request to get the cookie must be on a path not corresponding to the cookie.  
ie request to http://localhost:8080/cookie/get, and the Set-Cookie should have the path set like /ssc,  something NOT related to the request GET query string.

The next Jmeter request http://localhost:8080/ssc will not provide the cookie.  Browsers IE, FireFox, and Chrome support an unrelated path setting the cookie for another path.  I believe this is where the "check.cookies" filter comes into play. What I mean by this is JMeter will not allow http://localhost:8080/cookie to set a cookie with "/ssc" as the path.

So, example request sequence:
GET http://localhost:8080/ssc/somepath/cookie/test?cookieName=test&age=1&path=/cookie&version=1&value=sampleValue
Response cookie:
Set-Cookie: test=sampleValue;Max-Age=1;Path=/cookie;Version=1

Next:
POST http://localhost:8081/cookie/test
This SHOULD have the cookie, but it will not.  I will attach my WAR, my WAR code, and my jmeter script.
Comment 19 Zach Calvert 2014-04-08 03:10:17 UTC
Created attachment 31488 [details]
The webapp that supports a servlet on path /ssc/* and /cookie/*

This WAR file can be deployed on any servlet service.  Note this was built using a JDK 1.6, so it should function on 6/7/8 JDKs.
Comment 20 Zach Calvert 2014-04-08 03:11:47 UTC
Created attachment 31489 [details]
Jmeter script showing the problem

Run this script against the previously attached WAR.  The second execution, POST labeled Show broken for /cookie as Path, should have the cookie as part of the request body.  It will not.
Comment 21 Zach Calvert 2014-04-08 03:12:58 UTC
Created attachment 31490 [details]
Source code for creating WAR file

Zip file of the source code.  Can be built by unzipping and running 
mvn clean install
Output will be in the target directory, webapp.war
Comment 22 Philippe Mouawad 2014-04-08 21:11:13 UTC
Could you confirm you use Compatibility policy for CookieManager ?
Also which implementation of CookieHandler do you use ?
Thanks
Comment 23 Zach Calvert 2014-04-08 21:13:01 UTC
I attached my example.jmx file, you should be able to see everything I have configured.

I used Cookie Policy: "Compatibility" and Implementation: "HC4CookieHandler"
Comment 25 Philippe Mouawad 2014-05-25 20:16:21 UTC
Changing to enhancement as it is possible currently to workaround this as described below:
Set CookieManager.check.cookies=false

Als as per Oleg answer, we need the fix in HTTPClient.
Comment 26 Philippe Mouawad 2015-12-27 21:12:42 UTC
Bug fixed within Bug 57319

Added JUNIT Test case for it.
Author: pmouawad
Date: Sun Dec 27 21:12:04 2015
New Revision: 1721846

URL: http://svn.apache.org/viewvc?rev=1721846&view=rev
Log:
Bug 56358 - Cookie manager supports cross port cookies and RFC6265
Bugzilla Id: 56358

Modified:
    jmeter/trunk/test/src/org/apache/jmeter/protocol/http/control/TestCookieManager.java
    jmeter/trunk/xdocs/changes.xml