xref: /aosp_15_r20/external/curl/tests/unit/unit1660.c (revision 6236dae45794135f37c4eb022389c904c8b0090d)
1*6236dae4SAndroid Build Coastguard Worker /***************************************************************************
2*6236dae4SAndroid Build Coastguard Worker  *                                  _   _ ____  _
3*6236dae4SAndroid Build Coastguard Worker  *  Project                     ___| | | |  _ \| |
4*6236dae4SAndroid Build Coastguard Worker  *                             / __| | | | |_) | |
5*6236dae4SAndroid Build Coastguard Worker  *                            | (__| |_| |  _ <| |___
6*6236dae4SAndroid Build Coastguard Worker  *                             \___|\___/|_| \_\_____|
7*6236dae4SAndroid Build Coastguard Worker  *
8*6236dae4SAndroid Build Coastguard Worker  * Copyright (C) Daniel Stenberg, <[email protected]>, et al.
9*6236dae4SAndroid Build Coastguard Worker  *
10*6236dae4SAndroid Build Coastguard Worker  * This software is licensed as described in the file COPYING, which
11*6236dae4SAndroid Build Coastguard Worker  * you should have received as part of this distribution. The terms
12*6236dae4SAndroid Build Coastguard Worker  * are also available at https://curl.se/docs/copyright.html.
13*6236dae4SAndroid Build Coastguard Worker  *
14*6236dae4SAndroid Build Coastguard Worker  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15*6236dae4SAndroid Build Coastguard Worker  * copies of the Software, and permit persons to whom the Software is
16*6236dae4SAndroid Build Coastguard Worker  * furnished to do so, under the terms of the COPYING file.
17*6236dae4SAndroid Build Coastguard Worker  *
18*6236dae4SAndroid Build Coastguard Worker  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19*6236dae4SAndroid Build Coastguard Worker  * KIND, either express or implied.
20*6236dae4SAndroid Build Coastguard Worker  *
21*6236dae4SAndroid Build Coastguard Worker  * SPDX-License-Identifier: curl
22*6236dae4SAndroid Build Coastguard Worker  *
23*6236dae4SAndroid Build Coastguard Worker  ***************************************************************************/
24*6236dae4SAndroid Build Coastguard Worker #include "curlcheck.h"
25*6236dae4SAndroid Build Coastguard Worker 
26*6236dae4SAndroid Build Coastguard Worker #include "urldata.h"
27*6236dae4SAndroid Build Coastguard Worker #include "hsts.h"
28*6236dae4SAndroid Build Coastguard Worker 
29*6236dae4SAndroid Build Coastguard Worker static CURLcode
unit_setup(void)30*6236dae4SAndroid Build Coastguard Worker unit_setup(void)
31*6236dae4SAndroid Build Coastguard Worker {
32*6236dae4SAndroid Build Coastguard Worker   return CURLE_OK;
33*6236dae4SAndroid Build Coastguard Worker }
34*6236dae4SAndroid Build Coastguard Worker 
35*6236dae4SAndroid Build Coastguard Worker static void
unit_stop(void)36*6236dae4SAndroid Build Coastguard Worker unit_stop(void)
37*6236dae4SAndroid Build Coastguard Worker {
38*6236dae4SAndroid Build Coastguard Worker   curl_global_cleanup();
39*6236dae4SAndroid Build Coastguard Worker }
40*6236dae4SAndroid Build Coastguard Worker 
41*6236dae4SAndroid Build Coastguard Worker #if defined(CURL_DISABLE_HTTP) || defined(CURL_DISABLE_HSTS)
42*6236dae4SAndroid Build Coastguard Worker UNITTEST_START
43*6236dae4SAndroid Build Coastguard Worker {
44*6236dae4SAndroid Build Coastguard Worker   puts("nothing to do when HTTP or HSTS are disabled");
45*6236dae4SAndroid Build Coastguard Worker }
46*6236dae4SAndroid Build Coastguard Worker UNITTEST_STOP
47*6236dae4SAndroid Build Coastguard Worker #else
48*6236dae4SAndroid Build Coastguard Worker 
49*6236dae4SAndroid Build Coastguard Worker struct testit {
50*6236dae4SAndroid Build Coastguard Worker   const char *host;
51*6236dae4SAndroid Build Coastguard Worker   const char *chost; /* if non-NULL, use to lookup with */
52*6236dae4SAndroid Build Coastguard Worker   const char *hdr; /* if NULL, just do the lookup */
53*6236dae4SAndroid Build Coastguard Worker   const CURLcode result; /* parse result */
54*6236dae4SAndroid Build Coastguard Worker };
55*6236dae4SAndroid Build Coastguard Worker 
56*6236dae4SAndroid Build Coastguard Worker static const struct testit headers[] = {
57*6236dae4SAndroid Build Coastguard Worker   /* two entries read from disk cache, verify first */
58*6236dae4SAndroid Build Coastguard Worker   { "-", "readfrom.example", NULL, CURLE_OK},
59*6236dae4SAndroid Build Coastguard Worker   { "-", "old.example", NULL, CURLE_OK},
60*6236dae4SAndroid Build Coastguard Worker   /* delete the remaining one read from disk */
61*6236dae4SAndroid Build Coastguard Worker   { "readfrom.example", NULL, "max-age=\"0\"", CURLE_OK},
62*6236dae4SAndroid Build Coastguard Worker 
63*6236dae4SAndroid Build Coastguard Worker   { "example.com", NULL, "max-age=\"31536000\"\r\n", CURLE_OK },
64*6236dae4SAndroid Build Coastguard Worker   { "example.com", NULL, "max-age=\"21536000\"\r\n", CURLE_OK },
65*6236dae4SAndroid Build Coastguard Worker   { "example.com", NULL, "max-age=\"21536000\"; \r\n", CURLE_OK },
66*6236dae4SAndroid Build Coastguard Worker   { "example.com", NULL, "max-age=\"21536000\"; includeSubDomains\r\n",
67*6236dae4SAndroid Build Coastguard Worker     CURLE_OK },
68*6236dae4SAndroid Build Coastguard Worker   { "example.org", NULL, "max-age=\"31536000\"\r\n", CURLE_OK },
69*6236dae4SAndroid Build Coastguard Worker   { "this.example", NULL, "max=\"31536\";", CURLE_BAD_FUNCTION_ARGUMENT },
70*6236dae4SAndroid Build Coastguard Worker   { "this.example", NULL, "max-age=\"31536", CURLE_BAD_FUNCTION_ARGUMENT },
71*6236dae4SAndroid Build Coastguard Worker   { "this.example", NULL, "max-age=31536\"", CURLE_OK },
72*6236dae4SAndroid Build Coastguard Worker   /* max-age=0 removes the entry */
73*6236dae4SAndroid Build Coastguard Worker   { "this.example", NULL, "max-age=0", CURLE_OK },
74*6236dae4SAndroid Build Coastguard Worker   { "another.example", NULL, "includeSubDomains; ",
75*6236dae4SAndroid Build Coastguard Worker     CURLE_BAD_FUNCTION_ARGUMENT },
76*6236dae4SAndroid Build Coastguard Worker 
77*6236dae4SAndroid Build Coastguard Worker   /* Two max-age is illegal */
78*6236dae4SAndroid Build Coastguard Worker   { "example.com", NULL,
79*6236dae4SAndroid Build Coastguard Worker     "max-age=\"21536000\"; includeSubDomains; max-age=\"3\";",
80*6236dae4SAndroid Build Coastguard Worker     CURLE_BAD_FUNCTION_ARGUMENT },
81*6236dae4SAndroid Build Coastguard Worker   /* Two includeSubDomains is illegal */
82*6236dae4SAndroid Build Coastguard Worker   { "2.example.com", NULL,
83*6236dae4SAndroid Build Coastguard Worker     "max-age=\"21536000\"; includeSubDomains; includeSubDomains;",
84*6236dae4SAndroid Build Coastguard Worker     CURLE_BAD_FUNCTION_ARGUMENT },
85*6236dae4SAndroid Build Coastguard Worker   /* use a unknown directive "include" that should be ignored */
86*6236dae4SAndroid Build Coastguard Worker   { "3.example.com", NULL, "max-age=\"21536000\"; include; includeSubDomains;",
87*6236dae4SAndroid Build Coastguard Worker     CURLE_OK },
88*6236dae4SAndroid Build Coastguard Worker   /* remove the "3.example.com" one, should still match the example.com */
89*6236dae4SAndroid Build Coastguard Worker   { "3.example.com", NULL, "max-age=\"0\"; includeSubDomains;",
90*6236dae4SAndroid Build Coastguard Worker     CURLE_OK },
91*6236dae4SAndroid Build Coastguard Worker   { "-", "foo.example.com", NULL, CURLE_OK},
92*6236dae4SAndroid Build Coastguard Worker   { "-", "foo.xample.com", NULL, CURLE_OK},
93*6236dae4SAndroid Build Coastguard Worker 
94*6236dae4SAndroid Build Coastguard Worker   /* should not match */
95*6236dae4SAndroid Build Coastguard Worker   { "example.net", "forexample.net", "max-age=\"31536000\"\r\n", CURLE_OK },
96*6236dae4SAndroid Build Coastguard Worker 
97*6236dae4SAndroid Build Coastguard Worker   /* should not match either, since forexample.net is not in the example.net
98*6236dae4SAndroid Build Coastguard Worker      domain */
99*6236dae4SAndroid Build Coastguard Worker   { "example.net", "forexample.net",
100*6236dae4SAndroid Build Coastguard Worker     "max-age=\"31536000\"; includeSubDomains\r\n", CURLE_OK },
101*6236dae4SAndroid Build Coastguard Worker   /* remove example.net again */
102*6236dae4SAndroid Build Coastguard Worker   { "example.net", NULL, "max-age=\"0\"; includeSubDomains\r\n", CURLE_OK },
103*6236dae4SAndroid Build Coastguard Worker 
104*6236dae4SAndroid Build Coastguard Worker   /* make this live for 7 seconds */
105*6236dae4SAndroid Build Coastguard Worker   { "expire.example", NULL, "max-age=\"7\"\r\n", CURLE_OK },
106*6236dae4SAndroid Build Coastguard Worker   { NULL, NULL, NULL, CURLE_OK }
107*6236dae4SAndroid Build Coastguard Worker };
108*6236dae4SAndroid Build Coastguard Worker 
109*6236dae4SAndroid Build Coastguard Worker static void showsts(struct stsentry *e, const char *chost)
110*6236dae4SAndroid Build Coastguard Worker {
111*6236dae4SAndroid Build Coastguard Worker   if(!e)
112*6236dae4SAndroid Build Coastguard Worker     printf("'%s' is not HSTS\n", chost);
113*6236dae4SAndroid Build Coastguard Worker   else {
114*6236dae4SAndroid Build Coastguard Worker     printf("%s [%s]: %" CURL_FORMAT_CURL_OFF_T "%s\n",
115*6236dae4SAndroid Build Coastguard Worker            chost, e->host, e->expires,
116*6236dae4SAndroid Build Coastguard Worker            e->includeSubDomains ? " includeSubDomains" : "");
117*6236dae4SAndroid Build Coastguard Worker   }
118*6236dae4SAndroid Build Coastguard Worker }
119*6236dae4SAndroid Build Coastguard Worker 
120*6236dae4SAndroid Build Coastguard Worker UNITTEST_START
121*6236dae4SAndroid Build Coastguard Worker {
122*6236dae4SAndroid Build Coastguard Worker   CURLcode result;
123*6236dae4SAndroid Build Coastguard Worker   struct stsentry *e;
124*6236dae4SAndroid Build Coastguard Worker   struct hsts *h = Curl_hsts_init();
125*6236dae4SAndroid Build Coastguard Worker   int i;
126*6236dae4SAndroid Build Coastguard Worker   const char *chost;
127*6236dae4SAndroid Build Coastguard Worker   CURL *easy;
128*6236dae4SAndroid Build Coastguard Worker   char savename[256];
129*6236dae4SAndroid Build Coastguard Worker 
130*6236dae4SAndroid Build Coastguard Worker   abort_unless(h, "Curl_hsts_init()");
131*6236dae4SAndroid Build Coastguard Worker 
132*6236dae4SAndroid Build Coastguard Worker   curl_global_init(CURL_GLOBAL_ALL);
133*6236dae4SAndroid Build Coastguard Worker   easy = curl_easy_init();
134*6236dae4SAndroid Build Coastguard Worker   if(!easy) {
135*6236dae4SAndroid Build Coastguard Worker     Curl_hsts_cleanup(&h);
136*6236dae4SAndroid Build Coastguard Worker     curl_global_cleanup();
137*6236dae4SAndroid Build Coastguard Worker     abort_unless(easy, "curl_easy_init()");
138*6236dae4SAndroid Build Coastguard Worker   }
139*6236dae4SAndroid Build Coastguard Worker 
140*6236dae4SAndroid Build Coastguard Worker   Curl_hsts_loadfile(easy, h, arg);
141*6236dae4SAndroid Build Coastguard Worker 
142*6236dae4SAndroid Build Coastguard Worker   for(i = 0; headers[i].host ; i++) {
143*6236dae4SAndroid Build Coastguard Worker     if(headers[i].hdr) {
144*6236dae4SAndroid Build Coastguard Worker       result = Curl_hsts_parse(h, headers[i].host, headers[i].hdr);
145*6236dae4SAndroid Build Coastguard Worker 
146*6236dae4SAndroid Build Coastguard Worker       if(result != headers[i].result) {
147*6236dae4SAndroid Build Coastguard Worker         fprintf(stderr, "Curl_hsts_parse(%s) failed: %d\n",
148*6236dae4SAndroid Build Coastguard Worker                 headers[i].hdr, result);
149*6236dae4SAndroid Build Coastguard Worker         unitfail++;
150*6236dae4SAndroid Build Coastguard Worker         continue;
151*6236dae4SAndroid Build Coastguard Worker       }
152*6236dae4SAndroid Build Coastguard Worker       else if(result) {
153*6236dae4SAndroid Build Coastguard Worker         printf("Input %u: error %d\n", i, (int) result);
154*6236dae4SAndroid Build Coastguard Worker         continue;
155*6236dae4SAndroid Build Coastguard Worker       }
156*6236dae4SAndroid Build Coastguard Worker     }
157*6236dae4SAndroid Build Coastguard Worker 
158*6236dae4SAndroid Build Coastguard Worker     chost = headers[i].chost ? headers[i].chost : headers[i].host;
159*6236dae4SAndroid Build Coastguard Worker     e = Curl_hsts(h, chost, TRUE);
160*6236dae4SAndroid Build Coastguard Worker     showsts(e, chost);
161*6236dae4SAndroid Build Coastguard Worker   }
162*6236dae4SAndroid Build Coastguard Worker 
163*6236dae4SAndroid Build Coastguard Worker   printf("Number of entries: %zu\n", Curl_llist_count(&h->list));
164*6236dae4SAndroid Build Coastguard Worker 
165*6236dae4SAndroid Build Coastguard Worker   /* verify that it is exists for 7 seconds */
166*6236dae4SAndroid Build Coastguard Worker   chost = "expire.example";
167*6236dae4SAndroid Build Coastguard Worker   for(i = 100; i < 110; i++) {
168*6236dae4SAndroid Build Coastguard Worker     e = Curl_hsts(h, chost, TRUE);
169*6236dae4SAndroid Build Coastguard Worker     showsts(e, chost);
170*6236dae4SAndroid Build Coastguard Worker     deltatime++; /* another second passed */
171*6236dae4SAndroid Build Coastguard Worker   }
172*6236dae4SAndroid Build Coastguard Worker 
173*6236dae4SAndroid Build Coastguard Worker   msnprintf(savename, sizeof(savename), "%s.save", arg);
174*6236dae4SAndroid Build Coastguard Worker   (void)Curl_hsts_save(easy, h, savename);
175*6236dae4SAndroid Build Coastguard Worker   Curl_hsts_cleanup(&h);
176*6236dae4SAndroid Build Coastguard Worker   curl_easy_cleanup(easy);
177*6236dae4SAndroid Build Coastguard Worker   curl_global_cleanup();
178*6236dae4SAndroid Build Coastguard Worker }
179*6236dae4SAndroid Build Coastguard Worker UNITTEST_STOP
180*6236dae4SAndroid Build Coastguard Worker #endif
181