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