#!/bin/sh
#
# Copyright (c) 2021 Tobias Bäumer <tobiasbaeumer@gmail.com>
#
# This file is part of the pam_usb project. pam_usb is free software;
# you can redistribute it and/or modify it under the terms of the GNU General
# Public License version 2, as published by the Free Software Foundation.
#
# pam_usb is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
# Street, Fifth Floor, Boston, MA 02110-1301 USA.

INSTALL=0
UNINSTALL=0
PAMUSB_CHECK=/usr/bin/pamusb-check
ID=/usr/bin/id
LOGGER=/usr/bin/logger
STAT=/usr/bin/stat
AWK=/usr/bin/awk
SED=/usr/bin/sed
HEAD=/usr/bin/head
PIDOF=/usr/bin/pidof
KILL=/usr/bin/kill
GNOME_KEYRING_DAEMON=/usr/bin/gnome-keyring-daemon
KEYFILE="$HOME/.pamusb/.keyring_unlock_password"

while [ "$1" != "" ]; do
    case $1 in
        --install)   INSTALL=1 ;;
        --uninstall) UNINSTALL=1 ;;
        *) printf 'Usage: %s [--install|--uninstall]\n' "${0##*/}" >&2; exit 1 ;;
    esac
    shift
done

do_install() {
    if [ "$("$ID" -u)" = "0" ]; then
        printf 'Do not run --install as root; files belong in your user home.\n' >&2
        exit 1
    fi

    if [ -t 0 ]; then
        printf 'Enter your keyring unlock password: '
        stty -echo
        read -r UNLOCK_PASSWORD
        stty echo
        printf '\n'
    else
        read -r UNLOCK_PASSWORD
    fi

    mkdir -p "$HOME/.pamusb"
    printf 'UNLOCK_PASSWORD=%s\n' "$UNLOCK_PASSWORD" > "$KEYFILE"
    chmod 0600 "$KEYFILE"

    mkdir -p "$HOME/.config/autostart"

    cat > "$HOME/.config/autostart/pamusb-keyring-unlock-gnome.desktop" <<'EOF'
[Desktop Entry]
Type=Application
Exec=/usr/bin/pamusb-keyring-unlock-gnome
Hidden=false
NoDisplay=false
X-GNOME-Autostart-enabled=true
Name=pam_usb keyring unlock
Comment=Unlock GNOME keyring with pam_usb
EOF

    cat > "$HOME/.config/autostart/gnome-keyring-secrets.desktop" <<'EOF'
[Desktop Entry]
Hidden=true
EOF

    printf '\nInstallation complete.\n'
    printf 'WARNING: Your keyring password is stored in cleartext at %s/.pamusb/.keyring_unlock_password\n' "$HOME"
    printf 'Make sure your home directory is encrypted if you rely on this feature for security.\n'
}

do_uninstall() {
    rm -f "$KEYFILE"
    rm -f "$HOME/.config/autostart/pamusb-keyring-unlock-gnome.desktop"
    rm -f "$HOME/.config/autostart/gnome-keyring-secrets.desktop"
    printf 'Uninstall complete. Removed password file and autostart entries.\n'
}

if [ "$INSTALL" = "1" ]; then
    do_install
    exit 0
fi

if [ "$UNINSTALL" = "1" ]; then
    do_uninstall
    exit 0
fi

# Check for valid authentication
USER_NAME=$("$ID" -un)
if ! "$PAMUSB_CHECK" "$USER_NAME" > /dev/null 2>&1; then
    "$LOGGER" -p local0.error -t "${0##*/}[$$]" pamusb-check failed.
    exit 1
fi

# Check if password file exists
if [ ! -f "$KEYFILE" ]; then
    "$LOGGER" -p local0.notice -t "${0##*/}[$$]" No password file found, exiting.
    exit 0
fi

# Ensure file has 0600 (if FS supports it)
PERMISSIONS=$("$STAT" -c "%a %n" "$KEYFILE" | "$AWK" '{print $1}')
if [ ! "$PERMISSIONS" = "600" ]; then
    "$LOGGER" -p local0.error -t "${0##*/}[$$]" Bad permissions on ~/.pamusb/.keyring_unlock_password. Please change them to 0600.
    exit 1
fi

# Kill existing keyring instance
KEYRING_PIDS=$("$PIDOF" gnome-keyring-daemon)
if [ -n "$KEYRING_PIDS" ] && "$KILL" $KEYRING_PIDS; then
    "$LOGGER" -p local0.notice -t "${0##*/}[$$]" Killed existing gnome-keyring-instance.
else
    "$LOGGER" -p local0.notice -t "${0##*/}[$$]" Couldn\'t kill existing gnome-keyring-instance - was it launched already?
fi

# Read UNLOCK_PASSWORD without sourcing the file as shell code.
UNLOCK_PASSWORD=$("$SED" -n 's/^UNLOCK_PASSWORD=//p' "$KEYFILE" | "$HEAD" -n 1)
case "$UNLOCK_PASSWORD" in
    '"'*'"') UNLOCK_PASSWORD=${UNLOCK_PASSWORD#\"}; UNLOCK_PASSWORD=${UNLOCK_PASSWORD%\"} ;;
esac
if [ -z "$UNLOCK_PASSWORD" ]; then
    "$LOGGER" -p local0.error -t "${0##*/}[$$]" Could not read UNLOCK_PASSWORD from file.
    exit 1
fi

# Perform unlock — pass via stdin pipe so the password never appears as a process argument
printf '%s' "$UNLOCK_PASSWORD" | "$GNOME_KEYRING_DAEMON" --daemonize --login \
    && "$GNOME_KEYRING_DAEMON" --start  > /dev/null 2>&1; UNLOCKED=$? \
    && "$LOGGER" -p local0.notice -t "${0##*/}[$$]" Keyring unlocked. \
    || "$LOGGER" -p local0.error -t "${0##*/}[$$]" Keyring unlock failed.

exit $UNLOCKED
