Skip to content

gh-160171: Fix ssl get_unverified_chain() on resumed server sessions - #160172

Open
gpshead wants to merge 2 commits into
python:mainfrom
gpshead:ssl-unverified-chain-resumption
Open

gpshead wants to merge 2 commits into
python:mainfrom
gpshead:ssl-unverified-chain-resumption

Conversation

@gpshead

@gpshead gpshead commented Oct 22, 2026 •

Copy link
Copy Markdown
Member

On the server side, decide whether there is a client certificate from SSL_get_peer_certificate() rather than from the chain, and treat a NULL chain as empty, so a ticket-resumed session reports the client's certificate and a client without one gives [] instead of [None]. A session ticket only stores the peer certificate, so intermediates are still missing after resumption and get_verified_chain() is empty on any resumed connection; the docs now say so. The test echo server now calls the public methods and replies with the exception instead of dying, so a regression fails instead of hanging.

Fixes #160171

ANT-2026-2RMA0IPV

…sions

Include the client's certificate when the session was resumed from a
ticket, and return [] instead of raising AttributeError when the client
sent no certificate.
@read-the-docs-community

read-the-docs-community Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

@gpshead
gpshead marked this pull request as ready for review October 22, 2026 05:30
@gpshead
gpshead requested a review from picnixz as a code owner October 22, 2026 05:30
Comment thread Doc/library/ssl.rst
Comment on lines +1299 to +1300
The verified chain is not stored with a session, so the list is empty
when the session was resumed (see :attr:`~SSLSocket.session_reused`).

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.

Suggested change
The verified chain is not stored with a session, so the list is empty
when the session was resumed (see :attr:`~SSLSocket.session_reused`).
The verified chain is not stored with a session, so the list is empty
when the session is resumed (see :attr:`~SSLSocket.session_reused`).

Comment thread Lib/test/test_ssl.py
Comment on lines +5718 to +5719
# TODO: sessions aren't compatible with TLSv1.3 yet
client_context.maximum_version = ssl.TLSVersion.TLSv1_2

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.

Is it the case? I thought that we had a session resumption for 1.3

Comment thread Lib/test/test_ssl.py
) as s:
s.connect((HOST, server.port))
self.assertTrue(s.session_reused)
s.write(b'UNVERIFIEDCHAIN\n')

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.

Can we have a test with the VERIFIEDCHAIN callback?

Comment thread Modules/_ssl.c Outdated
Comment thread Modules/_ssl.c
X509 *peer = SSL_get_peer_certificate(self->ssl);

if (peer == NULL) {
peerobj = Py_NewRef(Py_None);

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.

So this is changed right? we're never having a list with a single None? I think we should just document that [None] is no longer possible to be returned.

Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SSLSocket.get_unverified_chain() omits the client certificate after ticket resumption

2 participants