[Python-checkins] cpython (merge 2.7 -> 2.7): Merge heads

serhiy.storchaka python-checkins at python.org
Mon Jan 26 09:28:18 CET 2015


https://hg.python.org/cpython/rev/36ca5e765704
changeset:   94295:36ca5e765704
branch:      2.7
parent:      94292:1e12c9e5bc89
parent:      94284:9a4882b12218
user:        Serhiy Storchaka <storchaka at gmail.com>
date:        Mon Jan 26 10:27:31 2015 +0200
summary:
  Merge heads

files:
  Doc/library/argparse.rst         |    9 +-
  Doc/library/logging.handlers.rst |   19 +-
  Doc/library/ssl.rst              |   35 ++-
  Doc/library/time.rst             |   13 +-
  Lib/httplib.py                   |    9 +-
  Lib/rfc822.py                    |    7 +-
  Lib/ssl.py                       |   20 +-
  Lib/test/test_httplib.py         |   39 ++-
  Lib/test/test_rfc822.py          |    6 +
  Lib/test/test_ssl.py             |   64 +++-
  Misc/NEWS                        |    8 +
  Modules/_ssl.c                   |  139 +++++++-
  Modules/_ssl_data.h              |  297 ++++++++++++++++++-
  Tools/ssl/make_ssl_data.py       |   57 ++-
  setup.py                         |    2 +-
  15 files changed, 651 insertions(+), 73 deletions(-)


diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst
--- a/Doc/library/argparse.rst
+++ b/Doc/library/argparse.rst
@@ -1499,12 +1499,15 @@
    * parser_class - class which will be used to create sub-parser instances, by
      default the class of the current parser (e.g. ArgumentParser)
 
-   * dest - name of the attribute under which sub-command name will be
+   * action_ - the basic type of action to be taken when this argument is
+     encountered at the command line
+
+   * dest_ - name of the attribute under which sub-command name will be
      stored; by default None and no value is stored
 
-   * help - help for sub-parser group in help output, by default None
+   * help_ - help for sub-parser group in help output, by default None
 
-   * metavar - string presenting available sub-commands in help; by default it
+   * metavar_ - string presenting available sub-commands in help; by default it
      is None and presents sub-commands in form {cmd1, cmd2, ..}
 
    Some example usage::
diff --git a/Doc/library/logging.handlers.rst b/Doc/library/logging.handlers.rst
--- a/Doc/library/logging.handlers.rst
+++ b/Doc/library/logging.handlers.rst
@@ -185,15 +185,16 @@
    You can use the *maxBytes* and *backupCount* values to allow the file to
    :dfn:`rollover` at a predetermined size. When the size is about to be exceeded,
    the file is closed and a new file is silently opened for output. Rollover occurs
-   whenever the current log file is nearly *maxBytes* in length; if *maxBytes* is
-   zero, rollover never occurs.  If *backupCount* is non-zero, the system will save
-   old log files by appending the extensions '.1', '.2' etc., to the filename. For
-   example, with a *backupCount* of 5 and a base file name of :file:`app.log`, you
-   would get :file:`app.log`, :file:`app.log.1`, :file:`app.log.2`, up to
-   :file:`app.log.5`. The file being written to is always :file:`app.log`.  When
-   this file is filled, it is closed and renamed to :file:`app.log.1`, and if files
-   :file:`app.log.1`, :file:`app.log.2`, etc.  exist, then they are renamed to
-   :file:`app.log.2`, :file:`app.log.3` etc.  respectively.
+   whenever the current log file is nearly *maxBytes* in length; if either of
+   *maxBytes* or *backupCount* is zero, rollover never occurs.  If *backupCount*
+   is non-zero, the system will save old log files by appending the extensions
+   '.1', '.2' etc., to the filename. For example, with a *backupCount* of 5 and
+   a base file name of :file:`app.log`, you would get :file:`app.log`,
+   :file:`app.log.1`, :file:`app.log.2`, up to :file:`app.log.5`. The file being
+   written to is always :file:`app.log`.  When this file is filled, it is closed
+   and renamed to :file:`app.log.1`, and if files :file:`app.log.1`,
+   :file:`app.log.2`, etc.  exist, then they are renamed to :file:`app.log.2`,
+   :file:`app.log.3` etc.  respectively.
 
    .. versionchanged:: 2.6
       *delay* was added.
diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst
--- a/Doc/library/ssl.rst
+++ b/Doc/library/ssl.rst
@@ -638,6 +638,13 @@
 
    .. versionadded:: 2.7.9
 
+.. data:: HAS_ALPN
+
+   Whether the OpenSSL library has built-in support for the *Application-Layer
+   Protocol Negotiation* TLS extension as described in :rfc:`7301`.
+
+   .. versionadded:: 2.7.10
+
 .. data:: HAS_ECDH
 
    Whether the OpenSSL library has built-in support for Elliptic Curve-based
@@ -864,9 +871,19 @@
 
    .. versionadded:: 2.7.9
 
+.. method:: SSLSocket.selected_alpn_protocol()
+
+   Return the protocol that was selected during the TLS handshake.  If
+   :meth:`SSLContext.set_alpn_protocols` was not called, if the other party does
+   not support ALPN, if this socket does not support any of the client's
+   proposed protocols, or if the handshake has not happened yet, ``None`` is
+   returned.
+
+   .. versionadded:: 2.7.10
+
 .. method:: SSLSocket.selected_npn_protocol()
 
-   Returns the higher-level protocol that was selected during the TLS/SSL
+   Return the higher-level protocol that was selected during the TLS/SSL
    handshake. If :meth:`SSLContext.set_npn_protocols` was not called, or
    if the other party does not support NPN, or if the handshake has not yet
    happened, this will return ``None``.
@@ -1034,6 +1051,20 @@
       when connected, the :meth:`SSLSocket.cipher` method of SSL sockets will
       give the currently selected cipher.
 
+.. method:: SSLContext.set_alpn_protocols(protocols)
+
+   Specify which protocols the socket should advertise during the SSL/TLS
+   handshake. It should be a list of ASCII strings, like ``['http/1.1',
+   'spdy/2']``, ordered by preference. The selection of a protocol will happen
+   during the handshake, and will play out according to :rfc:`7301`. After a
+   successful handshake, the :meth:`SSLSocket.selected_alpn_protocol` method will
+   return the agreed-upon protocol.
+
+   This method will raise :exc:`NotImplementedError` if :data:`HAS_ALPN` is
+   False.
+
+   .. versionadded:: 2.7.10
+
 .. method:: SSLContext.set_npn_protocols(protocols)
 
    Specify which protocols the socket should advertise during the SSL/TLS
@@ -1072,7 +1103,7 @@
 
    Due to the early negotiation phase of the TLS connection, only limited
    methods and attributes are usable like
-   :meth:`SSLSocket.selected_npn_protocol` and :attr:`SSLSocket.context`.
+   :meth:`SSLSocket.selected_alpn_protocol` and :attr:`SSLSocket.context`.
    :meth:`SSLSocket.getpeercert`, :meth:`SSLSocket.getpeercert`,
    :meth:`SSLSocket.cipher` and :meth:`SSLSocket.compress` methods require that
    the TLS connection has progressed beyond the TLS Client Hello and therefore
diff --git a/Doc/library/time.rst b/Doc/library/time.rst
--- a/Doc/library/time.rst
+++ b/Doc/library/time.rst
@@ -222,12 +222,13 @@
 
 .. function:: sleep(secs)
 
-   Suspend execution for the given number of seconds.  The argument may be a
-   floating point number to indicate a more precise sleep time. The actual
-   suspension time may be less than that requested because any caught signal will
-   terminate the :func:`sleep` following execution of that signal's catching
-   routine.  Also, the suspension time may be longer than requested by an arbitrary
-   amount because of the scheduling of other activity in the system.
+   Suspend execution of the current thread for the given number of seconds.
+   The argument may be a floating point number to indicate a more precise sleep
+   time. The actual suspension time may be less than that requested because any
+   caught signal will terminate the :func:`sleep` following execution of that
+   signal's catching routine.  Also, the suspension time may be longer than
+   requested by an arbitrary amount because of the scheduling of other activity
+   in the system.
 
 
 .. function:: strftime(format[, t])
diff --git a/Lib/httplib.py b/Lib/httplib.py
--- a/Lib/httplib.py
+++ b/Lib/httplib.py
@@ -313,6 +313,11 @@
                 hlist.append(line)
                 self.addheader(headerseen, line[len(headerseen)+1:].strip())
                 continue
