fix(tunnel,aura-gui): macOS TUN auto-assign + admin-access check
Two bugs found in the GUI's first end-to-end test: ## #41 was incomplete — `Some("")` is not the same as `None` for tun-rs The agent's earlier #41 fix passed `""` to `Configuration::tun_name()` expecting the tun crate to treat empty as "let the kernel auto-assign". It doesn't. Looking at tun-0.8.9/src/platform/macos/device.rs: if !tun_name.starts_with("utun") { return Err(Error::InvalidName); } An empty string fails `starts_with("utun")` so the create errors out before the kernel is ever consulted. The auto-assign branch ONLY triggers when `config.tun_name` is `None` — which requires us to skip the `.tun_name()` call entirely, not pass a sentinel value. Fix: split the builder chain so `.tun_name()` is only called when the sanitized name is non-empty. The kernel now correctly auto-picks the next free `utunN` for the standard provisioned `tun_name = "aura0"` config. User-visible symptom this resolves: the GUI's Connect button consistently died with `failed to create TUN device 'aura0'` followed by an InvalidName chain, even though aura was running as root. ## check_admin_access tested the wrong command shape `check_admin_access` ran `sudo -n <aura> --help` and inferred the sudoers entry was installed iff that succeeded. But our sudoers entry is scoped to `<aura> client *` — `<aura> --help` does NOT match, so even when the entry was correctly installed and Connect was already working, the yellow "One-time setup needed" banner stayed up forever. Switched to `sudo -n -l <aura>` which lists matching sudoers entries for the binary path itself. Returns 0 iff ANY entry covers it without a password — works regardless of the per-command scope. ## Verification - `cargo test -p aura-tunnel --lib tun` — all 3 sanitize / create tests pass - Rebuilt `target/release/aura` and `/Applications/Aura.app` against the fixes - Confirmed via `sudo -n -l /Users/xah30/AuraVPN/target/release/aura` that the installed sudoers entry is detectable by the new check 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -221,24 +221,30 @@ fn get_aura_binary_path(state: tauri::State<'_, Arc<AppState>>) -> String {
|
||||
state.aura_binary.lock().display().to_string()
|
||||
}
|
||||
|
||||
/// `true` if `sudo -n <aura> --help` runs without prompting (i.e. the NOPASSWD sudoers entry is
|
||||
/// installed). The UI uses this to gate the "Install admin access" button so the user only sees
|
||||
/// it when it's actually needed.
|
||||
/// `true` if the NOPASSWD sudoers entry for `<aura> client *` is installed and works.
|
||||
///
|
||||
/// We use `sudo -n -l <aura>` which lists the sudoers entries matching the binary path and
|
||||
/// returns 0 iff at least one entry covers it without a password. This is correct even when our
|
||||
/// sudoers fragment is scoped to `<aura> client *` (and so wouldn't match `<aura> --help` —
|
||||
/// that's why the earlier `sudo -n <aura> --help` check kept saying "not installed" while in
|
||||
/// reality the entry was there and Connect was working).
|
||||
#[tauri::command]
|
||||
fn check_admin_access(state: tauri::State<'_, Arc<AppState>>) -> bool {
|
||||
let bin = state.aura_binary.lock().clone();
|
||||
#[cfg(unix)]
|
||||
{
|
||||
match std::process::Command::new("/usr/bin/sudo")
|
||||
let output = std::process::Command::new("/usr/bin/sudo")
|
||||
.arg("-n")
|
||||
.arg("-l")
|
||||
.arg(bin)
|
||||
.arg("--help")
|
||||
.stdin(std::process::Stdio::null())
|
||||
.stdout(std::process::Stdio::null())
|
||||
.stderr(std::process::Stdio::null())
|
||||
.status()
|
||||
{
|
||||
Ok(s) => s.success(),
|
||||
.output();
|
||||
match output {
|
||||
Ok(out) => {
|
||||
// sudo -n -l <cmd> prints the matching entry's command path on stdout when allowed
|
||||
// (e.g. "/usr/local/bin/aura"); on refusal it exits non-zero and prints to stderr.
|
||||
out.status.success()
|
||||
}
|
||||
Err(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user