8211018: Session Resumption without Server-Side State

Reviewed-by: xuelei, jnimeh, jjiang
This commit is contained in:
Anthony Scarpino 2019-06-11 16:31:37 -07:00
parent 9597144fb2
commit 94e1d7530f
21 changed files with 1620 additions and 150 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -33,11 +33,34 @@ import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSessionContext;
import sun.security.action.GetIntegerAction;
import sun.security.action.GetPropertyAction;
import sun.security.util.Cache;
/**
* @systemProperty jdk.tls.server.enableSessionTicketExtension} determines if the
* server will provide stateless session tickets, if the client supports it,
* as described in RFC 5077 and RFC 8446. a stateless session ticket
* contains the encrypted server's state which saves server resources.
*
* {@systemProperty jdk.tls.client.enableSessionTicketExtension} determines if the
* client will send an extension in the ClientHello in the pre-TLS 1.3.
* This extension allows the client to accept the server's session state for
* Server Side stateless resumption (RFC 5077). Setting the property to
* "true" turns this on, by default it is false. For TLS 1.3, the system
* property is not needed as this support is part of the spec.
*
* {@systemProperty jdk.tls.server.sessionTicketTimeout} determines how long
* a session in the server cache or the stateless resumption tickets are
* available for use. The value set by the property can be modified by
* {@code SSLSessionContext.setSessionTimeout()} during runtime.
*
*/
final class SSLSessionContextImpl implements SSLSessionContext {
private final static int DEFAULT_MAX_CACHE_SIZE = 20480;
// Default lifetime of a session. 24 hours
final static int DEFAULT_SESSION_TIMEOUT = 86400;
private final Cache<SessionId, SSLSessionImpl> sessionCache;
// session cache, session id as key
@ -46,16 +69,24 @@ final class SSLSessionContextImpl implements SSLSessionContext {
private int cacheLimit; // the max cache size
private int timeout; // timeout in seconds
// Does this context support stateless session (RFC 5077)
private boolean statelessSession = true;
// package private
SSLSessionContextImpl() {
cacheLimit = getDefaultCacheLimit(); // default cache size
timeout = 86400; // default, 24 hours
SSLSessionContextImpl(boolean server) {
timeout = DEFAULT_SESSION_TIMEOUT;
cacheLimit = getDefaults(server); // default cache size
// use soft reference
sessionCache = Cache.newSoftMemoryCache(cacheLimit, timeout);
sessionHostPortCache = Cache.newSoftMemoryCache(cacheLimit, timeout);
}
// Stateless sessions when available, but there is a cache
boolean statelessEnabled() {
return statelessSession;
}
/**
* Returns the <code>SSLSession</code> bound to the specified session id.
*/
@ -163,8 +194,7 @@ final class SSLSessionContextImpl implements SSLSessionContext {
}
private static String getKey(String hostname, int port) {
return (hostname + ":" +
String.valueOf(port)).toLowerCase(Locale.ENGLISH);
return (hostname + ":" + port).toLowerCase(Locale.ENGLISH);
}
// cache a SSLSession
@ -197,8 +227,51 @@ final class SSLSessionContextImpl implements SSLSessionContext {
}
}
private static int getDefaultCacheLimit() {
private int getDefaults(boolean server) {
try {
String st;
// Property for Session Cache state
if (server) {
st = GetPropertyAction.privilegedGetProperty(
"jdk.tls.server.enableSessionTicketExtension", "true");
} else {
st = GetPropertyAction.privilegedGetProperty(
"jdk.tls.client.enableSessionTicketExtension", "true");
}
if (st.compareToIgnoreCase("false") == 0) {
statelessSession = false;
}
// Property for Session Ticket Timeout. The value can be changed
// by SSLSessionContext.setSessionTimeout(int)
String s = GetPropertyAction.privilegedGetProperty(
"jdk.tls.server.sessionTicketTimeout");
if (s != null) {
try {
int t = Integer.parseInt(s);
if (t < 0 ||
t > NewSessionTicket.MAX_TICKET_LIFETIME) {
timeout = DEFAULT_SESSION_TIMEOUT;
if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
SSLLogger.warning("Invalid timeout given " +
"jdk.tls.server.sessionTicketTimeout: " + t +
". Set to default value " + timeout);
}
} else {
timeout = t;
}
} catch (NumberFormatException e) {
setSessionTimeout(DEFAULT_SESSION_TIMEOUT);
if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
SSLLogger.warning("Invalid timeout for " +
"jdk.tls.server.sessionTicketTimeout: " + s +
". Set to default value " + timeout);
}
}
}
int defaultCacheLimit = GetIntegerAction.privilegedGetProperty(
"javax.net.ssl.sessionCacheSize", DEFAULT_MAX_CACHE_SIZE);