diff --git a/ylong_http_client/src/async_impl/client.rs b/ylong_http_client/src/async_impl/client.rs index b505020ddddce7e400560e771350c4bbdc3a643c..03cd8c458ef1d5ba4f6c9a5b1e90e41ffc4d7cfb 100644 --- a/ylong_http_client/src/async_impl/client.rs +++ b/ylong_http_client/src/async_impl/client.rs @@ -800,6 +800,20 @@ impl ClientBuilder { self } + /// Stores the keying material to SSLKEYLOGFILE. + /// + /// # Examples + /// + /// ``` + /// use ylong_http_client::async_impl::ClientBuilder; + /// + /// let builder = ClientBuilder::new().store_keylog_file(); + /// ``` + pub fn store_keylog_file(mut self) -> Self { + self.tls = self.tls.store_keylog(); + self + } + /// Loads trusted root certificates from a file. The file should contain a /// sequence of PEM-formatted CA certificates. /// diff --git a/ylong_http_client/src/util/c_openssl/adapter.rs b/ylong_http_client/src/util/c_openssl/adapter.rs index d2d5820a481c23c28f1685f2f25a0bc14ed9f824..39d1aa8a04d35fda57b822f673dc4f58f65dbd76 100644 --- a/ylong_http_client/src/util/c_openssl/adapter.rs +++ b/ylong_http_client/src/util/c_openssl/adapter.rs @@ -331,6 +331,14 @@ impl TlsConfigBuilder { self } + pub(crate) fn store_keylog(mut self) -> Self { + self.inner = self.inner.map(|mut builder| { + builder.set_keylog_callback(); + builder + }); + self + } + /// Controls the use of TLS server name indication. /// /// Defaults to `true` -- sets sni. diff --git a/ylong_http_client/src/util/c_openssl/ffi/callback.rs b/ylong_http_client/src/util/c_openssl/ffi/callback.rs index 04d133c1eac3d65cdf0f271fc47625175ec39090..b682fb0894d79db76f820b364da9658ac8f87733 100644 --- a/ylong_http_client/src/util/c_openssl/ffi/callback.rs +++ b/ylong_http_client/src/util/c_openssl/ffi/callback.rs @@ -11,8 +11,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::ffi::{c_int, c_void}; +use std::ffi::{c_char, c_int, c_void, CStr}; +use std::io::Write; +use crate::util::c_openssl::ffi::ssl::SSL; use crate::util::c_openssl::ffi::x509::X509_STORE_CTX; use crate::util::c_openssl::foreign::ForeignRef; use crate::util::c_openssl::x509::X509StoreContextRef; @@ -26,3 +28,22 @@ pub(crate) extern "C" fn cert_verify(ctx: *mut X509_STORE_CTX, arg: *mut c_void) verifier.verify(&ServerCerts::new(ctx)) as c_int } } + +pub(crate) extern "C" fn ssl_ctx_keylog_cb_func(_ssl: *const SSL, line: *const c_char) { + if let Some(path) = std::env::var_os("SSLKEYLOGFILE") { + let mut file = std::fs::OpenOptions::new() + .create(true) + .append(true) + .open(path) + .unwrap(); + + let data = unsafe { CStr::from_ptr(line).to_bytes() }; + + let mut line = Vec::with_capacity(data.len() + 1); + line.extend_from_slice(data); + line.push(b'\n'); + + file.write_all(&line[..]).ok(); + file.flush().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 cd5c952c7986afad569c445a65e3d192fd72528b..0f1fb22d41f3fa2b3b91461e7bbf51d7f6196bbf 100644 --- a/ylong_http_client/src/util/c_openssl/ffi/ssl.rs +++ b/ylong_http_client/src/util/c_openssl/ffi/ssl.rs @@ -125,6 +125,11 @@ extern "C" { arg: *mut c_void, ); + pub(crate) fn SSL_CTX_set_keylog_callback( + ctx: *mut SSL_CTX, + callback: Option, + ); + #[cfg(feature = "c_boringssl")] pub(crate) fn SSL_CTX_set_min_proto_version( ctx: *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 c23bd612bd1d37068f3632d113f8240364b02c85..682be09f6543edca9c2779274f0cffd1079a3f8e 100644 --- a/ylong_http_client/src/util/c_openssl/ssl/ctx.rs +++ b/ylong_http_client/src/util/c_openssl/ssl/ctx.rs @@ -29,15 +29,15 @@ use crate::util::c_openssl::error::ErrorStack; use crate::util::c_openssl::ffi::ssl::SSL_CTX_ctrl; use crate::util::c_openssl::ffi::ssl::{ SSL_CTX_load_verify_locations, SSL_CTX_new, SSL_CTX_set_alpn_protos, SSL_CTX_set_cert_store, - SSL_CTX_set_cert_verify_callback, SSL_CTX_set_cipher_list, SSL_CTX_up_ref, - SSL_CTX_use_certificate_chain_file, SSL_CTX_use_certificate_file, SSL_CTX, + SSL_CTX_set_cert_verify_callback, SSL_CTX_set_cipher_list, SSL_CTX_set_keylog_callback, + SSL_CTX_up_ref, SSL_CTX_use_certificate_chain_file, SSL_CTX_use_certificate_file, SSL_CTX, }; #[cfg(feature = "c_boringssl")] use crate::util::c_openssl::ffi::ssl::{ SSL_CTX_set1_sigalgs_list, SSL_CTX_set_max_proto_version, SSL_CTX_set_min_proto_version, }; use crate::util::c_openssl::foreign::{Foreign, ForeignRef}; -use crate::util::c_openssl::{cert_verify, check_ptr, check_ret, ssl_init}; +use crate::util::c_openssl::{cert_verify, check_ptr, check_ret, ssl_ctx_keylog_cb_func, ssl_init}; use crate::util::config::tls::DefaultCertVerifier; #[cfg(feature = "__c_openssl")] @@ -266,6 +266,13 @@ impl SslContextBuilder { } } + pub(crate) fn set_keylog_callback(&mut self) { + let ptr = self.as_ptr_mut(); + unsafe { + SSL_CTX_set_keylog_callback(ptr, Some(ssl_ctx_keylog_cb_func)); + } + } + pub(crate) fn set_cert_store(&mut self, cert_store: X509Store) { let ptr = self.as_ptr_mut(); unsafe {