1use std::collections::HashMap;
13use std::fmt;
14use std::fs::File;
15use std::io::BufReader;
16use std::path::Path;
17use std::sync::{Arc, RwLock};
18
19use rustls::ServerConfig;
20use rustls_pki_types::pem::PemObject;
21use rustls_pki_types::{CertificateDer, CertificateRevocationListDer, PrivateKeyDer};
22
23pub const MAX_TLS_IDENTITIES: usize = 64;
25pub const MAX_SNI_LEN: usize = 253;
27pub const MAX_TRUST_ROOTS: usize = 256;
29pub const MAX_CRLS: usize = 16;
31pub const MAX_ALPN_PROTOCOLS: usize = 16;
33pub const MAX_ALPN_PROTOCOL_LEN: usize = 255;
35pub const MAX_IDENTITY_CHAIN: usize = 8;
37pub const MAX_TRUST_PEM_BYTES: usize = 1024 * 1024;
39
40#[derive(Debug)]
41pub enum TlsError {
42 CertFileNotFound(String),
43 KeyFileNotFound(String),
44 CertReadError(String),
45 KeyReadError(String),
46 NoCertificatesFound,
47 NoPrivateKeyFound,
48 MultiplePrivateKeysFound,
49 InvalidKey(String),
50 InvalidSniName(String),
51 DuplicateIdentity(String),
52 TooManyIdentities,
53 NoIdentities,
54 InvalidTrustRoots(String),
55 TooManyTrustRoots,
56 InvalidCrl(String),
57 TooManyCrls,
58 TrustRootsRequired,
59 InvalidAlpn(String),
60}
61
62impl fmt::Display for TlsError {
63 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64 match self {
65 Self::CertFileNotFound(path) => write!(f, "certificate file not found: {path}"),
66 Self::KeyFileNotFound(path) => write!(f, "key file not found: {path}"),
67 Self::CertReadError(msg) => write!(f, "failed to read certificate: {msg}"),
68 Self::KeyReadError(msg) => write!(f, "failed to read key: {msg}"),
69 Self::NoCertificatesFound => {
70 write!(f, "no valid certificates found in certificate file")
71 }
72 Self::NoPrivateKeyFound => write!(f, "no valid private key found in key file"),
73 Self::MultiplePrivateKeysFound => {
74 write!(f, "multiple private keys found; exactly one is required")
75 }
76 Self::InvalidKey(msg) => write!(f, "invalid private key: {msg}"),
77 Self::InvalidSniName(msg) => write!(f, "invalid SNI identity: {msg}"),
78 Self::DuplicateIdentity(name) => write!(f, "duplicate TLS identity: {name}"),
79 Self::TooManyIdentities => {
80 write!(f, "too many TLS identities (max {MAX_TLS_IDENTITIES})")
81 }
82 Self::NoIdentities => write!(f, "no TLS identities configured"),
83 Self::InvalidTrustRoots(msg) => write!(f, "invalid trust roots: {msg}"),
84 Self::TooManyTrustRoots => {
85 write!(f, "too many trust roots (max {MAX_TRUST_ROOTS})")
86 }
87 Self::InvalidCrl(msg) => write!(f, "invalid CRL: {msg}"),
88 Self::TooManyCrls => write!(f, "too many CRLs (max {MAX_CRLS})"),
89 Self::TrustRootsRequired => {
90 write!(f, "client authentication requires at least one trust root")
91 }
92 Self::InvalidAlpn(msg) => write!(f, "invalid ALPN protocols: {msg}"),
93 }
94 }
95}
96
97impl std::error::Error for TlsError {}
98
99#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
105pub enum ClientAuthMode {
106 #[default]
108 Disabled,
109 Optional,
112 Required,
114}
115
116pub fn load_tls_config(cert_path: &Path, key_path: &Path) -> Result<Arc<ServerConfig>, TlsError> {
118 load_tls_config_with_http2(cert_path, key_path, cfg!(feature = "http2"))
119}
120
121pub fn load_tls_config_with_http2(
129 cert_path: &Path,
130 key_path: &Path,
131 http2: bool,
132) -> Result<Arc<ServerConfig>, TlsError> {
133 load_tls_config_with_alpn(cert_path, key_path, http_alpn_protocols(http2))
134}
135
136pub fn load_tls_config_with_alpn(
143 cert_path: &Path,
144 key_path: &Path,
145 alpn: Vec<Vec<u8>>,
146) -> Result<Arc<ServerConfig>, TlsError> {
147 validate_alpn(&alpn)?;
148 let (certs, key) = load_identity(cert_path, key_path)?;
149 build_single_cert_config(certs, key, alpn)
150}
151
152fn validate_alpn(alpn: &[Vec<u8>]) -> Result<(), TlsError> {
154 if alpn.len() > MAX_ALPN_PROTOCOLS {
155 return Err(TlsError::InvalidAlpn(format!(
156 "too many ALPN protocols (max {MAX_ALPN_PROTOCOLS})"
157 )));
158 }
159 for protocol in alpn {
160 if protocol.is_empty() || protocol.len() > MAX_ALPN_PROTOCOL_LEN {
161 return Err(TlsError::InvalidAlpn(format!(
162 "ALPN protocol length must be 1..={MAX_ALPN_PROTOCOL_LEN}"
163 )));
164 }
165 }
166 Ok(())
167}
168
169pub fn parse_identity_pem(
174 cert_pem: &[u8],
175 key_pem: &[u8],
176) -> Result<(Vec<CertificateDer<'static>>, PrivateKeyDer<'static>), TlsError> {
177 use std::io::Cursor;
178 let certs = CertificateDer::pem_reader_iter(Cursor::new(cert_pem))
179 .collect::<Result<Vec<_>, _>>()
180 .map_err(|e| TlsError::CertReadError(e.to_string()))?;
181 if certs.is_empty() {
182 return Err(TlsError::NoCertificatesFound);
183 }
184 if certs.len() > MAX_IDENTITY_CHAIN {
185 return Err(TlsError::InvalidKey(format!(
186 "certificate chain too long (max {MAX_IDENTITY_CHAIN})"
187 )));
188 }
189 let mut private_key = None;
190 let mut key_count = 0;
191 for item in PrivateKeyDer::pem_reader_iter(Cursor::new(key_pem)) {
192 let key = item.map_err(|e| TlsError::KeyReadError(e.to_string()))?;
193 key_count += 1;
194 private_key = Some(key);
195 }
196 if key_count > 1 {
197 return Err(TlsError::MultiplePrivateKeysFound);
198 }
199 let key = private_key.ok_or(TlsError::NoPrivateKeyFound)?;
200 validate_key_pair(&certs, &key)?;
201 Ok((certs, key))
202}
203
204pub fn parse_trust_roots_pem(pem: &[u8]) -> Result<Vec<CertificateDer<'static>>, TlsError> {
206 if pem.len() > MAX_TRUST_PEM_BYTES {
207 return Err(TlsError::InvalidTrustRoots("trust PEM too large".into()));
208 }
209 use std::io::Cursor;
210 let certs = CertificateDer::pem_reader_iter(Cursor::new(pem))
211 .collect::<Result<Vec<_>, _>>()
212 .map_err(|e| TlsError::InvalidTrustRoots(e.to_string()))?;
213 if certs.is_empty() {
214 return Err(TlsError::InvalidTrustRoots("no certificates found".into()));
215 }
216 if certs.len() > MAX_TRUST_ROOTS {
217 return Err(TlsError::TooManyTrustRoots);
218 }
219 let mut store = rustls::RootCertStore::empty();
221 for cert in &certs {
222 store
223 .add(cert.clone())
224 .map_err(|e| TlsError::InvalidTrustRoots(e.to_string()))?;
225 }
226 Ok(certs)
227}
228
229pub fn parse_crls_pem(pem: &[u8]) -> Result<Vec<CertificateRevocationListDer<'static>>, TlsError> {
231 if pem.len() > MAX_TRUST_PEM_BYTES {
232 return Err(TlsError::InvalidCrl("CRL PEM too large".into()));
233 }
234 use std::io::Cursor;
235 let crls = CertificateRevocationListDer::pem_reader_iter(Cursor::new(pem))
236 .collect::<Result<Vec<_>, _>>()
237 .map_err(|e| TlsError::InvalidCrl(e.to_string()))?;
238 if crls.len() > MAX_CRLS {
239 return Err(TlsError::TooManyCrls);
240 }
241 Ok(crls)
242}
243
244fn build_single_cert_config(
245 certs: Vec<CertificateDer<'static>>,
246 key: PrivateKeyDer<'static>,
247 alpn: Vec<Vec<u8>>,
248) -> Result<Arc<ServerConfig>, TlsError> {
249 if certs.len() > MAX_IDENTITY_CHAIN {
250 return Err(TlsError::InvalidKey(format!(
251 "certificate chain too long (max {MAX_IDENTITY_CHAIN})"
252 )));
253 }
254 let mut config = ServerConfig::builder()
255 .with_no_client_auth()
256 .with_single_cert(certs, key)
257 .map_err(|e| TlsError::InvalidKey(e.to_string()))?;
258 config.alpn_protocols = alpn;
259 config.max_early_data_size = 0;
263 Ok(Arc::new(config))
264}
265
266pub fn load_identity(
268 cert_path: &Path,
269 key_path: &Path,
270) -> Result<(Vec<CertificateDer<'static>>, PrivateKeyDer<'static>), TlsError> {
271 let cert_file = File::open(cert_path)
272 .map_err(|_| TlsError::CertFileNotFound(cert_path.display().to_string()))?;
273 let cert_reader = BufReader::new(cert_file);
274 let certs = CertificateDer::pem_reader_iter(cert_reader)
275 .collect::<Result<Vec<_>, _>>()
276 .map_err(|e| TlsError::CertReadError(e.to_string()))?;
277 if certs.is_empty() {
278 return Err(TlsError::NoCertificatesFound);
279 }
280 if certs.len() > MAX_IDENTITY_CHAIN {
281 return Err(TlsError::InvalidKey(format!(
282 "certificate chain too long (max {MAX_IDENTITY_CHAIN})"
283 )));
284 }
285
286 let key_file = File::open(key_path)
287 .map_err(|_| TlsError::KeyFileNotFound(key_path.display().to_string()))?;
288 let key_reader = BufReader::new(key_file);
289 let mut private_key = None;
290 let mut key_count = 0;
291 for item in PrivateKeyDer::pem_reader_iter(key_reader) {
292 let key = item.map_err(|e| TlsError::KeyReadError(e.to_string()))?;
293 key_count += 1;
294 private_key = Some(key);
295 }
296 if key_count > 1 {
297 return Err(TlsError::MultiplePrivateKeysFound);
298 }
299 let key = private_key.ok_or(TlsError::NoPrivateKeyFound)?;
300 validate_key_pair(&certs, &key)?;
301 Ok((certs, key))
302}
303
304fn validate_key_pair(
307 certs: &[CertificateDer<'static>],
308 key: &PrivateKeyDer<'static>,
309) -> Result<(), TlsError> {
310 let provider = rustls::crypto::ring::default_provider();
311 let signing_key = provider
312 .key_provider
313 .load_private_key(key.clone_key())
314 .map_err(|e| TlsError::InvalidKey(e.to_string()))?;
315 let ck = rustls::sign::CertifiedKey::new(certs.to_vec(), signing_key);
316 ck.keys_match()
317 .map_err(|e| TlsError::InvalidKey(e.to_string()))?;
318 Ok(())
319}
320
321fn normalize_sni_name(name: &str) -> Result<(bool, String), TlsError> {
329 let trimmed = name.trim();
330 if trimmed.is_empty() {
331 return Err(TlsError::InvalidSniName("empty SNI name".into()));
332 }
333 if trimmed.len() > MAX_SNI_LEN + 2 {
334 return Err(TlsError::InvalidSniName(format!(
335 "SNI name too long (max {MAX_SNI_LEN})"
336 )));
337 }
338 let lower = trimmed.to_ascii_lowercase();
339 if let Some(rest) = lower.strip_prefix("*.") {
340 if rest.is_empty() || rest.contains('*') {
341 return Err(TlsError::InvalidSniName(
342 "wildcard must be exactly '*.suffix'".into(),
343 ));
344 }
345 validate_dns_labels(rest)?;
346 if !rest.contains('.') {
348 return Err(TlsError::InvalidSniName(
349 "wildcard suffix must contain a dot (e.g. *.example.com)".into(),
350 ));
351 }
352 if rest.len() > MAX_SNI_LEN {
353 return Err(TlsError::InvalidSniName(format!(
354 "wildcard suffix too long (max {MAX_SNI_LEN})"
355 )));
356 }
357 Ok((true, format!("*.{rest}")))
358 } else {
359 if lower.contains('*') {
360 return Err(TlsError::InvalidSniName(
361 "wildcard only allowed as leading '*.'".into(),
362 ));
363 }
364 validate_dns_labels(&lower)?;
365 if rustls::pki_types::DnsName::try_from(lower.as_str()).is_err() {
367 return Err(TlsError::InvalidSniName(format!(
368 "invalid DNS name: {trimmed}"
369 )));
370 }
371 Ok((false, lower))
372 }
373}
374
375fn validate_dns_labels(name: &str) -> Result<(), TlsError> {
376 if name.is_empty() || name.len() > MAX_SNI_LEN {
377 return Err(TlsError::InvalidSniName(format!(
378 "DNS name length must be 1..={MAX_SNI_LEN}"
379 )));
380 }
381 if name.starts_with('.') || name.ends_with('.') || name.starts_with('-') {
382 return Err(TlsError::InvalidSniName(
383 "invalid DNS label placement".into(),
384 ));
385 }
386 for label in name.split('.') {
387 if label.is_empty() || label.len() > 63 {
388 return Err(TlsError::InvalidSniName("invalid DNS label length".into()));
389 }
390 if label.starts_with('-') || label.ends_with('-') {
391 return Err(TlsError::InvalidSniName(
392 "DNS label must not start/end with '-'".into(),
393 ));
394 }
395 if !label
396 .bytes()
397 .all(|b| b.is_ascii_alphanumeric() || b == b'-')
398 {
399 return Err(TlsError::InvalidSniName(
400 "DNS labels must be ASCII alphanumeric or '-'".into(),
401 ));
402 }
403 }
404 Ok(())
405}
406
407#[derive(Debug)]
414struct SniResolver {
415 exact: HashMap<String, Arc<rustls::sign::CertifiedKey>>,
416 wildcards: Vec<(String, Arc<rustls::sign::CertifiedKey>)>,
417 default: Option<Arc<rustls::sign::CertifiedKey>>,
418}
419
420impl rustls::server::ResolvesServerCert for SniResolver {
421 fn resolve(
422 &self,
423 client_hello: rustls::server::ClientHello<'_>,
424 ) -> Option<Arc<rustls::sign::CertifiedKey>> {
425 if let Some(name) = client_hello.server_name() {
426 if name.len() > MAX_SNI_LEN {
427 return self.default.clone();
428 }
429 let lower = name.to_ascii_lowercase();
430 if let Some(k) = self.exact.get(&lower) {
431 return Some(k.clone());
432 }
433 if let Some(dot) = lower.find('.') {
436 let (label, suffix) = lower.split_at(dot);
437 let suffix = &suffix[1..];
438 if !label.is_empty() && !label.contains('.') {
439 for (w_suffix, key) in &self.wildcards {
440 if suffix == w_suffix {
441 return Some(key.clone());
442 }
443 }
444 }
445 }
446 self.default.clone()
447 } else {
448 self.default.clone()
449 }
450 }
451}
452
453#[derive(Debug, Clone)]
460pub struct TlsServerConfig {
461 config: Arc<ServerConfig>,
462 identities: Vec<String>,
463 has_default: bool,
464 client_auth: ClientAuthMode,
465 alpn: Vec<Vec<u8>>,
466}
467
468impl TlsServerConfig {
469 pub fn builder() -> TlsServerConfigBuilder {
471 TlsServerConfigBuilder::new()
472 }
473
474 pub fn server_config(&self) -> &Arc<ServerConfig> {
476 &self.config
477 }
478
479 pub fn into_server_config(&self) -> Arc<ServerConfig> {
481 self.config.clone()
482 }
483
484 pub fn identities(&self) -> &[String] {
486 &self.identities
487 }
488
489 pub fn has_default_identity(&self) -> bool {
491 self.has_default
492 }
493
494 pub fn client_auth(&self) -> ClientAuthMode {
496 self.client_auth
497 }
498
499 pub fn alpn_protocols(&self) -> &[Vec<u8>] {
501 &self.alpn
502 }
503}
504
505#[derive(Debug, Default)]
507pub struct TlsServerConfigBuilder {
508 identities: Vec<(String, Vec<CertificateDer<'static>>, PrivateKeyDer<'static>)>,
509 default: Option<(Vec<CertificateDer<'static>>, PrivateKeyDer<'static>)>,
510 client_auth: ClientAuthMode,
511 roots: Vec<CertificateDer<'static>>,
512 crls: Vec<CertificateRevocationListDer<'static>>,
513 http2: bool,
514 alpn: Option<Vec<Vec<u8>>>,
515}
516
517impl TlsServerConfigBuilder {
518 pub fn new() -> Self {
520 Self {
521 http2: cfg!(feature = "http2"),
522 ..Default::default()
523 }
524 }
525
526 pub fn http2(mut self, enabled: bool) -> Self {
530 self.http2 = enabled;
531 self.alpn = None;
532 self
533 }
534
535 pub fn alpn_protocols(mut self, protocols: Vec<Vec<u8>>) -> Result<Self, TlsError> {
543 validate_alpn(&protocols)?;
544 self.alpn = Some(protocols);
545 Ok(self)
546 }
547
548 pub fn add_identity(
550 mut self,
551 name: &str,
552 certs: Vec<CertificateDer<'static>>,
553 key: PrivateKeyDer<'static>,
554 ) -> Result<Self, TlsError> {
555 if self.identities.len() + usize::from(self.default.is_some()) >= MAX_TLS_IDENTITIES {
556 return Err(TlsError::TooManyIdentities);
557 }
558 let (is_wildcard, normalized) = normalize_sni_name(name)?;
559 let _ = is_wildcard;
560 if self.identities.iter().any(|(n, _, _)| n == &normalized) {
561 return Err(TlsError::DuplicateIdentity(normalized));
562 }
563 if certs.is_empty() {
564 return Err(TlsError::NoCertificatesFound);
565 }
566 if certs.len() > MAX_IDENTITY_CHAIN {
567 return Err(TlsError::InvalidKey(format!(
568 "certificate chain too long (max {MAX_IDENTITY_CHAIN})"
569 )));
570 }
571 validate_key_pair(&certs, &key)?;
572 self.identities.push((normalized, certs, key));
573 Ok(self)
574 }
575
576 pub fn default_identity(
578 mut self,
579 certs: Vec<CertificateDer<'static>>,
580 key: PrivateKeyDer<'static>,
581 ) -> Result<Self, TlsError> {
582 if certs.is_empty() {
583 return Err(TlsError::NoCertificatesFound);
584 }
585 if certs.len() > MAX_IDENTITY_CHAIN {
586 return Err(TlsError::InvalidKey(format!(
587 "certificate chain too long (max {MAX_IDENTITY_CHAIN})"
588 )));
589 }
590 validate_key_pair(&certs, &key)?;
591 self.default = Some((certs, key));
592 Ok(self)
593 }
594
595 pub fn single_identity(
597 self,
598 certs: Vec<CertificateDer<'static>>,
599 key: PrivateKeyDer<'static>,
600 ) -> Result<Self, TlsError> {
601 self.default_identity(certs, key)
602 }
603
604 pub fn client_auth_disabled(mut self) -> Self {
606 self.client_auth = ClientAuthMode::Disabled;
607 self.roots.clear();
608 self.crls.clear();
609 self
610 }
611
612 pub fn client_auth_required(
614 mut self,
615 roots: Vec<CertificateDer<'static>>,
616 ) -> Result<Self, TlsError> {
617 if roots.is_empty() {
618 return Err(TlsError::TrustRootsRequired);
619 }
620 if roots.len() > MAX_TRUST_ROOTS {
621 return Err(TlsError::TooManyTrustRoots);
622 }
623 self.client_auth = ClientAuthMode::Required;
624 self.roots = roots;
625 Ok(self)
626 }
627
628 pub fn client_auth_optional(
630 mut self,
631 roots: Vec<CertificateDer<'static>>,
632 ) -> Result<Self, TlsError> {
633 if roots.is_empty() {
634 return Err(TlsError::TrustRootsRequired);
635 }
636 if roots.len() > MAX_TRUST_ROOTS {
637 return Err(TlsError::TooManyTrustRoots);
638 }
639 self.client_auth = ClientAuthMode::Optional;
640 self.roots = roots;
641 Ok(self)
642 }
643
644 pub fn with_crls(
649 mut self,
650 crls: Vec<CertificateRevocationListDer<'static>>,
651 ) -> Result<Self, TlsError> {
652 if crls.len() > MAX_CRLS {
653 return Err(TlsError::TooManyCrls);
654 }
655 self.crls = crls;
656 Ok(self)
657 }
658
659 pub fn build(self) -> Result<TlsServerConfig, TlsError> {
665 if self.identities.is_empty() && self.default.is_none() {
666 return Err(TlsError::NoIdentities);
667 }
668 if self.client_auth != ClientAuthMode::Disabled && self.roots.is_empty() {
669 return Err(TlsError::TrustRootsRequired);
670 }
671 let provider = rustls::crypto::ring::default_provider();
672 let mut exact: HashMap<String, Arc<rustls::sign::CertifiedKey>> = HashMap::new();
673 let mut wildcards: Vec<(String, Arc<rustls::sign::CertifiedKey>)> = Vec::new();
674 let mut identity_names: Vec<String> = Vec::new();
675 for (name, certs, key) in self.identities {
676 let signing_key = provider
677 .key_provider
678 .load_private_key(key)
679 .map_err(|e| TlsError::InvalidKey(e.to_string()))?;
680 let ck = Arc::new(rustls::sign::CertifiedKey::new(certs, signing_key));
681 ck.keys_match()
682 .map_err(|e| TlsError::InvalidKey(e.to_string()))?;
683 if let Some(suffix) = name.strip_prefix("*.") {
684 wildcards.push((suffix.to_owned(), ck));
685 } else {
686 exact.insert(name.clone(), ck);
687 }
688 identity_names.push(name);
689 }
690 let default = match self.default {
691 Some((certs, key)) => {
692 let signing_key = provider
693 .key_provider
694 .load_private_key(key)
695 .map_err(|e| TlsError::InvalidKey(e.to_string()))?;
696 let ck = Arc::new(rustls::sign::CertifiedKey::new(certs, signing_key));
697 ck.keys_match()
698 .map_err(|e| TlsError::InvalidKey(e.to_string()))?;
699 Some(ck)
700 }
701 None => None,
702 };
703 let has_default = default.is_some();
704 let resolver = Arc::new(SniResolver {
705 exact,
706 wildcards,
707 default,
708 });
709 let verifier = build_client_verifier(self.client_auth, &self.roots, self.crls)?;
710 let mut config = ServerConfig::builder()
711 .with_client_cert_verifier(verifier)
712 .with_cert_resolver(resolver);
713 let alpn = self.alpn.unwrap_or_else(|| http_alpn_protocols(self.http2));
714 config.alpn_protocols = alpn.clone();
715 config.max_early_data_size = 0;
716 identity_names.sort();
717 Ok(TlsServerConfig {
718 config: Arc::new(config),
719 identities: identity_names,
720 has_default,
721 client_auth: self.client_auth,
722 alpn,
723 })
724 }
725}
726
727fn build_client_verifier(
728 mode: ClientAuthMode,
729 roots: &[CertificateDer<'static>],
730 crls: Vec<CertificateRevocationListDer<'static>>,
731) -> Result<Arc<dyn rustls::server::danger::ClientCertVerifier>, TlsError> {
732 use rustls::server::WebPkiClientVerifier;
733 match mode {
734 ClientAuthMode::Disabled => Ok(WebPkiClientVerifier::no_client_auth()),
735 ClientAuthMode::Optional | ClientAuthMode::Required => {
736 if roots.is_empty() {
737 return Err(TlsError::TrustRootsRequired);
738 }
739 let mut store = rustls::RootCertStore::empty();
740 for root in roots {
741 store
742 .add(root.clone())
743 .map_err(|e| TlsError::InvalidTrustRoots(e.to_string()))?;
744 }
745 let builder = WebPkiClientVerifier::builder(Arc::new(store));
746 let builder = if crls.is_empty() {
747 builder
748 } else {
749 builder.with_crls(crls)
750 };
751 let builder = match mode {
752 ClientAuthMode::Optional => builder.allow_unauthenticated(),
753 _ => builder,
754 };
755 builder
756 .build()
757 .map_err(|e| TlsError::InvalidTrustRoots(e.to_string()))
758 }
759 }
760}
761
762#[derive(Clone, Debug)]
773pub struct TlsReloadHandle {
774 inner: Arc<RwLock<Arc<ServerConfig>>>,
775}
776
777impl TlsReloadHandle {
778 pub fn new(initial: Arc<ServerConfig>) -> Self {
780 Self {
781 inner: Arc::new(RwLock::new(initial)),
782 }
783 }
784
785 pub fn from_tls_server_config(config: &TlsServerConfig) -> Self {
787 Self::new(config.into_server_config())
788 }
789
790 pub fn current(&self) -> Arc<ServerConfig> {
792 self.inner
793 .read()
794 .map(|g| g.clone())
795 .unwrap_or_else(|poisoned| poisoned.into_inner().clone())
796 }
797
798 pub fn replace(&self, next: Arc<ServerConfig>) {
804 if let Ok(mut guard) = self.inner.write() {
805 *guard = next;
806 }
807 }
808
809 pub fn replace_tls_server_config(&self, next: &TlsServerConfig) {
811 self.replace(next.into_server_config());
812 }
813}
814
815pub fn http_alpn_protocols(http2: bool) -> Vec<Vec<u8>> {
821 if http2 {
822 vec![b"h2".to_vec(), b"http/1.1".to_vec()]
823 } else {
824 vec![b"http/1.1".to_vec()]
825 }
826}
827
828#[cfg(test)]
829mod tests {
830 use super::{http_alpn_protocols, normalize_sni_name};
831
832 #[test]
833 fn h2_alpn_is_preferred_only_when_enabled() {
834 assert_eq!(
835 http_alpn_protocols(true),
836 vec![b"h2".to_vec(), b"http/1.1".to_vec()]
837 );
838 assert_eq!(http_alpn_protocols(false), vec![b"http/1.1".to_vec()]);
839 }
840
841 #[test]
842 fn sni_names_validate() {
843 assert!(normalize_sni_name("example.com").is_ok());
844 assert!(normalize_sni_name("LOCALHOST").is_ok());
845 assert!(normalize_sni_name("*.example.com").is_ok());
846 assert!(normalize_sni_name("").is_err());
847 assert!(normalize_sni_name("*").is_err());
848 assert!(normalize_sni_name("*.com").is_err());
849 assert!(normalize_sni_name("*.example.com.evil.*").is_err());
850 assert!(normalize_sni_name("bad_host!").is_err());
851 let (wild, norm) = normalize_sni_name("*.Example.COM").unwrap();
852 assert!(wild);
853 assert_eq!(norm, "*.example.com");
854 let (wild, norm) = normalize_sni_name("Example.COM").unwrap();
855 assert!(!wild);
856 assert_eq!(norm, "example.com");
857 }
858}