tls_api/
acceptor.rs

1use crate::acceptor_box::TlsAcceptorType;
2use crate::acceptor_box::TlsAcceptorTypeImpl;
3use crate::openssl::der_to_pkcs12;
4use crate::openssl::pkcs12_to_der;
5use crate::socket::AsyncSocket;
6use crate::stream::TlsStream;
7use crate::BoxFuture;
8use crate::ImplInfo;
9use crate::TlsAcceptorBox;
10use crate::TlsStreamDyn;
11use crate::TlsStreamWithSocket;
12use std::fmt;
13use std::marker;
14
15/// A builder for `TlsAcceptor`s.
16pub trait TlsAcceptorBuilder: Sized + Sync + Send + 'static {
17    /// Type of acceptor produced by this builder.
18    type Acceptor: TlsAcceptor;
19
20    /// Type of the underlying builder.
21    ///
22    /// Underlying builder might be needed to perform custom setup
23    /// when it is not supported by common API.
24    type Underlying;
25
26    /// Specify ALPN protocols for negotiation.
27    ///
28    /// This operation returns an error if the implemenation does not support ALPN.
29    ///
30    /// Whether ALPN is supported, can be queried using [`TlsAcceptor::SUPPORTS_ALPN`].
31    fn set_alpn_protocols(&mut self, protocols: &[&[u8]]) -> anyhow::Result<()>;
32
33    /// Get the underlying builder.
34    ///
35    /// API intentionally exposes the underlying acceptor builder to allow fine tuning
36    /// not possible in common API.
37    fn underlying_mut(&mut self) -> &mut Self::Underlying;
38
39    /// Finish the acceptor construction.
40    fn build(self) -> anyhow::Result<Self::Acceptor>;
41}
42
43/// A builder for server-side TLS connections.
44pub trait TlsAcceptor: Sized + Sync + Send + 'static {
45    /// Type of the builder for this acceptor.
46    type Builder: TlsAcceptorBuilder<Acceptor = Self>;
47
48    /// Type of the underlying acceptor.
49    type Underlying;
50
51    /// `crate::TlsStream<tls_api::AsyncSocketBox>`.
52    ///
53    /// In the world of HKT this would be:
54    ///
55    /// ```ignore
56    /// type TlsStream<S: TlsStreamDyn> : TlsStreamWithSocketDyn<S>;
57    /// ```
58    ///
59    /// Note each implementation has `accept_impl` function
60    /// which returns more specific type, providing both access to implementation details
61    /// and the underlying socket.
62    type TlsStream: TlsStreamDyn;
63
64    /// Get the underlying acceptor.
65    ///
66    /// API intentionally exposes the underlying acceptor builder to allow fine acceptor
67    /// not possible in common API.
68    fn underlying_mut(&mut self) -> &mut Self::Underlying;
69
70    /// Whether this acceptor type is implemented.
71    ///
72    /// For example, `tls-api-security-framework` is available on Linux,
73    /// but all operations result in error, so `IMPLEMENTED = false`
74    /// for that implementation.
75    const IMPLEMENTED: bool;
76    /// Whether this implementation supports ALPN negotiation.
77    const SUPPORTS_ALPN: bool;
78    /// Whether this implementation supports construction of acceptor using
79    /// a pair of a DER certificate and file pair.
80    const SUPPORTS_DER_KEYS: bool;
81    /// Whether this implementation supports construction of acceptor using
82    /// PKCS #12 file.
83    const SUPPORTS_PKCS12_KEYS: bool;
84
85    /// Dynamic (without type parameter) version of the acceptor.
86    ///
87    /// This function returns an acceptor type, which can be used to constructor acceptors.
88    const TYPE_DYN: &'static dyn TlsAcceptorType =
89        &TlsAcceptorTypeImpl::<Self>(marker::PhantomData);
90
91    /// Dynamic (without type parameter) version of the connector.
92    fn into_dyn(self) -> TlsAcceptorBox {
93        TlsAcceptorBox::new(self)
94    }
95
96    /// Implementation info.
97    fn info() -> ImplInfo;
98
99    /// New builder from given server key.
100    ///
101    /// Parameters are DER-encoded (binary) X509 cert and corresponding private key.
102    ///
103    /// Note if this implementation does not support DER keys directly,
104    /// `openssl` command is used to convert the certificate.
105    fn builder_from_der_key(cert: &[u8], key: &[u8]) -> anyhow::Result<Self::Builder> {
106        let _ = (cert, key);
107        assert!(!Self::SUPPORTS_DER_KEYS);
108
109        if !Self::SUPPORTS_PKCS12_KEYS {
110            Err(crate::CommonError::TlsBuilderFromFromDerOrPkcs12NotSupported(Self::TYPE_DYN))?;
111        }
112
113        let (pkcs12, pkcs12pass) = der_to_pkcs12(cert, key)?;
114
115        Self::builder_from_pkcs12(&pkcs12, &pkcs12pass)
116    }
117
118    /// New builder from given server key.
119    ///
120    /// Note if this implementation does not support PKCS #12 keys directly,
121    /// `openssl` command is used to convert the certificate.
122    fn builder_from_pkcs12(pkcs12: &[u8], passphrase: &str) -> anyhow::Result<Self::Builder> {
123        let _ = (pkcs12, passphrase);
124        assert!(!Self::SUPPORTS_PKCS12_KEYS);
125
126        if !Self::SUPPORTS_DER_KEYS {
127            Err(crate::CommonError::TlsBuilderFromFromDerOrPkcs12NotSupported(Self::TYPE_DYN))?;
128        }
129
130        let (cert, key) = pkcs12_to_der(pkcs12, passphrase)?;
131
132        Self::builder_from_der_key(&cert, &key)
133    }
134
135    /// Accept a connection.
136    ///
137    /// This operation returns a future which is resolved when the negotiation is complete,
138    /// and the stream is ready to send and receive.
139    ///
140    /// This version of `accept` returns a stream parameterized by the underlying socket type.
141    fn accept_with_socket<S>(
142        &self,
143        stream: S,
144    ) -> BoxFuture<'_, anyhow::Result<TlsStreamWithSocket<S>>>
145    where
146        S: AsyncSocket + fmt::Debug + Unpin;
147
148    /// Accept a connection.
149    ///
150    /// This operation returns a future which is resolved when the negotiation is complete,
151    /// and the stream is ready to send and receive.
152    ///
153    /// This version of `accept` returns a stream parameterized by the underlying socket type.
154    ///
155    /// Practically, [`accept`](Self::accept) is usually enough.
156    fn accept_impl_tls_stream<S>(
157        &self,
158        stream: S,
159    ) -> BoxFuture<'_, anyhow::Result<Self::TlsStream>>
160    where
161        S: AsyncSocket;
162
163    /// Accept a connection.
164    ///
165    /// This operation returns a future which is resolved when the negotiation is complete,
166    /// and the stream is ready to send and receive.
167    ///
168    /// This version return a stream of the underlying implementation, which
169    /// might be useful to obtain some TLS implementation-specific data.
170    ///
171    /// Practically, [`accept`](Self::accept) is usually enough.
172    fn accept<S>(&self, stream: S) -> BoxFuture<'_, anyhow::Result<TlsStream>>
173    where
174        S: AsyncSocket + fmt::Debug + Unpin,
175    {
176        BoxFuture::new(async move { self.accept_with_socket(stream).await.map(TlsStream::new) })
177    }
178}
179
180/// Common part of all connectors. Poor man replacement for HKT.
181#[macro_export]
182macro_rules! spi_acceptor_common {
183    ($stream: ty) => {
184        fn accept_with_socket<'a, S>(
185            &'a self,
186            stream: S,
187        ) -> $crate::BoxFuture<'a, anyhow::Result<$crate::TlsStreamWithSocket<S>>>
188        where
189            S: $crate::AsyncSocket,
190        {
191            $crate::BoxFuture::new(async move {
192                let crate_tls_stream: $stream = self.accept_impl(stream).await?;
193                Ok($crate::TlsStreamWithSocket::new(crate_tls_stream))
194            })
195        }
196
197        fn accept_impl_tls_stream<'a, S>(
198            &'a self,
199            stream: S,
200        ) -> tls_api::BoxFuture<'a, anyhow::Result<Self::TlsStream>>
201        where
202            S: AsyncSocket,
203        {
204            $crate::BoxFuture::new(self.accept_impl(tls_api::AsyncSocketBox::new(stream)))
205        }
206    };
207}