Index: /trunk/data/security/DST_Root_CA_X3.pem
===================================================================
--- /trunk/data/security/DST_Root_CA_X3.pem	(revision 9995)
+++ /trunk/data/security/DST_Root_CA_X3.pem	(revision 9995)
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/
+MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
+DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow
+PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD
+Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O
+rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq
+OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b
+xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw
+7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD
+aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
+HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG
+SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69
+ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr
+AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz
+R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5
+JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo
+Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ
+-----END CERTIFICATE-----
Index: /trunk/data/security/StartCom_Certification_Authority.pem
===================================================================
--- /trunk/data/security/StartCom_Certification_Authority.pem	(revision 9995)
+++ /trunk/data/security/StartCom_Certification_Authority.pem	(revision 9995)
@@ -0,0 +1,44 @@
+-----BEGIN CERTIFICATE-----
+MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEW
+MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg
+Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh
+dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM2WhcNMzYwOTE3MTk0NjM2WjB9
+MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi
+U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh
+cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA
+A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk
+pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf
+OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C
+Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT
+Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi
+HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM
+Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w
++2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+
+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3
+Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B
+26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID
+AQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE
+FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9j
+ZXJ0LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3Js
+LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFM
+BgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUHAgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0
+Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRwOi8vY2VydC5zdGFy
+dGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYgU3Rh
+cnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlh
+YmlsaXR5LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2Yg
+dGhlIFN0YXJ0Q29tIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFp
+bGFibGUgYXQgaHR0cDovL2NlcnQuc3RhcnRjb20ub3JnL3BvbGljeS5wZGYwEQYJ
+YIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNT
+TCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOCAgEAFmyZ
+9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8
+jhvh3TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUW
+FjgKXlf2Ysd6AgXmvB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJz
+ewT4F+irsfMuXGRuczE6Eri8sxHkfY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1
+ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3fsNrarnDy0RLrHiQi+fHLB5L
+EUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZEoalHmdkrQYu
+L6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq
+yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuC
+O3NJo2pXh5Tl1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6V
+um0ABj6y6koQOdjQK/W/7HW/lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkySh
+NOsF/5oirpt9P/FlUQqmMGqz9IgcgA38corog14=
+-----END CERTIFICATE-----
Index: /trunk/src/org/openstreetmap/josm/gui/MainApplication.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/MainApplication.java	(revision 9994)
+++ /trunk/src/org/openstreetmap/josm/gui/MainApplication.java	(revision 9995)
@@ -58,4 +58,5 @@
 import org.openstreetmap.josm.gui.preferences.server.ProxyPreference;
 import org.openstreetmap.josm.gui.util.GuiHelper;
+import org.openstreetmap.josm.io.CertificateAmendment;
 import org.openstreetmap.josm.io.DefaultProxySelector;
 import org.openstreetmap.josm.io.MessageNotifier;
@@ -401,4 +402,10 @@
         }
 
+        try {
+            CertificateAmendment.addMissingCertificates();
+        } catch (IOException ex) {
+            ex.printStackTrace();
+            Main.warn(getErrorMessage(Utils.getRootCause(ex)));
+        }
         Authenticator.setDefault(DefaultAuthenticator.getInstance());
         DefaultProxySelector proxySelector = new DefaultProxySelector(ProxySelector.getDefault());
Index: /trunk/src/org/openstreetmap/josm/io/CachedFile.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/io/CachedFile.java	(revision 9994)
+++ /trunk/src/org/openstreetmap/josm/io/CachedFile.java	(revision 9995)
@@ -6,4 +6,5 @@
 import java.io.BufferedInputStream;
 import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
 import java.io.Closeable;
 import java.io.File;
