mirror of
https://github.com/launchbadge/sqlx
synced 2024-11-10 06:24:16 +00:00
Support accept_invalid_certs & accept_invalid_hostnames with rustls
Co-authored-by: BlackHoleFox <blackholefoxdev@gmail.com>
This commit is contained in:
parent
a68872a35a
commit
1ed75ba5f0
4 changed files with 100 additions and 27 deletions
10
Cargo.lock
generated
10
Cargo.lock
generated
|
@ -2249,6 +2249,7 @@ dependencies = [
|
|||
"url",
|
||||
"uuid",
|
||||
"webpki",
|
||||
"webpki-roots",
|
||||
"whoami",
|
||||
]
|
||||
|
||||
|
@ -2927,6 +2928,15 @@ dependencies = [
|
|||
"untrusted",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webpki-roots"
|
||||
version = "0.20.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0f20dea7535251981a9670857150d571846545088359b28e4951d350bdaf179f"
|
||||
dependencies = [
|
||||
"webpki",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wepoll-sys"
|
||||
version = "3.0.1"
|
||||
|
|
|
@ -47,7 +47,7 @@ _rt-actix = []
|
|||
_rt-async-std = []
|
||||
_rt-tokio = []
|
||||
_tls-native-tls = []
|
||||
_tls-rustls = [ "rustls", "webpki" ]
|
||||
_tls-rustls = [ "rustls", "webpki", "webpki-roots" ]
|
||||
|
||||
# support offline/decoupled building (enables serialization of `Describe`)
|
||||
offline = [ "serde", "either/serde" ]
|
||||
|
@ -91,7 +91,7 @@ parking_lot = "0.11.0"
|
|||
rand = { version = "0.7.3", default-features = false, optional = true, features = [ "std" ] }
|
||||
regex = { version = "1.3.9", optional = true }
|
||||
rsa = { version = "0.3.0", optional = true }
|
||||
rustls = { version = "0.18.1", optional = true }
|
||||
rustls = { version = "0.18.1", features = [ "dangerous_configuration" ], optional = true }
|
||||
serde = { version = "1.0.106", features = [ "derive", "rc" ], optional = true }
|
||||
serde_json = { version = "1.0.51", features = [ "raw_value" ], optional = true }
|
||||
sha-1 = { version = "0.9.0", default-features = false, optional = true }
|
||||
|
@ -103,6 +103,7 @@ smallvec = "1.4.0"
|
|||
url = { version = "2.1.1", default-features = false }
|
||||
uuid = { version = "0.8.1", default-features = false, optional = true, features = [ "std" ] }
|
||||
webpki = { version = "0.21.3", optional = true }
|
||||
webpki-roots = { version = "0.20.0", optional = true }
|
||||
whoami = "0.9.0"
|
||||
stringprep = "0.1.2"
|
||||
lru-cache = "0.1.2"
|
||||
|
|
|
@ -6,11 +6,14 @@ use std::path::Path;
|
|||
use std::pin::Pin;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
use sqlx_rt::{fs, AsyncRead, AsyncWrite, TlsStream};
|
||||
use sqlx_rt::{AsyncRead, AsyncWrite, TlsStream};
|
||||
|
||||
use crate::error::Error;
|
||||
use std::mem::replace;
|
||||
|
||||
#[cfg(feature = "_tls-rustls")]
|
||||
mod rustls;
|
||||
|
||||
pub enum MaybeTlsStream<S>
|
||||
where
|
||||
S: AsyncRead + AsyncWrite + Unpin,
|
||||
|
@ -73,7 +76,10 @@ async fn configure_tls_connector(
|
|||
accept_invalid_hostnames: bool,
|
||||
root_cert_path: Option<&Path>,
|
||||
) -> Result<sqlx_rt::TlsConnector, Error> {
|
||||
use sqlx_rt::native_tls::{Certificate, TlsConnector};
|
||||
use sqlx_rt::{
|
||||
fs,
|
||||
native_tls::{Certificate, TlsConnector},
|
||||
};
|
||||
|
||||
let mut builder = TlsConnector::builder();
|
||||
builder
|
||||
|
@ -99,29 +105,7 @@ async fn configure_tls_connector(
|
|||
}
|
||||
|
||||
#[cfg(feature = "_tls-rustls")]
|
||||
async fn configure_tls_connector(
|
||||
_accept_invalid_certs: bool,
|
||||
_accept_invalid_hostnames: bool,
|
||||
root_cert_path: Option<&Path>,
|
||||
) -> Result<sqlx_rt::TlsConnector, Error> {
|
||||
// FIXME: Support accept_invalid_certs / accept_invalid_hostnames
|
||||
|
||||
use rustls::ClientConfig;
|
||||
use std::io::Cursor;
|
||||
use std::sync::Arc;
|
||||
|
||||
let mut config = ClientConfig::new();
|
||||
|
||||
if let Some(ca) = root_cert_path {
|
||||
let data = fs::read(ca).await?;
|
||||
let mut cursor = Cursor::new(data);
|
||||
config.root_store.add_pem_file(&mut cursor).map_err(|_| {
|
||||
Error::Tls(format!("Invalid certificate file: {}", ca.display()).into())
|
||||
})?;
|
||||
}
|
||||
|
||||
Ok(Arc::new(config).into())
|
||||
}
|
||||
use self::rustls::configure_tls_connector;
|
||||
|
||||
impl<S> AsyncRead for MaybeTlsStream<S>
|
||||
where
|
78
sqlx-core/src/net/tls/rustls.rs
Normal file
78
sqlx-core/src/net/tls/rustls.rs
Normal file
|
@ -0,0 +1,78 @@
|
|||
use rustls::{
|
||||
Certificate, ClientConfig, RootCertStore, ServerCertVerified, ServerCertVerifier, TLSError,
|
||||
WebPKIVerifier,
|
||||
};
|
||||
use sqlx_rt::fs;
|
||||
use std::sync::Arc;
|
||||
use std::{io::Cursor, path::Path};
|
||||
use webpki::DNSNameRef;
|
||||
|
||||
use crate::error::Error;
|
||||
|
||||
pub async fn configure_tls_connector(
|
||||
accept_invalid_certs: bool,
|
||||
accept_invalid_hostnames: bool,
|
||||
root_cert_path: Option<&Path>,
|
||||
) -> Result<sqlx_rt::TlsConnector, Error> {
|
||||
let mut config = ClientConfig::new();
|
||||
|
||||
if accept_invalid_certs {
|
||||
config
|
||||
.dangerous()
|
||||
.set_certificate_verifier(Arc::new(DummyTlsVerifier));
|
||||
} else {
|
||||
config
|
||||
.root_store
|
||||
.add_server_trust_anchors(&webpki_roots::TLS_SERVER_ROOTS);
|
||||
|
||||
if let Some(ca) = root_cert_path {
|
||||
let data = fs::read(ca).await?;
|
||||
let mut cursor = Cursor::new(data);
|
||||
config.root_store.add_pem_file(&mut cursor).map_err(|_| {
|
||||
Error::Tls(format!("Invalid certificate file: {}", ca.display()).into())
|
||||
})?;
|
||||
}
|
||||
|
||||
if accept_invalid_hostnames {
|
||||
config
|
||||
.dangerous()
|
||||
.set_certificate_verifier(Arc::new(NoHostnameTlsVerifier));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Arc::new(config).into())
|
||||
}
|
||||
|
||||
struct DummyTlsVerifier;
|
||||
|
||||
impl ServerCertVerifier for DummyTlsVerifier {
|
||||
fn verify_server_cert(
|
||||
&self,
|
||||
_roots: &RootCertStore,
|
||||
_presented_certs: &[Certificate],
|
||||
_dns_name: DNSNameRef<'_>,
|
||||
_ocsp_response: &[u8],
|
||||
) -> Result<ServerCertVerified, TLSError> {
|
||||
Ok(ServerCertVerified::assertion())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct NoHostnameTlsVerifier;
|
||||
|
||||
impl ServerCertVerifier for NoHostnameTlsVerifier {
|
||||
fn verify_server_cert(
|
||||
&self,
|
||||
roots: &RootCertStore,
|
||||
presented_certs: &[Certificate],
|
||||
dns_name: DNSNameRef<'_>,
|
||||
ocsp_response: &[u8],
|
||||
) -> Result<ServerCertVerified, TLSError> {
|
||||
let verifier = WebPKIVerifier::new();
|
||||
match verifier.verify_server_cert(roots, presented_certs, dns_name, ocsp_response) {
|
||||
Err(TLSError::WebPKIError(webpki::Error::CertNotValidForName)) => {
|
||||
Ok(ServerCertVerified::assertion())
|
||||
}
|
||||
res => res,
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue