commit 1c5776c1a1d9e2465f631bc756a19b78cd3895ab Author: root Date: Tue Jan 20 21:14:47 2026 +0200 Upload files to "/" diff --git a/PKGBUILD b/PKGBUILD new file mode 100644 index 0000000..911dbf5 --- /dev/null +++ b/PKGBUILD @@ -0,0 +1,30 @@ +# Maintainer: Zeev +pkgname=z-auth +pkgver=0.1.4 +pkgrel=1 +pkgdesc="Secure Z-Authentication Script (Hidden Source)" +arch=('any') +url="local" +license=('custom') +depends=('bash' 'zenity' 'sudo') +makedepends=('gcc') +install=z-auth.install +source=("z-auth.sh" "z-auth-wrapper.c") +md5sums=('SKIP' 'SKIP') + +build() { + # Compile the setuid wrapper + gcc -o z-auth-wrapper z-auth-wrapper.c +} + +package() { + # 1. Install the wrapper binary as /usr/bin/z-auth + # -D creates directories + # -m4755 sets permissions to rwsr-xr-x (Setuid Root) + install -Dm4755 z-auth-wrapper "$pkgdir/usr/bin/z-auth" + + # 2. Install the actual script to a protected location + # /usr/lib/z-auth/core.sh + # -m0700 sets permissions to rwx------ (Root only) + install -Dm0700 z-auth.sh "$pkgdir/usr/lib/z-auth/core.sh" +} diff --git a/z-auth-wrapper.c b/z-auth-wrapper.c new file mode 100644 index 0000000..4c76e6e --- /dev/null +++ b/z-auth-wrapper.c @@ -0,0 +1,27 @@ +#define _GNU_SOURCE +#include +#include +#include +#include + +int main(int argc, char *argv[]) { + /* + FIX: Bash drops privileges if Real UID != Effective UID. + We are running setuid root (EUID=0), but Real UID is the user. + We must promote ourselves to full root (Real UID = E-UID = 0) + so Bash treats us as root and allows reading the 0700 script. + */ + if (setuid(0) != 0) { + perror("Failed to setuid(0)"); + return 1; + } + + char *script_path = "/usr/lib/z-auth/core.sh"; + char *new_argv[] = { "/bin/bash", script_path, NULL }; + + extern char **environ; + execve("/bin/bash", new_argv, environ); + + perror("Failed to exec z-auth core script"); + return 1; +} diff --git a/z-auth.install b/z-auth.install new file mode 100644 index 0000000..7d108ca --- /dev/null +++ b/z-auth.install @@ -0,0 +1,42 @@ +PAM_FILE="/etc/pam.d/sudo" +AUTH_LINE="auth sufficient pam_exec.so quiet stdout /usr/bin/z-auth" + +post_install() { + echo ":: Configuring PAM for z-auth..." + + # Check if line already exists + if grep -q "/usr/bin/z-auth" "$PAM_FILE"; then + echo " PAM configuration already exists. Skipping." + else + # Backup + cp "$PAM_FILE" "$PAM_FILE.bak_zauth" + + # Insert after the first line (usually #%PAM-1.0) + # This places it at the very top of the rules, which is what we want for 'sufficient' + sed -i "2i$AUTH_LINE" "$PAM_FILE" + echo " Added z-auth to $PAM_FILE" + fi + + # Optional: Warning if the OLD manual line still exists + if grep -q "/usr/local/bin/z-auth.sh" "$PAM_FILE"; then + echo " WARNING: You have an old configuration pointing to /usr/local/bin/z-auth.sh." + echo " You should remove it manually to avoid redundancy." + fi +} + +post_upgrade() { + post_install +} + +post_remove() { + echo ":: Removing z-auth from PAM configuration..." + + if grep -q "/usr/bin/z-auth" "$PAM_FILE"; then + # Create backup before verifying + cp "$PAM_FILE" "$PAM_FILE.bak_zauth_remove" + + # Remove the exact line (or lines containing the binary path) + sed -i "\|/usr/bin/z-auth|d" "$PAM_FILE" + echo " Removed z-auth configuration." + fi +} diff --git a/z-auth.sh b/z-auth.sh new file mode 100644 index 0000000..e2048a3 --- /dev/null +++ b/z-auth.sh @@ -0,0 +1,177 @@ +#!/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