/rust/registry/src/index.crates.io-1949cf8c6b5b557f/rustls-0.23.23/src/client/handy.rs
Line | Count | Source |
1 | | use pki_types::ServerName; |
2 | | |
3 | | use crate::enums::SignatureScheme; |
4 | | use crate::msgs::persist; |
5 | | use crate::sync::Arc; |
6 | | use crate::{client, sign, NamedGroup}; |
7 | | |
8 | | /// An implementer of `ClientSessionStore` which does nothing. |
9 | | #[derive(Debug)] |
10 | | pub(super) struct NoClientSessionStorage; |
11 | | |
12 | | impl client::ClientSessionStore for NoClientSessionStorage { |
13 | 0 | fn set_kx_hint(&self, _: ServerName<'static>, _: NamedGroup) {} |
14 | | |
15 | 0 | fn kx_hint(&self, _: &ServerName<'_>) -> Option<NamedGroup> { |
16 | 0 | None |
17 | 0 | } |
18 | | |
19 | 0 | fn set_tls12_session(&self, _: ServerName<'static>, _: persist::Tls12ClientSessionValue) {} |
20 | | |
21 | 0 | fn tls12_session(&self, _: &ServerName<'_>) -> Option<persist::Tls12ClientSessionValue> { |
22 | 0 | None |
23 | 0 | } |
24 | | |
25 | 0 | fn remove_tls12_session(&self, _: &ServerName<'_>) {} |
26 | | |
27 | 0 | fn insert_tls13_ticket(&self, _: ServerName<'static>, _: persist::Tls13ClientSessionValue) {} |
28 | | |
29 | 0 | fn take_tls13_ticket(&self, _: &ServerName<'_>) -> Option<persist::Tls13ClientSessionValue> { |
30 | 0 | None |
31 | 0 | } |
32 | | } |
33 | | |
34 | | #[cfg(any(feature = "std", feature = "hashbrown"))] |
35 | | mod cache { |
36 | | use alloc::collections::VecDeque; |
37 | | use core::fmt; |
38 | | |
39 | | use pki_types::ServerName; |
40 | | |
41 | | use crate::lock::Mutex; |
42 | | use crate::msgs::persist; |
43 | | use crate::{limited_cache, NamedGroup}; |
44 | | |
45 | | const MAX_TLS13_TICKETS_PER_SERVER: usize = 8; |
46 | | |
47 | | struct ServerData { |
48 | | kx_hint: Option<NamedGroup>, |
49 | | |
50 | | // Zero or one TLS1.2 sessions. |
51 | | #[cfg(feature = "tls12")] |
52 | | tls12: Option<persist::Tls12ClientSessionValue>, |
53 | | |
54 | | // Up to MAX_TLS13_TICKETS_PER_SERVER TLS1.3 tickets, oldest first. |
55 | | tls13: VecDeque<persist::Tls13ClientSessionValue>, |
56 | | } |
57 | | |
58 | | impl Default for ServerData { |
59 | 0 | fn default() -> Self { |
60 | 0 | Self { |
61 | 0 | kx_hint: None, |
62 | 0 | #[cfg(feature = "tls12")] |
63 | 0 | tls12: None, |
64 | 0 | tls13: VecDeque::with_capacity(MAX_TLS13_TICKETS_PER_SERVER), |
65 | 0 | } |
66 | 0 | } |
67 | | } |
68 | | |
69 | | /// An implementer of `ClientSessionStore` that stores everything |
70 | | /// in memory. |
71 | | /// |
72 | | /// It enforces a limit on the number of entries to bound memory usage. |
73 | | pub struct ClientSessionMemoryCache { |
74 | | servers: Mutex<limited_cache::LimitedCache<ServerName<'static>, ServerData>>, |
75 | | } |
76 | | |
77 | | impl ClientSessionMemoryCache { |
78 | | /// Make a new ClientSessionMemoryCache. `size` is the |
79 | | /// maximum number of stored sessions. |
80 | | #[cfg(feature = "std")] |
81 | 0 | pub fn new(size: usize) -> Self { |
82 | 0 | let max_servers = size.saturating_add(MAX_TLS13_TICKETS_PER_SERVER - 1) |
83 | 0 | / MAX_TLS13_TICKETS_PER_SERVER; |
84 | 0 | Self { |
85 | 0 | servers: Mutex::new(limited_cache::LimitedCache::new(max_servers)), |
86 | 0 | } |
87 | 0 | } |
88 | | |
89 | | /// Make a new ClientSessionMemoryCache. `size` is the |
90 | | /// maximum number of stored sessions. |
91 | | #[cfg(not(feature = "std"))] |
92 | | pub fn new<M: crate::lock::MakeMutex>(size: usize) -> Self { |
93 | | let max_servers = size.saturating_add(MAX_TLS13_TICKETS_PER_SERVER - 1) |
94 | | / MAX_TLS13_TICKETS_PER_SERVER; |
95 | | Self { |
96 | | servers: Mutex::new::<M>(limited_cache::LimitedCache::new(max_servers)), |
97 | | } |
98 | | } |
99 | | } |
100 | | |
101 | | impl super::client::ClientSessionStore for ClientSessionMemoryCache { |
102 | 0 | fn set_kx_hint(&self, server_name: ServerName<'static>, group: NamedGroup) { |
103 | 0 | self.servers |
104 | 0 | .lock() |
105 | 0 | .unwrap() |
106 | 0 | .get_or_insert_default_and_edit(server_name, |data| data.kx_hint = Some(group)); |
107 | 0 | } |
108 | | |
109 | 0 | fn kx_hint(&self, server_name: &ServerName<'_>) -> Option<NamedGroup> { |
110 | 0 | self.servers |
111 | 0 | .lock() |
112 | 0 | .unwrap() |
113 | 0 | .get(server_name) |
114 | 0 | .and_then(|sd| sd.kx_hint) |
115 | 0 | } |
116 | | |
117 | 0 | fn set_tls12_session( |
118 | 0 | &self, |
119 | 0 | _server_name: ServerName<'static>, |
120 | 0 | _value: persist::Tls12ClientSessionValue, |
121 | 0 | ) { |
122 | | #[cfg(feature = "tls12")] |
123 | | self.servers |
124 | | .lock() |
125 | | .unwrap() |
126 | | .get_or_insert_default_and_edit(_server_name.clone(), |data| { |
127 | | data.tls12 = Some(_value) |
128 | | }); |
129 | 0 | } |
130 | | |
131 | 0 | fn tls12_session( |
132 | 0 | &self, |
133 | 0 | _server_name: &ServerName<'_>, |
134 | 0 | ) -> Option<persist::Tls12ClientSessionValue> { |
135 | | #[cfg(not(feature = "tls12"))] |
136 | 0 | return None; |
137 | | |
138 | | #[cfg(feature = "tls12")] |
139 | | self.servers |
140 | | .lock() |
141 | | .unwrap() |
142 | | .get(_server_name) |
143 | | .and_then(|sd| sd.tls12.as_ref().cloned()) |
144 | 0 | } |
145 | | |
146 | 0 | fn remove_tls12_session(&self, _server_name: &ServerName<'static>) { |
147 | | #[cfg(feature = "tls12")] |
148 | | self.servers |
149 | | .lock() |
150 | | .unwrap() |
151 | | .get_mut(_server_name) |
152 | | .and_then(|data| data.tls12.take()); |
153 | 0 | } |
154 | | |
155 | 0 | fn insert_tls13_ticket( |
156 | 0 | &self, |
157 | 0 | server_name: ServerName<'static>, |
158 | 0 | value: persist::Tls13ClientSessionValue, |
159 | 0 | ) { |
160 | 0 | self.servers |
161 | 0 | .lock() |
162 | 0 | .unwrap() |
163 | 0 | .get_or_insert_default_and_edit(server_name.clone(), |data| { |
164 | 0 | if data.tls13.len() == data.tls13.capacity() { |
165 | 0 | data.tls13.pop_front(); |
166 | 0 | } |
167 | 0 | data.tls13.push_back(value); |
168 | 0 | }); |
169 | 0 | } |
170 | | |
171 | 0 | fn take_tls13_ticket( |
172 | 0 | &self, |
173 | 0 | server_name: &ServerName<'static>, |
174 | 0 | ) -> Option<persist::Tls13ClientSessionValue> { |
175 | 0 | self.servers |
176 | 0 | .lock() |
177 | 0 | .unwrap() |
178 | 0 | .get_mut(server_name) |
179 | 0 | .and_then(|data| data.tls13.pop_back()) |
180 | 0 | } |
181 | | } |
182 | | |
183 | | impl fmt::Debug for ClientSessionMemoryCache { |
184 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
185 | | // Note: we omit self.servers as it may contain sensitive data. |
186 | 0 | f.debug_struct("ClientSessionMemoryCache") |
187 | 0 | .finish() |
188 | 0 | } |
189 | | } |
190 | | } |
191 | | |
192 | | #[cfg(any(feature = "std", feature = "hashbrown"))] |
193 | | pub use cache::ClientSessionMemoryCache; |
194 | | |
195 | | #[derive(Debug)] |
196 | | pub(super) struct FailResolveClientCert {} |
197 | | |
198 | | impl client::ResolvesClientCert for FailResolveClientCert { |
199 | 0 | fn resolve( |
200 | 0 | &self, |
201 | 0 | _root_hint_subjects: &[&[u8]], |
202 | 0 | _sigschemes: &[SignatureScheme], |
203 | 0 | ) -> Option<Arc<sign::CertifiedKey>> { |
204 | 0 | None |
205 | 0 | } |
206 | | |
207 | 0 | fn has_certs(&self) -> bool { |
208 | 0 | false |
209 | 0 | } |
210 | | } |
211 | | |
212 | | /// An exemplar `ResolvesClientCert` implementation that always resolves to a single |
213 | | /// [RFC 7250] raw public key. |
214 | | /// |
215 | | /// [RFC 7250]: https://tools.ietf.org/html/rfc7250 |
216 | | #[derive(Clone, Debug)] |
217 | | pub struct AlwaysResolvesClientRawPublicKeys(Arc<sign::CertifiedKey>); |
218 | | impl AlwaysResolvesClientRawPublicKeys { |
219 | | /// Create a new `AlwaysResolvesClientRawPublicKeys` instance. |
220 | 0 | pub fn new(certified_key: Arc<sign::CertifiedKey>) -> Self { |
221 | 0 | Self(certified_key) |
222 | 0 | } |
223 | | } |
224 | | |
225 | | impl client::ResolvesClientCert for AlwaysResolvesClientRawPublicKeys { |
226 | 0 | fn resolve( |
227 | 0 | &self, |
228 | 0 | _root_hint_subjects: &[&[u8]], |
229 | 0 | _sigschemes: &[SignatureScheme], |
230 | 0 | ) -> Option<Arc<sign::CertifiedKey>> { |
231 | 0 | Some(Arc::clone(&self.0)) |
232 | 0 | } |
233 | | |
234 | 0 | fn only_raw_public_keys(&self) -> bool { |
235 | 0 | true |
236 | 0 | } |
237 | | |
238 | | /// Returns true if the resolver is ready to present an identity. |
239 | | /// |
240 | | /// Even though the function is called `has_certs`, it returns true |
241 | | /// although only an RPK (Raw Public Key) is available, not an actual certificate. |
242 | 0 | fn has_certs(&self) -> bool { |
243 | 0 | true |
244 | 0 | } |
245 | | } |
246 | | |
247 | | #[cfg(test)] |
248 | | #[macro_rules_attribute::apply(test_for_each_provider)] |
249 | | mod tests { |
250 | | use std::prelude::v1::*; |
251 | | |
252 | | use pki_types::{ServerName, UnixTime}; |
253 | | |
254 | | use super::provider::cipher_suite; |
255 | | use super::NoClientSessionStorage; |
256 | | use crate::client::ClientSessionStore; |
257 | | use crate::msgs::base::PayloadU16; |
258 | | use crate::msgs::enums::NamedGroup; |
259 | | use crate::msgs::handshake::CertificateChain; |
260 | | #[cfg(feature = "tls12")] |
261 | | use crate::msgs::handshake::SessionId; |
262 | | use crate::msgs::persist::Tls13ClientSessionValue; |
263 | | use crate::suites::SupportedCipherSuite; |
264 | | use crate::sync::Arc; |
265 | | |
266 | | #[test] |
267 | | fn test_noclientsessionstorage_does_nothing() { |
268 | | let c = NoClientSessionStorage {}; |
269 | | let name = ServerName::try_from("example.com").unwrap(); |
270 | | let now = UnixTime::now(); |
271 | | |
272 | | c.set_kx_hint(name.clone(), NamedGroup::X25519); |
273 | | assert_eq!(None, c.kx_hint(&name)); |
274 | | |
275 | | #[cfg(feature = "tls12")] |
276 | | { |
277 | | use crate::msgs::persist::Tls12ClientSessionValue; |
278 | | let SupportedCipherSuite::Tls12(tls12_suite) = |
279 | | cipher_suite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 |
280 | | else { |
281 | | unreachable!() |
282 | | }; |
283 | | |
284 | | c.set_tls12_session( |
285 | | name.clone(), |
286 | | Tls12ClientSessionValue::new( |
287 | | tls12_suite, |
288 | | SessionId::empty(), |
289 | | Arc::new(PayloadU16::empty()), |
290 | | &[], |
291 | | CertificateChain::default(), |
292 | | now, |
293 | | 0, |
294 | | true, |
295 | | ), |
296 | | ); |
297 | | assert!(c.tls12_session(&name).is_none()); |
298 | | c.remove_tls12_session(&name); |
299 | | } |
300 | | |
301 | | let SupportedCipherSuite::Tls13(tls13_suite) = cipher_suite::TLS13_AES_256_GCM_SHA384 |
302 | | else { |
303 | | unreachable!(); |
304 | | }; |
305 | | c.insert_tls13_ticket( |
306 | | name.clone(), |
307 | | Tls13ClientSessionValue::new( |
308 | | tls13_suite, |
309 | | Arc::new(PayloadU16::empty()), |
310 | | &[], |
311 | | CertificateChain::default(), |
312 | | now, |
313 | | 0, |
314 | | 0, |
315 | | 0, |
316 | | ), |
317 | | ); |
318 | | assert!(c.take_tls13_ticket(&name).is_none()); |
319 | | } |
320 | | } |