The initializeKeyStore() method of SSLContextFactory uses SSLContextFactory.class.getResourceAsStream() followed by SSLContextFactory.class.getClassLoader().getResourceAsStream() to locate the configured SocketKeyStore. Both of these seem to return null if SocketKeyStore is a local path.
The Configuring QuickFIX/J section of the user manual states valid values for SocketKeyStore are "File path", so I assume this isn't intentional.
Applying the patch below to SSLContextFactory.java fixes the issue for me:
75a84,89
> if (in == null) {
> try
{
> in = new FileInputStream(keyStoreName);
> }
catch (FileNotFoundException ex)
{
> }
> }
I've attached the abridged output from running a test app with -Djavax.net.debug=ssl:handshake, this shows the SSL handshake is failing due to an empty certificate chain, and that a keystore hasn't been loaded.
Before:
-----------------
<20071001-17:33:32, FIX.4.4:SOURCE->TARGET, event> (Session FIX.4.4:SOURCE->TARGET schedule is daily, 00:00:00 UTC - 00:00:00 UTC (daily, 00:00:00 UTC - 00:00:00 UTC))
<20071001-17:33:32, FIX.4.4:SOURCE->TARGET, event> (Created session: FIX.4.4:SOURCE->TARGET)
trigger seeding of SecureRandom
done seeding SecureRandom
Using SSLEngineImpl.
%% No cached client session
-
-
- ClientHello, TLSv1
RandomCookie: ...
Session ID: {}
Cipher Suites: ...
Compression Methods:
{ 0 }
***
SocketConnector-0, WRITE: TLSv1 Handshake, length = 73
SocketConnector-0, WRITE: SSLv2 client hello message, length = 98
SocketConnectorIoProcessor-0.0, READ: TLSv1 Handshake, length = 1425
*** ServerHello, TLSv1
RandomCookie: ...
Session ID: ...
Cipher Suite: SSL_RSA_WITH_RC4_128_MD5
Compression Method: 0
***
%% Created: [Session-1, SSL_RSA_WITH_RC4_128_MD5]
** SSL_RSA_WITH_RC4_128_MD5
*** Certificate chain
chain [0] = [
[
Version: V1
Subject: ...
Signature Algorithm: ...
Key: Sun RSA public key, 1024 bits
modulus: ...
public exponent: ...
Validity: [From: Tue Jun 07 19:13:15 BST 2005,
To: Fri Jun 05 19:13:15 BST 2015]
Issuer: ...
SerialNumber: ...
]
Algorithm: [MD5withRSA]
Signature: ...
]
***
*** CertificateRequest
Cert Types: RSA, DSS,
Cert Authorities:
...
*** ServerHelloDone
*** Certificate chain
***
*** ClientKeyExchange, RSA PreMasterSecret, TLSv1
Random Secret: ...
SocketConnectorIoProcessor-0.0, WRITE: TLSv1 Handshake, length = 141
SESSION KEYGEN:
...
CONNECTION KEYGEN:
Client Nonce:
...
Server Nonce:
...
Master Secret:
...
Client MAC write Secret:
...
Server MAC write Secret:
...
Client write key:
...
Server write key:
...
... no IV for cipher
SocketConnectorIoProcessor-0.0, WRITE: TLSv1 Change Cipher Spec, length = 1
*** Finished
verify_data: ...
***
SocketConnectorIoProcessor-0.0, WRITE: TLSv1 Handshake, length = 32
SocketConnectorIoProcessor-0.0, READ: TLSv1 Alert, length = 2
SocketConnectorIoProcessor-0.0, RECV TLSv1 ALERT: fatal, bad_certificate
SocketConnectorIoProcessor-0.0, fatal: engine already closed. Rethrowing javax.net.ssl.SSLException: Received fatal alert: bad_certificate
SocketConnectorIoProcessor-0.0, fatal: engine already closed. Rethrowing javax.net.ssl.SSLException: Received fatal alert: bad_certificate
<20071001-17:33:37, FIX.4.4:SOURCE->TARGET, event> (Disconnecting)
SocketConnectorIoProcessor-0.0, called closeOutbound()
SocketConnectorIoProcessor-0.0, closeOutboundInternal()
SocketConnectorIoProcessor-0.0, SEND TLSv1 ALERT: warning, description = close_notify
SocketConnectorIoProcessor-0.0, WRITE: TLSv1 Alert, length = 18
SocketConnectorIoProcessor-0.0, called closeInbound()
SocketConnectorIoProcessor-0.0, fatal: engine already closed. Rethrowing javax.net.ssl.SSLException: Inbound closed before receiving peer's close_notify: possible truncation attack?
SocketConnectorIoProcessor-0.0, called closeOutbound()
SocketConnectorIoProcessor-0.0, closeOutboundInternal()
-----------------
After:
-----------------
<20071001-17:34:17, FIX.4.4:SOURCE->TARGET, event> (Session FIX.4.4:SOURCE->TARGET schedule is daily, 00:00:00 UTC - 00:00:00 UTC (daily, 00:00:00 UTC - 00:00:00 UTC))
<20071001-17:34:17, FIX.4.4:SOURCE->TARGET, event> (Created session: FIX.4.4:SOURCE->TARGET)
***
found key for : TARGET
chain [0] = [
[
Version: V1
Subject: ...
Signature Algorithm: ...
Key: Sun RSA public key, 1024 bits
modulus: ...
public exponent: ...
Validity: [From: Wed Jun 06 16:51:56 BST 2007,
To: Sat Jun 03 16:51:56 BST 2017]
Issuer: ...
SerialNumber: ...
]
Algorithm: [MD5withRSA]
Signature:
...
]
***
trigger seeding of SecureRandom
done seeding SecureRandom
Using SSLEngineImpl.
%% No cached client session
*** ClientHello, TLSv1
RandomCookie: ...
Session ID: {}
Cipher Suites: ...
Compression Methods: { 0 }
***
SocketConnector-0, WRITE: TLSv1 Handshake, length = 73
SocketConnector-0, WRITE: SSLv2 client hello message, length = 98
SocketConnectorIoProcessor-0.0, READ: TLSv1 Handshake, length = 1425
- ServerHello, TLSv1
RandomCookie: ...
Session ID: ...
Cipher Suite: SSL_RSA_WITH_RC4_128_MD5
Compression Method: 0
***
%% Created: [Session-1, SSL_RSA_WITH_RC4_128_MD5]
- SSL_RSA_WITH_RC4_128_MD5
- Certificate chain
chain [0] = [
[
Version: V1
Subject: ...
Signature Algorithm: ...
Key: Sun RSA public key, 1024 bits
modulus: ...
public exponent: ...
Validity: [From: Tue Jun 07 19:13:15 BST 2005,
To: Fri Jun 05 19:13:15 BST 2015]
Issuer: ...
SerialNumber: ...
]
Algorithm: [MD5withRSA]
Signature:
...
]
***
-
-
- CertificateRequest
Cert Types: RSA, DSS,
Cert Authorities:
...
- ServerHelloDone
matching alias: TARGET
- Certificate chain
chain [0] = [
[
Version: V1
Subject: ...
Signature Algorithm: ...
Key: Sun RSA public key, 1024 bits
modulus: ...
public exponent: ...
Validity: [From: Wed Jun 06 16:51:56 BST 2007,
To: Sat Jun 03 16:51:56 BST 2017]
Issuer: ...
SerialNumber: ...
]
Algorithm: [MD5withRSA]
Signature:
...
]
***
-
-
- ClientKeyExchange, RSA PreMasterSecret, TLSv1
Random Secret: ...
SocketConnectorIoProcessor-0.0, WRITE: TLSv1 Handshake, length = 604
SESSION KEYGEN:
PreMaster Secret:
...
CONNECTION KEYGEN:
Client Nonce:
...
Server Nonce:
...
Master Secret:
...
Client MAC write Secret:
...
Server MAC write Secret:
...
Client write key:
...
Server write key:
...
... no IV for cipher
- CertificateVerify
SocketConnectorIoProcessor-0.0, WRITE: TLSv1 Handshake, length = 134
SocketConnectorIoProcessor-0.0, WRITE: TLSv1 Change Cipher Spec, length = 1
- Finished
verify_data: ...
***
SocketConnectorIoProcessor-0.0, WRITE: TLSv1 Handshake, length = 32
SocketConnectorIoProcessor-0.0, READ: TLSv1 Change Cipher Spec, length = 1
SocketConnectorIoProcessor-0.0, READ: TLSv1 Handshake, length = 32
- Finished
verify_data: ...
***
%% Cached client session: [Session-1, SSL_RSA_WITH_RC4_128_MD5]
QFJ Timer, WRITE: TLSv1 Application Data, length = 156
<20071001-17:34:21, FIX.4.4:SOURCE->TARGET, event> (Initiated logon request)
<20071001-17:34:21, FIX.4.4:SOURCE->TARGET, event> (Logon contains ResetSeqNumFlag=Y, resetting sequence numbers to 1)
<20071001-17:34:21, FIX.4.4:SOURCE->TARGET, event> (Received logon response)
-----------------
Thanks,
James
|