+            elif headerseen is not None:
+                # An empty header name. These aren't allowed in HTTP, but it's
+                # probably a benign mistake. Don't add the header, just keep
+                # going.
+                continue
             else:
                 # It's not a header line; throw it back and stop here.
                 if not self.dict:
@@ -723,7 +728,7 @@
         endpoint passed to set_tunnel. This is done by sending a HTTP CONNECT
         request to the proxy server when the connection is established.
 
-        This method must be called before the HTML connection has been
+        This method must be called before the HTTP connection has been
         established.
 
         The headers argument should be a mapping of extra HTTP headers
@@ -1129,7 +1134,7 @@
         "Accept arguments to set the host/port, since the superclass doesn't."
 
         if host is not None:
-            self._conn._set_hostport(host, port)
+            (self._conn.host, self._conn.port) = self._conn._get_hostport(host, port)
         self._conn.connect()
 
     def getfile(self):
diff --git a/Lib/rfc822.py b/Lib/rfc822.py
--- a/Lib/rfc822.py
+++ b/Lib/rfc822.py
@@ -179,6 +179,11 @@
                 lst.append(line)
                 self.dict[headerseen] = line[len(headerseen)+1:].strip()
                 continue
+            elif headerseen is not None:
+                # An empty header name. These aren't allowed in HTTP, but it's
+                # probably a benign mistake. Don't add the header, just keep
+                # going.
+                continue
             else:
                 # It's not a header line; throw it back and stop here.
                 if not self.dict:
