From cfc29a7efd5f74828be4d4a0f749179e881368dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=BB=BA=E8=BE=9B?= Date: Wed, 5 Jul 2023 16:01:42 +0800 Subject: [PATCH] =?UTF-8?q?c=5Fopenssl=E9=83=A8=E5=88=86=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E8=A6=86=E7=9B=96=E7=8E=87=E6=8F=90=E5=8D=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 张建辛 --- ylong_http_client/Cargo.toml | 4 +- ylong_http_client/src/async_impl/client.rs | 17 ++ .../src/util/c_openssl/adapter.rs | 152 ++++++++++++------ .../src/util/c_openssl/ffi/ssl.rs | 5 - .../src/util/c_openssl/ssl/ctx.rs | 43 +---- .../src/util/c_openssl/ssl/ssl_base.rs | 2 +- ylong_http_client/src/util/c_openssl/x509.rs | 13 +- ylong_http_client/tests/common/async_utils.rs | 6 +- ylong_http_client/tests/common/mod.rs | 12 +- ylong_http_client/tests/common/sync_utils.rs | 2 - ylong_http_client/tests/sdv_async_http.rs | 2 +- .../tests/sdv_async_https_c_ssl.rs | 2 +- .../tests/sdv_sync_https_c_ssl.rs | 2 +- 13 files changed, 142 insertions(+), 120 deletions(-) diff --git a/ylong_http_client/Cargo.toml b/ylong_http_client/Cargo.toml index 2f9dabe..1efc648 100644 --- a/ylong_http_client/Cargo.toml +++ b/ylong_http_client/Cargo.toml @@ -103,9 +103,9 @@ required-features = ["sync", "http1_1", "tokio_base"] [[test]] name = "sdv_async_https_c_ssl" path = "./tests/sdv_async_https_c_ssl.rs" -required-features = ["async", "http1_1", "c_openssl_1_1", "tokio_base"] +required-features = ["async", "http1_1", "__tls", "tokio_base"] [[test]] name = "sdv_sync_https_c_ssl" path = "./tests/sdv_sync_https_c_ssl.rs" -required-features = ["sync", "http1_1", "c_openssl_1_1", "tokio_base"] +required-features = ["sync", "http1_1", "__tls", "tokio_base"] diff --git a/ylong_http_client/src/async_impl/client.rs b/ylong_http_client/src/async_impl/client.rs index 522a4fb..c58f927 100644 --- a/ylong_http_client/src/async_impl/client.rs +++ b/ylong_http_client/src/async_impl/client.rs @@ -518,6 +518,14 @@ impl ClientBuilder { /// Loads trusted root certificates from a file. The file should contain a /// sequence of PEM-formatted CA certificates. + /// + /// # Examples + /// + /// ``` + /// use ylong_http_client::async_impl::ClientBuilder; + /// + /// let builder = ClientBuilder::new().set_ca_file("ca.crt"); + /// ``` #[cfg(feature = "__tls")] pub fn set_ca_file(mut self, path: &str) -> Self { self.tls = self.tls.set_ca_file(path); @@ -571,6 +579,15 @@ impl ClientBuilder { /// Controls the use of built-in system certificates during certificate validation. /// Default to `true` -- uses built-in system certs. + /// + /// # Examples + /// + /// ``` + /// use ylong_http_client::async_impl::ClientBuilder; + /// + /// let builder = ClientBuilder::new() + /// .tls_built_in_root_certs(false); + /// ``` #[cfg(feature = "__tls")] pub fn tls_built_in_root_certs(mut self, is_use: bool) -> ClientBuilder { self.tls = self.tls.build_in_root_certs(is_use); diff --git a/ylong_http_client/src/util/c_openssl/adapter.rs b/ylong_http_client/src/util/c_openssl/adapter.rs index 4e348b7..5701610 100644 --- a/ylong_http_client/src/util/c_openssl/adapter.rs +++ b/ylong_http_client/src/util/c_openssl/adapter.rs @@ -195,46 +195,6 @@ impl TlsConfigBuilder { self } - /// Sets the leaf certificate. - /// - /// Use `add_extra_chain_cert` to add the remainder of the certificate chain. - /// - /// # Examples - /// - /// ```no_run - /// use ylong_http_client::util::{TlsConfigBuilder, Cert}; - /// - /// let x509 = Cert::from_pem(b"pem-content").unwrap(); - /// let builder = TlsConfigBuilder::new().set_certificate(&x509); - /// ``` - pub fn set_certificate(mut self, cert: &Cert) -> Self { - self.inner = self.inner.set_certificate(cert.as_ref()); - self - } - - /// Appends a certificate to the certificate chain. - /// - /// This chain should contain all certificates necessary to go from the - /// certificate specified by `set_certificate` to a trusted root. - /// - /// This method is based on `openssl::SslContextBuilder::add_extra_chain_cert`. - /// - /// # Examples - /// - /// ```no_run - /// use ylong_http_client::util::{TlsConfigBuilder, Cert}; - /// - /// let root = Cert::from_pem(b"pem-content").unwrap(); - /// let chain = Cert::from_pem(b"pem-content").unwrap(); - /// let builder = TlsConfigBuilder::new() - /// .set_certificate(&root) - /// .add_extra_chain_cert(chain); - /// ``` - pub fn add_extra_chain_cert(mut self, cert: Cert) -> Self { - self.inner = self.inner.add_extra_chain_cert(cert.into_inner()); - self - } - /// Adds custom root certificate. pub fn add_root_certificates(mut self, certs: Certificate) -> Self { for cert in certs.inner { @@ -340,7 +300,7 @@ impl Default for TlsConfigBuilder { /// /// let builder = TlsConfig::builder(); /// ``` -#[derive(Debug, Clone)] +#[derive(Clone)] pub struct TlsConfig(SslContext); impl TlsConfig { @@ -550,7 +510,10 @@ impl Certificate { #[cfg(test)] mod ut_openssl_adapter { - use crate::util::{Cert, TlsConfigBuilder, TlsFileType, TlsVersion}; + use crate::{ + util::{Cert, TlsConfigBuilder, TlsFileType, TlsVersion}, + AlpnProtocol, AlpnProtocolList, Certificate, + }; /// UT test cases for `TlsConfigBuilder::new`. /// @@ -651,32 +614,95 @@ mod ut_openssl_adapter { assert!(builder.is_err()); } - /// UT test cases for `X509::from_pem`. + /// UT test cases for `TlsConfigBuilder::add_root_certificates`. /// /// # Brief - /// 1. Creates a `X509` by calling `X509::from_pem`. + /// 1. Creates a `TlsConfigBuilder` by calling `TlsConfigBuilder::new`. + /// 2. Calls `add_root_certificates`. + /// 3. Provides PEM-formatted certificates. + /// 4. Checks if the result is as expected. + #[test] + fn ut_add_root_certificates() { + let builder = TlsConfigBuilder::new() + .add_root_certificates( + Certificate::from_pem(include_bytes!("../../../tests/file/root-ca.pem")) + .expect("Sets certs error."), + ) + .build(); + assert!(builder.is_ok()); + } + + /// UT test cases for `TlsConfigBuilder::build_in_root_certs`. + /// + /// # Brief + /// 1. Creates a `TlsConfigBuilder` by calling `TlsConfigBuilder::new`. + /// 2. Calls `build_in_root_certs`. + /// 3. Checks if the result is as expected. + #[test] + fn ut_build_in_root_certs() { + let builder = TlsConfigBuilder::new().build_in_root_certs(true).build(); + assert!(builder.is_ok()); + } + + /// UT test cases for `TlsConfigBuilder::set_alpn_proto_list`. + /// + /// # Brief + /// 1. Creates a `TlsConfigBuilder` by calling `TlsConfigBuilder::new`. + /// 2. Calls `set_alpn_proto_list`. + /// 3. Provides `AlpnProtocol`s. + /// 4. Checks if the result is as expected. + #[test] + fn ut_set_alpn_proto_list() { + let builder = TlsConfigBuilder::new() + .set_alpn_proto_list( + AlpnProtocolList::new() + .extend(AlpnProtocol::HTTP11) + .extend(AlpnProtocol::H2), + ) + .build(); + assert!(builder.is_ok()); + } + + /// UT test cases for `TlsConfig::ssl`. + /// + /// # Brief + /// 1. Creates a `TlsConfig` by calling `TlsConfigBuilder::new` and `TlsConfigBuilder::build`. + /// 2. Creates a `TlsSsl` by calling `TlsConfig::ssl`. + /// 3. Calls `TlsSsl::set_sni_verify` and `TlsSsl::into_inner`. + /// 4. Checks if the result is as expected. + #[test] + fn ut_tls_ssl() { + let config = TlsConfigBuilder::new() + .build() + .expect("TlsConfig build error."); + let mut ssl = config.ssl().expect("Ssl build error."); + ssl.set_sni_verify("host name") + .expect("Set SNI verify error."); + let _ssl = ssl.into_inner(); + } + + /// UT test cases for `Cert::from_pem`. + /// + /// # Brief + /// 1. Creates a `Cert` by calling `Cert::from_pem`. /// 2. Provides an invalid pem as argument. /// 3. Checks if the result is as expected. #[test] fn ut_x509_from_pem() { let pem = "(pem-content)"; let x509 = Cert::from_pem(pem.as_bytes()); - // println!("{:?}", x509); assert!(x509.is_err()); let cert = include_bytes!("../../../tests/file/root-ca.pem"); println!("{:?}", std::str::from_utf8(cert).unwrap()); - // let debugged = format!("{:#?}", cert); - // println!("{debugged}"); let x509 = Cert::from_pem(cert); - // println!("{:?}", x509); assert!(x509.is_ok()); } - /// UT test cases for `X509::from_der`. + /// UT test cases for `Cert::from_der`. /// /// # Brief - /// 1. Creates a `X509` by calling `X509::from_der`. + /// 1. Creates a `Cert` by calling `Cert::from_der`. /// 2. Provides an invalid der as argument. /// 3. Checks if the result is as expected. #[test] @@ -685,4 +711,30 @@ mod ut_openssl_adapter { let x509 = Cert::from_der(der.as_bytes()); assert!(x509.is_err()); } + + /// UT test cases for `Cert::stack_from_pem`. + /// + /// # Brief + /// 1. Creates a `Cert` by calling `Cert::stack_from_pem`. + /// 2. Provides pem bytes as argument. + /// 3. Checks if the result is as expected. + #[test] + fn ut_cert_stack_from_der() { + let v = include_bytes!("../../../tests/file/root-ca.pem"); + let x509 = Cert::stack_from_pem(v); + assert!(x509.is_ok()); + } + + /// UT test cases for `Certificate::from_pem`. + /// + /// # Brief + /// 1. Creates a `Certificate` by calling `Certificate::from_pem`. + /// 2. Provides pem bytes as argument. + /// 3. Checks if the result is as expected. + #[test] + fn ut_certificate_from_pem() { + let v = include_bytes!("../../../tests/file/root-ca.pem"); + let certs = Certificate::from_pem(v); + assert!(certs.is_ok()); + } } diff --git a/ylong_http_client/src/util/c_openssl/ffi/ssl.rs b/ylong_http_client/src/util/c_openssl/ffi/ssl.rs index 26717c9..c614044 100644 --- a/ylong_http_client/src/util/c_openssl/ffi/ssl.rs +++ b/ylong_http_client/src/util/c_openssl/ffi/ssl.rs @@ -77,11 +77,6 @@ extern "C" { cert_chain_file: *const c_char, ) -> c_int; - /// Loads the certificate `cert` into ctx.\ - /// The rest of the certificates needed to form the complete certificate chain - /// can be specified using the `SSL_CTX_add_extra_chain_cert` function - pub(crate) fn SSL_CTX_use_certificate(ctx: *mut SSL_CTX, cert: *mut C_X509) -> c_int; - /// Client sets the list of protocols available to be negotiated. pub(crate) fn SSL_CTX_set_alpn_protos( s: *mut SSL_CTX, diff --git a/ylong_http_client/src/util/c_openssl/ssl/ctx.rs b/ylong_http_client/src/util/c_openssl/ssl/ctx.rs index bbf0f98..c984d35 100644 --- a/ylong_http_client/src/util/c_openssl/ssl/ctx.rs +++ b/ylong_http_client/src/util/c_openssl/ssl/ctx.rs @@ -26,8 +26,8 @@ use crate::{ ffi::ssl::{ SSL_CTX_ctrl, SSL_CTX_load_verify_locations, SSL_CTX_new, SSL_CTX_set_alpn_protos, SSL_CTX_set_cert_store, SSL_CTX_set_cipher_list, SSL_CTX_set_ciphersuites, - SSL_CTX_up_ref, SSL_CTX_use_certificate, SSL_CTX_use_certificate_chain_file, - SSL_CTX_use_certificate_file, SSL_CTX, + SSL_CTX_up_ref, SSL_CTX_use_certificate_chain_file, SSL_CTX_use_certificate_file, + SSL_CTX, }, foreign::{Foreign, ForeignRef}, ssl_init, @@ -290,45 +290,6 @@ impl SslContextBuilder { } } - /// Sets the leaf certificate. - /// - /// Use `add_extra_chain_cert` to add the remainder of the certificate chain. - pub(crate) fn set_certificate(self, key: &X509Ref) -> Self { - let ptr = match self.as_ptr() { - Ok(ptr) => ptr, - Err(e) => return SslContextBuilder(Err(e)), - }; - - match check_ret(unsafe { SSL_CTX_use_certificate(ptr, key.as_ptr()) }) { - Ok(_num) => self, - Err(e) => SslContextBuilder(Err(e)), - } - } - - /// Appends a certificate to the certificate chain. - /// - /// This chain should contain all certificates necessary to go from the certificate specified by - /// `set_certificate` to a trusted root. - pub(crate) fn add_extra_chain_cert(self, cert: X509) -> Self { - let ptr = match self.as_ptr() { - Ok(ptr) => ptr, - Err(e) => return SslContextBuilder(Err(e)), - }; - - match check_ret(unsafe { - SSL_CTX_ctrl( - ptr, - SSL_CTRL_EXTRA_CHAIN_CERT, - 0, - cert.as_ptr() as *mut c_void, - ) - } as c_int) - { - Ok(_num) => self, - Err(e) => SslContextBuilder(Err(e)), - } - } - /// Sets the protocols to sent to the server for Application Layer Protocol Negotiation (ALPN). pub(crate) fn set_alpn_protos(self, protocols: &[u8]) -> Self { assert!(protocols.len() <= c_uint::max_value() as usize); diff --git a/ylong_http_client/src/util/c_openssl/ssl/ssl_base.rs b/ylong_http_client/src/util/c_openssl/ssl/ssl_base.rs index d37bc40..4ce3567 100644 --- a/ylong_http_client/src/util/c_openssl/ssl/ssl_base.rs +++ b/ylong_http_client/src/util/c_openssl/ssl/ssl_base.rs @@ -57,7 +57,7 @@ impl Ssl { /// Client connect to Server. /// only `sync` use. - #[allow(dead_code)] + #[cfg(feature = "sync")] pub(crate) fn connect(self, stream: S) -> Result, HandshakeError> where S: Read + Write, diff --git a/ylong_http_client/src/util/c_openssl/x509.rs b/ylong_http_client/src/util/c_openssl/x509.rs index b8dd587..9d0fcfe 100644 --- a/ylong_http_client/src/util/c_openssl/x509.rs +++ b/ylong_http_client/src/util/c_openssl/x509.rs @@ -111,6 +111,13 @@ impl X509VerifyResult { } } +impl fmt::Display for X509VerifyResult { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.write_str(self.error_string()) + } +} + +#[cfg(test)] impl fmt::Debug for X509VerifyResult { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt.debug_struct("X509VerifyResult") @@ -120,12 +127,6 @@ impl fmt::Debug for X509VerifyResult { } } -impl fmt::Display for X509VerifyResult { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.write_str(self.error_string()) - } -} - foreign_type!( type CStruct = X509_STORE; fn drop = X509_STORE_free; diff --git a/ylong_http_client/tests/common/async_utils.rs b/ylong_http_client/tests/common/async_utils.rs index 42374cb..206f921 100644 --- a/ylong_http_client/tests/common/async_utils.rs +++ b/ylong_http_client/tests/common/async_utils.rs @@ -11,8 +11,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -#![cfg(feature = "async")] - use std::sync::Arc; use ylong_http_client::async_impl::Client; @@ -376,7 +374,7 @@ macro_rules! async_client_assertions { } } -#[cfg(feature = "c_openssl_1_1")] +#[cfg(feature = "__tls")] pub fn async_build_https_client(tls_config: &str) -> Arc { let client = ylong_http_client::async_impl::Client::builder() .set_ca_file(tls_config) @@ -385,7 +383,7 @@ pub fn async_build_https_client(tls_config: &str) -> Arc { std::sync::Arc::new(client) } -#[cfg(not(feature = "c_openssl_1_1"))] +#[cfg(not(feature = "__tls"))] pub fn async_build_http_client() -> Arc { let client = ylong_http_client::async_impl::Client::new(); Arc::new(client) diff --git a/ylong_http_client/tests/common/mod.rs b/ylong_http_client/tests/common/mod.rs index 02c7958..5c21e4a 100644 --- a/ylong_http_client/tests/common/mod.rs +++ b/ylong_http_client/tests/common/mod.rs @@ -17,24 +17,24 @@ mod async_utils; #[cfg(feature = "sync")] mod sync_utils; -#[cfg(all(feature = "async", not(feature = "c_openssl_1_1")))] +#[cfg(all(feature = "async", not(feature = "__tls")))] pub use async_utils::async_build_http_client; -#[cfg(all(feature = "async", feature = "c_openssl_1_1"))] +#[cfg(all(feature = "async", feature = "__tls"))] pub use async_utils::async_build_https_client; use tokio::runtime::Runtime; -#[cfg(not(feature = "c_openssl_1_1"))] +#[cfg(not(feature = "__tls"))] use tokio::sync::mpsc::{Receiver, Sender}; /// Server handle. -#[cfg(feature = "c_openssl_1_1")] +#[cfg(feature = "__tls")] pub struct TlsHandle { pub port: u16, } -#[cfg(not(feature = "c_openssl_1_1"))] +#[cfg(not(feature = "__tls"))] pub struct HttpHandle { pub port: u16, @@ -265,7 +265,7 @@ macro_rules! set_server_fn { }; } -#[cfg(feature = "c_openssl_1_1")] +#[cfg(feature = "__tls")] macro_rules! start_tls_server { ($service_fn: ident) => {{ let mut port = 10000; diff --git a/ylong_http_client/tests/common/sync_utils.rs b/ylong_http_client/tests/common/sync_utils.rs index 49d6aa0..5af4264 100644 --- a/ylong_http_client/tests/common/sync_utils.rs +++ b/ylong_http_client/tests/common/sync_utils.rs @@ -11,8 +11,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -#![cfg(feature = "sync")] - #[macro_export] macro_rules! sync_client_test_case { ( diff --git a/ylong_http_client/tests/sdv_async_http.rs b/ylong_http_client/tests/sdv_async_http.rs index 6654ac6..ad7cb5c 100644 --- a/ylong_http_client/tests/sdv_async_http.rs +++ b/ylong_http_client/tests/sdv_async_http.rs @@ -11,7 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#![cfg(all(feature = "async", not(feature = "c_openssl_1_1")))] +#![cfg(all(feature = "async", not(feature = "__tls")))] #[macro_use] mod common; diff --git a/ylong_http_client/tests/sdv_async_https_c_ssl.rs b/ylong_http_client/tests/sdv_async_https_c_ssl.rs index e36faef..3b12022 100644 --- a/ylong_http_client/tests/sdv_async_https_c_ssl.rs +++ b/ylong_http_client/tests/sdv_async_https_c_ssl.rs @@ -11,7 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#![cfg(all(feature = "async", feature = "c_openssl_1_1"))] +#![cfg(all(feature = "async", feature = "__tls"))] #[macro_use] mod common; diff --git a/ylong_http_client/tests/sdv_sync_https_c_ssl.rs b/ylong_http_client/tests/sdv_sync_https_c_ssl.rs index 010a457..ad70088 100644 --- a/ylong_http_client/tests/sdv_sync_https_c_ssl.rs +++ b/ylong_http_client/tests/sdv_sync_https_c_ssl.rs @@ -11,7 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#![cfg(all(feature = "sync", feature = "c_openssl_1_1"))] +#![cfg(all(feature = "sync", feature = "__tls"))] use crate::common::init_test_work_runtime; use common::TlsHandle; -- Gitee