mirror of
https://github.com/curl/curl.git
synced 2026-04-12 12:21:42 +08:00
Now the logic for handling name duplicates and picking the longest expiry and strictest subdomain is the same for the callback as for when reading from file. Also strip trailing dots from the hostname added by the callback. A minor side-effect is that the hostname provided by the callback can now enable subdomains by starting the name with a dot, but we discourage using such hostnames in documentation. Amended test 1915 to verify. Closes #21201
151 lines
4.7 KiB
C
151 lines
4.7 KiB
C
/***************************************************************************
|
|
* _ _ ____ _
|
|
* Project ___| | | | _ \| |
|
|
* / __| | | | |_) | |
|
|
* | (__| |_| | _ <| |___
|
|
* \___|\___/|_| \_\_____|
|
|
*
|
|
* Copyright (C) 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
|
|
* are also available at https://curl.se/docs/copyright.html.
|
|
*
|
|
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
|
* copies of the Software, and permit persons to whom the Software is
|
|
* furnished to do so, under the terms of the COPYING file.
|
|
*
|
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
* KIND, either express or implied.
|
|
*
|
|
* SPDX-License-Identifier: curl
|
|
*
|
|
***************************************************************************/
|
|
#include "first.h"
|
|
|
|
#include "testtrace.h"
|
|
|
|
struct state {
|
|
int index;
|
|
};
|
|
|
|
/* "read" is from the point of the library, it wants data from us */
|
|
static CURLSTScode hstsread(CURL *curl, struct curl_hstsentry *e, void *userp)
|
|
{
|
|
struct entry {
|
|
const char *name;
|
|
const char *exp;
|
|
};
|
|
|
|
static const struct entry preload_hosts[] = {
|
|
#if (SIZEOF_TIME_T < 5)
|
|
{ "1.example.com", "20370320 01:02:03" },
|
|
{ "2.example.com.", "20370320 03:02:01" },
|
|
{ "3.example.com", "20370319 01:02:03" },
|
|
{ ".3.example.com", "20270319 01:02:03" },
|
|
#else
|
|
{ "1.example.com", "25250320 01:02:03" },
|
|
{ "2.example.com.", "25250320 03:02:01" },
|
|
{ "3.example.com", "25250319 01:02:03" },
|
|
{ ".3.example.com", "22250319 01:02:03" },
|
|
#endif
|
|
{ "4.example.com", "" }, /* forever */
|
|
{ ".4.example.com", "20370319 01:02:03" },
|
|
{ NULL, NULL } /* end of list marker */
|
|
};
|
|
|
|
const char *host;
|
|
const char *expire;
|
|
struct state *s = (struct state *)userp;
|
|
(void)curl;
|
|
host = preload_hosts[s->index].name;
|
|
expire = preload_hosts[s->index++].exp;
|
|
|
|
if(host) {
|
|
curlx_strcopy(e->name, e->namelen, host, strlen(host));
|
|
e->includeSubDomains = FALSE;
|
|
curlx_strcopy(e->expire, sizeof(e->expire), expire, strlen(expire));
|
|
curl_mfprintf(stderr, "add '%s'\n", host);
|
|
}
|
|
else
|
|
return CURLSTS_DONE;
|
|
return CURLSTS_OK;
|
|
}
|
|
|
|
/* verify error from callback */
|
|
static CURLSTScode hstsreadfail(CURL *curl, struct curl_hstsentry *e,
|
|
void *userp)
|
|
{
|
|
(void)curl;
|
|
(void)e;
|
|
(void)userp;
|
|
return CURLSTS_FAIL;
|
|
}
|
|
|
|
/* check that we get the hosts back in the save */
|
|
static CURLSTScode hstswrite(CURL *curl, struct curl_hstsentry *e,
|
|
struct curl_index *i, void *userp)
|
|
{
|
|
(void)curl;
|
|
(void)userp;
|
|
curl_mprintf("[%zu/%zu] %s%s %s\n", i->index, i->total,
|
|
e->includeSubDomains ? "." : "", e->name, e->expire);
|
|
return CURLSTS_OK;
|
|
}
|
|
|
|
/*
|
|
* Read/write HSTS cache entries via callback.
|
|
*/
|
|
|
|
static CURLcode test_lib1915(const char *URL)
|
|
{
|
|
CURLcode result = CURLE_OK;
|
|
CURL *curl;
|
|
struct state st = { 0 };
|
|
|
|
global_init(CURL_GLOBAL_ALL);
|
|
|
|
debug_config.nohex = TRUE;
|
|
debug_config.tracetime = TRUE;
|
|
|
|
easy_init(curl);
|
|
easy_setopt(curl, CURLOPT_URL, URL);
|
|
easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 1L);
|
|
easy_setopt(curl, CURLOPT_HSTSREADFUNCTION, hstsread);
|
|
easy_setopt(curl, CURLOPT_HSTSREADDATA, &st);
|
|
easy_setopt(curl, CURLOPT_HSTSWRITEFUNCTION, hstswrite);
|
|
easy_setopt(curl, CURLOPT_HSTSWRITEDATA, &st);
|
|
easy_setopt(curl, CURLOPT_HSTS_CTRL, CURLHSTS_ENABLE);
|
|
easy_setopt(curl, CURLOPT_DEBUGDATA, &debug_config);
|
|
easy_setopt(curl, CURLOPT_DEBUGFUNCTION, libtest_debug_cb);
|
|
easy_setopt(curl, CURLOPT_VERBOSE, 1L);
|
|
result = curl_easy_perform(curl);
|
|
curl_easy_cleanup(curl);
|
|
curl = NULL;
|
|
if(result == CURLE_OPERATION_TIMEDOUT) /* we expect that on Windows */
|
|
result = CURLE_COULDNT_CONNECT;
|
|
curl_mprintf("First request returned %d\n", result);
|
|
result = CURLE_OK;
|
|
|
|
easy_init(curl);
|
|
easy_setopt(curl, CURLOPT_URL, URL);
|
|
easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 1L);
|
|
easy_setopt(curl, CURLOPT_HSTSREADFUNCTION, hstsreadfail);
|
|
easy_setopt(curl, CURLOPT_HSTSREADDATA, &st);
|
|
easy_setopt(curl, CURLOPT_HSTSWRITEFUNCTION, hstswrite);
|
|
easy_setopt(curl, CURLOPT_HSTSWRITEDATA, &st);
|
|
easy_setopt(curl, CURLOPT_HSTS_CTRL, CURLHSTS_ENABLE);
|
|
easy_setopt(curl, CURLOPT_DEBUGDATA, &debug_config);
|
|
easy_setopt(curl, CURLOPT_DEBUGFUNCTION, libtest_debug_cb);
|
|
easy_setopt(curl, CURLOPT_VERBOSE, 1L);
|
|
result = curl_easy_perform(curl);
|
|
curl_easy_cleanup(curl);
|
|
curl = NULL;
|
|
curl_mprintf("Second request returned %d\n", result);
|
|
|
|
test_cleanup:
|
|
curl_easy_cleanup(curl);
|
|
curl_global_cleanup();
|
|
return result;
|
|
}
|