@@ -202,7 +207,7 @@
         data in RFC 2822-like formats with special header formats.
         """
         i = line.find(':')
-        if i > 0:
+        if i > -1:
             return line[:i].lower()
         return None
 
diff --git a/Lib/ssl.py b/Lib/ssl.py
--- a/Lib/ssl.py
+++ b/Lib/ssl.py
@@ -123,7 +123,7 @@
 _import_symbols('SSL_ERROR_')
 _import_symbols('PROTOCOL_')
 
-from _ssl import HAS_SNI, HAS_ECDH, HAS_NPN
+from _ssl import HAS_SNI, HAS_ECDH, HAS_NPN, HAS_ALPN
 
 from _ssl import _OPENSSL_API_VERSION
 
@@ -365,6 +365,17 @@
 
         self._set_npn_protocols(protos)
 
+    def set_alpn_protocols(self, alpn_protocols):
+        protos = bytearray()
+        for protocol in alpn_protocols:
+            b = protocol.encode('ascii')
+            if len(b) == 0 or len(b) > 255:
+                raise SSLError('ALPN protocols must be 1 to 255 in length')
+            protos.append(len(b))
+            protos.extend(b)
+
+        self._set_alpn_protocols(protos)
+
     def _load_windows_store_certs(self, storename, purpose):
         certs = bytearray()
         for cert, encoding, trust in enum_certificates(storename):
@@ -647,6 +658,13 @@
         else:
             return self._sslobj.selected_npn_protocol()
 
+    def selected_alpn_protocol(self):
+        self._checkClosed()
+        if not self._sslobj or not _ssl.HAS_ALPN:
+            return None
+        else:
+            return self._sslobj.selected_alpn_protocol()
+
     def cipher(self):
         self._checkClosed()
         if not self._sslobj:
diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py
--- a/Lib/test/test_httplib.py
+++ b/Lib/test/test_httplib.py
@@ -164,6 +164,16 @@
         conn.request('GET', '/foo')
         self.assertTrue(sock.data.startswith(expected))
 
+    def test_malformed_headers_coped_with(self):
+        # Issue 19996
+        body = "HTTP/1.1 200 OK\r\nFirst: val\r\n: nval\r\nSecond: val\r\n\r\n"
+        sock = FakeSocket(body)
+        resp = httplib.HTTPResponse(sock)
+        resp.begin()
+
+        self.assertEqual(resp.getheader('First'), 'val')
+        self.assertEqual(resp.getheader('Second'), 'val')
+
 
 class BasicTest(TestCase):
     def test_status_lines(self):
@@ -461,7 +471,11 @@
         self.assertEqual(httplib.responses[httplib.NOT_FOUND], "Not Found")
 
 
-class SourceAddressTest(TestCase):
+class TestServerMixin:
+    """A limited socket server mixin.
+
+    This is used by test cases for testing http connection end points.
+    """
     def setUp(self):
         self.serv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
         self.port = test_support.bind_port(self.serv)
@@ -476,6 +490,7 @@
         self.serv.close()
         self.serv = None
 
+class SourceAddressTest(TestServerMixin, TestCase):
     def testHTTPConnectionSourceAddress(self):
         self.conn = httplib.HTTPConnection(HOST, self.port,
                 source_address=('', self.source_port))
@@ -492,6 +507,24 @@
         # for an ssl_wrapped connect() to actually return from.
 
 
+class HTTPTest(TestServerMixin, TestCase):
+    def testHTTPConnection(self):
+        self.conn = httplib.HTTP(host=HOST, port=self.port, strict=None)
+        self.conn.connect()
+        self.assertEqual(self.conn._conn.host, HOST)
+        self.assertEqual(self.conn._conn.port, self.port)
+
+    def testHTTPWithConnectHostPort(self):
+        testhost = 'unreachable.test.domain'
+        testport = '80'
+        self.conn = httplib.HTTP(host=testhost, port=testport)
+        self.conn.connect(host=HOST, port=self.port)
+        self.assertNotEqual(self.conn._conn.host, testhost)
+        self.assertNotEqual(self.conn._conn.port, testport)
+        self.assertEqual(self.conn._conn.host, HOST)
+        self.assertEqual(self.conn._conn.port, self.port)
+
+
 class TimeoutTest(TestCase):
     PORT = None
 
@@ -537,6 +570,7 @@
         self.assertEqual(httpConn.sock.gettimeout(), 30)
         httpConn.close()
 
+
 class HTTPSTest(TestCase):
 
     def setUp(self):
@@ -713,7 +747,8 @@
 @test_support.reap_threads
 def test_main(verbose=None):
     test_support.run_unittest(HeaderTests, OfflineTest, BasicTest, TimeoutTest,
-                              HTTPSTest, SourceAddressTest, TunnelTests)
+                              HTTPTest, HTTPSTest, SourceAddressTest,
+                              TunnelTests)
 
 if __name__ == '__main__':
     test_main()
diff --git a/Lib/test/test_rfc822.py b/Lib/test/test_rfc822.py
--- a/Lib/test/test_rfc822.py
+++ b/Lib/test/test_rfc822.py
@@ -248,6 +248,12 @@
         eq(rfc822.quote('foo\\wacky"name'), 'foo\\\\wacky\\"name')
         eq(rfc822.unquote('"foo\\\\wacky\\"name"'), 'foo\\wacky"name')
 
+    def test_invalid_headers(self):
+        eq = self.assertEqual
+        msg = self.create_message("First: val\n: otherval\nSecond: val2\n")
+        eq(msg.getheader('First'), 'val')
+        eq(msg.getheader('Second'), 'val2')
+
 
 def test_main():
     test_support.run_unittest(MessageTestCase)
diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py
--- a/Lib/test/test_ssl.py
+++ b/Lib/test/test_ssl.py
@@ -1569,7 +1569,8 @@
                 try:
                     self.sslconn = self.server.context.wrap_socket(
                         self.sock, server_side=True)
-                    self.server.selected_protocols.append(self.sslconn.selected_npn_protocol())
+                    self.server.selected_npn_protocols.append(self.sslconn.selected_npn_protocol())
+                    self.server.selected_alpn_protocols.append(self.sslconn.selected_alpn_protocol())
                 except socket.error as e:
                     # We treat ConnectionResetError as though it were an
                     # SSLError - OpenSSL on Ubuntu abruptly closes the
@@ -1678,7 +1679,8 @@
         def __init__(self, certificate=None, ssl_version=None,
                      certreqs=None, cacerts=None,
                      chatty=True, connectionchatty=False, starttls_server=False,
-                     npn_protocols=None, ciphers=None, context=None):
+                     npn_protocols=None, alpn_protocols=None,
+                     ciphers=None, context=None):
             if context:
                 self.context = context
             else:
@@ -1693,6 +1695,8 @@
                     self.context.load_cert_chain(certificate)
                 if npn_protocols:
                     self.context.set_npn_protocols(npn_protocols)
+                if alpn_protocols:
+                    self.context.set_alpn_protocols(alpn_protocols)
                 if ciphers:
                     self.context.set_ciphers(ciphers)
             self.chatty = chatty
@@ -1702,7 +1706,8 @@
             self.port = support.bind_port(self.sock)
             self.flag = None
             self.active = False
-            self.selected_protocols = []
+            self.selected_npn_protocols = []
+            self.selected_alpn_protocols = []
             self.conn_errors = []
             threading.Thread.__init__(self)
             self.daemon = True
@@ -1927,11 +1932,13 @@
                     'compression': s.compression(),
                     'cipher': s.cipher(),
                     'peercert': s.getpeercert(),
+                    'client_alpn_protocol': s.selected_alpn_protocol(),
                     'client_npn_protocol': s.selected_npn_protocol(),
                     'version': s.version(),
                 })
                 s.close()
-            stats['server_npn_protocols'] = server.selected_protocols
+            stats['server_alpn_protocols'] = server.selected_alpn_protocols
+            stats['server_npn_protocols'] = server.selected_npn_protocols
         return stats
 
     def try_protocol_combo(server_protocol, client_protocol, expect_success,
@@ -2787,6 +2794,55 @@
             if "ADH" not in parts and "EDH" not in parts and "DHE" not in parts:
                 self.fail("Non-DH cipher: " + cipher[0])
 
+        def test_selected_alpn_protocol(self):
+            # selected_alpn_protocol() is None unless ALPN is used.
+            context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
+            context.load_cert_chain(CERTFILE)
+            stats = server_params_test(context, context,
+                                       chatty=True, connectionchatty=True)
+            self.assertIs(stats['client_alpn_protocol'], None)
+
+        @unittest.skipUnless(ssl.HAS_ALPN, "ALPN support required")
+        def test_selected_alpn_protocol_if_server_uses_alpn(self):
+            # selected_alpn_protocol() is None unless ALPN is used by the client.
+            client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
+            client_context.load_verify_locations(CERTFILE)
+            server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
+            server_context.load_cert_chain(CERTFILE)
+            server_context.set_alpn_protocols(['foo', 'bar'])
+            stats = server_params_test(client_context, server_context,
+                                       chatty=True, connectionchatty=True)
+            self.assertIs(stats['client_alpn_protocol'], None)
+
+        @unittest.skipUnless(ssl.HAS_ALPN, "ALPN support needed for this test")
+        def test_alpn_protocols(self):
+            server_protocols = ['foo', 'bar', 'milkshake']
+            protocol_tests = [
+                (['foo', 'bar'], 'foo'),
+                (['bar', 'foo'], 'foo'),
+                (['milkshake'], 'milkshake'),
+                (['http/3.0', 'http/4.0'], None)
+            ]
+            for client_protocols, expected in protocol_tests:
+                server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
+                server_context.load_cert_chain(CERTFILE)
+                server_context.set_alpn_protocols(server_protocols)
+                client_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
+                client_context.load_cert_chain(CERTFILE)
+                client_context.set_alpn_protocols(client_protocols)
+                stats = server_params_test(client_context, server_context,
+                                           chatty=True, connectionchatty=True)
+
+                msg = "failed trying %s (s) and %s (c).\n" \
+                      "was expecting %s, but got %%s from the %%s" \
+                          % (str(server_protocols), str(client_protocols),
+                             str(expected))
+                client_result = stats['client_alpn_protocol']
+                self.assertEqual(client_result, expected, msg % (client_result, "client"))
+                server_result = stats['server_alpn_protocols'][-1] \
+                    if len(stats['server_alpn_protocols']) else 'nothing'
+                self.assertEqual(server_result, expected, msg % (server_result, "server"))
+
         def test_selected_npn_protocol(self):
             # selected_npn_protocol() is None unless NPN is used
             context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -15,6 +15,14 @@
 Library
 -------
 
+- Issue #19996: Make :mod:`httplib` ignore headers with no name rather than
+  assuming the body has started.
+
+- Issue #20188: Support Application-Layer Protocol Negotiation (ALPN) in the ssl
+  module.
+
+- Issue #23248: Update ssl error codes from latest OpenSSL git master.
+
 - Issue #23098: 64-bit dev_t is now supported in the os module.
 
 - Issue #23063: In the disutils' check command, fix parsing of reST with code or
diff --git a/Modules/_ssl.c b/Modules/_ssl.c
--- a/Modules/_ssl.c
+++ b/Modules/_ssl.c
@@ -105,6 +105,11 @@
 # define HAVE_SNI 0
 #endif
 
+/* ALPN added in OpenSSL 1.0.2 */
+#if OPENSSL_VERSION_NUMBER >= 0x1000200fL && !defined(OPENSSL_NO_TLSEXT)
+# define HAVE_ALPN
+#endif
+
 enum py_ssl_error {
     /* these mirror ssl.h */
     PY_SSL_ERROR_NONE,
@@ -205,9 +210,13 @@
     PyObject_HEAD
     SSL_CTX *ctx;
 #ifdef OPENSSL_NPN_NEGOTIATED
-    char *npn_protocols;
+    unsigned char *npn_protocols;
     int npn_protocols_len;
 #endif
+#ifdef HAVE_ALPN
+    unsigned char *alpn_protocols;
+    int alpn_protocols_len;
+#endif
 #ifndef OPENSSL_NO_TLSEXT
     PyObject *set_hostname;
 #endif
@@ -1408,7 +1417,20 @@
 
     if (out == NULL)
         Py_RETURN_NONE;
-    return PyUnicode_FromStringAndSize((char *) out, outlen);
+    return PyString_FromStringAndSize((char *)out, outlen);
+}
+#endif
+
+#ifdef HAVE_ALPN
+static PyObject *PySSL_selected_alpn_protocol(PySSLSocket *self) {
+    const unsigned char *out;
+    unsigned int outlen;
+
+    SSL_get0_alpn_selected(self->ssl, &out, &outlen);
+
+    if (out == NULL)
+        Py_RETURN_NONE;
+    return PyString_FromStringAndSize((char *)out, outlen);
 }
 #endif
 
@@ -1925,6 +1947,9 @@
 #ifdef OPENSSL_NPN_NEGOTIATED
     {"selected_npn_protocol", (PyCFunction)PySSL_selected_npn_protocol, METH_NOARGS},
 #endif
+#ifdef HAVE_ALPN
+    {"selected_alpn_protocol", (PyCFunction)PySSL_selected_alpn_protocol, METH_NOARGS},
+#endif
     {"compression", (PyCFunction)PySSL_compression, METH_NOARGS},
     {"shutdown", (PyCFunction)PySSL_SSLshutdown, METH_NOARGS,
      PySSL_SSLshutdown_doc},
@@ -2032,6 +2057,9 @@
 #ifdef OPENSSL_NPN_NEGOTIATED
     self->npn_protocols = NULL;
 #endif
+#ifdef HAVE_ALPN
+    self->alpn_protocols = NULL;
+#endif
 #ifndef OPENSSL_NO_TLSEXT
     self->set_hostname = NULL;
 #endif
@@ -2091,7 +2119,10 @@
     context_clear(self);
     SSL_CTX_free(self->ctx);
 #ifdef OPENSSL_NPN_NEGOTIATED
-    PyMem_Free(self->npn_protocols);
+    PyMem_FREE(self->npn_protocols);
+#endif
+#ifdef HAVE_ALPN
+    PyMem_FREE(self->alpn_protocols);
 #endif
     Py_TYPE(self)->tp_free(self);
 }
@@ -2117,6 +2148,30 @@
     Py_RETURN_NONE;
 }
 
+static int
+do_protocol_selection(int alpn, unsigned char **out, unsigned char *outlen,
+                      const unsigned char *server_protocols, unsigned int server_protocols_len,
+                      const unsigned char *client_protocols, unsigned int client_protocols_len)
+{
+    int ret;
+    if (client_protocols == NULL) {
+        client_protocols = (unsigned char *)"";
+        client_protocols_len = 0;
+    }
+    if (server_protocols == NULL) {
+        server_protocols = (unsigned char *)"";
+        server_protocols_len = 0;
+    }
+
+    ret = SSL_select_next_proto(out, outlen,
+                                server_protocols, server_protocols_len,
+                                client_protocols, client_protocols_len);
+    if (alpn && ret != OPENSSL_NPN_NEGOTIATED)
+        return SSL_TLSEXT_ERR_NOACK;
+
+    return SSL_TLSEXT_ERR_OK;
+}
+
 #ifdef OPENSSL_NPN_NEGOTIATED
 /* this callback gets passed to SSL_CTX_set_next_protos_advertise_cb */
 static int
@@ -2127,10 +2182,10 @@
     PySSLContext *ssl_ctx = (PySSLContext *) args;
 
     if (ssl_ctx->npn_protocols == NULL) {
-        *data = (unsigned char *) "";
+        *data = (unsigned char *)"";
         *len = 0;
     } else {
-        *data = (unsigned char *) ssl_ctx->npn_protocols;
+        *data = ssl_ctx->npn_protocols;
         *len = ssl_ctx->npn_protocols_len;
     }
 
@@ -2143,23 +2198,9 @@
               const unsigned char *server, unsigned int server_len,
               void *args)
 {
-    PySSLContext *ssl_ctx = (PySSLContext *) args;
-
-    unsigned char *client = (unsigned char *) ssl_ctx->npn_protocols;
-    int client_len;
-
-    if (client == NULL) {
-        client = (unsigned char *) "";
-        client_len = 0;
-    } else {
-        client_len = ssl_ctx->npn_protocols_len;
-    }
-
-    SSL_select_next_proto(out, outlen,
-                          server, server_len,
-                          client, client_len);
-
-    return SSL_TLSEXT_ERR_OK;
+    PySSLContext *ctx = (PySSLContext *)args;
+    return do_protocol_selection(0, out, outlen, server, server_len,
+                                 ctx->npn_protocols, ctx->npn_protocols_len);
 }
 #endif
 
@@ -2202,6 +2243,50 @@
 #endif
 }
 
+#ifdef HAVE_ALPN
+static int
+_selectALPN_cb(SSL *s,
+              const unsigned char **out, unsigned char *outlen,
+              const unsigned char *client_protocols, unsigned int client_protocols_len,
+              void *args)
+{
+    PySSLContext *ctx = (PySSLContext *)args;
+    return do_protocol_selection(1, (unsigned char **)out, outlen,
+                                 ctx->alpn_protocols, ctx->alpn_protocols_len,
+                                 client_protocols, client_protocols_len);
+}
+#endif
+
+static PyObject *
+_set_alpn_protocols(PySSLContext *self, PyObject *args)
+{
+#ifdef HAVE_ALPN
+    Py_buffer protos;
+
+    if (!PyArg_ParseTuple(args, "s*:set_npn_protocols", &protos))
+        return NULL;
+
+    PyMem_FREE(self->alpn_protocols);
+    self->alpn_protocols = PyMem_Malloc(protos.len);
+    if (!self->alpn_protocols)
+        return PyErr_NoMemory();
+    memcpy(self->alpn_protocols, protos.buf, protos.len);
+    self->alpn_protocols_len = protos.len;
+    PyBuffer_Release(&protos);
+
+    if (SSL_CTX_set_alpn_protos(self->ctx, self->alpn_protocols, self->alpn_protocols_len))
+        return PyErr_NoMemory();
+    SSL_CTX_set_alpn_select_cb(self->ctx, _selectALPN_cb, self);
+
+    PyBuffer_Release(&protos);
+    Py_RETURN_NONE;
+#else
+    PyErr_SetString(PyExc_NotImplementedError,
+                    "The ALPN extension requires OpenSSL 1.0.2 or later.");
+    return NULL;
+#endif
+}
+
 static PyObject *
 get_verify_mode(PySSLContext *self, void *c)
 {
@@ -3188,6 +3273,8 @@
                        METH_VARARGS | METH_KEYWORDS, NULL},
     {"set_ciphers", (PyCFunction) set_ciphers,
                     METH_VARARGS, NULL},
+    {"_set_alpn_protocols", (PyCFunction) _set_alpn_protocols,
+                           METH_VARARGS, NULL},
     {"_set_npn_protocols", (PyCFunction) _set_npn_protocols,
                            METH_VARARGS, NULL},
     {"load_cert_chain", (PyCFunction) load_cert_chain,
@@ -4100,6 +4187,14 @@
     Py_INCREF(r);
     PyModule_AddObject(m, "HAS_NPN", r);
 
+#ifdef HAVE_ALPN
+    r = Py_True;
+#else
+    r = Py_False;
+#endif
+    Py_INCREF(r);
+    PyModule_AddObject(m, "HAS_ALPN", r);
+
     /* Mappings for error codes */
     err_codes_to_names = PyDict_New();
     err_names_to_codes = PyDict_New();
diff --git a/Modules/_ssl_data.h b/Modules/_ssl_data.h
--- a/Modules/_ssl_data.h
+++ b/Modules/_ssl_data.h
@@ -1,5 +1,5 @@
 /* File generated by Tools/ssl/make_ssl_data.py */
-/* Generated on 2012-05-16T23:56:40.981382 */
+/* Generated on 2015-01-17T20:33:43.377453 */
 
 static struct py_ssl_library_code library_codes[] = {
     {"PEM", ERR_LIB_PEM},
@@ -179,6 +179,11 @@
   #else
     {"BAD_CHECKSUM", ERR_LIB_SSL, 104},
   #endif
+  #ifdef SSL_R_BAD_DATA
+    {"BAD_DATA", ERR_LIB_SSL, SSL_R_BAD_DATA},
+  #else
+    {"BAD_DATA", ERR_LIB_SSL, 390},
+  #endif
   #ifdef SSL_R_BAD_DATA_RETURNED_BY_CALLBACK
     {"BAD_DATA_RETURNED_BY_CALLBACK", ERR_LIB_SSL, SSL_R_BAD_DATA_RETURNED_BY_CALLBACK},
   #else
@@ -309,6 +314,46 @@
   #else
     {"BAD_SIGNATURE", ERR_LIB_SSL, 123},
   #endif
+  #ifdef SSL_R_BAD_SRP_A_LENGTH
+    {"BAD_SRP_A_LENGTH", ERR_LIB_SSL, SSL_R_BAD_SRP_A_LENGTH},
+  #else
+    {"BAD_SRP_A_LENGTH", ERR_LIB_SSL, 347},
+  #endif
+  #ifdef SSL_R_BAD_SRP_B_LENGTH
+    {"BAD_SRP_B_LENGTH", ERR_LIB_SSL, SSL_R_BAD_SRP_B_LENGTH},
+  #else
+    {"BAD_SRP_B_LENGTH", ERR_LIB_SSL, 348},
+  #endif
+  #ifdef SSL_R_BAD_SRP_G_LENGTH
+    {"BAD_SRP_G_LENGTH", ERR_LIB_SSL, SSL_R_BAD_SRP_G_LENGTH},
+  #else
+    {"BAD_SRP_G_LENGTH", ERR_LIB_SSL, 349},
+  #endif
+  #ifdef SSL_R_BAD_SRP_N_LENGTH
+    {"BAD_SRP_N_LENGTH", ERR_LIB_SSL, SSL_R_BAD_SRP_N_LENGTH},
+  #else
+    {"BAD_SRP_N_LENGTH", ERR_LIB_SSL, 350},
+  #endif
+  #ifdef SSL_R_BAD_SRP_PARAMETERS
+    {"BAD_SRP_PARAMETERS", ERR_LIB_SSL, SSL_R_BAD_SRP_PARAMETERS},
+  #else
+    {"BAD_SRP_PARAMETERS", ERR_LIB_SSL, 371},
+  #endif
+  #ifdef SSL_R_BAD_SRP_S_LENGTH
+    {"BAD_SRP_S_LENGTH", ERR_LIB_SSL, SSL_R_BAD_SRP_S_LENGTH},
+  #else
+    {"BAD_SRP_S_LENGTH", ERR_LIB_SSL, 351},
+  #endif
+  #ifdef SSL_R_BAD_SRTP_MKI_VALUE
+    {"BAD_SRTP_MKI_VALUE", ERR_LIB_SSL, SSL_R_BAD_SRTP_MKI_VALUE},
+  #else
+    {"BAD_SRTP_MKI_VALUE", ERR_LIB_SSL, 352},
+  #endif
+  #ifdef SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST
+    {"BAD_SRTP_PROTECTION_PROFILE_LIST", ERR_LIB_SSL, SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST},
+  #else
+    {"BAD_SRTP_PROTECTION_PROFILE_LIST", ERR_LIB_SSL, 353},
+  #endif
   #ifdef SSL_R_BAD_SSL_FILETYPE
     {"BAD_SSL_FILETYPE", ERR_LIB_SSL, SSL_R_BAD_SSL_FILETYPE},
   #else
@@ -324,6 +369,11 @@
   #else
     {"BAD_STATE", ERR_LIB_SSL, 126},
   #endif
+  #ifdef SSL_R_BAD_VALUE
+    {"BAD_VALUE", ERR_LIB_SSL, SSL_R_BAD_VALUE},
+  #else
+    {"BAD_VALUE", ERR_LIB_SSL, 384},
+  #endif
   #ifdef SSL_R_BAD_WRITE_RETRY
     {"BAD_WRITE_RETRY", ERR_LIB_SSL, SSL_R_BAD_WRITE_RETRY},
   #else
@@ -354,6 +404,16 @@
   #else
     {"CA_DN_TOO_LONG", ERR_LIB_SSL, 132},
   #endif
+  #ifdef SSL_R_CA_KEY_TOO_SMALL
+    {"CA_KEY_TOO_SMALL", ERR_LIB_SSL, SSL_R_CA_KEY_TOO_SMALL},
+  #else
+    {"CA_KEY_TOO_SMALL", ERR_LIB_SSL, 397},
+  #endif
+  #ifdef SSL_R_CA_MD_TOO_WEAK
+    {"CA_MD_TOO_WEAK", ERR_LIB_SSL, SSL_R_CA_MD_TOO_WEAK},
+  #else
+    {"CA_MD_TOO_WEAK", ERR_LIB_SSL, 398},
+  #endif
   #ifdef SSL_R_CCS_RECEIVED_EARLY
     {"CCS_RECEIVED_EARLY", ERR_LIB_SSL, SSL_R_CCS_RECEIVED_EARLY},
   #else
@@ -364,6 +424,11 @@
   #else
     {"CERTIFICATE_VERIFY_FAILED", ERR_LIB_SSL, 134},
   #endif
+  #ifdef SSL_R_CERT_CB_ERROR
+    {"CERT_CB_ERROR", ERR_LIB_SSL, SSL_R_CERT_CB_ERROR},
+  #else
+    {"CERT_CB_ERROR", ERR_LIB_SSL, 377},
+  #endif
   #ifdef SSL_R_CERT_LENGTH_MISMATCH
     {"CERT_LENGTH_MISMATCH", ERR_LIB_SSL, SSL_R_CERT_LENGTH_MISMATCH},
   #else
@@ -454,6 +519,11 @@
   #else
     {"DECRYPTION_FAILED_OR_BAD_RECORD_MAC", ERR_LIB_SSL, 281},
   #endif
+  #ifdef SSL_R_DH_KEY_TOO_SMALL
+    {"DH_KEY_TOO_SMALL", ERR_LIB_SSL, SSL_R_DH_KEY_TOO_SMALL},
+  #else
+    {"DH_KEY_TOO_SMALL", ERR_LIB_SSL, 394},
+  #endif
   #ifdef SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG
     {"DH_PUBLIC_VALUE_LENGTH_IS_WRONG", ERR_LIB_SSL, SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG},
   #else
@@ -494,11 +564,26 @@
   #else
     {"ECC_CERT_SHOULD_HAVE_SHA1_SIGNATURE", ERR_LIB_SSL, 323},
   #endif
+  #ifdef SSL_R_ECDH_REQUIRED_FOR_SUITEB_MODE
+    {"ECDH_REQUIRED_FOR_SUITEB_MODE", ERR_LIB_SSL, SSL_R_ECDH_REQUIRED_FOR_SUITEB_MODE},
+  #else
+    {"ECDH_REQUIRED_FOR_SUITEB_MODE", ERR_LIB_SSL, 374},
+  #endif
   #ifdef SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER
     {"ECGROUP_TOO_LARGE_FOR_CIPHER", ERR_LIB_SSL, SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER},
   #else
     {"ECGROUP_TOO_LARGE_FOR_CIPHER", ERR_LIB_SSL, 310},
   #endif
+  #ifdef SSL_R_EE_KEY_TOO_SMALL
+    {"EE_KEY_TOO_SMALL", ERR_LIB_SSL, SSL_R_EE_KEY_TOO_SMALL},
+  #else
+    {"EE_KEY_TOO_SMALL", ERR_LIB_SSL, 399},
+  #endif
+  #ifdef SSL_R_EMPTY_SRTP_PROTECTION_PROFILE_LIST
+    {"EMPTY_SRTP_PROTECTION_PROFILE_LIST", ERR_LIB_SSL, SSL_R_EMPTY_SRTP_PROTECTION_PROFILE_LIST},
+  #else
+    {"EMPTY_SRTP_PROTECTION_PROFILE_LIST", ERR_LIB_SSL, 354},
+  #endif
   #ifdef SSL_R_ENCRYPTED_LENGTH_TOO_LONG
     {"ENCRYPTED_LENGTH_TOO_LONG", ERR_LIB_SSL, SSL_R_ENCRYPTED_LENGTH_TOO_LONG},
   #else
@@ -529,6 +614,16 @@
   #else
     {"GOT_A_FIN_BEFORE_A_CCS", ERR_LIB_SSL, 154},
   #endif
+  #ifdef SSL_R_GOT_NEXT_PROTO_BEFORE_A_CCS
+    {"GOT_NEXT_PROTO_BEFORE_A_CCS", ERR_LIB_SSL, SSL_R_GOT_NEXT_PROTO_BEFORE_A_CCS},
+  #else
+    {"GOT_NEXT_PROTO_BEFORE_A_CCS", ERR_LIB_SSL, 355},
+  #endif
+  #ifdef SSL_R_GOT_NEXT_PROTO_WITHOUT_EXTENSION
+    {"GOT_NEXT_PROTO_WITHOUT_EXTENSION", ERR_LIB_SSL, SSL_R_GOT_NEXT_PROTO_WITHOUT_EXTENSION},
+  #else
+    {"GOT_NEXT_PROTO_WITHOUT_EXTENSION", ERR_LIB_SSL, 356},
+  #endif
   #ifdef SSL_R_HTTPS_PROXY_REQUEST
     {"HTTPS_PROXY_REQUEST", ERR_LIB_SSL, SSL_R_HTTPS_PROXY_REQUEST},
   #else
@@ -544,6 +639,16 @@
   #else
     {"ILLEGAL_PADDING", ERR_LIB_SSL, 283},
   #endif
+  #ifdef SSL_R_ILLEGAL_SUITEB_DIGEST
+    {"ILLEGAL_SUITEB_DIGEST", ERR_LIB_SSL, SSL_R_ILLEGAL_SUITEB_DIGEST},
+  #else
+    {"ILLEGAL_SUITEB_DIGEST", ERR_LIB_SSL, 380},
+  #endif
+  #ifdef SSL_R_INAPPROPRIATE_FALLBACK
+    {"INAPPROPRIATE_FALLBACK", ERR_LIB_SSL, SSL_R_INAPPROPRIATE_FALLBACK},
+  #else
+    {"INAPPROPRIATE_FALLBACK", ERR_LIB_SSL, 373},
+  #endif
   #ifdef SSL_R_INCONSISTENT_COMPRESSION
     {"INCONSISTENT_COMPRESSION", ERR_LIB_SSL, SSL_R_INCONSISTENT_COMPRESSION},
   #else
@@ -564,11 +669,26 @@
   #else
     {"INVALID_COMPRESSION_ALGORITHM", ERR_LIB_SSL, 341},
   #endif
+  #ifdef SSL_R_INVALID_NULL_CMD_NAME
+    {"INVALID_NULL_CMD_NAME", ERR_LIB_SSL, SSL_R_INVALID_NULL_CMD_NAME},
+  #else
+    {"INVALID_NULL_CMD_NAME", ERR_LIB_SSL, 385},
+  #endif
   #ifdef SSL_R_INVALID_PURPOSE
     {"INVALID_PURPOSE", ERR_LIB_SSL, SSL_R_INVALID_PURPOSE},
   #else
     {"INVALID_PURPOSE", ERR_LIB_SSL, 278},
   #endif
+  #ifdef SSL_R_INVALID_SERVERINFO_DATA
+    {"INVALID_SERVERINFO_DATA", ERR_LIB_SSL, SSL_R_INVALID_SERVERINFO_DATA},
+  #else
+    {"INVALID_SERVERINFO_DATA", ERR_LIB_SSL, 388},
+  #endif
+  #ifdef SSL_R_INVALID_SRP_USERNAME
+    {"INVALID_SRP_USERNAME", ERR_LIB_SSL, SSL_R_INVALID_SRP_USERNAME},
+  #else
+    {"INVALID_SRP_USERNAME", ERR_LIB_SSL, 357},
+  #endif
   #ifdef SSL_R_INVALID_STATUS_RESPONSE
     {"INVALID_STATUS_RESPONSE", ERR_LIB_SSL, SSL_R_INVALID_STATUS_RESPONSE},
   #else
@@ -689,6 +809,16 @@
   #else
     {"MISSING_DSA_SIGNING_CERT", ERR_LIB_SSL, 165},
   #endif
+  #ifdef SSL_R_MISSING_ECDH_CERT
+    {"MISSING_ECDH_CERT", ERR_LIB_SSL, SSL_R_MISSING_ECDH_CERT},
+  #else
+    {"MISSING_ECDH_CERT", ERR_LIB_SSL, 382},
+  #endif
+  #ifdef SSL_R_MISSING_ECDSA_SIGNING_CERT
+    {"MISSING_ECDSA_SIGNING_CERT", ERR_LIB_SSL, SSL_R_MISSING_ECDSA_SIGNING_CERT},
+  #else
+    {"MISSING_ECDSA_SIGNING_CERT", ERR_LIB_SSL, 381},
+  #endif
   #ifdef SSL_R_MISSING_EXPORT_TMP_DH_KEY
     {"MISSING_EXPORT_TMP_DH_KEY", ERR_LIB_SSL, SSL_R_MISSING_EXPORT_TMP_DH_KEY},
   #else
@@ -714,6 +844,11 @@
   #else
     {"MISSING_RSA_SIGNING_CERT", ERR_LIB_SSL, 170},
   #endif
+  #ifdef SSL_R_MISSING_SRP_PARAM
+    {"MISSING_SRP_PARAM", ERR_LIB_SSL, SSL_R_MISSING_SRP_PARAM},
+  #else
+    {"MISSING_SRP_PARAM", ERR_LIB_SSL, 358},
+  #endif
   #ifdef SSL_R_MISSING_TMP_DH_KEY
     {"MISSING_TMP_DH_KEY", ERR_LIB_SSL, SSL_R_MISSING_TMP_DH_KEY},
   #else
@@ -739,6 +874,11 @@
   #else
     {"MISSING_VERIFY_MESSAGE", ERR_LIB_SSL, 174},
   #endif
+  #ifdef SSL_R_MULTIPLE_SGC_RESTARTS
+    {"MULTIPLE_SGC_RESTARTS", ERR_LIB_SSL, SSL_R_MULTIPLE_SGC_RESTARTS},
+  #else
+    {"MULTIPLE_SGC_RESTARTS", ERR_LIB_SSL, 346},
+  #endif
   #ifdef SSL_R_NON_SSLV2_INITIAL_PACKET
     {"NON_SSLV2_INITIAL_PACKET", ERR_LIB_SSL, SSL_R_NON_SSLV2_INITIAL_PACKET},
   #else
@@ -819,6 +959,11 @@
   #else
     {"NO_METHOD_SPECIFIED", ERR_LIB_SSL, 188},
   #endif
+  #ifdef SSL_R_NO_PEM_EXTENSIONS
+    {"NO_PEM_EXTENSIONS", ERR_LIB_SSL, SSL_R_NO_PEM_EXTENSIONS},
+  #else
+    {"NO_PEM_EXTENSIONS", ERR_LIB_SSL, 389},
+  #endif
   #ifdef SSL_R_NO_PRIVATEKEY
     {"NO_PRIVATEKEY", ERR_LIB_SSL, SSL_R_NO_PRIVATEKEY},
   #else
@@ -854,6 +999,16 @@
   #else
     {"NO_SHARED_CIPHER", ERR_LIB_SSL, 193},
   #endif
+  #ifdef SSL_R_NO_SHARED_SIGATURE_ALGORITHMS
+    {"NO_SHARED_SIGATURE_ALGORITHMS", ERR_LIB_SSL, SSL_R_NO_SHARED_SIGATURE_ALGORITHMS},
+  #else
+    {"NO_SHARED_SIGATURE_ALGORITHMS", ERR_LIB_SSL, 376},
+  #endif
+  #ifdef SSL_R_NO_SRTP_PROFILES
+    {"NO_SRTP_PROFILES", ERR_LIB_SSL, SSL_R_NO_SRTP_PROFILES},
+  #else
+    {"NO_SRTP_PROFILES", ERR_LIB_SSL, 359},
+  #endif
   #ifdef SSL_R_NO_VERIFY_CALLBACK
     {"NO_VERIFY_CALLBACK", ERR_LIB_SSL, SSL_R_NO_VERIFY_CALLBACK},
   #else
@@ -879,6 +1034,16 @@
   #else
     {"OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED", ERR_LIB_SSL, 344},
   #endif
+  #ifdef SSL_R_ONLY_DTLS_1_2_ALLOWED_IN_SUITEB_MODE
+    {"ONLY_DTLS_1_2_ALLOWED_IN_SUITEB_MODE", ERR_LIB_SSL, SSL_R_ONLY_DTLS_1_2_ALLOWED_IN_SUITEB_MODE},
+  #else
+    {"ONLY_DTLS_1_2_ALLOWED_IN_SUITEB_MODE", ERR_LIB_SSL, 387},
+  #endif
+  #ifdef SSL_R_ONLY_TLS_1_2_ALLOWED_IN_SUITEB_MODE
+    {"ONLY_TLS_1_2_ALLOWED_IN_SUITEB_MODE", ERR_LIB_SSL, SSL_R_ONLY_TLS_1_2_ALLOWED_IN_SUITEB_MODE},
+  #else
+    {"ONLY_TLS_1_2_ALLOWED_IN_SUITEB_MODE", ERR_LIB_SSL, 379},
+  #endif
   #ifdef SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE
     {"ONLY_TLS_ALLOWED_IN_FIPS_MODE", ERR_LIB_SSL, SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE},
   #else
@@ -934,6 +1099,16 @@
   #else
     {"PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE", ERR_LIB_SSL, 204},
   #endif
+  #ifdef SSL_R_PEM_NAME_BAD_PREFIX
+    {"PEM_NAME_BAD_PREFIX", ERR_LIB_SSL, SSL_R_PEM_NAME_BAD_PREFIX},
+  #else
+    {"PEM_NAME_BAD_PREFIX", ERR_LIB_SSL, 391},
+  #endif
+  #ifdef SSL_R_PEM_NAME_TOO_SHORT
+    {"PEM_NAME_TOO_SHORT", ERR_LIB_SSL, SSL_R_PEM_NAME_TOO_SHORT},
+  #else
+    {"PEM_NAME_TOO_SHORT", ERR_LIB_SSL, 392},
+  #endif
   #ifdef SSL_R_PRE_MAC_LENGTH_TOO_LONG
     {"PRE_MAC_LENGTH_TOO_LONG", ERR_LIB_SSL, SSL_R_PRE_MAC_LENGTH_TOO_LONG},
   #else
@@ -1069,11 +1244,36 @@
   #else
     {"SHORT_READ", ERR_LIB_SSL, 219},
   #endif
+  #ifdef SSL_R_SIGNATURE_ALGORITHMS_ERROR
+    {"SIGNATURE_ALGORITHMS_ERROR", ERR_LIB_SSL, SSL_R_SIGNATURE_ALGORITHMS_ERROR},
+  #else
+    {"SIGNATURE_ALGORITHMS_ERROR", ERR_LIB_SSL, 360},
+  #endif
   #ifdef SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE
     {"SIGNATURE_FOR_NON_SIGNING_CERTIFICATE", ERR_LIB_SSL, SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE},
   #else
     {"SIGNATURE_FOR_NON_SIGNING_CERTIFICATE", ERR_LIB_SSL, 220},
   #endif
+  #ifdef SSL_R_SRP_A_CALC
+    {"SRP_A_CALC", ERR_LIB_SSL, SSL_R_SRP_A_CALC},
+  #else
+    {"SRP_A_CALC", ERR_LIB_SSL, 361},
+  #endif
+  #ifdef SSL_R_SRTP_COULD_NOT_ALLOCATE_PROFILES
+    {"SRTP_COULD_NOT_ALLOCATE_PROFILES", ERR_LIB_SSL, SSL_R_SRTP_COULD_NOT_ALLOCATE_PROFILES},
+  #else
+    {"SRTP_COULD_NOT_ALLOCATE_PROFILES", ERR_LIB_SSL, 362},
+  #endif
+  #ifdef SSL_R_SRTP_PROTECTION_PROFILE_LIST_TOO_LONG
+    {"SRTP_PROTECTION_PROFILE_LIST_TOO_LONG", ERR_LIB_SSL, SSL_R_SRTP_PROTECTION_PROFILE_LIST_TOO_LONG},
+  #else
+    {"SRTP_PROTECTION_PROFILE_LIST_TOO_LONG", ERR_LIB_SSL, 363},
+  #endif
+  #ifdef SSL_R_SRTP_UNKNOWN_PROTECTION_PROFILE
+    {"SRTP_UNKNOWN_PROTECTION_PROFILE", ERR_LIB_SSL, SSL_R_SRTP_UNKNOWN_PROTECTION_PROFILE},
+  #else
+    {"SRTP_UNKNOWN_PROTECTION_PROFILE", ERR_LIB_SSL, 364},
+  #endif
   #ifdef SSL_R_SSL23_DOING_SESSION_ID_REUSE
     {"SSL23_DOING_SESSION_ID_REUSE", ERR_LIB_SSL, SSL_R_SSL23_DOING_SESSION_ID_REUSE},
   #else
@@ -1179,6 +1379,11 @@
   #else
     {"SSL_LIBRARY_HAS_NO_CIPHERS", ERR_LIB_SSL, 230},
   #endif
+  #ifdef SSL_R_SSL_NEGATIVE_LENGTH
+    {"SSL_NEGATIVE_LENGTH", ERR_LIB_SSL, SSL_R_SSL_NEGATIVE_LENGTH},
+  #else
+    {"SSL_NEGATIVE_LENGTH", ERR_LIB_SSL, 372},
+  #endif
   #ifdef SSL_R_SSL_SESSION_ID_CALLBACK_FAILED
     {"SSL_SESSION_ID_CALLBACK_FAILED", ERR_LIB_SSL, SSL_R_SSL_SESSION_ID_CALLBACK_FAILED},
   #else
@@ -1229,6 +1434,11 @@
   #else
     {"TLSV1_ALERT_EXPORT_RESTRICTION", ERR_LIB_SSL, 1060},
   #endif
+  #ifdef SSL_R_TLSV1_ALERT_INAPPROPRIATE_FALLBACK
+    {"TLSV1_ALERT_INAPPROPRIATE_FALLBACK", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_INAPPROPRIATE_FALLBACK},
+  #else
+    {"TLSV1_ALERT_INAPPROPRIATE_FALLBACK", ERR_LIB_SSL, 1086},
+  #endif
   #ifdef SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY
     {"TLSV1_ALERT_INSUFFICIENT_SECURITY", ERR_LIB_SSL, SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY},
   #else
@@ -1294,6 +1504,21 @@
   #else
     {"TLS_CLIENT_CERT_REQ_WITH_ANON_CIPHER", ERR_LIB_SSL, 232},
   #endif
+  #ifdef SSL_R_TLS_HEARTBEAT_PEER_DOESNT_ACCEPT
+    {"TLS_HEARTBEAT_PEER_DOESNT_ACCEPT", ERR_LIB_SSL, SSL_R_TLS_HEARTBEAT_PEER_DOESNT_ACCEPT},
+  #else
+    {"TLS_HEARTBEAT_PEER_DOESNT_ACCEPT", ERR_LIB_SSL, 365},
+  #endif
+  #ifdef SSL_R_TLS_HEARTBEAT_PENDING
+    {"TLS_HEARTBEAT_PENDING", ERR_LIB_SSL, SSL_R_TLS_HEARTBEAT_PENDING},
+  #else
+    {"TLS_HEARTBEAT_PENDING", ERR_LIB_SSL, 366},
+  #endif
+  #ifdef SSL_R_TLS_ILLEGAL_EXPORTER_LABEL
+    {"TLS_ILLEGAL_EXPORTER_LABEL", ERR_LIB_SSL, SSL_R_TLS_ILLEGAL_EXPORTER_LABEL},
+  #else
+    {"TLS_ILLEGAL_EXPORTER_LABEL", ERR_LIB_SSL, 367},
+  #endif
   #ifdef SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST
     {"TLS_INVALID_ECPOINTFORMAT_LIST", ERR_LIB_SSL, SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST},
   #else
@@ -1399,6 +1624,16 @@
   #else
     {"UNKNOWN_CIPHER_TYPE", ERR_LIB_SSL, 249},
   #endif
+  #ifdef SSL_R_UNKNOWN_CMD_NAME
+    {"UNKNOWN_CMD_NAME", ERR_LIB_SSL, SSL_R_UNKNOWN_CMD_NAME},
+  #else
+    {"UNKNOWN_CMD_NAME", ERR_LIB_SSL, 386},
+  #endif
+  #ifdef SSL_R_UNKNOWN_DIGEST
+    {"UNKNOWN_DIGEST", ERR_LIB_SSL, SSL_R_UNKNOWN_DIGEST},
+  #else
+    {"UNKNOWN_DIGEST", ERR_LIB_SSL, 368},
+  #endif
   #ifdef SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE
     {"UNKNOWN_KEY_EXCHANGE_TYPE", ERR_LIB_SSL, SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE},
   #else
@@ -1469,16 +1704,36 @@
   #else
     {"UNSUPPORTED_STATUS_TYPE", ERR_LIB_SSL, 329},
   #endif
+  #ifdef SSL_R_USE_SRTP_NOT_NEGOTIATED
+    {"USE_SRTP_NOT_NEGOTIATED", ERR_LIB_SSL, SSL_R_USE_SRTP_NOT_NEGOTIATED},
+  #else
+    {"USE_SRTP_NOT_NEGOTIATED", ERR_LIB_SSL, 369},
+  #endif
+  #ifdef SSL_R_VERSION_TOO_LOW
+    {"VERSION_TOO_LOW", ERR_LIB_SSL, SSL_R_VERSION_TOO_LOW},
+  #else
+    {"VERSION_TOO_LOW", ERR_LIB_SSL, 396},
+  #endif
   #ifdef SSL_R_WRITE_BIO_NOT_SET
     {"WRITE_BIO_NOT_SET", ERR_LIB_SSL, SSL_R_WRITE_BIO_NOT_SET},
   #else
     {"WRITE_BIO_NOT_SET", ERR_LIB_SSL, 260},
   #endif
+  #ifdef SSL_R_WRONG_CERTIFICATE_TYPE
+    {"WRONG_CERTIFICATE_TYPE", ERR_LIB_SSL, SSL_R_WRONG_CERTIFICATE_TYPE},
+  #else
+    {"WRONG_CERTIFICATE_TYPE", ERR_LIB_SSL, 383},
+  #endif
   #ifdef SSL_R_WRONG_CIPHER_RETURNED
     {"WRONG_CIPHER_RETURNED", ERR_LIB_SSL, SSL_R_WRONG_CIPHER_RETURNED},
   #else
     {"WRONG_CIPHER_RETURNED", ERR_LIB_SSL, 261},
   #endif
+  #ifdef SSL_R_WRONG_CURVE
+    {"WRONG_CURVE", ERR_LIB_SSL, SSL_R_WRONG_CURVE},
+  #else
+    {"WRONG_CURVE", ERR_LIB_SSL, 378},
+  #endif
   #ifdef SSL_R_WRONG_MESSAGE_TYPE
     {"WRONG_MESSAGE_TYPE", ERR_LIB_SSL, SSL_R_WRONG_MESSAGE_TYPE},
   #else
@@ -1499,6 +1754,11 @@
   #else
     {"WRONG_SIGNATURE_SIZE", ERR_LIB_SSL, 265},
   #endif
+  #ifdef SSL_R_WRONG_SIGNATURE_TYPE
+    {"WRONG_SIGNATURE_TYPE", ERR_LIB_SSL, SSL_R_WRONG_SIGNATURE_TYPE},
+  #else
+    {"WRONG_SIGNATURE_TYPE", ERR_LIB_SSL, 370},
+  #endif
   #ifdef SSL_R_WRONG_SSL_VERSION
     {"WRONG_SSL_VERSION", ERR_LIB_SSL, SSL_R_WRONG_SSL_VERSION},
   #else
@@ -1519,6 +1779,11 @@
   #else
     {"X509_VERIFICATION_SETUP_PROBLEMS", ERR_LIB_SSL, 269},
   #endif
+  #ifdef X509_R_AKID_MISMATCH
+    {"AKID_MISMATCH", ERR_LIB_X509, X509_R_AKID_MISMATCH},
+  #else
+    {"AKID_MISMATCH", ERR_LIB_X509, 110},
+  #endif
   #ifdef X509_R_BAD_X509_FILETYPE
     {"BAD_X509_FILETYPE", ERR_LIB_X509, X509_R_BAD_X509_FILETYPE},
   #else
@@ -1539,11 +1804,26 @@
   #else
     {"CERT_ALREADY_IN_HASH_TABLE", ERR_LIB_X509, 101},
   #endif
+  #ifdef X509_R_CRL_ALREADY_DELTA
+    {"CRL_ALREADY_DELTA", ERR_LIB_X509, X509_R_CRL_ALREADY_DELTA},
+  #else
+    {"CRL_ALREADY_DELTA", ERR_LIB_X509, 127},
+  #endif
+  #ifdef X509_R_CRL_VERIFY_FAILURE
+    {"CRL_VERIFY_FAILURE", ERR_LIB_X509, X509_R_CRL_VERIFY_FAILURE},
+  #else
+    {"CRL_VERIFY_FAILURE", ERR_LIB_X509, 131},
+  #endif
   #ifdef X509_R_ERR_ASN1_LIB
     {"ERR_ASN1_LIB", ERR_LIB_X509, X509_R_ERR_ASN1_LIB},
   #else
     {"ERR_ASN1_LIB", ERR_LIB_X509, 102},
   #endif
+  #ifdef X509_R_IDP_MISMATCH
+    {"IDP_MISMATCH", ERR_LIB_X509, X509_R_IDP_MISMATCH},
+  #else
+    {"IDP_MISMATCH", ERR_LIB_X509, 128},
+  #endif
   #ifdef X509_R_INVALID_DIRECTORY
     {"INVALID_DIRECTORY", ERR_LIB_X509, X509_R_INVALID_DIRECTORY},
   #else
@@ -1559,6 +1839,11 @@
   #else
     {"INVALID_TRUST", ERR_LIB_X509, 123},
   #endif
+  #ifdef X509_R_ISSUER_MISMATCH
+    {"ISSUER_MISMATCH", ERR_LIB_X509, X509_R_ISSUER_MISMATCH},
+  #else
+    {"ISSUER_MISMATCH", ERR_LIB_X509, 129},
+  #endif
   #ifdef X509_R_KEY_TYPE_MISMATCH
     {"KEY_TYPE_MISMATCH", ERR_LIB_X509, X509_R_KEY_TYPE_MISMATCH},
   #else
@@ -1584,11 +1869,21 @@
   #else
     {"METHOD_NOT_SUPPORTED", ERR_LIB_X509, 124},
   #endif
+  #ifdef X509_R_NEWER_CRL_NOT_NEWER
+    {"NEWER_CRL_NOT_NEWER", ERR_LIB_X509, X509_R_NEWER_CRL_NOT_NEWER},
+  #else
+    {"NEWER_CRL_NOT_NEWER", ERR_LIB_X509, 132},
+  #endif
   #ifdef X509_R_NO_CERT_SET_FOR_US_TO_VERIFY
     {"NO_CERT_SET_FOR_US_TO_VERIFY", ERR_LIB_X509, X509_R_NO_CERT_SET_FOR_US_TO_VERIFY},
   #else
     {"NO_CERT_SET_FOR_US_TO_VERIFY", ERR_LIB_X509, 105},
   #endif
+  #ifdef X509_R_NO_CRL_NUMBER
+    {"NO_CRL_NUMBER", ERR_LIB_X509, X509_R_NO_CRL_NUMBER},
+  #else
+    {"NO_CRL_NUMBER", ERR_LIB_X509, 130},
+  #endif
   #ifdef X509_R_PUBLIC_KEY_DECODE_ERROR
     {"PUBLIC_KEY_DECODE_ERROR", ERR_LIB_X509, X509_R_PUBLIC_KEY_DECODE_ERROR},
   #else
diff --git a/Tools/ssl/make_ssl_data.py b/Tools/ssl/make_ssl_data.py
--- a/Tools/ssl/make_ssl_data.py
+++ b/Tools/ssl/make_ssl_data.py
@@ -5,8 +5,7 @@
 `library` and `reason` mnemnonics to a more recent OpenSSL version.
 
 It takes two arguments:
-- the path to the OpenSSL include files' directory
-  (e.g. openssl-1.0.1-beta3/include/openssl/)
+- the path to the OpenSSL source tree (e.g. git checkout)
 - the path to the C file to be generated
   (probably Modules/_ssl_data.h)
 """
