60 Commits

Author SHA1 Message Date
Pierre Warnier e1cf43502a Merge pull request #107 from shadow-utils-rs/feat/integration-tests-release
tests: integration tests for all 14 tools + CHANGELOG for v0.1.0
v0.1.0
2026-03-24 16:07:46 +01:00
Pierre Warnier 7bd47ff3d0 tests: add integration tests for all 14 tools, add CHANGELOG
Add integration tests for the 8 remaining tools:
- useradd, userdel, usermod (user management)
- groupadd, groupdel, groupmod (group management)
- pwck, grpck (file consistency checkers)

101 new tests covering clap parsing, flag conflicts, error paths,
and root-only file mutation operations with synthetic /etc/ files.

Total test count: 461 → 562.

Also adds CHANGELOG.md for v0.1.0 release.
2026-03-24 15:59:04 +01:00
Pierre Warnier caac89485d Merge pull request #105 from shadow-utils-rs/fix/93-104-prod-ready
prod: 11 production-readiness fixes
2026-03-24 15:45:16 +01:00
Pierre Warnier 5d8ac9587d review: address all 13 Copilot review comments
- Fix cargo build --release --workspace in test scripts
- Document setuid-on-symlinks as intentional in Makefile
- Warn (not abort) on subid allocation failure in useradd
- Propagate subid file read errors instead of unwrap_or_default
- Update SELinux docs to describe best-effort behavior
- Add env_clear() to getfattr subprocess in selinux.rs
- Use hardening::sanitized_env() in nscd.rs instead of local reimpl
- Create testuser in pam-e2e.sh, add cleanup
- Document su-as-root limitation in pam-e2e.sh
- Fix set -e exit code capture in gnu-compat.sh
- Add 5 date validation unit tests in chage
- Wire audit::log_user_event into all 7 tools
2026-03-24 15:42:08 +01:00
Pierre Warnier 3fbeaf448c chore: remove Cargo.lock from tracking (library convention) 2026-03-24 15:25:11 +01:00
Pierre Warnier dddd5713ac deps: upgrade nix 0.29 → 0.30 to unify with uucore
Eliminates duplicate nix crate that caused cargo-deny ban failure.
Adapts to nix 0.30 API: fsync/fcntl/fchownat now take AsFd instead
of raw i32 file descriptors; use AT_FDCWD for fchownat.
2026-03-24 15:24:54 +01:00
Pierre Warnier 83080f53dd CI: upgrade cargo-deny-action to v2 for edition 2024 support
The v1 action bundles an old Cargo that doesn't recognize edition 2024.
v2 uses the host toolchain, so we install stable Rust first.
2026-03-24 15:18:07 +01:00
Pierre Warnier 8ba8f940fd prod: GNU compat tests, PAM e2e, setuid, SELinux, audit, packaging
Fixes #93 — GNU compatibility test suite (tests/gnu-compat.sh)
Fixes #94 — PAM end-to-end test script (tests/pam-e2e.sh)
Fixes #95 — Setuid permissions in Makefile (chmod 4755)
Fixes #96 — nscd env_clear() on subprocess spawning
Fixes #97 — SELinux file context support (getfattr/chcon/restorecon)
Fixes #98 — Audit logging to syslog/auditd
Fixes #99 — subuid/subgid allocation in useradd
Fixes #100 — Debian packaging (debian/control, debian/rules)
Fixes #101 — Fedora packaging (shadow-rs.spec)
Fixes #103 — Recursive chown on usermod UID change
Fixes #104 — Proper date validation (Feb 31 rejected)

456 tests, zero clippy warnings. Binary: 894KB (release-small).
2026-03-24 15:15:21 +01:00
Pierre Warnier bcf1eae8a9 Merge pull request #92 from shadow-utils-rs/fix/78-86-88-final
fix: binary <1MB, test helpers, completions
2026-03-24 14:55:12 +01:00
Pierre Warnier 748f0ad88d fix: binary size <1MB, shared test helpers, shell completions
Fixes #78 — Binary size: release-small profile achieves 894KB (<1MB).
  Default release also shrank from 1.5MB to 1.3MB thanks to
  panic=abort + codegen-units=1 from PR #91.

