drawbridge_server/auth/
tls.rs1use std::io::BufRead;
5use std::ops::Deref;
6
7use anyhow::{bail, Context};
8use rustls::server::WebPkiClientVerifier;
9use rustls::{RootCertStore, ServerConfig};
10use rustls_pemfile::Item::{Pkcs1Key, Pkcs8Key, Sec1Key, X509Certificate};
11use rustls_pki_types::CertificateDer;
12use rustls_pki_types::PrivateKeyDer;
13
14#[derive(Clone, Copy, Debug)]
15#[repr(transparent)]
16pub struct TrustedCertificate;
17
18#[repr(transparent)]
19#[allow(missing_debug_implementations)]
20#[derive(Clone)]
21pub struct Config(ServerConfig);
22
23impl Deref for Config {
24 type Target = ServerConfig;
25
26 fn deref(&self) -> &Self::Target {
27 &self.0
28 }
29}
30
31impl From<Config> for ServerConfig {
32 fn from(conf: Config) -> Self {
33 conf.0
34 }
35}
36
37fn read_certificates(mut rd: impl BufRead) -> anyhow::Result<Vec<CertificateDer<'static>>> {
38 rustls_pemfile::read_all(&mut rd)
39 .map(|item| match item? {
40 X509Certificate(buf) => Ok(buf),
41 _ => bail!("unsupported certificate type"),
42 })
43 .collect()
44}
45
46impl Config {
47 pub fn read(
48 mut certs: impl BufRead,
49 mut key: impl BufRead,
50 mut cas: impl BufRead,
51 ) -> anyhow::Result<Self> {
52 let certs =
53 read_certificates(&mut certs).context("failed to read server certificate chain")?;
54 let key = {
55 if let Some(key) = rustls_pemfile::read_all(&mut key).next() {
56 match key? {
57 Pkcs1Key(inner) => PrivateKeyDer::from(inner),
58 Pkcs8Key(inner) => PrivateKeyDer::from(inner),
59 Sec1Key(inner) => PrivateKeyDer::from(inner),
60 _ => {
61 bail!("Unexpected key type found");
62 }
63 }
64 } else {
65 bail!("No key found")
66 }
67 };
68
69 let client_verifier = {
70 let mut roots = RootCertStore::empty();
71 read_certificates(&mut cas)
72 .context("failed to read CA certificates")?
73 .into_iter()
74 .try_for_each(|cert| roots.add(cert))
75 .context("failed to construct root certificate store")?;
76 WebPkiClientVerifier::builder(roots.into())
78 .allow_unauthenticated()
79 .build()?
80 };
81
82 ServerConfig::builder()
83 .with_client_cert_verifier(client_verifier)
84 .with_single_cert(certs, key)
85 .context("invalid server certificate key")
86 .map(Self)
87 }
88}