You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@commons.apache.org by "Eduardo (Jira)" <ji...@apache.org> on 2021/04/07 15:23:00 UTC

[jira] [Comment Edited] (NET-408) problem connecting to ProFTPD with FTPES

    [ https://issues.apache.org/jira/browse/NET-408?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17316422#comment-17316422 ] 

Eduardo edited comment on NET-408 at 4/7/21, 3:22 PM:
------------------------------------------------------

 

For anyone interested: 

the code above was not working for me in java 14 or 16, (I think 11 too), because the "getHost" method is not available anymore, but the cyberduck code helped here (specifically getPeerHost()) : 

[https://github.com/iterate-ch/cyberduck/blob/master/ftp/src/main/java/ch/cyberduck/core/ftp/FTPClient.java]

 
{code:java}
// @Override
    protected void _prepareDataSocket_(final Socket socket) {
        if(preferences.getBoolean("ftp.tls.session.requirereuse")) {
            if(socket instanceof SSLSocket) {
                // Control socket is SSL
                final SSLSession session = ((SSLSocket) _socket_).getSession();
                if(session.isValid()) {
                    final SSLSessionContext context = session.getSessionContext();
                    context.setSessionCacheSize(preferences.getInteger("ftp.ssl.session.cache.size"));
                    try {
                        final Field sessionHostPortCache = context.getClass().getDeclaredField("sessionHostPortCache");
                        sessionHostPortCache.setAccessible(true);
                        final Object cache = sessionHostPortCache.get(context);
                        final Method putMethod = cache.getClass().getDeclaredMethod("put", Object.class, Object.class);
                        putMethod.setAccessible(true);
                        Method getHostMethod;
                        try {
                            getHostMethod = socket.getClass().getMethod("getPeerHost");
                        }
                        catch(NoSuchMethodException e) {
                            // Running in IKVM
                            getHostMethod = socket.getClass().getDeclaredMethod("getHost");
                        }
                        getHostMethod.setAccessible(true);
                        Object peerHost = getHostMethod.invoke(socket);
                        putMethod.invoke(cache, String.format("%s:%s", peerHost, socket.getPort()).toLowerCase(Locale.ROOT), session);
                    }
                    catch(NoSuchFieldException e) {
                        // Not running in expected JRE
                        log.warn("No field sessionHostPortCache in SSLSessionContext", e);
                    }
                    catch(Exception e) {
                        // Not running in expected JRE
                        log.warn(e.getMessage());
                    }
                }
                else {
                    log.warn(String.format("SSL session %s for socket %s is not rejoinable", session, socket));
                }
            }
        }
    }
{code}
 

 

I had to uncomment this though: 

context.setSessionCacheSize(preferences.getInteger("ftp.ssl.session.cache.size"));

Any idea what can be replaced here? Is this necessary anyhow? it seems to work out with 

// context.setSessionCacheSize(preferences.getInteger("ftp.ssl.session.cache.size"));


was (Author: eduardo-rs):
 

For anyone interested: 

the code above was not working for me in java 14 or 16, (I think 11 too), because the "getHost" method is not available anymore, but the cyberduck code helped here: 

[https://github.com/iterate-ch/cyberduck/blob/master/ftp/src/main/java/ch/cyberduck/core/ftp/FTPClient.java]

 
{code:java}
// @Override
    protected void _prepareDataSocket_(final Socket socket) {
        if(preferences.getBoolean("ftp.tls.session.requirereuse")) {
            if(socket instanceof SSLSocket) {
                // Control socket is SSL
                final SSLSession session = ((SSLSocket) _socket_).getSession();
                if(session.isValid()) {
                    final SSLSessionContext context = session.getSessionContext();
                    context.setSessionCacheSize(preferences.getInteger("ftp.ssl.session.cache.size"));
                    try {
                        final Field sessionHostPortCache = context.getClass().getDeclaredField("sessionHostPortCache");
                        sessionHostPortCache.setAccessible(true);
                        final Object cache = sessionHostPortCache.get(context);
                        final Method putMethod = cache.getClass().getDeclaredMethod("put", Object.class, Object.class);
                        putMethod.setAccessible(true);
                        Method getHostMethod;
                        try {
                            getHostMethod = socket.getClass().getMethod("getPeerHost");
                        }
                        catch(NoSuchMethodException e) {
                            // Running in IKVM
                            getHostMethod = socket.getClass().getDeclaredMethod("getHost");
                        }
                        getHostMethod.setAccessible(true);
                        Object peerHost = getHostMethod.invoke(socket);
                        putMethod.invoke(cache, String.format("%s:%s", peerHost, socket.getPort()).toLowerCase(Locale.ROOT), session);
                    }
                    catch(NoSuchFieldException e) {
                        // Not running in expected JRE
                        log.warn("No field sessionHostPortCache in SSLSessionContext", e);
                    }
                    catch(Exception e) {
                        // Not running in expected JRE
                        log.warn(e.getMessage());
                    }
                }
                else {
                    log.warn(String.format("SSL session %s for socket %s is not rejoinable", session, socket));
                }
            }
        }
    }
{code}
 

 

I had to uncomment this though: 

context.setSessionCacheSize(preferences.getInteger("ftp.ssl.session.cache.size"));

Any idea what can be replaced here? Is this necessary anyhow? it seems to work out with 

// context.setSessionCacheSize(preferences.getInteger("ftp.ssl.session.cache.size"));

> problem connecting to ProFTPD with FTPES
> ----------------------------------------
>
>                 Key: NET-408
>                 URL: https://issues.apache.org/jira/browse/NET-408
>             Project: Commons Net
>          Issue Type: Bug
>          Components: FTP
>    Affects Versions: 2.2, 3.0
>         Environment: ProFTPD 1.3.3d on SUSE Linux Enterprise Server 10.1 32bit, Kernel 2.6.16.46-0.12-default (config file attached)
> ProFTPD 1.3.3d on OpenSUSE 64bit Linux 2.6.34.8-0.2-desktop
> Java 1.5
>            Reporter: Michael Voigt
>            Priority: Major
>         Attachments: BCFTPSClient.java, FTPSClientWithTLSResumption.zip, PTFTPSClient.java, ftpes.jpg, proftpd.conf
>
>
> I have a problem with the FTPClient connecting to a ProFTPD server.
> If the server uses the configuration option "TLSProtocol TLSv1", I
> cannot connect to it at all. I recieve the following error message:
> - javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection
> On the server side I see in the log:
> unable to accept TLS connection: protocol error:
> -  (1) error:14094416:SSL routines:SSL3_READ_BYTES:sslv3 alert
> certificate unknown
> - TLS/TLS-C negotiation failed on control channel
> If the server uses the configuration option "TLSProtocol SSLv23", I
> can connect to it but I cant transfer any files. In the server log I
> see:
> - starting TLS negotiation on data connection
> - TLSv1/SSLv3 renegotiation accepted, using cipher RC4-MD5 (128 bits)
> - client did not reuse SSL session, rejecting data connection (see
> TLSOption NoSessionReuseRequired)
> - unable to open data connection: TLS negotiation failed
> If I add the NoSessionReuseRequired parameter to the ProFTPD config
> everything works fine.
> Here is my code:
>                FTPClient ftpClient = new FTPClient();
>                ftpClient = new FTPSClient("TLS");
>                // this throws an exception with TLSProtocol TLSv1
>                ftpClient.connect(host, port);
>                int reply = ftpClient.getReplyCode();
>                if (!FTPReply.isPositiveCompletion(reply)) {
>                        ftpClient.disconnect();
>                        log.error("The FTP Server did not return a positive completion reply!");
>                        throw new FtpTransferException(ECCUtils.ERROR_FTP_CONNECTION);
>                }
>                boolean loginSuccessful = ftpClient.login(userName, password);
>                if (!loginSuccessful) {
>                        log.error("Login to the FTP Server failed! The credentials are not valid.");
>                        throw new FtpTransferException(ECCUtils.ERROR_FTP_LOGIN);
>                }
>                ftpClient.execPBSZ(0);
>                ftpClient.execPROT("P");
>                boolean success = ftpClient.storeFile(fileName, fis);
>                if (!success) {
>                        // this is false if "NoSessionReuseRequired" is not set
>                }
> Now my question is if it is generally possible to connect to a server
> with "TLSProtocol TLSv1" or "TLSProtocol SSLv23" without the
> "NoSessionReuseRequired" parameter? Could someone provide a piece of
> example code for this?



--
This message was sent by Atlassian Jira
(v8.3.4#803005)