Fix CVE-2021-37533
(cherry picked from commit 47e04e34f6d14431a9ce1881a6dee8035ff3839a)
This commit is contained in:
parent
d60f3b962d
commit
c06e35a9b8
241
CVE-2021-37533.patch
Normal file
241
CVE-2021-37533.patch
Normal file
@ -0,0 +1,241 @@
|
||||
From: Markus Koschany <apo@debian.org>
|
||||
Date: Wed, 28 Dec 2022 13:36:54 +0100
|
||||
Subject: CVE-2021-37533
|
||||
|
||||
Bug-Debian: https://bugs.debian.org/1025910
|
||||
Origin: https://github.com/apache/commons-net/commit/b0bff89f70cfea70009e22f87639816cc3993974
|
||||
---
|
||||
.../java/org/apache/commons/net/ftp/FTPClient.java | 91 ++++++++++++++++++----
|
||||
.../org/apache/commons/net/ftp/FTPClientTest.java | 41 +++++++---
|
||||
2 files changed, 106 insertions(+), 26 deletions(-)
|
||||
|
||||
diff --git a/src/main/java/org/apache/commons/net/ftp/FTPClient.java b/src/main/java/org/apache/commons/net/ftp/FTPClient.java
|
||||
index bec47d1..16d969b 100644
|
||||
--- a/src/main/java/org/apache/commons/net/ftp/FTPClient.java
|
||||
+++ b/src/main/java/org/apache/commons/net/ftp/FTPClient.java
|
||||
@@ -307,6 +307,18 @@ implements Configurable
|
||||
*/
|
||||
public static final String FTP_SYSTEM_TYPE_DEFAULT = "org.apache.commons.net.ftp.systemType.default";
|
||||
|
||||
+ /**
|
||||
+ * The system property that defines the default for {@link #isIpAddressFromPasvResponse()}. This property, if present, configures the default for the
|
||||
+ * following: If the client receives the servers response for a PASV request, then that response will contain an IP address. If this property is true, then
|
||||
+ * the client will use that IP address, as requested by the server. This is compatible to version {@code 3.8.0}, and before. If this property is false, or
|
||||
+ * absent, then the client will ignore that IP address, and instead use the remote address of the control connection.
|
||||
+ *
|
||||
+ * @see #isIpAddressFromPasvResponse()
|
||||
+ * @see #setIpAddressFromPasvResponse(boolean)
|
||||
+ * @since 3.9.0
|
||||
+ */
|
||||
+ public static final String FTP_IP_ADDRESS_FROM_PASV_RESPONSE = "org.apache.commons.net.ftp.ipAddressFromPasvResponse";
|
||||
+
|
||||
/**
|
||||
* The name of an optional systemType properties file ({@value}), which is loaded
|
||||
* using {@link Class#getResourceAsStream(String)}.<br>
|
||||
@@ -506,6 +518,8 @@ implements Configurable
|
||||
__featuresMap = null;
|
||||
}
|
||||
|
||||
+ private boolean ipAddressFromPasvResponse = Boolean.parseBoolean(System.getProperty(FTPClient.FTP_IP_ADDRESS_FROM_PASV_RESPONSE));
|
||||
+
|
||||
/**
|
||||
* Parse the pathname from a CWD reply.
|
||||
* <p>
|
||||
@@ -565,37 +579,43 @@ implements Configurable
|
||||
{
|
||||
java.util.regex.Matcher m = __PARMS_PAT.matcher(reply);
|
||||
if (!m.find()) {
|
||||
- throw new MalformedServerReplyException(
|
||||
- "Could not parse passive host information.\nServer Reply: " + reply);
|
||||
+ throw new MalformedServerReplyException("Could not parse passive host information.\nServer Reply: " + reply);
|
||||
}
|
||||
|
||||
- __passiveHost = m.group(1).replace(',', '.'); // Fix up to look like IP address
|
||||
+ int pasvPort;
|
||||
+ // Fix up to look like IP address
|
||||
+ String pasvHost = "0,0,0,0".equals(m.group(1)) ? _socket_.getInetAddress().getHostAddress() : m.group(1).replace(',', '.');
|
||||
|
||||
try
|
||||
{
|
||||
int oct1 = Integer.parseInt(m.group(2));
|
||||
int oct2 = Integer.parseInt(m.group(3));
|
||||
- __passivePort = (oct1 << 8) | oct2;
|
||||
+ pasvPort = (oct1 << 8) | oct2;
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
- throw new MalformedServerReplyException(
|
||||
- "Could not parse passive port information.\nServer Reply: " + reply);
|
||||
+ throw new MalformedServerReplyException("Could not parse passive port information.\nServer Reply: " + reply);
|
||||
}
|
||||
-
|
||||
- if (__passiveNatWorkaroundStrategy != null) {
|
||||
- try {
|
||||
- String passiveHost = __passiveNatWorkaroundStrategy.resolve(__passiveHost);
|
||||
- if (!__passiveHost.equals(passiveHost)) {
|
||||
- fireReplyReceived(0,
|
||||
- "[Replacing PASV mode reply address "+__passiveHost+" with "+passiveHost+"]\n");
|
||||
- __passiveHost = passiveHost;
|
||||
+ if (isIpAddressFromPasvResponse()) {
|
||||
+ // Pre-3.9.0 behavior
|
||||
+ if (__passiveNatWorkaroundStrategy != null) {
|
||||
+ try {
|
||||
+ final String newPassiveHost = __passiveNatWorkaroundStrategy.resolve(pasvHost);
|
||||
+ if (!pasvHost.equals(newPassiveHost)) {
|
||||
+ fireReplyReceived(0, "[Replacing PASV mode reply address " + __passiveHost + " with " + newPassiveHost + "]\n");
|
||||
+ pasvHost = newPassiveHost;
|
||||
+ }
|
||||
+ } catch (final UnknownHostException e) { // Should not happen as we are passing in an IP address
|
||||
+ throw new MalformedServerReplyException("Could not parse passive host information.\nServer Reply: " + reply);
|
||||
}
|
||||
- } catch (UnknownHostException e) { // Should not happen as we are passing in an IP address
|
||||
- throw new MalformedServerReplyException(
|
||||
- "Could not parse passive host information.\nServer Reply: " + reply);
|
||||
}
|
||||
+ } else if (_socket_ == null) {
|
||||
+ pasvHost = null; // For unit testing.
|
||||
+ } else {
|
||||
+ pasvHost = _socket_.getInetAddress().getHostAddress();
|
||||
}
|
||||
+ __passiveHost = pasvHost;
|
||||
+ __passivePort = pasvPort;
|
||||
}
|
||||
|
||||
protected void _parseExtendedPassiveModeReply(String reply)
|
||||
@@ -3968,6 +3988,43 @@ implements Configurable
|
||||
}
|
||||
return __systemName;
|
||||
}
|
||||
+
|
||||
+ /**
|
||||
+ * Returns, whether the IP address from the server's response should be used.
|
||||
+ * Until 3.9.0, this has always been the case. Beginning with 3.9.0,
|
||||
+ * that IP address will be silently ignored, and replaced with the remote
|
||||
+ * IP address of the control connection, unless this configuration option is
|
||||
+ * given, which restores the old behavior. To enable this by default, use
|
||||
+ * the system property {@link FTPClient#FTP_IP_ADDRESS_FROM_PASV_RESPONSE}.
|
||||
+ * @return True, if the IP address from the server's response will be used
|
||||
+ * (pre-3.9 compatible behavior), or false (ignore that IP address).
|
||||
+ *
|
||||
+ * @see FTPClient#FTP_IP_ADDRESS_FROM_PASV_RESPONSE
|
||||
+ * @see #setIpAddressFromPasvResponse(boolean)
|
||||
+ * @since 3.9.0
|
||||
+ */
|
||||
+ public boolean isIpAddressFromPasvResponse() {
|
||||
+ return ipAddressFromPasvResponse;
|
||||
+ }
|
||||
+
|
||||
+ /**
|
||||
+ * Sets whether the IP address from the server's response should be used.
|
||||
+ * Until 3.9.0, this has always been the case. Beginning with 3.9.0,
|
||||
+ * that IP address will be silently ignored, and replaced with the remote
|
||||
+ * IP address of the control connection, unless this configuration option is
|
||||
+ * given, which restores the old behavior. To enable this by default, use
|
||||
+ * the system property {@link FTPClient#FTP_IP_ADDRESS_FROM_PASV_RESPONSE}.
|
||||
+ *
|
||||
+ * @param usingIpAddressFromPasvResponse True, if the IP address from the
|
||||
+ * server's response should be used (pre-3.9.0 compatible behavior), or
|
||||
+ * false (ignore that IP address).
|
||||
+ * @see FTPClient#FTP_IP_ADDRESS_FROM_PASV_RESPONSE
|
||||
+ * @see #isIpAddressFromPasvResponse
|
||||
+ * @since 3.9.0
|
||||
+ */
|
||||
+ public void setIpAddressFromPasvResponse(boolean usingIpAddressFromPasvResponse) {
|
||||
+ this.ipAddressFromPasvResponse = usingIpAddressFromPasvResponse;
|
||||
+ }
|
||||
}
|
||||
|
||||
/* Emacs configuration
|
||||
diff --git a/src/test/java/org/apache/commons/net/ftp/FTPClientTest.java b/src/test/java/org/apache/commons/net/ftp/FTPClientTest.java
|
||||
index e43f075..faac5bd 100644
|
||||
--- a/src/test/java/org/apache/commons/net/ftp/FTPClientTest.java
|
||||
+++ b/src/test/java/org/apache/commons/net/ftp/FTPClientTest.java
|
||||
@@ -147,56 +147,79 @@ public class FTPClientTest extends TestCase {
|
||||
|
||||
public void testParsePassiveModeReplyForLocalAddressWithNatWorkaround() throws Exception {
|
||||
FTPClient client = new PassiveNatWorkAroundLocalClient("8.8.8.8");
|
||||
+ client.setIpAddressFromPasvResponse(true);
|
||||
client._parsePassiveModeReply("227 Entering Passive Mode (172,16,204,138,192,22).");
|
||||
assertEquals("8.8.8.8", client.getPassiveHost());
|
||||
+ client.setIpAddressFromPasvResponse(false);
|
||||
+ client._parsePassiveModeReply("227 Entering Passive Mode (172,16,204,138,192,22).");
|
||||
+ assertNull(client.getPassiveHost());
|
||||
}
|
||||
|
||||
public void testParsePassiveModeReplyForNonLocalAddressWithNatWorkaround() throws Exception {
|
||||
FTPClient client = new PassiveNatWorkAroundLocalClient("8.8.8.8");
|
||||
+ client.setIpAddressFromPasvResponse(true);
|
||||
client._parsePassiveModeReply("227 Entering Passive Mode (8,8,4,4,192,22).");
|
||||
assertEquals("8.8.4.4", client.getPassiveHost());
|
||||
+ client.setIpAddressFromPasvResponse(false);
|
||||
+ client._parsePassiveModeReply("227 Entering Passive Mode (8,8,4,4,192,22).");
|
||||
+ assertNull(client.getPassiveHost());
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation") // testing deprecated code
|
||||
public void testParsePassiveModeReplyForLocalAddressWithNatWorkaroundDisabled() throws Exception {
|
||||
FTPClient client = new PassiveNatWorkAroundLocalClient("8.8.8.8");
|
||||
client.setPassiveNatWorkaround(false);
|
||||
+ client.setIpAddressFromPasvResponse(true);
|
||||
client._parsePassiveModeReply("227 Entering Passive Mode (172,16,204,138,192,22).");
|
||||
assertEquals("172.16.204.138", client.getPassiveHost());
|
||||
+ client.setIpAddressFromPasvResponse(false);
|
||||
+ client._parsePassiveModeReply("227 Entering Passive Mode (172,16,204,138,192,22).");
|
||||
+ assertNull(client.getPassiveHost());
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation") // testing deprecated code
|
||||
public void testParsePassiveModeReplyForNonLocalAddressWithNatWorkaroundDisabled() throws Exception {
|
||||
FTPClient client = new PassiveNatWorkAroundLocalClient("8.8.8.8");
|
||||
+ client.setIpAddressFromPasvResponse(true);
|
||||
client.setPassiveNatWorkaround(false);
|
||||
client._parsePassiveModeReply("227 Entering Passive Mode (8,8,4,4,192,22).");
|
||||
assertEquals("8.8.4.4", client.getPassiveHost());
|
||||
+ client.setIpAddressFromPasvResponse(false);
|
||||
+ client._parsePassiveModeReply("227 Entering Passive Mode (8,8,4,4,192,22).");
|
||||
+ assertNull(client.getPassiveHost());
|
||||
}
|
||||
|
||||
public void testParsePassiveModeReplyForLocalAddressWithoutNatWorkaroundStrategy() throws Exception {
|
||||
FTPClient client = new PassiveNatWorkAroundLocalClient("8.8.8.8");
|
||||
client.setPassiveNatWorkaroundStrategy(null);
|
||||
+ client.setIpAddressFromPasvResponse(true);
|
||||
client._parsePassiveModeReply("227 Entering Passive Mode (172,16,204,138,192,22).");
|
||||
assertEquals("172.16.204.138", client.getPassiveHost());
|
||||
+ client.setIpAddressFromPasvResponse(false);
|
||||
+ client._parsePassiveModeReply("227 Entering Passive Mode (172,16,204,138,192,22).");
|
||||
+ assertNull(client.getPassiveHost());
|
||||
}
|
||||
|
||||
public void testParsePassiveModeReplyForNonLocalAddressWithoutNatWorkaroundStrategy() throws Exception {
|
||||
FTPClient client = new PassiveNatWorkAroundLocalClient("8.8.8.8");
|
||||
+ client.setIpAddressFromPasvResponse(true);
|
||||
client.setPassiveNatWorkaroundStrategy(null);
|
||||
client._parsePassiveModeReply("227 Entering Passive Mode (8,8,4,4,192,22).");
|
||||
assertEquals("8.8.4.4", client.getPassiveHost());
|
||||
+ client.setIpAddressFromPasvResponse(false);
|
||||
+ client._parsePassiveModeReply("227 Entering Passive Mode (8,8,4,4,192,22).");
|
||||
+ assertNull(client.getPassiveHost());
|
||||
}
|
||||
|
||||
public void testParsePassiveModeReplyForLocalAddressWithSimpleNatWorkaroundStrategy() throws Exception {
|
||||
- FTPClient client = new PassiveNatWorkAroundLocalClient("8.8.8.8");
|
||||
- client.setPassiveNatWorkaroundStrategy(new FTPClient.HostnameResolver() {
|
||||
- @Override
|
||||
- public String resolve(String hostname) throws UnknownHostException {
|
||||
- return "4.4.4.4";
|
||||
- }
|
||||
-
|
||||
- });
|
||||
+ final FTPClient client = new PassiveNatWorkAroundLocalClient("8.8.8.8");
|
||||
+ client.setPassiveNatWorkaroundStrategy(hostname -> "4.4.4.4");
|
||||
+ client.setIpAddressFromPasvResponse(true);
|
||||
client._parsePassiveModeReply("227 Entering Passive Mode (172,16,204,138,192,22).");
|
||||
assertEquals("4.4.4.4", client.getPassiveHost());
|
||||
+ client.setIpAddressFromPasvResponse(false);
|
||||
+ client._parsePassiveModeReply("227 Entering Passive Mode (172,16,204,138,192,22).");
|
||||
+ assertNull(client.getPassiveHost());
|
||||
}
|
||||
- }
|
||||
+
|
||||
+}
|
||||
@ -1,10 +1,12 @@
|
||||
Name: apache-commons-net
|
||||
Version: 3.6
|
||||
Release: 6
|
||||
Release: 7
|
||||
Summary: Java library for Internet protocol
|
||||
License: ASL 2.0
|
||||
URL: http://commons.apache.org/net/
|
||||
Source0: http://archive.apache.org/dist/commons/net/source/commons-net-3.6-src.tar.gz
|
||||
# https://github.com/apache/commons-net/commit/b0bff89f70cfea70009e22f87639816cc3993974
|
||||
Patch0: CVE-2021-37533.patch
|
||||
BuildArch: noarch
|
||||
|
||||
BuildRequires: maven-local mvn(junit:junit) mvn(org.apache.commons:commons-parent:pom:)
|
||||
@ -35,7 +37,7 @@ rm src/test/java/org/apache/commons/net/ftp/TestConnectTimeout.java
|
||||
%mvn_alias : org.apache.commons:commons-net
|
||||
|
||||
%build
|
||||
%mvn_build
|
||||
%mvn_build -- -Dmaven.compiler.source=1.8 -Dmaven.compiler.target=1.8
|
||||
|
||||
%install
|
||||
%mvn_install
|
||||
@ -47,6 +49,9 @@ rm src/test/java/org/apache/commons/net/ftp/TestConnectTimeout.java
|
||||
%doc README.md RELEASE-NOTES.txt
|
||||
|
||||
%changelog
|
||||
* Thu Nov 23 2023 yaoxin <yao_xin001@hoperun.com> - 3.6-7
|
||||
- Fix CVE-2021-37533
|
||||
|
||||
* Mon Jun 05 2023 wangkai <13474090681@163.com> - 3.6-6
|
||||
- Remove TestConnectTimeout for ftp
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user