Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ json = ["serde", "serde_json"]
websocket = ["http-ws"]
# feature for trusted local network:
# - http/2 clear text over plain tcp connection
# - http/3 connection to server with self signed certificates
# - allow invalid certificates for client in http/1, http/2 and/or http/3
dangerous = []

[dependencies]
Expand Down
89 changes: 24 additions & 65 deletions client/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ pub struct ClientBuilder {
local_addr: Option<SocketAddr>,
max_http_version: Version,
service: HttpService,
#[cfg(feature = "dangerous")]
allow_invalid_certificate: bool,
}

impl Default for ClientBuilder {
Expand All @@ -49,6 +51,8 @@ impl ClientBuilder {
local_addr: None,
max_http_version: max_http_version(),
service: base_service(),
#[cfg(feature = "dangerous")]
allow_invalid_certificate: false,
}
}

Expand Down Expand Up @@ -155,14 +159,22 @@ impl ClientBuilder {
#[cfg(feature = "openssl")]
/// enable openssl as tls connector.
pub fn openssl(mut self) -> Self {
self.connector = connector::openssl::connect(self.alpn_from_version());
self.connector = connector::openssl::connect(
self.alpn_from_version(),
#[cfg(feature = "dangerous")]
self.allow_invalid_certificate,
);
self
}

#[cfg(any(feature = "rustls", feature = "rustls-ring-crypto"))]
/// enable rustls as tls connector.
pub fn rustls(mut self) -> Self {
self.connector = connector::rustls::connect(self.alpn_from_version());
self.connector = connector::rustls::connect(
self.alpn_from_version(),
#[cfg(feature = "dangerous")]
self.allow_invalid_certificate,
);
self
}

Expand Down Expand Up @@ -381,6 +393,13 @@ impl ClientBuilder {
self
}

#[cfg(feature = "dangerous")]
/// Allow invalid certificate for tls connection.
pub fn allow_invalid_certificate(mut self) -> Self {
self.allow_invalid_certificate = true;
self
}

/// Finish the builder and construct [Client] instance.
pub fn finish(self) -> Client {
#[cfg(feature = "http3")]
Expand All @@ -403,70 +422,10 @@ impl ClientBuilder {

#[cfg(feature = "dangerous")]
{
use xitca_tls::rustls::{
self, DigitallySignedStruct,
client::danger::HandshakeSignatureValid,
crypto::{verify_tls12_signature, verify_tls13_signature},
pki_types::{CertificateDer, ServerName, UnixTime},
};

#[derive(Debug)]
pub(crate) struct SkipServerVerification;

impl SkipServerVerification {
fn new() -> Arc<Self> {
Arc::new(Self)
}
}

impl rustls::client::danger::ServerCertVerifier for SkipServerVerification {
fn verify_server_cert(
&self,
_end_entity: &CertificateDer<'_>,
_intermediates: &[CertificateDer<'_>],
_server_name: &ServerName<'_>,
_ocsp: &[u8],
_now: UnixTime,
) -> Result<rustls::client::danger::ServerCertVerified, rustls::Error> {
Ok(rustls::client::danger::ServerCertVerified::assertion())
}

fn verify_tls12_signature(
&self,
message: &[u8],
cert: &CertificateDer<'_>,
dss: &DigitallySignedStruct,
) -> Result<HandshakeSignatureValid, rustls::Error> {
verify_tls12_signature(
message,
cert,
dss,
&rustls::crypto::ring::default_provider().signature_verification_algorithms,
)
}

fn verify_tls13_signature(
&self,
message: &[u8],
cert: &CertificateDer<'_>,
dss: &DigitallySignedStruct,
) -> Result<HandshakeSignatureValid, rustls::Error> {
verify_tls13_signature(
message,
cert,
dss,
&rustls::crypto::ring::default_provider().signature_verification_algorithms,
)
}

fn supported_verify_schemes(&self) -> Vec<rustls::SignatureScheme> {
rustls::crypto::ring::default_provider()
.signature_verification_algorithms
.supported_schemes()
}
if self.allow_invalid_certificate {
cfg.dangerous()
.set_certificate_verifier(crate::tls::dangerous::rustls::SkipServerVerification::new());
}

cfg.dangerous().set_certificate_verifier(SkipServerVerification::new());
}

let mut endpoint = match self.local_addr {
Expand Down
29 changes: 25 additions & 4 deletions client/src/tls/connector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ pub(crate) mod openssl {
}
}

pub(crate) fn connect(protocols: &[&[u8]]) -> Connector {
pub(crate) fn connect(protocols: &[&[u8]], #[cfg(feature = "dangerous")] allow_invalid_certs: bool) -> Connector {
let mut alpn = Vec::with_capacity(20);
for proto in protocols {
alpn.put_u8(proto.len() as u8);
Expand All @@ -81,6 +81,13 @@ pub(crate) mod openssl {
ssl.set_alpn_protos(&alpn)
.unwrap_or_else(|e| panic!("Can not set ALPN protocol: {e:?}"));

#[cfg(feature = "dangerous")]
{
if allow_invalid_certs {
ssl.set_verify(openssl::ssl::SslVerifyMode::NONE);
}
}

Box::new(ssl.build())
}
}
Expand All @@ -89,11 +96,10 @@ pub(crate) mod openssl {
pub(crate) mod rustls {
use std::sync::Arc;

use super::*;
use webpki_roots::TLS_SERVER_ROOTS;
use xitca_tls::rustls::{self, ClientConfig, ClientConnection, RootCertStore, pki_types::ServerName};

use super::*;

pub struct TlsConnector(Arc<ClientConfig>);

impl<'n> Service<(&'n str, TlsStream)> for TlsConnector {
Expand Down Expand Up @@ -123,7 +129,7 @@ pub(crate) mod rustls {
}
}

pub(crate) fn connect(protocols: &[&[u8]]) -> Connector {
pub(crate) fn connect(protocols: &[&[u8]], #[cfg(feature = "dangerous")] allow_invalid_certs: bool) -> Connector {
let mut root_certs = RootCertStore::empty();

root_certs.extend(TLS_SERVER_ROOTS.iter().cloned());
Expand All @@ -134,6 +140,21 @@ pub(crate) mod rustls {

config.alpn_protocols = protocols.iter().map(|p| p.to_vec()).collect();

#[cfg(feature = "dangerous")]
{
if allow_invalid_certs {
#[cfg(feature = "rustls-ring-crypto")]
{
config
.dangerous()
.set_certificate_verifier(crate::tls::dangerous::rustls::SkipServerVerification::new());
}

#[cfg(not(feature = "rustls-ring-crypto"))]
unimplemented!("cannot skip server verification without `rustls-ring-crypto` feature");
}
}

Box::new(TlsConnector(Arc::new(config)))
}
}
67 changes: 67 additions & 0 deletions client/src/tls/dangerous.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#[cfg(feature = "rustls-ring-crypto")]
pub(crate) mod rustls {
use std::sync::Arc;
use xitca_tls::rustls::{
self,
client::danger::HandshakeSignatureValid,
crypto::{verify_tls12_signature, verify_tls13_signature},
pki_types::{CertificateDer, ServerName, UnixTime},
DigitallySignedStruct,
};

#[derive(Debug)]
pub(crate) struct SkipServerVerification;

impl SkipServerVerification {
pub(crate) fn new() -> Arc<Self> {
Arc::new(Self)
}
}

impl rustls::client::danger::ServerCertVerifier for SkipServerVerification {
fn verify_server_cert(
&self,
_end_entity: &CertificateDer<'_>,
_intermediates: &[CertificateDer<'_>],
_server_name: &ServerName<'_>,
_ocsp: &[u8],
_now: UnixTime,
) -> Result<rustls::client::danger::ServerCertVerified, rustls::Error> {
Ok(rustls::client::danger::ServerCertVerified::assertion())
}

fn verify_tls12_signature(
&self,
message: &[u8],
cert: &CertificateDer<'_>,
dss: &DigitallySignedStruct,
) -> Result<HandshakeSignatureValid, rustls::Error> {
verify_tls12_signature(
message,
cert,
dss,
&rustls::crypto::ring::default_provider().signature_verification_algorithms,
)
}

fn verify_tls13_signature(
&self,
message: &[u8],
cert: &CertificateDer<'_>,
dss: &DigitallySignedStruct,
) -> Result<HandshakeSignatureValid, rustls::Error> {
verify_tls13_signature(
message,
cert,
dss,
&rustls::crypto::ring::default_provider().signature_verification_algorithms,
)
}

fn supported_verify_schemes(&self) -> Vec<rustls::SignatureScheme> {
rustls::crypto::ring::default_provider()
.signature_verification_algorithms
.supported_schemes()
}
}
}
2 changes: 2 additions & 0 deletions client/src/tls/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
pub(crate) mod connector;
#[cfg(feature = "dangerous")]
pub(crate) mod dangerous;

pub type TlsStream = Box<dyn xitca_io::io::AsyncIoDyn + Send + Sync>;
6 changes: 3 additions & 3 deletions test/tests/h3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use xitca_test::{test_h3_server, Error};
async fn h3_get() -> Result<(), Error> {
let mut handle = test_h3_server(fn_service(handle))?;

let c = Client::new();
let c = Client::builder().allow_invalid_certificate().finish();
let server_url = format!("https://localhost:{}/", handle.addr().port());

for _ in 0..3 {
Expand All @@ -37,7 +37,7 @@ async fn h3_no_host_header() -> Result<(), Error> {

let server_url = format!("https://{}/host", handle.ip_port_string());

let c = Client::new();
let c = Client::builder().allow_invalid_certificate().finish();

for _ in 0..3 {
let mut req = c.get(&server_url).version(Version::HTTP_3);
Expand All @@ -61,7 +61,7 @@ async fn h3_no_host_header() -> Result<(), Error> {
async fn h3_post() -> Result<(), Error> {
let mut handle = test_h3_server(fn_service(handle))?;

let c = Client::new();
let c = Client::builder().allow_invalid_certificate().finish();

let server_url = format!("https://localhost:{}/", handle.addr().port());

Expand Down
Loading