Skip to content

Commit e530cd6

Browse files
authored
Return correct value from SSLSession.getPacketSize() when using native SSL implementation (#13095)
Motivation: We didnt return the maximum size of SSL packet and tried to calculate it. This didnt work as SSL_max_seal_overhead(...) can only be used to calculate the maximum overhead for when encrypting ourself (and not the remote peer). Because of this we sometimes returned a smaller number then what is possible. This had the affect that when users did use getPacketSize() to size the ByteBuffer we could end up in a situation that would never produce a bug enough ByteBuffer and so never finish the handshake. This issue only accoured when users use the SSLEngine directly. When using our SslHandler we were not affected by this as we use a different approach there. Modifications: - Upgrade netty-tcnative to be able to reuse the the defined constant - Add unit test that did loop forever before this change Result: Fixes #13073
1 parent fdfbb04 commit e530cd6

4 files changed

Lines changed: 88 additions & 7 deletions

File tree

bom/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@
6565

6666
<properties>
6767
<!-- Keep in sync with ../pom.xml -->
68-
<tcnative.version>2.0.54.Final</tcnative.version>
68+
<tcnative.version>2.0.55.Final</tcnative.version>
6969
</properties>
7070

7171
<build>

handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslEngine.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2627,7 +2627,7 @@ public int getPeerPort() {
26272627

26282628
@Override
26292629
public int getPacketBufferSize() {
2630-
return maxEncryptedPacketLength();
2630+
return SSL.SSL_MAX_ENCRYPTED_LENGTH;
26312631
}
26322632

26332633
@Override

handler/src/test/java/io/netty/handler/ssl/SSLEngineTest.java

Lines changed: 85 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1645,6 +1645,10 @@ protected void handshake(BufferType type, boolean delegate, SSLEngine clientEngi
16451645
if (isHandshakeFinished(clientResult)) {
16461646
clientHandshakeFinished = true;
16471647
}
1648+
1649+
if (clientResult.getStatus() == Status.BUFFER_OVERFLOW) {
1650+
cTOs = increaseDstBuffer(clientEngine.getSession().getPacketBufferSize(), type, cTOs);
1651+
}
16481652
}
16491653

16501654
if (!serverHandshakeFinished) {
@@ -1656,6 +1660,10 @@ protected void handshake(BufferType type, boolean delegate, SSLEngine clientEngi
16561660
if (isHandshakeFinished(serverResult)) {
16571661
serverHandshakeFinished = true;
16581662
}
1663+
1664+
if (serverResult.getStatus() == Status.BUFFER_OVERFLOW) {
1665+
sTOc = increaseDstBuffer(serverEngine.getSession().getPacketBufferSize(), type, sTOc);
1666+
}
16591667
}
16601668

16611669
cTOs.flip();
@@ -1674,10 +1682,16 @@ protected void handshake(BufferType type, boolean delegate, SSLEngine clientEngi
16741682
runDelegatedTasks(delegate, clientResult, clientEngine);
16751683
assertEquals(sTOc.position() - sTOcPos, clientResult.bytesConsumed());
16761684
assertEquals(clientAppReadBuffer.position() - clientAppReadBufferPos, clientResult.bytesProduced());
1685+
assertEquals(0, clientAppReadBuffer.position());
16771686

16781687
if (isHandshakeFinished(clientResult)) {
16791688
clientHandshakeFinished = true;
16801689
}
1690+
1691+
if (clientResult.getStatus() == Status.BUFFER_OVERFLOW) {
1692+
clientAppReadBuffer = increaseDstBuffer(
1693+
clientEngine.getSession().getApplicationBufferSize(), type, clientAppReadBuffer);
1694+
}
16811695
} else {
16821696
assertEquals(0, sTOc.remaining());
16831697
}
@@ -1688,26 +1702,59 @@ protected void handshake(BufferType type, boolean delegate, SSLEngine clientEngi
16881702
runDelegatedTasks(delegate, serverResult, serverEngine);
16891703
assertEquals(cTOs.position() - cTOsPos, serverResult.bytesConsumed());
16901704
assertEquals(serverAppReadBuffer.position() - serverAppReadBufferPos, serverResult.bytesProduced());
1705+
assertEquals(0, serverAppReadBuffer.position());
16911706

16921707
if (isHandshakeFinished(serverResult)) {
16931708
serverHandshakeFinished = true;
16941709
}
1710+
1711+
if (serverResult.getStatus() == Status.BUFFER_OVERFLOW) {
1712+
serverAppReadBuffer = increaseDstBuffer(
1713+
serverEngine.getSession().getApplicationBufferSize(), type, serverAppReadBuffer);
1714+
}
16951715
} else {
16961716
assertFalse(cTOs.hasRemaining());
16971717
}
16981718

1699-
cTOsHasRemaining = cTOs.hasRemaining();
1700-
sTOcHasRemaining = sTOc.hasRemaining();
1719+
cTOsHasRemaining = compactOrClear(cTOs);
1720+
sTOcHasRemaining = compactOrClear(sTOc);
1721+
1722+
serverAppReadBuffer.clear();
1723+
clientAppReadBuffer.clear();
17011724

1702-
sTOc.compact();
1703-
cTOs.compact();
1725+
if (clientEngine.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) {
1726+
clientHandshakeFinished = true;
1727+
}
1728+
1729+
if (serverEngine.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) {
1730+
serverHandshakeFinished = true;
1731+
}
17041732
} while (!clientHandshakeFinished || !serverHandshakeFinished ||
17051733
// We need to ensure we feed all the data to the engine to not end up with a corrupted state.
17061734
// This is especially important with TLS1.3 which may produce sessions after the "main handshake" is
17071735
// done
17081736
cTOsHasRemaining || sTOcHasRemaining);
17091737
}
17101738

1739+
private static boolean compactOrClear(ByteBuffer buffer) {
1740+
if (buffer.hasRemaining()) {
1741+
buffer.compact();
1742+
return true;
1743+
}
1744+
buffer.clear();
1745+
return false;
1746+
}
1747+
1748+
private ByteBuffer increaseDstBuffer(int maxBufferSize,
1749+
BufferType type, ByteBuffer dstBuffer) {
1750+
assumeFalse(maxBufferSize == dstBuffer.remaining());
1751+
// We need to increase the destination buffer
1752+
dstBuffer.flip();
1753+
ByteBuffer tmpBuffer = allocateBuffer(type, maxBufferSize + dstBuffer.remaining());
1754+
tmpBuffer.put(dstBuffer);
1755+
return tmpBuffer;
1756+
}
1757+
17111758
private static boolean isHandshakeFinished(SSLEngineResult result) {
17121759
return result.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.FINISHED;
17131760
}
@@ -4243,6 +4290,40 @@ public void testInvalidSNIIsIgnoredAndNotThrow(SSLEngineTestParam param) throws
42434290
}
42444291
}
42454292

