#!/bin/bash

version="0.0.2"
reldate="2026/08/15"

scriptname=$(basename ${0})

if (( EUID != 0 )); then
    echo "${scriptname} must be run as root"
    exit 1
fi

pam_files=(login sddm su sudo sudo-i polkit-1 kde)
yubi_string="auth sufficient pam_u2f.so authfile=/etc/u2f_keys userpresence=0"

udev_nlx_rulefile=/usr/share/nanolx/yubikey-lock.rules
udev_sys_rulefile=/etc/udev/rules.d/99-yubikey-lock.rules

case ${1} in
    enable )
        if [ ! -f /etc/u2f_keys ]; then
            echo "/etc/u2f_keys not found, exiting!"
            echo "use pamu2fcfg to create the configuration in /etc/u2fkeys"
            exit 1
        fi

        # create overrides for /usr/lib/pam.d/{polkit-1,kde}
        [ ! -f /etc/pam.d/polkit-1 ] && cp /usr/lib/pam.d/polkit-1 /etc/pam.d/
        [ ! -f /etc/pam.d/kde ] && cp /usr/lib/pam.d/kde /etc/pam.d/

        for file in ${pam_files[@]}; do
            if grep -q "${yubi_string}" /etc/pam.d/${file}; then
                echo "skip: Yubikey already enabled in: /etc/pam.d/${file}"
                continue
            fi

            # check where common-auth is included and substract 1
            # we need to put Yubikey entry above
            line=$(awk '/@include common-auth/ {print FNR}' /etc/pam.d/${file})
            line=$((line-1))

            echo "Enabling Yubikey in: /etc/pam.d/${file}"
            sed "${line} i ${yubi_string}" -i /etc/pam.d/${file}
        done

        echo -e "\nNote: if pkexec does not respond after applying this changes
it may be a conflict with your Desktop's polkit-agent running
e.g. the helper for KDE, XFCE or GNOME. You may try whether

\`systemctl stop polkit-agent-helper.service\`

solves the issue. If so, consider

\`systemctl disable polkit-agent-helper.service\`

at your own risk, keep in mind to eventually re-enable it."
    ;;

    disable )
        for file in ${pam_files[@]}; do
            if ! grep -q "${yubi_string}" /etc/pam.d/${file}; then
                echo "skip: Yubikey not enabled in: /etc/pam.d/${file}"
                continue
            fi

            echo "Disabling Yubikey in: /etc/pam.d/${file}"
            sed '/pam_u2f.so/d' -i /etc/pam.d/${file}
        done
    ;;

    check )
        for file in ${pam_files[@]}; do
            if grep -q "${yubi_string}" /etc/pam.d/${file}; then
                echo -e "Yubikey in /etc/pam.d/${file}:\t enabled"
            else
                echo -e "Yubikey in /etc/pam.d/${file}:\t disabled"
            fi
        done
        if [ -f ${udev_sys_rulefile} ]; then
            echo -e "Yubikey will lock the screen upon removal: enabled"
        else
            echo -e "Yubikey will lock the screen upon removal: disabled"
        fi
    ;;

    enable-lock-on-remove )
        if [ ! -f ${udev_sys_rulefile} ]; then
            cp ${udev_nlx_rulefile} ${udev_sys_rulefile}
            udevadm control --reload-rules
        else
            echo "Yubikey will lock the screen upon removal already enabled."
        fi
    ;;

    disable-lock-on-remove )
        if [ -f ${udev_sys_rulefile} ]; then
            rm ${udev_sys_rulefile}
            udevadm control --reload-rules
        else
            echo "Yubikey will lock the screen upon removal is not enabled."
        fi
    ;;

    version)
        echo "${scriptname} ${version} (${reldate})"
    ;;

    * )
        echo -e "${scriptname} v${version} (${reldate})
© 2026 Christopher Roy Bratusek <nano@jpberlin.de>

licensed under the GNU General Public License v3 (or newer)

This script enables passwordless logins, sudo and screensaver unlock for the
following PAM modules:

    ${pam_files[@]}

as long as a Yubikey known to the system is plugged in.

options:
    enable
        enable passwordless login (as long as a known Yubikey is plugged in)
    disable
        disable passwordless login
    check
        check status of passwordless logins
    enable-lock-on-remove
        enable screenlocking when Yubikey is removed from PC
    disable-lock-on-remove
        disable screenlocking when Yubikey is removed from PC
    version
        print version
"
    ;;
esac
