1use std::{io::BufReader, path::PathBuf};
2
3use anyhow::{bail, Context};
4use rustls::{
5 client::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier},
6 server::{AllowAnyAuthenticatedClient, NoClientAuth, ServerSessionMemoryCache},
7 ClientConfig, DigitallySignedStruct, OwnedTrustAnchor, RootCertStore, ServerConfig,
8};
9
10pub const DEFAULT_FORMARD_PORT: u16 = 8443;
11
12pub struct NoVerifier;
13
14pub static QUIC_ALPN: &[u8] = b"h3";
15
16impl ServerCertVerifier for NoVerifier {
17 fn verify_server_cert(
18 &self,
19 _end_entity: &rustls::Certificate,
20 _intermediates: &[rustls::Certificate],
21 _server_name: &rustls::ServerName,
22 _scts: &mut dyn Iterator<Item = &[u8]>,
23 _ocsp_response: &[u8],
24 _now: std::time::SystemTime,
25 ) -> Result<ServerCertVerified, rustls::Error> {
26 Ok(ServerCertVerified::assertion())
27 }
28
29 fn verify_tls12_signature(
30 &self,
31 _message: &[u8],
32 _cert: &rustls::Certificate,
33 _dss: &DigitallySignedStruct,
34 ) -> Result<HandshakeSignatureValid, rustls::Error> {
35 Ok(HandshakeSignatureValid::assertion())
36 }
37
38 fn verify_tls13_signature(
39 &self,
40 _message: &[u8],
41 _cert: &rustls::Certificate,
42 _dss: &DigitallySignedStruct,
43 ) -> Result<HandshakeSignatureValid, rustls::Error> {
44 Ok(HandshakeSignatureValid::assertion())
45 }
46}
47
48pub fn load_private_key(filename: &PathBuf) -> anyhow::Result<rustls::PrivateKey> {
49 let keyfile = std::fs::File::open(filename).context("cannot open private key file")?;
50 let mut reader = std::io::BufReader::new(keyfile);
51
52 loop {
53 match rustls_pemfile::read_one(&mut reader)? {
54 Some(rustls_pemfile::Item::RSAKey(key)) => return Ok(rustls::PrivateKey(key)),
55 Some(rustls_pemfile::Item::PKCS8Key(key)) => return Ok(rustls::PrivateKey(key)),
56 Some(rustls_pemfile::Item::ECKey(key)) => return Ok(rustls::PrivateKey(key)),
57 None => break,
58 _ => {}
59 }
60 }
61
62 bail!("no keys found (encrypted keys not supported)")
63}
64
65pub fn load_certs(filename: &PathBuf) -> anyhow::Result<Vec<rustls::Certificate>> {
68 let certfile = std::fs::File::open(filename).context("cannot open certificate file")?;
69 let mut reader = BufReader::new(certfile);
70 Ok(rustls_pemfile::certs(&mut reader)?
71 .iter()
72 .map(|v| rustls::Certificate(v.clone()))
73 .collect())
74}
75
76pub fn build_client_root_store(cafile: &Option<PathBuf>) -> anyhow::Result<RootCertStore> {
77 let mut root_store = RootCertStore::empty();
78 if let Some(cafile) = cafile {
79 let mut pem =
80 std::io::BufReader::new(std::fs::File::open(cafile).context("cannot open ca file")?);
81 let certs = rustls_pemfile::certs(&mut pem)?;
82 let (added, _skipped) = root_store.add_parsable_certificates(&certs);
83 if added == 0 {
84 bail!("cannot parse cert");
85 }
86 } else {
87 root_store.add_server_trust_anchors(webpki_roots::TLS_SERVER_ROOTS.0.iter().map(|ta| {
88 OwnedTrustAnchor::from_subject_spki_name_constraints(
89 ta.subject,
90 ta.spki,
91 ta.name_constraints,
92 )
93 }));
94 }
95 Ok(root_store)
96}
97
98pub fn build_tls_server_config(
99 certs: PathBuf,
100 key: PathBuf,
101 client_ca: Option<PathBuf>,
102) -> anyhow::Result<ServerConfig> {
103 let certs = load_certs(&certs)?;
104 let keys = load_private_key(&key)?;
105
106 let tls_config = rustls::ServerConfig::builder().with_safe_defaults();
107
108 let client_verifier = match client_ca {
110 Some(client_certs) => {
111 let client_certs = load_certs(&client_certs)?;
112 let mut client_auth_roots = RootCertStore::empty();
113 for cert in client_certs {
114 client_auth_roots.add(&cert)?;
115 }
116 AllowAnyAuthenticatedClient::new(client_auth_roots).boxed()
117 }
118 None => {
119 NoClientAuth::boxed()
122 }
123 };
124
125 let mut tls_config = tls_config
126 .with_client_cert_verifier(client_verifier)
128 .with_single_cert(certs, keys)?;
129
130 tls_config.ticketer = rustls::Ticketer::new()?;
132 tls_config.session_storage = ServerSessionMemoryCache::new(256);
133 Ok(tls_config)
134}
135
136pub fn build_tls_client_config(
137 cacert: &Option<PathBuf>,
138 client_cert: &PathBuf,
139 client_key: &PathBuf,
140) -> anyhow::Result<ClientConfig> {
141 let root_store = build_client_root_store(cacert)?;
142
143 let tls_config = rustls::ClientConfig::builder()
144 .with_safe_defaults()
145 .with_root_certificates(root_store);
146
147 let certs = load_certs(client_cert)?;
148 let key = load_private_key(client_key)?;
149 let tls_config = tls_config.with_single_cert(certs, key)?;
150
151 Ok(tls_config)
152}
153
154pub struct NeverProducesTickets {}
155
156impl rustls::server::ProducesTickets for NeverProducesTickets {
157 fn enabled(&self) -> bool {
158 false
159 }
160 fn lifetime(&self) -> u32 {
161 0
162 }
163 fn encrypt(&self, _bytes: &[u8]) -> Option<Vec<u8>> {
164 None
165 }
166 fn decrypt(&self, _bytes: &[u8]) -> Option<Vec<u8>> {
167 None
168 }
169}