You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by el...@apache.org on 2022/04/04 21:40:07 UTC
[mina-ftpserver] branch 1.1.X updated: o Declare 2 constants and use them o Applied Arturo Bernarl patch (PR 17) o Code refactoring o Exclude ftpserevr.properties from the packages
This is an automated email from the ASF dual-hosted git repository.
elecharny pushed a commit to branch 1.1.X
in repository https://gitbox.apache.org/repos/asf/mina-ftpserver.git
The following commit(s) were added to refs/heads/1.1.X by this push:
new c1a29e25 o Declare 2 constants and use them o Applied Arturo Bernarl patch (PR 17) o Code refactoring o Exclude ftpserevr.properties from the packages
c1a29e25 is described below
commit c1a29e25ab680127b32a410f4bd8ae169b29384a
Author: emmanuel lecharny <el...@apache.org>
AuthorDate: Mon Apr 4 23:38:44 2022 +0200
o Declare 2 constants and use them
o Applied Arturo Bernarl patch (PR 17)
o Code refactoring
o Exclude ftpserevr.properties from the packages
---
.../ftpserver/command/CommandFactoryFactory.java | 4 +-
.../org/apache/ftpserver/command/impl/MD5.java | 26 ++-
.../ftpserver/impl/IODataConnectionFactory.java | 237 +++++++++++----------
.../org/apache/ftpserver/util/EncryptUtils.java | 4 +-
4 files changed, 143 insertions(+), 128 deletions(-)
diff --git a/core/src/main/java/org/apache/ftpserver/command/CommandFactoryFactory.java b/core/src/main/java/org/apache/ftpserver/command/CommandFactoryFactory.java
index 0ac2d247..d2149110 100644
--- a/core/src/main/java/org/apache/ftpserver/command/CommandFactoryFactory.java
+++ b/core/src/main/java/org/apache/ftpserver/command/CommandFactoryFactory.java
@@ -99,9 +99,9 @@ public class CommandFactoryFactory {
DEFAULT_COMMAND_MAP.put("HELP", new HELP());
DEFAULT_COMMAND_MAP.put("LANG", new LANG());
DEFAULT_COMMAND_MAP.put("LIST", new LIST());
- DEFAULT_COMMAND_MAP.put("MD5", new MD5());
+ DEFAULT_COMMAND_MAP.put(MD5.MD5, new MD5());
DEFAULT_COMMAND_MAP.put("MFMT", new MFMT());
- DEFAULT_COMMAND_MAP.put("MMD5", new MD5());
+ DEFAULT_COMMAND_MAP.put(MD5.MMD5, new MD5());
DEFAULT_COMMAND_MAP.put("MDTM", new MDTM());
DEFAULT_COMMAND_MAP.put("MLST", new MLST());
DEFAULT_COMMAND_MAP.put("MKD", new MKD());
diff --git a/core/src/main/java/org/apache/ftpserver/command/impl/MD5.java b/core/src/main/java/org/apache/ftpserver/command/impl/MD5.java
index 881951a8..f98c5141 100644
--- a/core/src/main/java/org/apache/ftpserver/command/impl/MD5.java
+++ b/core/src/main/java/org/apache/ftpserver/command/impl/MD5.java
@@ -48,6 +48,11 @@ import org.slf4j.LoggerFactory;
* @author <a href="http://mina.apache.org">Apache MINA Project</a>
*/
public class MD5 extends AbstractCommand {
+ /** The MD5 String constant */
+ public static final String MD5 = "MD5";
+
+ /** The MMD5 String constant */
+ public static final String MMD5 = "MMD5";
private final Logger LOG = LoggerFactory.getLogger(MD5.class);
@@ -61,11 +66,7 @@ public class MD5 extends AbstractCommand {
// reset state variables
session.resetState();
- boolean isMMD5 = false;
-
- if ("MMD5".equals(request.getCommand())) {
- isMMD5 = true;
- }
+ boolean isMMD5 = MMD5.equals(request.getCommand());
// print file information
String argument = request.getArgument();
@@ -83,6 +84,7 @@ public class MD5 extends AbstractCommand {
}
String[] fileNames = null;
+
if (isMMD5) {
fileNames = argument.split(",");
} else {
@@ -90,6 +92,7 @@ public class MD5 extends AbstractCommand {
}
StringBuilder sb = new StringBuilder();
+
for (int i = 0; i < fileNames.length; i++) {
String fileName = fileNames[i].trim();
@@ -128,6 +131,7 @@ public class MD5 extends AbstractCommand {
}
InputStream is = null;
+
try {
is = file.createInputStream(0);
String md5Hash = md5(is);
@@ -135,14 +139,19 @@ public class MD5 extends AbstractCommand {
if (i > 0) {
sb.append(", ");
}
+
boolean nameHasSpaces = fileName.indexOf(' ') >= 0;
+
if(nameHasSpaces) {
sb.append('"');
}
+
sb.append(fileName);
+
if(nameHasSpaces) {
sb.append('"');
}
+
sb.append(' ');
sb.append(md5Hash);
@@ -157,10 +166,10 @@ public class MD5 extends AbstractCommand {
}
if (isMMD5) {
session.write(LocalizedFtpReply.translate(session, request, context,
- 252, "MMD5", sb.toString()));
+ 252, MMD5, sb.toString()));
} else {
session.write(LocalizedFtpReply.translate(session, request, context,
- 251, "MD5", sb.toString()));
+ 251, MD5, sb.toString()));
}
}
@@ -173,12 +182,13 @@ public class MD5 extends AbstractCommand {
*/
private String md5(InputStream is) throws IOException,
NoSuchAlgorithmException {
- MessageDigest digest = MessageDigest.getInstance("MD5");
+ MessageDigest digest = MessageDigest.getInstance(MD5);
DigestInputStream dis = new DigestInputStream(is, digest);
byte[] buffer = new byte[1024];
int read = dis.read(buffer);
+
while (read > -1) {
read = dis.read(buffer);
}
diff --git a/core/src/main/java/org/apache/ftpserver/impl/IODataConnectionFactory.java b/core/src/main/java/org/apache/ftpserver/impl/IODataConnectionFactory.java
index ba86514d..42b97454 100644
--- a/core/src/main/java/org/apache/ftpserver/impl/IODataConnectionFactory.java
+++ b/core/src/main/java/org/apache/ftpserver/impl/IODataConnectionFactory.java
@@ -74,6 +74,7 @@ public class IODataConnectionFactory implements ServerDataConnectionFactory {
public IODataConnectionFactory(final FtpServerContext serverContext, final FtpIoSession session) {
this.session = session;
this.serverContext = serverContext;
+
if ((session != null) && (session.getListener() != null) && session.getListener().getDataConnectionConfiguration().isImplicitSsl()) {
secure = true;
}
@@ -83,37 +84,37 @@ public class IODataConnectionFactory implements ServerDataConnectionFactory {
* Close data socket. This method must be idempotent as we might call it multiple times during disconnect.
*/
public synchronized void closeDataConnection() {
-
- // close client socket if any
- if (dataSoc != null) {
- try {
- dataSoc.close();
- } catch (Exception ex) {
- LOG.warn("FtpDataConnection.closeDataSocket()", ex);
- }
- dataSoc = null;
- }
-
- // close server socket if any
- if (servSoc != null) {
- try {
- servSoc.close();
- } catch (Exception ex) {
- LOG.warn("FtpDataConnection.closeDataSocket()", ex);
+ // close client socket if any
+ if (dataSoc != null) {
+ try {
+ dataSoc.close();
+ } catch (Exception ex) {
+ LOG.warn("FtpDataConnection.closeDataSocket()", ex);
+ }
+ dataSoc = null;
}
+
+ // close server socket if any
+ if (servSoc != null) {
+ try {
+ servSoc.close();
+ } catch (Exception ex) {
+ LOG.warn("FtpDataConnection.closeDataSocket()", ex);
+ }
+
+ if (session != null) {
+ DataConnectionConfiguration dcc = session.getListener().getDataConnectionConfiguration();
- if (session != null) {
- DataConnectionConfiguration dcc = session.getListener().getDataConnectionConfiguration();
- if (dcc != null) {
- dcc.releasePassivePort(port);
- }
+ if (dcc != null) {
+ dcc.releasePassivePort(port);
+ }
+ }
+
+ servSoc = null;
}
-
- servSoc = null;
- }
-
- // reset request time
- requestTime = 0L;
+
+ // reset request time
+ requestTime = 0L;
}
/**
@@ -128,9 +129,9 @@ public class IODataConnectionFactory implements ServerDataConnectionFactory {
this.address = address.getAddress();
port = address.getPort();
requestTime = System.currentTimeMillis();
- }
+ }
- private SslConfiguration getSslConfiguration() {
+ private SslConfiguration getSslConfiguration() {
DataConnectionConfiguration dataCfg = session.getListener().getDataConnectionConfiguration();
SslConfiguration configuration = dataCfg.getSslConfiguration();
@@ -153,6 +154,7 @@ public class IODataConnectionFactory implements ServerDataConnectionFactory {
// get the passive port
int passivePort = session.getListener().getDataConnectionConfiguration().requestPassivePort();
+
if (passivePort == -1) {
servSoc = null;
throw new DataConnectionException("Cannot find an available passive port.");
@@ -200,6 +202,7 @@ public class IODataConnectionFactory implements ServerDataConnectionFactory {
return new InetSocketAddress(address, port);
} catch (Exception ex) {
closeDataConnection();
+
throw new DataConnectionException("Failed to initate passive data connection: " + ex.getMessage(), ex);
}
}
@@ -238,6 +241,7 @@ public class IODataConnectionFactory implements ServerDataConnectionFactory {
// get socket depending on the selection
dataSoc = null;
DataConnectionConfiguration dataConfig = session.getListener().getDataConnectionConfiguration();
+
try {
if (!passive) {
if (secure) {
@@ -286,71 +290,74 @@ public class IODataConnectionFactory implements ServerDataConnectionFactory {
dataSoc.connect(new InetSocketAddress(address, port));
} else {
-
- if (secure) {
- LOG.debug("Opening secure passive data connection");
- // this is where we wrap the unsecured socket as a SSLSocket. This is
- // due to the JVM bug described in FTPSERVER-241.
-
- // get server socket factory
- SslConfiguration ssl = getSslConfiguration();
-
- // we've already checked this, but let's do it again
- if (ssl == null) {
- throw new FtpException("Data connection SSL not configured");
- }
-
- SSLSocketFactory ssocketFactory = ssl.getSocketFactory();
-
- Socket serverSocket = servSoc.accept();
-
- SSLSocket sslSocket = (SSLSocket) ssocketFactory.createSocket(serverSocket, serverSocket.getInetAddress().getHostAddress(), serverSocket.getPort(), true);
- sslSocket.setUseClientMode(false);
-
- // initialize server socket
- if (ssl.getClientAuth() == ClientAuth.NEED) {
- sslSocket.setNeedClientAuth(true);
- } else if (ssl.getClientAuth() == ClientAuth.WANT) {
- sslSocket.setWantClientAuth(true);
- }
-
- if (ssl.getEnabledCipherSuites() != null) {
- sslSocket.setEnabledCipherSuites(ssl.getEnabledCipherSuites());
- }
-
- if (ssl.getEnabledProtocol() != null) {
- sslSocket.setEnabledProtocols(new String[] {ssl.getEnabledProtocol()});
+ if (secure) {
+ LOG.debug("Opening secure passive data connection");
+ // this is where we wrap the unsecured socket as a SSLSocket. This is
+ // due to the JVM bug described in FTPSERVER-241.
+
+ // get server socket factory
+ SslConfiguration ssl = getSslConfiguration();
+
+ // we've already checked this, but let's do it again
+ if (ssl == null) {
+ throw new FtpException("Data connection SSL not configured");
+ }
+
+ SSLSocketFactory ssocketFactory = ssl.getSocketFactory();
+
+ Socket serverSocket = servSoc.accept();
+
+ SSLSocket sslSocket = (SSLSocket) ssocketFactory.createSocket(serverSocket, serverSocket.getInetAddress().getHostAddress(), serverSocket.getPort(), true);
+ sslSocket.setUseClientMode(false);
+
+ // initialize server socket
+ if (ssl.getClientAuth() == ClientAuth.NEED) {
+ sslSocket.setNeedClientAuth(true);
+ } else if (ssl.getClientAuth() == ClientAuth.WANT) {
+ sslSocket.setWantClientAuth(true);
+ }
+
+ if (ssl.getEnabledCipherSuites() != null) {
+ sslSocket.setEnabledCipherSuites(ssl.getEnabledCipherSuites());
+ }
+
+ if (ssl.getEnabledProtocol() != null) {
+ sslSocket.setEnabledProtocols(new String[] {ssl.getEnabledProtocol()});
+ }
+
+ dataSoc = sslSocket;
+ } else {
+ LOG.debug("Opening passive data connection");
+
+ dataSoc = servSoc.accept();
}
-
- dataSoc = sslSocket;
- } else {
- LOG.debug("Opening passive data connection");
-
- dataSoc = servSoc.accept();
- }
-
- if (dataConfig.isPassiveIpCheck()) {
- // Let's make sure we got the connection from the same
- // client that we are expecting
- InetAddress remoteAddress = ((InetSocketAddress) session.getRemoteAddress()).getAddress();
- InetAddress dataSocketAddress = dataSoc.getInetAddress();
- if (!dataSocketAddress.equals(remoteAddress)) {
- LOG.warn("Passive IP Check failed. Closing data connection from " + dataSocketAddress + " as it does not match the expected address " + remoteAddress);
- closeDataConnection();
- return null;
+
+ if (dataConfig.isPassiveIpCheck()) {
+ // Let's make sure we got the connection from the same
+ // client that we are expecting
+ InetAddress remoteAddress = ((InetSocketAddress) session.getRemoteAddress()).getAddress();
+ InetAddress dataSocketAddress = dataSoc.getInetAddress();
+
+ if (!dataSocketAddress.equals(remoteAddress)) {
+ LOG.warn("Passive IP Check failed. Closing data connection from " + dataSocketAddress + " as it does not match the expected address " + remoteAddress);
+ closeDataConnection();
+
+ return null;
+ }
}
- }
-
- DataConnectionConfiguration dataCfg = session.getListener().getDataConnectionConfiguration();
-
- dataSoc.setSoTimeout(dataCfg.getIdleTime() * 1000);
- LOG.debug("Passive data connection opened");
+
+ DataConnectionConfiguration dataCfg = session.getListener().getDataConnectionConfiguration();
+
+ dataSoc.setSoTimeout(dataCfg.getIdleTime() * 1000);
+ LOG.debug("Passive data connection opened");
}
} catch (Exception ex) {
closeDataConnection();
LOG.warn("FtpDataConnection.getDataSocket()", ex);
+
throw ex;
}
+
dataSoc.setSoTimeout(dataConfig.getIdleTime() * 1000);
// Make sure we initiate the SSL handshake, or we'll
@@ -371,9 +378,9 @@ public class IODataConnectionFactory implements ServerDataConnectionFactory {
return null;
} else {
try {
- return InetAddress.getByName(host);
+ return InetAddress.getByName(host);
} catch (UnknownHostException ex) {
- throw new DataConnectionException("Failed to resolve address", ex);
+ throw new DataConnectionException("Failed to resolve address", ex);
}
}
}
@@ -384,14 +391,14 @@ public class IODataConnectionFactory implements ServerDataConnectionFactory {
* @see org.apache.ftpserver.DataConnectionFactory#isSecure()
*/
public boolean isSecure() {
- return secure;
+ return secure;
}
/**
* Set the security protocol.
*/
public void setSecure(final boolean secure) {
- this.secure = secure;
+ this.secure = secure;
}
/*
@@ -400,56 +407,52 @@ public class IODataConnectionFactory implements ServerDataConnectionFactory {
* @see org.apache.ftpserver.DataConnectionFactory#isZipMode()
*/
public boolean isZipMode() {
- return isZip;
+ return isZip;
}
/**
* Set zip mode.
*/
public void setZipMode(final boolean zip) {
- isZip = zip;
+ isZip = zip;
}
/**
* Check the data connection idle status.
*/
public synchronized boolean isTimeout(final long currTime) {
+ // data connection not requested - not a timeout
+ if (requestTime == 0L) {
+ return false;
+ }
+
+ // data connection active - not a timeout
+ if (dataSoc != null) {
+ return false;
+ }
+
+ // no idle time limit - not a timeout
+ int maxIdleTime = session.getListener().getDataConnectionConfiguration().getIdleTime() * 1000;
- // data connection not requested - not a timeout
- if (requestTime == 0L) {
- return false;
- }
-
- // data connection active - not a timeout
- if (dataSoc != null) {
- return false;
- }
-
- // no idle time limit - not a timeout
- int maxIdleTime = session.getListener().getDataConnectionConfiguration().getIdleTime() * 1000;
- if (maxIdleTime == 0) {
- return false;
- }
-
- // idle time is within limit - not a timeout
- if ((currTime - requestTime) < maxIdleTime) {
- return false;
- }
-
- return true;
+ if (maxIdleTime == 0) {
+ return false;
+ }
+
+ // idle time is within limit - not a timeout
+ return ((currTime - requestTime) >= maxIdleTime);
}
/**
* Dispose data connection - close all the sockets.
*/
public void dispose() {
- closeDataConnection();
+ closeDataConnection();
}
/**
* Sets the server's control address.
*/
public void setServerControlAddress(final InetAddress serverControlAddress) {
- this.serverControlAddress = serverControlAddress;
+ this.serverControlAddress = serverControlAddress;
}
}
diff --git a/core/src/main/java/org/apache/ftpserver/util/EncryptUtils.java b/core/src/main/java/org/apache/ftpserver/util/EncryptUtils.java
index 77077262..04be9fe5 100644
--- a/core/src/main/java/org/apache/ftpserver/util/EncryptUtils.java
+++ b/core/src/main/java/org/apache/ftpserver/util/EncryptUtils.java
@@ -22,6 +22,8 @@ package org.apache.ftpserver.util;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
+import org.apache.ftpserver.command.impl.MD5;
+
/**
* <strong>Internal class, do not use directly.</strong>
*
@@ -61,7 +63,7 @@ public class EncryptUtils {
String result = "";
try {
- result = encrypt(source, "MD5");
+ result = encrypt(source, MD5.MD5);
} catch (NoSuchAlgorithmException ex) {
// this should never happen
throw new RuntimeException(ex);