mirror of
https://github.com/launchbadge/sqlx.git
synced 2025-10-04 00:05:27 +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
10
Cargo.lock
generated
10
Cargo.lock
generated
@ -2249,6 +2249,7 @@ dependencies = [
|
|||||||
"url",
|
"url",
|
||||||
"uuid",
|
"uuid",
|
||||||
"webpki",
|
"webpki",
|
||||||
|
"webpki-roots",
|
||||||
"whoami",
|
"whoami",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -2927,6 +2928,15 @@ dependencies = [
|
|||||||
"untrusted",
|
"untrusted",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "webpki-roots"
|
||||||
|
version = "0.20.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0f20dea7535251981a9670857150d571846545088359b28e4951d350bdaf179f"
|
||||||
|
dependencies = [
|
||||||
|
"webpki",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wepoll-sys"
|
name = "wepoll-sys"
|
||||||
version = "3.0.1"
|
version = "3.0.1"
|
||||||
|
@ -47,7 +47,7 @@ _rt-actix = []
|
|||||||
_rt-async-std = []
|
_rt-async-std = []
|
||||||
_rt-tokio = []
|
_rt-tokio = []
|
||||||
_tls-native-tls = []
|
_tls-native-tls = []
|
||||||
_tls-rustls = [ "rustls", "webpki" ]
|
_tls-rustls = [ "rustls", "webpki", "webpki-roots" ]
|
||||||
|
|
||||||
# support offline/decoupled building (enables serialization of `Describe`)
|
# support offline/decoupled building (enables serialization of `Describe`)
|
||||||
offline = [ "serde", "either/serde" ]
|
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" ] }
|
rand = { version = "0.7.3", default-features = false, optional = true, features = [ "std" ] }
|
||||||
regex = { version = "1.3.9", optional = true }
|
regex = { version = "1.3.9", optional = true }
|
||||||
rsa = { version = "0.3.0", 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 = { version = "1.0.106", features = [ "derive", "rc" ], optional = true }
|
||||||
serde_json = { version = "1.0.51", features = [ "raw_value" ], optional = true }
|
serde_json = { version = "1.0.51", features = [ "raw_value" ], optional = true }
|
||||||
sha-1 = { version = "0.9.0", default-features = false, 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 }
|
url = { version = "2.1.1", default-features = false }
|
||||||
uuid = { version = "0.8.1", default-features = false, optional = true, features = [ "std" ] }
|
uuid = { version = "0.8.1", default-features = false, optional = true, features = [ "std" ] }
|
||||||
webpki = { version = "0.21.3", optional = true }
|
webpki = { version = "0.21.3", optional = true }
|
||||||
|
webpki-roots = { version = "0.20.0", optional = true }
|
||||||
whoami = "0.9.0"
|
whoami = "0.9.0"
|
||||||
stringprep = "0.1.2"
|
stringprep = "0.1.2"
|
||||||
lru-cache = "0.1.2"
|
lru-cache = "0.1.2"
|
||||||
|
@ -6,11 +6,14 @@ use std::path::Path;
|
|||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::task::{Context, Poll};
|
use std::task::{Context, Poll};
|
||||||
|
|
||||||
use sqlx_rt::{fs, AsyncRead, AsyncWrite, TlsStream};
|
use sqlx_rt::{AsyncRead, AsyncWrite, TlsStream};
|
||||||
|
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use std::mem::replace;
|
use std::mem::replace;
|
||||||
|
|
||||||
|
#[cfg(feature = "_tls-rustls")]
|
||||||
|
mod rustls;
|
||||||
|
|
||||||
pub enum MaybeTlsStream<S>
|
pub enum MaybeTlsStream<S>
|
||||||
where
|
where
|
||||||
S: AsyncRead + AsyncWrite + Unpin,
|
S: AsyncRead + AsyncWrite + Unpin,
|
||||||
@ -73,7 +76,10 @@ async fn configure_tls_connector(
|
|||||||
accept_invalid_hostnames: bool,
|
accept_invalid_hostnames: bool,
|
||||||
root_cert_path: Option<&Path>,
|
root_cert_path: Option<&Path>,
|
||||||
) -> Result<sqlx_rt::TlsConnector, Error> {
|
) -> 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();
|
let mut builder = TlsConnector::builder();
|
||||||
builder
|
builder
|
||||||
@ -99,29 +105,7 @@ async fn configure_tls_connector(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "_tls-rustls")]
|
#[cfg(feature = "_tls-rustls")]
|
||||||
async fn configure_tls_connector(
|
use self::rustls::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())
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S> AsyncRead for MaybeTlsStream<S>
|
impl<S> AsyncRead for MaybeTlsStream<S>
|
||||||
where
|
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…
x
Reference in New Issue
Block a user