So here's the deal. I have a web service WSDL that I need to make SOAP calls to outside my corporate network. The webservice is HTTPS SOAP, and requires a client certificate. I've generated the client code in Java from wsdl2java
, and things seem to go pretty well.
What I cannot do right now is receive a response from the web service through CXF. The SSL handshake seems to go just dandy even up to the point where CXF tries to do an HTTP POST, but times out waiting for a response (shown below):
Allow unsafe renegotiation: false
Allow legacy hello messages: true
Is initial handshake: false
Is secure renegotiation: false
*** HelloRequest (empty)
main, SEND TLSv1 ALERT: warning, description = no_renegotiation
Padded plaintext before ENCRYPTION: len = 24
0000: 01 64 01 FD 5B 38 03 A6 70 41 57 58 6D 75 60 F7 .d..[8..pAWXmu`.
0010: 93 1F 02 F3 C4 46 01 01 .....F..
main, WRITE: TLSv1 Alert, length = 24
[Raw write]: length = 29
0000: 15 03 01 00 18 0C 9B DF 1B 60 AB 12 EE C7 CF C9 .........`......
0010: 62 97 A5 5D 5F 14 48 E1 9F AD 8A 08 05 b..]_.H......
main, handling exception: java.net.SocketTimeoutException: Read timed out
main, called close()
main, called closeInternal(true)
main, SEND TLSv1 ALERT: warning, description = close_notify
Padded plaintext before ENCRYPTION: len = 24
0000: 01 00 BD 99 7A 7C 72 1F BB 11 2D AB 3F 53 C9 CD ....z.r...-.?S..
... continuing on
Now, if I use curl
or somethign similar, I can get a response in less than a second, so I know the web service isn't at fault. Below is the entirety of the code necessary to create the service port, including setup with TLS and an HTTP proxy. I have a very simple JUnit test to create and run this, too:
public static MYPORT setupTLS(MYPORT port) throws IOException,
GeneralSecurityException {
HTTPConduit httpConduit = (HTTPConduit) ClientProxy.getClient(port)
.getConduit();
String keyPassword = "password";
KeyStore keyStore = KeyStore.getInstance("pkcs12");
URL pkcs12_file = MECTPortFactory.class.getResource(System
.getProperty("pkcs12.keyFile"));
InputStream keyFile = pkcs12_file.openStream();
keyStore.load(keyFile, keyPassword.toCharArray());
KeyManager[] myKeyManagers = getKeyManagers(keyStore, keyPassword);
TLSClientParameters tlsCP = new TLSClientParameters();
tlsCP.setKeyManagers(myKeyManagers);
tlsCP.setDisableCNCheck(true);
FiltersType cipher_suite_filter = new FiltersType();
cipher_suite_filter.getInclude().add("SSL_RSA_WITH_3DES_EDE_CBC_SHA");
cipher_suite_filter.getExclude().add(".*_DH_anon_.*");
tlsCP.setCipherSuitesFilter(cipher_suite_filter);
httpConduit.setTlsClientParameters(tlsCP);
httpConduit.setClient(getHttpClient());
return port;
}
private static HTTPClientPolicy getHttpClient() {
HTTPClientPolicy client_policy = new HTTPClientPolicy();
client_policy.setProxyServer("PROXY_SERVER_ADDRESS");
client_policy.setProxyServerPort(8080);
client_policy.setAutoRedirect(true);
client_policy.setConnection(ConnectionType.KEEP_ALIVE);
client_policy.setAllowChunking(true);
client_policy.setReceiveTimeout(10000);
return client_policy;
}
private static KeyManager[] getKeyManagers(KeyStore keyStore,
String keyPassword) throws GeneralSecurityException, IOException {
String alg = KeyManagerFactory.getDefaultAlgorithm();
char[] keyPass = keyPassword != null ? keyPassword.toCharArray() : null;
KeyManagerFactory fac = KeyManagerFactory.getInstance(alg);
fac.init(keyStore, keyPass);
return fac.getKeyManagers();
}
Edit:
I've fiddled with some client settings such as changing whether to AutoRedirect, AllowChunking, etc., with no differences, so I don't think that's causing errors.
Edit2:
I don't get a response from the web service. How can I troubleshoot and fix what is causing CXF to time out instead of receiving the response?
OMG! I figured it out.
So I went traipsing through the interwebs and found this little gem:
How to configure SoapUI with client certificate authentication
And it references a very important note from Oracle/Sun:
Transport Layer Security (TLS) Renegotiation Issue Readme
then, further down:
So the long and short of it?
System.setProperty("sun.security.ssl.allowUnsafeRenegotiation", "true");
And things. Just. Work.