diff --git a/Cargo.lock b/Cargo.lock index 97eddba..5e323d6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -142,6 +142,29 @@ version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +[[package]] +name = "bindgen" +version = "0.69.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" +dependencies = [ + "bitflags 2.5.0", + "cexpr", + "clang-sys", + "itertools", + "lazy_static", + "lazycell", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn", + "which", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -150,9 +173,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.2" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" [[package]] name = "byteorder" @@ -172,12 +195,32 @@ version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0ba8f7aaa012f30d5b2861462f6708eccd49c3c39863fe083a308035f63d723" +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "clang-sys" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1" +dependencies = [ + "glob", + "libc", + "libloading", +] + [[package]] name = "clap" version = "4.5.1" @@ -326,6 +369,18 @@ dependencies = [ "shell-words", ] +[[package]] +name = "dunce" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" + +[[package]] +name = "either" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" + [[package]] name = "encode_unicode" version = "0.3.6" @@ -450,6 +505,12 @@ version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + [[package]] name = "hashbrown" version = "0.14.3" @@ -496,11 +557,21 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "home" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys 0.52.0", +] + [[package]] name = "hostsfile" version = "1.2.0" dependencies = [ "log", + "selinux", "tempfile", ] @@ -605,6 +676,15 @@ dependencies = [ "serde", ] +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.10" @@ -617,12 +697,28 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + [[package]] name = "libc" version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +[[package]] +name = "libloading" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" +dependencies = [ + "cfg-if", + "windows-targets 0.52.4", +] + [[package]] name = "libsqlite3-sys" version = "0.26.0" @@ -680,6 +776,12 @@ dependencies = [ "autocfg", ] +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.7.2" @@ -814,6 +916,16 @@ dependencies = [ "pin-utils", ] +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "num_cpus" version = "1.16.0" @@ -908,6 +1020,16 @@ dependencies = [ "log", ] +[[package]] +name = "prettyplease" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d3928fb5db768cb86f891ff014f0144589297e3c6a1aba6ed7cecfdace270c7" +dependencies = [ + "proc-macro2", + "syn", +] + [[package]] name = "proc-macro2" version = "1.0.78" @@ -954,6 +1076,12 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "reference-counted-singleton" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "242f841f006fa4f35979f74147f6d0be4402c19ca25b62b1c8e4c02e28288cb9" + [[package]] name = "regex" version = "1.10.3" @@ -989,7 +1117,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "549b9d036d571d42e6e85d1c1425e2ac83491075078ca9a15be021c56b1641f2" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "fallible-iterator", "fallible-streaming-iterator", "hashlink", @@ -1003,6 +1131,12 @@ version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustc_version" version = "0.4.0" @@ -1018,7 +1152,7 @@ version = "0.38.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "errno", "libc", "linux-raw-sys", @@ -1031,12 +1165,47 @@ version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "selinux" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53371b1e9bbbfffd65e5ac3c895c786ec35b7695bdc4a67a8b08c29c8d057e0b" +dependencies = [ + "bitflags 2.5.0", + "libc", + "once_cell", + "reference-counted-singleton", + "selinux-sys", + "thiserror", +] + +[[package]] +name = "selinux-sys" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89d45498373dc17ec8ebb72e1fd320c015647b0157fc81dddf678e2e00205fec" +dependencies = [ + "bindgen", + "cc", + "dunce", + "walkdir", +] + [[package]] name = "semver" version = "1.0.22" @@ -1151,6 +1320,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "smallvec" version = "1.13.1" @@ -1418,6 +1593,16 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "want" version = "0.3.1" @@ -1433,6 +1618,18 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix", +] + [[package]] name = "winapi" version = "0.3.9" diff --git a/README.md b/README.md index d058ef8..272c978 100644 --- a/README.md +++ b/README.md @@ -226,6 +226,12 @@ Note that you'll be responsible for updating manually. ## Development +### Cargo build feature for SELinux + +If your target system uses SELinux, you will want to enable the 'selinux' feature when building the innernet binary. +This will ensure that innernet maintains the correct selinux context on the /etc/hosts file when adding hosts. To do so add ```--features selinux``` to the ```cargo build``` options. +The `selinux-devel` package will need to be installed for the correct headers. + ### `innernet-server` Build dependencies - `rustc` / `cargo` (version 1.50.0 or higher) diff --git a/client/Cargo.toml b/client/Cargo.toml index 09ffb4e..32abf91 100644 --- a/client/Cargo.toml +++ b/client/Cargo.toml @@ -40,6 +40,9 @@ wireguard-control = { path = "../wireguard-control" } once_cell = "1.17.1" tempfile = "3" +[features] +selinux = ["hostsfile/selinux"] + [package.metadata.deb] assets = [ ["target/release/innernet", "usr/bin/", "755"], diff --git a/client/src/main.rs b/client/src/main.rs index 0f7f8e6..67cbf1a 100644 --- a/client/src/main.rs +++ b/client/src/main.rs @@ -15,7 +15,7 @@ use shared::{ RedeemContents, RenameCidrOpts, RenamePeerOpts, State, WrappedIoError, REDEEM_TRANSITION_WAIT, }; use std::{ - fmt, io, + io, net::SocketAddr, path::{Path, PathBuf}, thread, @@ -281,22 +281,6 @@ enum Command { }, } -/// Application-level error. -#[derive(Debug, Clone)] -pub(crate) struct ClientError(String); - -impl fmt::Display for ClientError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.0) - } -} - -impl std::error::Error for ClientError { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - None - } -} - fn update_hosts_file( interface: &InterfaceName, hosts_path: PathBuf, diff --git a/docker-tests/Dockerfile.innernet b/docker-tests/Dockerfile.innernet index 18baab1..d216582 100644 --- a/docker-tests/Dockerfile.innernet +++ b/docker-tests/Dockerfile.innernet @@ -16,13 +16,13 @@ RUN mkdir /repo \ #################################################################################################### FROM rust:slim-bookworm RUN apt-get update && \ - apt-get install -y --no-install-recommends libsqlite3-dev iproute2 iputils-ping build-essential clang libclang-dev && \ + apt-get install -y --no-install-recommends libsqlite3-dev iproute2 iputils-ping build-essential clang libclang-dev libselinux1-dev && \ rm -rf /var/lib/apt/lists/* WORKDIR /app COPY . . -RUN cargo build \ +RUN cargo build --features client/selinux \ && strip /app/target/debug/innernet /app/target/debug/innernet-server \ && cp /app/target/debug/innernet /app/target/debug/innernet-server /usr/bin/ \ && cargo clean diff --git a/hostsfile/Cargo.toml b/hostsfile/Cargo.toml index 77526c0..0fa8bb0 100644 --- a/hostsfile/Cargo.toml +++ b/hostsfile/Cargo.toml @@ -9,6 +9,7 @@ version = "1.2.0" [dependencies] log = "0.4" +selinux = { version = "0.4", optional = true } [dev-dependencies] tempfile = "3" diff --git a/hostsfile/src/lib.rs b/hostsfile/src/lib.rs index 514cc5c..b8844a2 100644 --- a/hostsfile/src/lib.rs +++ b/hostsfile/src/lib.rs @@ -285,6 +285,48 @@ impl HostsBuilder { fn write_and_swap(temp_path: &Path, hosts_path: &Path, contents: &[u8]) -> io::Result<()> { // Copy the file we plan on modifying so its permissions and metadata are preserved. std::fs::copy(hosts_path, temp_path)?; + + #[cfg(feature = "selinux")] + if selinux::current_mode() != selinux::SELinuxMode::NotRunning { + log::trace!("SELinux is running; copying context"); + use selinux::SecurityContext; + + const FOLLOW_SYMBOLIC_LINKS: bool = false; + const RAW_FORMAT: bool = false; + match SecurityContext::of_path(hosts_path, FOLLOW_SYMBOLIC_LINKS, RAW_FORMAT) { + Ok(Some(context)) => { + log::trace!( + "{} context is {:?}", + hosts_path.display(), + context.to_c_string() + ); + if let Err(err) = + context.set_for_path(temp_path, FOLLOW_SYMBOLIC_LINKS, RAW_FORMAT) + { + log::warn!( + "SELinux context of {} ({:?}) could not be set \ + ({} may become inaccessible due to permission errors): {:?}", + temp_path.display(), + context.to_c_string(), + hosts_path.display(), + err + ); + } + }, + Ok(None) => { + log::trace!("Hosts file {} had no SELinux context", hosts_path.display()); + }, + Err(err) => { + log::warn!( + "SELinux context of {} could not be retrieved \ + (file may become inaccessible due to permission errors): {:?}", + hosts_path.display(), + err + ); + }, + } + } + Self::write_clobber(temp_path, contents)?; std::fs::rename(temp_path, hosts_path)?; Ok(()) diff --git a/shared/src/prompts.rs b/shared/src/prompts.rs index 238249a..7855663 100644 --- a/shared/src/prompts.rs +++ b/shared/src/prompts.rs @@ -138,7 +138,7 @@ pub fn rename_cidr( }; let mut new_cidr = old_cidr; - new_cidr.contents.name = new_name.clone(); + new_cidr.contents.name.clone_from(&new_name); Ok( if args.yes