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 ==> START3969a4037,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 ==> END272a285,289
//CODE MODIFIED BY KAVITA FOR SESSION REUSE ==> START return controllerSession; //CODE MODIFIED BY KAVITA FOR SESSION REUSE ==> END
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.
Code tested, It works. Thanks to "ImDeveloper" (sukhdev-singh) for this contribution.
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.
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.