From 6384cff251c81d650445fbe0f358d81e32b9ea2d Mon Sep 17 00:00:00 2001 From: zu1k Date: Mon, 12 Sep 2022 21:34:26 +0800 Subject: [PATCH] feat: install_cert support linux Signed-off-by: zu1k --- Cargo.lock | 16 +++++- crates/trust_cert/Cargo.toml | 4 +- crates/trust_cert/src/lib.rs | 5 +- crates/trust_cert/src/linux.rs | 88 ++++++++++++++++---------------- crates/trust_cert/src/windows.rs | 4 +- 5 files changed, 65 insertions(+), 52 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0911e41..6fd055c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1092,6 +1092,18 @@ dependencies = [ "tempfile", ] +[[package]] +name = "nix" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e322c04a9e3440c327fca7b6c8a63e6890a32fa2ad689db972425f07e0d22abb" +dependencies = [ + "autocfg", + "bitflags", + "cfg-if", + "libc", +] + [[package]] name = "nom" version = "7.1.1" @@ -1921,10 +1933,10 @@ checksum = "f1ee9bd9239c339d714d657fac840c6d2a4f9c45f4f9ec7b0975113458be78db" [[package]] name = "trust_cert" -version = "0.0.1" +version = "0.0.2" dependencies = [ "cfg-if", - "libc", + "nix", "rcgen", "windows", ] diff --git a/crates/trust_cert/Cargo.toml b/crates/trust_cert/Cargo.toml index 214ce81..6cd0b0a 100644 --- a/crates/trust_cert/Cargo.toml +++ b/crates/trust_cert/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "trust_cert" -version = "0.0.1" +version = "0.0.2" edition = "2021" [dependencies] @@ -8,7 +8,7 @@ cfg-if = "1" rcgen = { version = "0.9", features = ["x509-parser"] } [target.'cfg(unix)'.dependencies] -libc = "0.2" +nix = { version = "0.25", default-features = false, features = ["user"] } [target.'cfg(windows)'.dependencies] windows = { version = "0.39", features = ["Win32_Security_Cryptography", "Win32_Foundation"] } diff --git a/crates/trust_cert/src/lib.rs b/crates/trust_cert/src/lib.rs index 3716a3b..b57ec7c 100644 --- a/crates/trust_cert/src/lib.rs +++ b/crates/trust_cert/src/lib.rs @@ -10,10 +10,9 @@ mod linux; pub fn trust_cert(cert: Certificate) { cfg_if::cfg_if! { if #[cfg(windows)] { - windows::install_cert(cert.serialize_der().unwrap()); + windows::install_cert(cert); } else if #[cfg(target_os = "linux")] { - todo!() - // linux::install_cert(); + linux::install_cert(cert); } else { panic!("not implemented on this target") } diff --git a/crates/trust_cert/src/linux.rs b/crates/trust_cert/src/linux.rs index e477088..73987f6 100644 --- a/crates/trust_cert/src/linux.rs +++ b/crates/trust_cert/src/linux.rs @@ -1,61 +1,62 @@ -use std::{env, fs, io::Write, path::Path, process::Command}; +use nix::unistd::getegid; +use rcgen::Certificate; +use std::{env, fs, path::Path, process::Command}; -pub fn install_cert() { - let (system_trust_filename, system_trust_cmd) = { +pub fn install_cert(cert: Certificate) { + if getegid().as_raw() != 0 { + println!("Please run with root permission"); + return; + } + + let (system_trust_filename, trust_cmd, trust_cmd_args) = { if path_exist("/etc/pki/ca-trust/source/anchors/") { ( "/etc/pki/ca-trust/source/anchors/{cert-name}.pem", - vec!["update-ca-trust", "extract"], + "update-ca-trust", + vec!["extract"], ) } else if path_exist("/usr/local/share/ca-certificates/") { ( "/usr/local/share/ca-certificates/{cert-name}.crt", - vec!["update-ca-certificates"], + "update-ca-certificates", + vec![], ) } else if path_exist("/etc/ca-certificates/trust-source/anchors/") { ( "/etc/ca-certificates/trust-source/anchors/{cert-name}.crt", - vec!["trust", "extract-compat"], + "trust", + vec!["extract-compat"], ) } else if path_exist("/usr/share/pki/trust/anchors") { ( "/usr/share/pki/trust/anchors/{cert-name}.pem", - vec!["update-ca-certificates"], + "update-ca-certificates", + vec![], ) } else { - ( - "/etc/pki/ca-trust/source/anchors/{cert-name}.pem", - vec!["update-ca-trust", "extract"], - ) + ("good-mitm.pem", "", vec![]) } }; - let cert = Path::new(&get_ca_root()).join("mitm-vip-unlocker.pem"); - let cert = fs::read(cert).unwrap(); - - let system_trust_name = system_trust_filename.replace("{cert-name}", "mitm-vip-unlocker"); - let mut cmd = cmd_with_sudo(vec!["tee", &system_trust_name]) - .spawn() - .unwrap(); - let stdin = cmd.stdin.as_mut().unwrap(); - stdin.write_all(&cert).unwrap(); + let cert = cert.serialize_pem().expect("serialize cert to pem format"); + let system_trust_name = system_trust_filename.replace("{cert-name}", "good-mitm"); + fs::write(system_trust_name, cert).expect("write cert to system trust ca location"); - cmd_with_sudo(system_trust_cmd).status().unwrap(); -} - -fn cmd_with_sudo(cmd: Vec<&str>) -> Command { - let mut cmd = cmd; - if unsafe { libc::getegid() } == 0 { - let mut command = Command::new(cmd[0]); - command.args(&cmd[1..]); - return command; + if trust_cmd.is_empty() { + println!( + "Installing to the system store is not yet supported on this Linux 😣 but Firefox and/or Chrome/Chromium will still work.", + ); + let cert_path = Path::new(&get_ca_root()).join("good-mitm.pem"); + println!( + "You can also manually install the root certificate at {}.", + cert_path.to_str().unwrap() + ); + } else { + Command::new(trust_cmd) + .args(trust_cmd_args) + .status() + .expect("failed to execute trust command"); } - - let mut sudo_cmd = vec!["--prompt=Sudo password:", "--"]; - sudo_cmd.append(&mut cmd); - let mut command = Command::new("sudo"); - command.args(&sudo_cmd); - command } fn get_ca_root() -> String { @@ -63,32 +64,33 @@ fn get_ca_root() -> String { return v; } - let dir = { - if let Ok(v) = env::var("XDG_DATA_HOM") { + let mut dir = { + if let Ok(v) = env::var("XDG_DATA_HOME") { return v; } if let Ok(v) = env::var("HOME") { return Path::new(&v) .join(".local") .join("share") - .into_os_string() - .into_string() + .to_str() + .map(|s| s.to_string()) .unwrap(); } String::new() }; - if dir.is_empty() { - String::new() - } else { - Path::new(&dir) + if !dir.is_empty() { + dir = Path::new(&dir) .join("mitm") .into_os_string() .into_string() .unwrap() } + + dir } +#[inline] fn path_exist(path: &str) -> bool { Path::new(path).exists() } diff --git a/crates/trust_cert/src/windows.rs b/crates/trust_cert/src/windows.rs index 8242f5e..08cfb2d 100644 --- a/crates/trust_cert/src/windows.rs +++ b/crates/trust_cert/src/windows.rs @@ -6,8 +6,8 @@ use windows::Win32::{ }, }; -pub fn install_cert(cert: Vec) { - let mut cert = cert; +pub fn install_cert(cert: Certificate) { + let mut cert = cert.serialize_der().unwrap(); unsafe { // get root store let store = CertOpenSystemStoreA(0, PSTR(String::from("ROOT\0").as_mut_ptr()));