aboutsummaryrefslogtreecommitdiffstats
path: root/netx/net/sourceforge/jnlp/security
diff options
context:
space:
mode:
authorOmair Majid <[email protected]>2010-10-22 10:44:12 -0400
committerOmair Majid <[email protected]>2010-10-22 10:44:12 -0400
commit12747b34f31cfb98c057f45e8aeb1711ea7341c8 (patch)
tree45b4d70163f9f19f014017bf33d0adaf725e03a6 /netx/net/sourceforge/jnlp/security
parent61aeaaf89164aa93280527c7eb80cf4c1432fbee (diff)
show security dialogs using the main AppContext
2010-10-22 Omair Majid <[email protected]> * netx/net/sourceforge/jnlp/NetxPanel.java (runLoader): Do not initialize JNLPRuntime here. (createAppletThreads): Initialize JNLPRuntim here. * netx/net/sourceforge/jnlp/runtime/ApplicationInstance.java: Switch from SecurityWarningDialog.AccessType to SecurityWarning.AccessType. * netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java (getInstance(JNLPFile,UpdatePolicy)): Switch to SecurityWarning. (initializeResources): Likewise. (checkTrustWithUser): Likewise. * netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java: Add securityDialogMesasgeHandler. (initialize): Set System look and feel. Start security thread. (startSecurityThread): New method. Starts a thread to show security dialogs. (getSecurityDialogHandler): Returns the securityDialogMessageHandler. * netx/net/sourceforge/jnlp/runtime/JNLPSecurityManager.java: Switch from SecurityWarningDialog.AccessType to SecurityWarning.AccessType. (checkAwtEventQueueAccess): New method. Skeleton code for allowing EventQueue acccess to applets. * netx/net/sourceforge/jnlp/security/AccessWarningPane.java: Switch from SecurityWarningDialog.AccessType to SecurityWarning.AccessType. * netx/net/sourceforge/jnlp/security/CertWarningPane.java: Likewise. * netx/net/sourceforge/jnlp/security/SecurityWarningDialog.java: Move DialogType and AccessType to SecurityWarning. (SecurityWarningDialog(DialogType,AccessType,JNLPFile,CertVerifier, X509Certificate,Object[])): New method. The catch-all construction. (SecurityWarningDialog(DialogType,AccessType,JNLPFile): Delegate to the new constructor. (SecurityWarningDialog(DialogType,AccessType,JNLPFile,CertVerifier)): Likewise. (SecurityWarningDialog(DialogType,AccessType,CertVerifier)): Likewise. (SecurityWarningDialog(DialogType,AccessType,JNLPFile,Object[])): Likewise. (SecurityWarningDialog(DialogType,X509Certificate)): Likewise. (showAccessWarningDialog(AccessType,JNLPFile)): Move to SecurityWarning class. (showAccessWarningDialog(AccessType,JNLPFile,Object[])): Likewise. (showNotAllSignedWarningDialog(JNLPFile)): Likewise. (showCertWarningDialog(AccessType,JNLPFile,CertVerifier)): Likewise. (showAppletWarning): Likewise. (initDialog): Make dialog non modal and remove window closing listener. (getValue): Make public. (dispose): New method. Notify listeners. (notifySelectionMade): New method. Notify listeners that user has made a decision. (addActionListener): New method. Add a listener to be notified when user makes a decision about this security warning. * netx/net/sourceforge/jnlp/security/VariableX509TrustManager.java: Switch from SecurityWarningDialog.AccessType to SecurityWarning.AccessType. * netx/net/sourceforge/jnlp/services/ServiceUtil.java: Likewise. * netx/net/sourceforge/jnlp/services/XClipboardService.java: Likewise. * netx/net/sourceforge/jnlp/services/XExtendedService.java: Likewise. * netx/net/sourceforge/jnlp/services/XFileOpenService.java: Likewise. * netx/net/sourceforge/jnlp/services/XFileSaveService.java: Likewise. * netx/net/sourceforge/jnlp/security/SecurityDialogMessage.java: New class. * netx/net/sourceforge/jnlp/security/SecurityDialogMessageHandler.java: New class. (run): New method. Runs the security message loop. (handleMessage): New method. Handles a SecurityDialogMessage to show a security warning. (postMessage): New method. Posts a message to sthe security message queue. * netx/net/sourceforge/jnlp/security/SecurityWarning.java: New class. Move AccessType and DialogType from SecurityWarningDialog to here. (showAccessWarningDialog): Moved from SecurityWarningDialog to here. (showAccessWarningDialog): Moved from SecurityWarningDialog to here. Modified to post messages to the security queue instead of showing a SecurityWarningDialog directly. (showNotAllSignedWarningDialog): Likewise. (showCertWarningDialog): Likewise. (showAppletWarning): Likewise. (getUserReponse): New method. Posts a message to the security thread and blocks until it gets a response from the user.
Diffstat (limited to 'netx/net/sourceforge/jnlp/security')
-rw-r--r--netx/net/sourceforge/jnlp/security/AccessWarningPane.java3
-rw-r--r--netx/net/sourceforge/jnlp/security/CertWarningPane.java3
-rw-r--r--netx/net/sourceforge/jnlp/security/SecurityDialogMessage.java44
-rw-r--r--netx/net/sourceforge/jnlp/security/SecurityDialogMessageHandler.java141
-rw-r--r--netx/net/sourceforge/jnlp/security/SecurityWarning.java298
-rw-r--r--netx/net/sourceforge/jnlp/security/SecurityWarningDialog.java266
-rw-r--r--netx/net/sourceforge/jnlp/security/VariableX509TrustManager.java6
7 files changed, 570 insertions, 191 deletions
diff --git a/netx/net/sourceforge/jnlp/security/AccessWarningPane.java b/netx/net/sourceforge/jnlp/security/AccessWarningPane.java
index 5afbfff..64c7727 100644
--- a/netx/net/sourceforge/jnlp/security/AccessWarningPane.java
+++ b/netx/net/sourceforge/jnlp/security/AccessWarningPane.java
@@ -56,6 +56,7 @@ import javax.swing.JPanel;
import javax.swing.SwingConstants;
import net.sourceforge.jnlp.JNLPFile;
+import net.sourceforge.jnlp.security.SecurityWarning.AccessType;
import net.sourceforge.jnlp.util.FileUtils;
/**
@@ -86,7 +87,7 @@ public class AccessWarningPane extends SecurityDialogPanel {
* Creates the actual GUI components, and adds it to this panel
*/
private void addComponents() {
- SecurityWarningDialog.AccessType type = parent.getAccessType();
+ AccessType type = parent.getAccessType();
JNLPFile file = parent.getFile();
String name = "";
diff --git a/netx/net/sourceforge/jnlp/security/CertWarningPane.java b/netx/net/sourceforge/jnlp/security/CertWarningPane.java
index 59559c4..163c20c 100644
--- a/netx/net/sourceforge/jnlp/security/CertWarningPane.java
+++ b/netx/net/sourceforge/jnlp/security/CertWarningPane.java
@@ -60,6 +60,7 @@ import javax.swing.SwingConstants;
import net.sourceforge.jnlp.JNLPFile;
import net.sourceforge.jnlp.PluginBridge;
import net.sourceforge.jnlp.runtime.JNLPRuntime;
+import net.sourceforge.jnlp.security.SecurityWarning.AccessType;
import net.sourceforge.jnlp.tools.KeyTool;
/**
@@ -85,7 +86,7 @@ public class CertWarningPane extends SecurityDialogPanel {
* Creates the actual GUI components, and adds it to this panel
*/
private void addComponents() {
- SecurityWarningDialog.AccessType type = parent.getAccessType();
+ AccessType type = parent.getAccessType();
JNLPFile file = parent.getFile();
Certificate c = parent.getJarSigner().getPublisher();
diff --git a/netx/net/sourceforge/jnlp/security/SecurityDialogMessage.java b/netx/net/sourceforge/jnlp/security/SecurityDialogMessage.java
new file mode 100644
index 0000000..c958fff
--- /dev/null
+++ b/netx/net/sourceforge/jnlp/security/SecurityDialogMessage.java
@@ -0,0 +1,44 @@
+package net.sourceforge.jnlp.security;
+
+import java.security.cert.X509Certificate;
+import java.util.concurrent.Semaphore;
+
+import javax.swing.JDialog;
+
+import net.sourceforge.jnlp.JNLPFile;
+import net.sourceforge.jnlp.security.SecurityWarning.AccessType;
+import net.sourceforge.jnlp.security.SecurityWarning.DialogType;
+
+/**
+ * Represents a message to the security framework to show a specific security
+ * dialog
+ */
+final class SecurityDialogMessage {
+
+ /*
+ * These fields contain information need to display the correct dialog type
+ */
+
+ public DialogType dialogType;
+ public AccessType accessType;
+ public JNLPFile file;
+ public CertVerifier certVerifier;
+ public X509Certificate certificate;
+ public Object[] extras;
+
+ /*
+ * Volatile because this is shared between threads and we dont want threads
+ * to use a cached value of this.
+ */
+ public volatile Object userResponse;
+
+ /*
+ * These two fields are used to block/unblock the application or the applet.
+ * If either of them is not null, call release() or dispose() on it to allow
+ * the application/applet to continue.
+ */
+
+ public Semaphore lock;
+ public JDialog toDispose;
+
+}
diff --git a/netx/net/sourceforge/jnlp/security/SecurityDialogMessageHandler.java b/netx/net/sourceforge/jnlp/security/SecurityDialogMessageHandler.java
new file mode 100644
index 0000000..7beca96
--- /dev/null
+++ b/netx/net/sourceforge/jnlp/security/SecurityDialogMessageHandler.java
@@ -0,0 +1,141 @@
+/* SecurityDialogMessageHandler.java
+ Copyright (C) 2010 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING. If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+package net.sourceforge.jnlp.security;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+
+import sun.awt.AppContext;
+
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
+
+/**
+ * Handles {@link SecurityDialogMessage}s and shows appropriate security
+ * dialogs.
+ * <p>
+ * In the current architecture, {@link SecurityWarningDialog}s are shown from a
+ * different {@link AppContext} than the {@link AppContext} that asks for a
+ * security prompt. This ensures that all security prompts are isolated and
+ * their Look and Feel is not affected by the Look and Feel of the
+ * applet/application.
+ * <p>
+ * This class contains allows a client application to post a
+ * {@link SecurityDialogMessage}. When this class finds a security message in
+ * the queue, it shows a security warning to the user, and sets
+ * {@link SecurityDialogMessage#userResponse} to the appropriate value.
+ */
+public final class SecurityDialogMessageHandler implements Runnable {
+
+ /** the queue of incoming messages to show security dialogs */
+ private BlockingQueue<SecurityDialogMessage> queue = new LinkedBlockingQueue<SecurityDialogMessage>();
+
+ /**
+ * Runs the message handler loop. This waits for incoming security messages
+ * and shows a security dialog.
+ */
+ @Override
+ public void run() {
+ if (JNLPRuntime.isDebug()) {
+ System.out.println("Starting security dialog thread");
+ }
+ while (true) {
+ try {
+ SecurityDialogMessage msg = queue.take();
+ handleMessage(msg);
+ } catch (InterruptedException e) {
+ }
+ }
+ }
+
+ /**
+ * Handles a single {@link SecurityDialogMessage} by showing a
+ * {@link SecurityWarningDialog}.
+ * <p>
+ * Once the user has made a choice the
+ * {@link SecurityDialogMessage#toDispose} (if not null) is disposed and
+ * {@link SecurityDialogMessage#lock} (in not null) is released.
+ *
+ * @param message the message indicating what type of security dialog to
+ * show
+ */
+ private void handleMessage(SecurityDialogMessage message) {
+ final SecurityDialogMessage msg = message;
+
+ final SecurityWarningDialog dialog = new SecurityWarningDialog(message.dialogType,
+ message.accessType, message.file, message.certVerifier, message.certificate, message.extras);
+
+ dialog.addActionListener(new ActionListener() {
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ msg.userResponse = dialog.getValue();
+ /* Allow the client to continue on the other side */
+ if (msg.toDispose != null) {
+ msg.toDispose.dispose();
+ }
+ if (msg.lock != null) {
+ msg.lock.release();
+ }
+ }
+ });
+ dialog.setVisible(true);
+
+ }
+
+ /**
+ * Post a message to the security event queue. This message will be picked
+ * up by the security thread and used to show the appropriate security
+ * dialog.
+ * <p>
+ * Once the user has made a choice the
+ * {@link SecurityDialogMessage#toDispose} (if not null) is disposed and
+ * {@link SecurityDialogMessage#lock} (in not null) is released.
+ *
+ * @param message indicates the type of security dialog to show
+ */
+ public void postMessage(SecurityDialogMessage message) {
+ try {
+ queue.put(message);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+}
diff --git a/netx/net/sourceforge/jnlp/security/SecurityWarning.java b/netx/net/sourceforge/jnlp/security/SecurityWarning.java
new file mode 100644
index 0000000..54ffc31
--- /dev/null
+++ b/netx/net/sourceforge/jnlp/security/SecurityWarning.java
@@ -0,0 +1,298 @@
+/* SecurityWarningDialogFactory.java
+ Copyright (C) 2010 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING. If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version.
+*/
+
+
+package net.sourceforge.jnlp.security;
+
+import java.awt.Dialog.ModalityType;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.concurrent.Semaphore;
+
+import javax.swing.JDialog;
+import javax.swing.SwingUtilities;
+
+import net.sourceforge.jnlp.JNLPFile;
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
+
+/**
+ * A factory for showing many possible types of security warning to the user.<p>
+ *
+ * This contains all the public methods that classes outside this package should
+ * use instead of using {@link SecurityWarningDialog} directly.
+ *
+ * All of these methods post a message to the
+ * {@link SecurityDialogMessageHandler} and block waiting for a response.
+ */
+public class SecurityWarning {
+ /** Types of dialogs we can create */
+ public static enum DialogType {
+ CERT_WARNING,
+ MORE_INFO,
+ CERT_INFO,
+ SINGLE_CERT_INFO,
+ ACCESS_WARNING,
+ NOTALLSIGNED_WARNING,
+ APPLET_WARNING
+ }
+
+ /** The types of access which may need user permission. */
+ public static enum AccessType {
+ READ_FILE,
+ WRITE_FILE,
+ CREATE_DESTKOP_SHORTCUT,
+ CLIPBOARD_READ,
+ CLIPBOARD_WRITE,
+ PRINTER,
+ NETWORK,
+ VERIFIED,
+ UNVERIFIED,
+ NOTALLSIGNED,
+ SIGNING_ERROR
+ }
+
+ /**
+ * Shows a warning dialog for different types of system access (i.e. file
+ * open/save, clipboard read/write, printing, etc).
+ *
+ * @param accessType the type of system access requested.
+ * @param file the jnlp file associated with the requesting application.
+ * @return true if permission was granted by the user, false otherwise.
+ */
+ public static boolean showAccessWarningDialog(AccessType accessType, JNLPFile file) {
+ return showAccessWarningDialog(accessType, file, null);
+ }
+
+ /**
+ * Shows a warning dialog for different types of system access (i.e. file
+ * open/save, clipboard read/write, printing, etc).
+ *
+ * @param accessType the type of system access requested.
+ * @param file the jnlp file associated with the requesting application.
+ * @param extras an optional array of Strings (typically) that gets
+ * passed to the dialog labels.
+ * @return true if permission was granted by the user, false otherwise.
+ */
+ public static boolean showAccessWarningDialog(final AccessType accessType,
+ final JNLPFile file, final Object[] extras) {
+ final SecurityDialogMessage message = new SecurityDialogMessage();
+
+ message.dialogType = DialogType.ACCESS_WARNING;
+ message.accessType = accessType;
+ message.file = file;
+ message.extras = extras;
+
+ Object selectedValue = getUserResponse(message);
+
+ if (selectedValue == null) {
+ return false;
+ } else if (selectedValue instanceof Integer) {
+ if (((Integer) selectedValue).intValue() == 0)
+ return true;
+ else
+ return false;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Shows a warning dialog for when the main application jars are signed,
+ * but extensions aren't
+ *
+ * @return true if permission was granted by the user, false otherwise.
+ */
+ public static boolean showNotAllSignedWarningDialog(JNLPFile file) {
+
+ final SecurityDialogMessage message = new SecurityDialogMessage();
+ message.dialogType = DialogType.NOTALLSIGNED_WARNING;
+ message.accessType = AccessType.NOTALLSIGNED;
+ message.file = file;
+ message.extras = new Object[0];
+
+ Object selectedValue = getUserResponse(message);
+
+ if (selectedValue == null) {
+ return false;
+ } else if (selectedValue instanceof Integer) {
+ if (((Integer)selectedValue).intValue() == 0) {
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Shows a security warning dialog according to the specified type of
+ * access. If <code>type</code> is one of AccessType.VERIFIED or
+ * AccessType.UNVERIFIED, extra details will be available with regards
+ * to code signing and signing certificates.
+ *
+ * @param accessType the type of warning dialog to show
+ * @param file the JNLPFile associated with this warning
+ * @param jarSigner the JarSigner used to verify this application
+ */
+ public static boolean showCertWarningDialog(AccessType accessType,
+ JNLPFile file, CertVerifier jarSigner) {
+
+ final SecurityDialogMessage message = new SecurityDialogMessage();
+ message.dialogType = DialogType.CERT_WARNING;
+ message.accessType = accessType;
+ message.file = file;
+ message.certVerifier = jarSigner;
+
+ Object selectedValue = getUserResponse(message);
+
+ if (selectedValue == null) {
+ return false;
+ } else if (selectedValue instanceof Integer) {
+ if (((Integer) selectedValue).intValue() == 0)
+ return true;
+ else
+ return false;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * FIXME This is unused. Remove it?
+ * @return (0, 1, 2) => (Yes, No, Cancel)
+ */
+ public static int showAppletWarning() {
+
+ SecurityDialogMessage message = new SecurityDialogMessage();
+ message.dialogType = DialogType.APPLET_WARNING;
+
+ Object selectedValue = getUserResponse(message);
+
+ // result 0 = Yes, 1 = No, 2 = Cancel
+ if (selectedValue == null) {
+ return 2;
+ } else if (selectedValue instanceof Integer) {
+ return ((Integer) selectedValue).intValue();
+ } else {
+ return 2;
+ }
+ }
+
+ /**
+ * Posts the message to the SecurityThread and gets the response. Blocks
+ * until a response has been recieved. It's safe to call this from an
+ * EventDispatchThread.
+ *
+ * @param message the SecuritDialogMessage indicating what type of dialog to
+ * display
+ * @return The user's response. Can be null. The exact answer depends on the
+ * type of message, but generally an Integer corresponding to the value 0
+ * indicates success/proceed, and everything else indicates failure
+ */
+ private static Object getUserResponse(final SecurityDialogMessage message) {
+ /*
+ * Want to show a security warning, while blocking the client
+ * application. This would be easy except there is a bug in showing
+ * modal JDialogs in a different AppContext. The source EventQueue -
+ * that sends the message to the (destination) EventQueue which is
+ * supposed to actually show the dialog - must not block. If the source
+ * EventQueue blocks, the destination EventQueue stops responding. So we
+ * have a hack here to work around it.
+ */
+
+ /*
+ * If this is the event dispatch thread the use the hack
+ */
+ if (SwingUtilities.isEventDispatchThread()) {
+ /*
+ * Create a tiny modal dialog (which creates a new EventQueue for
+ * this AppContext, but blocks the original client EventQueue) and
+ * then post the message - this makes the source EventQueue continue
+ * running - but dot not allow the actual applet/application to
+ * continue processing
+ */
+ final JDialog fakeDialog = new JDialog();
+ fakeDialog.setSize(0, 0);
+ fakeDialog.setResizable(false);
+ fakeDialog.setModalityType(ModalityType.APPLICATION_MODAL);
+ fakeDialog.addWindowListener(new WindowAdapter() {
+
+ @Override
+ public void windowOpened(WindowEvent e) {
+ message.toDispose = fakeDialog;
+ message.lock = null;
+ AccessController.doPrivileged(new PrivilegedAction<Void>() {
+ @Override
+ public Void run() {
+ JNLPRuntime.getSecurityDialogHandler().postMessage(message);
+ return null;
+ }
+ });
+ }
+ });
+
+ /* this dialog will be disposed/hidden when the user closes the security prompt */
+ fakeDialog.setVisible(true);
+ } else {
+ /*
+ * Otherwise do it the normal way. Post a message to the security
+ * thread to make it show the security dialog. Wait until it tells us
+ * to proceed.
+ */
+ message.toDispose = null;
+ message.lock = new Semaphore(0);
+ JNLPRuntime.getSecurityDialogHandler().postMessage(message);
+
+ boolean done = false;
+ while (!done) {
+ try {
+ message.lock.acquire();
+ done = true;
+ } catch (InterruptedException e) {
+ // ignore; retry
+ }
+ }
+
+ }
+
+ return message.userResponse;
+ }
+
+}
diff --git a/netx/net/sourceforge/jnlp/security/SecurityWarningDialog.java b/netx/net/sourceforge/jnlp/security/SecurityWarningDialog.java
index 14f5fe0..1937f1c 100644
--- a/netx/net/sourceforge/jnlp/security/SecurityWarningDialog.java
+++ b/netx/net/sourceforge/jnlp/security/SecurityWarningDialog.java
@@ -39,49 +39,29 @@ package net.sourceforge.jnlp.security;
import net.sourceforge.jnlp.JNLPFile;
import net.sourceforge.jnlp.runtime.JNLPRuntime;
+import net.sourceforge.jnlp.security.SecurityWarning.AccessType;
+import net.sourceforge.jnlp.security.SecurityWarning.DialogType;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
-
import java.security.cert.X509Certificate;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import java.util.List;
/**
- * Provides methods for showing security warning dialogs
- * for a wide range of JNLP security issues.
+ * Provides methods for showing security warning dialogs for a wide range of
+ * JNLP security issues. Note that the security dialogs should be running in the
+ * secure AppContext - this class should not be used directly from an applet or
+ * application. See {@link SecurityWarning} for a way to show security dialogs.
*
* @author <a href="mailto:[email protected]">Joshua Sumali</a>
*/
public class SecurityWarningDialog extends JDialog {
- /** Types of dialogs we can create */
- public static enum DialogType {
- CERT_WARNING,
- MORE_INFO,
- CERT_INFO,
- SINGLE_CERT_INFO,
- ACCESS_WARNING,
- NOTALLSIGNED_WARNING,
- APPLET_WARNING
- }
-
- /** The types of access which may need user permission. */
- public static enum AccessType {
- READ_FILE,
- WRITE_FILE,
- CREATE_DESTKOP_SHORTCUT,
- CLIPBOARD_READ,
- CLIPBOARD_WRITE,
- PRINTER,
- NETWORK,
- VERIFIED,
- UNVERIFIED,
- NOTALLSIGNED,
- SIGNING_ERROR
- }
-
/** The type of dialog we want to show */
private DialogType dialogType;
@@ -112,168 +92,67 @@ public class SecurityWarningDialog extends JDialog {
*/
private Object value;
- public SecurityWarningDialog(DialogType dialogType, AccessType accessType,
- JNLPFile file) {
- super();
- this.dialogType = dialogType;
- this.accessType = accessType;
- this.file = file;
- this.certVerifier = null;
- initialized = true;
- initDialog();
- }
-
- public SecurityWarningDialog(DialogType dialogType, AccessType accessType,
- JNLPFile file, CertVerifier jarSigner) {
- super();
- this.dialogType = dialogType;
- this.accessType = accessType;
- this.file = file;
- this.certVerifier = jarSigner;
- initialized = true;
- initDialog();
- }
-
- public SecurityWarningDialog(DialogType dialogType, AccessType accessType,
- CertVerifier certVerifier) {
+ SecurityWarningDialog(DialogType dialogType, AccessType accessType,
+ JNLPFile file, CertVerifier jarSigner, X509Certificate cert, Object[] extras) {
super();
this.dialogType = dialogType;
this.accessType = accessType;
- this.file = null;
- this.certVerifier = certVerifier;
+ this.file = file;
+ this.certVerifier = jarSigner;
+ this.cert = cert;
+ this.extras = extras;
initialized = true;
- initDialog();
- }
- public SecurityWarningDialog(DialogType dialogType, AccessType accessType,
- JNLPFile file, Object[] extras) {
- super();
- this.dialogType = dialogType;
- this.accessType = accessType;
- this.file = file;
- this.certVerifier = null;
- initialized = true;
- this.extras = extras;
- initDialog();
+ initDialog();
}
- //for displaying a single certificate
- public SecurityWarningDialog(DialogType dialogType, X509Certificate c) {
- super();
- this.dialogType = dialogType;
- this.accessType = null;
- this.file = null;
- this.certVerifier = null;
- this.cert = c;
- initialized = true;
- initDialog();
+ /**
+ * Construct a SecurityWarningDialog to display some sort of access warning
+ */
+ SecurityWarningDialog(DialogType dialogType, AccessType accessType,
+ JNLPFile file) {
+ this(dialogType, accessType, file, null, null, null);
}
/**
- * Returns if this dialog has been fully initialized yet.
- * @return true if this dialog has been initialized, and false otherwise.
+ * Create a SecurityWarningDialog to display a certificate-related warning
*/
- public boolean isInitialized(){
- return initialized;
+ SecurityWarningDialog(DialogType dialogType, AccessType accessType,
+ JNLPFile file, CertVerifier jarSigner) {
+ this(dialogType, accessType, file, jarSigner, null, null);
}
/**
- * Shows a warning dialog for different types of system access (i.e. file
- * open/save, clipboard read/write, printing, etc).
- *
- * @param accessType the type of system access requested.
- * @param file the jnlp file associated with the requesting application.
- * @return true if permission was granted by the user, false otherwise.
+ * Create a SecurityWarningDialog to display a certificate-related warning
*/
- public static boolean showAccessWarningDialog(AccessType accessType,
- JNLPFile file) {
- return showAccessWarningDialog(accessType, file, null);
+ SecurityWarningDialog(DialogType dialogType, AccessType accessType,
+ CertVerifier certVerifier) {
+ this(dialogType, accessType, null, certVerifier, null, null);
}
/**
- * Shows a warning dialog for different types of system access (i.e. file
- * open/save, clipboard read/write, printing, etc).
- *
- * @param accessType the type of system access requested.
- * @param file the jnlp file associated with the requesting application.
- * @param extras an optional array of Strings (typically) that gets
- * passed to the dialog labels.
- * @return true if permission was granted by the user, false otherwise.
+ * Create a SecurityWarningDialog to display some sort of access warning
+ * with more information
*/
- public static boolean showAccessWarningDialog(AccessType accessType,
+ SecurityWarningDialog(DialogType dialogType, AccessType accessType,
JNLPFile file, Object[] extras) {
- SecurityWarningDialog dialog = new SecurityWarningDialog(
- DialogType.ACCESS_WARNING, accessType, file, extras);
- dialog.setVisible(true);
- dialog.dispose();
-
- Object selectedValue = dialog.getValue();
- if (selectedValue == null) {
- return false;
- } else if (selectedValue instanceof Integer) {
- if (((Integer)selectedValue).intValue() == 0)
- return true;
- else
- return false;
- } else {
- return false;
- }
- }
+ this(dialogType, accessType, file, null, null, extras);
+ }
/**
- * Shows a warning dialog for when the main application jars are signed,
- * but extensions aren't
- *
- * @return true if permission was granted by the user, false otherwise.
+ * Create a SecurityWarningDailog to display information about a single
+ * certificate
*/
- public static boolean showNotAllSignedWarningDialog(JNLPFile file) {
- SecurityWarningDialog dialog = new SecurityWarningDialog(
- DialogType.NOTALLSIGNED_WARNING, AccessType.NOTALLSIGNED, file, (new Object[0]));
- dialog.setVisible(true);
- dialog.dispose();
-
- Object selectedValue = dialog.getValue();
- if (selectedValue == null) {
- return false;
- } else if (selectedValue instanceof Integer) {
- if (((Integer)selectedValue).intValue() == 0)
- return true;
- else
- return false;
- } else {
- return false;
- }
- }
+ SecurityWarningDialog(DialogType dialogType, X509Certificate c) {
+ this(dialogType, null, null, null, c, null);
+ }
/**
- * Shows a security warning dialog according to the specified type of
- * access. If <code>type</code> is one of AccessType.VERIFIED or
- * AccessType.UNVERIFIED, extra details will be available with regards
- * to code signing and signing certificates.
- *
- * @param accessType the type of warning dialog to show
- * @param file the JNLPFile associated with this warning
- * @param jarSigner the JarSigner used to verify this application
+ * Returns if this dialog has been fully initialized yet.
+ * @return true if this dialog has been initialized, and false otherwise.
*/
- public static boolean showCertWarningDialog(AccessType accessType,
- JNLPFile file, CertVerifier jarSigner) {
- SecurityWarningDialog dialog =
- new SecurityWarningDialog(DialogType.CERT_WARNING, accessType, file,
- jarSigner);
- dialog.setVisible(true);
- dialog.dispose();
-
- Object selectedValue = dialog.getValue();
- if (selectedValue == null) {
- return false;
- } else if (selectedValue instanceof Integer) {
- if (((Integer)selectedValue).intValue() == 0)
- return true;
- else
- return false;
- } else {
- return false;
- }
+ public boolean isInitialized(){
+ return initialized;
}
/**
@@ -320,23 +199,7 @@ public class SecurityWarningDialog extends JDialog {
dialog.dispose();
}
- public static int showAppletWarning() {
- SecurityWarningDialog dialog = new SecurityWarningDialog(DialogType.APPLET_WARNING,
- null, null, (CertVerifier) null);
- dialog.setVisible(true);
- dialog.dispose();
- Object selectedValue = dialog.getValue();
-
- //result 0 = Yes, 1 = No, 2 = Cancel
- if (selectedValue == null) {
- return 2;
- } else if (selectedValue instanceof Integer) {
- return ((Integer)selectedValue).intValue();
- } else {
- return 2;
- }
- }
private void initDialog() {
setSystemLookAndFeel();
@@ -356,7 +219,7 @@ public class SecurityWarningDialog extends JDialog {
dialogTitle = "Security Warning";
setTitle(dialogTitle);
- setModal(true);
+ setModal(false);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
@@ -366,10 +229,7 @@ public class SecurityWarningDialog extends JDialog {
WindowAdapter adapter = new WindowAdapter() {
private boolean gotFocus = false;
- @Override
- public void windowClosing(WindowEvent we) {
- setValue(null);
- }
+
@Override
public void windowGainedFocus(WindowEvent we) {
// Once window gets focus, set initial focus
@@ -454,7 +314,7 @@ public class SecurityWarningDialog extends JDialog {
this.value = value;
}
- protected Object getValue() {
+ public Object getValue() {
if (JNLPRuntime.isDebug()) {
System.out.println("Returning value:" + value);
}
@@ -462,6 +322,16 @@ public class SecurityWarningDialog extends JDialog {
}
/**
+ * Called when the SecurityWarningDialog is hidden - either because the user
+ * made a choice (Ok, Cancel, etc) or closed the window
+ */
+ @Override
+ public void dispose() {
+ notifySelectionMade();
+ super.dispose();
+ }
+
+ /**
* Updates the look and feel of the window to be the system look and feel
*/
protected void setSystemLookAndFeel() {
@@ -471,4 +341,26 @@ public class SecurityWarningDialog extends JDialog {
//don't worry if we can't.
}
}
+
+ private List<ActionListener> listeners = new CopyOnWriteArrayList<ActionListener>();
+
+ /**
+ * Notify all the listeners that the user has made a decision using this
+ * security dialog.
+ */
+ public void notifySelectionMade() {
+ for (ActionListener listener : listeners) {
+ listener.actionPerformed(null);
+ }
+ }
+
+ /**
+ * Adds an {@link ActionListener} which will be notified if the user makes a
+ * choice using this SecurityWarningDialog. The listener should use {@link #getValue()}
+ * to actually get the user's response.
+ */
+ public void addActionListener(ActionListener listener) {
+ listeners.add(listener);
+ }
+
}
diff --git a/netx/net/sourceforge/jnlp/security/VariableX509TrustManager.java b/netx/net/sourceforge/jnlp/security/VariableX509TrustManager.java
index d5ad6da..5e9c981 100644
--- a/netx/net/sourceforge/jnlp/security/VariableX509TrustManager.java
+++ b/netx/net/sourceforge/jnlp/security/VariableX509TrustManager.java
@@ -52,6 +52,8 @@ import sun.security.validator.ValidatorException;
import com.sun.net.ssl.internal.ssl.X509ExtendedTrustManager;
+import net.sourceforge.jnlp.security.SecurityWarning.AccessType;
+
/**
* This class implements an X509 Trust Manager. The certificates it trusts are
* "variable", in the sense that it can dynamically, and temporarily support
@@ -293,8 +295,8 @@ public class VariableX509TrustManager extends X509ExtendedTrustManager {
private boolean askUser(X509Certificate[] chain, String authType,
boolean isTrusted, boolean hostMatched,
String hostName) {
- return SecurityWarningDialog.showCertWarningDialog(
- SecurityWarningDialog.AccessType.UNVERIFIED, null,
+ return SecurityWarning.showCertWarningDialog(
+ AccessType.UNVERIFIED, null,
new HttpsCertVerifier(this, chain, authType,
isTrusted, hostMatched,
hostName));