Firefox SSL_ERROR_RX_UNKNOWN_ALERT error when accessing Tomcat site - ssl

When attempting to access my Apache Tomcat v9 site via HTTPS in Firefox, I am met with:
An error occurred during a connection to localhost:8443. SSL received an alert record with an unknown alert description.
Error code: SSL_ERROR_RX_UNKNOWN_ALERT
The Tomcat server has a certificate that is trusted by my Firefox. The Tomcat server is configured to require client certificates, of which I have one installed, but Firefox is not prompting me to select one.
There are no errors (or messages of any kind) in any logs in Tomcat. The strange thing is that this used to work last week but has stopped. I tried issuing the server a new certificate but that did not resolve this.

It turns out this is the cryptic error you get in Firefox when it cannot find a client certificate to send the server. In my case the client certificate I had installed expired a couple days ago (which is why it used to work) and so Firefox was not sending it to the server and was thus getting that response.
Generating a new client certificate and loading it into Firefox resolved the issue.
I was able reproduce the error later on by selecting "Cancel" when Firefox asks me what client certificate to use.
I am not sure if it's Tomcat giving the weird SSL response of if it's Firefox not able to understand what's going on but I hope this answer helps others facing this issue in the future.

Related

Tomcat (v7.0.47) behind Apache2 HTTPD (v2.4.23): connection fails after Java upgrade

We are running a legacy application on an Apache v7.0.47 server behind an Apache2 HTTPD proxy (v2.4.23).
I am trying to upgrade the Java version on the server (used by both the proxy as well as the tomcat) from v1.8.0_181 to v1.8.0_303.
After that upgrade the Tomcat does not respond any more to the Apache's passed-on requests (the application itself comes up and runs fine).
Both the Apache on its network facing side as well as Apache and Tomcat among each other were configured to "talk" TLS1.2 already for a while, so I don't think that the disabling of TLSv1.0 and TLSv1.1 in the later Java version is the cause of the issue here. And there is no error message in the logs giving any clue. The only indication is, that the Tomcat seems to close and tear down the connection without any response after having receiving the request. That seems to happen already in the SSL layer, since there is no entry in the access-log (of Tomcat).
Switching back to the "old" Java gets things going again, so firewall, network etc. are definitely NOT the issue here. With the newer Java version the connection setup fais again, causing the HTTPD to emit a "502 Bad gateway" error.
Any idea anyone what could cause the Tomcat to reject the HTTPD's requests just based on the Java version? Additional SSL verifications enabled by default in the newer stack? I searched extensively but didn't surface any suspect, yet.
Later addition: trying to identify the issue I found out that with Java v1.8.0_231 things are still working, with v1.8.0_241 and higher it fails.
Inspecting the release notes now to find a hint...
Any ideas or experiences with that upgrade anyone?
Just for the records - in case someone else stumbles over this question:
The issue here was that from Java v1.8.0_241 on upwards Java security verifies that a certificate chain read from a certificate store is rooted in a CA certificate that has a proper CA-flag. Since we were using an old certificate and trust store that had been generated with an old release of the java keytool back than this flag was missing and the new Java version thus rejected all the entries in that certificate file. It thus aborted the SSL connection setup and simply closed the connection without any response or indication.
There is a VM option -Djdk.security.allowNonCaAnchor=true that one can add to Tomcat's JAVA_OPTS variable (typically in a file setenv.sh) to disable this verification. After adding that our Tomcat was again responding to SSL-requests and worked OK again.
BTW: when trying to analyze SSL issues like the above the option -Djavax.net.debug=all:handshake:verbose proved to be a real live-saver! With this option one gets very details log output and can follow SSL handshakes and connection setups in detail. Once I had finally gotten a first useful error message pointing to this CA-flag issue searching for a solution (or rather workaround in this case) proved to be a snap compared to the initial search for what could be the issue here.

SSL/TLS error with website

I have a website using tls1.2,1.1 and 1.0(ssllabs) . I am using websense proxy to access it. Have enabled tls1.1 and tls1.2 on the WCG. I am still getting Peer disconnected error. The website worked once and is giving the error randomly. I have websense 8 and the URL in question is https://rem2.piiapps.com/site/login. It works fine with websense 7. I dont have a ssl bypass option due to security restrictions. Sometimes the browser indicates that the certificate is broken and sometimes it is healthy.
I did some analysis and found that this URL was using a real time communication protocol which is not supported by deafult in websense. It has to be tunneled in the incident list.

SSL certificate expired in android app but not in pc/mobile browsers

