Translate

Wednesday, March 29, 2017

Eclipse Plugins via HTTPS and Let's Encrypt

In this post, you'll learn how to update and add security to your Java version or import the Let’s Encrypt root certificate into your trust store.

· Security Zone

Having problems installing your favorite SourceForge-hosted Eclipse plugins? Getting a “No repository found” error for updates sites you know should exist?

You Might Just Need a Java Update

Chances are your update site uses HTTPS with a root certificate that isn’t trusted by your Java installation. Check your error log to see if an error message like this was logged: “unable to find valid certification path to requested target.”
As for SourceForge, this is caused by a recent move of its mirror servers to Let’s Encrypt certificates. And you will be affected by this even if you’re using plain HTTP URLs because SourceForge will redirect your downloads to one of its mirrors forcing HTTPS. Unfortunately, older Java versions do not include the necessary root certificates to support Let’s Encrypt.
The easiest way to fix this is to just update your Java to the latest version. Let’s Encrypt claims that Java 1.8.101 or newer will work, but it looks like neither v101 nor 102 contains the necessary certificates, but the latest 121 version does. Don’t forget to apply JCE Unlimited Strength policies to your new Java version, which are required by some SourceForge mirrors as well.

Adding Certificates to Your Java Trust Store

Of course just updating your Java version only works if the certificate you need has been added to the Java trust store. While this is the case for Let’s Encrypt, you might be out of luck for your favorite Eclipse plugin on some other site. Or you might be stuck with your older Java version for whatever reason. In that case, you’ll need to figure out which certificate is needed by the site in question and add it to your Java trust store.
The easiest way to do this, in general, is to open the update site URL in your web browser and view the certificate chain (this doesn’t work for SourceForge, see below). But you can get the Let’s Encrypt root certificate here, or just visit https://letsencrypt.org to export it yourself. Select the certificate you want to add to your trust store and save it to a file. Usually, this is the root certificate or one fairly high up the chain. You can then import the certificate into your Java trust store with the following command:
<path to JRE>/bin/keytool -importcert -keystore <path to JRE>/lib/security/cacerts -file <path to cert file> -alias <alias>

Choose a proper alias to recognize the certificate, and confirm the install. In case your trust store requires a password, the Oracle Java default is changeit. If you have a JDK installed, you might want to do this for both the JRE in the JDK and for the public JRE.
If you don’t want to change your system-wide trust store, you can also tell Eclipse to use a custom one. Just copy your system trust store to a new file and perform the above steps (or start fresh with whatever certificates you like) and add the following to your  eclipse.ini (make sure that it comes after the  -vmargs parameter):
-Djavax.net.ssl.trustStore="<path/to/custom/truststore>" 
-Djavax.net.ssl.trustStorePassword=<password>

Figuring Out the Right Certificates

If you want to really dig into this, here's how to figure out which servers are used by your update site, and which certificates they require.
The easiest way to figure out the certificates you need is to just open the update site in your web browser. However, this does not work if the website uses a different certificate than the download server. In fact, this is just what’s happening with SourceForge at the moment. The website itself is still using a GeoTrust certificate, which is supported by most Java versions, while many of the download mirrors it redirects you to have made the move to Let’s Encrypt.
So how can you figure this out? Your web browser won’t be of much help in this case because it will only let you view certificate information for websites, but not for downloads. If you feel comfortable with the command line,  curl and openssl, this will give you what you need.
First, let’s find the download server that actually serves our requested files. I’m using the popular PMD Eclipse plugin as an example here. The update site URL for its latest release is http://sourceforge.net/projects/pmd/files/pmd-eclipse/update-site-latest/. To identify the actual download server, we follow the HTTP redirect chain with HEAD requests in curl (I request the p2.index here, but you can use any file on the site for this):
curl -i -I -L http://sourceforge.net/projects/pmd/files/pmd-eclipse/update-site-latest/p2.index

The output will look something like this:
HTTP/1.0 301 Moved Permanently
...
Location: https://sourceforge.net/projects/pmd/files/pmd-eclipse/update-site-latest/p2.index
HTTP/1.1 302 Found
...
Location: https://netcologne.dl.sourceforge.net/project/pmd/pmd-eclipse/update-site-latest/p2.index
HTTP/2 200
server: nginx/1.11.10
date: Mon, 06 Mar 2017 09:38:56 GMT
content-type: application/octet-stream
content-length: 172
...

This tells us that the final download server is netcologne.dl.sourceforge.net, and as you can see, it uses HTTPS, even if the original URL didn’t.
Now, we can use openssl  to figure out the certificate chain used by this server:
echo -n | openssl s_client -host netcologne.dl.sourceforge.net -port 443 -prexit -showcerts
It gives us the certificate chain in blocks like this:
0 s:/.dl.sourceforge.net
   i://'s Encrypt/'s Encrypt Authority X3
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
This tells us the certificate subject s and issuer i, followed by the certificate’s encoded data. We can follow the certificates up the chain to the root, in this case
1 s://'s Encrypt/'s Encrypt Authority X3
   i:/ Signature Trust Co./ Root CA X3

If the root certificate is returned by the server, you can just save the block from  -----BEGIN CERTIFICATE-----  to  -----END CERTIFICATE-----  to a file and import it as outlined above. In this example, though the root certificate itself is not returned, it is assumed that your operating system’s trust store can provide it by name. At this point you can either use the name we’ve just figured out, DST Root CA X3, to dig around in your OS trust store to export this certificate and import it into your Java store. Or you can try to visit the certificate issuer’s website to download it from there. In our case, Let’s Encrypt has the full certificate path in its own HTTPS site, so we can just use our web browser again to save the certificate we want.
Once you figured out which certificates you need, and have added them to your trust store, you should be good to go. So go ahead, try it out, and have fun with your favorite plug-ins in Eclipse.