/SSLSessionReuseFTPSClient.java Secret
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); | |
} | |
} | |
} | |
} |
java.lang.NoSuchFieldException: No field sessionHostPortCache in class Lcom/android/org/conscrypt/ClientSessionContext; (declaration of 'com.android.org.conscrypt.ClientSessionContext' appears in /system/framework/conscrypt.jar)
System.err: at java.lang.Class.getDeclaredField(Native Method)
System.err: at ..*.SSLSessionReuseFTPSClient.prepareDataSocket(SSLSessionReuseFTPSClient.java:35)
System.err: at org.apache.commons.net.ftp.FTPSClient.openDataConnection(FTPSClient.java:628)
System.err: at org.apache.commons.net.ftp.FTPClient.openDataConnection(FTPClient.java:785)
System.err: at org.apache.commons.net.ftp.FTPClient.initiateListParsing(FTPClient.java:3409)
System.err: at org.apache.commons.net.ftp.FTPClient.initiateListParsing(FTPClient.java:3339)
System.err: at org.apache.commons.net.ftp.FTPClient.listFiles(FTPClient.java:3016)
System.err: at org.apache.commons.net.ftp.FTPClient.listFiles(FTPClient.java:3069)
System.err: at com.noah.httpstest.utils.FTPUtils$4.run(FTPUtils.java:265)
System.err: at java.lang.Thread.run(Thread.java:818)
java1.8
android studio 2.3.3
commons-net-3.6.jar
build:
compileSdkVersion 26
buildToolsVersion "26.0.1"
Don't know why, but this is working with openjdk version "1.8.0_151" and not working with openjdk version "1.8.0_161"
With openJDK 1.8.0_161 :
We must set :
System.setProperty("jdk.tls.useExtendedMasterSecret", "false");
according to
http://www.oracle.com/technetwork/java/javase/8u161-relnotes-4021379.html
Added TLS session hash and extended master secret extension support
In case of compatibility issues, an application may disable negotiation of this extension by setting the System Property jdk.tls.useExtendedMasterSecret to false in the JDK
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?
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
when i call storeFile method in FTPSClient is this _prepareDataSocket method automatically calls or how can i call this class from my class