python-2.7: Add support for TLS SNI (Server Name Indication) extension.
[slapos.git] / component / python-2.7 / tls_sni.patch
1 Description: Support TLS SNI extension in ssl module
2 Author: markk
3 Bug-Python: http://bugs.python.org/issue5639
4
5 --- a/Lib/ssl.py
6 +++ b/Lib/ssl.py
7 @@ -202,6 +202,7 @@
8      def __init__(self, sock, keyfile=None, certfile=None,
9                   server_side=False, cert_reqs=CERT_NONE,
10                   ssl_version=PROTOCOL_SSLv23, ca_certs=None,
11 +                 server_hostname=None,
12                   do_handshake_on_connect=True,
13                   suppress_ragged_eofs=True, ciphers=None):
14          # Can't use sock.type as other flags (such as SOCK_NONBLOCK) get
15 @@ -238,6 +239,7 @@
16              self._sslobj = _ssl.sslwrap(self._sock, server_side,
17                                          keyfile, certfile,
18                                          cert_reqs, ssl_version, ca_certs,
19 +                                        server_hostname,
20                                          ciphers)
21              if do_handshake_on_connect:
22                  self.do_handshake()
23 @@ -246,6 +248,7 @@
24          self.cert_reqs = cert_reqs
25          self.ssl_version = ssl_version
26          self.ca_certs = ca_certs
27 +        self.server_hostname = server_hostname
28          self.ciphers = ciphers
29          self.do_handshake_on_connect = do_handshake_on_connect
30          self.suppress_ragged_eofs = suppress_ragged_eofs
31 @@ -411,7 +414,7 @@
32              raise ValueError("attempt to connect already-connected SSLSocket!")
33          self._sslobj = _ssl.sslwrap(self._sock, False, self.keyfile, self.certfile,
34                                      self.cert_reqs, self.ssl_version,
35 -                                    self.ca_certs, self.ciphers)
36 +                                    self.ca_certs, self.server_hostname, self.ciphers)
37          try:
38              if return_errno:
39                  rc = socket.connect_ex(self, addr)
40 @@ -452,6 +455,7 @@
41                                cert_reqs=self.cert_reqs,
42                                ssl_version=self.ssl_version,
43                                ca_certs=self.ca_certs,
44 +                              server_hostname=None,
45                                ciphers=self.ciphers,
46                                do_handshake_on_connect=self.do_handshake_on_connect,
47                                suppress_ragged_eofs=self.suppress_ragged_eofs),
48 @@ -566,7 +570,7 @@
49          sock = sock._sock
50  
51      ssl_sock = _ssl.sslwrap(sock, 0, keyfile, certfile, CERT_NONE,
52 -                            PROTOCOL_SSLv23, None)
53 +                            PROTOCOL_SSLv23, None, None, None)
54      try:
55          sock.getpeername()
56      except socket_error:
57 --- a/Modules/_ssl.c
58 +++ b/Modules/_ssl.c
59 @@ -267,7 +267,7 @@
60                 enum py_ssl_server_or_client socket_type,
61                 enum py_ssl_cert_requirements certreq,
62                 enum py_ssl_version proto_version,
63 -               char *cacerts_file, char *ciphers)
64 +               char *cacerts_file, char *server_hostname, char *ciphers)
65  {
66      PySSLObject *self;
67      char *errstr = NULL;
68 @@ -389,6 +389,14 @@
69  
70      PySSL_BEGIN_ALLOW_THREADS
71      self->ssl = SSL_new(self->ctx); /* New ssl struct */
72 +#if OPENSSL_VERSION_NUMBER >= 0x0090806fL && !defined(OPENSSL_NO_TLSEXT)
73 +    /* If SNI isn't supported, we just don't call it and fail silently,
74 +     * as there's not much else we can do.
75 +     */
76 +    if ((socket_type == PY_SSL_CLIENT) &&
77 +             (proto_version != PY_SSL_VERSION_SSL2) && server_hostname)
78 +        SSL_set_tlsext_host_name(self->ssl, server_hostname);
79 +#endif
80      PySSL_END_ALLOW_THREADS
81      SSL_set_fd(self->ssl, Sock->sock_fd);       /* Set the socket for SSL */
82  #ifdef SSL_MODE_AUTO_RETRY
83 @@ -431,15 +439,16 @@
84      char *key_file = NULL;
85      char *cert_file = NULL;
86      char *cacerts_file = NULL;
87 +    char *server_hostname = NULL;
88      char *ciphers = NULL;
89  
90 -    if (!PyArg_ParseTuple(args, "O!i|zziizz:sslwrap",
91 +    if (!PyArg_ParseTuple(args, "O!i|zziizzz:sslwrap",
92                            PySocketModule.Sock_Type,
93                            &Sock,
94                            &server_side,
95                            &key_file, &cert_file,
96                            &verification_mode, &protocol,
97 -                          &cacerts_file, &ciphers))
98 +                          &cacerts_file, &server_hostname, &ciphers))
99          return NULL;
100  
101      /*
102 @@ -452,13 +461,13 @@
103  
104      return (PyObject *) newPySSLObject(Sock, key_file, cert_file,
105                                         server_side, verification_mode,
106 -                                       protocol, cacerts_file,
107 +                                       protocol, cacerts_file, server_hostname,
108                                         ciphers);
109  }
110  
111  PyDoc_STRVAR(ssl_doc,
112  "sslwrap(socket, server_side, [keyfile, certfile, certs_mode, protocol,\n"
113 -"                              cacertsfile, ciphers]) -> sslobject");
114 +"                              cacertsfile, ciphers, server_hostname]) -> sslobject");
115  
116  /* SSL object methods */
117