@@ -213,4 +214,22 @@
 
     /**
+     * Get the full content of the requested resource as a byte array.
+     * @return the full content of the requested resource as byte array
+     * @throws IOException in case of an I/O error
+     */
+    public byte[] getByteContent() throws IOException {
+        try (InputStream is = getInputStream()) {
+            ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+            int nRead;
+            byte[] data = new byte[8192];
+            while ((nRead = is.read(data, 0, data.length)) != -1) {
+                buffer.write(data, 0, nRead);
+            }
+            buffer.flush();
+            return buffer.toByteArray();
+        }
+    }
+
+    /**
      * Returns {@link #getInputStream()} wrapped in a buffered reader.
      * <p>
Index: /trunk/src/org/openstreetmap/josm/io/CertificateAmendment.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/io/CertificateAmendment.java	(revision 9995)
+++ /trunk/src/org/openstreetmap/josm/io/CertificateAmendment.java	(revision 9995)
@@ -0,0 +1,149 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.io;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.PKIXParameters;
+import java.security.cert.TrustAnchor;
+import java.security.cert.X509Certificate;
+import java.util.Objects;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManagerFactory;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.tools.Utils;
+
+/**
+ * Class to add missing root certificates to the list of trusted certificates
+ * for TLS connections.
+ *
+ * The added certificates are deemed trustworthy by the main web browsers and
+ * operating systems, but not included in some distributions of Java.
+ *
+ * The certificates are added in-memory at each start, nothing is written to disk.
+ */
+public class CertificateAmendment {
+
+    public static final String[] CERT_AMEND = { 
+        "resource://data/security/DST_Root_CA_X3.pem",
+        "resource://data/security/StartCom_Certification_Authority.pem"
+    };
+    public static final String[] SHA_HASHES = {
+        "139a5e4a4e0fa505378c72c5f700934ce8333f4e6b1b508886c4b0eb14f4be99",
+        "916a8f9232328192968c81c8edb672fa539f726861dfe379ca722050e19962cd"
+    };
+
+    /**
+     * Add missing root certificates to the list of trusted certificates for TLS connections.
+     * @throws IOException if an I/O error occurs
+     */
+    public static void addMissingCertificates() throws IOException {
+        if (!Main.pref.getBoolean("tls.add-missing-certificates", true))
+            return;
+        KeyStore keyStore;
+        try {
+            keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
+        } catch (KeyStoreException ex) {
+            throw new IOException(ex);
+        }
+        Path cacertsPath = Paths.get(System.getProperty("java.home"), "lib", "security", "cacerts");
+        try (InputStream is = Files.newInputStream(cacertsPath)) {
+            keyStore.load(is, "changeit".toCharArray());
+        } catch (NoSuchAlgorithmException ex) {
+            throw new RuntimeException(ex);
+        } catch (CertificateException ex) {
+            throw new IOException(ex);
+        }
+
+        CertificateFactory cf;
+        try {
+            cf = CertificateFactory.getInstance("X.509");
+        } catch (CertificateException ex) {
+            throw new RuntimeException(ex);
+        }
+        boolean certificateAdded = false;
+        for (int i = 0; i < CERT_AMEND.length; i++) {
+            CachedFile certCF = new CachedFile(CERT_AMEND[i]);
+            byte[] certBytes = certCF.getByteContent();
+            MessageDigest md;
+            try {
+                md = MessageDigest.getInstance("SHA-256");
+            } catch (NoSuchAlgorithmException ex) {
+                throw new RuntimeException(ex);
+            }
+            byte[] sha = md.digest(certBytes);
+            if (!SHA_HASHES[i].equals(Utils.toHexString(sha)))
+                throw new RuntimeException(tr("certificate hash mismatch"));
+
+            ByteArrayInputStream certIS = new ByteArrayInputStream(certBytes);
+            X509Certificate cert;
+            try {
+                cert = (X509Certificate) cf.generateCertificate(certIS);
+            } catch (CertificateException ex) {
+                throw new IOException(ex);
+            }
+            if (certificateIsMissing(keyStore, cert)) {
+                Main.debug(tr("Adding certificate for TLS connections: {0}", cert.getSubjectX500Principal().getName()));
+                String alias = "josm:" + new File(CERT_AMEND[i]).getName();
+                try {
+                    keyStore.setCertificateEntry(alias, cert);
+                } catch (KeyStoreException ex) {
+                    throw new AssertionError(ex);
+                }
+                certificateAdded = true;
+            }
+        }
+
+        if (certificateAdded) {
+            try {
+                TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+                tmf.init(keyStore);
+                SSLContext sslContext = SSLContext.getInstance("TLS");
+                sslContext.init(null, tmf.getTrustManagers(), null);
+                SSLContext.setDefault(sslContext);
+            } catch (NoSuchAlgorithmException | KeyStoreException | KeyManagementException ex) {
+                throw new RuntimeException(ex);
+            }
+        }
+    }
+
+    /**
+     * Check if the certificate is missing and needs to be added to the keystore.
+     * @param keyStore the keystore
+     * @param crt the certificate
+     * @return true, if the certificate is not contained in the keystore
+     */
+    private static boolean certificateIsMissing(KeyStore keyStore, X509Certificate crt) {
+        String id = crt.getSubjectX500Principal().getName();
+        PKIXParameters params;
+        try {
+            params = new PKIXParameters(keyStore);
+        } catch (KeyStoreException ex) {
+            throw new AssertionError(ex);
+        } catch (InvalidAlgorithmParameterException ex) {
+            throw new RuntimeException(ex);
+        }
+        for (TrustAnchor ta : params.getTrustAnchors()) {
+            X509Certificate cert = ta.getTrustedCert();
+            if (Objects.equals(id, cert.getSubjectX500Principal().getName()))
+                return false;
+        }
+        return true;
+    }
+}
Index: /trunk/test/unit/org/openstreetmap/josm/io/CertificateAmendmentTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/io/CertificateAmendmentTest.java	(revision 9995)
+++ /trunk/test/unit/org/openstreetmap/josm/io/CertificateAmendmentTest.java	(revision 9995)
@@ -0,0 +1,71 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.io;
+
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLConnection;
+
+import javax.net.ssl.SSLHandshakeException;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.openstreetmap.josm.JOSMFixture;
+
+/**
+ * Unit tests of {@link CertificateAmendment} class.
+ */
+public class CertificateAmendmentTest {
+
+    /**
+     * Setup test.
+     * @throws java.io.IOException in case of I/O exception
+     */
+    @BeforeClass
+    public static void setUp() throws IOException {
+        JOSMFixture.createUnitTestFixture().init();
+        CertificateAmendment.addMissingCertificates();
+    }
+
+    @Test
+    public void testDefault() throws IOException {
+        // something that is neither DST nor StartSSL
+        connect("https://google.com", true);
+    }
+
+    @Test
+    public void testLetsEncrypt() throws IOException {
+        // signed by letsencrypt
+        connect("https://helloworld.letsencrypt.org", true);
+        // signed by LE's cross-sign CA
+        connect("https://letsencrypt.org", true);
+    }
+
+    @Test
+    public void testStartSSL() throws IOException {
+        connect("https://map.dgpsonline.eu", true);
+        connect("https://www.startssl.com", true);
+    }
+
+    @Test
+    public void testBrokenCert() throws IOException {
+        // broken at the moment (may get fixed some day)
+        connect("https://www.pcwebshop.co.uk", false);
+    }
+
+    private void connect(String url, boolean shouldWork) throws IOException {
+        URLConnection connection = new URL(url).openConnection();
+        try {
+            connection.connect();
+        } catch (SSLHandshakeException e) {
+            if (shouldWork) {
+                Assert.fail("Untrusted: " + url);
+            } else {
+                return;
+            }
+        }
+        if (!shouldWork) {
+            Assert.fail("Expected error: " + url);
+        }
+    }
+}
