Skip to content

Commit 9a80576

Browse files
authored
remove npn support entirely. you should be using alpn (#932)
* remove npn support entirely. you should be using alpn * flake8
1 parent 688538c commit 9a80576

File tree

3 files changed

+1
-364
lines changed

3 files changed

+1
-364
lines changed

CHANGELOG.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Backward-incompatible changes:
1212
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1313

1414
- Remove deprecated ``OpenSSL.tsafe`` module.
15+
- Removed deprecated ``OpenSSL.SSL.Context.set_npn_advertise_callback``, ``OpenSSL.SSL.Context.set_npn_select_callback``, and ``OpenSSL.SSL.Connection.get_next_proto_negotiated``.
1516
- Drop support for Python 3.4
1617
- Drop support for OpenSSL 1.0.1
1718

src/OpenSSL/SSL.py

Lines changed: 0 additions & 180 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import os
22
import socket
3-
import warnings
43
from sys import platform
54
from functools import wraps, partial
65
from itertools import count, chain
@@ -342,98 +341,6 @@ def wrapper(ok, store_ctx):
342341
)
343342

344343

345-
class _NpnAdvertiseHelper(_CallbackExceptionHelper):
346-
"""
347-
Wrap a callback such that it can be used as an NPN advertisement callback.
348-
"""
349-
350-
def __init__(self, callback):
351-
_CallbackExceptionHelper.__init__(self)
352-
353-
@wraps(callback)
354-
def wrapper(ssl, out, outlen, arg):
355-
try:
356-
conn = Connection._reverse_mapping[ssl]
357-
protos = callback(conn)
358-
359-
# Join the protocols into a Python bytestring, length-prefixing
360-
# each element.
361-
protostr = b"".join(
362-
chain.from_iterable((int2byte(len(p)), p) for p in protos)
363-
)
364-
365-
# Save our callback arguments on the connection object. This is
366-
# done to make sure that they don't get freed before OpenSSL
367-
# uses them. Then, return them appropriately in the output
368-
# parameters.
369-
conn._npn_advertise_callback_args = [
370-
_ffi.new("unsigned int *", len(protostr)),
371-
_ffi.new("unsigned char[]", protostr),
372-
]
373-
outlen[0] = conn._npn_advertise_callback_args[0][0]
374-
out[0] = conn._npn_advertise_callback_args[1]
375-
return 0
376-
except Exception as e:
377-
self._problems.append(e)
378-
return 2 # SSL_TLSEXT_ERR_ALERT_FATAL
379-
380-
self.callback = _ffi.callback(
381-
"int (*)(SSL *, const unsigned char **, unsigned int *, void *)",
382-
wrapper,
383-
)
384-
385-
386-
class _NpnSelectHelper(_CallbackExceptionHelper):
387-
"""
388-
Wrap a callback such that it can be used as an NPN selection callback.
389-
"""
390-
391-
def __init__(self, callback):
392-
_CallbackExceptionHelper.__init__(self)
393-
394-
@wraps(callback)
395-
def wrapper(ssl, out, outlen, in_, inlen, arg):
396-
try:
397-
conn = Connection._reverse_mapping[ssl]
398-
399-
# The string passed to us is actually made up of multiple
400-
# length-prefixed bytestrings. We need to split that into a
401-
# list.
402-
instr = _ffi.buffer(in_, inlen)[:]
403-
protolist = []
404-
while instr:
405-
length = indexbytes(instr, 0)
406-
proto = instr[1 : length + 1]
407-
protolist.append(proto)
408-
instr = instr[length + 1 :]
409-
410-
# Call the callback
411-
outstr = callback(conn, protolist)
412-
413-
# Save our callback arguments on the connection object. This is
414-
# done to make sure that they don't get freed before OpenSSL
415-
# uses them. Then, return them appropriately in the output
416-
# parameters.
417-
conn._npn_select_callback_args = [
418-
_ffi.new("unsigned char *", len(outstr)),
419-
_ffi.new("unsigned char[]", outstr),
420-
]
421-
outlen[0] = conn._npn_select_callback_args[0][0]
422-
out[0] = conn._npn_select_callback_args[1]
423-
return 0
424-
except Exception as e:
425-
self._problems.append(e)
426-
return 2 # SSL_TLSEXT_ERR_ALERT_FATAL
427-
428-
self.callback = _ffi.callback(
429-
(
430-
"int (*)(SSL *, unsigned char **, unsigned char *, "
431-
"const unsigned char *, unsigned int, void *)"
432-
),
433-
wrapper,
434-
)
435-
436-
437344
NO_OVERLAPPING_PROTOCOLS = object()
438345

439346

@@ -653,14 +560,6 @@ def SSLeay_version(type):
653560
return _ffi.string(_lib.SSLeay_version(type))
654561

655562

