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
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
-----------
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) {
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);
}
+ 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! */
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * 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
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 {
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
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
# 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>