1 # Basic expect script for Kerberos tests.
2 # This is a DejaGnu test script.
3 # Written by Ian Lance Taylor, Cygnus Support, <ian@cygnus.com>.
4 # This script is automatically run by DejaGnu before running any of
5 # the Kerberos test scripts.
7 # This file provides several functions which deal with a local
8 # Kerberos database. We have to do this such that we don't interfere
9 # with any existing Kerberos database. We will create all the files
10 # in the directory $tmppwd, which will have been created by the
11 # testsuite default script. We will use $REALMNAME as our Kerberos
12 # realm name, defaulting to KRBTEST.COM.
15 set stty_init {erase \^h kill \^u}
19 set tgt_support_desmd5 0
20 set supported_enctypes "des-cbc-crc:normal"
21 set kdc_supported_enctypes "des-cbc-crc:normal"
23 # The names of the individual passes must be unique; lots of things
24 # depend on it. The PASSES variable may not contain comments; only
25 # small pieces get evaluated, so comments will do strange things.
27 # Most of the purpose of using multiple passes is to exercise the
28 # dependency of various bugs on configuration file settings,
29 # particularly with regards to encryption types.
31 # The des.no-kdc-md5 pass will fail if the KDC does not constrain
32 # session key enctypes to those in its permitted_enctypes list. It
33 # works by assuming enctype similarity, thus allowing the client to
34 # request a des-cbc-md4 session key. Since only des-cbc-crc is in the
35 # KDC's permitted_enctypes list, the TGT will be unusable.
37 # KLUDGE for tracking down leaking ptys
42 upvar 1 spawn_id spawn_id
43 verbose "spawn: args=$args"
44 set pid [eval oldspawn $args]
45 verbose "spawn: pid=$pid spawn_id=$spawn_id"
49 upvar 1 spawn_id spawn_id
50 verbose "wait: args=$args"
51 set ret [eval oldwait $args]
57 # Hack around Solaris 9 kernel race condition that causes last output
58 # from a pty to get dropped.
59 if { $PRIOCNTL_HACK } {
60 catch {exec priocntl -s -c FX -m 30 -p 30 -i pid [getpid]}
63 upvar 1 spawn_id spawn_id
68 if { $arg == "-ignore" \
70 || $arg == "-leaveopen" } {
75 if [string match "-*" $arg] {
86 set newargs [concat $newargs {priocntl -e -c FX -p 0}]
90 set pid [eval oldspawn $newargs]
95 # The des.des3-tgt.no-kdc-des3 pass will fail if the KDC doesn't
96 # constrain ticket key enctypes to those in permitted_enctypes. It
97 # does this by not putting des3 in the permitted_enctypes, while
98 # creating a TGT princpal that has a des3 key as well as a des key.
100 # XXX -- master_key_type is fragile w.r.t. permitted_enctypes; it is
101 # possible to configure things such that you have a master_key_type
102 # that is not permitted, and the error message used to be cryptic.
109 {supported_enctypes=des-cbc-crc:normal}
110 {kdc_supported_enctypes=des-cbc-crc:normal}
111 {dummy=[verbose -log "DES TGT, DES enctype"]}
117 {supported_enctypes=des-cbc-crc:normal}
118 {kdc_supported_enctypes=des3-cbc-sha1:normal des-cbc-crc:normal}
119 {dummy=[verbose -log "DES3 TGT, DES enctype"]}
125 {supported_enctypes=des3-cbc-sha1:normal des-cbc-crc:normal}
126 {kdc_supported_enctypes=des3-cbc-sha1:normal des-cbc-crc:normal}
127 {dummy=[verbose -log "DES3 TGT, DES3 + DES enctypes"]}
133 {supported_enctypes=aes256-cts-hmac-sha1-96:normal des-cbc-crc:normal}
134 {kdc_supported_enctypes=aes256-cts-hmac-sha1-96:normal des-cbc-crc:normal}
135 {permitted_enctypes(kdc)=aes256-cts-hmac-sha1-96 des-cbc-crc}
136 {permitted_enctypes(client)=aes256-cts-hmac-sha1-96 des-cbc-crc}
137 {permitted_enctypes(server)=aes256-cts-hmac-sha1-96 des-cbc-crc}
138 {master_key_type=aes256-cts-hmac-sha1-96}
139 {dummy=[verbose -log "AES + DES enctypes"]}
145 {supported_enctypes=aes256-cts-hmac-sha1-96:normal}
146 {kdc_supported_enctypes=aes256-cts-hmac-sha1-96:normal}
147 {permitted_enctypes(kdc)=aes256-cts-hmac-sha1-96}
148 {permitted_enctypes(client)=aes256-cts-hmac-sha1-96}
149 {permitted_enctypes(server)=aes256-cts-hmac-sha1-96}
150 {master_key_type=aes256-cts-hmac-sha1-96}
151 {dummy=[verbose -log "AES enctypes"]}
157 {supported_enctypes=aes256-cts-hmac-sha1-96:normal}
158 {kdc_supported_enctypes=aes256-cts-hmac-sha1-96:normal}
159 {permitted_enctypes(kdc)=aes256-cts-hmac-sha1-96}
160 {permitted_enctypes(client)=aes256-cts-hmac-sha1-96}
161 {permitted_enctypes(server)=aes256-cts-hmac-sha1-96}
162 {master_key_type=aes256-cts-hmac-sha1-96}
163 {dummy=[verbose -log "AES via TCP"]}
169 {supported_enctypes=aes256-cts-hmac-sha1-96:normal des3-cbc-sha1:normal des-cbc-crc:normal}
170 {kdc_supported_enctypes=aes256-cts-hmac-sha1-96:normal des3-cbc-sha1:normal des-cbc-crc:normal}
171 {permitted_enctypes(kdc)=aes256-cts-hmac-sha1-96 des3-cbc-sha1 des-cbc-crc}
172 {permitted_enctypes(client)=aes256-cts-hmac-sha1-96 des3-cbc-sha1 des-cbc-crc}
173 {permitted_enctypes(server)=aes256-cts-hmac-sha1-96 des3-cbc-sha1 des-cbc-crc}
174 {master_key_type=aes256-cts-hmac-sha1-96}
175 {dummy=[verbose -log "AES + DES enctypes"]}
181 {supported_enctypes=aes256-cts-hmac-sha1-96:normal des3-cbc-sha1:normal des-cbc-crc:normal}
182 {kdc_supported_enctypes=aes256-cts-hmac-sha1-96:normal des3-cbc-sha1:normal des-cbc-crc:normal}
183 {permitted_enctypes(kdc)=aes256-cts-hmac-sha1-96 des3-cbc-sha1 des-cbc-crc}
184 {permitted_enctypes(client)=aes256-cts-hmac-sha1-96 des3-cbc-sha1 des-cbc-crc}
185 {permitted_enctypes(server)=aes256-cts-hmac-sha1-96 des3-cbc-sha1 des-cbc-crc}
186 {master_key_type=aes256-cts-hmac-sha1-96}
187 {dummy=[verbose -log "AES + DES enctypes, DES3 TGT"]}
193 {supported_enctypes=des-cbc-crc:v4}
194 {kdc_supported_enctypes=des-cbc-crc:v4}
195 {default_tkt_enctypes(client)=des-cbc-crc}
196 {dummy=[verbose -log "DES TGT, DES-CRC enctype, V4 salt"]}
202 {supported_enctypes=des-cbc-md5:v4 des-cbc-crc:v4}
203 {kdc_supported_enctypes=des-cbc-md5:v4 des-cbc-crc:v4}
204 {default_tkt_enctypes(client)=des-cbc-md5 des-cbc-crc}
205 {dummy=[verbose -log "DES TGT, DES-MD5 and -CRC enctypes, V4 salt"]}
208 all-des-des3-enctypes
211 {supported_enctypes=des3-cbc-sha1:normal des-cbc-crc:normal \
212 des-cbc-md5:normal des-cbc-crc:v4 des-cbc-md5:norealm \
214 {kdc_supported_enctypes=des3-cbc-sha1:normal des-cbc-crc:normal \
215 des-cbc-md5:normal des-cbc-crc:v4 des-cbc-md5:norealm \
217 {dummy=[verbose -log "DES3 TGT, many DES3 + DES enctypes"]}
224 {permitted_enctypes(kdc)=des-cbc-crc}
225 {default_tgs_enctypes(client)=des-cbc-md5 des-cbc-md4 des-cbc-crc}
226 {default_tkt_enctypes(client)=des-cbc-md5 des-cbc-md4 des-cbc-crc}
227 {supported_enctypes=des-cbc-crc:normal}
228 {kdc_supported_enctypes=des-cbc-crc:normal}
229 {master_key_type=des-cbc-crc}
230 {dummy=[verbose -log \
231 "DES TGT, KDC permitting only des-cbc-crc"]}
234 des.des3-tgt.no-kdc-des3
237 {permitted_enctypes(kdc)=des-cbc-crc}
238 {default_tgs_enctypes(client)=des-cbc-crc}
239 {default_tkt_enctypes(client)=des-cbc-crc}
240 {supported_enctypes=des3-cbc-sha1:normal des-cbc-crc:normal}
241 {kdc_supported_enctypes=des3-cbc-sha1:normal des-cbc-crc:normal}
242 {master_key_type=des-cbc-crc}
243 {dummy=[verbose -log \
244 "DES3 TGT, KDC permitting only des-cbc-crc"]}
248 # des.md5-tgt is set as unused, since it won't trigger the error case
249 # if SUPPORT_DESMD5 isn't honored.
251 # The des.md5-tgt pass will fail if enctype similarity is inconsisent;
252 # between 1.0.x and 1.1, the decrypt functions became more strict
253 # about matching enctypes, while the KDB retrieval functions didn't
254 # coerce the enctype to match what was requested. It works by setting
255 # SUPPORT_DESMD5 on the TGT principal, forcing an enctype of
256 # des-cbc-md5 on the TGT key. Since the database only contains a
257 # des-cbc-crc key, the decrypt will fail if enctypes are not coerced.
259 # des.no-kdc-md5.client-md4-skey is retained in unsed_passes, even
260 # though des.no-kdc-md5 is roughly equivalent, since the associated
261 # comment needs additional investigation at some point re the kadmin
264 # The des.no-kdc-md5.client-md4-skey will fail on TGS requests due to
265 # the KDC issuing session keys that it won't accept. It will also
266 # fail for a kadmin client, but for different reasons, since the kadm5
267 # library does some curious filtering of enctypes, and also uses
268 # get_in_tkt() rather than get_init_creds(); the former does an
269 # intersection of the enctypes provided by the caller and those listed
270 # in the config file!
277 supported_enctypes=des-cbc-crc:normal
278 kdc_supported_enctypes=des-cbc-crc:normal
279 {permitted_enctypes(kdc)=des-cbc-md5 des-cbc-md4 des-cbc-crc}
280 {permitted_enctypes(client)=des-cbc-md5 des-cbc-md4 des-cbc-crc}
281 {dummy=[verbose -log "DES TGT, SUPPORTS_DESMD5"]}
284 des.md5-tgt.no-kdc-md5
287 {permitted_enctypes(kdc)=des-cbc-crc}
288 {default_tgs_enctypes(client)=des-cbc-crc}
289 {default_tkt_enctypes(client)=des-cbc-crc}
290 {supported_enctypes=des-cbc-crc:normal}
291 {kdc_supported_enctypes=des-cbc-crc:normal}
292 {master_key_type=des-cbc-crc}
293 {dummy=[verbose -log \
294 "DES TGT, SUPPORTS_DESMD5, KDC permitting only des-cbc-crc"]}
297 des.no-kdc-md5.client-md4-skey
299 {permitted_enctypes(kdc)=des-cbc-crc}
300 {permitted_enctypes(client)=des-cbc-crc des-cbc-md4}
301 {default_tgs_enctypes(client)=des-cbc-crc des-cbc-md4}
302 {default_tkt_enctypes(client)=des-cbc-md4}
303 {supported_enctypes=des-cbc-crc:normal}
304 {kdc_supported_enctypes=des-cbc-crc:normal}
305 {dummy=[verbose -log \
306 "DES TGT, DES enctype, KDC permitting only des-cbc-crc, client requests des-cbc-md4 session key"]}
311 {supported_enctypes=\
312 aes256-cts-hmac-sha1-96:normal aes256-cts-hmac-sha1-96:norealm \
313 aes128-cts-hmac-sha1-96:normal aes128-cts-hmac-sha1-96:norealm \
314 des3-cbc-sha1:normal des3-cbc-sha1:none \
315 des-cbc-md5:normal des-cbc-md4:normal des-cbc-crc:normal \
316 des-cbc-md5:v4 des-cbc-md4:v4 des-cbc-crc:v4 \
318 {kdc_supported_enctypes=\
319 des3-cbc-sha1:normal des3-cbc-sha1:none \
320 des-cbc-md5:normal des-cbc-md4:normal des-cbc-crc:normal \
321 des-cbc-md5:v4 des-cbc-md4:v4 des-cbc-crc:v4 \
323 {dummy=[verbose -log "DES3 TGT, default enctypes"]}
325 # This won't work for anything using GSSAPI until it gets AES support.
329 {supported_enctypes=aes256-cts-hmac-sha1-96:normal}
330 {kdc_supported_enctypes=aes256-cts-hmac-sha1-96:normal}
331 {permitted_enctypes(kdc)=aes256-cts-hmac-sha1-96}
332 {permitted_enctypes(client)=aes256-cts-hmac-sha1-96}
333 {permitted_enctypes(server)=aes256-cts-hmac-sha1-96}
334 {master_key_type=aes256-cts-hmac-sha1-96}
335 {dummy=[verbose -log "AES only, no DES or DES3 support"]}
338 # {supported_enctypes=des-cbc-md5:normal des-cbc-crc:normal twofish256-hmac-sha1:normal }
339 # {kdc_supported_enctypes= des-cbc-md5:normal des-cbc-crc:normal twofish256-hmac-sha1:normal}
341 # This shouldn't be necessary on dejagnu-1.4 and later, but 1.3 seems
342 # to need it because its runtest.exp doesn't deal with PASS at all.
343 if [info exists PASS] {
344 foreach pass $passes {
345 if { [lsearch -exact $PASS [lindex $pass 0]] >= 0 } {
346 lappend MULTIPASS $pass
350 set MULTIPASS $passes
353 set last_passname_conf ""
354 set last_passname_db ""
356 # We do everything in a temporary directory.
357 if ![info exists TMPDIR] {
358 set tmppwd "[pwd]/tmpdir"
359 if ![file isdirectory $tmppwd] {
360 catch "exec mkdir $tmppwd" status
365 verbose "tmppwd=$tmppwd"
367 # On Ultrix, use /bin/sh5 in preference to /bin/sh.
368 if ![info exists BINSH] {
369 if [file exists /bin/sh5] {
376 # For security, we must not use generally known passwords. This is
377 # because some of the tests may be run as root. If the passwords were
378 # generally know, then somebody could work out the appropriate
379 # Kerberos ticket to use, and come in when, say, the telnetd daemon
380 # was being tested by root. The window for doing this is very very
381 # small, so the password does not have to be perfect, it just can't be
383 if ![info exists KEY] {
384 catch {exec $BINSH -c "echo $$"} KEY
385 verbose "KEY is $KEY"
386 set keyfile [open $tmppwd/KEY w]
391 # Clear away any files left over from a previous run.
392 # We can't use them now because we don't know the right KEY.
393 # krb5.conf might change if running tests on another host
394 catch "exec rm -f $tmppwd/db.ok $tmppwd/srvtab $tmppwd/krb5.conf $tmppwd/kdc.conf $tmppwd/cpw_srvtab $tmppwd/krb.realms $tmppwd/krb.conf"
396 # Put the installed kerberos directories on PATH.
397 # This needs to be fixed for V5.
398 # set env(PATH) $env(PATH):/usr/kerberos/bin:/usr/kerberos/etc
399 # verbose "PATH=$env(PATH)"
401 # Some of the tests expect $env(USER) to be set.
402 if ![info exists env(USER)] {
403 if [info exists env(LOGNAME)] {
404 set env(USER) $env(LOGNAME)
406 if [info exists logname] {
407 set env(USER) $logname
409 catch "exec whoami" env(USER)
414 # set the realm. The user can override this on the runtest line.
415 if ![info exists REALMNAME] {
416 set REALMNAME "KRBTEST.COM"
418 verbose "Test realm is $REALMNAME"
420 # Find some programs we need. We use the binaries from the build tree
421 # if they exist. If they do not, then they must be in PATH. We
422 # expect $objdir to be ...tests/dejagnu.
425 {KDB5_UTIL $objdir/../../kadmin/dbutil/kdb5_util}
426 {KRB5KDC $objdir/../../kdc/krb5kdc}
427 {KADMIND $objdir/../../kadmin/server/kadmind}
428 {KADMIN $objdir/../../kadmin/cli/kadmin}
429 {KADMIN_LOCAL $objdir/../../kadmin/cli/kadmin.local}
430 {KINIT $objdir/../../clients/kinit/kinit}
431 {KTUTIL $objdir/../../kadmin/ktutil/ktutil}
432 {KLIST $objdir/../../clients/klist/klist}
433 {KDESTROY $objdir/../../clients/kdestroy/kdestroy}
434 {RESOLVE $objdir/../resolve/resolve}
435 {T_INETD $objdir/t_inetd}
437 set varname [lindex $i 0]
438 if ![info exists $varname] {
439 eval set varval [lindex $i 1]
440 set varval [findfile $varval]
442 verbose "$varname=$varval"
444 eval set varval \$$varname
445 verbose "$varname already set to $varval"
449 if ![info exists RLOGIN] {
453 if ![info exists RLOGIN_FLAGS] {
454 set RLOGIN_FLAGS "-x"
457 # We use a couple of variables to hold shell prompts which may be
458 # overridden by the user.
460 if ![info exists ROOT_PROMPT] {
461 set ROOT_PROMPT "(%|#|>|\\$) $"
464 if ![info exists SHELL_PROMPT] {
465 set SHELL_PROMPT "(%|#|>|\\$) $"
468 verbose "setting up onexit handler (old handler=[exit -onexit])"
469 exit -onexit [concat {
470 verbose "calling stop_kerberos_daemons (onexit handler)"
471 stop_kerberos_daemons;
476 # Most of the tests won't work if the user has a .k5login file, unless
477 # the user's name appears with $REALMNAME in .k5login
479 # This procedure returns 1 if the .k5login file appears to be OK, 0
480 # otherwise. This check is not foolproof.
482 # Note that this previously checked for a username with no realm; this
483 # works for krb4's kuserok() but not for krb5_kuserok(), due to some
484 # implementation details. *sigh*
486 proc check_k5login { testname } {
490 if {![file exists ~/.k5login]} {
491 if {$env(USER) == "root"} {
498 verbose "looking for $env(USER)@$REALMNAME in ~/.k5login" 2
499 set file [open ~/.k5login r]
500 while { [gets $file principal] != -1 } {
501 verbose " found $principal" 2
502 if { $principal == "$env(USER)@$REALMNAME" } {
509 note "$testname test requires that your name appear in your ~/.k5login"
510 note "file in the form $env(USER)@$REALMNAME"
511 unsupported "$testname"
516 proc check_klogin { testname } {
520 if {![file exists ~/.klogin]} {
521 if {$env(USER) == "root"} {
528 verbose "looking for $env(USER) in ~/.klogin" 2
529 set file [open ~/.klogin r]
530 while { [gets $file principal] != -1 } {
531 verbose " found $principal" 2
532 if { $principal == "$env(USER)" \
533 || $principal == "$env(USER)@$REALMNAME" } {
540 note "$testname test requires that your name appear in your ~/.klogin"
541 note "file without a realm."
542 unsupported "$testname"
548 # Check the exit status of a spawned program. Returns 1 if the
549 # program succeeded, 0 if it failed.
551 proc check_exit_status { testname } {
554 verbose "about to wait ($testname)"
555 set status_list [wait -i $spawn_id]
556 verbose "wait -i $spawn_id returned $status_list ($testname)"
557 catch "close -i $spawn_id"
558 if { [lindex $status_list 2] != 0 || [lindex $status_list 3] != 0 } {
559 verbose -log "exit status: $status_list"
571 # These procedures implement an environment variable stack. They use
572 # the global variable $envvars_tosave for the purpose of identifying
573 # which environment variables to save. They also track which ones are
574 # unset at any particular point. The stack pointer is $envstackp,
575 # which is an integer. The arrays $envstack$envstackp and
576 # $unenvstack$envstackp store respectively the set of old environment
577 # variables/values pushed onto the stack and the set of old unset
578 # environment variables for a given value of $envstackp.
580 # Changing the value of $envvars_tosave after performing the first
581 # push operation may result in strangeness.
586 # Push set of current environment variables.
588 proc envstack_push { } {
590 global envvars_tosave
592 global envstack$envstackp
593 global unenvstack$envstackp
595 verbose "envstack_push: starting, sp=$envstackp"
596 foreach i $envvars_tosave {
597 if [info exists env($i)] {
598 verbose "envstack_push: saving $i=$env($i)"
599 set envstack${envstackp}($i) $env($i)
601 verbose "envstack_push: marking $i as unset"
602 set unenvstack${envstackp}($i) unset
606 verbose "envstack_push: exiting, sp=$envstackp"
612 # Pop set of current environment variables.
614 proc envstack_pop { } {
618 verbose "envstack_pop: starting, sp=$envstackp"
620 global envstack$envstackp # YUCK!!! no obvious better way though...
621 global unenvstack$envstackp
622 if {$envstackp < 0} {
623 perror "envstack_pop: stack underflow!"
626 if [info exists envstack$envstackp] {
627 foreach i [array names envstack$envstackp] {
628 if [info exists env($i)] {
629 verbose "envstack_pop: $i was $env($i)"
631 eval set env($i) \$envstack${envstackp}($i)
632 verbose "envstack_pop: restored $i to $env($i)"
634 unset envstack$envstackp
636 if [info exists unenvstack$envstackp] {
637 foreach i [array names unenvstack$envstackp] {
638 if [info exists env($i)] {
639 verbose "envstack_pop: $i was $env($i)"
641 verbose "envstack_pop: $i unset"
643 verbose "envstack_pop: ignoring already unset $i"
646 unset unenvstack$envstackp
648 verbose "envstack_pop: exiting, sp=$envstackp"
652 # Initialize the envstack
655 KRB5_CONFIG KRB5CCNAME KRBTKFILE KRB5RCACHEDIR
656 KERBEROS_SERVER KRB5_KDC_PROFILE
658 set krb5_init_vars [list ]
659 # XXX -- fix me later!
660 foreach i $runvarlist {
661 verbose "processing $i"
662 if {[regexp "^(\[^=\]*)=(.*)" $i foo evar evalue]} {
663 verbose "adding $evar to savelist"
664 lappend envvars_tosave $evar
665 verbose "savelist $envvars_tosave"
666 lappend krb5_init_vars $i
672 # setup_runtime_flags
673 # Sets the proper flags for shared libraries.
674 # Configuration is through a site.exp and the runvarlist variable
675 # Returns 1 if variables were already set, otherwise 0
676 proc setup_runtime_env { } {
678 global krb5_init_vars
681 foreach i $krb5_init_vars {
682 regexp "^(\[^=\]*)=(.*)" $i foo evar evalue
683 set env($evar) "$evalue"
684 verbose "$evar=$evalue"
690 # This procedure will get the local hostname. It sets the global
691 # variables hostname (the full name) and localhostname (the first part
692 # of the name). Returns 1 on success, 0 on failure.
694 proc get_hostname { } {
701 if {[info exists hostname] && [info exists localhostname]} {
707 catch "exec $RESOLVE -q >$tmppwd/hostname" exec_output
709 if ![string match "" $exec_output] {
710 verbose -log $exec_output
711 perror "can't get hostname"
714 set file [open $tmppwd/hostname r]
715 if { [ gets $file hostname ] == -1 } {
716 perror "no output from hostname"
720 catch "exec rm -f $tmppwd/hostname" exec_output
721 regexp "^(\[^.\]*)\\.(.*)$" $hostname foo localhostname domain
723 set hostname [string tolower $hostname]
724 set localhostname [string tolower $localhostname]
725 set domain [string tolower $domain]
726 verbose "hostname: $hostname; localhostname: $localhostname; domain $domain"
731 # modify_principal name options...
733 proc modify_principal { name args } {
737 spawn $KADMIN_LOCAL -r $REALMNAME
740 fail "modprinc (kadmin.local)"
744 fail "modprinc (kadmin.local)"
748 expect "kadmin.local: "
749 send "modprinc $args $name\r"
750 expect -re "modprinc \[^\n\r\]* $name"
751 expect -re "Principal .* modified."
755 if ![check_exit_status "kadmin.local modprinc"] {
756 perror "kadmin.local modprinc exited abnormally"
761 # kdc listens on +0..+3, depending whether we're testing reachable or not
762 # client tries +1 and +6
766 # application servers (krlogind, telnetd, krshd, ftpd, etc) +8
767 if [info exists PORTBASE] {
768 set portbase $PORTBASE
773 # setup_kerberos_files
774 # This procedure will create some Kerberos files which must be created
775 # manually before trying to run any Kerberos programs. Returns 1 on
776 # success, 0 on failure.
778 proc setup_kerberos_files { } {
783 global supported_enctypes
784 global kdc_supported_enctypes
785 global last_passname_conf
786 global multipass_name
787 global master_key_type
795 setup_krb5_conf client
796 setup_krb5_conf server
799 # Create a kdc.conf file.
800 if { ![file exists $tmppwd/kdc.conf] \
801 || $last_passname_conf != $multipass_name } {
802 if ![info exists master_key_type] {
803 set master_key_type des-cbc-md5
805 set conffile [open $tmppwd/kdc.conf w]
806 puts $conffile "\[kdcdefaults\]"
807 puts $conffile " kdc_ports = $portbase,[expr 1 + $portbase],[expr 2 + $portbase]"
808 puts $conffile " kdc_tcp_ports = $portbase,[expr 1 + $portbase],[expr 2 + $portbase]"
810 puts $conffile "\[realms\]"
811 puts $conffile " $REALMNAME = \{"
812 # puts $conffile " database_name = $tmppwd/db"
813 puts $conffile " admin_database_name = $tmppwd/adb"
814 puts $conffile " admin_database_lockfile = $tmppwd/adb.lock"
815 puts $conffile " key_stash_file = $tmppwd/stash"
816 puts $conffile " acl_file = $tmppwd/acl"
817 puts $conffile " kadmind_port = [expr 4 + $portbase]"
818 puts $conffile " kpasswd_port = [expr 5 + $portbase]"
819 puts $conffile " max_life = 1:00:00"
820 puts $conffile " max_renewable_life = 3:00:00"
821 puts $conffile " master_key_type = $master_key_type"
822 puts $conffile " master_key_name = master/key"
823 puts $conffile " supported_enctypes = $supported_enctypes"
824 puts $conffile " kdc_supported_enctypes = $kdc_supported_enctypes"
825 if { $mode == "tcp" } {
826 puts $conffile " kdc_ports = [expr 3 + $portbase]"
827 puts $conffile " kdc_tcp_ports = [expr 1 + $portbase],[expr 3 + $portbase]"
829 puts $conffile " kdc_ports = [expr 1 + $portbase]"
830 puts $conffile " kdc_tcp_ports = [expr 3 + $portbase]"
832 puts $conffile " default_principal_expiration = 2037.12.31.23.59.59"
833 puts $conffile " default_principal_flags = -postdateable forwardable"
834 puts $conffile " dict_file = $tmppwd/dictfile"
841 if ![file exists $tmppwd/acl] {
842 set aclfile [open $tmppwd/acl w]
843 puts $aclfile "krbtest/admin@$REALMNAME *"
847 # Create krb.conf file
848 if ![file exists $tmppwd/krb.conf] {
849 set conffile [open $tmppwd/krb.conf w]
850 puts $conffile "$REALMNAME"
851 puts $conffile "$REALMNAME $hostname:[expr 1 + $portbase] admin server"
855 # Create krb.realms file
856 if ![file exists $tmppwd/krb.realms] {
857 set conffile [open $tmppwd/krb.realms w]
858 puts $conffile ".[string toupper $domain] $REALMNAME"
859 puts $conffile "[string toupper $domain]. $REALMNAME"
863 # Create dictfile file.
864 if ![file exists $tmppwd/dictfile] {
865 set dictfile [open $tmppwd/dictfile w]
866 puts $dictfile "weak_password"
870 set last_passname_conf $multipass_name
874 proc setup_krb5_conf { {type client} } {
879 global last_passname_conf
880 global multipass_name
881 global default_tgs_enctypes
882 global default_tkt_enctypes
883 global permitted_enctypes
886 global KRB5_DB_MODULE_DIR
888 # Create a krb5.conf file.
889 if { ![file exists $tmppwd/krb5.$type.conf] \
890 || $last_passname_conf != $multipass_name } {
891 set conffile [open $tmppwd/krb5.$type.conf w]
892 puts $conffile "\[libdefaults\]"
893 puts $conffile " default_realm = $REALMNAME"
894 puts $conffile " dns_lookup_kdc = false"
895 if [info exists default_tgs_enctypes($type)] {
897 " default_tgs_enctypes = $default_tgs_enctypes($type)"
899 if [info exists default_tkt_enctypes($type)] {
901 " default_tkt_enctypes = $default_tkt_enctypes($type)"
903 if [info exists permitted_enctypes($type)] {
905 " permitted_enctypes = $permitted_enctypes($type)"
907 puts $conffile " krb4_config = $tmppwd/krb.conf"
908 puts $conffile " krb4_realms = $tmppwd/krb.realms"
909 puts $conffile " krb4_srvtab = $tmppwd/v4srvtab"
910 if { $mode == "tcp" } {
911 puts $conffile " udp_preference_limit = 1"
914 puts $conffile "\[realms\]"
915 puts $conffile " $REALMNAME = \{"
916 # There's probably nothing listening here. It would be a good
917 # test for the handling of a non-responsive KDC address. However,
918 # on some systems, like Tru64, we often wind up with the client's
919 # socket bound to this address, causing our request to appear in
920 # our incoming queue as if it were a response, which causes test
921 # failures. If we were running the client and KDC on different
922 # hosts, this would be okay....
923 #puts $conffile " kdc = $hostname:[expr 6 + $portbase]"
924 puts $conffile " kdc = $hostname:[expr 1 + $portbase]"
925 puts $conffile " admin_server = $hostname:[expr 4 + $portbase]"
926 puts $conffile " kpasswd_server = $hostname:[expr 5 + $portbase]"
927 puts $conffile " default_domain = $domain"
928 puts $conffile " krb524_server = $hostname:[expr 7 + $portbase]"
929 puts $conffile " database_module = foo_db2"
932 puts $conffile "\[domain_realm\]"
933 puts $conffile " .$domain = $REALMNAME"
934 puts $conffile " $domain = $REALMNAME"
936 puts $conffile "\[logging\]"
937 puts $conffile " admin_server = FILE:$tmppwd/kadmind5.log"
938 puts $conffile " kdc = FILE:$tmppwd/kdc.log"
939 puts $conffile " default = FILE:$tmppwd/others.log"
941 puts $conffile "\[dbmodules\]"
942 puts $conffile " db_module_dir = $tmppwd/../../../util/fakedest$KRB5_DB_MODULE_DIR"
943 puts $conffile " foo_db2 = {"
944 puts $conffile " db_library = db2"
945 puts $conffile " database_name = $tmppwd/db"
951 # Save the original values of the environment variables we are going
954 # XXX deal with envstack later.
956 if [info exists env(KRB5_CONFIG)] {
957 set orig_krb5_conf $env(KRB5_CONFIG)
959 catch "unset orig_krb5_config"
962 if [info exists env(KRB5CCNAME)] {
963 set orig_krb5ccname $env(KRB5CCNAME)
965 catch "unset orig_krb5ccname"
968 if [ info exists env(KRB5RCACHEDIR)] {
969 set orig_krb5rcachedir $env(KRB5RCACHEDIR)
971 catch "unset orig_krb5rcachedir"
974 if [ info exists env(KERBEROS_SERVER)] {
975 set orig_kerberos_server $env(KERBEROS_SERVER)
977 catch "unset orig_kerberos_server"
981 # Set the environment variables needed to run Kerberos programs.
983 proc setup_kerberos_env { {type client} } {
988 global krb5_init_vars
991 # Set the environment variable KRB5_CONFIG to point to our krb5.conf file.
992 # All the Kerberos tools check KRB5_CONFIG.
993 # Actually, V5 doesn't currently use this.
994 set env(KRB5_CONFIG) $tmppwd/krb5.$type.conf
995 verbose "KRB5_CONFIG=$env(KRB5_CONFIG)"
997 # Direct the Kerberos programs at a local ticket file.
998 set env(KRB5CCNAME) $tmppwd/tkt
999 verbose "KRB5CCNAME=$env(KRB5CCNAME)"
1001 # Direct the Kerberos programs at a local ticket file.
1002 set env(KRBTKFILE) $tmppwd/tktv4
1003 verbose "KRBTKFILE=$env(KRBTKFILE)"
1005 # Direct the Kerberos server at a cache file stored in the
1006 # temporary directory.
1007 set env(KRB5RCACHEDIR) $tmppwd
1008 verbose "KRB5RCACHEDIR=$env(KRB5RCACHEDIR)"
1010 # Tell the Kerberos tools how to contact the $REALMNAME server.
1011 set env(KERBEROS_SERVER) "$REALMNAME:$hostname:[expr 1 + $portbase]"
1012 verbose "KERBEROS_SERVER=$env(KERBEROS_SERVER)"
1014 # Get the run time environment variables... (including LD_LIBRARY_PATH)
1017 # Set our kdc config file.
1018 set env(KRB5_KDC_PROFILE) $tmppwd/kdc.conf
1019 verbose "KRB5_KDC_PROFILE=$env(KRB5_KDC_PROFILE)"
1021 # Create an environment setup script. (For convenience)
1022 if ![file exists $tmppwd/env.sh] {
1023 set envfile [open $tmppwd/env.sh w]
1024 puts $envfile "KRB5_CONFIG=$env(KRB5_CONFIG)"
1025 puts $envfile "KRB5CCNAME=$env(KRB5CCNAME)"
1026 puts $envfile "KRB5RCACHEDIR=$env(KRB5RCACHEDIR)"
1027 puts $envfile "KERBEROS_SERVER=$env(KERBEROS_SERVER)"
1028 puts $envfile "KRB5_KDC_PROFILE=$env(KRB5_KDC_PROFILE)"
1029 puts $envfile "export KRB5_CONFIG KRB5CCNAME KRB5RCACHEDIR"
1030 puts $envfile "export KERBEROS_SERVER KRB5_KDC_PROFILE"
1031 foreach i $krb5_init_vars {
1032 regexp "^(\[^=\]*)=(.*)" $i foo evar evalue
1033 puts $envfile "$evar=$env($evar)"
1034 puts $envfile "export $evar"
1038 if ![file exists $tmppwd/env.csh] {
1039 set envfile [open $tmppwd/env.csh w]
1040 puts $envfile "setenv KRB5_CONFIG $env(KRB5_CONFIG)"
1041 puts $envfile "setenv KRB5CCNAME $env(KRB5CCNAME)"
1042 puts $envfile "setenv KRB5RCACHEDIR $env(KRB5RCACHEDIR)"
1043 puts $envfile "setenv KERBEROS_SERVER $env(KERBEROS_SERVER)"
1044 puts $envfile "setenv KRB5_KDC_PROFILE $env(KRB5_KDC_PROFILE)"
1045 foreach i $krb5_init_vars {
1046 regexp "^(\[^=\]*)=(.*)" $i foo evar evalue
1047 puts $envfile "setenv $evar $env($evar)"
1054 # Restore the Kerberos environment, in case setup_kerberos_env was
1055 # already called by an earlier test.
1057 proc restore_kerberos_env { } {
1059 global orig_krb5_config
1060 global orig_krb5ccname
1061 global orig_krb5rcachedir
1062 global orig_kerberos_server
1064 if [info exists orig_krb5_config] {
1065 set env(KRB5_CONFIG) $orig_krb5_config
1067 catch "unset env(KRB5_CONFIG)"
1070 if [info exists orig_krb5ccname] {
1071 set env(KRB5CCNAME) $orig_krb5ccname
1073 catch "unset env(KRB5CCNAME)"
1076 if [info exists orig_krb5rcachedir] {
1077 set env(KRB5RCACHEDIR) $orig_krb5rcachedir
1079 catch "unset env(KRB5RCACHEDIR)"
1082 if [info exists orig_kerberos_server] {
1083 set env(KERBEROS_SERVER) $orig_kerberos_server
1085 catch "unset env(KERBEROS_SERVER)"
1091 # Initialize the Kerberos database. If the argument is non-zero, call
1092 # pass at relevant points. Returns 1 on success, 0 on failure.
1094 proc setup_kerberos_db { standalone } {
1102 global tgt_support_desmd5
1103 global multipass_name
1104 global last_passname_db
1108 if {!$standalone && [file exists $tmppwd/db.ok] \
1109 && $last_passname_db == $multipass_name} {
1113 catch "exec rm -f [glob -nocomplain $tmppwd/db* $tmppwd/adb*]"
1115 # Creating a new database means we need a new srvtab.
1116 catch "exec rm -f $tmppwd/srvtab"
1119 if { ![setup_kerberos_files] || ![setup_kerberos_env kdc] } {
1123 # Set up a common expect_after for use in multiple places.
1126 set test "$test (timeout)"
1130 set test "$test (eof)"
1135 set test "kdb5_util create"
1141 verbose "starting $test"
1142 spawn $KDB5_UTIL -r $REALMNAME create
1143 expect_after $def_exp_after
1145 expect "Enter KDC database master key:"
1147 set test "kdb5_util create (verify)"
1148 send "masterkey$KEY\r"
1149 expect "Re-enter KDC database master key to verify:"
1151 set test "kdb5_util create"
1152 send "masterkey$KEY\r"
1154 -re "\[Cc\]ouldn't" {
1158 "Cannot find/read stored" exp_continue
1159 "Warning: proceeding without master key" exp_continue
1163 if ![check_exit_status kdb5_util] {
1167 set ret [catch $body]
1180 # Stash the master key in a file.
1181 set test "kdb5_util stash"
1186 spawn $KDB5_UTIL -r $REALMNAME stash
1187 verbose "starting $test"
1188 expect_after $def_exp_after
1189 expect "Enter KDC database master key:"
1190 send "masterkey$KEY\r"
1193 if ![check_exit_status kdb5_util] {
1197 set ret [catch $body]
1205 catch "exec rm -f $tmppwd/db.ok $tmppwd/adb.db"
1213 # Add an admin user.
1214 #send_user "will run: $KADMIN_LOCAL -r $REALMNAME\n"
1216 set test "kadmin.local ank krbtest/admin"
1221 spawn $KADMIN_LOCAL -r $REALMNAME
1222 verbose "starting $test"
1223 expect_after $def_exp_after
1225 expect "kadmin.local: "
1226 send "ank krbtest/admin@$REALMNAME\r"
1228 expect "ank krbtest/admin@$REALMNAME\r"
1229 expect "Enter password for principal \"krbtest/admin@$REALMNAME\":"
1230 send "adminpass$KEY\r"
1231 expect "Re-enter password for principal \"krbtest/admin@$REALMNAME\":"
1232 send "adminpass$KEY\r"
1234 "Principal \"krbtest/admin@$REALMNAME\" created" { }
1235 "Principal or policy already exists while creating*" { }
1237 expect "kadmin.local: "
1241 if ![check_exit_status kadmin_local] {
1245 set ret [catch $body]
1253 catch "exec rm -f $tmppwd/db.ok $tmppwd/adb.db"
1262 # Set the TGT key to DES3.
1263 set test "kadmin.local TGT to DES3"
1268 spawn $KADMIN_LOCAL -r $REALMNAME -e des3-cbc-sha1:normal
1269 verbose "starting $test"
1270 expect_after $def_exp_after
1272 expect "kadmin.local: "
1273 send "cpw -randkey krbtgt/$REALMNAME@$REALMNAME\r"
1275 expect "cpw -randkey krbtgt/$REALMNAME@$REALMNAME\r"
1277 "Key for \"krbtgt/$REALMNAME@$REALMNAME\" randomized." { }
1279 expect "kadmin.local: "
1283 if ![check_exit_status kadmin_local] {
1287 set ret [catch $body]
1295 catch "exec rm -f $tmppwd/db.ok $tmppwd/adb.db"
1303 if $tgt_support_desmd5 {
1304 # Make TGT support des-cbc-md5
1305 set test "kadmin.local TGT to SUPPORT_DESMD5"
1310 spawn $KADMIN_LOCAL -r $REALMNAME
1311 verbose "starting $test"
1312 expect_after $def_exp_after
1314 expect "kadmin.local: "
1315 send "modprinc +support_desmd5 krbtgt/$REALMNAME@$REALMNAME\r"
1317 expect "modprinc +support_desmd5 krbtgt/$REALMNAME@$REALMNAME\r"
1319 "Principal \"krbtgt/$REALMNAME@$REALMNAME\" modified.\r\n" { }
1321 expect "kadmin.local: "
1325 if ![check_exit_status kadmin_local] {
1329 set ret [catch $body]
1337 catch "exec rm -f $tmppwd/db.ok $tmppwd/adb.db"
1347 # create the admin database lock file
1348 catch "exec touch $tmppwd/adb.lock"
1350 set last_passname_db $multipass_name
1354 proc start_tail { fname spawnid_var pid_var which standalone } {
1355 upvar $spawnid_var spawnid
1359 set f [open $fname a]
1361 spawn tail -f $fname
1362 set spawnid $spawn_id
1365 set markstr "===MARK $pid [clock format [clock seconds]] ==="
1370 set otimeout $timeout
1373 while { $ok == 0 && $p < 3 } {
1376 -ex "$markstr\r\n" { set ok 1 }
1377 -re "\[^\r\n\]*\r\n" { exp_continue }
1379 # Some versions of GNU tail had a race condition where
1380 # the first batch of data would be read from the end
1381 # of the file, and then there was a brief window
1382 # before calling stat and recording the size of the
1383 # file. If the marker is written during that window,
1384 # then yet another file modification is needed to get
1385 # the first one noticed.
1387 verbose -log "no tail output yet, prodding with a blank line"
1394 verbose -log "tail $fname output:"
1395 verbose -log [exec tail $fname]
1397 verbose -log "tail -f timed out ($timeout sec) looking for mark in $which log"
1400 perror "$which tail -f timed out ($timeout sec) looking for mark in $which log"
1402 stop_kerberos_daemons
1404 expect -i $spawn_id eof
1406 set timeout $otimeout
1413 set timeout $otimeout
1417 # start_kerberos_daemons
1418 # A procedure to build a Kerberos database and start up the kerberos
1419 # and kadmind daemons. This sets the global variables kdc_pid,
1420 # kdc_spawn_id, kadmind_pid, and kadmind_spawn_id. The procedure
1421 # stop_kerberos_daemons should be used to stop the daemons. If the
1422 # argument is non-zero, call pass at relevant points. Returns 1 on
1423 # success, 0 on failure.
1425 proc start_kerberos_daemons { standalone } {
1434 global kadmind_spawn_id
1439 if ![setup_kerberos_db 0] {
1444 catch "exec rm -f $tmppwd/krb.log"
1445 catch "exec rm -f $tmppwd/kadmind.log"
1446 catch "exec rm -f $tmppwd/krb5kdc_rcache"
1449 # Start up the kerberos daemon
1450 # Why are we doing all this with the log file you may ask.
1451 # We need a handle on when the server starts. If we log the output
1452 # of the server to say stderr, then if we stop looking for output,
1453 # buffers will fill and the server will stop working....
1454 # So, we look to see when a line is added to the log file and then
1456 # The same thing is done a little later for the kadmind
1457 set kdc_lfile $tmppwd/kdc.log
1458 set kadmind_lfile $tmppwd/kadmind5.log
1460 if ![start_tail $kdc_lfile tailf_spawn_id tailf_pid krb5kdc $standalone] {
1465 setup_kerberos_env kdc
1466 spawn $KRB5KDC -r $REALMNAME -n -4 full
1468 set kdc_pid [exp_pid]
1469 set kdc_spawn_id $spawn_id
1473 -re "commencing operation\r\n" { }
1474 -re "krb5kdc: \[a-zA-Z\]* - Cannot bind server socket to \[ 0-9a-fA-F:.\]*\r\n" {
1475 verbose -log "warning: $expect_out(0,string)"
1478 "no sockets set up?" {
1480 verbose -log "krb5kdc startup failed to bind listening sockets"
1483 perror "krb5kdc startup failed to bind listening sockets"
1485 stop_kerberos_daemons
1486 exec kill $tailf_pid
1487 expect -i $tailf_spawn_id eof
1488 wait -i $tailf_spawn_id
1493 verbose -log "krb5kdc startup timed out"
1496 perror "krb5kdc startup timed out"
1498 stop_kerberos_daemons
1499 exec kill $tailf_pid
1500 expect -i $tailf_spawn_id eof
1501 wait -i $tailf_spawn_id
1505 exec kill $tailf_pid
1506 expect -i $tailf_spawn_id eof
1507 wait -i $tailf_spawn_id
1513 # Give the kerberos daemon a few seconds to get set up.
1517 # Save setting of KRB5_KTNAME. We do not want to override kdc.conf
1518 # file during kadmind startup. (this is in case user has KRB5_KTNAME
1519 # set before starting make check)
1521 if [info exists env(KRB5_KTNAME)] {
1522 set start_save_ktname $env(KRB5_KTNAME)
1524 catch "unset env(KRB5_KTNAME)"
1526 if ![start_tail $kadmind_lfile tailf_spawn_id tailf_pid kadmind $standalone] {
1530 # Start up the kadmind daemon
1531 # XXXX kadmind uses stderr a lot. the sh -c and redirect can be
1532 # removed when this is fixed
1534 setup_kerberos_env kdc
1535 spawn $BINSH -c "exec $KADMIND -r $REALMNAME -nofork 2>>$kadmind_lfile"
1537 set kadmind_pid [exp_pid]
1538 set kadmind_spawn_id $spawn_id
1540 # Restore KRB5_KTNAME
1541 if [info exists start_save_ktname] {
1542 set env(KRB5_KTNAME) $start_save_ktname
1543 unset start_save_ktname
1548 "Seeding random number" exp_continue
1549 "cannot initialize network" {
1551 verbose -log "kadmind failed network init"
1554 perror "kadmind failed network init"
1556 stop_kerberos_daemons
1557 exec kill $tailf_pid
1558 expect -i $tailf_spawn_id eof
1559 wait -i $tailf_spawn_id
1562 "cannot bind to network address" {
1564 verbose -log "kadmind failed to bind socket"
1567 perror "kadmind failed to bind socket"
1569 stop_kerberos_daemons
1570 exec kill $tailf_pid
1571 expect -i $tailf_spawn_id eof
1572 wait -i $tailf_spawn_id
1575 "No principal in keytab matches desired name" {
1582 verbose -log "kadmind failed to start"
1585 verbose -log "kadmind failed to start"
1586 perror "kadmind failed to start"
1589 stop_kerberos_daemons
1590 exec kill $tailf_pid
1591 expect -i $tailf_spawn_id eof
1592 wait -i $tailf_spawn_id
1596 exec kill $tailf_pid
1597 expect -i $tailf_spawn_id eof
1598 wait -i $tailf_spawn_id
1604 # Give the kadmind daemon a few seconds to get set up.
1610 # stop_kerberos_daemons
1611 # Stop the kerberos daemons. Returns 1 on success, 0 on failure.
1613 proc stop_kerberos_daemons { } {
1617 global kadmind_spawn_id
1619 verbose "entered stop_kerberos_daemons"
1621 if [info exists kdc_pid] {
1622 if [catch "exec kill $kdc_pid" msg] {
1623 verbose "kill kdc: $msg"
1625 if [catch "expect -i $kdc_spawn_id eof" msg] {
1626 verbose "expect kdc eof: $msg"
1628 set kdc_list [wait -i $kdc_spawn_id]
1629 verbose "wait -i $kdc_spawn_id returned $kdc_list (kdc)"
1634 if [info exists kadmind_pid] {
1635 if [catch "exec kill $kadmind_pid" msg] {
1636 verbose "kill kadmind: $msg"
1638 if [catch "expect -i $kadmind_spawn_id eof" msg] {
1639 verbose "expect kadmind eof: $msg"
1641 set kadmind_list [wait -i $kadmind_spawn_id]
1642 verbose "wait -i $kadmind_spawn_id returned $kadmind_list (kadmind5)"
1647 verbose "exiting stop_kerberos_daemons"
1653 # Add an key to the Kerberos database. start_kerberos_daemons must be
1654 # called before this procedure. If the standalone argument is
1655 # non-zero, call pass at relevant points. Returns 1 on success, 0 on
1658 proc add_kerberos_key { kkey standalone } {
1664 # Use kadmin to add an key.
1665 set test "kadmin ank $kkey"
1668 setup_kerberos_env client
1669 spawn $KADMIN -p krbtest/admin@$REALMNAME -q "ank $kkey@$REALMNAME"
1671 verbose "starting $test"
1673 "Cannot contact any KDC" {
1674 set test "$test (lost KDC)"
1678 set test "$test (timeout)"
1682 set test "$test (eof)"
1686 expect -re "assword\[^\r\n\]*: *"
1687 send "adminpass$KEY\r"
1688 expect "Enter password for principal \"$kkey@$REALMNAME\":"
1691 expect "Re-enter password for principal \"$kkey@$REALMNAME\":"
1695 "Principal \"$kkey@$REALMNAME\" created" { }
1696 "Principal or policy already exists while creating*" { }
1699 if ![check_exit_status kadmin] {
1703 set ret [catch $body]
1724 spawn $KADMIN_LOCAL -r $REALMNAME
1727 perror "failed to get debugging dump of database (eof)"
1730 perror "failed to get debugging dump of database (timeout)"
1733 expect "kadmin.local: "
1735 expect "kadmin.local: "
1742 # Add a key with a random password to the Kerberos database.
1743 # start_kerberos_daemons must be called before this procedure. If the
1744 # standalone argument is non-zero, call pass at relevant points.
1745 # Returns 1 on success, 0 on failure.
1747 proc add_random_key { kkey standalone } {
1753 # Use kadmin to add an key.
1754 set test "kadmin ark $kkey"
1757 setup_kerberos_env client
1758 spawn $KADMIN -p krbtest/admin@$REALMNAME -q "ank -randkey $kkey@$REALMNAME"
1762 set test "$test (timeout)"
1766 set test "$test (eof)"
1770 expect -re "assword\[^\r\n\]*: *"
1771 send "adminpass$KEY\r"
1773 "Principal \"$kkey@$REALMNAME\" created" { }
1774 "Principal or policy already exists while creating*" { }
1777 if ![check_exit_status kadmin] {
1797 # Set up a srvtab file. start_kerberos_daemons and add_random_key
1798 # $id/$hostname must be called before this procedure. If the
1799 # argument is non-zero, call pass at relevant points. Returns 1 on
1800 # success, 0 on failure. If the id field is not provided, host is used.
1802 proc setup_srvtab { standalone {id host} } {
1811 if {!$standalone && [file exists $tmppwd/srvtab] && $last_service == $id} {
1815 catch "exec rm -f $tmppwd/srvtab $tmppwd/srvtab.old"
1817 if ![get_hostname] {
1821 catch "exec rm -f $hostname-new-srvtab"
1824 setup_kerberos_env kdc
1825 spawn $KADMIN_LOCAL -r $REALMNAME
1828 -re "(.*)\r\nkadmin.local: " {
1829 fail "kadmin.local srvtab (unmatched output: $expect_out(1,string))"
1831 catch "exec rm -f $tmppwd/srvtab"
1833 catch "expect_after"
1837 fail "kadmin.local srvtab"
1839 catch "exec rm -f $tmppwd/srvtab"
1841 catch "expect_after"
1845 fail "kadmin.local srvtab"
1847 catch "exec rm -f $tmppwd/srvtab"
1849 catch "expect_after"
1853 expect "kadmin.local: "
1854 send "xst -k $hostname-new-srvtab $id/$hostname\r"
1855 expect "xst -k $hostname-new-srvtab $id/$hostname\r\n"
1857 -re ".*Entry for principal $id/$hostname.* added to keytab WRFILE:$hostname-new-srvtab." { }
1858 -re "\r\nkadmin.local: " {
1860 fail "kadmin.local srvtab"
1862 catch "exec rm -f $tmppwd/srvtab"
1868 expect "kadmin.local: "
1872 if ![check_exit_status "kadmin.local srvtab"] {
1874 catch "exec rm -f $tmppwd/srvtab"
1879 catch "exec mv -f $hostname-new-srvtab $tmppwd/srvtab" exec_output
1880 if ![string match "" $exec_output] {
1881 verbose -log "$exec_output"
1882 perror "can't mv new srvtab"
1887 pass "kadmin.local srvtab"
1890 # Make the srvtab file globally readable in case we are using a
1891 # root shell and the srvtab is NFS mounted.
1892 catch "exec chmod a+r $tmppwd/srvtab"
1894 # Remember what we just extracted
1895 set last_service $id
1901 # Use kinit to get a ticket. If the argument is non-zero, call pass
1902 # at relevant points. Returns 1 on success, 0 on failure.
1904 proc kinit { name pass standalone } {
1909 # Use kinit to get a ticket.
1911 # For now always get forwardable tickets. Later when we need to make
1912 # tests that distiguish between forwardable tickets and otherwise
1913 # we should but another option to this proc. --proven
1915 spawn $KINIT -5 -f $name@$REALMNAME
1917 "Password for $name@$REALMNAME:" {
1918 verbose "kinit started"
1931 if ![check_exit_status kinit] {
1942 proc kinit_kt { name keytab standalone testname } {
1947 # Use kinit to get a ticket.
1949 # For now always get forwardable tickets. Later when we need to make
1950 # tests that distiguish between forwardable tickets and otherwise
1951 # we should but another option to this proc. --proven
1953 spawn $KINIT -5 -f -k -t $keytab $name@$REALMNAME
1956 fail "kinit $testname"
1961 if ![check_exit_status "kinit $testname"] {
1966 pass "kinit $testname"
1972 # List tickets. Requires client and server names, and test name.
1973 # Checks that klist exist status is zero.
1974 # Records pass or fail, and returns 1 or 0.
1975 proc do_klist { myname servname testname } {
1981 -re "Ticket cache:\[ \]*(.+:)?$tmppwd/tkt.*Default principal:\[ \]*$myname.*$servname\r\n" {
1982 verbose "klist started"
1996 if ![check_exit_status $testname] {
2003 proc do_klist_kt { keytab testname } {
2007 spawn $KLIST -5 -e -k $keytab
2009 -re "Keytab name:\[ \]*(.+:)?.*KVNO Principal\r\n---- -*\r\n" {
2010 verbose "klist started"
2024 -re { *[0-9][0-9]* *[a-zA-Z/@.-]* \([/a-zA-Z 0-9-]*\) *\r\n} {
2025 verbose -log "key: $expect_out(buffer)"
2031 if ![check_exit_status $testname] {
2038 proc do_klist_err { testname } {
2043 # Might say "credentials cache" or "credentials cache file".
2045 -re "klist: No credentials cache.*found.*\r\n" {
2046 verbose "klist started"
2057 # We can't use check_exit_status, because we expect an exit status
2060 set status_list [wait -i $spawn_id]
2061 verbose "wait -i $spawn_id returned $status_list ($testname)"
2062 if { [lindex $status_list 2] != 0 } {
2063 fail "$testname (bad exit status) $status_list"
2065 } else { if { [lindex $status_list 3] != 1 } {
2066 fail "$testname (bad exit status) $status_list"
2074 proc do_kdestroy { testname } {
2077 if ![check_exit_status $testname] {
2085 proc xst { keytab name } {
2090 setup_kerberos_env kdc
2091 spawn $KADMIN_LOCAL -r $REALMNAME
2095 -re "(.*)\r\nkadmin.local: " {
2096 fail "kadmin.local xst $keytab (unmatched output: $expect_out(1,string)"
2097 catch "expect_after"
2101 fail "kadmin.local xst $keytab (timeout)"
2102 catch "expect_after"
2106 fail "kadmin.local xst $keytab (eof)"
2107 catch "expect_after"
2111 expect "kadmin.local: "
2112 send "xst -k $keytab $name\r"
2113 expect -re "xst -k \[^\r\n\]*\r\n.*Entry for principal .* added to keytab WRFILE:.*\r\nkadmin.local: "
2117 if ![check_exit_status "kadmin.local $keytab"] {
2118 perror "kadmin.local xst $keytab exited abnormally"
2124 # v4_compatible_enctype
2125 # Returns 1 if v4 testing is enabled this passes encryption types are compatable with kerberos 4 work
2126 proc v4_compatible_enctype {} {
2127 global supported_enctypes
2130 if ![info exists KRBIV] {
2134 if { $KRBIV && [string first des-cbc-crc:v4 "$supported_enctypes"] >= 0} {
2142 # Use kinit to get a ticket. If the argument is non-zero, call pass
2143 # at relevant points. Returns 1 on success, 0 on failure.
2145 proc v4kinit { name pass standalone } {
2151 # Use kinit to get a ticket.
2153 # For now always get forwardable tickets. Later when we need to make
2154 # tests that distiguish between forwardable tickets and otherwise
2155 # we should but another option to this proc. --proven
2157 spawn $KINIT -4 $name@$REALMNAME
2159 "Password for $name@$REALMNAME:" {
2160 verbose "v4kinit started"
2173 if {$des3_krbtgt == 0} {
2174 if ![check_exit_status v4kinit] {
2178 # Fail if kinit is successful with a des3 TGT.
2179 set status_list [wait -i $spawn_id]
2180 set testname v4kinit
2181 verbose "wait -i $spawn_id returned $status_list ($testname)"
2182 if { [lindex $status_list 2] != 0 || [lindex $status_list 3] != 1 } {
2183 verbose -log "exit status: $status_list"
2184 fail "$testname (exit status)"
2194 proc v4kinit_kt { name keytab standalone } {
2199 # Use kinit to get a ticket.
2201 # For now always get forwardable tickets. Later when we need to make
2202 # tests that distiguish between forwardable tickets and otherwise
2203 # we should but another option to this proc. --proven
2205 spawn $KINIT -4 -k -t $keytab $name@$REALMNAME
2213 if ![check_exit_status kinit] {
2225 # Client and server are regular expressions.
2226 proc v4klist { client server testname } {
2232 -re "Kerberos 4 ticket cache:\[ \]*(.+:)?$tmppwd/tkt.*Principal:\[ \]*$client.*$server\r\n" {
2233 verbose "klist started"
2247 if ![check_exit_status $testname] {
2255 proc v4kdestroy { testname } {
2258 if ![check_exit_status $testname] {
2265 # Try to list the krb4 tickets -- there shouldn't be any ticket file.
2266 proc v4klist_none { testname } {
2270 # Double check that the ticket was destroyed.
2273 -re "Kerberos 4 ticket cache:\[ \]*(.+:)?$tmppwd/tkt.*klist: You have no tickets cached.*\r\n" {
2274 verbose "v4klist started"
2275 pass "$testname (output)"
2278 fail "$testname (output)"
2279 # Skip the 'wait' below, if it's taking too long.
2280 untested "$testname (exit status)"
2284 fail "$testname (output)"
2287 # We can't use check_exit_status, because we expect an exit status
2290 set status_list [wait -i $spawn_id]
2291 verbose "wait -i $spawn_id returned $status_list (v4klist)"
2292 if { [lindex $status_list 2] != 0 } {
2293 fail "$testname (exit status)"
2296 if { [lindex $status_list 3] != 1 } {
2297 fail "$testname (exit status)"
2300 pass "$testname (exit status)"
2306 # Set up a root shell using rlogin $hostname -l root. This is used
2307 # when testing the daemons that must be run as root, such as telnetd
2308 # or rlogind. This sets the global variables rlogin_spawn_id and
2309 # rlogin_pid. Returns 1 on success, 0 on failure.
2311 # This procedure will only succeed if the person running the test has
2312 # a valid ticket for a name listed in the /.klogin file. Naturally,
2313 # Kerberos must already be installed on this machine. It's a pain,
2314 # but I can't think of a better approach.
2316 if ![info exists can_get_root] { set can_get_root yes }
2318 proc setup_root_shell { testname } {
2325 global rlogin_spawn_id
2329 global krb5_init_vars
2334 if [string match $can_get_root no] {
2335 note "$testname test requires ability to log in as root"
2336 unsupported $testname
2340 # Make sure we are using the original values of the environment
2341 # variables. This means that the caller must call
2342 # setup_kerberos_env after calling this procedure.
2344 # XXX fixme to deal with envstack
2345 restore_kerberos_env
2349 set me [exec whoami]
2350 if [string match root $me] {
2351 return [setup_root_shell_noremote $testname]
2354 if ![get_hostname] {
2359 # If you have not installed Kerberos on your system, and you want
2360 # to run these tests, you can do it if you are willing to put your
2361 # root password in this file (this is not a very good idea, but
2362 # it's safe enough if you disconnect from the network and remember
2363 # to remove the password later). Change the rlogin in the next
2364 # line to be /usr/ucb/rlogin (or whatever is appropriate for your
2365 # system). Then change the lines after "word:" a few lines
2366 # farther down to be
2367 # send "rootpassword\r"
2370 eval spawn $RLOGIN $hostname -l root $RLOGIN_FLAGS
2371 set rlogin_spawn_id $spawn_id
2372 set rlogin_pid [exp_pid]
2373 set old_timeout $timeout
2378 -re {connect to address [0-9a-fA-F.:]*: Connection refused} {
2379 note $expect_out(buffer)
2383 -re "word:|erberos rlogin failed|ection refused|ection reset by peer|not authorized" {
2384 note "$testname test requires ability to rlogin as root"
2385 unsupported "$testname"
2386 set timeout $old_timeout
2391 "Cannot assign requested address" {
2392 note "$testname: rlogin as root 'cannot assign requested address'"
2393 unsupported "$testname"
2394 set timeout $old_timeout
2399 -re "usage: rlogin|illegal option -- x|invalid option -- x" {
2400 note "$testname: rlogin doesn't like command-line flags"
2401 unsupported "$testname"
2402 set timeout $old_timeout
2407 -re "$ROOT_PROMPT" { }
2409 perror "timeout from rlogin $hostname -l root"
2410 perror "If you have an unusual root prompt,"
2411 perror "try running with ROOT_PROMPT=\"regexp\""
2412 set timeout $old_timeout
2419 # reported some errors, continued, and failed
2420 note "$testname test requires ability to log in as root"
2421 unsupported $testname
2424 # perror "eof from rlogin $hostname -l root"
2425 note "eof (and unrecognized messages?) from rlogin $hostname -l root"
2426 note "$testname test requires ability to log in as root"
2427 unsupported $testname
2430 set timeout $old_timeout
2431 catch "expect_after"
2439 perror "timeout from rlogin $hostname -l root"
2441 set timeout $old_timeout
2442 catch "expect_after"
2447 perror "eof from rlogin $hostname -l root"
2449 set timeout $old_timeout
2450 catch "expect_after"
2456 # Make sure the root shell is using /bin/sh.
2459 -re "$ROOT_PROMPT" { }
2462 # Set up a shell variable tmppwd. The callers use this to keep
2463 # command line lengths down. The command line length is important
2464 # because we are feeding input to a shell via a pty. On some
2465 # systems a pty will only accept 255 characters.
2466 send "tmppwd=$tmppwd\r"
2468 -re "$ROOT_PROMPT" { }
2471 # Set up our krb5.conf
2472 send "KRB5_CONFIG=$tmppwd/krb5.server.conf\r"
2474 -re "$ROOT_PROMPT" { }
2476 send "export KRB5_CONFIG\r"
2478 -re "$ROOT_PROMPT" { }
2481 # For all of our runtime environment variables - send them over...
2482 foreach i $krb5_init_vars {
2483 regexp "^(\[^=\]*)=(.*)" $i foo evar evalue
2484 send "$evar=$env($evar)\r"
2486 -re "$ROOT_PROMPT" { }
2489 send "export $evar\r"
2491 -re "$ROOT_PROMPT" { }
2495 # Move over to the right directory.
2499 -re "$ROOT_PROMPT" { }
2501 perror "root shell can not cd to $dir"
2502 set timeout $old_timeout
2510 set timeout $old_timeout
2515 proc setup_root_shell_noremote { testname } {
2520 global rlogin_spawn_id
2524 global krb5_init_vars
2527 set rlogin_spawn_id $spawn_id
2528 set rlogin_pid [exp_pid]
2532 perror "timeout from root shell"
2534 catch "expect_after"
2538 perror "eof from root shell"
2540 catch "expect_after"
2545 -re "$ROOT_PROMPT" { }
2548 # Set up a shell variable tmppwd. The callers use this to keep
2549 # command line lengths down. The command line length is important
2550 # because we are feeding input to a shell via a pty. On some
2551 # systems a pty will only accept 255 characters.
2552 send "tmppwd=$tmppwd\r"
2554 -re "$ROOT_PROMPT" { }
2557 # Set up our krb5.conf
2558 send "KRB5_CONFIG=$tmppwd/krb5.server.conf\r"
2560 -re "$ROOT_PROMPT" { }
2562 send "export KRB5_CONFIG\r"
2564 -re "$ROOT_PROMPT" { }
2567 # For all of our runtime environment variables - send them over...
2568 foreach i $krb5_init_vars {
2569 regexp "^(\[^=\]*)=(.*)" $i foo evar evalue
2570 send "$evar=$env($evar)\r"
2572 -re "$ROOT_PROMPT" { }
2575 send "export $evar\r"
2577 -re "$ROOT_PROMPT" { }
2581 # Move over to the right directory.
2585 -re "$ROOT_PROMPT" { }
2587 perror "root shell can not cd to $dir"
2598 # Kill off a root shell started by setup_root_shell.
2600 proc stop_root_shell { } {
2601 global rlogin_spawn_id
2604 catch "close -i $rlogin_spawn_id"
2605 catch "exec kill $rlogin_pid"
2607 catch "exec kill -9 $rlogin_pid"
2608 catch "wait -i $rlogin_spawn_id"
2611 # Check the date. The string will be the output of date on this
2612 # system, and we must make sure that it is in the same timezone as the
2613 # output of date run a second time. The first date will be run on an
2614 # rlogin or some such connection to the local system. This is to test
2615 # to make sure that the TZ environment variable is handled correctly.
2616 # Returns 1 on sucess, 0 on failure.
2618 proc check_date { date } {
2619 catch "exec date" ndate
2622 scan $date "%s %s %d %d:%d:%d %s %d" adow amon adom ahr amn asc atz ayr
2623 scan $ndate "%s %s %d %d:%d:%d %s %d" ndow nmon ndom nhr nmn nsc ntz nyr
2624 if { $atz != $ntz } {
2625 verbose -log "date check failed: $atz != $ntz"
2631 proc touch { file } {
2632 set f [open $file "a"]
2637 # Implement this in tcl someday?
2638 proc tail1 { file } {
2643 # Sets up a wraper script to set the runtime shared library environment
2644 # variables and then executes a specific command. This is used to allow
2645 # a "rsh klist" or telnetd to execute login.krb5.
2646 proc setup_wrapper { file command } {
2649 global krb5_init_vars
2651 # We will start with a BINSH script
2652 catch "exec rm -f $file"
2654 set f [open $file "w" 0777]
2656 puts $f "KRB5_CONFIG=$env(KRB5_CONFIG)"
2657 puts $f "export KRB5_CONFIG"
2658 foreach i $krb5_init_vars {
2659 regexp "^(\[^=\]*)=(.*)" $i foo evar evalue
2660 puts $f "$evar=$env($evar)"
2661 puts $f "export $evar"
2663 puts $f "exec $command"
2670 stop_kerberos_daemons
2673 # helpful sometimes for debugging the test suite
2674 proc spawn_xterm { } {
2676 foreach i {KDB5_UTIL KRB5KDC KADMIND KADMIN KADMIN_LOCAL KINIT KTUTIL KLIST RLOGIN RLOGIND FTP FTPD KPASSWD REALMNAME GSSCLIENT} {
2678 if [info exists $i] { set env($i) [set $i] }