1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-30 12:37:49 +00:00

Merge pull request #2438 from jhscheer/id_selinux_context

id: add support for showing SELinux context (--context/-Z)
This commit is contained in:
Sylvestre Ledru 2021-08-02 23:36:09 +02:00 committed by GitHub
commit b877486265
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 425 additions and 34 deletions

View file

@ -13,7 +13,7 @@ env:
PROJECT_NAME: coreutils
PROJECT_DESC: "Core universal (cross-platform) utilities"
PROJECT_AUTH: "uutils"
RUST_MIN_SRV: "1.43.1" ## v1.43.0
RUST_MIN_SRV: "1.47.0" ## MSRV v1.47.0
RUST_COV_SRV: "2021-05-06" ## (~v1.52.0) supported rust version for code coverage; (date required/used by 'coverage') ## !maint: refactor when code coverage support is included in the stable channel
on: [push, pull_request]
@ -249,6 +249,8 @@ jobs:
# { os, target, cargo-options, features, use-cross, toolchain }
- { os: ubuntu-latest , target: arm-unknown-linux-gnueabihf , features: feat_os_unix_gnueabihf , use-cross: use-cross }
- { os: ubuntu-latest , target: aarch64-unknown-linux-gnu , features: feat_os_unix_gnueabihf , use-cross: use-cross }
- { os: ubuntu-latest , target: x86_64-unknown-linux-gnu , features: feat_os_unix , use-cross: use-cross }
# - { os: ubuntu-latest , target: x86_64-unknown-linux-gnu , features: feat_selinux , use-cross: use-cross }
# - { os: ubuntu-18.04 , target: i586-unknown-linux-gnu , features: feat_os_unix , use-cross: use-cross } ## note: older windows platform; not required, dev-FYI only
# - { os: ubuntu-18.04 , target: i586-unknown-linux-gnu , features: feat_os_unix , use-cross: use-cross } ## note: older windows platform; not required, dev-FYI only
- { os: ubuntu-18.04 , target: i686-unknown-linux-gnu , features: feat_os_unix , use-cross: use-cross }

198
Cargo.lock generated
View file

@ -73,6 +73,29 @@ dependencies = [
"compare",
]
[[package]]
name = "bindgen"
version = "0.59.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "453c49e5950bb0eb63bb3df640e31618846c89d5b7faa54040d76e98e0134375"
dependencies = [
"bitflags",
"cexpr",
"clang-sys",
"clap",
"env_logger 0.8.4",
"lazy_static",
"lazycell",
"log",
"peeking_take_while",
"proc-macro2",
"quote 1.0.9",
"regex",
"rustc-hash",
"shlex",
"which",
]
[[package]]
name = "bit-set"
version = "0.5.2"
@ -94,6 +117,18 @@ version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]]
name = "bitvec"
version = "0.19.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8942c8d352ae1838c9dda0b0ca2ab657696ef2232a20147cf1b30ae1a9cb4321"
dependencies = [
"funty",
"radium",
"tap",
"wyz",
]
[[package]]
name = "blake2b_simd"
version = "0.5.11"
@ -144,6 +179,15 @@ version = "1.0.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a72c244c1ff497a746a7e1fb3d14bd08420ecda70c8f25c7112f2781652d787"
[[package]]
name = "cexpr"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db507a7679252d2276ed0dd8113c6875ec56d3089f9225b2b42c30cc1f8e5c89"
dependencies = [
"nom",
]
[[package]]
name = "cfg-if"
version = "0.1.10"
@ -169,6 +213,17 @@ dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "clang-sys"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "853eda514c284c2287f4bf20ae614f8781f40a81d32ecda6e91449304dfe077c"
dependencies = [
"glob 0.3.0",
"libc",
"libloading",
]
[[package]]
name = "clap"
version = "2.33.3"
@ -232,6 +287,7 @@ dependencies = [
"rand 0.7.3",
"regex",
"rlimit",
"selinux",
"sha1",
"tempfile",
"textwrap",
@ -582,6 +638,19 @@ dependencies = [
"regex",
]
[[package]]
name = "env_logger"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3"
dependencies = [
"atty",
"humantime",
"log",
"regex",
"termcolor",
]
[[package]]
name = "fake-simd"
version = "0.1.2"
@ -624,6 +693,12 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
[[package]]
name = "funty"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7"
[[package]]
name = "generic-array"
version = "0.8.4"
@ -731,6 +806,12 @@ dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "humantime"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
[[package]]
name = "if_rust_version"
version = "1.0.0"
@ -786,12 +867,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.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ccac4b00700875e6a07c6cde370d44d32fa01c5a65cdd2fca6858c479d28bb3"
[[package]]
name = "libloading"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f84d96438c15fcd6c3f244c8fce01d1e2b9c6b5623e9c711dc9286d8fc92d6a"
dependencies = [
"cfg-if 1.0.0",
"winapi 0.3.9",
]
[[package]]
name = "locale"
version = "0.2.2"
@ -923,6 +1020,18 @@ version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb"
[[package]]
name = "nom"
version = "6.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7413f999671bd4745a7b624bd370a569fb6bc574b23c83a3c5ed2e453f3d5e2"
dependencies = [
"bitvec",
"funty",
"memchr 2.4.0",
"version_check",
]
[[package]]
name = "ntapi"
version = "0.3.6"
@ -1088,6 +1197,12 @@ dependencies = [
"proc-macro-hack",
]
[[package]]
name = "peeking_take_while"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
[[package]]
name = "pkg-config"
version = "0.3.19"
@ -1179,7 +1294,7 @@ version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a44883e74aa97ad63db83c4bf8ca490f02b2fc02f92575e720c8551e843c945f"
dependencies = [
"env_logger",
"env_logger 0.7.1",
"log",
"rand 0.7.3",
"rand_core 0.5.1",
@ -1200,6 +1315,12 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "radium"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8"
[[package]]
name = "rand"
version = "0.5.6"
@ -1368,6 +1489,12 @@ dependencies = [
"redox_syscall 0.2.9",
]
[[package]]
name = "reference-counted-singleton"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e03aec30be874d0786379a6ee483c653c58dd6863ad4ed873e697ed968f9358"
[[package]]
name = "regex"
version = "1.5.4"
@ -1422,6 +1549,12 @@ version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e52c148ef37f8c375d49d5a73aa70713125b7f19095948a923f80afdeb22ec2"
[[package]]
name = "rustc-hash"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "same-file"
version = "1.0.6"
@ -1437,6 +1570,32 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "selinux"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd525eeb189eb26c8471463186bba87644e3d8a9c7ae392adaf9ec45ede574bc"
dependencies = [
"bitflags",
"libc",
"once_cell",
"reference-counted-singleton",
"selinux-sys",
"thiserror",
]
[[package]]
name = "selinux-sys"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d842d177120716580c4c6cb56dfe3c5f3a3e3dcec635091f1b2034b6c0be4c6"
dependencies = [
"bindgen",
"cc",
"dunce",
"walkdir",
]
[[package]]
name = "sha1"
version = "0.6.0"
@ -1468,6 +1627,12 @@ dependencies = [
"generic-array",
]
[[package]]
name = "shlex"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42a568c8f2cd051a4d283bd6eb0343ac214c1b0f1ac19f93e1175b2dee38c73d"
[[package]]
name = "signal-hook"
version = "0.3.9"
@ -1565,6 +1730,12 @@ dependencies = [
"unicode-xid 0.2.2",
]
[[package]]
name = "tap"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
[[package]]
name = "tempfile"
version = "3.2.0"
@ -1598,6 +1769,15 @@ dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "termcolor"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
dependencies = [
"winapi-util",
]
[[package]]
name = "termion"
version = "1.5.6"
@ -2075,6 +2255,7 @@ name = "uu_id"
version = "0.0.7"
dependencies = [
"clap",
"selinux",
"uucore",
"uucore_procs",
]
@ -2837,6 +3018,15 @@ version = "0.10.2+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
[[package]]
name = "which"
version = "3.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d011071ae14a2f6671d0b74080ae0cd8ebf3a6f8c9589a2cd45f23126fe29724"
dependencies = [
"libc",
]
[[package]]
name = "wild"
version = "2.0.4"
@ -2889,6 +3079,12 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "wyz"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214"
[[package]]
name = "xattr"
version = "0.2.2"

View file

@ -1,6 +1,8 @@
# coreutils (uutils)
# * see the repository LICENSE, README, and CONTRIBUTING files for more information
# spell-checker:ignore (libs) libselinux
[package]
name = "coreutils"
version = "0.0.7"
@ -138,6 +140,11 @@ feat_os_unix_musl = [
#
"feat_require_unix",
]
# "feat_selinux" == set of utilities providing support for SELinux Security Context if enabled with `--features feat_selinux`.
# NOTE:
# The selinux(-sys) crate requires `libselinux` headers and shared library to be accessible in the C toolchain at compile time.
# Running a uutils compiled with `feat_selinux` requires an SELinux enabled Kernel at run time.
feat_selinux = ["id/selinux", "selinux"]
## feature sets with requirements (restricting cross-platform availability)
#
# ** NOTE: these `feat_require_...` sets should be minimized as much as possible to encourage cross-platform availability of utilities
@ -229,6 +236,7 @@ clap = { version = "2.33", features = ["wrap_help"] }
lazy_static = { version="1.3" }
textwrap = { version="=0.11.0", features=["term_size"] } # !maint: [2020-05-10; rivy] unstable crate using undocumented features; pinned currently, will review
uucore = { version=">=0.0.9", package="uucore", path="src/uucore" }
selinux = { version="0.1.3", optional = true }
# * uutils
uu_test = { optional=true, version="0.0.7", package="uu_test", path="src/uu/test" }
#

View file

@ -28,7 +28,7 @@ pub fn main() {
if val == "1" && key.starts_with(env_feature_prefix) {
let krate = key[env_feature_prefix.len()..].to_lowercase();
match krate.as_ref() {
"default" | "macos" | "unix" | "windows" => continue, // common/standard feature names
"default" | "macos" | "unix" | "windows" | "selinux" => continue, // common/standard feature names
"nightly" | "test_unimplemented" => continue, // crate-local custom features
"test" => continue, // over-ridden with 'uu_test' to avoid collision with rust core crate 'test'
s if s.starts_with(feature_prefix) => continue, // crate feature sets

View file

@ -1 +1 @@
msrv = "1.43.1"
msrv = "1.47.0"

View file

@ -18,7 +18,11 @@ path = "src/id.rs"
clap = { version = "2.33", features = ["wrap_help"] }
uucore = { version=">=0.0.9", package="uucore", path="../../uucore", features=["entries", "process"] }
uucore_procs = { version=">=0.0.6", package="uucore_procs", path="../../uucore_procs" }
selinux = { version="0.1.3", optional = true }
[[bin]]
name = "id"
path = "src/main.rs"
[features]
feat_selinux = ["selinux"]

View file

@ -5,7 +5,10 @@
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
//
// spell-checker:ignore (ToDO) asid auditid auditinfo auid cstr egid emod euid getaudit getlogin gflag nflag pline rflag termid uflag gsflag zflag cflag
// README:
// This was originally based on BSD's `id`
// (noticeable in functionality, usage text, options text, etc.)
// and synced with:
@ -25,8 +28,10 @@
//
// * Help text based on BSD's `id` manpage and GNU's `id` manpage.
//
// spell-checker:ignore (ToDO) asid auditid auditinfo auid cstr egid emod euid getaudit getlogin gflag nflag pline rflag termid uflag gsflag zflag
// * This passes GNU's coreutils Test suite (8.32) for "tests/id/context.sh" if compiled with
// `--features feat_selinux`. It should also pass "tests/id/no-context.sh", but that depends on
// `uu_ls -Z` being implemented and therefore fails at the moment
//
#![allow(non_camel_case_types)]
#![allow(dead_code)]
@ -35,6 +40,8 @@
extern crate uucore;
use clap::{crate_version, App, Arg};
#[cfg(all(target_os = "linux", feature = "selinux"))]
use selinux;
use std::ffi::CStr;
use uucore::entries::{self, Group, Locate, Passwd};
pub use uucore::libc;
@ -50,6 +57,11 @@ macro_rules! cstr2cow {
static ABOUT: &str = "Print user and group information for each specified USER,
or (when USER omitted) for the current user.";
#[cfg(not(feature = "selinux"))]
static CONTEXT_HELP_TEXT: &str = "print only the security context of the process (not enabled)";
#[cfg(feature = "selinux")]
static CONTEXT_HELP_TEXT: &str = "print only the security context of the process";
mod options {
pub const OPT_AUDIT: &str = "audit"; // GNU's id does not have this
pub const OPT_CONTEXT: &str = "context";
@ -93,6 +105,8 @@ struct State {
gsflag: bool, // --groups
rflag: bool, // --real
zflag: bool, // --zero
cflag: bool, // --context
selinux_supported: bool,
ids: Option<Ids>,
// The behavior for calling GNU's `id` and calling GNU's `id $USER` is similar but different.
// * The SELinux context is only displayed without a specified user.
@ -109,6 +123,7 @@ struct State {
// 1000 10 968 975
// +++ exited with 0 +++
user_specified: bool,
exit_code: i32,
}
pub fn uumain(args: impl uucore::Args) -> i32 {
@ -132,8 +147,21 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
gsflag: matches.is_present(options::OPT_GROUPS),
rflag: matches.is_present(options::OPT_REAL_ID),
zflag: matches.is_present(options::OPT_ZERO),
cflag: matches.is_present(options::OPT_CONTEXT),
selinux_supported: {
#[cfg(feature = "selinux")]
{
selinux::kernel_support() != selinux::KernelSupport::Unsupported
}
#[cfg(not(feature = "selinux"))]
{
false
}
},
user_specified: !users.is_empty(),
ids: None,
exit_code: 0,
};
let default_format = {
@ -141,13 +169,16 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
!(state.uflag || state.gflag || state.gsflag)
};
if (state.nflag || state.rflag) && default_format {
if (state.nflag || state.rflag) && default_format && !state.cflag {
crash!(1, "cannot print only names or real IDs in default format");
}
if (state.zflag) && default_format {
if state.zflag && default_format && !state.cflag {
// NOTE: GNU test suite "id/zero.sh" needs this stderr output:
crash!(1, "option --zero not permitted in default format");
}
if state.user_specified && state.cflag {
crash!(1, "cannot print security context when user specified");
}
let delimiter = {
if state.zflag {
@ -163,7 +194,23 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
'\n'
}
};
let mut exit_code = 0;
if state.cflag {
if state.selinux_supported {
// print SElinux context and exit
#[cfg(all(target_os = "linux", feature = "selinux"))]
if let Ok(context) = selinux::SecurityContext::current(false) {
let bytes = context.as_bytes();
print!("{}{}", String::from_utf8_lossy(bytes), line_ending);
} else {
// print error because `cflag` was explicitly requested
crash!(1, "can't get process context");
}
return state.exit_code;
} else {
crash!(1, "--context (-Z) works only on an SELinux-enabled kernel");
}
}
for i in 0..=users.len() {
let possible_pw = if !state.user_specified {
@ -173,7 +220,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
Ok(p) => Some(p),
Err(_) => {
show_error!("'{}': no such user", users[i]);
exit_code = 1;
state.exit_code = 1;
if i + 1 >= users.len() {
break;
} else {
@ -187,17 +234,17 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
if matches.is_present(options::OPT_PASSWORD) {
// BSD's `id` ignores all but the first specified user
pline(possible_pw.map(|v| v.uid()));
return exit_code;
return state.exit_code;
};
if matches.is_present(options::OPT_HUMAN_READABLE) {
// BSD's `id` ignores all but the first specified user
pretty(possible_pw);
return exit_code;
return state.exit_code;
}
if matches.is_present(options::OPT_AUDIT) {
// BSD's `id` ignores specified users
auditid();
return exit_code;
return state.exit_code;
}
let (uid, gid) = possible_pw.map(|p| (p.uid(), p.gid())).unwrap_or((
@ -217,7 +264,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
if state.nflag {
entries::gid2grp(gid).unwrap_or_else(|_| {
show_error!("cannot find name for group ID {}", gid);
exit_code = 1;
state.exit_code = 1;
gid.to_string()
})
} else {
@ -232,7 +279,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
if state.nflag {
entries::uid2usr(uid).unwrap_or_else(|_| {
show_error!("cannot find name for user ID {}", uid);
exit_code = 1;
state.exit_code = 1;
uid.to_string()
})
} else {
@ -257,7 +304,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
if state.nflag {
entries::gid2grp(id).unwrap_or_else(|_| {
show_error!("cannot find name for group ID {}", id);
exit_code = 1;
state.exit_code = 1;
id.to_string()
})
} else {
@ -276,7 +323,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
}
if default_format {
id_print(&state, groups);
id_print(&mut state, groups);
}
print!("{}", line_ending);
@ -285,7 +332,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
}
}
exit_code
state.exit_code
}
pub fn uu_app() -> App<'static, 'static> {
@ -319,6 +366,7 @@ pub fn uu_app() -> App<'static, 'static> {
Arg::with_name(options::OPT_GROUP)
.short("g")
.long(options::OPT_GROUP)
.conflicts_with(options::OPT_EFFECTIVE_USER)
.help("Display only the effective group ID as a number"),
)
.arg(
@ -328,6 +376,7 @@ pub fn uu_app() -> App<'static, 'static> {
.conflicts_with_all(&[
options::OPT_GROUP,
options::OPT_EFFECTIVE_USER,
options::OPT_CONTEXT,
options::OPT_HUMAN_READABLE,
options::OPT_PASSWORD,
options::OPT_AUDIT,
@ -379,7 +428,8 @@ pub fn uu_app() -> App<'static, 'static> {
Arg::with_name(options::OPT_CONTEXT)
.short("Z")
.long(options::OPT_CONTEXT)
.help("NotImplemented: print only the security context of the process"),
.conflicts_with_all(&[options::OPT_GROUP, options::OPT_EFFECTIVE_USER])
.help(CONTEXT_HELP_TEXT),
)
.arg(
Arg::with_name(options::ARG_USERS)
@ -499,34 +549,80 @@ fn auditid() {
println!("asid={}", auditinfo.ai_asid);
}
fn id_print(state: &State, groups: Vec<u32>) {
fn id_print(state: &mut State, groups: Vec<u32>) {
let uid = state.ids.as_ref().unwrap().uid;
let gid = state.ids.as_ref().unwrap().gid;
let euid = state.ids.as_ref().unwrap().euid;
let egid = state.ids.as_ref().unwrap().egid;
print!("uid={}({})", uid, entries::uid2usr(uid).unwrap());
print!(" gid={}({})", gid, entries::gid2grp(gid).unwrap());
print!(
"uid={}({})",
uid,
entries::uid2usr(uid).unwrap_or_else(|_| {
show_error!("cannot find name for user ID {}", uid);
state.exit_code = 1;
uid.to_string()
})
);
print!(
" gid={}({})",
gid,
entries::gid2grp(gid).unwrap_or_else(|_| {
show_error!("cannot find name for group ID {}", gid);
state.exit_code = 1;
gid.to_string()
})
);
if !state.user_specified && (euid != uid) {
print!(" euid={}({})", euid, entries::uid2usr(euid).unwrap());
print!(
" euid={}({})",
euid,
entries::uid2usr(euid).unwrap_or_else(|_| {
show_error!("cannot find name for user ID {}", euid);
state.exit_code = 1;
euid.to_string()
})
);
}
if !state.user_specified && (egid != gid) {
print!(" egid={}({})", euid, entries::gid2grp(egid).unwrap());
print!(
" egid={}({})",
euid,
entries::gid2grp(egid).unwrap_or_else(|_| {
show_error!("cannot find name for group ID {}", egid);
state.exit_code = 1;
egid.to_string()
})
);
}
print!(
" groups={}",
groups
.iter()
.map(|&gr| format!("{}({})", gr, entries::gid2grp(gr).unwrap()))
.map(|&gr| format!(
"{}({})",
gr,
entries::gid2grp(gr).unwrap_or_else(|_| {
show_error!("cannot find name for group ID {}", gr);
state.exit_code = 1;
gr.to_string()
})
))
.collect::<Vec<_>>()
.join(",")
);
// NOTE: (SELinux NotImplemented) placeholder:
// if !state.user_specified {
// // print SElinux context (does not depend on "-Z")
// print!(" context={}", get_selinux_contexts().join(":"));
// }
#[cfg(all(target_os = "linux", feature = "selinux"))]
if state.selinux_supported
&& !state.user_specified
&& std::env::var_os("POSIXLY_CORRECT").is_none()
{
// print SElinux context (does not depend on "-Z")
if let Ok(context) = selinux::SecurityContext::current(false) {
let bytes = context.as_bytes();
print!(" context={}", String::from_utf8_lossy(bytes));
}
}
}
#[cfg(not(target_os = "linux"))]

View file

@ -17,9 +17,9 @@ fn test_id_no_specified_user() {
let exp_result = unwrap_or_return!(expected_result(&ts, &[]));
let mut _exp_stdout = exp_result.stdout_str().to_string();
#[cfg(target_os = "linux")]
#[cfg(not(feature = "feat_selinux"))]
{
// NOTE: (SELinux NotImplemented) strip 'context' part from exp_stdout:
// NOTE: strip 'context' part from exp_stdout if selinux not enabled:
// example:
// uid=1001(runner) gid=121(docker) groups=121(docker),4(adm),101(systemd-journal) \
// context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
@ -363,3 +363,88 @@ fn test_id_zero() {
}
}
}
#[test]
#[cfg(feature = "feat_selinux")]
fn test_id_context() {
use selinux::{self, KernelSupport};
if selinux::kernel_support() == KernelSupport::Unsupported {
println!("test skipped: Kernel has no support for SElinux context",);
return;
}
let ts = TestScenario::new(util_name!());
for c_flag in &["-Z", "--context"] {
ts.ucmd()
.args(&[c_flag])
.succeeds()
.stdout_only(unwrap_or_return!(expected_result(&ts, &[c_flag])).stdout_str());
for &z_flag in &["-z", "--zero"] {
let args = [c_flag, z_flag];
ts.ucmd()
.args(&args)
.succeeds()
.stdout_only(unwrap_or_return!(expected_result(&ts, &args)).stdout_str());
for &opt1 in &["--name", "--real"] {
// id: cannot print only names or real IDs in default format
let args = [opt1, c_flag];
ts.ucmd()
.args(&args)
.succeeds()
.stdout_only(unwrap_or_return!(expected_result(&ts, &args)).stdout_str());
let args = [opt1, c_flag, z_flag];
ts.ucmd()
.args(&args)
.succeeds()
.stdout_only(unwrap_or_return!(expected_result(&ts, &args)).stdout_str());
for &opt2 in &["--user", "--group", "--groups"] {
// u/g/G n/r z Z
// for now, we print clap's standard response for "conflicts_with" instead of:
// id: cannot print "only" of more than one choice
let args = [opt2, c_flag, opt1];
let _result = ts.ucmd().args(&args).fails();
// let exp_result = unwrap_or_return!(expected_result(&args));
// result
// .stdout_is(exp_result.stdout_str())
// .stderr_is(exp_result.stderr_str())
// .code_is(exp_result.code());
}
}
for &opt2 in &["--user", "--group", "--groups"] {
// u/g/G z Z
// for now, we print clap's standard response for "conflicts_with" instead of:
// id: cannot print "only" of more than one choice
let args = [opt2, c_flag];
let _result = ts.ucmd().args(&args).fails();
// let exp_result = unwrap_or_return!(expected_result(&args));
// result
// .stdout_is(exp_result.stdout_str())
// .stderr_is(exp_result.stderr_str())
// .code_is(exp_result.code());
}
}
}
}
#[test]
#[cfg(unix)]
fn test_id_no_specified_user_posixly() {
// gnu/tests/id/no-context.sh
let ts = TestScenario::new(util_name!());
let result = ts.ucmd().env("POSIXLY_CORRECT", "1").run();
assert!(!result.stdout_str().contains("context="));
if !is_ci() {
result.success();
}
#[cfg(all(target_os = "linux", feature = "feat_selinux"))]
{
use selinux::{self, KernelSupport};
if selinux::kernel_support() == KernelSupport::Unsupported {
println!("test skipped: Kernel has no support for SElinux context",);
} else {
let result = ts.ucmd().succeeds();
assert!(result.stdout_str().contains("context="));
}
}
}