#![cfg(feature = "tls")]
use std::io::{self, BufReader};
use std::sync::Arc;
use tokio_rustls::rustls::pki_types::{CertificateDer, PrivateKeyDer};
use tokio_rustls::rustls::ServerConfig;
use tokio_rustls::TlsAcceptor;
pub fn acceptor_from_pem(cert_path: &str, key_path: &str) -> io::Result<TlsAcceptor> {
let certs = load_certs(cert_path)?;
let key = load_key(key_path)?;
let config = ServerConfig::builder()
.with_no_client_auth()
.with_single_cert(certs, key)
.map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?;
Ok(TlsAcceptor::from(Arc::new(config)))
}
fn load_certs(path: &str) -> io::Result<Vec<CertificateDer<'static>>> {
let file = std::fs::File::open(path)?;
let mut reader = BufReader::new(file);
rustls_pemfile::certs(&mut reader).collect::<Result<Vec<_>, _>>()
}
fn load_key(path: &str) -> io::Result<PrivateKeyDer<'static>> {
let file = std::fs::File::open(path)?;
let mut reader = BufReader::new(file);
rustls_pemfile::private_key(&mut reader)?
.ok_or_else(|| io::Error::new(io::ErrorKind::InvalidInput, "no private key found"))
}
#[cfg(all(test, feature = "tls"))]
mod tests {
use super::*;
#[test]
fn missing_files_error_cleanly() {
match acceptor_from_pem("/nonexistent/cert.pem", "/nonexistent/key.pem") {
Ok(_) => panic!("expected an error for nonexistent cert/key files"),
Err(err) => assert_eq!(err.kind(), std::io::ErrorKind::NotFound),
}
}
}