javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate

tip

Import the server certificate into your truststore.

You have a different solution? A short tip here would help you and many other users who saw this issue last week.

  • h3. Background This problem happens especially in GFv3.x as the following JVM options is added -Dcom.sun.enterprise.security.httpsOutboundKeyAlias=s1as The impact of this is that it sets the default client cert to be sent is s1as. Although this option is there is GFv2, it was not enabled in the JVM options. So no issues unless one set it. Now the internals of GFv3 opensource suggest that on startup 1) GFv301 will replace the HttpsURLConnection setDefault to have a KeyManager that will sent "httpsOutboundKeyAlias"/s1as is client cert is requested. 2) Gfv312 also does this 3) Now in GFv301, it does not set the SSLContext but in GFv312x due to change GLASSFISH-15369, it seems that SSLContext.setDefault() is called to make the SSLContext have a default key manager that will submit s1as as the client cert if requested Well the behaviour is that things that work say in GFv2 may not work in GFv301 (if URLConnection to a https://... that does optional client cert request). For example ==> https://www.java.net//forum/topic/glassfish/glassfish/axis2-generated-stub-soap-webservice-call-not-working-glassfish-312?force=516 where javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate may happen in GFV312 (but may work in GFv301) due to (3). h3. Now the problem is this The issue is that a) GFv3 set the default alias to sent the client cert globally b) In GFv312, SSL artifact created from HttpsURLConnection and SSLContext will have this KeyManager that does chooseClientAlias() from X509ExtendedKeymanager and always returns s1as irregardless if the issuer matches with s1as +Look at J2EEKeyManager.java+ https://java.net/projects/glassfish/sources/svn/content/tags/3.1.2/security/core/src/main/java/com/sun/enterprise/security/ssl/J2EEKeyManager.java As you may see, from the code, the fix/issues are: a) Not setting com.sun.enterprise.security.httpsOutboundKeyAlias may help (if you do not ever use client cert) but the code may always return null for some conditions (ie: !server&!acc) b) Even if the property is explicitly set, the chooseClientAlias should still check if this alias is compatible with what the SSL server requested otherwise it should return NULL +Symptom+ For this issue even if you added all the SSL cert to the client trust store, if the remote SSL server ask for say an optional client cert (or required), the handshake will fail since the wrong client cert (self-signed s1as) is submitted which is totally different from the valid cert the server accepts. {noformat} javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate at sun.security.ssl.Alerts.getSSLException(Alerts.java:192) at sun.security.ssl.Alerts.getSSLException(Alerts.java:154) at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1961) at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1077) at sun.security.ssl.SSLSocketImpl.waitForClose(SSLSocketImpl.java:1707) at sun.security.ssl.HandshakeOutStream.flush(HandshakeOutStream.java:122) at sun.security.ssl.Handshaker.sendChangeCipherSpec(Handshaker.java:972) at sun.security.ssl.ClientHandshaker.sendChangeCipherAndFinish(ClientHandshaker.java:1087) at sun.security.ssl.ClientHandshaker.serverHelloDone(ClientHandshaker.java:1006) at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:285) at sun.security.ssl.Handshaker.processLoop(Handshaker.java:868) at sun.security.ssl.Handshaker.process_record(Handshaker.java:804) at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1016) at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1312) at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1339) at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1323) at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:515) at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185) {noformat}
    via by gfuser9999,
  • h3. Background This problem happens especially in GFv3.x as the following JVM options is added -Dcom.sun.enterprise.security.httpsOutboundKeyAlias=s1as The impact of this is that it sets the default client cert to be sent is s1as. Although this option is there is GFv2, it was not enabled in the JVM options. So no issues unless one set it. Now the internals of GFv3 opensource suggest that on startup 1) GFv301 will replace the HttpsURLConnection setDefault to have a KeyManager that will sent "httpsOutboundKeyAlias"/s1as is client cert is requested. 2) Gfv312 also does this 3) Now in GFv301, it does not set the SSLContext but in GFv312x due to change GLASSFISH-15369, it seems that SSLContext.setDefault() is called to make the SSLContext have a default key manager that will submit s1as as the client cert if requested Well the behaviour is that things that work say in GFv2 may not work in GFv301 (if URLConnection to a https://... that does optional client cert request). For example ==> https://www.java.net//forum/topic/glassfish/glassfish/axis2-generated-stub-soap-webservice-call-not-working-glassfish-312?force=516 where javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate may happen in GFV312 (but may work in GFv301) due to (3). h3. Now the problem is this The issue is that a) GFv3 set the default alias to sent the client cert globally b) In GFv312, SSL artifact created from HttpsURLConnection and SSLContext will have this KeyManager that does chooseClientAlias() from X509ExtendedKeymanager and always returns s1as irregardless if the issuer matches with s1as +Look at J2EEKeyManager.java+ https://java.net/projects/glassfish/sources/svn/content/tags/3.1.2/security/core/src/main/java/com/sun/enterprise/security/ssl/J2EEKeyManager.java As you may see, from the code, the fix/issues are: a) Not setting com.sun.enterprise.security.httpsOutboundKeyAlias may help (if you do not ever use client cert) but the code may always return null for some conditions (ie: !server&!acc) b) Even if the property is explicitly set, the chooseClientAlias should still check if this alias is compatible with what the SSL server requested otherwise it should return NULL +Symptom+ For this issue even if you added all the SSL cert to the client trust store, if the remote SSL server ask for say an optional client cert (or required), the handshake will fail since the wrong client cert (self-signed s1as) is submitted which is totally different from the valid cert the server accepts. {noformat} javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate at sun.security.ssl.Alerts.getSSLException(Alerts.java:192) at sun.security.ssl.Alerts.getSSLException(Alerts.java:154) at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1961) at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1077) at sun.security.ssl.SSLSocketImpl.waitForClose(SSLSocketImpl.java:1707) at sun.security.ssl.HandshakeOutStream.flush(HandshakeOutStream.java:122) at sun.security.ssl.Handshaker.sendChangeCipherSpec(Handshaker.java:972) at sun.security.ssl.ClientHandshaker.sendChangeCipherAndFinish(ClientHandshaker.java:1087) at sun.security.ssl.ClientHandshaker.serverHelloDone(ClientHandshaker.java:1006) at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:285) at sun.security.ssl.Handshaker.processLoop(Handshaker.java:868) at sun.security.ssl.Handshaker.process_record(Handshaker.java:804) at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1016) at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1312) at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1339) at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1323) at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:515) at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185) {noformat}
    via by gfuser9999,
    • javax.net.ssl.SSLHandshakeException: Received fatal alert: bad_certificate at sun.security.ssl.Alerts.getSSLException(Alerts.java:192) at sun.security.ssl.Alerts.getSSLException(Alerts.java:154) at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1961) at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1077) at sun.security.ssl.SSLSocketImpl.waitForClose(SSLSocketImpl.java:1707) at sun.security.ssl.HandshakeOutStream.flush(HandshakeOutStream.java:122) at sun.security.ssl.Handshaker.sendChangeCipherSpec(Handshaker.java:972) at sun.security.ssl.ClientHandshaker.sendChangeCipherAndFinish(ClientHandshaker.java:1087) at sun.security.ssl.ClientHandshaker.serverHelloDone(ClientHandshaker.java:1006) at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:285) at sun.security.ssl.Handshaker.processLoop(Handshaker.java:868) at sun.security.ssl.Handshaker.process_record(Handshaker.java:804) at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1016) at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1312) at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1339) at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1323) at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:515) at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)

    Users with the same issue

    Unknown visitor1 times, last one,
    Unknown visitor1 times, last one,
    Unknown visitor1 times, last one,
    Unknown visitor1 times, last one,
    Unknown visitor1 times, last one,
    132 more bugmates