tls_api_security_framework_2/
acceptor.rs1use 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#[cfg(any(target_os = "macos", target_os = "ios"))]
18pub struct SecureTransportTlsAcceptorBuilder {
19 pub identity: SecIdentity,
20 pub certs: Vec<SecCertificate>,
21}
22
23#[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}