Coverage Report

Created: 2025-05-07 06:59

/rust/registry/src/index.crates.io-6f17d22bba15001f/rustls-0.23.26/src/server/handy.rs
Line
Count
Source (jump to first uncovered line)
1
use alloc::vec::Vec;
2
use core::fmt::Debug;
3
4
use crate::server::ClientHello;
5
use crate::sync::Arc;
6
use crate::{server, sign};
7
8
/// Something which never stores sessions.
9
#[derive(Debug)]
10
pub struct NoServerSessionStorage {}
11
12
impl server::StoresServerSessions for NoServerSessionStorage {
13
0
    fn put(&self, _id: Vec<u8>, _sec: Vec<u8>) -> bool {
14
0
        false
15
0
    }
16
0
    fn get(&self, _id: &[u8]) -> Option<Vec<u8>> {
17
0
        None
18
0
    }
19
0
    fn take(&self, _id: &[u8]) -> Option<Vec<u8>> {
20
0
        None
21
0
    }
22
0
    fn can_cache(&self) -> bool {
23
0
        false
24
0
    }
25
}
26
27
#[cfg(any(feature = "std", feature = "hashbrown"))]
28
mod cache {
29
    use alloc::vec::Vec;
30
    use core::fmt::{Debug, Formatter};
31
32
    use crate::lock::Mutex;
33
    use crate::sync::Arc;
34
    use crate::{limited_cache, server};
35
36
    /// An implementer of `StoresServerSessions` that stores everything
37
    /// in memory.  If enforces a limit on the number of stored sessions
38
    /// to bound memory usage.
39
    pub struct ServerSessionMemoryCache {
40
        cache: Mutex<limited_cache::LimitedCache<Vec<u8>, Vec<u8>>>,
41
    }
42
43
    impl ServerSessionMemoryCache {
44
        /// Make a new ServerSessionMemoryCache.  `size` is the maximum
45
        /// number of stored sessions, and may be rounded-up for
46
        /// efficiency.
47
        #[cfg(feature = "std")]
48
0
        pub fn new(size: usize) -> Arc<Self> {
49
0
            Arc::new(Self {
50
0
                cache: Mutex::new(limited_cache::LimitedCache::new(size)),
51
0
            })
52
0
        }
53
54
        /// Make a new ServerSessionMemoryCache.  `size` is the maximum
55
        /// number of stored sessions, and may be rounded-up for
56
        /// efficiency.
57
        #[cfg(not(feature = "std"))]
58
        pub fn new<M: crate::lock::MakeMutex>(size: usize) -> Arc<Self> {
59
            Arc::new(Self {
60
                cache: Mutex::new::<M>(limited_cache::LimitedCache::new(size)),
61
            })
62
        }
63
    }
64
65
    impl server::StoresServerSessions for ServerSessionMemoryCache {
66
0
        fn put(&self, key: Vec<u8>, value: Vec<u8>) -> bool {
67
0
            self.cache
68
0
                .lock()
69
0
                .unwrap()
70
0
                .insert(key, value);
71
0
            true
72
0
        }
73
74
0
        fn get(&self, key: &[u8]) -> Option<Vec<u8>> {
75
0
            self.cache
76
0
                .lock()
77
0
                .unwrap()
78
0
                .get(key)
79
0
                .cloned()
80
0
        }
81
82
0
        fn take(&self, key: &[u8]) -> Option<Vec<u8>> {
83
0
            self.cache.lock().unwrap().remove(key)
84
0
        }
85
86
0
        fn can_cache(&self) -> bool {
87
0
            true
88
0
        }
89
    }
90
91
    impl Debug for ServerSessionMemoryCache {
92
0
        fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
93
0
            f.debug_struct("ServerSessionMemoryCache")
94
0
                .finish()
95
0
        }
96
    }
97
98
    #[cfg(test)]
