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
|