summaryrefslogtreecommitdiffstats
path: root/src/tests/dejagnu/krb-root/telnet.exp
blob: c283d6150bccbc3460aeebbbee5cb7f36542f19d (plain)
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
# Kerberos telnet test.
# This is a DejaGnu test script.
# This script tests Kerberos telnet.
# Written by Ian Lance Taylor, Cygnus Support, <ian@cygnus.com>.

# 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
}