javatomcattomcat9java-security

Tomcat 9 server: javax.net.ssl.SSLHandshakeException: Empty server certificate chain


I am trying to establish ssl connection to tomact server which I ve installed at my local machine. The server.xml has following entries:

<Connector
       protocol="org.apache.coyote.http11.Http11NioProtocol"
       port="8443" maxThreads="200"
       scheme="https" secure="true" SSLEnabled="true"
       sslImplementationName="localSSLImplementation keystoreFile="~/localhost.p12" 
       keystorePass="myPassword"
       keystoreType="PKCS12"
       
       truststoreFile="~/truststore.p12"
       truststorePass="changeit"
       truststoreType="PKCS12"
       truststoreProvider="SUN"
       clientAuth="required" sslProtocol="TLS"  sslEnabledProtocols="TLSv1.1,TLSv1.2"/>

I have a self signed certificate and private-public key pair present at localhost.p12

I exported this certificate and imported it in truststore.p12, which has entries imported from JRE's cacerts as well.

Now when clientAuth="optional" is set I can connect to tomcat server seamlessly but I can see the stackTrace for tomcat in my eclipse as follows :

javax.net.ssl|DEBUG|15|https-jsse-nio-8443-exec-6|2021-04-22 12:43:24.104 IST|Alert.java:238|Received alert message (
"Alert": {
  "level"      : "fatal",
  "description": "certificate_unknown"
}
)
javax.net.ssl|DEBUG|14|https-jsse-nio-8443-exec-5|2021-04-22 12:43:24.104 IST|Alert.java:238|Received alert message (
"Alert": {
  "level"      : "fatal",
  "description": "certificate_unknown"
}
)
javax.net.ssl|ERROR|15|https-jsse-nio-8443-exec-6|2021-04-22 12:43:24.106 IST|TransportContext.java:341|Fatal (CERTIFICATE_UNKNOWN): Received fatal alert: certificate_unknown (
"throwable" : {
  javax.net.ssl.SSLHandshakeException: Received fatal alert: certificate_unknown
    at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131)
    at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:117)
    at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:336)
    at java.base/sun.security.ssl.Alert$AlertConsumer.consume(Alert.java:293)
    at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:185)
    at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:171)
    at java.base/sun.security.ssl.SSLEngineImpl.decode(SSLEngineImpl.java:681)
    at java.base/sun.security.ssl.SSLEngineImpl.readRecord(SSLEngineImpl.java:636)
    at java.base/sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:454)
    at java.base/sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:433)
    at java.base/javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:637)
    at org.apache.tomcat.util.net.SecureNioChannel.handshakeUnwrap(SecureNioChannel.java:511)
    at org.apache.tomcat.util.net.SecureNioChannel.handshake(SecureNioChannel.java:243)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1685)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.base/java.lang.Thread.run(Thread.java:829)}

)
javax.net.ssl|ERROR|14|https-jsse-nio-8443-exec-5|2021-04-22 12:43:24.106 IST|TransportContext.java:341|Fatal (CERTIFICATE_UNKNOWN): Received fatal alert: certificate_unknown (
"throwable" : {
  javax.net.ssl.SSLHandshakeException: Received fatal alert: certificate_unknown
    at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131)
    at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:117)
    at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:336)
    at java.base/sun.security.ssl.Alert$AlertConsumer.consume(Alert.java:293)
    at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:185)
    at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:171)
    at java.base/sun.security.ssl.SSLEngineImpl.decode(SSLEngineImpl.java:681)
    at java.base/sun.security.ssl.SSLEngineImpl.readRecord(SSLEngineImpl.java:636)
    at java.base/sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:454)
    at java.base/sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:433)
    at java.base/javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:637)
    at org.apache.tomcat.util.net.SecureNioChannel.handshakeUnwrap(SecureNioChannel.java:511)
    at org.apache.tomcat.util.net.SecureNioChannel.handshake(SecureNioChannel.java:243)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1685)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.base/java.lang.Thread.run(Thread.java:829)}

)
javax.net.ssl|ALL|16|https-jsse-nio-8443-exec-7|2021-04-22 12:43:24.116 IST|X509Authentication.java:295|No X.509 cert selected for EC
javax.net.ssl|ALL|19|https-jsse-nio-8443-exec-10|2021-04-22 12:43:24.151 IST|X509Authentication.java:295|No X.509 cert selected for EC
javax.net.ssl|ALL|18|https-jsse-nio-8443-exec-9|2021-04-22 12:43:24.187 IST|SSLEngineImpl.java:752|Closing outbound of SSLEngine
javax.net.ssl|WARNING|18|https-jsse-nio-8443-exec-9|2021-04-22 12:43:24.188 IST|SSLEngineOutputRecord.java:168|outbound has closed, ignore outbound application data
javax.net.ssl|ALL|10|https-jsse-nio-8443-exec-1|2021-04-22 12:43:24.406 IST|SSLEngineImpl.java:752|Closing outbound of SSLEngine
javax.net.ssl|ALL|13|https-jsse-nio-8443-exec-4|2021-04-22 12:43:24.432 IST|SSLEngineImpl.java:752|Closing outbound of SSLEngine
javax.net.ssl|ALL|13|https-jsse-nio-8443-exec-4|2021-04-22 12:43:24.433 IST|SSLEngineImpl.java:752|Closing outbound of SSLEngine
javax.net.ssl|ALL|11|https-jsse-nio-8443-exec-2|2021-04-22 12:43:24.438 IST|SSLEngineImpl.java:752|Closing outbound of SSLEngine
javax.net.ssl|ALL|11|https-jsse-nio-8443-exec-2|2021-04-22 12:43:24.441 IST|SSLEngineImpl.java:752|Closing outbound of SSLEngine

