]> granicus.if.org Git - curl/commitdiff
cookie: Add support for cookie prefixes
authorDaniel Gustafsson <daniel@yesql.se>
Sat, 16 Feb 2019 23:09:30 +0000 (00:09 +0100)
committerDaniel Gustafsson <daniel@yesql.se>
Sat, 16 Feb 2019 23:09:30 +0000 (00:09 +0100)
The draft-ietf-httpbis-rfc6265bis-02 draft, specify a set of prefixes
and how they should affect cookie initialization, which has been
adopted by the major browsers. This adds support for the two prefixes
defined, __Host- and __Secure, and updates the testcase with the
supplied examples from the draft.

Closes #3554
Reviewed-by: Daniel Stenberg <daniel@haxx.se>
docs/HTTP-COOKIES.md
docs/ROADMAP.md
lib/cookie.c
lib/cookie.h
tests/data/test1561

index 66e39d232531890018a273431ecb7818170be674..632cb4ebe1817e1dc55f056de3af024d6cabf475 100644 (file)
   original [Netscape spec from 1994](https://curl.haxx.se/rfc/cookie_spec.html).
 
   In 2011, [RFC6265](https://www.ietf.org/rfc/rfc6265.txt) was finally
-  published and details how cookies work within HTTP. In 2017, an update was
+  published and details how cookies work within HTTP. In 2016, an update which
+  added support for prefixes was
+  [proposed](https://tools.ietf.org/html/draft-ietf-httpbis-cookie-prefixes-00),
+  and in 2017, another update was
   [drafted](https://tools.ietf.org/html/draft-ietf-httpbis-cookie-alone-01)
-  to deprecate modification of 'secure' cookies from non-secure origins.
+  to deprecate modification of 'secure' cookies from non-secure origins. Both
+  of these drafs have been incorporated into a proposal to
+  [replace](https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-02)
+  RFC6265. Cookie prefixes and secure cookie modification protection has been
+  implemented by curl.
 
 ## Cookies saved to disk
 
index 497c45b542a8d374792cd15c47e85b40790c397f..cbcaa2235c67c4c091b040c15852615ed5e8339d 100644 (file)
@@ -10,16 +10,6 @@ QUIC
 
  See the [QUIC wiki page](https://github.com/curl/curl/wiki/QUIC).
 
-HTTP cookies
-------------
-
-On top of what we already support, the prefix cookie draft has been adopted by
-the httpwg in IETF and we should support it as the popular browsers will:
-
-[Cookie Prefixes](https://tools.ietf.org/html/draft-ietf-httpbis-cookie-prefixes-00)
-
-[Firefox bug report about secure cookies](https://bugzilla.mozilla.org/show_bug.cgi?id=976073)
-
 SRV records
 -----------
 
index 4fb992ac9df917a688e12eec31c4f58403c7e6de..3a3f45de3855d1d7e21f4d6c26fb4ad3d91eeec7 100644 (file)
@@ -528,6 +528,19 @@ Curl_cookie_add(struct Curl_easy *data,
         while(*whatptr && ISBLANK(*whatptr))
           whatptr++;
 
+        /*
+         * Check if we have a reserved prefix set before anything else, as we
+         * otherwise have to test for the prefix in both the cookie name and
+         * "the rest". Prefixes must start with '__' and end with a '-', so
+         * only test for names where that can possibly be true.
+         */
+        if(nlen > 3 && name[0] == '_' && name[1] == '_') {
+          if(strncasecompare("__Secure-", name, 9))
+            co->prefix |= COOKIE_PREFIX__SECURE;
+          else if(strncasecompare("__Host-", name, 7))
+            co->prefix |= COOKIE_PREFIX__HOST;
+        }
+
         if(!co->name) {
           /* The very first name/value pair is the actual cookie name */
           if(!sep) {
@@ -862,6 +875,11 @@ Curl_cookie_add(struct Curl_easy *data,
         co->name = strdup(ptr);
         if(!co->name)
           badcookie = TRUE;
+        /* For Netscape file format cookies we check prefix on the name */
+        if(strncasecompare("__Secure-", co->name, 9))
+          co->prefix |= COOKIE_PREFIX__SECURE;
+        else if(strncasecompare("__Host-", co->name, 7))
+          co->prefix |= COOKIE_PREFIX__HOST;
         break;
       case 6:
         co->value = strdup(ptr);
@@ -890,6 +908,26 @@ Curl_cookie_add(struct Curl_easy *data,
 
   }
 
+  if(co->prefix & COOKIE_PREFIX__SECURE) {
+    /* The __Secure- prefix only requires that the cookie be set secure */
+    if(!co->secure) {
+      freecookie(co);
+      return NULL;
+    }
+  }
+  if(co->prefix & COOKIE_PREFIX__HOST) {
+    /*
+     * The __Host- prefix requires the cookie to be secure, have a "/" path
+     * and not have a domain set.
+     */
+    if(co->secure && co->path && strcmp(co->path, "/") == 0 && !co->tailmatch)
+      ;
+    else {
+      freecookie(co);
+      return NULL;
+    }
+  }
+
   if(!c->running &&    /* read from a file */
      c->newsession &&  /* clean session cookies */
      !co->expires) {   /* this is a session cookie since it doesn't expire! */
index 3ee457c6225fba87b223a1d95b9656e3e77cb6fe..b2730cfb91d92bea4d281879a29bc84aa4634dd9 100644 (file)
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -44,8 +44,16 @@ struct Cookie {
   bool livecookie;   /* updated from a server, not a stored file */
   bool httponly;     /* true if the httponly directive is present */
   int creationtime;  /* time when the cookie was written */
+  unsigned char prefix; /* bitmap fields indicating which prefix are set */
 };
 
+/*
+ * Available cookie prefixes, as defined in
+ * draft-ietf-httpbis-rfc6265bis-02
+ */
+#define COOKIE_PREFIX__SECURE (1<<0)
+#define COOKIE_PREFIX__HOST (1<<1)
+
 #define COOKIE_HASH_SIZE 256
 
 struct CookieInfo {
index ff448c95f172a22982722db5de2df0fed01d3d05..69352fda2fd196a7ab0691da48a9358f107e8bf2 100644 (file)
@@ -18,6 +18,15 @@ Date: Thu, 09 Nov 2010 14:49:00 GMT
 Server: test-server/fake
 Set-Cookie: super=secret; domain=example.com; path=/1561; secure;
 Set-Cookie: supersuper=secret; domain=example.com; path=/1561/login/; secure;
+Set-Cookie: __Secure-SID=12345; Domain=example.com
+Set-Cookie: __Secure-SID=12346; Secure; Domain=example.com
+Set-Cookie: supersupersuper=secret; __Secure-SID=12346; Secure; Domain=example.com
+Set-Cookie: __Host-SID=22345
+Set-Cookie: __Host-SID=22346; Secure
+Set-Cookie: __Host-SID=22347; Domain=example.com
+Set-Cookie: __Host-SID=22348; Domain=example.com; Path=/
+Set-Cookie: __Host-SID=22349; Secure; Domain=example.com; Path=/
+Set-Cookie: __Host-SID=12346; Secure; Path=/
 Content-Length: 7
 
 nomnom
@@ -33,6 +42,14 @@ Set-Cookie: public=yes; domain=example.com; path=/foo;
 Set-Cookie: supersuper=secret; domain=example.com; path=/1561/login/en;
 Set-Cookie: supersuper=secret; domain=example.com; path=/1561/login;
 Set-Cookie: secureoverhttp=yes; domain=example.com; path=/1561; secure;
+Set-Cookie: __Secure-SID=22345; Domain=example.com
+Set-Cookie: __Secure-SID=22346; Secure; Domain=example.com
+Set-Cookie: __Host-SID=32345
+Set-Cookie: __Host-SID=32346; Secure
+Set-Cookie: __Host-SID=32347; Domain=example.com
+Set-Cookie: __Host-SID=32348; Domain=example.com; Path=/
+Set-Cookie: __Host-SID=32349; Secure; Domain=example.com; Path=/
+Set-Cookie: __Host-SID=32350; Secure; Path=/
 Content-Length: 7
 
 nomnom
@@ -77,6 +94,9 @@ Accept: */*
 # This file was generated by libcurl! Edit at your own risk.
 
 .example.com   TRUE    /foo    FALSE   0       public  yes
+www.example.com        FALSE   /       TRUE    0       __Host-SID      12346
+.example.com   TRUE    /       TRUE    0       supersupersuper secret
+.example.com   TRUE    /       TRUE    0       __Secure-SID    12346
 .example.com   TRUE    /1561/login/    TRUE    0       supersuper      secret
 #HttpOnly_.example.com TRUE    /15     FALSE   0       super   secret
 </file>