mirror of
https://github.com/git/git.git
synced 2026-07-01 12:21:51 +02:00
http: reject unsupported proxy URL schemes
An explicit proxy URL with an unrecognized scheme such as htpp://127.0.0.1 is currently accepted. Git parses the URL, extracts the host part, and then passes only that host to libcurl. Because no proxy type is selected for the unknown scheme, Git leaves libcurl at its default HTTP proxy type, so the typo is silently treated as an HTTP proxy. Reject proxy URLs with explicit unsupported schemes instead of silently accepting them. Keep the existing host:port-without-scheme behavior unchanged. Implement the SOCKS proxy handling with a shared table-driven mapping. Add a regression test to cover the unsupported-scheme case. Signed-off-by: Aliwoto <aminnimaj@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
@@ -744,6 +744,69 @@ static int has_proxy_cert_password(void)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct socks_proxy_type {
|
||||
const char *name;
|
||||
long curlsym;
|
||||
} socks_proxy_types[] = {
|
||||
{ "socks", CURLPROXY_SOCKS4 },
|
||||
{ "socks4", CURLPROXY_SOCKS4 },
|
||||
{ "socks4a", CURLPROXY_SOCKS4A },
|
||||
{ "socks5", CURLPROXY_SOCKS5 },
|
||||
{ "socks5h", CURLPROXY_SOCKS5_HOSTNAME },
|
||||
};
|
||||
|
||||
static const struct socks_proxy_type *find_socks_proxy_type(const char *protocol)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!protocol)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(socks_proxy_types); i++) {
|
||||
if (!strcmp(socks_proxy_types[i].name, protocol))
|
||||
return &socks_proxy_types[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int is_socks_proxy_protocol(const char *protocol)
|
||||
{
|
||||
return !!find_socks_proxy_type(protocol);
|
||||
}
|
||||
|
||||
static int set_curl_proxy_type(CURL *result, const char *protocol)
|
||||
{
|
||||
const struct socks_proxy_type *socks_proxy_type;
|
||||
|
||||
if (!protocol || !strcmp(protocol, "http"))
|
||||
return 0;
|
||||
|
||||
socks_proxy_type = find_socks_proxy_type(protocol);
|
||||
if (socks_proxy_type) {
|
||||
curl_easy_setopt(result, CURLOPT_PROXYTYPE, socks_proxy_type->curlsym);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!strcmp(protocol, "https")) {
|
||||
curl_easy_setopt(result, CURLOPT_PROXYTYPE, (long)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);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Return 1 if redactions have been made, 0 otherwise. */
|
||||
static int redact_sensitive_header(struct strbuf *header, size_t offset)
|
||||
{
|
||||
@@ -1214,30 +1277,6 @@ static CURL *get_curl_handle(void)
|
||||
} else if (curl_http_proxy) {
|
||||
struct strbuf proxy = STRBUF_INIT;
|
||||
|
||||
if (starts_with(curl_http_proxy, "socks5h"))
|
||||
curl_easy_setopt(result,
|
||||
CURLOPT_PROXYTYPE, (long)CURLPROXY_SOCKS5_HOSTNAME);
|
||||
else if (starts_with(curl_http_proxy, "socks5"))
|
||||
curl_easy_setopt(result,
|
||||
CURLOPT_PROXYTYPE, (long)CURLPROXY_SOCKS5);
|
||||
else if (starts_with(curl_http_proxy, "socks4a"))
|
||||
curl_easy_setopt(result,
|
||||
CURLOPT_PROXYTYPE, (long)CURLPROXY_SOCKS4A);
|
||||
else if (starts_with(curl_http_proxy, "socks"))
|
||||
curl_easy_setopt(result,
|
||||
CURLOPT_PROXYTYPE, (long)CURLPROXY_SOCKS4);
|
||||
else if (starts_with(curl_http_proxy, "https")) {
|
||||
curl_easy_setopt(result, CURLOPT_PROXYTYPE, (long)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);
|
||||
}
|
||||
if (strstr(curl_http_proxy, "://"))
|
||||
credential_from_url(&proxy_auth, curl_http_proxy);
|
||||
else {
|
||||
@@ -1247,6 +1286,10 @@ static CURL *get_curl_handle(void)
|
||||
strbuf_release(&url);
|
||||
}
|
||||
|
||||
if (set_curl_proxy_type(result, proxy_auth.protocol) < 0)
|
||||
die("Invalid proxy URL '%s': unsupported proxy scheme '%s'",
|
||||
curl_http_proxy, proxy_auth.protocol);
|
||||
|
||||
if (!proxy_auth.host)
|
||||
die("Invalid proxy URL '%s'", curl_http_proxy);
|
||||
|
||||
@@ -1257,7 +1300,7 @@ static CURL *get_curl_handle(void)
|
||||
if (ver->version_num < 0x075400)
|
||||
die("libcurl 7.84 or later is required to support paths in proxy URLs");
|
||||
|
||||
if (!starts_with(proxy_auth.protocol, "socks"))
|
||||
if (!is_socks_proxy_protocol(proxy_auth.protocol))
|
||||
die("Invalid proxy URL '%s': only SOCKS proxies support paths",
|
||||
curl_http_proxy);
|
||||
|
||||
|
||||
@@ -95,4 +95,10 @@ test_expect_success 'Unix socket requires localhost' - <<\EOT
|
||||
}
|
||||
EOT
|
||||
|
||||
test_expect_success 'unknown proxy scheme is rejected' '
|
||||
test_must_fail git clone -c http.proxy=htpp://127.0.0.1 \
|
||||
https://example.com/repo.git 2>err &&
|
||||
test_grep "unsupported proxy scheme '\''htpp'\''" err
|
||||
'
|
||||
|
||||
test_done
|
||||
|
||||
Reference in New Issue
Block a user