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.
This commit is contained in:
Johann150 2021-02-10 23:34:40 +01:00
parent fb0a30e5fc
commit 8fd9ca15c3
No known key found for this signature in database
GPG key ID: 9EE6577A2A06F8F1
2 changed files with 23 additions and 13 deletions

View file

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

View file

@ -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)))
}