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