4293+
@MethodSource("newTestParams")
4294+
@ParameterizedTest
4295+
public void testBufferUnderflowPacketSizeDependency(SSLEngineTestParam param) throws Exception {
4296+
SelfSignedCertificate ssc = new SelfSignedCertificate();
4297+
clientSslCtx = wrapContext(param, SslContextBuilder.forClient()
4298+
.keyManager(ssc.certificate(), ssc.privateKey())
4299+
.trustManager((TrustManagerFactory) null)
4300+
.sslProvider(sslClientProvider())
4301+
.sslContextProvider(clientSslContextProvider())
4302+
.protocols(param.protocols())
4303+
.ciphers(param.ciphers())
4304+
.build());
4305+
serverSslCtx = wrapContext(param, SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey())
4306+
.sslProvider(sslServerProvider())
4307+
.sslContextProvider(serverSslContextProvider())
4308+
.protocols(param.protocols())
4309+
.ciphers(param.ciphers())
4310+
.clientAuth(ClientAuth.REQUIRE)
4311+
.build());
4312+
SSLEngine clientEngine = null;
4313+
SSLEngine serverEngine = null;
4314+
try {
4315+
clientEngine = wrapEngine(clientSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
4316+
serverEngine = wrapEngine(serverSslCtx.newEngine(UnpooledByteBufAllocator.DEFAULT));
4317+
4318+
handshake(param.type(), param.delegate(), clientEngine, serverEngine);
4319+
} catch (SSLHandshakeException expected) {
4320+
// Expected
4321+
} finally {
4322+
cleanupClientSslEngine(clientEngine);
4323+
cleanupServerSslEngine(serverEngine);
4324+
}
4325+
}
4326+
42464327
protected SSLEngine wrapEngine(SSLEngine engine) {
42474328
return engine;
42484329
}

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -598,7 +598,7 @@
598598
<os.detection.classifierWithLikes>fedora,suse,arch</os.detection.classifierWithLikes>
599599
<tcnative.artifactId>netty-tcnative</tcnative.artifactId>
600600
<!-- Keep in sync with bom/pom.xml -->
601-
<tcnative.version>2.0.54.Final</tcnative.version>
601+
<tcnative.version>2.0.55.Final</tcnative.version>
602602
<tcnative.classifier>${os.detected.classifier}</tcnative.classifier>
603603
<conscrypt.groupId>org.conscrypt</conscrypt.groupId>
604604
<conscrypt.artifactId>conscrypt-openjdk-uber</conscrypt.artifactId>

0 commit comments

Comments
 (0)