diff --git a/Cargo.lock b/Cargo.lock index e8964c3..bdbf591 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -31,22 +31,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "core-foundation" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a89e2ae426ea83155dccf10c0fa6b1463ef6d5fcb44cee0b224a408fa640a62" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b" - [[package]] name = "foreign-types" version = "0.3.2" @@ -76,22 +60,11 @@ dependencies = [ name = "gempress" version = "0.1.1" dependencies = [ - "native-tls", + "openssl", "thiserror", "url", ] -[[package]] -name = "getrandom" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - [[package]] name = "idna" version = "0.2.3" @@ -103,51 +76,18 @@ dependencies = [ "unicode-normalization", ] -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - [[package]] name = "libc" version = "0.2.101" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3cb00336871be5ed2c8ed44b60ae9959dc5b9f08539422ed43f09e34ecaeba21" -[[package]] -name = "log" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" -dependencies = [ - "cfg-if", -] - [[package]] name = "matches" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" -[[package]] -name = "native-tls" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48ba9f7719b5a0f42f338907614285fb5fd70e53858141f69898a1fb7203b24d" -dependencies = [ - "lazy_static", - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - [[package]] name = "once_cell" version = "1.8.0" @@ -168,12 +108,6 @@ dependencies = [ "openssl-sys", ] -[[package]] -name = "openssl-probe" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28988d872ab76095a6e6ac88d99b54fd267702734fd7ffe610ca27f533ddb95a" - [[package]] name = "openssl-sys" version = "0.9.66" @@ -199,12 +133,6 @@ version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" -[[package]] -name = "ppv-lite86" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" - [[package]] name = "proc-macro2" version = "1.0.29" @@ -223,97 +151,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "rand" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", - "rand_hc", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" -dependencies = [ - "getrandom", -] - -[[package]] -name = "rand_hc" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" -dependencies = [ - "rand_core", -] - -[[package]] -name = "redox_syscall" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" -dependencies = [ - "bitflags", -] - -[[package]] -name = "remove_dir_all" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" -dependencies = [ - "winapi", -] - -[[package]] -name = "schannel" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" -dependencies = [ - "lazy_static", - "winapi", -] - -[[package]] -name = "security-framework" -version = "2.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525bc1abfda2e1998d152c45cf13e696f76d0a4972310b22fac1658b05df7c87" -dependencies = [ - "bitflags", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9dd14d83160b528b7bfd66439110573efcfbe281b17fc2ca9f39f550d619c7e" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "syn" version = "1.0.76" @@ -325,20 +162,6 @@ dependencies = [ "unicode-xid", ] -[[package]] -name = "tempfile" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" -dependencies = [ - "cfg-if", - "libc", - "rand", - "redox_syscall", - "remove_dir_all", - "winapi", -] - [[package]] name = "thiserror" version = "1.0.28" @@ -412,31 +235,3 @@ name = "vcpkg" version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - -[[package]] -name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/README.md b/README.md index e69de29..345eb7c 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,4 @@ +# Astrofarm + +A farming simulator for the gemini web. + diff --git a/lib/gempress/Cargo.toml b/lib/gempress/Cargo.toml index 8902980..b17e2de 100644 --- a/lib/gempress/Cargo.toml +++ b/lib/gempress/Cargo.toml @@ -11,6 +11,6 @@ repository = "https://github.com/garritfra/astrofarm/tree/main/lib/gempress" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -native-tls = "0.2.8" +openssl = "0.10.36" thiserror = "1.0.28" url = "2.2.2" diff --git a/lib/gempress/make_cert.sh b/lib/gempress/make_cert.sh index 8114045..fbcb524 100755 --- a/lib/gempress/make_cert.sh +++ b/lib/gempress/make_cert.sh @@ -1,7 +1 @@ openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes -subj '/CN=localhost' - -openssl pkcs12 -export -out identity.pfx -inkey key.pem -in cert.pem - -# Cleanup -rm key.pem cert.pem - diff --git a/lib/gempress/src/error.rs b/lib/gempress/src/error.rs index ec861c8..dad836e 100644 --- a/lib/gempress/src/error.rs +++ b/lib/gempress/src/error.rs @@ -9,7 +9,7 @@ pub enum GempressError { NoIdentity(io::Error), #[error("failed parse certificate: {0:#?}")] - InvalidCertificate(#[from] native_tls::Error), + InvalidCertificate(#[from] openssl::error::Error), #[error("invalid request: {0}")] InvalidRequest(String), diff --git a/lib/gempress/src/gemini.rs b/lib/gempress/src/gemini.rs index 94d1058..7de09f6 100644 --- a/lib/gempress/src/gemini.rs +++ b/lib/gempress/src/gemini.rs @@ -1,8 +1,11 @@ use std::fmt; -use crate::error::{GempressError, GempressResult}; -use native_tls::TlsStream; -use std::{io::Write, net::TcpStream, str::FromStr}; + +use openssl::ssl::SslStream; +use openssl::x509::X509; + use url::Url; +use std::{io::Write, net::TcpStream, str::FromStr}; +use crate::error::{GempressError, GempressResult}; /// Gemini status codes as defined in Appendix 1 /// TODO: fill out remaining codes @@ -19,10 +22,10 @@ impl fmt::Display for StatusCode { } /// A gemini request -#[derive(Debug, PartialEq, Eq)] pub struct Request { /// The requested resource path pub url: Url, + pub certificate: Option, } impl Request { @@ -74,7 +77,9 @@ impl FromStr for Request { let url = Url::parse(&raw) .map_err(|e| GempressError::InvalidRequest(format!("invalid url: {}", e)))?; - Ok(Self { url }) + let certificate: Option = None; + + Ok(Self { url, certificate }) } } @@ -83,11 +88,11 @@ pub struct Response { pub status_code: StatusCode, pub meta: Vec, pub body: Vec, - stream: TlsStream, + stream: SslStream, } impl Response { - pub(crate) fn new(stream: TlsStream) -> Self { + pub(crate) fn new(stream: SslStream) -> Self { Self { status_code: StatusCode::Success, meta: "text/gemini".into(), diff --git a/lib/gempress/src/io.rs b/lib/gempress/src/io.rs index 6625d36..b237284 100644 --- a/lib/gempress/src/io.rs +++ b/lib/gempress/src/io.rs @@ -1,5 +1,4 @@ use crate::error::{GempressError, GempressResult}; -use native_tls::Identity; use std::fs::File; use std::io::{self, Read}; use std::path::Path; @@ -14,14 +13,6 @@ pub fn read_file(file_path: &str) -> Result, io::Error> { Ok(buf) } -/// Read certificate file -pub fn load_cert(cert_file: &str, password: &str) -> GempressResult { - let identity = read_file(&cert_file).map_err(GempressError::NoIdentity)?; - let identity = Identity::from_pkcs12(&identity, &password)?; - - Ok(identity) -} - /// Resolve path to a file, returning index.gmi if a subdirectory is encountered /// /// If path points to a file, it is returned. diff --git a/lib/gempress/src/lib.rs b/lib/gempress/src/lib.rs index 78d6f98..18b3c59 100644 --- a/lib/gempress/src/lib.rs +++ b/lib/gempress/src/lib.rs @@ -1,4 +1,4 @@ -extern crate native_tls; +extern crate openssl; /// Types representing the gemini specification pub mod gemini; @@ -14,14 +14,14 @@ use std::path::PathBuf; use std::sync::Arc; pub use error::{GempressError, GempressResult}; -use native_tls::{TlsAcceptor, TlsStream}; +use openssl::ssl::{SslMethod, SslAcceptor, SslStream, SslFiletype}; /// Configuration for a Gempress server. #[derive(Clone, Debug)] pub struct Config { // Path to the identity file - identityPath: PathBuf, - password: String, + certPath: PathBuf, + keyPath: PathBuf, } impl Config { @@ -44,10 +44,10 @@ impl Config { /// let config = gempress::Config::from_identity(PathBuf::from("identity.pfx"), "password".into()); /// let mut app = Gempress::new(config); /// ``` - pub fn from_identity(identityPath: PathBuf, password: String) -> Self { + pub fn new(certPath: PathBuf, keyPath: PathBuf) -> Self { Self { - identityPath, - password, + certPath, + keyPath, } } } @@ -156,17 +156,13 @@ impl Gempress { /// Bind the server to a network port, then execute the callback pub fn listen(self, port: u16, callback: F) -> GempressResult<()> { - // Read certificate - // TODO: Can a password be optional? - let identity = io::load_cert( - &self.config.identityPath.to_str().unwrap_or(""), - &self.config.password, - )?; - - let address = format!("0.0.0.0:{}", port); - let listener = TcpListener::bind(address).map_err(GempressError::BindFailed)?; - let acceptor = TlsAcceptor::new(identity).unwrap(); - let acceptor = Arc::new(acceptor); + let mut acceptor = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap(); + acceptor.set_private_key_file(&self.config.keyPath, SslFiletype::PEM).unwrap(); + acceptor.set_certificate_chain_file(&self.config.certPath).unwrap(); + acceptor.check_private_key().unwrap(); + let acceptor = Arc::new(acceptor.build()); + + let listener = TcpListener::bind(format!("0.0.0.0:{}", port)).map_err(GempressError::BindFailed)?; logger::info(format!("Listening on port {}", port)); @@ -195,7 +191,7 @@ impl Gempress { Ok(()) } - fn handle_client(&self, mut stream: TlsStream) -> GempressResult<()> { + fn handle_client(&self, mut stream: SslStream) -> GempressResult<()> { let mut buffer = [0; 1024]; stream @@ -204,19 +200,22 @@ impl Gempress { let raw_request = String::from_utf8(buffer.to_vec())?; - let request = gemini::Request::parse(&raw_request)?; + let mut request = gemini::Request::parse(&raw_request)?; + + request.certificate = None; // TODO + let mut response = gemini::Response::new(stream); + response.status(gemini::StatusCode::Success)?; let maybe_layer = self .stack .iter() .find(|&l| l.path == request.url.path()); - response.status(gemini::StatusCode::Success)?; match maybe_layer { - Some(layer) => { (layer.handler)(Box::new(request), Box::new(response)); }, - None => { response.status(gemini::StatusCode::NotFound)?.send("Not found".as_bytes()); }, + Some(layer) => { (layer.handler)(Box::new(request), Box::new(response))?; }, + None => { response.status(gemini::StatusCode::NotFound)?.send("Not found".as_bytes())?; }, }; Ok(()) diff --git a/src/main.rs b/src/main.rs index c450108..0cd4fc3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,18 +5,30 @@ use gempress::error::GempressResult; use gempress::gemini; use gempress::gemini::StatusCode; use std::path::PathBuf; +use std::hash::{Hash, Hasher}; +use std::collections::hash_map::DefaultHasher; + +fn calculate_hash(t: &T) -> u64 { + let mut s = DefaultHasher::new(); + t.hash(&mut s); + s.finish() +} fn index_handler(req: Box, mut res: Box) -> GempressResult<()>{ - res.status(StatusCode::Success)?.send(br#" + let response = format!(r#" # Astrofarm -Hello from index route! - "#)?; +Hello, {} + "#, "user"); + + println!("Index handler"); + + res.status(StatusCode::Success)?.send(response.as_bytes())?; Ok(()) } fn main() { // Run make_cert.sh to generate a certificate - let config = gempress::Config::from_identity(PathBuf::from("identity.pfx"), "password".into()); + let config = gempress::Config::new(PathBuf::from("cert.pem"), PathBuf::from("key.pem")); let mut app = Gempress::new(config);