use webpki; pub use crate::msgs::handshake::{DistinguishedName, DistinguishedNames}; use crate::pemfile; use crate::x509; use crate::key; #[cfg(feature = "logging")] use crate::log::{debug, trace}; use std::io; /// This is like a `webpki::TrustAnchor`, except it owns /// rather than borrows its memory. That prevents lifetimes /// leaking up the object tree. #[derive(Debug, Clone)] pub struct OwnedTrustAnchor { subject: Vec, spki: Vec, name_constraints: Option>, } impl OwnedTrustAnchor { fn from_trust_anchor(t: &webpki::TrustAnchor) -> OwnedTrustAnchor { OwnedTrustAnchor { subject: t.subject.to_vec(), spki: t.spki.to_vec(), name_constraints: t.name_constraints.map(|x| x.to_vec()), } } pub fn to_trust_anchor(&self) -> webpki::TrustAnchor { webpki::TrustAnchor { subject: &self.subject, spki: &self.spki, name_constraints: self.name_constraints .as_ref() .map(Vec::as_slice), } } } /// A container for root certificates able to provide a root-of-trust /// for connection authentication. #[derive(Debug, Clone)] pub struct RootCertStore { /// The list of roots. pub roots: Vec, } impl RootCertStore { /// Make a new, empty `RootCertStore`. pub fn empty() -> RootCertStore { RootCertStore { roots: Vec::new() } } /// Return true if there are no certificates. pub fn is_empty(&self) -> bool { self.len() == 0 } /// Say how many certificates are in the container. pub fn len(&self) -> usize { self.roots.len() } /// Return the Subject Names for certificates in the container. pub fn get_subjects(&self) -> DistinguishedNames { let mut r = DistinguishedNames::new(); for ota in &self.roots { let mut name = Vec::new(); name.extend_from_slice(&ota.subject); x509::wrap_in_sequence(&mut name); r.push(DistinguishedName::new(name)); } r } /// Add a single DER-encoded certificate to the store. pub fn add(&mut self, der: &key::Certificate) -> Result<(), webpki::Error> { let ta = webpki::trust_anchor_util::cert_der_as_trust_anchor(&der.0)?; let ota = OwnedTrustAnchor::from_trust_anchor(&ta); self.roots.push(ota); Ok(()) } /// Adds all the given TrustAnchors `anchors`. This does not /// fail. pub fn add_server_trust_anchors(&mut self, &webpki::TLSServerTrustAnchors(anchors): &webpki::TLSServerTrustAnchors) { for ta in anchors { self.roots.push(OwnedTrustAnchor::from_trust_anchor(ta)); } } /// Parse a PEM file and add all certificates found inside. /// Errors are non-specific; they may be io errors in `rd` and /// PEM format errors, but not certificate validity errors. /// /// This is because large collections of root certificates often /// include ancient or syntactically invalid certificates. CAs /// are competent like that. /// /// Returns the number of certificates added, and the number /// which were extracted from the PEM but ultimately unsuitable. pub fn add_pem_file(&mut self, rd: &mut dyn io::BufRead) -> Result<(usize, usize), ()> { let ders = pemfile::certs(rd)?; let mut valid_count = 0; let mut invalid_count = 0; for der in ders { #[cfg_attr(not(feature = "logging"), allow(unused_variables))] match self.add(&der) { Ok(_) => valid_count += 1, Err(err) => { trace!("invalid cert der {:?}", der); debug!("certificate parsing failed: {:?}", err); invalid_count += 1 } } } debug!("add_pem_file processed {} valid and {} invalid certs", valid_count, invalid_count); Ok((valid_count, invalid_count)) } }