~int80h/gemserv

827a9c148193b9726fbd9ffa4c1a02661b12ff7a — int 80h 4 months ago eb12946 master v0.6.6
Bug fix: File path is checked to make sure it's in the root directory or in ~/public_gemini
5 files changed, 71 insertions(+), 2 deletions(-)

M Cargo.lock
M Cargo.toml
M README
M src/con_handler.rs
M src/main.rs
M Cargo.lock => Cargo.lock +29 -1
@@ 7,6 7,15 @@ name = "agena-cgi"
version = "0.1.0"

[[package]]
name = "aho-corasick"
version = "0.7.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
dependencies = [
 "memchr",
]

[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"


@@ 186,12 195,14 @@ dependencies = [

[[package]]
name = "gemserv"
version = "0.6.5"
version = "0.6.6"
dependencies = [
 "futures-util",
 "lazy_static",
 "log",
 "mime",
 "new_mime_guess",
 "regex",
 "rustls-pemfile",
 "serde",
 "serde_derive",


@@ 504,6 515,23 @@ dependencies = [
]

[[package]]
name = "regex"
version = "1.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
dependencies = [
 "aho-corasick",
 "memchr",
 "regex-syntax",
]

[[package]]
name = "regex-syntax"
version = "0.6.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"

[[package]]
name = "ring"
version = "0.16.20"
source = "registry+https://github.com/rust-lang/crates.io-index"

M Cargo.toml => Cargo.toml +3 -1
@@ 1,6 1,6 @@
[package]
name = "gemserv"
version = "0.6.5"
version = "0.6.6"
authors = ["int 80h <int@80h.dev>"]
edition = "2018"
description = "A gemini server"


@@ 27,6 27,8 @@ log = "0.4.14"
simple_logger = "1.16"
sha2 = "0.9.8"
x509-parser = "0.12"
regex = "1.5.4"
lazy_static = "1.4.0"

[dependencies.tokio-rustls]
version = "0.23.2"

M README => README +4 -0
@@ 78,6 78,10 @@ TLS variables

## Changelog

### [0.6.6] - 20220217

Bug fix: File path is checked to make sure it's in the root directory or in ~/public_gemini

### [0.6.5] - 20220209

Bug fix: Another traversal bug.

M src/con_handler.rs => src/con_handler.rs +33 -0
@@ 3,6 3,7 @@ use std::path::{Path, PathBuf};
use tokio::fs::{self, File};
use tokio::io::{self, AsyncBufReadExt, AsyncWrite, BufReader};
use url::Url;
use regex::Regex;

#[cfg(any(feature = "cgi", feature = "scgi"))]
use crate::cgi;


@@ 15,6 16,7 @@ use crate::util;

type Result<T = ()> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>;


fn get_mime(path: &Path) -> String {
    let mut mime = "text/gemini".to_string();
    if path.is_dir() {


@@ 248,6 250,37 @@ pub async fn handle_connection(mut con: conn::Connection, url: url::Url) -> Resu
        }
    }

    match path.canonicalize() {
        Ok(p) => {
            if !p.starts_with(&con.srv.server.dir) {
                if con.srv.server.usrdir.unwrap_or(false) {
                    #[cfg(target_os = "macos")]
                    lazy_static! {
                        static ref RE: Regex = Regex::new(r"^/Users/([^/]*)/public_gemini(.*)").unwrap();
                    }
                    #[cfg(not(target_os = "macos"))]
                    lazy_static! {
                        static ref RE: Regex = Regex::new(r"^/home/([^/]*)/public_gemini(.*)").unwrap();
                    }
                    if !RE.is_match(p.to_str().unwrap()) {
                        logger::logger(con.peer_addr, Status::NotFound, url.as_str());
                        con.send_status(Status::NotFound, None).await?;
                        return Ok(());
                    }
                } else {
                    logger::logger(con.peer_addr, Status::NotFound, url.as_str());
                    con.send_status(Status::NotFound, None).await?;
                    return Ok(());
                }
            }
        },
        Err(_) => {
            logger::logger(con.peer_addr, Status::NotFound, url.as_str());
            con.send_status(Status::NotFound, None).await?;
            return Ok(());
        },
    }

    if !path.exists() {
        // See if it's a subpath of a CGI script before returning NotFound
        #[cfg(feature = "cgi")]

M src/main.rs => src/main.rs +2 -0
@@ 1,5 1,7 @@
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate lazy_static;

#[cfg(any(feature = "cgi", feature = "scgi"))]
mod cgi;