Skip to content

Commit 90fcb38

Browse files
authored
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).
1 parent e20f59a commit 90fcb38

File tree

2 files changed

+49
-13
lines changed
  • x-pack/plugin/security/src

2 files changed

+49
-13
lines changed

x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/transport/nio/SSLDriver.java

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,10 @@ private void handshake() throws SSLException {
349349
if (hasFlushPending() == false) {
350350
handshakeStatus = wrap(EMPTY_BUFFER_ARRAY).getHandshakeStatus();
351351
}
352-
continueHandshaking = false;
352+
// If we need NEED_TASK we should run the tasks immediately
353+
if (handshakeStatus != SSLEngineResult.HandshakeStatus.NEED_TASK) {
354+
continueHandshaking = false;
355+
}
353356
break;
354357
case NEED_TASK:
355358
runTasks();
@@ -432,8 +435,16 @@ private void runTasks() {
432435
}
433436

434437
private void maybeFinishHandshake() {
435-
// We only acknowledge that we are done handshaking if there are no bytes that need to be written
436-
if (hasFlushPending() == false) {
438+
if (engine.isOutboundDone() || engine.isInboundDone()) {
439+
// If the engine is partially closed, immediate transition to close mode.
440+
if (currentMode.isHandshake()) {
441+
currentMode = new CloseMode(true);
442+
} else {
443+
String message = "Expected to be in handshaking mode. Instead in non-handshaking mode: " + currentMode;
444+
throw new AssertionError(message);
445+
}
446+
} else if (hasFlushPending() == false) {
447+
// We only acknowledge that we are done handshaking if there are no bytes that need to be written
437448
if (currentMode.isHandshake()) {
438449
currentMode = new ApplicationMode();
439450
} else {
@@ -510,7 +521,7 @@ private CloseMode(boolean isHandshaking) {
510521
if (isHandshaking && engine.isInboundDone() == false) {
511522
// If we attempt to close during a handshake either we are sending an alert and inbound
512523
// should already be closed or we are sending a close_notify. If we send a close_notify
513-
// the peer will send an handshake error alert. If we attempt to receive the handshake alert,
524+
// the peer might send an handshake error alert. If we attempt to receive the handshake alert,
514525
// the engine will throw an IllegalStateException as it is not in a proper state to receive
515526
// handshake message. Closing inbound immediately after close_notify is the cleanest option.
516527
needToReceiveClose = false;

x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/transport/nio/SSLDriverTests.java

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,15 @@ public void testPingPongAndClose() throws Exception {
5757
public void testRenegotiate() throws Exception {
5858
SSLContext sslContext = getSSLContext();
5959

60-
SSLDriver clientDriver = getDriver(sslContext.createSSLEngine(), true);
61-
SSLDriver serverDriver = getDriver(sslContext.createSSLEngine(), false);
60+
SSLEngine serverEngine = sslContext.createSSLEngine();
61+
SSLEngine clientEngine = sslContext.createSSLEngine();
62+
63+
String[] serverProtocols = {"TLSv1.2"};
64+
serverEngine.setEnabledProtocols(serverProtocols);
65+
String[] clientProtocols = {"TLSv1.2"};
66+
clientEngine.setEnabledProtocols(clientProtocols);
67+
SSLDriver clientDriver = getDriver(clientEngine, true);
68+
SSLDriver serverDriver = getDriver(serverEngine, false);
6269

6370
handshake(clientDriver, serverDriver);
6471

@@ -119,16 +126,27 @@ public void testHandshakeFailureBecauseProtocolMismatch() throws Exception {
119126
SSLContext sslContext = getSSLContext();
120127
SSLEngine clientEngine = sslContext.createSSLEngine();
121128
SSLEngine serverEngine = sslContext.createSSLEngine();
122-
String[] serverProtocols = {"TLSv1.1", "TLSv1.2"};
129+
String[] serverProtocols = {"TLSv1.2"};
123130
serverEngine.setEnabledProtocols(serverProtocols);
124-
String[] clientProtocols = {"TLSv1"};
131+
String[] clientProtocols = {"TLSv1.1"};
125132
clientEngine.setEnabledProtocols(clientProtocols);
126133
SSLDriver clientDriver = getDriver(clientEngine, true);
127134
SSLDriver serverDriver = getDriver(serverEngine, false);
128135

129136
SSLException sslException = expectThrows(SSLException.class, () -> handshake(clientDriver, serverDriver));
130-
assertEquals("Client requested protocol TLSv1 not enabled or not supported", sslException.getMessage());
131-
failedCloseAlert(serverDriver, clientDriver);
137+
String oldExpected = "Client requested protocol TLSv1.1 not enabled or not supported";
138+
String jdk11Expected = "Received fatal alert: protocol_version";
139+
boolean expectedMessage = oldExpected.equals(sslException.getMessage()) || jdk11Expected.equals(sslException.getMessage());
140+
assertTrue("Unexpected exception message: " + sslException.getMessage(), expectedMessage);
141+
142+
// In JDK11 we need an non-application write
143+
if (serverDriver.needsNonApplicationWrite()) {
144+
serverDriver.nonApplicationWrite();
145+
}
146+
// Prior to JDK11 we still need to send a close alert
147+
if (serverDriver.isClosed() == false) {
148+
failedCloseAlert(serverDriver, clientDriver);
149+
}
132150
}
133151

134152
public void testHandshakeFailureBecauseNoCiphers() throws Exception {
@@ -144,11 +162,18 @@ public void testHandshakeFailureBecauseNoCiphers() throws Exception {
144162
SSLDriver clientDriver = getDriver(clientEngine, true);
145163
SSLDriver serverDriver = getDriver(serverEngine, false);
146164

147-
SSLException sslException = expectThrows(SSLException.class, () -> handshake(clientDriver, serverDriver));
148-
assertEquals("no cipher suites in common", sslException.getMessage());
149-
failedCloseAlert(serverDriver, clientDriver);
165+
expectThrows(SSLException.class, () -> handshake(clientDriver, serverDriver));
166+
// In JDK11 we need an non-application write
167+
if (serverDriver.needsNonApplicationWrite()) {
168+
serverDriver.nonApplicationWrite();
169+
}
170+
// Prior to JDK11 we still need to send a close alert
171+
if (serverDriver.isClosed() == false) {
172+
failedCloseAlert(serverDriver, clientDriver);
173+
}
150174
}
151175

176+
@AwaitsFix(bugUrl = "https://github.com/elastic/elasticsearch/issues/32144")
152177
public void testCloseDuringHandshake() throws Exception {
153178
SSLContext sslContext = getSSLContext();
154179
SSLDriver clientDriver = getDriver(sslContext.createSSLEngine(), true);

0 commit comments

Comments
 (0)