From da2598f823e95020defd54c6fdf3c82331ef12b3 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Thu, 16 Sep 2021 08:40:21 +0200 Subject: 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 --- docs/libcurl/opts/CURLOPT_HSTSREADFUNCTION.3 | 4 +++- lib/hsts.c | 2 +- lib/hsts.h | 2 +- lib/transfer.c | 2 +- tests/data/test1915 | 7 +++++-- tests/libtest/lib1915.c | 23 +++++++++++++++++++++++ 6 files changed, 34 insertions(+), 6 deletions(-) diff --git a/docs/libcurl/opts/CURLOPT_HSTSREADFUNCTION.3 b/docs/libcurl/opts/CURLOPT_HSTSREADFUNCTION.3 index d5e6ea542..2ed167fd9 100644 --- a/docs/libcurl/opts/CURLOPT_HSTSREADFUNCTION.3 +++ b/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. diff --git a/lib/hsts.c b/lib/hsts.c index fa91cf63f..052dc1157 100644 --- a/lib/hsts.c +++ b/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; diff --git a/lib/hsts.h b/lib/hsts.h index baa582864..653c05348 100644 --- a/lib/hsts.h +++ b/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 */ diff --git a/lib/transfer.c b/lib/transfer.c index 3e650b5b9..05fec7998 100644 --- a/lib/transfer.c +++ b/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); } /* diff --git a/tests/data/test1915 b/tests/data/test1915 index d0b2862f9..544dd4f41 100644 --- a/tests/data/test1915 +++ b/tests/data/test1915 @@ -36,15 +36,18 @@ http://%HOSTIP:%NOLISTENPORT/not-there/%TESTNUMBER # Verify data after the test has been "shot" -# 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 -7 +42 [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 diff --git a/tests/libtest/lib1915.c b/tests/libtest/lib1915.c index 2bd6ffce8..329f35453 100644 --- a/tests/libtest/lib1915.c +++ b/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; -- cgit v1.2.1