3

I just setup SSL certs on my server. I am pretty sure they are setup right. When go to https://mydomain.com/myapp in the browser the page loads correctly and the Green Lock shows in the address bar.

Doing a POST from Firefox>POSTER to this HTTPS url I get a valid response.

If I do the same POST from my Java client I get the following error:

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

On my server I have put the CA_ROOT certs in the JAVA.../jre/lib/security/cacert keystore.

Here is my posting code from my Java client.

URL url = new URL(Global.SERVER_URL);
HttpsURLConnection connection = null;
connection = (HttpsURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setReadTimeout(45000);
connection.setRequestProperty("Content-Type", "text/json");
connection.connect();

PLease Note: THIS IS NOT A SELF SIGNED CERT. It was issued by a CA

I have a feeling that Glassfish is not sending the full Cert Chain. I looked at the cert that the browser got and it was the full cert chain. I looked at the SSL error and that was only the Intermediate Cert and that for my domain.

How do I get Glassfish to send the full Cert chain?

Check SSL Chain

openssl.exe s_client -connect mydomain.com:443

Returns

WARNING: can't open config file: /usr/local/ssl/openssl.cnf
Loading 'screen' into random state - done
CONNECTED(00000190)
depth=0 C = US, ST = <edited>, L = <edited>, O = <edited>, OU = <edited>, CN = <edited>
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 C = US, ST = <edited>, L = <edited>, O = <edited>, OU = <edited>, CN = <edited>
verify error:num=27:certificate not trusted
verify return:1
depth=0 C = US, ST = <edited>, L = <edited>, O = <edited>, OU = <edited>, CN = <edited>
verify error:num=21:unable to verify the first certificate
verify return:1
---
Certificate chain
 0 s:/C=US/ST=<edited>/L=<edited>/O=<edited>/OU=<edited>/CN=<edited>
   i:/O=Cybertrust Inc/CN=Cybertrust Public SureServer SV CA
---
Server certificate
-----BEGIN CERTIFICATE-----
<edited>
-----END CERTIFICATE-----
subject=/C=US/ST=<edited>/L=<edited>/O=<edited>/OU=<edited>/CN=<edited>
issuer=/O=Cybertrust Inc/CN=Cybertrust Public SureServer SV CA
---
No client certificate CA names sent
---
SSL handshake has read 1676 bytes and written 513 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES128-GCM-SHA256
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES128-GCM-SHA256
    Session-ID: <edited>

    Session-ID-ctx:
    Master-Key: <edited>
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    Start Time: 1410274974
    Timeout   : 300 (sec)
    Verify return code: 21 (unable to verify the first certificate)
---
read:errno=0

SOLUTION

Accepted Answer from Bruno for the Concept

Additional Details:

  1. Get Keystore Explorer. Its a fantastic GUI tool to browse keystores.
  2. Open keystore.jks with Keystore Explorer.
  3. Right Click the Cert in question (mydomain) and View Details>Certificate Chain Details.
  4. if it does not show the full Cert chain then add it by right clicking the cert Edit Certificate Chain>Append Certificate.
  5. Restart Glassfish.
codeNinja
  • 1,442
  • 3
  • 25
  • 61
  • is it a self signed certificate? – bhowden Aug 28 '14 at 17:16
  • @bhowden it was issued by my company. the CA is Baltimore Cyber Trust Root. Not sure if that is in the jvm trust or not by default. On the server i added it to the jvm trust – codeNinja Aug 28 '14 at 17:45
  • 1
    ok. is the cert listed when you run a `keytool -list -keystore $JRE_HOME\lib\security\cacerts` ? – bhowden Aug 28 '14 at 18:34
  • 2
    Which version of Java are you using? Can you check the chain you get with `openssl s_client -servername your.host.name -connect your.host.name 443`? Are they in order? – Bruno Sep 04 '14 at 23:50
  • baltimorecybertrustca was ever in jre 1.4 and valid until 2025. fingerprint MD5: `90:F5:28:49:56:D1:5D:2C:B0:53:D4:4B:EF:6F:90:22` I suppose you need set up Glassfish properly and return full PKIX chain to client, in right order. Try to connect with openssl s_client as Bruno say in comment above. – user1516873 Sep 08 '14 at 11:54
  • 1
    @codeNinja It looks to me that it only returns one cert, not the full chain, there's only one entry at position 0 in your certificate chain. – Bruno Sep 09 '14 at 16:36
  • Java key store is **cacerts**, but not **cacert**. – Dmytro Plekhotkin Sep 08 '14 at 08:12

3 Answers3

4

Browsers and Java use different set of trusted root certificates, by default Browsers get this info from OS, Java supports own list, that's why it could be green in Browser and doesn't support in Java

To check what certificates support your version of Java: <jre_path>\bin\keytool -keystore "<jre_path>\lib\security\cacerts" -storepass changeit -list

And if you don't see your certificate just add it to <jre_path>\lib\security\cacerts file.

terma
  • 1,199
  • 1
  • 8
  • 15
  • its not a self signed cert. It was issued by a CA. As mentioned in the question the request/response works prefectly if done via the Browser (green lock in the address bar and everything) – codeNinja Aug 28 '14 at 20:25
  • 2
    @codeNinja As terma said, your browser and Java have separate sets of trusted CAs. Java's set of trusted CA roots might not include the root certificate for your chosen CA. – William Price Sep 07 '14 at 22:21
  • this is a Java Web Start app deployed to many users in the company. adding the cert to each persons computer is not viable. – codeNinja Sep 09 '14 at 15:18
2
---
Certificate chain
 0 s:/C=US/ST=<edited>/L=<edited>/O=<edited>/OU=<edited>/CN=<edited>
   i:/O=Cybertrust Inc/CN=Cybertrust Public SureServer SV CA
---

Unlike what you said in a comment, and according to this output, your server isn't sending any intermediate certificate. The certificate chain only has one certificate (at position 0): the server certificate.

On my server I have put the CA_ROOT certs in the JAVA.../jre/lib/security/cacert keystore.

Adding the intermediate certificates in the server side's truststore will have no effect on the chain presented by the server (it's only used to authenticate clients, if applicable).

