Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ensure key / values are shared between resumed sessions #13819

Merged
merged 4 commits into from
Feb 8, 2024
Merged

Conversation

normanmaurer
Copy link
Member

@normanmaurer normanmaurer commented Jan 31, 2024

Motivation:

When a session is resumed we need to also ensure we preserve the values that were put into the internal storage of the session.

Modifications:

Ensure we preserve the values / keys of the internal storage on resumption

Result:

Correctly implement session caching and reuse

@chrisvest
Copy link
Contributor

I don't think this change updates the last accessed time on session reuse. The OpenSslSessionCache updates the last accessed time of the NativeSslSession but this is not carried over to the DefaultSslSession used in ReferenceCountedOpenSslEngine.

The OpenSslEngineTest.assertSessionReusedForEngine() method should include assertions for the last accessed time being more recent than the creation time.

@normanmaurer
Copy link
Member Author

@chrisvest got it... Will do some more changes

@normanmaurer normanmaurer changed the title SSLSession.getLastAccessedTime() and getCreationTime() should be equa… TODO: RENAME SSLSession.getLastAccessedTime() and getCreationTime() should be equa… Feb 6, 2024
@normanmaurer normanmaurer changed the title TODO: RENAME SSLSession.getLastAccessedTime() and getCreationTime() should be equa… Ensure key / values are shared between resumed sessions Feb 7, 2024
Motivation:

When a session is resumed we need to also ensure we preserve the values that were put into the internal storage of the session.

Modifications:

Ensure we preserve the values / keys of the internal storage on resumption

Result:

Correctly implement session caching and reuse

Co-authored-by: Chris Vest <christianvest_hansen@apple.com>
Copy link
Contributor

@chrisvest chrisvest left a comment

Choose a reason for hiding this comment

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

One comment.

@normanmaurer
Copy link
Member Author

This will need to be ported to quic as well

@normanmaurer normanmaurer merged commit f0e9b40 into 4.1 Feb 8, 2024
15 checks passed
@normanmaurer normanmaurer deleted the ssl_session branch February 8, 2024 16:46
normanmaurer added a commit that referenced this pull request Feb 8, 2024
Motivation:

When a session is resumed we need to also ensure we preserve the values
that were put into the internal storage of the session.

Modifications:

Ensure we preserve the values / keys of the internal storage on
resumption

Result:

Correctly implement session caching and reuse

---------

Co-authored-by: Chris Vest <christianvest_hansen@apple.com>
franz1981 pushed a commit to franz1981/netty that referenced this pull request Feb 9, 2024
Motivation:

When a session is resumed we need to also ensure we preserve the values
that were put into the internal storage of the session.

Modifications:

Ensure we preserve the values / keys of the internal storage on
resumption

Result:

Correctly implement session caching and reuse

---------

Co-authored-by: Chris Vest <christianvest_hansen@apple.com>
Comment on lines +3626 to +3649
final String handshakeKey = "handshake";
TrustManagerFactory tmf = new ConstantTrustManagerFactory(new EmptyExtendedX509TrustManager() {
@Override
public void checkClientTrusted(java.security.cert.X509Certificate[] chain,
String authType, SSLEngine engine) {
// This is broken in conscrypt.
// TODO: Open an issue in the conscrypt project.
if (!Conscrypt.isEngineSupported(engine)) {
assertEquals(0, engine.getHandshakeSession().getValueNames().length);
}
engine.getHandshakeSession().putValue(handshakeKey, Boolean.TRUE);
}

@Override
public void checkServerTrusted(java.security.cert.X509Certificate[] chain,
String authType, SSLEngine engine) {
// This is broken in conscrypt.
// TODO: Open an issue in the conscrypt project.
if (!Conscrypt.isEngineSupported(engine)) {
assertEquals(0, engine.getHandshakeSession().getValueNames().length);
}
engine.getHandshakeSession().putValue(handshakeKey, Boolean.TRUE);
}
});
Copy link
Contributor

Choose a reason for hiding this comment

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

@XueleiFan I want to bring your attention to the use case captured here in this test, in the context of https://bugs.openjdk.org/browse/JDK-8245551.

What is being replicated here, is that a TrustManager implementation may - as part of validating the peer certificate - also compute a principal or other authorization data, capturing the identity, privileges and/or capabilities of the peer, and put that in the handshake session. Thus allowing the surrounding framework or application to later extract this data, make authorization decisions based on it.

Using the TrustManager in this way has two main advantages.

  1. Such authorization decisions needs to be based on the validated peer certificate chain, rather than the chain-as-presented (which may have the certs out-of-order), and the TrustManager is in the correct place and time to compute and inspect validated certificate chains.

  2. Extracting and validating such certificate data is potentially expensive and may involve encryption operations (for instance, the JDK TrustManager implementation does not share the validated chain it computes, so implementations based on it will have to compute it again), so it is desirable for performance to do this work per session, rather than per request.

From reading https://bugs.openjdk.org/browse/JDK-8245551 it sounds like we are being set up for these sessions to statelessly resume. It's not clear from the issue how distributed sessions would be enabled, or if it is somehow enabled by default and happens automatically (how would that work?). But stateless resumption would cause the authorization data to be lost, which the application might not expected, and may cause security issues.

I'm wondering if the session being stateless is an a priori assumption, or if it will be determined based on whether the handshake session gets any information added to it, or something else. If it's going to be the case that a session may or may not be in a stateless mode, and there's no changing this even as early as the TrustManager calls, then it's certainly desirable to be able to determine this fact from the session (and handshake session) so that informed decisions can be made about it; to reject sessions, to deploy work-arounds, etc.

I'll also note that in this scenario, if the session data is local-only then it won't be advantageous for the sessions to move across hosts, since the applications will be forced to have a request-level filter that re-computes validated certificate chains and extracts authorization on every move.

That's my feedback on the JDK issue.

/cc @sbordet FYI.

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.

None yet

2 participants