Skip to content

Commit

Permalink
feat(pkexec): elevate privileges only if necessary
Browse files Browse the repository at this point in the history
  • Loading branch information
NotAShelf committed Mar 18, 2024
1 parent 8d7d8dc commit 7fcdd5a
Show file tree
Hide file tree
Showing 5 changed files with 151 additions and 26 deletions.
99 changes: 98 additions & 1 deletion Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ resvg = "0.40.0"
serde = {version = "1.0", features = ["derive"]}
serde_json = "1.0"
which = "6.0"
whoami = "1.5.1"
wl-clipboard-rs = "0.8"
14 changes: 12 additions & 2 deletions src/pkexec.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::path::PathBuf;
use which::which;
use whoami::username;

pub fn get_pkexec_path() -> PathBuf {
match which("pkexec") {
Expand All @@ -8,6 +9,15 @@ pub fn get_pkexec_path() -> PathBuf {
}
}

pub fn pkexec_found(pkexec_path: &PathBuf) -> bool {
pkexec_path.is_file()
// We don't need to elevate privileges if we're using the Tray service
// as the root user. This shouldn't really happen, but it's possible
// depending on how Tailran is ran.
pub fn should_elevate_perms() -> bool {
let parent_user = username().to_string();

if parent_user.eq("root") {
return false;
}

true
}
14 changes: 8 additions & 6 deletions src/tailscale/status.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,17 +42,19 @@ pub fn get_status_json() -> String {
}

pub fn get_status() -> Result<Status, serde_json::Error> {
let mut st: Status = serde_json::from_str(get_status_json().as_str())?;
let dnssuffix = st.magic_dnssuffix.to_owned();
st.tailscale_up = match st.backend_state.as_str() {
let mut status: Status = serde_json::from_str(get_status_json().as_str())?;
let dnssuffix = status.magic_dnssuffix.to_owned();
status.tailscale_up = match status.backend_state.as_str() {
"Running" => true,
"Stopped" => false,
_ => false,
};

dns::dns_or_quote_hostname(&mut st.this_machine, &dnssuffix);
st.peers
dns::dns_or_quote_hostname(&mut status.this_machine, &dnssuffix);
status
.peers
.values_mut()
.for_each(|m: &mut Machine| dns::dns_or_quote_hostname(m, &dnssuffix));
Ok(st)

Ok(status)
}
49 changes: 32 additions & 17 deletions src/tray/menu.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::pkexec::{get_pkexec_path, pkexec_found};
use crate::pkexec::{get_pkexec_path, should_elevate_perms};
use crate::svg::renderer::ResvgRenderer;
use crate::tailscale::peer::copy_peer_ip;
use crate::tailscale::status::{get_current_status, Status};
Expand Down Expand Up @@ -46,19 +46,34 @@ impl SysTray {

fn do_service_link(&mut self, verb: &str) {
let pkexec_path = get_pkexec_path();
let elevate = should_elevate_perms();
let command = if elevate {
info!("Elevating permissions for pkexec.");
Command::new(pkexec_path)
.arg("tailscale")
.arg(verb)
.stdout(Stdio::piped())
.spawn()
} else {
Command::new("tailscale")
.arg(verb)
.stdout(Stdio::piped())
.spawn()
};

// Check if command was successfully created
let command = match command {
Ok(cmd) => cmd,
Err(err) => {
// Handle error appropriately, e.g., log and return early or panic
panic!("Failed to execute process: {:?}", err);
}
};

// TODO: consider using https://stackoverflow.com/a/66292796/554150
// or async? https://rust-lang.github.io/async-book/03_async_await/01_chapter.html
let child = Command::new(pkexec_path)
.arg("tailscale")
.arg(verb)
.stdout(Stdio::piped())
.spawn()
.expect("Failed to execute process");
let output = command.wait_with_output().expect("Failed to read stdout");

let output = child.wait_with_output().expect("Failed to read stdout");
info!(
"link {}: [{}]{}",
"Link {}: [{}]{}",
&verb,
output.status,
String::from_utf8_lossy(&output.stdout)
Expand All @@ -70,11 +85,15 @@ impl SysTray {
} else {
"disconnected"
};

// send notification through dbus
let _result = Notification::new()
.summary(format!("Connection {}", verb).as_str())
.body(format!("Tailscale service {verb_result}").as_str())
.icon("info")
.show();

// update status
self.update_status();
}
}
Expand Down Expand Up @@ -116,10 +135,6 @@ impl Tray for SysTray {
}

fn menu(&self) -> Vec<MenuItem<Self>> {
// TODO: build pkexec_exists into pkexec_path by failing early
// if pkexec cannot be found
let pkexec_path = get_pkexec_path();
let pkexec_exist: bool = pkexec_found(&pkexec_path);
let my_ip = self.ctx.ip.clone();

let mut my_sub = Vec::new();
Expand Down Expand Up @@ -147,7 +162,7 @@ impl Tray for SysTray {
label: "Connect".into(),
icon_name: "network-transmit-receive".into(),
enabled: !self.enabled(),
visible: pkexec_exist,
visible: true,
activate: Box::new(|this: &mut Self| this.do_service_link("up")),
..Default::default()
}
Expand All @@ -156,7 +171,7 @@ impl Tray for SysTray {
label: "Disconnect".into(),
icon_name: "network-offline".into(),
enabled: self.enabled(),
visible: pkexec_exist,
visible: true,
activate: Box::new(|this: &mut Self| this.do_service_link("down")),
..Default::default()
}
Expand Down

0 comments on commit 7fcdd5a

Please sign in to comment.