• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "curlcheck.h"
23 
24 #include "urldata.h"
25 #include "hsts.h"
26 
27 static CURLcode
unit_setup(void)28 unit_setup(void)
29 {
30   return CURLE_OK;
31 }
32 
33 static void
unit_stop(void)34 unit_stop(void)
35 {
36   curl_global_cleanup();
37 }
38 
39 #if defined(CURL_DISABLE_HTTP) || defined(CURL_DISABLE_HSTS)
40 UNITTEST_START
41 {
42   return 0; /* nothing to do when HTTP or HSTS are disabled */
43 }
44 UNITTEST_STOP
45 #else
46 
47 struct testit {
48   const char *host;
49   const char *chost; /* if non-NULL, use to lookup with */
50   const char *hdr; /* if NULL, just do the lookup */
51   const CURLcode result; /* parse result */
52 };
53 
54 static const struct testit headers[] = {
55   /* two entries read from disk cache, verify first */
56   { "-", "readfrom.example", NULL, CURLE_OK},
57   { "-", "old.example", NULL, CURLE_OK},
58   /* delete the remaining one read from disk */
59   { "readfrom.example", NULL, "max-age=\"0\"", CURLE_OK},
60 
61   { "example.com", NULL, "max-age=\"31536000\"\r\n", CURLE_OK },
62   { "example.com", NULL, "max-age=\"21536000\"\r\n", CURLE_OK },
63   { "example.com", NULL, "max-age=\"21536000\"; \r\n", CURLE_OK },
64   { "example.com", NULL, "max-age=\"21536000\"; includeSubDomains\r\n",
65     CURLE_OK },
66   { "example.org", NULL, "max-age=\"31536000\"\r\n", CURLE_OK },
67   { "this.example", NULL, "max=\"31536\";", CURLE_BAD_FUNCTION_ARGUMENT },
68   { "this.example", NULL, "max-age=\"31536", CURLE_BAD_FUNCTION_ARGUMENT },
69   { "this.example", NULL, "max-age=31536\"", CURLE_OK },
70   /* max-age=0 removes the entry */
71   { "this.example", NULL, "max-age=0", CURLE_OK },
72   { "another.example", NULL, "includeSubDomains; ",
73     CURLE_BAD_FUNCTION_ARGUMENT },
74 
75   /* Two max-age is illegal */
76   { "example.com", NULL,
77     "max-age=\"21536000\"; includeSubDomains; max-age=\"3\";",
78     CURLE_BAD_FUNCTION_ARGUMENT },
79   /* Two includeSubDomains is illegal */
80   { "2.example.com", NULL,
81     "max-age=\"21536000\"; includeSubDomains; includeSubDomains;",
82     CURLE_BAD_FUNCTION_ARGUMENT },
83   /* use a unknown directive "include" that should be ignored */
84   { "3.example.com", NULL, "max-age=\"21536000\"; include; includeSubDomains;",
85     CURLE_OK },
86   /* remove the "3.example.com" one, should still match the example.com */
87   { "3.example.com", NULL, "max-age=\"0\"; includeSubDomains;",
88     CURLE_OK },
89   { "-", "foo.example.com", NULL, CURLE_OK},
90   { "-", "foo.xample.com", NULL, CURLE_OK},
91 
92   /* should not match */
93   { "example.net", "forexample.net", "max-age=\"31536000\"\r\n", CURLE_OK },
94 
95   /* should not match either, since forexample.net is not in the example.net
96      domain */
97   { "example.net", "forexample.net",
98     "max-age=\"31536000\"; includeSubDomains\r\n", CURLE_OK },
99   /* remove example.net again */
100   { "example.net", NULL, "max-age=\"0\"; includeSubDomains\r\n", CURLE_OK },
101 
102   /* make this live for 7 seconds */
103   { "expire.example", NULL, "max-age=\"7\"\r\n", CURLE_OK },
104   { NULL, NULL, NULL, 0 }
105 };
106 
107 static void showsts(struct stsentry *e, const char *chost)
108 {
109   if(!e)
110     printf("'%s' is not HSTS\n", chost);
111   else {
112     printf("%s [%s]: %" CURL_FORMAT_CURL_OFF_T "%s\n",
113            chost, e->host, e->expires,
114            e->includeSubDomains ? " includeSubDomains" : "");
115   }
116 }
117 
118 UNITTEST_START
119 {
120   CURLcode result;
121   struct stsentry *e;
122   struct hsts *h = Curl_hsts_init();
123   int i;
124   const char *chost;
125   CURL *easy;
126   if(!h)
127     return 1;
128 
129   curl_global_init(CURL_GLOBAL_ALL);
130   easy = curl_easy_init();
131   if(!easy) {
132     Curl_hsts_cleanup(&h);
133     curl_global_cleanup();
134     return 1;
135   }
136 
137   Curl_hsts_loadfile(easy, h, "log/input1660");
138 
139   for(i = 0; headers[i].host ; i++) {
140     if(headers[i].hdr) {
141       result = Curl_hsts_parse(h, headers[i].host, headers[i].hdr);
142 
143       if(result != headers[i].result) {
144         fprintf(stderr, "Curl_hsts_parse(%s) failed: %d\n",
145                 headers[i].hdr, result);
146         unitfail++;
147         continue;
148       }
149       else if(result) {
150         printf("Input %u: error %d\n", i, (int) result);
151         continue;
152       }
153     }
154 
155     chost = headers[i].chost ? headers[i].chost : headers[i].host;
156     e = Curl_hsts(h, chost, TRUE);
157     showsts(e, chost);
158   }
159 
160   printf("Number of entries: %zu\n", h->list.size);
161 
162   /* verify that it is exists for 7 seconds */
163   chost = "expire.example";
164   for(i = 100; i < 110; i++) {
165     e = Curl_hsts(h, chost, TRUE);
166     showsts(e, chost);
167     deltatime++; /* another second passed */
168   }
169 
170   (void)Curl_hsts_save(easy, h, "log/hsts1660");
171   Curl_hsts_cleanup(&h);
172   curl_easy_cleanup(easy);
173   curl_global_cleanup();
174   return unitfail;
175 }
176 UNITTEST_STOP
177 #endif
178