-
-
Notifications
You must be signed in to change notification settings - Fork 925
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
On ubuntu 16.04, "certificate verify failed" errors for www.google.com #4802
Comments
Also, when i provide my own Also another point of clarification: while I'm getting the verify errors for google.com, I'm not getting the for other sites, like yahoo.com for example |
we're seeing the same issue with both |
The latest In the meantime you could try to install the previous version of the |
@nilsding so is this behavior incorrect of JRuby, since MRI and curl don't seem to do it? |
Based on jruby/jruby-openssl#141 (comment), it looks like this may be an issue with Downgrading Update In addition to downgrading, I also needed to update |
Usually these problems are just bad CA certs on the Java side compared to the native size (as MRI would use). I assume this is latest jruby-openssl, yes? jruby-openssl is supposed to also use system certs, but we've had challenges integrating the built-in "blessed" certs in JDK with ones from the system. |
@headius yes I'm just using the default jruby-openssl that comes with JRuby 9.1.13.0, which looks like its the latest version, 0.9.21 |
Yes it happens with latest jruby-openssl. And it correctly uses the system certs but in the system certs the equifax root cert was removed in the latest update of ca-certificates(or similar on other distributions). This issue is also reproducible on various different machines and distributions (given it already got the latest ca-certificates update). |
@andreaseger Hmmm so perhaps there's some config we can use for how deep to verify? From what you're saying, it sounds like JRuby's doing the right thing, but that ignores why native OpenSSL would do the "wrong" thing here, and if it's actually wrong. |
Well I would not say that jruby-openssl is the only library which does the right thing. I would rather assume that the other libraries are doing the correct thing. This post https://www.mail-archive.com/openssl-dev@openssl.org/msg38674.html referenced in the jruby-openssl issue explains the situation quite well. Seems to just be only now an issue here with the equifax certificate being revoked. And for apples certificates it's probably similar with one of the other certificates which got revoked in the recent updates. Oh and regarding verification depth I have tried setting |
In the "are we crazy?" file, we also encountered this issue using phantom 2.1.1 on Ubuntu 16.04, and your instructions for downgrading temporarily fixed the problem for us. I say temporarily because, hey, I want to pull those certs at some point, too. We are not using jruby, I'm just commenting for solidarity's sake in response to:
It's at least you and DocRaptor. |
@mediocrates Thanks for that! So it seems the cert change is causing problems for at least one other project. |
Well I'm downloading Ubuntu 16.04 to reproduce locally. I'll see if I can come up with anything. |
Well the good news is that 9.1.14 on fully-updated Ubuntu 16.04 was able to run @mohamedhafez's script without any errors. However the jruby-openssl issue is still open, so I'm not sure if this is fixed or my environment does not reflect yours. Can someone post the version of ca-certificates that introduces the problem, so I can confirm I'm on the same version? |
@headius Does your
If so, prefix those lines with a |
@headius it was ca-certificates 20170717~16.04.1 |
Ok after updating ca-certificates to This may not get fixed for 9.1.14 but we should be able to drop a jruby-openssl update shortly after. |
I can confirm that setting SSLContext.verify_depth to 0 does not solve the problem for me either. I tried this via http.verify_depth, HTTP.start with keyword arg :verify_depth, and hardcoded in HTTP#connect. I have not confirmed the depth setting is actually getting into the right place in jruby-openssl. |
Ok more clues. When I pass When I check the root certificates on Ubuntu, all GeoTrust certs are issued by GeoTrust. However when I grep for Equifax in my JDK install (1.8u131, same as the original report), I do get hits. I'm going to try to confirm that the GeoTrust cert in JDK 8u131 is still associated with Equifax. This may be a simple matter of out-of-date certs in OpenJDK. |
Yeah this is weird. I see the discrepancy on macos as well, but the Equifax certs have not been excluded there. Here's keychain for the GeoTrust Global CA cert: And here it is in the javax.net.debug log:
I have been unable to figure out where it's getting this GeoTrust+Equifax cert. |
I have confirmed this still breaks under OpenJDK 8u151. |
I tried updating the Java CA cert for "GeoTrust Global CA" and it still seems to think it is issued by Equifax. |
Another attempt: I had forgotten that Debian-based dists try to share a cacerts across all JDKs, in the ca-certificates-java package and /etc/ssl/certs/java/cacerts. The latest package for 16.04 is a version from 2016, but I could not find any references to Experian in the cacerts file. I also tried to forcibly update the GeoTrust cert in that global cacerts, and it did not appear to help. |
Forcibly updating ca-certificates-java to the lastest Debian package (20170930) also does not appear to help. |
Maybe related to the issue I had 2 years ago? lostisland/faraday#371 (comment) |
@tomekw Hmm could be. I could see some sort of ordering problem causing a thing like this. |
I've continued exploration. The logic in JRuby (jruby-openssl) is in StoreContext.verifyCertificate. This logic mimics what other SSL libraries do to acquire and verify the certificate chain. The problem still seems to be that we're getting a bad certificate. Once the chain is prepared, the logic proceeds to confirm that the last cert in the chain is self-signed and in the certificate store, which would indicate it is in the trust root. In the current case, that certificate comes in as the GeoTrust/Equifax cert of unknown origin. Because it's not self-signed, we attempt to acquire its issuer's certificate, but the Equiface cert is no longer available. So where is Equifax coming from? Running strace against Java seems to show it only looking at the cacerts in my JDK install. When I dump that complete keystore, there's no references to Equifax. |
Ok, so I've confirmed that the certs coming from the Java keystore are correct: the root "GeoTrust Global CA" certificate is self-signed self-issued. I've also figured out that Equifax is coming from the connection itself. Here's part of a packet read during handshake negotiation:
So either we are supposed to do something else with this data that does not run up against the revoked Equifax cert, or we're making the request in such a way that Google is sending us bad cert info. |
I think I've finally figured out what we're doing wrong. Google.com is sending a chain of certificates that still contains a "GeoTrust Global CA" certificate claiming that it was issued by Equifax. However the Equifax certificate is no longer trusted (in some contexts? all contexts?). We are doing the right thing, for a pre-2015 OpenSSL clone. However, OpenSSL changed how they verify the certificate chain around 2015. The change detailed above allows the verification logic to substitute a certificate from the trusted store for any untrusted cert coming back from the connection. In this case, we'd see that there's a better, newer cert for "GeoTrust Global CA" and use that one instead of the bad Equifax-issued cert Google is returning to us. I'm not sure the best way to do this at the moment, but it would be part of the StoreContext.verifyCertificate method I mentioned earlier. I'm also still confused why Google (and apparently Apple and others) are still returning this bad root certificate. |
Well, this is progress. With the following patch, the test script works properly. I seriously doubt I'm doing this right. My patch basically just eagerly searches through the incoming chain of certs, looks for matching DN in the trust store, and replaces the incoming cert with the trusted cert. That replaces the bad GeoTrust cert with a good one, and it works right. The OpenSSL logic appears to do this lazily. I need to study it more to figure out the proper fix. If someone else wants to jump in, let me know :-) diff --git a/src/main/java/org/jruby/ext/openssl/x509store/StoreContext.java b/src/main/java/org/jruby/ext/openssl/x509store/StoreContext.java
index 1e10880..3438edd 100644
--- a/src/main/java/org/jruby/ext/openssl/x509store/StoreContext.java
+++ b/src/main/java/org/jruby/ext/openssl/x509store/StoreContext.java
@@ -665,6 +665,19 @@ public class StoreContext {
num = chain.size();
x = chain.get(num - 1);
depth = verifyParameter.depth;
+
+ List<X509Object> objects = store.getObjects();
+ for (int j = 0; j < sktmp.size(); j++) {
+ X509AuxCertificate cert = sktmp.get(j);
+ for (X509Object obj : objects) {
+ if (obj instanceof Certificate) {
+ if (cert.cert.getSubjectDN().equals(((Certificate) obj).x509.getSubjectDN())) {
+ sktmp.set(j, ((Certificate) obj).x509);
+ }
+ }
+ }
+ }
+
for(;;) {
if ( depth < num ) break; |
Updated patch in jruby/jruby-openssl#149. This is a bit cleaner but needs some heavy review. The logic in OpenSSL is spread all over, but it does appear to attempt to replace certs in the untrusted list with equivalent certs from the store before proceeding on to verification. My version does that for all certs in the untrusted list, in turn, until none are left or one gets replaced. Once replaces, the rest of the chain is tossed out, since we have a trusted root. |
This will get fixed in an update release to jruby-openssl, but not before the 9.1.14 release. |
This has not been updated by anyone in a long time...is there a chance that it has generally healed as old certs get dumped and CAs updated? |
@headius Just retried with JRuby 9.1.17.0 on ubuntu 16.04 with all the latest packages, and everything is working properly again! |
yep, seems like both Apple and Google have updated their certificate chains. |
the certificate chain mess, seems to have been resolved. no reports at jossl's for a good while. |
I just did a
apt dist-upgrade
on my ubuntu 16.04 machine, and now when net::http tries to connect to www.google.com, it throws a "OpenSSL::SSL::SSLError: certificate verify failed". The ubuntu packages that got upgraded apparently affect the cert files and certificate verification, so i'm guessing that breaks jruby somehow:I thought it might be a bug with one of the packages, but
curl
still works without issue, and also the following code works in irb on ruby-2.3.0 on ubuntu, jruby 9.1.13.0 on mac, but not jruby 9.1.13.0 on my ubuntu machine:### Environment
JRuby version (
jruby -v
) and command line (flags, JRUBY_OPTS, etc):jruby 9.1.13.0 (2.3.3) 2017-09-06 8e1c115 OpenJDK 64-Bit Server VM 25.131-b11 on 1.8.0_131-8u131-b11-2ubuntu1.16.04.3-b11 +jit [linux-x86_64]
Operating system and platform (e.g.
uname -a
)Linux momoserver 4.4.0-96-generic #119-Ubuntu SMP Tue Sep 12 14:59:54 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
### Expected Behavior
www.google.com's ssl certificate should be verified without issue
### Actual Behavior
OpenSSL::SSL::SSLError: certificate verify failed
The text was updated successfully, but these errors were encountered: