3 Commits

Author SHA1 Message Date
Pierre Warnier 829b37f7a8 completions: add clap_complete shell completion generator (#106)
Feature-gated binary (--features completions) that generates bash/zsh/fish/
elvish/powershell completions from each tool's uu_app() definition.

Usage:
  shadow-rs-completions passwd --shell bash
  shadow-rs-completions --all --shell zsh --dir completions/

Also updates generate-completions.sh to use the new binary and adds
windows-sys skip to deny.toml for transitive clap dep.

Fixes #106
2026-04-03 12:18:18 +02: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 42b501cf2a security: fix TOCTOU, temp permissions, PATH injection; improve Rust idioms
Fixes found by Gemini code review:

Fixes #18 — lock: TOCTOU race eliminated via lock-via-link pattern.
  Write PID to temp file, hard_link() to lock path (atomic POSIX).
  Two processes detecting stale lock simultaneously can't both win.

Fixes #19 — atomic: temp file created with 0o600 from the start.
  Uses OpenOptions::create_new().mode() instead of File::create().
  No window where shadow hashes are world-readable.

Fixes #20 — nscd: absolute paths (/usr/sbin/nscd, /usr/sbin/sss_cache).
  Prevents PATH injection in setuid-root context.

Fixes #21 — error: thiserror derive replaces manual Display/Error impls.
  Less code, less room for mistakes. #[from] for io::Error, #[source]
  for IoPath.

Fixes #22 — parsers: splitn() iterator replaces Vec allocation.
  Zero heap allocation for field splitting on every line.

Fixes #23 — deny.toml: license allowlist + advisory scanning.
  cargo deny check passes (advisories ok, bans ok, licenses ok, sources ok).

142 tests passing on Debian/Alpine/Fedora, zero clippy warnings.
2026-03-23 14:25:19 +01:00