Coverage Report

Created: 2026-10-28 06:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/rustls-0.23.46/src/server/handy.rs
Line
Count
Source
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.  It 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
        /// After five sessions are put into a cache of size 2, exactly the
128
        /// two most recently added sessions remain.
129
        #[test]
130
        fn test_serversessionmemorycache_drops_to_maintain_size_invariant() {
131
            let c = ServerSessionMemoryCache::new(2);
132
            assert!(c.put(vec![0x01], vec![0x02]));
133
            assert!(c.put(vec![0x03], vec![0x04]));
134
            assert!(c.put(vec![0x05], vec![0x06]));
135
            assert!(c.put(vec![0x07], vec![0x08]));
136
            assert!(c.put(vec![0x09], vec![0x0a]));
137
138
            assert_eq!(c.get(&[0x01]), None);
139
            assert_eq!(c.get(&[0x03]), None);
140
            assert_eq!(c.get(&[0x05]), None);
141
            assert_eq!(c.get(&[0x07]), Some(vec![0x08]));
142
            assert_eq!(c.get(&[0x09]), Some(vec![0x0a]));
143
        }
144
145
        /// A cache of size 1 keeps the session put into it, and a second
146
        /// put replaces it.
147
        #[test]
148
        fn test_serversessionmemorycache_size_one_retains_session() {
149
            let c = ServerSessionMemoryCache::new(1);
150
            assert!(c.put(vec![0x01], vec![0x02]));
151
            assert_eq!(c.get(&[0x01]), Some(vec![0x02]));
152
153
            assert!(c.put(vec![0x03], vec![0x04]));
154
            assert_eq!(c.get(&[0x01]), None);
155
            assert_eq!(c.get(&[0x03]), Some(vec![0x04]));
156
        }
157
    }
