Add fallback trust source installation and improve code formatting
This commit is contained in:
+83
-25
@@ -11,7 +11,6 @@ use std::path::{Path, PathBuf};
|
||||
use std::process::{Command, Stdio};
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
// Default paths mirror the p11-kit / update-ca-trust layout used by this system.
|
||||
const DEFAULT_ROOT: &str = "/";
|
||||
const DEFAULT_ANCHORS_DIR: &str = "/etc/ca-certificates/trust-source/anchors";
|
||||
const DEFAULT_EXTRACTED_DIR: &str = "/etc/ca-certificates/extracted";
|
||||
@@ -20,7 +19,6 @@ const DEFAULT_SSL_CERT_PEM_LINK: &str = "/etc/ssl/cert.pem";
|
||||
const DEFAULT_SSL_CA_CERTIFICATES_BUNDLE_LINK: &str = "/etc/ssl/certs/ca-certificates.crt";
|
||||
const DEFAULT_SSL_CA_BUNDLE_CRT_LINK: &str = "/etc/ssl/certs/ca-bundle.crt";
|
||||
const DEFAULT_JAVA_CACERTS_LINK: &str = "/etc/ssl/certs/java/cacerts";
|
||||
// BLFS make-ca compatibility paths (commonly used by OpenSSL/libgit2 builds on LFS).
|
||||
const DEFAULT_PKI_TLS_CA_BUNDLE_CRT_LINK: &str = "/etc/pki/tls/certs/ca-bundle.crt";
|
||||
const DEFAULT_PKI_TLS_CA_BUNDLE_TRUST_CRT_LINK: &str = "/etc/pki/tls/certs/ca-bundle.trust.crt";
|
||||
const DEFAULT_PKI_TLS_JAVA_CACERTS_LINK: &str = "/etc/pki/tls/java/cacerts";
|
||||
@@ -29,9 +27,11 @@ const DEFAULT_CERTDATA_URL: &str =
|
||||
const DEFAULT_CERTDATA_OUTPUT: &str = "certdata.txt";
|
||||
const DEFAULT_MOZILLA_TRUST_P11KIT: &str =
|
||||
"/usr/share/ca-certificates/trust-source/mozilla.trust.p11-kit";
|
||||
const DEFAULT_ETC_MOZILLA_TRUST_P11KIT: &str =
|
||||
"/etc/ca-certificates/trust-source/mozilla.trust.p11-kit";
|
||||
const DEFAULT_PKI_MOZILLA_TRUST_P11KIT: &str = "/etc/pki/anchors/mozilla.trust.p11-kit";
|
||||
// make-ca uses a pinned ISRG Root X1 to bootstrap downloads from hg.mozilla.org
|
||||
// before the local trust store exists. We do the same for certdata fetch/sync.
|
||||
const DEFAULT_PKI_CA_TRUST_SOURCE_MOZILLA_TRUST_P11KIT: &str =
|
||||
"/etc/pki/ca-trust/source/mozilla.trust.p11-kit";
|
||||
const MOZILLA_HG_BOOTSTRAP_ROOT_PEM: &str = r#"-----BEGIN CERTIFICATE-----
|
||||
MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
|
||||
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
|
||||
@@ -517,11 +517,17 @@ fn resolve_sync_certdata_output(
|
||||
}
|
||||
|
||||
if dry_run {
|
||||
return Ok((build_sync_tmp_workspace_path(0).join(DEFAULT_CERTDATA_OUTPUT), None));
|
||||
return Ok((
|
||||
build_sync_tmp_workspace_path(0).join(DEFAULT_CERTDATA_OUTPUT),
|
||||
None,
|
||||
));
|
||||
}
|
||||
|
||||
let workspace = create_sync_tmp_workspace_dir()?;
|
||||
println!("Using temporary certdata workspace: {}", workspace.display());
|
||||
println!(
|
||||
"Using temporary certdata workspace: {}",
|
||||
workspace.display()
|
||||
);
|
||||
Ok((
|
||||
workspace.join(DEFAULT_CERTDATA_OUTPUT),
|
||||
Some(TempWorkspaceCleanup { path: workspace }),
|
||||
@@ -858,8 +864,7 @@ fn write_bootstrap_ca_tempfile() -> Result<PathBuf> {
|
||||
"{}{}",
|
||||
MOZILLA_HG_BOOTSTRAP_ROOT_PEM, MOZILLA_HG_BOOTSTRAP_DIGICERT_G2_ROOT_PEM
|
||||
);
|
||||
fs::write(&path, bundle)
|
||||
.with_context(|| format!("failed to write {}", path.display()))?;
|
||||
fs::write(&path, bundle).with_context(|| format!("failed to write {}", path.display()))?;
|
||||
#[cfg(unix)]
|
||||
{
|
||||
fs::set_permissions(&path, fs::Permissions::from_mode(0o600))
|
||||
@@ -1091,6 +1096,7 @@ fn run_certdata_convert(args: CertdataConvertArgs) -> Result<()> {
|
||||
)
|
||||
};
|
||||
|
||||
let mut rendered_p11kit: Option<String> = None;
|
||||
if args.dry_run {
|
||||
if let Some(parsed) = &parsed {
|
||||
let (certs, trusts) = count_cert_and_trust_objects(parsed);
|
||||
@@ -1100,17 +1106,20 @@ fn run_certdata_convert(args: CertdataConvertArgs) -> Result<()> {
|
||||
);
|
||||
}
|
||||
println!("[dry-run] Would write {}", output_host.display());
|
||||
if should_write_make_ca_mirror(&args.root, &output_target) {
|
||||
let fallback_targets = detect_trust_source_fallback_targets(&args.root, &output_target);
|
||||
if !fallback_targets.is_empty() {
|
||||
println!(
|
||||
"[dry-run] Would also write BLFS make-ca compatibility source {}",
|
||||
path_in_root(&args.root, Path::new(DEFAULT_PKI_MOZILLA_TRUST_P11KIT)).display()
|
||||
"[dry-run] If extraction is empty, would retry after installing compatibility trust source(s):"
|
||||
);
|
||||
for target in fallback_targets {
|
||||
println!(" - {}", path_in_root(&args.root, &target).display());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let parsed = parsed.context("certdata parse result missing")?;
|
||||
let p11kit = convert_certdata_to_p11kit_bundle(&parsed)?;
|
||||
install_file(&output_host, p11kit.as_bytes(), args.force, false)?;
|
||||
maybe_install_make_ca_mozilla_mirror(&args.root, &output_target, &p11kit, args.force)?;
|
||||
rendered_p11kit = Some(p11kit);
|
||||
}
|
||||
|
||||
if args.no_extract {
|
||||
@@ -1123,33 +1132,75 @@ fn run_certdata_convert(args: CertdataConvertArgs) -> Result<()> {
|
||||
.unwrap_or_else(|| PathBuf::from(DEFAULT_EXTRACTED_DIR));
|
||||
extract_trust(&args.root, &extract_output, args.dry_run)?;
|
||||
if !args.dry_run {
|
||||
if let Err(err) = ensure_nonempty_extraction_outputs(&args.root, &extract_output) {
|
||||
let Some(p11kit) = rendered_p11kit.as_deref() else {
|
||||
return Err(err);
|
||||
};
|
||||
let fallback_installs =
|
||||
install_fallback_trust_sources(&args.root, &output_target, p11kit, args.force)?;
|
||||
if fallback_installs == 0 {
|
||||
return Err(err);
|
||||
}
|
||||
println!("Retrying trust extraction after installing compatibility trust source(s).");
|
||||
extract_trust(&args.root, &extract_output, false)?;
|
||||
ensure_nonempty_extraction_outputs(&args.root, &extract_output)?;
|
||||
}
|
||||
}
|
||||
println!("certdata conversion and extraction complete.");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn should_write_make_ca_mirror(root: &Path, output_target: &Path) -> bool {
|
||||
output_target == Path::new(DEFAULT_MOZILLA_TRUST_P11KIT)
|
||||
&& path_in_root(root, Path::new("/etc/pki")).exists()
|
||||
fn detect_trust_source_fallback_targets(_root: &Path, output_target: &Path) -> Vec<PathBuf> {
|
||||
if output_target != Path::new(DEFAULT_MOZILLA_TRUST_P11KIT) {
|
||||
return Vec::new();
|
||||
}
|
||||
|
||||
let mut targets = Vec::new();
|
||||
let fallback_candidates = [
|
||||
DEFAULT_ETC_MOZILLA_TRUST_P11KIT,
|
||||
DEFAULT_PKI_MOZILLA_TRUST_P11KIT,
|
||||
DEFAULT_PKI_CA_TRUST_SOURCE_MOZILLA_TRUST_P11KIT,
|
||||
];
|
||||
let output_target = output_target.to_path_buf();
|
||||
for candidate in fallback_candidates {
|
||||
let candidate_path = PathBuf::from(candidate);
|
||||
if candidate_path == output_target || targets.contains(&candidate_path) {
|
||||
continue;
|
||||
}
|
||||
// Always include fallback paths; install_file() will create parent dirs.
|
||||
// Some chroots do not have /etc/pki* until later packages are installed.
|
||||
targets.push(candidate_path);
|
||||
}
|
||||
targets
|
||||
}
|
||||
|
||||
fn maybe_install_make_ca_mozilla_mirror(
|
||||
fn install_fallback_trust_sources(
|
||||
root: &Path,
|
||||
output_target: &Path,
|
||||
p11kit: &str,
|
||||
force: bool,
|
||||
) -> Result<()> {
|
||||
if !should_write_make_ca_mirror(root, output_target) {
|
||||
return Ok(());
|
||||
) -> Result<usize> {
|
||||
let mut installed = 0usize;
|
||||
let targets = detect_trust_source_fallback_targets(root, output_target);
|
||||
if targets.is_empty() {
|
||||
return Ok(0);
|
||||
}
|
||||
|
||||
let mirror_host = path_in_root(root, Path::new(DEFAULT_PKI_MOZILLA_TRUST_P11KIT));
|
||||
for target in targets {
|
||||
let mirror_host = path_in_root(root, &target);
|
||||
println!(
|
||||
"Installing BLFS make-ca compatibility trust source: {}",
|
||||
"Installing compatibility trust source: {}",
|
||||
mirror_host.display()
|
||||
);
|
||||
install_file(&mirror_host, p11kit.as_bytes(), force, false)
|
||||
match install_file(&mirror_host, p11kit.as_bytes(), force, false) {
|
||||
Ok(()) => installed += 1,
|
||||
Err(err) => eprintln!(
|
||||
"warning: unable to install compatibility trust source {}: {err}",
|
||||
mirror_host.display()
|
||||
),
|
||||
}
|
||||
}
|
||||
Ok(installed)
|
||||
}
|
||||
|
||||
fn ensure_nonempty_extraction_outputs(root: &Path, extract_output: &Path) -> Result<()> {
|
||||
@@ -2317,7 +2368,8 @@ CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR
|
||||
#[test]
|
||||
fn sync_certdata_output_respects_explicit_path() {
|
||||
let requested = PathBuf::from("/var/tmp/custom-certdata.txt");
|
||||
let (resolved, cleanup) = resolve_sync_certdata_output(Some(requested.clone()), false).unwrap();
|
||||
let (resolved, cleanup) =
|
||||
resolve_sync_certdata_output(Some(requested.clone()), false).unwrap();
|
||||
assert_eq!(resolved, requested);
|
||||
assert!(cleanup.is_none());
|
||||
}
|
||||
@@ -2326,7 +2378,10 @@ CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR
|
||||
fn sync_certdata_output_uses_tmp_workspace_and_cleans_it() {
|
||||
let (resolved, cleanup) = resolve_sync_certdata_output(None, false).unwrap();
|
||||
assert!(resolved.starts_with(Path::new("/tmp")));
|
||||
assert_eq!(resolved.file_name(), Some(OsStr::new(DEFAULT_CERTDATA_OUTPUT)));
|
||||
assert_eq!(
|
||||
resolved.file_name(),
|
||||
Some(OsStr::new(DEFAULT_CERTDATA_OUTPUT))
|
||||
);
|
||||
let workspace = resolved.parent().unwrap().to_path_buf();
|
||||
assert!(workspace.exists());
|
||||
|
||||
@@ -2338,7 +2393,10 @@ CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_TRUSTED_DELEGATOR
|
||||
fn sync_certdata_output_dry_run_uses_tmp_path_without_creating_workspace() {
|
||||
let (resolved, cleanup) = resolve_sync_certdata_output(None, true).unwrap();
|
||||
assert!(resolved.starts_with(Path::new("/tmp")));
|
||||
assert_eq!(resolved.file_name(), Some(OsStr::new(DEFAULT_CERTDATA_OUTPUT)));
|
||||
assert_eq!(
|
||||
resolved.file_name(),
|
||||
Some(OsStr::new(DEFAULT_CERTDATA_OUTPUT))
|
||||
);
|
||||
assert!(cleanup.is_none());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user