Browse Source

hsts: CURLSTS_FAIL from hsts read callback should fail transfer

... and have CURLE_ABORTED_BY_CALLBACK returned.

Extended test 1915 to verify.

Reported-by: Jonathan Cardoso
Fixes #7726
Closes #7729
Daniel Stenberg 2 years ago
parent
commit
da2598f823
6 changed files with 34 additions and 6 deletions
  1. 3 1
      docs/libcurl/opts/CURLOPT_HSTSREADFUNCTION.3
  2. 1 1
      lib/hsts.c
  3. 1 1
      lib/hsts.h
  4. 1 1
      lib/transfer.c
  5. 5 2
      tests/data/test1915
  6. 23 0
      tests/libtest/lib1915.c

+ 3 - 1
docs/libcurl/opts/CURLOPT_HSTSREADFUNCTION.3

@@ -46,7 +46,9 @@ might cause the name to not get accepted)
 
 The callback should return \fICURLSTS_OK\fP if it returns a name and is
 prepared to be called again (for another host) or \fICURLSTS_DONE\fP if it has
-no entry to return. It can also return \fICURLSTS_FAIL\fP to signal error.
+no entry to return. It can also return \fICURLSTS_FAIL\fP to signal
+error. Returning \fICURLSTS_FAIL\fP will stop the transfer from being
+performed and make \fICURLE_ABORTED_BY_CALLBACK\fP get returned.
 
 This option doesn't enable HSTS, you need to use \fICURLOPT_HSTS_CTRL(3)\fP to
 do that.

+ 1 - 1
lib/hsts.c

@@ -466,7 +466,7 @@ static CURLcode hsts_pull(struct Curl_easy *data, struct hsts *h)
           return result;
       }
       else if(sc == CURLSTS_FAIL)
-        return CURLE_BAD_FUNCTION_ARGUMENT;
+        return CURLE_ABORTED_BY_CALLBACK;
     } while(sc == CURLSTS_OK);
   }
   return CURLE_OK;

+ 1 - 1
lib/hsts.h

@@ -59,7 +59,7 @@ CURLcode Curl_hsts_loadcb(struct Curl_easy *data,
                           struct hsts *h);
 #else
 #define Curl_hsts_cleanup(x)
-#define Curl_hsts_loadcb(x,y)
+#define Curl_hsts_loadcb(x,y) CURLE_OK
 #define Curl_hsts_save(x,y,z)
 #endif /* CURL_DISABLE_HTTP || CURL_DISABLE_HSTS */
 #endif /* HEADER_CURL_HSTS_H */

+ 1 - 1
lib/transfer.c

@@ -1503,7 +1503,7 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
     }
 #endif
     Curl_http2_init_state(&data->state);
-    Curl_hsts_loadcb(data, data->hsts);
+    result = Curl_hsts_loadcb(data, data->hsts);
   }
 
   /*

+ 5 - 2
tests/data/test1915

@@ -36,15 +36,18 @@ http://%HOSTIP:%NOLISTENPORT/not-there/%TESTNUMBER
 
 # Verify data after the test has been "shot"
 <verify>
-# it fails because there's nothing on that port
+# 7 CURLE_COULDNT_CONNECT (expected since there's nothing listening there)
+# 42 CURLE_ABORTED_BY_CALLBACK
 <errorcode>
-7
+42
 </errorcode>
 <stdout>
 [0/4] 1.example.com 20370320 01:02:03
 [1/4] 2.example.com 20370320 03:02:01
 [2/4] 3.example.com 20370319 01:02:03
 [3/4] 4.example.com unlimited
+First request returned 7
+Second request returned 42
 </stdout>
 </verify>
 </testcase>

+ 23 - 0
tests/libtest/lib1915.c

@@ -65,6 +65,16 @@ static CURLSTScode hstsread(CURL *easy, struct curl_hstsentry *e,
   return CURLSTS_OK;
 }
 
+/* verify error from callback */
+static CURLSTScode hstsreadfail(CURL *easy, struct curl_hstsentry *e,
+                                void *userp)
+{
+  (void)easy;
+  (void)e;
+  (void)userp;
+  return CURLSTS_FAIL;
+}
+
 /* check that we get the hosts back in the save */
 static CURLSTScode hstswrite(CURL *easy, struct curl_hstsentry *e,
                              struct curl_index *i, void *userp)
@@ -97,6 +107,19 @@ int test(char *URL)
     curl_easy_setopt(hnd, CURLOPT_HSTS_CTRL, CURLHSTS_ENABLE);
     ret = curl_easy_perform(hnd);
     curl_easy_cleanup(hnd);
+    printf("First request returned %d\n", (int)ret);
+  }
+  hnd = curl_easy_init();
+  if(hnd) {
+    curl_easy_setopt(hnd, CURLOPT_URL, URL);
+    curl_easy_setopt(hnd, CURLOPT_HSTSREADFUNCTION, hstsreadfail);
+    curl_easy_setopt(hnd, CURLOPT_HSTSREADDATA, &st);
+    curl_easy_setopt(hnd, CURLOPT_HSTSWRITEFUNCTION, hstswrite);
+    curl_easy_setopt(hnd, CURLOPT_HSTSWRITEDATA, &st);
+    curl_easy_setopt(hnd, CURLOPT_HSTS_CTRL, CURLHSTS_ENABLE);
+    ret = curl_easy_perform(hnd);
+    curl_easy_cleanup(hnd);
+    printf("Second request returned %d\n", (int)ret);
   }
   curl_global_cleanup();
   return (int)ret;