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