We have a process use HttpClient to make https connection with different URLs. Our JDK version is 1.7. We found some URLs, if we use default JSSE SIN extension flag, which is turn on, we got the following exception:
javax.net.ssl.SSLProtocolException: handshake alert: unrecognized_name
If we set -Djsse.enableSNIExtension=false, some other URLs throw this exception:
javax.net.ssl.SSLException: Received fatal alert: unrecognized_name
Does anybody have idea about this?
The SNI extension will add the server_name(hostname) in the client hello message at the SSL handshake stage.
It may be needed by a server that serves requests for different hostnames or virtual hosts. It is used to resolve the Certificate for the hostname the client intend to communicate with. The server may be configured with a default certificate if the host name is not added or not found. The default certificate may be a multisigned certificate for all the hosts it serves.
The first warning you get may be a server responding with a default certificate but that also warns that the hostname is not recognized. The server probably does not recognize the hostname simply because it is not included in the configuration. Instead of ignoring the warning and use the default certificate, Java seems to throw an exception.
In the other case where you disabled SNI, you do not include the hostname anymore and the request is sent to a server that does not have a default certificate. It will respond with a fatal error because it cannot resolve any certificate for you.
Related
I have Mysql 8.0.19 as docker instance.
In our application previously we use JDK's default keystore for SSL.
With JDK's keystore connection to Mysql server is just fine with SSL and without SSL.
Here we didnt configured the SSL for Mysql manually. We are using default SSL mechanism of Mysql.
Now for some reason we decided to use our own keystore and to use that we overrided the keystore for JVM with below variables
-Djavax.net.ssl.keyStore=$keystorePath$
-Djavax.net.ssl.keyStorePassword=$sslKeyStorePwd$
-Djavax.net.ssl.trustStore=$keystorePath$"
-Djavax.net.ssl.trustStorePassword=$sslKeyStorePwd$
Now after this, connection to mysql for SSL is faling with below errors
javax.net.ssl|ERROR|01|main|2021-08-10 16:20:30.019 IST|TransportContext.java:313|Fatal (UNKNOWN_CA): Received fatal alert: unknown_ca (
"throwable" : {
javax.net.ssl.SSLHandshakeException: Received fatal alert: unknown_ca
at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:128)
at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:117)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:308)
at java.base/sun.security.ssl.Alert$AlertConsumer.consume(Alert.java:279)
Exception in thread "main" com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
at com.mysql.cj.jdbc.exceptions.SQLError.createCommunicationsException(SQLError.java:174)
In /var/lib/mysql/ we have
ca.pem,ca-key.pem,client-cert.pem,client-key.pem, public_key.pem,private_key.pem,server-cert.pem, server-key.pem.
To resolve this error I tried to import the ca.pem,client-cert.pem, server-cert.pem into our keystore but it didnt worked.
unknown_ca means that the certificate was not signed by a trusted Certificate Authority. My guess is that you do not have the whole chain in your keystore
There are 2 Websphere servers. First is Client and Second is Server (8.5.5.13).
An End-User makes a SOAP request to Client. Client receives the request, do some processing and then makes a REST request to the Server.
When the Server receives the request from Client it throws the below exception.
ERROR 22304 --- [ebContainer : 2]
c.i.w.s.c.impl.SSLHandshakeErrorTracker : SSLC0008E: Unable to
initialize SSL connection. Unauthorized access was denied or security
settings have expired. Exception is
javax.net.ssl.SSLHandshakeException: Client requested protocol TLSv1
not enabled or not supported
We have tested after enabling TLSv1.2 and then TLSv1 at the our Server level. We have exported the certificate from the Server and added in the Client trust store as well. But still we are not able to resolve the error.
Questions:
1. Do we need to keep the same TLS version at our Server which is present in the Client WebSphere?
2. We have deployed our application is java7. Is it due to Java version we are facing the issue?
3. Is it due to Certificate only, or something else?
When we disable the Global security at our Server then the request is processing correctly.
This error was due to the TLS version incompitability at Server. The client was sending the request using TLSv1 and server has TLSv1.2 enabled in it. For SSL handshake, the first thing is TLS compitability. The client and server should have same TLS versions.
After this if you are using one way SSL handshake, then the certificate from the server machine needs to extract and the same should be installed in the Client machine. This way SSL Handshake will happen.
I have a unix script running in server "CCC" from which am calling a servlet running in another server "GGG".(The server GGG is a secure server, having extra firewalls compared to normal server)
Also, the CCC is a ETL server, which is having a JRE. The script is calling the servlet using http, since I rule is applied, so redirection is happening to https, and the port no is also changing.
And am getting a bad certificate error, when i try to invoke the servlet.
The servlet URL when given in normal IE or chrome is giving me a valid response, am able to hit the server GGG.
The error am getting is :
javax.net.ssl.SSLHandshakeException: bad certificate
at com.ibm.jsse.bg.a(Unknown Source)
at com.ibm.jsse.b.a(Unknown Source)
at com.ibm.jsse.b.write(Unknown Source)
at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:81)
at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:139)
at org.apache.commons.httpclient.HttpConnection.flushRequestOutputStream(HttpConnection.java:827)
at org.apache.commons.httpclient.HttpMethodBase.writeRequest(HttpMethodBase.java:1975)
at org.apache.commons.httpclient.HttpMethodBase.execute(HttpMethodBase.java:993)
at org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.java:397)
at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:170)
at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:396)
at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:324)
at com.tgt.task.client.TaskClient.doGet(TaskClient.java:153)
at com.tgt.task.client.TaskClient.runClient(TaskClient.java:91)
at com.tgt.task.client.TaskClient.completeTask(TaskClient.java:68)
at com.tgt.task.client.TaskClient.main(TaskClient.java:53)
So, initially i checked the certs in cacerts for CCC server, it is having all the root certs, except the cert issued to the URL.
We found the issue started after the BIG IP cert renewal for the URL, i have followed up with my network team to have a look into the issue, they have confirmed that traffic from server CCC is going through fine to GGG passing the firewalls.
So captured the traffic when we tried to invoke the URL, we got the below:
client server SSLV2 282 Client Hello
server client SSLV3 1631 Server Hello
server client SSLv3 433 Certificate
client server SSLV3 190 Alert(Level: Fatal, Description: Bad Certificate)
Can you let me know is the issue because of the SSL versions used by the client and the server ?
or some other thing that i missed out in my analysis.
I even tried to import the cert for the URL in to cacerts in server CCC, but i got the errors:
keytool error: java.lang.Exception: Input not an X.509 certificate
So , i took the PKCS7 cert for the URl and tried to convert it into .cer and tried to import, but got the same error.
If it works with the browser, but not with a script, it has often to do with Server Name Indication (SNI). With SNI you can have multiple hosts with different certificates behind the same IP address. While all current browser support SNI, other implementations might not or might not enable SNI by default. If the client fails to use SNI on a site with multiple certificates behind the same IP it just gets the default certificate, which is often the wrong one.
I don't which Java version you are running, but I suggest you determine your version and then google of how to use SNI with your version. From my understanding SNI was enabled only in Java version 7.
I have checked the captured network packet and found that the URL is providing the correct certificate to the server CCC as per the SSL configuartions at BIG IP end, the client CCC is not able to validate it. And returning a bad certificate message.
here i tried openssl and tried the command:
s_client -connect host:443
verify error:num=20:unable to get local issuer certificate
verify error:num=27:certificate not trusted
verify error:num=21:unable to verify the first certificate
`No client certificate CA names sent`
SSL handshake has read 1745 bytes and written 304 bytes
New, TLSv1/SSLv3, Cipher is RC4-SHA
Server public key is 1024 bit
Compression: NONE
Expansion: NONE
SSL-Session:
Start Time: 1402019174
Timeout : 300 (sec)
Verify return code: 21 (unable to verify the first certificate)
I guess my server is not sending the complete trust chains list, as a result, client is not able to validate it.
Am not sure whether my analysis is correct or not, also i referred the below post:
OpenSSL: unable to verify the first certificate for Experian URL
If i need to send my server to send the complete trusted chain list, where i need to change the settings ? at BIG Ip end, or at server end ?
I'm using Netty for asynchronous http(s) requests. When the url for the request is https I'm adding this to the pipeline:
SSLEngine engine = SecureChatSslContextFactory.getClientContext().createSSLEngine();
engine.setUseClientMode(true);
pipeline.addLast("ssl", new SslHandler(engine));
This works well, I get the response back and everything, but a warning is being written to the output saying: UNKNOWN SERVER CERTIFICATE, for example if I issue a request for: https://www.google.com this is what I get:
UNKNOWN SERVER CERTIFICATE: CN=www.google.com, O=Google Inc, L=Mountain View, ST=California, C=US
Since everything is still working it's not that much of an issue for me, but there are two things I would like to know:
Why do I get that warning? googles' certificate is a "well known" one, the browsers don't seem to warn about it. Should I somehow tell the ssl engine where to look for the certificates?
Can I somehow catch this warning at runtime instead of having this message printed out?
Thanks.
Check to make sure that the "trust store" is correctly identified to Netty when you do this, you may have to look at adding ${JAVA_HOME}/jre/lib/security/cacerts as a trusted store.
If that's not configured you probably won't be able to connect over SSL
Dave,
Take a look at the code sample in this thread: Set up Netty with 2-way SSL Handsake (client and server certificate)
I think that will help you with your keystore and truststore setup.
I am using https to connect to an https server.
Specifically I am using apache httpclient and I configure the ssl context to use my keystore and truststore.
The https server I am using is IIS7 and is configured to require client authentication.
I think I have set it up properly.
Anyway, if I configure the httpClent's ssl context with a keystore (i.e. with client certificates) valid for IIS then there is no problem connecting.
Now my problem is the following:
If I do not configure the ssl context with any client certificate to send to IIS, there is no connection with the server. What makes me think though, is the fact that I was expecting to see some java exception in the code as a result of a hanshake failure alert.
Monitoring what is happening with wireshark, I could not see a certificate request from IIS to my application, but I noticed that after ServerHelloDone everything was encrypted.
I did not expect that. I think the handshake is usually in cleartext.
I used private key to decrypt traces and i saw a certificate request from IIS but after many starting and opening of new connections.
My app send back as a response a certificate of length 0 and IIS replies with a TLSv1 Finished.
After that the packets stop (i.e. seems that the communication ends).
I was expecting a handshake alert.
My question is, is this how it is supposed to work or at least how IIS works?
Or if I do not see the alert something is wrong with my use case?
Thanks
It sounds like IIS is only requiring client certificates for certain URLs (ie, for example.com/foo, but not example.com/bar).
In the initial handshake, it does not know which url you are requesting, so it does not require a certificate. When it sees that you are requesting a restricted resource (/foo), it then rehandshakes, requiring a certificate.
However, I would still expect a handshake_failure to occur.
As I was saying in an answer to this question, as far as I remember, IIS uses re-negotiation to get the client certificate. You should be able to change this behaviour using netsh and clientcertnegotiate=enable (depending on the version of IIS you're using).
You might also be interest in this similar question.
Failing to supply a certificate in response to a CertificateRequest isn't an SSL protocol error, so there is no handshake_error. 'Requiring' instead of just 'needing' client certificates is added-in by SSL libraries, and all they can do if you don't send one is just close the connection.