You'd need to make sure your keystore entry is set up with the full chain, as described in this question, following the same procedure as this answer.

What you see in the browser may well be the chain it has reconstructed, and the browser may also know these intermediate CA certs, where the JRE may not (different sets of trust anchors are used): you'll only increase the chances of the default JRE accepting your server certificate by presenting the full chain correctly. (Note that you don't need to present the root CA cert itself in the chain, it doesn't harm, but it's just network overhead.)

Community
  • 1
  • 1
Bruno
  • 119,590
  • 31
  • 270
  • 376
  • thanks for your help. This did it. I downloaded Keystore Explorer and simply doubled clicked my Keystore. Then i right click the CERT in question and added the ROOT and Intermediate Cert. Then Restart Glassfish! – codeNinja Sep 10 '14 at 15:14
0

SSLHandshakeException:

comes when a failed connection would look something like this. Usually indicating that there is some type of certificate validation issue, most likely your Truststore doesn't contain the Trusted root certificates that it needs.And Indicates that the client and server could not negotiate the desired level of security. The connection is no longer usable.

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

Example in detail to Send an HTTP POST request by using below code .

private void sendPost() throws Exception {

        String url = "https://selfsolve.apple.com/wcResults.do";
        URL obj = new URL(url);
        HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();

        //add reuqest header
        con.setRequestMethod("POST");
        con.setRequestProperty("User-Agent", "Mozilla/5.0");
        con.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
        con.setRequestProperty("Content-Type", "text/json");

        String urlParameters = "sn=C02G8416DRJM&cn=&locale=&caller=&num=12345";

        // Send post request
        con.setDoOutput(true);
        DataOutputStream wr = new DataOutputStream(con.getOutputStream());
        wr.writeBytes(urlParameters);
        wr.flush();
        wr.close();

        int responseCode = con.getResponseCode();
        System.out.println("\nSending 'POST' request to URL : " + url);
        System.out.println("Post parameters : " + urlParameters);
        System.out.println("Response Code : " + responseCode);

        BufferedReader in = new BufferedReader(
                new InputStreamReader(con.getInputStream()));
        String inputLine;
        StringBuffer response = new StringBuffer();

        while ((inputLine = in.readLine()) != null) {
            response.append(inputLine);
        }
        in.close();

        //print result
        System.out.println(response.toString());

    }

if response code is 200, means looks good.
for more detail to solve same exception refer below links.

Community
  • 1
  • 1
Rudra21
  • 242
  • 3
  • 13
  • I understand how the post part works. I am also sure that the error is due to the Brower having the CERT in its TrustStore while Java does not. The question is how do i resolve this for everyone to whom my product is deployed? – codeNinja Sep 04 '14 at 13:52
  • @codeNinja That you have to debug it only , need to confirm about certificate as well. But why you want to test using java code.Its working on browser. – Rudra21 Sep 04 '14 at 13:59
  • the HTTP request is actually made in a JAVA app. I was only testing in the browser for debugging. – codeNinja Sep 04 '14 at 14:13