Tomcat - Two Way SSL as Server - java

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.

Related

How to send TLS client certificate with no certification chain without modifying Java application source?

Gradle project needs to deploy build results to private Artifactory server. Latter requires client TLS authentication. User certificates are provided by server owner as a keystore with 1 private key entry, and that entry has certification chain of size 1:
Keystore type: JKS
Keystore provider: SUN
Your keystore contains 1 entry
Alias name: myalias
Creation date: 08.09.2020
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=myuser, O=Sharaga Inc, C=Far far away
Issuer: CN=CA, O=Sharaga Inc, C=Far far away
...
When Gradle tries to connect to server, Java TLS implementation refuses to send client certificate:
*** CertificateRequest
Cert Types: RSA, DSS, ECDSA
Supported Signature Algorithms: SHA256withRSA, SHA256withDSA, SHA256withECDSA, SHA384withRSA, Unknown (hash:0x5, signature:0x2), SHA384withECDSA, SHA512withRSA, Unknown (hash:0x6, signature:0x2), SHA512withECDSA, SHA1withRSA, SHA1withDSA, SHA1withECDSA
Cert Authorities:
<CN=CA, O=Sharaga Inc, C=Far far away>
pool-1-thread-1, READ: TLSv1.2 Handshake, length = 4
*** ServerHelloDone
Warning: no suitable certificate found - continuing without client authentication
*** Certificate chain
<Empty>
This behavior is observed under Java 8 and Java 11, both on Linux and Windows.
I tried to access the server with test application by modifying key manager implementation so that it always chooses "myalias" to send to server, and it worked:
// Uses Artifactory client library:
// https://github.com/jfrog/artifactory-client-java
PrivateKeyStrategy aliasStrategy = new PrivateKeyStrategy() {
#Override
public String chooseAlias(Map<String,PrivateKeyDetails> aliases, Socket socket) {
return "myalias";
}
};
char[] password = "keystorepassword".toCharArray();
Artifactory artifactory = ArtifactoryClientBuilder.create()
.setUrl("https://theserver/artifactory")
.setUsername("myuser")
.setPassword("mypassword")
.setSslContextBuilder(SSLContexts.custom().loadKeyMaterial(new File("mykeystore.pfx"), password, password, aliasStrategy))
.build();
TLS debug output:
*** CertificateRequest
Cert Types: RSA, DSS, ECDSA
Supported Signature Algorithms: SHA256withRSA, SHA256withDSA, SHA256withECDSA, SHA384withRSA, Unknown (hash:0x5, signature:0x2), SHA384withECDSA, SHA512withRSA, Unknown (hash:0x6, signature:0x2), SHA512withECDSA, SHA1withRSA, SHA1withDSA, SHA1withECDSA
Cert Authorities:
<CN=CA, O=Sharaga Inc, C=Far far away>
main, READ: TLSv1.2 Handshake, length = 4
*** ServerHelloDone
matching alias: myalias
*** Certificate chain
chain [0] = [
[
Version: V3
Subject:CN=myuser, O=Sharaga Inc, C=Far far away
Signature Algorithm: SHA256withRSA, OID = 1.2.840.113549.1.1.11
...
(Chain length is 1 here, but handshake succeeds.)
Is there a way to send client certificate without certification chain forcefully in existing Java application without changing/recompiling it? Maybe there are some system properties to tune this behavior?
After some debugging I found the reason. javax.net.ssl.keyStore* system properties do not affect Gradle Artifactory Plugin, it knew nothing about client certificate, and certificate chain was in fact empty (zero length).
If there is at least one certificate in a chain then it is sent to server successfully.

Java HTTPS client fails SSL handshake while curl succeeds

Apologies up front, I'm still pretty new to coding for SSL. I've been searching for answers for the past few days, and while I've found a lot of suggestions nothing has worked so far.
What I have is a server implemented on top of Dropwizard that needs to accept an incoming HTTPS connection and use the attached certificate to uniquely identify the client. I am currently using all self-signed certificates while I'm in development. The server certificate pair was created using a chain - root pair -> intermediate pair -> server pair. The server's P12 was created using a concatenation of the intermediate and server certificates plus the server private key. It was then added to an empty JKS and became the server's KeyStore.
Separately I've created two client certificates, one using the same intermediate pair as the base, and another as a pure stand-alone certificate pair. The x509 public key portion of both of these certificate pairs was added to a JKS file and became the server's TrustStore. The Dropwizard configuration follows:
type: "https"
port: "9843"
keyStorePath: "keystore.jks"
keyStorePassword: "changeme"
keyStoreType: "JKS"
trustStorePath: "truststore.jks"
trustStorePassword: "changeme"
trustStoreType: "JKS"
allowRenegotiation: false
validateCerts: false
validatePeers: false
needClientAuth: true
wantClientAuth: true
I can connect to the server using curl and either of the client certificate pairs:
curl -v --cert client.pem --key client.key -k https://localhost:9843/v1/ld
With SSL debug turned on, the server logs the following:
*** 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=*.me.com, O=Me, ST=Massachusetts, C=US>
<O=Internet Widgits Pty Ltd, ST=Massachusetts, C=US>
*** ServerHelloDone
dw-51, WRITE: TLSv1.2 Handshake, length = 3536
dw-44, READ: TLSv1.2 Handshake, length = 1047
*** Certificate chain
chain [0] = [
[
Version: V3
Subject: O=Internet Widgits Pty Ltd, L=North Reading, ST=Massachusetts, C=US
Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5
Key: Sun RSA public key, 2048 bits
modulus: 23250299629324311533731283912176366463399376328149948822580485256237233115567136794461732268017120297060017586981907979910958857247642884566364833267711927344361604478514119965230314679194017013023991389216461419030751049820266939279047536006291610734616600760688907006770883510297954698233112783686968024400749969025850008781641616624298935923926427096257861170476293580684942956111432790304698635393966967864288730561678135798437678912431564767611000006312358137647455886578135011989168265295083928014176435879778838966450081419161406209555593636745048857672445188811541416453143809594265089422302064600885289819601
public exponent: 65537
Validity: [From: Wed Dec 05 13:52:49 EST 2018,
To: Thu Dec 05 13:52:49 EST 2019]
Issuer: O=Internet Widgits Pty Ltd, ST=Massachusetts, C=US
SerialNumber: [ 8174655c c8387da4]
Certificate Extensions: 3
...
So far so good. Next I try to connect to my server using a Java client using the same certificate pair, combined in a single P12 file. Java code follows:
char[] password = "changeme".toCharArray();
KeyStore keystore = KeyStore.getInstance("PKCS12");
try (FileInputStream fileInputStream = new FileInputStream("client.p12")) {
keystore.load(fileInputStream, password);
}
SSLContext sslContext =
SSLContexts.custom()
.loadKeyMaterial(keystore, password)
.loadTrustMaterial(null, (chain, authType) -> true)
.build();
return HttpClients.custom()
.setSSLContext(sslContext)
.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
.build();
But when this client tries to connect the server logs the following:
*** 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=*.me.com, O=Me, ST=Massachusetts, C=US>
<O=Internet Widgits Pty Ltd, ST=Massachusetts, C=US>
*** ServerHelloDone
Warning: no suitable certificate found - continuing without client authentication
*** Certificate chain
<Empty>
***
I have also tried using a SSLConnectionSocketFactory initialized with the sslContext, and a Registry<ConnectionSocketFactory> registering the socketFactory for "https". Nothing has worked. I am totally at a loss as to why curl accepts the cert authorities and sends the client certificate but the java httpClient does not.
EDIT:
I tried adding the server's public certificate to the client request, it did not make a difference - I'm still seeing the same behavior. The code was updated as follows:
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(null, null);
try (FileInputStream fileInputStream = new FileInputStream("server.cert.pem")) {
try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(IOUtils.toByteArray(fileInputStream))) {
CertificateFactory certificateFactory = CertificateFactory.getInstance("X509");
Certificate certificate = certificateFactory.generateCertificate(byteArrayInputStream);
trustStore.setCertificateEntry("server", certificate);
}
}
SSLContext sslContext =
SSLContexts.custom()
.loadKeyMaterial(keystore, password)
.loadTrustMaterial(trustStore, (chain, authType) -> true)
.build();
So I ended up completely reworking how my certificates were being generated and I was able to get things working, with a caveat: it depended how the certificates were generated.
Works with Java client, curl, and Postman:
openssl genrsa -aes256 -out private/${SVRNAME}.key.pem 2048
openssl req -config ${CONFIGDIR}/openssl.cnf \
-new -x509 -days 7300 -sha256 -extensions v3_ca \
-key private/${SVRNAME}.key.pem \
-out certs/${SVRNAME}.cert.pem
Works with curl and Postman but not Java client:
openssl req -newkey rsa:2048 -nodes \
-keyout private/${CLINAME}.key.pem \
-x509 -days 365 -out certs/${CLINAME}.cert.pem
Not sure why the "quick" certificate caused so many problems but at least it is working now. Thanks to Patrick and Dave for the help!

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 7 / 8 and IBM JRE won't initialize DSA key

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.

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