@@ -15,9 +14,10 @@
 import os
 import re
 import sys
+import _ssl
 
 
-def parse_error_codes(h_file, prefix):
+def parse_error_codes(h_file, prefix, libcode):
     pat = re.compile(r"#define\W+(%s([\w]+))\W+(\d+)\b" % re.escape(prefix))
     codes = []
     with open(h_file, "r", encoding="latin1") as f:
@@ -26,7 +26,8 @@
             if match:
                 code, name, num = match.groups()
                 num = int(num)
-                codes.append((code, name, num))
+                # e.g. ("SSL_R_BAD_DATA", ("ERR_LIB_SSL", "BAD_DATA", 390))
+                codes.append((code, (libcode, name, num)))
     return codes
 
 if __name__ == "__main__":
@@ -34,12 +35,32 @@
     outfile = sys.argv[2]
     use_stdout = outfile == '-'
     f = sys.stdout if use_stdout else open(outfile, "w")
-    error_libraries = (
-        # (library code, mnemonic, error prefix, header file)
-        ('ERR_LIB_PEM', 'PEM', 'PEM_R_', 'pem.h'),
-        ('ERR_LIB_SSL', 'SSL', 'SSL_R_', 'ssl.h'),
-        ('ERR_LIB_X509', 'X509', 'X509_R_', 'x509.h'),
-        )
+    error_libraries = {
+        # mnemonic -> (library code, error prefix, header file)
+        'PEM': ('ERR_LIB_PEM', 'PEM_R_', 'crypto/pem/pem.h'),
+        'SSL': ('ERR_LIB_SSL', 'SSL_R_', 'ssl/ssl.h'),
+        'X509': ('ERR_LIB_X509', 'X509_R_', 'crypto/x509/x509.h'),
+        }
+
+    # Read codes from libraries
+    new_codes = []
+    for libcode, prefix, h_file in sorted(error_libraries.values()):
+        new_codes += parse_error_codes(os.path.join(openssl_inc, h_file),
+                                       prefix, libcode)
+    new_code_nums = set((libcode, num)
+                        for (code, (libcode, name, num)) in new_codes)
+
+    # Merge with existing codes (in case some old codes disappeared).
+    codes = {}
+    for errname, (libnum, errnum) in _ssl.err_names_to_codes.items():
+        lib = error_libraries[_ssl.lib_codes_to_names[libnum]]
+        libcode = lib[0]              # e.g. ERR_LIB_PEM
+        errcode = lib[1] + errname    # e.g. SSL_R_BAD_SSL_SESSION_ID_LENGTH
+        # Only keep it if the numeric codes weren't reused
+        if (libcode, errnum) not in new_code_nums:
+            codes[errcode] = libcode, errname, errnum
+    codes.update(dict(new_codes))
+
     def w(l):
         f.write(l + "\n")
     w("/* File generated by Tools/ssl/make_ssl_data.py */")
