Skip to main content

orbit_rustls/session/
client_v24.rs

1//! rustls 0.24 fleet-shared client-session adapter.
2
3use rustls_0_24::client::{
4    ClientSessionKey, ClientSessionStore, Tls12Session, Tls13Session,
5};
6use rustls_0_24::crypto::kx::NamedGroup;
7use rustls_0_24::pki_types::ServerName;
8
9use super::OrbitClientSessionStorage;
10use super::store::CLIENT_TLS13_TICKETS_PER_SERVER;
11
12const KX_HINT: u8 = 1;
13const TLS12_SESSION: u8 = 2;
14const TLS13_TICKET: u8 = 3;
15const DNS_NAME: u8 = 1;
16const IP_ADDRESS: u8 = 2;
17
18impl ClientSessionStore for OrbitClientSessionStorage {
19    fn set_kx_hint(
20        &self,
21        key: ClientSessionKey<'static>,
22        group: NamedGroup,
23    ) {
24        let Some((domain, server)) = storage_key(&key, KX_HINT) else {
25            return;
26        };
27        let value = u16::from(group).to_be_bytes();
28        let _ = self.primitive.put(&domain, &server, &value, self.ttl());
29    }
30
31    fn kx_hint(
32        &self,
33        key: &ClientSessionKey<'_>,
34    ) -> Option<NamedGroup> {
35        let (domain, server) = storage_key(key, KX_HINT)?;
36        let value = self.primitive.get(&domain, &server).ok()??;
37        let value: [u8; 2] = value.try_into().ok()?;
38        Some(NamedGroup::from(u16::from_be_bytes(value)))
39    }
40
41    fn set_tls12_session(
42        &self,
43        key: ClientSessionKey<'static>,
44        value: Tls12Session,
45    ) {
46        let Some((domain, server)) = storage_key(&key, TLS12_SESSION) else {
47            return;
48        };
49        let mut encoded = Vec::new();
50        value.encode(&mut encoded);
51        let _ = self.primitive.put(&domain, &server, &encoded, self.ttl());
52    }
53
54    fn tls12_session(
55        &self,
56        key: &ClientSessionKey<'_>,
57    ) -> Option<Tls12Session> {
58        let (domain, server) = storage_key(key, TLS12_SESSION)?;
59        let encoded = self.primitive.get(&domain, &server).ok()??;
60        match Tls12Session::from_slice(&encoded, &self.provider) {
61            Ok(value) => Some(value),
62            Err(error) => {
63                let _ = self.primitive.take(&domain, &server);
64                tracing::trace!(
65                    target: "orbit_rustls::client_session_cache",
66                    operation = "decode_tls12",
67                    %error,
68                    "discarding incompatible rustls client session"
69                );
70                None
71            }
72        }
73    }
74
75    fn remove_tls12_session(
76        &self,
77        key: &ClientSessionKey<'static>,
78    ) {
79        let Some((domain, server)) = storage_key(key, TLS12_SESSION) else {
80            return;
81        };
82        let _ = self.primitive.take(&domain, &server);
83    }
84
85    fn insert_tls13_ticket(
86        &self,
87        key: ClientSessionKey<'static>,
88        value: Tls13Session,
89    ) {
90        let Some((domain, server)) = storage_key(&key, TLS13_TICKET) else {
91            return;
92        };
93        let mut encoded = Vec::new();
94        value.encode(&mut encoded);
95        let _ = self.primitive.push(
96            &domain,
97            &server,
98            &encoded,
99            self.ttl(),
100            CLIENT_TLS13_TICKETS_PER_SERVER,
101        );
102    }
103
104    fn take_tls13_ticket(
105        &self,
106        key: &ClientSessionKey<'static>,
107    ) -> Option<Tls13Session> {
108        let (domain, server) = storage_key(key, TLS13_TICKET)?;
109        for _ in 0..CLIENT_TLS13_TICKETS_PER_SERVER {
110            let encoded = match self.primitive.take(&domain, &server) {
111                Ok(Some(encoded)) => encoded,
112                Ok(None) | Err(_) => return None,
113            };
114            match Tls13Session::from_slice(&encoded, &self.provider) {
115                Ok(value) => return Some(value),
116                Err(error) => {
117                    tracing::trace!(
118                        target: "orbit_rustls::client_session_cache",
119                        operation = "decode_tls13",
120                        %error,
121                        "discarding incompatible rustls client ticket"
122                    );
123                }
124            }
125        }
126        None
127    }
128}
129
130fn storage_key(
131    key: &ClientSessionKey<'_>,
132    record: u8,
133) -> Option<([u8; 33], Vec<u8>)> {
134    let mut domain = [0_u8; 33];
135    domain[0] = record;
136    domain[1..].copy_from_slice(&key.config_hash);
137
138    let mut server = Vec::new();
139    server.push(match &key.server_name {
140        ServerName::DnsName(_) => DNS_NAME,
141        ServerName::IpAddress(_) => IP_ADDRESS,
142        _ => return None,
143    });
144    server.extend_from_slice(key.server_name.to_str().as_bytes());
145    Some((domain, server))
146}