Skip to main content

mesquitte_core/server/
rustls.rs

1use std::{fs::File, io::BufReader, sync::Arc};
2
3use rustls::{server::WebPkiClientVerifier, RootCertStore};
4use tokio_rustls::{
5    rustls::{Error as RustlsError, ServerConfig},
6    TlsAcceptor,
7};
8
9use super::config::TlsConfig;
10
11#[derive(Debug, thiserror::Error)]
12#[error("Acceptor error")]
13pub enum Error {
14    #[error("I/O {0}")]
15    Io(#[from] std::io::Error),
16    #[error("Rustls error {0}")]
17    Rustls(#[from] RustlsError),
18    #[error("Invalid CA cert file {0}")]
19    InvalidCACert(String),
20    #[error("Invalid server key file {0}")]
21    InvalidServerKey(String),
22}
23
24pub fn rustls_server_config(cfg: &TlsConfig) -> Result<ServerConfig, Error> {
25    let cert_file = &mut BufReader::new(File::open(cfg.cert_file.clone())?);
26    let key_file = &mut BufReader::new(File::open(cfg.key_file.clone())?);
27
28    let cert_chain = rustls_pemfile::certs(cert_file).collect::<Result<Vec<_>, _>>()?;
29    let key = rustls_pemfile::private_key(key_file)?
30        .ok_or(Error::InvalidServerKey("invalid server key".to_string()))?;
31
32    let client_auth = if cfg.fail_if_no_peer_cert {
33        match &cfg.ca_file {
34            Some(ca) => {
35                let ca_file = &mut BufReader::new(File::open(ca)?);
36                let cert_chain = rustls_pemfile::certs(ca_file).collect::<Result<Vec<_>, _>>()?;
37                let mut client_auth_roots = RootCertStore::empty();
38                for root in cert_chain {
39                    client_auth_roots
40                        .add(root)
41                        .map_err(|e| Error::InvalidCACert(e.to_string()))?;
42                }
43                WebPkiClientVerifier::builder(client_auth_roots.into())
44                    .build()
45                    .map_err(|e| Error::InvalidCACert(e.to_string()))?
46            }
47            None => return Err(Error::InvalidCACert("empty ca".to_string())),
48        }
49    } else {
50        WebPkiClientVerifier::no_client_auth()
51    };
52
53    ServerConfig::builder()
54        .with_client_cert_verifier(client_auth)
55        .with_single_cert(cert_chain, key)
56        .map_err(|e| Error::InvalidCACert(e.to_string()))
57}
58
59pub fn rustls_acceptor(cfg: &TlsConfig) -> Result<TlsAcceptor, Error> {
60    Ok(TlsAcceptor::from(Arc::new(rustls_server_config(cfg)?)))
61}