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