Repository navigation
Description
Hello,
we are currently investigating a TLS issue after upgrading our application from Apache CXF 3.4.4 to Apache CXF 4.1.4. The application is started via OpenWebStart.
Scenario
Our server uses a certificate that is signed by our own internal Root CA.
- The Root CA is installed in the Windows certificate store (Windows-ROOT).
- The Root CA is not imported into the Java
cacertstruststore. - The server sends the complete certificate chain.
- The certificate itself appears to be valid (verified with
openssl s_client).
With CXF 3.4.4 the application starts successfully via OpenWebStart.
After upgrading to CXF 4.1.4 the TLS handshake fails with
sun.security.validator.ValidatorException:
PKIX path building failed:
sun.security.provider.certpath.SunCertPathBuilderException:
unable to find valid certification path to requested target
One additional observation makes us suspect that OpenWebStart might perform some certificate or truststore handling internally:
When we start the same application locally (without OpenWebStart) and connect to servers using our internal Root CA, we have always had to explicitly specify
-Djavax.net.ssl.trustStoreType=Windows-ROOT
Otherwise the connection fails, which is the expected behavior because the Root CA is only installed in the Windows certificate store.
However, when starting the application via OpenWebStart, this has never been necessary with the older CXF version. This makes us wonder whether OpenWebStart automatically integrates or exposes the Windows certificate store to the application in some way.
What changed
The most relevant change seems to be that CXF 4.x uses the JDK java.net.http.HttpClient (HttpClientHTTPConduit) by default, whereas CXF 3.4.x used the classic URLConnectionHTTPConduit.
Certificate generation (for reproduction)
The certificates were generated using the following OpenSSL commands:
# Create Root CA
openssl genrsa -aes256 -out ca-key.pem -passout pass:foobar 2048
openssl req -x509 -new -nodes -extensions v3_ca \
-key ca-key.pem \
-passin pass:foobar \
-days 3650 \
-out ca-root.pem \
-sha512 \
-subj "/C=DE/ST=/L=/O=/OU=/CN=Meine Test Root CA"
# Create server certificate
openssl genrsa -out localhost-key.pem -passout pass:foobar 2048
openssl req -new \
-key localhost-key.pem \
-passin pass:foobar \
-out localhost.csr \
-sha512 \
-subj "/C=DE/ST=/L=/O=/OU=/CN=localhost"
openssl x509 -req \
-in localhost.csr \
-CA ca-root.pem \
-CAkey ca-key.pem \
-passin pass:foobar \
-CAcreateserial \
-out localhost-pub.pem \
-days 3650 \
-sha512 \
-extfile <(printf "subjectAltName=DNS:localhost,IP:127.0.0.1,IP:::1")
# Create PKCS#12 keystore containing the server certificate and the Root CA
openssl pkcs12 -export \
-in localhost-pub.pem \
-inkey localhost-key.pem \
-out localhost-mit-ca.pfx \
-certfile ca-root.pem \
-passout pass:foobarWhat we tested
Default behavior
- CXF 3.4.4 + OpenWebStart → works
- CXF 4.1.4 + OpenWebStart → fails with PKIX error
Force Windows certificate store
Starting the application with
SET "JAVA_TOOL_OPTIONS=-Djavax.net.ssl.trustStoreType=Windows-ROOT"
javaws jnlp.jnlpmakes the CXF 4.1.4 version work again.
Force old CXF transport
Starting the application with
SET "JAVA_TOOL_OPTIONS=-Dorg.apache.cxf.transport.http.forceURLConnection=true"
javaws jnlp.jnlpalso makes the application work again.
Our question
Does OpenWebStart perform any special handling regarding certificate validation or truststores?
More specifically:
- Does OpenWebStart integrate the Windows certificate store into the JVM trust configuration?
- Does it modify the default
SSLContext,TrustManager, orHttpsURLConnectionconfiguration? - Is this integration only effective for
HttpsURLConnection(used by older CXF versions), while the newer JDKjava.net.http.HttpClientbypasses it?
Our observations suggest that OpenWebStart may provide certificate handling that works with HttpsURLConnection, but that this is no longer picked up by applications using the newer JDK HTTP client.
Could you clarify whether this is expected behavior, a known limitation, or whether additional configuration is required for applications using java.net.http.HttpClient?
Thank you.
Activity
AlBundy33 commentedon Jul 3, 2026
While discussing this issue with ChatGPT, we came up with a possible explanation. This is only a hypothesis and I would like to verify whether it actually applies to OpenWebStart.
The idea is that
HttpsURLConnectionandjava.net.http.HttpClientmight obtain their TLS configuration in different ways.If OpenWebStart customizes
HttpsURLConnection(for example viaHttpsURLConnection.setDefaultSSLSocketFactory(...)) but does not configure the JVM's defaultSSLContext, this could explain why applications usingURLConnectionwork while applications usingjava.net.http.HttpClientdo not.While investigating this further, I also looked into the IcedTea-Web sources and found this code:
https://github.com/AdoptOpenJDK/IcedTea-Web/blob/ca7af3366ef3e93a99477ca287df6a59595fcaa2/core/src/main/java/net/sourceforge/jnlp/runtime/JNLPRuntime.java#L290
A few questions:
JNLPRuntimethe runtime that is actually used by the launched application?SSLSocketFactory,TrustManager, orSSLContextfor the launched application?If the Windows trust store is indeed loaded, would it make sense to also configure the JVM's default
SSLContextso thatjava.net.http.HttpClientuses the same trust configuration asHttpsURLConnection?Thank you.
janakmulani commentedon Jul 4, 2026
@AlBundy33
However, when starting the application via OpenWebStart, this has never been necessary with the older CXF version. This makes us wonder whether OpenWebStart automatically integrates or exposes the Windows certificate store to the application in some way.
OWS does not automatically access Windows Certificate Store.
A workaround to manually adding certificates from Windows Cert Store to Java Cert Stores would be to specify the following JVM argument in the Jnlp file:
-Djavax.net.ssl.trustStoreType=Windows-ROOTFor this VM argument to be accepted by OWS you will need to add it to the whitelist in the deployment.properties file:
deployment.jvm.arguments.whitelist=-Djavax.net.ssl.trustStoreTypeDoes OpenWebStart integrate the Windows certificate store into the JVM trust configuration?
Does it modify the default SSLContext, TrustManager, or HttpsURLConnection configuration?
Is this integration only effective for HttpsURLConnection (used by older CXF versions), while the newer JDK java.net.http.HttpClient bypasses it?
OWS does not integrate Windows Cert Store.
OWS modifies SSL Context - it uses in stage1, the truststore of bundled JRE and in stage2, the trurtstore of the JRE used to launch the Jnlp. Moreover it also uses truststores created by it .config\icedtea-web\security dir.
See JnlpRuntime.initilize
Haven't tried java.net.http.HttpClient but have tried Apache HttpClient5, which needs to explicitly reconfigured.
AlBundy33 commentedon Jul 4, 2026
Set javax.net.ssl.trustStoreType for webstart is not a solution because admins have to modify the deployment.properties.
I've found my certificate in
~/.config\icedtea-web\security\trusted.certs(also shown in OpenWebStart Settings).So it seems that the trusted certs are also passed to started application.
Is there a documentation how to build OWS with ITW then I can check if settings the default sslconext solves the issue.
janakmulani commentedon Jul 4, 2026
<path>\jdk-1.8<path>\jdk-1.8AlBundy33 commentedon Jul 4, 2026
I've prepared some scripts but haven't tested ows yet.
build.sh
run.sh
AlBundy33 commentedon Jul 6, 2026
calling SSLContext.setDefault after HttpsURLConnection.setDefaultSSLSocketFactory seems not to work. :-/
AlBundy33 commentedon Jul 6, 2026
But maybe
SSLContext.setDefaultis a still a good idea if someone uses the HttpClient-API and works with selfsigned certificates 🤔janakmulani commentedon Jul 6, 2026
@AlBundy33 Will have a look.
AlBundy33 commentedon Jul 7, 2026
SSLContext.setDefault in JNLPRuntime together with a modifed CXF initialization works as expected.
We always set
tlsClientParameters.setUseHttpsURLConnectionDefaultSslSocketFactory(true);which explains why URLConnectionHTTPConduit works.(Because JNLPRuntime sets
HttpsURLConnection.setDefaultSSLSocketFactory)janakmulani commentedon Jul 7, 2026
@AlBundy33 can you please give steps to reproduce this issue?
AlBundy33 commentedon Jul 8, 2026
AlBundy33 commentedon Jul 8, 2026
AlBundy33 commentedon Jul 8, 2026
The attached test class intentionally uses only plain JDK APIs to demonstrate the behavior of
HttpsURLConnection.setDefaultSSLSocketFactory(...)andSSLContext.setDefault(...).It reproduces the underlying JDK behavior without involving CXF. This seems to explain the different behavior of the two CXF HTTP conduits:
URLConnectionHTTPConduitis based onHttpsURLConnectionand can be configured to use the defaultSSLSocketFactory(e.g. viaTLSClientParameters.setUseHttpsURLConnectionDefaultSslSocketFactory(true)), allowing it to benefit from a socket factory installed by OpenWebStart.HttpClientHTTPConduitis based onjava.net.http.HttpClientand can be configured with an explicitSSLContext(e.g. viaTLSClientParameters.setSslContext(...)). If the OpenWebStartSSLContextis not directly accessible or cannot easily be recreated, usingSSLContext.getDefault()would be a viable option—provided that OpenWebStart also installs its configuredSSLContextviaSSLContext.setDefault(...).In my opinion, calling
SSLContext.setDefault(...)in addition toHttpsURLConnection.setDefaultSSLSocketFactory(...)would make the OpenWebStart SSL configuration consistently available to both legacy and modern JDK HTTP client implementations.janakmulani commentedon Jul 8, 2026
@AlBundy33 Thanks. I will have a look.
AlBundy33 commentedon Jul 8, 2026
I had opencode perform an automated cross-check of the assumptions in this issue against the actual source code of IcedTea-Web, OpenJDK 17, and Apache CXF, and summarize the findings.
Findings
1. IcedTea-Web
JNLPRuntime.initialize()— only setsHttpsURLConnection.setDefaultSSLSocketFactoryLink
The code creates a custom
SSLContextwithVariableX509TrustManagerbut only registers it viaHttpsURLConnection.setDefaultSSLSocketFactory(sslSocketFactory). There is noSSLContext.setDefault(context)call. The customtrust configuration is therefore only visible to
HttpsURLConnection, not to the JVM-wide defaultSSLContext.2. OpenJDK 17
HttpClientImpl— usesSSLContext.getDefault()at construction timeLink
HttpClient.newHttpClient()→newBuilder().build()callsSSLContext.getDefault()once in the constructor:3. CXF
URLConnectionHTTPConduit(CXF 3.x) — can pick up ITW's socket factoryLink
When
isUseHttpsURLConnectionDefaultSslSocketFactory()is set, the conduit readsHttpsURLConnection.getDefaultSSLSocketFactory()— the factory that ITW installs.4. CXF
HttpClientHTTPConduit(CXF 4.x) — creates its own SSLContext, never usesSSLContext.getDefault()Link
SSLUtils.getSSLContext()always creates a fresh context viaSSLContext.getInstance("TLS")and initializes it with trust managers loaded fromjavax.net.ssl.trustStoresystem properties. It never callsSSLContext.getDefault().Conclusion
The root cause has two layers:
JNLPRuntime.java): AddingSSLContext.setDefault(context)would make the custom SSLContext available via the JVM-wide default.HttpClientHTTPConduit): Even withSSLContext.setDefault()in place, CXF still creates its own SSLContext viaSSLUtils.getSSLContext(). A customHTTPConduitConfigurerthat callstlsClientParameters.setSslContext(SSLContext.getDefault())— as demonstrated in comment 9 — bridges the gap.The combination of both changes ensures that ITW's certificate trust configuration is consistently available to both
URLConnection-based andHttpClient-based HTTP clients.