From 419898b96abeb2f9cdc77b22b34d71fff5451fd9 Mon Sep 17 00:00:00 2001 From: Ben Soares Date: Sun, 26 Jul 2020 00:41:42 +0100 Subject: [PATCH] JAL-3633 Memory only proxy auth password storage. Open Preferences->Connection tab when proxy password needed --- resources/lang/Messages.properties | 2 + src/jalview/bin/Cache.java | 136 ++++++++++++-------- src/jalview/gui/Preferences.java | 51 +++++--- src/jalview/jbgui/GPreferences.java | 232 +++++++++++++++++++++-------------- 4 files changed, 263 insertions(+), 158 deletions(-) diff --git a/resources/lang/Messages.properties b/resources/lang/Messages.properties index 44bff1d..d8217d2 100644 --- a/resources/lang/Messages.properties +++ b/resources/lang/Messages.properties @@ -590,6 +590,8 @@ label.use_proxy_server = Use these proxy servers label.auth_required = Authentication required label.username = Username label.password = Password +label.proxy_password_required = Proxy password required +label.not_stored = not stored in Preferences file label.rendering_style = {0} rendering style label.append_start_end = Append /start-end (/15-380) label.full_sequence_id = Full Sequence Id diff --git a/src/jalview/bin/Cache.java b/src/jalview/bin/Cache.java index 6648099..8051336 100755 --- a/src/jalview/bin/Cache.java +++ b/src/jalview/bin/Cache.java @@ -52,13 +52,16 @@ import org.apache.log4j.Logger; import org.apache.log4j.SimpleLayout; import jalview.datamodel.PDBEntry; +import jalview.gui.Preferences; import jalview.gui.UserDefinedColours; +import jalview.jbgui.GPreferences; import jalview.schemes.ColourSchemeLoader; import jalview.schemes.ColourSchemes; import jalview.schemes.UserColourScheme; import jalview.structure.StructureImportSettings; import jalview.urls.IdOrgSettings; import jalview.util.ColorUtils; +import jalview.util.MessageManager; import jalview.util.Platform; import jalview.ws.sifts.SiftsSettings; @@ -292,6 +295,9 @@ public class Cache public final static String PROXYTYPE_CUSTOM = "true"; + // in-memory only storage of proxy password, safer to use char array + public static char[] proxyAuthPassword = null; + /** Jalview Properties */ public static Properties applicationProperties = new Properties() { @@ -431,7 +437,7 @@ public class Cache switch (proxyType) { case PROXYTYPE_NONE: - setProxyProperties(null, null, null, null, null, null, null, null); + clearProxyProperties(); break; case PROXYTYPE_SYSTEM: // use system settings resetProxyProperties(); @@ -442,14 +448,11 @@ public class Cache String httpsHost = getDefault("PROXY_SERVER_HTTPS", httpHost); String httpsPort = getDefault("PROXY_PORT_HTTPS", httpPort); String httpUser = getDefault("PROXY_AUTH_USER", null); - String httpPassword = getDefault("PROXY_AUTH_PASSWORD", null); // https.proxyUser and https.proxyPassword are not able to be - // independently set in Preferences yet + // independently set in Preferences yet (or http.nonProxyHosts) String httpsUser = getDefault("PROXY_AUTH_USER_HTTPS", httpUser); - String httpsPassword = getDefault("PROXY_AUTH_PASSWORD_HTTPS", - httpPassword); setProxyProperties(httpHost, httpPort, httpsHost, httpsPort, httpUser, - httpPassword, httpsUser, httpsPassword); + proxyAuthPassword, httpsUser, proxyAuthPassword, "localhost"); break; default: String message = "Incorrect PROXY_TYPE - should be 'none' (clear proxy properties), 'false' (system settings), 'true' (custom settings): " @@ -1268,12 +1271,23 @@ public class Cache } // proxy properties methods + public static void clearProxyProperties() + { + setProxyProperties(null, null, null, null, null, null, null, null, + null); + } + public static void resetProxyProperties() { setProxyProperties(startupProxyProperties[0], startupProxyProperties[1], startupProxyProperties[2], startupProxyProperties[3], - startupProxyProperties[4], startupProxyProperties[5], - startupProxyProperties[6], startupProxyProperties[7]); + startupProxyProperties[4], + startupProxyProperties[5] == null ? null + : startupProxyProperties[5].toCharArray(), + startupProxyProperties[6], + startupProxyProperties[7] == null ? null + : startupProxyProperties[7].toCharArray(), + startupProxyProperties[8]); StringBuilder sb = new StringBuilder(); sb.append("Setting proxy properties to: http.proxyHost=") .append(startupProxyProperties[0]).append(", http.proxyPort=") @@ -1294,15 +1308,8 @@ public class Cache public static void setProxyProperties(String httpHost, String httpPort, String httpsHost, String httpsPort, String httpUser, - String httpPassword) - { - setProxyProperties(httpHost, httpPort, httpsHost, httpsPort, httpUser, - httpPassword, httpUser, httpPassword); - } - - public static void setProxyProperties(String httpHost, String httpPort, - String httpsHost, String httpsPort, String httpUser, - String httpPassword, String httpsUser, String httpsPassword) + char[] httpPassword, String httpsUser, char[] httpsPassword, + String nonProxyHosts) { setOrClearSystemProperty("http.proxyHost", httpHost); setOrClearSystemProperty("http.proxyPort", httpPort); @@ -1312,6 +1319,9 @@ public class Cache setOrClearSystemProperty("http.proxyPassword", httpPassword); setOrClearSystemProperty("https.proxyUser", httpsUser); setOrClearSystemProperty("https.proxyPassword", httpsPassword); + // are we using a custom proxy (password prompt might be required)? + boolean customProxySet = getDefault("USE_PROXY", PROXYTYPE_SYSTEM) + .equals(PROXYTYPE_CUSTOM); if (httpUser != null || httpsUser != null) { try @@ -1323,29 +1333,51 @@ public class Cache { if (getRequestorType() == RequestorType.PROXY) { - try + String scheme = getRequestingScheme(); + boolean needProxyPasswordSet = false; + if (customProxySet && + // we have a username but no password for the scheme being + // requested + (scheme.equalsIgnoreCase("http") + && (httpUser != null && httpUser.length() > 0 + && (httpPassword == null + || httpPassword.length == 0))) + || (scheme.equalsIgnoreCase("https") + && (httpsUser != null + && httpsUser.length() > 0 + && (httpsPassword == null + || httpsPassword.length == 0)))) { - if (getRequestingScheme().equalsIgnoreCase("http") - && getRequestingHost().equalsIgnoreCase(httpHost) - && getRequestingPort() == Integer.valueOf(httpPort)) + // open Preferences -> Connections + String message = MessageManager + .getString("label.proxy_password_required"); + openPreferencesConnectionsForProxyPassword(message); + } + else + { + try { - return new PasswordAuthentication(httpUser, - httpPassword == null ? new char[] {} - : httpPassword.toCharArray()); - } - if (getRequestingScheme().equalsIgnoreCase("https") - && getRequestingHost().equalsIgnoreCase(httpsHost) - && getRequestingPort() == Integer - .valueOf(httpsPort)) + if (scheme.equalsIgnoreCase("http") + && getRequestingHost().equalsIgnoreCase(httpHost) + && getRequestingPort() == Integer + .valueOf(httpPort)) + { + return new PasswordAuthentication(httpUser, + httpPassword); + } + if (scheme.equalsIgnoreCase("https") + && getRequestingHost().equalsIgnoreCase(httpsHost) + && getRequestingPort() == Integer + .valueOf(httpsPort)) + { + return new PasswordAuthentication(httpsUser, + httpsPassword); + } + } catch (NumberFormatException e) { - return new PasswordAuthentication(httpsUser, - httpsPassword == null ? new char[] {} - : httpsPassword.toCharArray()); + Cache.error("Problem with proxy port values [http:" + + httpPort + ", https:" + httpsPort + "]"); } - } catch (NumberFormatException e) - { - Cache.error("Problem with proxy port values [http:" - + httpPort + ", https:" + httpsPort + "]"); } } // non proxy request @@ -1365,21 +1397,27 @@ public class Cache { // reset the Authenticator to protect http.proxyUser and // http.proxyPassword Just In Case - Authenticator.setDefault(new Authenticator() - { - @Override - protected PasswordAuthentication getPasswordAuthentication() - { - return null; - } - }); + Authenticator.setDefault(null); } - // clear localhost from proxying unless nonProxyHosts already set (not - // currently configurable in Preferences) - String nonProxyHosts = startupProxyProperties[8]; - System.setProperty("http.nonProxyHosts", - nonProxyHosts == null ? "localhost" : nonProxyHosts); + // nonProxyHosts not currently configurable in Preferences + setOrClearSystemProperty("http.nonProxyHosts", nonProxyHosts); + } + + private static void openPreferencesConnectionsForProxyPassword( + String message) + { + // + Cache.info("Opening Preferences for proxy password"); + // Desktop.instance.preferences_actionPerformed(null); + Preferences p = new Preferences(GPreferences.CONNECTIONS_TAB); + p.grabFocus(); + } + + public static void setOrClearSystemProperty(String key, char[] value) + { + setOrClearSystemProperty(key, + (value == null) ? null : value.toString()); } public static void setOrClearSystemProperty(String key, String value) diff --git a/src/jalview/gui/Preferences.java b/src/jalview/gui/Preferences.java index 827c9a0..3cada85 100755 --- a/src/jalview/gui/Preferences.java +++ b/src/jalview/gui/Preferences.java @@ -193,7 +193,12 @@ public class Preferences extends GPreferences */ public Preferences() { - super(); + new Preferences(0); + } + + public Preferences(int selectTab) + { + super(selectTab); frame = new JInternalFrame(); frame.setContentPane(this); if (!Platform.isJS()) @@ -563,8 +568,9 @@ public class Preferences extends GPreferences proxyAuth.setSelected(Cache.getDefault("PROXY_AUTH", false)); proxyAuthUsernameTB .setText(Cache.getDefault("PROXY_AUTH_USERNAME", "")); - proxyAuthPasswordTB - .setText(Cache.getDefault("PROXY_AUTH_PASSWORD", "")); + // we are not storing or retrieving proxy password from .jalview_properties + proxyAuthPasswordTB.setText(Cache.proxyAuthPassword == null ? "" + : Cache.proxyAuthPassword.toString()); setCustomProxyEnabled(); defaultBrowser.setText(Cache.getDefault("DEFAULT_BROWSER", "")); @@ -838,19 +844,7 @@ public class Preferences extends GPreferences sequenceUrlLinks.getPrimaryUrlId()); // Proxy settings - Cache.applicationProperties.setProperty("USE_PROXY", - customProxy.isSelected() ? Cache.PROXYTYPE_CUSTOM - : noProxy.isSelected() ? Cache.PROXYTYPE_NONE - : Cache.PROXYTYPE_SYSTEM); - Cache.setOrRemove("PROXY_SERVER", proxyServerHttpTB.getText()); - Cache.setOrRemove("PROXY_PORT", proxyPortHttpTB.getText()); - Cache.setOrRemove("PROXY_SERVER_HTTPS", proxyServerHttpsTB.getText()); - Cache.setOrRemove("PROXY_PORT_HTTPS", proxyPortHttpsTB.getText()); - Cache.setOrRemove("PROXY_AUTH", - Boolean.toString(proxyAuth.isSelected())); - Cache.setOrRemove("PROXY_AUTH_USERNAME", proxyAuthUsernameTB.getText()); - Cache.setOrRemove("PROXY_AUTH_PASSWORD", proxyAuthPasswordTB.getText()); - setProxyFromSettings(); + saveProxySettings(); Cache.setProperty("VERSION_CHECK", Boolean.toString(versioncheck.isSelected())); @@ -957,7 +951,7 @@ public class Preferences extends GPreferences if (!previousProxyType.equals(proxyType)) Cache.log.info("Setting no proxy settings"); Cache.setProxyProperties(null, null, null, null, null, null, null, - null); + null, null); } else if (proxyType.equals(Cache.PROXYTYPE_CUSTOM)) { @@ -970,8 +964,10 @@ public class Preferences extends GPreferences Cache.getDefault("PROXY_PORT_HTTPS", null), proxyAuthSet ? Cache.getDefault("PROXY_AUTH_USERNAME", "") : null, - proxyAuthSet ? Cache.getDefault("PROXY_AUTH_PASSWORD", "") - : null); + proxyAuthSet ? Cache.proxyAuthPassword : null, + proxyAuthSet ? Cache.getDefault("PROXY_AUTH_USERNAME", "") + : null, + proxyAuthSet ? Cache.proxyAuthPassword : null, "localhost"); } else // systemProxy should be selected and is sensible default anyway { @@ -981,6 +977,23 @@ public class Preferences extends GPreferences } } + public void saveProxySettings() + { + Cache.applicationProperties.setProperty("USE_PROXY", + customProxy.isSelected() ? Cache.PROXYTYPE_CUSTOM + : noProxy.isSelected() ? Cache.PROXYTYPE_NONE + : Cache.PROXYTYPE_SYSTEM); + Cache.setOrRemove("PROXY_SERVER", proxyServerHttpTB.getText()); + Cache.setOrRemove("PROXY_PORT", proxyPortHttpTB.getText()); + Cache.setOrRemove("PROXY_SERVER_HTTPS", proxyServerHttpsTB.getText()); + Cache.setOrRemove("PROXY_PORT_HTTPS", proxyPortHttpsTB.getText()); + Cache.setOrRemove("PROXY_AUTH", + Boolean.toString(proxyAuth.isSelected())); + Cache.setOrRemove("PROXY_AUTH_USERNAME", proxyAuthUsernameTB.getText()); + Cache.proxyAuthPassword = proxyAuthPasswordTB.getPassword(); + setProxyFromSettings(); + } + /** * Do any necessary validation before saving settings. Return focus to the * first tab which fails validation. diff --git a/src/jalview/jbgui/GPreferences.java b/src/jalview/jbgui/GPreferences.java index 67da0f4..bc9584e 100755 --- a/src/jalview/jbgui/GPreferences.java +++ b/src/jalview/jbgui/GPreferences.java @@ -218,6 +218,8 @@ public class GPreferences extends JPanel /* * Connections tab components */ + protected JPanel connectTab; + protected JTable linkUrlTable = new JTable(); protected JButton editLink = new JButton(); @@ -246,6 +248,8 @@ public class GPreferences extends JPanel protected JLabel proxyAuthPasswordLabel = new JLabel(); + protected JLabel passwordNotStoredLabel = new JLabel(); + protected JTextField proxyServerHttpTB = new JTextField(); protected JTextField proxyPortHttpTB = new JTextField(); @@ -258,7 +262,7 @@ public class GPreferences extends JPanel protected JTextField proxyAuthUsernameTB = new JTextField(); - protected JTextField proxyAuthPasswordTB = new JPasswordField(); + protected JPasswordField proxyAuthPasswordTB = new JPasswordField(); protected JTextField defaultBrowser = new JTextField(); @@ -374,9 +378,14 @@ public class GPreferences extends JPanel */ public GPreferences() { + new GPreferences(0); + } + + public GPreferences(int selectTab) + { try { - jbInit(); + jbInit(selectTab); } catch (Exception ex) { ex.printStackTrace(); @@ -390,6 +399,13 @@ public class GPreferences extends JPanel */ private void jbInit() throws Exception { + jbInit(0); + } + + public final static int CONNECTIONS_TAB = 5; + + private void jbInit(int selectTab) throws Exception + { final JTabbedPane tabbedPane = new JTabbedPane(); this.setLayout(new BorderLayout()); JPanel okCancelPanel = initOkCancelPanel(); @@ -459,6 +475,16 @@ public class GPreferences extends JPanel } }); + + // select a given tab - currently only for Connections + switch (selectTab) + { + case CONNECTIONS_TAB: + tabbedPane.setSelectedComponent(connectTab); + break; + default: + } + } /** @@ -638,7 +664,7 @@ public class GPreferences extends JPanel */ private JPanel initConnectionsTab() { - JPanel connectTab = new JPanel(); + connectTab = new JPanel(); connectTab.setLayout(new GridBagLayout()); // Label for browser text box @@ -953,6 +979,10 @@ public class GPreferences extends JPanel .setText(MessageManager.getString("label.password") + ": "); proxyAuthPasswordLabel.setFont(LABEL_FONT); proxyAuthPasswordLabel.setHorizontalAlignment(SwingConstants.RIGHT); + passwordNotStoredLabel.setText( + "(" + MessageManager.getString("label.not_stored") + ")"); + passwordNotStoredLabel.setFont(LABEL_FONT_ITALIC); + passwordNotStoredLabel.setHorizontalAlignment(SwingConstants.LEFT); // Proxy type radio buttons noProxy.setFont(LABEL_FONT); @@ -1005,105 +1035,126 @@ public class GPreferences extends JPanel TitledBorder titledBorder1 = new TitledBorder( MessageManager.getString("label.proxy_servers")); proxyPanel.setBorder(titledBorder1); - GridBagConstraints gbc = new GridBagConstraints(); proxyPanel.setLayout(new GridBagLayout()); - - gbc.gridx = 0; - gbc.gridy = 0; + GridBagConstraints gbc = new GridBagConstraints(); + gbc.fill = GridBagConstraints.HORIZONTAL; gbc.weightx = 1.0; - gbc.gridheight = 1; - gbc.anchor = GridBagConstraints.WEST; - gbc.fill = GridBagConstraints.BOTH; - - gbc.gridwidth = 5; - proxyPanel.add(noProxy, gbc); - - gbc.gridy++; - proxyPanel.add(systemProxy, gbc); - - gbc.gridy++; - proxyPanel.add(customProxy, gbc); - - gbc.gridwidth = 1; - gbc.gridy++; - gbc.gridx = 0; - gbc.weightx = 0.1; - proxyPanel.add(httpLabel, gbc); - - gbc.gridx++; - gbc.anchor = GridBagConstraints.EAST; - gbc.weightx = 0.15; - proxyPanel.add(serverLabel, gbc); - gbc.gridx++; - gbc.anchor = GridBagConstraints.WEST; - gbc.weightx = 0.5; - proxyPanel.add(proxyServerHttpTB, gbc); - - gbc.gridx++; - gbc.anchor = GridBagConstraints.EAST; - gbc.weightx = 0.15; - proxyPanel.add(portLabel, gbc); + GridBagConstraints c = new GridBagConstraints(); + // Proxy type radio buttons (3) + JPanel ptPanel = new JPanel(); + ptPanel.setLayout(new GridBagLayout()); + c.weightx = 1.0; + c.gridy = 0; + c.gridx = 0; + c.gridwidth = 1; + c.fill = GridBagConstraints.HORIZONTAL; + ptPanel.add(noProxy, c); + c.gridy++; + ptPanel.add(systemProxy, c); + c.gridy++; + ptPanel.add(customProxy, c); - gbc.gridx++; - gbc.anchor = GridBagConstraints.WEST; - gbc.weightx = 0.1; - proxyPanel.add(proxyPortHttpTB, gbc); + gbc.gridy = 0; + proxyPanel.add(ptPanel, gbc); + + // host and port text boxes + JPanel hpPanel = new JPanel(); + hpPanel.setLayout(new GridBagLayout()); + // HTTP host port row + c.gridy = 0; + c.gridx = 0; + + c.weightx = 0.1; + c.anchor = GridBagConstraints.LINE_START; + hpPanel.add(httpLabel, c); + + c.gridx++; + c.weightx = 0.1; + c.anchor = GridBagConstraints.LINE_END; + hpPanel.add(serverLabel, c); + + c.gridx++; + c.weightx = 1.0; + c.anchor = GridBagConstraints.LINE_START; + hpPanel.add(proxyServerHttpTB, c); + + c.gridx++; + c.weightx = 0.1; + c.anchor = GridBagConstraints.LINE_END; + hpPanel.add(portLabel, c); + + c.gridx++; + c.weightx = 0.2; + c.anchor = GridBagConstraints.LINE_START; + hpPanel.add(proxyPortHttpTB, c); + + // HTTPS host port row + c.gridy++; + c.gridx = 0; + c.gridwidth = 1; + + c.anchor = GridBagConstraints.LINE_START; + hpPanel.add(httpsLabel, c); + + c.gridx++; + c.anchor = GridBagConstraints.LINE_END; + hpPanel.add(serverLabel2, c); + + c.gridx++; + c.anchor = GridBagConstraints.LINE_START; + hpPanel.add(proxyServerHttpsTB, c); + + c.gridx++; + c.anchor = GridBagConstraints.LINE_END; + hpPanel.add(portLabel2, c); + + c.gridx++; + c.anchor = GridBagConstraints.LINE_START; + hpPanel.add(proxyPortHttpsTB, c); gbc.gridy++; - gbc.gridx = 0; - gbc.anchor = GridBagConstraints.WEST; - gbc.weightx = 0.1; - proxyPanel.add(httpsLabel, gbc); - - gbc.gridx++; - gbc.anchor = GridBagConstraints.EAST; - gbc.weightx = 0.15; - proxyPanel.add(serverLabel2, gbc); - - gbc.gridx++; - gbc.anchor = GridBagConstraints.WEST; - gbc.weightx = 0.5; - proxyPanel.add(proxyServerHttpsTB, gbc); - - gbc.gridx++; - gbc.anchor = GridBagConstraints.EAST; - gbc.weightx = 0.15; - proxyPanel.add(portLabel2, gbc); - - gbc.gridx++; - gbc.anchor = GridBagConstraints.WEST; - gbc.weightx = 0.1; - proxyPanel.add(proxyPortHttpsTB, gbc); + proxyPanel.add(hpPanel, gbc); + // Require authentication checkbox gbc.gridy++; - gbc.gridx = 0; - gbc.gridwidth = 5; - gbc.anchor = GridBagConstraints.WEST; - gbc.weightx = 0.1; proxyPanel.add(proxyAuth, gbc); - gbc.gridy++; - gbc.gridx = 0; - gbc.gridwidth = 1; - gbc.anchor = GridBagConstraints.EAST; - proxyPanel.add(proxyAuthUsernameLabel, gbc); - - gbc.gridx++; - gbc.gridwidth = 4; - gbc.anchor = GridBagConstraints.WEST; - proxyPanel.add(proxyAuthUsernameTB, gbc); + // username and password + JPanel upPanel = new JPanel(); + upPanel.setLayout(new GridBagLayout()); + // username row + c.gridy = 0; + c.gridx = 0; + c.gridwidth = 1; + c.weightx = 0.4; + c.anchor = GridBagConstraints.LINE_END; + upPanel.add(proxyAuthUsernameLabel, c); + + c.gridx++; + c.weightx = 1.0; + c.anchor = GridBagConstraints.LINE_START; + upPanel.add(proxyAuthUsernameTB, c); + + // password row + c.gridy++; + c.gridx = 0; + c.weightx = 0.4; + c.anchor = GridBagConstraints.LINE_END; + upPanel.add(proxyAuthPasswordLabel, c); + + c.gridx++; + c.weightx = 1.0; + c.anchor = GridBagConstraints.LINE_START; + upPanel.add(proxyAuthPasswordTB, c); + + c.gridx++; + c.weightx = 0.4; + c.anchor = GridBagConstraints.LINE_START; + upPanel.add(passwordNotStoredLabel, c); gbc.gridy++; - gbc.gridx = 0; - gbc.gridwidth = 1; - gbc.anchor = GridBagConstraints.EAST; - proxyPanel.add(proxyAuthPasswordLabel, gbc); - - gbc.gridx++; - gbc.gridwidth = 4; - gbc.anchor = GridBagConstraints.WEST; - proxyPanel.add(proxyAuthPasswordTB, gbc); + proxyPanel.add(upPanel, gbc); return proxyPanel; } @@ -3024,6 +3075,7 @@ public class GPreferences extends JPanel boolean enabled = proxyAuth.isSelected() && proxyAuth.isEnabled(); proxyAuthUsernameLabel.setEnabled(enabled); proxyAuthPasswordLabel.setEnabled(enabled); + passwordNotStoredLabel.setEnabled(enabled); proxyAuthUsernameTB.setEnabled(enabled); proxyAuthPasswordTB.setEnabled(enabled); } -- 1.7.10.2