tcp_stream/
native_tls_impl.rs1use crate::{
2 HandshakeError, HandshakeResult, Identity, MidHandshakeTlsStream, StdTcpStream, TLSConfig,
3 TcpStream,
4};
5
6#[cfg(feature = "native-tls-futures")]
7use {
8 crate::AsyncTcpStream,
9 futures_io::{AsyncRead, AsyncWrite},
10};
11
12use native_tls::Certificate;
13use std::io;
14
15pub use native_tls::TlsConnector as NativeTlsConnector;
17
18pub use native_tls::TlsConnectorBuilder as NativeTlsConnectorBuilder;
20
21pub type NativeTlsStream = native_tls::TlsStream<StdTcpStream>;
23
24pub type NativeTlsMidHandshakeTlsStream = native_tls::MidHandshakeTlsStream<StdTcpStream>;
26
27pub type NativeTlsHandshakeError = native_tls::HandshakeError<StdTcpStream>;
29
30#[cfg(feature = "native-tls-futures")]
31pub type NativeTlsAsyncStream<S> = async_native_tls::TlsStream<S>;
33
34fn native_tls_connector_builder(
35 config: TLSConfig<'_, '_, '_>,
36) -> io::Result<NativeTlsConnectorBuilder> {
37 let mut builder = NativeTlsConnector::builder();
38 if let Some(identity) = config.identity {
39 let native_identity = match identity {
40 Identity::PKCS8 { pem, key } => native_tls::Identity::from_pkcs8(pem, key),
41 Identity::PKCS12 { der, password } => native_tls::Identity::from_pkcs12(der, password),
42 };
43 builder.identity(native_identity.map_err(io::Error::other)?);
44 }
45 if let Some(cert_chain) = config.cert_chain {
46 let mut cert_chain = std::io::BufReader::new(cert_chain.as_bytes());
47 for cert in rustls_pemfile::certs(&mut cert_chain).collect::<Result<Vec<_>, _>>()? {
48 builder
49 .add_root_certificate(Certificate::from_der(&cert[..]).map_err(io::Error::other)?);
50 }
51 }
52 Ok(builder)
53}
54
55fn native_tls_connector(config: TLSConfig<'_, '_, '_>) -> io::Result<NativeTlsConnector> {
56 native_tls_connector_builder(config)?
57 .build()
58 .map_err(io::Error::other)
59}
60
61#[allow(dead_code)]
62pub(crate) fn into_native_tls_impl(
63 s: TcpStream,
64 domain: &str,
65 config: TLSConfig<'_, '_, '_>,
66) -> HandshakeResult {
67 s.into_native_tls(&native_tls_connector(config)?, domain)
68}
69
70#[cfg(feature = "native-tls-futures")]
71#[allow(dead_code)]
72pub(crate) async fn into_native_tls_impl_async<
73 S: AsyncRead + AsyncWrite + Send + Unpin + 'static,
74>(
75 s: AsyncTcpStream<S>,
76 domain: &str,
77 config: TLSConfig<'_, '_, '_>,
78) -> io::Result<AsyncTcpStream<S>> {
79 s.into_native_tls(native_tls_connector_builder(config)?, domain)
80 .await
81}
82
83impl From<NativeTlsStream> for TcpStream {
84 fn from(s: NativeTlsStream) -> Self {
85 Self::NativeTls(s)
86 }
87}
88
89impl From<NativeTlsMidHandshakeTlsStream> for MidHandshakeTlsStream {
90 fn from(mid: NativeTlsMidHandshakeTlsStream) -> Self {
91 Self::NativeTls(mid)
92 }
93}
94
95impl From<NativeTlsHandshakeError> for HandshakeError {
96 fn from(error: NativeTlsHandshakeError) -> Self {
97 match error {
98 native_tls::HandshakeError::WouldBlock(mid) => Self::WouldBlock(mid.into()),
99 native_tls::HandshakeError::Failure(failure) => {
100 Self::Failure(io::Error::other(failure))
101 }
102 }
103 }
104}