Tomcat 7 / 8 and IBM JRE won't initialize DSA key - java

I'm reproducing a problem reported by one of our customers.
He has a Tomcat 7 running on AIX 7.1 with IBM JRE 7.
The Tomcat has a HTTPS connector defined:
<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
keystoreFile="/path/to/keystore.key" keystorePass="password"
maxThreads="150" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS" />
The keystore contains a 1024 bits DSA keypair.
When a HTTPS request comes in the DSA key won't be initialized, which results in a handshake failure.
Output from catalina.out with -Djavax.net.debug=all:
%% Initialized: [Session-2, SSL_NULL_WITH_NULL_NULL]
ssl: ServerHandshaker.setupPrivateKeyAndChain EC_EC
ssl: ServerHandshaker.setupPrivateKeyAndChain, chooseServerAlias null
ssl: ServerHandshaker.setupPrivateKeyAndChain RSA
ssl: ServerHandshaker.setupPrivateKeyAndChain, chooseServerAlias null
ssl: ServerHandshaker.setupPrivateKeyAndChain EC_EC
ssl: ServerHandshaker.setupPrivateKeyAndChain, chooseServerAlias null
ssl: ServerHandshaker.setupPrivateKeyAndChain EC_RSA
ssl: ServerHandshaker.setupPrivateKeyAndChain, chooseServerAlias null
%% Invalidated: [Session-2, SSL_NULL_WITH_NULL_NULL]
If I switch to IBM JRE 8 the key get's initialized:
%% Initialized: [Session-1, SSL_NULL_WITH_NULL_NULL]
ssl: ServerHandshaker.setupPrivateKeyAndChain EC_EC
ssl: ServerHandshaker.setupPrivateKeyAndChain, chooseServerAlias null
ssl: ServerHandshaker.setupPrivateKeyAndChain RSA
ssl: ServerHandshaker.setupPrivateKeyAndChain, chooseServerAlias null
ssl: ServerHandshaker.setupPrivateKeyAndChain EC_EC
ssl: ServerHandshaker.setupPrivateKeyAndChain, chooseServerAlias null
ssl: ServerHandshaker.setupPrivateKeyAndChain EC_RSA
ssl: ServerHandshaker.setupPrivateKeyAndChain, chooseServerAlias null
ssl: ServerHandshaker.setupPrivateKeyAndChain RSA
ssl: ServerHandshaker.setupPrivateKeyAndChain, chooseServerAlias null
ssl: ServerHandshaker.setupPrivateKeyAndChain DSA
matching alias: mykey
ssl: ServerHandshaker.setupPrivateKeyAndChain, chooseServerAlias mykey
ssl: ServerHandshaker.setupPrivateKeyAndChain, return true
JsseJCE: Using KeyPairGenerator DiffieHellman from provider TBD via init
DHCrypt: DH KeyPairGenerator from provider from init IBMJCE version 1.8
%% Negotiating: [Session-1, SSL_DHE_DSS_WITH_AES_128_CBC_SHA]
Our customer stated that the same keystore worked in Tomcat 6 and with the same JRE 7.
I did some tests with the original keystore in the following environment:
AIX
oslevel -s
7100-04-04-1717
Java
Java7 - IBM JRE - java7_64_SR3 (also SR10_FP1)
Java8 - IBM JRE - java8_64_SR3_FP22
Tomcat
apache-tomcat-6.0.36
apache-tomcat-7.0.69
apache-tomcat-8.5.16
The results are:
Working:
Tomcat 6 + Java 7
Tomcat 6 + Java 8
Tomcat 7 + Java 8
Tomcat 8 + Java 8
Not working:
Tomcat 7 + Java 7
Tomcat 8 + Java 7
It seems to be some issue which occours when running Tomcat 7 / 8 with IMB JRE 7, but not in other combinations.
The JREs have been installed only for reproducing this problem.
I really can't find the reason why it's not working in those combinations.
Any ideas what could be the reason or what I could try?
EDIT: Simply using JRE 8 is not possible due to other limitations.
We got a workaround by providing a keystore with 2048 bits RSA keys which works with all combinations. It still is really unsatisfying not to know what's the problem with the original keystore.

Related

enable HTTPS with self signed certificate on Sprint Boot

