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