@@ -47,21 +68,19 @@
     w("")
 
     w("static struct py_ssl_library_code library_codes[] = {")
-    for libcode, mnemo, _, _ in error_libraries:
+    for mnemo, (libcode, _, _) in sorted(error_libraries.items()):
         w('    {"%s", %s},' % (mnemo, libcode))
     w('    { NULL }')
     w('};')
     w("")
 
     w("static struct py_ssl_error_code error_codes[] = {")
-    for libcode, _, prefix, h_file in error_libraries:
-        codes = parse_error_codes(os.path.join(openssl_inc, h_file), prefix)
-        for code, name, num in sorted(codes):
-            w('  #ifdef %s' % (code))
-            w('    {"%s", %s, %s},' % (name, libcode, code))
-            w('  #else')
-            w('    {"%s", %s, %d},' % (name, libcode, num))
-            w('  #endif')
+    for errcode, (libcode, name, num) in sorted(codes.items()):
+        w('  #ifdef %s' % (errcode))
+        w('    {"%s", %s, %s},' % (name, libcode, errcode))
+        w('  #else')
+        w('    {"%s", %s, %d},' % (name, libcode, num))
+        w('  #endif')
     w('    { NULL }')
     w('};')
     if not use_stdout:
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -696,7 +696,7 @@
         exts.append( Extension('audioop', ['audioop.c']) )
 
         # Disabled on 64-bit platforms
-        if sys.maxint != 9223372036854775807L:
+        if sys.maxsize != 9223372036854775807L:
             # Operations on images
             exts.append( Extension('imageop', ['imageop.c']) )
         else:

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list