Re: [PATCH v4] http: add http.sslVerifyStatus to check stapled OCSP responses
- From
Junio C Hamano <gitster@pobox.com>
- Date
- Aug 17, 2026, 19:19 UTC
- Message-ID
- <xmqqfr0c4kss.fsf@gitster.g>
- In-Reply-To
- <20260817185242.22736-1-ggordon@gitlab.com>
graysongordon-gl <graysongordon1@gmail.com> writes:
Show 7 quoted lines
> Verified: t5551 over plain http and t5559 over https both pass all 61 > tests, with the four new ones skipping on the former and running on the > latter. > Documentation/config/http.adoc | 17 +++++++++++++++++ > http.c | 10 ++++++++++ > t/t5551-http-fetch-smart.sh | 29 +++++++++++++++++++++++++++++ > 3 files changed, 56 insertions(+)
OK, instead of adding a new test script that weighs 72-line we are testing the feature with 29-line addition, which sounds like a good economy ;-).
The code changes and the documentation haven't changed since the previous round, both looking good.
Will replace. Thanks.
Show 103 quoted lines
> diff --git a/Documentation/config/http.adoc b/Documentation/config/http.adoc
> index 792a71b413..40b849bf7f 100644
> --- a/Documentation/config/http.adoc
> +++ b/Documentation/config/http.adoc
> @@ -196,6 +196,23 @@ 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.
> ++
> +This is fail-closed: if the server staples no response, verification
> +fails. Set it per remote, e.g.
> +`http.https://example.com/.sslVerifyStatus`, rather than globally.
> ++
> +What it changes depends on the TLS backend libcurl was built against.
> +An OpenSSL-linked build ignores a stapled response unless this is set.
> +A GnuTLS-linked build consults the staple during ordinary certificate
> +verification, so it already rejects a revoked certificate under
> +`http.sslVerify` alone, and setting this to `false` does not disable
> +that. Where a backend cannot check the staple at all, git fails with an
> +error rather than continuing unchecked.
> +
> 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 caccf2108e..94f8dd817a 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,11 @@ static CURL *get_curl_handle(void)
> curl_easy_setopt(result, CURLOPT_SSL_VERIFYHOST, 2L);
> }
>
> + if (curl_ssl_verify_status &&
> + curl_easy_setopt(result, CURLOPT_SSL_VERIFYSTATUS, 1L) != CURLE_OK)
> + die(_("http.sslVerifyStatus is set, but the TLS backend of "
> + "this libcurl cannot verify certificate status"));
> +
> 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..c11e96c1ac 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 "cannot verify certificate status" 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