Hello,
I have the FTPServer class listed below.
This worked fine under the following environment:
- Java 11
- ftplet-api 1.1.0
- ftpserver-core 1.1.0
- mina-core 2.1.4
After I upgraded my application to the following environment:
- Java 17
- ftplet-api 1.2.0
- ftpserver-core 1.2.0
- mina-core 2.2.3
I got the following "Unsupported protocolTLS" error when trying to make an FTP
connection:
o.a.m.u.DefaultExceptionMonitor: S:- {"message":"Unexpected
exception.","exception":"java.lang.IllegalArgumentException: Unsupported
protocolTLS\n\tat
java.base/sun.security.ssl.ProtocolVersion.namesOf(ProtocolVersion.java:292)\n\tat
java.base/sun.security.ssl.SSLEngineImpl.setEnabledProtocols(SSLEngineImpl.java:896)\n\tat
org.apache.mina.filter.ssl.SslFilter.createEngine(SslFilter.java:334)\n\tat
org.apache.mina.filter.ssl.SslFilter.onConnected(SslFilter.java:278)\n\tat
org.apache.mina.filter.ssl.SslFilter.onPostAdd(SslFilter.java:250)\n\tat
org.apache.mina.core.filterchain.DefaultIoFilterChain.register(DefaultIoFilterChain.java:473)\n\t...
9 common frames omitted\nWrapped by:
org.apache.mina.core.filterchain.IoFilterLifeCycleException: onPostAdd():
sslFilter:SslFilter in (0x0000000A: nio socket, server,
192.168.76.1/192.168.76.1:20461 => /192.168.76.79:2121)\n\tat
org.apache.mina.core.filterchain.DefaultIoFilterChain.register(DefaultIoFilterChain.java:476)\n\tat
org.apache.mina.core.filterchain.DefaultIoFilterChain.addLast(DefaultIoFilterChain.java:234)\n\tat
org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder.buildFilterChain(DefaultIoFilterChainBuilder.java:553)\n\tat
org.apache.mina.core.polling.AbstractPollingIoProcessor$Processor.addNow(AbstractPollingIoProcessor.java:832)\n\tat
org.apache.mina.core.polling.AbstractPollingIoProcessor$Processor.handleNewSessions(AbstractPollingIoProcessor.java:752)\n\tat
org.apache.mina.core.polling.AbstractPollingIoProcessor$Processor.run(AbstractPollingIoProcessor.java:652)\n\tat
org.apache.mina.util.NamePreservingRunnable.run(NamePreservingRunnable.java:64)\n\tat
java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)\n\tat
java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)\n\tat
java.base/java.lang.Thread.run(Thread.java:840)\n"}
The release notes for ftpserver and mina do mention some changes around TLS,
but I am not sure if/how those would affect my application below:
https://mina.apache.org/ftpserver-project/download_1_2.html
https://mina.apache.org/mina-project/2.2-vs-2.1.html
Any help is much appreciated!
Mant thanks
import org.apache.ftpserver.DataConnectionConfigurationFactory;
import org.apache.ftpserver.FtpServer;
import org.apache.ftpserver.FtpServerFactory;
import org.apache.ftpserver.command.CommandFactory;
import org.apache.ftpserver.command.CommandFactoryFactory;
import org.apache.ftpserver.listener.ListenerFactory;
import org.apache.ftpserver.ssl.SslConfiguration;
import org.apache.ftpserver.ssl.SslConfigurationFactory;
import org.glassfish.jersey.client.JerseyClientBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jakarta.ws.rs.client.Client;
import java.io.File;
import java.nio.file.FileSystems;
import java.util.LinkedList;
import java.util.List;
public class FTPServer {
public static FTPConfiguration ftpConfiguration = null;
private static Logger logger = LoggerFactory.getLogger(FTPServer.class);
private static String[] safeDefaultCipherSuitesList =
{"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256","TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384","TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
"TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
"TLS_DHE_RSA_WITH_AES_256_GCM_SHA384"};
private FtpServer server = null;
private FtpLetImpl ftpLet = null;
public FTPServer(final FTPConfiguration ftpConfiguration) {
this.ftpConfiguration = ftpConfiguration;
}
public boolean isServerRunning() {
boolean bResult = false;
if ((!server.isStopped()) && ((ftpLet == null) ||
(!ftpLet.ShutdownServer()))) {
bResult = true;
}
return bResult;
}
public boolean stopServer() {
if (ftpLet.ShutdownServer()) {
try {
logger.info("Finished FTPlet task. Stopping server.");
ftpLet.closeIDMAdminSession();
server.stop();
return true;
} catch (Exception e) {
logger.error("Failed to STOP FTP server. Exception: ", e);
}
}
return false;
}
public boolean launchFtpServer() {
boolean bResult;
try {
DataConnectionConfigurationFactory configurationFactory = new
DataConnectionConfigurationFactory();
setActiveMode(configurationFactory);
configurationFactory.setImplicitSsl(ftpConfiguration.getSslConfig().isImplicitSslEnabled());
configurationFactory.setPassiveExternalAddress(ftpConfiguration.getPassiveExternalAddress());
configurationFactory.setPassivePorts(ftpConfiguration.getPassivePortRange());
ListenerFactory listenerFactory = new ListenerFactory();
if (ftpConfiguration.getSslConfig().isImplicitSslEnabled()) {
SslConfiguration sslConfiguration = getSslConfiguration();
if (null != sslConfiguration) {
listenerFactory.setSslConfiguration(sslConfiguration);
listenerFactory.setImplicitSsl(true);
}
}
listenerFactory.setPort(ftpConfiguration.getFtpPort());
listenerFactory.setIdleTimeout(ftpConfiguration.getTimeout());
listenerFactory.setDataConnectionConfiguration(configurationFactory.createDataConnectionConfiguration());
FtpServerFactory serverFactory = new FtpServerFactory();
serverFactory.addListener("default",
listenerFactory.createListener());
FTPFileSystemFactory ftpFS = new FTPFileSystemFactory(true);
ftpLet = new FtpLetImpl();
serverFactory.getFtplets().put(FtpLetImpl.class.getName(), ftpLet);
serverFactory.setCommandFactory(getCommandFactory());
serverFactory.setConnectionConfig(new FTPConnectionConfig(false,
500, 10, 10, 3, 0));
AuditChannel auditChannel = null;
if (ftpConfiguration.isAuditingEnabled()) {
auditChannel = new
FtpAuditEventConfiguration().createAuditChannel();
}
FTPUserManagerFactory ftpUserMgrFactory = new
FTPUserManagerFactory(auditChannel);
serverFactory.setUserManager(ftpUserMgrFactory);
ftpLet.setUserManagerFactory(ftpUserMgrFactory);
serverFactory.setFileSystem(ftpFS);
server = serverFactory.createServer();
logger.debug("FTP server starting...");
server.start();
bResult = true;
} catch (Exception e) {
bResult = false;
String msg = e.getMessage();
logger.error("Exception while starting the FTP server: {}", msg);
}
return bResult;
}
private void setActiveMode(DataConnectionConfigurationFactory connfactory) {
if (ftpConfiguration.getActivePort() == 0) {
connfactory.setActiveEnabled(false);
logger.debug("Active connections have been disabled.");
} else {
connfactory.setActiveEnabled(true);
connfactory.setActiveLocalPort(ftpConfiguration.getActivePort());
logger.debug("Active connections are enabled.");
}
}
private CommandFactory getCommandFactory() {
try {
CommandFactoryFactory allCommandsFactory = new
CommandFactoryFactory();
allCommandsFactory.setUseDefaultCommands(true);
allCommandsFactory.addCommand("PASS", new PASS());
allCommandsFactory.addCommand("DELE", new NotSupportedCommand());
allCommandsFactory.addCommand("RMD", new NotSupportedCommand());
allCommandsFactory.addCommand("RNFR", new NotSupportedCommand());
allCommandsFactory.addCommand("RNTO", new NotSupportedCommand());
allCommandsFactory.addCommand("SITE", new NotSupportedCommand());
return allCommandsFactory.createCommandFactory();
} catch (Exception ex) {
logger.error("Command factory could not be created.");
throw ex;
}
}
private SslConfiguration getSslConfiguration() {
SslConfiguration sslConfiguration = null;
SslConfigurationFactory sslConfigFactory = new
SslConfigurationFactory();
sslConfigFactory.setSslProtocol("TLS");
SslConfig config = ftpConfiguration.getSslConfig();
File sslFile = new File(config.getKeystorePath()
+ FileSystems.getDefault().getSeparator() +
config.getKeystoreFileName());
sslConfigFactory.setKeystoreFile(sslFile);
sslConfigFactory.setKeystorePassword(config.getKeystorePassword());
sslConfigFactory.setKeyAlias(config.getCertAlias());
if (config.getEnabledCipherSuites() != null) {
String[] cipherSuites = config.getEnabledCipherSuites().split(",");
sslConfigFactory.setEnabledCipherSuites(cipherSuites);
logger.info("Cipher Suites list defined in environment variable is
used:{}", config.getEnabledCipherSuites());
}else{
sslConfigFactory.setEnabledCipherSuites(safeDefaultCipherSuitesList);
logger.info("Default Cipher Suites list is used:{}", String.join(",
", safeDefaultCipherSuitesList));
}
sslConfiguration = sslConfigFactory.createSslConfiguration();
return sslConfiguration;
}
}