From 8861502e0746465c4124548681f05969c08f4cae Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Fri, 23 Jan 2015 17:30:26 -0500 Subject: [PATCH] prefer server alpn ordering over the client's --- Doc/library/ssl.rst | 3 ++- Lib/test/test_ssl.py | 4 ++-- Modules/_ssl.c | 33 ++++++++++++++++++++------------- 3 files changed, 24 insertions(+), 16 deletions(-) diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index 11b8aa90850..e7cf4250e2d 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -970,7 +970,8 @@ SSL sockets also have the following additional methods and attributes: 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, or if the handshake has not happened yet, ``None`` is + 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:: 3.5 diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index 30af08d0b0d..879d6fd788d 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -3054,9 +3054,9 @@ else: server_protocols = ['foo', 'bar', 'milkshake'] protocol_tests = [ (['foo', 'bar'], 'foo'), - (['bar', 'foo'], 'bar'), + (['bar', 'foo'], 'foo'), (['milkshake'], 'milkshake'), - (['http/3.0', 'http/4.0'], 'foo') + (['http/3.0', 'http/4.0'], None) ] for client_protocols, expected in protocol_tests: server_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1) diff --git a/Modules/_ssl.c b/Modules/_ssl.c index 2e19439366d..f0f362c1171 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -2276,18 +2276,25 @@ set_ciphers(PySSLContext *self, PyObject *args) } static int -do_protocol_selection(unsigned char **out, unsigned char *outlen, - const unsigned char *remote_protocols, unsigned int remote_protocols_len, - unsigned char *our_protocols, unsigned int our_protocols_len) +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) { - if (our_protocols == NULL) { - our_protocols = (unsigned char*)""; - our_protocols_len = 0; + 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; } - SSL_select_next_proto(out, outlen, - remote_protocols, remote_protocols_len, - our_protocols, our_protocols_len); + 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; } @@ -2319,7 +2326,7 @@ _selectNPN_cb(SSL *s, void *args) { PySSLContext *ctx = (PySSLContext *)args; - return do_protocol_selection(out, outlen, server, server_len, + return do_protocol_selection(0, out, outlen, server, server_len, ctx->npn_protocols, ctx->npn_protocols_len); } #endif @@ -2371,9 +2378,9 @@ _selectALPN_cb(SSL *s, void *args) { PySSLContext *ctx = (PySSLContext *)args; - return do_protocol_selection((unsigned char **)out, outlen, - client_protocols, client_protocols_len, - ctx->alpn_protocols, ctx->alpn_protocols_len); + return do_protocol_selection(1, (unsigned char **)out, outlen, + ctx->alpn_protocols, ctx->alpn_protocols_len, + client_protocols, client_protocols_len); } #endif