From bbfd877ee55485fc3f933a2e9c93e40a95cb836c Mon Sep 17 00:00:00 2001 From: fatalerrors Date: Tue, 2 Jun 2026 13:54:42 +0200 Subject: [PATCH] added wildcard support in rmhost --- profile.d/ssh.sh | 51 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/profile.d/ssh.sh b/profile.d/ssh.sh index 7bcf65e..064f688 100644 --- a/profile.d/ssh.sh +++ b/profile.d/ssh.sh @@ -52,10 +52,13 @@ rmhost() case "$1" in -h|--help) printf "rmhost: Remove host/IP from known_hosts files.\n\n" - printf "Usage: rmhost [--all-users] [hostname2|ip2 ...]\n\n" + printf "Usage: rmhost [--all-users] [pattern2|ip2 ...]\n\n" printf "Options:\n" printf " -a, --all-users Remove entries from all local users when run as root\n" - printf " -h, --help Display this help screen\n" + printf " -h, --help Display this help screen\n\n" + printf "Wildcards:\n" + printf " Glob patterns (*, ?, [...]) are expanded against unhashed known_hosts entries.\n" + printf " Hashed entries (prefixed with |1|) are never matched by wildcards.\n" return 0 ;; -a|--all-users) @@ -106,6 +109,50 @@ rmhost() fi for target in "$@"; do + # Wildcard: expand glob pattern against unhashed known_hosts entries + if [[ "$target" == *['*?[']* ]]; then + local -a _matched=() + local _wf _wl _wfield _whost _wmatch + local -a _wentries + for _wf in "${known_hosts_files[@]}"; do + [[ -f "$_wf" ]] || continue + while IFS= read -r _wl; do + [[ -z "$_wl" || "$_wl" == '#'* || "$_wl" == '|'* ]] && continue + _wfield="${_wl%% *}" + IFS=',' read -ra _wentries <<< "$_wfield" + for _whost in "${_wentries[@]}"; do + # Strip [host]:port notation to get the bare name for matching + if [[ "$_whost" == '['*']:'* ]]; then + _wmatch="${_whost#[}" + _wmatch="${_wmatch%%]:*}" + else + _wmatch="$_whost" + fi + # shellcheck disable=SC2053 + [[ "$_wmatch" == $target ]] && _matched+=("$_whost") + done + done < "$_wf" + done + + mapfile -t _matched < <(printf '%s\n' "${_matched[@]}" | sort -u) + + if [[ ${#_matched[@]} -eq 0 ]]; then + disp W "No known_hosts entries match pattern '$target'." + continue + fi + + local _key _known_hosts_file + for _key in "${_matched[@]}"; do + for _known_hosts_file in "${known_hosts_files[@]}"; do + disp I "Removing '$_key' from $_known_hosts_file..." + if ! ssh-keygen -R "$_key" -f "$_known_hosts_file" >/dev/null 2>&1; then + disp W "No known_hosts entry found for '$_key' in '$_known_hosts_file'." + fi + done + done + continue + fi + local hst="$target" local ip="" local v4=1