diff --git a/Cargo.toml b/Cargo.toml index 9415f5ee..fc9616e4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,9 +2,9 @@ members = ["xtask", "rar-common"] [package] -name = "RootAsRole" +name = "rootasrole" # The project version is managed on json file in resources/rootasrole.json -version = "3.0.0" +version = "3.0.2" rust-version = "1.76.0" authors = ["Eddie Billoir "] edition = "2021" @@ -17,6 +17,7 @@ keywords = ["sudo", "capabilities", "rbac", "linux", "security"] categories = ["command-line-utilities", "os::linux-apis", "config"] exclude = ["sudoers-reader/*", "book/*"] + [badges] maintainance ={ status = "actively-maintained", badge = "https://img.shields.io/badge/maintenance-actively%20maintained-brightgreen.svg" } @@ -54,7 +55,7 @@ serde_json = "1.0.128" toml = "0.8.13" [dependencies] -rar-common = { path = "rar-common" } +rar-common = { path = "rar-common", version = "3.0.0", package = "rootasrole-core" } tracing = "0.1.40" tracing-subscriber = "0.3.18" libc = "0.2.159" @@ -84,7 +85,7 @@ const_format = "0.2.33" hex = "0.4.3" [dev-dependencies] -env_logger = "*" +env_logger = "0.11.5" test-log = { version = "0.2.12", features = ["trace"] } tracing = "0.1.37" tracing-subscriber = { version = "0.3.16", default-features = false, features = ["env-filter", "fmt"] } diff --git a/README.md b/README.md index dbe19358..6fd6086f 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@

- +

