Skip to content

Commit

Permalink
Merge pull request libgit2#5473 from libgit2/ethomson/v0.28.5
Browse files Browse the repository at this point in the history
fetchhead: strip credentials from remote URL
  • Loading branch information
pks-t authored Mar 31, 2020
2 parents 1e5b139 + bb52d9f commit 7a2b969
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 4 deletions.
5 changes: 5 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ This is a bugfix release with the following changes:

- Fixes for several memory leaks.

- When fetching from an anonymous remote using a URL with authentication
information provided in the URL (eg `https://foo:bar@example.com/repo`),
we would erroneously include the literal URL in the FETCH_HEAD file.
We now remove that to match git's behavior.

v0.28.4
--------

Expand Down
38 changes: 35 additions & 3 deletions src/fetchhead.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "buffer.h"
#include "fileops.h"
#include "filebuf.h"
#include "netops.h"
#include "refs.h"
#include "repository.h"

Expand All @@ -36,6 +37,33 @@ int git_fetchhead_ref_cmp(const void *a, const void *b)
return 0;
}

static char *sanitized_remote_url(const char *remote_url)
{
gitno_connection_data url = {0};
char *sanitized = NULL;
int error;

if (gitno_connection_data_from_url(&url, remote_url, NULL) == 0) {
git_buf buf = GIT_BUF_INIT;

git__free(url.user);
git__free(url.pass);
url.user = url.pass = NULL;

if ((error = gitno_connection_data_fmt(&buf, &url)) < 0)
goto fallback;

sanitized = git_buf_detach(&buf);
}

fallback:
if (!sanitized)
sanitized = git__strdup(remote_url);

gitno_connection_data_free_ptrs(&url);
return sanitized;
}

int git_fetchhead_ref_create(
git_fetchhead_ref **out,
git_oid *oid,
Expand All @@ -57,11 +85,15 @@ int git_fetchhead_ref_create(
git_oid_cpy(&fetchhead_ref->oid, oid);
fetchhead_ref->is_merge = is_merge;

if (ref_name)
if (ref_name) {
fetchhead_ref->ref_name = git__strdup(ref_name);
GIT_ERROR_CHECK_ALLOC(fetchhead_ref->ref_name);
}

if (remote_url)
fetchhead_ref->remote_url = git__strdup(remote_url);
if (remote_url) {
fetchhead_ref->remote_url = sanitized_remote_url(remote_url);
GIT_ERROR_CHECK_ALLOC(fetchhead_ref->remote_url);
}

*out = fetchhead_ref;

Expand Down
29 changes: 29 additions & 0 deletions src/netops.c
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,35 @@ int gitno_connection_data_from_url(
return error;
}

int gitno_connection_data_fmt(git_buf *buf, gitno_connection_data *d)
{
if (d->host) {
git_buf_puts(buf, d->use_ssl ? prefix_https : prefix_http);

if (d->user) {
git_buf_puts(buf, d->user);

if (d->pass) {
git_buf_puts(buf, ":");
git_buf_puts(buf, d->pass);
}

git_buf_putc(buf, '@');
}

git_buf_puts(buf, d->host);

if (d->port && strcmp(d->port, gitno__default_port(d))) {
git_buf_putc(buf, ':');
git_buf_puts(buf, d->port);
}
}

git_buf_puts(buf, d->path ? d->path : "/");

return git_buf_oom(buf) ? -1 : 0;
}

void gitno_connection_data_free_ptrs(gitno_connection_data *d)
{
git__free(d->host); d->host = NULL;
Expand Down
3 changes: 3 additions & 0 deletions src/netops.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ int gitno_connection_data_from_url(
const char *url,
const char *service_suffix);

/* Format a URL into a buffer */
int gitno_connection_data_fmt(git_buf *buf, gitno_connection_data *data);

/* This frees all the pointers IN the struct, but not the struct itself. */
void gitno_connection_data_free_ptrs(gitno_connection_data *data);

Expand Down
20 changes: 19 additions & 1 deletion tests/fetchhead/nonetwork.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ void test_fetchhead_nonetwork__write(void)
typedef struct {
git_vector *fetchhead_vector;
size_t idx;
} fetchhead_ref_cb_data;
} fetchhead_ref_cb_data;

static int fetchhead_ref_cb(const char *name, const char *url,
const git_oid *oid, unsigned int is_merge, void *payload)
Expand Down Expand Up @@ -493,3 +493,21 @@ void test_fetchhead_nonetwork__create_with_multiple_refspecs(void)
git_remote_free(remote);
git_buf_dispose(&path);
}

void test_fetchhead_nonetwork__credentials_are_stripped(void)
{
git_fetchhead_ref *ref;
git_oid oid;

cl_git_pass(git_oid_fromstr(&oid, "49322bb17d3acc9146f98c97d078513228bbf3c0"));
cl_git_pass(git_fetchhead_ref_create(&ref, &oid, 0,
"refs/tags/commit_tree", "http://foo:bar@github.com/libgit2/TestGitRepository"));
cl_assert_equal_s(ref->remote_url, "http://github.com/libgit2/TestGitRepository");
git_fetchhead_ref_free(ref);

cl_git_pass(git_oid_fromstr(&oid, "49322bb17d3acc9146f98c97d078513228bbf3c0"));
cl_git_pass(git_fetchhead_ref_create(&ref, &oid, 0,
"refs/tags/commit_tree", "https://foo:bar@github.com/libgit2/TestGitRepository"));
cl_assert_equal_s(ref->remote_url, "https://github.com/libgit2/TestGitRepository");
git_fetchhead_ref_free(ref);
}
17 changes: 17 additions & 0 deletions tests/online/fetchhead.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,3 +154,20 @@ void test_online_fetchhead__colon_only_dst_refspec_creates_no_branch(void)

cl_assert_equal_i(refs, count_references());
}

void test_online_fetchhead__creds_get_stripped(void)
{
git_buf buf = GIT_BUF_INIT;
git_remote *remote;

cl_git_pass(git_repository_init(&g_repo, "./foo", 0));
cl_git_pass(git_remote_create_anonymous(&remote, g_repo, "https://libgit3:libgit3@bitbucket.org/libgit2/testgitrepository.git"));
cl_git_pass(git_remote_fetch(remote, NULL, NULL, NULL));

cl_git_pass(git_futils_readbuffer(&buf, "./foo/.git/FETCH_HEAD"));
cl_assert_equal_s(buf.ptr,
"49322bb17d3acc9146f98c97d078513228bbf3c0\t\thttps://bitbucket.org/libgit2/testgitrepository.git\n");

git_remote_free(remote);
git_buf_dispose(&buf);
}

0 comments on commit 7a2b969

Please sign in to comment.