Commit 7c21c1c4 authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

cookie parser: handle 'secure='

There are two keywords in cookie headers that don't follow the regular
name=value style: secure and httponly. Still we must support that they
are written like 'secure=' and then treat them as if they were written
'secure'. Test case 31 was much extended by Rob Ward to test this.

Bug: http://curl.haxx.se/bug/view.cgi?id=3349227
Reported by: "gnombat"
parent f8831d55
Loading
Loading
Loading
Loading
+161 −161
Original line number Diff line number Diff line
@@ -206,7 +206,6 @@ Curl_cookie_add(struct SessionHandle *data,
  if(httpheader) {
    /* This line was read off a HTTP-header */
    const char *ptr;
    const char *sep;
    const char *semiptr;
    char *what;

@@ -223,26 +222,28 @@ Curl_cookie_add(struct SessionHandle *data,

    ptr = lineptr;
    do {
      /* we have a <what>=<this> pair or a 'secure' word here */
      sep = strchr(ptr, '=');
      if(sep && (!semiptr || (semiptr>sep)) ) {
        /*
         * There is a = sign and if there was a semicolon too, which make sure
         * that the semicolon comes _after_ the equal sign.
         */

      /* we have a <what>=<this> pair or a stand-alone word here */
      name[0]=what[0]=0; /* init the buffers */
        if(1 <= sscanf(ptr, "%" MAX_NAME_TXT "[^;=]=%"
      if(1 <= sscanf(ptr, "%" MAX_NAME_TXT "[^;\r\n =]=%"
                     MAX_COOKIE_LINE_TXT "[^;\r\n]",
                     name, what)) {
          /* this is a <name>=<what> pair. We use strstore() below to properly
             deal with received cookie headers that have the same string
             property set more than once, and then we use the last one. */

        /* Use strstore() below to properly deal with received cookie
           headers that have the same string property set more than once,
           and then we use the last one. */
        const char *whatptr;
        bool done = FALSE;
        bool sep;
        size_t len=strlen(what);
        const char *endofn = &ptr[ strlen(name) ];

        /* skip trailing spaces in name */
        while(*endofn && ISBLANK(*endofn))
          endofn++;

        /* name ends with a '=' ? */
        sep = *endofn == '='?TRUE:FALSE;

        /* Strip off trailing whitespace from the 'what' */
          size_t len=strlen(what);
        while(len && ISBLANK(what[len-1])) {
          what[len-1]=0;
          len--;
@@ -250,11 +251,24 @@ Curl_cookie_add(struct SessionHandle *data,

        /* Skip leading whitespace from the 'what' */
        whatptr=what;
          while(*whatptr && ISBLANK(*whatptr)) {
        while(*whatptr && ISBLANK(*whatptr))
          whatptr++;
          }

          if(Curl_raw_equal("path", name)) {
        if(!len) {
          /* this was a "<name>=" with no content, and we must allow
             'secure' and 'httponly' specified this weirdly */
          done = TRUE;
          if(Curl_raw_equal("secure", name))
            co->secure = TRUE;
          else if(Curl_raw_equal("httponly", name))
            co->httponly = TRUE;
          else if(sep)
            /* there was a '=' so we're not done parsing this field */
            done = FALSE;
        }
        if(done)
          ;
        else if(Curl_raw_equal("path", name)) {
          strstore(&co->path, whatptr);
          if(!co->path) {
            badcookie = TRUE; /* out of memory bad */
@@ -387,21 +401,7 @@ Curl_cookie_add(struct SessionHandle *data,
      else {
        /* this is an "illegal" <what>=<this> pair */
      }
      }
      else {
        if(sscanf(ptr, "%" MAX_COOKIE_LINE_TXT "[^;\r\n]",
                  what)) {
          if(Curl_raw_equal("secure", what)) {
            co->secure = TRUE;
          }
          else if(Curl_raw_equal("httponly", what)) {
            co->httponly = TRUE;
          }
          /* else,
             unsupported keyword without assign! */

        }
      }
      if(!semiptr || !*semiptr) {
        /* we already know there are no more cookies */
        semiptr = NULL;
+44 −0
Original line number Diff line number Diff line
@@ -18,6 +18,28 @@ Content-Type: text/html
Funny-head: yesyes
Set-Cookie: foobar=name; domain=anything.com; path=/ ; secure
Set-Cookie:ismatch=this  ; domain=127.0.0.1; path=/silly/
Set-Cookie: sec1value=secure1  ; domain=127.0.0.1; path=/secure1/ ; secure
Set-Cookie: sec2value=secure2  ; domain=127.0.0.1; path=/secure2/ ; secure=
Set-Cookie: sec3value=secure3  ; domain=127.0.0.1; path=/secure3/ ; secure=
Set-Cookie: sec4value=secure4  ; secure=; domain=127.0.0.1; path=/secure4/ ; 
Set-Cookie: sec5value=secure5  ; secure; domain=127.0.0.1; path=/secure5/ ; 
Set-Cookie: sec6value=secure6  ; secure ; domain=127.0.0.1; path=/secure6/ ; 
Set-Cookie: sec7value=secure7  ; secure   ; domain=127.0.0.1; path=/secure7/ ; 
Set-Cookie: sec8value=secure8  ; secure= ; domain=127.0.0.1; path=/secure8/ ; 
Set-Cookie: secure=very1  ; secure=; domain=127.0.0.1; path=/secure9/; 
Set-Cookie: httpo1=value1  ; domain=127.0.0.1; path=/p1/; httponly
Set-Cookie: httpo2=value2  ; domain=127.0.0.1; path=/p2/; httponly=
Set-Cookie: httpo3=value3  ; httponly; domain=127.0.0.1; path=/p3/;
Set-Cookie: httpo4=value4  ; httponly=; domain=127.0.0.1; path=/p4/; 
Set-Cookie: httponly=myvalue1  ; domain=127.0.0.1; path=/p4/; httponly
Set-Cookie: httpandsec=myvalue2  ; domain=127.0.0.1; path=/p4/; httponly; secure
Set-Cookie: httpandsec2=myvalue3; domain=127.0.0.1; path=/p4/; httponly=; secure
Set-Cookie: httpandsec3=myvalue4  ; domain=127.0.0.1; path=/p4/; httponly; secure=
Set-Cookie: httpandsec4=myvalue5  ; domain=127.0.0.1; path=/p4/; httponly=; secure=
Set-Cookie: httpandsec5=myvalue6  ; domain=127.0.0.1; path=/p4/; secure; httponly=
Set-Cookie: httpandsec6=myvalue7  ; domain=127.0.0.1; path=/p4/; secure=; httponly=
Set-Cookie: httpandsec7=myvalue8  ; domain=127.0.0.1; path=/p4/; secure; httponly
Set-Cookie: httpandsec8=myvalue9; domain=127.0.0.1; path=/p4/; secure=; httponly
Set-Cookie: partmatch=present; domain=127.0.0.1 ; path=/;
Set-Cookie:eat=this; domain=moo.foo.moo;
Set-Cookie: eat=this-too; domain=.foo.moo;
@@ -69,6 +91,28 @@ Accept: */*
# This file was generated by libcurl! Edit at your own risk.

.127.0.0.1	TRUE	/silly/	FALSE	0	ismatch	this
.127.0.0.1	TRUE	/secure1/	TRUE	0	sec1value	secure1
.127.0.0.1	TRUE	/secure2/	TRUE	0	sec2value	secure2
.127.0.0.1	TRUE	/secure3/	TRUE	0	sec3value	secure3
.127.0.0.1	TRUE	/secure4/	TRUE	0	sec4value	secure4
.127.0.0.1	TRUE	/secure5/	TRUE	0	sec5value	secure5
.127.0.0.1	TRUE	/secure6/	TRUE	0	sec6value	secure6
.127.0.0.1	TRUE	/secure7/	TRUE	0	sec7value	secure7
.127.0.0.1	TRUE	/secure8/	TRUE	0	sec8value	secure8
.127.0.0.1	TRUE	/secure9/	TRUE	0	secure	very1
#HttpOnly_.127.0.0.1	TRUE	/p1/	FALSE	0	httpo1	value1
#HttpOnly_.127.0.0.1	TRUE	/p2/	FALSE	0	httpo2	value2
#HttpOnly_.127.0.0.1	TRUE	/p3/	FALSE	0	httpo3	value3
#HttpOnly_.127.0.0.1	TRUE	/p4/	FALSE	0	httpo4	value4
#HttpOnly_.127.0.0.1	TRUE	/p4/	FALSE	0	httponly	myvalue1
#HttpOnly_.127.0.0.1	TRUE	/p4/	TRUE	0	httpandsec	myvalue2
#HttpOnly_.127.0.0.1	TRUE	/p4/	TRUE	0	httpandsec2	myvalue3
#HttpOnly_.127.0.0.1	TRUE	/p4/	TRUE	0	httpandsec3	myvalue4
#HttpOnly_.127.0.0.1	TRUE	/p4/	TRUE	0	httpandsec4	myvalue5
#HttpOnly_.127.0.0.1	TRUE	/p4/	TRUE	0	httpandsec5	myvalue6
#HttpOnly_.127.0.0.1	TRUE	/p4/	TRUE	0	httpandsec6	myvalue7
#HttpOnly_.127.0.0.1	TRUE	/p4/	TRUE	0	httpandsec7	myvalue8
#HttpOnly_.127.0.0.1	TRUE	/p4/	TRUE	0	httpandsec8	myvalue9
.127.0.0.1	TRUE	/	FALSE	0	partmatch	present
127.0.0.1	FALSE	/we/want/	FALSE	2054030187	nodomain	value
#HttpOnly_127.0.0.1	FALSE	/silly/	FALSE	0	magic	yessir