Skip to content
Snippets Groups Projects
Commit 24fed952 authored by Pierre Gruet's avatar Pierre Gruet Committed by Ritesh Raj Sarraf
Browse files

Import Debian changes 1:4.1.48-7

parent 47aebdfe
No related branches found
Tags debian/1%4.1.48-7
1 merge request!18Update from debian/bookworm for apertis/v2024dev2
Pipeline #657122 canceled
netty (1:4.1.48-7) unstable; urgency=medium
* Team upload
* Raising Standards version to 4.6.2 (no change)
* Build-depending on log4j1.2-java (Closes: #1028805)
* Removing unneeded versioned build-dependencies
* Fixing debian/copyright syntax:
- Comments field name turned into Comment
- MIT license name turned into Expat
* Honouring filenamemangle in d/watch
* Update lintian override info format in d/libnetty-java.lintian-overrides
* Use secure URI in Homepage field.
* Set upstream metadata fields: Bug-Database, Bug-Submit, Repository-Browse.
-- Pierre Gruet <pgt@debian.org> Sun, 22 Jan 2023 17:43:44 +0100
netty (1:4.1.48-6) unstable; urgency=high
* Team upload.
* Fix CVE-2021-37136, CVE-2021-37137, CVE-2021-43797, CVE-2022-41881,
and CVE-2022-41915. Several out-of-memory, stack overflow or HTTP request
smuggling vulnerabilities have been discovered in Netty which may allow
attackers to cause a denial of service or bypass restrictions when used as
a proxy. (Closes: #1027180, #1014769, #1001437)
-- Markus Koschany <apo@debian.org> Sun, 01 Jan 2023 19:17:21 +0100
netty (1:4.1.48-5) unstable; urgency=medium
* Team upload.
* Fix FTBFS on Java 17 (Closes: #1011135)
-- tony mancill <tmancill@debian.org> Wed, 25 May 2022 22:09:22 -0700
netty (1:4.1.48-4) unstable; urgency=high
* Team upload.
......
......@@ -8,7 +8,7 @@ Uploaders:
Kyo Lee <kyo.lee@eucalyptus.com>
Build-Depends:
ant,
ant-contrib (>= 1.0~b3+svn177-8~),
ant-contrib,
debhelper-compat (= 13),
default-jdk,
groovy,
......@@ -17,8 +17,9 @@ Build-Depends:
libcompress-lzf-java,
libgoogle-gson-java,
libjavassist-java,
libjctools-java (>= 2.0),
libjctools-java,
libjzlib-java,
liblog4j1.2-java,
liblog4j2-java,
libmaven-antrun-plugin-java,
libmaven-bundle-plugin-java,
......@@ -28,11 +29,11 @@ Build-Depends:
libnetty-tcnative-java (>= 2.0.28),
libprotobuf-java,
libxz-java,
maven-debian-helper (>= 1.5)
Standards-Version: 4.5.1
maven-debian-helper
Standards-Version: 4.6.2
Vcs-Git: https://salsa.debian.org/java-team/netty.git
Vcs-Browser: https://salsa.debian.org/java-team/netty
Homepage: http://netty.io/
Homepage: https://netty.io/
Rules-Requires-Root: no
Package: libnetty-java
......
......@@ -11,7 +11,7 @@ License: Apache-2.0
Files: common/src/main/java/io/netty/util/internal/ThreadLocalRandom.java
Copyright: 2009, Red Hat Inc.
Comments:
Comment:
Written by Doug Lea with assistance from members of JCP JSR-166
Expert Group and released to the public domain, as explained at
http://creativecommons.org/licenses/publicdomain
......@@ -19,7 +19,7 @@ License: Apache-2.0
Files: codec/src/main/java/io/netty/handler/codec/base64/*
Copyright: 2009, Red Hat Inc.
Comments:
Comment:
Written by Robert Harder and released to the public domain, as explained at
http://creativecommons.org/licenses/publicdomain
License: Apache-2.0
......@@ -28,7 +28,7 @@ Files: codec-http2/src/main/java/io/netty/handler/codec/http2/Hpack*
codec-http2/src/test/java/io/netty/handler/codec/http2/Hpack*
codec-http2/src/test/java/io/netty/handler/codec/http2/TestHeaderListener.java
Copyright: 2014, Twitter, Inc.
Comments:
Comment:
Copied from the Twitter HPACK library (https://github.com/twitter/hpack)
License: Apache-2.0
......@@ -40,9 +40,9 @@ Files: common/src/main/java/io/netty/util/internal/logging/CommonsLogger.java
common/src/main/java/io/netty/util/internal/logging/MessageFormatter.java
common/src/test/java/io/netty/util/internal/logging/MessageFormatterTest.java
Copyright: 2004-2011, QOS.ch
Comments:
Comment:
Copied from the SLF4J project
License: MIT
License: Expat
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
......@@ -65,9 +65,9 @@ License: MIT
Files: codec-http/src/main/java/io/netty/handler/codec/http/websocketx/Utf8Validator.java
Copyright: 2008-2009, Bjoern Hoehrmann
Comments:
Comment:
Adaptation of http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
License: MIT-utf8-decoder
License: Expat-utf8-decoder
Permission is hereby granted, free of charge, to any person obtaining a copy of this software
and associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
......@@ -127,8 +127,8 @@ License: BSD-3-clause
Files: debian/*
Copyright: 2009, Thierry Carrez <thierry.carrez@ubuntu.com>
2011, Damien Raude-Morvan <drazzib@debian.org>
2015-2018, Emmanuel Bourg <ebourg@apache.org>
2016-2017, tony mancill <tmancill@debian.org>
2015-2022, Emmanuel Bourg <ebourg@apache.org>
2016-2022, tony mancill <tmancill@debian.org>
License: Apache-2.0
License: Apache-2.0
......
# netty-all.jar is intentionally empty but depends on the other netty artifacts
libnetty-java: codeless-jar usr/share/java/netty-all.jar
libnetty-java: codeless-jar [usr/share/java/netty-all.jar]
Description: compile with JDK 17
Source: https://github.com/netty/netty/commit/bb184794341255cf02f9b7156c5ad828b172fdab.patch
Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1011135
Comment: No longer needed after updating upstream to 4.1.52 or later
--- a/handler/src/main/java/io/netty/handler/ssl/util/OpenJdkSelfSignedCertGenerator.java
+++ b/handler/src/main/java/io/netty/handler/ssl/util/OpenJdkSelfSignedCertGenerator.java
@@ -66,7 +66,8 @@
info.set(X509CertInfo.VALIDITY, new CertificateValidity(notBefore, notAfter));
info.set(X509CertInfo.KEY, new CertificateX509Key(keypair.getPublic()));
info.set(X509CertInfo.ALGORITHM_ID,
- new CertificateAlgorithmId(new AlgorithmId(AlgorithmId.sha256WithRSAEncryption_oid)));
+ // sha256WithRSAEncryption
+ new CertificateAlgorithmId(AlgorithmId.get("1.2.840.113549.1.1.11")));
// Sign the cert to identify the algorithm that's used.
X509CertImpl cert = new X509CertImpl(info);
From: Markus Koschany <apo@debian.org>
Date: Sun, 1 Jan 2023 17:07:49 +0100
Subject: CVE-2021-37136
Bug-Debian: https://bugs.debian.org/1014769
Origin: https://github.com/netty/netty/commit/41d3d61a61608f2223bb364955ab2045dd5e4020
---
.../handler/codec/compression/Bzip2BlockDecompressor.java | 5 +++++
.../netty/handler/codec/compression/Bzip2Constants.java | 2 ++
.../io/netty/handler/codec/compression/Bzip2Decoder.java | 15 ++++++++-------
3 files changed, 15 insertions(+), 7 deletions(-)
diff --git a/codec/src/main/java/io/netty/handler/codec/compression/Bzip2BlockDecompressor.java b/codec/src/main/java/io/netty/handler/codec/compression/Bzip2BlockDecompressor.java
index ae05568..5a0b497 100644
--- a/codec/src/main/java/io/netty/handler/codec/compression/Bzip2BlockDecompressor.java
+++ b/codec/src/main/java/io/netty/handler/codec/compression/Bzip2BlockDecompressor.java
@@ -228,6 +228,11 @@ final class Bzip2BlockDecompressor {
bwtBlock[bwtBlockLength++] = nextByte;
}
}
+ if (bwtBlockLength > MAX_BLOCK_LENGTH) {
+ throw new DecompressionException("block length exceeds max block length: "
+ + bwtBlockLength + " > " + MAX_BLOCK_LENGTH);
+ }
+
this.bwtBlockLength = bwtBlockLength;
initialiseInverseBWT();
return true;
diff --git a/codec/src/main/java/io/netty/handler/codec/compression/Bzip2Constants.java b/codec/src/main/java/io/netty/handler/codec/compression/Bzip2Constants.java
index c0283a7..21b9a2b 100644
--- a/codec/src/main/java/io/netty/handler/codec/compression/Bzip2Constants.java
+++ b/codec/src/main/java/io/netty/handler/codec/compression/Bzip2Constants.java
@@ -49,6 +49,8 @@ final class Bzip2Constants {
static final int MIN_BLOCK_SIZE = 1;
static final int MAX_BLOCK_SIZE = 9;
+ static final int MAX_BLOCK_LENGTH = MAX_BLOCK_SIZE * BASE_BLOCK_SIZE;
+
/**
* Maximum possible Huffman alphabet size.
*/
diff --git a/codec/src/main/java/io/netty/handler/codec/compression/Bzip2Decoder.java b/codec/src/main/java/io/netty/handler/codec/compression/Bzip2Decoder.java
index b66ff59..3fc1001 100644
--- a/codec/src/main/java/io/netty/handler/codec/compression/Bzip2Decoder.java
+++ b/codec/src/main/java/io/netty/handler/codec/compression/Bzip2Decoder.java
@@ -291,26 +291,27 @@ public class Bzip2Decoder extends ByteToMessageDecoder {
}
final int blockLength = blockDecompressor.blockLength();
- final ByteBuf uncompressed = ctx.alloc().buffer(blockLength);
- boolean success = false;
+ ByteBuf uncompressed = ctx.alloc().buffer(blockLength);
try {
int uncByte;
while ((uncByte = blockDecompressor.read()) >= 0) {
uncompressed.writeByte(uncByte);
}
-
+ // We did read all the data, lets reset the state and do the CRC check.
+ currentState = State.INIT_BLOCK;
int currentBlockCRC = blockDecompressor.checkCRC();
streamCRC = (streamCRC << 1 | streamCRC >>> 31) ^ currentBlockCRC;
out.add(uncompressed);
- success = true;
+ uncompressed = null;
} finally {
- if (!success) {
+ if (uncompressed != null) {
uncompressed.release();
}
}
- currentState = State.INIT_BLOCK;
- break;
+ // Return here so the ByteBuf that was put in the List will be forwarded to the user and so can be
+ // released as soon as possible.
+ return;
case EOF:
in.skipBytes(in.readableBytes());
return;
From: Markus Koschany <apo@debian.org>
Date: Sun, 1 Jan 2023 18:28:34 +0100
Subject: CVE-2021-37137
Bug-Debian: https://bugs.debian.org/1014769
Origin: https://github.com/netty/netty/commit/6da4956b31023ae967451e1d94ff51a746a9194f
---
.../io/netty/handler/codec/compression/Snappy.java | 30 ++++++++++----
.../codec/compression/SnappyFrameDecoder.java | 46 ++++++++++++++++++----
2 files changed, 62 insertions(+), 14 deletions(-)
diff --git a/codec/src/main/java/io/netty/handler/codec/compression/Snappy.java b/codec/src/main/java/io/netty/handler/codec/compression/Snappy.java
index 8e1825d..c912ed2 100644
--- a/codec/src/main/java/io/netty/handler/codec/compression/Snappy.java
+++ b/codec/src/main/java/io/netty/handler/codec/compression/Snappy.java
@@ -38,12 +38,11 @@ public final class Snappy {
private static final int COPY_2_BYTE_OFFSET = 2;
private static final int COPY_4_BYTE_OFFSET = 3;
- private State state = State.READY;
+ private State state = State.READING_PREAMBLE;
private byte tag;
private int written;
private enum State {
- READY,
READING_PREAMBLE,
READING_TAG,
READING_LITERAL,
@@ -51,7 +50,7 @@ public final class Snappy {
}
public void reset() {
- state = State.READY;
+ state = State.READING_PREAMBLE;
tag = 0;
written = 0;
}
@@ -270,9 +269,6 @@ public final class Snappy {
public void decode(ByteBuf in, ByteBuf out) {
while (in.isReadable()) {
switch (state) {
- case READY:
- state = State.READING_PREAMBLE;
- // fall through
case READING_PREAMBLE:
int uncompressedLength = readPreamble(in);
if (uncompressedLength == PREAMBLE_NOT_FULL) {
@@ -281,7 +277,6 @@ public final class Snappy {
}
if (uncompressedLength == 0) {
// Should never happen, but it does mean we have nothing further to do
- state = State.READY;
return;
}
out.ensureWritable(uncompressedLength);
@@ -378,6 +373,27 @@ public final class Snappy {
return 0;
}
+ /**
+ * Get the length varint (a series of bytes, where the lower 7 bits
+ * are data and the upper bit is a flag to indicate more bytes to be
+ * read).
+ *
+ * @param in The input buffer to get the preamble from
+ * @return The calculated length based on the input buffer, or 0 if
+ * no preamble is able to be calculated
+ */
+ int getPreamble(ByteBuf in) {
+ if (state == State.READING_PREAMBLE) {
+ int readerIndex = in.readerIndex();
+ try {
+ return readPreamble(in);
+ } finally {
+ in.readerIndex(readerIndex);
+ }
+ }
+ return 0;
+ }
+
/**
* Reads a literal from the input buffer directly to the output buffer.
* A "literal" is an uncompressed segment of data stored directly in the
diff --git a/codec/src/main/java/io/netty/handler/codec/compression/SnappyFrameDecoder.java b/codec/src/main/java/io/netty/handler/codec/compression/SnappyFrameDecoder.java
index 4762e72..59fdc68 100644
--- a/codec/src/main/java/io/netty/handler/codec/compression/SnappyFrameDecoder.java
+++ b/codec/src/main/java/io/netty/handler/codec/compression/SnappyFrameDecoder.java
@@ -45,13 +45,19 @@ public class SnappyFrameDecoder extends ByteToMessageDecoder {
}
private static final int SNAPPY_IDENTIFIER_LEN = 6;
+ // See https://github.com/google/snappy/blob/1.1.9/framing_format.txt#L95
private static final int MAX_UNCOMPRESSED_DATA_SIZE = 65536 + 4;
+ // See https://github.com/google/snappy/blob/1.1.9/framing_format.txt#L82
+ private static final int MAX_DECOMPRESSED_DATA_SIZE = 65536;
+ // See https://github.com/google/snappy/blob/1.1.9/framing_format.txt#L82
+ private static final int MAX_COMPRESSED_CHUNK_SIZE = 16777216 - 1;
private final Snappy snappy = new Snappy();
private final boolean validateChecksums;
private boolean started;
private boolean corrupted;
+ private int numBytesToSkip;
/**
* Creates a new snappy-framed decoder with validation of checksums
@@ -82,6 +88,16 @@ public class SnappyFrameDecoder extends ByteToMessageDecoder {
return;
}
+ if (numBytesToSkip != 0) {
+ // The last chunkType we detected was RESERVED_SKIPPABLE and we still have some bytes to skip.
+ int skipBytes = Math.min(numBytesToSkip, in.readableBytes());
+ in.skipBytes(skipBytes);
+ numBytesToSkip -= skipBytes;
+
+ // Let's return and try again.
+ return;
+ }
+
try {
int idx = in.readerIndex();
final int inSize = in.readableBytes();
@@ -123,12 +139,15 @@ public class SnappyFrameDecoder extends ByteToMessageDecoder {
throw new DecompressionException("Received RESERVED_SKIPPABLE tag before STREAM_IDENTIFIER");
}
- if (inSize < 4 + chunkLength) {
- // TODO: Don't keep skippable bytes
- return;
- }
+ in.skipBytes(4);
- in.skipBytes(4 + chunkLength);
+ int skipBytes = Math.min(chunkLength, in.readableBytes());
+ in.skipBytes(skipBytes);
+ if (skipBytes != chunkLength) {
+ // We could skip all bytes, let's store the remaining so we can do so once we receive more
+ // data.
+ numBytesToSkip = chunkLength - skipBytes;
+ }
break;
case RESERVED_UNSKIPPABLE:
// The spec mandates that reserved unskippable chunks must immediately
@@ -141,7 +160,8 @@ public class SnappyFrameDecoder extends ByteToMessageDecoder {
throw new DecompressionException("Received UNCOMPRESSED_DATA tag before STREAM_IDENTIFIER");
}
if (chunkLength > MAX_UNCOMPRESSED_DATA_SIZE) {
- throw new DecompressionException("Received UNCOMPRESSED_DATA larger than 65540 bytes");
+ throw new DecompressionException("Received UNCOMPRESSED_DATA larger than " +
+ MAX_UNCOMPRESSED_DATA_SIZE + " bytes");
}
if (inSize < 4 + chunkLength) {
@@ -162,13 +182,25 @@ public class SnappyFrameDecoder extends ByteToMessageDecoder {
throw new DecompressionException("Received COMPRESSED_DATA tag before STREAM_IDENTIFIER");
}
+ if (chunkLength > MAX_COMPRESSED_CHUNK_SIZE) {
+ throw new DecompressionException("Received COMPRESSED_DATA that contains" +
+ " chunk that exceeds " + MAX_COMPRESSED_CHUNK_SIZE + " bytes");
+ }
+
if (inSize < 4 + chunkLength) {
return;
}
in.skipBytes(4);
int checksum = in.readIntLE();
- ByteBuf uncompressed = ctx.alloc().buffer();
+
+ int uncompressedSize = snappy.getPreamble(in);
+ if (uncompressedSize > MAX_DECOMPRESSED_DATA_SIZE) {
+ throw new DecompressionException("Received COMPRESSED_DATA that contains" +
+ " uncompressed data that exceeds " + MAX_DECOMPRESSED_DATA_SIZE + " bytes");
+ }
+
+ ByteBuf uncompressed = ctx.alloc().buffer(uncompressedSize, MAX_DECOMPRESSED_DATA_SIZE);
try {
if (validateChecksums) {
int oldWriterIndex = in.writerIndex();
From: Markus Koschany <apo@debian.org>
Date: Sun, 1 Jan 2023 18:42:42 +0100
Subject: CVE-2021-43797
Bug-Debian: https://bugs.debian.org/1001437
Origin: https://github.com/netty/netty/commit/07aa6b5938a8b6ed7a6586e066400e2643897323
---
.../handler/codec/http/DefaultHttpHeaders.java | 8 ++
.../handler/codec/http/HttpObjectDecoder.java | 8 +-
.../handler/codec/http/HttpRequestDecoderTest.java | 87 ++++++++++++++++++++--
.../codec/http/HttpResponseDecoderTest.java | 78 +++++++++++++++++++
4 files changed, 171 insertions(+), 10 deletions(-)
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/DefaultHttpHeaders.java b/codec-http/src/main/java/io/netty/handler/codec/http/DefaultHttpHeaders.java
index 675d513..33064f6 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/DefaultHttpHeaders.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/DefaultHttpHeaders.java
@@ -367,6 +367,10 @@ public class DefaultHttpHeaders extends HttpHeaders {
private static void validateHeaderNameElement(byte value) {
switch (value) {
+ case 0x1c:
+ case 0x1d:
+ case 0x1e:
+ case 0x1f:
case 0x00:
case '\t':
case '\n':
@@ -391,6 +395,10 @@ public class DefaultHttpHeaders extends HttpHeaders {
private static void validateHeaderNameElement(char value) {
switch (value) {
+ case 0x1c:
+ case 0x1d:
+ case 0x1e:
+ case 0x1f:
case 0x00:
case '\t':
case '\n':
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java b/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java
index 1384df7..4aa864a 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java
@@ -759,7 +759,7 @@ public abstract class HttpObjectDecoder extends ByteToMessageDecoder {
int valueStart;
int valueEnd;
- nameStart = findNonWhitespace(sb, 0, false);
+ nameStart = findNonWhitespace(sb, 0);
for (nameEnd = nameStart; nameEnd < length; nameEnd ++) {
char ch = sb.charAtUnsafe(nameEnd);
// https://tools.ietf.org/html/rfc7230#section-3.2.4
@@ -794,7 +794,7 @@ public abstract class HttpObjectDecoder extends ByteToMessageDecoder {
}
name = sb.subStringUnsafe(nameStart, nameEnd);
- valueStart = findNonWhitespace(sb, colonEnd, true);
+ valueStart = findNonWhitespace(sb, colonEnd);
if (valueStart == length) {
value = EMPTY_VALUE;
} else {
@@ -833,12 +833,12 @@ public abstract class HttpObjectDecoder extends ByteToMessageDecoder {
return c == ' ' || c == (char) 0x09 || c == (char) 0x0B || c == (char) 0x0C || c == (char) 0x0D;
}
- private static int findNonWhitespace(AppendableCharSequence sb, int offset, boolean validateOWS) {
+ private static int findNonWhitespace(AppendableCharSequence sb, int offset) {
for (int result = offset; result < sb.length(); ++result) {
char c = sb.charAtUnsafe(result);
if (!Character.isWhitespace(c)) {
return result;
- } else if (validateOWS && !isOWS(c)) {
+ } else if (!isOWS(c)) {
// Only OWS is supported for whitespace
throw new IllegalArgumentException("Invalid separator, only a single space or horizontal tab allowed," +
" but received a '" + c + "'");
diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/HttpRequestDecoderTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/HttpRequestDecoderTest.java
index 4f83d82..753cf35 100644
--- a/codec-http/src/test/java/io/netty/handler/codec/http/HttpRequestDecoderTest.java
+++ b/codec-http/src/test/java/io/netty/handler/codec/http/HttpRequestDecoderTest.java
@@ -15,6 +15,7 @@
*/
package io.netty.handler.codec.http;
+import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.embedded.EmbeddedChannel;
import io.netty.handler.codec.TooLongFrameException;
@@ -357,6 +358,75 @@ public class HttpRequestDecoderTest {
assertFalse(channel.finish());
}
+ @Test
+ public void testHeaderNameStartsWithControlChar1c() {
+ testHeaderNameStartsWithControlChar(0x1c);
+ }
+
+ @Test
+ public void testHeaderNameStartsWithControlChar1d() {
+ testHeaderNameStartsWithControlChar(0x1d);
+ }
+
+ @Test
+ public void testHeaderNameStartsWithControlChar1e() {
+ testHeaderNameStartsWithControlChar(0x1e);
+ }
+
+ @Test
+ public void testHeaderNameStartsWithControlChar1f() {
+ testHeaderNameStartsWithControlChar(0x1f);
+ }
+
+ @Test
+ public void testHeaderNameStartsWithControlChar0c() {
+ testHeaderNameStartsWithControlChar(0x0c);
+ }
+
+ private void testHeaderNameStartsWithControlChar(int controlChar) {
+ ByteBuf requestBuffer = Unpooled.buffer();
+ requestBuffer.writeCharSequence("GET /some/path HTTP/1.1\r\n" +
+ "Host: netty.io\r\n", CharsetUtil.US_ASCII);
+ requestBuffer.writeByte(controlChar);
+ requestBuffer.writeCharSequence("Transfer-Encoding: chunked\r\n\r\n", CharsetUtil.US_ASCII);
+ testInvalidHeaders0(requestBuffer);
+ }
+
+ @Test
+ public void testHeaderNameEndsWithControlChar1c() {
+ testHeaderNameEndsWithControlChar(0x1c);
+ }
+
+ @Test
+ public void testHeaderNameEndsWithControlChar1d() {
+ testHeaderNameEndsWithControlChar(0x1d);
+ }
+
+ @Test
+ public void testHeaderNameEndsWithControlChar1e() {
+ testHeaderNameEndsWithControlChar(0x1e);
+ }
+
+ @Test
+ public void testHeaderNameEndsWithControlChar1f() {
+ testHeaderNameEndsWithControlChar(0x1f);
+ }
+
+ @Test
+ public void testHeaderNameEndsWithControlChar0c() {
+ testHeaderNameEndsWithControlChar(0x0c);
+ }
+
+ private void testHeaderNameEndsWithControlChar(int controlChar) {
+ ByteBuf requestBuffer = Unpooled.buffer();
+ requestBuffer.writeCharSequence("GET /some/path HTTP/1.1\r\n" +
+ "Host: netty.io\r\n", CharsetUtil.US_ASCII);
+ requestBuffer.writeCharSequence("Transfer-Encoding", CharsetUtil.US_ASCII);
+ requestBuffer.writeByte(controlChar);
+ requestBuffer.writeCharSequence(": chunked\r\n\r\n", CharsetUtil.US_ASCII);
+ testInvalidHeaders0(requestBuffer);
+ }
+
@Test
public void testWhitespace() {
String requestStr = "GET /some/path HTTP/1.1\r\n" +
@@ -366,9 +436,9 @@ public class HttpRequestDecoderTest {
}
@Test
- public void testWhitespaceBeforeTransferEncoding01() {
+ public void testWhitespaceInTransferEncoding01() {
String requestStr = "GET /some/path HTTP/1.1\r\n" +
- " Transfer-Encoding : chunked\r\n" +
+ "Transfer-Encoding : chunked\r\n" +
"Content-Length: 1\r\n" +
"Host: netty.io\r\n\r\n" +
"a";
@@ -376,9 +446,9 @@ public class HttpRequestDecoderTest {
}
@Test
- public void testWhitespaceBeforeTransferEncoding02() {
+ public void testWhitespaceInTransferEncoding02() {
String requestStr = "POST / HTTP/1.1" +
- " Transfer-Encoding : chunked\r\n" +
+ "Transfer-Encoding : chunked\r\n" +
"Host: target.com" +
"Content-Length: 65\r\n\r\n" +
"0\r\n\r\n" +
@@ -475,15 +545,20 @@ public class HttpRequestDecoderTest {
assertTrue(request.headers().contains("Transfer-Encoding", "chunked", false));
assertFalse(request.headers().contains("Content-Length"));
LastHttpContent c = channel.readInbound();
+ c.release();
assertFalse(channel.finish());
}
private static void testInvalidHeaders0(String requestStr) {
+ testInvalidHeaders0(Unpooled.copiedBuffer(requestStr, CharsetUtil.US_ASCII));
+ }
+
+ private static void testInvalidHeaders0(ByteBuf requestBuffer) {
EmbeddedChannel channel = new EmbeddedChannel(new HttpRequestDecoder());
- assertTrue(channel.writeInbound(Unpooled.copiedBuffer(requestStr, CharsetUtil.US_ASCII)));
+ assertTrue(channel.writeInbound(requestBuffer));
HttpRequest request = channel.readInbound();
+ assertThat(request.decoderResult().cause(), instanceOf(IllegalArgumentException.class));
assertTrue(request.decoderResult().isFailure());
- assertTrue(request.decoderResult().cause() instanceof IllegalArgumentException);
assertFalse(channel.finish());
}
}
diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/HttpResponseDecoderTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/HttpResponseDecoderTest.java
index b0ccd0c..a7418b0 100644
--- a/codec-http/src/test/java/io/netty/handler/codec/http/HttpResponseDecoderTest.java
+++ b/codec-http/src/test/java/io/netty/handler/codec/http/HttpResponseDecoderTest.java
@@ -727,4 +727,82 @@ public class HttpResponseDecoderTest {
assertEquals("netty.io", response.headers().get(HttpHeaderNames.HOST));
assertFalse(channel.finish());
}
+
+ @Test
+ public void testHeaderNameStartsWithControlChar1c() {
+ testHeaderNameStartsWithControlChar(0x1c);
+ }
+
+ @Test
+ public void testHeaderNameStartsWithControlChar1d() {
+ testHeaderNameStartsWithControlChar(0x1d);
+ }
+
+ @Test
+ public void testHeaderNameStartsWithControlChar1e() {
+ testHeaderNameStartsWithControlChar(0x1e);
+ }
+
+ @Test
+ public void testHeaderNameStartsWithControlChar1f() {
+ testHeaderNameStartsWithControlChar(0x1f);
+ }
+
+ @Test
+ public void testHeaderNameStartsWithControlChar0c() {
+ testHeaderNameStartsWithControlChar(0x0c);
+ }
+
+ private void testHeaderNameStartsWithControlChar(int controlChar) {
+ ByteBuf responseBuffer = Unpooled.buffer();
+ responseBuffer.writeCharSequence("HTTP/1.1 200 OK\r\n" +
+ "Host: netty.io\r\n", CharsetUtil.US_ASCII);
+ responseBuffer.writeByte(controlChar);
+ responseBuffer.writeCharSequence("Transfer-Encoding: chunked\r\n\r\n", CharsetUtil.US_ASCII);
+ testInvalidHeaders0(responseBuffer);
+ }
+
+ @Test
+ public void testHeaderNameEndsWithControlChar1c() {
+ testHeaderNameEndsWithControlChar(0x1c);
+ }
+
+ @Test
+ public void testHeaderNameEndsWithControlChar1d() {
+ testHeaderNameEndsWithControlChar(0x1d);
+ }
+
+ @Test
+ public void testHeaderNameEndsWithControlChar1e() {
+ testHeaderNameEndsWithControlChar(0x1e);
+ }
+
+ @Test
+ public void testHeaderNameEndsWithControlChar1f() {
+ testHeaderNameEndsWithControlChar(0x1f);
+ }
+
+ @Test
+ public void testHeaderNameEndsWithControlChar0c() {
+ testHeaderNameEndsWithControlChar(0x0c);
+ }
+
+ private void testHeaderNameEndsWithControlChar(int controlChar) {
+ ByteBuf responseBuffer = Unpooled.buffer();
+ responseBuffer.writeCharSequence("HTTP/1.1 200 OK\r\n" +
+ "Host: netty.io\r\n", CharsetUtil.US_ASCII);
+ responseBuffer.writeCharSequence("Transfer-Encoding", CharsetUtil.US_ASCII);
+ responseBuffer.writeByte(controlChar);
+ responseBuffer.writeCharSequence(": chunked\r\n\r\n", CharsetUtil.US_ASCII);
+ testInvalidHeaders0(responseBuffer);
+ }
+
+ private static void testInvalidHeaders0(ByteBuf responseBuffer) {
+ EmbeddedChannel channel = new EmbeddedChannel(new HttpResponseDecoder());
+ assertTrue(channel.writeInbound(responseBuffer));
+ HttpResponse response = channel.readInbound();
+ assertThat(response.decoderResult().cause(), instanceOf(IllegalArgumentException.class));
+ assertTrue(response.decoderResult().isFailure());
+ assertFalse(channel.finish());
+ }
}
From: Markus Koschany <apo@debian.org>
Date: Sun, 1 Jan 2023 19:08:24 +0100
Subject: CVE-2022-41881
Bug-Debian: https://bugs.debian.org/1027180
Origin: https://github.com/netty/netty/commit/cd91cf3c99123bd1e53fd6a1de0e3d1922f05bb2
---
.../handler/codec/haproxy/HAProxyMessage.java | 16 ++++--
.../codec/haproxy/HAProxyMessageDecoderTest.java | 65 ++++++++++++++++++++++
2 files changed, 76 insertions(+), 5 deletions(-)
diff --git a/codec-haproxy/src/main/java/io/netty/handler/codec/haproxy/HAProxyMessage.java b/codec-haproxy/src/main/java/io/netty/handler/codec/haproxy/HAProxyMessage.java
index 1777e67..45d24a2 100644
--- a/codec-haproxy/src/main/java/io/netty/handler/codec/haproxy/HAProxyMessage.java
+++ b/codec-haproxy/src/main/java/io/netty/handler/codec/haproxy/HAProxyMessage.java
@@ -34,6 +34,9 @@ import java.util.List;
* Message container for decoded HAProxy proxy protocol parameters
*/
public final class HAProxyMessage extends AbstractReferenceCounted {
+
+ // Let's pick some conservative limit here.
+ private static final int MAX_NESTING_LEVEL = 128;
private static final ResourceLeakDetector<HAProxyMessage> leakDetector =
ResourceLeakDetectorFactory.instance().newResourceLeakDetector(HAProxyMessage.class);
@@ -223,7 +226,7 @@ public final class HAProxyMessage extends AbstractReferenceCounted {
}
private static List<HAProxyTLV> readTlvs(final ByteBuf header) {
- HAProxyTLV haProxyTLV = readNextTLV(header);
+ HAProxyTLV haProxyTLV = readNextTLV(header, 0);
if (haProxyTLV == null) {
return Collections.emptyList();
}
@@ -235,12 +238,15 @@ public final class HAProxyMessage extends AbstractReferenceCounted {
if (haProxyTLV instanceof HAProxySSLTLV) {
haProxyTLVs.addAll(((HAProxySSLTLV) haProxyTLV).encapsulatedTLVs());
}
- } while ((haProxyTLV = readNextTLV(header)) != null);
+ } while ((haProxyTLV = readNextTLV(header, 0)) != null);
return haProxyTLVs;
}
- private static HAProxyTLV readNextTLV(final ByteBuf header) {
-
+ private static HAProxyTLV readNextTLV(final ByteBuf header, int nestingLevel) {
+ if (nestingLevel > MAX_NESTING_LEVEL) {
+ throw new HAProxyProtocolException(
+ "Maximum TLV nesting level reached: " + nestingLevel + " (expected: < " + MAX_NESTING_LEVEL + ')');
+ }
// We need at least 4 bytes for a TLV
if (header.readableBytes() < 4) {
return null;
@@ -261,7 +267,7 @@ public final class HAProxyMessage extends AbstractReferenceCounted {
final List<HAProxyTLV> encapsulatedTlvs = new ArrayList<HAProxyTLV>(4);
do {
- final HAProxyTLV haProxyTLV = readNextTLV(byteBuf);
+ final HAProxyTLV haProxyTLV = readNextTLV(byteBuf, nestingLevel + 1);
if (haProxyTLV == null) {
break;
}
diff --git a/codec-haproxy/src/test/java/io/netty/handler/codec/haproxy/HAProxyMessageDecoderTest.java b/codec-haproxy/src/test/java/io/netty/handler/codec/haproxy/HAProxyMessageDecoderTest.java
index 2c323ea..00c0ac2 100644
--- a/codec-haproxy/src/test/java/io/netty/handler/codec/haproxy/HAProxyMessageDecoderTest.java
+++ b/codec-haproxy/src/test/java/io/netty/handler/codec/haproxy/HAProxyMessageDecoderTest.java
@@ -16,6 +16,7 @@
package io.netty.handler.codec.haproxy;
import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.embedded.EmbeddedChannel;
import io.netty.handler.codec.ProtocolDetectionResult;
@@ -28,6 +29,9 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
+import java.io.ByteArrayOutputStream;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
import java.util.List;
import static io.netty.buffer.Unpooled.*;
@@ -1107,4 +1111,65 @@ public class HAProxyMessageDecoderTest {
assertNull(result.detectedProtocol());
incompleteHeader.release();
}
+
+ @Test
+ public void testNestedTLV() throws Exception {
+ ByteArrayOutputStream headerWriter = new ByteArrayOutputStream();
+ //src_ip = "AAAA", dst_ip = "BBBB", src_port = "CC", dst_port = "DD"
+ headerWriter.write(new byte[] {'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'C', 'C', 'D', 'D'});
+ //write TLVs
+ int countOfTLVs = 8100;
+ ByteBuffer tlvLengthBuf = ByteBuffer.allocate(2);
+ tlvLengthBuf.order(ByteOrder.BIG_ENDIAN);
+ short totalLength = (short) (countOfTLVs * (1 + 2 + 1 + 4));
+ for (int i = 0; i < countOfTLVs; i++) {
+ //write PP2_TYPE_SSL TLV
+ headerWriter.write(0x20); //PP2_TYPE_SSL
+ //notice that the TLV length cannot be bigger than 0xffff
+ totalLength -= 1 + 2; //exclude type and length themselves
+ tlvLengthBuf.clear();
+ tlvLengthBuf.putShort(totalLength);
+ //add to the header
+ headerWriter.write(tlvLengthBuf.array());
+ //write client field
+ headerWriter.write(1);
+ //write verify field
+ headerWriter.write(new byte[] {'V', 'V', 'V', 'V'});
+ //subtract the client and verify fields
+ totalLength -= 1 + 4;
+ }
+ byte[] header = headerWriter.toByteArray();
+ ByteBuffer numsWrite = ByteBuffer.allocate(2);
+ numsWrite.order(ByteOrder.BIG_ENDIAN);
+ numsWrite.putShort((short) header.length);
+
+ final ByteBuf data = Unpooled.buffer();
+ data.writeBytes(new byte[] {
+ (byte) 0x0D,
+ (byte) 0x0A,
+ (byte) 0x0D,
+ (byte) 0x0A,
+ (byte) 0x00,
+ (byte) 0x0D,
+ (byte) 0x0A,
+ (byte) 0x51,
+ (byte) 0x55,
+ (byte) 0x49,
+ (byte) 0x54,
+ (byte) 0x0A
+ });
+ //verCmd = 32
+ byte versionCmd = 0x20 | 1; //V2 | ProxyCmd
+ data.writeByte(versionCmd);
+ data.writeByte(17); //TPAF_TCP4_BYTE
+ data.writeBytes(numsWrite.array());
+ data.writeBytes(header);
+
+ assertThrows(HAProxyProtocolException.class, new Executable() {
+ @Override
+ public void execute() {
+ ch.writeInbound(data);
+ }
+ });
+ }
}
This diff is collapsed.
......@@ -15,3 +15,9 @@
CVE-2021-21290.patch
CVE-2021-21295.patch
CVE-2021-21409.patch
21-java-17.patch
CVE-2021-37136.patch
CVE-2021-37137.patch
CVE-2021-43797.patch
CVE-2022-41881.patch
CVE-2022-41915.patch
---
Bug-Database: https://github.com/netty/netty/issues
Bug-Submit: https://github.com/netty/netty/issues/new
Repository-Browse: https://github.com/netty/netty
version=4
opts="repack,compression=xz" \
opts="repack, compression=xz, \
filenamemangle=s%.*/netty-([\d\.]+).Final%@PACKAGE@-$1%" \
https://github.com/netty/netty/tags .*/netty-([\d\.]+).Final.tar.gz
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment