tls_api_security_framework_2/
connector.rs

1#[cfg(any(target_os = "macos", target_os = "ios"))]
2use security_framework::certificate::SecCertificate;
3#[cfg(any(target_os = "macos", target_os = "ios"))]
4use security_framework::secure_transport::ClientBuilder;
5
6use std::str;
7
8use std::future::Future;
9use tls_api::spi_connector_common;
10use tls_api::AsyncSocket;
11use tls_api::AsyncSocketBox;
12use tls_api::ImplInfo;
13
14#[cfg(not(any(target_os = "macos", target_os = "ios")))]
15type ClientBuilder = void::Void;
16
17pub struct TlsConnector(pub ClientBuilder);
18pub struct TlsConnectorBuilder(pub ClientBuilder);
19
20impl tls_api::TlsConnectorBuilder for TlsConnectorBuilder {
21    type Connector = TlsConnector;
22    type Underlying = ClientBuilder;
23
24    fn underlying_mut(&mut self) -> &mut Self::Underlying {
25        &mut self.0
26    }
27
28    fn set_alpn_protocols(&mut self, protocols: &[&[u8]]) -> anyhow::Result<()> {
29        #[cfg(any(target_os = "macos", target_os = "ios"))]
30        {
31            let protocols: Vec<&str> = protocols
32                .iter()
33                .map(|p| {
34                    str::from_utf8(p)
35                        .map_err(|e| crate::Error::ReturnedAlpnProtocolIsNotUtf8(e).into())
36                })
37                .collect::<anyhow::Result<_>>()?;
38            self.0.alpn_protocols(&protocols);
39            Ok(())
40        }
41        #[cfg(not(any(target_os = "macos", target_os = "ios")))]
42        {
43            let _ = protocols;
44            crate::not_ios_or_macos()
45        }
46    }
47
48    fn set_verify_hostname(&mut self, verify: bool) -> anyhow::Result<()> {
49        #[cfg(any(target_os = "macos", target_os = "ios"))]
50        {
51            self.0.danger_accept_invalid_hostnames(!verify);
52            Ok(())
53        }
54        #[cfg(not(any(target_os = "macos", target_os = "ios")))]
55        {
56            let _ = verify;
57            crate::not_ios_or_macos()
58        }
59    }
60
61    fn add_root_certificate(&mut self, cert: &[u8]) -> anyhow::Result<()> {
62        #[cfg(any(target_os = "macos", target_os = "ios"))]
63        {
64            let cert = SecCertificate::from_der(cert).map_err(anyhow::Error::new)?;
65            // TODO: overrides, not adds: https://github.com/kornelski/rust-security-framework/pull/116
66            self.0.anchor_certificates(&[cert]);
67            Ok(())
68        }
69        #[cfg(not(any(target_os = "macos", target_os = "ios")))]
70        {
71            let _ = cert;
72            crate::not_ios_or_macos()
73        }
74    }
75
76    fn build(self) -> anyhow::Result<TlsConnector> {
77        Ok(TlsConnector(self.0))
78    }
79}
80
81impl TlsConnector {
82    pub fn connect_impl<'a, S>(
83        &'a self,
84        domain: &'a str,
85        stream: S,
86    ) -> impl Future<Output = anyhow::Result<crate::TlsStream<S>>> + 'a
87    where
88        S: AsyncSocket,
89    {
90        #[cfg(any(target_os = "macos", target_os = "ios"))]
91        {
92            crate::handshake::new_slient_handshake(self, domain, stream)
93        }
94        #[cfg(not(any(target_os = "macos", target_os = "ios")))]
95        {
96            let _ = (domain, stream);
97            async { crate::not_ios_or_macos() }
98        }
99    }
100}
101
102impl tls_api::TlsConnector for TlsConnector {
103    type Builder = TlsConnectorBuilder;
104
105    type Underlying = ClientBuilder;
106    type TlsStream = crate::TlsStream<AsyncSocketBox>;
107
108    fn underlying_mut(&mut self) -> &mut Self::Underlying {
109        &mut self.0
110    }
111
112    const IMPLEMENTED: bool = crate::IMPLEMENTED;
113    const SUPPORTS_ALPN: bool = true;
114
115    fn info() -> ImplInfo {
116        crate::info()
117    }
118
119    fn builder() -> anyhow::Result<TlsConnectorBuilder> {
120        #[cfg(any(target_os = "macos", target_os = "ios"))]
121        {
122            Ok(TlsConnectorBuilder(ClientBuilder::new()))
123        }
124        #[cfg(not(any(target_os = "macos", target_os = "ios")))]
125        {
126            crate::not_ios_or_macos()
127        }
128    }
129
130    spi_connector_common!();
131}