1
//! TLS server trait implementations for Rustls.
2

            
3
use async_trait::async_trait;
4
use futures::{AsyncRead, AsyncWrite};
5
use pin_project::pin_project;
6
use std::{
7
    borrow::Cow,
8
    io::{Error as IoError, Result as IoResult},
9
    marker::PhantomData,
10
    pin::Pin,
11
    sync::Arc,
12
    task::{Context, Poll},
13
};
14
use tracing::instrument;
15

            
16
use crate::{CertifiedConn, StreamOps, tls::TlsAcceptorSettings, tls::TlsConnector};
17
use futures_rustls::rustls::ServerConfig as RustlsServerConfig;
18

            
19
/// A server-side TLS stream.
20
///
21
/// Created by [`RustlsAcceptor`].
22
#[pin_project]
23
pub struct RustlsServerStream<S> {
24
    /// The underlying Rustls stream.
25
    ///
26
    /// We have to wrap this so that we can also expose the certificate we sent,
27
    /// for use in Tor's link authentication.
28
    #[pin]
29
    stream: futures_rustls::server::TlsStream<S>,
30

            
31
    /// The certificate that we sent.
32
    ///
33
    /// (If we sent multiple certs, this should be the one corresponding to our private key.)
34
    cert_der: Arc<[u8]>,
35
}
36

            
37
impl<S: AsyncRead + AsyncWrite + Unpin> AsyncRead for RustlsServerStream<S> {
38
18
    fn poll_read(
39
18
        self: Pin<&mut Self>,
40
18
        cx: &mut Context<'_>,
41
18
        buf: &mut [u8],
42
18
    ) -> Poll<IoResult<usize>> {
43
18
        self.project().stream.poll_read(cx, buf)
44
18
    }
45
}
46

            
47
impl<S: AsyncRead + AsyncWrite + Unpin> AsyncWrite for RustlsServerStream<S> {
48
    fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll<IoResult<usize>> {
49
        self.project().stream.poll_write(cx, buf)
50
    }
51

            
52
    fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<IoResult<()>> {
53
        self.project().stream.poll_flush(cx)
54
    }
55

            
56
    fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<IoResult<()>> {
57
        self.project().stream.poll_close(cx)
58
    }
59
}
60

            
61
impl<S: StreamOps> StreamOps for RustlsServerStream<S> {
62
    fn set_tcp_notsent_lowat(&self, notsent_lowat: u32) -> IoResult<()> {
63
        self.stream.get_ref().0.set_tcp_notsent_lowat(notsent_lowat)
64
    }
65

            
66
    fn new_handle(&self) -> Box<dyn StreamOps + Send + Unpin> {
67
        self.stream.get_ref().0.new_handle()
68
    }
69
}
70

            
71
impl<S: AsyncRead + AsyncWrite + Unpin> CertifiedConn for RustlsServerStream<S> {
72
    fn peer_certificate(&self) -> IoResult<Option<Cow<'_, [u8]>>> {
73
        let (_, session) = self.stream.get_ref();
74
        Ok(session
75
            .peer_certificates()
76
            .and_then(|certs| certs.first().map(|c| Cow::from(c.as_ref()))))
77
    }
78

            
79
    fn export_keying_material(
80
        &self,
81
        len: usize,
82
        label: &[u8],
83
        context: Option<&[u8]>,
84
    ) -> IoResult<Vec<u8>> {
85
        let (_, session) = self.stream.get_ref();
86
        session
87
            .export_keying_material(vec![0_u8; len], label, context)
88
            .map_err(|e| IoError::new(std::io::ErrorKind::InvalidData, e))
89
    }
90

            
91
6
    fn own_certificate(&self) -> IoResult<Option<Cow<'_, [u8]>>> {
92
6
        Ok(Some(Cow::from(self.cert_der.as_ref())))
93
6
    }
