Received fatal alert: unknown_ca while mutual authentication
I'm working on a web service client which need to communicate with a server who has mutual authentication enabled.
I've done the following steps.
- Added the server certificate(self signed) to a trust store and set it to the
HttpsURLConnection
using theSSLSocketFactory
. - Gave the client certificate(CA signed) to the server admin to add it to their trusted store.
- Created a keystore by importing the client certificate and created a keymanager to `HttpsURLConnection'.
When I try to run this sample I'm getting an exception saying
org.springframework.ws.soap.axiom.AxiomSoapMessageException: Could not write message to OutputStream: java.net.SocketException: Software caused connection abort: recv failed; nested exception is javax.xml.stream.XMLStreamException: java.net.SocketException: Software caused connection abort: recv failed
at org.springframework.ws.soap.axiom.AxiomSoapMessage.writeTo(AxiomSoapMessage.java:261)
at org.springframework.ws.transport.AbstractWebServiceConnection.send(AbstractWebServiceConnection.java:45)
at org.springframework.ws.client.core.WebServiceTemplate.sendRequest(WebServiceTemplate.java:586)
at org.springframework.ws.client.core.WebServiceTemplate.doSendAndReceive(WebServiceTemplate.java:549)
at org.springframework.ws.client.core.WebServiceTemplate.sendAndReceive(WebServiceTemplate.java:502)
at org.springframework.ws.client.core.WebServiceTemplate.sendAndReceive(WebServiceTemplate.java:480)
at test.SamlTest.request(SamlTest.java:29)
at test.SamlTest.main(SamlTest.java:63)
Caused by: javax.xml.stream.XMLStreamException: java.net.SocketException: Software caused connection abort: recv failed
at com.sun.xml.internal.stream.writers.XMLStreamWriterImpl.writeStartDocument(Unknown Source)
at org.apache.axiom.soap.impl.llom.SOAPEnvelopeImpl.internalSerialize(SOAPEnvelopeImpl.java:193)
at org.apache.axiom.om.impl.llom.OMElementImpl.internalSerialize(OMElementImpl.java:756)
at org.apache.axiom.soap.impl.llom.SOAPMessageImpl.internalSerialize(SOAPMessageImpl.java:71)
at org.apache.axiom.om.impl.llom.OMDocumentImpl.internalSerialize(OMDocumentImpl.java:324)
at org.apache.axiom.om.impl.llom.OMDocumentImpl.serialize(OMDocumentImpl.java:375)
at org.springframework.ws.soap.axiom.AxiomSoapMessage.writeTo(AxiomSoapMessage.java:252)
... 7 more
Caused by: java.net.SocketException: Software caused connection abort: recv failed
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(Unknown Source)
at com.sun.net.ssl.internal.ssl.InputRecord.readFully(Unknown Source)
at com.sun.net.ssl.internal.ssl.InputRecord.readV3Record(Unknown Source)
at com.sun.net.ssl.internal.ssl.InputRecord.read(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source)
at sun.net.www.protocol.https.HttpsClient.afterConnect(Unknown Source)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(Unknown Source)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(Unknown Source)
at org.springframework.ws.transport.http.HttpUrlConnection.getRequestOutputStream(HttpUrlConnection.java:81)
at org.springframework.ws.transport.AbstractSenderConnection$RequestTransportOutputStream.createOutputStream(AbstractSenderConnection.java:101)
at org.springframework.ws.transport.TransportOutputStream.getOutputStream(TransportOutputStream.java:41)
at org.springframework.ws.transport.TransportOutputStream.write(TransportOutputStream.java:64)
at com.sun.xml.internal.stream.writers.UTF8OutputStreamWriter.write(Unknown Source)
at com.sun.xml.internal.stream.writers.UTF8OutputStreamWriter.write(Unknown Source)
... 14 more
What am I missing?
UPDATED
Please find the log after enabling jvm log
trigger seeding of SecureRandom
done seeding SecureRandom
%% No cached client session
*** ClientHello, TLSv1
RandomCookie: GMT: 1274794757 bytes = { 250, 192, 120, 159, 84, 244, 96, 103, 128, 221, 36, 200, 229, 95, 84, 152, 179, 202, 161, 56, 95, 161, 234, 136, 128, 52, 45, 228 }
Session ID: {}
Compression Methods: { 0 }
***
main, WRITE: TLSv1 Handshake, length = 73
main, WRITE: SSLv2 client hello message, length = 98
main, READ: TLSv1 Handshake, length = 74
*** ServerHello, TLSv1
Cipher Suite: SSL_RSA_WITH_RC4_128_MD5
Compression Method: 0
***
%% Created: [Session-1, SSL_RSA_WITH_RC4_128_MD5]
** SSL_RSA_WITH_RC4_128_MD5
main, READ: TLSv1 Handshake, length = 976
*** Certificate chain
chain [0] = [
[
Version: V3
Subject: EMAILADDRESS=email@email.com, CN=email@email.com, OU=MyOU, O=xyz
Signature Algorithm: MD5withRSA, OID = 1.2.840.113549.1.1.4
Key: Sun RSA public key, 1024 bits
public exponent: 65537
Validity: [From: Tue Jul 18 02:30:07 IST 2006,
To: Mon Jul 13 02:30:07 IST 2026]
Issuer: EMAILADDRESS=email@email.com, CN=email@email.com, OU=MyOU, O=xyz
SerialNumber: [ ]
Certificate Extensions: 3
[1]: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
]
]
[2]: ObjectId: 2.5.29.35 Criticality=false
AuthorityKeyIdentifier [
KeyIdentifier [
]
[EMAILADDRESS=email@email.com, CN=email@email.com, OU=MyOU, O=xyz]
SerialNumber: [ ecbcae10 2ba4c279]
]
[3]: ObjectId: 2.5.29.19 Criticality=false
BasicConstraints:[
CA:true
PathLen:2147483647
]
]
Algorithm: [MD5withRSA]
Signature:
]
***
main, SEND TLSv1 ALERT: fatal, description = certificate_unknown
main, WRITE: TLSv1 Alert, length = 2
main, called closeSocket()
main, handling exception: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
Exception in thread "main" javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(Unknown Source)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(Unknown Source)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(Unknown Source)
at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Unknown Source)
at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source)
at sun.net.www.protocol.https.HttpsClient.afterConnect(Unknown Source)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(Unknown Source)
at com.arun.test.http.TiMutualAuthClient.main(TiMutualAuthClient.java:71)
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.validator.PKIXValidator.doBuild(Unknown Source)
at sun.security.validator.PKIXValidator.engineValidate(Unknown Source)
at sun.security.validator.Validator.validate(Unknown Source)
at com.sun.net.ssl.internal.ssl.X509开发者_如何学编程TrustManagerImpl.validate(Unknown Source)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source)
... 13 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(Unknown Source)
at java.security.cert.CertPathBuilder.build(Unknown Source)
... 19 more
Thank you
Does the client keystore contain a private key entry? Not clear from your description. It is also not clear where the unknown_ca comes from: it doesn't show up in your stack trace. It would be best to run the client with -Djavax.net.debug=ssl,handshake and post the results.
I think the problem was with the client certificate used by me. It has the following extension values set
Certificate Key Usage
Critical
Signing
Non-repudiation
Key Encipherment
Data Encipherment
Extended Key Usage
Not Critical
TLS Web Server Authentication (1.3.6.1.5.5.7.3.1)
TLS Web Client Authentication (1.3.6.1.5.5.7.3.2)
Once I created a self signed certificate without any extensions and used it as my client certificate, it worked fine.
You need to put the public key of the CA that certified the user (or the public key of the user themselves if it is a self-certified key that they're using) into the server's keystore. Otherwise the server simply doesn't know whether the user's certificate is for real or is being presented by someone impersonating them. Having the certificate in there ahead of time allows the server to understand the identity and trust it (which the SSL protocol requires as part of preventing trivial man-in-the-middle attacks).
精彩评论