Allow Passwords for server

This commit is contained in:
p11 2024-02-09 22:59:53 +01:00
parent 5020406acc
commit ef1afa42fa

View File

@ -31,10 +31,11 @@ fn main() {
let mut args = env::args(); let mut args = env::args();
args.next(); args.next();
let address = args.next().unwrap_or("127.0.0.1:8080".to_string()); let address = args.next().unwrap_or("127.0.0.1:8080".to_string());
start_server(path, &address); let password = args.next();
start_server(path, &address, password);
} }
fn start_server(path: PathBuf, address: &str) { fn start_server(path: PathBuf, address: &str, password: Option<String>) {
let listener = TcpListener::bind(address).expect("Invalid bind address!"); let listener = TcpListener::bind(address).expect("Invalid bind address!");
eprintln!("Strated server!"); eprintln!("Strated server!");
@ -58,7 +59,8 @@ fn start_server(path: PathBuf, address: &str) {
let context = context.clone(); let context = context.clone();
let path = path.clone(); let path = path.clone();
pool.execute(move || handle_connection(context, path, stream)); let password = password.clone();
pool.execute(move || handle_connection(context, path, stream, password.as_deref()));
} }
} }
@ -139,7 +141,12 @@ struct Context {
infos: HashMap<Box<str>, Arc<Mutex<SiteInfo>>>, infos: HashMap<Box<str>, Arc<Mutex<SiteInfo>>>,
} }
fn handle_connection(context: Arc<Mutex<Context>>, path: PathBuf, mut stream: TcpStream) { fn handle_connection(
context: Arc<Mutex<Context>>,
path: PathBuf,
mut stream: TcpStream,
password: Option<&str>,
) {
let Some(request) = Request::from(&stream) else { let Some(request) = Request::from(&stream) else {
eprintln!("Invalid request!"); eprintln!("Invalid request!");
return; return;
@ -151,12 +158,86 @@ fn handle_connection(context: Arc<Mutex<Context>>, path: PathBuf, mut stream: Tc
eprintln!("- Path: {}", request.path); eprintln!("- Path: {}", request.path);
eprintln!("- Version: {}", request.version); eprintln!("- Version: {}", request.version);
eprintln!("- Headers:"); eprintln!("- Headers:");
for header in request.headers { for header in &request.headers {
eprintln!(" - {header}"); eprintln!(" - {header}");
} }
eprintln!("- Body: {}", request.body); eprintln!("- Body: {}", request.body);
eprintln!(); eprintln!();
#[derive(PartialEq, Eq)]
enum Access {
None,
Full,
}
let mut access = Access::None;
let mut cookie = None;
if let Some(password) = password {
for entry in request.body.split('&') {
let Some((key, input)) = entry.split_once('=') else {
continue;
};
if key == "password" && input == password {
access = Access::Full;
cookie = Some(password);
break;
}
}
if access == Access::None {
for header in request.headers {
let Some((key, values)) = header.split_once(':') else {
continue;
};
let key = key.trim();
if key != "Cookie" {
continue;
}
for cookie in values.split(',') {
let cookie = cookie.trim();
let Some((name, state)) = cookie.split_once('=') else {
continue;
};
if name != "password" {
continue;
}
if state != password {
continue;
}
access = Access::Full;
break;
}
}
}
if access == Access::None {
let _ = write!(stream, "HTTP/1.1 200 OK\r\n");
let _ = write!(stream, "Content-Type: text/html; charset=\"utf-8\"\r\n");
let _ = write!(stream, "\r\n");
let html = html! {
h1 { "Authentification required" }
form method="POST" {
input type="password" name="password" placeholder="Password";
br;
input type="submit" value="Authenticate!";
}
};
let _ = stream.write_all(html.into_string().as_bytes());
return;
}
}
let (mut relative_path, _) = request let (mut relative_path, _) = request
.path .path
.split_once('?') .split_once('?')
@ -261,6 +342,7 @@ fn handle_connection(context: Arc<Mutex<Context>>, path: PathBuf, mut stream: Tc
file_paths, file_paths,
partial, partial,
start_level, start_level,
cookie,
) )
} }
@ -301,6 +383,7 @@ fn handle_relative_connection(
file_paths: DocumentPaths, file_paths: DocumentPaths,
partial: Option<usize>, partial: Option<usize>,
start_level: usize, start_level: usize,
cookie: Option<&str>,
) { ) {
let mut name = None; let mut name = None;
let mut text = None; let mut text = None;
@ -374,6 +457,10 @@ fn handle_relative_connection(
let _ = write!(stream, "HTTP/1.1 200 OK\r\n"); let _ = write!(stream, "HTTP/1.1 200 OK\r\n");
let _ = write!(stream, "Content-Type: text/html; charset=\"utf-8\"\r\n"); let _ = write!(stream, "Content-Type: text/html; charset=\"utf-8\"\r\n");
if let Some(password) = cookie {
let _ = write!(stream, "Set-Cookie: password={password}\r\n");
}
let _ = write!(stream, "\r\n"); let _ = write!(stream, "\r\n");
let parent_path = relative_path let parent_path = relative_path