diff --git a/handler/src/main/java/io/netty/handler/ssl/SslHandler.java b/handler/src/main/java/io/netty/handler/ssl/SslHandler.java
index d7e1770efb..3f175b33fd 100644
--- a/handler/src/main/java/io/netty/handler/ssl/SslHandler.java
+++ b/handler/src/main/java/io/netty/handler/ssl/SslHandler.java
@@ -646,17 +646,45 @@ public class SslHandler
return false;
}
- @Override
- public void inboundBufferUpdated(final ChannelHandlerContext ctx) throws Exception {
- final ByteBuf in = ctx.inboundByteBuffer();
+ /**
+ * Returns true
if the given {@link ByteBuf} is encrypted. Be aware that this method
+ * will not increase the readerIndex of the given {@link ByteBuf}.
+ *
+ * @param buffer
+ * The {@link ByteBuf} to read from. Be aware that it must have at least 5 bytes to read,
+ * otherwise it will throw an {@link IllegalArgumentException}.
+ * @return encrypted
+ * true
if the {@link ByteBuf} is encrypted, false
otherwise.
+ * @throws IllegalArgumentException
+ * Is thrown if the given {@link ByteBuf} has not at least 5 bytes to read.
+ */
+ public static boolean isEncrypted(ByteBuf buffer) {
+ return getEncryptedPacketLength(buffer) != -1;
+ }
- if (in.readableBytes() < 5) {
- return;
+ /**
+ * Return how much bytes can be read out of the encrypted data. Be aware that this method will not increase
+ * the readerIndex of the given {@link ByteBuf}.
+ *
+ * @param buffer
+ * The {@link ByteBuf} to read from. Be aware that it must have at least 5 bytes to read,
+ * otherwise it will throw an {@link IllegalArgumentException}.
+ * @return length
+ * The length of the encrypted packet that is included in the buffer. This will
+ * return -1
if the given {@link ByteBuf} is not encrypted at all.
+ * @throws IllegalArgumentException
+ * Is thrown if the given {@link ByteBuf} has not at least 5 bytes to read.
+ */
+ private static int getEncryptedPacketLength(ByteBuf buffer) {
+ if (buffer.readableBytes() < 5) {
+ throw new IllegalArgumentException("buffer must have at least 5 readable bytes");
}
+ int packetLength = 0;
+
// SSLv3 or TLS - Check ContentType
boolean tls;
- switch (in.getUnsignedByte(in.readerIndex())) {
+ switch (buffer.getUnsignedByte(buffer.readerIndex())) {
case 20: // change_cipher_spec
case 21: // alert
case 22: // handshake
@@ -668,13 +696,12 @@ public class SslHandler
tls = false;
}
- int packetLength = -1;
if (tls) {
// SSLv3 or TLS - Check ProtocolVersion
- int majorVersion = in.getUnsignedByte(in.readerIndex() + 1);
+ int majorVersion = buffer.getUnsignedByte(buffer.readerIndex() + 1);
if (majorVersion == 3) {
// SSLv3 or TLS
- packetLength = (getShort(in, in.readerIndex() + 3) & 0xFFFF) + 5;
+ packetLength = (getShort(buffer, buffer.readerIndex() + 3) & 0xFFFF) + 5;
if (packetLength <= 5) {
// Neither SSLv3 or TLSv1 (i.e. SSLv2 or bad data)
tls = false;
@@ -688,16 +715,16 @@ public class SslHandler
if (!tls) {
// SSLv2 or bad data - Check the version
boolean sslv2 = true;
- int headerLength = (in.getUnsignedByte(
- in.readerIndex()) & 0x80) != 0 ? 2 : 3;
- int majorVersion = in.getUnsignedByte(
- in.readerIndex() + headerLength + 1);
+ int headerLength = (buffer.getUnsignedByte(
+ buffer.readerIndex()) & 0x80) != 0 ? 2 : 3;
+ int majorVersion = buffer.getUnsignedByte(
+ buffer.readerIndex() + headerLength + 1);
if (majorVersion == 2 || majorVersion == 3) {
// SSLv2
if (headerLength == 2) {
- packetLength = (getShort(in, in.readerIndex()) & 0x7FFF) + 2;
+ packetLength = (getShort(buffer, buffer.readerIndex()) & 0x7FFF) + 2;
} else {
- packetLength = (getShort(in, in.readerIndex()) & 0x3FFF) + 3;
+ packetLength = (getShort(buffer, buffer.readerIndex()) & 0x3FFF) + 3;
}
if (packetLength <= headerLength) {
sslv2 = false;
@@ -707,15 +734,31 @@ public class SslHandler
}
if (!sslv2) {
- // Bad data - discard the buffer and raise an exception.
- NotSslRecordException e = new NotSslRecordException(
- "not an SSL/TLS record: " + ByteBufUtil.hexDump(in));
- in.skipBytes(in.readableBytes());
- ctx.fireExceptionCaught(e);
- setHandshakeFailure(e);
- return;
+ return -1;
}
}
+ return packetLength;
+ }
+
+ @Override
+ public void inboundBufferUpdated(final ChannelHandlerContext ctx) throws Exception {
+ final ByteBuf in = ctx.inboundByteBuffer();
+
+ if (in.readableBytes() < 5) {
+ return;
+ }
+
+ int packetLength = getEncryptedPacketLength(in);
+
+ if (packetLength == -1) {
+ // Bad data - discard the buffer and raise an exception.
+ NotSslRecordException e = new NotSslRecordException(
+ "not an SSL/TLS record: " + ByteBufUtil.hexDump(in));
+ in.skipBytes(in.readableBytes());
+ ctx.fireExceptionCaught(e);
+ setHandshakeFailure(e);
+ return;
+ }
assert packetLength > 0;