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