1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 2020 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
9  *
10  * This software is licensed as described in the file COPYING, which
11  * you should have received as part of this distribution. The terms
12  * are also available at https://curl.se/docs/copyright.html.
13  *
14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15  * copies of the Software, and permit persons to whom the Software is
16  * furnished to do so, under the terms of the COPYING file.
17  *
18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19  * KIND, either express or implied.
20  *
21  ***************************************************************************/
22 #include "test.h"
23 
24 #include "testutil.h"
25 #include "warnless.h"
26 #include "memdebug.h"
27 
28 struct entry {
29   const char *name;
30   const char *exp;
31 };
32 
33 static struct entry preload_hosts[] = {
34   /* curl turns 39 that day just before 31-bit time_t overflow */
35   { "1.example.com", "20370320 01:02:03" },
36   { "2.example.com", "20370320 03:02:01" },
37   { "3.example.com", "20370319 01:02:03" },
38   { "4.example.com", "" },
39   { NULL, NULL } /* end of list marker */
40 };
41 
42 struct state {
43   int index;
44 };
45 
46 /* "read" is from the point of the library, it wants data from us */
hstsread(CURL * easy,struct curl_hstsentry * e,void * userp)47 static CURLSTScode hstsread(CURL *easy, struct curl_hstsentry *e,
48                             void *userp)
49 {
50   const char *host;
51   const char *expire;
52   struct state *s = (struct state *)userp;
53   (void)easy;
54   host = preload_hosts[s->index].name;
55   expire = preload_hosts[s->index++].exp;
56 
57   if(host && (strlen(host) < e->namelen)) {
58     strcpy(e->name, host);
59     e->includeSubDomains = FALSE;
60     strcpy(e->expire, expire);
61     fprintf(stderr, "add '%s'\n", host);
62   }
63   else
64     return CURLSTS_DONE;
65   return CURLSTS_OK;
66 }
67 
68 /* verify error from callback */
hstsreadfail(CURL * easy,struct curl_hstsentry * e,void * userp)69 static CURLSTScode hstsreadfail(CURL *easy, struct curl_hstsentry *e,
70                                 void *userp)
71 {
72   (void)easy;
73   (void)e;
74   (void)userp;
75   return CURLSTS_FAIL;
76 }
77 
78 /* check that we get the hosts back in the save */
hstswrite(CURL * easy,struct curl_hstsentry * e,struct curl_index * i,void * userp)79 static CURLSTScode hstswrite(CURL *easy, struct curl_hstsentry *e,
80                              struct curl_index *i, void *userp)
81 {
82   (void)easy;
83   (void)userp;
84   printf("[%zu/%zu] %s %s\n", i->index, i->total, e->name, e->expire);
85   return CURLSTS_OK;
86 }
87 
88 /*
89  * Read/write HSTS cache entries via callback.
90  */
91 
test(char * URL)92 int test(char *URL)
93 {
94   CURLcode ret = CURLE_OK;
95   CURL *hnd;
96   struct state st = {0};
97 
98   curl_global_init(CURL_GLOBAL_ALL);
99 
100   hnd = curl_easy_init();
101   if(hnd) {
102     curl_easy_setopt(hnd, CURLOPT_URL, URL);
103     curl_easy_setopt(hnd, CURLOPT_HSTSREADFUNCTION, hstsread);
104     curl_easy_setopt(hnd, CURLOPT_HSTSREADDATA, &st);
105     curl_easy_setopt(hnd, CURLOPT_HSTSWRITEFUNCTION, hstswrite);
106     curl_easy_setopt(hnd, CURLOPT_HSTSWRITEDATA, &st);
107     curl_easy_setopt(hnd, CURLOPT_HSTS_CTRL, CURLHSTS_ENABLE);
108     ret = curl_easy_perform(hnd);
109     curl_easy_cleanup(hnd);
110     printf("First request returned %d\n", (int)ret);
111   }
112   hnd = curl_easy_init();
113   if(hnd) {
114     curl_easy_setopt(hnd, CURLOPT_URL, URL);
115     curl_easy_setopt(hnd, CURLOPT_HSTSREADFUNCTION, hstsreadfail);
116     curl_easy_setopt(hnd, CURLOPT_HSTSREADDATA, &st);
117     curl_easy_setopt(hnd, CURLOPT_HSTSWRITEFUNCTION, hstswrite);
118     curl_easy_setopt(hnd, CURLOPT_HSTSWRITEDATA, &st);
119     curl_easy_setopt(hnd, CURLOPT_HSTS_CTRL, CURLHSTS_ENABLE);
120     ret = curl_easy_perform(hnd);
121     curl_easy_cleanup(hnd);
122     printf("Second request returned %d\n", (int)ret);
123   }
124   curl_global_cleanup();
125   return (int)ret;
126 }
127