AbuMariam
AbuMariam

Reputation: 3698

Why am I getting "No issuer certificate for certificate in certification path found" error for a known and trusted certificate?

I am trying to connect to a server with a Java Http client to make a web service call. If I turn net debugging on with the below code..

System.setProperty("javax.net.debug", "all");

I am seeing that certificates from Entrust seem to be added as trusted certificates. Among those added were the below...

 adding as trusted cert:
 Subject: CN=Entrust.net Certification Authority (2048), OU=(c)    1999   Entrust.net Limited, OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.), O=Entrust.net
 Issuer:  CN=Entrust.net Certification Authority (2048), OU=(c) 1999 Entrust.net Limited, OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.), O=Entrust.net
 Algorithm: RSA; Serial number: 0x3863def8
 Valid from Fri Dec 24 12:50:51 EST 1999 until Tue Jul 24 10:15:12 EDT 2029

It seems as if the server is using a cert from Entrust because I also see in the debug...

main, READ: TLSv1 Handshake, length = 2649
*** Certificate chain
chain [0] =   [0]         Version: 3
     SerialNumber: 1356119177
       IssuerDN: C=US,O=Entrust\, Inc.,OU=See www.entrust.net/legal-terms,OU=(c) 2012 Entrust\, Inc. - for authorized use only,CN=Entrust Certification Authority - L1K
       Start Date: Wed Jul 15 11:50:20 EDT 2015
       Final Date: Sun Jul 15 18:27:04 EDT 2018

And yet during the handshake process I get the below exception...

***
Caught: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: 
PKIX path building failed: java.security.cert.CertPathBuilderException: 
No issuer certificate for certificate in certification path found.
main, SEND TLSv1 ALERT:  fatal, description = certificate_unknown

Upvotes: 3

Views: 22190

Answers (2)

prem
prem

Reputation: 853

I was able to fix this by adding server certificate to my java client (jre's cacerts and jssecacerts).

If we add a certificate to java client this way we are asking our jre to trust this server's certificate.

echo | openssl s_client -showcerts -connect www.xyz.com:443 2>&1 |
sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > /tmp/cert.pem

#cacerts
keytool -import -alias certname -file /tmp/cert.pem -keystore
/usr/java/jdk1.8.0_45/jre/lib/security/cacerts -storepass changeit

#jssecacerts(Normally we remove this file)
keytool -import -alias certname -file /tmp/cert.pem -keystore
/usr/java/jdk1.8.0_45/jre/lib/security/jssecacerts -storepass changeit

If this piece of client code is executed via application server , please restart your application server.

Make sure you have openssl, keytool in enviornment variables and change your respective JAVA_HOME location.

Upvotes: 1

AbuMariam
AbuMariam

Reputation: 3698

I got around this problem by creating a Trust Manager which accepts the server's certificate and pointed my Apache HttpClient to use that Trust Manager...

 private class TrustAll implements X509TrustManager
{
    public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException
{
}

public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException
{
}

public X509Certificate[] getAcceptedIssuers()
{
    return new X509Certificate[0];
}

}

TrustManager[] trustArray = [new TrustAll()] as TrustManager[]
SSLContext ctx = SSLContext.getInstance("TLSv1");
ctx.init(null, trustArray, null);

// create an http client builder
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
 httpClientBuilder.setSslcontext(ctx)

 httpclient = httpClientBuilder.build();

Upvotes: -2

Related Questions