Skip to main content

rustls/server/
mod.rs

1use alloc::vec::Vec;
2
3use pki_types::{DnsName, UnixTime};
4
5use crate::crypto::cipher::Payload;
6use crate::crypto::{CipherSuite, Identity};
7use crate::enums::{ApplicationProtocol, ProtocolVersion};
8use crate::error::InvalidMessage;
9use crate::msgs::{Codec, MaybeEmpty, Reader, SessionId, SizedPayload};
10pub use crate::verify::NoClientAuth;
11use crate::verify::VerifiedIdentity;
12#[cfg(feature = "webpki")]
13pub use crate::webpki::{
14    ClientVerifierBuilder, ParsedCertificate, VerifierBuilderError, WebPkiClientVerifier,
15};
16
17pub(crate) mod config;
18pub use config::{
19    CipherSuiteSelector, ClientHello, InvalidSniPolicy, PreferClientOrder, PreferServerOrder,
20    ServerConfig, ServerCredentialResolver, StoresServerSessions, Tls13Tickets, WantsServerCert,
21};
22
23mod connection;
24pub use connection::{Accepted, ReadEarlyData, ServerConnection, ServerHandshake, ServerSide};
25
26pub(crate) mod handy;
27#[cfg(feature = "webpki")]
28pub use handy::ServerNameResolver;
29pub use handy::{NoServerSessionStorage, ServerSessionMemoryCache};
30
31mod hs;
32pub(crate) use hs::{ChooseConfig, ServerHandler, ServerState};
33
34mod tls12;
35pub(crate) use tls12::TLS12_HANDLER;
36use tls12::Tls12ServerSessionValue;
37
38mod tls13;
39pub(crate) use tls13::TLS13_HANDLER;
40use tls13::Tls13ServerSessionValue;
41
42/// Dangerous configuration that should be audited and used with extreme care.
43pub mod danger {
44    pub use crate::verify::{ClientIdentity, ClientVerifier, SignatureVerificationInput};
45}
46
47#[cfg(test)]
48mod test;
49
50#[derive(Debug)]
51pub(crate) enum ServerSessionValue<'a> {
52    Tls12(Tls12ServerSessionValue<'a>),
53    Tls13(Tls13ServerSessionValue<'a>),
54}
55
56impl<'a> Codec<'a> for ServerSessionValue<'a> {
57    fn encode(&self, bytes: &mut Vec<u8>) {
58        match self {
59            Self::Tls12(value) => {
60                ProtocolVersion::TLSv1_2.encode(bytes);
61                value.encode(bytes);
62            }
63            Self::Tls13(value) => {
64                ProtocolVersion::TLSv1_3.encode(bytes);
65                value.encode(bytes);
66            }
67        }
68    }
69
70    fn read(r: &mut Reader<'a>) -> Result<Self, InvalidMessage> {
71        match ProtocolVersion::read(r)? {
72            ProtocolVersion::TLSv1_2 => Ok(Self::Tls12(Tls12ServerSessionValue::read(r)?)),
73            ProtocolVersion::TLSv1_3 => Ok(Self::Tls13(Tls13ServerSessionValue::read(r)?)),
74            _ => Err(InvalidMessage::UnknownProtocolVersion),
75        }
76    }
77}
78
79#[derive(Debug)]
80pub(crate) struct CommonServerSessionValue<'a> {
81    pub(crate) creation_time_sec: u64,
82    pub(crate) sni: Option<DnsName<'a>>,
83    pub(crate) cipher_suite: CipherSuite,
84    pub(crate) peer_identity: Option<VerifiedIdentity<'a>>,
85    pub(crate) alpn: Option<ApplicationProtocol<'a>>,
86    pub(crate) application_data: SizedPayload<'a, u16, MaybeEmpty>,
87}
88
89impl<'a> CommonServerSessionValue<'a> {
90    pub(crate) fn new(
91        sni: Option<&DnsName<'a>>,
92        cipher_suite: CipherSuite,
93        peer_identity: Option<VerifiedIdentity<'a>>,
94        alpn: Option<ApplicationProtocol<'a>>,
95        application_data: Vec<u8>,
96        creation_time: UnixTime,
97    ) -> Self {
98        Self {
99            creation_time_sec: creation_time.as_secs(),
100            sni: sni.map(|s| s.to_owned()),
101            cipher_suite,
102            peer_identity,
103            alpn,
104            application_data: SizedPayload::from(Payload::new(application_data)),
105        }
106    }
107
108    fn into_owned(self) -> CommonServerSessionValue<'static> {
109        CommonServerSessionValue {
110            creation_time_sec: self.creation_time_sec,
111            sni: self.sni.map(|s| s.to_owned()),
112            cipher_suite: self.cipher_suite,
113            peer_identity: self
114                .peer_identity
115                .map(|i| i.into_owned()),
116            alpn: self.alpn.map(|a| a.to_owned()),
117            application_data: self.application_data.into_owned(),
118        }
119    }
120
121    pub(crate) fn can_resume(&self, suite: CipherSuite, sni: Option<&DnsName<'_>>) -> bool {
122        // The RFCs underspecify what happens if we try to resume to
123        // an unoffered/varying suite.  We merely don't resume in weird cases.
124        //
125        // RFC 6066 says "A server that implements this extension MUST NOT accept
126        // the request to resume the session if the server_name extension contains
127        // a different name. Instead, it proceeds with a full handshake to
128        // establish a new session."
129        //
130        // RFC 9846: "The server MUST ensure that it selects
131        // a compatible PSK (if any) and cipher suite."
132        self.cipher_suite == suite && self.sni.as_ref() == sni
133    }
134}
135
136impl Codec<'_> for CommonServerSessionValue<'_> {
137    fn encode(&self, bytes: &mut Vec<u8>) {
138        self.creation_time_sec.encode(bytes);
139        if let Some(sni) = &self.sni {
140            1u8.encode(bytes);
141            let sni_bytes: &str = sni.as_ref();
142            SizedPayload::<u8, MaybeEmpty>::from(Payload::Borrowed(sni_bytes.as_bytes()))
143                .encode(bytes);
144        } else {
145            0u8.encode(bytes);
146        }
147        self.cipher_suite.encode(bytes);
148        if let Some(identity) = &self.peer_identity {
149            1u8.encode(bytes);
150            identity.encode(bytes);
151        } else {
152            0u8.encode(bytes);
153        }
154        if let Some(alpn) = &self.alpn {
155            1u8.encode(bytes);
156            alpn.encode(bytes);
157        } else {
158            0u8.encode(bytes);
159        }
160        self.application_data.encode(bytes);
161    }
162
163    fn read(r: &mut Reader<'_>) -> Result<Self, InvalidMessage> {
164        let creation_time_sec = u64::read(r)?;
165        let sni = match u8::read(r)? {
166            1 => {
167                let dns_name = SizedPayload::<u8, MaybeEmpty>::read(r)?;
168                let dns_name = match DnsName::try_from(dns_name.bytes()) {
169                    Ok(dns_name) => dns_name.to_owned(),
170                    Err(_) => return Err(InvalidMessage::InvalidServerName),
171                };
172
173                Some(dns_name)
174            }
175            _ => None,
176        };
177
178        Ok(Self {
179            creation_time_sec,
180            sni,
181            cipher_suite: CipherSuite::read(r)?,
182            peer_identity: match u8::read(r)? {
183                1 => Some(VerifiedIdentity::assertion(Identity::read(r)?.into_owned())),
184                _ => None,
185            },
186            alpn: match u8::read(r)? {
187                1 => Some(ApplicationProtocol::read(r)?.to_owned()),
188                _ => None,
189            },
190            application_data: SizedPayload::read(r)?.into_owned(),
191        })
192    }
193}
194
195/// A key that identifies a server-side resumable session.
196pub struct ServerSessionKey<'a> {
197    inner: &'a [u8],
198}
199
200impl<'a> ServerSessionKey<'a> {
201    pub(crate) fn new(inner: &'a [u8]) -> Self {
202        Self { inner }
203    }
204}
205
206impl<'a> From<&'a SessionId> for ServerSessionKey<'a> {
207    fn from(session_id: &'a SessionId) -> Self {
208        Self::new(session_id.as_ref())
209    }
210}
211
212impl AsRef<[u8]> for ServerSessionKey<'_> {
213    fn as_ref(&self) -> &[u8] {
214        self.inner
215    }
216}