I have two apps, one is written in nodejs (which in this case is simple mock-server) and spring app (core app). I want to create a SSL connection between this two. Firstly I generated pair of key and cert, then simply setup a nodejs to work over SSL (I used this example: setting SSL - nodeJs).
I have checked that when I wrote in browser https://localhost:3000 it gives me a "secure" connection (with open padlock - so it's ok).
Next I was making a configuration on spring app using setting SSL - Spring. I took a cert from previous step generation and set it in keystore into .p12 file. In spring application I changed the url to node app to https.
When I try to connect from spring app and get some mock data from node I'm getting this stacktrace:
Caused by: javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
I found something in stack but when I set this cert in specific directory and then restart my app, result is same.
Have anyone maybe a clue what could be wrong in this configuration and some suggestion how to fix it?
I found the solution of this problem. I don't know why, but when I created a keystore with cert inside and then use it in my spring app it cannot find this keystore with cert globally. I was looking for documentation about openJDK11 (because I used it) and find a link to Enabling Unlimited Strength Jurisdiction Policy and check file for which I have version of openJDK11.
In my case the line from crypto.policy was commented, don't know why. When I uncommented it and set unlimited it gives me one more error, but then I find one another solution. I found that, that I need to add my sign-self certificate to cacerts file (how to add my self-signed cert to cacerts). After this two operation it works as charm.
Related
I have a Java desktop application with which I was able to successfully GET data from an API at an https URL. The client had their own PKI, and in my app, they entered their pki password and their path to their truststore and pki to run the app, and system properties (keystore, truststore, etc) were set in the code to accept these values. Everything worked fine.
Now, I'm trying to implement the same thing via ssl using glassfish in a Java web app, but I am getting a javax.net.ssl.SSLHandshakeException: Received fatal alert: unknown_ca (this is the specific exc currently; before debugging, it was "PKIX path building failed...unable to find valid certification path to requested target")
I researched how to debug, including...
1) Java HTTPS client certificate authentication
Solution: Client already has a pkcs12 keystore, but ticket solved by using openssl to re(?)generate pkcs12, then use keytool to generate truststore.
(my comment: My clients already have certs in p12/pfx format, plus a truststore jks file containing trusted entities to use directly, so this solution doesn't seem to fit)
2) Using browser's certificate in java program
Solution: Add server certs to truststore
(my comment: this guidance seems opposite of the one directly below. I assume that these 'server certs' are for the https api servers?. My client truststore contains entries for https api sites to be accessed. It makes sense to me to add them to glassfish truststore since glassfish is server side; however, this is what i'm doing (i.e., -Djavax.net.ssl.trustStore=clientPathTo/truststore.jks in glassfish JVM) and getting exception at bottom)
3) Unable to find valid certification path to requested target - error even after cert imported
Solution: Add client cert to -Djavax.net.ssl.trustStore=${com.sun.aas.instanceRoot}/config/cacerts.jks
(my comment: I have not tried this but does it make sense for a copy of the client cert to be located on the server?
One thing that is confusing is when people say 'server', I can't tell if they mean 'web server' or 'app server'.
Anyway, I ran Glassfish in debug mode and set javax.net.debug==ssl. In the logs, I can see the following:
client HELLO
server HELLO
server presents its certificate chain
server makes a certificate request
glassfish presents a certificate chain
glassfish attempts to generate a session key, data is
exchanged, then it finishes with a data verification fatal ALERT:
unknown ca, session invalidated
javax.net.ssl.SSLHandshakeException...
------UPDATE------
I am running glassfish 4.1.1.
Here is the full Exception
javax.net.ssl.SSLHandshakeException: Received fatal alert: unknown_ca
atsun.security.ssl.Alerts.getSSLException(Alerts.java:192)
atsun.security.ssl.Alerts.getSSLException(Alerts.java:154)
atsun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:2023)
atsun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1125)
atsun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
atsun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
atsun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
atsun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)
atsun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
atsun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1546)
atsun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1474)
atsun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:254)
atbeans.ApiReader.sendGet(ApiReader.java:122)
atbeans.SelBeanController.showData(SelBeanController.java:43)
atsun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
atsun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
atsun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
atjava.lang.reflect.Method.invoke(Method.java:498)
atjavax.el.ELUtil.invokeMethod(ELUtil.java:332)
atjavax.el.BeanELResolver.invoke(BeanELResolver.java:537)
atjavax.el.CompositeELResolver.invoke(CompositeELResolver.java:256)
atcom.sun.el.parser.AstValue.invoke(AstValue.java:283)
atsom.sun.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:304)
atcom.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105)
atjavax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:87)
atcome.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102)
atjavax.faces.component.UICommand.broadcast(UICommant.java:315)
atjavax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:790)
atjavax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1282)
atcome.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)
atcome.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
atcome.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198)
atjavax.faces.webapp.FacesServlet.service(FacesServlet.java:658)
atorg.apache.cataline.core.StandardWrapper.service(StandardWrapper.java:1682)
atorg.apache.cataline.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:344)
atorg.apache.cataline.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
atorg.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:393)
atorg.apache.cataline.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)
atorg.apache.cataline.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
atorg.apache.cataline.core.StandardWrapperValve.invoke(StandardWrapperValve.java:316)
atorg.apache.cataline.core.StandardContextValve.invoke(StandardContextValve.java:160)
atorg.apache.cataline.core.StandardPipeline.doInvoke(StandardPipeline.java:734)
atorg.apache.cataline.core.StandardPipeline.invoke(StandardPipeline.java:673)
atcom.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)
atorg.apache.cataline.core.StandardHostValve.invoke(StandardHostValve.java:174)
atorg.apache.cataline.CoyoteAdapter.doService(CoyoteAdapter.java:416)
atorg.apache.cataline.CoyoteAdapter.service(CoyoteAdapter.java:283)
atcom.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:459)
atcom.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:167)
atorg.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:206)
atorg.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:180)
atorg.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:235)
atorg.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
atorg.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:283)
atorg.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:200)
atorg.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:132)
atorg.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:111)
atorg.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
atorg.glassfish.grizzly.nio.trasport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:536)
atorg.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112)
atorg.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117)
atorg.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:56)
atorg.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137)
atorg.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:591)
atorg.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:571)
atjava.lang.Thread.run(Thread.java:745)
I have following situation - I want to get page content using https request and java agent. However, I'm getting following error message:
javax.net.ssl.SSLHandshakeException: com.ibm.jsse2.util.j: Certificate chaining error
I already imported internet certificates to my local notes cacerts file, but nothing changed.
However, when I'm running same code in Eclipse, using keystore with certificates downloaded from page I try to receive and it works fine.
I'm out of ideas, any suggestions will be appreciated!
===EDIT===
Dmytro Pastovenskyi's answer helped me, but additionally to get rid of protocol_version exception I had to use following code, setting version of TLS used:
System.setProperty("https.protocols", "TLSv1");
It seems nessesary to establish connection to some sites using 1.6 IBM JAVA.
I had same issue some times before.
It looks like IBM Domino server more strict when it check certificates. Our administrator who at the beginning said that chain is correct later found an issue with chain (and yes, it worked for .NET/JAVA and other platform, just not with Domino). Try to find some online tools that verify chain.
Before chain is fixed you can simply disabled certificate validation. I've an article how to do it (+ some other articles that may help you). Have a look here: Disabling certificate validation in Java
Im trying to add a user using Java 6 and Apache Directory API to Active Directory running on windows server 2008, but the result i get is (UNWILLING_TO_PERFORM), now i understand that it needs a secure connection and to use unicodePwd attribute to add the password, which i did, or at least tried to do.
The server admin created a certificate for the account i use when adding users, i exported it and added it to cacert in /jre/lib/security/.
I tried to see if i can just connect securely to the AD server without performing any operations, i get 2 scenarios that fail on the binding operation .bind():
1- if i connect using port 636 and use startTLS() available in ldapNetworkConnection : then i either get PROTOCOL_ERROR server will disconnect
2- if i connect using port 389 and use startTLS() available in LdapConnectionConfig i get "Failed to initialize the SSL context" and "IllegalArgumentException :TLSv1.1"
I added the trust manager but still no luck, below is the code so far.
LdapConnectionConfig config = new LdapConnectionConfig();
config.setLdapHost(IP);
config.setLdapPort(389);
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init((KeyStore)null);
config.setTrustManagers(tmf.getTrustManagers());
config.setName("CN=TestAdmin,CN=Users,DC=bmrk,DC=com");
config.setCredentials("P#ssw0rd");
LdapNetworkConnection ldapNetworkConnection = new LdapNetworkConnection(config);
ldapNetworkConnection.connect();
ldapNetworkConnection.startTls();
ldapNetworkConnection.bind();
// EDIT
i switched to JNDI LDAP APIs it gave me a more reasonable error, apparently the issue comes from the SSL handshake, my app isn't able to find the valid certificate, any recommendations?
Any help is really appreciated.
Thanks,
In Case anyone is interested, my only issue was in the adding the server that generated the certificate as a CA authority in the cacerts file so that the JVM can trust certificates issued by the server although it worked smoothly and perfect with JNDI ldap APIs it doesn't work with Apache Directory not sure why.
so my recommendation is to use JNDI instead of Apache Directory and make sure you export the certificate for the account used to login to Active Directory as PKCS12 and add it to the keystore.
so it's 2 certificates, 1 for the login/bind account and 1 for the server to act as a CA (Certificate Authority).
Also Java 6 support TLSv1 as a maximum security protocol which isn't the standard case with Apache LDAP, so either upgrade you Java or use JNDI.
it works perfectly with Java 7.
I am trying to get a grasp on the fundamentals of Java Mail API and TLS. I have the following scenario:
There is an STMP server that uses TLS & SSL. If I log on to this server with some client, I can send authenticated &verified e-mails without any problems.
Then I try to run a web server on a different machine, that sends mail using the previously mentioned SMTP server. I still want to send TLS & SSL emails, however no matter how I configure the startup properties I get the following well known 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
I found a lot of people having similar issues, however my question is this:
Considering the previuosly described scenario, do I have to get some kind of certificate to the web server (possible somewhere in the JRE), or should it just work fine since the mail server already has that certificate & authentication mechanizm running. Shouldn't it be possible to just use the certificate of the SMTP server? Anyway, if I have to install the certificate to the machine that uses the STMP server how can I get that certificate?
I'm pretty new to JavaMail API and I have seen lots of articles about this but I could not find the answer black & white for my question.
Your client (that is in your case the one running on the webserver) needs to verify the SSL certificate of the mail server. It seems that your java truststore doesn't contain that certificate.
So you either need to put that certificate into the default truststore of your JRE (what I wouldn't recommend) or define a different truststore for your application (that of course needs to contain the mail servers certificate). To do that set this VM parameter: Djavax.net.ssl.trustStore=<path-to-truststore>
Edit: Ah I missed some part of your question.
To get the certificate of the mail server use something like openssl. See for example:
https://serverfault.com/questions/139728/how-to-download-ssl-certificate-from-a-website
The answer is in the JavaMail FAQ.
Quoted text from the linked site:
Q: When connecting to my mail server over SSL I get an exception like "unable to find valid certification path to requested target".
A: Your server is probably using a test certificate or self-signed certificate instead of a certificate signed by a commercial Certificate Authority. You'll need to install the server's certificate into your trust store. The InstallCert program will help.
Alternatively, you can set the "mail.protocol.ssl.trust" property to the host name of your mail server. See the javadocs for the protocol provider packages for details.
Other common causes of this problem are:
There's a firewall or anti-virus program intercepting your request.
There's something wrong in your JDK installation preventing it from finding the certificates for the trusted certificate authorities.
You're running in an application server that has overridden the JDK's list of trusted certificate authorities.
I am trying to trouble shoot a two way SSL handshake mechanism. I get an error
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
This indicates that one of my keystore or my truststore files does not have the appropriate entries. I know the way to trouble shoot this is to go to the server's truststore do the keytool list check the signing authorities and come to the client's key/truststore and verify this.
Can someone list these steps clearly (with the appropriate commands) please? Googling is not leading me anywhere. I just need a list of steps of "How can I confirm that Client X can talk to Server Y with two way SSL using Cert Z"?
The SunCertPathBuilderException exception is thrown whenever there the certificate validator fails to establish a chain between the certificate and a root certificate.
The easiest way to confirm that the certificate validates is to use a graphical tool like
Keyman, or
KeyTool IUI
The above tools are recommended since the exception is usually thrown in the absence of a root certificate.
If you want to examine what certificates are getting exchanged, it is better to switch on the ssl debug flag on the JVM node where the validation is failing.
Another option is to use a network traffic capture utility like Ethereal or Microsoft Netmon to obtain a dump of the traffic containing the certificate exchanges.
PS: Are you using the right keystore in the first place? I remember doing the same mistake many moons ago...