summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/config.txt21
-rw-r--r--http.c71
2 files changed, 91 insertions, 1 deletions
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 09e95e9e98..41a9ff2b6a 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -2003,6 +2003,27 @@ http.sslCAPath::
with when fetching or pushing over HTTPS. Can be overridden
by the `GIT_SSL_CAPATH` environment variable.
+http.sslBackend::
+ Name of the SSL backend to use (e.g. "openssl" or "schannel").
+ This option is ignored if cURL lacks support for choosing the SSL
+ backend at runtime.
+
+http.schannelCheckRevoke::
+ Used to enforce or disable certificate revocation checks in cURL
+ when http.sslBackend is set to "schannel". Defaults to `true` if
+ unset. Only necessary to disable this if Git consistently errors
+ and the message is about checking the revocation status of a
+ certificate. This option is ignored if cURL lacks support for
+ setting the relevant SSL option at runtime.
+
+http.schannelUseSSLCAInfo::
+ As of cURL v7.60.0, the Secure Channel backend can use the
+ certificate bundle provided via `http.sslCAInfo`, but that would
+ override the Windows Certificate Store. Since this is not desirable
+ by default, Git will tell cURL not to use that bundle by default
+ when the `schannel` backend was configured via `http.sslBackend`,
+ unless `http.schannelUseSSLCAInfo` overrides this behavior.
+
http.pinnedpubkey::
Public key of the https service. It may either be the filename of
a PEM or DER encoded public key file or a string starting with
diff --git a/http.c b/http.c
index 98ff122585..28009ca73a 100644
--- a/http.c
+++ b/http.c
@@ -155,6 +155,16 @@ static struct active_request_slot *active_queue_head;
static char *cached_accept_language;
+static char *http_ssl_backend;
+
+static int http_schannel_check_revoke = 1;
+/*
+ * With the backend being set to `schannel`, setting sslCAinfo would override
+ * the Certificate Store in cURL v7.60.0 and later, which is not what we want
+ * by default.
+ */
+static int http_schannel_use_ssl_cainfo;
+
size_t fread_buffer(char *ptr, size_t eltsize, size_t nmemb, void *buffer_)
{
size_t size = eltsize * nmemb;
@@ -302,6 +312,22 @@ static int http_options(const char *var, const char *value, void *cb)
curl_ssl_try = git_config_bool(var, value);
return 0;
}
+ if (!strcmp("http.sslbackend", var)) {
+ free(http_ssl_backend);
+ http_ssl_backend = xstrdup_or_null(value);
+ return 0;
+ }
+
+ if (!strcmp("http.schannelcheckrevoke", var)) {
+ http_schannel_check_revoke = git_config_bool(var, value);
+ return 0;
+ }
+
+ if (!strcmp("http.schannelusesslcainfo", var)) {
+ http_schannel_use_ssl_cainfo = git_config_bool(var, value);
+ return 0;
+ }
+
if (!strcmp("http.minsessions", var)) {
min_curl_sessions = git_config_int(var, value);
#ifndef USE_CURL_MULTI
@@ -803,6 +829,16 @@ static CURL *get_curl_handle(void)
}
#endif
+ if (http_ssl_backend && !strcmp("schannel", http_ssl_backend) &&
+ !http_schannel_check_revoke) {
+#if LIBCURL_VERSION_NUM >= 0x072c00
+ curl_easy_setopt(result, CURLOPT_SSL_OPTIONS, CURLSSLOPT_NO_REVOKE);
+#else
+ warning("CURLSSLOPT_NO_REVOKE not applied to curl SSL options because\n"
+ "your curl version is too old (< 7.44.0)");
+#endif
+ }
+
if (http_proactive_auth)
init_curl_http_auth(result);
@@ -844,7 +880,13 @@ static CURL *get_curl_handle(void)
if (ssl_pinnedkey != NULL)
curl_easy_setopt(result, CURLOPT_PINNEDPUBLICKEY, ssl_pinnedkey);
#endif
- if (ssl_cainfo != NULL)
+ if (http_ssl_backend && !strcmp("schannel", http_ssl_backend) &&
+ !http_schannel_use_ssl_cainfo) {
+ curl_easy_setopt(result, CURLOPT_CAINFO, NULL);
+#if LIBCURL_VERSION_NUM >= 0x073400
+ curl_easy_setopt(result, CURLOPT_PROXY_CAINFO, NULL);
+#endif
+ } else if (ssl_cainfo != NULL)
curl_easy_setopt(result, CURLOPT_CAINFO, ssl_cainfo);
if (curl_low_speed_limit > 0 && curl_low_speed_time > 0) {
@@ -995,6 +1037,33 @@ void http_init(struct remote *remote, const char *url, int proactive_auth)
git_config(urlmatch_config_entry, &config);
free(normalized_url);
+#if LIBCURL_VERSION_NUM >= 0x073800
+ if (http_ssl_backend) {
+ const curl_ssl_backend **backends;
+ struct strbuf buf = STRBUF_INIT;
+ int i;
+
+ switch (curl_global_sslset(-1, http_ssl_backend, &backends)) {
+ case CURLSSLSET_UNKNOWN_BACKEND:
+ strbuf_addf(&buf, _("Unsupported SSL backend '%s'. "
+ "Supported SSL backends:"),
+ http_ssl_backend);
+ for (i = 0; backends[i]; i++)
+ strbuf_addf(&buf, "\n\t%s", backends[i]->name);
+ die("%s", buf.buf);
+ case CURLSSLSET_NO_BACKENDS:
+ die(_("Could not set SSL backend to '%s': "
+ "cURL was built without SSL backends"),
+ http_ssl_backend);
+ case CURLSSLSET_TOO_LATE:
+ die(_("Could not set SSL backend to '%s': already set"),
+ http_ssl_backend);
+ case CURLSSLSET_OK:
+ break; /* Okay! */
+ }
+ }
+#endif
+
if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK)
die("curl_global_init failed");