tor_rtcompat/impls/
native_tls.rs1use crate::traits::{CertifiedConn, StreamOps, TlsConnector, TlsProvider};
4
5use async_trait::async_trait;
6use futures::{AsyncRead, AsyncWrite};
7use native_tls_crate as native_tls;
8use std::io::{Error as IoError, Result as IoResult};
9use tracing::instrument;
10
11#[cfg_attr(
15 docsrs,
16 doc(cfg(all(
17 feature = "native-tls",
18 any(feature = "tokio", feature = "async-std", feature = "smol")
19 )))
20)]
21#[derive(Default, Clone)]
22#[non_exhaustive]
23pub struct NativeTlsProvider {}
24
25impl<S> CertifiedConn for async_native_tls::TlsStream<S>
26where
27 S: AsyncRead + AsyncWrite + Unpin,
28{
29 fn peer_certificate(&self) -> IoResult<Option<Vec<u8>>> {
30 let cert = self.peer_certificate();
31 match cert {
32 Ok(Some(c)) => {
33 let der = c.to_der().map_err(IoError::other)?;
34 Ok(Some(der))
35 }
36 Ok(None) => Ok(None),
37 Err(e) => Err(IoError::other(e)),
38 }
39 }
40
41 fn export_keying_material(
42 &self,
43 _len: usize,
44 _label: &[u8],
45 _context: Option<&[u8]>,
46 ) -> IoResult<Vec<u8>> {
47 Err(std::io::Error::new(
48 std::io::ErrorKind::Unsupported,
49 tor_error::bad_api_usage!("native-tls does not support exporting keying material"),
50 ))
51 }
52}
53
54impl<S: AsyncRead + AsyncWrite + StreamOps + Unpin> StreamOps for async_native_tls::TlsStream<S> {
55 fn set_tcp_notsent_lowat(&self, notsent_lowat: u32) -> IoResult<()> {
56 self.get_ref().set_tcp_notsent_lowat(notsent_lowat)
57 }
58
59 fn new_handle(&self) -> Box<dyn StreamOps + Send + Unpin> {
60 self.get_ref().new_handle()
61 }
62}
63
64pub struct NativeTlsConnector<S> {
66 connector: async_native_tls::TlsConnector,
68 _phantom: std::marker::PhantomData<fn(S) -> S>,
70}
71
72#[async_trait]
73impl<S> TlsConnector<S> for NativeTlsConnector<S>
74where
75 S: AsyncRead + AsyncWrite + StreamOps + Unpin + Send + 'static,
76{
77 type Conn = async_native_tls::TlsStream<S>;
78
79 #[instrument(skip_all, level = "trace")]
80 async fn negotiate_unvalidated(&self, stream: S, sni_hostname: &str) -> IoResult<Self::Conn> {
81 let conn = self
82 .connector
83 .connect(sni_hostname, stream)
84 .await
85 .map_err(IoError::other)?;
86 Ok(conn)
87 }
88}
89
90impl<S> TlsProvider<S> for NativeTlsProvider
91where
92 S: AsyncRead + AsyncWrite + StreamOps + Unpin + Send + 'static,
93{
94 type Connector = NativeTlsConnector<S>;
95
96 type TlsStream = async_native_tls::TlsStream<S>;
97
98 fn tls_connector(&self) -> Self::Connector {
99 let mut builder = native_tls::TlsConnector::builder();
100 builder
105 .danger_accept_invalid_certs(true)
106 .danger_accept_invalid_hostnames(true);
107
108 builder.disable_built_in_roots(true);
111
112 let connector = builder.into();
113
114 NativeTlsConnector {
115 connector,
116 _phantom: std::marker::PhantomData,
117 }
118 }
119
120 fn supports_keying_material_export(&self) -> bool {
121 false
122 }
123}