1 use webpki; 2 3 use crate::key; 4 #[cfg(feature = "logging")] 5 use crate::log::{debug, trace}; 6 pub use crate::msgs::handshake::{DistinguishedName, DistinguishedNames}; 7 use crate::pemfile; 8 use crate::x509; 9 use std::io; 10 11 /// This is like a `webpki::TrustAnchor`, except it owns 12 /// rather than borrows its memory. That prevents lifetimes 13 /// leaking up the object tree. 14 #[derive(Debug, Clone)] 15 pub struct OwnedTrustAnchor { 16 subject: Vec<u8>, 17 spki: Vec<u8>, 18 name_constraints: Option<Vec<u8>>, 19 } 20 21 impl OwnedTrustAnchor { 22 /// Copy a `webpki::TrustAnchor` into owned memory from_trust_anchor(t: &webpki::TrustAnchor) -> OwnedTrustAnchor23 pub fn from_trust_anchor(t: &webpki::TrustAnchor) -> OwnedTrustAnchor { 24 OwnedTrustAnchor { 25 subject: t.subject.to_vec(), 26 spki: t.spki.to_vec(), 27 name_constraints: t.name_constraints.map(|x| x.to_vec()), 28 } 29 } 30 31 /// Get a `webpki::TrustAnchor` by borrowing the owned elements. to_trust_anchor(&self) -> webpki::TrustAnchor32 pub fn to_trust_anchor(&self) -> webpki::TrustAnchor { 33 webpki::TrustAnchor { 34 subject: &self.subject, 35 spki: &self.spki, 36 name_constraints: self 37 .name_constraints 38 .as_ref() 39 .map(Vec::as_slice), 40 } 41 } 42 } 43 44 impl From<webpki::TrustAnchor<'_>> for OwnedTrustAnchor { from(t: webpki::TrustAnchor) -> OwnedTrustAnchor45 fn from(t: webpki::TrustAnchor) -> OwnedTrustAnchor { 46 Self::from_trust_anchor(&t) 47 } 48 } 49 50 impl<'a> Into<webpki::TrustAnchor<'a>> for &'a OwnedTrustAnchor { into(self) -> webpki::TrustAnchor<'a>51 fn into(self) -> webpki::TrustAnchor<'a> { 52 self.to_trust_anchor() 53 } 54 } 55 56 /// A container for root certificates able to provide a root-of-trust 57 /// for connection authentication. 58 #[derive(Debug, Clone)] 59 pub struct RootCertStore { 60 /// The list of roots. 61 pub roots: Vec<OwnedTrustAnchor>, 62 } 63 64 impl RootCertStore { 65 /// Make a new, empty `RootCertStore`. empty() -> RootCertStore66 pub fn empty() -> RootCertStore { 67 RootCertStore { roots: Vec::new() } 68 } 69 70 /// Return true if there are no certificates. is_empty(&self) -> bool71 pub fn is_empty(&self) -> bool { 72 self.len() == 0 73 } 74 75 /// Say how many certificates are in the container. len(&self) -> usize76 pub fn len(&self) -> usize { 77 self.roots.len() 78 } 79 80 /// Return the Subject Names for certificates in the container. get_subjects(&self) -> DistinguishedNames81 pub fn get_subjects(&self) -> DistinguishedNames { 82 let mut r = DistinguishedNames::new(); 83 84 for ota in &self.roots { 85 let mut name = Vec::new(); 86 name.extend_from_slice(&ota.subject); 87 x509::wrap_in_sequence(&mut name); 88 r.push(DistinguishedName::new(name)); 89 } 90 91 r 92 } 93 94 /// Add a single DER-encoded certificate to the store. add(&mut self, der: &key::Certificate) -> Result<(), webpki::Error>95 pub fn add(&mut self, der: &key::Certificate) -> Result<(), webpki::Error> { 96 let ta = webpki::trust_anchor_util::cert_der_as_trust_anchor(&der.0)?; 97 98 let ota = OwnedTrustAnchor::from_trust_anchor(&ta); 99 self.roots.push(ota); 100 Ok(()) 101 } 102 103 /// Adds all the given TrustAnchors `anchors`. This does not 104 /// fail. add_server_trust_anchors( &mut self, &webpki::TLSServerTrustAnchors(anchors): &webpki::TLSServerTrustAnchors, )105 pub fn add_server_trust_anchors( 106 &mut self, 107 &webpki::TLSServerTrustAnchors(anchors): &webpki::TLSServerTrustAnchors, 108 ) { 109 for ta in anchors { 110 self.roots 111 .push(OwnedTrustAnchor::from_trust_anchor(ta)); 112 } 113 } 114 115 /// Parse a PEM file and add all certificates found inside. 116 /// Errors are non-specific; they may be io errors in `rd` and 117 /// PEM format errors, but not certificate validity errors. 118 /// 119 /// This is because large collections of root certificates often 120 /// include ancient or syntactically invalid certificates. CAs 121 /// are competent like that. 122 /// 123 /// Returns the number of certificates added, and the number 124 /// which were extracted from the PEM but ultimately unsuitable. add_pem_file(&mut self, rd: &mut dyn io::BufRead) -> Result<(usize, usize), ()>125 pub fn add_pem_file(&mut self, rd: &mut dyn io::BufRead) -> Result<(usize, usize), ()> { 126 let ders = pemfile::certs(rd)?; 127 let mut valid_count = 0; 128 let mut invalid_count = 0; 129 130 for der in ders { 131 #[cfg_attr(not(feature = "logging"), allow(unused_variables))] 132 match self.add(&der) { 133 Ok(_) => valid_count += 1, 134 Err(err) => { 135 trace!("invalid cert der {:?}", der); 136 debug!("certificate parsing failed: {:?}", err); 137 invalid_count += 1 138 } 139 } 140 } 141 142 debug!( 143 "add_pem_file processed {} valid and {} invalid certs", 144 valid_count, invalid_count 145 ); 146 147 Ok((valid_count, invalid_count)) 148 } 149 } 150