1 //! The `openssl` provider.
2 
3 use crate::{BoxFutureTlsStream, Error, TlsProvider, TlsStream, TlsTransport};
4 use openssl::ssl::{SslConnector, SslMethod};
5 use std::io;
6 use std::pin::{Pin, pin};
7 
8 /// The `openssl` provider.
9 pub struct OpenSslProvider {
10     _priv: (),
11 }
12 
13 impl TlsProvider for OpenSslProvider {
connect(&self, server_name: String, transport: Box<dyn TlsTransport>) -> BoxFutureTlsStream14     fn connect(&self, server_name: String, transport: Box<dyn TlsTransport>) -> BoxFutureTlsStream {
15         Box::pin(async move {
16             // Per the `openssl` crate's recommendation, we're using the
17             // `SslConnector` to set up a Ssl object with secure defaults:
18             //
19             // https://docs.rs/openssl/latest/openssl/ssl/struct.SslConnector.html
20             // > OpenSSL's default configuration is highly insecure. This
21             // > connector manages the OpenSSL structures, configuring cipher
22             // > suites, session options, hostname verification, and more.
23             let config = SslConnector::builder(SslMethod::tls_client())?
24                 .build()
25                 .configure()?;
26             let ssl = config.into_ssl(&server_name)?;
27             let mut stream = tokio_openssl::SslStream::new(ssl, transport)?;
28             Pin::new(&mut stream).connect().await?;
29             Ok(Box::new(OpenSslStream(stream)) as Box<dyn TlsStream>)
30         })
31     }
32 }
33 
34 impl Default for OpenSslProvider {
default() -> Self35     fn default() -> Self {
36         Self { _priv: () }
37     }
38 }
39 
40 struct OpenSslStream(tokio_openssl::SslStream<Box<dyn TlsTransport>>);
41 
42 impl TlsStream for OpenSslStream {}
43 
44 impl tokio::io::AsyncRead for OpenSslStream {
poll_read( mut self: std::pin::Pin<&mut Self>, cx: &mut std::task::Context<'_>, buf: &mut tokio::io::ReadBuf<'_>, ) -> std::task::Poll<io::Result<()>>45     fn poll_read(
46         mut self: std::pin::Pin<&mut Self>,
47         cx: &mut std::task::Context<'_>,
48         buf: &mut tokio::io::ReadBuf<'_>,
49     ) -> std::task::Poll<io::Result<()>> {
50         pin!(&mut self.as_mut().0).poll_read(cx, buf)
51     }
52 }
53 
54 impl tokio::io::AsyncWrite for OpenSslStream {
poll_write( mut self: std::pin::Pin<&mut Self>, cx: &mut std::task::Context<'_>, buf: &[u8], ) -> std::task::Poll<io::Result<usize>>55     fn poll_write(
56         mut self: std::pin::Pin<&mut Self>,
57         cx: &mut std::task::Context<'_>,
58         buf: &[u8],
59     ) -> std::task::Poll<io::Result<usize>> {
60         pin!(&mut self.as_mut().0).poll_write(cx, buf)
61     }
62 
poll_flush( mut self: std::pin::Pin<&mut Self>, cx: &mut std::task::Context<'_>, ) -> std::task::Poll<Result<(), io::Error>>63     fn poll_flush(
64         mut self: std::pin::Pin<&mut Self>,
65         cx: &mut std::task::Context<'_>,
66     ) -> std::task::Poll<Result<(), io::Error>> {
67         pin!(&mut self.as_mut().0).poll_flush(cx)
68     }
69 
poll_shutdown( mut self: std::pin::Pin<&mut Self>, cx: &mut std::task::Context<'_>, ) -> std::task::Poll<Result<(), io::Error>>70     fn poll_shutdown(
71         mut self: std::pin::Pin<&mut Self>,
72         cx: &mut std::task::Context<'_>,
73     ) -> std::task::Poll<Result<(), io::Error>> {
74         pin!(&mut self.as_mut().0).poll_shutdown(cx)
75     }
76 }
77 
78 impl From<openssl::ssl::Error> for Error {
from(e: openssl::ssl::Error) -> Self79     fn from(e: openssl::ssl::Error) -> Self {
80         Error::msg(e.to_string())
81     }
82 }
83 impl From<openssl::error::ErrorStack> for Error {
from(e: openssl::error::ErrorStack) -> Self84     fn from(e: openssl::error::ErrorStack) -> Self {
85         openssl::ssl::Error::from(e).into()
86     }
87 }
88