Changeset 15469 in josm for trunk


Ignore:
Timestamp:
2019-10-22T23:32:51+02:00 (4 years ago)
Author:
Don-vip
Message:

fix #10033, fix #15748, fix #17097 - drop remote control https support

Rationale: all modern browsers (including next version of Safari) allow mixed-content to localhost.

Cross-platform / cross-browser HTTPS support is a pain to maintain, was never completed, and is no longer needed.

Location:
trunk
Files:
1 deleted
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/build.xml

    r15462 r15469  
    198198                <attribute name="Application-Name" value="JOSM - Java OpenStreetMap Editor"/>
    199199                <!-- Java 9 stuff. Entries are safely ignored by Java 8 -->
    200                 <attribute name="Add-Exports" value="java.base/sun.security.util java.base/sun.security.x509 java.desktop/com.apple.eawt java.desktop/com.sun.imageio.spi java.desktop/com.sun.imageio.plugins.jpeg javafx.graphics/com.sun.javafx.application jdk.deploy/com.sun.deploy.config" />
     200                <attribute name="Add-Exports" value="java.desktop/com.apple.eawt java.desktop/com.sun.imageio.spi java.desktop/com.sun.imageio.plugins.jpeg javafx.graphics/com.sun.javafx.application jdk.deploy/com.sun.deploy.config" />
    201201                <attribute name="Add-Opens" value="java.base/java.lang java.base/java.nio java.base/jdk.internal.loader java.base/jdk.internal.ref java.desktop/javax.imageio.spi java.desktop/javax.swing.text.html java.prefs/java.util.prefs" />
    202202            </manifest>
     
    417417            <arg value="-Xdoclint:-html" if:set="isJava13" />
    418418            <arg value="-html5" if:set="isJava9" />
    419             <arg value="--add-exports" if:set="isJava9" />
    420             <arg value="java.base/sun.security.util=ALL-UNNAMED" if:set="isJava9" />
    421             <arg value="--add-exports" if:set="isJava9" />
    422             <arg value="java.base/sun.security.x509=ALL-UNNAMED" if:set="isJava9" />
    423419            <arg value="--add-exports" if:set="isJava9" unless:set="noJavaFX" />
    424420            <arg value="javafx.graphics/com.sun.javafx.application=ALL-UNNAMED" if:set="isJava9" unless:set="noJavaFX" />
     
    515511                    <jvmarg value="--add-modules" if:set="isJava9" unless:set="isJava11" />
    516512                    <jvmarg value="java.activation,java.se.ee" if:set="isJava9" unless:set="isJava11" />
    517                     <jvmarg value="--add-exports" if:set="isJava9" />
    518                     <jvmarg value="java.base/sun.security.util=ALL-UNNAMED" if:set="isJava9" />
    519                     <jvmarg value="--add-exports" if:set="isJava9" />
    520                     <jvmarg value="java.base/sun.security.x509=ALL-UNNAMED" if:set="isJava9" />
    521513                    <jvmarg value="--add-exports" if:set="isJava9" unless:set="noJavaFX" />
    522514                    <jvmarg value="javafx.graphics/com.sun.javafx.application=ALL-UNNAMED" if:set="isJava9" unless:set="noJavaFX" />
  • trunk/josm-latest.jnlp

    r15380 r15469  
    2121    </security>
    2222    <resources>
    23         <java version="1.8+" max-heap-size="2048m" java-vm-args="--add-modules=java.scripting,java.sql --add-exports=java.base/sun.security.util=ALL-UNNAMED --add-exports=java.base/sun.security.x509=ALL-UNNAMED --add-exports=java.desktop/com.apple.eawt=ALL-UNNAMED --add-exports=java.desktop/com.sun.imageio.spi=ALL-UNNAMED --add-exports=javafx.graphics/com.sun.javafx.application=ALL-UNNAMED --add-exports=jdk.deploy/com.sun.deploy.config=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.nio=ALL-UNNAMED --add-opens=java.base/jdk.internal.loader=ALL-UNNAMED --add-opens=java.base/jdk.internal.ref=ALL-UNNAMED --add-opens=java.desktop/javax.imageio.spi=ALL-UNNAMED --add-exports=java.desktop/com.sun.imageio.plugins.jpeg=ALL-UNNAMED --add-opens=java.desktop/javax.swing.text.html=ALL-UNNAMED --add-opens=java.prefs/java.util.prefs=ALL-UNNAMED"/>
     23        <java version="1.8+" max-heap-size="2048m" java-vm-args="--add-modules=java.scripting,java.sql --add-exports=java.desktop/com.apple.eawt=ALL-UNNAMED --add-exports=java.desktop/com.sun.imageio.spi=ALL-UNNAMED --add-exports=javafx.graphics/com.sun.javafx.application=ALL-UNNAMED --add-exports=jdk.deploy/com.sun.deploy.config=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.nio=ALL-UNNAMED --add-opens=java.base/jdk.internal.loader=ALL-UNNAMED --add-opens=java.base/jdk.internal.ref=ALL-UNNAMED --add-opens=java.desktop/javax.imageio.spi=ALL-UNNAMED --add-exports=java.desktop/com.sun.imageio.plugins.jpeg=ALL-UNNAMED --add-opens=java.desktop/javax.swing.text.html=ALL-UNNAMED --add-opens=java.prefs/java.util.prefs=ALL-UNNAMED"/>
    2424        <jar href="josm-latest.jar"/>
    2525        <property name="java.util.Arrays.useLegacyMergeSort" value="true"/>
  • trunk/josm.jnlp

    r15380 r15469  
    2121    </security>
    2222    <resources>
    23         <java version="1.8+" max-heap-size="2048m" java-vm-args="--add-modules=java.scripting,java.sql --add-exports=java.base/sun.security.util=ALL-UNNAMED --add-exports=java.base/sun.security.x509=ALL-UNNAMED --add-exports=java.desktop/com.apple.eawt=ALL-UNNAMED --add-exports=java.desktop/com.sun.imageio.spi=ALL-UNNAMED --add-exports=java.desktop/com.sun.imageio.plugins.jpeg=ALL-UNNAMED --add-exports=javafx.graphics/com.sun.javafx.application=ALL-UNNAMED --add-exports=jdk.deploy/com.sun.deploy.config=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.nio=ALL-UNNAMED --add-opens=java.base/jdk.internal.loader=ALL-UNNAMED --add-opens=java.base/jdk.internal.ref=ALL-UNNAMED --add-opens=java.desktop/javax.imageio.spi=ALL-UNNAMED --add-opens=java.desktop/javax.swing.text.html=ALL-UNNAMED --add-opens=java.prefs/java.util.prefs=ALL-UNNAMED"/>
     23        <java version="1.8+" max-heap-size="2048m" java-vm-args="--add-modules=java.scripting,java.sql --add-exports=java.desktop/com.apple.eawt=ALL-UNNAMED --add-exports=java.desktop/com.sun.imageio.spi=ALL-UNNAMED --add-exports=java.desktop/com.sun.imageio.plugins.jpeg=ALL-UNNAMED --add-exports=javafx.graphics/com.sun.javafx.application=ALL-UNNAMED --add-exports=jdk.deploy/com.sun.deploy.config=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.nio=ALL-UNNAMED --add-opens=java.base/jdk.internal.loader=ALL-UNNAMED --add-opens=java.base/jdk.internal.ref=ALL-UNNAMED --add-opens=java.desktop/javax.imageio.spi=ALL-UNNAMED --add-opens=java.desktop/javax.swing.text.html=ALL-UNNAMED --add-opens=java.prefs/java.util.prefs=ALL-UNNAMED"/>
    2424        <jar href="josm-tested.jar"/>
    2525        <property name="java.util.Arrays.useLegacyMergeSort" value="true"/>
  • trunk/src/org/openstreetmap/josm/data/Preferences.java

    r14978 r15469  
    8383
    8484    private static final String[] OBSOLETE_PREF_KEYS = {
     85        "remotecontrol.https.enabled", /* remove entry after Dec. 2019 */
     86        "remotecontrol.https.port", /* remove entry after Dec. 2019 */
    8587    };
    8688
  • trunk/src/org/openstreetmap/josm/gui/MainApplication.java

    r15321 r15469  
    2727import java.security.CodeSource;
    2828import java.security.GeneralSecurityException;
    29 import java.security.KeyStoreException;
    30 import java.security.NoSuchAlgorithmException;
    3129import java.security.PermissionCollection;
    3230import java.security.Permissions;
    3331import java.security.Policy;
    34 import java.security.cert.CertificateException;
    3532import java.util.ArrayList;
    3633import java.util.Arrays;
     
    929926        SwingUtilities.invokeLater(new GuiFinalizationWorker(args, proxySelector));
    930927
    931         if (PlatformManager.isPlatformWindows()) {
    932             try {
    933                 // Check for insecure certificates to remove.
    934                 // This is Windows-dependant code but it can't go to preStartupHook (need i18n)
    935                 // neither startupHook (need to be called before remote control)
    936                 PlatformHookWindows.removeInsecureCertificates();
    937             } catch (NoSuchAlgorithmException | CertificateException | KeyStoreException | IOException e) {
    938                 Logging.error(e);
    939             }
    940         }
    941 
    942928        if (RemoteControl.PROP_REMOTECONTROL_ENABLED.get()) {
    943929            RemoteControl.start();
  • trunk/src/org/openstreetmap/josm/gui/preferences/remotecontrol/RemoteControlPreference.java

    r14138 r15469  
    88import java.awt.GridBagLayout;
    99import java.awt.event.ActionListener;
    10 import java.io.IOException;
    11 import java.security.GeneralSecurityException;
    12 import java.security.KeyStore;
    13 import java.security.KeyStoreException;
    14 import java.security.NoSuchAlgorithmException;
    15 import java.security.cert.CertificateException;
    1610import java.util.LinkedHashMap;
    1711import java.util.Map;
     
    2014import javax.swing.BorderFactory;
    2115import javax.swing.Box;
    22 import javax.swing.JButton;
    2316import javax.swing.JCheckBox;
    2417import javax.swing.JLabel;
    25 import javax.swing.JOptionPane;
    2618import javax.swing.JPanel;
    2719import javax.swing.JSeparator;
     
    3628import org.openstreetmap.josm.io.remotecontrol.PermissionPrefWithDefault;
    3729import org.openstreetmap.josm.io.remotecontrol.RemoteControl;
    38 import org.openstreetmap.josm.io.remotecontrol.RemoteControlHttpsServer;
    3930import org.openstreetmap.josm.io.remotecontrol.handler.RequestHandler;
    4031import org.openstreetmap.josm.spi.preferences.Config;
    4132import org.openstreetmap.josm.tools.GBC;
    42 import org.openstreetmap.josm.tools.Logging;
    43 import org.openstreetmap.josm.tools.PlatformHookWindows;
    44 import org.openstreetmap.josm.tools.PlatformManager;
    4533
    4634/**
     
    7361    private final Map<PermissionPrefWithDefault, JCheckBox> prefs = new LinkedHashMap<>();
    7462    private JCheckBox enableRemoteControl;
    75     private JCheckBox enableHttpsSupport;
    76 
    77     private JButton installCertificate;
    78     private JButton uninstallCertificate;
    7963
    8064    private final JCheckBox loadInNewLayer = new JCheckBox(tr("Download as new layer"));
     
    9377
    9478        final JLabel portLabel = new JLabel("<html>"
    95                 + tr("JOSM will always listen at <b>port {0}</b> (http) and <b>port {1}</b> (https) on localhost."
    96                 + "<br>These ports are not configurable because they are referenced by external applications talking to JOSM.",
    97                 Config.getPref().get("remote.control.port", "8111"),
    98                 Config.getPref().get("remote.control.https.port", "8112")) + "</html>");
     79                + tr("JOSM will always listen at <b>port {0}</b> (http) on localhost."
     80                + "<br>This port is not configurable because it is referenced by external applications talking to JOSM.",
     81                Config.getPref().get("remote.control.port", "8111")) + "</html>");
    9982        portLabel.setFont(portLabel.getFont().deriveFont(Font.PLAIN));
    10083        remote.add(portLabel, GBC.eol().insets(5, 5, 0, 10).fill(GBC.HORIZONTAL));
     
    10790
    10891        remote.add(wrapper, GBC.eol().fill(GBC.HORIZONTAL).insets(5, 5, 5, 5));
    109 
    110         boolean https = RemoteControl.PROP_REMOTECONTROL_HTTPS_ENABLED.get();
    111 
    112         enableHttpsSupport = new JCheckBox(tr("Enable HTTPS support"), https);
    113         wrapper.add(enableHttpsSupport, GBC.eol().fill(GBC.HORIZONTAL));
    114 
    115         // Certificate installation only available on Windows for now, see #10033
    116         if (PlatformManager.isPlatformWindows()) {
    117             installCertificate = new JButton(tr("Install..."));
    118             uninstallCertificate = new JButton(tr("Uninstall..."));
    119             installCertificate.setToolTipText(tr("Install JOSM localhost certificate to system/browser root keystores"));
    120             uninstallCertificate.setToolTipText(tr("Uninstall JOSM localhost certificate from system/browser root keystores"));
    121             wrapper.add(new JLabel(tr("Certificate:")), GBC.std().insets(15, 5, 0, 0));
    122             wrapper.add(installCertificate, GBC.std().insets(5, 5, 0, 0));
    123             wrapper.add(uninstallCertificate, GBC.eol().insets(5, 5, 0, 0));
    124             enableHttpsSupport.addActionListener(e -> installCertificate.setEnabled(enableHttpsSupport.isSelected()));
    125             installCertificate.addActionListener(e -> {
    126                 try {
    127                     boolean changed = RemoteControlHttpsServer.setupPlatform(
    128                             RemoteControlHttpsServer.loadJosmKeystore());
    129                     String msg = changed ?
    130                             tr("Certificate has been successfully installed.") :
    131                             tr("Certificate is already installed. Nothing to do.");
    132                     Logging.info(msg);
    133                     JOptionPane.showMessageDialog(wrapper, msg);
    134                 } catch (IOException | GeneralSecurityException ex) {
    135                     Logging.error(ex);
    136                 }
    137             });
    138             uninstallCertificate.addActionListener(e -> {
    139                 try {
    140                     String msg;
    141                     KeyStore ks = PlatformHookWindows.getRootKeystore();
    142                     if (ks.containsAlias(RemoteControlHttpsServer.ENTRY_ALIAS)) {
    143                         Logging.info(tr("Removing certificate {0} from root keystore.", RemoteControlHttpsServer.ENTRY_ALIAS));
    144                         ks.deleteEntry(RemoteControlHttpsServer.ENTRY_ALIAS);
    145                         msg = tr("Certificate has been successfully uninstalled.");
    146                     } else {
    147                         msg = tr("Certificate is not installed. Nothing to do.");
    148                     }
    149                     Logging.info(msg);
    150                     JOptionPane.showMessageDialog(wrapper, msg);
    151                 } catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException ex) {
    152                     Logging.error(ex);
    153                 }
    154             });
    155             installCertificate.setEnabled(https);
    156         }
    15792
    15893        wrapper.add(new JSeparator(), GBC.eop().fill(GBC.HORIZONTAL).insets(15, 5, 15, 5));
     
    174109                RequestHandler.globalConfirmationKey, RequestHandler.globalConfirmationDefault));
    175110
    176         ActionListener remoteControlEnabled = e -> {
    177             GuiHelper.setEnabledRec(wrapper, enableRemoteControl.isSelected());
    178             enableHttpsSupport.setEnabled(RemoteControl.supportsHttps());
    179             // 'setEnabled(false)' does not work for JLabel with html text, so do it manually
    180             // FIXME: use QuadStateCheckBox to make checkboxes unset when disabled
    181             if (installCertificate != null && uninstallCertificate != null) {
    182                 // Install certificate button is enabled if HTTPS is also enabled
    183                 installCertificate.setEnabled(enableRemoteControl.isSelected()
    184                         && enableHttpsSupport.isSelected() && RemoteControl.supportsHttps());
    185                 // Uninstall certificate button is always enabled
    186                 uninstallCertificate.setEnabled(RemoteControl.supportsHttps());
    187             }
    188         };
     111        ActionListener remoteControlEnabled = e -> GuiHelper.setEnabledRec(wrapper, enableRemoteControl.isSelected());
    189112        enableRemoteControl.addActionListener(remoteControlEnabled);
    190113        remoteControlEnabled.actionPerformed(null);
     
    195118    public boolean ok() {
    196119        boolean enabled = enableRemoteControl.isSelected();
    197         boolean httpsEnabled = enableHttpsSupport.isSelected();
    198120        boolean changed = RemoteControl.PROP_REMOTECONTROL_ENABLED.put(enabled);
    199         boolean httpsChanged = RemoteControl.PROP_REMOTECONTROL_HTTPS_ENABLED.put(httpsEnabled);
    200121        if (enabled) {
    201122            for (Entry<PermissionPrefWithDefault, JCheckBox> p : prefs.entrySet()) {
     
    211132                RemoteControl.stop();
    212133            }
    213         } else if (httpsChanged) {
    214             if (httpsEnabled) {
    215                 RemoteControlHttpsServer.restartRemoteControlHttpsServer();
    216             } else {
    217                 RemoteControlHttpsServer.stopRemoteControlHttpsServer();
    218             }
    219134        }
    220135        return false;
  • trunk/src/org/openstreetmap/josm/io/remotecontrol/RemoteControl.java

    r13929 r15469  
    1111import org.openstreetmap.josm.io.remotecontrol.handler.RequestHandler;
    1212import org.openstreetmap.josm.spi.preferences.Config;
    13 import org.openstreetmap.josm.tools.Logging;
    1413
    1514/**
     
    2827
    2928    /**
    30      * If the remote control feature is enabled or disabled for HTTPS. If disabled,
    31      * only HTTP access will be available.
    32      * @since 7335
    33      */
    34     public static final BooleanProperty PROP_REMOTECONTROL_HTTPS_ENABLED = new BooleanProperty(
    35             "remotecontrol.https.enabled", false);
    36 
    37     /**
    3829     * RemoteControl HTTP protocol version. Change minor number for compatible
    3930     * interface extensions. Change major number in case of incompatible
     
    4839    public static void start() {
    4940        RemoteControlHttpServer.restartRemoteControlHttpServer();
    50         if (supportsHttps()) {
    51             RemoteControlHttpsServer.restartRemoteControlHttpsServer();
    52         }
    5341    }
    5442
     
    5947    public static void stop() {
    6048        RemoteControlHttpServer.stopRemoteControlHttpServer();
    61         if (supportsHttps()) {
    62             RemoteControlHttpsServer.stopRemoteControlHttpsServer();
    63         }
    64     }
    65 
    66     /**
    67      * Determines if the current JVM support HTTPS remote control.
    68      * @return {@code true} if the JVM provides {@code sun.security.x509} classes
    69      * @since 12703
    70      */
    71     public static boolean supportsHttps() {
    72         try {
    73             return Class.forName("sun.security.x509.GeneralName") != null;
    74         } catch (ClassNotFoundException | SecurityException e) {
    75             Logging.trace(e);
    76             return false;
    77         }
    7849    }
    7950
  • trunk/src/org/openstreetmap/josm/tools/PlatformHook.java

    r15193 r15469  
    1010import java.io.InputStreamReader;
    1111import java.nio.charset.StandardCharsets;
    12 import java.security.KeyStore;
    1312import java.security.KeyStoreException;
    1413import java.security.NoSuchAlgorithmException;
     
    162161    default String getOSBuildNumber() {
    163162        return "";
    164     }
    165 
    166     /**
    167      * Setup system keystore to add JOSM HTTPS certificate (for remote control).
    168      * @param entryAlias The entry alias to use
    169      * @param trustedCert the JOSM certificate for localhost
    170      * @return {@code true} if something has changed as a result of the call (certificate installation, etc.)
    171      * @throws KeyStoreException in case of error
    172      * @throws IOException in case of error
    173      * @throws CertificateException in case of error
    174      * @throws NoSuchAlgorithmException in case of error
    175      * @since 7343
    176      */
    177     default boolean setupHttpsCertificate(String entryAlias, KeyStore.TrustedCertificateEntry trustedCert)
    178             throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
    179         // TODO setup HTTPS certificate on Unix and OS X systems
    180         return false;
    181163    }
    182164
  • trunk/src/org/openstreetmap/josm/tools/PlatformHookWindows.java

    r15006 r15469  
    3232
    3333import java.awt.Desktop;
    34 import java.awt.GraphicsEnvironment;
    3534import java.io.BufferedWriter;
    3635import java.io.File;
     
    5049import java.nio.file.InvalidPathException;
    5150import java.nio.file.Path;
    52 import java.security.InvalidKeyException;
    53 import java.security.KeyFactory;
    5451import java.security.KeyStore;
    5552import java.security.KeyStoreException;
    5653import java.security.MessageDigest;
    5754import java.security.NoSuchAlgorithmException;
    58 import java.security.NoSuchProviderException;
    59 import java.security.PublicKey;
    60 import java.security.SignatureException;
    6155import java.security.cert.Certificate;
    6256import java.security.cert.CertificateException;
    6357import java.security.cert.X509Certificate;
    64 import java.security.spec.InvalidKeySpecException;
    65 import java.security.spec.X509EncodedKeySpec;
    6658import java.text.ParseException;
    6759import java.util.ArrayList;
     
    7971import java.util.regex.Pattern;
    8072
    81 import javax.swing.JOptionPane;
    82 
    8373import org.openstreetmap.josm.data.Preferences;
    8474import org.openstreetmap.josm.data.StructUtils;
    8575import org.openstreetmap.josm.data.StructUtils.StructEntry;
    8676import org.openstreetmap.josm.data.StructUtils.WriteExplicitly;
    87 import org.openstreetmap.josm.gui.MainApplication;
    8877import org.openstreetmap.josm.io.CertificateAmendment.NativeCertAmend;
    8978import org.openstreetmap.josm.io.NetworkManager;
     
    147136        }
    148137    }
    149 
    150     private static final byte[] INSECURE_PUBLIC_KEY = new byte[] {
    151         0x30, (byte) 0x82, 0x1, 0x22, 0x30, 0xd, 0x6, 0x9, 0x2a, (byte) 0x86, 0x48,
    152         (byte) 0x86, (byte) 0xf7, 0xd, 0x1, 0x1, 0x1, 0x5, 0x0, 0x3, (byte) 0x82, 0x1, 0xf, 0x0,
    153         0x30, (byte) 0x82, 0x01, 0x0a, 0x02, (byte) 0x82, 0x01, 0x01, 0x00, (byte) 0x95, (byte) 0x95, (byte) 0x88,
    154         (byte) 0x84, (byte) 0xc8, (byte) 0xd9, 0x6b, (byte) 0xc5, (byte) 0xda, 0x0b, 0x69, (byte) 0xbf, (byte) 0xfc,
    155         0x7e, (byte) 0xb9, (byte) 0x96, 0x2c, (byte) 0xeb, (byte) 0x8f, (byte) 0xbc, 0x6e, 0x40, (byte) 0xe6, (byte) 0xe2,
    156         (byte) 0xfc, (byte) 0xf1, 0x7f, 0x73, (byte) 0xa7, (byte) 0x9d, (byte) 0xde, (byte) 0xc7, (byte) 0x88, 0x57, 0x51,
    157         (byte) 0x84, (byte) 0xed, (byte) 0x96, (byte) 0xfb, (byte) 0xe1, 0x38, (byte) 0xef, 0x08, 0x2b, (byte) 0xf3,
    158         (byte) 0xc7, (byte) 0xc3, 0x5d, (byte) 0xfe, (byte) 0xf9, 0x51, (byte) 0xe6, 0x29, (byte) 0xfc, (byte) 0xe5, 0x0d,
    159         (byte) 0xa1, 0x0d, (byte) 0xa8, (byte) 0xb4, (byte) 0xae, 0x26, 0x18, 0x19, 0x4d, 0x6c, 0x0c, 0x3b, 0x12, (byte) 0xba,
    160         (byte) 0xbc, 0x5f, 0x32, (byte) 0xb3, (byte) 0xbe, (byte) 0x9d, 0x17, 0x0d, 0x4d, 0x2f, 0x1a, 0x48, (byte) 0xb7,
    161         (byte) 0xac, (byte) 0xf7, 0x1a, 0x43, 0x01, (byte) 0x97, (byte) 0xf4, (byte) 0xf8, 0x4c, (byte) 0xbb, 0x6a, (byte) 0xbc,
    162         0x33, (byte) 0xe1, 0x73, 0x1e, (byte) 0x86, (byte) 0xfb, 0x2e, (byte) 0xb1, 0x63, 0x75, (byte) 0x85, (byte) 0xdc,
    163         (byte) 0x82, 0x6c, 0x28, (byte) 0xf1, (byte) 0xe3, (byte) 0x90, 0x63, (byte) 0x9d, 0x3d, 0x48, (byte) 0x8a, (byte) 0x8c,
    164         0x47, (byte) 0xe2, 0x10, 0x0b, (byte) 0xef, (byte) 0x91, (byte) 0x94, (byte) 0xb0, 0x6c, 0x4c, (byte) 0x80, 0x76, 0x03,
    165         (byte) 0xe1, (byte) 0xb6, (byte) 0x90, (byte) 0x87, (byte) 0xd9, (byte) 0xae, (byte) 0xf4, (byte) 0x8e, (byte) 0xe0,
    166         (byte) 0x9f, (byte) 0xe7, 0x3a, 0x2c, 0x2f, 0x21, (byte) 0xd4, 0x46, (byte) 0xba, (byte) 0x95, 0x70, (byte) 0xa9, 0x5b,
    167         0x20, 0x2a, (byte) 0xfa, 0x52, 0x3e, (byte) 0x9d, (byte) 0xd9, (byte) 0xef, 0x28, (byte) 0xc5, (byte) 0xd1, 0x60,
    168         (byte) 0x89, 0x68, 0x6e, 0x7f, (byte) 0xd7, (byte) 0x9e, (byte) 0x89, 0x4c, (byte) 0xeb, 0x4d, (byte) 0xd2, (byte) 0xc6,
    169         (byte) 0xf4, 0x2d, 0x02, 0x5d, (byte) 0xda, (byte) 0xde, 0x33, (byte) 0xfe, (byte) 0xc1, 0x7e, (byte) 0xde, 0x4f, 0x1f,
    170         (byte) 0x9b, 0x6e, 0x6f, 0x0f, 0x66, 0x71, 0x19, (byte) 0xe9, 0x43, 0x3c, (byte) 0x83, 0x0a, 0x0f, 0x28, 0x21, (byte) 0xc8,
    171         0x38, (byte) 0xd3, 0x4e, 0x48, (byte) 0xdf, (byte) 0xd4, (byte) 0x99, (byte) 0xb5, (byte) 0xc6, (byte) 0x8d, (byte) 0xd4,
    172         (byte) 0xc1, 0x69, 0x58, 0x79, (byte) 0x82, 0x32, (byte) 0x82, (byte) 0xd4, (byte) 0x86, (byte) 0xe2, 0x04, 0x08, 0x63,
    173         (byte) 0x87, (byte) 0xf0, 0x2a, (byte) 0xf6, (byte) 0xec, 0x3e, 0x51, 0x0f, (byte) 0xda, (byte) 0xb4, 0x67, 0x19, 0x5e,
    174         0x16, 0x02, (byte) 0x9f, (byte) 0xf1, 0x19, 0x0c, 0x3e, (byte) 0xb8, 0x04, 0x49, 0x07, 0x53, 0x02, 0x03, 0x01, 0x00, 0x01
    175     };
    176138
    177139    private static final String WINDOWS_ROOT = "Windows-ROOT";
     
    374336        ks.load(null, null);
    375337        return ks;
    376     }
    377 
    378     /**
    379      * Removes potential insecure certificates installed with previous versions of JOSM on Windows.
    380      * @throws NoSuchAlgorithmException on unsupported signature algorithms
    381      * @throws CertificateException if any of the certificates in the Windows keystore could not be loaded
    382      * @throws KeyStoreException if no Provider supports a KeyStoreSpi implementation for the type "Windows-ROOT"
    383      * @throws IOException if there is an I/O or format problem with the keystore data, if a password is required but not given
    384      * @since 7335
    385      */
    386     public static void removeInsecureCertificates() throws NoSuchAlgorithmException, CertificateException, KeyStoreException, IOException {
    387         // We offered before a public private key we need now to remove from Windows PCs as it might be a huge security risk (see #10230)
    388         PublicKey insecurePubKey = null;
    389         try {
    390             insecurePubKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(INSECURE_PUBLIC_KEY));
    391         } catch (InvalidKeySpecException | NoSuchAlgorithmException e) {
    392             Logging.error(e);
    393             return;
    394         }
    395         KeyStore ks = getRootKeystore();
    396         Enumeration<String> en = ks.aliases();
    397         Collection<String> insecureCertificates = new ArrayList<>();
    398         while (en.hasMoreElements()) {
    399             String alias = en.nextElement();
    400             // Look for certificates associated with a private key
    401             if (ks.isKeyEntry(alias)) {
    402                 try {
    403                     ks.getCertificate(alias).verify(insecurePubKey);
    404                     // If no exception, this is a certificate signed with the insecure key -> remove it
    405                     insecureCertificates.add(alias);
    406                 } catch (InvalidKeyException | NoSuchProviderException | SignatureException e) {
    407                     // If exception this is not a certificate related to JOSM, just trace it
    408                     Logging.trace(alias + " --> " + e.getClass().getName());
    409                     Logging.trace(e);
    410                 }
    411             }
    412         }
    413         // Remove insecure certificates
    414         if (!insecureCertificates.isEmpty()) {
    415             StringBuilder message = new StringBuilder("<html>");
    416             message.append(tr("A previous version of JOSM has installed a custom certificate "+
    417                     "in order to provide HTTPS support for Remote Control:"))
    418                    .append("<br><ul>");
    419             for (String alias : insecureCertificates) {
    420                 message.append("<li>")
    421                        .append(alias)
    422                        .append("</li>");
    423             }
    424             message.append("</ul>")
    425                    .append(tr("It appears it could be an important <b>security risk</b>.<br><br>"+
    426                     "You are now going to be prompted by Windows to remove this insecure certificate.<br>"+
    427                     "For your own safety, <b>please click Yes</b> in next dialog."))
    428                    .append("</html>");
    429             JOptionPane.showMessageDialog(MainApplication.getMainFrame(), message.toString(), tr("Warning"), JOptionPane.WARNING_MESSAGE);
    430             for (String alias : insecureCertificates) {
    431                 Logging.warn(tr("Removing insecure certificate from {0} keystore: {1}", WINDOWS_ROOT, alias));
    432                 try {
    433                     ks.deleteEntry(alias);
    434                 } catch (KeyStoreException e) {
    435                     Logging.log(Logging.LEVEL_ERROR, tr("Unable to remove insecure certificate from keystore: {0}", e.getMessage()), e);
    436                 }
    437             }
    438         }
    439     }
    440 
    441     @Override
    442     public boolean setupHttpsCertificate(String entryAlias, KeyStore.TrustedCertificateEntry trustedCert)
    443             throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
    444         KeyStore ks = getRootKeystore();
    445         // Look for certificate to install
    446         try {
    447             String alias = ks.getCertificateAlias(trustedCert.getTrustedCertificate());
    448             if (alias != null) {
    449                 // JOSM certificate found, return
    450                 Logging.debug(tr("JOSM localhost certificate found in {0} keystore: {1}", WINDOWS_ROOT, alias));
    451                 return false;
    452             }
    453         } catch (ArrayIndexOutOfBoundsException e) {
    454             // catch error of JDK-8172244 as bug seems to not be fixed anytime soon
    455             Logging.log(Logging.LEVEL_ERROR, "JDK-8172244 occurred. Abort HTTPS setup", e);
    456             return false;
    457         }
    458         if (!GraphicsEnvironment.isHeadless()) {
    459             // JOSM certificate not found, warn user
    460             StringBuilder message = new StringBuilder("<html>");
    461             message.append(tr("Remote Control is configured to provide HTTPS support.<br>"+
    462                     "This requires to add a custom certificate generated by JOSM to the Windows Root CA store.<br><br>"+
    463                     "You are now going to be prompted by Windows to confirm this operation.<br>"+
    464                     "To enable proper HTTPS support, <b>please click Yes</b> in next dialog.<br><br>"+
    465                     "If unsure, you can also click No then disable HTTPS support in Remote Control preferences."))
    466                    .append("</html>");
    467             JOptionPane.showMessageDialog(MainApplication.getMainFrame(), message.toString(),
    468                     tr("HTTPS support in Remote Control"), JOptionPane.INFORMATION_MESSAGE);
    469         }
    470         // install it to Windows-ROOT keystore, used by IE, Chrome and Safari, but not by Firefox
    471         Logging.info(tr("Adding JOSM localhost certificate to {0} keystore", WINDOWS_ROOT));
    472         ks.setEntry(entryAlias, trustedCert, null);
    473         return true;
    474338    }
    475339
  • trunk/test/unit/org/openstreetmap/josm/io/remotecontrol/RemoteControlTest.java

    r14217 r15469  
    1111import java.net.URL;
    1212import java.nio.charset.StandardCharsets;
    13 import java.nio.file.Files;
    14 import java.nio.file.Paths;
    1513import java.security.GeneralSecurityException;
    1614import java.security.KeyStore.TrustedCertificateEntry;
    17 import java.security.SecureRandom;
    18 import java.security.cert.X509Certificate;
    19 
    20 import javax.net.ssl.HostnameVerifier;
    21 import javax.net.ssl.HttpsURLConnection;
    22 import javax.net.ssl.SSLContext;
    23 import javax.net.ssl.TrustManager;
    24 import javax.net.ssl.X509TrustManager;
    2515
    2616import org.junit.After;
     
    3121import org.openstreetmap.josm.spi.preferences.Config;
    3222import org.openstreetmap.josm.testutils.JOSMTestRules;
    33 import org.openstreetmap.josm.tools.Logging;
    3423import org.openstreetmap.josm.tools.PlatformHookWindows;
    3524import org.openstreetmap.josm.tools.PlatformManager;
     
    4534
    4635    private String httpBase;
    47     private String httpsBase;
    4836
    4937    private static class PlatformHookWindowsMock extends MockUp<PlatformHookWindows> {
     
    6755    @Before
    6856    public void setUp() throws GeneralSecurityException {
    69         RemoteControl.PROP_REMOTECONTROL_HTTPS_ENABLED.put(true);
    70         deleteKeystore();
    71 
    7257        if (PlatformManager.isPlatformWindows() && "True".equals(System.getenv("APPVEYOR"))) {
    7358            // appveyor doesn't like us tinkering with the root keystore, so mock this out
     
    7762
    7863        RemoteControl.start();
    79         disableCertificateValidation();
    8064        httpBase = "http://127.0.0.1:"+Config.getPref().getInt("remote.control.port", 8111);
    81         httpsBase = "https://127.0.0.1:"+Config.getPref().getInt("remote.control.https.port", 8112);
    82     }
    83 
    84     /**
    85      * Deletes JOSM keystore, if it exists.
    86      */
    87     public static void deleteKeystore() {
    88         try {
    89             Files.deleteIfExists(Paths.get(
    90                     RemoteControl.getRemoteControlDir()).resolve(RemoteControlHttpsServer.KEYSTORE_FILENAME));
    91         } catch (IOException e) {
    92             Logging.error(e);
    93         }
    94     }
    95 
    96     /**
    97      * Disable all HTTPS validation mechanisms as described
    98      * <a href="http://stackoverflow.com/a/2893932/2257172">here</a> and
    99      * <a href="http://stackoverflow.com/a/19542614/2257172">here</a>
    100      * @throws GeneralSecurityException if a security error occurs
    101      */
    102     public void disableCertificateValidation() throws GeneralSecurityException {
    103         // Create a trust manager that does not validate certificate chains
    104         TrustManager[] trustAllCerts = new TrustManager[] {
    105             new X509TrustManager() {
    106                 @Override
    107                 @SuppressFBWarnings(value = "WEAK_TRUST_MANAGER")
    108                 public X509Certificate[] getAcceptedIssuers() {
    109                     return new X509Certificate[0];
    110                 }
    111 
    112                 @Override
    113                 @SuppressFBWarnings(value = "WEAK_TRUST_MANAGER")
    114                 public void checkClientTrusted(X509Certificate[] certs, String authType) {
    115                 }
    116 
    117                 @Override
    118                 @SuppressFBWarnings(value = "WEAK_TRUST_MANAGER")
    119                 public void checkServerTrusted(X509Certificate[] certs, String authType) {
    120                 }
    121             }
    122         };
    123 
    124         // Install the all-trusting trust manager
    125         SSLContext sc = SSLContext.getInstance("TLS");
    126         sc.init(null, trustAllCerts, new SecureRandom());
    127         HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
    128 
    129         // Create all-trusting host name verifier
    130         HostnameVerifier allHostsValid = (hostname, session) -> true;
    131 
    132         // Install the all-trusting host verifier
    133         HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
    13465    }
    13566
     
    14980    public void testHttpListOfCommands() throws Exception {
    15081        testListOfCommands(httpBase);
    151     }
    152 
    153     /**
    154      * Tests that sending an HTTPS request without command results in HTTP 400, with all available commands in error message.
    155      * @throws Exception if an error occurs
    156      */
    157     @Test
    158     public void testHttpsListOfCommands() throws Exception {
    159         testListOfCommands(httpsBase);
    16082    }
    16183
  • trunk/test/unit/org/openstreetmap/josm/tools/PlatformHookOsxTest.java

    r14190 r15469  
    3838    public void testStartupHook() {
    3939        hook.startupHook((a, b, c, d) -> System.out.println("callback"));
    40     }
    41 
    42     /**
    43      * Test method for {@code PlatformHookOsx#setupHttpsCertificate}
    44      * @throws Exception if an error occurs
    45      */
    46     @Test
    47     public void testSetupHttpsCertificate() throws Exception {
    48         assertFalse(hook.setupHttpsCertificate(null, null));
    4940    }
    5041
  • trunk/test/unit/org/openstreetmap/josm/tools/PlatformHookWindowsTest.java

    r14412 r15469  
    77import static org.junit.Assert.assertNull;
    88import static org.junit.Assert.assertTrue;
    9 import static org.junit.Assume.assumeFalse;
    109import static org.junit.Assert.fail;
    1110
     
    1312import java.io.File;
    1413import java.io.IOException;
    15 import java.security.KeyStore;
    16 import java.security.KeyStore.TrustedCertificateEntry;
    1714import java.security.KeyStoreException;
    1815import java.util.Collection;
     
    2219import org.openstreetmap.josm.JOSMFixture;
    2320import org.openstreetmap.josm.TestUtils;
    24 import org.openstreetmap.josm.io.remotecontrol.RemoteControlHttpsServer;
    25 import org.openstreetmap.josm.io.remotecontrol.RemoteControlTest;
    2621import org.openstreetmap.josm.spi.preferences.Config;
    2722
     
    6459            try {
    6560                PlatformHookWindows.getRootKeystore();
    66                 fail("Expected KeyStoreException");
    67             } catch (KeyStoreException e) {
    68                 Logging.info(e.getMessage());
    69             }
    70         }
    71     }
    72 
    73     /**
    74      * Test method for {@code PlatformHookWindows#removeInsecureCertificates}
    75      * @throws Exception if an error occurs
    76      */
    77     @Test
    78     public void testRemoveInsecureCertificates() throws Exception {
    79         if (PlatformManager.isPlatformWindows()) {
    80             PlatformHookWindows.removeInsecureCertificates();
    81         } else {
    82             try {
    83                 PlatformHookWindows.removeInsecureCertificates();
    84                 fail("Expected KeyStoreException");
    85             } catch (KeyStoreException e) {
    86                 Logging.info(e.getMessage());
    87             }
    88         }
    89     }
    90 
    91     /**
    92      * Test method for {@code PlatformHookWindows#setupHttpsCertificate}
    93      * @throws Exception if an error occurs
    94      */
    95     @Test
    96     public void testSetupHttpsCertificate() throws Exception {
    97         // appveyor doesn't like us tinkering with the root keystore
    98         assumeFalse(PlatformManager.isPlatformWindows() && "True".equals(System.getenv("APPVEYOR")));
    99 
    100         RemoteControlTest.deleteKeystore();
    101         KeyStore ks = RemoteControlHttpsServer.loadJosmKeystore();
    102         TrustedCertificateEntry trustedCert = new KeyStore.TrustedCertificateEntry(ks.getCertificate(ks.aliases().nextElement()));
    103         if (PlatformManager.isPlatformWindows()) {
    104             hook.setupHttpsCertificate(RemoteControlHttpsServer.ENTRY_ALIAS, trustedCert);
    105         } else {
    106             try {
    107                 hook.setupHttpsCertificate(RemoteControlHttpsServer.ENTRY_ALIAS, trustedCert);
    10861                fail("Expected KeyStoreException");
    10962            } catch (KeyStoreException e) {
Note: See TracChangeset for help on using the changeset viewer.