diff --git a/core/src/commands/generate.rs b/core/src/commands/generate.rs index 8cfc5d0..2d20375 100644 --- a/core/src/commands/generate.rs +++ b/core/src/commands/generate.rs @@ -1,5 +1,8 @@ use crate::{ - trust_stores::{nss::NSSValue, nss_profile::NSSProfile, CAValue}, + trust_stores::{ + firefox::FirefoxTrustStore, nss::NSSValue, nss_profile::NSSProfile, + utils::check_if_firefox_exists, CAValue, + }, utils::{get_certificates_from_data_dir, save_generated_cert_key_files}, x509::{ ca_cert::CACert, ca_req::CAReq, distinguished_name::DistinguishedName, leaf_cert::LeafCert, @@ -313,11 +316,22 @@ pub fn generate( }; ca_value_object.install_certificate()?; let nss_profile_object: NSSProfile = NSSProfile::new(); - let ca_unique_name: String = "vanish-root-test-123456-ujjwalpppp".to_string(); + let ca_unique_name: String = "vanish-root-test-123456-shubham-brr".to_string(); let caroot: String = "/home/jerry/.local/share/vanish/ca_cert.pem".to_string(); - let mkcert: NSSValue = NSSValue::new(nss_profile_object, ca_unique_name, caroot); + let mkcert: NSSValue = + NSSValue::new(nss_profile_object, ca_unique_name.clone(), caroot.clone()); let success: bool = mkcert.install_nss(); - + let firefox_exists: bool = check_if_firefox_exists()?; + if firefox_exists { + let firefox_trust_store_object: FirefoxTrustStore = + FirefoxTrustStore::new(ca_unique_name, caroot)?; + let paths_with_trust_stores: Vec = + FirefoxTrustStore::find_cert_directories(&firefox_trust_store_object)?; + FirefoxTrustStore::install_firefox_certificates( + &firefox_trust_store_object, + paths_with_trust_stores, + ); + } if success { println!("Certificate installed successfully."); } else { @@ -454,11 +468,23 @@ pub fn generate( }; ca_value_object.install_certificate()?; let nss_profile_object: NSSProfile = NSSProfile::new(); - let ca_unique_name: String = "vanish-root-testing-1234-ujjwal".to_string(); + let ca_unique_name: String = "vanish-root-testing-1234-shubham-brr".to_string(); let caroot: String = "/home/jerry/.local/share/vanish/ca_cert.pem".to_string(); - let mkcert: NSSValue = NSSValue::new(nss_profile_object, ca_unique_name, caroot); + let mkcert: NSSValue = + NSSValue::new(nss_profile_object, ca_unique_name.clone(), caroot.clone()); let success: bool = mkcert.install_nss(); - + let firefox_exists: bool = check_if_firefox_exists()?; + if firefox_exists { + let firefox_trust_store_object: FirefoxTrustStore = + FirefoxTrustStore::new(ca_unique_name, caroot)?; + let paths_with_trust_stores: Vec = + FirefoxTrustStore::find_cert_directories(&firefox_trust_store_object)?; + println!("{:?}", paths_with_trust_stores); + FirefoxTrustStore::install_firefox_certificates( + &firefox_trust_store_object, + paths_with_trust_stores, + ); + } if success { println!("Certificate installed successfully."); } else { diff --git a/core/src/trust_stores/errors.rs b/core/src/trust_stores/errors.rs index 9270c32..85d97fd 100644 --- a/core/src/trust_stores/errors.rs +++ b/core/src/trust_stores/errors.rs @@ -26,6 +26,7 @@ impl fmt::Display for TrustStoreError { impl Error for TrustStoreError {} +#[derive(Debug)] pub enum FirefoxTrustStoreError { ENVVariableNotFound(VarError, String), IOError(io::Error), @@ -47,3 +48,5 @@ impl fmt::Display for FirefoxTrustStoreError { } } } + +impl Error for FirefoxTrustStoreError {} diff --git a/core/src/trust_stores/firefox.rs b/core/src/trust_stores/firefox.rs index edb9513..7552ef6 100644 --- a/core/src/trust_stores/firefox.rs +++ b/core/src/trust_stores/firefox.rs @@ -1,47 +1,93 @@ use super::errors::FirefoxTrustStoreError; +use std::process::exit; use std::{ - env, ffi, fs, io, + env, fs, io, path::{Path, PathBuf}, + process::{Command, ExitStatus}, }; - pub struct FirefoxTrustStore { firefox_profile: Vec, + certutil_path: Option, + ca_unique_name: String, + vanish_ca_path: String, } impl FirefoxTrustStore { - pub fn new() -> Result { + pub fn new( + ca_unique_name: String, + vanish_ca_path: String, + ) -> Result { let mut firefox_profile: Vec = Vec::::new(); + let mut certutil_path: Option = None; + #[cfg(target_os = "linux")] { let home: String = env::var("HOME").map_err(|err: env::VarError| { FirefoxTrustStoreError::ENVVariableNotFound(err, "HOME".to_string()) })?; - firefox_profile.push(home.clone() + "/.morzilla/firefox/"); - firefox_profile.push(home + "/snap/firefox/common/.mozilla/firefox/"); + firefox_profile.push(format!("{}/.mozilla/firefox", home)); + firefox_profile.push(format!("{}/snap/firefox/common/.mozilla/firefox", home)); + + if Command::new("certutil").output().is_ok() { + certutil_path = Some("certutil".to_string()); + } } + #[cfg(target_os = "windows")] { let userprofile: String = env::var("USERPROFILE").map_err(|err: env::VarError| { FirefoxTrustStoreError::ENVVariableNotFound(err, "USERPROFILE".to_string()) })?; - firefox_profile.push(userprofile + "\\AppData\\Roaming\\Mozilla\\Firefox\\Profiles"); + firefox_profile.push(format!( + "{}\\AppData\\Roaming\\Mozilla\\Firefox\\Profiles", + userprofile + )); + + // NOT SURE + if Command::new("certutil").output().is_ok() { + certutil_path = Some("certutil".to_string()); + } } + #[cfg(target_os = "macos")] { let home: String = env::var("HOME").map_err(|err: env::VarError| { FirefoxTrustStoreError::ENVVariableNotFound(err, "HOME".to_string()) })?; - firefox_profile.push(home + "/Library/Application Support/Firefox/Profiles/"); + firefox_profile.push(format!( + "{}/Library/Application Support/Firefox/Profiles/", + home + )); + + if Command::new("certutil").output().is_ok() { + certutil_path = Some("certutil".to_string()); + } else if Path::new("/usr/local/opt/nss/bin/certutil").exists() { + certutil_path = Some("/usr/local/opt/nss/bin/certutil".to_string()); + } else if let Ok(out) = Command::new("brew").arg("--prefix").arg("nss").output() { + let path = String::from_utf8_lossy(&out.stdout).trim().to_string(); + let full_path = format!("{}/bin/certutil", path); + if Path::new(&full_path).exists() { + certutil_path = Some(full_path); + } + } } - Ok(FirefoxTrustStore { firefox_profile }) + + Ok(FirefoxTrustStore { + firefox_profile, + certutil_path, + vanish_ca_path, + ca_unique_name, + }) } pub fn find_cert_directories(&self) -> Result, FirefoxTrustStoreError> { let mut cert_dirs: Vec = Vec::new(); - + println!("Firefox Profiles: {:?}", &self.firefox_profile); for profile_dir in &self.firefox_profile { let path: &Path = Path::new(profile_dir); + println!("{:?} exists: {:?}", &path, &path.exists()); if path.exists() && path.is_dir() { + println!("Path is a dir: {:?}", &path); for entry in fs::read_dir(path) .map_err(|err: io::Error| FirefoxTrustStoreError::IOError(err))? { @@ -67,5 +113,39 @@ impl FirefoxTrustStore { } } - pub fn install_firefox_certificates(&self) {} + pub fn install_firefox_certificates(&self, cert_paths: Vec) { + match &self.certutil_path { + Some(path) => { + for cert_dir in cert_paths { + let cmd_result: Result = Command::new(path) + .arg("-A") + .arg("-d") + .arg(cert_dir.to_str().unwrap()) + .arg("-t") + .arg("C,,") + .arg("-n") + .arg(&self.ca_unique_name) + .arg("-i") + .arg(&self.vanish_ca_path) + .status(); + + match cmd_result { + Ok(status) if status.success() => { + println!("Successfully installed certificate in {:?}", cert_dir); + } + Ok(_) => { + eprintln!("Failed to install certificate in {:?}", cert_dir); + } + Err(err) => { + eprintln!("Error executing certutil: {:?}", err); + } + } + } + } + None => { + eprint!("No certutil found. Please install!"); + exit(1); + } + }; + } } diff --git a/core/src/trust_stores/mod.rs b/core/src/trust_stores/mod.rs index 51e2ce4..113b6f3 100644 --- a/core/src/trust_stores/mod.rs +++ b/core/src/trust_stores/mod.rs @@ -2,6 +2,7 @@ mod errors; pub mod firefox; pub mod nss; pub mod nss_profile; +pub mod utils; #[cfg(target_os = "linux")] mod linux; diff --git a/core/src/trust_stores/nss.rs b/core/src/trust_stores/nss.rs index 1bd3335..4ee0008 100644 --- a/core/src/trust_stores/nss.rs +++ b/core/src/trust_stores/nss.rs @@ -63,7 +63,7 @@ impl NSSValue { .arg("-n") .arg(&self.ca_unique_name) .arg("-i") - .arg(format!("{}", self.caroot)) + .arg(&self.caroot) .status(); if let Err(err) = cmd { diff --git a/core/src/trust_stores/utils.rs b/core/src/trust_stores/utils.rs new file mode 100644 index 0000000..cf7c27c --- /dev/null +++ b/core/src/trust_stores/utils.rs @@ -0,0 +1,23 @@ +use std::{fs, io}; + +pub fn check_if_firefox_exists() -> Result { + let firefox_paths: Vec = vec![ + "/usr/bin/firefox".to_string(), + "/usr/bin/firefox-nightly".to_string(), + "/usr/bin/firefox-developer-edition".to_string(), + "/snap/firefox".to_string(), + "/Applications/Firefox.app".to_string(), + "/Applications/FirefoxDeveloperEdition.app".to_string(), + "/Applications/Firefox Developer Edition.app".to_string(), + "/Applications/Firefox Nightly.app".to_string(), + "C:\\Program Files\\Mozilla Firefox".to_string(), + ]; + + for path in firefox_paths { + if fs::metadata(&path).is_ok() { + return Ok(true); + } + } + + Ok(false) +}