use std::fs::File;
use std::io;
use std::path::Path;
use std::sync::Arc;
use rustls::ServerConfig;
use rustls::pki_types::pem::PemObject;
use rustls::pki_types::{CertificateDer, PrivateKeyDer};
pub fn build_server_config(cert_path: &Path, key_path: &Path) -> io::Result<Arc<ServerConfig>> {
let certs = load_certs(cert_path)?;
let key = load_key(key_path)?;
ServerConfig::builder()
.with_no_client_auth()
.with_single_cert(certs, key)
.map(Arc::new)
.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, format!("tls: {err}")))
}
fn load_certs(path: &Path) -> io::Result<Vec<CertificateDer<'static>>> {
let file = File::open(path).map_err(|err| {
io::Error::new(
err.kind(),
format!("tls: open certificate {}: {err}", path.display()),
)
})?;
let certs = CertificateDer::pem_reader_iter(file)
.collect::<Result<Vec<_>, _>>()
.map_err(|err| {
io::Error::new(
io::ErrorKind::InvalidData,
format!("tls: parse certificate {}: {err}", path.display()),
)
})?;
if certs.is_empty() {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
format!("tls: no certificates in {}", path.display()),
));
}
Ok(certs)
}
fn load_key(path: &Path) -> io::Result<PrivateKeyDer<'static>> {
let file = File::open(path).map_err(|err| {
io::Error::new(
err.kind(),
format!("tls: open private key {}: {err}", path.display()),
)
})?;
PrivateKeyDer::from_pem_reader(file).map_err(|err| {
io::Error::new(
io::ErrorKind::InvalidData,
format!("tls: no usable private key in {}: {err}", path.display()),
)
})
}