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::split::SplitConnection;
11use crate::conn::{
12    Accepted, Connection, NeedsInput, ServerNext, SideData, Tcp, 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    /// The handshake is complete.
86    ///
87    /// Now see [`SplitConnection`] to continue the connection.
88    Complete(SplitConnection<ServerSide>),
89}
90
91impl ServerHandshake {
92    /// Creates a new [`ServerHandshake`] via the payload of the [`ServerHandshake::NeedsInput`] variant.
93    ///
94    /// It is a fundamental fact of server TLS connections that the server reads first; this is reflected
95    /// in the returned type.
96    ///
97    /// You may wrap this in the [`ServerHandshake::NeedsInput`] variant to generalise the type to a
98    /// [`ServerHandshake`].
99    ///
100    /// The returned object should be fed data from a single potential client.
101    pub fn start() -> NeedsInput<ServerSide> {
102        NeedsInput::new(Connection::for_acceptor(Tcp))
103    }
104}
105
106impl TryFrom<Connection<ServerSide, Tcp>> for ServerHandshake {
107    type Error = Error;
108
109    fn try_from(conn: Connection<ServerSide, Tcp>) -> Result<Self, Error> {
110        Ok(match ServerNext::try_from(conn)? {
111            ServerNext::NeedsInput(conn) => Self::NeedsInput(NeedsInput(conn)),
112
113            ServerNext::ChooseConfig(accepted) => Self::Accepted(accepted),
114
115            ServerNext::VerifyClientIdentity(verify) => Self::VerifyClientIdentity(verify),
116
117            ServerNext::Complete(conn) => Self::Complete(SplitConnection::try_from(conn)?),
118        })
119    }
120}
121
122/// State associated with a server connection.
123#[derive(Default)]
124pub struct ServerSide {
125    sni: Option<DnsName<'static>>,
126    received_resumption_data: Option<Vec<u8>>,
127}
128
129impl ServerSide {
130    /// Retrieves the resumption data supplied by the client, if any.
131    ///
132    /// Returns `Some` if and only if a valid resumption ticket has been received from the client.
133    pub fn received_resumption_data(&self) -> Option<&[u8]> {
134        self.received_resumption_data.as_deref()
135    }
136
137    /// Retrieves the server name, if any, used to select the certificate and private key.
138    ///
139    /// This returns `None` until some time after the client's server name indication
140    /// (SNI) extension value is processed during the handshake. It will never be
141    /// `None` when the connection is ready to send or process application data,
142    /// unless the client does not support SNI.
143    ///
144    /// This is useful for application protocols that need to enforce that the
145    /// server name matches an application layer protocol hostname. For
146    /// example, HTTP/1.1 servers commonly expect the `Host:` header field of
147    /// every request on a connection to match the hostname in the SNI extension
148    /// when the client provides the SNI extension.
149    ///
150    /// The server name is also used to match sessions during session resumption.
151    pub fn server_name(&self) -> Option<&DnsName<'static>> {
152        self.sni.as_ref()
153    }
154}
155
156impl SideData for ServerSide {
157    type Handshake = ServerHandshake;
158    type QuicHandshake = QuicServerHandshake;
159
160    type PeerIdentity<'a> = ClientIdentity<'static, 'a>;
161}
162
163impl SideOutput for ServerSide {
164    fn emit(&mut self, ev: Event) {
165        match ev {
166            Event::ReceivedServerName(sni) => self.sni = sni,
167            Event::ResumptionData(data) => self.received_resumption_data = Some(data),
168            _ => unreachable!(),
169        }
170    }
171}
172
173impl crate::conn::private::Side for ServerSide {
174    type State = ServerState;
175}
176
177impl fmt::Debug for ServerSide {
178    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
179        f.debug_struct("ServerSide")
180            .field("sni", &self.sni)
181            .finish_non_exhaustive()
182    }
183}