1 use webpki;
2 
3 pub use crate::msgs::handshake::{DistinguishedName, DistinguishedNames};
4 use crate::pemfile;
5 use crate::x509;
6 use crate::key;
7 #[cfg(feature = "logging")]
8 use crate::log::{debug, trace};
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 {
from_trust_anchor(t: &webpki::TrustAnchor) -> OwnedTrustAnchor22     fn from_trust_anchor(t: &webpki::TrustAnchor) -> OwnedTrustAnchor {
23         OwnedTrustAnchor {
24             subject: t.subject.to_vec(),
25             spki: t.spki.to_vec(),
26             name_constraints: t.name_constraints.map(|x| x.to_vec()),
27         }
28     }
29 
to_trust_anchor(&self) -> webpki::TrustAnchor30     pub fn to_trust_anchor(&self) -> webpki::TrustAnchor {
31         webpki::TrustAnchor {
32             subject: &self.subject,
33             spki: &self.spki,
34             name_constraints: self.name_constraints
35                 .as_ref()
36                 .map(Vec::as_slice),
37         }
38     }
39 }
40 
41 /// A container for root certificates able to provide a root-of-trust
42 /// for connection authentication.
43 #[derive(Debug, Clone)]
44 pub struct RootCertStore {
45     /// The list of roots.
46     pub roots: Vec<OwnedTrustAnchor>,
47 }
48 
49 impl RootCertStore {
50     /// Make a new, empty `RootCertStore`.
empty() -> RootCertStore51     pub fn empty() -> RootCertStore {
52         RootCertStore { roots: Vec::new() }
53     }
54 
55     /// Return true if there are no certificates.
is_empty(&self) -> bool56     pub fn is_empty(&self) -> bool {
57         self.len() == 0
58     }
59 
60     /// Say how many certificates are in the container.
len(&self) -> usize61     pub fn len(&self) -> usize {
62         self.roots.len()
63     }
64 
65     /// Return the Subject Names for certificates in the container.
get_subjects(&self) -> DistinguishedNames66     pub fn get_subjects(&self) -> DistinguishedNames {
67         let mut r = DistinguishedNames::new();
68 
69         for ota in &self.roots {
70             let mut name = Vec::new();
71             name.extend_from_slice(&ota.subject);
72             x509::wrap_in_sequence(&mut name);
73             r.push(DistinguishedName::new(name));
74         }
75 
76         r
77     }
78 
79     /// Add a single DER-encoded certificate to the store.
add(&mut self, der: &key::Certificate) -> Result<(), webpki::Error>80     pub fn add(&mut self, der: &key::Certificate) -> Result<(), webpki::Error> {
81         let ta = webpki::trust_anchor_util::cert_der_as_trust_anchor(&der.0)?;
82 
83         let ota = OwnedTrustAnchor::from_trust_anchor(&ta);
84         self.roots.push(ota);
85         Ok(())
86     }
87 
88     /// Adds all the given TrustAnchors `anchors`.  This does not
89     /// fail.
add_server_trust_anchors(&mut self, &webpki::TLSServerTrustAnchors(anchors): &webpki::TLSServerTrustAnchors)90     pub fn add_server_trust_anchors(&mut self,
91                                     &webpki::TLSServerTrustAnchors(anchors):
92                                         &webpki::TLSServerTrustAnchors) {
93         for ta in anchors {
94             self.roots.push(OwnedTrustAnchor::from_trust_anchor(ta));
95         }
96     }
97 
98     /// Parse a PEM file and add all certificates found inside.
99     /// Errors are non-specific; they may be io errors in `rd` and
100     /// PEM format errors, but not certificate validity errors.
101     ///
102     /// This is because large collections of root certificates often
103     /// include ancient or syntactically invalid certificates.  CAs
104     /// are competent like that.
105     ///
106     /// Returns the number of certificates added, and the number
107     /// which were extracted from the PEM but ultimately unsuitable.
add_pem_file(&mut self, rd: &mut dyn io::BufRead) -> Result<(usize, usize), ()>108     pub fn add_pem_file(&mut self, rd: &mut dyn io::BufRead) -> Result<(usize, usize), ()> {
109         let ders = pemfile::certs(rd)?;
110         let mut valid_count = 0;
111         let mut invalid_count = 0;
112 
113         for der in ders {
114             #[cfg_attr(not(feature = "logging"), allow(unused_variables))]
115             match self.add(&der) {
116                 Ok(_) => valid_count += 1,
117                 Err(err) => {
118                     trace!("invalid cert der {:?}", der);
119                     debug!("certificate parsing failed: {:?}", err);
120                     invalid_count += 1
121                 }
122             }
123         }
124 
125         debug!("add_pem_file processed {} valid and {} invalid certs",
126               valid_count,
127               invalid_count);
128 
129         Ok((valid_count, invalid_count))
130     }
131 }
132