blob: 891c6c56158d281e336f73cf92121c892c1e4e63 [file] [log] [blame]
Jean-Paul Calderone7fb6b212011-06-06 08:31:28 -04001# Copyright (C) Jean-Paul Calderone
2# See LICENSE for details.
3
Alex Gaynorca749b52019-02-10 17:23:19 -05004from __future__ import print_function
5
Jean-Paul Calderone7fb6b212011-06-06 08:31:28 -04006from sys import stdout
7from socket import SOL_SOCKET, SO_REUSEADDR, socket
8
9from OpenSSL.crypto import FILETYPE_PEM, load_privatekey, load_certificate
10from OpenSSL.SSL import TLSv1_METHOD, Context, Connection
11
Hynek Schlawack8b7e4552016-03-13 07:51:09 +010012
Jean-Paul Calderone7fb6b212011-06-06 08:31:28 -040013def load(domain):
14 crt = open(domain + ".crt")
15 key = open(domain + ".key")
16 result = (
17 load_privatekey(FILETYPE_PEM, key.read()),
18 load_certificate(FILETYPE_PEM, crt.read()))
19 crt.close()
20 key.close()
21 return result
22
23
24def main():
25 """
26 Run an SNI-enabled server which selects between a few certificates in a
27 C{dict} based on the handshake request it receives from a client.
28 """
29 port = socket()
30 port.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
31 port.bind(('', 8443))
32 port.listen(3)
33
Alex Gaynorca749b52019-02-10 17:23:19 -050034 print('Accepting...', end="")
Jean-Paul Calderone7fb6b212011-06-06 08:31:28 -040035 stdout.flush()
36 server, addr = port.accept()
Alex Gaynorca749b52019-02-10 17:23:19 -050037 print('accepted', addr)
Jean-Paul Calderone7fb6b212011-06-06 08:31:28 -040038
39 server_context = Context(TLSv1_METHOD)
40 server_context.set_tlsext_servername_callback(pick_certificate)
41
42 server_ssl = Connection(server_context, server)
43 server_ssl.set_accept_state()
44 server_ssl.do_handshake()
45 server.close()
46
47
48certificates = {
49 "example.invalid": load("example.invalid"),
50 "another.invalid": load("another.invalid"),
Hynek Schlawack8b7e4552016-03-13 07:51:09 +010051}
Jean-Paul Calderone7fb6b212011-06-06 08:31:28 -040052
53
54def pick_certificate(connection):
55 try:
56 key, cert = certificates[connection.get_servername()]
57 except KeyError:
58 pass
59 else:
60 new_context = Context(TLSv1_METHOD)
61 new_context.use_privatekey(key)
62 new_context.use_certificate(cert)
63 connection.set_context(new_context)
Hynek Schlawack8b7e4552016-03-13 07:51:09 +010064
65
66if __name__ == '__main__':
67 raise SystemExit(main())