Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 106 additions & 0 deletions SPECS/pyOpenSSL/CVE-2026-27448.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
From 78ec927c245a69420bbaa065079bef3058abb770 Mon Sep 17 00:00:00 2001
From: AllSpark <allspark@microsoft.com>
Date: Thu, 26 Mar 2026 08:10:56 +0000
Subject: [PATCH] Handle exceptions in set_tlsext_servername_callback callbacks
(#1478): call sys.excepthook and return fatal alert; add changelog entry and
test

Signed-off-by: Azure Linux Security Servicing Account <azurelinux-security@microsoft.com>
Upstream-reference: AI Backport of https://github.com/pyca/pyopenssl/commit/d41a814759a9fb49584ca8ab3f7295de49a85aa0.patch
---
CHANGELOG.rst | 2 ++
src/OpenSSL/SSL.py | 7 ++++++-
tests/test_ssl.py | 40 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 48 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index a7b9e58..923378f 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -31,6 +31,8 @@ Changes:
- Added ``Context.set_tlsext_use_srtp`` to enable negotiation of SRTP keying material.
`#734 <https://github.com/pyca/pyopenssl/pull/734>`_

+- ``Context.set_tlsext_servername_callback`` now handles exceptions raised in the callback by calling ``sys.excepthook`` and returning a fatal TLS alert. Previously, exceptions were silently swallowed and the handshake would proceed as if the callback had succeeded.
+

----

diff --git a/src/OpenSSL/SSL.py b/src/OpenSSL/SSL.py
index e3eddae..4894dbf 100644
--- a/src/OpenSSL/SSL.py
+++ b/src/OpenSSL/SSL.py
@@ -1,5 +1,6 @@
import os
import socket
+import sys
from sys import platform
from functools import wraps, partial
from itertools import count, chain
@@ -1363,7 +1364,11 @@ class Context(object):
"""
@wraps(callback)
def wrapper(ssl, alert, arg):
- callback(Connection._reverse_mapping[ssl])
+ try:
+ callback(Connection._reverse_mapping[ssl])
+ except Exception:
+ sys.excepthook(*sys.exc_info())
+ return 2 # SSL_TLSEXT_ERR_ALERT_FATAL
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Patch looks good w.r.t upstream

return 0

self._tlsext_servername_callback = _ffi.callback(
diff --git a/tests/test_ssl.py b/tests/test_ssl.py
index 0831904..0f7e171 100644
--- a/tests/test_ssl.py
+++ b/tests/test_ssl.py
@@ -1725,6 +1725,46 @@ class TestServerNameCallback(object):

assert args == [(server, b"foo1.example.com")]

+ def test_servername_callback_exception(self, monkeypatch):
+ """
+ When the callback passed to `Context.set_tlsext_servername_callback`
+ raises an exception, ``sys.excepthook`` is called with the exception
+ and the handshake fails with an ``Error``.
+ """
+ exc = TypeError("server name callback failed")
+
+ def servername(conn):
+ raise exc
+
+ excepthook_calls = []
+
+ def custom_excepthook(exc_type, exc_value, exc_tb):
+ excepthook_calls.append((exc_type, exc_value, exc_tb))
+
+ context = Context(TLSv1_METHOD)
+ context.set_tlsext_servername_callback(servername)
+
+ # Necessary to actually accept the connection
+ context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
+ context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
+
+ # Do a little connection to trigger the logic
+ server = Connection(context, None)
+ server.set_accept_state()
+
+ client = Connection(Context(TLSv1_METHOD), None)
+ client.set_connect_state()
+ client.set_tlsext_host_name(b"foo1.example.com")
+
+ monkeypatch.setattr(sys, "excepthook", custom_excepthook)
+ with pytest.raises(Error):
+ interact_in_memory(server, client)
+
+ assert len(excepthook_calls) == 1
+ assert excepthook_calls[0][0] is TypeError
+ assert excepthook_calls[0][1] is exc
+ assert excepthook_calls[0][2] is not None
+

class TestNextProtoNegotiation(object):
"""
--
2.45.4

8 changes: 6 additions & 2 deletions SPECS/pyOpenSSL/pyOpenSSL.spec
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
Summary: Python wrapper module around the OpenSSL library
Name: pyOpenSSL
Version: 18.0.0
Release: 8%{?dist}
Release: 9%{?dist}
License: ASL 2.0
Vendor: Microsoft Corporation
Distribution: Mariner
Group: Development/Languages/Python
URL: https://github.com/pyca/pyopenssl
Source0: https://files.pythonhosted.org/packages/source/p/pyOpenSSL/%{name}-%{version}.tar.gz
Patch0: CVE-2026-27448.patch
BuildArch: noarch

%description
Expand Down Expand Up @@ -39,7 +40,7 @@ BuildRequires: python3-six
High-level wrapper around a subset of the OpenSSL library.

%prep
%autosetup
%autosetup -p1

%build
%py3_build
Expand All @@ -59,6 +60,9 @@ LANG=en_US.UTF-8 PYTHONPATH=%{buildroot}%{python3_sitelib} \
%{python3_sitelib}/*

%changelog
* Thu Mar 26 2026 Azure Linux Security Servicing Account <azurelinux-security@microsoft.com> - 18.0.0-9
- Patch for CVE-2026-27448

* Fri Dec 03 2021 Thomas Crain <thcrain@microsoft.com> - 18.0.0-8
- Replace easy_install usage with pip in %%check sections

Expand Down
Loading