#!/bin/sh

export PATH=/bin:/usr/bin:/sbin:/usr/sbin
VARLIB="/var/lib/pam_sshauth"
EXTRAUSERS="/var/lib/extrausers"
SOCKETDIR="${VARLIB}/${PAM_SSHAUTH_HOST}/${PAM_USER}"
SOCKET="${SOCKETDIR}/socket"
export DISPLAY=${PAM_TTY}
export SSH_ASKPASS="/usr/bin/shm_askpass"

test -x /usr/bin/daemon || exit 1

#
# waitfor
#
# Wait for our socket to appear.
#

waitfor () {
    S=$1

    while [ ! -S "${S}" ]; do
        sleep 1
    done
}

#
# get_extrafiles_user
#
# get our /etc/passwd entry, and store where nss_extrafiles wants
# them to be stored.
#

get_extrafiles_user () {
    S=$1

    ssh -S ${S} ${PAM_SSHAUTH_HOST} getent passwd ${PAM_USER} \
        >> ${EXTRAUSERS}/passwd
    ssh -S ${S} ${PAM_SSHAUTH_HOST} getent shadow ${PAM_USER} \
        >> ${EXTRAUSERS}/shadow
}

#
# get_extrafiles_group
#
# get our /etc/group entries for our user, and store where
# nss_extrafiles wants them to be stored.
#

get_extrafiles_group () {
    S=$1

    GROUPS=$(ssh -S ${S} ${PAM_SSHAUTH_HOST} id -G ${PAM_USER})
    ssh -S ${S} ${PAM_SSHAUTH_HOST} getent group ${GROUPS} \
        >> ${EXTRAUSERS}/group
}

#
# cleanup_user
#
# Remove all mention of a user from ${EXTRAFILES}
#

cleanup_user () {
    U=$1

    sed -i "/${U}/d" ${EXTRAUSERS}/passwd
    sed -i "/${U}/d" ${EXTRAUSERS}/shadow
    sed -i "/${U}/d" ${EXTRAUSERS}/group
}

open_socket () {
    S=$1

    if [ -n "${DISPLAY}" ]; then
        #
        # We have a $DISPLAY variable set.  Spawn an ssh session.
        # Note, you must install the "daemon" package to obtain the "daemon"
        # utility.  This nice little program easily backgrounds any script or
        # command, and has the added advantage (for us) of disassociating from
        # the controlling terminal.  With no controlling terminal, and $DISPLAY
        # set, ssh will use the program specified in SSH_ASKPASS to obtain the
        # passowrd.  Since this was stored in the "auth" phase above,
        # shm_askpass will pass it to ssh for it to authenticate with.
        #

        daemon -i -- ssh -q -N -X -M -S "${S}" -l ${PAM_USER} \
                         ${PAM_SSHAUTH_HOST}

        #
        # Wait for the socket to actually become available before returning.
        #

        waitfor "${S}"
    fi
}

close_socket () {
    S=$1
    ssh -q -S "$S" -O exit ${PAM_SSHAUTH_HOST}
    rm -rf "${SOCKETDIR}"
}

#
# This is an example session helper script to be used in conjunction with
# pam_exec and libpam_sshauth.
#

case ${PAM_TYPE} in

auth)

    logger "ltsp-session: start auth"

    #
    # Make sure our /var/lib/ directory exists.
    #

    if [ ! -d "${VARLIB}" ]; then
        mkdir -p "${VARLIB}"
        chmod 777 "${VARLIB}"
    fi

    #
    # Construct our socket directory.
    #

    if [ ! -d "${SOCKETDIR}" ]; then
        mkdir -p "${SOCKETDIR}"
    fi

    #
    # We're authenticating, so we'll store the auth token using shm_askpass
    # shm_askpass --write will read a password from stdin, and store it in
    # POSIX shared memory.
    #

    shm_askpass --write

    open_socket "${SOCKET}"

    if [ -S "${SOCKET}" ]; then

        #
        # Use the socket to pull across the user geometries.
        #

        get_extrafiles_user  "${SOCKET}"
        get_extrafiles_group "${SOCKET}"

        #
        # We're done bringing the user geometries across.  Close the socket as
        # root.
        #

        close_socket "${SOCKET}"

    else
        logger "ltsp-session: no \$DISPLAY"
    fi

    logger "ltsp-session: end auth"
    ;;

open_session)

    #
    # opening a session as user.  Re-spawn our ssh socket, this time as the
    # user.
    #

    logger "ltsp-session: start open_session"
    open_socket "${SOCKET}"
    logger "ltsp-session: end open_session"

    ;;

close_session)

    #
    # We're closing the session down, so cause the socket to exit.
    #

    logger "ltsp-session: start close_session"
    close_socket "${SOCKET}"
    cleanup_user ${PAM_USER}
    logger "ltsp-session: end close_session"

    ;;

esac

logger "ltsp-session: exiting"
exit 0
