From d8d08e9528f746050f7f60447a16e6fc1a539cf3 Mon Sep 17 00:00:00 2001 From: Ali Farahani Date: Thu, 5 Jun 2025 13:05:41 +0100 Subject: [PATCH 1/5] add safety net --- .../org/apache/hc/core5/reactor/ssl/SSLIOSession.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLIOSession.java b/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLIOSession.java index 528dc0b5a0..0b26b8b31e 100644 --- a/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLIOSession.java +++ b/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLIOSession.java @@ -73,6 +73,8 @@ @Internal public class SSLIOSession implements IOSession { + public static final int UNPRODUCTIVE_CYCLE_COUNT_LIMIT = 10_000; + enum TLSHandShakeState { READY, INITIALIZED, HANDSHAKING, COMPLETE } private static final ByteBuffer EMPTY_BUFFER = ByteBuffer.allocate(0); @@ -602,10 +604,16 @@ private void decryptData(final IOSession protocolSession) throws IOException { final ByteBuffer inEncryptedBuf = inEncrypted.acquire(); inEncryptedBuf.flip(); try { + int unproductiveCounter = 0; while (inEncryptedBuf.hasRemaining()) { final ByteBuffer inPlainBuf = inPlain.acquire(); try { final SSLEngineResult result = doUnwrap(inEncryptedBuf, inPlainBuf); + if(result.getStatus() == SSLEngineResult.Status.OK && result.bytesConsumed() == 0){ + unproductiveCounter ++; + } else { + unproductiveCounter = 0; + } if (!inEncryptedBuf.hasRemaining() && result.getHandshakeStatus() == HandshakeStatus.NEED_UNWRAP) { throw new SSLException("Unable to complete SSL handshake"); } @@ -626,6 +634,9 @@ private void decryptData(final IOSession protocolSession) throws IOException { } break; } + if(unproductiveCounter > UNPRODUCTIVE_CYCLE_COUNT_LIMIT){ + throw new SSLException(String.format("Unable to decrypt incoming data due to unproductive cycle. Position on the buffer %s and the limit is %s with handshake status of %s and EndOfStream flag as %s", inEncryptedBuf.position(), inEncryptedBuf.limit(), result.getHandshakeStatus(), endOfStream)); + } } finally { inPlain.release(); } From f89ef50594783bc3faa3b29b33e37cb14e6b0e60 Mon Sep 17 00:00:00 2001 From: Ali Farahani Date: Thu, 5 Jun 2025 14:45:41 +0100 Subject: [PATCH 2/5] update unproductive counter limit --- .../main/java/org/apache/hc/core5/reactor/ssl/SSLIOSession.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLIOSession.java b/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLIOSession.java index 0b26b8b31e..89615ddade 100644 --- a/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLIOSession.java +++ b/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLIOSession.java @@ -73,7 +73,7 @@ @Internal public class SSLIOSession implements IOSession { - public static final int UNPRODUCTIVE_CYCLE_COUNT_LIMIT = 10_000; + public static final int UNPRODUCTIVE_CYCLE_COUNT_LIMIT = 1000; enum TLSHandShakeState { READY, INITIALIZED, HANDSHAKING, COMPLETE } From f308861ce99021849ba1959b0fcce5122b08c922 Mon Sep 17 00:00:00 2001 From: Ali Farahani Date: Thu, 5 Jun 2025 15:59:06 +0100 Subject: [PATCH 3/5] renaming and reformating --- .../org/apache/hc/core5/reactor/ssl/SSLIOSession.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLIOSession.java b/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLIOSession.java index 89615ddade..d962b0f4f7 100644 --- a/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLIOSession.java +++ b/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLIOSession.java @@ -73,7 +73,7 @@ @Internal public class SSLIOSession implements IOSession { - public static final int UNPRODUCTIVE_CYCLE_COUNT_LIMIT = 1000; + public static final int UNPRODUCTIVE_DOUNWRAP_CYCLES_LIMIT = 1000; enum TLSHandShakeState { READY, INITIALIZED, HANDSHAKING, COMPLETE } @@ -604,15 +604,15 @@ private void decryptData(final IOSession protocolSession) throws IOException { final ByteBuffer inEncryptedBuf = inEncrypted.acquire(); inEncryptedBuf.flip(); try { - int unproductiveCounter = 0; + int unproductiveDoUnwrapCycles = 0; while (inEncryptedBuf.hasRemaining()) { final ByteBuffer inPlainBuf = inPlain.acquire(); try { final SSLEngineResult result = doUnwrap(inEncryptedBuf, inPlainBuf); if(result.getStatus() == SSLEngineResult.Status.OK && result.bytesConsumed() == 0){ - unproductiveCounter ++; + unproductiveDoUnwrapCycles ++; } else { - unproductiveCounter = 0; + unproductiveDoUnwrapCycles = 0; } if (!inEncryptedBuf.hasRemaining() && result.getHandshakeStatus() == HandshakeStatus.NEED_UNWRAP) { throw new SSLException("Unable to complete SSL handshake"); @@ -634,7 +634,7 @@ private void decryptData(final IOSession protocolSession) throws IOException { } break; } - if(unproductiveCounter > UNPRODUCTIVE_CYCLE_COUNT_LIMIT){ + if (unproductiveDoUnwrapCycles > UNPRODUCTIVE_DOUNWRAP_CYCLES_LIMIT) { throw new SSLException(String.format("Unable to decrypt incoming data due to unproductive cycle. Position on the buffer %s and the limit is %s with handshake status of %s and EndOfStream flag as %s", inEncryptedBuf.position(), inEncryptedBuf.limit(), result.getHandshakeStatus(), endOfStream)); } } finally { From 2d8ebd957c575411951ab6672645be30bedc5c7e Mon Sep 17 00:00:00 2001 From: Ali Farahani Date: Wed, 11 Jun 2025 12:09:32 +0100 Subject: [PATCH 4/5] code style fix --- .../java/org/apache/hc/core5/reactor/ssl/SSLIOSession.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLIOSession.java b/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLIOSession.java index d962b0f4f7..6797123170 100644 --- a/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLIOSession.java +++ b/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLIOSession.java @@ -609,8 +609,8 @@ private void decryptData(final IOSession protocolSession) throws IOException { final ByteBuffer inPlainBuf = inPlain.acquire(); try { final SSLEngineResult result = doUnwrap(inEncryptedBuf, inPlainBuf); - if(result.getStatus() == SSLEngineResult.Status.OK && result.bytesConsumed() == 0){ - unproductiveDoUnwrapCycles ++; + if (result.getStatus() == SSLEngineResult.Status.OK && result.bytesConsumed() == 0) { + unproductiveDoUnwrapCycles++; } else { unproductiveDoUnwrapCycles = 0; } From 4f0091d357bc014ce892ff760ded0cadc91d6e10 Mon Sep 17 00:00:00 2001 From: Ali Farahani Date: Wed, 11 Jun 2025 16:28:51 +0100 Subject: [PATCH 5/5] incorporate hard safety net logic --- .../org/apache/hc/core5/reactor/ssl/SSLIOSession.java | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLIOSession.java b/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLIOSession.java index 6797123170..6b56e193e8 100644 --- a/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLIOSession.java +++ b/httpcore5/src/main/java/org/apache/hc/core5/reactor/ssl/SSLIOSession.java @@ -73,8 +73,6 @@ @Internal public class SSLIOSession implements IOSession { - public static final int UNPRODUCTIVE_DOUNWRAP_CYCLES_LIMIT = 1000; - enum TLSHandShakeState { READY, INITIALIZED, HANDSHAKING, COMPLETE } private static final ByteBuffer EMPTY_BUFFER = ByteBuffer.allocate(0); @@ -604,16 +602,10 @@ private void decryptData(final IOSession protocolSession) throws IOException { final ByteBuffer inEncryptedBuf = inEncrypted.acquire(); inEncryptedBuf.flip(); try { - int unproductiveDoUnwrapCycles = 0; while (inEncryptedBuf.hasRemaining()) { final ByteBuffer inPlainBuf = inPlain.acquire(); try { final SSLEngineResult result = doUnwrap(inEncryptedBuf, inPlainBuf); - if (result.getStatus() == SSLEngineResult.Status.OK && result.bytesConsumed() == 0) { - unproductiveDoUnwrapCycles++; - } else { - unproductiveDoUnwrapCycles = 0; - } if (!inEncryptedBuf.hasRemaining() && result.getHandshakeStatus() == HandshakeStatus.NEED_UNWRAP) { throw new SSLException("Unable to complete SSL handshake"); } @@ -634,7 +626,7 @@ private void decryptData(final IOSession protocolSession) throws IOException { } break; } - if (unproductiveDoUnwrapCycles > UNPRODUCTIVE_DOUNWRAP_CYCLES_LIMIT) { + if (result.bytesConsumed() == 0) { throw new SSLException(String.format("Unable to decrypt incoming data due to unproductive cycle. Position on the buffer %s and the limit is %s with handshake status of %s and EndOfStream flag as %s", inEncryptedBuf.position(), inEncryptedBuf.limit(), result.getHandshakeStatus(), endOfStream)); } } finally {