From a1cbb344fb01300e1ba99efa10d419133df14d39 Mon Sep 17 00:00:00 2001 From: Joseph Hobbs Date: Tue, 13 Aug 2024 10:59:07 -0400 Subject: [PATCH] Enforce root permission on AccessPoint constructor --- Cargo.lock | 19 +++++++++++++++++++ proton_err/src/error.rs | 4 ++++ proton_wap/Cargo.toml | 1 + proton_wap/src/ap.rs | 15 +++++++++++++++ 4 files changed, 39 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 0fe71f4..1058464 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -127,6 +127,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "cidr" version = "0.2.3" @@ -332,6 +338,18 @@ dependencies = [ "tokio-timer", ] +[[package]] +name = "nix" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +dependencies = [ + "bitflags 2.6.0", + "cfg-if 1.0.0", + "cfg_aliases", + "libc", +] + [[package]] name = "nl80211" version = "0.0.2" @@ -584,6 +602,7 @@ name = "proton_wap" version = "0.1.0" dependencies = [ "network-manager", + "nix", "pnet", "proton_cfg", "proton_dev", diff --git a/proton_err/src/error.rs b/proton_err/src/error.rs index 26fdf0b..c1bcb18 100644 --- a/proton_err/src/error.rs +++ b/proton_err/src/error.rs @@ -39,6 +39,9 @@ pub enum ProtonError { /// Could not parse into CIDR range. CouldNotParseAsCidr (String), + /// Root permissions required. + MustHaveRootPermissions, + /// CIDR range must contain network gateway. CidrMustContainGateway { /// Provided CIDR network range. @@ -57,6 +60,7 @@ impl Display for ProtonError { use ProtonError::*; let error = match self { MustBeEthernetInterface => "must be Ethernet interface", + MustHaveRootPermissions => "must execute with root permissions", HotspotNotInitialized => "hotspot not initialized", CouldNotFindWirelessInterface => "could not find wireless interface", CouldNotGetDeviceInformation => "could not get wireless device information", diff --git a/proton_wap/Cargo.toml b/proton_wap/Cargo.toml index f805b43..c318a53 100644 --- a/proton_wap/Cargo.toml +++ b/proton_wap/Cargo.toml @@ -8,6 +8,7 @@ name = "proton_wap" path = "src/lib.rs" [dependencies] +nix = { version = "0.29.0", features = ["user"] } [dependencies.network-manager] path = "../network-manager" diff --git a/proton_wap/src/ap.rs b/proton_wap/src/ap.rs index 0947a7c..83bf456 100644 --- a/proton_wap/src/ap.rs +++ b/proton_wap/src/ap.rs @@ -8,6 +8,8 @@ use network_manager::{ ConnectionState, }; +use nix::unistd::Uid; + use proton_cfg::HotspotConfig; use proton_dev::{ @@ -21,6 +23,14 @@ use proton_err::{ }; /// A wireless access point. +/// +/// **Note**: to construct and use this, you must run the associated +/// binary with root permissions. This is because some of the functionality +/// of the `AccessPoint` structure requires direct control over your +/// device's network interface. +/// +/// This is enforced by `AccessPoint::new()`, as the constructor will return +/// a `ProtonError` if you attempt to execute it without root permission. pub struct AccessPoint { /// Device discovery manager. device_manager: DeviceManager, @@ -44,6 +54,11 @@ impl AccessPoint { wlifname: &str, config: HotspotConfig, ) -> ProtonResult { + // Check if the user is `root` + if !Uid::effective().is_root() { + return Err (ProtonError::MustHaveRootPermissions); + } + // Initialize NetworkManager API let network_manager = NetworkManager::new();