travis-ci: switch to Xcode 10.1 macOS image
[gitweb.git] / http.c
diff --git a/http.c b/http.c
index 4162860ee316365091ac3978a83d2311682b8079..eacc2a75ef2e41da9d5f5741defcf1952e6c01a3 100644 (file)
--- 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,15 @@ 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 supported with cURL < 7.44.0"));
+#endif
+       }
+
        if (http_proactive_auth)
                init_curl_http_auth(result);
 
@@ -844,7 +879,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) {
@@ -866,8 +907,7 @@ static CURL *get_curl_handle(void)
        curl_easy_setopt(result, CURLOPT_PROTOCOLS,
                         get_curl_allowed_protocols(-1));
 #else
-       warning("protocol restrictions not applied to curl redirects because\n"
-               "your curl version is too old (>= 7.19.4)");
+       warning(_("Protocol restrictions not supported with cURL < 7.19.4"));
 #endif
        if (getenv("GIT_CURL_VERBOSE"))
                curl_easy_setopt(result, CURLOPT_VERBOSE, 1L);
@@ -995,6 +1035,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");
 
@@ -2394,7 +2461,7 @@ int finish_http_object_request(struct http_object_request *freq)
                unlink_or_warn(freq->tmpfile.buf);
                return -1;
        }
-       if (hashcmp(freq->sha1, freq->real_sha1)) {
+       if (!hasheq(freq->sha1, freq->real_sha1)) {
                unlink_or_warn(freq->tmpfile.buf);
                return -1;
        }