So here's a weird situation. I have a website running on https. I also have an app on android which leverages this website to make rest API calls. Everything was working fine until now. Recently my hoster changed something and everything is falling apart. When I fire rest request from browser it works fine. But when I do it using the app it doesn't work and I get this exception:
javax.net.ssl.SSLHandshakeException: com.android.org.bouncycastle.jce.exception.ExtCertPathValidatorException:
Could not validate certificate: Certificate expired at Thu Aug 21 06:03:34 EDT 2014 (compared to Sat Aug 22 17:41:59 EDT 2015)
at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java
But everything working fine on pc and I double checked the certificates are expiring on 2016.
So I went a step further and tried to browsershot my website and I got some funny results. Out of 300 browsers I got the same issue in a couple of them.
http://i.stack.imgur.com/d86tE.png
http://oi60.tinypic.com/30ml1n4.jpg
Also I'm now getting this warning in my host while installing SSL.
"Note: You do not have a dedicated IP address. As a result, web browsers that do not support SNI will probably give false security warnings to your users when they access any of your SSL websites. Microsoft® Internet Explorer™ on Windows XP™ is the most widely used web browser that does not support SNI."
I'm not 100% sure whether this warning was there earlier or not but I'm just trying to put the pieces together.
There is nothing wrong with the code as my apps on the phone have stopped working which was working earlier.
Server Name Indication (SNI) means that the client (browser, app) sends the expected host name inside the SSL/TLS handshake. This is similar to the Host HTTP header and makes it possible to have multiple virtual servers with different hostnames share the same IP address.
If your client does not support SNI the server will either send some default certificate back or will trigger an error in the SSL/TLS handshake.
SNI is supported by all modern browsers, but older browsers or platforms like IE8 on XP do not support SNI. Also the Apache HTTP Request Library as shipped with the Android SDK does not support SNI which might be the issue in your case.
Everything was working fine until now. Recently my hoster changed something and everything is falling apart.
I guess this is the result of an incomplete change. It looks like the certificate for clients using SNI was replaced with a newer version because the previous one expired. But the default certificate of the site, i.e. the one used for non-SNI clients, is still the old expired certificate. Thus you get a valid certificate with all clients using SNI but an expired error with all clients not capable of doing SNI.
I ran into the same problem while calling a third party API from my android app.
To solve the problem I used HttpsURLConnection class from javax.net.ssl package which has SNI support.
A example to perform an API call.
import javax.net.ssl.HttpsURLConnection;
import java.net.URL;
public void performApiCall() {
try {
URL url = new URL("https://yourdestination.com");
HttpsURLConnection connection = (HttpsURLConnection)url.openConnection();
connection.setRequestProperty("content-type", "application/x-www-form-urlencoded");
connection.setRequestMethod("POST");
// other stuffs like adding parameters etc. Used android.util.Pair.
connection.connect();
// you can read response based on connection.getResponseCode()
}catch(Exception e){
e.printStackTrace();
}
}

Why does my wss:// (WebSockets over SSL/TLS) connection immediately disconnect without giving any errors?

Posting this for anybody else running across the same problem.
I was working on a browser client that used stanza.io to connect to an XMPP server (Prosody, in my case). I was using a wss:// connection by default. At some point during development, my client failed to connect at all - it would immediately disconnect silently, without providing any kind of useful error information.
There were no error logs, no error codes, no confirmation dialogs or bars, no indications of what might be wrong.
After hours of debugging, I eventually found the problem; as I was messing around with the configuration of my XMPP server, I had re-generated the SSL certificates for the XMPPd. Since I was using self-signed certificates, this would cause an SSL error. Because I had visited that same URI over HTTPS before, I'd already manually approved the old self-signed certificate - but obviously that approval was no longer valid after regenerating the SSL certificate.
The key to the problem is this: If your SSL certificate causes a warning of any sort, wss:// WebSocket connections will immediately fail, and there is no canonical way to detect this.
As stated above, there appears to be no standardized way to even detect that this problem is occurring, let alone solve it. The best solution to this problem that I have been able to find, is as follows:
If the WebSocket disconnects prior to having received a login confirmation (XMPP-specific), try to make a plaintext ws:// (without SSL) connection to the non-SSL port.
If the plaintext connection succeeds, this means that the server is up - thus the problem is with the SSL certificate. (If the plaintext connection also fails, the server is simply unavailable.)
Display an error to the user, indicating that there was an SSL problem, and that they should check the certificate, with instructions on how to manually approve it.
Provide a target="_blank" link to the wss:// URL, but replacing the protocol with https://. This might be Prosody-specific, but by visiting that URL you will see the SSL warning page. Prosody will display a text that starts with "It works!" after approving the certificate - if the server-side is a custom application, you should display a message saying that "the problem has been solved, you can close this tab now".
In the background, in the main application, keep attempting to reconnect over wss:// every few seconds. Once a connection succeeds, this means the user has approved the certificate. Hide/remove the error and continue the normal connection/login process.
It's far from a smooth process, UX-wise, but it's the smoothest approach I've found. It is not possible to iframe the error page (this was one of my first ideas) - Chrome will refuse to load it at all, Firefox will hide the "Add exception" button, and I'd imagine other browsers exhibit similar behaviour.
Remember that modern browsers do not like self-signed certificates.
Therefore, if your secure WebSocket connection dies before ending the handshake, it could mean that the certificate has not been accepted.
In order to solve the issue, you can:
buy a certificate signed by a Central Authority
simply open in a new
Tab or Window the link of you WebSocket's URI and tell the browser to
trust the connection.
Come back to your WebSocket and it should work.
This is what I did and it worked:
1 - Generate self signed certificate
2 - Create an https websockets server this way

