fix(sudo): prevent sudo_command = "sudo" finding gsudo
This commit is contained in:
65
src/sudo.rs
65
src/sudo.rs
@@ -5,7 +5,6 @@ use std::path::PathBuf;
|
|||||||
use color_eyre::eyre::Context;
|
use color_eyre::eyre::Context;
|
||||||
use color_eyre::eyre::Result;
|
use color_eyre::eyre::Result;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use strum::AsRefStr;
|
|
||||||
use strum::Display;
|
use strum::Display;
|
||||||
|
|
||||||
use crate::command::CommandExt;
|
use crate::command::CommandExt;
|
||||||
@@ -38,36 +37,32 @@ pub struct SudoExecuteOpts<'a> {
|
|||||||
pub user: Option<&'a str>,
|
pub user: Option<&'a str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sudo {
|
#[cfg(not(target_os = "windows"))]
|
||||||
/// Get the `sudo` binary or the `gsudo` binary in the case of `gsudo`
|
const DETECT_ORDER: [SudoKind; 5] = [
|
||||||
/// masquerading as the `sudo` binary.
|
SudoKind::Doas,
|
||||||
fn determine_sudo_variant(sudo_p: PathBuf) -> (PathBuf, SudoKind) {
|
SudoKind::Sudo,
|
||||||
match which("gsudo") {
|
SudoKind::Pkexec,
|
||||||
Some(gsudo_p) => {
|
SudoKind::Run0,
|
||||||
match std::fs::canonicalize(&gsudo_p).unwrap() == std::fs::canonicalize(&sudo_p).unwrap() {
|
SudoKind::Please,
|
||||||
true => (gsudo_p, SudoKind::Gsudo),
|
];
|
||||||
false => (sudo_p, SudoKind::Sudo),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => (sudo_p, SudoKind::Sudo),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
const DETECT_ORDER: [SudoKind; 2] = [SudoKind::Gsudo, SudoKind::Sudo];
|
||||||
|
|
||||||
|
impl Sudo {
|
||||||
/// Get the `sudo` binary for this platform.
|
/// Get the `sudo` binary for this platform.
|
||||||
pub fn detect() -> Option<Self> {
|
pub fn detect() -> Option<Self> {
|
||||||
which("doas")
|
for kind in DETECT_ORDER {
|
||||||
.map(|p| (p, SudoKind::Doas))
|
if let Some(path) = kind.which() {
|
||||||
.or_else(|| which("sudo").map(Self::determine_sudo_variant))
|
return Some(Self { path, kind });
|
||||||
.or_else(|| which("gsudo").map(|p| (p, SudoKind::Gsudo)))
|
}
|
||||||
.or_else(|| which("pkexec").map(|p| (p, SudoKind::Pkexec)))
|
}
|
||||||
.or_else(|| which("run0").map(|p| (p, SudoKind::Run0)))
|
None
|
||||||
.or_else(|| which("please").map(|p| (p, SudoKind::Please)))
|
|
||||||
.map(|(path, kind)| Self { path, kind })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create Sudo from SudoKind, if found in the system
|
/// Create Sudo from SudoKind, if found in the system
|
||||||
pub fn new(kind: SudoKind) -> Option<Self> {
|
pub fn new(kind: SudoKind) -> Option<Self> {
|
||||||
which(kind.as_ref()).map(|path| Self { path, kind })
|
kind.which().map(|path| Self { path, kind })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the path to the `sudo` binary. Do not use this to execute `sudo` directly - either use
|
/// Gets the path to the `sudo` binary. Do not use this to execute `sudo` directly - either use
|
||||||
@@ -277,7 +272,7 @@ impl Sudo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Display, Deserialize, AsRefStr)]
|
#[derive(Clone, Copy, Debug, Display, Deserialize)]
|
||||||
#[serde(rename_all = "lowercase")]
|
#[serde(rename_all = "lowercase")]
|
||||||
#[strum(serialize_all = "lowercase")]
|
#[strum(serialize_all = "lowercase")]
|
||||||
pub enum SudoKind {
|
pub enum SudoKind {
|
||||||
@@ -288,3 +283,23 @@ pub enum SudoKind {
|
|||||||
Run0,
|
Run0,
|
||||||
Please,
|
Please,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl SudoKind {
|
||||||
|
fn binary_name(self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
SudoKind::Doas => "doas",
|
||||||
|
SudoKind::Sudo if cfg!(not(target_os = "windows")) => "sudo",
|
||||||
|
// on windows, hardcode the sudo path to ensure we find Windows Sudo
|
||||||
|
// rather than gsudo masquerading as sudo
|
||||||
|
SudoKind::Sudo => r"C:\Windows\System32\sudo.exe",
|
||||||
|
SudoKind::Gsudo => "gsudo",
|
||||||
|
SudoKind::Pkexec => "pkexec",
|
||||||
|
SudoKind::Run0 => "run0",
|
||||||
|
SudoKind::Please => "please",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn which(self) -> Option<PathBuf> {
|
||||||
|
which(self.binary_name())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user