diff --git a/.changeset/happy-apes-check.md b/.changeset/happy-apes-check.md new file mode 100644 index 00000000..3e1443c1 --- /dev/null +++ b/.changeset/happy-apes-check.md @@ -0,0 +1,5 @@ +--- +'pastebar-app': patch +--- + +Updated hardware uuid detection for Mac and Windows diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 1c99640f..3d5287e8 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -792,6 +792,37 @@ dependencies = [ "yansi", ] +[[package]] +name = "com" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e17887fd17353b65b1b2ef1c526c83e26cd72e74f598a8dc1bee13a48f3d9f6" +dependencies = [ + "com_macros", +] + +[[package]] +name = "com_macros" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d375883580a668c7481ea6631fc1a8863e33cc335bf56bfad8d7e6d4b04b13a5" +dependencies = [ + "com_macros_support", + "proc-macro2", + "syn 1.0.109", +] + +[[package]] +name = "com_macros_support" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad899a1087a9296d5644792d7cb72b8e34c1bec8e7d4fbc002230169a6e8710c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "combine" version = "4.6.6" @@ -1562,6 +1593,21 @@ dependencies = [ "new_debug_unreachable", ] +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + [[package]] name = "futures-channel" version = "0.3.30" @@ -1569,6 +1615,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", + "futures-sink", ] [[package]] @@ -1651,6 +1698,7 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ + "futures-channel", "futures-core", "futures-io", "futures-macro", @@ -2961,8 +3009,12 @@ dependencies = [ name = "mid" version = "2.0.0" dependencies = [ + "chrono", "hex", "hmac-sha256", + "serde", + "serde_derive", + "wmi", ] [[package]] @@ -6296,6 +6348,12 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" +[[package]] +name = "widestring" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311" + [[package]] name = "winapi" version = "0.3.9" @@ -6781,6 +6839,22 @@ dependencies = [ "wayland-protocols-wlr", ] +[[package]] +name = "wmi" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dcdf3cb61b91b8b306b2a9ceb7cb2cbce776bc310ef5b7ef909b15c97f46a41" +dependencies = [ + "chrono", + "com", + "futures", + "log", + "serde", + "thiserror", + "widestring", + "winapi", +] + [[package]] name = "wry" version = "0.24.7" diff --git a/src-tauri/libs/mid-hardware-id/Cargo.toml b/src-tauri/libs/mid-hardware-id/Cargo.toml index 988d717c..531a197b 100644 --- a/src-tauri/libs/mid-hardware-id/Cargo.toml +++ b/src-tauri/libs/mid-hardware-id/Cargo.toml @@ -14,5 +14,9 @@ categories = ["authentication", "config", "accessibility"] doctest = false [dependencies] +wmi = "0.11.0" +serde = { version = "1.0", features = ["derive"] } +serde_derive = "1.0" +chrono = "0.4" hex = "0.4.3" hmac-sha256 = "1.1.7" diff --git a/src-tauri/libs/mid-hardware-id/src/lib.rs b/src-tauri/libs/mid-hardware-id/src/lib.rs index 703231fa..e68f363c 100644 --- a/src-tauri/libs/mid-hardware-id/src/lib.rs +++ b/src-tauri/libs/mid-hardware-id/src/lib.rs @@ -22,9 +22,9 @@ use windows::get_mid_result; #[derive(Debug)] pub struct MidData { - pub key: String, - pub result: Vec, - pub hash: String, + pub key: String, + pub result: Vec, + pub hash: String, } /// Gets unique platform metrics and returns a `Result`, which can be a MID hash (SHA-256) or a `MIDError`. @@ -47,10 +47,10 @@ pub struct MidData { /// } /// ``` pub fn get(key: &str) -> Result { - match data(key) { - Ok(mid) => Ok(mid.hash), - Err(err) => Err(err), - } + match data(key) { + Ok(mid) => Ok(mid.hash), + Err(err) => Err(err), + } } /// Returns MID key/result/hash as [`MidData`] @@ -65,25 +65,25 @@ pub fn get(key: &str) -> Result { /// let mid_data = mid::data("mySecretKey").unwrap(); /// ``` pub fn data(key: &str) -> Result { - if key.is_empty() { - return Err(MIDError::EmptyMidKey); - } - - match get_mid_result() { - Ok(mid) => { - let mid_result: Vec = mid.split('|').map(|s| s.to_string()).collect(); - - let hmac_result = HMAC::mac(mid.as_bytes(), key.as_bytes()); - let mid_hash = hex::encode(hmac_result); - - Ok(MidData { - key: String::from(key), - result: mid_result, - hash: mid_hash, - }) - } - Err(err) => Err(err), + if key.is_empty() { + return Err(MIDError::EmptyMidKey); + } + + match get_mid_result() { + Ok(mid) => { + let mid_result: Vec = mid.split('|').map(|s| s.to_string()).collect(); + + let hmac_result = HMAC::mac(mid.as_bytes(), key.as_bytes()); + let mid_hash = hex::encode(hmac_result); + + Ok(MidData { + key: String::from(key), + result: mid_result, + hash: mid_hash, + }) } + Err(err) => Err(err), + } } /// Output the MID key/result/hash to the console in `debug_assertions` mode. @@ -100,27 +100,27 @@ pub fn data(key: &str) -> Result { /// mid::print("mySecretKey"); /// ``` pub fn print(key: &str) { - match data(key) { - Ok(mid) => { - debug!("MID.print[key]: {}", mid.key); - debug!("MID.print[result]: {:?}", mid.result); - debug!("MID.print[hash]: {}", mid.hash); - } - Err(err) => debug!("MID.print[error]: {}", err), + match data(key) { + Ok(mid) => { + debug!("MID.print[key]: {}", mid.key); + debug!("MID.print[result]: {:?}", mid.result); + debug!("MID.print[hash]: {}", mid.hash); } + Err(err) => debug!("MID.print[error]: {}", err), + } } #[test] fn test_mid_operations() { - match get("mykey") { - Ok(mid) => debug!("MID.get: {}", mid), - Err(err) => debug!("MID.get[error]: {}", err), - } + match get("mykey") { + Ok(mid) => debug!("MID.get: {}", mid), + Err(err) => debug!("MID.get[error]: {}", err), + } - match data("mykey") { - Ok(log_data) => debug!("MID.data: {:?}", log_data), - Err(err) => debug!("MID.data[error]: {}", err), - } + match data("mykey") { + Ok(log_data) => debug!("MID.data: {:?}", log_data), + Err(err) => debug!("MID.data[error]: {}", err), + } - print("mykey"); + print("mykey"); } diff --git a/src-tauri/libs/mid-hardware-id/src/macos.rs b/src-tauri/libs/mid-hardware-id/src/macos.rs index 6f3ec191..c5255a8b 100644 --- a/src-tauri/libs/mid-hardware-id/src/macos.rs +++ b/src-tauri/libs/mid-hardware-id/src/macos.rs @@ -6,64 +6,22 @@ use std::process::{Command, Stdio}; #[cfg(target_os = "macos")] pub(crate) fn get_mid_result() -> Result { - let combined_output = Command::new("sh") + let output = Command::new("sh") .arg("-c") - .arg(r#"system_profiler SPHardwareDataType SPSecureElementDataType"#) + .arg("system_profiler SPHardwareDataType | awk '/Hardware UUID/ { print $3; }'") .stderr(Stdio::piped()) .stdout(Stdio::piped()) - .spawn(); + .output() + .map_err(|_| MIDError::ResultMidError)?; - match combined_output { - Ok(output) => { - let output = output.wait_with_output().unwrap(); - if !output.status.success() { - return Err(MIDError::ResultMidError); - } - let system_profiler_output = String::from_utf8_lossy(&output.stdout); - if system_profiler_output.is_empty() { - return Err(MIDError::ResultMidError); - } - - let targets = [ - "Model Number", - "Serial Number", - "Hardware UUID", - "Provisioning UDID", - "Platform ID", - "SEID", - ]; - - let combined_string = process_output(&system_profiler_output, &targets); - - if combined_string.is_empty() { - return Err(MIDError::ResultMidError); - } - - Ok(combined_string) - } - Err(_e) => Err(MIDError::ResultMidError), - } -} - -#[cfg(target_os = "macos")] -fn process_output(output_str: &str, targets: &[&str]) -> String { - let mut result = Vec::new(); - - for target in targets { - for line in output_str.to_lowercase().lines() { - if line.contains(&target.to_lowercase()) { - let parts: Vec<&str> = line.split(":").collect(); - - if parts.len() == 2 { - let value = parts[1].trim().to_string(); - - if !value.is_empty() { - result.push(value); - } - } - } - } + if !output.status.success() { + return Err(MIDError::ResultMidError); } - result.join("|") + let uuid = String::from_utf8_lossy(&output.stdout).trim().to_string(); + if uuid.is_empty() { + return Err(MIDError::ResultMidError); + } + + Ok(uuid) } diff --git a/src-tauri/libs/mid-hardware-id/src/windows.rs b/src-tauri/libs/mid-hardware-id/src/windows.rs index 6c877858..285d064d 100644 --- a/src-tauri/libs/mid-hardware-id/src/windows.rs +++ b/src-tauri/libs/mid-hardware-id/src/windows.rs @@ -1,56 +1,32 @@ +#[cfg(target_os = "windows")] +use wmi::{COMLibrary, WMIConnection}; + +#[cfg(target_os = "windows")] +use serde::Deserialize; + #[cfg(target_os = "windows")] use crate::errors::MIDError; #[cfg(target_os = "windows")] -use std::os::windows::process::CommandExt; +#[derive(Deserialize)] +#[allow(non_snake_case)] +struct UUIDGeneric { + UUID: String, +} #[cfg(target_os = "windows")] -use std::process::Command; -use std::process::Stdio; +pub fn get_mid_result() -> Result { + let com_connection = unsafe { COMLibrary::assume_initialized() }; + let wmi_connection = + WMIConnection::new(com_connection.into()).map_err(|_| MIDError::ResultMidError)?; -const CREATE_NO_WINDOW: u32 = 0x08000000; + let computer_uuid_base: Vec = wmi_connection + .raw_query("SELECT UUID from Win32_ComputerSystemProduct WHERE UUID IS NOT NULL") + .map_err(|_| MIDError::ResultMidError)?; -#[cfg(target_os = "windows")] -pub(crate) fn get_mid_result() -> Result { - let combined_output = Command::new("powershell") - .args([ - "-WindowStyle", - "Hidden", - "-command", - r#" - $csproduct = Get-WmiObject Win32_ComputerSystemProduct | Select-Object -ExpandProperty UUID; - $bios = Get-WmiObject Win32_BIOS | Select-Object -ExpandProperty SerialNumber; - $baseboard = Get-WmiObject Win32_BaseBoard | Select-Object -ExpandProperty SerialNumber; - $cpu = Get-WmiObject Win32_Processor | Select-Object -ExpandProperty ProcessorId; - "$csproduct|$bios|$baseboard|$cpu" - "#, - ]) - .creation_flags(CREATE_NO_WINDOW) - .stderr(Stdio::piped()) - .stdout(Stdio::piped()) - .spawn(); - - match combined_output { - Ok(output) => { - let output = output.wait_with_output().unwrap(); - if !output.status.success() { - return Err(MIDError::ResultMidError); - } - let combined_output = String::from_utf8_lossy(&output.stdout); - if combined_output.is_empty() { - return Err(MIDError::ResultMidError); - } - - println!("Device ID: {}", combined_output.trim()); - - Ok( - combined_output - .trim() - .trim_start_matches('|') - .trim_end_matches('|') - .to_lowercase(), - ) - } - Err(_e) => Err(MIDError::ResultMidError), + if let Some(uuid_entry) = computer_uuid_base.first() { + Ok(uuid_entry.UUID.to_string()) + } else { + Err(MIDError::ResultMidError) } }