From 06f19043ed516a87e559e358c7549fd814ab7de2 Mon Sep 17 00:00:00 2001 From: hinto-janaiyo Date: Wed, 7 Dec 2022 20:22:08 -0500 Subject: [PATCH] sudo: add [try_wait()] 5 second loop check for sudo --- src/constants.rs | 2 +- src/sudo.rs | 88 ++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 79 insertions(+), 11 deletions(-) diff --git a/src/constants.rs b/src/constants.rs index 96ac1cb..6828d39 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -83,7 +83,7 @@ pub const TOKIO_SECOND: tokio::time::Duration = std::time::Duration::from_secs(1 pub const XMRIG_ADMIN_REASON: &str = r#"The large hashrate difference between XMRig and other miners like Monero and P2Pool's built-in miners is mostly due to XMRig configuring CPU MSRs and setting up hugepages. Other miners like Monero or P2Pool's built-in miner do not do this. It can be done manually but it isn't recommended since XMRig does this for you automatically, but only if it has the proper admin priviledges."#; // Password buttons -pub const PASSWORD_TEXT: &str = "Enter sudo/admin password here..."; +pub const PASSWORD_TEXT: &str = "Enter sudo/admin password..."; pub const PASSWORD_LEAVE: &str = "Return to the previous screen"; pub const PASSWORD_ENTER: &str = "Attempt with the current password"; pub const PASSWORD_HIDE: &str = "Toggle hiding/showing the password"; diff --git a/src/sudo.rs b/src/sudo.rs index 2d50941..807c332 100644 --- a/src/sudo.rs +++ b/src/sudo.rs @@ -20,8 +20,15 @@ // Only gets imported in [main.rs] for Unix. use zeroize::Zeroize; -use std::sync::{Arc,Mutex}; -use std::thread; +use std::{ + thread, + sync::{Arc,Mutex}, + process::*, + io::Write, +}; +use crate::{ + constants::*, +}; use log::*; #[derive(Debug,Clone)] @@ -58,18 +65,79 @@ impl SudoState { info!("Sudo ... Password Wipe OK"); } + // Spawns a thread and tests sudo with the provided password. + // Sudo takes the password through STDIN via [--stdin]. + // Sets the appropriate state fields on success/failure. pub fn test_sudo(state: Arc>) { - std::thread::spawn(move || { + thread::spawn(move || { + // Set to testing state.lock().unwrap().testing = true; - info!("in test_sudo()"); - std::thread::sleep(std::time::Duration::from_secs(3)); - state.lock().unwrap().testing = false; - if state.lock().unwrap().pass == "secret" { - state.lock().unwrap().msg = "Correct!".to_string(); - } else { - state.lock().unwrap().msg = "Incorrect password!".to_string(); + + // Make sure sudo timestamp is reset + let reset = Command::new("sudo") + .arg("--reset-timestamp") + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .stdin(Stdio::piped()) + .status(); + match reset { + Ok(_) => info!("Sudo | Resetting timestamp ... OK"), + Err(e) => { + error!("Sudo | Couldn't reset timestamp: {}", e); + Self::wipe(&state); + state.lock().unwrap().msg = format!("Sudo error: {}", e); + state.lock().unwrap().testing = false; + return + }, } + + // Spawn testing sudo + let mut sudo = Command::new("sudo") + .args(["--stdin", "--validate"]) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .stdin(Stdio::piped()) + .spawn() + .unwrap(); + + // Write pass to STDIN + let mut stdin = sudo.stdin.take().unwrap(); + stdin.write_all(state.lock().unwrap().pass.as_bytes()).unwrap(); + drop(stdin); + + // Sudo re-prompts and will hang. + // To workaround this, try checking + // results for 5 seconds in a loop. + let mut success = false; + for i in 1..=5 { + match sudo.try_wait() { + Ok(Some(code)) => if code.success() { + info!("Sudo | Password ... OK!"); + success = true; + /* spawn xmrig */ + break + }, + Ok(None) => { + info!("Sudo | Waiting [{}/5]...", i); + std::thread::sleep(SECOND); + }, + Err(e) => { + error!("Sudo | Couldn't reset timestamp: {}", e); + Self::wipe(&state); + state.lock().unwrap().msg = format!("Sudo error: {}", e); + state.lock().unwrap().testing = false; + return + }, + } + } + // + state.lock().unwrap().msg = match success { + true => "OK!".to_string(), + false => "Incorrect password!".to_string(), + }; + sudo.kill(); Self::wipe(&state); + state.lock().unwrap().testing = false; }); } }