summaryrefslogtreecommitdiffstats
path: root/core/modules/pam/data/opt/openslx/scripts/pam_script_ses_close
diff options
context:
space:
mode:
Diffstat (limited to 'core/modules/pam/data/opt/openslx/scripts/pam_script_ses_close')
-rwxr-xr-xcore/modules/pam/data/opt/openslx/scripts/pam_script_ses_close83
1 files changed, 83 insertions, 0 deletions
diff --git a/core/modules/pam/data/opt/openslx/scripts/pam_script_ses_close b/core/modules/pam/data/opt/openslx/scripts/pam_script_ses_close
new file mode 100755
index 00000000..cd35a86b
--- /dev/null
+++ b/core/modules/pam/data/opt/openslx/scripts/pam_script_ses_close
@@ -0,0 +1,83 @@
+#!/bin/ash
+
+# Needed as pam_script clears PATH
+export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/openslx/sbin:/opt/openslx/bin"
+
+# can only work if script is run as root
+[ "x$(whoami)" = "xroot" ] || exit 0
+
+# NSA needs to know
+if [ "x$PAM_SERVICE" != "xsu" -a "x$PAM_SERVICE" != "xsudo" ]; then
+ . /opt/openslx/config
+ if [ "x$SLX_REMOTE_LOG_SESSIONS" = "xyes" -o "x$PAM_USER" = "xroot" ]; then
+ slxlog "session-close" "$PAM_USER logged out on $PAM_TTY"
+ elif [ "x$SLX_REMOTE_LOG_SESSIONS" = "xanonymous" ]; then
+ slxlog "session-close" "User logged out on $PAM_TTY"
+ fi
+fi
+
+# source hooks if there are any
+if [ -d "/opt/openslx/scripts/pam_script_ses_close.d" ]; then
+ for HOOK in $(ls "/opt/openslx/scripts/pam_script_ses_close.d"); do
+ # failure is non-critical
+ . "/opt/openslx/scripts/pam_script_ses_close.d/$HOOK" || slxlog "pam-sesclose-hooks" "Could not source '$HOOK'."
+ done
+fi
+
+# do not kill all root processes :)
+[ "x${PAM_USER}" = "xroot" ] && exit 0
+
+# Async block: Check if user has no session open anymore, if not
+# kill any remaining processes belonging to the user and unmount
+# everything at $USERHOME and below.
+{
+ sleep 2 # Give things some time
+ # Use who (utmp) to determine sessions by the user. loginctl might be nicer, but
+ # a simple show-user $USER will also include detached sessions (eg. screen) which
+ # makes this quite pointless. This needs to be investigated some day.
+ SESSIONCOUNT=$(who | grep "^${PAM_USER}\\b" | wc -l)
+ if [ "$SESSIONCOUNT" = "0" ]; then
+
+ # last session, close all ghost user processes
+ pkill -u "${PAM_USER}"
+
+ # check if user's processes are still running
+ for TIMEOUT in 1 1 2 FAIL; do
+ if ! ps -o pid,s -u "$PAM_USER" -U "$PAM_USER" | grep -q -v -E "PID|Z"; then
+ # nothing running anymore
+ break
+ fi
+ if [ "$TIMEOUT" = "FAIL" ]; then
+ # still something running, send SIGKILL
+ pkill -9 -u "${PAM_USER}"
+ else
+ # give some time
+ sleep "${TIMEOUT}"
+ fi
+ done
+
+ fi
+
+ # just to be sure we check again, since the pkilling above might have taken some time...
+ SESSIONCOUNT=$(who | grep "^${PAM_USER}\\b" | wc -l)
+ if [ "$SESSIONCOUNT" = "0" ]; then
+
+ # unmount the home directory structure
+ USER_HOME=$(getent passwd "$PAM_USER" | awk -F ':' '{print $6}')
+ if [ -n "$USER_HOME" ]; then
+ for TIMEOUT in 0 0 2 2 FAIL; do
+ OK=yes
+ for dir in $(cat /proc/mounts | awk '{print $2}' | grep -e "^${USER_HOME}\$" -e "^${USER_HOME}/.*\$"); do
+ umount "$dir" || OK=no
+ done
+ [ "$TIMEOUT" = "FAIL" -o "$OK" = "yes" ] && break
+ sleep "$TIMEOUT"
+ done
+ fi
+
+ fi
+
+} &
+
+exit 0
+