Home  >  Article  >  Java  >  How to Reuse the TLS Session for Data Connections in FTPS with Apache Commons Net?

How to Reuse the TLS Session for Data Connections in FTPS with Apache Commons Net?

Mary-Kate Olsen
Mary-Kate OlsenOriginal
2024-11-11 22:42:03282browse

How to Reuse the TLS Session for Data Connections in FTPS with Apache Commons Net?

How to Connect to FTPS Server with Data Connection Using the Same TLS Session

The Apache Commons Net FTPS implementation does not automatically reuse the TLS session for data connections when connecting to certain FTPS servers. This can cause TLS handshake errors when the data connection is attempted.

To ensure the data connection uses the same TLS session as the control connection:

  1. Check if the FTPS server supports TLS session reuse: Some servers, such as FileZilla Server, enforce TLS session reuse for the data connections.
  2. Reuse the session using custom code: You can override the _prepareDataSocket_ method in the FTPSClient class to manually set the session for the data connection.
@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("sessionsByHostAndPort");
                    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 sessionsByHostAndPort 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));
            }
        }
    }
}
  1. Override Spring Integration's createClientInstance(): Create a custom factory that returns the FTPSClient with the _prepareDataSocket_ override.
  2. Set jdk.tls.useExtendedMasterSecret to false (Java 8u161 and above): This is a workaround for SSLHandshakeException in JDK 8u161.
System.setProperty("jdk.tls.useExtendedMasterSecret", "false");

The above is the detailed content of How to Reuse the TLS Session for Data Connections in FTPS with Apache Commons Net?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn