92baa4
From 4ce37d79704623778fbe266397c85ed2b735e4dd Mon Sep 17 00:00:00 2001
92baa4
From: Daniel Stenberg <daniel@haxx.se>
92baa4
Date: Fri, 15 Mar 2013 14:18:16 +0100
92baa4
Subject: [PATCH 1/7] HTTP proxy: insert slash in URL if missing
92baa4
92baa4
curl has been accepting URLs using slightly wrong syntax for a long
92baa4
time, such as when completely missing as slash "http://example.org" or
92baa4
missing a slash when a query part is given
92baa4
"http://example.org?q=foobar".
92baa4
92baa4
curl would translate these into a legitimate HTTP request to servers,
92baa4
although as was shown in bug #1206 it was not adjusted properly in the
92baa4
cases where a HTTP proxy was used.
92baa4
92baa4
Test 1213 and 1214 were added to the test suite to verify this fix.
92baa4
92baa4
The test HTTP server was adjusted to allow us to specify test number in
92baa4
the host name only without using any slashes in a given URL.
92baa4
92baa4
Bug: http://curl.haxx.se/bug/view.cgi?id=1206
92baa4
Reported by: ScottJi
92baa4
92baa4
Upstream-commit: e4b733e3f1a771bd1017cdcfb355fcb9caffe646
92baa4
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
92baa4
---
92baa4
 lib/url.c              | 38 ++++++++++++++++++++++++++++++++++
92baa4
 tests/FILEFORMAT       |  4 ++++
92baa4
 tests/data/Makefile.am |  2 +-
92baa4
 tests/data/Makefile.in |  2 +-
92baa4
 tests/data/test1213    | 53 +++++++++++++++++++++++++++++++++++++++++++++++
92baa4
 tests/data/test1214    | 53 +++++++++++++++++++++++++++++++++++++++++++++++
92baa4
 tests/server/sws.c     | 56 ++++++++++++++++++++++++++++++++++++++++++--------
92baa4
 7 files changed, 198 insertions(+), 10 deletions(-)
92baa4
 create mode 100644 tests/data/test1213
92baa4
 create mode 100644 tests/data/test1214
92baa4
92baa4
diff --git a/lib/url.c b/lib/url.c
92baa4
index 181f0a4..77549ba 100644
92baa4
--- a/lib/url.c
92baa4
+++ b/lib/url.c
92baa4
@@ -3584,6 +3584,7 @@ static CURLcode parseurlandfillconn(struct SessionHandle *data,
92baa4
   char protobuf[16];
92baa4
   const char *protop;
92baa4
   CURLcode result;
92baa4
+  bool fix_slash = FALSE;
92baa4
 
92baa4
   *prot_missing = FALSE;
92baa4
 
92baa4
@@ -3730,12 +3731,14 @@ static CURLcode parseurlandfillconn(struct SessionHandle *data,
92baa4
     memcpy(path+1, query, hostlen);
92baa4
 
92baa4
     path[0]='/'; /* prepend the missing slash */
92baa4
+    fix_slash = TRUE;
92baa4
 
92baa4
     *query=0; /* now cut off the hostname at the ? */
92baa4
   }
92baa4
   else if(!path[0]) {
92baa4
     /* if there's no path set, use a single slash */
92baa4
     strcpy(path, "/");
92baa4
+    fix_slash = TRUE;
92baa4
   }
92baa4
 
92baa4
   /* If the URL is malformatted (missing a '/' after hostname before path) we
92baa4
@@ -3748,6 +3751,41 @@ static CURLcode parseurlandfillconn(struct SessionHandle *data,
92baa4
        is bigger than the path. Use +1 to move the zero byte too. */
92baa4
     memmove(&path[1], path, strlen(path)+1);
92baa4
     path[0] = '/';
92baa4
+    fix_slash = TRUE;
92baa4
+  }
92baa4
+
92baa4
+
92baa4
+  /*
92baa4
+   * "fix_slash" means that the URL was malformatted so we need to generate an
92baa4
+   * updated version with the new slash inserted at the right place!  We need
92baa4
+   * the corrected URL when communicating over HTTP proxy and we don't know at
92baa4
+   * this point if we're using a proxy or not.
92baa4
+   */
92baa4
+  if(fix_slash) {
92baa4
+    char *reurl;
92baa4
+
92baa4
+    size_t plen = strlen(path); /* new path, should be 1 byte longer than
92baa4
+                                   the original */
92baa4
+    size_t urllen = strlen(data->change.url); /* original URL length */
92baa4
+
92baa4
+    reurl = malloc(urllen + 2); /* 2 for zerobyte + slash */
92baa4
+    if(!reurl)
92baa4
+      return CURLE_OUT_OF_MEMORY;
92baa4
+
92baa4
+    /* copy the prefix */
92baa4
+    memcpy(reurl, data->change.url, urllen - (plen-1));
92baa4
+
92baa4
+    /* append the trailing piece + zerobyte */
92baa4
+    memcpy(&reurl[urllen - (plen-1)], path, plen + 1);
92baa4
+
92baa4
+    /* possible free the old one */
92baa4
+    if(data->change.url_alloc) {
92baa4
+      Curl_safefree(data->change.url);
92baa4
+      data->change.url_alloc = FALSE;
92baa4
+    }
92baa4
+
92baa4
+    data->change.url = reurl;
92baa4
+    data->change.url_alloc = TRUE; /* free this later */
92baa4
   }
92baa4
 
