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;
    }
}

Reply via email to