1
0
mirror of https://github.com/fafhrd91/actix-net synced 2025-03-20 16:05:18 +01:00

fix rustls panic when generating dns name from ip (#296)

* fix rustls panic when generating dns name from ip

* Update rustls.rs

* update changelog

Co-authored-by: Rob Ede <robjtede@icloud.com>
This commit is contained in:
fakeshadow 2021-03-24 09:32:04 -07:00 committed by GitHub
parent b7bfff2b32
commit a3c9ebc7fa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 44 additions and 27 deletions

View File

@ -1,6 +1,10 @@
# Changes # Changes
## Unreleased - 2021-xx-xx ## Unreleased - 2021-xx-xx
* Changed `connect::ssl::rustls::RustlsConnectorService` to return error when `DNSNameRef`
generation failed instead of panic. [#296]
[#296]: https://github.com/actix/actix-net/pull/296
## 3.0.0-beta.4 - 2021-02-24 ## 3.0.0-beta.4 - 2021-02-24

View File

@ -1,6 +1,6 @@
use std::{ use std::{
fmt,
future::Future, future::Future,
io,
pin::Pin, pin::Pin,
sync::Arc, sync::Arc,
task::{Context, Poll}, task::{Context, Poll},
@ -10,7 +10,7 @@ pub use tokio_rustls::rustls::Session;
pub use tokio_rustls::{client::TlsStream, rustls::ClientConfig}; pub use tokio_rustls::{client::TlsStream, rustls::ClientConfig};
pub use webpki_roots::TLS_SERVER_ROOTS; pub use webpki_roots::TLS_SERVER_ROOTS;
use actix_codec::{AsyncRead, AsyncWrite}; use actix_rt::net::ActixStream;
use actix_service::{Service, ServiceFactory}; use actix_service::{Service, ServiceFactory};
use futures_core::{future::LocalBoxFuture, ready}; use futures_core::{future::LocalBoxFuture, ready};
use log::trace; use log::trace;
@ -44,12 +44,13 @@ impl Clone for RustlsConnector {
} }
} }
impl<T: Address, U> ServiceFactory<Connection<T, U>> for RustlsConnector impl<T, U> ServiceFactory<Connection<T, U>> for RustlsConnector
where where
U: AsyncRead + AsyncWrite + Unpin + fmt::Debug, T: Address,
U: ActixStream,
{ {
type Response = Connection<T, TlsStream<U>>; type Response = Connection<T, TlsStream<U>>;
type Error = std::io::Error; type Error = io::Error;
type Config = (); type Config = ();
type Service = RustlsConnectorService; type Service = RustlsConnectorService;
type InitError = (); type InitError = ();
@ -76,43 +77,55 @@ impl Clone for RustlsConnectorService {
impl<T, U> Service<Connection<T, U>> for RustlsConnectorService impl<T, U> Service<Connection<T, U>> for RustlsConnectorService
where where
T: Address, T: Address,
U: AsyncRead + AsyncWrite + Unpin + fmt::Debug, U: ActixStream,
{ {
type Response = Connection<T, TlsStream<U>>; type Response = Connection<T, TlsStream<U>>;
type Error = std::io::Error; type Error = io::Error;
type Future = ConnectAsyncExt<T, U>; type Future = RustlsConnectorServiceFuture<T, U>;
actix_service::always_ready!(); actix_service::always_ready!();
fn call(&self, stream: Connection<T, U>) -> Self::Future { fn call(&self, connection: Connection<T, U>) -> Self::Future {
trace!("SSL Handshake start for: {:?}", stream.host()); trace!("SSL Handshake start for: {:?}", connection.host());
let (io, stream) = stream.replace_io(()); let (stream, connection) = connection.replace_io(());
let host = DNSNameRef::try_from_ascii_str(stream.host())
.expect("rustls currently only handles hostname-based connections. See https://github.com/briansmith/webpki/issues/54"); match DNSNameRef::try_from_ascii_str(connection.host()) {
ConnectAsyncExt { Ok(host) => RustlsConnectorServiceFuture::Future {
fut: TlsConnector::from(self.connector.clone()).connect(host, io), connect: TlsConnector::from(self.connector.clone()).connect(host, stream),
stream: Some(stream), connection: Some(connection),
},
Err(_) => RustlsConnectorServiceFuture::InvalidDns,
} }
} }
} }
pub struct ConnectAsyncExt<T, U> { pub enum RustlsConnectorServiceFuture<T, U> {
fut: Connect<U>, /// See issue https://github.com/briansmith/webpki/issues/54
stream: Option<Connection<T, ()>>, InvalidDns,
Future {
connect: Connect<U>,
connection: Option<Connection<T, ()>>,
},
} }
impl<T, U> Future for ConnectAsyncExt<T, U> impl<T, U> Future for RustlsConnectorServiceFuture<T, U>
where where
T: Address, T: Address,
U: AsyncRead + AsyncWrite + Unpin + fmt::Debug, U: ActixStream,
{ {
type Output = Result<Connection<T, TlsStream<U>>, std::io::Error>; type Output = Result<Connection<T, TlsStream<U>>, io::Error>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let this = self.get_mut(); match self.get_mut() {
let stream = ready!(Pin::new(&mut this.fut).poll(cx))?; Self::InvalidDns => Poll::Ready(Err(
let s = this.stream.take().unwrap(); io::Error::new(io::ErrorKind::Other, "rustls currently only handles hostname-based connections. See https://github.com/briansmith/webpki/issues/54")
trace!("SSL Handshake success: {:?}", s.host()); )),
Poll::Ready(Ok(s.replace_io(stream).1)) Self::Future { connect, connection } => {
let stream = ready!(Pin::new(connect).poll(cx))?;
let connection = connection.take().unwrap();
trace!("SSL Handshake success: {:?}", connection.host());
Poll::Ready(Ok(connection.replace_io(stream).1))
}
}
} }
} }