I'm trying to launch web server with HTTPS on Spring Boot 1.4 ( and on 2.0.X). But I fail to connect to started server.
Here is my steps:
Add SSL properties to application.yml
server:
ssl:
enabled: true
key-store: classpath:keystore.jks
key-store-password: password
key-password: password
key-alias: tomcat
port: 8443
Generate self sign certificate on src/main/resources
`keytool -genkey -alias tomcat -keyalg RSA -keystore keystore.jks
After run of application
`mvn clean install && java -jar target/audiochat.war
Then in browser https://localhost:8433 (Chrome, Firefox, Edge)
ERR_SSL_VERSION_OR_CIPHER_MISMATCH
I was try to test SSL handshake
openssl s_client -connect localhost:8443
CONNECTED(000001A8)
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 7 bytes and written 308 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
Protocol : TLSv1.2
Cipher : 0000
Session-ID:
Session-ID-ctx:
Master-Key:
Key-Arg : None
PSK identity: None
PSK identity hint: None
SRP username: None
Start Time: 1522596727
Timeout : 300 (sec)
Verify return code: 0 (ok)
---
28412:error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure:s23_clnt.c:769:
Any ideas on correct setup of HTTPS on SpringBoot ?

Tomcat - Two Way SSL as Server

I'm trying to implement two way SSL on a new web service that we are building and I'm having some issues.
First some info on the environment.
Server version: Apache Tomcat/8.0.36
Server built: Jun 9 2016 13:55:50 UTC
Server number: 8.0.36.0
OS Name: Linux
OS Version: 3.10.0-514.el7.x86_64
Architecture: amd64
JVM Version: 1.8.0_111-b14
JVM Vendor: Oracle Corporation
We use an internal certificate authority to sign all of our certificates. So all the client certificates are signed by our internal root. When I trust the root certificate in the client trust store everything works. All client certificates signed by the internal root work.
However, if I remove the root certificate from the client trust store, and add individual client certificates instead I get a cert chain error.
*** ECDH ServerKeyExchange
Signature Algorithm SHA512withRSA
Server key: Sun EC public key, 256 bits
public x coord: 107108750176335210433834926983330116805775068919227166974389735341685270962458
public y coord: 93195725734236902743006469378087068209149058097948526490562555560744449337507
parameters: secp256r1 [NIST P-256, X9.62 prime256v1] (1.2.840.10045.3.1.7)
*** CertificateRequest
Cert Types: RSA, DSS, ECDSA
Supported Signature Algorithms: SHA512withECDSA, SHA512withRSA, SHA384withECDSA, SHA384withRSA, SHA256withECDSA, SHA256withRSA, SHA256withDSA, SHA224withECDSA, SHA224withRSA, SHA224withDSA, SHA1withECDSA, SHA1withRSA, SHA1withDSA Cert Authorities:
<CN=Client, OU=Information Technology, O=Company, L=Calgary, ST=Alberta, C=CA>
*** ServerHelloDone
http-nio2-8443-exec-4, WRITE: TLSv1.2 Handshake, length = 4482 http-nio2-8443-exec-2, READ: TLSv1.2 Handshake, length = 7
*** Certificate chain
<Empty>
***
http-nio2-8443-exec-2, fatal error: 42: null cert chain
javax.net.ssl.SSLHandshakeException: null cert chain %% Invalidated:[Session-2, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256]
http-nio2-8443-exec-2, SEND TLSv1.2 ALERT: fatal, description = bad_certificate http-nio2-8443-exec-2, WRITE: TLSv1.2 Alert, length = 2 http-nio2-8443-exec-2, fatal: engine already closed. Rethrowing javax.net.ssl.SSLHandshakeException: null cert chain http-nio2-8443-exec-2, called closeOutbound() http-nio2-8443-exec-2, closeOutboundInternal()
This is an issue for us as we can't have all the client certificates in the company granted access to this endpoint, it kind of defeats the purpose.
The company root certificate is in another trust store used on server startup. Here are my configs.
Server.xml connector:
<Connector protocol="org.apache.coyote.http11.Http11Nio2Protocol"
port="8443" maxThreads="24" minSpareThreads="4" maxSpareThreads="4" acceptCount="1000" server=" "
scheme="https" secure="true" SSLEnabled="true"
keystoreFile="certs/servercert.jks" keystorePass=" CrazyPasswordHere"
clientAuth="true" truststoreFile="/usr/local/tomcat/certs/clienttrust.jks" truststorePass="CrazyPasswordHere"
sslEnabledProtocols="TLSv1.2" sslProtocol="TLS"
ciphers="TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,TLS_DHE_RSA_WITH_AES_128_CBC_SHA"
useServerCipherSuitesOrder="true" compression="on" compressionMinSize="2048"
compressableMimeType="text/html,text/xml,text/plain,text/css,text/javascript,application/javascript" />
Systemd init:
# Systemd unit file for tomcat
[Unit]
Description=Apache Tomcat
After=syslog.target network.target
[Service]
Type=forking
Environment=JAVA_HOME=/usr/lib/jvm/jre
Environment=CATALINA_PID=/usr/local/tomcat/temp/tomcat.pid
Environment=CATALINA_HOME=/usr/local/tomcat
Environment=CATALINA_BASE=/usr/local/tomcat
Environment='CATALINA_OPTS= -Xms2048M -Xmx2048M -server -XX:+UseParallelGC \ -Dcom.sun.management.jmxremote \
-Dcom.sun.management.jmxremote.port=8090 \ -Dcom.sun.management.jmxremote.ssl=false \ -Dcom.sun.management.jmxremote.authenticate=true \ -Dcom.sun.management.jmxremote.password.file=/usr/local/tomcat/conf/jmxremote.password \ -Dcom.sun.management.jmxremote.access.file=/usr/local/tomcat/conf/jmxremote.access \ -Djavax.net.debug=SSL \ -Djavax.net.ssl.trustStore=/usr/local/tomcat/certs/servertrust.jks \ -Djavax.net.ssl.trustStorePassword=CrazyPasswordHere \ -Djavax.net.ssl.keyStore=/usr/local/tomcat/certs/serverclient.jks \ -Djavax.net.ssl.keyStorePassword=CrazyPasswordHere '
Environment='JAVA_OPTS=-Djava.awt.headless=true -Djava.security.egd=file:/dev/./urandom'
ExecStart=/usr/local/tomcat/bin/startup.sh
ExecStop=/bin/kill -15 $MAINPID
User=tomcat
Group=tomcat
[Install]
WantedBy=multi-user.target
Any input here would be great! I can't imagine that the solution here is that every client cert signed by a specific authority is supposed to have access...
Thanks!
Classic. You are conflating authentication with authorization. It is the job of SSL to authenticate via the mechanism you have already set up, and which as you say is working perfectly. It is the job of Tomcat, or the application, to use that information to define who is authorized to use the webapp. This is done via web.xml, CMA, etc.

