_aliases.nix (2911B)
1 # modules/features/pentest/_aliases.nix — reach a toolkit's `.py` scripts by 2 # bare name, without taking a name a real tool already owns. 3 # 4 # impacket installs 70 example scripts as `secretsdump.py`, `psexec.py`, 5 # `GetUserSPNs.py`. Muscle memory from Kali wants both `secretsdump.py` and 6 # `secretsdump`, so this symlinks the suffix away — except that impacket also 7 # ships `split.py`, `ping.py`, `net.py`, `reg.py`, `services.py`, `attrib.py` 8 # and `smbclient.py`. Stripping those blindly is not a style question: 9 # environment.systemPackages merges every package into one profile with 10 # buildEnv, so `impacket-aliases/bin/net` and `samba/bin/net` is a hard 11 # collision and the whole system stops building. Before this guard existed the 12 # probe in python.nix failed exactly there. 13 # 14 # So: the `<prefix>-<name>` alias is always made, and the bare one only when no 15 # package in `reservedFrom` (plus `extraReserved`) already owns that name. The 16 # reserved set is read from those packages' bin/ at build time, so it tracks 17 # what is really installed instead of a list that rots. 18 # 19 # secretsdump.py -> secretsdump, impacket-secretsdump (free) 20 # net.py -> impacket-net (samba owns `net`) 21 # 22 # $out/collisions records every name that was held back, so `pentest-cheat` and 23 # a future reviewer can see what moved and why. 24 { lib, pkgs }: 25 { 26 package, 27 prefix, 28 reservedFrom ? [ ], 29 extraReserved ? [ ], 30 }: 31 pkgs.runCommand "${prefix}-aliases" 32 { 33 meta.description = "suffix-free aliases for ${package.pname or prefix}, collision-guarded"; 34 } 35 '' 36 mkdir -p $out/bin 37 : > $out/collisions 38 39 reserved=$( 40 { 41 for d in ${lib.escapeShellArgs (map (p: "${p}/bin") reservedFrom)}; do 42 [ -d "$d" ] && ls -1 "$d" 43 done 44 ${lib.optionalString (extraReserved != [ ]) ''printf '%s\n' ${lib.escapeShellArgs extraReserved}''} 45 } | sort -u 46 ) 47 is_reserved() { printf '%s\n' "$reserved" | grep -qxF "$1"; } 48 49 for f in ${package}/bin/*.py; do 50 [ -e "$f" ] || continue 51 base=$(basename "$f" .py) 52 53 # Always reachable under the prefix, whatever happens to the bare name. 54 ln -s "$f" "$out/bin/${prefix}-$base" 55 56 if is_reserved "$base"; then 57 echo "$base (held back: a real tool owns this name) -> ${prefix}-$base" >> $out/collisions 58 else 59 ln -s "$f" "$out/bin/$base" 60 fi 61 done 62 63 # Belt and braces: assert no bare alias is a reserved name, so a future 64 # change to the logic above fails here rather than at system-rebuild time. 65 for b in $out/bin/*; do 66 n=$(basename "$b") 67 case "$n" in ${prefix}-*) continue ;; esac 68 if is_reserved "$n"; then 69 echo "${prefix}-aliases: bare alias '$n' shadows a real tool" >&2 70 exit 1 71 fi 72 done 73 74 echo "${prefix}-aliases: $(ls -1 $out/bin | wc -l) aliases, $(wc -l < $out/collisions) held back" 75 ''