I am working on a tutorial for some of my coworkers in an effort to educate them on how to diagnose and deal with SSL Certificate errors.
One of the specific errors we run into is the 'peer not authenticated' error that pops out in our logs when we have a bad SSL remote.
I have created a local set of certificates:
Root CA
Intermediate CA
Self-signed certificate
Root CA signed certificate
Intermediate CA signed certificate with no chain
Intermediate CA signed certificate with chain
Additionally, I've got a maven based project using the maven-jetty-plugin to run up the container with different SSL configurations on different ports. During the course of this I can get the PKIX path validation errors no problem, what I cannot seem to explicitly trigger is a 'peer not authenticated' error.
Can anyone point me in a direction to noodle this one out?
Related
Let me give a little bit of background before I ask the question, so that we have clarity on the problem itself. We need to support one way SSL with Elasticsearch (v5.2.x), using searchguard ssl. We have a list of procedures for developers (not for production), which takes care of generating a self signed SSL cert. Here we've one root (locally created) and the actual cert. If we import the keystore (containing the private key and signed cert) and the truststore (containing the root cert) everything works fine.
But couple of days back, we got one request from a client. There, in production we need to support SSL. So, we followed the steps below:
with our script, we generated the private key, imported it into the keystore, and also generated the csr.
We gave the client the csr. He got it signed by a proper CA, and gave us back the cert.
Now the chain of trust is of length 3, for the cert given. So, there's a root CA, which signed the cert (issuer1), which signed the cert (issuer2), which in turn signed the actual csr.
For importing the actual cert to the keystore, we imported all the three parents, and then imported the actual cert.
Then we removed all the parent certs from keystore. So, now the keystore has only the private key and the actual cert.
We imported all the three parent certs into the truststore.
Now, if we start Elasticsearch, the following error is thrown: [ERROR][c.f.s.s.t.SearchGuardSSLNettyTransport] [uyyIg3i] SSL Problem Received fatal alert: certificate_unknown
javax.net.ssl.SSLException: Received fatal alert: certificate_unknown
Funny thing is, the exact procedure works, if we have only the root ca, signing the actual csr. Any help is appreciated for figuring out the root cause of this issue, as I'm sort of out of ideas now.
After couple of tiresome debugging sessions, we found out the CN-name and the actual host-name to be different. After making both of them same, we got it working.
We have a Java web application running inside GlassFish 3 web server.
Our application connects to a LDAP server for authentication. Now customer is running LDAP on SSL i.e ldaps.
So we fetched the certificate from their LDAP server and added it to our trusted certificate. But still we sometime gets:
exception is 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]
Further investigation by LDAP admin, his words:
"We added additional servers behind the load balancer. If they
trust just the server CERT instead of the CA then you would be
experiencing this problem. They should trust the CA or should not
perform any certificate validation"
Which means that there are many LDAP server running behind the load balancer and each server has different certificate, and we just trust on one particular certificate.
Now the resolution they say is to trust on the CA and not on individual certificate.
NOW at this point I am confused!
Is it the case that we can get a CA certificate and trust on it so that any certificate issued by that CA will be automatically trusted..
If so how to do that?
Will the CA certificate be fetched from the LDAP server or do we have to ask for it?
Or have I created a wrong mind model for this or is there a concept missing?
Also what is "trusted root certificate"?
What they are saying is that the servers are signed using a common CA (like Verisign, Thwate etc). All you need to do is trust that CA (you do this by importing the CA's trusted root certificate).
You will need to find out which CA is being used and then check your cacerts file to see if you already trust the CA (apparently you dont since you are receiving the error). There a number of ways you can find out the CA being used but you can simply ask your LDAP admin which CA is being used. Some companies also use a local CA and this could very well be how your ldap servers are setup.
I have a strange problem (it's 100% server configuration problem,) for example I want to download something from Dropbox:
Resolving dl.dropboxusercontent.com... 23.23.160.146, 50.17.227.107,
54.221.248.69, ... Connecting to dl.dropboxusercontent.com|23.23.160.146|:443... connected. ERROR:
cannot verify dl.dropboxusercontent.com’s certificate, issued by
“/C=US/ST=CA/O=SonicWALL Inc./CN=SonicWALL Firewall DPI-SSL”:
Self-signed certificate encountered. To connect to
dl.dropboxusercontent.com insecurely, use ‘--no-check-certificate’.
Yes, I know that I can use --non-check-certificate but when I want to use SSL connection in Java app I have something like this:
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
This app works great in other servers or in local machines, any ideas what is wrong here?
/C=US/ST=CA/O=SonicWALL Inc./CN=SonicWALL Firewall DPI-SSL
Your traffic is visibly intercepted by a deep packet inspection firewall that acts as a MITM proxy to monitor your traffic.
This can generally be thought of as "legitimate" MITM attacker. (However legitimate this may be depends on a number of legal and ethical aspects.) Your local network administrator should be able to tell you a little bit about this. If this is part of a company network, this company is monitoring your traffic, including the contents of your HTTPS connection (so it's no longer secure from end-to-end). It the firewall does its job properly, it should still secure the connection from the firewall to the server (It's probably hard to know whether it check certificates properly.)
In general, such a firewall or proxy acts as its own Certification Authority, effectively forging each certificate as requested.
Most clients on the corporate network would trust certificates it issues (like the one you're facing) because system administrators would also install the CA certificate as a trusted certificate into each machine within that network. You probably have it the OS trusted root certificates.
However, it is likely that network administrators did not install this CA certificate into your JRE installation (which uses its own set of trust anchors by default).
Try to export that CA certificate (see the name above) from a reference machine and import it into the truststore you're using (either your JRE's default truststore: cacerts or a new truststore you build and pass to your application via the javax.net.trustStore properties).
Typically, you can use something like this (assuming you've exported the Firewall's CA as "firewallca.pem"):
keytool -import -file firewallca.pem -alias firewallca -keystore truststore.jks
If the truststore.jks file doesn't exist, it will be created. Otherwise, you can take a copy of the cacerts file in the lib/security directory of your JRE. You can also do this directly on the cacerts file (using -keystore /path/to/truststore.jks, provided you have write access to it).
If you choose not to do it on the default truststore (that cacerts file) but use a local truststore like truststore.jks, you'll can use it by using this system property when running your application: -Djavax.net.trustStore=/path/to/truststore.jks
For other ways of configuring your truststore, check this answer.
Another way to fix this is to tell Java to use your OS's truststore. I'll assume you're using Windows here. Using these system properties should work:
-Djavax.net.trustStore=NONE -Djavax.net.trustStoreType=WINDOWS-ROOT
(Try with WINDOWS-MY instead of WINDOWS-ROOT if this doesn't work.)
The WINDOWS-MY/WINDOWS-ROOT is a bit buggy in that it will miss some of the certificates in the Windows store: it uses the certificate "friendly name" (non unique) as the keystore alias (unique), so a certificate with a given friendly name will hide the others with the same name. (This effectively reduces the number of CA certificates that are trusted unfortunately.)
Since you're in an environment where presumably all the traffic goes through your DPI firewall, you'll probably only ever have to use one CA certificate at most. As long is it doesn't share its "friendly name" in the Windows list with any other cert, you should be fine.
You need to add the server's SSL certificate in your client's Java keystore. Take a look at this SO post:
Resolving javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed Error?
TIP: This is because your client's JVM does not 'trust' the server's SSL cert. So you need to add the cert in your keystore.
I am experiencing an issue when calling web service in my java project. The web service client is running in an java ee application deployed in WebSphere 7. The SSL certificate chain is having the root certificate of Go Daddy Class 2 Certificate Authority. and I do see it in the cacerts file under the WebsPhere JVM folder, but I am keeping getting untrusted certificate error:
java.security.cert.CertPathValidatorException: The certificate issued by OU=Go Daddy Class 2 Certification Authority, O="The Go Daddy Group, Inc.", C=US is not trusted; internal cause is:
java.security.cert.CertPathValidatorException: Certificate chaining error
Cant figure out why getting this error, and how I can resolve this issue. Please help me.
The web service is running in Server A, The client works well when I run it on my machine, the cacerts on my machine includes that root certificate.
When the client get deployed with an web application onto Server A, it doesn't work. We checked the cacerts file, it does include the go daddy root certificate.
When the client and webservice get deployed onto some other envs running with VeriSign certificate chain, it works as well.
Thanks
In my opinion, the CA root public key should be added to your trust store as you are using your server it as a webservice client and not a webservice server.
On your admin console, you should have:
Security->SSL certificate and key management->Key stores and certificates-> NodeDefaultTrustStore-> Signer certificates
Chaining error
You haven't imported the chain correctly, or there is something wrong with it. I use GoDaddy certificates and I don't get chaining errors, so it is more likely the former.
I'm trying to set up a test environment for our application that uses X.509 client authentication over HTTPS in Tomcat 6.0. The servlet code is expecting to get a certificate chain as an array of X509Certificate objects using the javax.servlet.request.X509Certificate of the servlet request. However, this array only contains a single item (the client certificate), where I'm expecting it to have two (the client certificate and the root CA certificate that signed it).
Here's what I've done so far:
Generate a self-signed CA certificate using openssl.
Import the CA certificate as a trusted root certificate into a newly create Java keystore.
Configure the Tomcat HTTPS connector to require client authentication using the keystore created in step 2 as the truststore:
clientAuth="true"
truststoreFile="<path_to_truststore>"
Generate a new client certificate using openssl and sign it with the CA certificate.
Start Tomcat.
Install the client certificate in Chrome and navigate to my server's homepage. Stepping through the code in debug, I can see that the array returned as the javax.servlet.request.X509Certificate attribute only has the client certificate.
I know that Tomcat is picking up the root CA certificate from the truststore because when I delete it from the truststore, I get an SSL connection error. It's just not making it into the servlet request like the documentation says it should. Am I missing any additional configuration here? Perhaps Tomcat (or Java or JSSE) is expecting some additional X509 V3 extensions or something?
Any help is appreciated!
EDIT
Looks like my setup is legit, and this falls into the category of unusual but expected behavior due to a simplified test environment. In an enterprise scenario it's unlikely that the root certificate authority is going to be directly signing client certificates for individual users. Clearly when this code was written and tested, there was at least one intermediate CA involved in the trust chain.
What your are seeing is what is expected: Chrome is not sending the CA.
During the TSL Handshake when authenticating the client, the server will send a list of acceptable CAs as part of its CertificateRequest Message (RFC), the browser will then present a Certificate signed by one of these CAs.
ADD
btw, a great way of debugging an SSL connection client side is to use the fantastic openssl tools
openssl s_client -connect ssl.server.com:443
or for SSLV3 only servers
openssl s_client -connect ssl.server.com:443 -ssl3
This will print (among other things) the list of acceptable CAs.
To debug the server side add this to the JVM command line -Djavax.net.debug=ssl
The identity keystore should contain the cert signed by the CA ; not the self-signed cert. The CA root should be in the truststore.
Also, what is the purpose of step 4 ?