summaryrefslogtreecommitdiffstats
path: root/remote/modules/pam/data/opt/openslx/scripts/pam_script_ses_close
blob: e4a7c1b40b18e1a6b53b4b186aee70bedbe9772f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#!/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

[ "x${PAM_SERVICE%greeter}" != "x${PAM_SERVICE}" ] && 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