Add option to disable port check (#61)

This commit is contained in:
Johann150 2021-06-11 08:00:39 +02:00 committed by GitHub
commit 9c15bd5d9a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 35 additions and 4 deletions

View file

@ -138,6 +138,8 @@ Agate also supports different certificates for different hostnames, see the sect
If you want to serve the same content for multiple domains, you can instead disable the hostname check by not specifying `--hostname`. In this case Agate will disregard a request's hostname apart from checking that there is one.
When one or more `--hostname`s are specified, Agate will check that the hostnames and port in request URLs match the specified hostnames and the listening ports. If Agate is behind a proxy on another port and receives a request wil an URL specifying the proxy port, this port may not match one of Agate's listening ports and the request will be rejected: it is possible to disable the port check with `--skip-port-check`.
### Certificates
Agate has support for using multiple certificates with the `--certs` option. Agate will thus always require that a client uses SNI, which should not be a problem since the Gemini specification also requires SNI to be used.

View file

@ -82,6 +82,7 @@ struct Args {
log_ips: bool,
only_tls13: bool,
central_config: bool,
skip_port_check: bool,
}
fn args() -> Result<Args> {
@ -140,6 +141,11 @@ fn args() -> Result<Args> {
"ed25519",
"Generate keys using the Ed25519 signature algorithm instead of the default ECDSA.",
);
opts.optflag(
"",
"skip-port-check",
"Skip URL port check even when a hostname is specified.",
);
let matches = opts.parse(&args[1..]).map_err(|f| f.to_string())?;
@ -263,6 +269,7 @@ fn args() -> Result<Args> {
log_ips: matches.opt_present("log-ip"),
only_tls13: matches.opt_present("only-tls13"),
central_config: matches.opt_present("central-conf"),
skip_port_check: matches.opt_present("skip-port-check"),
})
}
@ -413,10 +420,13 @@ impl RequestHandle {
}
// correct port
if let Some(port) = url.port() {
// Validate that the port in the URL is the same as for the stream this request came in on.
if port != self.stream.get_ref().0.local_addr().unwrap().port() {
return Err((53, "proxy request refused"));
if !ARGS.skip_port_check {
if let Some(port) = url.port() {
// Validate that the port in the URL is the same as for the stream this request
// came in on.
if port != self.stream.get_ref().0.local_addr().unwrap().port() {
return Err((53, "Proxy request refused"));
}
}
}
Ok(url)

View file

@ -372,6 +372,25 @@ fn port_check() {
assert_eq!(page.header.status, Status::ProxyRequestRefused);
}
#[test]
/// - port is not checked if the skip option is passed.
fn port_check_skipped() {
let page = get(
&[
"--addr",
"[::]:19720",
"--hostname",
"example.org",
"--skip-port-check",
],
addr(19720),
"gemini://example.org:1971/",
)
.expect("could not get page");
assert_eq!(page.header.status, Status::Success);
}
#[test]
/// - status for paths with hidden segments is "gone" if file does not exist
fn secret_nonexistent() {