Unverified Commit 002b2ffe by Edward Thomson Committed by GitHub

Merge pull request #6026 from libgit2/ethomson/proxy

Update proxy configuration
parents d56b4079 3c0f14cc
......@@ -35,6 +35,46 @@ static const char *default_port_for_scheme(const char *scheme)
return NULL;
}
int git_net_url_dup(git_net_url *out, git_net_url *in)
{
if (in->scheme) {
out->scheme = git__strdup(in->scheme);
GIT_ERROR_CHECK_ALLOC(out->scheme);
}
if (in->host) {
out->host = git__strdup(in->host);
GIT_ERROR_CHECK_ALLOC(out->host);
}
if (in->port) {
out->port = git__strdup(in->port);
GIT_ERROR_CHECK_ALLOC(out->port);
}
if (in->path) {
out->path = git__strdup(in->path);
GIT_ERROR_CHECK_ALLOC(out->path);
}
if (in->query) {
out->query = git__strdup(in->query);
GIT_ERROR_CHECK_ALLOC(out->query);
}
if (in->username) {
out->username = git__strdup(in->username);
GIT_ERROR_CHECK_ALLOC(out->username);
}
if (in->password) {
out->password = git__strdup(in->password);
GIT_ERROR_CHECK_ALLOC(out->password);
}
return 0;
}
int git_net_url_parse(git_net_url *url, const char *given)
{
struct http_parser_url u = {0};
......@@ -404,6 +444,80 @@ int git_net_url_fmt_path(git_buf *buf, git_net_url *url)
return git_buf_oom(buf) ? -1 : 0;
}
static bool matches_pattern(
git_net_url *url,
const char *pattern,
size_t pattern_len)
{
const char *domain, *port = NULL, *colon;
size_t host_len, domain_len, port_len = 0, wildcard = 0;
GIT_UNUSED(url);
GIT_UNUSED(pattern);
if (!pattern_len)
return false;
else if (pattern_len == 1 && pattern[0] == '*')
return true;
else if (pattern_len > 1 && pattern[0] == '*' && pattern[1] == '.')
wildcard = 2;
else if (pattern[0] == '.')
wildcard = 1;
domain = pattern + wildcard;
domain_len = pattern_len - wildcard;
if ((colon = memchr(domain, ':', domain_len)) != NULL) {
domain_len = colon - domain;
port = colon + 1;
port_len = pattern_len - wildcard - domain_len - 1;
}
/* A pattern's port *must* match if it's specified */
if (port_len && git__strlcmp(url->port, port, port_len) != 0)
return false;
/* No wildcard? Host must match exactly. */
if (!wildcard)
return !git__strlcmp(url->host, domain, domain_len);
/* Wildcard: ensure there's (at least) a suffix match */
if ((host_len = strlen(url->host)) < domain_len ||
memcmp(url->host + (host_len - domain_len), domain, domain_len))
return false;
/* The pattern is *.domain and the host is simply domain */
if (host_len == domain_len)
return true;
/* The pattern is *.domain and the host is foo.domain */
return (url->host[host_len - domain_len - 1] == '.');
}
bool git_net_url_matches_pattern(git_net_url *url, const char *pattern)
{
return matches_pattern(url, pattern, strlen(pattern));
}
bool git_net_url_matches_pattern_list(
git_net_url *url,
const char *pattern_list)
{
const char *pattern, *pattern_end, *sep;
for (pattern = pattern_list;
pattern && *pattern;
pattern = sep ? sep + 1 : NULL) {
sep = strchr(pattern, ',');
pattern_end = sep ? sep : strchr(pattern, '\0');
if (matches_pattern(url, pattern, (pattern_end - pattern)))
return true;
}
return false;
}
void git_net_url_dispose(git_net_url *url)
{
if (url->username)
......
......@@ -21,6 +21,9 @@ typedef struct git_net_url {
#define GIT_NET_URL_INIT { NULL }
/** Duplicate a URL */
extern int git_net_url_dup(git_net_url *out, git_net_url *in);
/** Parses a string containing a URL into a structure. */
extern int git_net_url_parse(git_net_url *url, const char *str);
......@@ -54,6 +57,14 @@ extern int git_net_url_fmt(git_buf *out, git_net_url *url);
/** Place the path and query string into the given buffer. */
extern int git_net_url_fmt_path(git_buf *buf, git_net_url *url);
/** Determines if the url matches given pattern or pattern list */
extern bool git_net_url_matches_pattern(
git_net_url *url,
const char *pattern);
extern bool git_net_url_matches_pattern_list(
git_net_url *url,
const char *pattern_list);
/** Disposes the contents of the structure. */
extern void git_net_url_dispose(git_net_url *url);
......
......@@ -849,75 +849,140 @@ int git_remote_ls(const git_remote_head ***out, size_t *size, git_remote *remote
return remote->transport->ls(out, size, remote->transport);
}
int git_remote__get_http_proxy(git_remote *remote, bool use_ssl, char **proxy_url)
static int lookup_config(char **out, git_config *cfg, const char *name)
{
git_config *cfg;
git_config_entry *ce = NULL;
git_buf val = GIT_BUF_INIT;
int error;
GIT_ASSERT_ARG(remote);
if (!proxy_url || !remote->repo)
return -1;
if ((error = git_config__lookup_entry(&ce, cfg, name, false)) < 0)
return error;
*proxy_url = NULL;
if (ce && ce->value) {
*out = git__strdup(ce->value);
GIT_ERROR_CHECK_ALLOC(*out);
} else {
error = GIT_ENOTFOUND;
}
if ((error = git_repository_config__weakptr(&cfg, remote->repo)) < 0)
git_config_entry_free(ce);
return error;
}
static void url_config_trim(git_net_url *url)
{
size_t len = strlen(url->path);
if (url->path[len - 1] == '/') {
len--;
} else {
while (len && url->path[len - 1] != '/')
len--;
}
url->path[len] = '\0';
}
static int http_proxy_config(char **out, git_remote *remote, git_net_url *url)
{
git_config *cfg;
git_buf buf = GIT_BUF_INIT;
git_net_url lookup_url = GIT_NET_URL_INIT;
int error;
/* Go through the possible sources for proxy configuration, from most specific
* to least specific. */
if ((error = git_net_url_dup(&lookup_url, url)) < 0 ||
(error = git_repository_config__weakptr(&cfg, remote->repo)) < 0)
goto done;
/* remote.<name>.proxy config setting */
if (remote->name && remote->name[0]) {
git_buf buf = GIT_BUF_INIT;
git_buf_clear(&buf);
if ((error = git_buf_printf(&buf, "remote.%s.proxy", remote->name)) < 0)
return error;
if ((error = git_buf_printf(&buf, "remote.%s.proxy", remote->name)) < 0 ||
(error = lookup_config(out, cfg, buf.ptr)) != GIT_ENOTFOUND)
goto done;
}
error = git_config__lookup_entry(&ce, cfg, git_buf_cstr(&buf), false);
git_buf_dispose(&buf);
while (true) {
git_buf_clear(&buf);
if (error < 0)
return error;
if ((error = git_buf_puts(&buf, "http.")) < 0 ||
(error = git_net_url_fmt(&buf, &lookup_url)) < 0 ||
(error = git_buf_puts(&buf, ".proxy")) < 0 ||
(error = lookup_config(out, cfg, buf.ptr)) != GIT_ENOTFOUND)
goto done;
if (ce && ce->value) {
*proxy_url = git__strdup(ce->value);
goto found;
}
if (! lookup_url.path[0])
break;
url_config_trim(&lookup_url);
}
/* http.proxy config setting */
if ((error = git_config__lookup_entry(&ce, cfg, "http.proxy", false)) < 0)
git_buf_clear(&buf);
error = lookup_config(out, cfg, "http.proxy");
done:
git_buf_dispose(&buf);
git_net_url_dispose(&lookup_url);
return error;
}
if (ce && ce->value) {
*proxy_url = git__strdup(ce->value);
goto found;
}
static int http_proxy_env(char **out, git_remote *remote, git_net_url *url)
{
git_buf proxy_env = GIT_BUF_INIT, no_proxy_env = GIT_BUF_INIT;
bool use_ssl = (strcmp(url->scheme, "https") == 0);
int error;
GIT_UNUSED(remote);
/* http_proxy / https_proxy environment variables */
error = git__getenv(&val, use_ssl ? "https_proxy" : "http_proxy");
error = git__getenv(&proxy_env, use_ssl ? "https_proxy" : "http_proxy");
/* try uppercase environment variables */
if (error == GIT_ENOTFOUND)
error = git__getenv(&val, use_ssl ? "HTTPS_PROXY" : "HTTP_PROXY");
error = git__getenv(&proxy_env, use_ssl ? "HTTPS_PROXY" : "HTTP_PROXY");
if (error < 0) {
if (error == GIT_ENOTFOUND) {
git_error_clear();
error = 0;
}
if (error)
goto done;
/* no_proxy/NO_PROXY environment variables */
error = git__getenv(&no_proxy_env, "no_proxy");
if (error == GIT_ENOTFOUND)
error = git__getenv(&no_proxy_env, "NO_PROXY");
if (error && error != GIT_ENOTFOUND)
goto done;
if (!git_net_url_matches_pattern_list(url, no_proxy_env.ptr))
*out = git_buf_detach(&proxy_env);
else
error = GIT_ENOTFOUND;
done:
git_buf_dispose(&proxy_env);
git_buf_dispose(&no_proxy_env);
return error;
}
}
*proxy_url = git_buf_detach(&val);
int git_remote__http_proxy(char **out, git_remote *remote, git_net_url *url)
{
int error;
found:
GIT_ERROR_CHECK_ALLOC(*proxy_url);
git_config_entry_free(ce);
GIT_ASSERT_ARG(out);
GIT_ASSERT_ARG(remote);
GIT_ASSERT_ARG(remote->repo);
*out = NULL;
/*
* Go through the possible sources for proxy configuration,
* Examine the various git config options first, then
* consult environment variables.
*/
if ((error = http_proxy_config(out, remote, url)) != GIT_ENOTFOUND ||
(error = http_proxy_env(out, remote, url)) != GIT_ENOTFOUND)
return error;
return 0;
}
......
......@@ -15,6 +15,7 @@
#include "refspec.h"
#include "vector.h"
#include "net.h"
#define GIT_REMOTE_ORIGIN "origin"
......@@ -46,7 +47,7 @@ typedef struct git_remote_connection_opts {
int git_remote__connect(git_remote *remote, git_direction direction, const git_remote_callbacks *callbacks, const git_remote_connection_opts *conn);
int git_remote__urlfordirection(git_buf *url_out, struct git_remote *remote, int direction, const git_remote_callbacks *callbacks);
int git_remote__get_http_proxy(git_remote *remote, bool use_ssl, char **proxy_url);
int git_remote__http_proxy(char **out, git_remote *remote, git_net_url *url);
git_refspec *git_remote__matching_refspec(git_remote *remote, const char *refname);
git_refspec *git_remote__matching_dst_refspec(git_remote *remote, const char *refname);
......
......@@ -290,7 +290,6 @@ static int lookup_proxy(
{
const char *proxy;
git_remote *remote;
bool use_ssl;
char *config = NULL;
int error = 0;
......@@ -304,9 +303,8 @@ static int lookup_proxy(
case GIT_PROXY_AUTO:
remote = transport->owner->owner;
use_ssl = !strcmp(transport->server.url.scheme, "https");
error = git_remote__get_http_proxy(remote, use_ssl, &config);
error = git_remote__http_proxy(&config, remote, &transport->server.url);
if (error || !config)
goto done;
......
......@@ -429,7 +429,7 @@ static int winhttp_stream_connect(winhttp_stream *s)
proxy_opts = &t->owner->proxy;
if (proxy_opts->type == GIT_PROXY_AUTO) {
/* Set proxy if necessary */
if (git_remote__get_http_proxy(t->owner->owner, (strcmp(t->server.url.scheme, "https") == 0), &proxy_url) < 0)
if (git_remote__http_proxy(&proxy_url, t->owner->owner, &t->server.url) < 0)
goto on_error;
}
else if (proxy_opts->type == GIT_PROXY_SPECIFIED) {
......
......@@ -168,6 +168,17 @@ extern int git__strncasecmp(const char *a, const char *b, size_t sz);
extern int git__strcasesort_cmp(const char *a, const char *b);
/*
* Compare some NUL-terminated `a` to a possibly non-NUL terminated
* `b` of length `b_len`; like `strncmp` but ensuring that
* `strlen(a) == b_len` as well.
*/
GIT_INLINE(int) git__strlcmp(const char *a, const char *b, size_t b_len)
{
int cmp = strncmp(a, b, b_len);
return cmp ? cmp : (int)a[b_len];
}
typedef struct {
git_atomic32 refcount;
void *owner;
......
......@@ -123,3 +123,14 @@ void test_core_string__strcasecmp(void)
cl_assert(git__strcasecmp("et", "e\342\202\254ghi=") < 0);
cl_assert(git__strcasecmp("\303\215", "\303\255") < 0);
}
void test_core_string__strlcmp(void)
{
const char foo[3] = { 'f', 'o', 'o' };
cl_assert(git__strlcmp("foo", "foo", 3) == 0);
cl_assert(git__strlcmp("foo", foo, 3) == 0);
cl_assert(git__strlcmp("foo", "foobar", 3) == 0);
cl_assert(git__strlcmp("foobar", "foo", 3) > 0);
cl_assert(git__strlcmp("foo", "foobar", 6) < 0);
}
......@@ -4,19 +4,19 @@
static git_net_url source, target;
void test_network_joinpath__initialize(void)
void test_network_url_joinpath__initialize(void)
{
memset(&source, 0, sizeof(source));
memset(&target, 0, sizeof(target));
}
void test_network_joinpath__cleanup(void)
void test_network_url_joinpath__cleanup(void)
{
git_net_url_dispose(&source);
git_net_url_dispose(&target);
}
void test_network_joinpath__target_paths_and_queries(void)
void test_network_url_joinpath__target_paths_and_queries(void)
{
cl_git_pass(git_net_url_parse(&source, "http://example.com/a/b"));
......@@ -31,7 +31,7 @@ void test_network_joinpath__target_paths_and_queries(void)
git_net_url_dispose(&target);
}
void test_network_joinpath__source_query_removed(void)
void test_network_url_joinpath__source_query_removed(void)
{
cl_git_pass(git_net_url_parse(&source, "http://example.com/a/b?query&one&two"));
......@@ -46,7 +46,7 @@ void test_network_joinpath__source_query_removed(void)
git_net_url_dispose(&target);
}
void test_network_joinpath__source_lacks_path(void)
void test_network_url_joinpath__source_lacks_path(void)
{
cl_git_pass(git_net_url_parse(&source, "http://example.com"));
......@@ -91,7 +91,7 @@ void test_network_joinpath__source_lacks_path(void)
git_net_url_dispose(&target);
}
void test_network_joinpath__source_is_slash(void)
void test_network_url_joinpath__source_is_slash(void)
{
cl_git_pass(git_net_url_parse(&source, "http://example.com/"));
......@@ -137,7 +137,7 @@ void test_network_joinpath__source_is_slash(void)
}
void test_network_joinpath__source_has_query(void)
void test_network_url_joinpath__source_has_query(void)
{
cl_git_pass(git_net_url_parse(&source, "http://example.com?query"));
......@@ -183,7 +183,7 @@ void test_network_joinpath__source_has_query(void)
}
void test_network_joinpath__empty_query_ignored(void)
void test_network_url_joinpath__empty_query_ignored(void)
{
cl_git_pass(git_net_url_parse(&source, "http://example.com/foo"));
......
......@@ -3,19 +3,19 @@
static git_net_url conndata;
void test_network_urlparse__initialize(void)
void test_network_url_parse__initialize(void)
{
memset(&conndata, 0, sizeof(conndata));
}
void test_network_urlparse__cleanup(void)
void test_network_url_parse__cleanup(void)
{
git_net_url_dispose(&conndata);
}
/* Hostname */
void test_network_urlparse__hostname_trivial(void)
void test_network_url_parse__hostname_trivial(void)
{
cl_git_pass(git_net_url_parse(&conndata, "http://example.com/resource"));
cl_assert_equal_s(conndata.scheme, "http");
......@@ -27,7 +27,7 @@ void test_network_urlparse__hostname_trivial(void)
cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
}
void test_network_urlparse__hostname_root(void)
void test_network_url_parse__hostname_root(void)
{
cl_git_pass(git_net_url_parse(&conndata, "http://example.com/"));
cl_assert_equal_s(conndata.scheme, "http");
......@@ -39,7 +39,7 @@ void test_network_urlparse__hostname_root(void)
cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
}
void test_network_urlparse__hostname_implied_root(void)
void test_network_url_parse__hostname_implied_root(void)
{
cl_git_pass(git_net_url_parse(&conndata, "http://example.com"));
cl_assert_equal_s(conndata.scheme, "http");
......@@ -51,7 +51,7 @@ void test_network_urlparse__hostname_implied_root(void)
cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
}
void test_network_urlparse__hostname_implied_root_custom_port(void)
void test_network_url_parse__hostname_implied_root_custom_port(void)
{
cl_git_pass(git_net_url_parse(&conndata, "http://example.com:42"));
cl_assert_equal_s(conndata.scheme, "http");
......@@ -63,7 +63,7 @@ void test_network_urlparse__hostname_implied_root_custom_port(void)
cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
}
void test_network_urlparse__hostname_implied_root_empty_port(void)
void test_network_url_parse__hostname_implied_root_empty_port(void)
{
cl_git_pass(git_net_url_parse(&conndata, "http://example.com:"));
cl_assert_equal_s(conndata.scheme, "http");
......@@ -75,7 +75,7 @@ void test_network_urlparse__hostname_implied_root_empty_port(void)
cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
}
void test_network_urlparse__hostname_encoded_password(void)
void test_network_url_parse__hostname_encoded_password(void)
{
cl_git_pass(git_net_url_parse(&conndata,
"https://user:pass%2fis%40bad@hostname.com:1234/"));
......@@ -88,7 +88,7 @@ void test_network_urlparse__hostname_encoded_password(void)
cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
}
void test_network_urlparse__hostname_user(void)
void test_network_url_parse__hostname_user(void)
{
cl_git_pass(git_net_url_parse(&conndata,
"https://user@example.com/resource"));
......@@ -101,7 +101,7 @@ void test_network_urlparse__hostname_user(void)
cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
}
void test_network_urlparse__hostname_user_pass(void)
void test_network_url_parse__hostname_user_pass(void)
{
/* user:pass@hostname.tld/resource */
cl_git_pass(git_net_url_parse(&conndata,
......@@ -115,7 +115,7 @@ void test_network_urlparse__hostname_user_pass(void)
cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
}
void test_network_urlparse__hostname_port(void)
void test_network_url_parse__hostname_port(void)
{
/* hostname.tld:port/resource */
cl_git_pass(git_net_url_parse(&conndata,
......@@ -129,7 +129,7 @@ void test_network_urlparse__hostname_port(void)
cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
}
void test_network_urlparse__hostname_empty_port(void)
void test_network_url_parse__hostname_empty_port(void)
{
cl_git_pass(git_net_url_parse(&conndata, "http://example.com:/resource"));
cl_assert_equal_s(conndata.scheme, "http");
......@@ -141,7 +141,7 @@ void test_network_urlparse__hostname_empty_port(void)
cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
}
void test_network_urlparse__hostname_user_port(void)
void test_network_url_parse__hostname_user_port(void)
{
/* user@hostname.tld:port/resource */
cl_git_pass(git_net_url_parse(&conndata,
......@@ -155,7 +155,7 @@ void test_network_urlparse__hostname_user_port(void)
cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
}
void test_network_urlparse__hostname_user_pass_port(void)
void test_network_url_parse__hostname_user_pass_port(void)
{
/* user:pass@hostname.tld:port/resource */
cl_git_pass(git_net_url_parse(&conndata,
......@@ -171,7 +171,7 @@ void test_network_urlparse__hostname_user_pass_port(void)
/* IPv4 addresses */
void test_network_urlparse__ipv4_trivial(void)
void test_network_url_parse__ipv4_trivial(void)
{
cl_git_pass(git_net_url_parse(&conndata, "http://192.168.1.1/resource"));
cl_assert_equal_s(conndata.scheme, "http");
......@@ -183,7 +183,7 @@ void test_network_urlparse__ipv4_trivial(void)
cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
}
void test_network_urlparse__ipv4_root(void)
void test_network_url_parse__ipv4_root(void)
{
cl_git_pass(git_net_url_parse(&conndata, "http://192.168.1.1/"));
cl_assert_equal_s(conndata.scheme, "http");
......@@ -195,7 +195,7 @@ void test_network_urlparse__ipv4_root(void)
cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
}
void test_network_urlparse__ipv4_implied_root(void)
void test_network_url_parse__ipv4_implied_root(void)
{
cl_git_pass(git_net_url_parse(&conndata, "http://192.168.1.1"));
cl_assert_equal_s(conndata.scheme, "http");
......@@ -207,7 +207,7 @@ void test_network_urlparse__ipv4_implied_root(void)
cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
}
void test_network_urlparse__ipv4_implied_root_custom_port(void)
void test_network_url_parse__ipv4_implied_root_custom_port(void)
{
cl_git_pass(git_net_url_parse(&conndata, "http://192.168.1.1:42"));
cl_assert_equal_s(conndata.scheme, "http");
......@@ -219,7 +219,7 @@ void test_network_urlparse__ipv4_implied_root_custom_port(void)
cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
}
void test_network_urlparse__ipv4_implied_root_empty_port(void)
void test_network_url_parse__ipv4_implied_root_empty_port(void)
{
cl_git_pass(git_net_url_parse(&conndata, "http://192.168.1.1:"));
cl_assert_equal_s(conndata.scheme, "http");
......@@ -231,7 +231,7 @@ void test_network_urlparse__ipv4_implied_root_empty_port(void)
cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
}
void test_network_urlparse__ipv4_encoded_password(void)
void test_network_url_parse__ipv4_encoded_password(void)
{
cl_git_pass(git_net_url_parse(&conndata,
"https://user:pass%2fis%40bad@192.168.1.1:1234/"));
......@@ -244,7 +244,7 @@ void test_network_urlparse__ipv4_encoded_password(void)
cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
}
void test_network_urlparse__ipv4_user(void)
void test_network_url_parse__ipv4_user(void)
{
cl_git_pass(git_net_url_parse(&conndata,
"https://user@192.168.1.1/resource"));
......@@ -257,7 +257,7 @@ void test_network_urlparse__ipv4_user(void)
cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
}
void test_network_urlparse__ipv4_user_pass(void)
void test_network_url_parse__ipv4_user_pass(void)
{
cl_git_pass(git_net_url_parse(&conndata,
"https://user:pass@192.168.1.1/resource"));
......@@ -270,7 +270,7 @@ void test_network_urlparse__ipv4_user_pass(void)
cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
}
void test_network_urlparse__ipv4_port(void)
void test_network_url_parse__ipv4_port(void)
{
cl_git_pass(git_net_url_parse(&conndata,
"https://192.168.1.1:9191/resource"));
......@@ -283,7 +283,7 @@ void test_network_urlparse__ipv4_port(void)
cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
}
void test_network_urlparse__ipv4_empty_port(void)
void test_network_url_parse__ipv4_empty_port(void)
{
cl_git_pass(git_net_url_parse(&conndata, "http://192.168.1.1:/resource"));
cl_assert_equal_s(conndata.scheme, "http");
......@@ -295,7 +295,7 @@ void test_network_urlparse__ipv4_empty_port(void)
cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
}
void test_network_urlparse__ipv4_user_port(void)
void test_network_url_parse__ipv4_user_port(void)
{
cl_git_pass(git_net_url_parse(&conndata,
"https://user@192.168.1.1:9191/resource"));
......@@ -308,7 +308,7 @@ void test_network_urlparse__ipv4_user_port(void)
cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
}
void test_network_urlparse__ipv4_user_pass_port(void)
void test_network_url_parse__ipv4_user_pass_port(void)
{
cl_git_pass(git_net_url_parse(&conndata,
"https://user:pass@192.168.1.1:9191/resource"));
......@@ -323,7 +323,7 @@ void test_network_urlparse__ipv4_user_pass_port(void)
/* IPv6 addresses */
void test_network_urlparse__ipv6_trivial(void)
void test_network_url_parse__ipv6_trivial(void)
{
cl_git_pass(git_net_url_parse(&conndata, "http://[fe80::dcad:beff:fe00:0001]/resource"));
cl_assert_equal_s(conndata.scheme, "http");
......@@ -335,7 +335,7 @@ void test_network_urlparse__ipv6_trivial(void)
cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
}
void test_network_urlparse__ipv6_root(void)
void test_network_url_parse__ipv6_root(void)
{
cl_git_pass(git_net_url_parse(&conndata, "http://[fe80::dcad:beff:fe00:0001]/"));
cl_assert_equal_s(conndata.scheme, "http");
......@@ -347,7 +347,7 @@ void test_network_urlparse__ipv6_root(void)
cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
}
void test_network_urlparse__ipv6_implied_root(void)
void test_network_url_parse__ipv6_implied_root(void)
{
cl_git_pass(git_net_url_parse(&conndata, "http://[fe80::dcad:beff:fe00:0001]"));
cl_assert_equal_s(conndata.scheme, "http");
......@@ -359,7 +359,7 @@ void test_network_urlparse__ipv6_implied_root(void)
cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
}
void test_network_urlparse__ipv6_implied_root_custom_port(void)
void test_network_url_parse__ipv6_implied_root_custom_port(void)
{
cl_git_pass(git_net_url_parse(&conndata, "http://[fe80::dcad:beff:fe00:0001]:42"));
cl_assert_equal_s(conndata.scheme, "http");
......@@ -371,7 +371,7 @@ void test_network_urlparse__ipv6_implied_root_custom_port(void)
cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
}
void test_network_urlparse__ipv6_implied_root_empty_port(void)
void test_network_url_parse__ipv6_implied_root_empty_port(void)
{
cl_git_pass(git_net_url_parse(&conndata, "http://[fe80::dcad:beff:fe00:0001]:"));
cl_assert_equal_s(conndata.scheme, "http");
......@@ -383,7 +383,7 @@ void test_network_urlparse__ipv6_implied_root_empty_port(void)
cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
}
void test_network_urlparse__ipv6_encoded_password(void)
void test_network_url_parse__ipv6_encoded_password(void)
{
cl_git_pass(git_net_url_parse(&conndata,
"https://user:pass%2fis%40bad@[fe80::dcad:beff:fe00:0001]:1234/"));
......@@ -396,7 +396,7 @@ void test_network_urlparse__ipv6_encoded_password(void)
cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
}
void test_network_urlparse__ipv6_user(void)
void test_network_url_parse__ipv6_user(void)
{
cl_git_pass(git_net_url_parse(&conndata,
"https://user@[fe80::dcad:beff:fe00:0001]/resource"));
......@@ -409,7 +409,7 @@ void test_network_urlparse__ipv6_user(void)
cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
}
void test_network_urlparse__ipv6_user_pass(void)
void test_network_url_parse__ipv6_user_pass(void)
{
cl_git_pass(git_net_url_parse(&conndata,
"https://user:pass@[fe80::dcad:beff:fe00:0001]/resource"));
......@@ -422,7 +422,7 @@ void test_network_urlparse__ipv6_user_pass(void)
cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
}
void test_network_urlparse__ipv6_port(void)
void test_network_url_parse__ipv6_port(void)
{
cl_git_pass(git_net_url_parse(&conndata,
"https://[fe80::dcad:beff:fe00:0001]:9191/resource"));
......@@ -435,7 +435,7 @@ void test_network_urlparse__ipv6_port(void)
cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
}
void test_network_urlparse__ipv6_empty_port(void)
void test_network_url_parse__ipv6_empty_port(void)
{
cl_git_pass(git_net_url_parse(&conndata, "http://[fe80::dcad:beff:fe00:0001]:/resource"));
cl_assert_equal_s(conndata.scheme, "http");
......@@ -447,7 +447,7 @@ void test_network_urlparse__ipv6_empty_port(void)
cl_assert_equal_i(git_net_url_is_default_port(&conndata), 1);
}
void test_network_urlparse__ipv6_user_port(void)
void test_network_url_parse__ipv6_user_port(void)
{
cl_git_pass(git_net_url_parse(&conndata,
"https://user@[fe80::dcad:beff:fe00:0001]:9191/resource"));
......@@ -460,7 +460,7 @@ void test_network_urlparse__ipv6_user_port(void)
cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
}
void test_network_urlparse__ipv6_user_pass_port(void)
void test_network_url_parse__ipv6_user_pass_port(void)
{
cl_git_pass(git_net_url_parse(&conndata,
"https://user:pass@[fe80::dcad:beff:fe00:0001]:9191/resource"));
......@@ -473,7 +473,7 @@ void test_network_urlparse__ipv6_user_pass_port(void)
cl_assert_equal_i(git_net_url_is_default_port(&conndata), 0);
}
void test_network_urlparse__ipv6_invalid_addresses(void)
void test_network_url_parse__ipv6_invalid_addresses(void)
{
/* Opening bracket missing */
cl_git_fail_with(GIT_EINVALIDSPEC, git_net_url_parse(&conndata,
......
#include "clar_libgit2.h"
#include "net.h"
struct url_pattern {
const char *url;
const char *pattern;
bool matches;
};
void test_network_url_pattern__single(void)
{
git_net_url url;
size_t i;
struct url_pattern url_patterns[] = {
/* Wildcard matches */
{ "https://example.com/", "", false },
{ "https://example.com/", "*", true },
/* Literal and wildcard matches */
{ "https://example.com/", "example.com", true },
{ "https://example.com/", ".example.com", true },
{ "https://example.com/", "*.example.com", true },
{ "https://www.example.com/", "www.example.com", true },
{ "https://www.example.com/", ".example.com", true },
{ "https://www.example.com/", "*.example.com", true },
/* Literal and wildcard failures */
{ "https://example.com/", "example.org", false },
{ "https://example.com/", ".example.org", false },
{ "https://example.com/", "*.example.org", false },
{ "https://foo.example.com/", "www.example.com", false },
/*
* A port in the pattern is optional; if no port is
* present, it matches *all* ports.
*/
{ "https://example.com/", "example.com:443", true },
{ "https://example.com/", "example.com:80", false },
{ "https://example.com:1443/", "example.com", true },
/* Failures with similar prefix/suffix */
{ "https://texample.com/", "example.com", false },
{ "https://example.com/", "mexample.com", false },
{ "https://example.com:44/", "example.com:443", false },
{ "https://example.com:443/", "example.com:44", false },
};
for (i = 0; i < ARRAY_SIZE(url_patterns); i++) {
cl_git_pass(git_net_url_parse(&url, url_patterns[i].url));
cl_assert_(git_net_url_matches_pattern(&url, url_patterns[i].pattern) == url_patterns[i].matches, url_patterns[i].pattern);
git_net_url_dispose(&url);
}
}
void test_network_url_pattern__list(void)
{
git_net_url url;
size_t i;
struct url_pattern url_patterns[] = {
/* Wildcard matches */
{ "https://example.com/", "", false },
{ "https://example.com/", "*", true },
{ "https://example.com/", ",example.com,", true },
{ "https://example.com/", "foo,,example.com,,bar", true },
{ "https://example.com/", "foo,,zzz,,*,,bar", true },
/* Literals */
{ "https://example.com/", "example.com", true },
{ "https://example.com/", "foo.bar,example.com", true },
{ "https://example.com/", "foo.bar", false },
{ "https://example.com/", "foo.bar,example.org", false },
{ "https://www.example.com/", "foo.example.com,www.example.com,bar.example.com", true },
{ "https://www.example.com/", "foo.example.com,baz.example.com,bar.example.com", false },
{ "https://foo.example.com/", "www.example.com", false },
{ "https://foo.example.com/", "bar.example.com,www.example.com,", false },
/* Wildcards */
{ "https://example.com/", ".example.com", true },
{ "https://example.com/", "*.example.com", true },
{ "https://example.com/", "foo.com,bar.com,.example.com", true },
{ "https://example.com/", ".foo.com,.bar.com,.example.com", true },
{ "https://example.com/", ".foo.com,.bar.com,asdf.com", false },
{ "https://example.com/", "*.foo,*.bar,*.example.com,*.asdf", true },
{ "https://example.com/", "*.foo,*.bar,*.asdf", false },
/* Ports! */
{ "https://example.com/", "example.com:443", true },
{ "https://example.com/", "example.com:42,example.com:443,example.com:99", true },
{ "https://example.com/", "example.com:42,example.com:80,example.org:443", false },
{ "https://example.com:1443/", "example.com", true },
{ "https://example.com:44/", "example.com:443", false },
{ "https://example.com:443/", "example.com:44", false },
};
for (i = 0; i < ARRAY_SIZE(url_patterns); i++) {
cl_git_pass(git_net_url_parse(&url, url_patterns[i].url));
cl_assert_(git_net_url_matches_pattern_list(&url, url_patterns[i].pattern) == url_patterns[i].matches, url_patterns[i].pattern);
git_net_url_dispose(&url);
}
}
......@@ -4,17 +4,17 @@
static git_net_url conndata;
void test_network_redirect__initialize(void)
void test_network_url_redirect__initialize(void)
{
memset(&conndata, 0, sizeof(conndata));
}
void test_network_redirect__cleanup(void)
void test_network_url_redirect__cleanup(void)
{
git_net_url_dispose(&conndata);
}
void test_network_redirect__redirect_http(void)
void test_network_url_redirect__redirect_http(void)
{
cl_git_pass(git_net_url_parse(&conndata,
"http://example.com/foo/bar/baz"));
......@@ -28,7 +28,7 @@ void test_network_redirect__redirect_http(void)
cl_assert_equal_p(conndata.password, NULL);
}
void test_network_redirect__redirect_ssl(void)
void test_network_url_redirect__redirect_ssl(void)
{
cl_git_pass(git_net_url_parse(&conndata,
"https://example.com/foo/bar/baz"));
......@@ -42,7 +42,7 @@ void test_network_redirect__redirect_ssl(void)
cl_assert_equal_p(conndata.password, NULL);
}
void test_network_redirect__redirect_leaves_root_path(void)
void test_network_url_redirect__redirect_leaves_root_path(void)
{
cl_git_pass(git_net_url_parse(&conndata,
"https://example.com/foo/bar/baz"));
......@@ -56,7 +56,7 @@ void test_network_redirect__redirect_leaves_root_path(void)
cl_assert_equal_p(conndata.password, NULL);
}
void test_network_redirect__redirect_encoded_username_password(void)
void test_network_url_redirect__redirect_encoded_username_password(void)
{
cl_git_pass(git_net_url_parse(&conndata,
"https://user%2fname:pass%40word%zyx%v@example.com/foo/bar/baz"));
......@@ -70,7 +70,7 @@ void test_network_redirect__redirect_encoded_username_password(void)
cl_assert_equal_s(conndata.password, "pass@word%zyx%v");
}
void test_network_redirect__redirect_cross_host_denied(void)
void test_network_url_redirect__redirect_cross_host_denied(void)
{
cl_git_pass(git_net_url_parse(&conndata, "https://bar.com/bar/baz"));
cl_git_fail_with(git_net_url_apply_redirect(&conndata,
......@@ -78,7 +78,7 @@ void test_network_redirect__redirect_cross_host_denied(void)
-1);
}
void test_network_redirect__redirect_http_downgrade_denied(void)
void test_network_url_redirect__redirect_http_downgrade_denied(void)
{
cl_git_pass(git_net_url_parse(&conndata, "https://foo.com/bar/baz"));
cl_git_fail_with(git_net_url_apply_redirect(&conndata,
......@@ -86,7 +86,7 @@ void test_network_redirect__redirect_http_downgrade_denied(void)
-1);
}
void test_network_redirect__redirect_relative(void)
void test_network_url_redirect__redirect_relative(void)
{
cl_git_pass(git_net_url_parse(&conndata, "http://foo.com/bar/baz/biff"));
cl_git_pass(git_net_url_apply_redirect(&conndata,
......@@ -99,7 +99,7 @@ void test_network_redirect__redirect_relative(void)
cl_assert_equal_p(conndata.password, NULL);
}
void test_network_redirect__redirect_relative_ssl(void)
void test_network_url_redirect__redirect_relative_ssl(void)
{
cl_git_pass(git_net_url_parse(&conndata, "https://foo.com/bar/baz/biff"));
cl_git_pass(git_net_url_apply_redirect(&conndata,
......@@ -112,7 +112,7 @@ void test_network_redirect__redirect_relative_ssl(void)
cl_assert_equal_p(conndata.password, NULL);
}
void test_network_redirect__service_query_no_query_params_in_location(void)
void test_network_url_redirect__service_query_no_query_params_in_location(void)
{
cl_git_pass(git_net_url_parse(&conndata, "https://foo.com/bar/info/refs?service=git-upload-pack"));
cl_git_pass(git_net_url_apply_redirect(&conndata,
......@@ -120,7 +120,7 @@ void test_network_redirect__service_query_no_query_params_in_location(void)
cl_assert_equal_s(conndata.path, "/baz");
}
void test_network_redirect__service_query_with_query_params_in_location(void)
void test_network_url_redirect__service_query_with_query_params_in_location(void)
{
cl_git_pass(git_net_url_parse(&conndata, "https://foo.com/bar/info/refs?service=git-upload-pack"));
cl_git_pass(git_net_url_apply_redirect(&conndata,
......
......@@ -36,6 +36,7 @@ static char *_remote_expectcontinue = NULL;
static int _orig_proxies_need_reset = 0;
static char *_orig_http_proxy = NULL;
static char *_orig_https_proxy = NULL;
static char *_orig_no_proxy = NULL;
static int ssl_cert(git_cert *cert, int valid, const char *host, void *payload)
{
......@@ -110,9 +111,11 @@ void test_online_clone__cleanup(void)
if (_orig_proxies_need_reset) {
cl_setenv("HTTP_PROXY", _orig_http_proxy);
cl_setenv("HTTPS_PROXY", _orig_https_proxy);
cl_setenv("NO_PROXY", _orig_no_proxy);
git__free(_orig_http_proxy);
git__free(_orig_https_proxy);
git__free(_orig_no_proxy);
}
git_libgit2_opts(GIT_OPT_SET_SSL_CERT_LOCATIONS, NULL, NULL);
......@@ -854,6 +857,7 @@ void test_online_clone__proxy_credentials_in_environment(void)
_orig_http_proxy = cl_getenv("HTTP_PROXY");
_orig_https_proxy = cl_getenv("HTTPS_PROXY");
_orig_no_proxy = cl_getenv("NO_PROXY");
_orig_proxies_need_reset = 1;
g_options.fetch_opts.proxy_opts.type = GIT_PROXY_AUTO;
......@@ -865,6 +869,7 @@ void test_online_clone__proxy_credentials_in_environment(void)
cl_setenv("HTTP_PROXY", url.ptr);
cl_setenv("HTTPS_PROXY", url.ptr);
cl_setenv("NO_PROXY", NULL);
cl_git_pass(git_clone(&g_repo, "http://github.com/libgit2/TestGitRepository", "./foo", &g_options));
......
#include "clar_libgit2.h"
#include "remote.h"
#include "net.h"
static git_repository *repo;
static git_net_url url = GIT_NET_URL_INIT;
static int orig_proxies_need_reset = 0;
static char *orig_http_proxy = NULL;
static char *orig_https_proxy = NULL;
static char *orig_no_proxy = NULL;
void test_remote_httpproxy__initialize(void)
{
git_remote *remote;
repo = cl_git_sandbox_init("testrepo");
cl_git_pass(git_remote_create(&remote, repo, "lg2", "https://github.com/libgit2/libgit2"));
cl_git_pass(git_net_url_parse(&url, "https://github.com/libgit2/libgit2"));
git_remote_free(remote);
orig_proxies_need_reset = 0;
}
void test_remote_httpproxy__cleanup(void)
{
if (orig_proxies_need_reset) {
cl_setenv("HTTP_PROXY", orig_http_proxy);
cl_setenv("HTTPS_PROXY", orig_https_proxy);
cl_setenv("NO_PROXY", orig_no_proxy);
git__free(orig_http_proxy);
git__free(orig_https_proxy);
git__free(orig_no_proxy);
}
git_net_url_dispose(&url);
cl_git_sandbox_cleanup();
}
void assert_proxy_is(const char *expected)
{
git_remote *remote;
char *proxy;
cl_git_pass(git_remote_lookup(&remote, repo, "lg2"));
cl_git_pass(git_remote__http_proxy(&proxy, remote, &url));
if (expected)
cl_assert_equal_s(proxy, expected);
else
cl_assert_equal_p(proxy, expected);
git_remote_free(remote);
git__free(proxy);
}
void assert_config_match(const char *config, const char *expected)
{
git_remote *remote;
char *proxy;
if (config)
cl_repo_set_string(repo, config, expected);
cl_git_pass(git_remote_lookup(&remote, repo, "lg2"));
cl_git_pass(git_remote__http_proxy(&proxy, remote, &url));
if (expected)
cl_assert_equal_s(proxy, expected);
else
cl_assert_equal_p(proxy, expected);
git_remote_free(remote);
git__free(proxy);
}
void test_remote_httpproxy__config_overrides(void)
{
/*
* http.proxy should be honored, then http.<url>.proxy should
* be honored in increasing specificity of the url. finally,
* remote.<name>.proxy is the most specific.
*/
assert_config_match(NULL, NULL);
assert_config_match("http.proxy", "http://localhost:1/");
assert_config_match("http.https://github.com.proxy", "http://localhost:2/");
assert_config_match("http.https://github.com/.proxy", "http://localhost:3/");
assert_config_match("http.https://github.com/libgit2.proxy", "http://localhost:4/");
assert_config_match("http.https://github.com/libgit2/.proxy", "http://localhost:5/");
assert_config_match("http.https://github.com/libgit2/libgit2.proxy", "http://localhost:6/");
assert_config_match("remote.lg2.proxy", "http://localhost:7/");
}
void test_remote_httpproxy__config_empty_overrides(void)
{
/*
* with greater specificity, an empty config entry overrides
* a set one
*/
assert_config_match("http.proxy", "http://localhost:1/");
assert_config_match("http.https://github.com.proxy", "");
assert_config_match("http.https://github.com/libgit2/libgit2.proxy", "http://localhost:2/");
assert_config_match("remote.lg2.proxy", "");
}
void test_remote_httpproxy__env(void)
{
orig_http_proxy = cl_getenv("HTTP_PROXY");
orig_https_proxy = cl_getenv("HTTPS_PROXY");
orig_no_proxy = cl_getenv("NO_PROXY");
orig_proxies_need_reset = 1;
/* HTTP proxy is ignored for HTTPS */
cl_setenv("HTTP_PROXY", "http://localhost:9/");
assert_proxy_is(NULL);
/* HTTPS proxy is honored for HTTPS */
cl_setenv("HTTPS_PROXY", "http://localhost:10/");
assert_proxy_is("http://localhost:10/");
/* NO_PROXY is honored */
cl_setenv("NO_PROXY", "github.com:443");
assert_proxy_is(NULL);
cl_setenv("NO_PROXY", "github.com:80");
assert_proxy_is("http://localhost:10/");
cl_setenv("NO_PROXY", "github.com");
assert_proxy_is(NULL);
cl_setenv("NO_PROXY", "github.dev,github.com,github.foo");
assert_proxy_is(NULL);
/* configuration overrides environment variables */
cl_setenv("NO_PROXY", "github.none");
assert_config_match("http.https://github.com.proxy", "http://localhost:11/");
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment