Skip to content

Commit 1ceac41

Browse files
committed
expect tests: tls module
This one requires much more active participation on the host
1 parent 3f45ff4 commit 1ceac41

File tree

1 file changed

+188
-0
lines changed

1 file changed

+188
-0
lines changed

lua_tests/tls-test.expect

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
#!/usr/bin/env expect
2+
3+
# Walk a NodeMCU device through some basic functionality tests.
4+
#
5+
# Requires `socat` and `openssl` on the host side; tested only on Linux.
6+
#
7+
# Tries to guess the host's IP address using `ip route get`, but this can be
8+
# overridden with the -ip command line option.
9+
#
10+
# A typical invocation looks like:
11+
# TCLLIBPATH=./expectnmcu ./tls-test.expect -serial /dev/ttyUSB3 -wifi "$(cat wificmd)"
12+
#
13+
# where the file `wificmd` contains something like
14+
# wifi.setmode(wifi.STATION); wifi.sta.config({...}); wifi.sta.connect()
15+
# where the ... is filled in with the local network's configuration. All on
16+
# one line, tho', so that the script just gets one prompt back.
17+
#
18+
# For debugging the test itself, it may be useful to invoke expect with -d,
19+
# which will give a great deal of diagnostic information about the expect state
20+
# machine's internals:
21+
# TCLLIBPATH=./expectnmcu expect -d ./tls-test.expect ...
22+
23+
24+
package require struct::stack
25+
package require expectnmcu::core
26+
27+
::struct::stack ulogstack
28+
proc pushulog { new } {
29+
ulogstack push [log_user -info]
30+
log_user ${new}
31+
}
32+
proc populog { } { log_user [ulogstack pop] }
33+
34+
proc genectls { curve pfx } {
35+
exec "openssl" "ecparam" "-genkey" "-name" ${curve} "-out" "${pfx}.key"
36+
exec "openssl" "req" "-new" "-sha256" "-subj" "/CN=${curve}" "-key" "${pfx}.key" "-out" "${pfx}.csr"
37+
exec "openssl" "req" "-x509" "-sha256" "-days" "365" "-key" "${pfx}.key" "-in" "${pfx}.csr" "-out" "${pfx}.crt"
38+
}
39+
40+
proc preptls { victim } {
41+
::expectnmcu::core::send_exp_prompt_c ${victim} "function tlsbasic(id,port,host)"
42+
::expectnmcu::core::send_exp_prompt_c ${victim} " local c = tls.createConnection()"
43+
::expectnmcu::core::send_exp_prompt_c ${victim} " c:on(\"receive\", function(sck, d) print(\"RECV\",id,d) end)"
44+
::expectnmcu::core::send_exp_prompt_c ${victim} " c:on(\"connection\", function(sck) print(\"CONN\",id); sck:send(\"GET / HTTP/1.0\\r\\n\\r\\n\") end)"
45+
::expectnmcu::core::send_exp_prompt_c ${victim} " c:on(\"disconnection\", function(sck) print(\"DISC\",id) end)"
46+
::expectnmcu::core::send_exp_prompt_c ${victim} " c:connect(port,host)"
47+
::expectnmcu::core::send_exp_prompt_c ${victim} " return c"
48+
::expectnmcu::core::send_exp_prompt ${victim} "end"
49+
}
50+
51+
# Basic connectivity test, including disconnection of localsid.
52+
proc basicconntest { id localsid victimsid victimconn } {
53+
set timeout 15
54+
expect {
55+
-i ${localsid} -re ".+" {
56+
# If socat says anything, it's almost surely an error
57+
exit 1
58+
}
59+
-i ${victimsid} "CONN\t${id}" { }
60+
}
61+
set timeout 2
62+
pushulog 0
63+
expect {
64+
-i ${localsid} "GET / HTTP/1.0\r\n\r\n" {
65+
send -i ${localsid} "abracadabra"
66+
}
67+
}
68+
populog
69+
expect {
70+
-i ${victimsid} "RECV\t${id}\tabracadabra" {
71+
::expectnmcu::core::send_exp_prompt ${victimsid} "${victimconn}:send(\"test 1 2 3 4\")"
72+
}
73+
}
74+
pushulog 0
75+
expect {
76+
-i ${localsid} "test 1 2 3 4" {
77+
close -i ${localsid}
78+
}
79+
}
80+
populog
81+
set timeout 15
82+
expect {
83+
-i ${victimsid} "DISC\t${id}" { }
84+
}
85+
}
86+
87+
# Generate some TLS certificates for our use, if they don't exist
88+
set fntls256v1 "test-256v1"
89+
if { ! [file exists "${fntls256v1}.key" ] } { genectls "prime256v1" ${fntls256v1} }
90+
set fntls384r1 "test-384r1"
91+
if { ! [file exists "${fntls384r1}.key" ] } { genectls "secp384r1" ${fntls384r1} }
92+
93+
package require cmdline
94+
set cmd_parameters {
95+
{ serial.arg "/dev/ttyUSB0" "Set the serial interface name" }
96+
{ wifi.arg "" "Command to run to bring up the network" }
97+
{ ip.arg "" "My IP address (will guess if not given)" }
98+
# { debug "Turn on debugging" }
99+
}
100+
set cmd_usage "- A NodeMCU TLS test program"
101+
if {[catch {array set cmdopts [cmdline::getoptions ::argv $cmd_parameters $cmd_usage]}]} {
102+
send_user [cmdline::usage $cmd_parameters $cmd_usage]
103+
exit 0
104+
}
105+
106+
# if { ${cmdopts(debug)} } { exp_internal 1 }
107+
108+
send_user "===> Note: Serial port is ${cmdopts(serial)}; debug is ${cmdopts(debug)} <===\n"
109+
110+
set victim [::expectnmcu::core::connect ${cmdopts(serial)} 115200]
111+
::expectnmcu::core::reboot ${cmdopts(serial)} 115200
112+
113+
# Wait for the system to boot
114+
::expectnmcu::core::waitboot ${victim}
115+
send_user "\n===> Machine has booted <===\n"
116+
117+
# Program a routine for TLS connections
118+
preptls ${victim}
119+
120+
# Connect the board to the network
121+
122+
if {[expr 0 < [string length ${cmdopts(wifi)}]]} {
123+
::expectnmcu::core::send_exp_prompt ${victim} ${cmdopts(wifi)}
124+
}
125+
126+
for {set i 0} {${i} < 10} {incr i} {
127+
send -i ${victim} "=wifi.sta.getip()\n"
128+
expect {
129+
-i ${victim} -re "\n(\[^\n\t]+)\t\[^\t]+\t\[^\t]+\n> " {
130+
set victimip ${expect_out(1,string)}
131+
send_user "\n===> Victim IP address ${victimip} <===\n"
132+
break
133+
}
134+
-i ${victim} -ex "nil\r\n> " {
135+
# must not be connected
136+
sleep 1
137+
}
138+
}
139+
}
140+
if {[expr 10 == $i]} {
141+
send_user "\n===> Unable to connect to network; bailing out! <===\n"
142+
exit 1
143+
}
144+
145+
if {[expr 0 < [string length ${cmdopts(ip)}]]} {
146+
set myip ${cmdopts(ip)}
147+
} else {
148+
# Guess our IP address by using the victim's
149+
spawn "ip" "route" "get" ${victimip}
150+
expect {
151+
-re "src (\[^ ]*) " {
152+
set myip ${expect_out(1,string)}
153+
}
154+
}
155+
close
156+
}
157+
158+
::expectnmcu::core::send_exp_prompt ${victim} "tls.setDebug(2)"
159+
::expectnmcu::core::send_exp_prompt ${victim} "tls.cert.verify(false)"
160+
161+
send_user "\n===> TEST SSL 256v1, no verify <===\n"
162+
163+
spawn -noecho "socat" "STDIO,cfmakeraw" "OPENSSL-LISTEN:12345,verify=0,certificate=${fntls256v1}.crt,key=${fntls256v1}.key,reuseaddr"
164+
::expectnmcu::core::send_exp_prompt ${victim} "c = tlsbasic(0,12345,\"${myip}\")"
165+
basicconntest 0 ${spawn_id} ${victim} "c"
166+
167+
send_user "\n===> TEST SSL 384r1, no verify <===\n"
168+
169+
spawn -noecho "socat" "STDIO,cfmakeraw" "OPENSSL-LISTEN:12345,verify=0,certificate=${fntls384r1}.crt,key=${fntls384r1}.key,reuseaddr"
170+
::expectnmcu::core::send_exp_prompt ${victim} "c = tlsbasic(1,12345,\"${myip}\")"
171+
basicconntest 1 ${spawn_id} ${victim} "c"
172+
173+
send_user "\n===> TEST SSL 384r1, verify <===\n"
174+
175+
set cert [open "${fntls384r1}.crt"]
176+
::expectnmcu::core::send_exp_prompt_c ${victim} "tls.cert.verify(\[\["
177+
while { [gets $cert line] >= 0 } {
178+
::expectnmcu::core::send_exp_prompt_c ${victim} $line
179+
}
180+
::expectnmcu::core::send_exp_prompt ${victim} "]])"
181+
close ${cert}
182+
::expectnmcu::core::send_exp_prompt ${victim} "tls.cert.verify(true)"
183+
184+
spawn -noecho "socat" "STDIO,cfmakeraw" "OPENSSL-LISTEN:12345,verify=0,certificate=${fntls384r1}.crt,key=${fntls384r1}.key,reuseaddr"
185+
::expectnmcu::core::send_exp_prompt ${victim} "c = tlsbasic(2,12345,\"${myip}\")"
186+
basicconntest 2 ${spawn_id} ${victim} "c"
187+
188+
send_user "\n===> TESTS OK <===\n"

0 commit comments

Comments
 (0)