Skip to content

Commit

Permalink
feat: install_cert support linux
Browse files Browse the repository at this point in the history
Signed-off-by: zu1k <i@zu1k.com>
  • Loading branch information
zu1k committed Sep 12, 2022
1 parent cf41610 commit 6384cff
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 52 deletions.
16 changes: 14 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions crates/trust_cert/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
[package]
name = "trust_cert"
version = "0.0.1"
version = "0.0.2"
edition = "2021"

[dependencies]
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"] }
5 changes: 2 additions & 3 deletions crates/trust_cert/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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")
}
Expand Down
88 changes: 45 additions & 43 deletions crates/trust_cert/src/linux.rs
Original file line number Diff line number Diff line change
@@ -1,94 +1,96 @@
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 {
if let Ok(v) = env::var("CAROOT") {
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()
}
4 changes: 2 additions & 2 deletions crates/trust_cert/src/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ use windows::Win32::{
},
};

pub fn install_cert(cert: Vec<u8>) {
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()));
Expand Down

1 comment on commit 6384cff

@vercel
Copy link

@vercel vercel bot commented on 6384cff Sep 12, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.