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}