agate

Simple gemini server for static files
git clone https://github.com/mbrubeck/agate.git
Log | Files | Refs | README

commit 8fd9ca15c3df8757b0268f9be49a952142fb333f
parent fb0a30e5fc9ee6136ed627e3059647ee6b52bb35
Author: Johann150 <johann.galle@protonmail.com>
Date:   Wed, 10 Feb 2021 23:34:40 +0100

better error message for missing keys (again)

adresses comments from #33
Loading the certificate and key file is done at startup because:
1. We can detect the incorrect file faster and fail the whole server and not
   just a worker thread. All subsequent worker threads would fail for the same
   reason anyway.
2. We do not have to read the same unchanged files over and over again. This
   is good because file I/O is slower than in-memory cloning instead.

Diffstat:
MCHANGELOG.md | 2++
Msrc/main.rs | 34+++++++++++++++++++++-------------
2 files changed, 23 insertions(+), 13 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md @@ -16,9 +16,11 @@ Thank you to @gegeweb for contributing to this release. ### Changed * The changelog is now also kept in this file in addition to the GitHub releases. +* Certificate chain and key file are now only loaded once at startup, certificate changes need a restart to take effect. ### Fixed * The Syntax for the IPv6 address in the README has been corrected. +* Give a better error message when no keys are found in the key file instead of panicking with a range check. ## [2.4.1] - 2020-02-08 ### Fixed diff --git a/src/main.rs b/src/main.rs @@ -6,7 +6,7 @@ use { percent_encoding::{percent_decode_str, percent_encode, AsciiSet, CONTROLS}, rustls::{ internal::pemfile::{certs, pkcs8_private_keys}, - NoClientAuth, ServerConfig, + Certificate, NoClientAuth, PrivateKey, ServerConfig, }, std::{ borrow::Cow, error::Error, ffi::OsStr, fmt::Write, fs::File, io::BufReader, @@ -68,8 +68,8 @@ static ARGS: Lazy<Args> = Lazy::new(|| { struct Args { addrs: Vec<SocketAddr>, content_dir: String, - cert_file: String, - key_file: String, + cert_chain: Vec<Certificate>, + key: PrivateKey, hostnames: Vec<Host>, language: Option<String>, silent: bool, @@ -150,11 +150,26 @@ fn args() -> Result<Args> { "0.0.0.0:1965".parse().unwrap(), ]; } + + let cert_file = File::open(check_path( + matches.opt_get_default("cert", "cert.pem".into())?, + )?)?; + let cert_chain = certs(&mut BufReader::new(cert_file)).or(Err("bad cert"))?; + + let key_file = File::open(check_path( + matches.opt_get_default("key", "key.rsa".into())?, + )?)?; + let key = pkcs8_private_keys(&mut BufReader::new(key_file)) + .or(Err("bad key file"))? + .drain(..) + .next() + .ok_or("no keys found")?; + Ok(Args { addrs, content_dir: check_path(matches.opt_get_default("content", "content".into())?)?, - cert_file: check_path(matches.opt_get_default("cert", "cert.pem".into())?)?, - key_file: check_path(matches.opt_get_default("key", "key.rsa".into())?)?, + cert_chain, + key, hostnames, language: matches.opt_str("lang"), silent: matches.opt_present("s"), @@ -176,18 +191,11 @@ fn check_path(s: String) -> Result<String, String> { static TLS: Lazy<TlsAcceptor> = Lazy::new(|| acceptor().unwrap()); fn acceptor() -> Result<TlsAcceptor> { - let cert_file = File::open(&ARGS.cert_file)?; - let certs = certs(&mut BufReader::new(cert_file)).or(Err("bad cert"))?; - - let key_file = File::open(&ARGS.key_file)?; - let mut keys = pkcs8_private_keys(&mut BufReader::new(key_file)).or(Err("bad key"))?; - let mut config = ServerConfig::new(NoClientAuth::new()); if ARGS.only_tls13 { config.versions = vec![rustls::ProtocolVersion::TLSv1_3]; } - assert!(!keys.is_empty(), "no valid keys"); - config.set_single_cert(certs, keys.remove(0))?; + config.set_single_cert(ARGS.cert_chain.clone(), ARGS.key.clone())?; Ok(TlsAcceptor::from(Arc::new(config))) }