Ignore:
Timestamp:
2017-04-17T14:07:04+02:00 (3 years ago)
Author:
Don-vip
Message:

fix #14649 - load Dutch Government (G2 & G3) certificates from Windows keystore if not found in Java keystore

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/io/CertificateAmendment.java

    r11903 r11943  
    1616import java.security.KeyStoreException;
    1717import java.security.MessageDigest;
     18import java.security.NoSuchAlgorithmException;
     19import java.security.cert.CertificateEncodingException;
     20import java.security.cert.CertificateException;
    1821import java.security.cert.CertificateFactory;
    1922import java.security.cert.PKIXParameters;
     
    4043public final class CertificateAmendment {
    4144
    42     private static final String[] CERT_AMEND = {
    43         "resource://data/security/DST_Root_CA_X3.pem"
     45    /**
     46     * A certificate amendment.
     47     * @since 11940
     48     */
     49    public static class CertAmend {
     50        private final String id;
     51        private final String sha256;
     52
     53        CertAmend(String path, String sha256) {
     54            this.id = path;
     55            this.sha256 = sha256;
     56        }
     57
     58        /**
     59         * Returns the certificate identifier.
     60         * @return path for JOSM embedded certificate, alias for platform certificate
     61         */
     62        public final String getId() {
     63            return id;
     64        }
     65
     66        /**
     67         * Returns the SHA-256 hash.
     68         * @return the SHA-256 hash, in hexadecimal
     69         */
     70        public final String getSha256() {
     71            return sha256;
     72        }
     73    }
     74
     75    /**
     76     * Certificates embedded in JOSM
     77     */
     78    private static final CertAmend[] CERT_AMEND = {
     79        new CertAmend("resource://data/security/DST_Root_CA_X3.pem",
     80                "0687260331a72403d909f105e69bcf0d32e1bd2493ffc6d9206d11bcd6770739")
    4481    };
    4582
    46     private static final String[] SHA_HASHES = {
    47         "0687260331a72403d909f105e69bcf0d32e1bd2493ffc6d9206d11bcd6770739"
     83    /**
     84     * Certificates looked into platform native keystore and not embedded in JOSM.
     85     * Identifiers must match Windows keystore aliases for efficient search.
     86     */
     87    private static final CertAmend[] PLATFORM_CERT_AMEND = {
     88        new CertAmend("Staat der Nederlanden Root CA - G2",
     89                "668c83947da63b724bece1743c31a0e6aed0db8ec5b31be377bb784f91b6716f"),
     90        new CertAmend("Government of Netherlands G3",
     91                "3c4fb0b95ab8b30032f432b86f535fe172c185d0fd39865837cf36187fa6f428")
    4892    };
    4993
     
    66110        }
    67111
     112        MessageDigest md = MessageDigest.getInstance("SHA-256");
    68113        CertificateFactory cf = CertificateFactory.getInstance("X.509");
    69114        boolean certificateAdded = false;
    70         for (int i = 0; i < CERT_AMEND.length; i++) {
    71             try (CachedFile certCF = new CachedFile(CERT_AMEND[i])) {
    72                 byte[] certBytes = certCF.getByteContent();
    73                 ByteArrayInputStream certIS = new ByteArrayInputStream(certBytes);
    74                 X509Certificate cert = (X509Certificate) cf.generateCertificate(certIS);
    75                 MessageDigest md = MessageDigest.getInstance("SHA-256");
    76                 String sha1 = Utils.toHexString(md.digest(cert.getEncoded()));
    77                 if (!SHA_HASHES[i].equals(sha1)) {
    78                     throw new IllegalStateException(
    79                             tr("Error adding certificate {0} - certificate fingerprint mismatch. Expected {1}, was {2}",
    80                             CERT_AMEND[i],
    81                             SHA_HASHES[i],
    82                             sha1
    83                             ));
    84                 }
    85                 if (certificateIsMissing(keyStore, cert)) {
    86                     if (Main.isDebugEnabled()) {
    87                         Main.debug(tr("Adding certificate for TLS connections: {0}", cert.getSubjectX500Principal().getName()));
    88                     }
    89                     String alias = "josm:" + new File(CERT_AMEND[i]).getName();
    90                     keyStore.setCertificateEntry(alias, cert);
     115        // Add embedded certificates. Exit in case of error
     116        for (CertAmend certAmend : CERT_AMEND) {
     117            try (CachedFile certCF = new CachedFile(certAmend.id)) {
     118                X509Certificate cert = (X509Certificate) cf.generateCertificate(
     119                        new ByteArrayInputStream(certCF.getByteContent()));
     120                if (checkAndAddCertificate(md, cert, certAmend, keyStore)) {
    91121                    certificateAdded = true;
    92122                }
    93123            }
     124        }
     125
     126        try {
     127            // Try to add platform certificates. Do not exit in case of error (embedded certificates may be OK)
     128            for (CertAmend certAmend : PLATFORM_CERT_AMEND) {
     129                X509Certificate cert = Main.platform.getX509Certificate(certAmend);
     130                if (checkAndAddCertificate(md, cert, certAmend, keyStore)) {
     131                    certificateAdded = true;
     132                }
     133            }
     134        } catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException | IllegalStateException e) {
     135            Main.error(e);
    94136        }
    95137
     
    101143            SSLContext.setDefault(sslContext);
    102144        }
     145    }
     146
     147    private static boolean checkAndAddCertificate(MessageDigest md, X509Certificate cert, CertAmend certAmend, KeyStore keyStore)
     148            throws CertificateEncodingException, KeyStoreException, InvalidAlgorithmParameterException {
     149        if (cert != null) {
     150            String sha256 = Utils.toHexString(md.digest(cert.getEncoded()));
     151            if (!certAmend.sha256.equals(sha256)) {
     152                throw new IllegalStateException(
     153                        tr("Error adding certificate {0} - certificate fingerprint mismatch. Expected {1}, was {2}",
     154                            certAmend.id, certAmend.sha256, sha256));
     155            }
     156            if (certificateIsMissing(keyStore, cert)) {
     157                if (Main.isDebugEnabled()) {
     158                    Main.debug(tr("Adding certificate for TLS connections: {0}", cert.getSubjectX500Principal().getName()));
     159                }
     160                String alias = "josm:" + new File(certAmend.id).getName();
     161                keyStore.setCertificateEntry(alias, cert);
     162                return true;
     163            }
     164        }
     165        return false;
    103166    }
    104167
Note: See TracChangeset for help on using the changeset viewer.