tls_api_openssl/
acceptor.rs

1use openssl::pkcs12::ParsedPkcs12_2;
2
3use tls_api::async_as_sync::AsyncIoAsSyncIo;
4use tls_api::spi_acceptor_common;
5use tls_api::AsyncSocket;
6use tls_api::AsyncSocketBox;
7use tls_api::ImplInfo;
8
9use crate::encode_alpn_protos;
10use crate::handshake::HandshakeFuture;
11use anyhow::Context;
12use std::future::Future;
13
14pub struct TlsAcceptorBuilder(pub openssl::ssl::SslAcceptorBuilder);
15
16pub struct TlsAcceptor(pub openssl::ssl::SslAcceptor);
17
18fn to_openssl_pkcs12(pkcs12: &[u8], passphrase: &str) -> anyhow::Result<ParsedPkcs12_2> {
19    let pkcs12 = openssl::pkcs12::Pkcs12::from_der(pkcs12)?;
20    pkcs12.parse2(passphrase).context("Parse passphrase")
21}
22
23impl tls_api::TlsAcceptorBuilder for TlsAcceptorBuilder {
24    type Acceptor = TlsAcceptor;
25
26    type Underlying = openssl::ssl::SslAcceptorBuilder;
27
28    fn underlying_mut(&mut self) -> &mut openssl::ssl::SslAcceptorBuilder {
29        &mut self.0
30    }
31
32    fn set_alpn_protocols(&mut self, protocols: &[&[u8]]) -> anyhow::Result<()> {
33        let protocols = encode_alpn_protos(protocols)?;
34        self.0
35            .set_alpn_select_callback(move |_ssl, client_protocols| {
36                match openssl::ssl::select_next_proto(&protocols, client_protocols) {
37                    Some(selected) => Ok(selected),
38                    None => Err(openssl::ssl::AlpnError::NOACK),
39                }
40            });
41        Ok(())
42    }
43
44    fn build(self) -> anyhow::Result<TlsAcceptor> {
45        Ok(TlsAcceptor(self.0.build()))
46    }
47}
48
49impl TlsAcceptorBuilder {
50    pub fn builder_mut(&mut self) -> &mut openssl::ssl::SslAcceptorBuilder {
51        &mut self.0
52    }
53}
54
55impl TlsAcceptor {
56    fn accept_impl<S>(
57        &self,
58        stream: S,
59    ) -> impl Future<Output = anyhow::Result<crate::TlsStream<S>>> + '_
60    where
61        S: AsyncSocket,
62    {
63        HandshakeFuture::Initial(
64            move |stream| self.0.accept(stream),
65            AsyncIoAsSyncIo::new(stream),
66        )
67    }
68}
69
70impl tls_api::TlsAcceptor for TlsAcceptor {
71    type Builder = TlsAcceptorBuilder;
72
73    type Underlying = openssl::ssl::SslAcceptor;
74    type TlsStream = crate::TlsStream<AsyncSocketBox>;
75
76    fn underlying_mut(&mut self) -> &mut Self::Underlying {
77        &mut self.0
78    }
79
80    const IMPLEMENTED: bool = true;
81    const SUPPORTS_ALPN: bool = true;
82    const SUPPORTS_DER_KEYS: bool = true;
83    const SUPPORTS_PKCS12_KEYS: bool = true;
84
85    fn info() -> ImplInfo {
86        crate::into()
87    }
88
89    fn builder_from_der_key(cert: &[u8], key: &[u8]) -> anyhow::Result<TlsAcceptorBuilder> {
90        let cert = openssl::x509::X509::from_der(cert).map_err(anyhow::Error::new)?;
91        let pkey = openssl::pkey::PKey::private_key_from_der(key).map_err(anyhow::Error::new)?;
92
93        let mut builder =
94            openssl::ssl::SslAcceptor::mozilla_intermediate(openssl::ssl::SslMethod::tls())
95                .map_err(anyhow::Error::new)?;
96
97        builder
98            .set_certificate(cert.as_ref())
99            .map_err(anyhow::Error::new)?;
100        builder
101            .set_private_key(pkey.as_ref())
102            .map_err(anyhow::Error::new)?;
103
104        Ok(TlsAcceptorBuilder(builder))
105    }
106
107    fn builder_from_pkcs12(pkcs12: &[u8], passphrase: &str) -> anyhow::Result<TlsAcceptorBuilder> {
108        let mut builder =
109            openssl::ssl::SslAcceptor::mozilla_intermediate(openssl::ssl::SslMethod::tls())
110                .map_err(anyhow::Error::new)?;
111
112        let pkcs12 = to_openssl_pkcs12(pkcs12, passphrase)?;
113
114        if let Some(cert) = &pkcs12.cert {
115            builder.set_certificate(cert).map_err(anyhow::Error::new)?;
116        }
117        if let Some(pkey) = &pkcs12.pkey {
118            builder.set_private_key(pkey).map_err(anyhow::Error::new)?;
119        }
120
121        if let Some(chain) = pkcs12.ca {
122            for x509 in chain {
123                builder
124                    .add_extra_chain_cert(x509)
125                    .map_err(anyhow::Error::new)?;
126            }
127        }
128
129        Ok(TlsAcceptorBuilder(builder))
130    }
131
132    spi_acceptor_common!(crate::TlsStream<S>);
133}