commons-net
commons-net copied to clipboard
FTPES with TLS Session Reuse for FileZilla Server (need also BouncyCastle and a subclass).
Connecting to ftp.example.com on the command port and then to the corresponding IP x.x.x.x on the data port prevents the server from accepting the same TLS session. Therefore, the Filezilla server needs to set peerHost before socket.connect to allow TLS session resumption.
With this new version, FTPeS to the server with TLS session resumption works with this subclass :
package org.mypackage;
import java.io.IOException;
import java.net.Socket;
import java.security.SecureRandom;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import org.apache.commons.net.ftp.FTPSClient;
import org.apache.commons.net.util.TrustManagerUtils;
import org.bouncycastle.jsse.BCExtendedSSLSession;
import org.bouncycastle.jsse.BCSSLSocket;
import org.bouncycastle.jsse.provider.BouncyCastleJsseProvider;
public class FTPSClientSSLSessionReuse extends FTPSClient {
public FTPSClientSSLSessionReuse (boolean isImplicit) throws Exception {
super(isImplicit, createSSLContext());
setEnabledProtocols(new String[] {"TLSv1.2"});
setUseEPSVwithIPv4(true);
}
private static SSLContext createSSLContext() throws Exception {
SSLContext context = SSLContext.getInstance("TLS", new BouncyCastleJsseProvider());
context.init(
null,
new TrustManager[] {TrustManagerUtils.getValidateServerCertificateTrustManager()},
new SecureRandom());
return context;
}
@Override
protected void _prepareDataSocket_(final Socket socket) throws IOException {
if (_socket_ instanceof BCSSLSocket sslSocket) {
BCExtendedSSLSession bcSession = sslSocket.getBCSession();
if (bcSession != null && bcSession.isValid() && socket instanceof BCSSLSocket dataSslSocket) {
dataSslSocket.setBCSessionToResume(bcSession);
// Next line could be a solution if this function was called before connect
dataSslSocket.setHost(bcSession.getPeerHost());
}
}
}
}