Browser is not prompting for a client certificate

Background:
I am updating an internal application to a two-step authentication process. I want to add a client certificate authentication process (via a smart card) on top of a traditional username/password form. The application is written in C#, hosted on IIS7, and targeting Chrome and IE8.
Problem:
I am having issues with getting the application to prompt the user for a client certificate. I have been debugging the application with the help of Fiddler. When I have a test client certificate saved in Fiddler's user's directory (C:\Documents and Settings\USER\My Documents\Fiddler2), the application works as expected. I am prompted for a PIN number protecting the smart card, and, when entered correctly, takes me to the login form. When I close Fiddler, the application throws a 403 Forbidden error instead (since Fiddler is no longer running and pointing to its certificate). What I haven't been able to figure out is why the application won't prompt for a certificate normally.
Current Server Setup:
Self Signed Certificate was created
443 Binding is pointing at Self Signed Certificate
Anonymous Authentication is Enabled
The Self Signed Certificate was added to both the Trusted Root CA and Intermediate CA (I read that another person had it in both rather than just the Trusted Root CA and that solved their issue, though neither set up has worked for us).
I cleared out the rest of the certificates in the Trusted Root CA that I didn't need (I read elsewhere that having too many certificates would cause SSL to choke).
I am out of ideas to try other than starting from scratch on another server. Does anyone know what the issue might be? This seems like it should be fairly straight forward and that I'm missing something minor. Any ideas are welcomed.
Update:
After spending more time with this issue today, I strongly believe it has to do with IIS7 not being configured correctly (I did not set up it originally). I think this because I enabled Failed Request Tracing, looked at the subsequent .xml files being generated, and saw that a 500 error was being thrown.
Chrome is throwing a "Access to the webpage was denied" message rather than a "403 - Forbidden: Access is denied". I don't know if this helps. I do know that when I do not make certificates required, the site will work as intended. Requiring a certificate is where it fails.
The Application Pool is set to .Net 4.0 | Classic | Network Service.
Your problem is that the browser doesn't either get the request to provide client certificate or there is a security related option to block it from happening. IE offers certificate only if the web site is in correct zone (intranet or trusted sites). Please check this before everything.
If that doesn't help then see this answer for next step. The netsh documentation says:
clientcertnegotiation
Optional. Specifies whether the negotiation of certificate is enabled or disabled. Default is disabled.
Enable that and even the dumbest browser should notice that it is supposed to offer certificate for authentication. To diagnose your problem further you can use WireShark to see the negotiation in action.
In every browser I've seen, the browser will not prompt you to select a certificate if it does not have any certificates signed by a CA the server trusts. So make sure your server is configured with the correct CAs. As Boklucius suggested, you can use openssl to examine the list of trusted CAs your server is sending to clients and see whether the CA you have signed your client certificates with is among them.
Try openssl s_client -connect yourip:443 -prexit
And see if the CA (your self signed cert) is send to the client in the Acceptable client certificate CA names.
you need to install openssl first if you don't have it
I'll throw in a "try restarting the browser" suggestion, particularly if you installed the certificate while the browser was running.
To add a rather painful lesson to the mix: Make sure you quit Skype (or any other application) that eats port 443.
So the idea here is if you are running a dev environment on the same machine (both client and IIS), and your team uses Skype or some other app to communicate.
Watch the hours go by as you try and debug this problem, seemingly doing everything "right", netsh http sslcerts and such, even rebooting but to no avail. Well, turns out Skype will eat 443 so turn it off and "poof" there goes your certificate prompt.
Then feel free to throw things at the wall, shout obscenities or just "Rage, rage against the dying of the light".
Also, make sure Fiddler isn't getting in the way. If you have it decrypting the SSL, it'll corrupt the message back to IE, and it doesn't have the certificate installed, so it can't offer it. Turn off fiddler, and voila, the certificate prompt appears.
In Firefox, if you press 'Cancel' the first time you're prompted for a certificate, and you left the sneaky 'Remember this decision' box checked, then Firefox will remember that and never offer it again.
You can view and delete your previous remembered decisions in Firefox Preferences -> Privacy & Security (about:preferences#privacy), View Certificates, and check the Authentication Decisions tab.
Just connecting to my VPN and trying showed me the certificate prompt. Needs to be done only the first time.