1 """A library for integrating Python's builtin ``ssl`` library with CherryPy.
2
3 The ssl module must be importable for SSL functionality.
4
5 To use this module, set ``CherryPyWSGIServer.ssl_adapter`` to an instance of
6 ``BuiltinSSLAdapter``.
7 """
8
9 try:
10 import ssl
11 except ImportError:
12 ssl = None
13
14 try:
15 from _pyio import DEFAULT_BUFFER_SIZE
16 except ImportError:
17 try:
18 from io import DEFAULT_BUFFER_SIZE
19 except ImportError:
20 DEFAULT_BUFFER_SIZE = -1
21
22 import sys
23
24 from cherrypy import wsgiserver
25
26
28 """A wrapper for integrating Python's builtin ssl module with CherryPy."""
29
30 certificate = None
31 """The filename of the server SSL certificate."""
32
33 private_key = None
34 """The filename of the server's private key file."""
35
36 - def __init__(self, certificate, private_key, certificate_chain=None):
42
43 - def bind(self, sock):
44 """Wrap and return the given socket."""
45 return sock
46
47 - def wrap(self, sock):
48 """Wrap and return the given socket, plus WSGI environ entries."""
49 try:
50 s = ssl.wrap_socket(sock, do_handshake_on_connect=True,
51 server_side=True, certfile=self.certificate,
52 keyfile=self.private_key, ssl_version=ssl.PROTOCOL_SSLv23)
53 except ssl.SSLError:
54 e = sys.exc_info()[1]
55 if e.errno == ssl.SSL_ERROR_EOF:
56
57
58
59 return None, {}
60 elif e.errno == ssl.SSL_ERROR_SSL:
61 if e.args[1].endswith('http request'):
62
63 raise wsgiserver.NoSSLError
64 elif e.args[1].endswith('unknown protocol'):
65
66
67 return None, {}
68 raise
69 return s, self.get_environ(s)
70
71
73 """Create WSGI environ entries to be merged into each request."""
74 cipher = sock.cipher()
75 ssl_environ = {
76 "wsgi.url_scheme": "https",
77 "HTTPS": "on",
78 'SSL_PROTOCOL': cipher[1],
79 'SSL_CIPHER': cipher[0]
80
81
82 }
83 return ssl_environ
84
85 if sys.version_info >= (3, 0):
88 else:
91