177 lines
4.4 KiB
Bash
177 lines
4.4 KiB
Bash
#!/bin/bash
|
|
exec 2>/dev/null
|
|
PINCODE="2606"
|
|
|
|
# Detect the target user (default to current user or UID 1000 user if running as root)
|
|
get_target_user() {
|
|
if [ -n "$PAM_USER" ]; then
|
|
echo "$PAM_USER"
|
|
elif [ -n "$SUDO_USER" ]; then
|
|
echo "$SUDO_USER"
|
|
else
|
|
echo "$USER"
|
|
fi
|
|
}
|
|
|
|
# Helper to find the correct Xauthority file
|
|
get_xauthority() {
|
|
local target_user="$1"
|
|
local target_uid
|
|
target_uid=$(id -u "$target_user")
|
|
|
|
# Common locations for Xauthority
|
|
local candidates=(
|
|
"/run/user/$target_uid/gdm/Xauthority"
|
|
"/run/user/$target_uid/.mutter-Xwaylandauth.*"
|
|
"/home/$target_user/.Xauthority"
|
|
)
|
|
|
|
for pattern in "${candidates[@]}"; do
|
|
# Expand glob pattern
|
|
for file in $pattern; do
|
|
if [ -r "$file" ]; then
|
|
echo "$file"
|
|
return 0
|
|
fi
|
|
done
|
|
done
|
|
return 1
|
|
}
|
|
|
|
# Identify a usable TTY device
|
|
identify_tty() {
|
|
# 1. Try standard /dev/tty (standard controlling terminal)
|
|
# Use subshell to test opening it without exiting script on failure
|
|
if ( : < /dev/tty ) 2>/dev/null; then
|
|
echo "/dev/tty"
|
|
return 0
|
|
fi
|
|
|
|
# 2. Try PAM_TTY if set (provided by PAM module)
|
|
if [ -n "$PAM_TTY" ]; then
|
|
# Use simple pattern matching
|
|
case "$PAM_TTY" in
|
|
/dev/*)
|
|
if [ -c "$PAM_TTY" ]; then
|
|
echo "$PAM_TTY"
|
|
return 0
|
|
fi
|
|
;;
|
|
ssh|:*)
|
|
# Not a char device (X11 or SSH)
|
|
return 1
|
|
;;
|
|
*)
|
|
# Potentially a device name without /dev/ (e.g. tty1)
|
|
if [ -c "/dev/$PAM_TTY" ]; then
|
|
echo "/dev/$PAM_TTY"
|
|
return 0
|
|
fi
|
|
;;
|
|
esac
|
|
fi
|
|
|
|
return 1
|
|
}
|
|
|
|
verify_pin() {
|
|
local input="$1"
|
|
if [ "$input" = "$PINCODE" ]; then
|
|
exit 0
|
|
else
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
z_auth_gui() {
|
|
local target_user
|
|
target_user=$(get_target_user)
|
|
|
|
# Fallback/Guess display if needed
|
|
if [ -z "$DISPLAY" ]; then
|
|
export DISPLAY=:0
|
|
fi
|
|
|
|
# Try to find authority file
|
|
local auth_file
|
|
auth_file=$(get_xauthority "$target_user")
|
|
|
|
if [ -n "$auth_file" ]; then
|
|
export XAUTHORITY="$auth_file"
|
|
fi
|
|
|
|
local input_pincode
|
|
input_pincode=$(sudo -u "$target_user" zenity --entry \
|
|
--title="Security Check" \
|
|
--text="Enter Sudo PIN for $target_user:" \
|
|
--hide-text \
|
|
--width=300 2>/dev/null)
|
|
|
|
# If zenity failed/cancelled, return 1 to allow fallback
|
|
# DO NOT exit 1 here, otherwise we kill the script before trying TTY
|
|
if [ $? -ne 0 ]; then
|
|
return 1
|
|
fi
|
|
|
|
|
|
if verify_pin "$input_pincode"; then
|
|
exit 0
|
|
else
|
|
sudo -u "$target_user" zenity --error --text="Wrong PIN!" --no-wrap 2>/dev/null
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
z_auth_no_gui() {
|
|
local tty_device="$1"
|
|
|
|
if [ -z "$tty_device" ] || [ ! -c "$tty_device" ]; then
|
|
# Check failed, but silenced now
|
|
exit 1
|
|
fi
|
|
|
|
local input_pincode
|
|
|
|
# Use the identified TTY device for input and output
|
|
echo -n "Enter Security PIN: " > "$tty_device"
|
|
read -s input_pincode < "$tty_device"
|
|
echo > "$tty_device"
|
|
|
|
if verify_pin "$input_pincode"; then
|
|
exit 0
|
|
else
|
|
echo "Incorrect PIN." > "$tty_device"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
main_function() {
|
|
# Determine where we are
|
|
local identified_tty
|
|
identified_tty=$(identify_tty) # e.g. /dev/tty3 or /dev/pts/1
|
|
|
|
# Logic:
|
|
# 1. If we are on a REAL console (/dev/tty1...tty6), FORCE TTY mode.
|
|
# Why? Because forcing GUI (DISPLAY=:0) on TTY3 will spawn a window
|
|
# on TTY1/2 (where X is), which is invisible to the user on TTY3, causing a hang.
|
|
if [[ "$identified_tty" =~ /dev/tty[0-9]+ ]]; then
|
|
z_auth_no_gui "$identified_tty"
|
|
# If it returns, it passed validation
|
|
return
|
|
fi
|
|
|
|
# 2. If we are NOT on a real console (e.g. /dev/pts/* or no TTY), try GUI first.
|
|
# This covers GNOME Terminal, SSH X11 forwarding, etc.
|
|
# If GUI fails (e.g. headless SSH), fallback to TTY.
|
|
z_auth_gui
|
|
|
|
# 3. GUI failed or returned 1? Fallback to TTY if we have one.
|
|
if [ -n "$identified_tty" ]; then
|
|
z_auth_no_gui "$identified_tty"
|
|
else
|
|
# No GUI, no TTY -> Fail
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
main_function
|