From 738a258496318edb6e264b13b8a6d0dc313795d3 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Sun, 9 Aug 2026 11:22:59 +0900 Subject: refactor(ca-bundle): extract composer/ca_bundle into the shirabe-ca-bundle crate Move `Composer\CaBundle` out of shirabe-external-packages and into its own crate, so the path is `shirabe_ca_bundle::CaBundle` instead of `shirabe_external_packages::composer::ca_bundle::CaBundle`. Co-Authored-By: Claude Opus 5 (1M context) --- Cargo.lock | 5 ++ Cargo.toml | 1 + crates/shirabe-ca-bundle/Cargo.toml | 7 ++ crates/shirabe-ca-bundle/src/ca_bundle.rs | 76 ++++++++++++++++++++++ crates/shirabe-ca-bundle/src/lib.rs | 3 + crates/shirabe-external-packages/src/composer.rs | 2 - .../src/composer/ca_bundle.rs | 3 - .../src/composer/ca_bundle/ca_bundle.rs | 76 ---------------------- crates/shirabe/Cargo.toml | 1 + crates/shirabe/src/util/stream_context_factory.rs | 2 +- crates/shirabe/src/util/tls_helper.rs | 2 +- 11 files changed, 95 insertions(+), 83 deletions(-) create mode 100644 crates/shirabe-ca-bundle/Cargo.toml create mode 100644 crates/shirabe-ca-bundle/src/ca_bundle.rs create mode 100644 crates/shirabe-ca-bundle/src/lib.rs delete mode 100644 crates/shirabe-external-packages/src/composer/ca_bundle.rs delete mode 100644 crates/shirabe-external-packages/src/composer/ca_bundle/ca_bundle.rs diff --git a/Cargo.lock b/Cargo.lock index 543f3dbb..543c1df1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2096,6 +2096,7 @@ dependencies = [ "serde_json", "serial_test", "sha1", + "shirabe-ca-bundle", "shirabe-class-map-generator", "shirabe-external-packages", "shirabe-metadata-minifier", @@ -2117,6 +2118,10 @@ dependencies = [ "url", ] +[[package]] +name = "shirabe-ca-bundle" +version = "0.0.1" + [[package]] name = "shirabe-class-map-generator" version = "0.0.1" diff --git a/Cargo.toml b/Cargo.toml index a6435d88..2ed93005 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ edition = "2024" [workspace.dependencies] shirabe = { path = "crates/shirabe" } +shirabe-ca-bundle = { path = "crates/shirabe-ca-bundle" } shirabe-class-map-generator = { path = "crates/shirabe-class-map-generator" } shirabe-external-packages = { path = "crates/shirabe-external-packages" } shirabe-metadata-minifier = { path = "crates/shirabe-metadata-minifier" } diff --git a/crates/shirabe-ca-bundle/Cargo.toml b/crates/shirabe-ca-bundle/Cargo.toml new file mode 100644 index 00000000..e5608175 --- /dev/null +++ b/crates/shirabe-ca-bundle/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "shirabe-ca-bundle" +version.workspace = true +edition.workspace = true + +[lints] +workspace = true diff --git a/crates/shirabe-ca-bundle/src/ca_bundle.rs b/crates/shirabe-ca-bundle/src/ca_bundle.rs new file mode 100644 index 00000000..3c372cb1 --- /dev/null +++ b/crates/shirabe-ca-bundle/src/ca_bundle.rs @@ -0,0 +1,76 @@ +//! ref: composer/vendor/composer/ca-bundle/src/CaBundle.php + +#[derive(Debug)] +pub struct CaBundle; + +impl CaBundle { + // TODO(plugin): unused for now; kept for API parity. + // TODO(phase-c): The original inspects the linked OpenSSL version to decide + // whether openssl_x509_parse can be called safely. Certificate handling is + // slated to move to reqwest, so this dummy always reports safe. + pub fn is_openssl_parse_safe() -> bool { + true + } + + // The original `$logger` parameter (PSR LoggerInterface) is replaced by a + // `()` placeholder: CaBundle is expected to be subsumed by a Rust TLS + // library and removed, so it does not need a real logger. + // + // TODO(phase-c): Dummy stand-in until HTTP handling moves to reqwest, which + // discovers the system CA bundle itself. This probes the SSL_CERT_FILE / + // SSL_CERT_DIR environment variables and the common distribution CA + // locations, returning the first that exists. Unlike the original it does + // not consult OpenSSL's default cert locations, does not validate the + // candidate before returning it, and has no bundled cacert.pem fallback. + pub fn get_system_ca_root_bundle_path(_logger: ()) -> String { + if let Ok(file) = std::env::var("SSL_CERT_FILE") + && std::path::Path::new(&file).is_file() + { + return file; + } + + const CA_FILE_PATHS: &[&str] = &[ + "/etc/pki/tls/certs/ca-bundle.crt", + "/etc/ssl/certs/ca-certificates.crt", + "/etc/ssl/ca-bundle.pem", + "/usr/local/share/certs/ca-root-nss.crt", + "/usr/ssl/certs/ca-bundle.crt", + "/opt/local/share/curl/curl-ca-bundle.crt", + "/usr/local/share/curl/curl-ca-bundle.crt", + "/usr/share/ssl/certs/ca-bundle.crt", + "/etc/ssl/cert.pem", + "/usr/local/etc/ssl/cert.pem", + "/usr/local/etc/openssl/cert.pem", + "/usr/local/etc/openssl@1.1/cert.pem", + ]; + for path in CA_FILE_PATHS { + if std::path::Path::new(path).is_file() { + return path.to_string(); + } + } + + if let Ok(dir) = std::env::var("SSL_CERT_DIR") + && std::path::Path::new(&dir).is_dir() + { + return dir; + } + + const CA_DIR_PATHS: &[&str] = &["/etc/pki/tls/certs", "/etc/ssl/certs"]; + for path in CA_DIR_PATHS { + if std::path::Path::new(path).is_dir() { + return path.to_string(); + } + } + + String::new() + } + + // TODO(phase-c): Dummy stand-in until reqwest validates certificates itself. + // The original parses the file with OpenSSL and rejects malformed or expired + // bundles; here we only require the file to exist and be non-empty. + pub fn validate_ca_file(ca_file: &str, _logger: ()) -> bool { + std::fs::read(ca_file) + .map(|c| !c.is_empty()) + .unwrap_or(false) + } +} diff --git a/crates/shirabe-ca-bundle/src/lib.rs b/crates/shirabe-ca-bundle/src/lib.rs new file mode 100644 index 00000000..2a325096 --- /dev/null +++ b/crates/shirabe-ca-bundle/src/lib.rs @@ -0,0 +1,3 @@ +pub mod ca_bundle; + +pub use ca_bundle::*; diff --git a/crates/shirabe-external-packages/src/composer.rs b/crates/shirabe-external-packages/src/composer.rs index da1ab285..c95f237d 100644 --- a/crates/shirabe-external-packages/src/composer.rs +++ b/crates/shirabe-external-packages/src/composer.rs @@ -1,5 +1,3 @@ -pub mod ca_bundle; pub mod xdebug_handler; -pub use ca_bundle::*; pub use xdebug_handler::*; diff --git a/crates/shirabe-external-packages/src/composer/ca_bundle.rs b/crates/shirabe-external-packages/src/composer/ca_bundle.rs deleted file mode 100644 index 2a325096..00000000 --- a/crates/shirabe-external-packages/src/composer/ca_bundle.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod ca_bundle; - -pub use ca_bundle::*; diff --git a/crates/shirabe-external-packages/src/composer/ca_bundle/ca_bundle.rs b/crates/shirabe-external-packages/src/composer/ca_bundle/ca_bundle.rs deleted file mode 100644 index 3c372cb1..00000000 --- a/crates/shirabe-external-packages/src/composer/ca_bundle/ca_bundle.rs +++ /dev/null @@ -1,76 +0,0 @@ -//! ref: composer/vendor/composer/ca-bundle/src/CaBundle.php - -#[derive(Debug)] -pub struct CaBundle; - -impl CaBundle { - // TODO(plugin): unused for now; kept for API parity. - // TODO(phase-c): The original inspects the linked OpenSSL version to decide - // whether openssl_x509_parse can be called safely. Certificate handling is - // slated to move to reqwest, so this dummy always reports safe. - pub fn is_openssl_parse_safe() -> bool { - true - } - - // The original `$logger` parameter (PSR LoggerInterface) is replaced by a - // `()` placeholder: CaBundle is expected to be subsumed by a Rust TLS - // library and removed, so it does not need a real logger. - // - // TODO(phase-c): Dummy stand-in until HTTP handling moves to reqwest, which - // discovers the system CA bundle itself. This probes the SSL_CERT_FILE / - // SSL_CERT_DIR environment variables and the common distribution CA - // locations, returning the first that exists. Unlike the original it does - // not consult OpenSSL's default cert locations, does not validate the - // candidate before returning it, and has no bundled cacert.pem fallback. - pub fn get_system_ca_root_bundle_path(_logger: ()) -> String { - if let Ok(file) = std::env::var("SSL_CERT_FILE") - && std::path::Path::new(&file).is_file() - { - return file; - } - - const CA_FILE_PATHS: &[&str] = &[ - "/etc/pki/tls/certs/ca-bundle.crt", - "/etc/ssl/certs/ca-certificates.crt", - "/etc/ssl/ca-bundle.pem", - "/usr/local/share/certs/ca-root-nss.crt", - "/usr/ssl/certs/ca-bundle.crt", - "/opt/local/share/curl/curl-ca-bundle.crt", - "/usr/local/share/curl/curl-ca-bundle.crt", - "/usr/share/ssl/certs/ca-bundle.crt", - "/etc/ssl/cert.pem", - "/usr/local/etc/ssl/cert.pem", - "/usr/local/etc/openssl/cert.pem", - "/usr/local/etc/openssl@1.1/cert.pem", - ]; - for path in CA_FILE_PATHS { - if std::path::Path::new(path).is_file() { - return path.to_string(); - } - } - - if let Ok(dir) = std::env::var("SSL_CERT_DIR") - && std::path::Path::new(&dir).is_dir() - { - return dir; - } - - const CA_DIR_PATHS: &[&str] = &["/etc/pki/tls/certs", "/etc/ssl/certs"]; - for path in CA_DIR_PATHS { - if std::path::Path::new(path).is_dir() { - return path.to_string(); - } - } - - String::new() - } - - // TODO(phase-c): Dummy stand-in until reqwest validates certificates itself. - // The original parses the file with OpenSSL and rejects malformed or expired - // bundles; here we only require the file to exist and be non-empty. - pub fn validate_ca_file(ca_file: &str, _logger: ()) -> bool { - std::fs::read(ca_file) - .map(|c| !c.is_empty()) - .unwrap_or(false) - } -} diff --git a/crates/shirabe/Cargo.toml b/crates/shirabe/Cargo.toml index eef7daf4..469b7e32 100644 --- a/crates/shirabe/Cargo.toml +++ b/crates/shirabe/Cargo.toml @@ -4,6 +4,7 @@ version.workspace = true edition.workspace = true [dependencies] +shirabe-ca-bundle.workspace = true shirabe-class-map-generator.workspace = true shirabe-external-packages.workspace = true shirabe-metadata-minifier.workspace = true diff --git a/crates/shirabe/src/util/stream_context_factory.rs b/crates/shirabe/src/util/stream_context_factory.rs index b407e897..6a63537d 100644 --- a/crates/shirabe/src/util/stream_context_factory.rs +++ b/crates/shirabe/src/util/stream_context_factory.rs @@ -7,7 +7,7 @@ use crate::util::Filesystem; use crate::util::Platform; use crate::util::http::ProxyManager; use indexmap::IndexMap; -use shirabe_external_packages::composer::ca_bundle::CaBundle; +use shirabe_ca_bundle::CaBundle; use shirabe_php_shim::{ HHVM_VERSION, PHP_MAJOR_VERSION, PHP_MINOR_VERSION, PHP_RELEASE_VERSION, PhpMixed, array_replace_recursive, extension_loaded, function_exists, php_uname, stream_context_create, diff --git a/crates/shirabe/src/util/tls_helper.rs b/crates/shirabe/src/util/tls_helper.rs index 0df30b1a..0c3f44dc 100644 --- a/crates/shirabe/src/util/tls_helper.rs +++ b/crates/shirabe/src/util/tls_helper.rs @@ -1,6 +1,6 @@ //! ref: composer/src/Composer/Util/TlsHelper.php -use shirabe_external_packages::composer::ca_bundle::ca_bundle::CaBundle; +use shirabe_ca_bundle::ca_bundle::CaBundle; use shirabe_pcre::Preg; use shirabe_php_shim::{ PhpMixed, ltrim, php_regex, preg_quote, str_replace, strtolower, substr, substr_count, -- cgit v1.3.1-4-g156e