656-
def _warn_npn():
657-
warnings.warn(
658-
"NPN is deprecated. Protocols should switch to using ALPN.",
659-
DeprecationWarning,
660-
stacklevel=3,
661-
)
662-
663-
664563
def _make_requires(flag, error):
665564
"""
666565
Builds a decorator that ensures that functions that rely on OpenSSL
@@ -686,11 +585,6 @@ def explode(*args, **kwargs):
686585
return _requires_decorator
687586

688587

689-
_requires_npn = _make_requires(
690-
_lib.Cryptography_HAS_NEXTPROTONEG, "NPN not available"
691-
)
692-
693-
694588
_requires_alpn = _make_requires(
695589
_lib.Cryptography_HAS_ALPN, "ALPN not available"
696590
)
@@ -768,10 +662,6 @@ def __init__(self, method):
768662
self._keylog_callback = None
769663
self._tlsext_servername_callback = None
770664
self._app_data = None
771-
self._npn_advertise_helper = None
772-
self._npn_advertise_callback = None
773-
self._npn_select_helper = None
774-
self._npn_select_callback = None
775665
self._alpn_select_helper = None
776666
self._alpn_select_callback = None
777667
self._ocsp_helper = None
@@ -1467,47 +1357,6 @@ def set_tlsext_use_srtp(self, profiles):
14671357
_lib.SSL_CTX_set_tlsext_use_srtp(self._context, profiles) == 0
14681358
)
14691359

1470-
@_requires_npn
1471-
def set_npn_advertise_callback(self, callback):
1472-
"""
1473-
Specify a callback function that will be called when offering `Next
1474-
Protocol Negotiation
1475-
<https://technotes.googlecode.com/git/nextprotoneg.html>`_ as a server.
1476-
1477-
:param callback: The callback function. It will be invoked with one
1478-
argument, the :class:`Connection` instance. It should return a
1479-
list of bytestrings representing the advertised protocols, like
1480-
``[b'http/1.1', b'spdy/2']``.
1481-
1482-
.. versionadded:: 0.15
1483-
"""
1484-
_warn_npn()
1485-
self._npn_advertise_helper = _NpnAdvertiseHelper(callback)
1486-
self._npn_advertise_callback = self._npn_advertise_helper.callback
1487-
_lib.SSL_CTX_set_next_protos_advertised_cb(
1488-
self._context, self._npn_advertise_callback, _ffi.NULL
1489-
)
1490-
1491-
@_requires_npn
1492-
def set_npn_select_callback(self, callback):
1493-
"""
1494-
Specify a callback function that will be called when a server offers
1495-
Next Protocol Negotiation options.
1496-
1497-
:param callback: The callback function. It will be invoked with two
1498-
arguments: the Connection, and a list of offered protocols as
1499-
bytestrings, e.g. ``[b'http/1.1', b'spdy/2']``. It should return
1500-
one of those bytestrings, the chosen protocol.
1501-
1502-
.. versionadded:: 0.15
1503-
"""
1504-
_warn_npn()
1505-
self._npn_select_helper = _NpnSelectHelper(callback)
1506-
self._npn_select_callback = self._npn_select_helper.callback
1507-
_lib.SSL_CTX_set_next_proto_select_cb(
1508-
self._context, self._npn_select_callback, _ffi.NULL
1509-
)
1510-
15111360
@_requires_alpn
15121361
def set_alpn_protos(self, protos):
15131362
"""
@@ -1637,13 +1486,6 @@ def __init__(self, context, socket=None):
16371486
self._context = context
16381487
self._app_data = None
16391488

1640-
# References to strings used for Next Protocol Negotiation. OpenSSL's
1641-
# header files suggest that these might get copied at some point, but
1642-
# doesn't specify when, so we store them here to make sure they don't
1643-
# get freed before OpenSSL uses them.
1644-
self._npn_advertise_callback_args = None
1645-
self._npn_select_callback_args = None
1646-
16471489
# References to strings used for Application Layer Protocol
16481490
# Negotiation. These strings get copied at some point but it's well
16491491
# after the callback returns, so we have to hang them somewhere to
@@ -1687,10 +1529,6 @@ def __getattr__(self, name):
16871529
def _raise_ssl_error(self, ssl, result):
16881530
if self._context._verify_helper is not None:
16891531
self._context._verify_helper.raise_if_problem()
1690-
if self._context._npn_advertise_helper is not None:
1691-
self._context._npn_advertise_helper.raise_if_problem()
1692-
if self._context._npn_select_helper is not None:
1693-
self._context._npn_select_helper.raise_if_problem()
16941532
if self._context._alpn_select_helper is not None:
16951533
self._context._alpn_select_helper.raise_if_problem()
16961534
if self._context._ocsp_helper is not None:
@@ -2505,24 +2343,6 @@ def get_protocol_version(self):
25052343
version = _lib.SSL_version(self._ssl)
25062344
return version
25072345

2508-
@_requires_npn
2509-
def get_next_proto_negotiated(self):
2510-
"""
2511-
Get the protocol that was negotiated by NPN.
2512-
2513-
:returns: A bytestring of the protocol name. If no protocol has been
2514-
negotiated yet, returns an empty string.
2515-
2516-
.. versionadded:: 0.15
2517-
"""
2518-
_warn_npn()
2519-
data = _ffi.new("unsigned char **")
2520-
data_len = _ffi.new("unsigned int *")
2521-
2522-
_lib.SSL_get0_next_proto_negotiated(self._ssl, data, data_len)
2523-
2524-
return _ffi.buffer(data[0], data_len[0])[:]
2525-
25262346
@_requires_alpn
25272347
def set_alpn_protos(self, protos):
25282348
"""

0 commit comments

Comments
 (0)