ssl_upgrade_error rabbitMQ

I have sucessfully configurated RabbitMQ to accept TLS-Connections(Only TLS1.1 and TLS1.2)
now I have written a Java program which connects to the rabbitMQ-Server.
The server(10.0.0.120) and the 2 clients(10.0.0.121-122) are all running on an seperate RaspberryPI which almost same configuration
I can connect to the Server using openssl
root#10.0.0.122:~# openssl s_client -connect 10.0.0.120:5671
...
SSL-Session:
Protocol : TLSv1.2
Cipher : AES256-SHA256
Session-ID: 2D1E2F6CECA4DCB3D7403E9DEF9F9DEAADF5AC15298D6CA54120F26D70D5E4A7
Session-ID-ctx:
Master-Key: 003C06F78281F23D8E2D7432E84B59EEABE586FA4472CF29259F8E7DAE4BD5F2F678A7F4FA27F9FBE6616481BAEEA131
Key-Arg : None
PSK identity: None
PSK identity hint: None
SRP username: None
Start Time: 1422352831
Timeout : 300 (sec)
Verify return code: 19 (self signed certificate in certificate chain)
---
root#10.0.0.121:~# openssl s_client -connect 10.0.0.120:5671
...
SSL-Session:
Protocol : TLSv1.2
Cipher : AES256-SHA256
Session-ID: B5538A83AE671DF2295632D02549C2E3059EED8DC73235DCE3D58FD69ABF7A62
Session-ID-ctx:
Master-Key: 86F3DDB68E5AB3796A9B762289AE7BD6D0E9A71CB549836D1A01C468180CAB98B9B819A1AF2255AE0BBF8B5911823EB8
Key-Arg : None
PSK identity: None
PSK identity hint: None
SRP username: None
Start Time: 1422352895
Timeout : 300 (sec)
Verify return code: 19 (self signed certificate in certificate chain)
---
both have the same java version
root#10.0.0.121:~# java -version
java version "1.7.0_40"
Java(TM) SE Runtime Environment (build 1.7.0_40-b43)
Java HotSpot(TM) Client VM (build 24.0-b56, mixed mode)
root#10.0.0.122:~# java -version
java version "1.7.0_40"
Java(TM) SE Runtime Environment (build 1.7.0_40-b43)
Java HotSpot(TM) Client VM (build 24.0-b56, mixed mode)
and on both is running the same jar file
root#10.0.0.121:~# md5sum rabbitReceive.jar
6df91e2e714341588908798f7e28fa10 rabbitReceive.jar
root#10.0.0.122:~# md5sum rabbitReceive.jar
6df91e2e714341588908798f7e28fa10 rabbitReceive.jar
when I start the JAR file on 10.0.0.122 (where it works!) I get this on the rabbitMQ server log
=INFO REPORT==== 27-Jan-2015::11:07:11 ===
accepting AMQP connection <0.3709.0> (10.0.0.121:52944 -> 10.0.0.120:5671)
when I start the Jar file on 10.0.0.121 I get this on the rabbitMQ server log
=INFO REPORT==== 27-Jan-2015::11:08:06 ===
accepting AMQP connection <0.3755.0> (10.0.0.122:37283 -> 10.0.0.120:5671)
=ERROR REPORT==== 27-Jan-2015::11:08:11 ===
Error on AMQP connection <0.3755.0>:
{ssl_upgrade_error,timeout}
and this exception in the Clients JVM
java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:196)
at java.net.SocketInputStream.read(SocketInputStream.java:122)
at sun.security.ssl.InputRecord.readFully(InputRecord.java:442)
at sun.security.ssl.InputRecord.read(InputRecord.java:480)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:927)
at sun.security.ssl.SSLSocketImpl.waitForClose(SSLSocketImpl.java:1705)
at sun.security.ssl.HandshakeOutStream.flush(HandshakeOutStream.java:122 )
at sun.security.ssl.Handshaker.kickstart(Handshaker.java:909)
at sun.security.ssl.SSLSocketImpl.kickstartHandshake(SSLSocketImpl.java: 1423)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl. java:1288)
at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:702)
at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:122)
at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82 )
at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)
at java.io.DataOutputStream.flush(DataOutputStream.java:123)
at com.rabbitmq.client.impl.SocketFrameHandler.sendHeader(SocketFrameHan dler.java:129)
at com.rabbitmq.client.impl.SocketFrameHandler.sendHeader(SocketFrameHan dler.java:134)
at com.rabbitmq.client.impl.AMQConnection.start(AMQConnection.java:278)
at com.rabbitmq.client.ConnectionFactory.newConnection(ConnectionFactory .java:617)
at com.rabbitmq.client.ConnectionFactory.newConnection(ConnectionFactory .java:639)
at rabbitMqTest.Test.main(Test.java:97)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl. java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces sorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoa der.java:58)
Any Ideas what the problem could be?
As you see, between the start of your jar and the error, there are exactly 5 seconds between.
By default, the ssl-handshake timeout is set to 5 seconds. Your problem is that the ssl handshake can't be done in the default 5 seconds.
You need to change the NORMAL_TIMEOUT and possible the HANDSHAKE_TIMEOUT too at the top of rabbit_reader.erl to increase the timeout.
You can find the configuration-settings are described here.

