1
0
mirror of https://github.com/tw93/Mole.git synced 2026-03-22 18:30:08 +00:00

fix: pass through sudo's native prompt instead of hardcoding 'Password:' (#599)

* pass through sudo prompt instead of hardcoding Password:

* simplify: remove redundant retry loop, sudo handles retries internally

* keep stty safety net and styled prefix

* fix: clear clamshell sudo prompt lines correctly

---------

Co-authored-by: Tw93 <hitw93@gmail.com>
This commit is contained in:
Yuval Dinodia
2026-03-20 19:33:44 -04:00
committed by GitHub
parent 2c2249b9a5
commit 7403f4d35e
2 changed files with 70 additions and 44 deletions

View File

@@ -44,59 +44,25 @@ is_clamshell_mode() {
_request_password() {
local tty_path="$1"
local attempts=0
local show_hint=true
# Extra safety: ensure sudo cache is cleared before password input
sudo -k 2> /dev/null
# Save original terminal settings and ensure they're restored on exit
local stty_orig
stty_orig=$(stty -g < "$tty_path" 2> /dev/null || echo "")
trap '[[ -n "${stty_orig:-}" ]] && stty "${stty_orig:-}" < "$tty_path" 2> /dev/null || true' RETURN
while ((attempts < 3)); do
local password=""
# Show hint on first attempt about Touch ID appearing again
if [[ $show_hint == true ]] && check_touchid_support; then
if check_touchid_support; then
echo -e "${GRAY}Note: Touch ID dialog may appear once more, just cancel it${NC}" > "$tty_path"
show_hint=false
fi
printf "${PURPLE}${ICON_ARROW}${NC} Password: " > "$tty_path"
echo -e "${PURPLE}${ICON_ARROW}${NC} Enter your credentials:" > "$tty_path"
# Disable terminal echo to hide password input (keep canonical mode for reliable input)
stty -echo < "$tty_path" 2> /dev/null || true
IFS= read -r password < "$tty_path" || password=""
# Restore terminal echo immediately
stty echo < "$tty_path" 2> /dev/null || true
printf "\n" > "$tty_path"
if [[ -z "$password" ]]; then
unset password
attempts=$((attempts + 1))
if [[ $attempts -lt 3 ]]; then
echo -e "${GRAY}${ICON_WARNING}${NC} Password cannot be empty" > "$tty_path"
fi
continue
fi
# Verify password with sudo
# NOTE: macOS PAM will trigger Touch ID before password auth - this is system behavior
if printf '%s\n' "$password" | sudo -S -p "" -v > /dev/null 2>&1; then
unset password
# shellcheck disable=SC2024,SC2094
# Intentionally route sudo's native prompt to the same TTY device it reads from.
if sudo -v < "$tty_path" > /dev/null 2> "$tty_path"; then
return 0
fi
unset password
attempts=$((attempts + 1))
if [[ $attempts -lt 3 ]]; then
echo -e "${GRAY}${ICON_WARNING}${NC} Incorrect password, try again" > "$tty_path"
fi
done
return 1
}
@@ -154,10 +120,14 @@ request_sudo_access() {
# Check if in clamshell mode - if yes, skip Touch ID entirely
if is_clamshell_mode; then
local clear_lines=3
if check_touchid_support; then
clear_lines=4
fi
echo -e "${PURPLE}${ICON_ARROW}${NC} ${prompt_msg}"
if _request_password "$tty_path"; then
# Clear all prompt lines (use safe clearing method)
safe_clear_lines 3 "$tty_path"
safe_clear_lines "$clear_lines" "$tty_path"
return 0
fi
return 1

View File

@@ -70,3 +70,59 @@ setup() {
result=$(bash -c "source '$PROJECT_ROOT/lib/core/common.sh'; source '$PROJECT_ROOT/lib/core/sudo.sh'; echo \$MOLE_SUDO_ESTABLISHED")
[[ "$result" == "false" ]] || [[ -z "$result" ]]
}
@test "request_sudo_access clears four lines in clamshell mode when Touch ID hint is shown" {
run bash -c '
source "'"$PROJECT_ROOT"'/lib/core/common.sh"
source "'"$PROJECT_ROOT"'/lib/core/sudo.sh"
tty_file="$(mktemp)"
chmod 600 "$tty_file"
sudo() {
case "$1" in
-n) return 1 ;;
-k) return 0 ;;
*) return 1 ;;
esac
}
tty() { printf "%s\n" "$tty_file"; }
is_clamshell_mode() { return 0; }
check_touchid_support() { return 0; }
_request_password() { return 0; }
safe_clear_lines() { printf "CLEAR:%s\n" "$1"; }
request_sudo_access "Admin access required"
'
[ "$status" -eq 0 ]
[[ "$output" == *"CLEAR:4"* ]]
}
@test "request_sudo_access keeps three-line cleanup in clamshell mode without Touch ID" {
run bash -c '
source "'"$PROJECT_ROOT"'/lib/core/common.sh"
source "'"$PROJECT_ROOT"'/lib/core/sudo.sh"
tty_file="$(mktemp)"
chmod 600 "$tty_file"
sudo() {
case "$1" in
-n) return 1 ;;
-k) return 0 ;;
*) return 1 ;;
esac
}
tty() { printf "%s\n" "$tty_file"; }
is_clamshell_mode() { return 0; }
check_touchid_support() { return 1; }
_request_password() { return 0; }
safe_clear_lines() { printf "CLEAR:%s\n" "$1"; }
request_sudo_access "Admin access required"
'
[ "$status" -eq 0 ]
[[ "$output" == *"CLEAR:3"* ]]
}