Skip to main content

rustls/server/
connection.rs

1use alloc::boxed::Box;
2use alloc::vec::Vec;
3use core::fmt;
4
5use pki_types::{DnsName, FipsStatus};
6
7use super::config::ServerConfig;
8use crate::common_state::{CommonState, Event, Side};
9use crate::conn::private::SideOutput;
10use crate::conn::{
11    Accepted, Connection, KeyingMaterialExporter, NeedsInput, Processed, ServerNext, SideData, Tcp,
12    Transport, VerifyPeerIdentity,
13};
14#[cfg(doc)]
15use crate::crypto;
16use crate::error::Error;
17use crate::msgs::ServerExtensionsInput;
18use crate::quic::ServerHandshake as QuicServerHandshake;
19use crate::server::hs::{ExpectClientHello, ReadClientHello, ServerState};
20use crate::sync::Arc;
21use crate::verify::ClientIdentity;
22
23impl Connection<ServerSide, Tcp> {
24    /// Make a new [`ServerSide`] [`Connection`].
25    ///
26    /// `config` controls how we behave in the TLS protocol.
27    pub fn new(config: Arc<ServerConfig>) -> Result<Self, Error> {
28        Self::for_server(config, ServerExtensionsInput::default(), Tcp)
29    }
30}
31
32impl<T: Transport> Connection<ServerSide, T> {
33    pub(crate) fn for_server(
34        config: Arc<ServerConfig>,
35        extra_exts: ServerExtensionsInput,
36        transport: T,
37    ) -> Result<Self, Error> {
38        let mut common = CommonState::new(Side::Server, config.fips());
39        common
40            .send
41            .set_max_fragment_size(config.max_fragment_size)?;
42        let protocol = transport.protocol();
43        Ok(Self {
44            state: Ok(Box::new(ExpectClientHello::new(
45                config,
46                extra_exts,
47                Vec::new(),
48                protocol,
49            ))
50            .into()),
51            side: ServerSide::default(),
52            transport,
53            common,
54        })
55    }
56
57    pub(crate) fn for_acceptor(transport: T) -> Self {
58        Self {
59            state: Ok(ReadClientHello::new(transport.protocol()).into()),
60            side: ServerSide::default(),
61            transport,
62            common: CommonState::new(Side::Server, FipsStatus::Unvalidated),
63        }
64    }
65}
66
67/// An in-progress TLS server handshake.
68#[non_exhaustive]
69#[derive(Debug)]
70pub enum ServerHandshake {
71    /// More data needs to be received to make progress.
72    NeedsInput(NeedsInput<ServerSide>),
73
74    /// A complete `ClientHello` has been received.
75    ///
76    /// The handshake can be progressed by choosing a [`ServerConfig`] based on
77    /// [`Accepted::client_hello()`] and providing it to [`Accepted::choose_config()`].
78    Accepted(Accepted<Tcp>),
79
80    /// The client's presented identity must be verified.
81    ///
82    /// See [`VerifyPeerIdentity`] for how to proceed.
83    VerifyClientIdentity(VerifyPeerIdentity<ServerSide, Tcp>),
84
85    /// A piece of TLS1.3 0RTT/"early" data has been received from the client.
86    ///
87    /// Read it via [`ReceivedEarlyData::into_next()`] to continue the handshake.
88    EarlyData(ReceivedEarlyData),
89
90    /// The handshake is complete.
91    Complete(Connection<ServerSide, Tcp>),
92}
93
94impl ServerHandshake {
95    /// Creates a new [`ServerHandshake`] via the payload of the [`ServerHandshake::NeedsInput`] variant.
96    ///
97    /// It is a fundamental fact of server TLS connections that the server reads first; this is reflected
98    /// in the returned type.
99    ///
100    /// You may wrap this in the [`ServerHandshake::NeedsInput`] variant to generalise the type to a
101    /// [`ServerHandshake`].
102    ///
103    /// The returned object should be fed data from a single potential client.
104    pub fn start() -> NeedsInput<ServerSide> {
105        NeedsInput::new(Connection::for_acceptor(Tcp))
106    }
107}
108
109impl TryFrom<Processed<ServerSide, Tcp>> for ServerHandshake {
110    type Error = Error;
111
112    fn try_from(processed: Processed<ServerSide, Tcp>) -> Result<Self, Error> {
113        match processed {
114            Processed::Progress(conn) => Self::try_from(conn),
115            Processed::EarlyData { conn, data } => {
116                Ok(Self::EarlyData(ReceivedEarlyData { data, conn }))
117            }
118        }
119    }
120}
121
122impl TryFrom<Connection<ServerSide, Tcp>> for ServerHandshake {
123    type Error = Error;
124
125    fn try_from(conn: Connection<ServerSide, Tcp>) -> Result<Self, Error> {
126        Ok(match ServerNext::try_from(conn)? {
127            ServerNext::NeedsInput(conn) => Self::NeedsInput(NeedsInput(conn)),
128
129            ServerNext::ChooseConfig(accepted) => Self::Accepted(accepted),
130
131            ServerNext::VerifyClientIdentity(verify) => Self::VerifyClientIdentity(verify),
132
133            ServerNext::Complete(conn) => Self::Complete(conn),
134        })
135    }
136}
137
138/// State associated with a server connection.
139#[derive(Default)]
140pub struct ServerSide {
141    sni: Option<DnsName<'static>>,
142    received_resumption_data: Option<Vec<u8>>,
143}
144
145impl ServerSide {
146    /// Retrieves the resumption data supplied by the client, if any.
147    ///
148    /// Returns `Some` if and only if a valid resumption ticket has been received from the client.
149    pub fn received_resumption_data(&self) -> Option<&[u8]> {
150        self.received_resumption_data.as_deref()
151    }
152
153    /// Retrieves the server name, if any, used to select the certificate and private key.
154    ///
155    /// This returns `None` until some time after the client's server name indication
156    /// (SNI) extension value is processed during the handshake. It will never be
157    /// `None` when the connection is ready to send or process application data,
158    /// unless the client does not support SNI.
159    ///
160    /// This is useful for application protocols that need to enforce that the
161    /// server name matches an application layer protocol hostname. For
162    /// example, HTTP/1.1 servers commonly expect the `Host:` header field of
163    /// every request on a connection to match the hostname in the SNI extension
164    /// when the client provides the SNI extension.
165    ///
166    /// The server name is also used to match sessions during session resumption.
167    pub fn server_name(&self) -> Option<&DnsName<'static>> {
168        self.sni.as_ref()
169    }
170}
171
172impl SideData for ServerSide {
173    type Handshake = ServerHandshake;
174    type QuicHandshake = QuicServerHandshake;
175
176    type PeerIdentity<'a> = ClientIdentity<'static, 'a>;
177}
178
179impl SideOutput for ServerSide {
180    fn emit(&mut self, ev: Event) {
181        match ev {
182            Event::ReceivedServerName(sni) => self.sni = sni,
183            Event::ResumptionData(data) => self.received_resumption_data = Some(data),
184            _ => unreachable!(),
185        }
186    }
187}
188
189impl crate::conn::private::Side for ServerSide {
190    type State = ServerState;
191}
192
193impl fmt::Debug for ServerSide {
194    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
195        f.debug_struct("ServerSide")
196            .field("sni", &self.sni)
197            .finish_non_exhaustive()
198    }
199}
200
201/// A piece of early data received from the client during the handshake.
202///
203/// "Early data" is also known as "0-RTT data".
204///
205/// **Beware** that early data is subject to replay by an attacker; see [RFC 9846
206/// appendix F.5][] for more detail.
207///
208/// The data is received in arbitrary-sized pieces.  Avoid writing your application to be
209/// sensitive to the boundaries.
210///
211/// [RFC 9846 appendix F.5]: https://datatracker.ietf.org/doc/html/rfc9846#appendix-F.5
212pub struct ReceivedEarlyData {
213    data: Vec<u8>,
214    conn: Connection<ServerSide, Tcp>,
215}
216
217impl ReceivedEarlyData {
218    /// Obtain the received early data.
219    ///
220    /// The returned [`NeedsInput`] should be given the same input buffer: it may
221    /// already contain further messages from the client.
222    pub fn into_next(self) -> (Vec<u8>, NeedsInput<ServerSide>) {
223        (self.data, NeedsInput(self.conn))
224    }
225
226    #[doc = include_str!("../doc/early_exporter.md")]
227    pub fn early_exporter(&mut self) -> Result<KeyingMaterialExporter, Error> {
228        self.conn.common.early_exporter()
229    }
230}
231
232impl fmt::Debug for ReceivedEarlyData {
233    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
234        f.debug_struct("ReceivedEarlyData")
235            .finish_non_exhaustive()
236    }
237}