]> git.scottworley.com Git - voter/blob - src/main.rs
Path validation
[voter] / src / main.rs
1 use std::path::{Path, PathBuf};
2
3 const DATA_PATH: &str = "/var/lib/voter";
4
5 fn validate_path(path: &str) -> Result<PathBuf, cgi::Response> {
6 let invalid_path = || cgi::text_response(404, "Invalid path");
7 if path == "/" {
8 return Err(cgi::text_response(404, "(This is the voting place. You should have been given a more specific URL for the specific thing you've been invited to vote on.)"));
9 }
10 if path.contains("..") || !path.starts_with("/") {
11 return Err(invalid_path());
12 }
13 let dir = Path::new(&format!("{DATA_PATH}{path}")).to_path_buf();
14 if !dir
15 .canonicalize()
16 .map_err(|_| invalid_path())?
17 .starts_with(DATA_PATH)
18 {
19 return Err(invalid_path());
20 }
21 if !dir.is_dir() {
22 return Err(invalid_path());
23 }
24 Ok(dir)
25 }
26
27 fn prompt_for_vote(dir: PathBuf, request: cgi::Request) -> Result<cgi::Response, cgi::Response> {
28 Err(cgi::text_response(503, "Not Implemented"))
29 }
30
31 fn record_vote(dir: PathBuf, request: cgi::Request) -> Result<cgi::Response, cgi::Response> {
32 Err(cgi::text_response(503, "Not Implemented"))
33 }
34
35 fn respond(request: cgi::Request) -> Result<cgi::Response, cgi::Response> {
36 let dir = validate_path(request.uri().path())?;
37 match request.method() {
38 &cgi::http::Method::GET => prompt_for_vote(dir, request),
39 &cgi::http::Method::POST => record_vote(dir, request),
40 _ => Err(cgi::text_response(405, "Huh?")),
41 }
42 }
43
44 fn respond_or_report_error(request: cgi::Request) -> cgi::Response {
45 match respond(request) {
46 Ok(result) => result,
47 Err(error) => error,
48 }
49 }
50
51 cgi::cgi_main! { respond_or_report_error }