Menu

#2 SSL session reuse functionality in ftp4j

open
2
2021-10-12
2014-09-13
ImDeveloper
No

I am using ftp4j 1.7.2 client in an application to upload and download large file.

One of the customer FTPs sever is forcing SSL session reuse. Customer can not change any configuration on FTPs server side.

ftp4j does not seems to work if server forces SSL session reuse.
How do i upload/download files in case case of SSL session reuse.

On a side note -
I tried to modify ftp4j code for reusing SSL session. After code changes, it seems to work fine for me. Please let me know if these code changes are ok and will not cause any issue.

Do you want to take these code changes in ftp4j library?

Any help/info on this will be appreciated.

diff FTPClient.java FTPClient_changed.java

40a41,42

import java.lang.reflect.Field;
import java.lang.reflect.Method;
48a51
import java.util.Locale;
54a58,60
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSessionContext;
import javax.net.ssl.SSLSocket;
372a379,391

/*
* Session created after login for controller channel
* Need this to reuse while sending data commands.
/
private SSLSession controllerSession = null;

/*
* Session created after login for controller channel
* Need this to reuse while sending data commands.
/
private boolean reuseSession = true;

375a395

503c523,568
< return sslSocketFactory.createSocket(socket, host, port, true);


  //return sslSocketFactory.createSocket(socket, host, port, true);

  if (controllerSession == null)
      throw new IOException("No controllerSession available to reuse in data channel");

  Socket socket1 = sslSocketFactory.createSocket(socket, host, port, true);
  SSLSocket dataChannel=(SSLSocket)socket1;

  //CODE MODIFIED BY KAVITA FOR SESSION REUSE ==> START
  //If controller channel session needs to be reused by data channel then modify sessioncache  
  //to store same session value for key (host,port)
  if(reuseSession)
  {
      final SSLSessionContext sessionContext = controllerSession.getSessionContext();
      dataChannel.setEnableSessionCreation(false);

      sessionContext.setSessionCacheSize(100);
      try {
          final Field sessionHostPortCache = sessionContext.getClass().getDeclaredField("sessionHostPortCache");
          sessionHostPortCache.setAccessible(true);
          final Object cache = sessionHostPortCache.get(sessionContext);
          final Method method = cache.getClass().getDeclaredMethod("put", Object.class, Object.class);
          method.setAccessible(true);
          final String key = String.format("%s:%s", socket.getInetAddress().getHostName(),
              String.valueOf(socket.getPort())).toLowerCase(Locale.ROOT);
          method.invoke(cache, key, controllerSession);
      }

      catch(NoSuchFieldException e) {
          // Not running in expected JRE
          e.printStackTrace();
          System.out.println("No field sessionHostPortCache in SSLSessionContext");
      }
      catch(Exception e) {
          // Not running in expected JRE
           e.printStackTrace();
           System.out.println(e.getMessage());
      }
     }

  System.out.println("for data channel"+dataChannel.getSession()+" controllerSession="+controllerSession);

  //CODE MODIFIED BY KAVITA FOR SESSION REUSE ==> END

  return socket1;

1222c1287,1289
< communication.ssl(sslSocketFactory);


              //CODE MODIFIED BY KAVITA FOR SESSION REUSE ==> START
              controllerSession = communication.ssl(sslSocketFactory);
              //CODE MODIFIED BY KAVITA FOR SESSION REUSE ==> START

3969a4037,4044
public boolean isReuseSession() {
return reuseSession;
}

public void setReuseSession(boolean reuseSession) {
this.reuseSession = reuseSession;
}

diff FTPCommunicationChannel.java FTPCommunicationChannel_changed.java
27a28,29

import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
265c267
< public void ssl(SSLSocketFactory sslSocketFactory) throws IOException {


public SSLSession ssl(SSLSocketFactory sslSocketFactory) throws IOException {
268a271,280

  //CODE MODIFIED BY KAVITA FOR SESSION REUSE ==> START
  SSLSocket controllerSocket=(SSLSocket)connection;

  //Get the session and send it back to reuse for data channel
  final SSLSession controllerSession = ((SSLSocket) connection).getSession();
  System.out.println("Session for controll channel"+controllerSocket.getSession());

  //CODE MODIFIED BY KAVITA FOR SESSION REUSE ==> END

272a285,289

  //CODE MODIFIED BY KAVITA FOR SESSION REUSE ==> START
  return  controllerSession;
  //CODE MODIFIED BY KAVITA FOR SESSION REUSE ==> END

Discussion

  • Deguich

    Deguich - 2018-11-28

    Hi,
    Please, could you make a new ftp4j release including this ssl_reuse functionality ?
    ftp4j client library is really the best but I cannot use it anymore since ssl reuse become a standard on FTPS server ...
    Thanks.

     
  • Deguich

    Deguich - 2018-11-30

    Code tested, It works. Thanks to "ImDeveloper" (sukhdev-singh) for this contribution.

     
  • Deguich

    Deguich - 2020-08-24

    Don't work any more, new JDK cannot compile this code , trying to access to private or protected data. This code produce a security issue.

    We need an official ssl_reuse functionality. VSFTP enable this option by default, so lot of ftp over ssl explicit server can't be used with ftp4j :
    http://vsftpd.beasts.org/vsftpd_conf.html see require_ssl_reuse option.

     
  • Deguich

    Deguich - 2021-10-12

    Same problem with apache library ...
    https://issues.apache.org/jira/browse/NET-408
    FileZilla Server seems to enable ftps SSL Reuse by default, more and more FTP Server cannot be used with Java.

     

Log in to post a comment.