Fixes #86 — Shared test helper crate at tests/common/mod.rs with
  skip_unless_root(), setup_prefix(), setup_full_prefix(), read_file().

Fixes #88 — Shell completion script at util/generate-completions.sh
  (placeholder — generates minimal bash/zsh/fish completions).

456 tests, zero clippy warnings.
2026-03-24 14:48:37 +01:00
Pierre Warnier 20afe8c73b Merge pull request #91 from shadow-utils-rs/fix/79-90-uutils-compliance
infra: uutils compliance — edition 2024, unsafe deny, dead_code deny
2026-03-24 14:44:24 +01:00
Pierre Warnier 9e3faa966c address Copilot review: fix docs, feature-gate crypt, MSRV 1.94, CI msrv job 2026-03-24 14:43:38 +01:00
Pierre Warnier 896a4214b6 infra: uutils compliance — edition 2024, unsafe deny, dead_code deny
Fixes #79 — CODE_OF_CONDUCT.md (Contributor Covenant 2.1)
Fixes #80 — locales/en-US.ftl for all 14 tools
Fixes #81 — rust-version = "1.85.0" in workspace
Fixes #82 — edition 2024 (resolver 3, unsafe extern blocks)
Fixes #83 — GitHub Actions CI (fmt, clippy, test, cargo-deny)
Fixes #84 — .clippy.toml with MSRV and quality thresholds
Fixes #85 — deny.toml tightened (multiple-versions=deny)
Fixes #87 — panic=abort, codegen-units=1 in release profile
Fixes #89 — Makefile with install/uninstall/clean targets
Fixes #90 — workspace lints: cargo group, unused_qualifications

Key policy changes enforced by cargo:
- unsafe_code = "deny" workspace-wide. Only pam.rs and crypt.rs
  have #[allow(unsafe_code)] (C FFI boundaries).
- dead_code = "deny" workspace-wide. No unused code allowed.
- Edition 2024: set_var/remove_var are unsafe, so sanitize_env
  returns a Vec instead of mutating. Signal handler removed
  (was unsafe). localtime_r replaced with pure Rust calendar math.

456 tests, zero clippy warnings.
2026-03-24 14:30:22 +01:00
Pierre Warnier a6e6ef63b2 Merge pull request #77 from shadow-utils-rs/fix/56-67-69-70-remaining
docs/fixes: man pages, benchmarks, BSD research, Copilot findings
2026-03-24 13:12:34 +01:00
Pierre Warnier 81d0e1776d docs/fixes: man pages, benchmarks, BSD research, Copilot findings
Fixes #56 — 14 man pages in docs/man/ (markdown format).
Fixes #67 — 8 Copilot findings fixed:
  - useradd: proper date validation (Feb 31 rejected)
  - userdel/usermod: --root wired to SysRoot
  - usermod: --expiredate validates input
  - usermod: --login validates name + updates shadow/group
  - userdel: -f separated from -r behavior
  - useradd: home dir resolved through SysRoot
  - skel: preserves directory permissions
Fixes #69 — benchmark script (benches/benchmark.sh)
Fixes #70 — FreeBSD/NetBSD reference (docs/FREEBSD-NETBSD-REFERENCE.md)

456 tests, zero clippy warnings.
2026-03-24 13:05:40 +01:00
Pierre Warnier cdf13a8ed3 Merge pull request #76 from shadow-utils-rs/fix/75-gshadow-lock
security: add gshadow lock in useradd (Codex finding)
2026-03-24 12:38:55 +01:00
Pierre Warnier 688dd7f2fd security: add gshadow lock in useradd write_new_gshadow
Fixes #75 — found by Codex (GPT-5.4) and Copilot.

write_new_gshadow now acquires FileLock on gshadow_path before
atomic_write. Prevents concurrent groupmod/useradd from silently
overwriting each other's gshadow changes.
2026-03-24 12:33:11 +01:00
Pierre Warnier 4c92f922c4 Merge pull request #74 from shadow-utils-rs/fix/73-gemini-round3
security: fix 5 Gemini round 3 findings
2026-03-24 12:04:53 +01:00
Pierre Warnier 9242fe4993 security: fix 5 Gemini round 3 findings
Fixes #73

