|
Hi,
still working on the migration from JSSE to BCJSSE when doing FTP and got
more failing testcases. I'm still trying to get a MRE that I can provide
but maybe a description of the test already leads to an answer.
The test checks the ability to download files as a client by first
testing some error cases (file not found, no permission to read, etc).
FTP is defined that way that you request for a data connection (passive
or active) and that the data connection is established before the
server is returning an error code in case of one of mentioned error cases.
So first I test the condition of "permission denied":
---> EPSV
<-- 229 Entering Extended Passive Mode (|||13208|)
Trying to connect to '127.0.0.1':13208
Check proxy for URI ftp://127.0.0.1:13208
Used proxy for URI ftp://127.0.0.1:13208: DIRECT
connected to '127.0.0.1':13208
---> RETR remotefile.txt
Data connection established
Switching to TLS
prepare TLS session resumption for data connection
<-- 553 '/remotefile.txt': cannot read.
Adter that I'm changing the permission and try again. When using JSSE
this works fine but with BCJSSE the clients stops using session resumption:
---> EPSV
<-- 229 Entering Extended Passive Mode (|||13208|)
Trying to connect to '127.0.0.1':13208
Check proxy for URI ftp://127.0.0.1:13208
Used proxy for URI ftp://127.0.0.1:13208: DIRECT
connected to '127.0.0.1':13208
---> RETR remotefile.txt
Data connection established
Switching to TLS
prepare TLS session resumption for data connection
<-- 550 Connection received without reused SSL session
Number of bytes transfered: 0
I've added some debug messages to the code where I set the session to
be resumed:
public static void prepareSocketForSessionReuse(final SSLSocket oldSocket, final SSLSocket newSocket) throws FtpException {
System.out.println(Thread.currentThread().getName() + ": " + oldSocket.getClass());
System.out.println(Thread.currentThread().getName() + ": " + newSocket.getClass());
if (oldSocket instanceof BCSSLSocket || newSocket instanceof BCSSLSocket) {
try {
BCSSLSocket oldS = (BCSSLSocket) oldSocket;
BCSSLSocket newS = (BCSSLSocket) newSocket;
BCExtendedSSLSession session = oldS.getBCSession();
newSocket.setEnabledProtocols(new String[] {session.getProtocol()});
System.out.println("session is valid: " + session.isValid());
newS.setBCSessionToResume(session);
System.out.println("set session: " + TextTools.join(session.getId()));
return;
}
catch(ClassCastException cce) {
throw new FtpException("incompatible socket types, both sockets must be BC-sockets or non-BC-sockets");
}
}
// ...
}
The output shows that the session is considered invalid at that time. I
suppose that the reason is that the session gets invalidated because the
resuming handshake hasn't been finished:
prepare TLS session resumption for data connection
pool-4-thread-1: class org.bouncycastle.jsse.provider.ProvSSLSocketWrap
pool-4-thread-1: class org.bouncycastle.jsse.provider.ProvSSLSocketWrap
session is valid: false
set session: 60 2f de 77 7b 81 1f c1 64 f8 48 3a 80 0c e7 42 91 ea c2 9d 55 b5 1c 90 6e d4 e2 40 0e 2a b4 12
Is it possible to prevent a session to be invalidated by any SSLSocket
except the one that originally created it? Or is this actually a bug
in BC I've found?
Thanks and cheers, Lothar
|