use std::path::{Path, PathBuf};
use crate::core::binary_provenance::{parse_cargo_installs, provenance_report};
use crate::core::doctor::{CheckStatus, DoctorCheck};
const CHECK_NAME: &str = "binary_provenance";
pub(super) fn check_binary_provenance() -> DoctorCheck {
let exe = std::env::current_exe().ok();
let cargo_home = cargo_home_dir();
let ledger_raw = cargo_home
.as_ref()
.and_then(|h| std::fs::read_to_string(h.join(".crates2.json")).ok());
check_binary_provenance_with(
exe.as_deref(),
cargo_home.as_deref(),
ledger_raw.as_deref(),
env!("CARGO_PKG_VERSION"),
)
}
fn check_binary_provenance_with(
exe: Option<&Path>,
cargo_home: Option<&Path>,
ledger_raw: Option<&str>,
running_version: &str,
) -> DoctorCheck {
let Some((exe, bin_name)) = exe.and_then(|p| {
let name = p.file_name()?.to_str()?.to_owned();
Some((p, name))
}) else {
return DoctorCheck::new(
CHECK_NAME,
CheckStatus::Unknown,
"the running executable's path could not be resolved — install provenance \
cannot be verified (issue #4033)",
);
};
let Some(cargo_home) = cargo_home else {
return DoctorCheck::new(
CHECK_NAME,
CheckStatus::Unknown,
format!(
"no `$CARGO_HOME` or home directory resolved — cannot tell whether the \
running `{bin_name}` is a cargo install (issue #4033)"
),
);
};
let ledger = ledger_raw.and_then(parse_cargo_installs);
let (status, message) = provenance_report(
&bin_name,
running_version,
exe,
&cargo_home.join("bin"),
ledger.as_deref(),
&|dir| dir.exists(),
);
DoctorCheck::new(CHECK_NAME, status, message)
}
fn cargo_home_dir() -> Option<PathBuf> {
match std::env::var("CARGO_HOME") {
Ok(h) if !h.is_empty() => Some(PathBuf::from(h)),
_ => Some(dirs::home_dir()?.join(".cargo")),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn provenance_is_unknown_without_a_ledger() {
let check = check_binary_provenance_with(
Some(Path::new("/usr/local/bin/tm")),
Some(Path::new("/home/x/.cargo")),
None,
"1.3.1",
);
assert_eq!(
check.status,
CheckStatus::Unknown,
"message: {}",
check.message
);
assert_eq!(check.name, CHECK_NAME);
}
#[test]
fn provenance_is_unknown_without_a_cargo_home() {
let check = check_binary_provenance_with(
Some(Path::new("/usr/local/bin/tm")),
None,
Some("{}"),
"1.3.1",
);
assert_eq!(check.status, CheckStatus::Unknown, "{}", check.message);
}
#[test]
fn provenance_is_unknown_for_a_shadowing_binary() {
let ledger = r#"{"installs":{
"trusty-mpm 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)":
{"bins":["tm"]}}}"#;
let check = check_binary_provenance_with(
Some(Path::new("/Users/x/.local/bin/tm")),
Some(Path::new("/Users/x/.cargo")),
Some(ledger),
"1.3.1",
);
assert_eq!(
check.status,
CheckStatus::Unknown,
"message: {}",
check.message
);
assert!(check.message.contains(".local/bin/tm"), "{}", check.message);
}
#[test]
fn provenance_is_unknown_for_a_downloader_replaced_cargo_install() {
let ledger = r#"{"installs":{
"trusty-mpm 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)":
{"bins":["tm"]}}}"#;
let check = check_binary_provenance_with(
Some(Path::new("/Users/x/.cargo/bin/tm")),
Some(Path::new("/Users/x/.cargo")),
Some(ledger),
"1.4.0",
);
assert_ne!(
check.status,
CheckStatus::Fail,
"a successful no-cargo upgrade must not fail doctor: {}",
check.message
);
assert_eq!(
check.status,
CheckStatus::Unknown,
"message: {}",
check.message
);
assert!(check.message.contains("NEWER"), "{}", check.message);
}
#[test]
fn provenance_fails_when_the_running_binary_is_older_than_the_ledger() {
let ledger = r#"{"installs":{
"trusty-mpm 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)":
{"bins":["tm"]}}}"#;
let check = check_binary_provenance_with(
Some(Path::new("/Users/x/.cargo/bin/tm")),
Some(Path::new("/Users/x/.cargo")),
Some(ledger),
"1.3.1",
);
assert_eq!(check.status, CheckStatus::Fail, "{}", check.message);
assert!(check.message.contains("OLDER"), "{}", check.message);
}
#[test]
fn provenance_is_unknown_without_an_exe() {
let check = check_binary_provenance_with(
None,
Some(Path::new("/home/x/.cargo")),
Some("{}"),
"1.3.1",
);
assert_eq!(check.status, CheckStatus::Unknown);
}
#[test]
fn live_check_reports_unknown_for_an_uninstalled_binary() {
let check = check_binary_provenance();
println!(
"LIVE binary_provenance -> {:?}: {}",
check.status, check.message
);
assert_eq!(
check.status,
CheckStatus::Unknown,
"a binary cargo never installed must be UNKNOWN, not Ok: {}",
check.message
);
}
#[test]
fn provenance_reports_the_ledger_verdict() {
let ledger = r#"{"installs":{
"trusty-mpm 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)":
{"bins":["tm"]}}}"#;
let check = check_binary_provenance_with(
Some(Path::new("/Users/x/.cargo/bin/tm")),
Some(Path::new("/Users/x/.cargo")),
Some(ledger),
"1.3.1",
);
assert_eq!(check.status, CheckStatus::Ok, "message: {}", check.message);
assert!(check.message.contains("crates.io"), "{}", check.message);
}
}