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