-
-
Save lukehansen/cd1931426d1e432d0993005f9976e6fb to your computer and use it in GitHub Desktop.
import java.io.IOException; | |
import java.lang.reflect.Field; | |
import java.lang.reflect.Method; | |
import java.net.Socket; | |
import java.util.Locale; | |
import javax.net.ssl.SSLSession; | |
import javax.net.ssl.SSLSessionContext; | |
import javax.net.ssl.SSLSocket; | |
import org.apache.commons.net.ftp.FTPSClient; | |
import com.google.common.base.Throwables; | |
public class SSLSessionReuseFTPSClient extends FTPSClient { | |
// adapted from: https://trac.cyberduck.io/changeset/10760 | |
@Override | |
protected void _prepareDataSocket_(final 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 Throwables.propagate(e); | |
} | |
} | |
} | |
} |
Respect :)
I implemented the mentioned solution and still getting same error. My java version is 1.8.0_221. This part of code is executed (I saw debugging) and I also added System.setProperty("jdk.tls.useExtendedMasterSecret", "false");
javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:994)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1367)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1395)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1379)
at org.apache.commons.net.ftp.FTPSClient.openDataConnection(FTPSClient.java:646)
at org.apache.commons.net.ftp.FTPClient._retrieveFile(FTPClient.java:1899)
at org.apache.commons.net.ftp.FTPClient.retrieveFile(FTPClient.java:1885)
at com.motoresocasion.core.utils.ftp.FtpClient.downloadFile(FtpClient.java:72)
Caused by: java.io.EOFException: SSL peer shut down incorrectly
at sun.security.ssl.InputRecord.read(InputRecord.java:505)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:975)
... 26 common frames omitted
I have the same problem too, for retrieving the Field "sessionHostPortCache", basically I view the source code for class "SSLSessionConnecion" there is no "sessionHostPortCache" Fiels, that Field is exist in class call "SSLSessionConnecionImp" from package "sun. security. ssl", but this package is removed from android default SDK, (because some of the function for original SDK package Android doesn't support), also I cannot find that class from jsse.jar library (inside jre1.8u151 folder) , then I tried to build my own from OpenJDK 1.8 source code directly, but it got problem that android studio cannot identify class from the custom-made library. I also tried lgrousset advice, but got no hope, anyone have a ideas?