Timeout for request and cgi

This commit is contained in:
int 80h
2020-05-22 15:12:28 -04:00
parent e80abd0553
commit 12ed0e7c03
3 changed files with 36 additions and 13 deletions

View File

@@ -7,7 +7,7 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
tokio = { version = "0.2", features = [ "net", "io-util", "rt-threaded" ] } tokio = { version = "0.2", features = [ "time", "fs", "process", "net", "io-util", "rt-threaded" ] }
openssl = "0.10" openssl = "0.10"
tokio-openssl = "0.4" tokio-openssl = "0.4"
futures-util = "0.3" futures-util = "0.3"

View File

@@ -1,7 +1,7 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::io; use std::io;
use std::path::PathBuf; use std::path::PathBuf;
use std::process::Command; use tokio::process::Command;
use url::Url; use url::Url;
use crate::config; use crate::config;
@@ -44,8 +44,27 @@ pub async fn cgi(
let cmd = Command::new(path.to_str().unwrap()) let cmd = Command::new(path.to_str().unwrap())
.env_clear() .env_clear()
.envs(&envs) .envs(&envs)
.output() .output();
.unwrap();
let cmd = match tokio::time::timeout(tokio::time::Duration::from_secs(5), cmd).await {
Ok(c) => {
match c {
Ok(cc) => cc,
Err(_) => {
logger::logger(con.peer_addr, Status::CGIError, url.as_str());
con.send_status(Status::CGIError, None).await?;
return Ok(());
},
}
},
Err(_) => {
logger::logger(con.peer_addr, Status::CGIError, url.as_str());
con.send_status(Status::CGIError, None).await?;
return Ok(());
},
};
if !cmd.status.success() { if !cmd.status.success() {
logger::logger(con.peer_addr, Status::CGIError, url.as_str()); logger::logger(con.peer_addr, Status::CGIError, url.as_str());
con.send_status(Status::CGIError, None).await?; con.send_status(Status::CGIError, None).await?;

View File

@@ -66,10 +66,10 @@ async fn get_binary(mut con: conn::Connection, path: PathBuf, meta: String) -> i
Ok(()) Ok(())
} }
fn get_content(path: PathBuf, u: url::Url) -> Result<String, io::Error> { async fn get_content(path: PathBuf, u: url::Url) -> Result<String, io::Error> {
let meta = fs::metadata(&path).expect("Unable to read metadata"); let meta = tokio::fs::metadata(&path).await?;
if meta.is_file() { if meta.is_file() {
return Ok(std::fs::read_to_string(path).expect("Unable to read file")); return Ok(tokio::fs::read_to_string(path).await?);
} }
let mut list = String::from("# Directory Listing\r\n\r\n"); let mut list = String::from("# Directory Listing\r\n\r\n");
@@ -104,7 +104,11 @@ async fn handle_connection(
None => "index.gemini".to_string(), None => "index.gemini".to_string(),
}; };
let mut buffer = [0; 1024]; let mut buffer = [0; 1024];
con.stream.read(&mut buffer).await?; if let Err(_) = tokio::time::timeout(tokio::time::Duration::from_secs(5), con.stream.read(&mut buffer)).await {
logger::logger(con.peer_addr, Status::BadRequest, "");
con.send_status(Status::BadRequest, None).await?;
return Ok(());
}
let mut request = match String::from_utf8(buffer[..].to_vec()) { let mut request = match String::from_utf8(buffer[..].to_vec()) {
Ok(request) => request, Ok(request) => request,
Err(_) => { Err(_) => {
@@ -201,7 +205,7 @@ async fn handle_connection(
return Ok(()); return Ok(());
} }
let mut meta = fs::metadata(&path).expect("Unable to read metadata"); let mut meta = tokio::fs::metadata(&path).await?;
let mut perm = meta.permissions(); let mut perm = meta.permissions();
// TODO fix me // TODO fix me
@@ -218,19 +222,18 @@ async fn handle_connection(
} }
if path.join(&index).exists() { if path.join(&index).exists() {
path.push(index); path.push(index);
meta = fs::metadata(&path).expect("Unable to read metadata"); meta = tokio::fs::metadata(&path).await?;
perm = meta.permissions(); perm = meta.permissions();
if perm.mode() & 0o0444 != 0o444 { if perm.mode() & 0o0444 != 0o444 {
let mut p = path.clone(); let mut p = path.clone();
p.pop(); p.pop();
path.push(format!("{}/", p.display())); path.push(format!("{}/", p.display()));
meta = fs::metadata(&path).expect("Unable to read metadata"); meta = tokio::fs::metadata(&path).await?;
perm = meta.permissions(); perm = meta.permissions();
} }
} }
} }
// TODO add timeout
match &srv.server.cgi { match &srv.server.cgi {
Some(c) => { Some(c) => {
if c.trim_end_matches("/") == path.parent().unwrap().to_str().unwrap() { if c.trim_end_matches("/") == path.parent().unwrap().to_str().unwrap() {
@@ -259,7 +262,7 @@ async fn handle_connection(
get_binary(con, path, mime).await?; get_binary(con, path, mime).await?;
return Ok(()); return Ok(());
} }
let content = get_content(path, url)?; let content = get_content(path, url).await?;
con.send_body(status::Status::Success, Some(&mime), Some(content)) con.send_body(status::Status::Success, Some(&mime), Some(content))
.await?; .await?;
logger::logger(con.peer_addr, Status::Success, &request); logger::logger(con.peer_addr, Status::Success, &request);
@@ -293,6 +296,7 @@ fn main() -> io::Result<()> {
let mut runtime = runtime::Builder::new() let mut runtime = runtime::Builder::new()
.threaded_scheduler() .threaded_scheduler()
.enable_io() .enable_io()
.enable_time()
.build()?; .build()?;
let handle = runtime.handle().clone(); let handle = runtime.handle().clone();