diff --git a/Cargo.lock b/Cargo.lock index 8677d43..a011c61 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -141,7 +141,9 @@ checksum = "3c6ed94e98ecff0c12dd1b04c15ec0d7d9458ca8fe806cea6f12954efe74c63b" name = "burrow" version = "0.1.0" dependencies = [ + "caps", "clap", + "nix", "tokio", "tun", ] @@ -179,6 +181,16 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "caps" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "190baaad529bcfbde9e1a19022c42781bdb6ff9de25721abdb8fd98c0807730b" +dependencies = [ + "libc", + "thiserror", +] + [[package]] name = "cc" version = "1.0.79" diff --git a/burrow/Cargo.toml b/burrow/Cargo.toml index 8880c8b..92059ba 100644 --- a/burrow/Cargo.toml +++ b/burrow/Cargo.toml @@ -10,3 +10,9 @@ crate-type = ["lib", "staticlib"] tokio = { version = "1.21", features = ["rt", "macros"] } tun = { version = "0.1", path = "../tun" } clap = { version = "4.3.2", features = ["derive"] } + +[target.'cfg(target_os = "linux")'.dependencies] +caps = "0.5.5" + +[target.'cfg(target_os = "macos")'.dependencies] +nix = { version = "0.26.2" } diff --git a/burrow/src/ensureroot.rs b/burrow/src/ensureroot.rs new file mode 100644 index 0000000..8648268 --- /dev/null +++ b/burrow/src/ensureroot.rs @@ -0,0 +1,35 @@ +// Check capabilities on Linux +#[cfg(target_os = "linux")] +pub fn ensure_root() { + use caps::{has_cap, CapSet, Capability}; + + let cap_net_admin = Capability::CAP_NET_ADMIN; + if let Ok(has_cap) = has_cap(None, CapSet::Effective, cap_net_admin) { + if !has_cap { + eprintln!( + "This action needs the CAP_NET_ADMIN permission. Did you mean to run it as root?" + ); + std::process::exit(77); + } + } else { + eprintln!("Failed to check capabilities. Please file a bug report!"); + std::process::exit(71); + } +} + +// Check for root user on macOS +#[cfg(target_os = "macos")] +pub fn ensure_root() { + use nix::unistd::Uid; + + let current_uid = Uid::current(); + if !current_uid.is_root() { + eprintln!("This action must be run as root!"); + std::process::exit(77); + } +} + +#[cfg(target_family = "windows")] +pub fn ensure_root() { + todo!() +} diff --git a/burrow/src/lib.rs b/burrow/src/lib.rs index 7d83484..6abc28f 100644 --- a/burrow/src/lib.rs +++ b/burrow/src/lib.rs @@ -1,3 +1 @@ -pub fn hello_world() { - println!("Hello, world!"); -} +pub mod ensureroot; diff --git a/burrow/src/main.rs b/burrow/src/main.rs index 7ef7530..256f292 100644 --- a/burrow/src/main.rs +++ b/burrow/src/main.rs @@ -23,6 +23,8 @@ enum Commands { struct StartArgs {} async fn try_main() -> Result<()> { + burrow::ensureroot::ensure_root(); + let iface = TunInterface::new()?; println!("{:?}", iface.name()); @@ -31,6 +33,8 @@ async fn try_main() -> Result<()> { #[tokio::main(flavor = "current_thread")] async fn main() { + println!("Platform: {}", std::env::consts::OS); + let cli = Cli::parse(); match &cli.command { Commands::Start(..) => { diff --git a/tun/src/unix/apple/mod.rs b/tun/src/unix/apple/mod.rs index a2a5674..a88078d 100644 --- a/tun/src/unix/apple/mod.rs +++ b/tun/src/unix/apple/mod.rs @@ -6,7 +6,7 @@ use std::io::{IoSlice, Write}; use std::net::{Ipv4Addr, SocketAddrV4}; use std::os::fd::{AsRawFd, RawFd}; use std::{ - io::{Error, Read}, + io::{Error}, mem, }; diff --git a/tun/src/unix/mod.rs b/tun/src/unix/mod.rs index 28b4ec8..8f194b7 100644 --- a/tun/src/unix/mod.rs +++ b/tun/src/unix/mod.rs @@ -71,7 +71,7 @@ mod test { use super::*; use std::io::Write; - use std::io::{self, BufRead}; + use std::net::Ipv4Addr; #[throws]