Critical: useradd lock-then-read (hold lock across all file ops).
Medium: skel only copies regular files (skip FIFOs/devices).
Medium: lock PID file uses create_new (O_EXCL, no symlink follow).
Medium: usermod validates group names before mutation.
Medium: userdel canonicalizes paths before protected-dir check.

436 tests, zero clippy warnings.
2026-03-24 11:58:48 +01:00
Pierre Warnier f8fc2118b8 Merge pull request #72 from shadow-utils-rs/fix/71-gemini-phase2-3-findings
security: fix 10 Gemini findings, deduplicate hardening
2026-03-24 11:47:34 +01:00
Pierre Warnier c66e9c9374 security: fix 10 Gemini findings, deduplicate hardening boilerplate
Fixes #71

Critical:
- userdel: reads actual home dir from passwd BEFORE deleting entry
- userdel: safe recursive delete (refuses /, mount points, symlinks)

High:
- chage: pure calendar date parsing (no mktime timezone dependency)
- chpasswd: passwords zeroed via zeroize after use
- All 14 tools: hardening functions moved to shadow_core::hardening
  module (-506 lines duplicated boilerplate, +69 shared module)

Medium:
- useradd: create_dir instead of check-then-create (TOCTOU fix)
- newgrp: password read from /dev/tty with echo disabled
- usermod: chown home directory when UID changes

Low:
- pwck/grpck: documented that sorting strips comments
- chpasswd: passwords use Zeroizing<String>

436 tests, zero clippy warnings. Net -159 lines.
2026-03-24 11:38:12 +01:00
Pierre Warnier b4fe23f158 Merge pull request #68 from shadow-utils-rs/feat/phase3-group-management
phase3: all 7 remaining tools — shadow-rs complete
2026-03-24 10:55:23 +01:00
Pierre Warnier 8ee65a7552 phase3: implement groupadd, groupdel, groupmod, grpck, chfn, chsh, newgrp
All 14 shadow-utils tools are now implemented.

groupadd: create groups with auto GID allocation, system groups, force mode.
groupdel: delete groups, checks for primary group usage.
groupmod: modify GID, rename, password changes.
grpck: verify /etc/group and /etc/gshadow integrity.
chfn: change GECOS sub-fields (name, room, phone).
chsh: change login shell with /etc/shells validation.
newgrp: change effective group with crypt(3) password verification.

449 tests, zero clippy warnings, all 14 tools in multicall binary.
2026-03-24 10:47:07 +01:00
Pierre Warnier b3a3041726 Merge pull request #66 from shadow-utils-rs/feat/phase2-user-management
phase2: useradd, userdel, usermod, chpasswd, chage
2026-03-24 10:29:42 +01:00
Pierre Warnier ed5bb0b71a phase2: implement useradd, userdel, usermod, chpasswd, chage
Fixes #57 — useradd: create user accounts with all core flags
  (-c, -d, -e, -f, -g, -G, -m, -M, -k, -N, -o, -p, -r, -s, -u, -U).
  UID/GID allocation, home dir creation, skel copy, shadow entry.

Fixes #62 — userdel: remove user from passwd/shadow/group/gshadow.
  Flags: -f, -r, -P. Removes from membership lists.

Fixes #63 — usermod: modify user properties.
  Flags: -c, -d, -e, -f, -g, -G, -a, -L, -U, -l, -s, -u, -P.
  Lock/unlock via shadow, group membership management.

Fixes #64 — chpasswd: batch password change from stdin.
  Reads username:password pairs, updates /etc/shadow.
  Supports -e (pre-encrypted), -R (chroot).

Fixes #65 — chage: password aging management.
  All flags: -d, -E, -I, -l, -m, -M, -R, -W.
  List mode (-l) shows aging info. Matches GNU output format.

364 tests, zero clippy warnings.
2026-03-24 10:19:52 +01:00