92baa4
   /*************************************************************
92baa4
diff --git a/tests/FILEFORMAT b/tests/FILEFORMAT
92baa4
index d79cbf7..96cd5c8 100644
92baa4
--- a/tests/FILEFORMAT
92baa4
+++ b/tests/FILEFORMAT
92baa4
@@ -250,6 +250,10 @@ If a CONNECT is used to the server (to emulate HTTPS etc over proxy), the port
92baa4
 number given in the CONNECT request will be used to identify which test that
92baa4
 is being run, if the proxy host name is said to start with 'test'.
92baa4
 
92baa4
+If there's no non-zero test number found in the above to places, the HTTP test
92baa4
+server will use the number following the last dot in the given url so that
92baa4
+"foo.bar.123" gets treated as test case 123.
92baa4
+
92baa4
 Set type="perl" to write the test case as a perl script. It implies that
92baa4
 there's no memory debugging and valgrind gets shut off for this test.
92baa4
 
92baa4
diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am
92baa4
index 4e37ed9..5e12f62 100644
92baa4
--- a/tests/data/Makefile.am
92baa4
+++ b/tests/data/Makefile.am
92baa4
@@ -77,7 +77,7 @@ test1110 test1111 test1112 test1113 test1114 test1115 test1116 test1117	\
92baa4
 test1118 test1119 test1120 test1121 test1122 test1123 test1124 test1125	\
92baa4
 test1126 test1127 test1128 test1129 test1130 test1131 test1132 test1133 \
92baa4
 test1200 test1201 test1202 test1203 test1204 test1205 test1206 test1207 \
92baa4
-test1208 test1209 test1210 test1211 test1216 test1218 \
92baa4
+test1208 test1209 test1210 test1211 test1213 test1214 test1216 test1218 \
92baa4
 test1220 test1221 test1222 test1223 test1233 \
92baa4
 test1300 test1301 test1302 test1303 test1304 test1305	\
92baa4
 test1306 test1307 test1308 test1309 test1310 test1311 test1312 test1313 \
92baa4
diff --git a/tests/data/Makefile.in b/tests/data/Makefile.in
92baa4
index d7f9ac2..597c1fb 100644
92baa4
--- a/tests/data/Makefile.in
92baa4
+++ b/tests/data/Makefile.in
92baa4
@@ -341,7 +341,7 @@ test1110 test1111 test1112 test1113 test1114 test1115 test1116 test1117	\
92baa4
 test1118 test1119 test1120 test1121 test1122 test1123 test1124 test1125	\
92baa4
 test1126 test1127 test1128 test1129 test1130 test1131 test1132 test1133 \
92baa4
 test1200 test1201 test1202 test1203 test1204 test1205 test1206 test1207 \
92baa4
-test1208 test1209 test1210 test1211 test1216 test1218 \
92baa4
+test1208 test1209 test1210 test1211 test1213 test1214 test1216 test1218 \
92baa4
 test1220 test1221 test1222 test1223 \
92baa4
 test1300 test1301 test1302 test1303 test1304 test1305	\
92baa4
 test1306 test1307 test1308 test1309 test1310 test1311 test1312 test1313 \
92baa4
diff --git a/tests/data/test1213 b/tests/data/test1213
92baa4
new file mode 100644
92baa4
index 0000000..d0d12b4
92baa4
--- /dev/null
92baa4
+++ b/tests/data/test1213
92baa4
@@ -0,0 +1,53 @@
92baa4
+<testcase>
92baa4
+<info>
92baa4
+<keywords>
92baa4
+HTTP
92baa4
+HTTP GET
92baa4
+HTTP proxy
92baa4
+</keywords>
92baa4
+</info>
92baa4
+
92baa4
+# Server-side
92baa4
+<reply>
92baa4
+<data>
92baa4
+HTTP/1.1 200 OK
92baa4
+Date: Thu, 09 Nov 2010 14:49:00 GMT
92baa4
+Server: test-server/fake
92baa4
+Content-Type: text/html
92baa4
+Funny-head: yesyes
92baa4
+Content-Length: 22
92baa4
+
92baa4
+the content goes here
92baa4
+</data>
92baa4
+</reply>
92baa4
+
92baa4
+# Client-side
92baa4
+<client>
92baa4
+<server>
92baa4
+http
92baa4
+</server>
92baa4
+ <name>
92baa4
+HTTP with proxy and host-only URL
92baa4
+ </name>
92baa4
+# the thing here is that this sloppy form is accepted and we convert it
92baa4
+# for normal server use, and we need to make sure it gets converted to
92baa4
+# RFC style even for proxies
92baa4
+ <command>
92baa4
+-x %HOSTIP:%HTTPPORT we.want.that.site.com.1213
92baa4
+</command>
92baa4
+</client>
92baa4
+
92baa4
+# Verify data after the test has been "shot"
92baa4
+<verify>
92baa4
+<strip>
92baa4
+^User-Agent:.*
92baa4
+</strip>
92baa4
+<protocol>
92baa4
+GET HTTP://we.want.that.site.com.1213/ HTTP/1.1
92baa4
+Host: we.want.that.site.com.1213
92baa4
+Accept: */*
92baa4
+Proxy-Connection: Keep-Alive
92baa4
+
92baa4
+</protocol>
92baa4
+</verify>
92baa4
+</testcase>
92baa4
diff --git a/tests/data/test1214 b/tests/data/test1214
92baa4
new file mode 100644
92baa4
index 0000000..8c36ade
92baa4
--- /dev/null
92baa4
+++ b/tests/data/test1214
92baa4
@@ -0,0 +1,53 @@
92baa4
+<testcase>
92baa4
+<info>
92baa4
+<keywords>
92baa4
+HTTP
92baa4
+HTTP GET
92baa4
+HTTP proxy
92baa4
+</keywords>
92baa4
+</info>
92baa4
+
92baa4
+# Server-side
92baa4
+<reply>
92baa4
+<data>
92baa4
+HTTP/1.1 200 OK
92baa4
+Date: Thu, 09 Nov 2010 14:49:00 GMT
92baa4
+Server: test-server/fake
92baa4
+Content-Type: text/html
92baa4
+Funny-head: yesyes
92baa4
+Content-Length: 22
92baa4
+
92baa4
+the content goes here
92baa4
+</data>
92baa4
+</reply>
92baa4
+
92baa4
+# Client-side
92baa4
+<client>
92baa4
+<server>
92baa4
+http
92baa4
+</server>
92baa4
+ <name>
92baa4
+HTTP with proxy and URL with ? and no slash separator
92baa4
+ </name>
92baa4
+# the thing here is that this sloppy form is accepted and we convert it
92baa4
+# for normal server use, and we need to make sure it gets converted to
92baa4
+# RFC style even for proxies
92baa4
+ <command>
92baa4
+-x %HOSTIP:%HTTPPORT http://we.want.that.site.com.1214?moo=foo
92baa4
+</command>
92baa4
+</client>
92baa4
+
92baa4
+# Verify data after the test has been "shot"
92baa4
+<verify>
92baa4
+<strip>
92baa4
+^User-Agent:.*
92baa4
+</strip>
92baa4
+<protocol>
92baa4
+GET http://we.want.that.site.com.1214/?moo=foo HTTP/1.1
92baa4
+Host: we.want.that.site.com.1214
92baa4
+Accept: */*
92baa4
+Proxy-Connection: Keep-Alive
92baa4
+
92baa4
+</protocol>
92baa4
+</verify>
92baa4
+</testcase>
92baa4
diff --git a/tests/server/sws.c b/tests/server/sws.c
92baa4
index a7de09f..aef55ea 100644
92baa4
--- a/tests/server/sws.c
92baa4
+++ b/tests/server/sws.c
92baa4
@@ -507,15 +507,24 @@ static int ProcessRequest(struct httprequest *req)
92baa4
       else
92baa4
         req->partno = 0;
92baa4
 
92baa4
-      sprintf(logbuf, "Requested test number %ld part %ld",
92baa4
-              req->testno, req->partno);
92baa4
-      logmsg("%s", logbuf);
92baa4
+      if(req->testno) {
92baa4
+
92baa4
+        sprintf(logbuf, "Requested test number %ld part %ld",
92baa4
+                req->testno, req->partno);
92baa4
+        logmsg("%s", logbuf);
92baa4
 
92baa4
-      /* find and parse <servercmd> for this test */
92baa4
-      parse_servercmd(req);
92baa4
+        /* find and parse <servercmd> for this test */
92baa4
+        parse_servercmd(req);
92baa4
+      }
92baa4
+      else
92baa4
+        req->testno = DOCNUMBER_NOTHING;
92baa4
 
92baa4
     }
92baa4
-    else {
92baa4
+
92baa4
+    if(req->testno == DOCNUMBER_NOTHING) {
92baa4
+      /* didn't find any in the first scan, try alternative test case
92baa4
+         number placements */
92baa4
+
92baa4
       if(sscanf(req->reqbuf, "CONNECT %" MAXDOCNAMELEN_TXT "s HTTP/%d.%d",
92baa4
                 doc, &prot_major, &prot_minor) == 3) {
92baa4
         char *portp = NULL;
92baa4
@@ -563,8 +572,39 @@ static int ProcessRequest(struct httprequest *req)
92baa4
         parse_servercmd(req);
92baa4
       }
92baa4
       else {
92baa4
-        logmsg("Did not find test number in PATH");
92baa4
-        req->testno = DOCNUMBER_404;
92baa4
+        /* there was no trailing slash and it wasn't CONNECT, then we get the
92baa4
+           the number off the last dot instead, IE we consider the TLD to be
92baa4
+           the test number. Test 123 can then be written as
92baa4
+           "example.com.123". */
92baa4
+
92baa4
+        /* find the last dot */
92baa4
+        ptr = strrchr(doc, '.');
92baa4
+
92baa4
+        /* get the number after it */
92baa4
+        if(ptr) {
92baa4
+          ptr++; /* skip the dot */
92baa4
+
92baa4
+          req->testno = strtol(ptr, &ptr, 10);
92baa4
+
92baa4
+          if(req->testno > 10000) {
92baa4
+            req->partno = req->testno % 10000;
92baa4
+            req->testno /= 10000;
92baa4
+          }
92baa4
+          else
92baa4
+            req->partno = 0;
92baa4
+
92baa4
+          sprintf(logbuf, "Requested test number %ld part %ld (from host name)",
92baa4
+                  req->testno, req->partno);
92baa4
+          logmsg("%s", logbuf);
92baa4
+
92baa4
+        }
92baa4
+
92baa4
+        if(!req->testno) {
92baa4
+          logmsg("Did not find test number in PATH");
92baa4
+          req->testno = DOCNUMBER_404;
92baa4
+        }
92baa4
+        else
92baa4
+          parse_servercmd(req);
92baa4
       }
92baa4
     }
92baa4
   }
92baa4
-- 
92baa4
2.1.0
92baa4
92baa4
92baa4
From 052143a4aaac9ce91ffdb6ae88eb5888c54d66aa Mon Sep 17 00:00:00 2001
92baa4
From: YAMADA Yasuharu <yasuharu.yamada@access-company.com>
92baa4
Date: Sat, 18 May 2013 22:51:31 +0200
92baa4
Subject: [PATCH 2/7] cookies: only consider full path matches
92baa4
92baa4
I found a bug which cURL sends cookies to the path not to aim at.
92baa4
For example:
92baa4
- cURL sends a request to http://example.fake/hoge/
92baa4
- server returns cookie which with path=/hoge;
92baa4
  the point is there is NOT the '/' end of path string.
92baa4
- cURL sends a request to http://example.fake/hogege/ with the cookie.
92baa4
92baa4
The reason for this old "feature" is because that behavior is what is
92baa4
described in the original netscape cookie spec:
92baa4
http://curl.haxx.se/rfc/cookie_spec.html
92baa4
92baa4
The current cookie spec (RFC6265) clarifies the situation:
92baa4
http://tools.ietf.org/html/rfc6265#section-5.2.4
92baa4
Upstream-commit: 04f52e9b4db01bcbf672c9c69303a4e4ad0d0fb9
92baa4
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
92baa4
---
92baa4
 lib/cookie.c           | 33 ++++++++++++++++++++++++++----
92baa4
 tests/data/Makefile.am |  2 +-
92baa4
 tests/data/Makefile.in |  2 +-
92baa4
 tests/data/test1228    | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++
92baa4
 tests/data/test46      |  8 ++++----
92baa4
 tests/data/test8       |  2 +-
92baa4
 6 files changed, 90 insertions(+), 11 deletions(-)
92baa4
 create mode 100644 tests/data/test1228
92baa4
92baa4
diff --git a/lib/cookie.c b/lib/cookie.c
92baa4
index ac4d89c..a4480c0 100644
92baa4
--- a/lib/cookie.c
92baa4
+++ b/lib/cookie.c
92baa4
@@ -143,6 +143,34 @@ static bool tailmatch(const char *cooke_domain, const char *hostname)
92baa4
   return FALSE;
92baa4
 }
92baa4
 
