tls_api_openssl/
connector.rs

1use tls_api::async_as_sync::AsyncIoAsSyncIo;
2use tls_api::spi_connector_common;
3use tls_api::AsyncSocket;
4use tls_api::AsyncSocketBox;
5use tls_api::BoxFuture;
6use tls_api::ImplInfo;
7
8use crate::encode_alpn_protos;
9use crate::handshake::HandshakeFuture;
10use std::future::Future;
11
12pub struct TlsConnectorBuilder {
13    pub builder: openssl::ssl::SslConnectorBuilder,
14    pub verify_hostname: bool,
15}
16
17pub struct TlsConnector {
18    pub connector: openssl::ssl::SslConnector,
19    pub verify_hostname: bool,
20}
21
22impl tls_api::TlsConnectorBuilder for TlsConnectorBuilder {
23    type Connector = TlsConnector;
24
25    type Underlying = openssl::ssl::SslConnectorBuilder;
26
27    fn underlying_mut(&mut self) -> &mut openssl::ssl::SslConnectorBuilder {
28        &mut self.builder
29    }
30
31    fn set_alpn_protocols(&mut self, protocols: &[&[u8]]) -> anyhow::Result<()> {
32        self.builder
33            .set_alpn_protos(&encode_alpn_protos(protocols)?)
34            .map_err(anyhow::Error::new)
35    }
36
37    fn set_verify_hostname(&mut self, verify: bool) -> anyhow::Result<()> {
38        self.verify_hostname = verify;
39        Ok(())
40    }
41
42    fn add_root_certificate(&mut self, cert: &[u8]) -> anyhow::Result<()> {
43        let cert = openssl::x509::X509::from_der(cert).map_err(anyhow::Error::new)?;
44
45        self.builder
46            .cert_store_mut()
47            .add_cert(cert)
48            .map_err(anyhow::Error::new)?;
49
50        Ok(())
51    }
52
53    fn build(self) -> anyhow::Result<TlsConnector> {
54        Ok(TlsConnector {
55            connector: self.builder.build(),
56            verify_hostname: self.verify_hostname,
57        })
58    }
59}
60
61impl TlsConnectorBuilder {
62    pub fn builder_mut(&mut self) -> &mut openssl::ssl::SslConnectorBuilder {
63        &mut self.builder
64    }
65}
66
67impl TlsConnector {
68    pub fn connect_impl<'a, S>(
69        &'a self,
70        domain: &'a str,
71        stream: S,
72    ) -> impl Future<Output = anyhow::Result<crate::TlsStream<S>>> + 'a
73    where
74        S: AsyncSocket,
75    {
76        let client_configuration = match self.connector.configure() {
77            Ok(client_configuration) => client_configuration,
78            Err(e) => return BoxFuture::new(async { Err(anyhow::Error::new(e)) }),
79        };
80        let client_configuration = client_configuration.verify_hostname(self.verify_hostname);
81        BoxFuture::new(HandshakeFuture::Initial(
82            move |stream| client_configuration.connect(domain, stream),
83            AsyncIoAsSyncIo::new(stream),
84        ))
85    }
86}
87
88impl tls_api::TlsConnector for TlsConnector {
89    type Builder = TlsConnectorBuilder;
90
91    type Underlying = openssl::ssl::SslConnector;
92    type TlsStream = crate::TlsStream<AsyncSocketBox>;
93
94    fn underlying_mut(&mut self) -> &mut Self::Underlying {
95        &mut self.connector
96    }
97
98    const IMPLEMENTED: bool = true;
99    const SUPPORTS_ALPN: bool = true;
100
101    fn info() -> ImplInfo {
102        crate::into()
103    }
104
105    fn builder() -> anyhow::Result<TlsConnectorBuilder> {
106        let builder = openssl::ssl::SslConnector::builder(openssl::ssl::SslMethod::tls())
107            .map_err(anyhow::Error::new)?;
108        Ok(TlsConnectorBuilder {
109            builder,
110            verify_hostname: true,
111        })
112    }
113
114    spi_connector_common!(crate::TlsStream<S>);
115}