diff --git a/.bleep b/.bleep index 220b9e9..6efaac4 100644 --- a/.bleep +++ b/.bleep @@ -1 +1 @@ -b01a9bc71ff892b2fdbb47f6bb3f9eac88907435 \ No newline at end of file +aadd07a5b3064b0fbdf57c8c02a5ef7b65b5fc03 \ No newline at end of file diff --git a/pingora-core/Cargo.toml b/pingora-core/Cargo.toml index c5bce77..6efad9a 100644 --- a/pingora-core/Cargo.toml +++ b/pingora-core/Cargo.toml @@ -79,6 +79,7 @@ jemallocator = "0.5" [features] default = ["openssl"] -openssl = ["pingora-openssl"] -boringssl = ["pingora-boringssl"] -patched_http1 = [] \ No newline at end of file +openssl = ["pingora-openssl", "some_tls"] +boringssl = ["pingora-boringssl", "some_tls"] +patched_http1 = [] +some_tls = [] \ No newline at end of file diff --git a/pingora-core/src/connectors/http/mod.rs b/pingora-core/src/connectors/http/mod.rs index c399530..33c5e01 100644 --- a/pingora-core/src/connectors/http/mod.rs +++ b/pingora-core/src/connectors/http/mod.rs @@ -95,6 +95,7 @@ impl Connector { } #[cfg(test)] +#[cfg(feature = "some_tls")] mod tests { use super::*; use crate::protocols::http::v1::client::HttpSession as Http1Session; diff --git a/pingora-core/src/connectors/http/v1.rs b/pingora-core/src/connectors/http/v1.rs index 66f7bbb..fb5dfd0 100644 --- a/pingora-core/src/connectors/http/v1.rs +++ b/pingora-core/src/connectors/http/v1.rs @@ -103,6 +103,7 @@ mod tests { } #[tokio::test] + #[cfg(feature = "some_tls")] async fn test_connect_tls() { let connector = Connector::new(None); let peer = HttpPeer::new(("1.1.1.1", 443), true, "one.one.one.one".into()); diff --git a/pingora-core/src/connectors/http/v2.rs b/pingora-core/src/connectors/http/v2.rs index 05b3072..433bc4b 100644 --- a/pingora-core/src/connectors/http/v2.rs +++ b/pingora-core/src/connectors/http/v2.rs @@ -460,6 +460,7 @@ mod tests { use crate::upstreams::peer::HttpPeer; #[tokio::test] + #[cfg(feature = "some_tls")] async fn test_connect_h2() { let connector = Connector::new(None); let mut peer = HttpPeer::new(("1.1.1.1", 443), true, "one.one.one.one".into()); @@ -472,6 +473,7 @@ mod tests { } #[tokio::test] + #[cfg(feature = "some_tls")] async fn test_connect_h1() { let connector = Connector::new(None); let mut peer = HttpPeer::new(("1.1.1.1", 443), true, "one.one.one.one".into()); @@ -497,6 +499,7 @@ mod tests { } #[tokio::test] + #[cfg(feature = "some_tls")] async fn test_h2_single_stream() { let connector = Connector::new(None); let mut peer = HttpPeer::new(("1.1.1.1", 443), true, "one.one.one.one".into()); @@ -528,6 +531,7 @@ mod tests { } #[tokio::test] + #[cfg(feature = "some_tls")] async fn test_h2_multiple_stream() { let connector = Connector::new(None); let mut peer = HttpPeer::new(("1.1.1.1", 443), true, "one.one.one.one".into()); diff --git a/pingora-core/src/connectors/mod.rs b/pingora-core/src/connectors/mod.rs index 09ed01a..2d4584c 100644 --- a/pingora-core/src/connectors/mod.rs +++ b/pingora-core/src/connectors/mod.rs @@ -365,6 +365,7 @@ fn test_reusable_stream(stream: &mut Stream) -> bool { } #[cfg(test)] +#[cfg(feature = "some_tls")] mod tests { use pingora_error::ErrorType; diff --git a/pingora-core/src/connectors/tls.rs b/pingora-core/src/connectors/tls.rs index 8a6bd63..01dd8b3 100644 --- a/pingora-core/src/connectors/tls.rs +++ b/pingora-core/src/connectors/tls.rs @@ -17,8 +17,8 @@ use pingora_error::{Error, ErrorType::*, OrErr, Result}; use std::sync::{Arc, Once}; use super::ConnectorOptions; -use crate::protocols::ssl::client::handshake; -use crate::protocols::ssl::SslStream; +use crate::protocols::tls::client::handshake; +use crate::protocols::tls::SslStream; use crate::protocols::IO; use crate::tls::ext::{ add_host, clear_error_stack, ssl_add_chain_cert, ssl_set_groups_list, diff --git a/pingora-core/src/lib.rs b/pingora-core/src/lib.rs index 7a70d56..fbc3394 100644 --- a/pingora-core/src/lib.rs +++ b/pingora-core/src/lib.rs @@ -58,8 +58,8 @@ pub use pingora_boringssl as tls; #[cfg(all(not(feature = "boringssl"), feature = "openssl"))] pub use pingora_openssl as tls; -#[cfg(all(not(feature = "boringssl"), not(feature = "openssl")))] -pub mod tls; +#[cfg(not(feature = "some_tls"))] +pub use protocols::tls::dummy_tls as tls; pub mod prelude { pub use crate::server::configuration::Opt; diff --git a/pingora-core/src/listeners/mod.rs b/pingora-core/src/listeners/mod.rs index cc8edb8..cb6e2c6 100644 --- a/pingora-core/src/listeners/mod.rs +++ b/pingora-core/src/listeners/mod.rs @@ -26,7 +26,7 @@ use std::{fs::Permissions, sync::Arc}; use l4::{ListenerEndpoint, Stream as L4Stream}; use tls::Acceptor; -pub use crate::protocols::ssl::server::TlsAccept; +pub use crate::protocols::tls::server::TlsAccept; pub use l4::{ServerAddress, TcpSocketOptions}; pub use tls::{TlsSettings, ALPN}; @@ -213,6 +213,7 @@ mod test { } #[tokio::test] + #[cfg(feature = "some_tls")] async fn test_listen_tls() { use tokio::io::AsyncReadExt; diff --git a/pingora-core/src/listeners/tls.rs b/pingora-core/src/listeners/tls.rs index 1dd63d4..55a7139 100644 --- a/pingora-core/src/listeners/tls.rs +++ b/pingora-core/src/listeners/tls.rs @@ -16,14 +16,14 @@ use log::debug; use pingora_error::{ErrorType, OrErr, Result}; use std::ops::{Deref, DerefMut}; -use crate::protocols::ssl::{ +use crate::protocols::tls::{ server::{handshake, handshake_with_callback, TlsAcceptCallbacks}, SslStream, }; use crate::protocols::IO; use crate::tls::ssl::{SslAcceptor, SslAcceptorBuilder, SslFiletype, SslMethod}; -pub use crate::protocols::ssl::ALPN; +pub use crate::protocols::tls::ALPN; pub const TLS_CONF_ERR: ErrorType = ErrorType::Custom("TLSConfigError"); diff --git a/pingora-core/src/protocols/digest.rs b/pingora-core/src/protocols/digest.rs index e080a89..3150306 100644 --- a/pingora-core/src/protocols/digest.rs +++ b/pingora-core/src/protocols/digest.rs @@ -22,7 +22,7 @@ use once_cell::sync::OnceCell; use super::l4::ext::{get_recv_buf, get_tcp_info, TCP_INFO}; use super::l4::socket::SocketAddr; use super::raw_connect::ProxyDigest; -use super::ssl::digest::SslDigest; +use super::tls::digest::SslDigest; /// The information can be extracted from a connection #[derive(Clone, Debug, Default)] diff --git a/pingora-core/src/protocols/mod.rs b/pingora-core/src/protocols/mod.rs index 32695e1..fb30992 100644 --- a/pingora-core/src/protocols/mod.rs +++ b/pingora-core/src/protocols/mod.rs @@ -18,14 +18,14 @@ mod digest; pub mod http; pub mod l4; pub mod raw_connect; -pub mod ssl; +pub mod tls; pub use digest::{ Digest, GetProxyDigest, GetSocketDigest, GetTimingDigest, ProtoDigest, SocketDigest, TimingDigest, }; pub use l4::ext::TcpKeepalive; -pub use ssl::ALPN; +pub use tls::ALPN; use async_trait::async_trait; use std::fmt::Debug; @@ -53,7 +53,7 @@ pub trait Ssl { } /// Return the [`ssl::SslDigest`] for logging - fn get_ssl_digest(&self) -> Option> { + fn get_ssl_digest(&self) -> Option> { None } diff --git a/pingora-core/src/protocols/ssl/client.rs b/pingora-core/src/protocols/tls/client.rs similarity index 100% rename from pingora-core/src/protocols/ssl/client.rs rename to pingora-core/src/protocols/tls/client.rs diff --git a/pingora-core/src/protocols/ssl/digest.rs b/pingora-core/src/protocols/tls/digest.rs similarity index 100% rename from pingora-core/src/protocols/ssl/digest.rs rename to pingora-core/src/protocols/tls/digest.rs diff --git a/pingora-core/src/protocols/tls/dummy_tls/mod.rs b/pingora-core/src/protocols/tls/dummy_tls/mod.rs new file mode 100644 index 0000000..9a841d6 --- /dev/null +++ b/pingora-core/src/protocols/tls/dummy_tls/mod.rs @@ -0,0 +1,805 @@ +// Copyright 2024 Cloudflare, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! This module contains a dummy TLS implementation for the scenarios where real TLS +//! implementations are unavailable. + +macro_rules! impl_display { + ($ty:ty) => { + impl std::fmt::Display for $ty { + fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { + Ok(()) + } + } + }; +} + +macro_rules! impl_deref { + ($from:ty => $to:ty) => { + impl std::ops::Deref for $from { + type Target = $to; + fn deref(&self) -> &$to { + unimplemented!(); + } + } + impl std::ops::DerefMut for $from { + fn deref_mut(&mut self) -> &mut $to { + unimplemented!(); + } + } + }; +} + +pub mod ssl { + use super::error::ErrorStack; + use super::x509::verify::X509VerifyParamRef; + use super::x509::{X509VerifyResult, X509}; + + /// An error returned from an ALPN selection callback. + pub struct AlpnError; + impl AlpnError { + /// Terminate the handshake with a fatal alert. + pub const ALERT_FATAL: AlpnError = Self {}; + + /// Do not select a protocol, but continue the handshake. + pub const NOACK: AlpnError = Self {}; + } + + /// A type which allows for configuration of a client-side TLS session before connection. + pub struct ConnectConfiguration; + impl_deref! {ConnectConfiguration => SslRef} + impl ConnectConfiguration { + /// Configures the use of Server Name Indication (SNI) when connecting. + pub fn set_use_server_name_indication(&mut self, _use_sni: bool) { + unimplemented!(); + } + + /// Configures the use of hostname verification when connecting. + pub fn set_verify_hostname(&mut self, _verify_hostname: bool) { + unimplemented!(); + } + + /// Returns an `Ssl` configured to connect to the provided domain. + pub fn into_ssl(self, _domain: &str) -> Result { + unimplemented!(); + } + + /// Like `SslContextBuilder::set_verify`. + pub fn set_verify(&mut self, _mode: SslVerifyMode) { + unimplemented!(); + } + + /// Like `SslContextBuilder::set_alpn_protos`. + pub fn set_alpn_protos(&mut self, _protocols: &[u8]) -> Result<(), ErrorStack> { + unimplemented!(); + } + + /// Returns a mutable reference to the X509 verification configuration. + pub fn param_mut(&mut self) -> &mut X509VerifyParamRef { + unimplemented!(); + } + } + + /// An SSL error. + #[derive(Debug)] + pub struct Error; + impl_display!(Error); + impl Error { + pub fn code(&self) -> ErrorCode { + unimplemented!(); + } + } + + /// An error code returned from SSL functions. + #[derive(PartialEq)] + pub struct ErrorCode(i32); + impl ErrorCode { + /// An error occurred in the SSL library. + pub const SSL: ErrorCode = Self(0); + } + + /// An identifier of a session name type. + pub struct NameType; + impl NameType { + pub const HOST_NAME: NameType = Self {}; + } + + /// The state of an SSL/TLS session. + pub struct Ssl; + impl Ssl { + /// Creates a new `Ssl`. + pub fn new(_ctx: &SslContextRef) -> Result { + unimplemented!(); + } + } + impl_deref! {Ssl => SslRef} + + /// A type which wraps server-side streams in a TLS session. + pub struct SslAcceptor; + impl SslAcceptor { + /// Creates a new builder configured to connect to non-legacy clients. This should + /// generally be considered a reasonable default choice. + pub fn mozilla_intermediate_v5( + _method: SslMethod, + ) -> Result { + unimplemented!(); + } + } + + /// A builder for `SslAcceptor`s. + pub struct SslAcceptorBuilder; + impl SslAcceptorBuilder { + /// Consumes the builder, returning a `SslAcceptor`. + pub fn build(self) -> SslAcceptor { + unimplemented!(); + } + + /// Sets the callback used by a server to select a protocol for Application Layer Protocol + /// Negotiation (ALPN). + pub fn set_alpn_select_callback(&mut self, _callback: F) + where + F: for<'a> Fn(&mut SslRef, &'a [u8]) -> Result<&'a [u8], AlpnError> + + 'static + + Sync + + Send, + { + unimplemented!(); + } + + /// Loads a certificate chain from a file. + pub fn set_certificate_chain_file>( + &mut self, + _file: P, + ) -> Result<(), ErrorStack> { + unimplemented!(); + } + + /// Loads the private key from a file. + pub fn set_private_key_file>( + &mut self, + _file: P, + _file_type: SslFiletype, + ) -> Result<(), ErrorStack> { + unimplemented!(); + } + + /// Sets the maximum supported protocol version. + pub fn set_max_proto_version( + &mut self, + _version: Option, + ) -> Result<(), ErrorStack> { + unimplemented!(); + } + } + + /// Reference to an [`SslCipher`]. + pub struct SslCipherRef; + impl SslCipherRef { + /// Returns the name of the cipher. + pub fn name(&self) -> &'static str { + unimplemented!(); + } + } + + /// A type which wraps client-side streams in a TLS session. + pub struct SslConnector; + impl SslConnector { + /// Creates a new builder for TLS connections. + pub fn builder(_method: SslMethod) -> Result { + Ok(SslConnectorBuilder) + } + + /// Returns a structure allowing for configuration of a single TLS session before connection. + pub fn configure(&self) -> Result { + Ok(ConnectConfiguration) + } + + /// Returns a shared reference to the inner raw `SslContext`. + pub fn context(&self) -> &SslContextRef { + &SslContextRef + } + } + + /// A builder for `SslConnector`s. + pub struct SslConnectorBuilder; + impl SslConnectorBuilder { + /// Consumes the builder, returning an `SslConnector`. + pub fn build(self) -> SslConnector { + SslConnector + } + + /// Sets the list of supported ciphers for protocols before TLSv1.3. + pub fn set_cipher_list(&mut self, _cipher_list: &str) -> Result<(), ErrorStack> { + Ok(()) + } + + /// Sets the context’s supported signature algorithms. + pub fn set_sigalgs_list(&mut self, _sigalgs: &str) -> Result<(), ErrorStack> { + Ok(()) + } + + /// Sets the minimum supported protocol version. + pub fn set_min_proto_version( + &mut self, + _version: Option, + ) -> Result<(), ErrorStack> { + Ok(()) + } + + /// Sets the maximum supported protocol version. + pub fn set_max_proto_version( + &mut self, + _version: Option, + ) -> Result<(), ErrorStack> { + Ok(()) + } + + /// Use the default locations of trusted certificates for verification. + pub fn set_default_verify_paths(&mut self) -> Result<(), ErrorStack> { + Ok(()) + } + + /// Loads trusted root certificates from a file. + pub fn set_ca_file>( + &mut self, + _file: P, + ) -> Result<(), ErrorStack> { + Ok(()) + } + + /// Loads a leaf certificate from a file. + pub fn set_certificate_file>( + &mut self, + _file: P, + _file_type: SslFiletype, + ) -> Result<(), ErrorStack> { + Ok(()) + } + + /// Loads the private key from a file. + pub fn set_private_key_file>( + &mut self, + _file: P, + _file_type: SslFiletype, + ) -> Result<(), ErrorStack> { + Ok(()) + } + + /// Sets the TLS key logging callback. + pub fn set_keylog_callback(&mut self, _callback: F) + where + F: Fn(&SslRef, &str) + 'static + Sync + Send, + { + } + } + + /// A context object for TLS streams. + pub struct SslContext; + impl SslContext { + /// Creates a new builder object for an `SslContext`. + pub fn builder(_method: SslMethod) -> Result { + unimplemented!(); + } + } + impl_deref! {SslContext => SslContextRef} + + /// A builder for `SslContext`s. + pub struct SslContextBuilder; + impl SslContextBuilder { + /// Consumes the builder, returning a new `SslContext`. + pub fn build(self) -> SslContext { + unimplemented!(); + } + } + + /// Reference to [`SslContext`] + pub struct SslContextRef; + + /// An identifier of the format of a certificate or key file. + pub struct SslFiletype; + impl SslFiletype { + /// The PEM format. + pub const PEM: SslFiletype = Self {}; + } + + /// A type specifying the kind of protocol an `SslContext`` will speak. + pub struct SslMethod; + impl SslMethod { + /// Support all versions of the TLS protocol. + pub fn tls() -> SslMethod { + Self + } + } + + /// Reference to an [`Ssl`]. + pub struct SslRef; + impl SslRef { + /// Like [`SslContextBuilder::set_verify`]. + pub fn set_verify(&mut self, _mode: SslVerifyMode) { + unimplemented!(); + } + + /// Returns the current cipher if the session is active. + pub fn current_cipher(&self) -> Option<&SslCipherRef> { + unimplemented!(); + } + + /// Sets the host name to be sent to the server for Server Name Indication (SNI). + pub fn set_hostname(&mut self, _hostname: &str) -> Result<(), ErrorStack> { + unimplemented!(); + } + + /// Returns the peer’s certificate, if present. + pub fn peer_certificate(&self) -> Option { + unimplemented!(); + } + + /// Returns the certificate verification result. + pub fn verify_result(&self) -> X509VerifyResult { + unimplemented!(); + } + + /// Returns a string describing the protocol version of the session. + pub fn version_str(&self) -> &'static str { + unimplemented!(); + } + + /// Returns the protocol selected via Application Layer Protocol Negotiation (ALPN). + pub fn selected_alpn_protocol(&self) -> Option<&[u8]> { + unimplemented!(); + } + + /// Returns the servername sent by the client via Server Name Indication (SNI). + pub fn servername(&self, _type_: NameType) -> Option<&str> { + unimplemented!(); + } + } + + /// Options controlling the behavior of certificate verification. + pub struct SslVerifyMode; + impl SslVerifyMode { + /// Verifies that the peer’s certificate is trusted. + pub const PEER: Self = Self {}; + + /// Disables verification of the peer’s certificate. + pub const NONE: Self = Self {}; + } + + /// An SSL/TLS protocol version. + pub struct SslVersion; + impl SslVersion { + /// TLSv1.0 + pub const TLS1: SslVersion = Self {}; + + /// TLSv1.2 + pub const TLS1_2: SslVersion = Self {}; + + /// TLSv1.3 + pub const TLS1_3: SslVersion = Self {}; + } + + /// A standard implementation of protocol selection for Application Layer Protocol Negotiation + /// (ALPN). + pub fn select_next_proto<'a>(_server: &[u8], _client: &'a [u8]) -> Option<&'a [u8]> { + unimplemented!(); + } +} + +pub mod ssl_sys { + pub const X509_V_OK: i32 = 0; + pub const X509_V_ERR_INVALID_CALL: i32 = 69; +} + +pub mod error { + use super::ssl::Error; + + /// Collection of [`Errors`] from OpenSSL. + #[derive(Debug)] + pub struct ErrorStack; + impl_display!(ErrorStack); + impl std::error::Error for ErrorStack {} + impl ErrorStack { + /// Returns the contents of the OpenSSL error stack. + pub fn get() -> ErrorStack { + unimplemented!(); + } + + /// Returns the errors in the stack. + pub fn errors(&self) -> &[Error] { + unimplemented!(); + } + } +} + +pub mod x509 { + use super::asn1::{Asn1IntegerRef, Asn1StringRef, Asn1TimeRef}; + use super::error::ErrorStack; + use super::hash::{DigestBytes, MessageDigest}; + use super::nid::Nid; + + /// An `X509` public key certificate. + #[derive(Debug, Clone)] + pub struct X509; + impl_deref! {X509 => X509Ref} + impl X509 { + /// Deserializes a PEM-encoded X509 structure. + pub fn from_pem(_pem: &[u8]) -> Result { + unimplemented!(); + } + } + + /// A type to destructure and examine an `X509Name`. + pub struct X509NameEntries<'a> { + marker: std::marker::PhantomData<&'a ()>, + } + impl<'a> Iterator for X509NameEntries<'a> { + type Item = &'a X509NameEntryRef; + fn next(&mut self) -> Option<&'a X509NameEntryRef> { + unimplemented!(); + } + } + + /// Reference to `X509NameEntry`. + pub struct X509NameEntryRef; + impl X509NameEntryRef { + pub fn data(&self) -> &Asn1StringRef { + unimplemented!(); + } + } + + /// Reference to `X509Name`. + pub struct X509NameRef; + impl X509NameRef { + /// Returns the name entries by the nid. + pub fn entries_by_nid(&self, _nid: Nid) -> X509NameEntries<'_> { + unimplemented!(); + } + } + + /// Reference to `X509`. + pub struct X509Ref; + impl X509Ref { + /// Returns this certificate’s subject name. + pub fn subject_name(&self) -> &X509NameRef { + unimplemented!(); + } + + /// Returns a digest of the DER representation of the certificate. + pub fn digest(&self, _hash_type: MessageDigest) -> Result { + unimplemented!(); + } + + /// Returns the certificate’s Not After validity period. + pub fn not_after(&self) -> &Asn1TimeRef { + unimplemented!(); + } + + /// Returns this certificate’s serial number. + pub fn serial_number(&self) -> &Asn1IntegerRef { + unimplemented!(); + } + } + + /// The result of peer certificate verification. + pub struct X509VerifyResult; + impl X509VerifyResult { + /// Return the integer representation of an `X509VerifyResult`. + pub fn as_raw(&self) -> i32 { + unimplemented!(); + } + } + + pub mod store { + use super::super::error::ErrorStack; + use super::X509; + + /// A builder type used to construct an `X509Store`. + pub struct X509StoreBuilder; + impl X509StoreBuilder { + /// Returns a builder for a certificate store.. + pub fn new() -> Result { + unimplemented!(); + } + + /// Constructs the `X509Store`. + pub fn build(self) -> X509Store { + unimplemented!(); + } + + /// Adds a certificate to the certificate store. + pub fn add_cert(&mut self, _cert: X509) -> Result<(), ErrorStack> { + unimplemented!(); + } + } + + /// A certificate store to hold trusted X509 certificates. + pub struct X509Store; + impl_deref! {X509Store => X509StoreRef} + + /// Reference to an `X509Store`. + pub struct X509StoreRef; + } + + pub mod verify { + /// Reference to `X509VerifyParam`. + pub struct X509VerifyParamRef; + } +} + +pub mod nid { + /// A numerical identifier for an OpenSSL object. + pub struct Nid; + impl Nid { + pub const COMMONNAME: Nid = Self {}; + pub const ORGANIZATIONNAME: Nid = Self {}; + pub const ORGANIZATIONALUNITNAME: Nid = Self {}; + } +} + +pub mod pkey { + use super::error::ErrorStack; + + /// A public or private key. + #[derive(Clone)] + pub struct PKey { + marker: std::marker::PhantomData, + } + impl std::ops::Deref for PKey { + type Target = PKeyRef; + fn deref(&self) -> &PKeyRef { + unimplemented!(); + } + } + impl std::ops::DerefMut for PKey { + fn deref_mut(&mut self) -> &mut PKeyRef { + unimplemented!(); + } + } + impl PKey { + pub fn private_key_from_pem(_pem: &[u8]) -> Result, ErrorStack> { + unimplemented!(); + } + } + + /// Reference to `PKey`. + pub struct PKeyRef { + marker: std::marker::PhantomData, + } + + /// A tag type indicating that a key has private components. + #[derive(Clone)] + pub enum Private {} + unsafe impl HasPrivate for Private {} + + /// A trait indicating that a key has private components. + pub unsafe trait HasPrivate {} +} + +pub mod hash { + /// A message digest algorithm. + pub struct MessageDigest; + impl MessageDigest { + pub fn sha256() -> MessageDigest { + unimplemented!(); + } + } + + /// The resulting bytes of a digest. + pub struct DigestBytes; + impl AsRef<[u8]> for DigestBytes { + fn as_ref(&self) -> &[u8] { + unimplemented!(); + } + } +} + +pub mod asn1 { + use super::bn::BigNum; + use super::error::ErrorStack; + + /// A reference to an `Asn1Integer`. + pub struct Asn1IntegerRef; + impl Asn1IntegerRef { + /// Converts the integer to a `BigNum`. + pub fn to_bn(&self) -> Result { + unimplemented!(); + } + } + + /// A reference to an `Asn1String`. + pub struct Asn1StringRef; + impl Asn1StringRef { + pub fn as_utf8(&self) -> Result<&str, ErrorStack> { + unimplemented!(); + } + } + + /// Reference to an `Asn1Time` + pub struct Asn1TimeRef; + impl_display! {Asn1TimeRef} +} + +pub mod bn { + use super::error::ErrorStack; + + /// Dynamically sized large number implementation + pub struct BigNum; + impl BigNum { + /// Returns a hexadecimal string representation of `self`. + pub fn to_hex_str(&self) -> Result<&str, ErrorStack> { + unimplemented!(); + } + } +} + +pub mod ext { + use super::error::ErrorStack; + use super::pkey::{HasPrivate, PKeyRef}; + use super::ssl::{Ssl, SslAcceptor, SslRef}; + use super::x509::store::X509StoreRef; + use super::x509::verify::X509VerifyParamRef; + use super::x509::X509Ref; + + /// Add name as an additional reference identifier that can match the peer's certificate + pub fn add_host(_verify_param: &mut X509VerifyParamRef, _host: &str) -> Result<(), ErrorStack> { + unimplemented!(); + } + + /// Set the verify cert store of `_ssl` + pub fn ssl_set_verify_cert_store( + _ssl: &mut SslRef, + _cert_store: &X509StoreRef, + ) -> Result<(), ErrorStack> { + unimplemented!(); + } + + /// Load the certificate into `_ssl` + pub fn ssl_use_certificate(_ssl: &mut SslRef, _cert: &X509Ref) -> Result<(), ErrorStack> { + unimplemented!(); + } + + /// Load the private key into `_ssl` + pub fn ssl_use_private_key(_ssl: &mut SslRef, _key: &PKeyRef) -> Result<(), ErrorStack> + where + T: HasPrivate, + { + unimplemented!(); + } + + /// Clear the error stack + pub fn clear_error_stack() {} + + /// Create a new [Ssl] from &[SslAcceptor] + pub fn ssl_from_acceptor(_acceptor: &SslAcceptor) -> Result { + unimplemented!(); + } + + /// Suspend the TLS handshake when a certificate is needed. + pub fn suspend_when_need_ssl_cert(_ssl: &mut SslRef) { + unimplemented!(); + } + + /// Unblock a TLS handshake after the certificate is set. + pub fn unblock_ssl_cert(_ssl: &mut SslRef) { + unimplemented!(); + } + + /// Whether the TLS error is SSL_ERROR_WANT_X509_LOOKUP + pub fn is_suspended_for_cert(_error: &super::ssl::Error) -> bool { + unimplemented!(); + } + + /// Add the certificate into the cert chain of `_ssl` + pub fn ssl_add_chain_cert(_ssl: &mut SslRef, _cert: &X509Ref) -> Result<(), ErrorStack> { + unimplemented!(); + } + + /// Set renegotiation + pub fn ssl_set_renegotiate_mode_freely(_ssl: &mut SslRef) {} + + /// Set the curves/groups of `_ssl` + pub fn ssl_set_groups_list(_ssl: &mut SslRef, _groups: &str) -> Result<(), ErrorStack> { + unimplemented!(); + } + + /// Sets whether a second keyshare to be sent in client hello when PQ is used. + pub fn ssl_use_second_key_share(_ssl: &mut SslRef, _enabled: bool) {} + + /// Get a mutable SslRef ouf of SslRef, which is a missing functionality even when holding &mut SslStream + /// # Safety + pub unsafe fn ssl_mut(_ssl: &SslRef) -> &mut SslRef { + unimplemented!(); + } +} + +pub mod tokio_ssl { + use std::pin::Pin; + use std::task::{Context, Poll}; + use tokio::io::{AsyncRead, AsyncWrite, ReadBuf}; + + use super::error::ErrorStack; + use super::ssl::{Error, Ssl, SslRef}; + + /// A TLS session over a stream. + #[derive(Debug)] + pub struct SslStream { + marker: std::marker::PhantomData, + } + impl SslStream { + /// Creates a new `SslStream`. + pub fn new(_ssl: Ssl, _stream: S) -> Result { + unimplemented!(); + } + + /// Initiates a client-side TLS handshake. + pub async fn connect(self: Pin<&mut Self>) -> Result<(), Error> { + unimplemented!(); + } + + /// Initiates a server-side TLS handshake. + pub async fn accept(self: Pin<&mut Self>) -> Result<(), Error> { + unimplemented!(); + } + + /// Returns a shared reference to the `Ssl` object associated with this stream. + pub fn ssl(&self) -> &SslRef { + unimplemented!(); + } + + /// Returns a shared reference to the underlying stream. + pub fn get_ref(&self) -> &S { + unimplemented!(); + } + + /// Returns a mutable reference to the underlying stream. + pub fn get_mut(&mut self) -> &mut S { + unimplemented!(); + } + } + impl AsyncRead for SslStream + where + S: AsyncRead + AsyncWrite, + { + fn poll_read( + self: Pin<&mut Self>, + _ctx: &mut Context<'_>, + _buf: &mut ReadBuf<'_>, + ) -> Poll> { + unimplemented!(); + } + } + impl AsyncWrite for SslStream + where + S: AsyncRead + AsyncWrite, + { + fn poll_write( + self: Pin<&mut Self>, + _ctx: &mut Context<'_>, + _buf: &[u8], + ) -> Poll> { + unimplemented!(); + } + + fn poll_flush(self: Pin<&mut Self>, _ctx: &mut Context<'_>) -> Poll> { + unimplemented!(); + } + + fn poll_shutdown( + self: Pin<&mut Self>, + _ctx: &mut Context<'_>, + ) -> Poll> { + unimplemented!(); + } + } +} diff --git a/pingora-core/src/protocols/ssl/mod.rs b/pingora-core/src/protocols/tls/mod.rs similarity index 99% rename from pingora-core/src/protocols/ssl/mod.rs rename to pingora-core/src/protocols/tls/mod.rs index f1ce8b9..b1edf23 100644 --- a/pingora-core/src/protocols/ssl/mod.rs +++ b/pingora-core/src/protocols/tls/mod.rs @@ -18,6 +18,9 @@ pub mod client; pub mod digest; pub mod server; +#[cfg(not(feature = "some_tls"))] +pub mod dummy_tls; + use crate::protocols::digest::TimingDigest; use crate::protocols::{Ssl, UniqueID}; use crate::tls::{self, ssl, tokio_ssl::SslStream as InnerSsl}; diff --git a/pingora-core/src/protocols/ssl/server.rs b/pingora-core/src/protocols/tls/server.rs similarity index 99% rename from pingora-core/src/protocols/ssl/server.rs rename to pingora-core/src/protocols/tls/server.rs index c85846b..1da1d45 100644 --- a/pingora-core/src/protocols/ssl/server.rs +++ b/pingora-core/src/protocols/tls/server.rs @@ -143,6 +143,7 @@ impl ResumableAccept for SslStream } #[tokio::test] +#[cfg(feature = "some_tls")] async fn test_async_cert() { use tokio::io::AsyncReadExt; let acceptor = ssl::SslAcceptor::mozilla_intermediate_v5(ssl::SslMethod::tls()) diff --git a/pingora-core/src/upstreams/peer.rs b/pingora-core/src/upstreams/peer.rs index c4a23a8..fad8471 100644 --- a/pingora-core/src/upstreams/peer.rs +++ b/pingora-core/src/upstreams/peer.rs @@ -36,7 +36,7 @@ use crate::protocols::TcpKeepalive; use crate::tls::x509::X509; use crate::utils::{get_organization_unit, CertKey}; -pub use crate::protocols::ssl::ALPN; +pub use crate::protocols::tls::ALPN; /// The interface to trace the connection pub trait Tracing: Send + Sync + std::fmt::Debug { diff --git a/pingora-core/tests/test_basic.rs b/pingora-core/tests/test_basic.rs index 171f757..9842009 100644 --- a/pingora-core/tests/test_basic.rs +++ b/pingora-core/tests/test_basic.rs @@ -18,6 +18,7 @@ use hyper::Client; use hyperlocal::{UnixClientExt, Uri}; use utils::init; +#[cfg(feature = "some_tls")] #[tokio::test] async fn test_http() { init(); @@ -25,6 +26,7 @@ async fn test_http() { assert_eq!(res.status(), reqwest::StatusCode::OK); } +#[cfg(feature = "some_tls")] #[tokio::test] async fn test_https_http2() { init(); @@ -49,6 +51,7 @@ async fn test_https_http2() { assert_eq!(res.version(), reqwest::Version::HTTP_11); } +#[cfg(feature = "some_tls")] #[tokio::test] async fn test_uds() { init();