@@ -16,7 +16,7 @@ -# RootAsRole (V3.0.0) : A memory-safe and security-oriented alternative to sudo/su commands +# RootAsRole (V3.0.2) : A memory-safe and security-oriented alternative to sudo/su commands **RootAsRole** is a project to allow Linux/Unix administrators to delegate their administrative tasks access rights to users. Its main features are : diff --git a/book/src/chsr/README.md b/book/src/chsr/README.md index f7a6ca46..9b8df0a8 100644 --- a/book/src/chsr/README.md +++ b/book/src/chsr/README.md @@ -84,11 +84,13 @@ chsr options path [operation] Environment options: chsr options env [operation] setpolicy [policy] Specify the policy for environment settings (delete-all, keep-all, inherit). - set [key=value,...] Set the policy as delete-all and the key-value map to enforce. + set [key=value,...] Set variables to enforce. + keep-only [key,...] Set the policy as delete-all and the key map to keep. + delete-only [key,...] Set the policy as keep-all and the key map to delete. whitelist, wl [listing] Manage the whitelist for environment settings. blacklist, bl [listing] Manage the blacklist for environment settings. checklist, cl [listing] Manage the checklist for environment settings. (Removed if contains unsafe chars) - + setlist, sl [listing] Manage the setlist for environment settings. (define environment variables) Timeout options: chsr options timeout [operation] diff --git a/book/src/faq.md b/book/src/faq.md index 363fd897..81e3f7e1 100644 --- a/book/src/faq.md +++ b/book/src/faq.md @@ -2,6 +2,12 @@ This page contains known issues and solutions for RootAsRole project. +## Why I cannot do `cargo install rootasrole` command ? + +The `cargo install` command is primarily designed to install Rust binaries into a user’s local environment, specifically into the `.cargo/bin` directory in the user’s home directory. The philosophy behind this is to keep the installation process simple and unprivileged, avoiding system-wide changes that would require administrative privileges. + +RootAsRole is a privilege escalation tool that is designed to be system-wide and with administrative privileges. Therefore, it is not suitable for installation via `cargo install`. Instead, you should install it with the package manager of your distribution or by compiling it from source. The main reason for RootAsRole being on crates.io is to claim the name and warn users when they try to install it via `cargo install`. + ## capable does not work on my OS, what can I do ? capable is a tool based on eBPF features, so it requires a Linux kernel version 4.1 or later. Additionnally you need many kernel features enabled, [described here](https://github.com/iovisor/bcc/blob/master/INSTALL.md#kernel-configuration). It is also, possible that the program cannot allocate memory, in this case you may consider to add CAP_SYS_RESOURCE capability to the program, but this may not solve completely the issue. diff --git a/build.rs b/build.rs index 8a77ea39..c5648460 100644 --- a/build.rs +++ b/build.rs @@ -1,19 +1,25 @@ -use serde_json::Value; -use std::error::Error; -use std::fs::File; -use std::io::{BufRead, BufReader, Write}; +use std::{ + error::Error, + fs::{self, File}, + io::{BufRead, BufReader, Write}, + path::Path, +}; -use std::path::Path; +use toml::Table; -fn write_version<'a>(f: &'a mut File, doc: &'a Value) -> Result<&'a str, Box> { - let package_version = doc - .get("version") - .ok_or("No version found")? +fn package_version>(path: P) -> Result> { + let cargo_toml = fs::read_to_string(path)?; + let value: Table = cargo_toml.parse::()?; + Ok(value["package"]["version"] .as_str() - .unwrap(); + .map(|s| s.to_string()) + .expect("Failed to get package version")) +} + +fn write_version<'a>(f: &'a mut File, package_version: &'a str) -> Result<&'a str, Box> { f.write_all( format!( - "pub const PACKAGE_VERSION: &'static str = \"{}\";\n", + "pub const PACKAGE_VERSION: &str = \"{}\";\n", package_version ) .as_bytes(), @@ -57,59 +63,44 @@ fn set_readme_version(package_version: &str, file: &str) -> Result<(), Box { - if let Err(err) = set_cargo_version(package_version, "Cargo.toml") { - eprintln!("cargo:warning={}", err); - } - //if folder capable/ exists - if Path::new("capable/capable").is_dir() { - if let Err(err) = set_cargo_version(package_version, "capable/capable/Cargo.toml") { - eprintln!("cargo:warning={}", err); - } - if let Err(err) = - set_cargo_version(package_version, "capable/capable-ebpf/Cargo.toml") - { - eprintln!("cargo:warning={}", err); - } - if let Err(err) = - set_cargo_version(package_version, "capable/capable-common/Cargo.toml") - { - eprintln!("cargo:warning={}", err); - } - } - if let Err(err) = set_cargo_version(package_version, "xtask/Cargo.toml") { - eprintln!("cargo:warning={}", err); - } - if let Err(err) = set_readme_version(package_version, "README.md") { - eprintln!("cargo:warning={}", err); - } - //if let Err(err) = set_pkgbuild_version(package_version, "PKGBUILD") { - //eprintln!("cargo:warning={}", err); - //} - } - Err(err) => { - eprintln!("cargo:warning={}", err); - } + write_version(&mut f, &package_version).expect("Failed to write version"); + + if let Err(err) = set_cargo_version(&package_version, "rar-common/Cargo.toml") { + eprintln!("cargo:warning={}", err); } - // let xml = include_str!("resources/rootasrole.xml"); - // if let Err(err) = write_dtd(&mut f, xml) { - // eprintln!("cargo:warning={}", err); - // } + if let Err(err) = set_cargo_version(&package_version, "xtask/Cargo.toml") { + eprintln!("cargo:warning={}", err); + } - f.flush().unwrap(); + if let Err(err) = set_readme_version(&package_version, "README.md") { + eprintln!("cargo:warning={}", err); + } } diff --git a/rar-common/Cargo.toml b/rar-common/Cargo.toml index d9be09b2..f5ef1b64 100644 --- a/rar-common/Cargo.toml +++ b/rar-common/Cargo.toml @@ -1,7 +1,9 @@ [package] -name = "rar-common" -version = "0.1.0" +name = "rootasrole-core" +version = "3.0.2" edition = "2021" +description = "This core crate contains the RBAC and main features for the RootAsRole project." +license = "GPL-3.0-or-later" [dependencies] tracing = "0.1.40" @@ -27,7 +29,7 @@ once_cell = "1.19.0" hex = "0.4.3" [dev-dependencies] -env_logger = "*" +env_logger = "0.11.5" test-log = { version = "0.2.12", features = ["trace"] } tracing = "0.1.37" tracing-subscriber = { version = "0.3.16", default-features = false, features = ["env-filter", "fmt"] } @@ -37,4 +39,4 @@ pcre2 = ["dep:pcre2"] finder = ["dep:glob"] [lints.rust] -unexpected_cfgs = { level = "allow", check-cfg = ['cfg(tarpaulin_include)'] } \ No newline at end of file +unexpected_cfgs = { level = "allow", check-cfg = ['cfg(tarpaulin_include)'] } diff --git a/rar-common/src/database/migration.rs b/rar-common/src/database/migration.rs index 9a1b2389..85c4625b 100644 --- a/rar-common/src/database/migration.rs +++ b/rar-common/src/database/migration.rs @@ -91,6 +91,7 @@ impl Migration { while migrated == ChangeResult::UpgradeIndirect || migrated == ChangeResult::DowngradeIndirect { + migrated = ChangeResult::None; for migration in migrations { match migration.change(doc, &from, &to)? { ChangeResult::UpgradeDirect | ChangeResult::DowngradeDirect => { @@ -123,6 +124,7 @@ impl Migration { /// If the version is already the current version, nothing is done. /// If the version is older, the database is upgraded. /// If the version is newer, the database is downgraded. + /// Returns true if the database was migrated, false if it was already at the current version. pub fn migrate( version: &Version, doc: &mut T, diff --git a/rar-common/src/database/mod.rs b/rar-common/src/database/mod.rs index 793ab580..0fdadcbd 100644 --- a/rar-common/src/database/mod.rs +++ b/rar-common/src/database/mod.rs @@ -69,12 +69,14 @@ pub fn read_json_config( )?; let versionned_config: Versioning>> = serde_json::from_reader(file)?; let config = versionned_config.data; - if Migration::migrate( + if let Ok(true) = Migration::migrate( &versionned_config.version, &mut *config.as_ref().borrow_mut(), versionning::JSON_MIGRATIONS, - )? { + ) { save_json(settings.clone(), config.clone())?; + } else { + debug!("No migrations needed"); } make_weak_config(&config); Ok(config) diff --git a/rar-common/src/database/versionning.rs b/rar-common/src/database/versionning.rs index 787dc01f..f46ec9f5 100644 --- a/rar-common/src/database/versionning.rs +++ b/rar-common/src/database/versionning.rs @@ -33,32 +33,6 @@ impl Default for Versioning { } } -pub(crate) const JSON_MIGRATIONS: &[Migration] = &[ - Migration { - from: || Version::parse("3.0.0-alpha.4").unwrap(), - to: || Version::parse("3.0.0-alpha.5").unwrap(), - up: |_, _| Ok(()), - down: |_, _| Ok(()), - }, - Migration { - from: || Version::parse("3.0.0-alpha.5").unwrap(), - to: || Version::parse("3.0.0").unwrap(), - up: |_, _| Ok(()), - down: |_, _| Ok(()), - }, -]; +pub(crate) const JSON_MIGRATIONS: &[Migration] = &[]; -pub(crate) const SETTINGS_MIGRATIONS: &[Migration] = &[ - Migration { - from: || Version::parse("3.0.0-alpha.4").unwrap(), - to: || Version::parse("3.0.0-alpha.5").unwrap(), - up: |_, _| Ok(()), - down: |_, _| Ok(()), - }, - Migration { - from: || Version::parse("3.0.0-alpha.5").unwrap(), - to: || Version::parse("3.0.0").unwrap(), - up: |_, _| Ok(()), - down: |_, _| Ok(()), - }, -]; +pub(crate) const SETTINGS_MIGRATIONS: &[Migration] = &[]; diff --git a/rar-common/src/lib.rs b/rar-common/src/lib.rs index be1f9af3..6c904e42 100644 --- a/rar-common/src/lib.rs +++ b/rar-common/src/lib.rs @@ -256,12 +256,12 @@ where read_effective(false).or(dac_override_effective(false))?; debug!("{}", serde_json::to_string_pretty(&value)?); let settingsfile = rc_refcell!(value.data); - if Migration::migrate( + if let Ok(true) = Migration::migrate( &value.version, &mut *settingsfile.as_ref().borrow_mut(), SETTINGS_MIGRATIONS, - )? { - Migration::migrate( + ) { + if let Ok(true) = Migration::migrate( &value.version, &mut *settingsfile .as_ref() @@ -270,8 +270,13 @@ where .as_ref() .borrow_mut(), JSON_MIGRATIONS, - )?; - save_settings(settingsfile.clone())?; + ) { + save_settings(settingsfile.clone())?; + } else { + debug!("No config migrations needed"); + } + } else { + debug!("No settings migrations needed"); } Ok(settingsfile) } diff --git a/rar-common/src/version.rs b/rar-common/src/version.rs index ce6ba159..2a6bbc3a 100644 --- a/rar-common/src/version.rs +++ b/rar-common/src/version.rs @@ -1,4 +1,4 @@ // This file is generated by build.rs // Do not edit this file directly // Instead edit build.rs and run cargo build -pub const PACKAGE_VERSION: &str = "3.0.0-alpha.5"; +pub const PACKAGE_VERSION: &str = "3.0.2"; diff --git a/src/chsr/cli/usage.rs b/src/chsr/cli/usage.rs index 47a20a3b..6aa9fa23 100644 --- a/src/chsr/cli/usage.rs +++ b/src/chsr/cli/usage.rs @@ -102,10 +102,13 @@ chsr options path [operation] const RAR_USAGE_OPTIONS_ENV :&str = formatcp!("{UNDERLINE}{BOLD}Environment options:{RST} chsr options env [operation] {BOLD}setpolicy{RST} [policy] Specify the policy for environment settings (delete-all, keep-all, inherit). - {BOLD}set{RST} [key=value,...] Set the policy as delete-all and the key-value map to enforce. + {BOLD}set{RST} [key=value,...] Set variables to enforce. + {BOLD}keep-only{RST} [key,...] Set the policy as delete-all and the key map to keep. + {BOLD}delete-only{RST} [key,...] Set the policy as keep-all and the key map to delete. {BOLD}whitelist, wl{RST} [listing] Manage the whitelist for environment settings. {BOLD}blacklist, bl{RST} [listing] Manage the blacklist for environment settings. {BOLD}checklist, cl{RST} [listing] Manage the checklist for environment settings. (Removed if contains unsafe chars) + {BOLD}setlist, sl{RST} [listing] Manage the setlist for environment settings. (define environment variables) ",UNDERLINE=UNDERLINE, BOLD=BOLD, RST=RST); const RAR_USAGE_OPTIONS_TIMEOUT: &str = formatcp!( diff --git a/src/sr/timeout.rs b/src/sr/timeout.rs index ee4d805c..6475a613 100644 --- a/src/sr/timeout.rs +++ b/src/sr/timeout.rs @@ -159,7 +159,10 @@ fn write_lockfile(lockfile_path: &Path) { .expect("Failed to write to lockfile"); } +#[cfg(not(test))] const TS_LOCATION: &str = "/var/run/rar/ts"; +#[cfg(test)] +const TS_LOCATION: &str = "target/ts"; fn read_cookies(user: &Cred) -> Result, Box> { let path = Path::new(TS_LOCATION).join(user.user.uid.as_raw().to_string()); diff --git a/src/version.rs b/src/version.rs deleted file mode 100644 index e7239f23..00000000 --- a/src/version.rs +++ /dev/null @@ -1,4 +0,0 @@ -// This file is generated by build.rs -// Do not edit this file directly -// Instead edit build.rs and run cargo build -pub const PACKAGE_VERSION: &'static str = "3.0.0"; diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml index 4079b74c..af77b088 100644 --- a/xtask/Cargo.toml +++ b/xtask/Cargo.toml @@ -1,8 +1,9 @@ [package] name = "xtask" # The project version is managed on json file in resources/rootasrole.json -version = "3.0.0" +version = "3.0.2" edition = "2021" +publish = false [[bin]] name = "postinst" diff --git a/xtask/src/installer/build.rs b/xtask/src/installer/build.rs index aa96d931..30f88da3 100644 --- a/xtask/src/installer/build.rs +++ b/xtask/src/installer/build.rs @@ -3,6 +3,8 @@ use std::{fs, os::unix, process::Command}; use anyhow::Context; use tracing::debug; +use crate::util::change_dir_to_git_root; + use super::BuildOptions; fn build_binary( @@ -22,6 +24,7 @@ fn build_binary( } pub fn build(options: &BuildOptions) -> Result<(), anyhow::Error> { + change_dir_to_git_root()?; if options.clean_before { Command::new("cargo") .arg("clean") diff --git a/xtask/src/installer/install.rs b/xtask/src/installer/install.rs index a722f084..6411202c 100644 --- a/xtask/src/installer/install.rs +++ b/xtask/src/installer/install.rs @@ -13,7 +13,7 @@ use strum::EnumIs; use tracing::{debug, error, info}; use crate::installer::Profile; -use crate::util::{detect_priv_bin, BOLD, RED, RST}; +use crate::util::{change_dir_to_git_root, detect_priv_bin, BOLD, RED, RST}; use anyhow::{anyhow, Context}; use super::{CHSR_DEST, SR_DEST}; @@ -199,6 +199,7 @@ pub fn install( .unwrap() )) })?; + change_dir_to_git_root()?; // change to the root of the project before elevating privileges env::set_var("ROOTASROLE_INSTALLER_NESTED", "1"); tracing::warn!("Elevating privileges..."); std::process::Command::new(priv_exe) diff --git a/xtask/src/util.rs b/xtask/src/util.rs index 9de1f866..22a43bdf 100644 --- a/xtask/src/util.rs +++ b/xtask/src/util.rs @@ -3,6 +3,7 @@ use std::{ io, os::{fd::AsRawFd, unix::fs::MetadataExt}, path::Path, + process::Command, }; use anyhow::{anyhow, Context}; @@ -119,6 +120,16 @@ fn read_or_dac_override(effective: bool) -> Result<(), capctl::Error> { Ok(()) } +pub fn change_dir_to_git_root() -> Result<(), anyhow::Error> { + let output = Command::new("git") + .args(&["rev-parse", "--show-toplevel"]) + .output()?; + let git_root = String::from_utf8(output.stdout)?.trim().to_string(); + debug!("Changing directory to git root: {}", git_root); + std::env::set_current_dir(git_root)?; + Ok(()) +} + /// Set or unset the immutable flag on a file /// # Arguments /// * `file` - The file to set the immutable flag on