Skip to content

Commit

Permalink
Merge branch 'js/https-proxy-config' into jch
Browse files Browse the repository at this point in the history
A handful of options to configure SSL when talking to proxies have
been added.

* js/https-proxy-config:
  http: add environment variable support for HTTPS proxies
  http: add client cert support for HTTPS proxies
  • Loading branch information
gitster committed Mar 18, 2020
2 parents c60393d + af02651 commit 312f09c
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 5 deletions.
21 changes: 21 additions & 0 deletions Documentation/config/http.txt
Expand Up @@ -29,6 +29,27 @@ 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. Can be overridden by the `GIT_PROXY_SSL_CERT` environment
variable.

http.proxySSLKey::
The pathname of a file that stores a private key to use to authenticate with
an HTTPS proxy. Can be overridden by the `GIT_PROXY_SSL_KEY` environment
variable.

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. Can be overriden by the `GIT_PROXY_SSL_CERT_PASSWORD_PROTECTED`
environment variable.

http.proxySSLCAInfo::
Pathname to the file containing the certificate bundle that should be used to
verify the proxy with when using an HTTPS proxy. Can be overriden by the
`GIT_PROXY_SSL_CAINFO` environment variable.

http.emptyAuth::
Attempt authentication without seeking a username or password. This
can be used to attempt GSS-Negotiate authentication without specifying
Expand Down
74 changes: 69 additions & 5 deletions http.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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)) {
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -1160,6 +1211,13 @@ void http_init(struct remote *remote, const char *url, int proactive_auth)
max_requests = DEFAULT_MAX_REQUESTS;
#endif

set_from_env(&http_proxy_ssl_cert, "GIT_PROXY_SSL_CERT");
set_from_env(&http_proxy_ssl_key, "GIT_PROXY_SSL_KEY");
set_from_env(&http_proxy_ssl_ca_info, "GIT_PROXY_SSL_CAINFO");

if (getenv("GIT_PROXY_SSL_CERT_PASSWORD_PROTECTED"))
proxy_ssl_cert_password_required = 1;

if (getenv("GIT_CURL_FTP_NO_EPSV"))
curl_ftp_no_epsv = 1;

Expand Down Expand Up @@ -1230,6 +1288,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);
}

Expand Down

0 comments on commit 312f09c

Please sign in to comment.