1#!/bin/sh
2#
3# Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan
4# (Royal Institute of Technology, Stockholm, Sweden). 
5# All rights reserved. 
6#
7# Portions Copyright (c) 2009 - 2010 Apple Inc. All rights reserved.
8#
9# Redistribution and use in source and binary forms, with or without 
10# modification, are permitted provided that the following conditions 
11# are met: 
12#
13# 1. Redistributions of source code must retain the above copyright 
14#    notice, this list of conditions and the following disclaimer. 
15#
16# 2. Redistributions in binary form must reproduce the above copyright 
17#    notice, this list of conditions and the following disclaimer in the 
18#    documentation and/or other materials provided with the distribution. 
19#
20# 3. Neither the name of the Institute nor the names of its contributors 
21#    may be used to endorse or promote products derived from this software 
22#    without specific prior written permission. 
23#
24# THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
25# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
26# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
27# ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
28# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
29# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
30# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
31# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
32# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
33# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
34# SUCH DAMAGE. 
35
36env_setup="@env_setup@"
37confdir="@confdir@"
38testdir="@testdir@"
39
40if [ "$UID" != 0 ] ; then
41    echo "must run script as root since it create users"
42    exit 1
43fi
44
45mkdir -p $testdir 2> /dev/null
46
47hodadmin="/System/Library/PrivateFrameworks/Heimdal.framework/Helpers/hod-admin"
48
49u=heimdaltestuser
50v=heimdaltestusersrp
51uid=82367346
52o=heimdalother
53u2=heimdaltestuser2
54s=heimdaltestservice
55mme="heimdaltestuser@me.com"
56mmeq="heimdaltestuser\\@me.com"
57r=WELLKNOWN:COM.APPLE.LKDC
58pw=foo
59
60. ${env_setup}
61
62KRB5_CONFIG="${1-${confdir}/krb5.conf}"
63export KRB5_CONFIG
64
65logfile=${testdir}/messages.log
66tempfile=${testdir}/tempfile
67cache="FILE:${testdir}/cache.krb5"
68
69testfailed="echo test failed; cat ${logfile}; exit 1"
70
71kdc="${kdc} --addresses=localhost"
72
73kkinit="${kinit}"
74kklist="${klist}"
75kkdestroy="${kdestroy}"
76
77kinit="${kinit} -c $cache"
78klist="${klist} -c $cache"
79kgetcred="${kgetcred} -c $cache"
80kdestroy="${kdestroy} -c $cache"
81
82mkdir -p ${testdir}
83
84rm -f ${testdir}/out-*
85rm -rf ${testdir}/smb
86
87mkdir "${testdir}/smb"
88> "${testdir}/smb/there-is-a-file-here"
89
90> ${logfile}
91
92toggle_launchd() {
93
94
95    digestservice=com.apple.Kerberos.digest-service
96    kcmservice=com.apple.Kerberos.kcm
97    ds=/System/Library/LaunchDaemons/$digestservice.plist
98    kcm=/System/Library/LaunchDaemons/$kcmservice.plist
99
100    if [ $1 = "malloc-set" ] ; then
101        launchctl setenv MallocStackLoggingNoCompact 1
102        launchctl setenv MallocErrorAbort 1
103    elif [ $1 = "malloc-unset" ] ; then
104        launchctl unsetenv MallocStackLoggingNoCompact
105        launchctl unsetenv MallocErrorAbort
106    fi
107    
108    launchctl unload $ds
109    killall -9 digest-service 2>/dev/null
110    launchctl load $ds
111    launchctl unload $kcm
112    killall -9 kcm 2>/dev/null
113    launchctl load $kcm
114}
115
116toogle_ntlm () {
117    if [ $1 = "disable" ] ; then
118	op=write
119	arg="-bool false"
120    elif [ $1 = "enable" ] ; then
121	op=delete
122	arg=""
123    else
124	exit 1
125    fi
126    defaults $op /Library/Preferences/com.apple.GSS.NTLM NTLMv1 $arg
127    defaults $op /Library/Preferences/com.apple.GSS.NTLM NTLMv2 $arg
128
129    killall -9 digest-service
130    killall -9 kcm
131}
132
133echo "Checking if UserEventAgent and smbplugin have done their job"
134if ! echo 'show com.apple.smb' | scutil | grep NetBIOSName > /dev/null ; then
135    echo "they have not"
136    echo 'show com.apple.smb' | scutil | sed 's/^/     /'
137    exit 1
138fi
139
140echo "Creating lkdc user"
141
142echo "    delete"
143dscl . -delete /Users/$u 2>/dev/null >/dev/null
144echo "    create"
145dscl . -create /Users/$u
146echo "    RealName"
147dscl . -append /Users/$u RealName "Heimdal testuser"
148dscl . -append /Users/$u RecordName "${mme}"
149dscl . -append /Users/$u dsAttrTypeStandard:AltSecurityIdentities 'X509:<T>C=SE,CN=hx509 Test Root CA<S>CN=pkinit,C=SE'
150dscl . -delete /Users/$u AuthenticationAuthority
151dscl . -append /Users/$u AuthenticationAuthority ';ShadowHash;HASHLIST:<SALTED-SHA1,SMB-NT>'
152dscl . -append /Users/$u UniqueID $uid
153dscl . -append /Users/$u PrimaryGroupID 20
154dscl . -append /Users/$u NFSHomeDirectory "${testdir}/smb"
155echo "    Password"
156dscl . -passwd /Users/$u $pw
157echo "    Check keys"
158
159echo "Creating srp lkdc user"
160
161echo "    delete"
162dscl . -delete /Users/$v 2>/dev/null >/dev/null
163echo "    create"
164dscl . -create /Users/$v
165echo "    RealName"
166dscl . -append /Users/$v RealName "Heimdal testuser srp"
167dscl . -append /Users/$v RecordName "srp${mme}"
168dscl . -delete /Users/$v AuthenticationAuthority
169dscl . -append /Users/$v AuthenticationAuthority ';ShadowHash;HASHLIST:<SALTED-SHA1,SMB-NT>'
170dscl . -append /Users/$v UniqueID $(expr $uid + 1)
171dscl . -append /Users/$v PrimaryGroupID 20
172dscl . -append /Users/$v NFSHomeDirectory "${testdir}/smb"
173echo "    SRP verififer (no pw)"
174dscl . -passwd /Users/$u $pw
175$hodadmin . srp-verifier $v srp$pw
176
177
178# XXX opendirectory/plist backend should do this
179$hodadmin . password \
180    --encryption-types=aes256-cts-hmac-sha1-96 \
181    --encryption-types=aes128-cts-hmac-sha1-96 \
182    --encryption-types=des3-cbc-sha1 \
183    --encryption-types=arcfour-hmac-md5 \
184    /Users/$u $pw
185
186{ dscl . -read /Users/$u KerberosKeys 2>&1 | grep KerberosKeys: > /dev/null ; } || \
187    { echo "KerberosKeys missing" ; exit 1; }
188{ dscl . -read /Users/$u HeimdalSRPKey 2>&1 | grep HeimdalSRPKey: > /dev/null ; } || \
189     { echo "SRP verififer missing" ; exit 1; }
190
191{ dscl . -read /Users/$u dsAttrTypeStandard:AltSecurityIdentities | grep pkinit > /dev/null; } || \
192    { echo "asi missing" ; exit 1; }
193
194#{ dscl . -read /Users/$v KerberosKeys 2>&1 | grep KerberosKeys: > /dev/null ; } && \
195#    { echo "KerberosKey there when they should not be" ; exit 1; }
196{ dscl . -read /Users/$v HeimdalSRPKey 2>&1 | grep HeimdalSRPKey: > /dev/null ; } || \
197    { echo "SRP verifier missing" ; exit 1; }
198
199
200chown -R $u "${testdir}/smb"
201
202echo $pw > ${testdir}/foopassword
203echo srp$pw > ${testdir}/srpfoopassword
204
205echo "Server domain"
206
207echo "    delete"
208dscl . -delete /Users/$o 2>/dev/null >/dev/null
209echo "    create"
210dscl . -create /Users/$o
211dscl . -append /Users/$o UniqueID $(expr $uid + 2)
212dscl . -append /Users/$o PrimaryGroupID 20
213
214echo "    setflags"
215$hodadmin . principal-setflags $o Server Forwardable
216
217echo "    password"
218$hodadmin . password  $o domain || exit 1
219
220echo "Creating server user"
221
222echo "    delete"
223dscl . -delete /Users/$u2 2>/dev/null >/dev/null
224echo "    create"
225dscl . -create /Users/$u2
226dscl . -append /Users/$u2 UniqueID $(expr $uid + 3)
227dscl . -append /Users/$u2 PrimaryGroupID 20
228echo "    password"
229dscl . -passwd /Users/$u2 $pw
230echo "    checking user"
231(dscl . -read /Users/$u KerberosKeys | grep KerberosKeys > /dev/null) || \
232    { echo "KerberosKeys missing" ; exit 1; }
233
234echo "    setflags"
235$hodadmin . principal-setflags /Computers/$s Server
236
237echo "    password"
238$hodadmin . password          /Computers/$s user-password
239
240foundlines=$(${kadmin} -l dump | wc -l)
241if [ "X${foundlines}" = "X" -o "X${foundlines}" = X0 ] ; then
242    echo "dumpfile contained nothing"
243    exit 1
244fi
245
246echo "done user creation"
247
248toogle_ntlm enable
249
250echo Starting kdc
251env MallocStackLoggingNoCompact=1 MallocErrorAbort=1 MallocLogFile=${testdir}/malloc-log \
252${kdc} &
253kdcpid=$!
254
255sh ${wait_kdc} KDC ${logfile}
256if [ "$?" != 0 ] ; then
257    kill -9 ${kdcpid}
258    exit 1
259fi
260
261trap "kill -9 ${kdcpid}; echo signal killing kdc; exit 1;" EXIT
262
263ec=0
264
265for a in 1 2 3 4 5 6 7 8 9 10 ; do
266    echo "Getting client initial tickets ${a}"; > ${logfile}
267    ${kinit} --kdc-hostname=localhost --canon --password-file=${testdir}/foopassword ${u}@${r} || \
268	{ ec=1 ; eval "${testfailed}"; }
269done
270
271echo "Getting client initial tickets";> ${logfile}
272${kkdestroy} -A
273${kkinit} --kdc-hostname=localhost --canon --password-file=${testdir}/foopassword ${u}@${r} || \
274	{ ec=1 ; eval "${testfailed}"; }
275${kkinit} --kdc-hostname=localhost --canon --password-file=${testdir}/srpfoopassword ${v}@${r} || \
276	{ ec=1 ; eval "${testfailed}"; }
277
278
279echo "Checking that credentials are stored"
280(${kklist} -l | grep ${u}) >/dev/null || { ec=1 ; eval "${testfailed}"; }
281(${kklist} -l | grep ${v}) >/dev/null || { ec=1 ; eval "${testfailed}"; }
282
283echo "checking that u2 is first" > ${logfile}
284(${kklist} | grep ${v}) >/dev/null || { ec=1 ; eval "${testfailed}"; }
285echo "checking that u2 still is first (sleep 20)" > ${logfile}
286sleep 20
287(${kklist} | grep ${v}) >/dev/null || { ec=1 ; eval "${testfailed}"; }
288
289${kkdestroy} -A
290
291
292echo "Gettting client initial tickets"
293${kinit} --kdc-hostname=localhost --canon --password-file=${testdir}/foopassword ${u}@${r} || \
294    { ec=1; eval "${testfailed}"; }
295echo "Getting tickets"; > ${logfile}
296${kgetcred} host/${r}@${r} || { ec=1 ; eval "${testfailed}"; }
297echo "Listing tickets"; > ${logfile}
298${klist} > /dev/null || { ec=1 ; eval "${testfailed}"; }
299
300${kdestroy}
301
302echo "Getting PKINIT credentials"; > ${logfile}
303${kinit} -C FILE:${hx509_data}/pkinit.crt,${hx509_data}/pkinit.key \
304	-D KEYCHAIN: --canon \
305        --kdc-hostname=localhost \
306	"${mmeq}@${r}" || \
307	{ ec=1 ; eval "${testfailed}"; }
308
309echo "Getting tickets"; > ${logfile}
310${kgetcred} host/${r}@${r} || { ec=1 ; eval "${testfailed}"; }
311echo "Listing tickets"; > ${logfile}
312${klist} > /dev/null || { ec=1 ; eval "${testfailed}"; }
313${kdestroy}
314
315
316echo "Get kerberos ticket for gss test"; > ${logfile}
317${kinit} --kdc-hostname=localhost --canon --password-file=${testdir}/foopassword ${u}@${r} || \
318	{ ec=1 ; eval "${testfailed}"; }
319
320echo "testing Kerberos GSS mech" ; > ${logfile}
321env KRB5CCNAME=FILE:/tmp/heimdal/cache.krb5 ${test_context} \
322    --mech=krb5 --wrap --verbose \
323    service@localhost || { ec=1 ; eval "${testfailed}"; }
324
325
326echo "testing Kerberos GSS mech (no homedir)" ; > ${logfile}
327sandbox-exec -p '(version 1) (allow default) (deny file* (subpath #"/private/var/root") (with send-signal SIGABRT))' \
328env CFFIXED_USER_HOME=/ KRB5CCNAME=/tmp/heimdal/cache.krb5 \
329${test_context} \
330    --no-homedir \
331    --mech=krb5 --wrap --verbose \
332    service@localhost || { ec=1 ; eval "${testfailed}"; }
333
334${kdestroy}
335
336#echo "testing IAKERB GSS mech"
337#${test_context} \
338#    --client-name=heimdaltestuser@WELLKNOWN:COM.APPLE.LKDC \
339#    --password="$pw" \
340#    --cred-type=iakerb \
341#    --mech=iakerb --wrap --verbose \
342#    service@localhost || { ec=1 ; eval "${testfailed}"; }
343
344echo "test_gssntlm"
345
346toggle_launchd malloc-set
347
348domain=$(echo 'show com.apple.smb ' | scutil   | grep NetBIOSName | sed 's/  NetBIOSName : //')
349
350${test_gssntlm} --user=$u --domain='' --password=$pw || { ec=1 ; eval "${testfailed}"; }
351${test_gssntlm} --user=$u --domain=FOO --password=$pw || { ec=1 ; eval "${testfailed}"; }
352${test_gssntlm} --user=$u --domain=$domain --password=$pw || { ec=1 ; eval "${testfailed}"; }
353
354defaults delete /Library/Preferences/com.apple.GSS.NTLM AllowedHosts
355
356defaults write /Library/Preferences/com.apple.GSS.NTLM AllowedHosts -array host.local
357
358for a in \
359    "0 host@host.local host.local" \
360    "0 host@host.local" \
361    "0 host@host.local \*.local" \
362    "1 host@host.local host2.local" \
363    "1 host@host.local 2host.local" \
364    "1 host@host.local \*.local2" \
365    "1 host@host.local \*.2local"
366do
367    echo "---running test $a"
368    set -- $a
369    eres=$1
370    host=$2
371    shift 2
372    if test $# -ne 0 ; then
373	defaults write \
374	    /Library/Preferences/com.apple.GSS.NTLM AllowedHosts -array "$@"
375    else
376	defaults delete \
377	    /Library/Preferences/com.apple.GSS.NTLM AllowedHosts
378    fi
379
380    echo "   NTLM GSS mech"
381    ${test_context} \
382	--client-name=$u \
383	--password=$pw \
384	--mech-type=ntlm \
385	--mutual \
386        --ret-mech-type=ntlm \
387        ${host} > /dev/null 2>&1
388    res=$?
389    test "$res" = "$eres" || { \
390	defaults delete /Library/Preferences/com.apple.GSS.NTLM AllowedHosts ; \
391	echo "test failed"; exit 1; \
392    }
393
394    echo "   NTLM GSS mech channel bindings"
395    ${test_context} \
396	--client-name=$u \
397	--password=$pw \
398	--mech-type=ntlm \
399	--mutual \
400        --channel-binding="0123456789abcdef" \
401        --ret-mech-type=ntlm \
402        ${host} > /dev/null 2>&1
403    res=$?
404    test "$res" = "$eres" ||  { \
405	defaults delete /Library/Preferences/com.apple.GSS.NTLM AllowedHosts ; \
406	echo "test failed"; exit 1; \
407    }
408
409done
410
411defaults delete /Library/Preferences/com.apple.GSS.NTLM AllowedHosts
412
413echo "check NTLM GUEST account"; > ${logfile}
414${test_context} \
415	--client-name=GUEST \
416	--password="" \
417	--mech-type=ntlm \
418	--mutual \
419        --ret-mech-type=ntlm \
420    	cifs@localhost || { echo "test failed"; exit 1; }
421
422echo "check that NTLM can be disabled"; > ${logfile}
423toogle_ntlm disable
424${test_context} \
425    --client-name=$u \
426    --password=$pw \
427    --mech-type=ntlm \
428    --mutual \
429    --ret-mech-type=ntlm \
430       cifs@localhost > /dev/null 2>&1 && \
431        { echo "test failed"; exit 1; }
432
433echo "check that NTLM can be enabled again"; > ${logfile}
434toogle_ntlm enable
435
436${test_context} \
437    --client-name=$u \
438    --password=$pw \
439    --mech-type=ntlm \
440    --mutual \
441    --ret-mech-type=ntlm \
442       cifs@localhost > /dev/null 2>&1 || \
443        { echo "test failed"; exit 1; }
444
445
446echo "check NTLM GUEST@domain account"; > ${logfile}
447${test_context} \
448	--client-name=GUEST@domain \
449	--password="" \
450	--mech-type=ntlm \
451	--mutual \
452        --ret-mech-type=ntlm \
453        --verbose \
454    	cifs@localhost > ${tempfile} || { echo "test failed"; exit 1; }
455
456grep -e "^source.server.: GUEST@${domain}" ${tempfile} > /dev/null || \
457	{ echo "failed to find guest@DOMAIN"; exit 1; }
458
459rm "${tempfile}"
460
461
462
463echo "Getting tickets (leaks check)"; > ${logfile}
464${kinit} --kdc-hostname=localhost --canon --password-file=${testdir}/foopassword ${u}@${r} || \
465    { ec=1 ; eval "${testfailed}"; }
466
467echo "Getting PKINIT credentials (leaks check)"; > ${logfile}
468${kinit} -C FILE:${hx509_data}/pkinit.crt,${hx509_data}/pkinit.key \
469	-D KEYCHAIN: --canon \
470        --kdc-hostname=localhost \
471	"${mmeq}@${r}" || \
472	{ ec=1 ; eval "${testfailed}"; }
473
474#echo "checking policy"
475#pwpolicy -u $u -setpolicy "usingExpirationDate=1 expirationDateGMT=01/01/01" > /dev/null
476#echo "getting policy"
477#pwpolicy -u $u -getpolicy
478#
479#echo "getting ticket"
480#${kinit} --kdc-hostname=localhost --canon --password-file=${testdir}/foopassword ${u}@${r} && \
481#    { echo "expected to fail"; exit 1; }
482#
483#echo "unsetting policy"
484#pwpolicy -u $u -setpolicy "usingExpirationDate=0"
485#
486#echo "getting ticket"
487#${kinit} --kdc-hostname=localhost --canon --password-file=${testdir}/foopassword ${u}@${r} || \
488#    { echo "expected to pass"; exit 1; }
489
490
491echo "checking mounting with NTLM"
492host=$(hostname)
493if expr "$host" : '.*\.apple\.com' > /dev/null ; then
494    #launchctl load -F /System/Library/LaunchDaemons/com.apple.smbd.plist
495    #killall smbd
496    ${winmount} ${testbase}/apple/coswin7-local.plist ${host} || exit 1
497else
498    echo "not running windows mount test since you are no on apple network"
499fi
500
501
502sh ${leaks_kill} --check digest-service digest-service || exit 1
503sh ${leaks_kill} --check kcm kcm || exit 1
504
505echo "killing kdc (${kdcpid})"
506sh ${leaks_kill} kdc $kdcpid || exit 1
507
508toggle_launchd malloc-unset
509
510rm -rf "${testdir}/smb"
511dscl . -delete /Users/$u
512dscl . -delete /Users/$u2
513dscl . -delete /Users/$v
514dscl . -delete /Users/$s
515dscl . -delete /Users/$o
516
517trap "" EXIT
518
519exit $ec
520