tls_api_security_framework_2/
acceptor.rs

1use std::future::Future;
2
3#[cfg(any(target_os = "macos", target_os = "ios"))]
4use security_framework::certificate::SecCertificate;
5#[cfg(any(target_os = "macos", target_os = "ios"))]
6use security_framework::identity::SecIdentity;
7#[cfg(any(target_os = "macos", target_os = "ios"))]
8use security_framework::import_export::Pkcs12ImportOptions;
9
10use tls_api::spi_acceptor_common;
11use tls_api::AsyncSocket;
12use tls_api::AsyncSocketBox;
13use tls_api::ImplInfo;
14
15/// To be replaced with [`security_framework::secure_transport::ServerBuilder`]
16/// in the next version of the `security_framework`.
17#[cfg(any(target_os = "macos", target_os = "ios"))]
18pub struct SecureTransportTlsAcceptorBuilder {
19    pub identity: SecIdentity,
20    pub certs: Vec<SecCertificate>,
21}
22
23/// To be replaced with `security_framework::secure_transport::ServerBuilder`
24/// in the next version of the `security_framework`.
25#[cfg(not(any(target_os = "macos", target_os = "ios")))]
26pub type SecureTransportTlsAcceptorBuilder = void::Void;
27
28pub struct TlsAcceptor(pub SecureTransportTlsAcceptorBuilder);
29pub struct TlsAcceptorBuilder(pub SecureTransportTlsAcceptorBuilder);
30
31impl tls_api::TlsAcceptorBuilder for TlsAcceptorBuilder {
32    type Acceptor = TlsAcceptor;
33    type Underlying = SecureTransportTlsAcceptorBuilder;
34
35    fn set_alpn_protocols(&mut self, _protocols: &[&[u8]]) -> anyhow::Result<()> {
36        Err(crate::Error::AlpnOnServer.into())
37    }
38
39    fn underlying_mut(&mut self) -> &mut Self::Underlying {
40        &mut self.0
41    }
42
43    fn build(self) -> anyhow::Result<Self::Acceptor> {
44        Ok(TlsAcceptor(self.0))
45    }
46}
47
48#[cfg(any(target_os = "macos", target_os = "ios"))]
49fn pkcs12_to_sf_objects(
50    pkcs12: &[u8],
51    passphrase: &str,
52) -> anyhow::Result<(SecIdentity, Vec<SecCertificate>)> {
53    let imported_identities = Pkcs12ImportOptions::new()
54        .passphrase(passphrase)
55        .import(pkcs12)
56        .map_err(anyhow::Error::new)?;
57    let mut identities: Vec<(SecIdentity, Vec<SecCertificate>)> = imported_identities
58        .into_iter()
59        .flat_map(|i| {
60            let cert_chain = i.cert_chain;
61            i.identity.map(|i| (i, cert_chain.unwrap_or(Vec::new())))
62        })
63        .collect();
64    if identities.len() == 0 {
65        Err(crate::Error::IdentitiesNotFoundInPkcs12.into())
66    } else if identities.len() == 1 {
67        Ok(identities.pop().unwrap())
68    } else {
69        Err(crate::Error::MoreThanOneIdentityInPkcs12(identities.len() as _).into())
70    }
71}
72
73impl TlsAcceptor {
74    fn accept_impl<'a, S>(
75        &'a self,
76        stream: S,
77    ) -> impl Future<Output = anyhow::Result<crate::TlsStream<S>>> + 'a
78    where
79        S: AsyncSocket,
80    {
81        #[cfg(any(target_os = "macos", target_os = "ios"))]
82        {
83            crate::handshake::new_server_handshake(self, stream)
84        }
85        #[cfg(not(any(target_os = "macos", target_os = "ios")))]
86        {
87            let _ = stream;
88            async { crate::not_ios_or_macos() }
89        }
90    }
91}
92
93impl tls_api::TlsAcceptor for TlsAcceptor {
94    type Builder = TlsAcceptorBuilder;
95
96    type Underlying = SecureTransportTlsAcceptorBuilder;
97    type TlsStream = crate::TlsStream<AsyncSocketBox>;
98
99    fn underlying_mut(&mut self) -> &mut Self::Underlying {
100        &mut self.0
101    }
102
103    const IMPLEMENTED: bool = crate::IMPLEMENTED;
104    const SUPPORTS_ALPN: bool = false;
105    const SUPPORTS_DER_KEYS: bool = false;
106    const SUPPORTS_PKCS12_KEYS: bool = true;
107
108    fn info() -> ImplInfo {
109        crate::info()
110    }
111
112    fn builder_from_pkcs12(pkcs12: &[u8], passphrase: &str) -> anyhow::Result<TlsAcceptorBuilder> {
113        #[cfg(any(target_os = "macos", target_os = "ios"))]
114        {
115            let (identity, certs) = pkcs12_to_sf_objects(pkcs12, passphrase)?;
116            Ok(TlsAcceptorBuilder(SecureTransportTlsAcceptorBuilder {
117                identity,
118                certs,
119            }))
120        }
121        #[cfg(not(any(target_os = "macos", target_os = "ios")))]
122        {
123            let _ = (pkcs12, passphrase);
124            crate::not_ios_or_macos()
125        }
126    }
127
128    spi_acceptor_common!();
129}