Index: src/org/openstreetmap/josm/io/CertificateAmendment.java
===================================================================
--- src/org/openstreetmap/josm/io/CertificateAmendment.java	(revision 0)
+++ src/org/openstreetmap/josm/io/CertificateAmendment.java	(working copy)
@@ -0,0 +1,141 @@
+// 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" };
+    public static final String[] SHA_HASHES = { "139a5e4a4e0fa505378c72c5f700934ce8333f4e6b1b508886c4b0eb14f4be99" };
+
+    /**
+     * 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 {
+        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;
+    }
+}

Property changes on: src/org/openstreetmap/josm/io/CertificateAmendment.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: src/org/openstreetmap/josm/gui/MainApplication.java
===================================================================
--- src/org/openstreetmap/josm/gui/MainApplication.java	(revision 9992)
+++ src/org/openstreetmap/josm/gui/MainApplication.java	(working copy)
@@ -57,6 +57,7 @@
 import org.openstreetmap.josm.gui.preferences.server.OAuthAccessTokenHolder;
 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;
 import org.openstreetmap.josm.io.OnlineResource;
@@ -400,6 +401,12 @@
             }
         }
 
+        try {
+            CertificateAmendment.addMissingCertificates();
+        } catch (IOException ex) {
+            ex.printStackTrace();
+            Main.warn(getErrorMessage(Utils.getRootCause(ex)));
+        }
         Authenticator.setDefault(DefaultAuthenticator.getInstance());
         DefaultProxySelector proxySelector = new DefaultProxySelector(ProxySelector.getDefault());
         ProxySelector.setDefault(proxySelector);
Index: src/org/openstreetmap/josm/io/CachedFile.java
===================================================================
--- src/org/openstreetmap/josm/io/CachedFile.java	(revision 9992)
+++ src/org/openstreetmap/josm/io/CachedFile.java	(working copy)
@@ -5,6 +5,7 @@
 
 import java.io.BufferedInputStream;
 import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
 import java.io.Closeable;
 import java.io.File;
 import java.io.FileInputStream;
@@ -212,6 +213,24 @@
     }
 
     /**
+     * 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>
      * Detects Unicode charset in use utilizing {@link UTFInputStreamReader}.
Index: data/security/DST_Root_CA_X3.pem
===================================================================
--- data/security/DST_Root_CA_X3.pem	(revision 0)
+++ data/security/DST_Root_CA_X3.pem	(working copy)
@@ -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-----
