v / vlib / net / http / server_tls_test.v
537 lines · 513 sloc · 17.47 KB · 6768fdffe5da44d0356dd1135cda6ec130b1e1c8
Raw
1// vtest build: !sanitize-memory-clang
2// Hermetic TLS-termination test for net.http.Server: spin up a local HTTPS
3// server with an in-memory cert/key, hit it with http.fetch (validate: false),
4// and assert the round-trip.
5
6module main
7
8import net
9import net.http
10import net.mbedtls
11import time
12
13const server_tls_cert = '-----BEGIN CERTIFICATE-----\nMIIEOTCCAyECFG64Q2g46jZb3kRbDOJWX/BwjSp6MA0GCSqGSIb3DQEBCwUAMEUx\nCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRl\ncm5ldCBXaWRnaXRzIFB0eSBMdGQwIBcNMjMwODAyMTcyOTQyWhgPMjA1MDEyMTcx\nNzI5NDJaMGsxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRQwEgYD\nVQQHDAtMb3MgQW5nZWxlczEdMBsGA1UECgwUQ2F0YWx5c3QgRGV2ZWxvcG1lbnQx\nEjAQBgNVBAMMCWxvY2FsaG9zdDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC\nggIBALqAI4fqUi+QBVWcsXglouLdOML5+w0+1hSR1KdO0Q5XPdQAs/yYWJ+KUkDw\nG++rfy9DUPq7FNRBVurXQkcAtn6gXdllGUSjwUiDo/N4mMOyS/2sufBuaeww7jVi\nrppH+zwP1tUnjRd6khl6bi1Ian9VSzr3Iy9CkXIg1GU4CPXkOydLeoQfepXxWoK1\nOUNwT3VKC/stAfY3j/NIIeiJYkyuRGFCkxn/BUjN+AsXiTugRcYKEFHdIPkOuCXp\nYbhf+lLsczpxCs3rdZG9b/N6mEDCzXTmeHkmsjdPTf+1k5DZZvKzVBBrgdxCgBb7\n5RwjF5v9WmnIc33wWgfJC6FaUzj9NYxYUbPHD+jTz0rJB/jj4u/xJlM/e5NRmXdW\n70pOMKXtWjRSolLOFIPKLY1qs3KMTAZxKKWPDDF7WlMJxMRt7nnnks5yw43Nog4C\njDLk1ZgETnPpLgo3jbmJdIv+OHKTJrBlVvDq7VTyixCoS5G8KoOmyQJhaXG6NwE2\niVhH5JIKgzgCfetfDsnjxqJ/qtrFXPa8FF2TsomD0NK/GZmIcs+9OeVB75Jn5uhF\nfLHScpiTbuu5w3P/LI/MqihLRB6RRNnRzPH8fIg5bYC9b770ta/8GcFRuYE8t+UR\nGtqXJoIKixbDlqV54kal8FQzYzhETf9+NM6Kb/lKEfG/pslvAgMBAAEwDQYJKoZI\nhvcNAQELBQADggEBALI3uNiNO0QE1brA3QYFK+d9ZroB72NrJ0UNkzYHDg2Fc6xg\n4aVVfaxY08+TmKc0JlMOW+pUxeCW/+UBSngdQiR9EE9xm0k0XIrAsy9RXxRvEtPu\nM1VI2h7ayp1Y2BrnQinevTSgtqLRyS1VbOFRl1FiyVvinw2I0KsDdAMNevAPXcOa\nQ8pUgUq6f56DkhocQaj+hxD/uV8HryNxuoSXnPhvfTN3z4YRGzsaWevJ9EYJliOM\n+XugcqfFJ+W7/QCEcAHCL+Bw6OydG5NFORr3p57PXjjcL/uKmxPBrWg2Bz6uT4uR\nMhj0zttiFHLAt9jGfyk6W57UNUja1e1ggftJJhs=\n-----END CERTIFICATE-----\n'
14
15const server_tls_key = '-----BEGIN RSA PRIVATE KEY-----\n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\n-----END RSA PRIVATE KEY-----\n'
16
17struct EchoHandler {
18mut:
19 last_path string
20}
21
22fn (mut h EchoHandler) handle(req http.Request) http.Response {
23 h.last_path = req.url
24 return http.Response{
25 status_code: 200
26 body: 'tls hello ${req.url}'
27 }
28}
29
30struct BlockingHandler {
31 started chan bool
32 release chan bool
33}
34
35fn (mut h BlockingHandler) handle(req http.Request) http.Response {
36 h.started <- true
37 _ := <-h.release
38 return http.Response{
39 status_code: 200
40 header: http.new_header(key: .connection, value: 'close')
41 body: 'released'
42 }
43}
44
45fn pick_port() !int {
46 mut l := net.listen_tcp(.ip, '127.0.0.1:0')!
47 port := l.addr()!.port()!
48 l.close()!
49 return port
50}
51
52fn test_server_tls_round_trip() {
53 $if use_openssl ? {
54 // TLS termination for net.http.Server is not yet supported on the
55 // OpenSSL backend; the listener stub reports a clear runtime error and
56 // the test is skipped here so the suite stays green under
57 // `-d use_openssl`.
58 eprintln('skipping: TLS server not implemented for -d use_openssl yet')
59 return
60 }
61 port := pick_port() or {
62 assert false, 'pick_port: ${err}'
63 return
64 }
65 mut srv := &http.Server{
66 addr: '127.0.0.1:${port}'
67 cert: server_tls_cert
68 cert_key: server_tls_key
69 in_memory_verification: true
70 accept_timeout: time.second
71 handler: EchoHandler{}
72 show_startup_message: false
73 }
74 t := spawn srv.listen_and_serve()
75 srv.wait_till_running() or {
76 srv.close()
77 t.wait()
78 assert false, 'server failed to start: ${err}'
79 return
80 }
81 defer {
82 srv.close()
83 t.wait()
84 }
85 // Give the listener a beat to come up.
86 time.sleep(50 * time.millisecond)
87
88 resp := http.fetch(
89 url: 'https://127.0.0.1:${port}/hello'
90 validate: false
91 ) or {
92 assert false, 'fetch failed: ${err}'
93 return
94 }
95 assert resp.status_code == 200
96 assert resp.body == 'tls hello /hello'
97}
98
99fn test_server_tls_stop() {
100 $if use_openssl ? {
101 eprintln('skipping: TLS server not implemented for -d use_openssl yet')
102 return
103 }
104 port := pick_port() or {
105 assert false, 'pick_port: ${err}'
106 return
107 }
108 mut srv := &http.Server{
109 addr: '127.0.0.1:${port}'
110 cert: server_tls_cert
111 cert_key: server_tls_key
112 in_memory_verification: true
113 accept_timeout: 100 * time.millisecond
114 handler: EchoHandler{}
115 show_startup_message: false
116 }
117 t := spawn srv.listen_and_serve()
118 srv.wait_till_running() or {
119 srv.close()
120 t.wait()
121 assert false, 'server failed to start: ${err}'
122 return
123 }
124 srv.stop()
125 assert srv.status() == .stopped
126 t.wait()
127 assert srv.status() == .closed
128}
129
130fn test_server_tls_close_caps_default_accept_poll() {
131 $if use_openssl ? {
132 eprintln('skipping: TLS server not implemented for -d use_openssl yet')
133 return
134 }
135 port := pick_port() or {
136 assert false, 'pick_port: ${err}'
137 return
138 }
139 mut srv := &http.Server{
140 addr: '127.0.0.1:${port}'
141 cert: server_tls_cert
142 cert_key: server_tls_key
143 in_memory_verification: true
144 handler: EchoHandler{}
145 show_startup_message: false
146 }
147 t := spawn srv.listen_and_serve()
148 srv.wait_till_running() or {
149 srv.close()
150 t.wait()
151 assert false, 'server failed to start: ${err}'
152 return
153 }
154 sw := time.new_stopwatch()
155 srv.close()
156 t.wait()
157 assert sw.elapsed() < time.second
158 assert srv.status() == .closed
159}
160
161fn test_server_tls_close_waits_for_active_request() {
162 $if use_openssl ? {
163 eprintln('skipping: TLS server not implemented for -d use_openssl yet')
164 return
165 }
166 port := pick_port() or {
167 assert false, 'pick_port: ${err}'
168 return
169 }
170 started := chan bool{cap: 1}
171 release := chan bool{cap: 1}
172 done := chan string{cap: 1}
173 mut srv := &http.Server{
174 addr: '127.0.0.1:${port}'
175 cert: server_tls_cert
176 cert_key: server_tls_key
177 in_memory_verification: true
178 accept_timeout: time.second
179 handler: BlockingHandler{
180 started: started
181 release: release
182 }
183 show_startup_message: false
184 }
185 t := spawn srv.listen_and_serve()
186 srv.wait_till_running() or {
187 srv.close()
188 t.wait()
189 assert false, 'server failed to start: ${err}'
190 return
191 }
192 spawn fn [done, port] () {
193 resp := http.fetch(
194 url: 'https://127.0.0.1:${port}/blocked'
195 enable_http2: false
196 validate: false
197 ) or {
198 done <- 'error: ${err}'
199 return
200 }
201 done <- resp.body
202 }()
203 select {
204 _ := <-started {}
205 msg := <-done {
206 srv.close()
207 t.wait()
208 assert false, 'client finished before handler started: ${msg}'
209 return
210 }
211 2 * time.second {
212 srv.close()
213 t.wait()
214 assert false, 'timed out waiting for handler to start'
215 return
216 }
217 }
218 srv.close()
219 time.sleep(50 * time.millisecond)
220 release <- true
221 assert (<-done) == 'released'
222 t.wait()
223 assert srv.status() == .closed
224}
225
226fn test_server_tls_close_during_silent_handshake() {
227 $if use_openssl ? {
228 eprintln('skipping: TLS server not implemented for -d use_openssl yet')
229 return
230 }
231 port := pick_port() or {
232 assert false, 'pick_port: ${err}'
233 return
234 }
235 mut srv := &http.Server{
236 addr: '127.0.0.1:${port}'
237 cert: server_tls_cert
238 cert_key: server_tls_key
239 in_memory_verification: true
240 accept_timeout: 100 * time.millisecond
241 handler: EchoHandler{}
242 show_startup_message: false
243 }
244 t := spawn srv.listen_and_serve()
245 srv.wait_till_running() or {
246 srv.close()
247 t.wait()
248 assert false, 'server failed to start: ${err}'
249 return
250 }
251 mut client := net.dial_tcp('127.0.0.1:${port}') or {
252 srv.close()
253 t.wait()
254 assert false, 'tcp dial failed: ${err}'
255 return
256 }
257 defer {
258 client.close() or {}
259 }
260 time.sleep(50 * time.millisecond)
261 sw := time.new_stopwatch()
262 srv.close()
263 t.wait()
264 assert sw.elapsed() < time.second
265 assert srv.status() == .closed
266}
267
268fn test_server_tls_close_interrupts_idle_keep_alive() {
269 $if use_openssl ? {
270 eprintln('skipping: TLS server not implemented for -d use_openssl yet')
271 return
272 }
273 port := pick_port() or {
274 assert false, 'pick_port: ${err}'
275 return
276 }
277 mut srv := &http.Server{
278 addr: '127.0.0.1:${port}'
279 cert: server_tls_cert
280 cert_key: server_tls_key
281 in_memory_verification: true
282 accept_timeout: time.second
283 read_timeout: 5 * time.second
284 handler: EchoHandler{}
285 show_startup_message: false
286 }
287 t := spawn srv.listen_and_serve()
288 srv.wait_till_running() or {
289 srv.close()
290 t.wait()
291 assert false, 'server failed to start: ${err}'
292 return
293 }
294 mut client := mbedtls.new_ssl_conn(mbedtls.SSLConnectConfig{}) or {
295 srv.close()
296 t.wait()
297 assert false, 'ssl client init failed: ${err}'
298 return
299 }
300 defer {
301 client.shutdown() or {}
302 }
303 client.dial('127.0.0.1', port) or {
304 srv.close()
305 t.wait()
306 assert false, 'ssl dial failed: ${err}'
307 return
308 }
309 request := 'GET /idle HTTP/1.1\r\nHost: 127.0.0.1:${port}\r\nConnection: keep-alive\r\n\r\n'
310 client.write_string(request) or {
311 srv.close()
312 t.wait()
313 assert false, 'ssl write failed: ${err}'
314 return
315 }
316 mut buf := []u8{len: 4096}
317 n := client.read(mut buf) or {
318 srv.close()
319 t.wait()
320 assert false, 'ssl read failed: ${err}'
321 return
322 }
323 response := buf[..n].bytestr()
324 assert response.to_lower().contains('connection: keep-alive')
325 assert response.contains('tls hello /idle')
326
327 sw := time.new_stopwatch()
328 srv.close()
329 t.wait()
330 assert sw.elapsed() < 2 * time.second
331 assert srv.status() == .closed
332}
333
334fn test_server_tls_close_interrupts_idle_h2() {
335 $if use_openssl ? {
336 eprintln('skipping: TLS server not implemented for -d use_openssl yet')
337 return
338 }
339 port := pick_port() or {
340 assert false, 'pick_port: ${err}'
341 return
342 }
343 mut srv := &http.Server{
344 addr: '127.0.0.1:${port}'
345 cert: server_tls_cert
346 cert_key: server_tls_key
347 in_memory_verification: true
348 accept_timeout: time.second
349 read_timeout: 5 * time.second
350 enable_http2: true
351 handler: EchoHandler{}
352 show_startup_message: false
353 }
354 t := spawn srv.listen_and_serve()
355 srv.wait_till_running() or {
356 srv.close()
357 t.wait()
358 assert false, 'server failed to start: ${err}'
359 return
360 }
361 mut client := mbedtls.new_ssl_conn(mbedtls.SSLConnectConfig{
362 alpn_protocols: ['h2']
363 }) or {
364 srv.close()
365 t.wait()
366 assert false, 'ssl client init failed: ${err}'
367 return
368 }
369 defer {
370 client.shutdown() or {}
371 }
372 client.dial('127.0.0.1', port) or {
373 srv.close()
374 t.wait()
375 assert false, 'ssl dial failed: ${err}'
376 return
377 }
378 assert client.negotiated_alpn() == 'h2'
379 mut h2 := http.new_h2_conn(client)
380 resp := h2.do(http.H2ClientRequest{
381 method: 'GET'
382 scheme: 'https'
383 authority: '127.0.0.1:${port}'
384 path: '/h2-idle'
385 }) or {
386 srv.close()
387 t.wait()
388 assert false, 'h2 request failed: ${err}'
389 return
390 }
391 assert resp.status == 200
392 assert resp.body.bytestr() == 'tls hello /h2-idle'
393
394 sw := time.new_stopwatch()
395 srv.close()
396 t.wait()
397 assert sw.elapsed() < 2 * time.second
398 assert srv.status() == .closed
399}
400
401fn test_server_tls_close_interrupts_incomplete_h2_request() {
402 $if use_openssl ? {
403 eprintln('skipping: TLS server not implemented for -d use_openssl yet')
404 return
405 }
406 port := pick_port() or {
407 assert false, 'pick_port: ${err}'
408 return
409 }
410 mut srv := &http.Server{
411 addr: '127.0.0.1:${port}'
412 cert: server_tls_cert
413 cert_key: server_tls_key
414 in_memory_verification: true
415 accept_timeout: time.second
416 read_timeout: 2 * time.second
417 enable_http2: true
418 handler: EchoHandler{}
419 show_startup_message: false
420 }
421 t := spawn srv.listen_and_serve()
422 srv.wait_till_running() or {
423 srv.close()
424 t.wait()
425 assert false, 'server failed to start: ${err}'
426 return
427 }
428 mut client := mbedtls.new_ssl_conn(mbedtls.SSLConnectConfig{
429 alpn_protocols: ['h2']
430 }) or {
431 srv.close()
432 t.wait()
433 assert false, 'ssl client init failed: ${err}'
434 return
435 }
436 defer {
437 client.shutdown() or {}
438 }
439 client.dial('127.0.0.1', port) or {
440 srv.close()
441 t.wait()
442 assert false, 'ssl dial failed: ${err}'
443 return
444 }
445 assert client.negotiated_alpn() == 'h2'
446 mut enc := http.H2HpackEncoder{}
447 block := enc.encode([
448 http.H2HeaderField{':method', 'POST'},
449 http.H2HeaderField{':scheme', 'https'},
450 http.H2HeaderField{':authority', '127.0.0.1:${port}'},
451 http.H2HeaderField{':path', '/h2-incomplete'},
452 ])
453 mut out := []u8{}
454 out << http.h2_client_preface.bytes()
455 out << http.H2Frame(http.H2SettingsFrame{}).encode()
456 out << http.H2Frame(http.H2HeadersFrame{
457 stream_id: 1
458 fragment: block
459 end_headers: true
460 end_stream: false
461 }).encode()
462 written := client.write(out) or {
463 srv.close()
464 t.wait()
465 assert false, 'ssl write failed: ${err}'
466 return
467 }
468 assert written == out.len
469 time.sleep(100 * time.millisecond)
470
471 sw := time.new_stopwatch()
472 srv.close()
473 t.wait()
474 assert sw.elapsed() < time.second
475 assert srv.status() == .closed
476}
477
478fn test_server_tls_h2_negotiation() {
479 $if use_openssl ? {
480 eprintln('skipping: TLS server not implemented for -d use_openssl yet')
481 return
482 }
483 port := pick_port() or {
484 assert false, 'pick_port: ${err}'
485 return
486 }
487 mut srv := &http.Server{
488 addr: '127.0.0.1:${port}'
489 cert: server_tls_cert
490 cert_key: server_tls_key
491 in_memory_verification: true
492 accept_timeout: time.second
493 enable_http2: true
494 handler: EchoHandler{}
495 show_startup_message: false
496 }
497 t := spawn srv.listen_and_serve()
498 srv.wait_till_running() or {
499 srv.close()
500 t.wait()
501 assert false, 'server failed to start: ${err}'
502 return
503 }
504 defer {
505 srv.close()
506 t.wait()
507 }
508 time.sleep(50 * time.millisecond)
509
510 // Client opts into HTTP/2; server must select `h2` via ALPN and serve the
511 // request through its HTTP/2 driver.
512 resp := http.fetch(
513 url: 'https://127.0.0.1:${port}/h2'
514 enable_http2: true
515 validate: false
516 ) or {
517 assert false, 'h2 fetch failed: ${err}'
518 return
519 }
520 assert resp.version() == .v2_0
521 assert resp.status_code == 200
522 assert resp.body == 'tls hello /h2'
523
524 // With HTTP/2 disabled on the client, the server must keep speaking
525 // HTTP/1.1 to the same listener. (enable_http2 defaults to true since
526 // vlang/v#27384, so it must be opted out of explicitly here.)
527 resp_h1 := http.fetch(
528 url: 'https://127.0.0.1:${port}/h1'
529 enable_http2: false
530 validate: false
531 ) or {
532 assert false, 'h1 fetch failed: ${err}'
533 return
534 }
535 assert resp_h1.version() == .v1_1
536 assert resp_h1.status_code == 200
537}
538