158
}
159
160
#[cfg(any(feature = "std", feature = "hashbrown"))]
161
pub use cache::ServerSessionMemoryCache;
162
163
/// Something which never produces tickets.
164
#[derive(Debug)]
165
pub(super) struct NeverProducesTickets {}
166
167
impl server::ProducesTickets for NeverProducesTickets {
168
0
    fn enabled(&self) -> bool {
169
0
        false
170
0
    }
171
0
    fn lifetime(&self) -> u32 {
172
0
        0
173
0
    }
174
0
    fn encrypt(&self, _bytes: &[u8]) -> Option<Vec<u8>> {
175
0
        None
176
0
    }
177
0
    fn decrypt(&self, _bytes: &[u8]) -> Option<Vec<u8>> {
178
0
        None
179
0
    }
180
}
181
182
/// An exemplar `ResolvesServerCert` implementation that always resolves to a single
183
/// [RFC 7250] raw public key.
184
///
185
/// [RFC 7250]: https://tools.ietf.org/html/rfc7250
186
#[derive(Clone, Debug)]
187
pub struct AlwaysResolvesServerRawPublicKeys(Arc<sign::CertifiedKey>);
188
189
impl AlwaysResolvesServerRawPublicKeys {
190
    /// Create a new `AlwaysResolvesServerRawPublicKeys` instance.
191
0
    pub fn new(certified_key: Arc<sign::CertifiedKey>) -> Self {
192
0
        Self(certified_key)
193
0
    }
194
}
195
196
impl server::ResolvesServerCert for AlwaysResolvesServerRawPublicKeys {
197
0
    fn resolve(&self, _client_hello: ClientHello<'_>) -> Option<Arc<sign::CertifiedKey>> {
198
0
        Some(self.0.clone())
199
0
    }
200
201
0
    fn only_raw_public_keys(&self) -> bool {
202
0
        true
203
0
    }
204
}
205
206
#[cfg(any(feature = "std", feature = "hashbrown"))]
207
mod sni_resolver {
208
    use alloc::string::{String, ToString};
209
    use core::fmt::Debug;
210
211
    use pki_types::{DnsName, ServerName};
212
213
    use crate::error::Error;
214
    use crate::hash_map::HashMap;
215
    use crate::server::ClientHello;
216
    use crate::sync::Arc;
217
    use crate::webpki::{ParsedCertificate, verify_server_name};
218
    use crate::{server, sign};
219
220
    /// Something that resolves do different cert chains/keys based
221
    /// on client-supplied server name (via SNI).
222
    #[derive(Debug)]
223
    pub struct ResolvesServerCertUsingSni {
224
        by_name: HashMap<String, Arc<sign::CertifiedKey>>,
225
    }
226
227
    impl ResolvesServerCertUsingSni {
228
        /// Create a new and empty (i.e., knows no certificates) resolver.
229
0
        pub fn new() -> Self {
230
0
            Self {
231
0
                by_name: HashMap::new(),
232
0
            }
233
0
        }
234
235
        /// Add a new `sign::CertifiedKey` to be used for the given SNI `name`.
236
        ///
237
        /// This function fails if `name` is not a valid DNS name, or if
238
        /// it's not valid for the supplied certificate, or if the certificate
239
        /// chain is syntactically faulty.
240
0
        pub fn add(&mut self, name: &str, ck: sign::CertifiedKey) -> Result<(), Error> {
241
0
            let server_name = {
242
0
                let checked_name = DnsName::try_from(name)
243
0
                    .map_err(|_| Error::General("Bad DNS name".into()))
244
0
                    .map(|name| name.to_lowercase_owned())?;
245
0
                ServerName::DnsName(checked_name)
246
            };
247
248
            // Check the certificate chain for validity:
249
            // - it should be non-empty list
250
            // - the first certificate should be parsable as a x509v3,
251
            // - the first certificate should quote the given server name
252
            //   (if provided)
253
            //
254
            // These checks are not security-sensitive.  They are the
255
            // *server* attempting to detect accidental misconfiguration.
256
257
0
            ck.end_entity_cert()
258
0
                .and_then(ParsedCertificate::try_from)
259
0
                .and_then(|cert| verify_server_name(&cert, &server_name))?;
260
261
0
            if let ServerName::DnsName(name) = server_name {
262
0
                self.by_name
263
0
                    .insert(name.as_ref().to_string(), Arc::new(ck));
264
0
            }
265
0
            Ok(())
266
0
        }
267
    }
268
269
    impl server::ResolvesServerCert for ResolvesServerCertUsingSni {
270
0
        fn resolve(&self, client_hello: ClientHello<'_>) -> Option<Arc<sign::CertifiedKey>> {
271
0
            if let Some(name) = client_hello.server_name() {
272
0
                self.by_name.get(name).cloned()
273
            } else {
274
                // This kind of resolver requires SNI
275
0
                None
276
            }
277
0
        }
278
    }
279
280
    #[cfg(test)]
281
    mod tests {
282
        use super::*;
283
        use crate::server::ResolvesServerCert;
284
285
        #[test]
286
        fn test_resolvesservercertusingsni_requires_sni() {
287
            let rscsni = ResolvesServerCertUsingSni::new();
288
            assert!(
289
                rscsni
290
                    .resolve(ClientHello {
291
                        server_name: &None,
292
                        signature_schemes: &[],
293
                        alpn: None,
294
                        server_cert_types: None,
295
                        client_cert_types: None,
296
                        cipher_suites: &[],
297
                        certificate_authorities: None,
298
                        named_groups: None,
299
                    })
300
                    .is_none()
301
            );
302
        }
303
304
        #[test]
305
        fn test_resolvesservercertusingsni_handles_unknown_name() {
306
            let rscsni = ResolvesServerCertUsingSni::new();
307
            let name = DnsName::try_from("hello.com")
308
                .unwrap()
309
                .to_owned();
310
            assert!(
311
                rscsni
312
                    .resolve(ClientHello {
313
                        server_name: &Some(name),
314
                        signature_schemes: &[],
315
                        alpn: None,
316
                        server_cert_types: None,
317
                        client_cert_types: None,
318
                        cipher_suites: &[],
319
                        certificate_authorities: None,
320
                        named_groups: None,
321
                    })
322
                    .is_none()
323
            );
324
        }
325
    }
326
}
327
328
#[cfg(any(feature = "std", feature = "hashbrown"))]
329
pub use sni_resolver::ResolvesServerCertUsingSni;
330
331
#[cfg(test)]
332
mod tests {
333
    use std::vec;
334
335
    use super::*;
336
    use crate::server::{ProducesTickets, StoresServerSessions};
337
338
    #[test]
339
    fn test_noserversessionstorage_drops_put() {
340
        let c = NoServerSessionStorage {};
341
        assert!(!c.put(vec![0x01], vec![0x02]));
342
    }
343
344
    #[test]
345
    fn test_noserversessionstorage_denies_gets() {
346
        let c = NoServerSessionStorage {};
347
        c.put(vec![0x01], vec![0x02]);
348
        assert_eq!(c.get(&[]), None);
349
        assert_eq!(c.get(&[0x01]), None);
350
        assert_eq!(c.get(&[0x02]), None);
351
    }
352
353
    #[test]
354
    fn test_noserversessionstorage_denies_takes() {
355
        let c = NoServerSessionStorage {};
356
        assert_eq!(c.take(&[]), None);
357
        assert_eq!(c.take(&[0x01]), None);
358
        assert_eq!(c.take(&[0x02]), None);
359
    }
360
361
    #[test]
362
    fn test_neverproducestickets_does_nothing() {
363
        let npt = NeverProducesTickets {};
364
        assert!(!npt.enabled());
365
        assert_eq!(0, npt.lifetime());
366
        assert_eq!(None, npt.encrypt(&[]));
367
        assert_eq!(None, npt.decrypt(&[]));
368
    }
369
}