Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 3d87f4c

Browse files
authored
[2.7] bpo-30622: Improve NPN support detection (pythonGH-5859) (python#5863)
The ssl module now detects missing NPN support in LibreSSL. Co-Authored-By: Bernard Spil <[email protected]> Signed-off-by: Christian Heimes <[email protected]>. (cherry picked from commit 6cdb795) Co-authored-by: Christian Heimes <[email protected]>
1 parent a5c9112 commit 3d87f4c

File tree

3 files changed

+38
-7
lines changed

3 files changed

+38
-7
lines changed

Doc/library/ssl.rst

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1808,6 +1808,23 @@ successful call of :func:`~ssl.RAND_add`, :func:`~ssl.RAND_bytes` or
18081808
:func:`~ssl.RAND_pseudo_bytes` is sufficient.
18091809

18101810

1811+
.. ssl-libressl:
1812+
1813+
LibreSSL support
1814+
----------------
1815+
1816+
LibreSSL is a fork of OpenSSL 1.0.1. The ssl module has limited support for
1817+
LibreSSL. Some features are not available when the ssl module is compiled
1818+
with LibreSSL.
1819+
1820+
* LibreSSL >= 2.6.1 no longer supports NPN. The methods
1821+
:meth:`SSLContext.set_npn_protocols` and
1822+
:meth:`SSLSocket.selected_npn_protocol` are not available.
1823+
* :meth:`SSLContext.set_default_verify_paths` ignores the env vars
1824+
:envvar:`SSL_CERT_FILE` and :envvar:`SSL_CERT_PATH` although
1825+
:func:`get_default_verify_paths` still reports them.
1826+
1827+
18111828
.. seealso::
18121829

18131830
Class :class:`socket.socket`
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
The ssl module now detects missing NPN support in LibreSSL.

Modules/_ssl.c

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,19 @@ struct py_ssl_library_code {
127127
# define HAVE_ALPN
128128
#endif
129129

130+
/* We cannot rely on OPENSSL_NO_NEXTPROTONEG because LibreSSL 2.6.1 dropped
131+
* NPN support but did not set OPENSSL_NO_NEXTPROTONEG for compatibility
132+
* reasons. The check for TLSEXT_TYPE_next_proto_neg works with
133+
* OpenSSL 1.0.1+ and LibreSSL.
134+
*/
135+
#ifdef OPENSSL_NO_NEXTPROTONEG
136+
# define HAVE_NPN 0
137+
#elif defined(TLSEXT_TYPE_next_proto_neg)
138+
# define HAVE_NPN 1
139+
#else
140+
# define HAVE_NPN 0
141+
# endif
142+
130143
#ifndef INVALID_SOCKET /* MS defines this */
131144
#define INVALID_SOCKET (-1)
132145
#endif
@@ -285,7 +298,7 @@ static unsigned int _ssl_locks_count = 0;
285298
typedef struct {
286299
PyObject_HEAD
287300
SSL_CTX *ctx;
288-
#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
301+
#ifdef HAVE_NPN
289302
unsigned char *npn_protocols;
290303
int npn_protocols_len;
291304
#endif
@@ -2195,7 +2208,7 @@ context_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
21952208
return NULL;
21962209
}
21972210
self->ctx = ctx;
2198-
#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
2211+
#ifdef HAVE_NPN
21992212
self->npn_protocols = NULL;
22002213
#endif
22012214
#ifdef HAVE_ALPN
@@ -2273,7 +2286,7 @@ context_dealloc(PySSLContext *self)
22732286
PyObject_GC_UnTrack(self);
22742287
context_clear(self);
22752288
SSL_CTX_free(self->ctx);
2276-
#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
2289+
#ifdef HAVE_NPN
22772290
PyMem_FREE(self->npn_protocols);
22782291
#endif
22792292
#ifdef HAVE_ALPN
@@ -2303,7 +2316,7 @@ set_ciphers(PySSLContext *self, PyObject *args)
23032316
Py_RETURN_NONE;
23042317
}
23052318

2306-
#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG) || defined(HAVE_ALPN)
2319+
#if defined(HAVE_NPN) || defined(HAVE_ALPN)
23072320
static int
23082321
do_protocol_selection(int alpn, unsigned char **out, unsigned char *outlen,
23092322
const unsigned char *server_protocols, unsigned int server_protocols_len,
@@ -2329,7 +2342,7 @@ do_protocol_selection(int alpn, unsigned char **out, unsigned char *outlen,
23292342
}
23302343
#endif
23312344

2332-
#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
2345+
#ifdef HAVE_NPN
23332346
/* this callback gets passed to SSL_CTX_set_next_protos_advertise_cb */
23342347
static int
23352348
_advertiseNPN_cb(SSL *s,
@@ -2364,7 +2377,7 @@ _selectNPN_cb(SSL *s,
23642377
static PyObject *
23652378
_set_npn_protocols(PySSLContext *self, PyObject *args)
23662379
{
2367-
#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
2380+
#ifdef HAVE_NPN
23682381
Py_buffer protos;
23692382

23702383
if (!PyArg_ParseTuple(args, "s*:set_npn_protocols", &protos))
@@ -4373,7 +4386,7 @@ init_ssl(void)
43734386
Py_INCREF(r);
43744387
PyModule_AddObject(m, "HAS_ECDH", r);
43754388

4376-
#if defined(OPENSSL_NPN_NEGOTIATED) && !defined(OPENSSL_NO_NEXTPROTONEG)
4389+
#ifdef HAVE_NPN
43774390
r = Py_True;
43784391
#else
43794392
r = Py_False;

0 commit comments

Comments
 (0)