Questionon 1:- I don't if that should be happening or not as I have specified the same certificate in truststoreFile

Question 2:- if I change the clientAuth="required", which I intend to do, I observer following stack-trace along with warning in chrome.

stackTrace:-

avax.net.ssl|ALL|11|https-jsse-nio-8443-exec-2|2021-04-22 12:48:16.627 IST|X509Authentication.java:295|No X.509 cert selected for EC
javax.net.ssl|ALL|10|https-jsse-nio-8443-exec-1|2021-04-22 12:48:16.627 IST|X509Authentication.java:295|No X.509 cert selected for EC
javax.net.ssl|DEBUG|14|https-jsse-nio-8443-exec-5|2021-04-22 12:48:16.660 IST|Alert.java:238|Received alert message (
"Alert": {
  "level"      : "fatal",
  "description": "certificate_unknown"
}
)
javax.net.ssl|DEBUG|15|https-jsse-nio-8443-exec-6|2021-04-22 12:48:16.660 IST|Alert.java:238|Received alert message (
"Alert": {
  "level"      : "fatal",
  "description": "certificate_unknown"
}
)
javax.net.ssl|ERROR|14|https-jsse-nio-8443-exec-5|2021-04-22 12:48:16.662 IST|TransportContext.java:341|Fatal (CERTIFICATE_UNKNOWN): Received fatal alert: certificate_unknown (
"throwable" : {
  javax.net.ssl.SSLHandshakeException: Received fatal alert: certificate_unknown
    at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131)
    at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:117)
    at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:336)
    at java.base/sun.security.ssl.Alert$AlertConsumer.consume(Alert.java:293)
    at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:185)
    at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:171)
    at java.base/sun.security.ssl.SSLEngineImpl.decode(SSLEngineImpl.java:681)
    at java.base/sun.security.ssl.SSLEngineImpl.readRecord(SSLEngineImpl.java:636)
    at java.base/sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:454)
    at java.base/sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:433)
    at java.base/javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:637)
    at org.apache.tomcat.util.net.SecureNioChannel.handshakeUnwrap(SecureNioChannel.java:511)
    at org.apache.tomcat.util.net.SecureNioChannel.handshake(SecureNioChannel.java:243)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1685)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.base/java.lang.Thread.run(Thread.java:829)}

)
javax.net.ssl|ERROR|15|https-jsse-nio-8443-exec-6|2021-04-22 12:48:16.662 IST|TransportContext.java:341|Fatal (CERTIFICATE_UNKNOWN): Received fatal alert: certificate_unknown (
"throwable" : {
  javax.net.ssl.SSLHandshakeException: Received fatal alert: certificate_unknown
    at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131)
    at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:117)
    at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:336)
    at java.base/sun.security.ssl.Alert$AlertConsumer.consume(Alert.java:293)
    at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:185)
    at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:171)
    at java.base/sun.security.ssl.SSLEngineImpl.decode(SSLEngineImpl.java:681)
    at java.base/sun.security.ssl.SSLEngineImpl.readRecord(SSLEngineImpl.java:636)
    at java.base/sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:454)
    at java.base/sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:433)
    at java.base/javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:637)
    at org.apache.tomcat.util.net.SecureNioChannel.handshakeUnwrap(SecureNioChannel.java:511)
    at org.apache.tomcat.util.net.SecureNioChannel.handshake(SecureNioChannel.java:243)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1685)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.base/java.lang.Thread.run(Thread.java:829)}

)
javax.net.ssl|ALL|16|https-jsse-nio-8443-exec-7|2021-04-22 12:48:16.669 IST|X509Authentication.java:295|No X.509 cert selected for EC
javax.net.ssl|ERROR|18|https-jsse-nio-8443-exec-9|2021-04-22 12:48:16.680 IST|TransportContext.java:341|Fatal (BAD_CERTIFICATE): Empty server certificate chain (
"throwable" : {
  javax.net.ssl.SSLHandshakeException: Empty server certificate chain
    at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131)
    at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:117)
    at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:336)
    at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:292)
    at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:283)
    at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.onCertificate(CertificateMessage.java:390)
    at java.base/sun.security.ssl.CertificateMessage$T12CertificateConsumer.consume(CertificateMessage.java:375)
    at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:392)
    at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:443)
    at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask$DelegatedAction.run(SSLEngineImpl.java:1074)
    at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask$DelegatedAction.run(SSLEngineImpl.java:1061)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask.run(SSLEngineImpl.java:1008)
    at org.apache.tomcat.util.net.SecureNioChannel.tasks(SecureNioChannel.java:455)
    at org.apache.tomcat.util.net.SecureNioChannel.handshakeUnwrap(SecureNioChannel.java:519)
    at org.apache.tomcat.util.net.SecureNioChannel.handshake(SecureNioChannel.java:243)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1685)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.base/java.lang.Thread.run(Thread.java:829)}

)
javax.net.ssl|WARNING|18|https-jsse-nio-8443-exec-9|2021-04-22 12:48:16.682 IST|SSLEngineOutputRecord.java:168|outbound has closed, ignore outbound application data

Text Displayed in chrome:- when I try to connect to https://localhost:8443

This site can’t provide a secure connectionlocalhost didn’t accept your login certificate, or one may not have been provided.
Try contacting the system admin.
ERR_BAD_SSL_CLIENT_AUTH_CERT

If I try to establish connection through ssl clientI see following error:

SSL handshake has read 16672 bytes and written 388 bytes
Verification error: self signed certificate

======================================================================== Editing this post

commented section from Dave did help me to resolve my second issue, in which case I added self-signed cert to chrome.

But for first question, I am still able to see in my tomcat server's logs stack trace exactly similar to the first stack trace that I posted. So now my query is as I have imported the same root in server's truststore which has signed my client certificate. So why do I see javax.net.ssl.SSLHandshakeException: Received fatal alert: certificate_unknown in stack trace whenever I establish the connection from client to server?


Solution

  • Refer comment from Dave. I just figured out that the stack trace that I see saying certificate_unknown is because client doesn't trust my server's certificate which is a self-signed certificate. So that's normal as my browser doesn't trust the local certificate. If it is signed by authorized CA then that will solve the problem.