1use anyhow::{bail, Context, Result};
5use quinn::{Connection, IdleTimeout, ServerConfig};
6use rustls::server::AllowAnyAuthenticatedClient;
7use rustls::{Certificate, PrivateKey, RootCertStore};
8use rustls_pemfile::{certs, pkcs8_private_keys, rsa_private_keys};
9use std::{fs, path::Path, sync::Arc};
10
11const ALPN_QUIC_HTTP: &[&[u8]] = &[b"hq-29"];
12
13#[derive(Default)]
14pub struct ConfigOptions {
15 pub keylog: bool,
16 pub stateless_retry: bool,
17 pub max_idle_timeout: IdleTimeout,
18}
19
20pub fn server_config(
21 root_store: RootCertStore,
22 certs: Vec<Certificate>,
23 key: PrivateKey,
24 options: ConfigOptions,
25) -> Result<ServerConfig> {
26 let client_cert_verifier = Arc::new(AllowAnyAuthenticatedClient::new(root_store));
27
28 let mut server_crypto = rustls::ServerConfig::builder()
29 .with_safe_defaults()
30 .with_client_cert_verifier(client_cert_verifier)
31 .with_single_cert(certs, key)?;
32
33 server_crypto.alpn_protocols = ALPN_QUIC_HTTP.iter().map(|&x| x.into()).collect();
34 if options.keylog {
35 server_crypto.key_log = Arc::new(rustls::KeyLogFile::new());
36 }
37
38 let mut server_config = ServerConfig::with_crypto(Arc::new(server_crypto));
39 let transport_config = Arc::get_mut(&mut server_config.transport).unwrap();
40 transport_config.max_concurrent_uni_streams(0_u8.into());
41 transport_config.max_idle_timeout(Some(options.max_idle_timeout));
42 if options.stateless_retry {
43 server_config.use_retry(true);
44 }
45
46 Ok(server_config)
47}
48
49fn load_key<T: AsRef<Path>>(path: T) -> Result<PrivateKey> {
50 let path = path.as_ref();
51 let key = fs::read(path).context("failed to read private key")?;
52 let key = if path.extension().map_or(false, |x| x == "der") {
53 PrivateKey(key)
54 } else {
55 let pkcs8 = pkcs8_private_keys(&mut &*key).context("malformed PKCS #8 private key")?;
56 match pkcs8.into_iter().next() {
57 Some(x) => PrivateKey(x),
58 None => {
59 let rsa = rsa_private_keys(&mut &*key).context("malformed PKCS #1 private key")?;
60 match rsa.into_iter().next() {
61 Some(x) => PrivateKey(x),
62 None => {
63 bail!("no private keys found");
64 }
65 }
66 }
67 }
68 };
69
70 Ok(key)
71}
72
73fn load_certs<T: AsRef<Path>>(path: T) -> Result<Vec<Certificate>> {
74 let path = path.as_ref();
75 let cert_chain = fs::read(path).context("failed to read certificate chain")?;
76
77 let cert_chain = if path.extension().map_or(false, |x| x == "der") {
78 vec![Certificate(cert_chain)]
79 } else {
80 certs(&mut &*cert_chain)
81 .context("invalid PEM-encoded certificate")?
82 .into_iter()
83 .map(Certificate)
84 .collect()
85 };
86
87 Ok(cert_chain)
88}
89
90pub fn read_certs<T: AsRef<Path>>(
91 cert_path: T,
92 key_path: T,
93) -> Result<(Vec<Certificate>, PrivateKey)> {
94 let certs = load_certs(cert_path)?;
95 let key = load_key(key_path)?;
96 Ok((certs, key))
97}
98
99pub fn load_root_store<T: AsRef<Path>>(ca_file: T) -> Result<RootCertStore> {
100 let ca_file = ca_file.as_ref();
101 let mut store = RootCertStore::empty();
102 let certs = load_certs(ca_file)?;
103 store.add_parsable_certificates(&certs);
104
105 if store.is_empty() {
106 bail!("No valid certs found in file {ca_file:?}");
107 }
108
109 Ok(store)
110}
111
112pub fn get_pubkey_from_connection(connection: &Connection) -> Result<Vec<u8>> {
113 let peer_identity = connection
114 .peer_identity()
115 .context("Unable to read peer identity")?;
116
117 let certs = peer_identity
118 .downcast_ref::<Vec<Certificate>>()
119 .context("Unable to read cert")?;
120
121 Ok(certs
122 .first()
123 .context("Failed to get first certificate")?
124 .0
125 .clone())
126}