# Kerberos telnet test. # This is a DejaGnu test script. # This script tests Kerberos telnet. # Written by Ian Lance Taylor, Cygnus Support, . # Find the programs we need. We use the binaries from the build tree # if they exist. If they do not, then they must be in PATH. We # expect $objdir to be .../kerberos/src. if ![info exists TELNET] { set TELNET [findfile $objdir/../../appl/telnet/telnet/telnet] } if ![info exists TELNETD] { set TELNETD [findfile $objdir/../../appl/telnet/telnetd/telnetd] } if ![info exists LOGINKRB5] { set LOGINKRB5 [findfile $objdir/../../appl/bsd/login.krb5] } if ![regexp des- $supported_enctypes] { # Telnet needs a DES enctype. verbose "Skipping telnet tests for lack of DES support." return } # Remove old wrapper script catch "exec rm -f $tmppwd/login.wrap" # Start up a root shell. if ![setup_root_shell telnet] { return } # Make sure .k5login is reasonable. if ![check_k5login rlogin] { stop_root_shell return } # Set up the kerberos database. if {![get_hostname] \ || ![setup_kerberos_files] \ || ![setup_kerberos_env] \ || ![setup_kerberos_db 0]} { stop_root_shell return } # A procedure to start up the telnet daemon. proc start_telnet_daemon { args } { global REALMNAME global TELNETD global LOGINKRB5 global ROOT_PROMPT global tmppwd global hostname global rlogin_spawn_id global telnetd_pid global portbase # Setup the shared library wrapper for login.krb5 if ![file exists $tmppwd/login.wrap] { setup_wrapper $tmppwd/login.wrap "$LOGINKRB5 $*" } # The -debug argument tells it to accept a single connection, so # we don't need to use inetd. The portbase+8 is the port to listen at. # Note that tmppwd here is a shell variable, which is set in # setup_root_shell, not a TCL variable. send -i $rlogin_spawn_id "sh -c \"$TELNETD $args -debug -t \$tmppwd/srvtab -R $REALMNAME -L $tmppwd/login.wrap -X KERBEROS_V4 [expr 8 + $portbase]\" &\r" expect { -i $rlogin_spawn_id -re "$ROOT_PROMPT" { } timeout { send_error "ERROR: timeout from rlogin $hostname -l root\n" return } eof { send_error "ERROR: eof from rlogin $hostname -l root\n" return } } send -i $rlogin_spawn_id "echo \$!\r" expect { -i $rlogin_spawn_id -re "\[0-9\]+" { set telnetd_pid $expect_out(0,string) verbose "telnetd process ID is $telnetd_pid" } timeout { send_error "ERROR: timeout from rlogin $hostname -l root\n" return } eof { send_error "ERROR: eof from rlogin $hostname -l root\n" return } } expect { -i $rlogin_spawn_id -re "$ROOT_PROMPT" { } timeout { send_error "ERROR: timeout from rlogin $hostname -l root\n" return } eof { send_error "ERROR: eof from rlogin $hostname -l root\n" return } } # Give the telnet daemon a few seconds to get set up. sleep 2 } # A procedure to stop the telnet daemon. proc stop_telnet_daemon { } { global telnetd_pid if [info exists telnetd_pid] { catch "exec kill $telnetd_pid" unset telnetd_pid } } # Wrap the tests in a procedure, so that we can kill the daemons if # we get some sort of error. proc telnet_test { } { global REALMNAME global TELNET global BINSH global SHELL_PROMPT global KEY global hostname global localhostname global env global portbase # Start up the kerberos and kadmind daemons and get a srvtab and a # ticket file. if {![start_kerberos_daemons 0] \ || ![add_kerberos_key host/$hostname 0] \ || ![setup_srvtab 0] \ || ![add_kerberos_key $env(USER) 0] \ || ![kinit $env(USER) $env(USER)$KEY 0]} { return } # Start up the telnet daemon. start_telnet_daemon # Start up our telnet connection. We first try it without # authentication, so the daemon should prompt for a login. spawn $TELNET -- $hostname -[expr 8 + $portbase] set telnet_pid [exp_pid] expect_after { timeout { fail "$testname (timeout)" catch "expect_after" return } eof { fail "$testname (eof)" catch "expect_after" return } } set testname "simple telnet" expect { "ogin: " { pass $testname } } # Move back to telnet command mode and make sure it seems # reasonable. set testname "telnet command mode" send "\035" expect { "telnet> " { pass $testname } } set testname "telnet status" send "status\r" # use -nocase because telnet may output the fqdn in upper-case; # however, -nocase requires the whole pattern to be in lower case expect { -nocase -re "connected to $localhostname.*operating in single character mode.*catching signals locally.*remote character echo.*flow control.*escape character is '.\]'" { pass $testname } } set testname "back to command mode" # For some reason, the telnet client doesn't necessarily reset the # terminal mode back to raw after exiting command mode. # Kick it somewhat by sending a CR. send "\r" expect "ogin: " send "\035" expect { "telnet> " { pass $testname } } set testname "quit" send "quit\r" expect { "Connection closed.\r" { pass $testname } } expect_after # on hpux 10.x, the child telnet will hang in an ioctl(). This will # wait a while for an EOF, and kill the process if it doesn't exit by # itself. The hang doesn't happen when telnet is run at the shell. expect { eof { } timeout { stop_telnet_daemon } } if ![check_exit_status "exit status"] { return } pass "exit status" # The telnet daemon should have stopped, but we have no easy way # of checking whether it actually did. Kill it just in case. stop_telnet_daemon # Try an authenticated connection. start_telnet_daemon spawn $TELNET -a -k $REALMNAME -- $hostname -[expr 8 + $portbase] expect_after { timeout { fail "$testname (timeout)" catch "expect_after" return } "Connection closed by foreign host.\r" { fail "$testname (connection closed)" catch "expect_after" return } eof { fail "$testname (eof)" catch "expect_after" return } } set testname "authenticated telnet" expect "Kerberos V5 accepts you" expect { -re "$SHELL_PROMPT" { pass $testname } } # Switch to /bin/sh to try to avoid confusion from the shell # prompt. set testname "shell" send "$BINSH\r" expect -re "$SHELL_PROMPT" set testname "date" send "date\r" expect "date" expect { -re "\[A-Za-z0-9 :\]+\[\r\n\]+" { if [check_date $expect_out(0,string)] { pass "date" } else { fail "date" } } } expect -re "$SHELL_PROMPT" set testname "exit" send "exit\r" expect -re "$SHELL_PROMPT" send "exit\r" expect { "Connection closed by foreign host.\r" { pass $testname } } expect_after catch "expect eof" # We can't use check_exit_status, because we expect an exit status # of 1. set status_list [wait -i $spawn_id] verbose "wait -i $spawn_id returned $status_list (klist)" if { [lindex $status_list 2] != 0 || [lindex $status_list 3] != 1 } { send_log "exit status: $status_list\n" verbose "exit status: $status_list" fail "exit status" } else { pass "exit status" } # The telnet daemon should have stopped, but we have no easy way # of checking whether it actually did. Kill it just in case. stop_telnet_daemon # Try an authenticated encrypted connection. start_telnet_daemon spawn $TELNET -a -x -k $REALMNAME -- $hostname -[expr 8 + $portbase] expect_after { timeout { fail $testname catch "expect_after" return } eof { fail $testname catch "expect_after" return } } set testname "encrypted telnet" expect "Kerberos V5 accepts you" expect { -re "$SHELL_PROMPT" { pass $testname } } # Make sure the encryption is not destroying the text. set testname "echo" send "echo hello\r" expect "echo hello" expect "hello" expect { -re "$SHELL_PROMPT" { pass $testname } } # Move back to telnet command mode and check the encryption status. set testname "encryption status" send "\035" expect "telnet> " send "status\r" expect { -re "Currently encrypting output with DES_CFB64.*Currently decrypting input with DES_CFB64" { pass $testname } } set testname "exit status" send "exit\r" expect "Connection closed by foreign host.\r" expect_after catch "expect eof" # We can't use check_exit_status, because we expect an exit status # of 1. set status_list [wait -i $spawn_id] verbose "wait -i $spawn_id returned $status_list (klist)" if { [lindex $status_list 2] != 0 || [lindex $status_list 3] != 1 } { send_log "exit status: $status_list\n" verbose "exit status: $status_list" fail "exit status" } else { pass "exit status" } # The telnet daemon should have stopped, but we have no easy way # of checking whether it actually did. Kill it just in case. stop_telnet_daemon set testname "reject unencrypted telnet" # Check rejection of unencrypted client when encryption is required start_telnet_daemon -e # unencrypted, unauthenticated spawn $TELNET -- $hostname -[expr 8 + $portbase] expect_after { timeout { fail $testname catch "expect_after" return } eof { fail $testname catch "expect_after" return } } expect { -re "Unencrypted connection refused.*\n" { pass $testname } } catch "expect_after" catch "expect eof" catch wait # The telnet daemon should have stopped, but we have no easy way # of checking whether it actually did. Kill it just in case. stop_telnet_daemon } # Run the test. Logging in sometimes takes a while, so increase the # timeout. set oldtimeout $timeout set timeout 60 set status [catch telnet_test msg] set timeout $oldtimeout # Shut down the kerberos daemons, the telnet daemon, and the rlogin # process. stop_kerberos_daemons stop_telnet_daemon stop_root_shell if { $status != 0 } { send_error "ERROR: error in telnet.exp\n" send_error "$msg\n" exit 1 }