92baa4
+static bool pathmatch(const char* cookie_path, const char* url_path)
92baa4
+{
92baa4
+  size_t cookie_path_len = strlen(cookie_path);
92baa4
+  size_t url_path_len = strlen(url_path);
92baa4
+
92baa4
+  if(url_path_len < cookie_path_len)
92baa4
+    return FALSE;
92baa4
+
92baa4
+  /* not using checkprefix() because matching should be case-sensitive */
92baa4
+  if(strncmp(cookie_path, url_path, cookie_path_len))
92baa4
+    return FALSE;
92baa4
+
92baa4
+  /* it is true if cookie_path and url_path are the same */
92baa4
+  if(cookie_path_len == url_path_len)
92baa4
+    return TRUE;
92baa4
+
92baa4
+  /* here, cookie_path_len < url_path_len */
92baa4
+
92baa4
+  /* it is false if cookie path is /example and url path is /examples */
92baa4
+  if(cookie_path[cookie_path_len - 1] != '/') {
92baa4
+    if(url_path[cookie_path_len] != '/') {
92baa4
+      return FALSE;
92baa4
+    }
92baa4
+  }
92baa4
+  /* matching! */
92baa4
+  return TRUE;
92baa4
+}
92baa4
+
92baa4
 /*
92baa4
  * Load cookies from all given cookie files (CURLOPT_COOKIEFILE).
92baa4
  */
92baa4
@@ -841,10 +869,7 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
92baa4
 
92baa4
         /* now check the left part of the path with the cookies path
92baa4
            requirement */
