mirror of https://github.com/fafhrd91/actix-net
Add feature for using rustls 0.23
This commit is contained in:
parent
85191934c8
commit
b88733d84f
|
@ -2,9 +2,11 @@
|
|||
|
||||
## Unreleased
|
||||
|
||||
- Add `rustls-0_23` crate feature which excludes any root certificate methods or re-exports.
|
||||
|
||||
## 3.3.0
|
||||
|
||||
- Add `rustls-0_22` create feature which excludes any root certificate methods or re-exports.
|
||||
- Add `rustls-0_22` crate feature which excludes any root certificate methods or re-exports.
|
||||
|
||||
## 3.2.0
|
||||
|
||||
|
|
|
@ -61,6 +61,11 @@ rustls-0_22 = ["dep:tokio-rustls-025", "dep:rustls-pki-types-1"]
|
|||
rustls-0_22-webpki-roots = ["rustls-0_22", "dep:webpki-roots-026"]
|
||||
rustls-0_22-native-roots = ["rustls-0_22", "dep:rustls-native-certs-07"]
|
||||
|
||||
# use rustls v0.23 impls
|
||||
rustls-0_23 = ["dep:tokio-rustls-026", "dep:rustls-pki-types-1"]
|
||||
rustls-0_23-webpki-roots = ["rustls-0_23", "dep:webpki-roots-026"]
|
||||
rustls-0_23-native-roots = ["rustls-0_23", "dep:rustls-native-certs-07"]
|
||||
|
||||
# use native-tls impls
|
||||
native-tls = ["dep:tokio-native-tls"]
|
||||
|
||||
|
@ -98,9 +103,12 @@ tokio-rustls-024 = { package = "tokio-rustls", version = "0.24", optional = true
|
|||
webpki-roots-025 = { package = "webpki-roots", version = "0.25", optional = true }
|
||||
|
||||
# rustls v0.22
|
||||
rustls-pki-types-1 = { package = "rustls-pki-types", version = "1", optional = true }
|
||||
rustls-pki-types-1 = { package = "rustls-pki-types", version = "1", optional = true } # Also used for rustls v0.23
|
||||
tokio-rustls-025 = { package = "tokio-rustls", version = "0.25", optional = true }
|
||||
webpki-roots-026 = { package = "webpki-roots", version = "0.26", optional = true }
|
||||
webpki-roots-026 = { package = "webpki-roots", version = "0.26", optional = true } # Also used for rustls v0.23
|
||||
|
||||
# rustls v0.23
|
||||
tokio-rustls-026 = { package = "tokio-rustls", version = "0.26", optional = true }
|
||||
|
||||
# native root certificates for rustls impls
|
||||
rustls-native-certs-06 = { package = "rustls-native-certs", version = "0.6", optional = true }
|
||||
|
|
|
@ -25,6 +25,9 @@ pub mod rustls_0_21;
|
|||
#[cfg(feature = "rustls-0_22")]
|
||||
pub mod rustls_0_22;
|
||||
|
||||
#[cfg(feature = "rustls-0_23")]
|
||||
pub mod rustls_0_23;
|
||||
|
||||
#[cfg(feature = "native-tls")]
|
||||
pub mod native_tls;
|
||||
|
||||
|
|
|
@ -0,0 +1,161 @@
|
|||
//! Rustls based connector service.
|
||||
//!
|
||||
//! See [`TlsConnector`] for main connector service factory docs.
|
||||
|
||||
use std::{
|
||||
future::Future,
|
||||
io,
|
||||
pin::Pin,
|
||||
sync::Arc,
|
||||
task::{Context, Poll},
|
||||
};
|
||||
|
||||
use actix_rt::net::ActixStream;
|
||||
use actix_service::{Service, ServiceFactory};
|
||||
use actix_utils::future::{ok, Ready};
|
||||
use futures_core::ready;
|
||||
use rustls_pki_types_1::ServerName;
|
||||
use tokio_rustls::{
|
||||
client::TlsStream as AsyncTlsStream, rustls::ClientConfig, Connect as RustlsConnect,
|
||||
TlsConnector as RustlsTlsConnector,
|
||||
};
|
||||
use tokio_rustls_026 as tokio_rustls;
|
||||
|
||||
use crate::connect::{Connection, Host};
|
||||
|
||||
pub mod reexports {
|
||||
//! Re-exports from the `rustls` v0.23 ecosystem that are useful for connectors.
|
||||
|
||||
pub use tokio_rustls_026::{client::TlsStream as AsyncTlsStream, rustls::ClientConfig};
|
||||
#[cfg(feature = "rustls-0_23-webpki-roots")]
|
||||
pub use webpki_roots_026::TLS_SERVER_ROOTS;
|
||||
}
|
||||
|
||||
/// Returns root certificates via `rustls-native-certs` crate as a rustls certificate store.
|
||||
///
|
||||
/// See [`rustls_native_certs::load_native_certs()`] for more info on behavior and errors.
|
||||
#[cfg(feature = "rustls-0_23-native-roots")]
|
||||
pub fn native_roots_cert_store() -> io::Result<tokio_rustls::rustls::RootCertStore> {
|
||||
let mut root_certs = tokio_rustls::rustls::RootCertStore::empty();
|
||||
|
||||
for cert in rustls_native_certs_07::load_native_certs()? {
|
||||
root_certs.add(cert).unwrap();
|
||||
}
|
||||
|
||||
Ok(root_certs)
|
||||
}
|
||||
|
||||
/// Returns standard root certificates from `webpki-roots` crate as a rustls certificate store.
|
||||
#[cfg(feature = "rustls-0_23-webpki-roots")]
|
||||
pub fn webpki_roots_cert_store() -> tokio_rustls::rustls::RootCertStore {
|
||||
let mut root_certs = tokio_rustls::rustls::RootCertStore::empty();
|
||||
root_certs.extend(webpki_roots_026::TLS_SERVER_ROOTS.to_owned());
|
||||
root_certs
|
||||
}
|
||||
|
||||
/// Connector service factory using `rustls`.
|
||||
#[derive(Clone)]
|
||||
pub struct TlsConnector {
|
||||
connector: Arc<ClientConfig>,
|
||||
}
|
||||
|
||||
impl TlsConnector {
|
||||
/// Constructs new connector service factory from a `rustls` client configuration.
|
||||
pub fn new(connector: Arc<ClientConfig>) -> Self {
|
||||
TlsConnector { connector }
|
||||
}
|
||||
|
||||
/// Constructs new connector service from a `rustls` client configuration.
|
||||
pub fn service(connector: Arc<ClientConfig>) -> TlsConnectorService {
|
||||
TlsConnectorService { connector }
|
||||
}
|
||||
}
|
||||
|
||||
impl<R, IO> ServiceFactory<Connection<R, IO>> for TlsConnector
|
||||
where
|
||||
R: Host,
|
||||
IO: ActixStream + 'static,
|
||||
{
|
||||
type Response = Connection<R, AsyncTlsStream<IO>>;
|
||||
type Error = io::Error;
|
||||
type Config = ();
|
||||
type Service = TlsConnectorService;
|
||||
type InitError = ();
|
||||
type Future = Ready<Result<Self::Service, Self::InitError>>;
|
||||
|
||||
fn new_service(&self, _: ()) -> Self::Future {
|
||||
ok(TlsConnectorService {
|
||||
connector: self.connector.clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Connector service using `rustls`.
|
||||
#[derive(Clone)]
|
||||
pub struct TlsConnectorService {
|
||||
connector: Arc<ClientConfig>,
|
||||
}
|
||||
|
||||
impl<R, IO> Service<Connection<R, IO>> for TlsConnectorService
|
||||
where
|
||||
R: Host,
|
||||
IO: ActixStream,
|
||||
{
|
||||
type Response = Connection<R, AsyncTlsStream<IO>>;
|
||||
type Error = io::Error;
|
||||
type Future = ConnectFut<R, IO>;
|
||||
|
||||
actix_service::always_ready!();
|
||||
|
||||
fn call(&self, connection: Connection<R, IO>) -> Self::Future {
|
||||
tracing::trace!("TLS handshake start for: {:?}", connection.hostname());
|
||||
let (stream, conn) = connection.replace_io(());
|
||||
|
||||
match ServerName::try_from(conn.hostname()) {
|
||||
Ok(host) => ConnectFut::Future {
|
||||
connect: RustlsTlsConnector::from(Arc::clone(&self.connector))
|
||||
.connect(host.to_owned(), stream),
|
||||
connection: Some(conn),
|
||||
},
|
||||
Err(_) => ConnectFut::InvalidServerName,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Connect future for Rustls service.
|
||||
#[doc(hidden)]
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
pub enum ConnectFut<R, IO> {
|
||||
InvalidServerName,
|
||||
Future {
|
||||
connect: RustlsConnect<IO>,
|
||||
connection: Option<Connection<R, ()>>,
|
||||
},
|
||||
}
|
||||
|
||||
impl<R, IO> Future for ConnectFut<R, IO>
|
||||
where
|
||||
R: Host,
|
||||
IO: ActixStream,
|
||||
{
|
||||
type Output = io::Result<Connection<R, AsyncTlsStream<IO>>>;
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
match self.get_mut() {
|
||||
Self::InvalidServerName => Poll::Ready(Err(io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
"connection parameters specified invalid server name",
|
||||
))),
|
||||
|
||||
Self::Future {
|
||||
connect,
|
||||
connection,
|
||||
} => {
|
||||
let stream = ready!(Pin::new(connect).poll(cx))?;
|
||||
let connection = connection.take().unwrap();
|
||||
tracing::trace!("TLS handshake success: {:?}", connection.hostname());
|
||||
Poll::Ready(Ok(connection.replace_io(stream).1))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -49,6 +49,9 @@ pub mod rustls_0_21;
|
|||
#[cfg(feature = "rustls-0_22")]
|
||||
pub mod rustls_0_22;
|
||||
|
||||
#[cfg(feature = "rustls-0_23")]
|
||||
pub mod rustls_0_23;
|
||||
|
||||
#[cfg(feature = "native-tls")]
|
||||
pub mod native_tls;
|
||||
|
||||
|
|
|
@ -0,0 +1,161 @@
|
|||
//! Rustls based connector service.
|
||||
//!
|
||||
//! See [`TlsConnector`] for main connector service factory docs.
|
||||
|
||||
use std::{
|
||||
future::Future,
|
||||
io,
|
||||
pin::Pin,
|
||||
sync::Arc,
|
||||
task::{Context, Poll},
|
||||
};
|
||||
|
||||
use actix_rt::net::ActixStream;
|
||||
use actix_service::{Service, ServiceFactory};
|
||||
use actix_utils::future::{ok, Ready};
|
||||
use futures_core::ready;
|
||||
use rustls_pki_types_1::ServerName;
|
||||
use tokio_rustls::{
|
||||
client::TlsStream as AsyncTlsStream, rustls::ClientConfig, Connect as RustlsConnect,
|
||||
TlsConnector as RustlsTlsConnector,
|
||||
};
|
||||
use tokio_rustls_026 as tokio_rustls;
|
||||
|
||||
use crate::connect::{Connection, Host};
|
||||
|
||||
pub mod reexports {
|
||||
//! Re-exports from the `rustls` v0.23 ecosystem that are useful for connectors.
|
||||
|
||||
pub use tokio_rustls_025::{client::TlsStream as AsyncTlsStream, rustls::ClientConfig};
|
||||
#[cfg(feature = "rustls-0_23-webpki-roots")]
|
||||
pub use webpki_roots_026::TLS_SERVER_ROOTS;
|
||||
}
|
||||
|
||||
/// Returns root certificates via `rustls-native-certs` crate as a rustls certificate store.
|
||||
///
|
||||
/// See [`rustls_native_certs::load_native_certs()`] for more info on behavior and errors.
|
||||
#[cfg(feature = "rustls-0_23-native-roots")]
|
||||
pub fn native_roots_cert_store() -> io::Result<tokio_rustls::rustls::RootCertStore> {
|
||||
let mut root_certs = tokio_rustls::rustls::RootCertStore::empty();
|
||||
|
||||
for cert in rustls_native_certs_07::load_native_certs()? {
|
||||
root_certs.add(cert).unwrap();
|
||||
}
|
||||
|
||||
Ok(root_certs)
|
||||
}
|
||||
|
||||
/// Returns standard root certificates from `webpki-roots` crate as a rustls certificate store.
|
||||
#[cfg(feature = "rustls-0_23-webpki-roots")]
|
||||
pub fn webpki_roots_cert_store() -> tokio_rustls::rustls::RootCertStore {
|
||||
let mut root_certs = tokio_rustls::rustls::RootCertStore::empty();
|
||||
root_certs.extend(webpki_roots_026::TLS_SERVER_ROOTS.to_owned());
|
||||
root_certs
|
||||
}
|
||||
|
||||
/// Connector service factory using `rustls`.
|
||||
#[derive(Clone)]
|
||||
pub struct TlsConnector {
|
||||
connector: Arc<ClientConfig>,
|
||||
}
|
||||
|
||||
impl TlsConnector {
|
||||
/// Constructs new connector service factory from a `rustls` client configuration.
|
||||
pub fn new(connector: Arc<ClientConfig>) -> Self {
|
||||
TlsConnector { connector }
|
||||
}
|
||||
|
||||
/// Constructs new connector service from a `rustls` client configuration.
|
||||
pub fn service(connector: Arc<ClientConfig>) -> TlsConnectorService {
|
||||
TlsConnectorService { connector }
|
||||
}
|
||||
}
|
||||
|
||||
impl<R, IO> ServiceFactory<Connection<R, IO>> for TlsConnector
|
||||
where
|
||||
R: Host,
|
||||
IO: ActixStream + 'static,
|
||||
{
|
||||
type Response = Connection<R, AsyncTlsStream<IO>>;
|
||||
type Error = io::Error;
|
||||
type Config = ();
|
||||
type Service = TlsConnectorService;
|
||||
type InitError = ();
|
||||
type Future = Ready<Result<Self::Service, Self::InitError>>;
|
||||
|
||||
fn new_service(&self, _: ()) -> Self::Future {
|
||||
ok(TlsConnectorService {
|
||||
connector: self.connector.clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Connector service using `rustls`.
|
||||
#[derive(Clone)]
|
||||
pub struct TlsConnectorService {
|
||||
connector: Arc<ClientConfig>,
|
||||
}
|
||||
|
||||
impl<R, IO> Service<Connection<R, IO>> for TlsConnectorService
|
||||
where
|
||||
R: Host,
|
||||
IO: ActixStream,
|
||||
{
|
||||
type Response = Connection<R, AsyncTlsStream<IO>>;
|
||||
type Error = io::Error;
|
||||
type Future = ConnectFut<R, IO>;
|
||||
|
||||
actix_service::always_ready!();
|
||||
|
||||
fn call(&self, connection: Connection<R, IO>) -> Self::Future {
|
||||
tracing::trace!("TLS handshake start for: {:?}", connection.hostname());
|
||||
let (stream, conn) = connection.replace_io(());
|
||||
|
||||
match ServerName::try_from(conn.hostname()) {
|
||||
Ok(host) => ConnectFut::Future {
|
||||
connect: RustlsTlsConnector::from(Arc::clone(&self.connector))
|
||||
.connect(host.to_owned(), stream),
|
||||
connection: Some(conn),
|
||||
},
|
||||
Err(_) => ConnectFut::InvalidServerName,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Connect future for Rustls service.
|
||||
#[doc(hidden)]
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
pub enum ConnectFut<R, IO> {
|
||||
InvalidServerName,
|
||||
Future {
|
||||
connect: RustlsConnect<IO>,
|
||||
connection: Option<Connection<R, ()>>,
|
||||
},
|
||||
}
|
||||
|
||||
impl<R, IO> Future for ConnectFut<R, IO>
|
||||
where
|
||||
R: Host,
|
||||
IO: ActixStream,
|
||||
{
|
||||
type Output = io::Result<Connection<R, AsyncTlsStream<IO>>>;
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
match self.get_mut() {
|
||||
Self::InvalidServerName => Poll::Ready(Err(io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
"connection parameters specified invalid server name",
|
||||
))),
|
||||
|
||||
Self::Future {
|
||||
connect,
|
||||
connection,
|
||||
} => {
|
||||
let stream = ready!(Pin::new(connect).poll(cx))?;
|
||||
let connection = connection.take().unwrap();
|
||||
tracing::trace!("TLS handshake success: {:?}", connection.hostname());
|
||||
Poll::Ready(Ok(connection.replace_io(stream).1))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
#![cfg(all(
|
||||
feature = "accept",
|
||||
feature = "connect",
|
||||
feature = "rustls-0_22",
|
||||
feature = "rustls-0_23",
|
||||
feature = "openssl"
|
||||
))]
|
||||
|
||||
|
@ -14,11 +14,11 @@ use actix_server::TestServer;
|
|||
use actix_service::ServiceFactoryExt as _;
|
||||
use actix_tls::{
|
||||
accept::openssl::{Acceptor, TlsStream},
|
||||
connect::rustls_0_22::reexports::ClientConfig,
|
||||
connect::rustls_0_23::reexports::ClientConfig,
|
||||
};
|
||||
use actix_utils::future::ok;
|
||||
use rustls_pki_types_1::ServerName;
|
||||
use tokio_rustls_025::rustls::RootCertStore;
|
||||
use tokio_rustls_026::rustls::RootCertStore;
|
||||
|
||||
fn new_cert_and_key() -> (String, String) {
|
||||
let cert =
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#![cfg(all(
|
||||
feature = "accept",
|
||||
feature = "connect",
|
||||
feature = "rustls-0_22",
|
||||
feature = "rustls-0_23",
|
||||
feature = "openssl"
|
||||
))]
|
||||
|
||||
|
@ -15,7 +15,7 @@ use actix_rt::net::TcpStream;
|
|||
use actix_server::TestServer;
|
||||
use actix_service::ServiceFactoryExt as _;
|
||||
use actix_tls::{
|
||||
accept::rustls_0_22::{reexports::ServerConfig, Acceptor, TlsStream},
|
||||
accept::rustls_0_23::{reexports::ServerConfig, Acceptor, TlsStream},
|
||||
connect::openssl::reexports::SslConnector,
|
||||
};
|
||||
use actix_utils::future::ok;
|
||||
|
|
|
@ -30,7 +30,7 @@ async fn test_string() {
|
|||
assert_eq!(con.peer_addr().unwrap(), srv.addr());
|
||||
}
|
||||
|
||||
#[cfg(feature = "rustls-0_22")]
|
||||
#[cfg(feature = "rustls-0_23")]
|
||||
#[actix_rt::test]
|
||||
async fn test_rustls_string() {
|
||||
let srv = TestServer::start(|| {
|
||||
|
@ -112,7 +112,7 @@ async fn test_openssl_uri() {
|
|||
assert_eq!(con.peer_addr().unwrap(), srv.addr());
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "rustls-0_22", feature = "uri"))]
|
||||
#[cfg(all(feature = "rustls-0_23", feature = "uri"))]
|
||||
#[actix_rt::test]
|
||||
async fn test_rustls_uri_http1() {
|
||||
let srv = TestServer::start(|| {
|
||||
|
@ -129,7 +129,7 @@ async fn test_rustls_uri_http1() {
|
|||
assert_eq!(con.peer_addr().unwrap(), srv.addr());
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "rustls-0_22", feature = "uri"))]
|
||||
#[cfg(all(feature = "rustls-0_23", feature = "uri"))]
|
||||
#[actix_rt::test]
|
||||
async fn test_rustls_uri() {
|
||||
let srv = TestServer::start(|| {
|
||||
|
|
Loading…
Reference in New Issue