113498266Sopenharmony_ci/*************************************************************************** 213498266Sopenharmony_ci * _ _ ____ _ 313498266Sopenharmony_ci * Project ___| | | | _ \| | 413498266Sopenharmony_ci * / __| | | | |_) | | 513498266Sopenharmony_ci * | (__| |_| | _ <| |___ 613498266Sopenharmony_ci * \___|\___/|_| \_\_____| 713498266Sopenharmony_ci * 813498266Sopenharmony_ci * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 913498266Sopenharmony_ci * 1013498266Sopenharmony_ci * This software is licensed as described in the file COPYING, which 1113498266Sopenharmony_ci * you should have received as part of this distribution. The terms 1213498266Sopenharmony_ci * are also available at https://curl.se/docs/copyright.html. 1313498266Sopenharmony_ci * 1413498266Sopenharmony_ci * You may opt to use, copy, modify, merge, publish, distribute and/or sell 1513498266Sopenharmony_ci * copies of the Software, and permit persons to whom the Software is 1613498266Sopenharmony_ci * furnished to do so, under the terms of the COPYING file. 1713498266Sopenharmony_ci * 1813498266Sopenharmony_ci * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 1913498266Sopenharmony_ci * KIND, either express or implied. 2013498266Sopenharmony_ci * 2113498266Sopenharmony_ci * SPDX-License-Identifier: curl 2213498266Sopenharmony_ci * 2313498266Sopenharmony_ci ***************************************************************************/ 2413498266Sopenharmony_ci#include "curlcheck.h" 2513498266Sopenharmony_ci 2613498266Sopenharmony_ci#include "urldata.h" 2713498266Sopenharmony_ci#include "hsts.h" 2813498266Sopenharmony_ci 2913498266Sopenharmony_cistatic CURLcode 3013498266Sopenharmony_ciunit_setup(void) 3113498266Sopenharmony_ci{ 3213498266Sopenharmony_ci return CURLE_OK; 3313498266Sopenharmony_ci} 3413498266Sopenharmony_ci 3513498266Sopenharmony_cistatic void 3613498266Sopenharmony_ciunit_stop(void) 3713498266Sopenharmony_ci{ 3813498266Sopenharmony_ci curl_global_cleanup(); 3913498266Sopenharmony_ci} 4013498266Sopenharmony_ci 4113498266Sopenharmony_ci#if defined(CURL_DISABLE_HTTP) || defined(CURL_DISABLE_HSTS) 4213498266Sopenharmony_ciUNITTEST_START 4313498266Sopenharmony_ci{ 4413498266Sopenharmony_ci return 0; /* nothing to do when HTTP or HSTS are disabled */ 4513498266Sopenharmony_ci} 4613498266Sopenharmony_ciUNITTEST_STOP 4713498266Sopenharmony_ci#else 4813498266Sopenharmony_ci 4913498266Sopenharmony_cistruct testit { 5013498266Sopenharmony_ci const char *host; 5113498266Sopenharmony_ci const char *chost; /* if non-NULL, use to lookup with */ 5213498266Sopenharmony_ci const char *hdr; /* if NULL, just do the lookup */ 5313498266Sopenharmony_ci const CURLcode result; /* parse result */ 5413498266Sopenharmony_ci}; 5513498266Sopenharmony_ci 5613498266Sopenharmony_cistatic const struct testit headers[] = { 5713498266Sopenharmony_ci /* two entries read from disk cache, verify first */ 5813498266Sopenharmony_ci { "-", "readfrom.example", NULL, CURLE_OK}, 5913498266Sopenharmony_ci { "-", "old.example", NULL, CURLE_OK}, 6013498266Sopenharmony_ci /* delete the remaining one read from disk */ 6113498266Sopenharmony_ci { "readfrom.example", NULL, "max-age=\"0\"", CURLE_OK}, 6213498266Sopenharmony_ci 6313498266Sopenharmony_ci { "example.com", NULL, "max-age=\"31536000\"\r\n", CURLE_OK }, 6413498266Sopenharmony_ci { "example.com", NULL, "max-age=\"21536000\"\r\n", CURLE_OK }, 6513498266Sopenharmony_ci { "example.com", NULL, "max-age=\"21536000\"; \r\n", CURLE_OK }, 6613498266Sopenharmony_ci { "example.com", NULL, "max-age=\"21536000\"; includeSubDomains\r\n", 6713498266Sopenharmony_ci CURLE_OK }, 6813498266Sopenharmony_ci { "example.org", NULL, "max-age=\"31536000\"\r\n", CURLE_OK }, 6913498266Sopenharmony_ci { "this.example", NULL, "max=\"31536\";", CURLE_BAD_FUNCTION_ARGUMENT }, 7013498266Sopenharmony_ci { "this.example", NULL, "max-age=\"31536", CURLE_BAD_FUNCTION_ARGUMENT }, 7113498266Sopenharmony_ci { "this.example", NULL, "max-age=31536\"", CURLE_OK }, 7213498266Sopenharmony_ci /* max-age=0 removes the entry */ 7313498266Sopenharmony_ci { "this.example", NULL, "max-age=0", CURLE_OK }, 7413498266Sopenharmony_ci { "another.example", NULL, "includeSubDomains; ", 7513498266Sopenharmony_ci CURLE_BAD_FUNCTION_ARGUMENT }, 7613498266Sopenharmony_ci 7713498266Sopenharmony_ci /* Two max-age is illegal */ 7813498266Sopenharmony_ci { "example.com", NULL, 7913498266Sopenharmony_ci "max-age=\"21536000\"; includeSubDomains; max-age=\"3\";", 8013498266Sopenharmony_ci CURLE_BAD_FUNCTION_ARGUMENT }, 8113498266Sopenharmony_ci /* Two includeSubDomains is illegal */ 8213498266Sopenharmony_ci { "2.example.com", NULL, 8313498266Sopenharmony_ci "max-age=\"21536000\"; includeSubDomains; includeSubDomains;", 8413498266Sopenharmony_ci CURLE_BAD_FUNCTION_ARGUMENT }, 8513498266Sopenharmony_ci /* use a unknown directive "include" that should be ignored */ 8613498266Sopenharmony_ci { "3.example.com", NULL, "max-age=\"21536000\"; include; includeSubDomains;", 8713498266Sopenharmony_ci CURLE_OK }, 8813498266Sopenharmony_ci /* remove the "3.example.com" one, should still match the example.com */ 8913498266Sopenharmony_ci { "3.example.com", NULL, "max-age=\"0\"; includeSubDomains;", 9013498266Sopenharmony_ci CURLE_OK }, 9113498266Sopenharmony_ci { "-", "foo.example.com", NULL, CURLE_OK}, 9213498266Sopenharmony_ci { "-", "foo.xample.com", NULL, CURLE_OK}, 9313498266Sopenharmony_ci 9413498266Sopenharmony_ci /* should not match */ 9513498266Sopenharmony_ci { "example.net", "forexample.net", "max-age=\"31536000\"\r\n", CURLE_OK }, 9613498266Sopenharmony_ci 9713498266Sopenharmony_ci /* should not match either, since forexample.net is not in the example.net 9813498266Sopenharmony_ci domain */ 9913498266Sopenharmony_ci { "example.net", "forexample.net", 10013498266Sopenharmony_ci "max-age=\"31536000\"; includeSubDomains\r\n", CURLE_OK }, 10113498266Sopenharmony_ci /* remove example.net again */ 10213498266Sopenharmony_ci { "example.net", NULL, "max-age=\"0\"; includeSubDomains\r\n", CURLE_OK }, 10313498266Sopenharmony_ci 10413498266Sopenharmony_ci /* make this live for 7 seconds */ 10513498266Sopenharmony_ci { "expire.example", NULL, "max-age=\"7\"\r\n", CURLE_OK }, 10613498266Sopenharmony_ci { NULL, NULL, NULL, CURLE_OK } 10713498266Sopenharmony_ci}; 10813498266Sopenharmony_ci 10913498266Sopenharmony_cistatic void showsts(struct stsentry *e, const char *chost) 11013498266Sopenharmony_ci{ 11113498266Sopenharmony_ci if(!e) 11213498266Sopenharmony_ci printf("'%s' is not HSTS\n", chost); 11313498266Sopenharmony_ci else { 11413498266Sopenharmony_ci printf("%s [%s]: %" CURL_FORMAT_CURL_OFF_T "%s\n", 11513498266Sopenharmony_ci chost, e->host, e->expires, 11613498266Sopenharmony_ci e->includeSubDomains ? " includeSubDomains" : ""); 11713498266Sopenharmony_ci } 11813498266Sopenharmony_ci} 11913498266Sopenharmony_ci 12013498266Sopenharmony_ciUNITTEST_START 12113498266Sopenharmony_ci CURLcode result; 12213498266Sopenharmony_ci struct stsentry *e; 12313498266Sopenharmony_ci struct hsts *h = Curl_hsts_init(); 12413498266Sopenharmony_ci int i; 12513498266Sopenharmony_ci const char *chost; 12613498266Sopenharmony_ci CURL *easy; 12713498266Sopenharmony_ci char savename[256]; 12813498266Sopenharmony_ci 12913498266Sopenharmony_ci abort_unless(h, "Curl_hsts_init()"); 13013498266Sopenharmony_ci 13113498266Sopenharmony_ci curl_global_init(CURL_GLOBAL_ALL); 13213498266Sopenharmony_ci easy = curl_easy_init(); 13313498266Sopenharmony_ci if(!easy) { 13413498266Sopenharmony_ci Curl_hsts_cleanup(&h); 13513498266Sopenharmony_ci curl_global_cleanup(); 13613498266Sopenharmony_ci abort_unless(easy, "curl_easy_init()"); 13713498266Sopenharmony_ci } 13813498266Sopenharmony_ci 13913498266Sopenharmony_ci Curl_hsts_loadfile(easy, h, arg); 14013498266Sopenharmony_ci 14113498266Sopenharmony_ci for(i = 0; headers[i].host ; i++) { 14213498266Sopenharmony_ci if(headers[i].hdr) { 14313498266Sopenharmony_ci result = Curl_hsts_parse(h, headers[i].host, headers[i].hdr); 14413498266Sopenharmony_ci 14513498266Sopenharmony_ci if(result != headers[i].result) { 14613498266Sopenharmony_ci fprintf(stderr, "Curl_hsts_parse(%s) failed: %d\n", 14713498266Sopenharmony_ci headers[i].hdr, result); 14813498266Sopenharmony_ci unitfail++; 14913498266Sopenharmony_ci continue; 15013498266Sopenharmony_ci } 15113498266Sopenharmony_ci else if(result) { 15213498266Sopenharmony_ci printf("Input %u: error %d\n", i, (int) result); 15313498266Sopenharmony_ci continue; 15413498266Sopenharmony_ci } 15513498266Sopenharmony_ci } 15613498266Sopenharmony_ci 15713498266Sopenharmony_ci chost = headers[i].chost ? headers[i].chost : headers[i].host; 15813498266Sopenharmony_ci e = Curl_hsts(h, chost, TRUE); 15913498266Sopenharmony_ci showsts(e, chost); 16013498266Sopenharmony_ci } 16113498266Sopenharmony_ci 16213498266Sopenharmony_ci printf("Number of entries: %zu\n", h->list.size); 16313498266Sopenharmony_ci 16413498266Sopenharmony_ci /* verify that it is exists for 7 seconds */ 16513498266Sopenharmony_ci chost = "expire.example"; 16613498266Sopenharmony_ci for(i = 100; i < 110; i++) { 16713498266Sopenharmony_ci e = Curl_hsts(h, chost, TRUE); 16813498266Sopenharmony_ci showsts(e, chost); 16913498266Sopenharmony_ci deltatime++; /* another second passed */ 17013498266Sopenharmony_ci } 17113498266Sopenharmony_ci 17213498266Sopenharmony_ci msnprintf(savename, sizeof(savename), "%s.save", arg); 17313498266Sopenharmony_ci (void)Curl_hsts_save(easy, h, savename); 17413498266Sopenharmony_ci Curl_hsts_cleanup(&h); 17513498266Sopenharmony_ci curl_easy_cleanup(easy); 17613498266Sopenharmony_ci curl_global_cleanup(); 17713498266Sopenharmony_ci 17813498266Sopenharmony_ciUNITTEST_STOP 17913498266Sopenharmony_ci#endif 180