Skip to main content

rustls/server/
connection.rs

1use alloc::boxed::Box;
2use alloc::vec::Vec;
3use core::ops::Deref;
4use core::{fmt, mem};
5use std::io;
6
7use pki_types::{DnsName, FipsStatus};
8
9use super::config::{ClientHello, ServerConfig};
10use crate::common_state::{
11    CommonState, ConnectionOutputs, EarlyDataEvent, Event, Protocol, Side, maybe_send_fatal_alert,
12};
13use crate::conn::private::SideOutput;
14use crate::conn::split::SplitConnection;
15use crate::conn::{
16    Connection, ConnectionCommon, ConnectionCore, KeyingMaterialExporter, MessageIter, Reader,
17    SideData, StateMachine, TlsInputBuffer, Writer,
18};
19#[cfg(doc)]
20use crate::crypto;
21use crate::crypto::cipher::Payload;
22use crate::error::Error;
23use crate::log::trace;
24use crate::msgs::ServerExtensionsInput;
25use crate::server::hs::{ChooseConfig, ExpectClientHello, ReadClientHello, ServerState};
26use crate::suites::ExtractedSecrets;
27use crate::sync::Arc;
28use crate::vecbuf::ChunkVecBuffer;
29
30/// This represents a single TLS server connection.
31///
32/// Send TLS-protected data to the peer using the `io::Write` trait implementation.
33/// Read data from the peer using the `io::Read` trait implementation.
34pub struct ServerConnection {
35    pub(super) inner: ConnectionCommon<ServerSide>,
36}
37
38impl ServerConnection {
39    /// Make a new ServerConnection.  `config` controls how
40    /// we behave in the TLS protocol.
41    pub fn new(config: Arc<ServerConfig>) -> Result<Self, Error> {
42        Ok(Self {
43            inner: ConnectionCommon::new(ConnectionCore::for_server(
44                config,
45                ServerExtensionsInput::default(),
46                Protocol::Tcp,
47            )?),
48        })
49    }
50
51    /// Split a post-handshake connection into a [`SplitConnection`].
52    ///
53    /// This allows the two directions (transmit and receive) of the connection to be progressed
54    /// separately (including by different threads, which would allow dedicating a CPU core for each
55    /// direction rather than one per connection; this can dramatically improve performance for
56    /// full-duplex protocols).
57    ///
58    /// It also separates out the [`ConnectionOutputs`] which gives the application direct control
59    /// of how long this is kept.
60    ///
61    /// This fails if:
62    ///
63    /// - the handshake is not complete. Check with [`Connection::is_handshaking()`].
64    /// - there is any buffered application data.  Check with [`Connection::reader()`].
65    /// - there is any buffered TLS data to send.  Obtain it first with [`Connection::write_tls()`].
66    pub fn split(self) -> Result<SplitConnection<ServerSide>, Error> {
67        self.inner.split()
68    }
69
70    /// Retrieves the server name, if any, used to select the certificate and
71    /// private key.
72    ///
73    /// This returns `None` until some time after the client's server name indication
74    /// (SNI) extension value is processed during the handshake. It will never be
75    /// `None` when the connection is ready to send or process application data,
76    /// unless the client does not support SNI.
77    ///
78    /// This is useful for application protocols that need to enforce that the
79    /// server name matches an application layer protocol hostname. For
80    /// example, HTTP/1.1 servers commonly expect the `Host:` header field of
81    /// every request on a connection to match the hostname in the SNI extension
82    /// when the client provides the SNI extension.
83    ///
84    /// The server name is also used to match sessions during session resumption.
85    pub fn server_name(&self) -> Option<&DnsName<'_>> {
86        self.inner.core.side.server_name()
87    }
88
89    /// Application-controlled portion of the resumption ticket supplied by the client, if any.
90    ///
91    /// Recovered from the prior session's `set_resumption_data`. Integrity is guaranteed by rustls.
92    ///
93    /// Returns `Some` if and only if a valid resumption ticket has been received from the client.
94    pub fn received_resumption_data(&self) -> Option<&[u8]> {
95        self.inner
96            .core
97            .side
98            .received_resumption_data()
99    }
100
101    /// Set the resumption data to embed in future resumption tickets supplied to the client.
102    ///
103    /// Defaults to the empty byte string. Must be less than 2^15 bytes to allow room for other
104    /// data. Should be called while `is_handshaking` returns true to ensure all transmitted
105    /// resumption tickets are affected.
106    ///
107    /// Integrity will be assured by rustls, but the data will be visible to the client. If secrecy
108    /// from the client is desired, encrypt the data separately.
109    pub fn set_resumption_data(&mut self, data: &[u8]) -> Result<(), Error> {
110        assert!(data.len() < 2usize.pow(15));
111        match &mut self.inner.core.state {
112            Ok(st) => st.set_resumption_data(data),
113            Err(e) => Err(e.clone()),
114        }
115    }
116
117    /// Returns an `io::Read` implementer you can read bytes from that are
118    /// received from a client as TLS1.3 0RTT/"early" data, during the handshake.
119    ///
120    /// This returns `None` in many circumstances, such as :
121    ///
122    /// - Early data is disabled if [`ServerConfig::max_early_data_size`] is zero (the default).
123    /// - The session negotiated with the client is not TLS1.3.
124    /// - The client just doesn't support early data.
125    /// - The connection doesn't resume an existing session.
126    /// - The client hasn't sent a full ClientHello yet.
127    pub fn early_data(&mut self) -> Option<ReadEarlyData<'_>> {
128        if self
129            .inner
130            .core
131            .side
132            .early_data
133            .was_accepted()
134        {
135            Some(ReadEarlyData::new(&mut self.inner))
136        } else {
137            None
138        }
139    }
140}
141
142impl Connection for ServerConnection {
143    fn write_tls(&mut self, wr: &mut dyn io::Write) -> Result<usize, io::Error> {
144        self.inner.write_tls(wr)
145    }
146
147    fn wants_read(&self) -> bool {
148        self.inner.wants_read()
149    }
150
151    fn wants_write(&self) -> bool {
152        self.inner.wants_write()
153    }
154
155    fn reader(&mut self) -> Reader<'_> {
156        self.inner.reader()
157    }
158
159    fn writer(&mut self) -> Writer<'_> {
160        self.inner.writer()
161    }
162
163    fn process_new_packets(
164        &mut self,
165        input: &mut dyn TlsInputBuffer,
166    ) -> Result<crate::IoState, Error> {
167        self.inner.process_new_packets(input)
168    }
169
170    fn exporter(&mut self) -> Result<KeyingMaterialExporter, Error> {
171        self.inner.exporter()
172    }
173
174    fn dangerous_extract_secrets(self) -> Result<ExtractedSecrets, Error> {
175        self.inner.dangerous_extract_secrets()
176    }
177
178    fn set_buffer_limit(&mut self, limit: Option<usize>) {
179        self.inner.set_buffer_limit(limit)
180    }
181
182    fn set_plaintext_buffer_limit(&mut self, limit: Option<usize>) {
183        self.inner
184            .set_plaintext_buffer_limit(limit)
185    }
186
187    fn refresh_traffic_keys(&mut self) -> Result<(), Error> {
188        self.inner.refresh_traffic_keys()
189    }
190
191    fn send_close_notify(&mut self) {
192        self.inner.send_close_notify();
193    }
194
195    fn is_handshaking(&self) -> bool {
196        self.inner.is_handshaking()
197    }
198
199    fn fips(&self) -> FipsStatus {
200        self.inner.fips
201    }
202}
203
204impl Deref for ServerConnection {
205    type Target = ConnectionOutputs;
206
207    fn deref(&self) -> &Self::Target {
208        &self.inner
209    }
210}
211
212impl fmt::Debug for ServerConnection {
213    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
214        f.debug_struct("ServerConnection")
215            .finish_non_exhaustive()
216    }
217}
218
219/// An in-progress TLS server handshake.
220#[non_exhaustive]
221#[derive(Debug)]
222pub enum ServerHandshake {
223    /// More data needs to be received to make progress.
224    NeedsInput(NeedsInput),
225
226    /// A complete `ClientHello` has been received.
227    ///
228    /// The handshake can be progressed by choosing a [`ServerConfig`] based on
229    /// [`Accepted::client_hello()`] and providing it to [`Accepted::choose_config()`].
230    Accepted(Accepted),
231
232    /// The handshake is complete.
233    ///
234    /// Now see [`SplitConnection`] to continue the connection.
235    Complete(SplitConnection<ServerSide>),
236}
237
238impl ServerHandshake {
239    /// Creates a new [`ServerHandshake`] via the payload of the [`ServerHandshake::NeedsInput`] variant.
240    ///
241    /// It is a fundamental fact of server TLS connections that the server reads first; this is reflected
242    /// in the returned type.
243    ///
244    /// You may wrap this in the [`ServerHandshake::NeedsInput`] variant to generalise the type to a
245    /// [`ServerHandshake`].
246    ///
247    /// The returned object should be fed data from a single potential client.
248    pub fn start() -> NeedsInput {
249        NeedsInput {
250            inner: ConnectionCore::for_acceptor(Protocol::Tcp),
251        }
252    }
253}
254
255impl TryFrom<ConnectionCore<ServerSide>> for ServerHandshake {
256    type Error = Error;
257
258    fn try_from(mut inner: ConnectionCore<ServerSide>) -> Result<Self, Error> {
259        const MISUSED: Error = Error::Unreachable("forgot to restore state");
260
261        Ok(match mem::replace(&mut inner.state, Err(MISUSED))? {
262            ServerState::ChooseConfig(choose_config) => Self::Accepted(Accepted {
263                inner,
264                choose_config,
265            }),
266
267            state if state.is_traffic() => {
268                inner.state = Ok(state);
269                Self::Complete(SplitConnection::try_from(inner)?)
270            }
271
272            state => {
273                inner.state = Ok(state);
274                Self::NeedsInput(NeedsInput { inner })
275            }
276        })
277    }
278}
279
280/// More data needs to be received to make progress.
281///
282/// Provide the data to [`Self::process()`].
283pub struct NeedsInput {
284    inner: ConnectionCore<ServerSide>,
285}
286
287impl NeedsInput {
288    /// Progress the handshake by receiving further data.
289    ///
290    /// The data is obtained via `input`.  Any output produced is appended to `output` and
291    /// should be sent to the peer (including if this function returns an error, because
292    /// the `output` may contain an alert.)
293    ///
294    /// An error from this function is otherwise fatal to the connection, as it consumes
295    /// the [`NeedsInput`] object.
296    ///
297    /// On success, this returns:
298    ///
299    /// - a [`ServerHandshake::NeedsInput`] if more data is required.
300    /// - a [`ServerHandshake::Accepted`] if a whole `ClientHello` has been received, requiring
301    ///   and a choice of [`ServerConfig`] is required to continue.
302    /// - a [`ServerHandshake::Complete`] if the handshake is complete.
303    pub fn process(
304        mut self,
305        input: &mut dyn TlsInputBuffer,
306        output: &mut Vec<Vec<u8>>,
307    ) -> Result<ServerHandshake, Error> {
308        let mut iter = MessageIter::new(input, None, &mut self.inner);
309        let r = loop {
310            match iter.next() {
311                Some(Ok(_)) => {}
312                Some(Err(e)) => break Err(e),
313                None => break Ok(()),
314            };
315
316            // end loop as soon as traffic state is entered, as the above loop drops
317            // incoming appdata.
318            if iter
319                .state()
320                .as_ref()
321                .map(|st| st.is_traffic())
322                .unwrap_or_default()
323            {
324                break Ok(());
325            }
326        };
327
328        input.discard(
329            self.inner
330                .common
331                .recv
332                .deframer
333                .take_discard(),
334        );
335
336        while let Some(chunk) = self
337            .inner
338            .common
339            .send
340            .sendable_tls
341            .pop()
342        {
343            output.push(chunk);
344        }
345        r?;
346        ServerHandshake::try_from(self.inner)
347    }
348
349    /// Temporary escape hatch during migration to new API.
350    pub fn into_buffered_connection(self) -> ServerConnection {
351        ServerConnection {
352            inner: ConnectionCommon::new(self.inner),
353        }
354    }
355}
356
357impl fmt::Debug for NeedsInput {
358    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
359        f.debug_struct("NeedsInput")
360            .finish_non_exhaustive()
361    }
362}
363
364/// Represents a `ClientHello` message.
365///
366/// The handshake can be progressed by choosing a [`ServerConfig`] based on
367/// [`Accepted::client_hello()`] and providing it to [`Accepted::choose_config()`].
368pub struct Accepted {
369    // invariant: `inner.state` is `Err(_)` and requires restoring
370    inner: ConnectionCore<ServerSide>,
371    choose_config: Box<ChooseConfig>,
372}
373
374impl Accepted {
375    /// Get the [`ClientHello`] for this connection.
376    pub fn client_hello(&self) -> ClientHello<'_> {
377        let ch = self.choose_config.client_hello();
378        trace!("Accepted::client_hello(): {ch:#?}");
379        ch
380    }
381
382    /// Choose a [`ServerConfig`] to progress the handshake.
383    ///
384    /// Output to send to the peer is appended to `output`.  Typically, this is the `ServerHello`,
385    /// but it may also be an `Alert` if an error is returned.
386    ///
387    /// Returns an error if configuration-dependent validation of the received `ClientHello` message fails.
388    pub fn choose_config(
389        mut self,
390        config: Arc<ServerConfig>,
391        output: &mut Vec<Vec<u8>>,
392    ) -> Result<ServerHandshake, Error> {
393        let result = self.inner.accepted(
394            self.choose_config,
395            ServerExtensionsInput::default(),
396            None,
397            config,
398        );
399
400        let send_path = &mut self.inner.common.send;
401
402        if let Err(err) = &result {
403            maybe_send_fatal_alert(send_path, err);
404        }
405
406        while let Some(chunk) = send_path.sendable_tls.pop() {
407            output.push(chunk);
408        }
409
410        result?;
411
412        Ok(ServerHandshake::NeedsInput(NeedsInput {
413            inner: self.inner,
414        }))
415    }
416}
417
418impl fmt::Debug for Accepted {
419    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
420        f.debug_struct("Accepted")
421            .finish_non_exhaustive()
422    }
423}
424
425/// Allows reading of early data in resumed TLS1.3 connections.
426///
427/// "Early data" is also known as "0-RTT data".
428///
429/// This type implements [`io::Read`].
430pub struct ReadEarlyData<'a> {
431    common: &'a mut ConnectionCommon<ServerSide>,
432}
433
434impl<'a> ReadEarlyData<'a> {
435    fn new(common: &'a mut ConnectionCommon<ServerSide>) -> Self {
436        ReadEarlyData { common }
437    }
438
439    /// Returns the "early" exporter that can derive key material for use in early data
440    ///
441    /// See [RFC5705][] for general details on what exporters are, and [RFC8446 S7.5][] for
442    /// specific details on the "early" exporter.
443    ///
444    /// **Beware** that the early exporter requires care, as it is subject to the same
445    /// potential for replay as early data itself.  See [RFC8446 appendix E.5.1][] for
446    /// more detail.
447    ///
448    /// This function can be called at most once per connection. This function will error:
449    /// if called more than once per connection.
450    ///
451    /// If you are looking for the normal exporter, this is available from
452    /// [`Connection::exporter()`].
453    ///
454    /// [RFC5705]: https://datatracker.ietf.org/doc/html/rfc5705
455    /// [RFC8446 S7.5]: https://datatracker.ietf.org/doc/html/rfc8446#section-7.5
456    /// [RFC8446 appendix E.5.1]: https://datatracker.ietf.org/doc/html/rfc8446#appendix-E.5.1
457    /// [`Connection::exporter()`]: crate::conn::Connection::exporter()
458    pub fn exporter(&mut self) -> Result<KeyingMaterialExporter, Error> {
459        self.common.core.early_exporter()
460    }
461}
462
463impl io::Read for ReadEarlyData<'_> {
464    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
465        self.common
466            .core
467            .side
468            .early_data
469            .read(buf)
470    }
471}
472
473#[derive(Default)]
474pub(super) enum EarlyDataState {
475    #[default]
476    New,
477    Accepted {
478        received: ChunkVecBuffer,
479    },
480}
481
482impl EarlyDataState {
483    fn accept(&mut self) {
484        *self = Self::Accepted {
485            received: ChunkVecBuffer::new(None),
486        };
487    }
488
489    fn was_accepted(&self) -> bool {
490        matches!(self, Self::Accepted { .. })
491    }
492
493    #[expect(dead_code)]
494    fn peek(&self) -> Option<&[u8]> {
495        match self {
496            Self::Accepted { received, .. } => received.peek(),
497            _ => None,
498        }
499    }
500
501    #[expect(dead_code)]
502    fn pop(&mut self) -> Option<Vec<u8>> {
503        match self {
504            Self::Accepted { received, .. } => received.pop(),
505            _ => None,
506        }
507    }
508
509    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
510        match self {
511            Self::Accepted { received, .. } => received.read(buf),
512            _ => Err(io::Error::from(io::ErrorKind::BrokenPipe)),
513        }
514    }
515
516    fn take_received_plaintext(&mut self, bytes: Payload<'_>) {
517        let Self::Accepted { received } = self else {
518            return;
519        };
520
521        received.append(bytes.into_vec());
522    }
523}
524
525impl ConnectionCore<ServerSide> {
526    pub(crate) fn for_server(
527        config: Arc<ServerConfig>,
528        extra_exts: ServerExtensionsInput,
529        protocol: Protocol,
530    ) -> Result<Self, Error> {
531        let mut common = CommonState::new(Side::Server, config.fips());
532        common
533            .send
534            .set_max_fragment_size(config.max_fragment_size)?;
535        Ok(Self::new(
536            Box::new(ExpectClientHello::new(
537                config,
538                extra_exts,
539                Vec::new(),
540                protocol,
541            ))
542            .into(),
543            ServerConnectionData::default(),
544            common,
545        ))
546    }
547
548    pub(crate) fn for_acceptor(protocol: Protocol) -> Self {
549        Self::new(
550            ReadClientHello::new(protocol).into(),
551            ServerConnectionData::default(),
552            CommonState::new(Side::Server, FipsStatus::Unvalidated),
553        )
554    }
555}
556
557/// State associated with a server connection.
558#[derive(Default)]
559pub(crate) struct ServerConnectionData {
560    sni: Option<DnsName<'static>>,
561    received_resumption_data: Option<Vec<u8>>,
562    early_data: EarlyDataState,
563}
564
565impl ServerConnectionData {
566    pub(crate) fn received_resumption_data(&self) -> Option<&[u8]> {
567        self.received_resumption_data.as_deref()
568    }
569
570    pub(crate) fn server_name(&self) -> Option<&DnsName<'static>> {
571        self.sni.as_ref()
572    }
573}
574
575impl SideOutput for ServerConnectionData {
576    fn emit(&mut self, ev: Event<'_>) {
577        match ev {
578            Event::EarlyApplicationData(data) => self
579                .early_data
580                .take_received_plaintext(data),
581            Event::EarlyData(EarlyDataEvent::Accepted) => self.early_data.accept(),
582            Event::ReceivedServerName(sni) => self.sni = sni,
583            Event::ResumptionData(data) => self.received_resumption_data = Some(data),
584            _ => unreachable!(),
585        }
586    }
587}
588
589/// State associated with a server connection.
590#[expect(clippy::exhaustive_structs)]
591#[derive(Debug)]
592pub struct ServerSide;
593
594impl SideData for ServerSide {}
595
596impl crate::conn::private::Side for ServerSide {
597    type Data = ServerConnectionData;
598    type State = ServerState;
599}
600
601#[cfg(test)]
602mod tests {
603    use std::format;
604
605    use super::*;
606
607    // these branches not reachable externally, unless something else goes wrong.
608    #[test]
609    fn test_read_in_new_state() {
610        assert_eq!(
611            format!("{:?}", EarlyDataState::default().read(&mut [0u8; 5])),
612            "Err(Kind(BrokenPipe))"
613        );
614    }
615}