提交 ef976395 编写于 作者: K Knut Franke 提交者: Junio C Hamano

http: allow selection of proxy authentication method

CURLAUTH_ANY does not work with proxies which answer unauthenticated requests
with a 307 redirect to an error page instead of a 407 listing supported
authentication methods. Therefore, allow the authentication method to be set
using the environment variable GIT_HTTP_PROXY_AUTHMETHOD or configuration
variables http.proxyAuthmethod and remote.<name>.proxyAuthmethod (in analogy
to http.proxy and remote.<name>.proxy).

The following values are supported:

* anyauth (default)
* basic
* digest
* negotiate
* ntlm
Signed-off-by: NKnut Franke <k.franke@science-computing.de>
Signed-off-by: NElia Pinto <gitter.spiros@gmail.com>
Helped-by: NJunio C Hamano <gitster@pobox.com>
Helped-by: NEric Sunshine <sunshine@sunshineco.com>
Helped-by: NElia Pinto <gitter.spiros@gmail.com>
Signed-off-by: NJunio C Hamano <gitster@pobox.com>
上级 75488425
...@@ -1600,6 +1600,27 @@ http.proxy:: ...@@ -1600,6 +1600,27 @@ http.proxy::
`curl(1)`). This can be overridden on a per-remote basis; see `curl(1)`). This can be overridden on a per-remote basis; see
remote.<name>.proxy remote.<name>.proxy
http.proxyAuthMethod::
Set the method with which to authenticate against the HTTP proxy. This
only takes effect if the configured proxy string contains a user name part
(i.e. is of the form 'user@host' or 'user@host:port'). This can be
overridden on a per-remote basis; see `remote.<name>.proxyAuthMethod`.
Both can be overridden by the 'GIT_HTTP_PROXY_AUTHMETHOD' environment
variable. Possible values are:
+
--
* `anyauth` - Automatically pick a suitable authentication method. It is
assumed that the proxy answers an unauthenticated request with a 407
status code and one or more Proxy-authenticate headers with supported
authentication methods. This is the default.
* `basic` - HTTP Basic authentication
* `digest` - HTTP Digest authentication; this prevents the password from being
transmitted to the proxy in clear text
* `negotiate` - GSS-Negotiate authentication (compare the --negotiate option
of `curl(1)`)
* `ntlm` - NTLM authentication (compare the --ntlm option of `curl(1)`)
--
http.cookieFile:: http.cookieFile::
File containing previously stored cookie lines which should be used File containing previously stored cookie lines which should be used
in the Git http session, if they match the server. The file format in the Git http session, if they match the server. The file format
...@@ -2407,6 +2428,11 @@ remote.<name>.proxy:: ...@@ -2407,6 +2428,11 @@ remote.<name>.proxy::
the proxy to use for that remote. Set to the empty string to the proxy to use for that remote. Set to the empty string to
disable proxying for that remote. disable proxying for that remote.
remote.<name>.proxyAuthMethod::
For remotes that require curl (http, https and ftp), the method to use for
authenticating against the proxy in use (probably set in
`remote.<name>.proxy`). See `http.proxyAuthMethod`.
remote.<name>.fetch:: remote.<name>.fetch::
The default set of "refspec" for linkgit:git-fetch[1]. See The default set of "refspec" for linkgit:git-fetch[1]. See
linkgit:git-fetch[1]. linkgit:git-fetch[1].
......
...@@ -51,6 +51,10 @@ struct remote ...@@ -51,6 +51,10 @@ struct remote
The proxy to use for curl (http, https, ftp, etc.) URLs. The proxy to use for curl (http, https, ftp, etc.) URLs.
`http_proxy_authmethod`::
The method used for authenticating against `http_proxy`.
struct remotes can be found by name with remote_get(), and iterated struct remotes can be found by name with remote_get(), and iterated
through with for_each_remote(). remote_get(NULL) will return the through with for_each_remote(). remote_get(NULL) will return the
default remote, given the current branch and configuration. default remote, given the current branch and configuration.
......
...@@ -62,6 +62,24 @@ static long curl_low_speed_limit = -1; ...@@ -62,6 +62,24 @@ static long curl_low_speed_limit = -1;
static long curl_low_speed_time = -1; static long curl_low_speed_time = -1;
static int curl_ftp_no_epsv; static int curl_ftp_no_epsv;
static const char *curl_http_proxy; static const char *curl_http_proxy;
static const char *http_proxy_authmethod;
static struct {
const char *name;
long curlauth_param;
} proxy_authmethods[] = {
{ "basic", CURLAUTH_BASIC },
{ "digest", CURLAUTH_DIGEST },
{ "negotiate", CURLAUTH_GSSNEGOTIATE },
{ "ntlm", CURLAUTH_NTLM },
#ifdef LIBCURL_CAN_HANDLE_AUTH_ANY
{ "anyauth", CURLAUTH_ANY },
#endif
/*
* CURLAUTH_DIGEST_IE has no corresponding command-line option in
* curl(1) and is not included in CURLAUTH_ANY, so we leave it out
* here, too
*/
};
static const char *curl_cookie_file; static const char *curl_cookie_file;
static int curl_save_cookies; static int curl_save_cookies;
struct credential http_auth = CREDENTIAL_INIT; struct credential http_auth = CREDENTIAL_INIT;
...@@ -256,6 +274,9 @@ static int http_options(const char *var, const char *value, void *cb) ...@@ -256,6 +274,9 @@ static int http_options(const char *var, const char *value, void *cb)
if (!strcmp("http.proxy", var)) if (!strcmp("http.proxy", var))
return git_config_string(&curl_http_proxy, var, value); return git_config_string(&curl_http_proxy, var, value);
if (!strcmp("http.proxyauthmethod", var))
return git_config_string(&http_proxy_authmethod, var, value);
if (!strcmp("http.cookiefile", var)) if (!strcmp("http.cookiefile", var))
return git_config_string(&curl_cookie_file, var, value); return git_config_string(&curl_cookie_file, var, value);
if (!strcmp("http.savecookies", var)) { if (!strcmp("http.savecookies", var)) {
...@@ -304,6 +325,40 @@ static void init_curl_http_auth(CURL *result) ...@@ -304,6 +325,40 @@ static void init_curl_http_auth(CURL *result)
#endif #endif
} }
/* *var must be free-able */
static void var_override(const char **var, char *value)
{
if (value) {
free((void *)*var);
*var = xstrdup(value);
}
}
static void init_curl_proxy_auth(CURL *result)
{
var_override(&http_proxy_authmethod, getenv("GIT_HTTP_PROXY_AUTHMETHOD"));
#if LIBCURL_VERSION_NUM >= 0x070a07 /* CURLOPT_PROXYAUTH and CURLAUTH_ANY */
if (http_proxy_authmethod) {
int i;
for (i = 0; i < ARRAY_SIZE(proxy_authmethods); i++) {
if (!strcmp(http_proxy_authmethod, proxy_authmethods[i].name)) {
curl_easy_setopt(result, CURLOPT_PROXYAUTH,
proxy_authmethods[i].curlauth_param);
break;
}
}
if (i == ARRAY_SIZE(proxy_authmethods)) {
warning("unsupported proxy authentication method %s: using anyauth",
http_proxy_authmethod);
curl_easy_setopt(result, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
}
}
else
curl_easy_setopt(result, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
#endif
}
static int has_cert_password(void) static int has_cert_password(void)
{ {
if (ssl_cert == NULL || ssl_cert_password_required != 1) if (ssl_cert == NULL || ssl_cert_password_required != 1)
...@@ -476,9 +531,7 @@ static CURL *get_curl_handle(void) ...@@ -476,9 +531,7 @@ static CURL *get_curl_handle(void)
CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4); CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);
#endif #endif
} }
#if LIBCURL_VERSION_NUM >= 0x070a07 init_curl_proxy_auth(result);
curl_easy_setopt(result, CURLOPT_PROXYAUTH, CURLAUTH_ANY);
#endif
set_curl_keepalive(result); set_curl_keepalive(result);
...@@ -519,6 +572,9 @@ void http_init(struct remote *remote, const char *url, int proactive_auth) ...@@ -519,6 +572,9 @@ void http_init(struct remote *remote, const char *url, int proactive_auth)
if (remote && remote->http_proxy) if (remote && remote->http_proxy)
curl_http_proxy = xstrdup(remote->http_proxy); curl_http_proxy = xstrdup(remote->http_proxy);
if (remote)
var_override(&http_proxy_authmethod, remote->http_proxy_authmethod);
pragma_header = curl_slist_append(pragma_header, "Pragma: no-cache"); pragma_header = curl_slist_append(pragma_header, "Pragma: no-cache");
no_pragma_header = curl_slist_append(no_pragma_header, "Pragma:"); no_pragma_header = curl_slist_append(no_pragma_header, "Pragma:");
...@@ -617,6 +673,9 @@ void http_cleanup(void) ...@@ -617,6 +673,9 @@ void http_cleanup(void)
curl_http_proxy = NULL; curl_http_proxy = NULL;
} }
free((void *)http_proxy_authmethod);
http_proxy_authmethod = NULL;
if (cert_auth.password != NULL) { if (cert_auth.password != NULL) {
memset(cert_auth.password, 0, strlen(cert_auth.password)); memset(cert_auth.password, 0, strlen(cert_auth.password));
free(cert_auth.password); free(cert_auth.password);
......
...@@ -428,6 +428,9 @@ static int handle_config(const char *key, const char *value, void *cb) ...@@ -428,6 +428,9 @@ static int handle_config(const char *key, const char *value, void *cb)
} else if (!strcmp(subkey, ".proxy")) { } else if (!strcmp(subkey, ".proxy")) {
return git_config_string((const char **)&remote->http_proxy, return git_config_string((const char **)&remote->http_proxy,
key, value); key, value);
} else if (!strcmp(subkey, ".proxyauthmethod")) {
return git_config_string((const char **)&remote->http_proxy_authmethod,
key, value);
} else if (!strcmp(subkey, ".vcs")) { } else if (!strcmp(subkey, ".vcs")) {
return git_config_string(&remote->foreign_vcs, key, value); return git_config_string(&remote->foreign_vcs, key, value);
} }
......
...@@ -54,6 +54,7 @@ struct remote { ...@@ -54,6 +54,7 @@ struct remote {
* for curl remotes only * for curl remotes only
*/ */
char *http_proxy; char *http_proxy;
char *http_proxy_authmethod;
}; };
struct remote *remote_get(const char *name); struct remote *remote_get(const char *name);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册