99
    mod tests {
100
        use std::vec;
101
102
        use super::*;
103
        use crate::server::StoresServerSessions;
104
105
        #[test]
106
        fn test_serversessionmemorycache_accepts_put() {
107
            let c = ServerSessionMemoryCache::new(4);
108
            assert!(c.put(vec![0x01], vec![0x02]));
109
        }
110
111
        #[test]
112
        fn test_serversessionmemorycache_persists_put() {
113
            let c = ServerSessionMemoryCache::new(4);
114
            assert!(c.put(vec![0x01], vec![0x02]));
115
            assert_eq!(c.get(&[0x01]), Some(vec![0x02]));
116
            assert_eq!(c.get(&[0x01]), Some(vec![0x02]));
117
        }
118
119
        #[test]
120
        fn test_serversessionmemorycache_overwrites_put() {
121
            let c = ServerSessionMemoryCache::new(4);
122
            assert!(c.put(vec![0x01], vec![0x02]));
123
            assert!(c.put(vec![0x01], vec![0x04]));
124
            assert_eq!(c.get(&[0x01]), Some(vec![0x04]));
125
        }
126
127
        #[test]
128
        fn test_serversessionmemorycache_drops_to_maintain_size_invariant() {
129
            let c = ServerSessionMemoryCache::new(2);
130
            assert!(c.put(vec![0x01], vec![0x02]));
131
            assert!(c.put(vec![0x03], vec![0x04]));
132
            assert!(c.put(vec![0x05], vec![0x06]));
133
            assert!(c.put(vec![0x07], vec![0x08]));
134
            assert!(c.put(vec![0x09], vec![0x0a]));
135
136
            let count = c.get(&[0x01]).iter().count()
137
                + c.get(&[0x03]).iter().count()
138
                + c.get(&[0x05]).iter().count()
139
                + c.get(&[0x07]).iter().count()
140
                + c.get(&[0x09]).iter().count();
141
142
            assert!(count < 5);
143
        }
144
    }
