diff options
author | Omair Majid <[email protected]> | 2011-02-28 14:30:39 -0500 |
---|---|---|
committer | Omair Majid <[email protected]> | 2011-02-28 14:30:39 -0500 |
commit | 5df1503c77c6c1b6104baa22354bd1cd215f9cbc (patch) | |
tree | 3eee8ad62ede221369452fba3dd2423113e0df38 /netx | |
parent | 05dd25bd43df11fc874d857ced49bbe3c6e72a74 (diff) |
Integrate JNLPAuthenticator into the rest of the security subsystem
This patch integrates the password authentication pane into the rest of the
security dialog system. The password authentication dialog is now shown using
the secure thread, rather than the thread of the JNLP application.
2011-02-28 Omair Majid <[email protected]>
* netx/net/sourceforge/jnlp/resources/Messages.properties: Add Password,
Username and SAuthenticationPrompt.
* netx/net/sourceforge/jnlp/security/JNLPAuthenticator.java
(getPasswordAuthentication): Show password prompt using the secure thread.
* netx/net/sourceforge/jnlp/security/PasswordAuthenticationPane.java
(PasswordAuthenticationPane): Initialize variables.
(initialize): For consistency, rename to..
(addComponents): New method. Set the appropriate return value when user
takes an action.
(askUser): Remove.
(main): Remove.
* netx/net/sourceforge/jnlp/security/SecurityDialog.java
(initDialog): Add extra case for AUTHENTICATION dialog type.
(installPanel): Likewise.
* netx/net/sourceforge/jnlp/security/SecurityDialogs.java
(DialogType): Add AUTHENTICATION.
(showAuthenicationPrompt): New method. Shows a password authentication
prompt.
Diffstat (limited to 'netx')
5 files changed, 100 insertions, 117 deletions
diff --git a/netx/net/sourceforge/jnlp/resources/Messages.properties b/netx/net/sourceforge/jnlp/resources/Messages.properties index cbb51b3..8770b67 100644 --- a/netx/net/sourceforge/jnlp/resources/Messages.properties +++ b/netx/net/sourceforge/jnlp/resources/Messages.properties @@ -22,8 +22,10 @@ Continue=Do you want to continue? Field=Field
From=From
Name=Name
+Password=Password:
Publisher=Publisher
Unknown=<Unknown>
+Username=Username:
Value=Value
Version=Version
@@ -195,6 +197,7 @@ SHttpsUnverified=The website's certificate cannot be verified. SNotAllSignedSummary=Only parts of this application code are signed.
SNotAllSignedDetail=This application contains both signed and unsigned code. While signed code is safe if you trust the provider, unsigned code may imply code outside of the trusted provider's control.
SNotAllSignedQuestion=Do you wish to proceed and run this application anyway?
+SAuthenticationPrompt=The {0} server at {1} is requesting authentication. It says "{2}"
# Security - used for the More Information dialog
SBadKeyUsage=Resources contain entries whose signer certificate's KeyUsage extension doesn't allow code signing.
diff --git a/netx/net/sourceforge/jnlp/security/JNLPAuthenticator.java b/netx/net/sourceforge/jnlp/security/JNLPAuthenticator.java index 36b3233..5830b97 100644 --- a/netx/net/sourceforge/jnlp/security/JNLPAuthenticator.java +++ b/netx/net/sourceforge/jnlp/security/JNLPAuthenticator.java @@ -42,6 +42,7 @@ import java.net.PasswordAuthentication; public class JNLPAuthenticator extends Authenticator { + @Override public PasswordAuthentication getPasswordAuthentication() { // No security check is required here, because the only way to set @@ -50,12 +51,16 @@ public class JNLPAuthenticator extends Authenticator { String type = this.getRequestorType() == RequestorType.PROXY ? "proxy" : "web"; - // request auth info from user - PasswordAuthenticationPane pwDialog = new PasswordAuthenticationPane(); - PasswordAuthentication auth = pwDialog.askUser(this.getRequestingHost(), this.getRequestingPort(), this.getRequestingPrompt(), type); + String host = getRequestingHost(); + int port = getRequestingPort(); + String prompt = getRequestingPrompt(); - // send it along - return auth; + Object[] response = SecurityDialogs.showAuthenicationPrompt(host, port, prompt, type); + if (response == null) { + return null; + } else { + return new PasswordAuthentication((String) response[0], (char[]) response[1]); + } } } diff --git a/netx/net/sourceforge/jnlp/security/PasswordAuthenticationPane.java b/netx/net/sourceforge/jnlp/security/PasswordAuthenticationPane.java index 7a0411e..d449211 100644 --- a/netx/net/sourceforge/jnlp/security/PasswordAuthenticationPane.java +++ b/netx/net/sourceforge/jnlp/security/PasswordAuthenticationPane.java @@ -37,52 +37,59 @@ exception statement from your version. */ package net.sourceforge.jnlp.security; +import static net.sourceforge.jnlp.runtime.Translator.R; + import java.awt.Dimension; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.net.PasswordAuthentication; import javax.swing.JButton; -import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JPasswordField; import javax.swing.JTextField; -import javax.swing.SwingUtilities; - -import net.sourceforge.jnlp.runtime.JNLPRuntime; /** * Modal non-minimizable dialog to request http authentication credentials */ -public class PasswordAuthenticationPane extends JDialog { +public class PasswordAuthenticationPane extends SecurityDialogPanel { - private final JLabel jlInfo = new JLabel(""); private final JTextField jtfUserName = new JTextField(); private final JPasswordField jpfPassword = new JPasswordField(); - private boolean userCancelled; - public PasswordAuthenticationPane() { - initialize(); - } + private final String host; + private final int port; + private final String prompt; + private final String type; + + public PasswordAuthenticationPane(SecurityDialog parent, Object[] extras) { + super(parent); + host = (String) extras[0]; + port = (Integer) extras[1]; + prompt = (String) extras[2]; + type = (String) extras[3]; + + addComponents(); + } /** * Initialized the dialog components */ - public void initialize() { + public void addComponents() { - setTitle("IcedTea Java Plugin - Authorization needed to proceed"); + JLabel jlInfo = new JLabel(""); + jlInfo.setText("<html>" + R("SAuthenticationPrompt", type, host, prompt) + "</html>"); setLayout(new GridBagLayout()); - JLabel jlUserName = new JLabel("Username: "); - JLabel jlPassword = new JLabel("Password: "); - JButton jbOK = new JButton("OK"); - JButton jbCancel = new JButton("Cancel"); + JLabel jlUserName = new JLabel(R("Username")); + JLabel jlPassword = new JLabel(R("Password")); + JButton jbOK = new JButton(R("ButOk")); + JButton jbCancel = new JButton(R("ButCancel")); jtfUserName.setSize(20, 10); jpfPassword.setSize(20, 10); @@ -90,7 +97,7 @@ public class PasswordAuthenticationPane extends JDialog { GridBagConstraints c; c = new GridBagConstraints(); - c.fill = c.HORIZONTAL; + c.fill = GridBagConstraints.HORIZONTAL; c.gridx = 0; c.gridy = 0; c.gridwidth = 2; @@ -104,7 +111,7 @@ public class PasswordAuthenticationPane extends JDialog { add(jlUserName, c); c = new GridBagConstraints(); - c.fill = c.HORIZONTAL; + c.fill = GridBagConstraints.HORIZONTAL; c.gridx = 1; c.gridy = 1; c.insets = new Insets(10, 5, 3, 3); @@ -118,7 +125,7 @@ public class PasswordAuthenticationPane extends JDialog { add(jlPassword, c); c = new GridBagConstraints(); - c.fill = c.HORIZONTAL; + c.fill = GridBagConstraints.HORIZONTAL; c.gridx = 1; c.gridy = 2; c.insets = new Insets(5, 5, 3, 3); @@ -126,7 +133,7 @@ public class PasswordAuthenticationPane extends JDialog { add(jpfPassword, c); c = new GridBagConstraints(); - c.anchor = c.SOUTHEAST; + c.anchor = GridBagConstraints.SOUTHEAST; c.gridx = 1; c.gridy = 3; c.insets = new Insets(5, 5, 3, 70); @@ -134,7 +141,7 @@ public class PasswordAuthenticationPane extends JDialog { add(jbCancel, c); c = new GridBagConstraints(); - c.anchor = c.SOUTHEAST; + c.anchor = GridBagConstraints.SOUTHEAST; c.gridx = 1; c.gridy = 3; c.insets = new Insets(5, 5, 3, 3); @@ -143,105 +150,33 @@ public class PasswordAuthenticationPane extends JDialog { setMinimumSize(new Dimension(400, 150)); setMaximumSize(new Dimension(1024, 150)); - setAlwaysOnTop(true); setSize(400, 150); - setLocationRelativeTo(null); - - // OK => read supplied info and pass it on - jbOK.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - userCancelled = false; - dispose(); - } - }); - - // Cancel => discard supplied info and pass on an empty auth - jbCancel.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - userCancelled = true; - dispose(); - } - }); - - // "return" key in either user or password field => OK + parent.setLocationRelativeTo(null); + initialFocusComponent = jtfUserName; - jtfUserName.addActionListener(new ActionListener() { + ActionListener acceptActionListener = new ActionListener() { public void actionPerformed(ActionEvent e) { - userCancelled = false; - dispose(); + parent.setValue(new Object[] { jtfUserName.getText(), jpfPassword.getPassword() }); + parent.dispose(); } - }); + }; - jpfPassword.addActionListener(new ActionListener() { + ActionListener cancelActionListener = new ActionListener() { public void actionPerformed(ActionEvent e) { - userCancelled = false; - dispose(); - } - }); - } - - /** - * Present a dialog to the user asking them for authentication information - * - * @param host The host for with authentication is needed - * @param port The port being accessed - * @param prompt The prompt (realm) as presented by the server - * @param type The type of server (proxy/web) - * @return PasswordAuthentication containing the credentials (empty credentials if user cancelled) - */ - protected PasswordAuthentication askUser(String host, int port, String prompt, String type) { - PasswordAuthentication auth = null; - - host += port != -1 ? ":" + port : ""; - - // This frame is reusable. So reset everything first. - userCancelled = true; - jlInfo.setText("<html>The " + type + " server at " + host + - " is requesting authentication. It says \"" + prompt + "\"</html>"); - - try { - SwingUtilities.invokeAndWait(new Runnable() { - public void run() { - // show dialog to user - setVisible(true); - } - }); - - if (JNLPRuntime.isDebug()) { - System.out.println("password dialog shown"); - } - - // wait until dialog is gone - while (this.isShowing()) { - try { - Thread.sleep(200); - } catch (InterruptedException ie) { - } - } - - if (JNLPRuntime.isDebug()) { - System.out.println("password dialog closed"); + parent.setValue(null); + parent.dispose(); } + }; - if (!userCancelled) { - auth = new PasswordAuthentication(jtfUserName.getText(), jpfPassword.getPassword()); - } - } catch (Exception e) { - e.printStackTrace(); - - // Nothing else we can do. Empty auth will be returned - } - - return auth; - } - - public static void main(String[] args) { - PasswordAuthenticationPane frame = new PasswordAuthenticationPane(); + // OK => read supplied info and pass it on + jbOK.addActionListener(acceptActionListener); - PasswordAuthentication auth = frame.askUser("127.0.0.1", 3128, "Password for local proxy", "proxy"); + // Cancel => discard supplied info and pass on an empty auth + jbCancel.addActionListener(cancelActionListener); - System.err.println("Auth info: " + auth.getUserName() + ":" + new String(auth.getPassword())); - System.exit(0); + // "return" key in either user or password field => OK + jtfUserName.addActionListener(acceptActionListener); + jpfPassword.addActionListener(acceptActionListener); } } diff --git a/netx/net/sourceforge/jnlp/security/SecurityDialog.java b/netx/net/sourceforge/jnlp/security/SecurityDialog.java index cb37395..2fc201d 100644 --- a/netx/net/sourceforge/jnlp/security/SecurityDialog.java +++ b/netx/net/sourceforge/jnlp/security/SecurityDialog.java @@ -219,6 +219,8 @@ public class SecurityDialog extends JDialog { dialogTitle = "Applet Warning"; else if (dialogType == DialogType.NOTALLSIGNED_WARNING) dialogTitle = "Security Warning"; + else if (dialogType == DialogType.AUTHENTICATION) + dialogTitle = "Authentication Required"; setTitle(dialogTitle); setModalityType(ModalityType.MODELESS); @@ -291,6 +293,8 @@ public class SecurityDialog extends JDialog { panel = new AppletWarningPane(this, this.certVerifier); else if (dialogType == DialogType.NOTALLSIGNED_WARNING) panel = new NotAllSignedWarningPane(this); + else if (dialogType == DialogType.AUTHENTICATION) + panel = new PasswordAuthenticationPane(this, extras); add(panel, BorderLayout.CENTER); } diff --git a/netx/net/sourceforge/jnlp/security/SecurityDialogs.java b/netx/net/sourceforge/jnlp/security/SecurityDialogs.java index 5f10d69..9b93a73 100644 --- a/netx/net/sourceforge/jnlp/security/SecurityDialogs.java +++ b/netx/net/sourceforge/jnlp/security/SecurityDialogs.java @@ -40,6 +40,7 @@ package net.sourceforge.jnlp.security; import java.awt.Dialog.ModalityType; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; +import java.net.NetPermission; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.concurrent.Semaphore; @@ -69,7 +70,8 @@ public class SecurityDialogs { SINGLE_CERT_INFO, ACCESS_WARNING, NOTALLSIGNED_WARNING, - APPLET_WARNING + APPLET_WARNING, + AUTHENTICATION, } /** The types of access which may need user permission. */ @@ -208,6 +210,40 @@ public class SecurityDialogs { } /** + * Present a dialog to the user asking them for authentication information, + * and returns the user's response. The caller must have + * NetPermission("requestPasswordAuthentication") for this to work. + * + * @param host The host for with authentication is needed + * @param port The port being accessed + * @param prompt The prompt (realm) as presented by the server + * @param type The type of server (proxy/web) + * @return an array of objects representing user's authentication tokens + * @throws SecurityException if the caller does not have the appropriate permissions. + */ + public static Object[] showAuthenicationPrompt(String host, int port, String prompt, String type) { + + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + NetPermission requestPermission + = new NetPermission("requestPasswordAuthentication"); + sm.checkPermission(requestPermission); + } + + final SecurityDialogMessage message = new SecurityDialogMessage(); + + message.dialogType = DialogType.AUTHENTICATION; + message.extras = new Object[] { host, port, prompt, type }; + + Object response = getUserResponse(message); + if (response == null) { + return null; + } else { + return (Object[]) response; + } + } + + /** * FIXME This is unused. Remove it? * @return (0, 1, 2) => (Yes, No, Cancel) */ |