@@ -29,6 +29,23 @@ http.proxyAuthMethod::
* `ntlm` - NTLM authentication (compare the --ntlm option of `curl(1)`)
--
+http.proxySSLCert::
+ The pathname of a file that stores a client certificate to use to authenticate
+ with an HTTPS proxy.
+
+http.proxySSLKey::
+ The pathname of a file that stores a private key to use to authenticate with
+ an HTTPS proxy.
+
+http.proxySSLCertPasswordProtected::
+ Enable Git's password prompt for the proxy SSL certificate. Otherwise OpenSSL
+ will prompt the user, possibly many times, if the certificate or private key
+ is encrypted.
+
+http.proxySSLCAInfo::
+ Pathname to the file containing the certificate bundle that should be used to
+ verify the proxy with when using an HTTPS proxy.
+
http.emptyAuth::
Attempt authentication without seeking a username or password. This
can be used to attempt GSS-Negotiate authentication without specifying
@@ -86,6 +86,13 @@ static long curl_low_speed_time = -1;
static int curl_ftp_no_epsv;
static const char *curl_http_proxy;
static const char *http_proxy_authmethod;
+
+static const char *http_proxy_ssl_cert;
+static const char *http_proxy_ssl_key;
+static const char *http_proxy_ssl_ca_info;
+static struct credential proxy_cert_auth = CREDENTIAL_INIT;
+static int proxy_ssl_cert_password_required;
+
static struct {
const char *name;
long curlauth_param;
@@ -365,6 +372,20 @@ static int http_options(const char *var, const char *value, void *cb)
if (!strcmp("http.proxyauthmethod", var))
return git_config_string(&http_proxy_authmethod, var, value);
+ if (!strcmp("http.proxysslcert", var))
+ return git_config_string(&http_proxy_ssl_cert, var, value);
+
+ if (!strcmp("http.proxysslkey", var))
+ return git_config_string(&http_proxy_ssl_key, var, value);
+
+ if (!strcmp("http.proxysslcainfo", var))
+ return git_config_string(&http_proxy_ssl_ca_info, var, value);
+
+ if (!strcmp("http.proxysslcertpasswordprotected", var)) {
+ proxy_ssl_cert_password_required = git_config_bool(var, value);
+ return 0;
+ }
+
if (!strcmp("http.cookiefile", var))
return git_config_pathname(&curl_cookie_file, var, value);
if (!strcmp("http.savecookies", var)) {
@@ -565,6 +586,21 @@ static int has_cert_password(void)
return 1;
}
+#if LIBCURL_VERSION_NUM >= 0x073400
+static int has_proxy_cert_password(void)
+{
+ if (http_proxy_ssl_cert == NULL || proxy_ssl_cert_password_required != 1)
+ return 0;
+ if (!proxy_cert_auth.password) {
+ proxy_cert_auth.protocol = xstrdup("cert");
+ proxy_cert_auth.username = xstrdup("");
+ proxy_cert_auth.path = xstrdup(http_proxy_ssl_cert);
+ credential_fill(&proxy_cert_auth);
+ }
+ return 1;
+}
+#endif
+
#if LIBCURL_VERSION_NUM >= 0x071900
static void set_curl_keepalive(CURL *c)
{
@@ -924,8 +960,14 @@ static CURL *get_curl_handle(void)
#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);
+ } else if (ssl_cainfo != NULL || http_proxy_ssl_ca_info != NULL) {
+ if (ssl_cainfo != NULL)
+ curl_easy_setopt(result, CURLOPT_CAINFO, ssl_cainfo);
+#if LIBCURL_VERSION_NUM >= 0x073400
+ if (http_proxy_ssl_ca_info != NULL)
+ curl_easy_setopt(result, CURLOPT_PROXY_CAINFO, http_proxy_ssl_ca_info);
+#endif
+ }
if (curl_low_speed_limit > 0 && curl_low_speed_time > 0) {
curl_easy_setopt(result, CURLOPT_LOW_SPEED_LIMIT,
@@ -1018,9 +1060,18 @@ static CURL *get_curl_handle(void)
CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);
#endif
#if LIBCURL_VERSION_NUM >= 0x073400
- else if (starts_with(curl_http_proxy, "https"))
- curl_easy_setopt(result,
- CURLOPT_PROXYTYPE, CURLPROXY_HTTPS);
+ else if (starts_with(curl_http_proxy, "https")) {
+ curl_easy_setopt(result, CURLOPT_PROXYTYPE, CURLPROXY_HTTPS);
+
+ if (http_proxy_ssl_cert)
+ curl_easy_setopt(result, CURLOPT_PROXY_SSLCERT, http_proxy_ssl_cert);
+
+ if (http_proxy_ssl_key)
+ curl_easy_setopt(result, CURLOPT_PROXY_SSLKEY, http_proxy_ssl_key);
+
+ if (has_proxy_cert_password())
+ curl_easy_setopt(result, CURLOPT_PROXY_KEYPASSWD, proxy_cert_auth.password);
+ }
#endif
if (strstr(curl_http_proxy, "://"))
credential_from_url(&proxy_auth, curl_http_proxy);
@@ -1230,6 +1281,12 @@ void http_cleanup(void)
}
ssl_cert_password_required = 0;
+ if (proxy_cert_auth.password != NULL) {
+ memset(proxy_cert_auth.password, 0, strlen(proxy_cert_auth.password));
+ FREE_AND_NULL(proxy_cert_auth.password);
+ }
+ proxy_ssl_cert_password_required = 0;
+
FREE_AND_NULL(cached_accept_language);
}