summaryrefslogtreecommitdiffstats
path: root/data/ad/mountscript
blob: 810eed6c0fed2c02e32ed67fde33f63af59cfb8b (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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
###################################################################
#
#       This script is a part of the pam_script_ses_open script
#       and is not stand-alone!
#

VOLUME=
SEARCH=
RESULT=
REAL_ACCOUNT=
WAIT=
TMPDEL=
LOGFILES=
if ! grep -q "^${PAM_USER}:" "/etc/passwd"; then
	if which gawk &>/dev/null; then
		un64() {
			gawk 'BEGIN{FS=":: "}{c="base64 -d";if(/^\w+:: /) {print $2 |& c; close(c,"to"); c |& getline $2; close(c); printf("%s: %s\n", $1, $2); next} print $0 }'
		}
	else
		un64() {
			cat
		}
	fi
	# determine fileserver and share for home directories
	SEARCH=$(mktemp)
	TMPDEL="$TMPDEL $SEARCH"
	ldapsearch -l 3 -o nettimeout=3 -o ldif-wrap=no -x -LLL uid="${PAM_USER}" dn distinguishedName homeMount realAccount > "${SEARCH}" 2>&1
	BINDDN=$(cat "${SEARCH}" | grep -E '^(dn|distinguishedName):' | un64 | head -n 1 | cut -d ' ' -f 2-)
	if [ -z "$BINDDN" ]; then
		slxlog "pam-ad-ldapquery" "Could not query DN of user ${PAM_USER}. No home directory available" "${SEARCH}"
		WAIT=1
	else
		RESULT=$(mktemp)
		TMPDEL="$TMPDEL $RESULT"
		PW="/tmp/pw.${RANDOM}.${RANDOM}.${PAM_USER}.${RANDOM}"
		mkfifo -m 0600 "${PW}" || slxlog "pam-ad-fifo" "Could not create FIFO at ${PW}"
		(
			echo -n "${PAM_AUTHTOK}" > "${PW}"
		) &
		if ! ldapsearch -y "${PW}" -D "$BINDDN" -l 5 -o nettimeout=5 -o ldif-wrap=no -x -LLL uid="${PAM_USER}" homeMount realAccount > "${RESULT}" 2>&1; then
			slxlog "pam-ad-ldapquery" "Could not query LDAP-AD-Proxy for parameters of user '${PAM_USER}' (${BINDDN})." "${RESULT}"
			WAIT=1
		fi
		rm -f -- "${PW}"
		VOLUME=$(cat "${RESULT}" | grep '^homeMount:' | head -n 1 | cut -d ' ' -f 2-)
		[ -z "$REAL_ACCOUNT" ] && REAL_ACCOUNT=$(cat "${RESULT}" | grep '^realAccount:' | head -n 1 | cut -d ' ' -f 2-)
	fi
	[ -z "$VOLUME" ] && VOLUME=$(cat "${SEARCH}" | grep '^homeMount:' | head -n 1 | cut -d ' ' -f 2-)
	[ -z "$VOLUME" ] && slxlog "pam-ad-ldapvolume" "AD/Proxy did not provide 'homeMount'. Aborting mount for ${PAM_USER}." "${RESULT}"
	[ -z "$REAL_ACCOUNT" ] && REAL_ACCOUNT=$(cat "${SEARCH}" | grep '^realAccount:' | head -n 1 | cut -d ' ' -f 2-)
	[ -z "$REAL_ACCOUNT" ] && REAL_ACCOUNT="${PAM_USER}"
fi

if [ -n "${VOLUME}" ]; then
	isHomeMounted() {
		grep -Fuq " ${PERSISTENT_HOME_DIR} " /proc/mounts
	}
	# Most servers can work without, but some don't
	XDOMAIN=
	if [ -s "/opt/openslx/inc/shares" ]; then
		. /opt/openslx/inc/shares
		XDOMAIN="${SHARE_DOMAIN}"
	fi
	if [ -z "$XDOMAIN" ]; then
		XDOMAIN=$(<"/etc/ldap.conf" grep -m1 -i '^BASE\s.*DC=' | grep -o -E -i 'DC=([^,;]+)' | head -n 1 | cut -c 4-)
	fi
	if [ -z "$XDOMAIN" ]; then
		XDOMAIN=$(<"/etc/sssd/sssd.conf" grep -m1 -i '^ldap_search_base\s*=.*DC=' | grep -o -E -i 'DC=[^,;]+' | head -n 1 | cut -c 4-)
	fi
	if [ "x$XDOMAIN" = "x#" ]; then
		XDOMAIN=
	fi
	# Remember for hooks in pam_script_auth.d
	export PERSISTENT_NETPATH=$(echo "$VOLUME" | tr '/' '\')

	export USER="${REAL_ACCOUNT}"
	export PASSWD="${PAM_AUTHTOK}"

	# We try 7 different mount option combinations; launch them in 1 second steps until one of them succeeds
	CNT=0
	PIDS=
	for opt in "vers=3.0,sec=ntlmssp" "vers=2.1,sec=ntlmssp" "vers=1.0,sec=ntlm" "vers=3.0,sec=ntlmv2" "vers=1.0,sec=ntlmv2" "vers=3.0,sec=ntlm" "vers=2.0,sec=ntlmssp"; do
		# Also we try with and without explicit domain argument
		for dom in "#" $XDOMAIN; do # No quotes
			[ "x$dom" != "x#" ] && opt="${opt},domain=$dom"
			CNT=$(( CNT + 1 ))
			FILE=$(mktemp)
			LOGFILES="$LOGFILES $FILE"
			MOUNT_OPTS="-v -t cifs -o uid=${USER_UID},gid=${USER_GID},forceuid,forcegid,${opt},nounix,file_mode=0700,dir_mode=0700,noacl,nobrl"
			echo " ****** Trying '$opt'" > "$FILE"
			mount ${MOUNT_OPTS} "${VOLUME}" "${PERSISTENT_HOME_DIR}" >> "${FILE}" 2>&1 &
			PID=$!
			# Wait max. 1 second; remember PID if this mount call seems to be running after we stop waiting
			for waits in 1 2 3 4; do
				usleep 250000
				if isHomeMounted; then
					# A previously invoked mount call might have succeeded while this one is still running; try to stop it right away
					kill "$PID" &> /dev/null
					break 3
				fi
				kill -0 "$PID" || break
			done
			kill -0 "$PID" && PIDS="$PIDS $PID" # Remember all PIDs
		done
	done

	if [ -n "$PIDS" ]; then
		CNT=0
		while ! isHomeMounted && [ "$CNT" -lt 10 ] && kill -0 $PIDS; do # No quotes
			usleep 333000
			CNT=$(( CNT + 1 ))
		done
		kill -9 $PIDS # Kill any leftovers; No quotes
	fi

	if ! isHomeMounted; then
		LOG_COMBINED=$(mktemp)
		[ -n "$LOGFILES" ] && cat ${LOGFILES} > "$LOG_COMBINED" # No quotes
		slxlog --delete "pam-ad-mount" "Mount of '${VOLUME}' to '${PERSISTENT_HOME_DIR}' failed." "${LOG_COMBINED}"
	else
		PERSISTENT_OK=yes
		#chmod -R u+rwX "${PERSISTENT_HOME_DIR}" 2>/dev/null TODO: Still needed? Use '&' maybe?
	fi

	unset USER
	unset PASSWD
fi

[ -n "${TMPDEL}${LOGFILES}" ] && rm -f -- ${TMPDEL} ${LOGFILES} # No quotes
true