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