v / examples / ssl_server / server_sni_advanced.v
120 lines · 98 sloc · 2.72 KB · efc8f7fb3ef7e90a088db64ad2c68dd0698b90d5
Raw
1import net.mbedtls
2import os
3import io
4import net.http
5
6// first run cert/makecerts.sh to generate the certificates for this server
7
8// start the server with:
9// v run server_sni_advanced.v
10
11// test using curl:
12
13// connection using the 1x.dk certificate
14// curl -vik --resolve 1x.dk:8443:0.0.0.0 https://1x.dk:8443/
15
16// connection using the 2x.dk certificate
17// curl -vik --resolve 2x.dk:8443:0.0.0.0 https://2x.dk:8443/
18
19// default certificate (no sni callback)
20// curl -vik https://0.0.0.0:8443/
21
22@[heap]
23struct CertManager {
24mut:
25 // cache for the certificates
26 certs map[string]&mbedtls.SSLCerts
27}
28
29fn (mut cm CertManager) get_cert(mut _l mbedtls.SSLListener, host string) !&mbedtls.SSLCerts {
30 println('${host}')
31
32 if c := cm.certs[host] {
33 println('read certs for ${host} already ready')
34 return c
35 } else {
36 cert := os.read_file('cert/${host}.crt') or {
37 return error('Failed to read certificate ${host}: ${err}')
38 }
39 key := os.read_file('cert/${host}.key') or {
40 return error('Failed to read key ${host}: ${err}')
41 }
42 println('read certs for ${host}')
43
44 if mut c := mbedtls.new_sslcerts_in_memory('', cert, key) {
45 cm.certs[host] = c
46 return c
47 } else {
48 return error('mbedtls.new_sslcerts_in_memory err: ${err}')
49 }
50 }
51}
52
53fn main() {
54 // Load the default certificates
55 cert := os.read_file('cert/0x.dk.crt') or {
56 eprintln('Failed to read certificate: ${err}')
57 return
58 }
59 key := os.read_file('cert/0x.dk.key') or {
60 eprintln('Failed to read key: ${err}')
61 return
62 }
63
64 cm := CertManager{}
65
66 // Create the SSL configuration
67 mut config := mbedtls.SSLConnectConfig{
68 cert: cert
69 cert_key: key
70 in_memory_verification: true // !importent
71 get_certificate: cm.get_cert
72 }
73
74 mut server := mbedtls.new_ssl_listener('0.0.0.0:8443', config) or {
75 println('new_ssl_listener : ${err.msg()} : ${err.code()}')
76 return
77 }
78 println('Listening on https://0.0.0.0:8443')
79
80 // Accept and handle connections
81 for {
82 mut client := server.accept() or {
83 println('accept : ${err.msg()} : ${err.code()}')
84 continue
85 }
86 go handle_connection(mut client)
87 }
88
89 server.shutdown() or {
90 println('server.shutdown : ${err.msg()} : ${err.code()}')
91 return
92 }
93}
94
95fn handle_connection(mut ssl_conn mbedtls.SSLConn) {
96 mut reader := io.new_buffered_reader(reader: ssl_conn)
97
98 request := http.parse_request(mut reader) or {
99 println('parse_request failed : ${err}')
100 return
101 }
102
103 println('Received request: ${request.url}')
104
105 // Respond to the request
106 body := 'Hello, HTTPS!'
107 res := http.new_response(http.ResponseConfig{
108 body: body
109 })
110
111 ssl_conn.write(res.bytes()) or {
112 eprintln('Failed to write response: ${err}')
113 return
114 }
115
116 ssl_conn.shutdown() or {
117 eprintln('Failed to shutdown connection: ${err}')
118 return
119 }
120}
121