Tomcat: TLSv1.2 with strong ciphers not working

I installed Tomcat-7, configured support for TLSv1.2 on port 8443.
My Connector configuration:
protocol="org.apache.coyote.http11.Http11NioProtocol" SSLEnabled="true" scheme="https" secure="true" sslProtocol="TLSv1.2" sslEnabledProtocols="TLSv1.2"
I then configured a list of strong ciphers I wanted to use.
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
As I have read, Tomcat can either use Java JSSE or OpenSSL
JSSE protocol="org.apache.coyote.http11.Http11NioProtocol"
OpenSSL protocol="org.apache.coyote.http11.Http11AprProtocol"
My tomcat connector is configured with JSSE protocol.
It works if I add the following ciphers with SHA1. (No GCM with SHA1)
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA.
I have downloaded the Java cryptographic extensions policy files.
Tried with both Java 7 and Java 8.
Before I installed the Cryptographic Extensions I got the following error while starting up Tomcat
INFO: Initializing ProtocolHandler ["http-nio-8443"]
mai 20, 2014 3:57:43 PM org.apache.tomcat.util.net.jsse.JSSESocketFactory getEnableableCiphers
WARNING: None of the ciphers specified are supported by the SSL engine : TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
According to Java 7 Documentation all these strong ciphers with GCM-SHA384 and CBC-SHA384 should be supported:
http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#ciphersuites
If I change the ciphers just a little bit:
INFO: Initializing ProtocolHandler ["http-nio-8443"]
mai 20, 2014 4:21:11 PM org.apache.tomcat.util.net.jsse.JSSESocketFactory getEnableableCiphers
WARNING: None of the ciphers specified are supported by the SSL engine : TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA584,TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA584,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA584,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA584
That would indicate that that my list of ciphers are supported by my Tomcat/Java.
Could the problem be with the Browser? I have tried the latest Chromium and Firefox. After checking some commits I found out that Chromium does support SHA256, SHA384 and AES-GCM.
Found out that neither Chromium nor Firefox support these higher ciphers.
The strongest/highest cipher available is TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
No support for SHA384 and no AES_256_GCM
https://www.ssllabs.com/ssltest/viewMyClient.html
Cipher Suites (in order of preference)
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (0xc02b)
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 (0x9e)
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (0xc00a)
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (0xc009)
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (0xc013)
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (0xc014)
TLS_ECDHE_ECDSA_WITH_RC4_128_SHA (0xc007)
TLS_ECDHE_RSA_WITH_RC4_128_SHA (0xc011)
TLS_DHE_RSA_WITH_AES_128_CBC_SHA (0x33)
TLS_DHE_DSS_WITH_AES_128_CBC_SHA (0x32)
TLS_DHE_RSA_WITH_AES_256_CBC_SHA (0x39)
TLS_RSA_WITH_AES_128_GCM_SHA256 (0x9c)
TLS_RSA_WITH_AES_128_CBC_SHA (0x2f)
TLS_RSA_WITH_AES_256_CBC_SHA (0x35)
TLS_RSA_WITH_3DES_EDE_CBC_SHA (0xa)
TLS_RSA_WITH_RC4_128_SHA (0x5)
TLS_RSA_WITH_RC4_128_MD5 (0x4)
The standard algorithm name documentation you're quoting is just the list of names, which are effectively reserved, but not necessarily implemented.
The SunJSSE provider (the default JSSE provider in the Oracle JRE) doesn't implement any GCM cipher suite in Java 7. They are in the updated table for the Java 8 implementation.
You might also need sslProtocol="TLSv1.2".
I am a web developer and facing the similar issue running the application with Tomcat 7 and Java7 versions and found the fix.
by adding the below property in the server.xml file of tomcat in
ciphers="TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_RSA_WITH_RC4_128_SHA,TLS_RSA_WITH_AES_128_CBC_SHA256, TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA,SSL_RSA_WITH_RC4_128_SHA"
For Firefox 37.0.2, the list of supported ciphers is:
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (0xc02b)
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (0xc00a)
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (0xc009)
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (0xc013)
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (0xc014)
TLS_DHE_RSA_WITH_AES_128_CBC_SHA (0x33)
TLS_DHE_RSA_WITH_AES_256_CBC_SHA (0x39)
TLS_RSA_WITH_AES_128_CBC_SHA (0x2f)
TLS_RSA_WITH_AES_256_CBC_SHA (0x35)
TLS_RSA_WITH_3DES_EDE_CBC_SHA (0xa)