92baa4
-        if(!co->path ||
92baa4
-           /* not using checkprefix() because matching should be
92baa4
-              case-sensitive */
92baa4
-           !strncmp(co->path, path, strlen(co->path)) ) {
92baa4
+        if(!co->path || pathmatch(co->path, path) ) {
92baa4
 
92baa4
           /* and now, we know this is a match and we should create an
92baa4
              entry for the return-linked-list */
92baa4
diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am
92baa4
index 4e37ed9..64662c6 100644
92baa4
--- a/tests/data/Makefile.am
92baa4
+++ b/tests/data/Makefile.am
92baa4
@@ -78,7 +78,7 @@ test1118 test1119 test1120 test1121 test1122 test1123 test1124 test1125	\
92baa4
 test1126 test1127 test1128 test1129 test1130 test1131 test1132 test1133 \
92baa4
 test1200 test1201 test1202 test1203 test1204 test1205 test1206 test1207 \
92baa4
 test1208 test1209 test1210 test1211 test1213 test1214 test1216 test1218 \
92baa4
-test1220 test1221 test1222 test1223 test1233 \
92baa4
+test1220 test1221 test1222 test1223 test1233 test1236 \
92baa4
 test1300 test1301 test1302 test1303 test1304 test1305	\
92baa4
 test1306 test1307 test1308 test1309 test1310 test1311 test1312 test1313 \
92baa4
 test1314 test1315 test1316 test1317 test1318 test1319 test1320 test1321 \
92baa4
diff --git a/tests/data/Makefile.in b/tests/data/Makefile.in
92baa4
index 1e6d679..5296c09 100644
92baa4
--- a/tests/data/Makefile.in
92baa4
+++ b/tests/data/Makefile.in
92baa4
@@ -342,7 +342,7 @@ test1118 test1119 test1120 test1121 test1122 test1123 test1124 test1125	\
92baa4
 test1126 test1127 test1128 test1129 test1130 test1131 test1132 test1133 \
92baa4
 test1200 test1201 test1202 test1203 test1204 test1205 test1206 test1207 \
92baa4
 test1208 test1209 test1210 test1211 test1213 test1214 test1216 test1218 \
92baa4
-test1220 test1221 test1222 test1223 \
92baa4
+test1220 test1221 test1222 test1223 test1233 test1236 \
92baa4
 test1300 test1301 test1302 test1303 test1304 test1305	\
92baa4
 test1306 test1307 test1308 test1309 test1310 test1311 test1312 test1313 \
92baa4
 test1314 test1315 test1316 test1317 test1318 test1319 test1320 test1321 \
92baa4
diff --git a/tests/data/test1228 b/tests/data/test1228
92baa4
new file mode 100644
92baa4
index 0000000..0a76b87
92baa4
--- /dev/null
92baa4
+++ b/tests/data/test1228
92baa4
@@ -0,0 +1,54 @@
92baa4
+<testcase>
92baa4
+<info>
92baa4
+<keywords>
92baa4
+HTTP
92baa4
+HTTP GET
92baa4
+cookies 
92baa4
+cookie path
92baa4
+</keywords>
92baa4
+</info>
92baa4
+<reply>
92baa4
+<data>
92baa4
+HTTP/1.1 200 OK
92baa4
+Date: Tue, 25 Sep 2001 19:37:44 GMT
92baa4
+Set-Cookie: path1=root; domain=.example.fake; path=/;
92baa4
+Set-Cookie: path2=depth1; domain=.example.fake; path=/hoge;
92baa4
+Content-Length: 34
92baa4
+
92baa4
+This server says cookie path test
92baa4
+</data>
92baa4
+</reply>
92baa4
+
92baa4
+# Client-side
92baa4
+<client>
92baa4
+<server>
92baa4
+http
92baa4
+</server>
92baa4
+ <name>
92baa4
+HTTP cookie path match
92baa4
+ </name>
92baa4
+ <command>
92baa4
+http://example.fake/hoge/1228 http://example.fake/hogege/ -b nonexisting -x %HOSTIP:%HTTPPORT
92baa4
+</command>
92baa4
+</client>
92baa4
+
92baa4
+# Verify data after the test has been "shot"
92baa4
+<verify>
92baa4
+<strip>
92baa4
+^User-Agent:.*
92baa4
+</strip>
92baa4
+<protocol>
92baa4
+GET http://example.fake/hoge/1228 HTTP/1.1
92baa4
+Host: example.fake
92baa4
+Accept: */*
92baa4
+Proxy-Connection: Keep-Alive
92baa4
+
92baa4
+GET http://example.fake/hogege/ HTTP/1.1
92baa4
+Host: example.fake
92baa4
+Accept: */*
92baa4
+Proxy-Connection: Keep-Alive
92baa4
+Cookie: path1=root
92baa4
+
92baa4
+</protocol>
92baa4
+</verify>
92baa4
+</testcase>
92baa4
diff --git a/tests/data/test46 b/tests/data/test46
92baa4
index f73acde..b6f8f83 100644
92baa4
--- a/tests/data/test46
92baa4
+++ b/tests/data/test46
92baa4
@@ -52,8 +52,8 @@ TZ=GMT
92baa4
 www.fake.come	FALSE	/	FALSE	1022144953	cookiecliente	si
92baa4
 www.loser.com	FALSE	/	FALSE	1139150993	UID	99
92baa4
 %HOSTIP	FALSE	/	FALSE	1439150993	mooo	indeed
92baa4
-#HttpOnly_%HOSTIP	FALSE	/w	FALSE	1439150993	mooo2	indeed2
92baa4
-%HOSTIP	FALSE	/wa	FALSE	0	empty	
92baa4
+#HttpOnly_%HOSTIP	FALSE	/want	FALSE	1439150993	mooo2	indeed2
92baa4
+%HOSTIP	FALSE	/want	FALSE	0	empty	
92baa4
 </file>
92baa4
 </client>
92baa4
 
92baa4
@@ -77,8 +77,8 @@ Cookie: empty=; mooo2=indeed2; mooo=indeed
92baa4
 www.fake.come	FALSE	/	FALSE	1022144953	cookiecliente	si
92baa4
 www.loser.com	FALSE	/	FALSE	1139150993	UID	99
92baa4
 %HOSTIP	FALSE	/	FALSE	1439150993	mooo	indeed
92baa4
-#HttpOnly_%HOSTIP	FALSE	/w	FALSE	1439150993	mooo2	indeed2
92baa4
-%HOSTIP	FALSE	/wa	FALSE	0	empty	
92baa4
+#HttpOnly_%HOSTIP	FALSE	/want	FALSE	1439150993	mooo2	indeed2
92baa4
+%HOSTIP	FALSE	/want	FALSE	0	empty	
92baa4
 %HOSTIP	FALSE	/	FALSE	2054030187	ckyPersistent	permanent
92baa4
 %HOSTIP	FALSE	/	FALSE	0	ckySession	temporary
92baa4
 %HOSTIP	FALSE	/	FALSE	0	ASPSESSIONIDQGGQQSJJ	GKNBDIFAAOFDPDAIEAKDIBKE
92baa4
diff --git a/tests/data/test8 b/tests/data/test8
92baa4
index c36408a..4d54541 100644
92baa4
--- a/tests/data/test8
92baa4
+++ b/tests/data/test8
92baa4
@@ -59,7 +59,7 @@ perl -e 'if ("%HOSTIP" !~ /\.0\.0\.1$/) {print "Test only works for HOSTIPs endi
92baa4
 GET /we/want/8 HTTP/1.1
92baa4
 Host: %HOSTIP:%HTTPPORT
92baa4
 Accept: */*
92baa4
-Cookie: cookie=perhaps; cookie=yes; partmatch=present; foobar=name; blexp=yesyes
92baa4
+Cookie: cookie=perhaps; cookie=yes; foobar=name; blexp=yesyes
92baa4
 
92baa4
 </protocol>
92baa4
 </verify>
92baa4
-- 
92baa4
2.1.0
92baa4
92baa4
92baa4
From 847085920706380e75f8cb23f2a161cdcdfcb384 Mon Sep 17 00:00:00 2001
92baa4
From: YAMADA Yasuharu <yasuharu.yamada@access-company.com>
92baa4
Date: Wed, 12 Jun 2013 11:19:56 +0200
92baa4
Subject: [PATCH 3/7] cookies: follow-up fix for path checking
92baa4
92baa4
The initial fix to only compare full path names were done in commit
92baa4
04f52e9b4db0 but found out to be incomplete. This takes should make the
92baa4
change more complete and there's now two additional tests to verify
92baa4
(test 31 and 62).
92baa4
Upstream-commit: f24dc09d209a2f91ca38d854f0c15ad93f3d7e2d
92baa4
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
92baa4
---
92baa4
 lib/cookie.c      | 143 ++++++++++++++++++++++++++++++++++++++++++++++--------
92baa4
 lib/cookie.h      |   3 +-
92baa4
 tests/data/test31 |   3 ++
92baa4
 3 files changed, 128 insertions(+), 21 deletions(-)
92baa4
92baa4
diff --git a/lib/cookie.c b/lib/cookie.c
92baa4
index a4480c0..1d226cf 100644
92baa4
--- a/lib/cookie.c
92baa4
+++ b/lib/cookie.c
92baa4
@@ -106,6 +106,8 @@ static void freecookie(struct Cookie *co)
92baa4
     free(co->domain);
92baa4
   if(co->path)
92baa4
     free(co->path);
92baa4
+  if(co->spath)
92baa4
+    free(co->spath);
92baa4
   if(co->name)
92baa4
     free(co->name);
92baa4
   if(co->value)
92baa4
@@ -143,32 +145,114 @@ static bool tailmatch(const char *cooke_domain, const char *hostname)
92baa4
   return FALSE;
92baa4
 }
92baa4
 
92baa4
-static bool pathmatch(const char* cookie_path, const char* url_path)
92baa4
+/*
92baa4
+ * matching cookie path and url path
92baa4
+ * RFC6265 5.1.4 Paths and Path-Match
92baa4
+ */
92baa4
+static bool pathmatch(const char* cookie_path, const char* request_uri)
92baa4
 {
92baa4
-  size_t cookie_path_len = strlen(cookie_path);
92baa4
-  size_t url_path_len = strlen(url_path);
92baa4
+  size_t cookie_path_len;
92baa4
+  size_t uri_path_len;
92baa4
+  char* uri_path = NULL;
92baa4
+  char* pos;
92baa4
+  bool ret = FALSE;
92baa4
+
92baa4
+  /* cookie_path must not have last '/' separator. ex: /sample */
92baa4
+  cookie_path_len = strlen(cookie_path);
92baa4
+  if(1 == cookie_path_len) {
92baa4
+    /* cookie_path must be '/' */
92baa4
+    return TRUE;
92baa4
+  }
92baa4
 
92baa4
-  if(url_path_len < cookie_path_len)
92baa4
+  uri_path = strdup(request_uri);
92baa4
+  if(!uri_path)
92baa4
     return FALSE;
92baa4
+  pos = strchr(uri_path, '?');
92baa4
+  if(pos)
92baa4
+    *pos = 0x0;
92baa4
+
92baa4
+  /* #-fragments are already cut off! */
92baa4
+  if(0 == strlen(uri_path) || uri_path[0] != '/') {
92baa4
+    free(uri_path);
92baa4
+    uri_path = strdup("/");
92baa4
+    if(!uri_path)
92baa4
+      return FALSE;
92baa4
+  }
92baa4
+
92baa4
+  /* here, RFC6265 5.1.4 says
92baa4
+     4. Output the characters of the uri-path from the first character up
92baa4
+        to, but not including, the right-most %x2F ("/").
92baa4
+     but URL path /hoge?fuga=xxx means /hoge/index.cgi?fuga=xxx in some site
92baa4
+     without redirect.
92baa4
+     Ignore this algorithm because /hoge is uri path for this case
92baa4
+     (uri path is not /).
92baa4
+   */
92baa4
+
92baa4
+  uri_path_len = strlen(uri_path);
92baa4
+
92baa4
+  if(uri_path_len < cookie_path_len) {
92baa4
+    ret = FALSE;
92baa4
+    goto pathmatched;
92baa4
+  }
92baa4
 
92baa4
   /* not using checkprefix() because matching should be case-sensitive */
92baa4
-  if(strncmp(cookie_path, url_path, cookie_path_len))
92baa4
-    return FALSE;
92baa4
+  if(strncmp(cookie_path, uri_path, cookie_path_len)) {
92baa4
+    ret = FALSE;
92baa4
+    goto pathmatched;
92baa4
+  }
92baa4
 
92baa4
-  /* it is true if cookie_path and url_path are the same */
92baa4
-  if(cookie_path_len == url_path_len)
92baa4
-    return TRUE;
92baa4
+  /* The cookie-path and the uri-path are identical. */
92baa4
+  if(cookie_path_len == uri_path_len) {
92baa4
+    ret = TRUE;
92baa4
+    goto pathmatched;
92baa4
+  }
92baa4
 
92baa4
   /* here, cookie_path_len < url_path_len */
92baa4
+  if(uri_path[cookie_path_len] == '/') {
92baa4
+    ret = TRUE;
92baa4
+    goto pathmatched;
92baa4
+  }
92baa4
 
92baa4
-  /* it is false if cookie path is /example and url path is /examples */
92baa4
-  if(cookie_path[cookie_path_len - 1] != '/') {
92baa4
-    if(url_path[cookie_path_len] != '/') {
92baa4
-      return FALSE;
92baa4
-    }
92baa4
+  ret = FALSE;
92baa4
+
92baa4
+pathmatched:
92baa4
+  free(uri_path);
92baa4
+  return ret;
92baa4
+}
92baa4
+
92baa4
+/*
92baa4
+ * cookie path sanitize
92baa4
+ */
92baa4
+static char *sanitize_cookie_path(const char *cookie_path)
92baa4
+{
92baa4
+  size_t len;
92baa4
+  char *new_path = strdup(cookie_path);
92baa4
+  if(!new_path)
92baa4
+    return NULL;
92baa4
+
92baa4
+  /* some stupid site sends path attribute with '"'. */
92baa4
+  if(new_path[0] == '\"') {
92baa4
+    memmove((void *)new_path, (const void *)(new_path + 1), strlen(new_path));
92baa4
+  }
92baa4
+  if(new_path[strlen(new_path) - 1] == '\"') {
92baa4
+    new_path[strlen(new_path) - 1] = 0x0;
92baa4
+  }
92baa4
+
92baa4
+  /* RFC6265 5.2.4 The Path Attribute */
92baa4
+  if(new_path[0] != '/') {
92baa4
+    /* Let cookie-path be the default-path. */
92baa4
+    free(new_path);
92baa4
+    new_path = strdup("/");
92baa4
+    return new_path;
92baa4
+  }
92baa4
+
92baa4
+  /* convert /hoge/ to /hoge */
92baa4
+  len = strlen(new_path);
92baa4
+  if(1 < len && new_path[len - 1] == '/') {
92baa4
+    new_path[len - 1] = 0x0;
92baa4
   }
92baa4
-  /* matching! */
92baa4
-  return TRUE;
92baa4
+
92baa4
+  return new_path;
92baa4
 }
92baa4
 
92baa4
 /*
92baa4
@@ -316,6 +400,11 @@ Curl_cookie_add(struct SessionHandle *data,
92baa4
             badcookie = TRUE; /* out of memory bad */
92baa4
             break;
92baa4
           }
92baa4
+          co->spath = sanitize_cookie_path(co->path);
92baa4
+          if(!co->spath) {
92baa4
+            badcookie = TRUE; /* out of memory bad */
92baa4
+            break;
92baa4
+          }
92baa4
         }
92baa4
         else if(Curl_raw_equal("domain", name)) {
92baa4
           /* note that this name may or may not have a preceding dot, but
92baa4
@@ -489,6 +578,9 @@ Curl_cookie_add(struct SessionHandle *data,
92baa4
         if(co->path) {
92baa4
           memcpy(co->path, path, pathlen);
92baa4
           co->path[pathlen]=0; /* zero terminate */
92baa4
+          co->spath = sanitize_cookie_path(co->path);
92baa4
+          if(!co->spath)
92baa4
+            badcookie = TRUE; /* out of memory bad */
92baa4
         }
92baa4
         else
92baa4
           badcookie = TRUE;
92baa4
@@ -580,12 +672,21 @@ Curl_cookie_add(struct SessionHandle *data,
92baa4
           co->path = strdup(ptr);
92baa4
           if(!co->path)
92baa4
             badcookie = TRUE;
92baa4
+          else {
92baa4
+            co->spath = sanitize_cookie_path(co->path);
92baa4
+            if(!co->spath) {
92baa4
+              badcookie = TRUE; /* out of memory bad */
92baa4
+            }
92baa4
+          }
92baa4
           break;
92baa4
         }
92baa4
         /* this doesn't look like a path, make one up! */
92baa4
         co->path = strdup("/");
92baa4
         if(!co->path)
92baa4
           badcookie = TRUE;
92baa4
+        co->spath = strdup("/");
92baa4
+        if(!co->spath)
92baa4
+          badcookie = TRUE;
92baa4
         fields++; /* add a field and fall down to secure */
92baa4
         /* FALLTHROUGH */
92baa4
       case 3:
92baa4
@@ -656,14 +757,14 @@ Curl_cookie_add(struct SessionHandle *data,
92baa4
       if(replace_old) {
92baa4
         /* the domains were identical */
92baa4
 
92baa4
-        if(clist->path && co->path) {
92baa4
-          if(Curl_raw_equal(clist->path, co->path)) {
92baa4
+        if(clist->spath && co->spath) {
92baa4
+          if(Curl_raw_equal(clist->spath, co->spath)) {
92baa4
             replace_old = TRUE;
92baa4
           }
92baa4
           else
92baa4
             replace_old = FALSE;
92baa4
         }
92baa4
-        else if(!clist->path && !co->path)
92baa4
+        else if(!clist->spath && !co->spath)
92baa4
           replace_old = TRUE;
92baa4
         else
92baa4
           replace_old = FALSE;
92baa4
@@ -692,6 +793,8 @@ Curl_cookie_add(struct SessionHandle *data,
92baa4
           free(clist->domain);
92baa4
         if(clist->path)
92baa4
           free(clist->path);
92baa4
+        if(clist->spath)
92baa4
+          free(clist->spath);
92baa4
         if(clist->expirestr)
92baa4
           free(clist->expirestr);
92baa4
 
92baa4
@@ -869,7 +972,7 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
92baa4
 
92baa4
         /* now check the left part of the path with the cookies path
92baa4
            requirement */
92baa4
-        if(!co->path || pathmatch(co->path, path) ) {
92baa4
+        if(!co->spath || pathmatch(co->spath, path) ) {
92baa4
 
92baa4
           /* and now, we know this is a match and we should create an
92baa4
              entry for the return-linked-list */
92baa4
diff --git a/lib/cookie.h b/lib/cookie.h
92baa4
index d3b63f7..bd89082 100644
92baa4
--- a/lib/cookie.h
92baa4
+++ b/lib/cookie.h
92baa4
@@ -29,7 +29,8 @@ struct Cookie {
92baa4
   struct Cookie *next; /* next in the chain */
92baa4
   char *name;        /* <this> = value */
92baa4
   char *value;       /* name = <this> */
92baa4
-  char *path;         /* path = <this> */
92baa4
+  char *path;         /* path = <this> which is in Set-Cookie: */
92baa4
+  char *spath;        /* sanitized cookie path */
92baa4
   char *domain;      /* domain = <this> */
92baa4
   curl_off_t expires;  /* expires = <this> */
92baa4
   char *expirestr;   /* the plain text version */
92baa4
diff --git a/tests/data/test31 b/tests/data/test31
92baa4
index b1171d8..38af83b 100644
92baa4
--- a/tests/data/test31
92baa4
+++ b/tests/data/test31
92baa4
@@ -18,6 +18,8 @@ Content-Type: text/html
92baa4
 Funny-head: yesyes
92baa4
 Set-Cookie: foobar=name; domain=anything.com; path=/ ; secure
92baa4
 Set-Cookie:ismatch=this  ; domain=127.0.0.1; path=/silly/
92baa4
+Set-Cookie: overwrite=this  ; domain=127.0.0.1; path=/overwrite/
92baa4
+Set-Cookie: overwrite=this2  ; domain=127.0.0.1; path=/overwrite
92baa4
 Set-Cookie: sec1value=secure1  ; domain=127.0.0.1; path=/secure1/ ; secure
92baa4
 Set-Cookie: sec2value=secure2  ; domain=127.0.0.1; path=/secure2/ ; secure=
92baa4
 Set-Cookie: sec3value=secure3  ; domain=127.0.0.1; path=/secure3/ ; secure=
92baa4
@@ -94,6 +96,7 @@ Accept: */*
92baa4
 # This file was generated by libcurl! Edit at your own risk.
92baa4
 
92baa4
 .127.0.0.1	TRUE	/silly/	FALSE	0	ismatch	this
92baa4
+.127.0.0.1	TRUE	/overwrite	FALSE	0	overwrite	this2
92baa4
 .127.0.0.1	TRUE	/secure1/	TRUE	0	sec1value	secure1
92baa4
 .127.0.0.1	TRUE	/secure2/	TRUE	0	sec2value	secure2
92baa4
 .127.0.0.1	TRUE	/secure3/	TRUE	0	sec3value	secure3
92baa4
-- 
92baa4
2.1.0
92baa4
92baa4
92baa4
From ffe02d8f3950b5fcf0470890a112125327606f35 Mon Sep 17 00:00:00 2001
92baa4
From: YAMADA Yasuharu <yasuharu.yamada@access-company.com>
92baa4
Date: Tue, 17 Sep 2013 15:51:22 +0900
92baa4
Subject: [PATCH 4/7] cookies: add expiration
92baa4
92baa4
Implement: Expired Cookies These following situation, curl removes
92baa4
cookie(s) from struct CookieInfo if the cookie expired.
92baa4
 - Curl_cookie_add()
92baa4
 - Curl_cookie_getlist()
92baa4
 - cookie_output()
92baa4
92baa4
Upstream-commit: 4cfbb201c4f823ba31ba4b895044088fba6ae535
92baa4
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
92baa4
---
92baa4
 lib/cookie.c           | 37 ++++++++++++++++++++++++++
92baa4
 tests/data/Makefile.am |  2 +-
92baa4
 tests/data/Makefile.in |  2 +-
92baa4
 tests/data/test1415    | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++
92baa4
 4 files changed, 111 insertions(+), 2 deletions(-)
92baa4
 create mode 100644 tests/data/test1415
92baa4
92baa4
diff --git a/lib/cookie.c b/lib/cookie.c
92baa4
index 1d226cf..0ca0829 100644
92baa4
--- a/lib/cookie.c
92baa4
+++ b/lib/cookie.c
92baa4
@@ -289,6 +289,34 @@ static void strstore(char **str, const char *newstr)
92baa4
   *str = strdup(newstr);
92baa4
 }
92baa4
 
92baa4
+/*
92baa4
+ * remove_expired() removes expired cookies.
92baa4
+ */
92baa4
+static void remove_expired(struct CookieInfo *cookies)
92baa4
+{
92baa4
+  struct Cookie *co, *nx, *pv;
92baa4
+  curl_off_t now = (curl_off_t)time(NULL);
92baa4
+
92baa4
+  co = cookies->cookies;
92baa4
+  pv = NULL;
92baa4
+  while(co) {
92baa4
+    nx = co->next;
92baa4
+    if((co->expirestr || co->maxage) && co->expires < now) {
92baa4
+      if(co == cookies->cookies) {
92baa4
+        cookies->cookies = co->next;
92baa4
+      }
92baa4
+      else {
92baa4
+        pv->next = co->next;
92baa4
+      }
92baa4
+      cookies->numcookies--;
92baa4
+      freecookie(co);
92baa4
+    }
92baa4
+    else {
92baa4
+      pv = co;
92baa4
+    }
92baa4
+    co = nx;
92baa4
+  }
92baa4
+}
92baa4
 
92baa4
 /****************************************************************************
92baa4
  *
92baa4
@@ -740,6 +768,9 @@ Curl_cookie_add(struct SessionHandle *data,
92baa4
      superceeds an already existing cookie, which it may if the previous have
92baa4
      the same domain and path as this */
92baa4
 
92baa4
+  /* at first, remove expired cookies */
92baa4
+  remove_expired(c);
92baa4
+
92baa4
   clist = c->cookies;
92baa4
   replace_old = FALSE;
92baa4
   while(clist) {
92baa4
@@ -954,6 +985,9 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
92baa4
   if(!c || !c->cookies)
92baa4
     return NULL; /* no cookie struct or no cookies in the struct */
92baa4
 
92baa4
+  /* at first, remove expired cookies */
92baa4
+  remove_expired(c);
92baa4
+
92baa4
   co = c->cookies;
92baa4
 
92baa4
   while(co) {
92baa4
@@ -1196,6 +1230,9 @@ static int cookie_output(struct CookieInfo *c, const char *dumphere)
92baa4
        destination file */
92baa4
     return 0;
92baa4
 
92baa4
+  /* at first, remove expired cookies */
92baa4
+  remove_expired(c);
92baa4
+
92baa4
   if(strequal("-", dumphere)) {
92baa4
     /* use stdout */
92baa4
     out = stdout;
92baa4
diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am
92baa4
index 64662c6..f34268c 100644
92baa4
--- a/tests/data/Makefile.am
92baa4
+++ b/tests/data/Makefile.am
92baa4
@@ -92,7 +92,7 @@ test1371 test1372 test1373 test1374 test1375 test1376 test1377 test1378 \
92baa4
 test1379 test1380 test1381 test1382 test1383 test1384 test1385 test1386 \
92baa4
 test1387 test1388 test1389 test1390 test1391 test1392 test1393 \
92baa4
 test1400 test1401 test1402 test1403 test1404 test1405 test1406 test1407 \
92baa4
-test1408 test1409 test1410 test1411 test1412 test1413 \
92baa4
+test1408 test1409 test1410 test1411 test1412 test1413 test1415 \
92baa4
 test1500 test1501 test1502 test1503 test1504 test1505 test1506 test1507 \
92baa4
 test1508 \
92baa4
 test2000 test2001 test2002 test2003 test2004 test2005 test2006 test2007 \
92baa4
diff --git a/tests/data/Makefile.in b/tests/data/Makefile.in
92baa4
index 791fa1e..cd2c322 100644
92baa4
--- a/tests/data/Makefile.in
92baa4
+++ b/tests/data/Makefile.in
92baa4
@@ -356,7 +356,7 @@ test1371 test1372 test1373 test1374 test1375 test1376 test1377 test1378 \
92baa4
 test1379 test1380 test1381 test1382 test1383 test1384 test1385 test1386 \
92baa4
 test1387 test1388 test1389 test1390 test1391 test1392 test1393 \
92baa4
 test1400 test1401 test1402 test1403 test1404 test1405 test1406 test1407 \
92baa4
-test1408 test1409 test1410 test1411 test1412 test1413 \
92baa4
+test1408 test1409 test1410 test1411 test1412 test1413 test1415 \
92baa4
 test1500 test1501 test1502 test1503 test1504 test1505 test1506 test1507 \
92baa4
 test1508 \
92baa4
 test2000 test2001 test2002 test2003 test2004 test2005 test2006 test2007 \
92baa4
diff --git a/tests/data/test1415 b/tests/data/test1415
92baa4
new file mode 100644
92baa4
index 0000000..cc6bd70
92baa4
--- /dev/null
92baa4
+++ b/tests/data/test1415
92baa4
@@ -0,0 +1,72 @@
92baa4
+<testcase>
92baa4
+<info>
92baa4
+<keywords>
92baa4
+HTTP
92baa4
+HTTP GET
92baa4
+cookies
92baa4
+cookiejar
92baa4
+delete expired cookie
92baa4
+</keywords>
92baa4
+</info>
92baa4
+# Server-side
92baa4
+<reply>
92baa4
+<data>
92baa4
+HTTP/1.1 200 OK
92baa4
+Date: Thu, 09 Nov 2010 14:49:00 GMT
92baa4
+Server: test-server/fake
92baa4
+Content-Length: 4
92baa4
+Content-Type: text/html
92baa4
+Funny-head: yesyes
92baa4
+Set-Cookie: test1value=test1; domain=example.com; path=/;
92baa4
+Set-Cookie: test2value=test2; expires=Friday, 01-Jan-2038 00:00:00 GMT; domain=example.com; path=/;
92baa4
+Set-Cookie: test3value=test3; expires=Monday, 13-Jun-1988 03:04:55 GMT; domain=example.com; path=/;
92baa4
+Set-Cookie: test4value=test4; expires=Friday, 01-Jan-2038 00:00:00 GMT; domain=example.com; path=/;
92baa4
+Set-Cookie: test5value=test5; expires=Monday, 13-Jun-1988 03:04:55 GMT; domain=example.com; path=/;
92baa4
+Set-Cookie: test6value=test6; expires=Monday, 13-Jun-1988 03:04:55 GMT; domain=example.com; path=/;
92baa4
+Set-Cookie: test7value=test7; expires=Friday, 01-Jan-2038 00:00:00 GMT; domain=example.com; path=/;
92baa4
+Set-Cookie: test8value=test8; expires=Monday, 13-Jun-1988 03:04:55 GMT; domain=example.com; path=/;
92baa4
+
92baa4
+boo
92baa4
+</data>
92baa4
+</reply>
92baa4
+
92baa4
+# Client-side
92baa4
+<client>
92baa4
+<server>
92baa4
+http
92baa4
+</server>
92baa4
+<name>
92baa4
+Delete expired cookies
92baa4
+</name>
92baa4
+<setenv>
92baa4
+TZ=GMT
92baa4
+</setenv>
92baa4
+<command>
92baa4
+http://example.com/we/want/1415 -b none -c log/jar1415.txt -x %HOSTIP:%HTTPPORT
92baa4
+</command>
92baa4
+
92baa4
+# Verify data after the test has been "shot"
92baa4
+<verify>
92baa4
+<strip>
92baa4
+^User-Agent:.*
92baa4
+</strip>
92baa4
+<protocol>
92baa4
+GET http://example.com/we/want/1415 HTTP/1.1
92baa4
+Host: example.com
92baa4
+Accept: */*
92baa4
+Proxy-Connection: Keep-Alive
92baa4
+
92baa4
+</protocol>
92baa4
+
92baa4
+<file name="log/jar1415.txt" mode="text">
92baa4
+# Netscape HTTP Cookie File
92baa4
+# http://curl.haxx.se/docs/http-cookies.html
92baa4
+# This file was generated by libcurl! Edit at your own risk.
92baa4
+
92baa4
+.example.com	TRUE	/	FALSE	0	test1value	test1
92baa4
+.example.com	TRUE	/	FALSE	2145916800	test2value	test2
92baa4
+.example.com	TRUE	/	FALSE	2145916800	test4value	test4
92baa4
+.example.com	TRUE	/	FALSE	2145916800	test7value	test7
92baa4
+</file>
92baa4
+</verify>
92baa4
+</testcase>
92baa4
-- 
92baa4
2.1.0
92baa4
92baa4
92baa4
From f866a6369316df97b777289a34db03444f7dedbe Mon Sep 17 00:00:00 2001
92baa4
From: Daniel Stenberg <daniel@haxx.se>
92baa4
Date: Sat, 21 Sep 2013 13:43:39 -0500
92baa4
Subject: [PATCH 5/7] test1415: adjusted to work for 32bit time_t
92baa4
92baa4
The libcurl date parser returns INT_MAX for all dates > 2037 so this
92baa4
test is now made to use 2037 instead of 2038 to work the same for both
92baa4
32bit and 64bit time_t systems.
92baa4
92baa4
Upstream-commit: 34df869f99477edda61d639151b1edf75998abd9
92baa4
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
92baa4
---
92baa4
 tests/data/test1415 | 12 ++++++------
92baa4
 1 file changed, 6 insertions(+), 6 deletions(-)
92baa4
92baa4
diff --git a/tests/data/test1415 b/tests/data/test1415
92baa4
index cc6bd70..51eed3e 100644
92baa4
--- a/tests/data/test1415
92baa4
+++ b/tests/data/test1415
92baa4
@@ -18,12 +18,12 @@ Content-Length: 4
92baa4
 Content-Type: text/html
92baa4
 Funny-head: yesyes
92baa4
 Set-Cookie: test1value=test1; domain=example.com; path=/;
92baa4
-Set-Cookie: test2value=test2; expires=Friday, 01-Jan-2038 00:00:00 GMT; domain=example.com; path=/;
92baa4
+Set-Cookie: test2value=test2; expires=Friday, 01-Jan-2037 00:00:00 GMT; domain=example.com; path=/;
92baa4
 Set-Cookie: test3value=test3; expires=Monday, 13-Jun-1988 03:04:55 GMT; domain=example.com; path=/;
92baa4
-Set-Cookie: test4value=test4; expires=Friday, 01-Jan-2038 00:00:00 GMT; domain=example.com; path=/;
92baa4
+Set-Cookie: test4value=test4; expires=Friday, 01-Jan-2037 00:00:00 GMT; domain=example.com; path=/;
92baa4
 Set-Cookie: test5value=test5; expires=Monday, 13-Jun-1988 03:04:55 GMT; domain=example.com; path=/;
92baa4
 Set-Cookie: test6value=test6; expires=Monday, 13-Jun-1988 03:04:55 GMT; domain=example.com; path=/;
92baa4
-Set-Cookie: test7value=test7; expires=Friday, 01-Jan-2038 00:00:00 GMT; domain=example.com; path=/;
92baa4
+Set-Cookie: test7value=test7; expires=Friday, 01-Jan-2037 00:00:00 GMT; domain=example.com; path=/;
92baa4
 Set-Cookie: test8value=test8; expires=Monday, 13-Jun-1988 03:04:55 GMT; domain=example.com; path=/;
92baa4
 
92baa4
 boo
92baa4
@@ -64,9 +64,9 @@ Proxy-Connection: Keep-Alive
92baa4
 # This file was generated by libcurl! Edit at your own risk.
92baa4
 
92baa4
 .example.com	TRUE	/	FALSE	0	test1value	test1
92baa4
-.example.com	TRUE	/	FALSE	2145916800	test2value	test2
92baa4
-.example.com	TRUE	/	FALSE	2145916800	test4value	test4
92baa4
-.example.com	TRUE	/	FALSE	2145916800	test7value	test7
92baa4
+.example.com	TRUE	/	FALSE	2114380800	test2value	test2
92baa4
+.example.com	TRUE	/	FALSE	2114380800	test4value	test4
92baa4
+.example.com	TRUE	/	FALSE	2114380800	test7value	test7
92baa4
 </file>
92baa4
 </verify>
92baa4
 </testcase>
92baa4
-- 
92baa4
2.1.0
92baa4
92baa4
92baa4
From 8471ac93e881f7f17fe598086b6b548289716279 Mon Sep 17 00:00:00 2001
92baa4
From: Daniel Stenberg <daniel@haxx.se>
92baa4
Date: Thu, 16 Jan 2014 08:51:30 +0100
92baa4
Subject: [PATCH 6/7] cookie: max-age fixes
92baa4
92baa4
1 - allow >31 bit max-age values
92baa4
92baa4
2 - don't overflow on extremely large max-age values when we add the
92baa4
value to the current time
92baa4
92baa4
3 - make sure max-age takes precedence over expires as dictated by
92baa4
RFC6265
92baa4
92baa4
Bug: http://curl.haxx.se/mail/lib-2014-01/0130.html
92baa4
Reported-by: Chen Prog
92baa4
Upstream-commit: ecaf2f02f1df70f0bbcbbbf48914bfc83c8f2a56
92baa4
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
92baa4
---
92baa4
 lib/cookie.c | 38 ++++++++++++++++++++++++--------------
92baa4
 1 file changed, 24 insertions(+), 14 deletions(-)
92baa4
92baa4
diff --git a/lib/cookie.c b/lib/cookie.c
92baa4
index 0ca0829..d4fe9a3 100644
92baa4
--- a/lib/cookie.c
92baa4
+++ b/lib/cookie.c
92baa4
@@ -523,9 +523,6 @@ Curl_cookie_add(struct SessionHandle *data,
92baa4
             badcookie = TRUE;
92baa4
             break;
92baa4
           }
92baa4
-          co->expires =
92baa4
-            strtol((*co->maxage=='\"')?&co->maxage[1]:&co->maxage[0],NULL,10)
92baa4
-            + (long)now;
92baa4
         }
92baa4
         else if(Curl_raw_equal("expires", name)) {
92baa4
           strstore(&co->expirestr, whatptr);
92baa4
@@ -533,17 +530,6 @@ Curl_cookie_add(struct SessionHandle *data,
92baa4
             badcookie = TRUE;
92baa4
             break;
92baa4
           }
92baa4
-          /* Note that if the date couldn't get parsed for whatever reason,
92baa4
-             the cookie will be treated as a session cookie */
92baa4
-          co->expires = curl_getdate(what, &now;;
92baa4
-
92baa4
-          /* Session cookies have expires set to 0 so if we get that back
92baa4
-             from the date parser let's add a second to make it a
92baa4
-             non-session cookie */
92baa4
-          if(co->expires == 0)
92baa4
-            co->expires = 1;
92baa4
-          else if(co->expires < 0)
92baa4
-            co->expires = 0;
92baa4
         }
92baa4
         else if(!co->name) {
92baa4
           co->name = strdup(name);
92baa4
@@ -578,6 +564,30 @@ Curl_cookie_add(struct SessionHandle *data,
92baa4
         semiptr=strchr(ptr, '\0');
92baa4
     } while(semiptr);
92baa4
 
92baa4
+    if(co->maxage) {
92baa4
+      co->expires =
92baa4
+        curlx_strtoofft((*co->maxage=='\"')?
92baa4
+                        &co->maxage[1]:&co->maxage[0], NULL, 10);
92baa4
+      if(CURL_OFF_T_MAX - now < co->expires)
92baa4
+        /* avoid overflow */
92baa4
+        co->expires = CURL_OFF_T_MAX;
92baa4
+      else
92baa4
+        co->expires += now;
92baa4
+    }
92baa4
+    else if(co->expirestr) {
92baa4
+      /* Note that if the date couldn't get parsed for whatever reason,
92baa4
+         the cookie will be treated as a session cookie */
92baa4
+      co->expires = curl_getdate(co->expirestr, NULL);
92baa4
+
92baa4
+      /* Session cookies have expires set to 0 so if we get that back
92baa4
+         from the date parser let's add a second to make it a
92baa4
+         non-session cookie */
92baa4
+      if(co->expires == 0)
92baa4
+        co->expires = 1;
92baa4
+      else if(co->expires < 0)
92baa4
+        co->expires = 0;
92baa4
+    }
92baa4
+
92baa4
     if(!badcookie && !co->domain) {
92baa4
       if(domain) {
92baa4
         /* no domain was given in the header line, set the default */
92baa4
-- 
92baa4
2.1.0
92baa4
92baa4
92baa4
From ee52a81c23b918895b363b904ebb5fc9908b55cc Mon Sep 17 00:00:00 2001
92baa4
From: Tim Ruehsen <tim.ruehsen@gmx.de>
92baa4
Date: Tue, 19 Aug 2014 21:01:28 +0200
92baa4
Subject: [PATCH 7/7] cookies: only use full host matches for hosts used as IP
92baa4
 address
92baa4
92baa4
By not detecting and rejecting domain names for partial literal IP
92baa4
addresses properly when parsing received HTTP cookies, libcurl can be
92baa4
fooled to both send cookies to wrong sites and to allow arbitrary sites
92baa4
to set cookies for others.
92baa4
92baa4
CVE-2014-3613
92baa4
92baa4
Bug: http://curl.haxx.se/docs/adv_20140910A.html
92baa4
Upstream-commit: 8a75dbeb2305297640453029b7905ef51b87e8dd
92baa4
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
92baa4
---
92baa4
 lib/cookie.c        | 50 ++++++++++++++++++++++++++++++++++++++----------
92baa4
 tests/data/test1105 |  3 +--
92baa4
 tests/data/test31   | 55 +++++++++++++++++++++++++++--------------------------
92baa4
 tests/data/test8    |  3 ++-
92baa4
 4 files changed, 71 insertions(+), 40 deletions(-)
92baa4
92baa4
diff --git a/lib/cookie.c b/lib/cookie.c
92baa4
index d4fe9a3..956efd4 100644
92baa4
--- a/lib/cookie.c
92baa4
+++ b/lib/cookie.c
92baa4
@@ -94,6 +94,7 @@ Example set of cookies:
92baa4
 #include "strtoofft.h"
92baa4
 #include "rawstr.h"
92baa4
 #include "curl_memrchr.h"
92baa4
+#include "inet_pton.h"
92baa4
 
92baa4
 /* The last #include file should be: */
92baa4
 #include "memdebug.h"
92baa4
@@ -318,6 +319,28 @@ static void remove_expired(struct CookieInfo *cookies)
92baa4
   }
92baa4
 }
92baa4
 
92baa4
+/*
92baa4
+ * Return true if the given string is an IP(v4|v6) address.
92baa4
+ */
92baa4
+static bool isip(const char *domain)
92baa4
+{
92baa4
+  struct in_addr addr;
92baa4
+#ifdef ENABLE_IPV6
92baa4
+  struct in6_addr addr6;
92baa4
+#endif
92baa4
+
92baa4
+  if(Curl_inet_pton(AF_INET, domain, &addr)
92baa4
+#ifdef ENABLE_IPV6
92baa4
+     || Curl_inet_pton(AF_INET6, domain, &addr6)
92baa4
+#endif
92baa4
+    ) {
92baa4
+    /* domain name given as IP address */
92baa4
+    return TRUE;
92baa4
+  }
92baa4
+
92baa4
+  return FALSE;
92baa4
+}
92baa4
+
92baa4
 /****************************************************************************
92baa4
  *
92baa4
  * Curl_cookie_add()
92baa4
@@ -472,24 +495,27 @@ Curl_cookie_add(struct SessionHandle *data,
92baa4
                   whatptr);
92baa4
           }
92baa4
           else {
92baa4
+            bool is_ip;
92baa4
+
92baa4
             /* Now, we make sure that our host is within the given domain,
92baa4
                or the given domain is not valid and thus cannot be set. */
92baa4
 
92baa4
             if('.' == whatptr[0])
92baa4
               whatptr++; /* ignore preceding dot */
92baa4
 
92baa4
-            if(!domain || tailmatch(whatptr, domain)) {
92baa4
-              const char *tailptr=whatptr;
92baa4
-              if(tailptr[0] == '.')
92baa4
-                tailptr++;
92baa4
-              strstore(&co->domain, tailptr); /* don't prefix w/dots
92baa4
-                                                 internally */
92baa4
+            is_ip = isip(domain ? domain : whatptr);
a2d4e1
+
92baa4
+            if(!domain
92baa4
+               || (is_ip && !strcmp(whatptr, domain))
92baa4
+               || (!is_ip && tailmatch(whatptr, domain))) {
92baa4
+              strstore(&co->domain, whatptr);
92baa4
               if(!co->domain) {
92baa4
                 badcookie = TRUE;
92baa4
                 break;
92baa4
               }
92baa4
-              co->tailmatch=TRUE; /* we always do that if the domain name was
92baa4
-                                     given */
92baa4
+              if(!is_ip)
92baa4
+                co->tailmatch=TRUE; /* we always do that if the domain name was
92baa4
+                                       given */
92baa4
             }
92baa4
             else {
92baa4
               /* we did not get a tailmatch and then the attempted set domain
92baa4
@@ -991,6 +1017,7 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
92baa4
   time_t now = time(NULL);
92baa4
   struct Cookie *mainco=NULL;
92baa4
   size_t matches = 0;
92baa4
+  bool is_ip;
92baa4
 
92baa4
   if(!c || !c->cookies)
92baa4
     return NULL; /* no cookie struct or no cookies in the struct */
92baa4
@@ -998,6 +1025,9 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
92baa4
   /* at first, remove expired cookies */
92baa4
   remove_expired(c);
92baa4
 
92baa4
+  /* check if host is an IP(v4|v6) address */
92baa4
+  is_ip = isip(host);
92baa4
+
92baa4
   co = c->cookies;
92baa4
 
92baa4
   while(co) {
92baa4
@@ -1009,8 +1039,8 @@ struct Cookie *Curl_cookie_getlist(struct CookieInfo *c,
92baa4
 
92baa4
       /* now check if the domain is correct */
92baa4
       if(!co->domain ||
92baa4
-         (co->tailmatch && tailmatch(co->domain, host)) ||
92baa4
-         (!co->tailmatch && Curl_raw_equal(host, co->domain)) ) {
92baa4
+         (co->tailmatch && !is_ip && tailmatch(co->domain, host)) ||
92baa4
+         ((!co->tailmatch || is_ip) && Curl_raw_equal(host, co->domain)) ) {
92baa4
         /* the right part of the host matches the domain stuff in the
92baa4
            cookie data */
92baa4
 
92baa4
diff --git a/tests/data/test1105 b/tests/data/test1105
92baa4
index 922346f..ea7b198 100644
92baa4
--- a/tests/data/test1105
92baa4
+++ b/tests/data/test1105
92baa4
@@ -59,8 +59,7 @@ userid=myname&password=mypassword
92baa4
 # This file was generated by libcurl! Edit at your own risk.
92baa4
 
92baa4
 127.0.0.1	FALSE	/we/want/	FALSE	0	foobar	name
92baa4
-.127.0.0.1	TRUE	"/silly/"	FALSE	0	mismatch	this
92baa4
-.0.0.1	TRUE	/	FALSE	0	partmatch	present
92baa4
+127.0.0.1	FALSE	"/silly/"	FALSE	0	mismatch	this
92baa4
 </file>
92baa4
 </verify>
92baa4
 </testcase>
92baa4
diff --git a/tests/data/test31 b/tests/data/test31
92baa4
index 38af83b..dfcac04 100644
92baa4
--- a/tests/data/test31
92baa4
+++ b/tests/data/test31
92baa4
@@ -51,7 +51,8 @@ Set-Cookie: novalue; domain=reallysilly
92baa4
 Set-Cookie: test=yes; domain=foo.com; expires=Sat Feb 2 11:56:27 GMT 2030
92baa4
 Set-Cookie: test2=yes; domain=se; expires=Sat Feb 2 11:56:27 GMT 2030
92baa4
 Set-Cookie: magic=yessir; path=/silly/; HttpOnly
92baa4
-Set-Cookie: blexp=yesyes; domain=.0.0.1; domain=.0.0.1; expiry=totally bad;
92baa4
+Set-Cookie: blexp=yesyes; domain=127.0.0.1; domain=127.0.0.1; expiry=totally bad;
92baa4
+Set-Cookie: partialip=nono; domain=.0.0.1;
92baa4
 
92baa4
 boo
92baa4
 </data>
92baa4
@@ -95,34 +96,34 @@ Accept: */*
92baa4
 # http://curl.haxx.se/docs/http-cookies.html
92baa4
 # This file was generated by libcurl! Edit at your own risk.
92baa4
 
92baa4
-.127.0.0.1	TRUE	/silly/	FALSE	0	ismatch	this
92baa4
-.127.0.0.1	TRUE	/overwrite	FALSE	0	overwrite	this2
92baa4
-.127.0.0.1	TRUE	/secure1/	TRUE	0	sec1value	secure1
92baa4
-.127.0.0.1	TRUE	/secure2/	TRUE	0	sec2value	secure2
92baa4
-.127.0.0.1	TRUE	/secure3/	TRUE	0	sec3value	secure3
92baa4
-.127.0.0.1	TRUE	/secure4/	TRUE	0	sec4value	secure4
92baa4
-.127.0.0.1	TRUE	/secure5/	TRUE	0	sec5value	secure5
92baa4
-.127.0.0.1	TRUE	/secure6/	TRUE	0	sec6value	secure6
92baa4
-.127.0.0.1	TRUE	/secure7/	TRUE	0	sec7value	secure7
92baa4
-.127.0.0.1	TRUE	/secure8/	TRUE	0	sec8value	secure8
92baa4
-.127.0.0.1	TRUE	/secure9/	TRUE	0	secure	very1
92baa4
-#HttpOnly_.127.0.0.1	TRUE	/p1/	FALSE	0	httpo1	value1
92baa4
-#HttpOnly_.127.0.0.1	TRUE	/p2/	FALSE	0	httpo2	value2
92baa4
-#HttpOnly_.127.0.0.1	TRUE	/p3/	FALSE	0	httpo3	value3
92baa4
-#HttpOnly_.127.0.0.1	TRUE	/p4/	FALSE	0	httpo4	value4
92baa4
-#HttpOnly_.127.0.0.1	TRUE	/p4/	FALSE	0	httponly	myvalue1
92baa4
-#HttpOnly_.127.0.0.1	TRUE	/p4/	TRUE	0	httpandsec	myvalue2
92baa4
-#HttpOnly_.127.0.0.1	TRUE	/p4/	TRUE	0	httpandsec2	myvalue3
92baa4
-#HttpOnly_.127.0.0.1	TRUE	/p4/	TRUE	0	httpandsec3	myvalue4
92baa4
-#HttpOnly_.127.0.0.1	TRUE	/p4/	TRUE	0	httpandsec4	myvalue5
92baa4
-#HttpOnly_.127.0.0.1	TRUE	/p4/	TRUE	0	httpandsec5	myvalue6
92baa4
-#HttpOnly_.127.0.0.1	TRUE	/p4/	TRUE	0	httpandsec6	myvalue7
92baa4
-#HttpOnly_.127.0.0.1	TRUE	/p4/	TRUE	0	httpandsec7	myvalue8
92baa4
-#HttpOnly_.127.0.0.1	TRUE	/p4/	TRUE	0	httpandsec8	myvalue9
92baa4
-.127.0.0.1	TRUE	/	FALSE	0	partmatch	present
92baa4
+127.0.0.1	FALSE	/silly/	FALSE	0	ismatch	this
92baa4
+127.0.0.1	FALSE	/overwrite	FALSE	0	overwrite	this2
92baa4
+127.0.0.1	FALSE	/secure1/	TRUE	0	sec1value	secure1
92baa4
+127.0.0.1	FALSE	/secure2/	TRUE	0	sec2value	secure2
92baa4
+127.0.0.1	FALSE	/secure3/	TRUE	0	sec3value	secure3
92baa4
+127.0.0.1	FALSE	/secure4/	TRUE	0	sec4value	secure4
92baa4
+127.0.0.1	FALSE	/secure5/	TRUE	0	sec5value	secure5
92baa4
+127.0.0.1	FALSE	/secure6/	TRUE	0	sec6value	secure6
92baa4
+127.0.0.1	FALSE	/secure7/	TRUE	0	sec7value	secure7
92baa4
+127.0.0.1	FALSE	/secure8/	TRUE	0	sec8value	secure8
92baa4
+127.0.0.1	FALSE	/secure9/	TRUE	0	secure	very1
92baa4
+#HttpOnly_127.0.0.1	FALSE	/p1/	FALSE	0	httpo1	value1
92baa4
+#HttpOnly_127.0.0.1	FALSE	/p2/	FALSE	0	httpo2	value2
92baa4
+#HttpOnly_127.0.0.1	FALSE	/p3/	FALSE	0	httpo3	value3
92baa4
+#HttpOnly_127.0.0.1	FALSE	/p4/	FALSE	0	httpo4	value4
92baa4
+#HttpOnly_127.0.0.1	FALSE	/p4/	FALSE	0	httponly	myvalue1
92baa4
+#HttpOnly_127.0.0.1	FALSE	/p4/	TRUE	0	httpandsec	myvalue2
92baa4
+#HttpOnly_127.0.0.1	FALSE	/p4/	TRUE	0	httpandsec2	myvalue3
92baa4
+#HttpOnly_127.0.0.1	FALSE	/p4/	TRUE	0	httpandsec3	myvalue4
92baa4
+#HttpOnly_127.0.0.1	FALSE	/p4/	TRUE	0	httpandsec4	myvalue5
92baa4
+#HttpOnly_127.0.0.1	FALSE	/p4/	TRUE	0	httpandsec5	myvalue6
92baa4
+#HttpOnly_127.0.0.1	FALSE	/p4/	TRUE	0	httpandsec6	myvalue7
92baa4
+#HttpOnly_127.0.0.1	FALSE	/p4/	TRUE	0	httpandsec7	myvalue8
92baa4
+#HttpOnly_127.0.0.1	FALSE	/p4/	TRUE	0	httpandsec8	myvalue9
92baa4
+127.0.0.1	FALSE	/	FALSE	0	partmatch	present
92baa4
 127.0.0.1	FALSE	/we/want/	FALSE	2054030187	nodomain	value
92baa4
 #HttpOnly_127.0.0.1	FALSE	/silly/	FALSE	0	magic	yessir
92baa4
-.0.0.1	TRUE	/we/want/	FALSE	0	blexp	yesyes
92baa4
+127.0.0.1	FALSE	/we/want/	FALSE	0	blexp	yesyes
92baa4
 </file>
92baa4
 </verify>
92baa4
 </testcase>
92baa4
diff --git a/tests/data/test8 b/tests/data/test8
92baa4
index 4d54541..030fd55 100644
92baa4
--- a/tests/data/test8
92baa4
+++ b/tests/data/test8
92baa4
@@ -42,7 +42,8 @@ Set-Cookie: duplicate=test; domain=.0.0.1; domain=.0.0.1; path=/donkey;
92baa4
 Set-Cookie: cookie=yes; path=/we;
92baa4
 Set-Cookie: cookie=perhaps; path=/we/want;
92baa4
 Set-Cookie: nocookie=yes; path=/WE;
92baa4
-Set-Cookie: blexp=yesyes; domain=.0.0.1; domain=.0.0.1; expiry=totally bad;
92baa4
+Set-Cookie: blexp=yesyes; domain=%HOSTIP; domain=%HOSTIP; expiry=totally bad;
92baa4
+Set-Cookie: partialip=nono; domain=.0.0.1;
92baa4
 
92baa4
 </file>
92baa4
 <precheck>
92baa4
-- 
92baa4
2.1.0
92baa4