94
}
95

            
96
/// A server implementation for Rustls.
97
///
98
/// Accepts asynchronous streams (typically over TCP), and performs the server-side TLS handshake.
99
#[derive(Clone, derive_more::Debug)]
100
pub struct RustlsAcceptor<S> {
101
    /// The underlying TLS acceptor.
102
    #[debug(skip)]
103
    acceptor: futures_rustls::TlsAcceptor,
104
    /// The certificate corresponding to our private key.
105
    cert_der: Arc<[u8]>,
106
    /// Phantomdata to mark this type as invariant in S.
107
    _phantom: PhantomData<fn(S) -> S>,
108
}
109

            
110
#[async_trait]
111
impl<S> TlsConnector<S> for RustlsAcceptor<S>
112
where
113
    S: AsyncRead + AsyncWrite + StreamOps + Unpin + Send + 'static,
114
{
115
    type Conn = RustlsServerStream<S>;
116

            
117
    #[instrument(skip_all, level = "trace")]
118
    async fn negotiate_unvalidated(&self, stream: S, sni_hostname: &str) -> IoResult<Self::Conn> {
119
        let _ignore = sni_hostname;
120
        let stream = self.acceptor.accept(stream).await?;
121
        Ok(RustlsServerStream {
122
            stream,
123
            cert_der: Arc::clone(&self.cert_der),
124
        })
125
    }
126
}
127

            
128
impl<S> RustlsAcceptor<S> {
129
    /// Construct a new RustlsAcceptor from a provided [`TlsAcceptorSettings`]
130
6
    pub(crate) fn new(settings: &TlsAcceptorSettings) -> IoResult<Self> {
131
6
        let cert_der = settings.cert_der().into();
132

            
133
6
        let cfg: RustlsServerConfig = rustls_server_config(settings)?;
134
6
        let acceptor = futures_rustls::TlsAcceptor::from(Arc::new(cfg));
135
6
        Ok(Self {
136
6
            acceptor,
137
6
            cert_der,
138
6
            _phantom: PhantomData,
139
6
        })
140
6
    }
141
}
142

            
143
/// Try to convert a [`TlsAcceptorSettings`] into a configuration for a rustls server.
144
///
145
/// This is not necessarily suitable for general use outside of being a Tor relay.
146
6
fn rustls_server_config(settings: &TlsAcceptorSettings) -> IoResult<RustlsServerConfig> {
147
    use futures_rustls::rustls::pki_types as pki;
148
    use futures_rustls::rustls::version::{TLS12, TLS13};
149

            
150
    // Convert certificate and key into expected format.
151
6
    let cert_chain = settings
152
6
        .identity
153
6
        .certificates_der()
154
6
        .into_iter()
155
9
        .map(|c| pki::CertificateDer::from_slice(c).into_owned())
156
6
        .collect();
157
6
    let key_der = settings
158
6
        .identity
159
6
        .private_key_pkcs8_der()
160
6
        .map_err(IoError::other)?;
161
6
    let key_der =
162
6
        pki::PrivateKeyDer::Pkcs8(pki::PrivatePkcs8KeyDer::from(key_der.as_ref())).clone_key();
163

            
164
    // Initialize the ServerConfig.
165
6
    let mut config = RustlsServerConfig::builder_with_protocol_versions(&[&TLS12, &TLS13]) // 1.2 and 1.3 only.
166
6
        .with_no_client_auth() // Don't require client authentication.
167
6
        .with_single_cert(cert_chain, key_der)
168
6
        .map_err(|e| IoError::new(std::io::ErrorKind::InvalidData, e))?;
169

            
170
    // tor-spec:
171
    // > Implementations SHOULD NOT allow TLS session resumption – it can exacerbate some attacks
172
    // > (e.g. the “Triple Handshake” attack from Feb 2013), and it plays havoc with forward secrecy
173
    // > guarantees.
174
    //
175
    // rustls:
176
    // > If this is 0, no tickets are sent and clients will not be able to do any resumption.
177
6
    config.send_tls13_tickets = 0;
178

            
179
    // TODO: Possibly, modify config.  There are numerous fields we could adjust.
180

            
181
6
    Ok(config)
182
6
}