Java TLS client can't find certificate when accessing soap service

I have a java app that runs inside Tomcat. It is trying to access a TLS client certificate authenticated SOAP service. All certificates being used are self-signed. I specify the trustStore and keyStore via the Java Options in Tomcat and I have also tried doing it in code for all the needed properties before creating my service. Both keyStore and trustStore are JKS with RSA certificates. I have verified the certificates exist in the server's trustStore and that the self client certificate exists in the client keyStore and that the hashes are the same.
Client side:
c:\Program Files\Java\jre7\bin>keytool -list -keystore c:\tomcat\certs\tomcat.keystore
Enter keystore password:
Keystore type: JKS
Keystore provider: SUN
Your keystore contains 1 entry
tomcat, Jan 20, 2014, PrivateKeyEntry,
Certificate fingerprint (SHA1): 78:F3:30:A0:40:B0:CC:8D:86:1F:99:FF:7C:3B:85:7C:6D:C7:F2:D2
Server side:
C:\Program Files (x86)\Java\jre7\bin>keytool -list -keystore c:\tomcat\certs\tomcat.truststore
Enter keystore password:
Keystore type: JKS
Keystore provider: SUN
Your keystore contains 1 entry
clientcert, Jan 23, 2014, trustedCertEntry,
Certificate fingerprint (SHA1): 78:F3:30:A0:40:B0:CC:8D:86:1F:99:FF:7C:3B:85:7C:6D:C7:F2:D2
When I start Tomcat I see the loading of the keystore like this:
keyStore is : c:\tomcat\certs\tomcat.keystore
keyStore type is : JKS
keyStore provider is :
init keystore
init keymanager of type SunX509
***
found key for : tomcat
chain [0] = [
[
Version: V3
Subject: CN=Name, OU=Engineering, O=MyOrg, ST=NJ, C=US
...
At the end of server hello I see the certificate DN that I expect and was loaded from the keystore above:
*** CertificateRequest
Cert Types: RSA, DSS, ECDSA
Cert Authorities:
<CN=Name, OU=Engineering, O=MyOrg, ST=NJ, C=US>
[read] MD5 and SHA1 hashes: len = 115
...
Then immediately after the ServerHelloDone I see an empty Certificate chain with no "matching alias: mycert" logging like I would expect to see.
*** ServerHelloDone
[read] MD5 and SHA1 hashes: len = 4
0000: 0E 00 00 00 ....
*** Certificate chain
***
Server side I get this:
http-nio-8443-exec-2, READ: TLSv1 Handshake, length = 269
*** Certificate chain
***
http-nio-8443-exec-2, fatal error: 42: null cert chain
javax.net.ssl.SSLHandshakeException: null cert chain
%% Invalidated: [Session-1, TLS_RSA_WITH_AES_128_CBC_SHA]
http-nio-8443-exec-2, SEND TLSv1 ALERT: fatal, description = bad_certificate
http-nio-8443-exec-2, WRITE: TLSv1 Alert, length = 2
http-nio-8443-exec-2, fatal: engine already closed. Rethrowing javax.net.ssl.SSLHandshakeException: null cert chain
http-nio-8443-exec-2, called closeOutbound()
http-nio-8443-exec-2, closeOutboundInternal()
When I take the client's certificate and I load it into my browser and navigate to the site, I am prompted to choose the certificate and able to see the wsdl and such. So I believe the certificate is fine.
The Java client uses it's trustStore specified in the Java options just fine to validate the server which makes me believe the trustStore is loaded and used just fine. Finally, here's the client piece of code I think is responsible for creating the service:
System.setProperty("javax.net.ssl.keyStore","C:\\tomcat\\certs\\tomcat.keystore");
System.setProperty("javax.net.ssl.keyStorePassword", "password");
System.setProperty("javax.net.ssl.keyStoreType", "JKS");
System.setProperty("javax.net.ssl.trustStore","C:\\tomcat\\certs\tomcat.truststore");
System.setProperty("javax.net.ssl.trustStorePassword", "password");
System.setProperty("javax.net.ssl.trustStoreType", "JKS");
URL url = DocumentRepositoryProxy.class.getClassLoader().getResource("XDS.b_DocumentRepositoryWSDLSynchMTOM.wsdl");
QName qname = new QName("urn:ihe:iti:xds-b:2007", "DocumentRepository_Service");
DocumentRepositoryService service = new DocumentRepositoryService(url, qname);
if (handlerResolver != null)
service.setHandlerResolver(handlerResolver);
proxy = service.getDocumentRepositoryPortSoap12(new MTOMFeature(true, 1));
BindingProvider bp = (BindingProvider) proxy;
SOAPBinding binding = (SOAPBinding) bp.getBinding();
binding.setMTOMEnabled(true);
bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endpoint);
I've spent the majority of a week going down this rabbit hole and if anyone can help it'll save me some hairs.
Here's the answer. In my WEB-INF/cxf-servlet.xml file for my WebApp I needed to add this chunk of XML and the associated namespaces. The Java options in code were ignored completely so I removed them. Once I added this and restarted Tomcat everything worked on the first try.
Namespaces:
xmlns:sec="http://cxf.apache.org/configuration/security"
xmlns:http="http://cxf.apache.org/transports/http/configuration"
Elements:
<http:conduit name="*.http-conduit">
<http:tlsClientParameters>
<sec:keyManagers keyPassword="XXX">
<sec:keyStore type="JKS"
password="password"
file="C:/tomcat/certs/tomcat.keystore"/>
</sec:keyManagers>
<sec:trustManagers>
<sec:keyStore type="JKS"
password="password"
file="C:\tomcat\certs\tomcat.truststore"/>
</sec:trustManagers>
</http:tlsClientParameters>
</http:conduit>

Categories

Resources