tcp_stream/
openssl_impl.rs

1use crate::{
2    HandshakeError, HandshakeResult, Identity, MidHandshakeTlsStream, StdTcpStream, TLSConfig,
3    TcpStream,
4};
5
6#[cfg(feature = "openssl-futures")]
7use {
8    crate::AsyncTcpStream,
9    futures_io::{AsyncRead, AsyncWrite},
10};
11
12use openssl::x509::X509;
13use std::io;
14
15/// Reexport openssl's `TlsConnector`
16pub use openssl::ssl::{SslConnector as OpensslConnector, SslMethod as OpensslMethod};
17
18/// A `TcpStream` wrapped by openssl
19pub type OpensslStream = openssl::ssl::SslStream<StdTcpStream>;
20
21/// A `MidHandshakeTlsStream` from openssl
22pub type OpensslMidHandshakeTlsStream = openssl::ssl::MidHandshakeSslStream<StdTcpStream>;
23
24/// A `HandshakeError` from openssl
25pub type OpensslHandshakeError = openssl::ssl::HandshakeError<StdTcpStream>;
26
27/// An `ErrorStack` from openssl
28pub type OpensslErrorStack = openssl::error::ErrorStack;
29
30#[cfg(feature = "openssl-futures")]
31/// An async `TcpStream` wrapped by openssl
32pub type OpensslAsyncStream<S> = async_openssl::SslStream<S>;
33
34fn openssl_connector(config: TLSConfig<'_, '_, '_>) -> io::Result<OpensslConnector> {
35    let mut builder = OpensslConnector::builder(OpensslMethod::tls())?;
36    if let Some(identity) = config.identity {
37        let (cert, pkey, chain) = match identity {
38            Identity::PKCS8 { pem, key } => {
39                let pkey = openssl::pkey::PKey::private_key_from_pem(key)?;
40                let mut chain = openssl::x509::X509::stack_from_pem(pem)?.into_iter();
41                let cert = chain.next();
42                (cert, Some(pkey), Some(chain.collect()))
43            }
44            Identity::PKCS12 { der, password } => {
45                let mut openssl_identity =
46                    openssl::pkcs12::Pkcs12::from_der(der)?.parse2(password)?;
47                (
48                    openssl_identity.cert,
49                    openssl_identity.pkey,
50                    openssl_identity
51                        .ca
52                        .take()
53                        .map(|stack| stack.into_iter().collect::<Vec<_>>()),
54                )
55            }
56        };
57        if let Some(cert) = cert.as_ref() {
58            builder.set_certificate(cert)?;
59        }
60        if let Some(pkey) = pkey.as_ref() {
61            builder.set_private_key(pkey)?;
62        }
63        if let Some(chain) = chain.as_ref() {
64            for cert in chain.iter().rev() {
65                builder.add_extra_chain_cert(cert.to_owned())?;
66            }
67        }
68    }
69    if let Some(cert_chain) = config.cert_chain.as_ref() {
70        for cert in X509::stack_from_pem(cert_chain.as_bytes())?.drain(..).rev() {
71            builder.cert_store_mut().add_cert(cert)?;
72        }
73    }
74    Ok(builder.build())
75}
76
77#[allow(dead_code)]
78pub(crate) fn into_openssl_impl(
79    s: TcpStream,
80    domain: &str,
81    config: TLSConfig<'_, '_, '_>,
82) -> HandshakeResult {
83    s.into_openssl(&openssl_connector(config)?, domain)
84}
85
86#[cfg(feature = "openssl-futures")]
87#[allow(dead_code)]
88pub(crate) async fn into_openssl_impl_async<S: AsyncRead + AsyncWrite + Send + Unpin + 'static>(
89    s: AsyncTcpStream<S>,
90    domain: &str,
91    config: TLSConfig<'_, '_, '_>,
92) -> io::Result<AsyncTcpStream<S>> {
93    s.into_openssl(&openssl_connector(config)?, domain).await
94}
95
96impl From<OpensslStream> for TcpStream {
97    fn from(s: OpensslStream) -> Self {
98        Self::Openssl(s)
99    }
100}
101
102impl From<OpensslMidHandshakeTlsStream> for MidHandshakeTlsStream {
103    fn from(mid: OpensslMidHandshakeTlsStream) -> Self {
104        Self::Openssl(mid)
105    }
106}
107
108impl From<OpensslHandshakeError> for HandshakeError {
109    fn from(error: OpensslHandshakeError) -> Self {
110        match error {
111            openssl::ssl::HandshakeError::WouldBlock(mid) => Self::WouldBlock(mid.into()),
112            openssl::ssl::HandshakeError::Failure(failure) => {
113                Self::Failure(io::Error::other(failure.into_error()))
114            }
115            openssl::ssl::HandshakeError::SetupFailure(failure) => failure.into(),
116        }
117    }
118}
119
120impl From<OpensslErrorStack> for HandshakeError {
121    fn from(error: OpensslErrorStack) -> Self {
122        Self::Failure(error.into())
123    }
124}