Merge branch 'gg/http-ssl-verify-status' into seen

The HTTP transport has been taught to check the revocation status of
the server certificate using the stapled OCSP response during the
TLS handshake via a new 'http.sslVerifyStatus' configuration
variable.

* gg/http-ssl-verify-status:
  http: add http.sslVerifyStatus to check stapled OCSP responses
seen
Junio C Hamano 2026-08-31 13:53:28 -07:00
commit 9e37624e34
3 changed files with 57 additions and 0 deletions

View File

@ -196,6 +196,20 @@ http.sslVerify::
over HTTPS. Defaults to true. Can be overridden by the over HTTPS. Defaults to true. Can be overridden by the
`GIT_SSL_NO_VERIFY` environment variable. `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:: http.sslCert::
File containing the SSL certificate when fetching or pushing File containing the SSL certificate when fetching or pushing
over HTTPS. Can be overridden by the `GIT_SSL_CERT` environment over HTTPS. Can be overridden by the `GIT_SSL_CERT` environment

14
http.c
View File

@ -44,6 +44,7 @@ static CURL *curl_default;
char curl_errorstr[CURL_ERROR_SIZE]; char curl_errorstr[CURL_ERROR_SIZE];


static int curl_ssl_verify = -1; static int curl_ssl_verify = -1;
static int curl_ssl_verify_status;
static int curl_ssl_try; static int curl_ssl_try;
static char *curl_http_version; static char *curl_http_version;
static char *ssl_cert; 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); curl_ssl_verify = git_config_bool(var, value);
return 0; return 0;
} }
if (!strcmp("http.sslverifystatus", var)) {
curl_ssl_verify_status = git_config_bool(var, value);
return 0;
}
if (!strcmp("http.sslcipherlist", var)) if (!strcmp("http.sslcipherlist", var))
return git_config_string(&ssl_cipherlist, var, value); return git_config_string(&ssl_cipherlist, var, value);
if (!strcmp("http.sslversion", var)) if (!strcmp("http.sslversion", var))
@ -1133,6 +1138,15 @@ static CURL *get_curl_handle(void)
curl_easy_setopt(result, CURLOPT_SSL_VERIFYHOST, 2L); 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) { if (curl_http_version) {
long opt; long opt;
if (!get_curl_http_version_opt(curl_http_version, &opt)) { if (!get_curl_http_version_opt(curl_http_version, &opt)) {

View File

@ -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 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, # here user%40host is the URL-encoded version of user@host,
# which is our intentionally-odd username to catch parsing errors # which is our intentionally-odd username to catch parsing errors
url_user=$HTTPD_URL_USER/auth/smart/repo.git url_user=$HTTPD_URL_USER/auth/smart/repo.git