]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
http: consider cookies over localhost to be secure
authorDaniel Stenberg <daniel@haxx.se>
Mon, 10 May 2021 08:50:43 +0000 (10:50 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Tue, 10 Aug 2021 09:20:21 +0000 (11:20 +0200)
Updated test31.
Added test 392 to verify secure cookies used for http://localhost

Reviewed-by: Daniel Gustafsson
Fixes #6733
Closes #7263

lib/http.c
tests/data/Makefile.inc
tests/data/test31
tests/data/test392 [new file with mode: 0644]

index 05b971b20438c80ced72419bb316ad1a51c9e03e..54362362a3a6b4abd96bfece421537770e0fb198 100644 (file)
@@ -2711,14 +2711,16 @@ CURLcode Curl_http_cookies(struct Curl_easy *data,
     int count = 0;
 
     if(data->cookies && data->state.cookie_engine) {
+      const char *host = data->state.aptr.cookiehost ?
+        data->state.aptr.cookiehost : conn->host.name;
+      const bool secure_context =
+        conn->handler->protocol&CURLPROTO_HTTPS ||
+        strcasecompare("localhost", host) ||
+        !strcmp(host, "127.0.0.1") ||
+        !strcmp(host, "[::1]") ? TRUE : FALSE;
       Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
-      co = Curl_cookie_getlist(data->cookies,
-                               data->state.aptr.cookiehost?
-                               data->state.aptr.cookiehost:
-                               conn->host.name,
-                               data->state.up.path,
-                               (conn->handler->protocol&CURLPROTO_HTTPS)?
-                               TRUE:FALSE);
+      co = Curl_cookie_getlist(data->cookies, host, data->state.up.path,
+                               secure_context);
       Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
     }
     if(co) {
@@ -3564,18 +3566,21 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn,
 #if !defined(CURL_DISABLE_COOKIES)
   else if(data->cookies && data->state.cookie_engine &&
           checkprefix("Set-Cookie:", headp)) {
+    /* If there is a custom-set Host: name, use it here, or else use real peer
+       host name. */
+    const char *host = data->state.aptr.cookiehost?
+      data->state.aptr.cookiehost:conn->host.name;
+    const bool secure_context =
+      conn->handler->protocol&CURLPROTO_HTTPS ||
+      strcasecompare("localhost", host) ||
+      !strcmp(host, "127.0.0.1") ||
+      !strcmp(host, "[::1]") ? TRUE : FALSE;
+
     Curl_share_lock(data, CURL_LOCK_DATA_COOKIE,
                     CURL_LOCK_ACCESS_SINGLE);
-    Curl_cookie_add(data,
-                    data->cookies, TRUE, FALSE,
-                    headp + strlen("Set-Cookie:"),
-                    /* If there is a custom-set Host: name, use it
-                       here, or else use real peer host name. */
-                    data->state.aptr.cookiehost?
-                    data->state.aptr.cookiehost:conn->host.name,
-                    data->state.up.path,
-                    (conn->handler->protocol&CURLPROTO_HTTPS)?
-                    TRUE:FALSE);
+    Curl_cookie_add(data, data->cookies, TRUE, FALSE,
+                    headp + strlen("Set-Cookie:"), host,
+                    data->state.up.path, secure_context);
     Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
   }
 #endif
index 1636969622605d497b894d7051a1b7f4f70c3a4b..7e915c0c1acf938f7ee9c0ed020e7f32f725264c 100644 (file)
@@ -62,7 +62,7 @@ test343 test344 test345 test346 test347 test348 test349 test350 test351 \
 test352 test353 test354 test355 test356 test357 test358 test359 test360 \
 test361 test362 test363 test364 \
 \
-test393 test394 test395 test396 test397 \
+test392 test393 test394 test395 test396 test397 \
 \
 test400 test401 test402 test403 test404 test405 test406 test407 test408 \
 test409 test410 \
index 2ccb032549fa2740f65f1e53886e7bae7120befa..ac277264d89679c5753edcba48107a039940e15e 100644 (file)
@@ -24,32 +24,32 @@ Content-Type: text/html
 Funny-head: yesyes\r
 %if !hyper
 Set-Cookie: foobar=name; domain=anything.com; path=/ ; secure\r
-Set-Cookie:ismatch=this  ; domain=127.0.0.1; path=/silly/\r
-Set-Cookie: overwrite=this  ; domain=127.0.0.1; path=/overwrite/\r
-Set-Cookie: overwrite=this2  ; domain=127.0.0.1; path=/overwrite\r
-Set-Cookie: sec1value=secure1  ; domain=127.0.0.1; path=/secure1/ ; secure\r
-Set-Cookie: sec2value=secure2  ; domain=127.0.0.1; path=/secure2/ ; secure=\r
-Set-Cookie: sec3value=secure3  ; domain=127.0.0.1; path=/secure3/ ; secure=\r
-Set-Cookie: sec4value=secure4  ; secure=; domain=127.0.0.1; path=/secure4/ ; \r
-Set-Cookie: sec5value=secure5  ; secure; domain=127.0.0.1; path=/secure5/ ; \r
-Set-Cookie: sec6value=secure6  ; secure ; domain=127.0.0.1; path=/secure6/ ; \r
-Set-Cookie: sec7value=secure7  ; secure   ; domain=127.0.0.1; path=/secure7/ ; \r
-Set-Cookie: sec8value=secure8  ; secure= ; domain=127.0.0.1; path=/secure8/ ; \r
-Set-Cookie: secure=very1  ; secure=; domain=127.0.0.1; path=/secure9/; \r
-Set-Cookie: httpo1=value1  ; domain=127.0.0.1; path=/p1/; httponly\r
-Set-Cookie: httpo2=value2  ; domain=127.0.0.1; path=/p2/; httponly=\r
-Set-Cookie: httpo3=value3  ; httponly; domain=127.0.0.1; path=/p3/;\r
-Set-Cookie: httpo4=value4  ; httponly=; domain=127.0.0.1; path=/p4/; \r
-Set-Cookie: httponly=myvalue1  ; domain=127.0.0.1; path=/p4/; httponly\r
-Set-Cookie: httpandsec=myvalue2  ; domain=127.0.0.1; path=/p4/; httponly; secure\r
-Set-Cookie: httpandsec2=myvalue3; domain=127.0.0.1; path=/p4/; httponly=; secure\r
-Set-Cookie: httpandsec3=myvalue4  ; domain=127.0.0.1; path=/p4/; httponly; secure=\r
-Set-Cookie: httpandsec4=myvalue5  ; domain=127.0.0.1; path=/p4/; httponly=; secure=\r
-Set-Cookie: httpandsec5=myvalue6  ; domain=127.0.0.1; path=/p4/; secure; httponly=\r
-Set-Cookie: httpandsec6=myvalue7  ; domain=127.0.0.1; path=/p4/; secure=; httponly=\r
-Set-Cookie: httpandsec7=myvalue8  ; domain=127.0.0.1; path=/p4/; secure; httponly\r
-Set-Cookie: httpandsec8=myvalue9; domain=127.0.0.1; path=/p4/; secure=; httponly\r
-Set-Cookie: partmatch=present; domain=127.0.0.1 ; path=/;\r
+Set-Cookie:ismatch=this  ; domain=test31.curl; path=/silly/\r
+Set-Cookie: overwrite=this  ; domain=test31.curl; path=/overwrite/\r
+Set-Cookie: overwrite=this2  ; domain=test31.curl; path=/overwrite\r
+Set-Cookie: sec1value=secure1  ; domain=test31.curl; path=/secure1/ ; secure\r
+Set-Cookie: sec2value=secure2  ; domain=test31.curl; path=/secure2/ ; secure=\r
+Set-Cookie: sec3value=secure3  ; domain=test31.curl; path=/secure3/ ; secure=\r
+Set-Cookie: sec4value=secure4  ; secure=; domain=test31.curl; path=/secure4/ ; \r
+Set-Cookie: sec5value=secure5  ; secure; domain=test31.curl; path=/secure5/ ; \r
+Set-Cookie: sec6value=secure6  ; secure ; domain=test31.curl; path=/secure6/ ; \r
+Set-Cookie: sec7value=secure7  ; secure   ; domain=test31.curl; path=/secure7/ ; \r
+Set-Cookie: sec8value=secure8  ; secure= ; domain=test31.curl; path=/secure8/ ; \r
+Set-Cookie: secure=very1  ; secure=; domain=test31.curl; path=/secure9/; \r
+Set-Cookie: httpo1=value1  ; domain=test31.curl; path=/p1/; httponly\r
+Set-Cookie: httpo2=value2  ; domain=test31.curl; path=/p2/; httponly=\r
+Set-Cookie: httpo3=value3  ; httponly; domain=test31.curl; path=/p3/;\r
+Set-Cookie: httpo4=value4  ; httponly=; domain=test31.curl; path=/p4/; \r
+Set-Cookie: httponly=myvalue1  ; domain=test31.curl; path=/p4/; httponly\r
+Set-Cookie: httpandsec=myvalue2  ; domain=test31.curl; path=/p4/; httponly; secure\r
+Set-Cookie: httpandsec2=myvalue3; domain=test31.curl; path=/p4/; httponly=; secure\r
+Set-Cookie: httpandsec3=myvalue4  ; domain=test31.curl; path=/p4/; httponly; secure=\r
+Set-Cookie: httpandsec4=myvalue5  ; domain=test31.curl; path=/p4/; httponly=; secure=\r
+Set-Cookie: httpandsec5=myvalue6  ; domain=test31.curl; path=/p4/; secure; httponly=\r
+Set-Cookie: httpandsec6=myvalue7  ; domain=test31.curl; path=/p4/; secure=; httponly=\r
+Set-Cookie: httpandsec7=myvalue8  ; domain=test31.curl; path=/p4/; secure; httponly\r
+Set-Cookie: httpandsec8=myvalue9; domain=test31.curl; path=/p4/; secure=; httponly\r
+Set-Cookie: partmatch=present; domain=test31.curl ; path=/;\r
 Set-Cookie:eat=this; domain=moo.foo.moo;\r
 Set-Cookie: eat=this-too; domain=.foo.moo;\r
 Set-Cookie: nodomainnovalue\r
@@ -58,7 +58,7 @@ Set-Cookie: novalue; domain=reallysilly
 Set-Cookie: test=yes; domain=foo.com; expires=Sat Feb 2 11:56:27 GMT 2030\r
 Set-Cookie: test2=yes; domain=se; expires=Sat Feb 2 11:56:27 GMT 2030\r
 Set-Cookie: magic=yessir; path=/silly/; HttpOnly\r
-Set-Cookie: blexp=yesyes; domain=127.0.0.1; domain=127.0.0.1; expiry=totally bad;\r
+Set-Cookie: blexp=yesyes; domain=test31.curl; domain=test31.curl; expiry=totally bad;\r
 Set-Cookie: partialip=nono; domain=.0.0.1;\r
 Set-Cookie: withspaces=  yes  within and around    ;\r
 Set-Cookie: withspaces2 =before equals;\r
@@ -66,32 +66,32 @@ Set-Cookie: prespace=  yes before;
 Set-Cookie: securewithspace=after    ; secure =\r
 %else
 Set-Cookie: foobar=name; domain=anything.com; path=/ ; secure\r
-Set-Cookie: ismatch=this  ; domain=127.0.0.1; path=/silly/\r
-Set-Cookie: overwrite=this  ; domain=127.0.0.1; path=/overwrite/\r
-Set-Cookie: overwrite=this2  ; domain=127.0.0.1; path=/overwrite\r
-Set-Cookie: sec1value=secure1  ; domain=127.0.0.1; path=/secure1/ ; secure\r
-Set-Cookie: sec2value=secure2  ; domain=127.0.0.1; path=/secure2/ ; secure=\r
-Set-Cookie: sec3value=secure3  ; domain=127.0.0.1; path=/secure3/ ; secure=\r
-Set-Cookie: sec4value=secure4  ; secure=; domain=127.0.0.1; path=/secure4/ ;\r
-Set-Cookie: sec5value=secure5  ; secure; domain=127.0.0.1; path=/secure5/ ;\r
-Set-Cookie: sec6value=secure6  ; secure ; domain=127.0.0.1; path=/secure6/ ;\r
-Set-Cookie: sec7value=secure7  ; secure   ; domain=127.0.0.1; path=/secure7/ ;\r
-Set-Cookie: sec8value=secure8  ; secure= ; domain=127.0.0.1; path=/secure8/ ;\r
-Set-Cookie: secure=very1  ; secure=; domain=127.0.0.1; path=/secure9/;\r
-Set-Cookie: httpo1=value1  ; domain=127.0.0.1; path=/p1/; httponly\r
-Set-Cookie: httpo2=value2  ; domain=127.0.0.1; path=/p2/; httponly=\r
-Set-Cookie: httpo3=value3  ; httponly; domain=127.0.0.1; path=/p3/;\r
-Set-Cookie: httpo4=value4  ; httponly=; domain=127.0.0.1; path=/p4/;\r
-Set-Cookie: httponly=myvalue1  ; domain=127.0.0.1; path=/p4/; httponly\r
-Set-Cookie: httpandsec=myvalue2  ; domain=127.0.0.1; path=/p4/; httponly; secure\r
-Set-Cookie: httpandsec2=myvalue3; domain=127.0.0.1; path=/p4/; httponly=; secure\r
-Set-Cookie: httpandsec3=myvalue4  ; domain=127.0.0.1; path=/p4/; httponly; secure=\r
-Set-Cookie: httpandsec4=myvalue5  ; domain=127.0.0.1; path=/p4/; httponly=; secure=\r
-Set-Cookie: httpandsec5=myvalue6  ; domain=127.0.0.1; path=/p4/; secure; httponly=\r
-Set-Cookie: httpandsec6=myvalue7  ; domain=127.0.0.1; path=/p4/; secure=; httponly=\r
-Set-Cookie: httpandsec7=myvalue8  ; domain=127.0.0.1; path=/p4/; secure; httponly\r
-Set-Cookie: httpandsec8=myvalue9; domain=127.0.0.1; path=/p4/; secure=; httponly\r
-Set-Cookie: partmatch=present; domain=127.0.0.1 ; path=/;\r
+Set-Cookie: ismatch=this  ; domain=test31.curl; path=/silly/\r
+Set-Cookie: overwrite=this  ; domain=test31.curl; path=/overwrite/\r
+Set-Cookie: overwrite=this2  ; domain=test31.curl; path=/overwrite\r
+Set-Cookie: sec1value=secure1  ; domain=test31.curl; path=/secure1/ ; secure\r
+Set-Cookie: sec2value=secure2  ; domain=test31.curl; path=/secure2/ ; secure=\r
+Set-Cookie: sec3value=secure3  ; domain=test31.curl; path=/secure3/ ; secure=\r
+Set-Cookie: sec4value=secure4  ; secure=; domain=test31.curl; path=/secure4/ ;\r
+Set-Cookie: sec5value=secure5  ; secure; domain=test31.curl; path=/secure5/ ;\r
+Set-Cookie: sec6value=secure6  ; secure ; domain=test31.curl; path=/secure6/ ;\r
+Set-Cookie: sec7value=secure7  ; secure   ; domain=test31.curl; path=/secure7/ ;\r
+Set-Cookie: sec8value=secure8  ; secure= ; domain=test31.curl; path=/secure8/ ;\r
+Set-Cookie: secure=very1  ; secure=; domain=test31.curl; path=/secure9/;\r
+Set-Cookie: httpo1=value1  ; domain=test31.curl; path=/p1/; httponly\r
+Set-Cookie: httpo2=value2  ; domain=test31.curl; path=/p2/; httponly=\r
+Set-Cookie: httpo3=value3  ; httponly; domain=test31.curl; path=/p3/;\r
+Set-Cookie: httpo4=value4  ; httponly=; domain=test31.curl; path=/p4/;\r
+Set-Cookie: httponly=myvalue1  ; domain=test31.curl; path=/p4/; httponly\r
+Set-Cookie: httpandsec=myvalue2  ; domain=test31.curl; path=/p4/; httponly; secure\r
+Set-Cookie: httpandsec2=myvalue3; domain=test31.curl; path=/p4/; httponly=; secure\r
+Set-Cookie: httpandsec3=myvalue4  ; domain=test31.curl; path=/p4/; httponly; secure=\r
+Set-Cookie: httpandsec4=myvalue5  ; domain=test31.curl; path=/p4/; httponly=; secure=\r
+Set-Cookie: httpandsec5=myvalue6  ; domain=test31.curl; path=/p4/; secure; httponly=\r
+Set-Cookie: httpandsec6=myvalue7  ; domain=test31.curl; path=/p4/; secure=; httponly=\r
+Set-Cookie: httpandsec7=myvalue8  ; domain=test31.curl; path=/p4/; secure; httponly\r
+Set-Cookie: httpandsec8=myvalue9; domain=test31.curl; path=/p4/; secure=; httponly\r
+Set-Cookie: partmatch=present; domain=test31.curl ; path=/;\r
 Set-Cookie: eat=this; domain=moo.foo.moo;\r
 Set-Cookie: eat=this-too; domain=.foo.moo;\r
 Set-Cookie: nodomainnovalue\r
@@ -100,7 +100,7 @@ Set-Cookie: novalue; domain=reallysilly
 Set-Cookie: test=yes; domain=foo.com; expires=Sat Feb 2 11:56:27 GMT 2030\r
 Set-Cookie: test2=yes; domain=se; expires=Sat Feb 2 11:56:27 GMT 2030\r
 Set-Cookie: magic=yessir; path=/silly/; HttpOnly\r
-Set-Cookie: blexp=yesyes; domain=127.0.0.1; domain=127.0.0.1; expiry=totally bad;\r
+Set-Cookie: blexp=yesyes; domain=test31.curl; domain=test31.curl; expiry=totally bad;\r
 Set-Cookie: partialip=nono; domain=.0.0.1;\r
 Set-Cookie: withspaces=  yes  within and around    ;\r
 Set-Cookie: withspaces2 =before equals;\r
@@ -127,7 +127,7 @@ HTTP with weirdly formatted cookies and cookiejar storage
 TZ=GMT
 </setenv>
  <command>
-http://%HOSTIP:%HTTPPORT/we/want/%TESTNUMBER -b none -c log/jar%TESTNUMBER.txt
+http://test31.curl:%HTTPPORT/we/want/%TESTNUMBER -b none -c log/jar%TESTNUMBER.txt --resolve test31.curl:%HTTPPORT:127.0.0.1
 </command>
 <precheck>
 perl -e "print 'Test requires default test server host' if ( '%HOSTIP' ne '127.0.0.1' );"
@@ -138,7 +138,7 @@ perl -e "print 'Test requires default test server host' if ( '%HOSTIP' ne '127.0
 <verify>
 <protocol>
 GET /we/want/%TESTNUMBER HTTP/1.1\r
-Host: %HOSTIP:%HTTPPORT\r
+Host: test31.curl:%HTTPPORT\r
 User-Agent: curl/%VERSION\r
 Accept: */*\r
 \r
@@ -148,20 +148,20 @@ Accept: */*
 # https://curl.se/docs/http-cookies.html
 # This file was generated by libcurl! Edit at your own risk.
 
-127.0.0.1      FALSE   /we/want/       FALSE   0       prespace        yes before
-127.0.0.1      FALSE   /we/want/       FALSE   0       withspaces2     before equals
-127.0.0.1      FALSE   /we/want/       FALSE   0       withspaces      yes  within and around
-127.0.0.1      FALSE   /we/want/       FALSE   0       blexp   yesyes
-#HttpOnly_127.0.0.1    FALSE   /silly/ FALSE   0       magic   yessir
-127.0.0.1      FALSE   /we/want/       FALSE   2118138987      nodomain        value
-127.0.0.1      FALSE   /       FALSE   0       partmatch       present
-#HttpOnly_127.0.0.1    FALSE   /p4/    FALSE   0       httponly        myvalue1
-#HttpOnly_127.0.0.1    FALSE   /p4/    FALSE   0       httpo4  value4
-#HttpOnly_127.0.0.1    FALSE   /p3/    FALSE   0       httpo3  value3
-#HttpOnly_127.0.0.1    FALSE   /p2/    FALSE   0       httpo2  value2
-#HttpOnly_127.0.0.1    FALSE   /p1/    FALSE   0       httpo1  value1
-127.0.0.1      FALSE   /overwrite      FALSE   0       overwrite       this2
-127.0.0.1      FALSE   /silly/ FALSE   0       ismatch this
+test31.curl    FALSE   /we/want/       FALSE   0       prespace        yes before
+test31.curl    FALSE   /we/want/       FALSE   0       withspaces2     before equals
+test31.curl    FALSE   /we/want/       FALSE   0       withspaces      yes  within and around
+.test31.curl   TRUE    /we/want/       FALSE   0       blexp   yesyes
+#HttpOnly_test31.curl  FALSE   /silly/ FALSE   0       magic   yessir
+test31.curl    FALSE   /we/want/       FALSE   2118138987      nodomain        value
+.test31.curl   TRUE    /       FALSE   0       partmatch       present
+#HttpOnly_.test31.curl TRUE    /p4/    FALSE   0       httponly        myvalue1
+#HttpOnly_.test31.curl TRUE    /p4/    FALSE   0       httpo4  value4
+#HttpOnly_.test31.curl TRUE    /p3/    FALSE   0       httpo3  value3
+#HttpOnly_.test31.curl TRUE    /p2/    FALSE   0       httpo2  value2
+#HttpOnly_.test31.curl TRUE    /p1/    FALSE   0       httpo1  value1
+.test31.curl   TRUE    /overwrite      FALSE   0       overwrite       this2
+.test31.curl   TRUE    /silly/ FALSE   0       ismatch this
 </file>
 </verify>
 </testcase>
diff --git a/tests/data/test392 b/tests/data/test392
new file mode 100644 (file)
index 0000000..24430c1
--- /dev/null
@@ -0,0 +1,61 @@
+<testcase>
+<info>
+<keywords>
+HTTP
+HTTP GET
+cookies
+secure
+</keywords>
+</info>
+
+<reply>
+<data>
+HTTP/1.1 200 OK\r
+Date: Tue, 09 Nov 2010 14:49:00 GMT\r
+Server: test-server/fake\r
+Content-Length: 4\r
+Content-Type: text/html\r
+Funny-head: yesyes\r
+Set-Cookie: foobar=name; path=/; secure\r
+\r
+boo
+</data>
+</reply>
+
+# Client-side
+<client>
+<server>
+http
+</server>
+ <name>
+HTTP secure cookies over localhost
+ </name>
+
+<setenv>
+TZ=GMT
+</setenv>
+ <command>
+http://localhost:%HTTPPORT/%TESTNUMBER -b none http://localhost:%HTTPPORT/%TESTNUMBER
+</command>
+<precheck>
+perl -e "print 'Test requires default test server host' if ( '%HOSTIP' ne '127.0.0.1' );"
+</precheck>
+</client>
+
+# Verify data after the test has been "shot"
+<verify>
+<protocol>
+GET /%TESTNUMBER HTTP/1.1\r
+Host: localhost:%HTTPPORT\r
+User-Agent: curl/%VERSION\r
+Accept: */*\r
+\r
+GET /%TESTNUMBER HTTP/1.1\r
+Host: localhost:%HTTPPORT\r
+User-Agent: curl/%VERSION\r
+Accept: */*\r
+Cookie: foobar=name\r
+\r
+</protocol>
+</verify>
+</testcase>