1use alloc::vec::Vec;
2use core::fmt::Debug;
3
4use crate::server::{ServerSessionKey, StoresServerSessions};
5
6#[expect(clippy::exhaustive_structs)]
8#[derive(Debug)]
9pub struct NoServerSessionStorage {}
10
11impl StoresServerSessions for NoServerSessionStorage {
12 fn put(&self, _id: ServerSessionKey<'_>, _sec: Vec<u8>) -> bool {
13 false
14 }
15 fn get(&self, _id: ServerSessionKey<'_>) -> Option<Vec<u8>> {
16 None
17 }
18 fn take(&self, _id: ServerSessionKey<'_>) -> Option<Vec<u8>> {
19 None
20 }
21 fn can_cache(&self) -> bool {
22 false
23 }
24}
25
26mod cache {
27 use core::fmt::Formatter;
28
29 use super::*;
30 use crate::limited_cache;
31 use crate::lock::Mutex;
32 use crate::server::StoresServerSessions;
33 use crate::sync::Arc;
34
35 pub struct ServerSessionMemoryCache {
39 cache: Mutex<limited_cache::LimitedCache<Vec<u8>, Vec<u8>>>,
40 }
41
42 impl ServerSessionMemoryCache {
43 pub fn new(size: usize) -> Arc<Self> {
47 Arc::new(Self {
48 cache: Mutex::new(limited_cache::LimitedCache::new(size)),
49 })
50 }
51 }
52
53 impl StoresServerSessions for ServerSessionMemoryCache {
54 fn put(&self, key: ServerSessionKey<'_>, value: Vec<u8>) -> bool {
55 self.cache
56 .lock()
57 .unwrap()
58 .insert(key.as_ref().to_vec(), value);
59 true
60 }
61
62 fn get(&self, key: ServerSessionKey<'_>) -> Option<Vec<u8>> {
63 self.cache
64 .lock()
65 .unwrap()
66 .get(key.as_ref())
67 .cloned()
68 }
69
70 fn take(&self, key: ServerSessionKey<'_>) -> Option<Vec<u8>> {
71 self.cache
72 .lock()
73 .unwrap()
74 .remove(key.as_ref())
75 }
76
77 fn can_cache(&self) -> bool {
78 true
79 }
80 }
81
82 impl Debug for ServerSessionMemoryCache {
83 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
84 f.debug_struct("ServerSessionMemoryCache")
85 .finish_non_exhaustive()
86 }
87 }
88
89 #[cfg(test)]
90 mod tests {
91 use std::vec;
92
93 use super::*;
94 use crate::server::StoresServerSessions;
95
96 #[test]
97 fn test_serversessionmemorycache_accepts_put() {
98 let c = ServerSessionMemoryCache::new(4);
99 assert!(c.put(ServerSessionKey::new(&[0x01]), vec![0x02]));
100 }
101
102 #[test]
103 fn test_serversessionmemorycache_persists_put() {
104 let c = ServerSessionMemoryCache::new(4);
105 assert!(c.put(ServerSessionKey::new(&[0x01]), vec![0x02]));
106 assert_eq!(c.get(ServerSessionKey::new(&[0x01])), Some(vec![0x02]));
107 assert_eq!(c.get(ServerSessionKey::new(&[0x01])), Some(vec![0x02]));
108 }
109
110 #[test]
111 fn test_serversessionmemorycache_overwrites_put() {
112 let c = ServerSessionMemoryCache::new(4);
113 assert!(c.put(ServerSessionKey::new(&[0x01]), vec![0x02]));
114 assert!(c.put(ServerSessionKey::new(&[0x01]), vec![0x04]));
115 assert_eq!(c.get(ServerSessionKey::new(&[0x01])), Some(vec![0x04]));
116 }
117
118 #[test]
121 fn test_serversessionmemorycache_drops_to_maintain_size_invariant() {
122 let c = ServerSessionMemoryCache::new(2);
123 assert!(c.put(ServerSessionKey::new(&[0x01]), vec![0x02]));
124 assert!(c.put(ServerSessionKey::new(&[0x03]), vec![0x04]));
125 assert!(c.put(ServerSessionKey::new(&[0x05]), vec![0x06]));
126 assert!(c.put(ServerSessionKey::new(&[0x07]), vec![0x08]));
127 assert!(c.put(ServerSessionKey::new(&[0x09]), vec![0x0a]));
128
129 assert_eq!(c.get(ServerSessionKey::new(&[0x01])), None);
130 assert_eq!(c.get(ServerSessionKey::new(&[0x03])), None);
131 assert_eq!(c.get(ServerSessionKey::new(&[0x05])), None);
132 assert_eq!(c.get(ServerSessionKey::new(&[0x07])), Some(vec![0x08]));
133 assert_eq!(c.get(ServerSessionKey::new(&[0x09])), Some(vec![0x0a]));
134 }
135
136 #[test]
139 fn test_serversessionmemorycache_size_one_retains_session() {
140 let c = ServerSessionMemoryCache::new(1);
141 assert!(c.put(ServerSessionKey::new(&[0x01]), vec![0x02]));
142 assert_eq!(c.get(ServerSessionKey::new(&[0x01])), Some(vec![0x02]));
143
144 assert!(c.put(ServerSessionKey::new(&[0x03]), vec![0x04]));
145 assert_eq!(c.get(ServerSessionKey::new(&[0x01])), None);
146 assert_eq!(c.get(ServerSessionKey::new(&[0x03])), Some(vec![0x04]));
147 }
148 }
149}
150
151pub use cache::ServerSessionMemoryCache;
152
153#[cfg(feature = "webpki")]
154mod sni_resolver {
155 use core::fmt::Debug;
156
157 use pki_types::{DnsName, ServerName};
158
159 use crate::crypto::{CertificateIdentity, Credentials, Identity, SelectedCredential};
160 use crate::error::{Error, PeerIncompatible};
161 use crate::hash_map::HashMap;
162 use crate::server::{self, ClientHello};
163 use crate::sync::Arc;
164 use crate::webpki::{ParsedCertificate, verify_server_name};
165
166 #[derive(Debug)]
169 pub struct ServerNameResolver {
170 by_name: HashMap<DnsName<'static>, Arc<Credentials>>,
171 }
172
173 impl ServerNameResolver {
174 pub fn new() -> Self {
176 Self {
177 by_name: HashMap::new(),
178 }
179 }
180
181 pub fn add(&mut self, name: DnsName<'static>, ck: Credentials) -> Result<(), Error> {
186 let wrapped = ServerName::DnsName(name);
196 if let Identity::X509(CertificateIdentity { end_entity, .. }) = &*ck.identity {
197 let parsed = ParsedCertificate::try_from(end_entity)?;
198 verify_server_name(&parsed, &wrapped)?;
199 }
200
201 let ServerName::DnsName(name) = wrapped else {
202 unreachable!()
203 };
204
205 self.by_name.insert(name, Arc::new(ck));
206 Ok(())
207 }
208 }
209
210 impl server::ServerCredentialResolver for ServerNameResolver {
211 fn resolve(&self, client_hello: &ClientHello<'_>) -> Result<SelectedCredential, Error> {
212 let Some(name) = client_hello.server_name() else {
213 return Err(PeerIncompatible::NoServerNameProvided.into());
214 };
215
216 let Some(credentials) = self.by_name.get(name) else {
217 return Err(Error::NoSuitableCertificate);
218 };
219
220 match credentials.signer(client_hello.signature_schemes) {
221 Some(signer) => Ok(signer),
222 None => Err(PeerIncompatible::NoSignatureSchemesInCommon.into()),
223 }
224 }
225 }
226
227 #[cfg(test)]
228 mod tests {
229 use alloc::borrow::Cow;
230
231 use super::*;
232 use crate::server::ServerCredentialResolver;
233
234 #[test]
235 fn test_server_name_resolver_requires_sni() {
236 let rscsni = ServerNameResolver::new();
237 assert!(
238 rscsni
239 .resolve(&ClientHello::empty())
240 .is_err()
241 );
242 }
243
244 #[test]
245 fn test_server_name_resolver_handles_unknown_name() {
246 let server_name = DnsName::try_from("hello.com")
247 .unwrap()
248 .to_owned();
249 let mut ch = ClientHello::empty();
250 ch.server_name = Some(Cow::Borrowed(&server_name));
251
252 let rscsni = ServerNameResolver::new();
253 assert!(rscsni.resolve(&ch).is_err());
254 }
255 }
256}
257
258#[cfg(feature = "webpki")]
259pub use sni_resolver::ServerNameResolver;
260
261#[cfg(test)]
262mod tests {
263 use std::vec;
264
265 use super::*;
266 use crate::server::StoresServerSessions;
267
268 #[test]
269 fn test_noserversessionstorage_drops_put() {
270 let c = NoServerSessionStorage {};
271 assert!(!c.put(ServerSessionKey::new(&[0x01]), vec![0x02]));
272 }
273
274 #[test]
275 fn test_noserversessionstorage_denies_gets() {
276 let c = NoServerSessionStorage {};
277 c.put(ServerSessionKey::new(&[0x01]), vec![0x02]);
278 assert_eq!(c.get(ServerSessionKey::new(&[])), None);
279 assert_eq!(c.get(ServerSessionKey::new(&[0x01])), None);
280 assert_eq!(c.get(ServerSessionKey::new(&[0x02])), None);
281 }
282
283 #[test]
284 fn test_noserversessionstorage_denies_takes() {
285 let c = NoServerSessionStorage {};
286 assert_eq!(c.take(ServerSessionKey::new(&[])), None);
287 assert_eq!(c.take(ServerSessionKey::new(&[0x01])), None);
288 assert_eq!(c.take(ServerSessionKey::new(&[0x02])), None);
289 }
290}