Skip to content

Commit 3e67999

Browse files
dschojamill
authored andcommitted
Merge branch 'http-ssl-backend'
This topic branch brings support for choosing cURL's SSL backend at runtime via http.sslBackend, based on patches already submitted to the cURL project and backported to cURL 7.54.1 as used in Git for Windows' SDK. Signed-off-by: Johannes Schindelin <[email protected]>
2 parents 224963a + 2f992d4 commit 3e67999

File tree

2 files changed

+91
-1
lines changed

2 files changed

+91
-1
lines changed

Documentation/config.txt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2257,6 +2257,27 @@ http.sslCAPath::
22572257
with when fetching or pushing over HTTPS. Can be overridden
22582258
by the `GIT_SSL_CAPATH` environment variable.
22592259

2260+
http.sslBackend::
2261+
Name of the SSL backend to use (e.g. "openssl" or "schannel").
2262+
This option is ignored if cURL lacks support for choosing the SSL
2263+
backend at runtime.
2264+
2265+
http.schannelCheckRevoke::
2266+
Used to enforce or disable certificate revocation checks in cURL
2267+
when http.sslBackend is set to "schannel". Defaults to `true` if
2268+
unset. Only necessary to disable this if Git consistently errors
2269+
and the message is about checking the revocation status of a
2270+
certificate. This option is ignored if cURL lacks support for
2271+
setting the relevant SSL option at runtime.
2272+
2273+
http.schannelUseSSLCAInfo::
2274+
As of cURL v7.60.0, the Secure Channel backend can use the
2275+
certificate bundle provided via `http.sslCAInfo`, but that would
2276+
override the Windows Certificate Store. Since this is not desirable
2277+
by default, Git will tell cURL not to use that bundle by default
2278+
when the `schannel` backend was configured via `http.sslBackend`,
2279+
unless `http.schannelUseSSLCAInfo` overrides this behavior.
2280+
22602281
http.pinnedpubkey::
22612282
Public key of the https service. It may either be the filename of
22622283
a PEM or DER encoded public key file or a string starting with

http.c

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,16 @@ static struct active_request_slot *active_queue_head;
155155

156156
static char *cached_accept_language;
157157

158+
static char *http_ssl_backend;
159+
160+
static int http_schannel_check_revoke = 1;
161+
/*
162+
* With the backend being set to `schannel`, setting sslCAinfo would override
163+
* the Certificate Store in cURL v7.60.0 and later, which is not what we want
164+
* by default.
165+
*/
166+
static int http_schannel_use_ssl_cainfo;
167+
158168
size_t fread_buffer(char *ptr, size_t eltsize, size_t nmemb, void *buffer_)
159169
{
160170
size_t size = eltsize * nmemb;
@@ -302,6 +312,22 @@ static int http_options(const char *var, const char *value, void *cb)
302312
curl_ssl_try = git_config_bool(var, value);
303313
return 0;
304314
}
315+
if (!strcmp("http.sslbackend", var)) {
316+
free(http_ssl_backend);
317+
http_ssl_backend = xstrdup_or_null(value);
318+
return 0;
319+
}
320+
321+
if (!strcmp("http.schannelcheckrevoke", var)) {
322+
http_schannel_check_revoke = git_config_bool(var, value);
323+
return 0;
324+
}
325+
326+
if (!strcmp("http.schannelusesslcainfo", var)) {
327+
http_schannel_use_ssl_cainfo = git_config_bool(var, value);
328+
return 0;
329+
}
330+
305331
if (!strcmp("http.minsessions", var)) {
306332
min_curl_sessions = git_config_int(var, value);
307333
#ifndef USE_CURL_MULTI
@@ -803,6 +829,16 @@ static CURL *get_curl_handle(void)
803829
}
804830
#endif
805831

832+
if (http_ssl_backend && !strcmp("schannel", http_ssl_backend) &&
833+
!http_schannel_check_revoke) {
834+
#if LIBCURL_VERSION_NUM >= 0x072c00
835+
curl_easy_setopt(result, CURLOPT_SSL_OPTIONS, CURLSSLOPT_NO_REVOKE);
836+
#else
837+
warning("CURLSSLOPT_NO_REVOKE not applied to curl SSL options because\n"
838+
"your curl version is too old (>= 7.44.0)");
839+
#endif
840+
}
841+
806842
if (http_proactive_auth)
807843
init_curl_http_auth(result);
808844

@@ -844,7 +880,13 @@ static CURL *get_curl_handle(void)
844880
if (ssl_pinnedkey != NULL)
845881
curl_easy_setopt(result, CURLOPT_PINNEDPUBLICKEY, ssl_pinnedkey);
846882
#endif
847-
if (ssl_cainfo != NULL)
883+
if (http_ssl_backend && !strcmp("schannel", http_ssl_backend) &&
884+
!http_schannel_use_ssl_cainfo) {
885+
curl_easy_setopt(result, CURLOPT_CAINFO, NULL);
886+
#if LIBCURL_VERSION_NUM >= 0x073400
887+
curl_easy_setopt(result, CURLOPT_PROXY_CAINFO, NULL);
888+
#endif
889+
} else if (ssl_cainfo != NULL)
848890
curl_easy_setopt(result, CURLOPT_CAINFO, ssl_cainfo);
849891

850892
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)
9951037
git_config(urlmatch_config_entry, &config);
9961038
free(normalized_url);
9971039

1040+
#if LIBCURL_VERSION_NUM >= 0x073800
1041+
if (http_ssl_backend) {
1042+
const curl_ssl_backend **backends;
1043+
struct strbuf buf = STRBUF_INIT;
1044+
int i;
1045+
1046+
switch (curl_global_sslset(-1, http_ssl_backend, &backends)) {
1047+
case CURLSSLSET_UNKNOWN_BACKEND:
1048+
strbuf_addf(&buf, _("Unsupported SSL backend '%s'. "
1049+
"Supported SSL backends:"),
1050+
http_ssl_backend);
1051+
for (i = 0; backends[i]; i++)
1052+
strbuf_addf(&buf, "\n\t%s", backends[i]->name);
1053+
die("%s", buf.buf);
1054+
case CURLSSLSET_NO_BACKENDS:
1055+
die(_("Could not set SSL backend to '%s': "
1056+
"cURL was built without SSL backends"),
1057+
http_ssl_backend);
1058+
case CURLSSLSET_TOO_LATE:
1059+
die(_("Could not set SSL backend to '%s': already set"),
1060+
http_ssl_backend);
1061+
case CURLSSLSET_OK:
1062+
break; /* Okay! */
1063+
}
1064+
}
1065+
#endif
1066+
9981067
if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK)
9991068
die("curl_global_init failed");
10001069

0 commit comments

Comments
 (0)