From d71ff2b9db566b3f4b2eb29441c2df86715d4339 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 8 Mar 2021 08:30:32 +0100 Subject: [PATCH] hsts: enable by default No longer considered experimental. Closes #6700 --- CMakeLists.txt | 3 +++ configure.ac | 57 ++++++++++++++++++++++++++----------------- docs/CURL-DISABLE.md | 4 +++ docs/EXPERIMENTAL.md | 1 - lib/curl_get_line.c | 4 +-- lib/easy.c | 2 +- lib/hsts.c | 19 ++++++++++----- lib/hsts.h | 8 +++--- lib/http.c | 2 +- lib/setopt.c | 2 +- lib/url.c | 2 +- lib/urldata.h | 4 +-- lib/version.c | 2 +- tests/data/test493 | 1 + tests/unit/unit1660.c | 2 +- 15 files changed, 69 insertions(+), 44 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3a20028ba..02474e29c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -210,6 +210,8 @@ endif() option(CURL_DISABLE_ALTSVC "to disable alt-svc support" OFF) mark_as_advanced(CURL_DISABLE_ALTSVC) +option(CURL_DISABLE_HSTS "to disable HSTS support" OFF) +mark_as_advanced(CURL_DISABLE_HSTS) option(CURL_DISABLE_COOKIES "to disable cookies support" OFF) mark_as_advanced(CURL_DISABLE_COOKIES) option(CURL_DISABLE_CRYPTO_AUTH "to disable cryptographic authentication" OFF) @@ -1371,6 +1373,7 @@ _add_if("Largefile" (SIZEOF_CURL_OFF_T GREATER 4) AND _add_if("SSPI" USE_WINDOWS_SSPI) _add_if("GSS-API" HAVE_GSSAPI) _add_if("alt-svc" NOT CURL_DISABLE_ALTSVC) +_add_if("HSTS" NOT CURL_DISABLE_HSTS) # TODO SSP1 missing for SPNEGO _add_if("SPNEGO" NOT CURL_DISABLE_CRYPTO_AUTH AND (HAVE_GSSAPI OR USE_WINDOWS_SSPI)) diff --git a/configure.ac b/configure.ac index 2a00aea2b..5da2ac37c 100755 --- a/configure.ac +++ b/configure.ac @@ -165,13 +165,15 @@ curl_verbose_msg="enabled (--disable-verbose)" curl_rtmp_msg="no (--with-librtmp)" curl_mtlnk_msg="no (--with-libmetalink)" curl_psl_msg="no (--with-libpsl)" - curl_altsvc_msg="enabled"; + curl_altsvc_msg="enabled (--disable-alt-svc)" + curl_hsts_msg="enabled (--disable-hsts)" ssl_backends= curl_h1_msg="enabled (internal)" curl_h2_msg="no (--with-nghttp2, --with-hyper)" curl_h3_msg="no (--with-ngtcp2, --with-quiche)" enable_altsvc="yes" +enable_hsts="yes" dnl dnl Save some initial values the user might have provided @@ -395,9 +397,12 @@ AS_HELP_STRING([--disable-http],[Disable HTTP support]), AC_SUBST(CURL_DISABLE_RTSP, [1]) dnl toggle off alt-svc too when HTTP is disabled AC_DEFINE(CURL_DISABLE_ALTSVC, 1, [disable alt-svc]) + AC_DEFINE(CURL_DISABLE_HSTS, 1, [disable HSTS]) curl_h1_msg="no (--enable-http, --with-hyper)" curl_altsvc_msg="no"; + curl_hsts_msg="no (--enable-hsts)"; enable_altsvc="no" + enable_hsts="no" ;; *) AC_MSG_RESULT(yes) ;; @@ -5071,29 +5076,34 @@ AS_HELP_STRING([--disable-alt-svc],[Disable alt-svc support]), AC_MSG_RESULT(no) ) -dnl ************************************************************ -dnl switch on/off hsts -dnl -curl_hsts_msg="no (--enable-hsts)"; -AC_MSG_CHECKING([whether to support HSTS]) -AC_ARG_ENABLE(hsts, -AS_HELP_STRING([--enable-hsts],[Enable HSTS support]) -AS_HELP_STRING([--disable-hsts],[Disable HSTS support]), -[ case "$enableval" in - no) - AC_MSG_RESULT(no) - ;; - *) AC_MSG_RESULT(yes) - curl_hsts_msg="enabled"; - enable_hsts="yes" - ;; - esac ], - AC_MSG_RESULT(no) -) +dnl only check for HSTS if there's SSL present +if test -n "$SSL_ENABLED"; then -if test "$enable_hsts" = "yes"; then - AC_DEFINE(USE_HSTS, 1, [to enable HSTS]) - experimental="$experimental HSTS" + dnl ************************************************************ + dnl switch on/off hsts + dnl + AC_MSG_CHECKING([whether to support HSTS]) + AC_ARG_ENABLE(hsts, + AS_HELP_STRING([--enable-hsts],[Enable HSTS support]) + AS_HELP_STRING([--disable-hsts],[Disable HSTS support]), + [ case "$enableval" in + no) + AC_MSG_RESULT(no) + enable_hsts="no" + ;; + *) AC_MSG_RESULT(yes) + ;; + esac ], + AC_MSG_RESULT(no) + ) +else + AC_MSG_NOTICE([disables HSTS due to lack of SSL]) + enable_hsts="no" +fi + +if test "x$enable_hsts" != "xyes"; then + curl_hsts_msg="no (--enable-hsts)"; + AC_DEFINE(CURL_DISABLE_HSTS, 1, [disable alt-svc]) fi dnl ************************************************************* @@ -5480,6 +5490,7 @@ AC_MSG_NOTICE([Configured to build curl/libcurl: Metalink: ${curl_mtlnk_msg} PSL: ${curl_psl_msg} Alt-svc: ${curl_altsvc_msg} + HSTS: ${curl_hsts_msg} HTTP1: ${curl_h1_msg} HTTP2: ${curl_h2_msg} HTTP3: ${curl_h3_msg} diff --git a/docs/CURL-DISABLE.md b/docs/CURL-DISABLE.md index 6f703a3d9..3aa9608f8 100644 --- a/docs/CURL-DISABLE.md +++ b/docs/CURL-DISABLE.md @@ -37,6 +37,10 @@ about existing options to `curl_easy_setopt`. Disable the GOPHER protocol. +## CURL_DISABLE_HSTS + +Disable the HTTP Strict Transport Security support. + ## CURL_DISABLE_HTTP Disable the HTTP(S) protocols. Note that this then also disable HTTP proxy diff --git a/docs/EXPERIMENTAL.md b/docs/EXPERIMENTAL.md index 6a84f5e17..ce9a1b8e8 100644 --- a/docs/EXPERIMENTAL.md +++ b/docs/EXPERIMENTAL.md @@ -21,4 +21,3 @@ Experimental support in curl means: - The Hyper HTTP backend - HTTP/3 support and options - CURLSSLOPT_NATIVE_CA (No configure option, feature built in when supported) - - HSTS support and options diff --git a/lib/curl_get_line.c b/lib/curl_get_line.c index 438ede704..8f3b0bd8c 100644 --- a/lib/curl_get_line.c +++ b/lib/curl_get_line.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -23,7 +23,7 @@ #include "curl_setup.h" #if !defined(CURL_DISABLE_COOKIES) || !defined(CURL_DISABLE_ALTSVC) || \ - defined(USE_HSTS) + !defined(CURL_DISABLE_HSTS) #include "curl_get_line.h" #include "curl_memory.h" diff --git a/lib/easy.c b/lib/easy.c index 4ce1bbf63..460668191 100644 --- a/lib/easy.c +++ b/lib/easy.c @@ -895,7 +895,7 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data) (void)Curl_altsvc_load(outcurl->asi, outcurl->set.str[STRING_ALTSVC]); } #endif -#ifdef USE_HSTS +#ifndef CURL_DISABLE_HSTS if(data->hsts) { outcurl->hsts = Curl_hsts_init(); if(!outcurl->hsts) diff --git a/lib/hsts.c b/lib/hsts.c index fd4926f36..ef166f196 100644 --- a/lib/hsts.c +++ b/lib/hsts.c @@ -25,7 +25,7 @@ */ #include "curl_setup.h" -#if !defined(CURL_DISABLE_HTTP) && defined(USE_HSTS) +#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_HSTS) #include #include "urldata.h" #include "llist.h" @@ -37,6 +37,7 @@ #include "parsedate.h" #include "rand.h" #include "rename.h" +#include "strtoofft.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" @@ -58,7 +59,10 @@ static time_t debugtime(void *unused) char *timestr = getenv("CURL_TIME"); (void)unused; if(timestr) { - unsigned long val = strtol(timestr, NULL, 10) + deltatime; + curl_off_t val; + (void)curlx_strtoofft(timestr, NULL, 10, &val); + + val += (curl_off_t)deltatime; return (time_t)val; } return time(NULL); @@ -274,7 +278,7 @@ static CURLcode hsts_push(struct Curl_easy *data, e.namelen = strlen(sts->host); e.includeSubDomains = sts->includeSubDomains; - result = Curl_gmtime(sts->expires, &stamp); + result = Curl_gmtime((time_t)sts->expires, &stamp); if(result) return result; @@ -294,7 +298,7 @@ static CURLcode hsts_push(struct Curl_easy *data, static CURLcode hsts_out(struct stsentry *sts, FILE *fp) { struct tm stamp; - CURLcode result = Curl_gmtime(sts->expires, &stamp); + CURLcode result = Curl_gmtime((time_t)sts->expires, &stamp); if(result) return result; @@ -439,7 +443,10 @@ static CURLcode hsts_pull(struct Curl_easy *data, struct hsts *h) expires = Curl_getdate_capped(e.expire); else expires = TIME_T_MAX; /* the end of time */ - result = hsts_create(h, e.name, e.includeSubDomains, expires); + result = hsts_create(h, e.name, + /* bitfield to bool conversion: */ + e.includeSubDomains ? TRUE : FALSE, + expires); if(result) return result; } @@ -517,4 +524,4 @@ CURLcode Curl_hsts_loadcb(struct Curl_easy *data, struct hsts *h) return hsts_pull(data, h); } -#endif /* CURL_DISABLE_HTTP || USE_HSTS */ +#endif /* CURL_DISABLE_HTTP || CURL_DISABLE_HSTS */ diff --git a/lib/hsts.h b/lib/hsts.h index ae5db74a2..baa582864 100644 --- a/lib/hsts.h +++ b/lib/hsts.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 2020, Daniel Stenberg, , et al. + * Copyright (C) 2020 - 2021, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -23,7 +23,7 @@ ***************************************************************************/ #include "curl_setup.h" -#if !defined(CURL_DISABLE_HTTP) && defined(USE_HSTS) +#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_HSTS) #include #include "llist.h" @@ -35,7 +35,7 @@ struct stsentry { struct Curl_llist_element node; const char *host; bool includeSubDomains; - time_t expires; /* the timestamp of this entry's expiry */ + curl_off_t expires; /* the timestamp of this entry's expiry */ }; /* The HSTS cache. Needs to be able to tailmatch host names. */ @@ -61,5 +61,5 @@ CURLcode Curl_hsts_loadcb(struct Curl_easy *data, #define Curl_hsts_cleanup(x) #define Curl_hsts_loadcb(x,y) #define Curl_hsts_save(x,y,z) -#endif /* CURL_DISABLE_HTTP || USE_HSTS */ +#endif /* CURL_DISABLE_HTTP || CURL_DISABLE_HSTS */ #endif /* HEADER_CURL_HSTS_H */ diff --git a/lib/http.c b/lib/http.c index 02c81c419..3cb21760d 100644 --- a/lib/http.c +++ b/lib/http.c @@ -3618,7 +3618,7 @@ CURLcode Curl_http_header(struct Curl_easy *data, struct connectdata *conn, } } -#ifdef USE_HSTS +#ifndef CURL_DISABLE_HSTS /* If enabled, the header is incoming and this is over HTTPS */ else if(data->hsts && checkprefix("Strict-Transport-Security:", headp) && (conn->handler->flags & PROTOPT_SSL)) { diff --git a/lib/setopt.c b/lib/setopt.c index 53b30da35..55360cba1 100644 --- a/lib/setopt.c +++ b/lib/setopt.c @@ -2911,7 +2911,7 @@ CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) data->set.trailer_data = va_arg(param, void *); #endif break; -#ifdef USE_HSTS +#ifndef CURL_DISABLE_HSTS case CURLOPT_HSTSREADFUNCTION: data->set.hsts_read = va_arg(param, curl_hstsread_callback); break; diff --git a/lib/url.c b/lib/url.c index 19fcfb842..949e380aa 100644 --- a/lib/url.c +++ b/lib/url.c @@ -1944,7 +1944,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data, return CURLE_OUT_OF_MEMORY; } -#ifdef USE_HSTS +#ifndef CURL_DISABLE_HSTS if(data->hsts && strcasecompare("http", data->state.up.scheme)) { if(Curl_hsts(data->hsts, data->state.up.hostname, TRUE)) { char *url; diff --git a/lib/urldata.h b/lib/urldata.h index fec875652..b7b17e30c 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -1664,7 +1664,7 @@ struct UserDefined { curl_conv_callback convtonetwork; /* function to convert from UTF-8 encoding: */ curl_conv_callback convfromutf8; -#ifdef USE_HSTS +#ifndef CURL_DISABLE_HSTS curl_hstsread_callback hsts_read; void *hsts_read_userp; curl_hstswrite_callback hsts_write; @@ -1926,7 +1926,7 @@ struct Curl_easy { NOTE that the 'cookie' field in the UserDefined struct defines if the "engine" is to be used or not. */ -#ifdef USE_HSTS +#ifndef CURL_DISABLE_HSTS struct hsts *hsts; #endif #ifndef CURL_DISABLE_ALTSVC diff --git a/lib/version.c b/lib/version.c index b33f2fe83..d2c86baac 100644 --- a/lib/version.c +++ b/lib/version.c @@ -436,7 +436,7 @@ static curl_version_info_data version_info = { #ifndef CURL_DISABLE_ALTSVC | CURL_VERSION_ALTSVC #endif -#if defined(USE_HSTS) +#ifndef CURL_DISABLE_HSTS | CURL_VERSION_HSTS #endif #if defined(USE_GSASL) diff --git a/tests/data/test493 b/tests/data/test493 index bb0b5dee7..1dd498f0d 100644 --- a/tests/data/test493 +++ b/tests/data/test493 @@ -27,6 +27,7 @@ http HSTS +proxy diff --git a/tests/unit/unit1660.c b/tests/unit/unit1660.c index cc2451932..43efa24b3 100644 --- a/tests/unit/unit1660.c +++ b/tests/unit/unit1660.c @@ -36,7 +36,7 @@ unit_stop(void) curl_global_cleanup(); } -#if defined(CURL_DISABLE_HTTP) || !defined(USE_HSTS) +#if defined(CURL_DISABLE_HTTP) || defined(CURL_DISABLE_HSTS) UNITTEST_START { return 0; /* nothing to do when HTTP or HSTS are disabled */