proc server_pids { } { global env return [eval [concat exec $env(PS_ALL) | \ awk {{/kadmind4/ && !/awk/ && !/expect/ {printf("%d ", $2)}}}]] } proc server_exit { name status } { global wait_error_index wait_errno_index wait_status_index global server_id global kill verbose "$name: stopping V4 kpasswd server." 1 # We can't know whether the process exists or not, so we have # to ignore errors. XXX will close ever time out? catch {close $server_id} set pids [server_pids] if {$pids != {}} { verbose "server_exit killing process(es) $pids" catch {exec $kill $pids} } else { verbose "server_exit: couldn't find running server(s) to kill" } # wait hangs on AIX if the process was killed; since status == -1 # in that case, solve the problem by not waiting; the zombies will # be cleaned up when the test finishes if {$status == -1} { return 1 } set ret [wait -i $server_id] verbose "% Exit $ret" 2 if {[lindex $ret $wait_error_index] == -1} { fail "$name: wait returned error [lindex $ret $wait_errno_index]" return 0 } else { if { [lindex $ret $wait_status_index] == $status || (($status<0) && ([lindex $ret $wait_status_index] == ($status+256))) } { pass "$name" } else { fail "$name: unexpected return status [lindex $ret $wait_status_index], should be $status" return 0 } } return 1 } proc myfail { msg } { global mytest_status fail "$msg" set mytest_status 1 } proc server_start { name cmdline should_listen args } { global spawn_id server_id env global VFOURSERVER global mytest_status global sleep hostname set max_tries 60 verbose "$name: starting V4 kpasswd server." 1 for {set num_tries 0} {$num_tries <= $max_tries} {incr num_tries} { if {$num_tries} { exec $sleep 5 verbose "Couldn't connect to V4 kpasswd server; retrying ($num_tries so far)." } spawn $VFOURSERVER $cmdline set server_id $spawn_id foreach test $args { set mytest_status 0 uplevel 1 "expect { -i $server_id $test timeout { myfail \"$name: timeout\" } eof { myfail \"$name: eof while expecting string\" } }" if {$mytest_status == 1} { return 0 } } set pids [server_pids] if {$should_listen} { exec $sleep 1 set save_spawn_id $spawn_id spawn telnet $hostname kerberos_master expect { {Connection refused} { close -i $save_spawn_id wait -i $save_spawn_id close wait continue } {Connected} { send "close\n" close wait set spawn_id $save_spawn_id break } default { close -i $save_spawn_id wait -i $save_spawn_id catch {close} wait continue } } } else { break } } if {$pids == {}} { # Try twice to find the server processes. Not sure why, # but there seems to be some sort of race condition in the OS. verbose "server_start: couldn't find server process(es) -- trying again" exec $sleep 1 set pids [server_pids] } if {$num_tries > $max_tries} { myfail "$name: couldn't connect to V4 kpasswd server" return 0 } else { if {$pids != {}} { verbose "server_start: server process ID(s) is/are $pids" } pass "$name" return 1 } } proc exp_prog { name prog cmdline status args } { global spawn_id spawn_pid global mytest_status global wait_error_index wait_errno_index wait_status_index verbose "$name: spawning $prog $cmdline" 1 set spawn_pid [eval "spawn $prog $cmdline"] # at the end, eof is success # lappend args { eof { if {[regexp "\[\r\n\]$" $expect_out(buffer)] == 0} { myfail "final status message not newline-terminated" } } } lappend args { eof {} } foreach test $args { set mytest_status 0 uplevel 1 "expect { $test timeout { close; myfail \"$name: timeout\" } eof { myfail \"$name: eof while expecting string\" } }" if {$mytest_status == 1} { return 0 } } # at this point, the id is closed and we can wait on it. set ret [wait] verbose "% Exit $ret" 2 if {$status == -1} { return 1 } if {[lindex $ret $wait_error_index] == -1} { fail "$name: wait returned error [lindex $ret $wait_errno_index]" } else { if { [lindex $ret $wait_status_index] == $status || (($status<0) && ([lindex $ret $wait_status_index] == ($status+256))) } { pass "$name" } else { fail "$name: unexpected return status [lindex $ret $wait_status_index], should be $status" } } return 1 } proc fix_salt { name fullname oldpw newpw } { global kadmin_local exp_prog "$name: kadmin.local" $kadmin_local "" 0 { "kadmin.local:" { send "cpw $fullname\n" } } { "Enter password for principal \"$fullname\":" { send "$newpw\n" } } { "Re-enter password for principal \"$fullname\":" { send "$newpw\n" } } { # if we get cannot reuse pw, the salt is already right -re "Password .* changed." { send "quit\n" } -re "Cannot reuse password" { send "quit\n" } } } proc unexpire { name fullname } { global kadmin_local # While we're at it, make sure they aren't expired. exp_prog "$name: kadmin.local" $kadmin_local "" 0 { "kadmin.local:" { send "modprinc -expire \"May 6, 1999\" $fullname\n" } } { -re "Principal .* modified." { send "quit\n" } } } proc kpasswd_v4 { name fullname status oldpw newpw args } { global kpasswd_v4 s eval [concat { exp_prog $name $kpasswd_v4 "-u $fullname" $status { -re "Old password for $fullname:" { send "$oldpw\n" } } { -re "New Password for $fullname:" { send "$newpw\n" } } { -re "Verifying, please re-enter New Password for $fullname:" { send "$newpw\n" } } } $args] }