Skip to content

enh(NetSSL_OpenSSL): TLS 1.3 session resumption when session cache is enabled #5414 - #5417

Open
matejk wants to merge 2 commits into
mainfrom
5414-tls13-session-tickets
Open

enh(NetSSL_OpenSSL): TLS 1.3 session resumption when session cache is enabled #5414#5417
matejk wants to merge 2 commits into
mainfrom
5414-tls13-session-tickets

Conversation

@matejk

@matejk matejk commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Fixes #5414.

SecureSocketImpl::acceptSSL() disabled TLS 1.3 session tickets unconditionally,
so a POCO server could not offer TLS 1.3 session resumption at all. That call was
added for #2776: a TLS 1.3 server writes its tickets at handshake completion, and
if the client sends its data and closes without reading, the write fails with
EPIPE and the handshake is reported as failed even though the peer completed it.

Removing the call, as suggested in the issue, would reintroduce #2776 -- current
OpenSSL still sends tickets at handshake completion by default. Instead, tickets
become opt-in through the existing Context::enableSessionCache().

Changes

  • OpenSSL >= 3.0: handshake-time tickets stay suppressed. When the session cache
    is enabled on a server context, one ticket is requested with
    SSL_new_session_ticket() immediately before the first application data write,
    so it goes out with that data and the EPIPE window never opens.
  • OpenSSL 1.1.1, which cannot request a ticket after the handshake: tickets are
    suppressed only when the session cache is disabled.
  • acceptSSL() now reports "Cannot disable session tickets" instead of the
    copy-pasted "Cannot create SSL object", and frees the SSL object on that path,
    consistent with connectSSL().

The ticket is requested before the write rather than at handshake completion
because SSL_new_session_ticket() puts the connection back into the handshake
state until the ticket is written, and SSL_shutdown() fails in that state
("shutdown while in init"). Requesting it before the write that immediately
flushes it keeps that state from outliving a single call, and also means a
repeated completeHandshake() call cannot queue redundant tickets.

Behaviour

Default behaviour is unchanged on all OpenSSL versions: Context::init() sets
SSL_SESS_CACHE_OFF and SSLManager defaults cacheSessions to false, so
tickets stay suppressed unless an application opts in.

Two consequences are documented in Context::enableSessionCache():

  • With OpenSSL >= 3.0 a server that never writes application data issues no
    ticket, so its sessions cannot be resumed.
  • With OpenSSL 1.1.1, enabling the session cache restores handshake-time tickets
    and with them the Shutdown TLS1.3 connection #2776 failure mode.

A ticket can be used for one resumption only, so a client that resumes
repeatedly has to take a new session from each connection instead of reusing the
first one. FTPSClientSession does not do that yet -- it always takes the
session from the control connection -- so forceSessionReuse still fails from
the second data connection on. That is a separate client-side change.

Tests

TCPServerTest gains four cases:

  • testReuseSessionTLS13 -- session cache enabled: the session is resumable and
    is reused on reconnect. Verified to fail without the change.
  • testNoSessionTicketsTLS13 -- session cache disabled: no ticket, no reuse.
  • testClientClosesWithoutReadingTLS13 -- the Shutdown TLS1.3 connection #2776 scenario with the session
    cache enabled: the client sends and closes without reading, the server-side
    handshake still succeeds and the data arrives.
  • testShutdownWithoutDataTLS13 -- the server completes the handshake and shuts
    down without transferring data. Verified to fail if the ticket is requested at
    handshake completion instead of before the write.

Full NetSSL suite passes on macOS and Linux (OpenSSL 3.5.3); the two testProxy
errors are pre-existing and need an external proxy.

matejk added 2 commits July 25, 2026 14:06
…he first write

Requesting it right after the handshake leaves the connection in the
handshake state, which makes a shutdown without any data transfer fail.
@matejk matejk added this to the Release 1.16.0 milestone Jul 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

NetSSL_OpenSSL: TLS 1.3 session resumption not possible because acceptSSL() disables session tickets

1 participant