diff options
| author | Jan Wolff <janw@mailbox.org> | 2020-05-26 06:49:20 +0200 |
|---|---|---|
| committer | Jan Wolff <janw@mailbox.org> | 2020-05-26 06:49:20 +0200 |
| commit | 2ffc8ff0ccb0bfad7d69104cbc00b167589c780b (patch) | |
| tree | ff344bee57957c237bba560d59713a09ce3f3189 /src/server/handler.rs | |
| parent | aa041cc4a6d2ed4c817eadfdd36d3bd73d0f0cf1 (diff) | |
correctly adhere to spec in most request cases
Diffstat (limited to 'src/server/handler.rs')
| -rw-r--r-- | src/server/handler.rs | 31 |
1 files changed, 24 insertions, 7 deletions
diff --git a/src/server/handler.rs b/src/server/handler.rs index f32a015..db45073 100644 --- a/src/server/handler.rs +++ b/src/server/handler.rs @@ -20,11 +20,10 @@ fn send_header(stream: &mut SslStream<TcpStream>, header: &response::Header) { } pub fn handle_request(config: &ServerConfig, mut stream: SslStream<TcpStream>) { - let mut buffer = [0; 1026]; + let mut buffer = [0; 1024]; match stream.ssl_read(&mut buffer) { Ok(s) => { - if s == 0 { - println!("received empty request buffer"); + if s == 0 || s > 1025 { send_header(&mut stream, &response::bad_request()); return; } @@ -47,7 +46,11 @@ pub fn handle_request(config: &ServerConfig, mut stream: SslStream<TcpStream>) { let location = match Url::parse(&request) { Ok(url) => url, - Err(_) => config.default_host.join(&request).unwrap(), + Err(_) => { + println!("received invalid request url"); + send_header(&mut stream, &response::bad_request()); + return; + }, }; handle_response(config, location, &mut stream); @@ -69,25 +72,39 @@ fn write_line<T: Write>(line: &[u8], stream: &mut BufWriter<T>) -> Result<(), Er fn handle_response(config: &ServerConfig, url: Url, mut stream: &mut SslStream<TcpStream>) { println!("responding for: {}", url); - if url.scheme() != "gemini" { - send_header(&mut stream, &response::permanent_failure()); + // url scheme must be either "gemini://" or "//" (empty) + if url.scheme() != "gemini" && url.scheme() != "" { + send_header(&mut stream, &response::proxy_request_refused()); return; } + // url request host must match if url.host() != config.default_host.host() { send_header(&mut stream, &response::proxy_request_refused()); return; } + // TODO: also drop on incorrect port in request + let rel_path = match Path::new(url.path()).strip_prefix("/") { Ok(path) => path, Err(_) => { - Path::new("") + // empty path, gemini spec says to redirect client to root + send_header(&mut stream, &response::redirect_permanent( + config.default_host.as_str(), + )); + return; } }; let path = gen_path_index(&config.gem_root.join(rel_path)); + // make sure we can't escape gem_root + if !path.starts_with(&config.gem_root) { + send_header(&mut stream, &response::bad_request()); + return; + } + let file = match File::open(&path) { Ok(file) => file, Err(_) => { |
