]> git.scottworley.com Git - voter/blame - src/main.rs
Path validation
[voter] / src / main.rs
CommitLineData
c8402f1c 1use std::path::{Path, PathBuf};
d1df2e73 2
c8402f1c
SW
3const DATA_PATH: &str = "/var/lib/voter";
4
5fn 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
27fn prompt_for_vote(dir: PathBuf, request: cgi::Request) -> Result<cgi::Response, cgi::Response> {
28 Err(cgi::text_response(503, "Not Implemented"))
29}
30
31fn record_vote(dir: PathBuf, request: cgi::Request) -> Result<cgi::Response, cgi::Response> {
32 Err(cgi::text_response(503, "Not Implemented"))
33}
34
35fn 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
44fn respond_or_report_error(request: cgi::Request) -> cgi::Response {
45 match respond(request) {
46 Ok(result) => result,
47 Err(error) => error,
48 }
d1df2e73
SW
49}
50
c8402f1c 51cgi::cgi_main! { respond_or_report_error }