Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

transport/http: Include non-default ports in Host header #4882

Merged
merged 2 commits into from
Nov 18, 2018
Merged

transport/http: Include non-default ports in Host header #4882

merged 2 commits into from
Nov 18, 2018

Conversation

mx-shift
Copy link
Contributor

@mx-shift mx-shift commented Nov 7, 2018

When the port is omitted, the server assumes the default port for the
service is used (see
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Host). In
cases where the client provided a non-default port, it should be passed
along.

This hasn't been an issue so far as the git protocol doesn't include
server-generated URIs. I encountered this when implementing Rust
registry support for Sonatype Nexus. Rust's registry uses a git
repository for the package index. Clients look at a file in the root of
the package index to find the base URL for downloading the packages.
Sonatype Nexus looks at the incoming HTTP request (Host header and URL)
to determine the client-facing URL base as it may be running behind a
load balancer or reverse proxy. This client-facing URL base is then used
to construct the package download base URL. When libgit2 fetches the
index from Nexus on a non-default port, Nexus trusts the incorrect Host
header and generates an incorrect package download base URL.

src/transports/http.c Outdated Show resolved Hide resolved
Copy link
Member

@ethomson ethomson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure why the CI builds didn't start here... but there are a few typos (getno should be gitno, which is an abbreviation for git network operations, not an accessor). This is a bit confusing since we use git_ as a prefix everywhere except this one place. Alas.

src/netops.h Outdated
@@ -96,4 +96,6 @@ int gitno_extract_url_parts(
const char *url,
const char *default_port);

const char *getno__default_port(gitno_connection_data *data);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be gitno, not getno...

src/netops.c Outdated
static const char *default_port_http = "80";
static const char *default_port_https = "443";

const char *getno__default_port(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be gitno, not getno...

src/netops.c Outdated
data->use_ssl = true;
} else if (url[0] == '/')
default_port = data->use_ssl ? "443" : "80";
default_port = getno__default_port(data);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be gitno, not getno...

Constant strings and logic for HTTP(S) default ports were starting to be
spread throughout netops.c.  Instead of duplicating this again to
determine if a Host header should include the port, move the default
port constants and logic into an internal method in netops.{c,h}.
@mx-shift
Copy link
Contributor Author

mx-shift commented Nov 9, 2018

I'm puzzled by how this even compiled. I definitely built it using CMake and msbuild on Windows 10 and did not see a warning or error even though src/transports/http.c is very clearly referencing an undefined symbol. More puzzling is that I build Rust's Cargo using this version and it worked correctly.

When the port is omitted, the server assumes the default port for the
service is used (see
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Host). In
cases where the client provided a non-default port, it should be passed
along.

This hasn't been an issue so far as the git protocol doesn't include
server-generated URIs. I encountered this when implementing Rust
registry support for Sonatype Nexus. Rust's registry uses a git
repository for the package index. Clients look at a file in the root of
the package index to find the base URL for downloading the packages.
Sonatype Nexus looks at the incoming HTTP request (Host header and URL)
to determine the client-facing URL base as it may be running behind a
load balancer or reverse proxy. This client-facing URL base is then used
to construct the package download base URL. When libgit2 fetches the
index from Nexus on a non-default port, Nexus trusts the incorrect Host
header and generates an incorrect package download base URL.
@mx-shift
Copy link
Contributor Author

mx-shift commented Nov 9, 2018

Aha! When I first encountered the bug this PR fixes, I was using a Linux machine. Since then I switched to a Windows machine and didn't notice that libgit2 uses WinHTTP by default instead of src/transports/http.c. So my builds were succeeding because the code I was changing wasn't even being built and I saw successful test results because it was using WinHTTP which doesn't have the bug.

CI builds now pass and I'll test with a Linux VM later today.

@ethomson ethomson merged commit 4ef2b88 into libgit2:master Nov 18, 2018
@ethomson
Copy link
Member

Thanks for the PR!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants