tls_api_openssl/
connector.rs1use 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}