diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a6bb7afe..a56ab440 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,12 +33,12 @@ jobs: run: cargo clippy --features pg-type-postgis -- -D warnings - name: Lint minimal run: cargo clippy --no-default-features -- -D warnings - - name: Lint server-api without tls + - name: Lint server-api (rustcrypto, no tls provider) run: cargo clippy --no-default-features --features server-api -- -D warnings - name: Lint ring run: cargo clippy --no-default-features --features server-api-ring -- -D warnings - name: Lint client api - run: cargo clippy --features client-api-aws-lc-rs -- -D warnings + run: cargo clippy --no-default-features --features client-api-aws-lc-rs -- -D warnings test: name: Test @@ -58,13 +58,13 @@ jobs: run: cargo test --features pg-type-postgis - name: Run tests on minimal feature set run: cargo test --no-default-features - - name: Run tests without tls + - name: Run tests without tls provider run: cargo test --no-default-features --features server-api - name: Run tests on additional ring feature set run: cargo test --no-default-features --features server-api-ring - name: Run tests for client api if: runner.os != 'Windows' - run: cargo test --features client-api-aws-lc-rs + run: cargo test --no-default-features --features client-api-aws-lc-rs,pg-ext-types - name: Run check sqlite example run: cargo check --all-targets --features _sqlite,_bundled diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a1db5f0..c7e6ede6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,21 @@ Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Changed + +- SCRAM-SHA-256 authentication and `tls-server-end-point` channel binding are + now implemented with pure-Rust RustCrypto crates (`sha2`, `hmac`, `pbkdf2`, + `x509-cert`) instead of `ring`/`aws-lc-rs`, and are always available with + the `server-api` and `client-api` features. `ring` and `aws-lc-rs` are no + longer direct dependencies of pgwire; they only appear (via `tokio-rustls`) + when a `*-ring`/`*-aws-lc-rs` feature is selected. The plain `server-api` + and `client-api` features now include the TLS types backed by a provider-less + `rustls`: the application selects the rustls crypto provider, following the + rustls "bring your own provider" recommendation. Bare `client-api` (without + a provider suffix) now compiles standalone. The `simple-oidc-validator` + feature uses the `rust_crypto` backend of `jsonwebtoken` instead of + `aws-lc-rs`. + ### Added - Client API: transaction status tracking. `ClientInfo::transaction_status` diff --git a/Cargo.toml b/Cargo.toml index d5982517..9650a44b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,15 +36,22 @@ pin-project = { version = "1.1", optional = true } rand = { version = "0.10", optional = true } md5 = { version = "0.8", optional = true } hex = { version = "0.4", optional = true } -## scram libraries +## scram libraries (RustCrypto) base64 = { version = "0.23", optional = true } -ring = { version = "0.17", optional = true } -aws-lc-rs = { version = "1.7", optional = true } stringprep = { version = "0.1.2", optional = true } -x509-certificate = { version = "0.25", optional = true } +sha2 = { version = "0.10", optional = true } +hmac = { version = "0.12", optional = true } +pbkdf2 = { version = "0.12", optional = true } +x509-cert = { version = "0.3", default-features = false, features = [ + "pem", + "std", +], optional = true } ## oauth -jsonwebtoken = { version = "11", features = ["aws_lc_rs"], optional = true } +jsonwebtoken = { version = "11", default-features = false, features = [ + "use_pem", + "rust_crypto", +], optional = true } rsa = { version = "0.9", optional = true } reqwest = { version = "0.13", features = ["json", "rustls-no-provider"], optional = true } @@ -65,21 +72,17 @@ percent-encoding = { version = "2.0", optional = true } [features] default = ["server-api-aws-lc-rs", "pg-ext-types"] pg-ext-types = ["pg-type-chrono", "pg-type-rust-decimal", "pg-type-serde-json"] -_ring = [ - "dep:ring", - "tokio-rustls/ring", - "dep:rustls-pki-types", - "dep:base64", - "dep:stringprep", - "dep:x509-certificate", -] -_aws-lc-rs = [ - "dep:aws-lc-rs", - "tokio-rustls/aws-lc-rs", + +## Shared: TLS types (provider-less rustls) and SCRAM (pure-Rust RustCrypto) +_tls-scram = [ + "dep:tokio-rustls", "dep:rustls-pki-types", "dep:base64", "dep:stringprep", - "dep:x509-certificate", + "dep:sha2", + "dep:hmac", + "dep:pbkdf2", + "dep:x509-cert", ] server-api = [ "dep:tokio", @@ -92,16 +95,8 @@ server-api = [ "dep:postgres-types", "dep:serde_json", "dep:pg_interval", + "_tls-scram", ] -simple-oidc-validator = [ - "dep:jsonwebtoken", - "dep:rsa", - "dep:reqwest", - "dep:base64", - "dep:serde", -] -server-api-ring = ["server-api", "_ring"] -server-api-aws-lc-rs = ["server-api", "_aws-lc-rs"] client-api = [ "dep:percent-encoding", "dep:pin-project", @@ -110,13 +105,32 @@ client-api = [ "dep:futures", "dep:async-trait", "dep:md5", + "dep:hex", + "dep:rand", + "dep:postgres-types", + "dep:pg_interval", + "dep:serde_json", + "_tls-scram", ] -client-api-ring = ["client-api", "_ring", "dep:rustls-pki-types"] -client-api-aws-lc-rs = ["client-api", "_aws-lc-rs", "dep:rustls-pki-types"] + +## Compatibility aliases: additionally select a default rustls crypto provider +## for the application. With the plain `server-api`/`client-api` features, the +## application chooses its own provider (rustls "bring your own provider"). +server-api-ring = ["server-api", "tokio-rustls/ring"] +server-api-aws-lc-rs = ["server-api", "tokio-rustls/aws-lc-rs"] +client-api-ring = ["client-api", "tokio-rustls/ring"] +client-api-aws-lc-rs = ["client-api", "tokio-rustls/aws-lc-rs"] pg-type-chrono = ["dep:chrono", "postgres-types/with-chrono-0_4"] pg-type-rust-decimal = ["dep:rust_decimal"] pg-type-serde-json = ["dep:serde", "dep:serde_json", "postgres-types/with-serde_json-1"] pg-type-postgis = ["dep:postgis"] +simple-oidc-validator = [ + "dep:jsonwebtoken", + "dep:rsa", + "dep:reqwest", + "dep:base64", + "dep:serde", +] _sqlite = [] _bundled = ["rusqlite/bundled"] @@ -140,7 +154,10 @@ gluesql = { version = "0.20", default-features = false, features = [ ] } ## oauth -jsonwebtoken = { version = "11", features = ["aws_lc_rs"] } +jsonwebtoken = { version = "11", default-features = false, features = [ + "use_pem", + "rust_crypto", +] } rsa = { version = "0.9" } reqwest = { version = "0.13", features = ["json"] } diff --git a/src/api/auth/mod.rs b/src/api/auth/mod.rs index 8d9644ce..c3b40803 100644 --- a/src/api/auth/mod.rs +++ b/src/api/auth/mod.rs @@ -73,7 +73,6 @@ pub struct DefaultServerParameterProvider { pub search_path: String, pub is_superuser: bool, pub default_transaction_read_only: bool, - #[cfg(any(feature = "_aws-lc-rs", feature = "_ring"))] pub scram_iterations: usize, // format settings pub time_zone: String, @@ -98,7 +97,6 @@ impl Default for DefaultServerParameterProvider { search_path: "public".to_owned(), is_superuser: true, default_transaction_read_only: false, - #[cfg(any(feature = "_aws-lc-rs", feature = "_ring"))] scram_iterations: sasl::scram::SCRAM_ITERATIONS, time_zone: format_options.time_zone, @@ -143,7 +141,6 @@ impl ServerParameterProvider for DefaultServerParameterProvider { "default_transaction_read_only".to_owned(), bool_to_string(self.default_transaction_read_only), ); - #[cfg(any(feature = "_aws-lc-rs", feature = "_ring"))] params.insert( "scram_iterations".to_owned(), self.scram_iterations.to_string(), @@ -375,7 +372,6 @@ where pub mod cleartext; pub mod md5pass; pub mod noop; -#[cfg(any(feature = "_aws-lc-rs", feature = "_ring"))] pub mod sasl; #[cfg(feature = "simple-oidc-validator")] pub mod simple_oidc_validator; diff --git a/src/api/auth/sasl/scram.rs b/src/api/auth/sasl/scram.rs index c0591e58..4cc57ed9 100644 --- a/src/api/auth/sasl/scram.rs +++ b/src/api/auth/sasl/scram.rs @@ -1,15 +1,18 @@ use std::borrow::Cow; use std::fmt; use std::fmt::Write; -use std::num::NonZeroU32; use std::ops::BitXor; use std::str::{FromStr, Split}; use std::sync::Arc; use base64::Engine; use base64::engine::general_purpose::STANDARD; -use x509_certificate::SignatureAlgorithm; -use x509_certificate::certificate::CapturedX509Certificate; +use hmac::{Hmac, Mac}; +use pbkdf2::pbkdf2_hmac; +use sha2::{Digest, Sha256, Sha384, Sha512}; +use x509_cert::Certificate; +use x509_cert::der::Decode; +use x509_cert::der::oid::ObjectIdentifier; use crate::api::ClientInfo; /// Re-exports client-side SCRAM authentication types. @@ -21,11 +24,6 @@ use crate::messages::startup::{Authentication, PasswordMessageFamily}; use super::SASLState; -#[cfg(feature = "_aws-lc-rs")] -use aws_lc_rs::{digest, hmac, pbkdf2}; -#[cfg(all(feature = "_ring", not(feature = "_aws-lc-rs")))] -use ring::{digest, hmac, pbkdf2}; - /// Default SCRAM iteration count. pub const SCRAM_ITERATIONS: usize = 4096; @@ -779,23 +777,24 @@ impl<'a> ScamMessageChunker<'a> { fn hi(normalized_password: &[u8], salt: &[u8], iterations: usize) -> Vec { let mut buf = [0u8; 32]; - pbkdf2::derive( - pbkdf2::PBKDF2_HMAC_SHA256, - NonZeroU32::new(iterations as u32).unwrap(), - salt, + pbkdf2_hmac::( normalized_password, + salt, + iterations.try_into().expect("iterations out of u32 range"), &mut buf, ); buf.to_vec() } fn hmac(key: &[u8], msg: &[u8]) -> Vec { - let mac = hmac::Key::new(hmac::HMAC_SHA256, key); - hmac::sign(&mac, msg).as_ref().to_vec() + let mut mac = + as Mac>::new_from_slice(key).expect("HMAC can take key of any size"); + mac.update(msg); + mac.finalize().into_bytes().to_vec() } fn h(msg: &[u8]) -> Vec { - digest::digest(&digest::SHA256, msg).as_ref().to_vec() + Sha256::digest(msg).to_vec() } fn xor(lhs: &[u8], rhs: &[u8]) -> Vec { @@ -805,6 +804,16 @@ fn xor(lhs: &[u8], rhs: &[u8]) -> Vec { .collect() } +/// Signature algorithm OIDs relevant to `tls-server-end-point` channel +/// binding, as defined in RFC 5929 section 4.1 +/// (). +const OID_RSA_SHA1: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.5"); +const OID_RSA_SHA256: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.11"); +const OID_RSA_SHA384: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.12"); +const OID_RSA_SHA512: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.13"); +const OID_ECDSA_SHA256: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.10045.4.3.2"); +const OID_ECDSA_SHA384: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.10045.4.3.3"); + /// Compute signature of server certificate for `tls-server-end-point` channel /// binding. /// @@ -815,23 +824,24 @@ fn xor(lhs: &[u8], rhs: &[u8]) -> Vec { /// 2. use the certificate's algorithm if it's neither md5 or sha-1 /// 3. if the certificate has 0 or more than 1 signature algorithm, the /// behaviour is undefined at the time. -fn compute_cert_signature(cert: &[u8]) -> PgWireResult> { - let certs = CapturedX509Certificate::from_pem_multiple(cert) +fn compute_cert_signature(cert_pem: &[u8]) -> PgWireResult> { + // Hash the DER encoding of the first certificate in the pem data. + let (label, der_bytes) = x509_cert::der::pem::decode_vec(cert_pem) .map_err(|e| PgWireError::ApiError(Box::new(e)))?; - let x509 = &certs[0]; - let raw = x509.constructed_data(); - match x509.signature_algorithm() { - Some(SignatureAlgorithm::RsaSha1) - | Some(SignatureAlgorithm::RsaSha256) - | Some(SignatureAlgorithm::EcdsaSha256) => { - Ok(digest::digest(&digest::SHA256, raw).as_ref().to_vec()) - } - Some(SignatureAlgorithm::RsaSha384) | Some(SignatureAlgorithm::EcdsaSha384) => { - Ok(digest::digest(&digest::SHA384, raw).as_ref().to_vec()) - } - Some(SignatureAlgorithm::RsaSha512) => { - Ok(digest::digest(&digest::SHA512, raw).as_ref().to_vec()) - } + if label != "CERTIFICATE" { + return Err(PgWireError::ApiError(Box::new(std::io::Error::other( + format!("unexpected PEM label: {label}"), + )))); + } + + let certificate = + Certificate::from_der(&der_bytes).map_err(|e| PgWireError::ApiError(Box::new(e)))?; + + match certificate.signature_algorithm().oid { + // md5 and sha-1 based signatures are re-hashed with sha-256 + OID_RSA_SHA1 | OID_RSA_SHA256 | OID_ECDSA_SHA256 => Ok(Sha256::digest(&der_bytes).to_vec()), + OID_RSA_SHA384 | OID_ECDSA_SHA384 => Ok(Sha384::digest(&der_bytes).to_vec()), + OID_RSA_SHA512 => Ok(Sha512::digest(&der_bytes).to_vec()), _ => Err(PgWireError::UnsupportedCertificateSignatureAlgorithm), } } @@ -927,6 +937,27 @@ mod tests { ); } + #[test] + fn test_compute_cert_signature_with_rsa_sha256_cert() { + // examples/ssl/server.crt is signed with sha256WithRSAEncryption, so + // the tls-server-end-point hash must be SHA-256 over its DER data. + let pem = std::fs::read("examples/ssl/server.crt").unwrap(); + let signature = compute_cert_signature(&pem).unwrap(); + + let (label, der) = x509_cert::der::pem::decode_vec(&pem).unwrap(); + assert_eq!(label, "CERTIFICATE"); + assert_eq!(signature, Sha256::digest(der).to_vec()); + assert_eq!(signature.len(), 32); + } + + #[test] + fn test_compute_cert_signature_rejects_non_certificate_pem() { + let err = compute_cert_signature( + b"-----BEGIN PRIVATE KEY-----\nAAAA\n-----END PRIVATE KEY-----\n", + ); + assert!(err.is_err()); + } + #[cfg(feature = "client-api")] #[test] fn test_auth_roundtrip() -> PgWireClientResult<()> { diff --git a/src/api/mod.rs b/src/api/mod.rs index 781e9afb..b57f25e6 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -10,7 +10,6 @@ use bytes::Bytes; use futures::channel::oneshot; use futures::lock::Mutex; pub use postgres_types::Type; -#[cfg(any(feature = "_ring", feature = "_aws-lc-rs"))] use rustls_pki_types::CertificateDer; use crate::error::PgWireError; @@ -168,11 +167,9 @@ pub trait ClientInfo { fn session_extensions(&self) -> &SessionExtensions; /// Returns the TLS SNI server name, if available. - #[cfg(any(feature = "_ring", feature = "_aws-lc-rs"))] fn sni_server_name(&self) -> Option<&str>; /// Returns the client TLS certificates, if available. - #[cfg(any(feature = "_ring", feature = "_aws-lc-rs"))] fn client_certificates<'a>(&self) -> Option<&[CertificateDer<'a>]>; } @@ -213,7 +210,6 @@ pub struct DefaultClient { /// Connection metadata key-value pairs. pub metadata: HashMap, /// The TLS SNI server name, if using TLS. - #[cfg(any(feature = "_ring", feature = "_aws-lc-rs"))] pub sni_server_name: Option, /// In-memory portal and prepared statement store. pub portal_store: store::MemPortalStore, @@ -274,12 +270,10 @@ impl ClientInfo for DefaultClient { self.transaction_status = new_status } - #[cfg(any(feature = "_ring", feature = "_aws-lc-rs"))] fn sni_server_name(&self) -> Option<&str> { self.sni_server_name.as_deref() } - #[cfg(any(feature = "_ring", feature = "_aws-lc-rs"))] fn client_certificates<'a>(&self) -> Option<&[CertificateDer<'a>]> { None } @@ -296,7 +290,6 @@ impl DefaultClient { state: PgWireConnectionState::default(), transaction_status: TransactionStatus::Idle, metadata: HashMap::new(), - #[cfg(any(feature = "_ring", feature = "_aws-lc-rs"))] sni_server_name: None, portal_store: store::MemPortalStore::new(), session_extensions: SessionExtensions::new(), diff --git a/src/lib.rs b/src/lib.rs index 6de084d5..d60e65e1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -73,14 +73,23 @@ //! Server API (default): //! //! - `server-api-aws-lc-rs` *(enabled by default)*: the full server-side API -//! with `aws-lc-rs` as the TLS/crypto backend. -//! - `server-api-ring`: same as above but using `ring` as the crypto backend. +//! with `aws-lc-rs` installed as the default rustls crypto provider. +//! - `server-api-ring`: same as above but using `ring` as the rustls crypto +//! provider. +//! - `server-api`: the server-side API without selecting a rustls crypto +//! provider. SCRAM authentication is always available (implemented in pure +//! Rust with the RustCrypto crates); for TLS your application picks the +//! rustls provider itself, either by enabling a provider feature on your own +//! `rustls`/`tokio-rustls` dependency or by installing a process-wide default +//! with `rustls::crypto::CryptoProvider::install_default`. //! //! Client API: //! //! - `client-api-aws-lc-rs` / `client-api-ring`: the client-side API for -//! building proxies and protocol-level tooling, with the matching crypto -//! backend. +//! building proxies and protocol-level tooling, with the matching rustls +//! crypto provider. +//! - `client-api`: the client-side API without selecting a rustls crypto +//! provider (see `server-api` above). //! //! Data types: //! diff --git a/src/tokio/client.rs b/src/tokio/client.rs index d497f96c..ca2357b7 100644 --- a/src/tokio/client.rs +++ b/src/tokio/client.rs @@ -9,13 +9,11 @@ use std::task::{Context, Poll}; use futures::{Sink, SinkExt, Stream, StreamExt}; use pin_project::pin_project; -#[cfg(any(feature = "_ring", feature = "_aws-lc-rs"))] use rustls_pki_types::ServerName; use tokio::io::{AsyncRead, AsyncWrite}; use tokio::net::TcpStream; #[cfg(unix)] use tokio::net::UnixStream; -#[cfg(any(feature = "_ring", feature = "_aws-lc-rs"))] use tokio_rustls::client::TlsStream; use tokio_util::codec::{Decoder, Encoder, Framed}; @@ -86,7 +84,6 @@ pub struct PgWireClient { transaction_status: TransactionStatus, /// TLS connector retained so [`PgWireClient::cancel`] can open a second /// secured connection to the same server. - #[cfg(any(feature = "_ring", feature = "_aws-lc-rs"))] tls_connector: Option, } @@ -162,7 +159,6 @@ impl PgWireClient { { // The TLS connector is retained so `cancel` can open a second secured // connection later. When TLS is disabled there is no field to store. - #[cfg(any(feature = "_ring", feature = "_aws-lc-rs"))] let tls_connector_for_cancel = tls_connector.clone(); let socket = connect_socket(&config, tls_connector).await?; @@ -172,7 +168,6 @@ impl PgWireClient { config: config.clone(), server_information: ServerInformation::default(), transaction_status: TransactionStatus::Idle, - #[cfg(any(feature = "_ring", feature = "_aws-lc-rs"))] tls_connector: tls_connector_for_cancel, }; @@ -223,12 +218,7 @@ impl PgWireClient { /// Returns an error only if the second connection itself could not be /// established or the cancel message could not be written. pub async fn cancel(&self) -> PgWireClientResult<()> { - // TLS connector is only stored when a TLS backend is enabled; without - // TLS the cancel connection is always plaintext. - #[cfg(any(feature = "_ring", feature = "_aws-lc-rs"))] let tls_connector = self.tls_connector.clone(); - #[cfg(not(any(feature = "_ring", feature = "_aws-lc-rs")))] - let tls_connector: Option = None; let mut socket = connect_socket(&self.config, tls_connector).await?; @@ -315,7 +305,6 @@ impl Stream for PgWireClient { #[pin_project(project = ClientSocketProj)] pub enum ClientSocket { Plain(#[pin] TcpStream), - #[cfg(any(feature = "_ring", feature = "_aws-lc-rs"))] Secure(#[pin] Box>), #[cfg(unix)] Unix(#[pin] UnixStream), @@ -329,7 +318,6 @@ impl AsyncRead for ClientSocket { ) -> Poll> { match self.project() { ClientSocketProj::Plain(socket) => socket.poll_read(cx, buf), - #[cfg(any(feature = "_ring", feature = "_aws-lc-rs"))] ClientSocketProj::Secure(tls_socket) => tls_socket.poll_read(cx, buf), #[cfg(unix)] ClientSocketProj::Unix(socket) => socket.poll_read(cx, buf), @@ -345,7 +333,6 @@ impl AsyncWrite for ClientSocket { ) -> Poll> { match self.project() { ClientSocketProj::Plain(socket) => socket.poll_write(cx, buf), - #[cfg(any(feature = "_ring", feature = "_aws-lc-rs"))] ClientSocketProj::Secure(tls_socket) => tls_socket.poll_write(cx, buf), #[cfg(unix)] ClientSocketProj::Unix(tls_socket) => tls_socket.poll_write(cx, buf), @@ -355,7 +342,6 @@ impl AsyncWrite for ClientSocket { fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { match self.project() { ClientSocketProj::Plain(socket) => socket.poll_flush(cx), - #[cfg(any(feature = "_ring", feature = "_aws-lc-rs"))] ClientSocketProj::Secure(tls_socket) => tls_socket.poll_flush(cx), #[cfg(unix)] ClientSocketProj::Unix(tls_socket) => tls_socket.poll_flush(cx), @@ -368,7 +354,6 @@ impl AsyncWrite for ClientSocket { ) -> Poll> { match self.project() { ClientSocketProj::Plain(socket) => socket.poll_shutdown(cx), - #[cfg(any(feature = "_ring", feature = "_aws-lc-rs"))] ClientSocketProj::Secure(tls_socket) => tls_socket.poll_shutdown(cx), #[cfg(unix)] ClientSocketProj::Unix(tls_socket) => tls_socket.poll_shutdown(cx), @@ -376,7 +361,6 @@ impl AsyncWrite for ClientSocket { } } -#[cfg(any(feature = "_ring", feature = "_aws-lc-rs"))] async fn connect_tls( socket: TcpStream, config: &Config, @@ -402,7 +386,6 @@ async fn connect_tls( Ok(ClientSocket::Secure(Box::new(tls_stream))) } -#[cfg(any(feature = "_ring", feature = "_aws-lc-rs"))] pub(crate) async fn ssl_handshake( socket: TcpStream, config: &Config, @@ -455,15 +438,6 @@ pub(crate) async fn ssl_handshake( } } -#[cfg(not(any(feature = "_ring", feature = "_aws-lc-rs")))] -pub(crate) async fn ssl_handshake( - socket: ClientSocket, - _config: &Config, - _tls_connector: Option, -) -> PgWireClientResult { - Ok(socket) -} - /// Establish a framed connection to the server: TCP (optionually upgraded to /// TLS) or Unix domain socket. Shared by [`PgWireClient::connect`] (which then /// runs startup) and [`PgWireClient::cancel`] (which sends a `CancelRequest` diff --git a/src/tokio/mod.rs b/src/tokio/mod.rs index 286cf7c3..c57017da 100644 --- a/src/tokio/mod.rs +++ b/src/tokio/mod.rs @@ -13,21 +13,10 @@ pub use server::process_socket; pub use server::process_socket_unix; /// Re-export of `tokio_rustls` crate for TLS support. -#[cfg(any(feature = "_ring", feature = "_aws-lc-rs"))] pub use tokio_rustls; /// TLS acceptor type for incoming connections. -#[cfg(any(feature = "_ring", feature = "_aws-lc-rs"))] pub type TlsAcceptor = tokio_rustls::TlsAcceptor; /// TLS connector type for outgoing connections. -#[cfg(any(feature = "_ring", feature = "_aws-lc-rs"))] pub type TlsConnector = tokio_rustls::TlsConnector; -#[cfg(any(feature = "_ring", feature = "_aws-lc-rs"))] pub(super) const POSTGRESQL_ALPN_NAME: &[u8] = b"postgresql"; - -/// Placeholder TLS acceptor when no TLS backend is enabled. -#[cfg(not(any(feature = "_ring", feature = "_aws-lc-rs")))] -pub enum TlsAcceptor {} -/// Placeholder TLS connector when no TLS backend is enabled. -#[cfg(not(any(feature = "_ring", feature = "_aws-lc-rs")))] -pub enum TlsConnector {} diff --git a/src/tokio/server.rs b/src/tokio/server.rs index 66798d58..810c5276 100644 --- a/src/tokio/server.rs +++ b/src/tokio/server.rs @@ -4,14 +4,12 @@ use std::sync::Arc; use std::task::{Context, Poll}; use futures::{SinkExt, StreamExt}; -#[cfg(any(feature = "_ring", feature = "_aws-lc-rs"))] use rustls_pki_types::CertificateDer; use tokio::io::{AsyncRead, AsyncWrite}; use tokio::net::TcpStream; #[cfg(unix)] use tokio::net::UnixStream; use tokio::time::{Duration, sleep}; -#[cfg(any(feature = "_ring", feature = "_aws-lc-rs"))] use tokio_rustls::server::TlsStream; use tokio_util::codec::{Decoder, Encoder, Framed, FramedParts}; @@ -140,12 +138,10 @@ impl ClientInfo for Framed> { .set_transaction_status(new_status); } - #[cfg(any(feature = "_ring", feature = "_aws-lc-rs"))] fn sni_server_name(&self) -> Option<&str> { self.codec().client_info.sni_server_name() } - #[cfg(any(feature = "_ring", feature = "_aws-lc-rs"))] fn client_certificates<'a>(&self) -> Option<&[CertificateDer<'a>]> { // `process_socket` wraps the negotiated stream in `MaybeTls`, so the // connection is a `MaybeTls`, not a bare `TlsStream`. @@ -406,7 +402,6 @@ async fn peek_for_sslrequest( } } -#[cfg(any(feature = "_ring", feature = "_aws-lc-rs"))] fn check_alpn_for_direct_ssl(tls_socket: &TlsStream) -> Result<(), io::Error> { let (_, the_conn) = tls_socket.get_ref(); let mut accept = false; @@ -433,7 +428,6 @@ pub enum MaybeTls { Plain(TcpStream), #[cfg(unix)] Unix(UnixStream), - #[cfg(any(feature = "_ring", feature = "_aws-lc-rs"))] Tls(Box>), } @@ -443,7 +437,6 @@ macro_rules! maybe_tls { MaybeTls::Plain(io) => Pin::new(io).$poll_x($($args),*), #[cfg(unix)] MaybeTls::Unix(io) => Pin::new(io).$poll_x($($args),*), - #[cfg(any(feature = "_ring", feature = "_aws-lc-rs"))] MaybeTls::Tls(io) => Pin::new(io).$poll_x($($args),*), } }; @@ -507,7 +500,6 @@ pub async fn negotiate_tls( return Ok(Some(socket)); } - #[cfg(any(feature = "_ring", feature = "_aws-lc-rs"))] if let Some(tls_acceptor) = tls_acceptor { // mention the use of ssl let mut client_info = DefaultClient::new(addr, true); @@ -662,7 +654,13 @@ where Ok(()) } -#[cfg(all(test, any(feature = "_ring", feature = "_aws-lc-rs")))] +/// These tests build rustls configs, which requires a default crypto provider, +/// so they only run when a provider-backed feature (`server-api-ring` or +/// `server-api-aws-lc-rs`) is selected. +#[cfg(all( + test, + any(feature = "server-api-ring", feature = "server-api-aws-lc-rs") +))] mod tests { use super::*; use std::fs::File; @@ -804,11 +802,11 @@ mod tests { // The default provider is process-global and install-once; another TLS // test in this binary may have installed it already, so tolerate `Err`. - #[cfg(feature = "_aws-lc-rs")] + #[cfg(feature = "server-api-aws-lc-rs")] let _ = CryptoProvider::install_default( tokio_rustls::rustls::crypto::aws_lc_rs::default_provider(), ); - #[cfg(feature = "_ring")] + #[cfg(feature = "server-api-ring")] let _ = CryptoProvider::install_default(tokio_rustls::rustls::crypto::ring::default_provider()); @@ -920,11 +918,11 @@ mod tests { use std::net::SocketAddr; use tokio::net::{TcpListener, TcpStream}; - #[cfg(feature = "_aws-lc-rs")] + #[cfg(feature = "server-api-aws-lc-rs")] let _ = CryptoProvider::install_default( tokio_rustls::rustls::crypto::aws_lc_rs::default_provider(), ); - #[cfg(feature = "_ring")] + #[cfg(feature = "server-api-ring")] let _ = CryptoProvider::install_default(tokio_rustls::rustls::crypto::ring::default_provider());