aboutsummaryrefslogtreecommitdiff
path: root/src/lib/rpc/unit-test/lib/helpers.exp
blob: b69be5b6bb49ca3e9479d223702e323e640ebf7a (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
if {[info commands exp_version] != {}} {
	set exp_version_4 [regexp {^4} [exp_version]]
} else {
	set exp_version_4 [regexp {^4} [expect_version]]
}

# Backward compatibility until we're using expect 5 everywhere
if {$exp_version_4} {
	global wait_error_index wait_errno_index wait_status_index
	set wait_error_index 0
	set wait_errno_index 1
	set wait_status_index 1
} else {
	set wait_error_index 2
	set wait_errno_index 3
	set wait_status_index 3
}
				
proc set_from_env {varname default_value} {
    global env
    upvar $varname v

    if [info exists env($varname)] {
	set v $env($varname)
    } else {
	set v $default_value
    }
}
proc expect_tcl_prompt {} {
    global kadmin_tcl_spawn_id
    expect {
	-i $kadmin_tcl_spawn_id
	-re "^% $" { }
	-re . { perror "unexpected output {$expect_out(buffer)} from subprocess, expecting tcl prompt" }
	timeout { perror "timeout waiting for tcl prompt" }
	eof { perror "eof from subprocess when expecting tcl prompt" }
    }
}
proc send_tcl_cmd_await_echo {cmd} {
    global kadmin_tcl_spawn_id
    send -i $kadmin_tcl_spawn_id "$cmd\n"
    expect {
	-i $kadmin_tcl_spawn_id
	-ex "$cmd\r\n" { }
	timeout { perror "timeout waiting for tcl subprocess to echo input" }
	eof { perror "eof waiting for tcl subprocess to echo input" }
    }
}
proc expect_kadm_ok {} {
    global kadmin_tcl_spawn_id
    expect {
	-i $kadmin_tcl_spawn_id
	-re "^OK OVSEC_KADM_OK \[^\n\]*\n" {}
	-re "^ERROR \[^\n\]*\n" { perror "kadmin tcl subprocess reported unexpected error" }
	-re "^marshall_new_creds: \[^\n\]*\n" { exp_continue }
	-re "^gssapi_\[^\n\]*\n" { exp_continue }
	-re "^\r?\n" { exp_continue }
	eof	{ perror "kadmin tcl subprocess died" }
	default { perror "didn't get ok back" }
    }
}
# trying to translate rpc_test_setup.sh into inline tcl...
proc setup_database {} {
    global env spawn_id kadmin_tcl_spawn_id TESTDIR MAKE_KEYTAB CANON_HOST

    # XXXXX
    set_from_env TOP {/x/x/x/x/x}
    send_user "TOP=$TOP\n"

    set_from_env TESTDIR $env(TOP)/testing
    set_from_env CLNTTCL $TESTDIR/util/ovsec_kadm_clnt_tcl
    set_from_env TCLUTIL $TESTDIR/tcl/util.t
    set env(TCLUTIL) $TCLUTIL
    set_from_env MAKE_KEYTAB $TESTDIR/scripts/make-host-keytab.pl
    set env(PATH) "$TOP/install/admin:$env(PATH)"

    # $VERBOSE ?

    if [info exists spawn_id] { set x $spawn_id }
    spawn $CLNTTCL
    set kadmin_tcl_spawn_id $spawn_id
    if [info exists x] { set spawn_id $x }

    expect_tcl_prompt
    # tcl 8.4 for some reason screws up autodetection of output EOL
    # translation.  Work around it for now.
    send_tcl_cmd_await_echo "if { \[info commands fconfigure\] != \"\" } { fconfigure stdout -translation lf }"
    expect_tcl_prompt
    send_tcl_cmd_await_echo "source {$TCLUTIL}"
    expect_tcl_prompt
    send_tcl_cmd_await_echo "set h {$CANON_HOST}"
    expect {
	-ex "$CANON_HOST\r\n" { }
	timeout { perror "timeout waiting for subprocess" }
	eof { perror "eof from subprocess" }
    }
    expect_tcl_prompt

    send_tcl_cmd_await_echo {ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 server_handle}
    expect_kadm_ok
    expect "^% "
    send_tcl_cmd_await_echo {ovsec_kadm_create_principal $server_handle [simple_principal server/$h] {OVSEC_KADM_PRINCIPAL} admin}
    expect_kadm_ok
    expect "^% "
    send_tcl_cmd_await_echo {ovsec_kadm_randkey_principal $server_handle server/$h key}
    expect_kadm_ok
    expect "^% "
    send_tcl_cmd_await_echo {ovsec_kadm_create_principal $server_handle [simple_principal notserver/$h] {OVSEC_KADM_PRINCIPAL} admin}
    expect_kadm_ok
    expect "^% "
    send_tcl_cmd_await_echo {ovsec_kadm_randkey_principal $server_handle notserver/$h key}
    expect_kadm_ok
    expect "^% "
    send_tcl_cmd_await_echo {ovsec_kadm_destroy $server_handle}
    expect_kadm_ok
    expect "^% "
    wait -nowait -i $spawn_id
    close -i $spawn_id
}

if ![info exists CANON_HOST] {
    set CANON_HOST [exec $env(QUALNAME)]
    setup_database
    file delete $env(RPC_TEST_SRVTAB)
    exec $env(MAKE_KEYTAB) -princ "server/$CANON_HOST" $env(RPC_TEST_SRVTAB)
}


proc kinit {princ pass lifetime} {
	global kinit
	global wait_error_index wait_errno_index wait_status_index

	spawn -noecho $kinit -5 -l $lifetime $princ
	expect {
		-re "Password for $princ.*: " { send "$pass\n"; expect eof }
		timeout { perror "Timeout waiting for kinit"; close }
		eof
	}

	set ret [wait]
	if {[lindex $ret $wait_error_index] == -1} {
	 	perror \
	    "wait(kinit $princ) returned error [lindex $ret $wait_errno_index]"
	} else {
		if {[lindex $ret $wait_status_index] != 0} {
			perror \
		    "kinit $princ failed with [lindex $ret $wait_status_index]"
		}
	}
}

proc flush_server {} {
	global server_id
	global expect_out

	verbose "flushing server output" 1

	while {1} {
		set timeout 5

		expect {
			-i $server_id
			-re "^.+$" {
			    verbose "server output: $expect_out(buffer)"
			}
			timeout { break }
		}
	}
}

proc start_client {testname ccname user password lifetime count
		  {target ""}} {
	global env CLIENT PROT hostname spawn_id verbose

	if {$target == ""} {
		set target "server@$hostname"
	}

	set env(KRB5CCNAME) FILE:[pwd]/krb5cc_rpc_test_$ccname
	kinit $user $password $lifetime

	if {$verbose > 0} {
		spawn $CLIENT -a 1 -s 1 -m 1 $PROT $hostname $target $count
	} else {
		spawn $CLIENT $PROT $hostname $target $count
	}

	verbose "$testname: client $ccname started"

	unset env(KRB5CCNAME)
}

proc eof_client {testname ccname id status} {
	verbose "$testname: eof'ing for client $ccname" 1

	expect {
		-i $id
		-re "^marshall_new_creds\[^\n\]*\n" { exp_continue }
		-re "^gssapi_\[^\n\]*\n" { exp_continue }
		-re "^\r?\n" { exp_continue }
		eof { verbose $expect_out(buffer) 1 }
		timeout { 
			fail "$testname: timeout waiting for client $ccname to exit"
		}
	}
	wait_client $testname $ccname $id $status
}


proc wait_client {testname ccname id status} {
	global env
	global kill
	global kdestroy
	global wait_error_index wait_errno_index wait_status_index

	verbose "$testname: waiting for client $ccname" 1

	set ret [wait -i $id]
	if {[lindex $ret $wait_error_index] == -1} {
		fail \
       "$testname: wait $ccname returned error [lindex $ret $wait_errno_index]"
	} else {
		if {[lindex $ret $wait_status_index] == $status} {
			pass "$testname: client $ccname"
		} else {
			fail "$testname: client $ccname: unexpected return status [lindex $ret $wait_status_index], should be $status."
		}
	}

	set env(KRB5CCNAME) FILE:[pwd]/krb5cc_rpc_test_$ccname
 	if {[catch "exec $kdestroy -5"] != 0} {
 		perror "$testname: cannot destroy client $ccname ccache"
 	}

	unset env(KRB5CCNAME)
}