145
}
146
147
#[cfg(any(feature = "std", feature = "hashbrown"))]
148
pub use cache::ServerSessionMemoryCache;
149
150
/// Something which never produces tickets.
151
#[derive(Debug)]
152
pub(super) struct NeverProducesTickets {}
153
154
impl server::ProducesTickets for NeverProducesTickets {
155
0
    fn enabled(&self) -> bool {
156
0
        false
157
0
    }
158
0
    fn lifetime(&self) -> u32 {
159
0
        0
160
0
    }
161
0
    fn encrypt(&self, _bytes: &[u8]) -> Option<Vec<u8>> {
162
0
        None
163
0
    }
164
0
    fn decrypt(&self, _bytes: &[u8]) -> Option<Vec<u8>> {
165
0
        None
166
0
    }
167
}
168
169
/// An exemplar `ResolvesServerCert` implementation that always resolves to a single
170
/// [RFC 7250] raw public key.
171
///
172
/// [RFC 7250]: https://tools.ietf.org/html/rfc7250
173
#[derive(Clone, Debug)]
174
pub struct AlwaysResolvesServerRawPublicKeys(Arc<sign::CertifiedKey>);
175
176
impl AlwaysResolvesServerRawPublicKeys {
177
    /// Create a new `AlwaysResolvesServerRawPublicKeys` instance.
178
0
    pub fn new(certified_key: Arc<sign::CertifiedKey>) -> Self {
179
0
        Self(certified_key)
180
0
    }
181
}
182
183
impl server::ResolvesServerCert for AlwaysResolvesServerRawPublicKeys {
184
0
    fn resolve(&self, _client_hello: ClientHello<'_>) -> Option<Arc<sign::CertifiedKey>> {
185
0
        Some(Arc::clone(&self.0))
186
0
    }
187
188
0
    fn only_raw_public_keys(&self) -> bool {
189
0
        true
190
0
    }
191
}
192
193
#[cfg(any(feature = "std", feature = "hashbrown"))]
194
mod sni_resolver {
195
    use alloc::string::{String, ToString};
196
    use core::fmt::Debug;
197
198
    use pki_types::{DnsName, ServerName};
199
200
    use crate::error::Error;
201
    use crate::hash_map::HashMap;
202
    use crate::server::ClientHello;
203
    use crate::sync::Arc;
204
    use crate::webpki::{ParsedCertificate, verify_server_name};
205
    use crate::{server, sign};
206
207
    /// Something that resolves do different cert chains/keys based
208
    /// on client-supplied server name (via SNI).
209
    #[derive(Debug)]
210
    pub struct ResolvesServerCertUsingSni {
211
        by_name: HashMap<String, Arc<sign::CertifiedKey>>,
212
    }
213
214
    impl ResolvesServerCertUsingSni {
215
        /// Create a new and empty (i.e., knows no certificates) resolver.
216
0
        pub fn new() -> Self {
217
0
            Self {
218
0
                by_name: HashMap::new(),
219
0
            }
220
0
        }
221
222
        /// Add a new `sign::CertifiedKey` to be used for the given SNI `name`.
223
        ///
224
        /// This function fails if `name` is not a valid DNS name, or if
225
        /// it's not valid for the supplied certificate, or if the certificate
226
        /// chain is syntactically faulty.
227
0
        pub fn add(&mut self, name: &str, ck: sign::CertifiedKey) -> Result<(), Error> {
228
0
            let server_name = {
229
0
                let checked_name = DnsName::try_from(name)
230
0
                    .map_err(|_| Error::General("Bad DNS name".into()))
231
0
                    .map(|name| name.to_lowercase_owned())?;
232
0
                ServerName::DnsName(checked_name)
233
0
            };
234
0
235
0
            // Check the certificate chain for validity:
236
0
            // - it should be non-empty list
237
0
            // - the first certificate should be parsable as a x509v3,
238
0
            // - the first certificate should quote the given server name
239
0
            //   (if provided)
240
0
            //
241
0
            // These checks are not security-sensitive.  They are the
242
0
            // *server* attempting to detect accidental misconfiguration.
243
0
244
0
            ck.end_entity_cert()
245
0
                .and_then(ParsedCertificate::try_from)
246
0
                .and_then(|cert| verify_server_name(&cert, &server_name))?;
247
248
0
            if let ServerName::DnsName(name) = server_name {
249
0
                self.by_name
250
0
                    .insert(name.as_ref().to_string(), Arc::new(ck));
251
0
            }
252
0
            Ok(())
253
0
        }
254
    }
255
256
    impl server::ResolvesServerCert for ResolvesServerCertUsingSni {
257
0
        fn resolve(&self, client_hello: ClientHello<'_>) -> Option<Arc<sign::CertifiedKey>> {
258
0
            if let Some(name) = client_hello.server_name() {
259
0
                self.by_name.get(name).cloned()
260
            } else {
261
                // This kind of resolver requires SNI
262
0
                None
263
            }
264
0
        }
265
    }
266
267
    #[cfg(test)]
268
    mod tests {
269
        use super::*;
270
        use crate::server::ResolvesServerCert;
271
272
        #[test]
273
        fn test_resolvesservercertusingsni_requires_sni() {
274
            let rscsni = ResolvesServerCertUsingSni::new();
275
            assert!(
276
                rscsni
277
                    .resolve(ClientHello {
278
                        server_name: &None,
279
                        signature_schemes: &[],
280
                        alpn: None,
281
                        server_cert_types: None,
282
                        client_cert_types: None,
283
                        cipher_suites: &[],
284
                        certificate_authorities: None,
285
                    })
286
                    .is_none()
287
            );
288
        }
289
290
        #[test]
291
        fn test_resolvesservercertusingsni_handles_unknown_name() {
292
            let rscsni = ResolvesServerCertUsingSni::new();
293
            let name = DnsName::try_from("hello.com")
294
                .unwrap()
295
                .to_owned();
296
            assert!(
297
                rscsni
298
                    .resolve(ClientHello {
299
                        server_name: &Some(name),
300
                        signature_schemes: &[],
301
                        alpn: None,
302
                        server_cert_types: None,
303
                        client_cert_types: None,
304
                        cipher_suites: &[],
305
                        certificate_authorities: None,
306
                    })
307
                    .is_none()
308
            );
309
        }
310
    }
311
}
312
313
#[cfg(any(feature = "std", feature = "hashbrown"))]
314
pub use sni_resolver::ResolvesServerCertUsingSni;
315
316
#[cfg(test)]
317
mod tests {
318
    use std::vec;
319
320
    use super::*;
321
    use crate::server::{ProducesTickets, StoresServerSessions};
322
323
    #[test]
324
    fn test_noserversessionstorage_drops_put() {
325
        let c = NoServerSessionStorage {};
326
        assert!(!c.put(vec![0x01], vec![0x02]));
327
    }
328
329
    #[test]
330
    fn test_noserversessionstorage_denies_gets() {
331
        let c = NoServerSessionStorage {};
332
        c.put(vec![0x01], vec![0x02]);
333
        assert_eq!(c.get(&[]), None);
334
        assert_eq!(c.get(&[0x01]), None);
335
        assert_eq!(c.get(&[0x02]), None);
336
    }
337
338
    #[test]
339
    fn test_noserversessionstorage_denies_takes() {
340
        let c = NoServerSessionStorage {};
341
        assert_eq!(c.take(&[]), None);
342
        assert_eq!(c.take(&[0x01]), None);
343
        assert_eq!(c.take(&[0x02]), None);
344
    }
345
346
    #[test]
347
    fn test_neverproducestickets_does_nothing() {
348
        let npt = NeverProducesTickets {};
349
        assert!(!npt.enabled());
350
        assert_eq!(0, npt.lifetime());
351
        assert_eq!(None, npt.encrypt(&[]));
352
        assert_eq!(None, npt.decrypt(&[]));
353
    }
354
}