- Timestamp:
- 2019-10-22T23:32:51+02:00 (6 years ago)
- Location:
- trunk/src/org/openstreetmap/josm
- Files:
-
- 1 deleted
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/data/Preferences.java
r14978 r15469 83 83 84 84 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 */ 85 87 }; 86 88 -
trunk/src/org/openstreetmap/josm/gui/MainApplication.java
r15321 r15469 27 27 import java.security.CodeSource; 28 28 import java.security.GeneralSecurityException; 29 import java.security.KeyStoreException;30 import java.security.NoSuchAlgorithmException;31 29 import java.security.PermissionCollection; 32 30 import java.security.Permissions; 33 31 import java.security.Policy; 34 import java.security.cert.CertificateException;35 32 import java.util.ArrayList; 36 33 import java.util.Arrays; … … 929 926 SwingUtilities.invokeLater(new GuiFinalizationWorker(args, proxySelector)); 930 927 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 942 928 if (RemoteControl.PROP_REMOTECONTROL_ENABLED.get()) { 943 929 RemoteControl.start(); -
trunk/src/org/openstreetmap/josm/gui/preferences/remotecontrol/RemoteControlPreference.java
r14138 r15469 8 8 import java.awt.GridBagLayout; 9 9 import 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;16 10 import java.util.LinkedHashMap; 17 11 import java.util.Map; … … 20 14 import javax.swing.BorderFactory; 21 15 import javax.swing.Box; 22 import javax.swing.JButton;23 16 import javax.swing.JCheckBox; 24 17 import javax.swing.JLabel; 25 import javax.swing.JOptionPane;26 18 import javax.swing.JPanel; 27 19 import javax.swing.JSeparator; … … 36 28 import org.openstreetmap.josm.io.remotecontrol.PermissionPrefWithDefault; 37 29 import org.openstreetmap.josm.io.remotecontrol.RemoteControl; 38 import org.openstreetmap.josm.io.remotecontrol.RemoteControlHttpsServer;39 30 import org.openstreetmap.josm.io.remotecontrol.handler.RequestHandler; 40 31 import org.openstreetmap.josm.spi.preferences.Config; 41 32 import 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;45 33 46 34 /** … … 73 61 private final Map<PermissionPrefWithDefault, JCheckBox> prefs = new LinkedHashMap<>(); 74 62 private JCheckBox enableRemoteControl; 75 private JCheckBox enableHttpsSupport;76 77 private JButton installCertificate;78 private JButton uninstallCertificate;79 63 80 64 private final JCheckBox loadInNewLayer = new JCheckBox(tr("Download as new layer")); … … 93 77 94 78 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>"); 99 82 portLabel.setFont(portLabel.getFont().deriveFont(Font.PLAIN)); 100 83 remote.add(portLabel, GBC.eol().insets(5, 5, 0, 10).fill(GBC.HORIZONTAL)); … … 107 90 108 91 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 #10033116 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 }157 92 158 93 wrapper.add(new JSeparator(), GBC.eop().fill(GBC.HORIZONTAL).insets(15, 5, 15, 5)); … … 174 109 RequestHandler.globalConfirmationKey, RequestHandler.globalConfirmationDefault)); 175 110 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()); 189 112 enableRemoteControl.addActionListener(remoteControlEnabled); 190 113 remoteControlEnabled.actionPerformed(null); … … 195 118 public boolean ok() { 196 119 boolean enabled = enableRemoteControl.isSelected(); 197 boolean httpsEnabled = enableHttpsSupport.isSelected();198 120 boolean changed = RemoteControl.PROP_REMOTECONTROL_ENABLED.put(enabled); 199 boolean httpsChanged = RemoteControl.PROP_REMOTECONTROL_HTTPS_ENABLED.put(httpsEnabled);200 121 if (enabled) { 201 122 for (Entry<PermissionPrefWithDefault, JCheckBox> p : prefs.entrySet()) { … … 211 132 RemoteControl.stop(); 212 133 } 213 } else if (httpsChanged) {214 if (httpsEnabled) {215 RemoteControlHttpsServer.restartRemoteControlHttpsServer();216 } else {217 RemoteControlHttpsServer.stopRemoteControlHttpsServer();218 }219 134 } 220 135 return false; -
trunk/src/org/openstreetmap/josm/io/remotecontrol/RemoteControl.java
r13929 r15469 11 11 import org.openstreetmap.josm.io.remotecontrol.handler.RequestHandler; 12 12 import org.openstreetmap.josm.spi.preferences.Config; 13 import org.openstreetmap.josm.tools.Logging;14 13 15 14 /** … … 28 27 29 28 /** 30 * If the remote control feature is enabled or disabled for HTTPS. If disabled,31 * only HTTP access will be available.32 * @since 733533 */34 public static final BooleanProperty PROP_REMOTECONTROL_HTTPS_ENABLED = new BooleanProperty(35 "remotecontrol.https.enabled", false);36 37 /**38 29 * RemoteControl HTTP protocol version. Change minor number for compatible 39 30 * interface extensions. Change major number in case of incompatible … … 48 39 public static void start() { 49 40 RemoteControlHttpServer.restartRemoteControlHttpServer(); 50 if (supportsHttps()) {51 RemoteControlHttpsServer.restartRemoteControlHttpsServer();52 }53 41 } 54 42 … … 59 47 public static void stop() { 60 48 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} classes69 * @since 1270370 */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 }78 49 } 79 50 -
trunk/src/org/openstreetmap/josm/tools/PlatformHook.java
r15193 r15469 10 10 import java.io.InputStreamReader; 11 11 import java.nio.charset.StandardCharsets; 12 import java.security.KeyStore;13 12 import java.security.KeyStoreException; 14 13 import java.security.NoSuchAlgorithmException; … … 162 161 default String getOSBuildNumber() { 163 162 return ""; 164 }165 166 /**167 * Setup system keystore to add JOSM HTTPS certificate (for remote control).168 * @param entryAlias The entry alias to use169 * @param trustedCert the JOSM certificate for localhost170 * @return {@code true} if something has changed as a result of the call (certificate installation, etc.)171 * @throws KeyStoreException in case of error172 * @throws IOException in case of error173 * @throws CertificateException in case of error174 * @throws NoSuchAlgorithmException in case of error175 * @since 7343176 */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 systems180 return false;181 163 } 182 164 -
trunk/src/org/openstreetmap/josm/tools/PlatformHookWindows.java
r15006 r15469 32 32 33 33 import java.awt.Desktop; 34 import java.awt.GraphicsEnvironment;35 34 import java.io.BufferedWriter; 36 35 import java.io.File; … … 50 49 import java.nio.file.InvalidPathException; 51 50 import java.nio.file.Path; 52 import java.security.InvalidKeyException;53 import java.security.KeyFactory;54 51 import java.security.KeyStore; 55 52 import java.security.KeyStoreException; 56 53 import java.security.MessageDigest; 57 54 import java.security.NoSuchAlgorithmException; 58 import java.security.NoSuchProviderException;59 import java.security.PublicKey;60 import java.security.SignatureException;61 55 import java.security.cert.Certificate; 62 56 import java.security.cert.CertificateException; 63 57 import java.security.cert.X509Certificate; 64 import java.security.spec.InvalidKeySpecException;65 import java.security.spec.X509EncodedKeySpec;66 58 import java.text.ParseException; 67 59 import java.util.ArrayList; … … 79 71 import java.util.regex.Pattern; 80 72 81 import javax.swing.JOptionPane;82 83 73 import org.openstreetmap.josm.data.Preferences; 84 74 import org.openstreetmap.josm.data.StructUtils; 85 75 import org.openstreetmap.josm.data.StructUtils.StructEntry; 86 76 import org.openstreetmap.josm.data.StructUtils.WriteExplicitly; 87 import org.openstreetmap.josm.gui.MainApplication;88 77 import org.openstreetmap.josm.io.CertificateAmendment.NativeCertAmend; 89 78 import org.openstreetmap.josm.io.NetworkManager; … … 147 136 } 148 137 } 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, 0x01175 };176 138 177 139 private static final String WINDOWS_ROOT = "Windows-ROOT"; … … 374 336 ks.load(null, null); 375 337 return ks; 376 }377 378 /**379 * Removes potential insecure certificates installed with previous versions of JOSM on Windows.380 * @throws NoSuchAlgorithmException on unsupported signature algorithms381 * @throws CertificateException if any of the certificates in the Windows keystore could not be loaded382 * @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 given384 * @since 7335385 */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 key401 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 it405 insecureCertificates.add(alias);406 } catch (InvalidKeyException | NoSuchProviderException | SignatureException e) {407 // If exception this is not a certificate related to JOSM, just trace it408 Logging.trace(alias + " --> " + e.getClass().getName());409 Logging.trace(e);410 }411 }412 }413 // Remove insecure certificates414 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 @Override442 public boolean setupHttpsCertificate(String entryAlias, KeyStore.TrustedCertificateEntry trustedCert)443 throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {444 KeyStore ks = getRootKeystore();445 // Look for certificate to install446 try {447 String alias = ks.getCertificateAlias(trustedCert.getTrustedCertificate());448 if (alias != null) {449 // JOSM certificate found, return450 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 soon455 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 user460 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 Firefox471 Logging.info(tr("Adding JOSM localhost certificate to {0} keystore", WINDOWS_ROOT));472 ks.setEntry(entryAlias, trustedCert, null);473 return true;474 338 } 475 339
Note:
See TracChangeset
for help on using the changeset viewer.