Browse Source

chore(gempress): migrate to openssl

main
Garrit Franke 3 years ago
parent
commit
f425656615
Signed by: garrit
GPG Key ID: 65586C4DDA55EA2C
  1. 207
      Cargo.lock
  2. 4
      README.md
  3. 2
      lib/gempress/Cargo.toml
  4. 6
      lib/gempress/make_cert.sh
  5. 2
      lib/gempress/src/error.rs
  6. 19
      lib/gempress/src/gemini.rs
  7. 9
      lib/gempress/src/io.rs
  8. 45
      lib/gempress/src/lib.rs
  9. 20
      src/main.rs

207
Cargo.lock generated

@ -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"

4
README.md

@ -0,0 +1,4 @@
# Astrofarm
A farming simulator for the gemini web.

2
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"

6
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

2
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),

19
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<X509>,
}
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<X509> = None;
Ok(Self { url, certificate })
}
}
@ -83,11 +88,11 @@ pub struct Response {
pub status_code: StatusCode,
pub meta: Vec<u8>,
pub body: Vec<u8>,
stream: TlsStream<TcpStream>,
stream: SslStream<TcpStream>,
}
impl Response {
pub(crate) fn new(stream: TlsStream<TcpStream>) -> Self {
pub(crate) fn new(stream: SslStream<TcpStream>) -> Self {
Self {
status_code: StatusCode::Success,
meta: "text/gemini".into(),

9
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<Vec<u8>, io::Error> {
Ok(buf)
}
/// Read certificate file
pub fn load_cert(cert_file: &str, password: &str) -> GempressResult<Identity> {
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.

45
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<F: Fn()>(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<TcpStream>) -> GempressResult<()> {
fn handle_client(&self, mut stream: SslStream<TcpStream>) -> 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(())

20
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: Hash>(t: &T) -> u64 {
let mut s = DefaultHasher::new();
t.hash(&mut s);
s.finish()
}
fn index_handler(req: Box<gemini::Request>, mut res: Box<gemini::Response>) -> 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);

Loading…
Cancel
Save