Adjust SSLDriver behavior for JDK11 changes (#32145)

This is related to #32122. A number of things changed related to adding
TLS 1.3 support in JDK11. Some exception messages and other SSLEngine
behavior changed. This commit fixes assertions on exception messages.
Additionally it identifies two bugs related to how the SSLDriver behaves
in regards to JDK11 changes. Finally, it mutes a tests until correct
behavior can be identified. There is another open issue for that muted
test (#32144).
This commit is contained in:
Tim Brooks 2018-07-18 11:49:42 -06:00 committed by GitHub
parent e20f59aa71
commit 90fcb38448
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 49 additions and 13 deletions

View File

@ -349,7 +349,10 @@ public class SSLDriver implements AutoCloseable {
if (hasFlushPending() == false) { if (hasFlushPending() == false) {
handshakeStatus = wrap(EMPTY_BUFFER_ARRAY).getHandshakeStatus(); handshakeStatus = wrap(EMPTY_BUFFER_ARRAY).getHandshakeStatus();
} }
continueHandshaking = false; // If we need NEED_TASK we should run the tasks immediately
if (handshakeStatus != SSLEngineResult.HandshakeStatus.NEED_TASK) {
continueHandshaking = false;
}
break; break;
case NEED_TASK: case NEED_TASK:
runTasks(); runTasks();
@ -432,8 +435,16 @@ public class SSLDriver implements AutoCloseable {
} }
private void maybeFinishHandshake() { private void maybeFinishHandshake() {
// We only acknowledge that we are done handshaking if there are no bytes that need to be written if (engine.isOutboundDone() || engine.isInboundDone()) {
if (hasFlushPending() == false) { // If the engine is partially closed, immediate transition to close mode.
if (currentMode.isHandshake()) {
currentMode = new CloseMode(true);
} else {
String message = "Expected to be in handshaking mode. Instead in non-handshaking mode: " + currentMode;
throw new AssertionError(message);
}
} else if (hasFlushPending() == false) {
// We only acknowledge that we are done handshaking if there are no bytes that need to be written
if (currentMode.isHandshake()) { if (currentMode.isHandshake()) {
currentMode = new ApplicationMode(); currentMode = new ApplicationMode();
} else { } else {
@ -510,7 +521,7 @@ public class SSLDriver implements AutoCloseable {
if (isHandshaking && engine.isInboundDone() == false) { if (isHandshaking && engine.isInboundDone() == false) {
// If we attempt to close during a handshake either we are sending an alert and inbound // If we attempt to close during a handshake either we are sending an alert and inbound
// should already be closed or we are sending a close_notify. If we send a close_notify // should already be closed or we are sending a close_notify. If we send a close_notify
// the peer will send an handshake error alert. If we attempt to receive the handshake alert, // the peer might send an handshake error alert. If we attempt to receive the handshake alert,
// the engine will throw an IllegalStateException as it is not in a proper state to receive // the engine will throw an IllegalStateException as it is not in a proper state to receive
// handshake message. Closing inbound immediately after close_notify is the cleanest option. // handshake message. Closing inbound immediately after close_notify is the cleanest option.
needToReceiveClose = false; needToReceiveClose = false;

View File

@ -57,8 +57,15 @@ public class SSLDriverTests extends ESTestCase {
public void testRenegotiate() throws Exception { public void testRenegotiate() throws Exception {
SSLContext sslContext = getSSLContext(); SSLContext sslContext = getSSLContext();
SSLDriver clientDriver = getDriver(sslContext.createSSLEngine(), true); SSLEngine serverEngine = sslContext.createSSLEngine();
SSLDriver serverDriver = getDriver(sslContext.createSSLEngine(), false); SSLEngine clientEngine = sslContext.createSSLEngine();
String[] serverProtocols = {"TLSv1.2"};
serverEngine.setEnabledProtocols(serverProtocols);
String[] clientProtocols = {"TLSv1.2"};
clientEngine.setEnabledProtocols(clientProtocols);
SSLDriver clientDriver = getDriver(clientEngine, true);
SSLDriver serverDriver = getDriver(serverEngine, false);
handshake(clientDriver, serverDriver); handshake(clientDriver, serverDriver);
@ -119,16 +126,27 @@ public class SSLDriverTests extends ESTestCase {
SSLContext sslContext = getSSLContext(); SSLContext sslContext = getSSLContext();
SSLEngine clientEngine = sslContext.createSSLEngine(); SSLEngine clientEngine = sslContext.createSSLEngine();
SSLEngine serverEngine = sslContext.createSSLEngine(); SSLEngine serverEngine = sslContext.createSSLEngine();
String[] serverProtocols = {"TLSv1.1", "TLSv1.2"}; String[] serverProtocols = {"TLSv1.2"};
serverEngine.setEnabledProtocols(serverProtocols); serverEngine.setEnabledProtocols(serverProtocols);
String[] clientProtocols = {"TLSv1"}; String[] clientProtocols = {"TLSv1.1"};
clientEngine.setEnabledProtocols(clientProtocols); clientEngine.setEnabledProtocols(clientProtocols);
SSLDriver clientDriver = getDriver(clientEngine, true); SSLDriver clientDriver = getDriver(clientEngine, true);
SSLDriver serverDriver = getDriver(serverEngine, false); SSLDriver serverDriver = getDriver(serverEngine, false);
SSLException sslException = expectThrows(SSLException.class, () -> handshake(clientDriver, serverDriver)); SSLException sslException = expectThrows(SSLException.class, () -> handshake(clientDriver, serverDriver));
assertEquals("Client requested protocol TLSv1 not enabled or not supported", sslException.getMessage()); String oldExpected = "Client requested protocol TLSv1.1 not enabled or not supported";
failedCloseAlert(serverDriver, clientDriver); String jdk11Expected = "Received fatal alert: protocol_version";
boolean expectedMessage = oldExpected.equals(sslException.getMessage()) || jdk11Expected.equals(sslException.getMessage());
assertTrue("Unexpected exception message: " + sslException.getMessage(), expectedMessage);
// In JDK11 we need an non-application write
if (serverDriver.needsNonApplicationWrite()) {
serverDriver.nonApplicationWrite();
}
// Prior to JDK11 we still need to send a close alert
if (serverDriver.isClosed() == false) {
failedCloseAlert(serverDriver, clientDriver);
}
} }
public void testHandshakeFailureBecauseNoCiphers() throws Exception { public void testHandshakeFailureBecauseNoCiphers() throws Exception {
@ -144,11 +162,18 @@ public class SSLDriverTests extends ESTestCase {
SSLDriver clientDriver = getDriver(clientEngine, true); SSLDriver clientDriver = getDriver(clientEngine, true);
SSLDriver serverDriver = getDriver(serverEngine, false); SSLDriver serverDriver = getDriver(serverEngine, false);
SSLException sslException = expectThrows(SSLException.class, () -> handshake(clientDriver, serverDriver)); expectThrows(SSLException.class, () -> handshake(clientDriver, serverDriver));
assertEquals("no cipher suites in common", sslException.getMessage()); // In JDK11 we need an non-application write
failedCloseAlert(serverDriver, clientDriver); if (serverDriver.needsNonApplicationWrite()) {
serverDriver.nonApplicationWrite();
}
// Prior to JDK11 we still need to send a close alert
if (serverDriver.isClosed() == false) {
failedCloseAlert(serverDriver, clientDriver);
}
} }
@AwaitsFix(bugUrl = "https://github.com/elastic/elasticsearch/issues/32144")
public void testCloseDuringHandshake() throws Exception { public void testCloseDuringHandshake() throws Exception {
SSLContext sslContext = getSSLContext(); SSLContext sslContext = getSSLContext();
SSLDriver clientDriver = getDriver(sslContext.createSSLEngine(), true); SSLDriver clientDriver = getDriver(sslContext.createSSLEngine(), true);