-
-
Save riyaz-ali/48fb486f51c258b4e92c2d2be30c35c4 to your computer and use it in GitHub Desktop.
import org.apache.commons.net.PrintCommandListener; | |
import org.apache.commons.net.ftp.FTP; | |
import org.apache.commons.net.ftp.FTPFile; | |
import org.apache.commons.net.ftp.FTPSClient; | |
import java.io.FileInputStream; | |
import java.io.IOException; | |
import java.nio.file.FileSystems; | |
import java.nio.file.Path; | |
/** | |
* FTPUploadTest class to test FTPS upload using Apache commons net library | |
*/ | |
public class FTPUploadTest { | |
public static void main(String[] args) throws IOException { | |
// file to upload | |
// create a test.jpeg file in your current directory | |
Path path = FileSystems.getDefault().getPath("test.jpeg").toAbsolutePath(); | |
// we will be using https://dlptest.com/ftp-test/ FTP-server to test uploads | |
// thanks guys :D | |
FTPSClient client = new PatchedFTPSClient(); | |
try { | |
// to debug | |
client.addProtocolCommandListener(new PrintCommandListener(System.out)); | |
// connect to the server | |
client.connect("ftp.dlptest.com", 21); | |
// then login | |
client.login("[email protected]", "eiTqR7EMZD5zy7M"); | |
// exec PROT P | |
client.execPBSZ(0); | |
client.execPROT("P"); | |
// enter passive mode | |
client.enterLocalPassiveMode(); | |
// upload | |
client.setFileType(FTP.BINARY_FILE_TYPE); | |
if (client.storeUniqueFile(new FileInputStream(path.toFile()))) { | |
System.out.println("File Saved!"); | |
} else { | |
System.out.println("Failed to save file"); | |
} | |
// list | |
for (FTPFile file : client.listFiles("/")) { | |
System.out.println(file.toFormattedString()); | |
} | |
} finally { | |
client.disconnect(); | |
} | |
} | |
} |
import org.apache.commons.net.ftp.FTPSClient; | |
import javax.net.ssl.*; | |
import java.io.IOException; | |
import java.lang.reflect.Field; | |
import java.lang.reflect.Method; | |
import java.net.Socket; | |
import java.util.Locale; | |
/** | |
* FTPSClient to patch TLS session resumption support in Apache FTPSClient | |
* see also: http://eng.wealthfront.com/2016/06/10/connecting-to-an-ftps-server-with-ssl-session-reuse-in-java-7-and-8/ | |
* see also: https://gist.github.com/lukehansen/cd1931426d1e432d0993005f9976e6fb | |
*/ | |
public class PatchedFTPSClient extends FTPSClient { | |
@Override protected void _prepareDataSocket_(Socket socket) throws IOException { | |
if (socket instanceof SSLSocket) { | |
final SSLSession session = ((SSLSocket) _socket_).getSession(); | |
final SSLSessionContext context = session.getSessionContext(); | |
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); | |
final Method getHostMethod = socket.getClass().getDeclaredMethod("getHost"); | |
getHostMethod.setAccessible(true); | |
Object host = getHostMethod.invoke(socket); | |
final String key = String.format("%s:%s", host, String.valueOf(socket.getPort())).toLowerCase(Locale.ROOT); | |
putMethod.invoke(cache, key, session); | |
} catch (Exception e) { | |
throw new IOException(e); | |
} | |
} | |
} | |
} |
@riyaz-ali I am facing the same error as @anthonyblanchettepotvin
its not working on android!
No field sessionsByHostAndPort in class Lcom/android/org/conscrypt/ClientSessionContext; (declaration of 'com.android.org.conscrypt.ClientSessionContext' appears in /apex/com.android.conscrypt/javalib/conscrypt.jar)
Hi. Thank you. I had to change .getDeclaredMethod("getHost"); for .getDeclaredMethod("getPeerHost"); in JRE8 (openJDK) to make it work. Also, in JRE8, you had to set the protocol in TLS1.2, with TLS1.3 fails (cause 1.8 doesn't support 1.3)
Hi. Thank you. I had to change .getDeclaredMethod("getHost"); for .getDeclaredMethod("getPeerHost"); in JRE8 (openJDK) to make it work. Also, in JRE8, you had to set the protocol in TLS1.2, with TLS1.3 fails (cause 1.8 doesn't support 1.3)
thanks, but I had to use this inside my android application and I wasn't able to access sessionsByHostAndPort key. So, I used RestrictionBypass and it worked!
Hi riyaz-ali,
After tearing my hair out during hours to solve this problem with my filezilla server and my Java Apache commons FTPSClient that was every time resulting with the "TLS session of data connection not resumed." when trying to call ftpsClient.listFiles (login was working fine),
Your PatchedFTPSClient class definitely solved the problem !!!
Thanks a lot for your help.
Regards,
Lolo