0

I have recently migrated an application which is protected by client certificates from tomcat 7 to tomcat 9. The tomcat is supposed to validate the client certificates based on the self-signed certificate located in the truststore.

The working tomcat 7 configuration used the following connector (taken from server.xml):

<Connector 
  port="8443" 
  ...
  clientAuth="true" 
  truststoreFile="/usr/share/tomcat/truststore.jks" 
  truststorePass="..." 
/>

I have migrated this according to the official documentation to the following configuration in tomcat 9:

<Connector port="8443" ...>
  <SSLHostConfig protocols="TLSv1.2" certificateVerification="required"
                 truststoreFile="/usr/share/tomcat9/truststore.jks"
                 truststorePassword="..."
                 truststoreType="PKCS12">  
  </SSLHostConfig>
  ...
</Connector>

When starting up tomcat 9, I get the following error:

java.lang.IllegalArgumentException: the trustAnchors parameter must be non-empty

Googling this error yields a bunch of results and this usually does seem to point towards an empty/ non-accessible truststore. My truststore is not empty and is located in the same directory also used for the keystore, which can be used without problems. And because the same truststore works with tomcat 7, I am running out of ideas on how to make progress on this issue. Anyone got any ideas? Thank you.

In case it matters, the truststore looks like this:

> keytool -list -keystore truststore.jks                                                                                                                                                                                              

Keystore type: PKCS12
Keystore provider: SUN

Your keystore contains 1 entry

mycert, Sep 15, 2021, PrivateKeyEntry,
Certificate fingerprint (SHA-256): ...
dlkmp
  • 125
  • 8
  • Does this answer your question? [Error - trustAnchors parameter must be non-empty](https://stackoverflow.com/questions/6784463/error-trustanchors-parameter-must-be-non-empty) – Piotr P. Karwasz Sep 15 '21 at 20:21
  • [This answer](https://stackoverflow.com/a/45496332/11748454) in particular applies to your case: you have no `trustedCertEntry` in your keystore. Using the same file as truststore in Tomcat 7.0 should fail too. – Piotr P. Karwasz Sep 15 '21 at 20:23
  • 2
    @PiotrP.Karwasz: no it shouldn't or at least doesn't. Older Tomcat directly uses the JSSE TrustManager, which undocumentedly includes chain[0] from a privatekeyentry; see https://stackoverflow.com/questions/36576061/does-jsse-use-a-certificate-in-a-privatekeyentry-as-a-trust-anchor . This also works for _server_ auth in things like HttpsURLConnection. Tomcat 8.5 up has new logic to combine KeyStore (Java) and OpenSSL (PEM) configs, which (somehow?) alters this. But yes the solution is to use a trustedcertentry. – dave_thompson_085 Sep 16 '21 at 00:42
  • 1
    @dave_thompson_085: nice catch, indeed a different `TrustManagerFactory.init` method is called in Tomcat 8.5+ (cf. [source code](https://github.com/apache/tomcat/blob/dee5f2c1f744e789ab3a422de79385222d07ba6e/java/org/apache/tomcat/util/net/SSLUtilBase.java#L433)). To restore the previous behavior one might set `truststoreAlgorithm="SunPKIX"` (or any other alias for `PKIX`). – Piotr P. Karwasz Sep 16 '21 at 06:36

1 Answers1

3

Thanks to the analysis and comments by dave_thompson_085 and Piotr P. Karwasz, I could resolve the issue by adding truststoreAlgorithm="SunPKIX" to the connector configuration.

As they pointed out, this answer might be an alternative solution but involves modifying the truststore.

dlkmp
  • 125
  • 8