rustls/server/
handy.rs

1use crate::dns_name::DnsNameRef;
2use crate::error::Error;
3use crate::key;
4use crate::limited_cache;
5use crate::server;
6use crate::server::ClientHello;
7use crate::sign;
8
9use std::collections;
10use std::sync::{Arc, Mutex};
11
12/// Something which never stores sessions.
13pub struct NoServerSessionStorage {}
14
15impl server::StoresServerSessions for NoServerSessionStorage {
16    fn put(&self, _id: Vec<u8>, _sec: Vec<u8>) -> bool {
17        false
18    }
19    fn get(&self, _id: &[u8]) -> Option<Vec<u8>> {
20        None
21    }
22    fn take(&self, _id: &[u8]) -> Option<Vec<u8>> {
23        None
24    }
25    fn can_cache(&self) -> bool {
26        false
27    }
28}
29
30/// An implementer of `StoresServerSessions` that stores everything
31/// in memory.  If enforces a limit on the number of stored sessions
32/// to bound memory usage.
33pub struct ServerSessionMemoryCache {
34    cache: Mutex<limited_cache::LimitedCache<Vec<u8>, Vec<u8>>>,
35}
36
37impl ServerSessionMemoryCache {
38    /// Make a new ServerSessionMemoryCache.  `size` is the maximum
39    /// number of stored sessions, and may be rounded-up for
40    /// efficiency.
41    pub fn new(size: usize) -> Arc<Self> {
42        Arc::new(Self {
43            cache: Mutex::new(limited_cache::LimitedCache::new(size)),
44        })
45    }
46}
47
48impl server::StoresServerSessions for ServerSessionMemoryCache {
49    fn put(&self, key: Vec<u8>, value: Vec<u8>) -> bool {
50        self.cache
51            .lock()
52            .unwrap()
53            .insert(key, value);
54        true
55    }
56
57    fn get(&self, key: &[u8]) -> Option<Vec<u8>> {
58        self.cache
59            .lock()
60            .unwrap()
61            .get(key)
62            .cloned()
63    }
64
65    fn take(&self, key: &[u8]) -> Option<Vec<u8>> {
66        self.cache.lock().unwrap().remove(key)
67    }
68
69    fn can_cache(&self) -> bool {
70        true
71    }
72}
73
74/// Something which never produces tickets.
75pub(super) struct NeverProducesTickets {}
76
77impl server::ProducesTickets for NeverProducesTickets {
78    fn enabled(&self) -> bool {
79        false
80    }
81    fn lifetime(&self) -> u32 {
82        0
83    }
84    fn encrypt(&self, _bytes: &[u8]) -> Option<Vec<u8>> {
85        None
86    }
87    fn decrypt(&self, _bytes: &[u8]) -> Option<Vec<u8>> {
88        None
89    }
90}
91
92/// Something which always resolves to the same cert chain.
93pub(super) struct AlwaysResolvesChain(Arc<sign::CertifiedKey>);
94
95impl AlwaysResolvesChain {
96    /// Creates an `AlwaysResolvesChain`, auto-detecting the underlying private
97    /// key type and encoding.
98    pub(super) fn new(
99        chain: Vec<key::Certificate>,
100        priv_key: &key::PrivateKey,
101    ) -> Result<Self, Error> {
102        let key = sign::any_supported_type(priv_key)
103            .map_err(|_| Error::General("invalid private key".into()))?;
104        Ok(Self(Arc::new(sign::CertifiedKey::new(chain, key))))
105    }
106
107    /// Creates an `AlwaysResolvesChain`, auto-detecting the underlying private
108    /// key type and encoding.
109    ///
110    /// If non-empty, the given OCSP response and SCTs are attached.
111    pub(super) fn new_with_extras(
112        chain: Vec<key::Certificate>,
113        priv_key: &key::PrivateKey,
114        ocsp: Vec<u8>,
115        scts: Vec<u8>,
116    ) -> Result<Self, Error> {
117        let mut r = Self::new(chain, priv_key)?;
118
119        {
120            let cert = Arc::make_mut(&mut r.0);
121            if !ocsp.is_empty() {
122                cert.ocsp = Some(ocsp);
123            }
124            if !scts.is_empty() {
125                cert.sct_list = Some(scts);
126            }
127        }
128
129        Ok(r)
130    }
131}
132
133impl server::ResolvesServerCert for AlwaysResolvesChain {
134    fn resolve(&self, _client_hello: ClientHello) -> Option<Arc<sign::CertifiedKey>> {
135        Some(Arc::clone(&self.0))
136    }
137}
138
139/// Something that resolves do different cert chains/keys based
140/// on client-supplied server name (via SNI).
141pub struct ResolvesServerCertUsingSni {
142    by_name: collections::HashMap<String, Arc<sign::CertifiedKey>>,
143}
144
145impl ResolvesServerCertUsingSni {
146    /// Create a new and empty (i.e., knows no certificates) resolver.
147    pub fn new() -> Self {
148        Self {
149            by_name: collections::HashMap::new(),
150        }
151    }
152
153    /// Add a new `sign::CertifiedKey` to be used for the given SNI `name`.
154    ///
155    /// This function fails if `name` is not a valid DNS name, or if
156    /// it's not valid for the supplied certificate, or if the certificate
157    /// chain is syntactically faulty.
158    pub fn add(&mut self, name: &str, ck: sign::CertifiedKey) -> Result<(), Error> {
159        let checked_name = DnsNameRef::try_from(name)
160            .map_err(|_| Error::General("Bad DNS name".into()))
161            .map(|dns| dns.to_lowercase_owned())?;
162
163        // Check the certificate chain for validity:
164        // - it should be non-empty list
165        // - the first certificate should be parsable as a x509v3,
166        // - the first certificate should quote the given server name
167        //   (if provided)
168        //
169        // These checks are not security-sensitive.  They are the
170        // *server* attempting to detect accidental misconfiguration.
171
172        // Always reject an empty certificate chain.
173        let end_entity_cert = ck.end_entity_cert().map_err(|_| {
174            Error::General("No end-entity certificate in certificate chain".to_string())
175        })?;
176
177        // Reject syntactically-invalid end-entity certificates.
178        let end_entity_cert =
179            webpki::EndEntityCert::try_from(end_entity_cert.as_ref()).map_err(|_| {
180                Error::General(
181                    "End-entity certificate in certificate chain is syntactically invalid"
182                        .to_string(),
183                )
184            })?;
185
186        // Note that this doesn't fully validate that the certificate is valid; it only validates that the name is one
187        // that the certificate is valid for, if the certificate is
188        // valid.
189        let general_error =
190            || Error::General("The server certificate is not valid for the given name".to_string());
191
192        let name = webpki::DnsNameRef::try_from_ascii(checked_name.as_ref().as_bytes())
193            .map_err(|_| general_error())?;
194
195        end_entity_cert
196            .verify_is_valid_for_subject_name(webpki::SubjectNameRef::DnsName(name))
197            .map_err(|_| general_error())?;
198
199        let as_str: &str = checked_name.as_ref();
200        self.by_name
201            .insert(as_str.to_string(), Arc::new(ck));
202        Ok(())
203    }
204}
205
206impl server::ResolvesServerCert for ResolvesServerCertUsingSni {
207    fn resolve(&self, client_hello: ClientHello) -> Option<Arc<sign::CertifiedKey>> {
208        if let Some(name) = client_hello.server_name() {
209            self.by_name.get(name).cloned()
210        } else {
211            // This kind of resolver requires SNI
212            None
213        }
214    }
215}
216
217#[cfg(test)]
218mod test {
219    use super::*;
220    use crate::server::ProducesTickets;
221    use crate::server::ResolvesServerCert;
222    use crate::server::StoresServerSessions;
223
224    #[test]
225    fn test_noserversessionstorage_drops_put() {
226        let c = NoServerSessionStorage {};
227        assert!(!c.put(vec![0x01], vec![0x02]));
228    }
229
230    #[test]
231    fn test_noserversessionstorage_denies_gets() {
232        let c = NoServerSessionStorage {};
233        c.put(vec![0x01], vec![0x02]);
234        assert_eq!(c.get(&[]), None);
235        assert_eq!(c.get(&[0x01]), None);
236        assert_eq!(c.get(&[0x02]), None);
237    }
238
239    #[test]
240    fn test_noserversessionstorage_denies_takes() {
241        let c = NoServerSessionStorage {};
242        assert_eq!(c.take(&[]), None);
243        assert_eq!(c.take(&[0x01]), None);
244        assert_eq!(c.take(&[0x02]), None);
245    }
246
247    #[test]
248    fn test_serversessionmemorycache_accepts_put() {
249        let c = ServerSessionMemoryCache::new(4);
250        assert!(c.put(vec![0x01], vec![0x02]));
251    }
252
253    #[test]
254    fn test_serversessionmemorycache_persists_put() {
255        let c = ServerSessionMemoryCache::new(4);
256        assert!(c.put(vec![0x01], vec![0x02]));
257        assert_eq!(c.get(&[0x01]), Some(vec![0x02]));
258        assert_eq!(c.get(&[0x01]), Some(vec![0x02]));
259    }
260
261    #[test]
262    fn test_serversessionmemorycache_overwrites_put() {
263        let c = ServerSessionMemoryCache::new(4);
264        assert!(c.put(vec![0x01], vec![0x02]));
265        assert!(c.put(vec![0x01], vec![0x04]));
266        assert_eq!(c.get(&[0x01]), Some(vec![0x04]));
267    }
268
269    #[test]
270    fn test_serversessionmemorycache_drops_to_maintain_size_invariant() {
271        let c = ServerSessionMemoryCache::new(2);
272        assert!(c.put(vec![0x01], vec![0x02]));
273        assert!(c.put(vec![0x03], vec![0x04]));
274        assert!(c.put(vec![0x05], vec![0x06]));
275        assert!(c.put(vec![0x07], vec![0x08]));
276        assert!(c.put(vec![0x09], vec![0x0a]));
277
278        let count = c.get(&[0x01]).iter().count()
279            + c.get(&[0x03]).iter().count()
280            + c.get(&[0x05]).iter().count()
281            + c.get(&[0x07]).iter().count()
282            + c.get(&[0x09]).iter().count();
283
284        assert!(count < 5);
285    }
286
287    #[test]
288    fn test_neverproducestickets_does_nothing() {
289        let npt = NeverProducesTickets {};
290        assert!(!npt.enabled());
291        assert_eq!(0, npt.lifetime());
292        assert_eq!(None, npt.encrypt(&[]));
293        assert_eq!(None, npt.decrypt(&[]));
294    }
295
296    #[test]
297    fn test_resolvesservercertusingsni_requires_sni() {
298        let rscsni = ResolvesServerCertUsingSni::new();
299        assert!(rscsni
300            .resolve(ClientHello::new(&None, &[], None, &[]))
301            .is_none());
302    }
303
304    #[test]
305    fn test_resolvesservercertusingsni_handles_unknown_name() {
306        let rscsni = ResolvesServerCertUsingSni::new();
307        let name = DnsNameRef::try_from("hello.com")
308            .unwrap()
309            .to_owned();
310        assert!(rscsni
311            .resolve(ClientHello::new(&Some(name), &[], None, &[]))
312            .is_none());
313    }
314}