diff --git a/Documentation/config/http.adoc b/Documentation/config/http.adoc index 792a71b413..b54f627969 100644 --- a/Documentation/config/http.adoc +++ b/Documentation/config/http.adoc @@ -196,6 +196,20 @@ http.sslVerify:: over HTTPS. Defaults to true. Can be overridden by the `GIT_SSL_NO_VERIFY` environment variable. +http.sslVerifyStatus:: + Whether to check the revocation status of the server + certificate using the stapled OCSP response supplied during + the TLS handshake ("OCSP stapling"). Defaults to false, which + allows connections to servers without validating if the + certificate has been revoked by the certificate authority. + Enabling this option will prevent connections to servers that + have a certificate status other than "good" per RFC 6960. + Connections to servers that do not return a stapled response + will also be refused. ++ +Set it per remote, e.g. +`http.https://example.com/.sslVerifyStatus`, rather than globally. + http.sslCert:: File containing the SSL certificate when fetching or pushing over HTTPS. Can be overridden by the `GIT_SSL_CERT` environment diff --git a/http.c b/http.c index 510204e45f..240e7620d8 100644 --- a/http.c +++ b/http.c @@ -44,6 +44,7 @@ static CURL *curl_default; char curl_errorstr[CURL_ERROR_SIZE]; static int curl_ssl_verify = -1; +static int curl_ssl_verify_status; static int curl_ssl_try; static char *curl_http_version; static char *ssl_cert; @@ -400,6 +401,10 @@ static int http_options(const char *var, const char *value, curl_ssl_verify = git_config_bool(var, value); return 0; } + if (!strcmp("http.sslverifystatus", var)) { + curl_ssl_verify_status = git_config_bool(var, value); + return 0; + } if (!strcmp("http.sslcipherlist", var)) return git_config_string(&ssl_cipherlist, var, value); if (!strcmp("http.sslversion", var)) @@ -1133,6 +1138,15 @@ static CURL *get_curl_handle(void) curl_easy_setopt(result, CURLOPT_SSL_VERIFYHOST, 2L); } + if (curl_ssl_verify_status) { + CURLcode ret = curl_easy_setopt(result, + CURLOPT_SSL_VERIFYSTATUS, 1L); + if (ret != CURLE_OK) + die(_("http.sslVerifyStatus is set, but could not " + "enable OCSP status verification: %s"), + curl_easy_strerror(ret)); + } + if (curl_http_version) { long opt; if (!get_curl_http_version_opt(curl_http_version, &opt)) { diff --git a/t/t5551-http-fetch-smart.sh b/t/t5551-http-fetch-smart.sh index 805bec025c..75ab07f031 100755 --- a/t/t5551-http-fetch-smart.sh +++ b/t/t5551-http-fetch-smart.sh @@ -680,6 +680,35 @@ test_expect_success 'passing hostname resolution information works' ' git -c "http.curloptResolve=$BOGUS_HOST:$LIB_HTTPD_PORT:127.0.0.1" ls-remote "$BOGUS_HTTPD_URL/smart/repo.git" >/dev/null ' +test_lazy_prereq SSL_VERIFYSTATUS ' + test "$HTTPD_PROTO" = "https" && + test_might_fail git -c http.sslVerifyStatus=true \ + ls-remote "$HTTPD_URL/smart/repo.git" 2>err && + ! grep "http.sslVerifyStatus is set" err +' + +test_expect_success SSL_VERIFYSTATUS 'http.sslVerifyStatus=true fails without a staple' ' + test_must_fail git -c http.sslVerifyStatus=true \ + ls-remote "$HTTPD_URL/smart/repo.git" +' + +test_expect_success SSL_VERIFYSTATUS 'http.sslVerifyStatus=false is a no-op' ' + git -c http.sslVerifyStatus=false \ + ls-remote "$HTTPD_URL/smart/repo.git" >actual && + test_line_count -gt 0 actual +' + +test_expect_success SSL_VERIFYSTATUS 'per-URL sslVerifyStatus applies to a matching URL' ' + test_must_fail git -c "http.$HTTPD_URL/.sslVerifyStatus=true" \ + ls-remote "$HTTPD_URL/smart/repo.git" +' + +test_expect_success SSL_VERIFYSTATUS 'per-URL sslVerifyStatus is not applied to other URLs' ' + git -c "http.https://example.com/.sslVerifyStatus=true" \ + ls-remote "$HTTPD_URL/smart/repo.git" >actual && + test_line_count -gt 0 actual +' + # here user%40host is the URL-encoded version of user@host, # which is our intentionally-odd username to catch parsing errors url_user=$HTTPD_URL_USER/auth/smart/repo.git