Skip to content

Make it possible to notify the TrustManager of resumed sessions#14378

Merged
chrisvest merged 9 commits intonetty:mainfrom
chrisvest:5x-resumable-tm
Oct 23, 2024
Merged

Make it possible to notify the TrustManager of resumed sessions#14378
chrisvest merged 9 commits intonetty:mainfrom
chrisvest:5x-resumable-tm

Conversation

@chrisvest
Copy link
Copy Markdown
Member

@chrisvest chrisvest commented Sep 28, 2024

Motivation:
Some trust manager implementations produce custom user principals and store them in the SSLSession. Resumed TLS sessions, however, don't always recover the stored contents. For instance, with TLSv1.3 stateless session resumption, our TLS implementations only store the peer certificate chain (or even just the leaf cert) in the session ticket. In such a case, the trust manager would like to be notified of the resumption, so that the peer principal can be recreated and stored in the session once again.

Modification:
Add a ResumableX509ExtendedTrustManager interface, with callbacks for resumed client and server sessions. Add infrastructure (the ResumptionController) to detect session resumption in an SSLEngine implementation agnostic way; if a TLS handshake completed without any calls to the TrustManager, then we've made a "stateless resumption" (hand-wave details) and should call the appropriate resume method. The JDK APIs don't provide a method to reliably discern if a session has been resumed, so we instead detect if the trust manager was called during the handshake. We do this by wrapping user-supplied trust managers that implement the ResumableX509ExtendedTrustManager interface. The wrapper will monitor calls to the trust manager and register the relevant SSLEngine in the controller — the engine is the object that the trust manager and the SslHandler both have access to, which reliably identifies the specific TLS session. Before finished the handshake, the SslHandler queries the ResumptionController to see if the trust manager has already been called, or if it needs to be notified of resumption. Since it's possible that the peer certificates have expired since the initial session, the trust manager gets another change to throw CertificateException.

Result:
Handlers that expect to find user principals in the authenticated SSLSessions no longer find empty sessions, provided they use a trust manager that correctly implements ResumableX509ExtendedTrustManager.

This is a forward port of #14358, #14404, and #14411

Not needed anymore
…h session tickets (netty#14404)

Motivation:
If TLS is `OPTIONAL` then there won't always be a verified peer.
This means there will be no calls on the server `TrustManager` to check
if the client is trusted.
That makes it look like a resumed session to the resumption controller.
But there won't be any verified peer on the session, and trying to get
the peer certificates will throw an exception.

It's also a valid configuration to enable session tickets with TLSv1.2,
and doing so makes a meaningful change to the `SSLEngine` behavior that
we need to test for.

Modification:
- Collect the OpenSSL parameterization code for `SSLEngineTest`.
- Add tickets being enabled or not as a parameter.
- Fix a test that did not anticipate the session ticket behavior.
- Make the `ResumptionController` consider if the engine is in client
mode, or if it requires client authentication, and only propagate
`SSLPeerUnverifiedException` if so.
- Make the `ResumptionController` swallow the
`SSLPeerUnverifiedException` when client auth is OPTIONAL or NONE.
- Add a test for this scenario.

Result:
We now have test coverage with TLSv1.2 session tickets.
The `ResumableX509ExtendedTrustManager` interface can now be used
together with `ClientAuth.OPTIONAL`.
…ate tasks (netty#14411)

Motivation:
When doing a TLSv1.3 handshake with delegate task execution, clients may
complete the handshake in a delegate task wrap that does _not_ any data
written during the handshake. A subsequent unwrap of server response
data is then supposed to let the pending user data flow through to
wrapping - the `wrapLater` flag is tracking this - however, this does
not happen because the unwrap notices that the handshake promise has
already been completed by the earlier wrap call. The unwrap then
assumes, incorrectly, that not only has downstream been notified, but
user data has also been wrapped.

Modification:
The unwrap call should always attempt to wrap later, if the handshake is
finished or not handshaking, and we have pending user data to wrap.

Result:
No more data processing stalls on the client-side, after a TLSv1.3
handshake with task delegation. This also fixes the frequent test
timeouts from `SSLEngineTest.mustCallResumeTrustedOnSessionResumption`,
which was running into this exact scenario.
@chrisvest chrisvest merged commit c73ed93 into netty:main Oct 23, 2024
@chrisvest chrisvest deleted the 5x-resumable-tm branch October 23, 2024 17:31
@chrisvest chrisvest added this to the 5.0.0.Alpha6 milestone Dec 27, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant