aboutsummaryrefslogtreecommitdiffstats
path: root/netx/net/sourceforge
diff options
context:
space:
mode:
authorOmair Majid <[email protected]>2010-11-08 16:36:17 -0500
committerOmair Majid <[email protected]>2010-11-08 16:36:17 -0500
commitfe0ca6144db1e34521813d103fe6d65954ebe10c (patch)
treec44be19763c573bce8c310c5e77a523c59333c38 /netx/net/sourceforge
parent66292226de4b8120307cf4a5fd283260963e0e6f (diff)
integrate multiple keystore support into certificate viewer
2010-11-04 Omair Majid <[email protected]> * netx/net/sourceforge/jnlp/runtime/DeploymentConfiguration.java: Add KEY_USER_TRUSTED_CA_CERTS, KEY_USER_TRUSTED_JSSE_CA_CERTS, KEY_USER_TRUSTED_CERTS, KEY_USER_TRUSTED_JSSE_CERTS, KEY_USER_TRUSTED_CLIENT_CERTS, KEY_SYSTEM_TRUSTED_CA_CERTS, KEY_SYSTEM_TRUSTED_JSSE_CA_CERTS, KEY_SYSTEM_TRUSTED_CERTS, KEY_SYSTEM_TRUSTED_JSSE_CERTS, KEY_SYSTEM_TRUSTED_CLIENT_CERTS (loadDefaultProperties): Use the defined constants. * netx/net/sourceforge/jnlp/security/KeyStores.java: New class. (getPassword): New method. Return the default password used for KeyStores. (getKeyStore(Level,Type)): New method. Returns the appropriate KeyStore. (getKeyStore(Level,Type,String)): Likewise. (getCertKeyStores): New method. Return all the trusted certificate KeyStores. (getCAKeyStores): New method. Return all the trusted CA certificate KeyStores. (getKeyStoreLocation): New method. Return the location of the appropriate KeyStore. (toTranslatableString): New method. Return a string that can be used to create a human-readable name for the KeyStore. (toDisplayableString): New method. Return a human-readable name for the KeyStore. (createKeyStoreFromFile): New method. Creates a new KeyStore object, initializing it from the given file if possible. * netx/net/sourceforge/jnlp/security/viewer/CertificatePane.java (CertificatePane): Create two JTables. Populate the tables when done creating the user interface. (initializeKeyStore): Use the correct keystore. (addComponents): Do not read KeyStore. Create more interface elements to show the new possible KeyStores. Mark some buttons to be disabled when needed. (repopulateTable): Renamed to... (repopulateTables): New method. Read KeyStore and use the contents to create the user and system tables. (CertificateType): New class. (CertificateTypeListener): New class. Listens to JComboBox change events. (TabChangeListener): New class. Listens to new tab selections. (ImportButtonListener): Import certificates to the appropriate KeyStore. (ExportButtonListener): Find the certificate from the right table. (RemoveButtonListener): Find the certificate from the right table and right the KeyStore. (DetailsButtonListener): Find the certificate from the right table. * netx/net/sourceforge/jnlp/security/viewer/CertificateViewer.java (showCertficaiteViewer): Initialize the JNLPRuntime so the configuration gets loaded. * netx/net/sourceforge/jnlp/tools/KeyTool.java (addToKeyStore(File,KeyStore)): New method. Adds certificate from the file to the KeyStore. (addToKeyStore(X509Certificate,KeyStore)): New method. Adds a certificate to a KeyStore.
Diffstat (limited to 'netx/net/sourceforge')
-rw-r--r--netx/net/sourceforge/jnlp/runtime/DeploymentConfiguration.java32
-rw-r--r--netx/net/sourceforge/jnlp/security/KeyStores.java337
-rw-r--r--netx/net/sourceforge/jnlp/security/viewer/CertificatePane.java214
-rw-r--r--netx/net/sourceforge/jnlp/security/viewer/CertificateViewer.java3
-rw-r--r--netx/net/sourceforge/jnlp/tools/KeyTool.java39
5 files changed, 582 insertions, 43 deletions
diff --git a/netx/net/sourceforge/jnlp/runtime/DeploymentConfiguration.java b/netx/net/sourceforge/jnlp/runtime/DeploymentConfiguration.java
index 2ad3619..f2217ee 100644
--- a/netx/net/sourceforge/jnlp/runtime/DeploymentConfiguration.java
+++ b/netx/net/sourceforge/jnlp/runtime/DeploymentConfiguration.java
@@ -142,6 +142,18 @@ public final class DeploymentConfiguration {
*/
public static final String KEY_USER_NETX_RUNNING_FILE = "deployment.user.runningfile";
+ public static final String KEY_USER_TRUSTED_CA_CERTS = "deployment.user.security.trusted.cacerts";
+ public static final String KEY_USER_TRUSTED_JSSE_CA_CERTS = "deployment.user.security.trusted.jssecacerts";
+ public static final String KEY_USER_TRUSTED_CERTS = "deployment.user.security.trusted.certs";
+ public static final String KEY_USER_TRUSTED_JSSE_CERTS = "deployment.user.security.trusted.jssecerts";
+ public static final String KEY_USER_TRUSTED_CLIENT_CERTS = "deployment.user.security.trusted.clientauthcerts";
+
+ public static final String KEY_SYSTEM_TRUSTED_CA_CERTS = "deployment.system.security.cacerts";
+ public static final String KEY_SYSTEM_TRUSTED_JSSE_CA_CERTS = "deployment.system.security.jssecacerts";
+ public static final String KEY_SYSTEM_TRUSTED_CERTS = "deployment.system.security.trusted.certs";
+ public static final String KEY_SYSTEM_TRUSTED_JSSE_CERTS = "deployment.system.security.trusted.jssecerts";
+ public static final String KEY_SYSTEM_TRUSTED_CLIENT_CERTS = "deployment.system.security.trusted.clientautcerts";
+
public enum ConfigType {
System, User
}
@@ -315,17 +327,17 @@ public final class DeploymentConfiguration {
{ KEY_USER_NETX_RUNNING_FILE, LOCKS_DIR + File.separator + "netx_running" },
/* certificates and policy files */
{ "deployment.user.security.policy", "file://" + USER_SECURITY + File.separator + "java.policy" },
- { "deployment.user.security.trusted.cacerts", USER_SECURITY + File.separator + "trusted.cacerts" },
- { "deployment.user.security.trusted.jssecacerts", USER_SECURITY + File.separator + "trusted.jssecacerts" },
- { "deployment.user.security.trusted.certs", USER_SECURITY + File.separator + "trusted.certs" },
- { "deployment.user.security.trusted.jssecerts", USER_SECURITY + File.separator + "trusted.jssecerts"},
- { "deployment.user.security.trusted.clientauthcerts", USER_SECURITY + File.separator + "trusted.clientcerts" },
+ { KEY_USER_TRUSTED_CA_CERTS, USER_SECURITY + File.separator + "trusted.cacerts" },
+ { KEY_USER_TRUSTED_JSSE_CA_CERTS, USER_SECURITY + File.separator + "trusted.jssecacerts" },
+ { KEY_USER_TRUSTED_CERTS, USER_SECURITY + File.separator + "trusted.certs" },
+ { KEY_USER_TRUSTED_JSSE_CERTS, USER_SECURITY + File.separator + "trusted.jssecerts"},
+ { KEY_USER_TRUSTED_CLIENT_CERTS, USER_SECURITY + File.separator + "trusted.clientcerts" },
{ "deployment.system.security.policy", null },
- { "deployment.system.security.cacerts", SYSTEM_SECURITY + File.separator + "cacerts" },
- { "deployment.system.security.jssecacerts", SYSTEM_SECURITY + File.separator + "jssecacerts" },
- { "deployment.system.security.trusted.certs", SYSTEM_SECURITY + File.separator + "trusted.certs" },
- { "deployment.system.security.trusted.jssecerts", SYSTEM_SECURITY + File.separator + "trusted.jssecerts" },
- { "deployment.system.security.trusted.clientautcerts", SYSTEM_SECURITY + File.separator + "trusted.clientcerts" },
+ { KEY_SYSTEM_TRUSTED_CA_CERTS , SYSTEM_SECURITY + File.separator + "cacerts" },
+ { KEY_SYSTEM_TRUSTED_JSSE_CA_CERTS, SYSTEM_SECURITY + File.separator + "jssecacerts" },
+ { KEY_SYSTEM_TRUSTED_CERTS, SYSTEM_SECURITY + File.separator + "trusted.certs" },
+ { KEY_SYSTEM_TRUSTED_JSSE_CERTS, SYSTEM_SECURITY + File.separator + "trusted.jssecerts" },
+ { KEY_SYSTEM_TRUSTED_CLIENT_CERTS, SYSTEM_SECURITY + File.separator + "trusted.clientcerts" },
/* security access and control */
{ "deployment.security.askgrantdialog.show", String.valueOf(true) },
{ "deployment.security.askgrantdialog.notinca", String.valueOf(true) },
diff --git a/netx/net/sourceforge/jnlp/security/KeyStores.java b/netx/net/sourceforge/jnlp/security/KeyStores.java
new file mode 100644
index 0000000..4c7a60a
--- /dev/null
+++ b/netx/net/sourceforge/jnlp/security/KeyStores.java
@@ -0,0 +1,337 @@
+/* KeyStores.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.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import net.sourceforge.jnlp.runtime.DeploymentConfiguration;
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
+import net.sourceforge.jnlp.runtime.Translator;
+
+/**
+ * The <code>KeyStores</code> class allows easily accessing the various KeyStores
+ * used.
+ */
+public final class KeyStores {
+
+ /* this gets turned into user-readable strings, see toUserReadableString */
+
+ public enum Level {
+ USER,
+ SYSTEM,
+ }
+
+ public enum Type {
+ CERTS,
+ JSSE_CERTS,
+ CA_CERTS,
+ JSSE_CA_CERTS,
+ CLIENT_CERTS,
+ }
+
+ private static final String KEYSTORE_TYPE = "JKS";
+ /** the default password used to protect the KeyStores */
+ private static final String DEFAULT_PASSWORD = "changeit";
+
+ public static final char[] getPassword() {
+ return DEFAULT_PASSWORD.toCharArray();
+ }
+
+ /**
+ * Returns a KeyStore corresponding to the appropriate level level (user or
+ * system) and type.
+ *
+ * @param level whether the KeyStore desired is a user-level or system-level
+ * KeyStore
+ * @param type the type of KeyStore desired
+ * @return a KeyStore containing certificates from the appropriate
+ */
+ public static final KeyStore getKeyStore(Level level, Type type) {
+ boolean create = false;
+ if (level == Level.USER) {
+ create = true;
+ } else {
+ create = false;
+ }
+ return getKeyStore(level, type, create);
+ }
+
+ /**
+ * Returns a KeyStore corresponding to the appropriate level level (user or
+ * system) and type.
+ *
+ * @param level whether the KeyStore desired is a user-level or system-level
+ * KeyStore
+ * @param type the type of KeyStore desired
+ * @return a KeyStore containing certificates from the appropriate
+ */
+ public static final KeyStore getKeyStore(Level level, Type type, boolean create) {
+ String location = getKeyStoreLocation(level, type);
+ KeyStore ks = null;
+ try {
+ ks = createKeyStoreFromFile(new File(location), create, DEFAULT_PASSWORD);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return ks;
+ }
+
+ /**
+ * Returns an array of KeyStore that contain certificates that are trusted.
+ * The KeyStores contain certificates from different sources.
+ *
+ * @return an array of KeyStore containing trusted Certificates
+ */
+ public static final KeyStore[] getCertKeyStores() {
+ List<KeyStore> result = new ArrayList<KeyStore>(10);
+ KeyStore ks = null;
+
+ /* System-level JSSE certificates */
+ ks = getKeyStore(Level.SYSTEM, Type.JSSE_CERTS);
+ if (ks != null) {
+ result.add(ks);
+ }
+ /* System-level certificates */
+ ks = getKeyStore(Level.SYSTEM, Type.CERTS);
+ if (ks != null) {
+ result.add(ks);
+ }
+ /* User-level JSSE certificates */
+ ks = getKeyStore(Level.USER, Type.JSSE_CERTS);
+ if (ks != null) {
+ result.add(ks);
+ }
+ /* User-level certificates */
+ ks = getKeyStore(Level.USER, Type.CERTS);
+ if (ks != null) {
+ result.add(ks);
+ }
+
+ return result.toArray(new KeyStore[result.size()]);
+ }
+
+ /**
+ * Returns an array of KeyStore that contain trusted CA certificates.
+ *
+ * @return an array of KeyStore containing trusted CA certificates
+ */
+ public static final KeyStore[] getCAKeyStores() {
+ List<KeyStore> result = new ArrayList<KeyStore>(10);
+ KeyStore ks = null;
+
+ /* System-level JSSE CA certificates */
+ ks = getKeyStore(Level.SYSTEM, Type.JSSE_CA_CERTS);
+ if (ks != null) {
+ result.add(ks);
+ }
+ /* System-level CA certificates */
+ ks = getKeyStore(Level.SYSTEM, Type.CA_CERTS);
+ if (ks != null) {
+ result.add(ks);
+ }
+ /* User-level JSSE CA certificates */
+ ks = getKeyStore(Level.USER, Type.JSSE_CA_CERTS);
+ if (ks != null) {
+ result.add(ks);
+ }
+ /* User-level CA certificates */
+ ks = getKeyStore(Level.USER, Type.CA_CERTS);
+ if (ks != null) {
+ result.add(ks);
+ }
+
+ return result.toArray(new KeyStore[result.size()]);
+ }
+
+ /**
+ * Returns the location of a KeyStore corresponding to the given level and type.
+ * @param level
+ * @param type
+ * @return
+ */
+ public static final String getKeyStoreLocation(Level level, Type type) {
+ String configKey = null;
+ switch (level) {
+ case SYSTEM:
+ switch (type) {
+ case JSSE_CA_CERTS:
+ configKey = DeploymentConfiguration.KEY_SYSTEM_TRUSTED_JSSE_CA_CERTS;
+ break;
+ case CA_CERTS:
+ configKey = DeploymentConfiguration.KEY_SYSTEM_TRUSTED_CA_CERTS;
+ break;
+ case JSSE_CERTS:
+ configKey = DeploymentConfiguration.KEY_SYSTEM_TRUSTED_JSSE_CERTS;
+ break;
+ case CERTS:
+ configKey = DeploymentConfiguration.KEY_SYSTEM_TRUSTED_CERTS;
+ break;
+ case CLIENT_CERTS:
+ configKey = DeploymentConfiguration.KEY_SYSTEM_TRUSTED_CLIENT_CERTS;
+ break;
+ }
+ break;
+ case USER:
+ switch (type) {
+ case JSSE_CA_CERTS:
+ configKey = DeploymentConfiguration.KEY_USER_TRUSTED_JSSE_CA_CERTS;
+ break;
+ case CA_CERTS:
+ configKey = DeploymentConfiguration.KEY_USER_TRUSTED_CA_CERTS;
+ break;
+ case JSSE_CERTS:
+ configKey = DeploymentConfiguration.KEY_USER_TRUSTED_JSSE_CERTS;
+ break;
+ case CERTS:
+ configKey = DeploymentConfiguration.KEY_USER_TRUSTED_CERTS;
+ break;
+ case CLIENT_CERTS:
+ configKey = DeploymentConfiguration.KEY_SYSTEM_TRUSTED_CLIENT_CERTS;
+ break;
+ }
+ break;
+ }
+
+ if (configKey == null) {
+ throw new RuntimeException("Unspported");
+ }
+
+ return JNLPRuntime.getConfiguration().getProperty(configKey);
+ }
+
+ /**
+ * Returns a String that can be used as a translation key to create a
+ * user-visible representation of this KeyStore. Creates a string by
+ * concatenating a level and type, converting everything to Title Case and
+ * removing the _'s. (USER,CA_CERTS) becomes UserCaCerts.
+ *
+ * @param level
+ * @param type
+ * @return
+ */
+ public static final String toTranslatableString(Level level, Type type) {
+ StringBuilder response = new StringBuilder();
+
+ if (level != null) {
+ String levelString = level.toString();
+ response.append(levelString.substring(0, 1).toUpperCase());
+ response.append(levelString.substring(1).toLowerCase());
+ }
+
+ if (type != null) {
+ String typeString = type.toString();
+ StringTokenizer tokenizer = new StringTokenizer(typeString, "_");
+ while (tokenizer.hasMoreTokens()) {
+ String token = tokenizer.nextToken();
+ response.append(token.substring(0, 1).toUpperCase());
+ response.append(token.substring(1).toLowerCase());
+ }
+ }
+
+ return response.toString();
+ }
+
+ /**
+ * Returns a human readable name for this KeyStore
+ *
+ * @param level the level of the KeyStore
+ * @param type the type of KeyStore
+ * @return a localized name for this KeyStore
+ */
+ public static String toDisplayableString(Level level, Type type) {
+ return Translator.R(toTranslatableString(level, type));
+ }
+
+ /**
+ * Reads the file (using the password) and uses it to create a new
+ * {@link KeyStore}. If the file does not exist and should not be created,
+ * it returns an empty but initialized KeyStore
+ *
+ * @param file the file to load information from
+ * @param password the password to unlock the KeyStore file.
+ * @return a KeyStore containing data from the file
+ */
+ private static final KeyStore createKeyStoreFromFile(File file, boolean createIfNotFound,
+ String password) throws IOException, KeyStoreException, NoSuchAlgorithmException,
+ CertificateException {
+ FileInputStream fis = null;
+ KeyStore ks = null;
+
+ try {
+ if (createIfNotFound && !file.exists()) {
+ File parent = file.getParentFile();
+ if (!parent.isDirectory() && !parent.mkdirs()) {
+ throw new IOException("unable to create " + parent);
+ }
+ ks = KeyStore.getInstance(KEYSTORE_TYPE);
+ ks.load(null, password.toCharArray());
+ FileOutputStream fos = new FileOutputStream(file);
+ ks.store(fos, password.toCharArray());
+ fos.close();
+ }
+
+ // TODO catch exception when password is incorrect and prompt user
+
+ if (file.exists()) {
+ fis = new FileInputStream(file);
+ ks = KeyStore.getInstance(KEYSTORE_TYPE);
+ ks.load(fis, password.toCharArray());
+ } else {
+ ks = KeyStore.getInstance(KEYSTORE_TYPE);
+ ks.load(null, password.toCharArray());
+ }
+ } finally {
+ if (fis != null) {
+ fis.close();
+ }
+ }
+
+ return ks;
+ }
+
+}
diff --git a/netx/net/sourceforge/jnlp/security/viewer/CertificatePane.java b/netx/net/sourceforge/jnlp/security/viewer/CertificatePane.java
index 69b98b4..0bb01f4 100644
--- a/netx/net/sourceforge/jnlp/security/viewer/CertificatePane.java
+++ b/netx/net/sourceforge/jnlp/security/viewer/CertificatePane.java
@@ -44,93 +44,153 @@ import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.FileOutputStream;
+import java.io.OutputStream;
import java.io.PrintStream;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Enumeration;
+import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.JButton;
+import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
+import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
import javax.swing.table.DefaultTableModel;
+import net.sourceforge.jnlp.security.KeyStores;
import net.sourceforge.jnlp.security.SecurityUtil;
import net.sourceforge.jnlp.security.SecurityWarningDialog;
+import net.sourceforge.jnlp.security.KeyStores.Level;
import net.sourceforge.jnlp.tools.KeyTool;
public class CertificatePane extends JPanel {
/**
- * The certificates stored in the user's trusted.certs file.
+ * The certificates stored in the certificates file.
*/
private ArrayList<X509Certificate> certs = null;
+ private static final Dimension TABLE_DIMENSION = new Dimension(500,200);
+
/**
* "Issued To" and "Issued By" string pairs for certs.
*/
private String[][] issuedToAndBy = null;
private final String[] columnNames = { "Issued To", "Issued By" };
- private JTable table;
+ private final CertificateType[] certificateTypes = new CertificateType[] {
+ new CertificateType(KeyStores.Type.CA_CERTS),
+ new CertificateType(KeyStores.Type.JSSE_CA_CERTS),
+ new CertificateType(KeyStores.Type.CERTS),
+ new CertificateType(KeyStores.Type.JSSE_CERTS),
+ };
- private JDialog parent;
+ JTabbedPane tabbedPane;
+ private final JTable userTable;
+ private final JTable systemTable;
+ private JComboBox certificateTypeCombo;
+ private KeyStores.Type currentKeyStoreType;
+ private KeyStores.Level currentKeyStoreLevel;
+
+ /** JComponents that should be disbled for system store */
+ private final List<JComponent> disableForSystem;
+ private JDialog parent;
private JComponent defaultFocusComponent = null;
/**
- * The KeyStore associated with the user's trusted.certs file.
+ * The Current KeyStore. Only one table/tab is visible for interaction to
+ * the user. This KeyStore corresponds to that.
*/
private KeyStore keyStore = null;
public CertificatePane(JDialog parent) {
super();
this.parent = parent;
- initializeKeyStore();
+
+ userTable = new JTable(null);
+ systemTable = new JTable(null);
+ disableForSystem = new ArrayList<JComponent>();
+
addComponents();
+
+ currentKeyStoreType = ((CertificateType)(certificateTypeCombo.getSelectedItem())).getType();
+ if (tabbedPane.getSelectedIndex() == 0) {
+ currentKeyStoreLevel = Level.USER;
+ } else {
+ currentKeyStoreLevel = Level.SYSTEM;
+ }
+
+ repopulateTables();
}
/**
* Reads the user's trusted.cacerts keystore.
*/
private void initializeKeyStore() {
- try {
- keyStore = SecurityUtil.getUserKeyStore();
- } catch (Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
+ try {
+ keyStore = KeyStores.getKeyStore(currentKeyStoreLevel, currentKeyStoreType);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
}
//create the GUI here.
protected void addComponents() {
- readKeyStore();
JPanel main = new JPanel(new BorderLayout());
+ JPanel certificateTypePanel = new JPanel(new BorderLayout());
+ certificateTypePanel.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
+
+ JLabel certificateTypeLabel = new JLabel("Certificate Type:");
+
+ certificateTypeCombo = new JComboBox(certificateTypes);
+ certificateTypeCombo.addActionListener(new CertificateTypeListener());
+
+ certificateTypePanel.add(certificateTypeLabel, BorderLayout.LINE_START);
+ certificateTypePanel.add(certificateTypeCombo, BorderLayout.CENTER);
+
JPanel tablePanel = new JPanel(new BorderLayout());
- //Table
- DefaultTableModel tableModel
+ // User Table
+ DefaultTableModel userTableModel
= new DefaultTableModel(issuedToAndBy, columnNames);
- table = new JTable(tableModel);
- table.getTableHeader().setReorderingAllowed(false);
- table.setFillsViewportHeight(true);
- JScrollPane tablePane = new JScrollPane(table);
- tablePane.setPreferredSize(new Dimension(500,200));
- tablePane.setSize(new Dimension(500,200));
- tablePane.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
-
- JTabbedPane tabbedPane = new JTabbedPane();
- tabbedPane.addTab("User", tablePane);
+ userTable.setModel(userTableModel);
+ userTable.getTableHeader().setReorderingAllowed(false);
+ userTable.setFillsViewportHeight(true);
+ JScrollPane userTablePane = new JScrollPane(userTable);
+ userTablePane.setPreferredSize(TABLE_DIMENSION);
+ userTablePane.setSize(TABLE_DIMENSION);
+ userTablePane.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
+
+ // System Table
+ DefaultTableModel systemTableModel = new DefaultTableModel(issuedToAndBy, columnNames);
+ systemTable.setModel(systemTableModel);
+ systemTable.getTableHeader().setReorderingAllowed(false);
+ systemTable.setFillsViewportHeight(true);
+ JScrollPane systemTablePane = new JScrollPane(systemTable);
+ systemTablePane.setPreferredSize(TABLE_DIMENSION);
+ systemTablePane.setSize(TABLE_DIMENSION);
+ systemTablePane.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
+
+ tabbedPane = new JTabbedPane();
+ tabbedPane.addTab("User", userTablePane);
+ tabbedPane.addTab("System", systemTablePane);
+ tabbedPane.addChangeListener(new TabChangeListener());
+
JPanel buttonPanel = new JPanel(new FlowLayout());
String[] buttonNames = {"Import", "Export", "Remove", "Details"};
@@ -156,6 +216,10 @@ public class CertificatePane extends JPanel {
button.setMnemonic(buttonMnemonics[i]);
button.addActionListener(listeners[i]);
button.setSize(maxWidth, button.getSize().height);
+ // import and remove buttons
+ if (i == 0 || i == 2) {
+ disableForSystem.add(button);
+ }
buttonPanel.add(button);
}
@@ -169,6 +233,7 @@ public class CertificatePane extends JPanel {
defaultFocusComponent = closeButton;
closePanel.add(closeButton, BorderLayout.EAST);
+ main.add(certificateTypePanel, BorderLayout.NORTH);
main.add(tablePanel, BorderLayout.CENTER);
main.add(closePanel, BorderLayout.SOUTH);
@@ -204,6 +269,7 @@ public class CertificatePane extends JPanel {
}
} catch (Exception e) {
//TODO
+ e.printStackTrace();
}
}
@@ -211,14 +277,16 @@ public class CertificatePane extends JPanel {
* Re-reads the certs file and repopulates the JTable. This is typically
* called after a certificate was deleted from the keystore.
*/
- private void repopulateTable() {
+ private void repopulateTables() {
initializeKeyStore();
readKeyStore();
DefaultTableModel tableModel
= new DefaultTableModel(issuedToAndBy, columnNames);
- table.setModel(tableModel);
- repaint();
+ userTable.setModel(tableModel);
+
+ tableModel = new DefaultTableModel(issuedToAndBy, columnNames);
+ systemTable.setModel(tableModel);
}
public void focusOnDefaultButton() {
@@ -227,6 +295,61 @@ public class CertificatePane extends JPanel {
}
}
+ /** Allows storing KeyStores.Types in a JComponent */
+ private class CertificateType {
+ private final KeyStores.Type type;
+
+ public CertificateType(KeyStores.Type type) {
+ this.type = type;
+ }
+
+ public KeyStores.Type getType() {
+ return type;
+ }
+
+ public String toString() {
+ return KeyStores.toTranslatableString(null, type);
+ }
+ }
+
+ /** Invoked when a user selects a different certificate type */
+ private class CertificateTypeListener implements ActionListener {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ JComboBox source = (JComboBox) e.getSource();
+ CertificateType type = (CertificateType) source.getSelectedItem();
+ currentKeyStoreType = type.getType();
+ repopulateTables();
+ }
+ }
+
+ /**
+ * Invoked when a user selects a different tab (switches from user to system
+ * or vice versa). Changes the currentKeyStore Enables or disables buttons.
+ */
+ private class TabChangeListener implements ChangeListener {
+ @Override
+ public void stateChanged(ChangeEvent e) {
+ JTabbedPane source = (JTabbedPane) e.getSource();
+ switch (source.getSelectedIndex()) {
+ case 0:
+ currentKeyStoreLevel = Level.USER;
+ for (JComponent component : disableForSystem) {
+ component.setEnabled(true);
+ }
+ break;
+ case 1:
+ currentKeyStoreLevel = Level.SYSTEM;
+ for (JComponent component : disableForSystem) {
+ component.setEnabled(false);
+ }
+ break;
+ }
+ repopulateTables();
+
+ }
+ }
+
private class ImportButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
@@ -235,8 +358,12 @@ public class CertificatePane extends JPanel {
if(returnVal == JFileChooser.APPROVE_OPTION) {
try {
KeyTool kt = new KeyTool();
- kt.importCert(chooser.getSelectedFile());
- repopulateTable();
+ KeyStore ks = keyStore;
+ kt.addToKeyStore(chooser.getSelectedFile(), ks);
+ OutputStream os = new FileOutputStream(
+ KeyStores.getKeyStoreLocation(currentKeyStoreLevel, currentKeyStoreType));
+ ks.store(os, KeyStores.getPassword());
+ repopulateTables();
} catch (Exception ex) {
// TODO: handle exception
ex.printStackTrace();
@@ -247,6 +374,14 @@ public class CertificatePane extends JPanel {
private class ExportButtonListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
+
+ JTable table = null;
+ if (currentKeyStoreLevel == Level.USER) {
+ table = userTable;
+ } else {
+ table = systemTable;
+ }
+
//For now, let's just export in -rfc mode as keytool does.
//we'll write to a file the exported certificate.
@@ -263,7 +398,7 @@ public class CertificatePane extends JPanel {
Certificate c = keyStore.getCertificate(alias);
PrintStream ps = new PrintStream(chooser.getSelectedFile().getAbsolutePath());
KeyTool.dumpCert(c, ps);
- repopulateTable();
+ repopulateTables();
}
}
}
@@ -281,6 +416,12 @@ public class CertificatePane extends JPanel {
*/
public void actionPerformed(ActionEvent e) {
+ JTable table = null;
+ if (currentKeyStoreLevel == Level.USER) {
+ table = userTable;
+ } else {
+ table = systemTable;
+ }
try {
int selectedRow = table.getSelectedRow();
@@ -295,12 +436,12 @@ public class CertificatePane extends JPanel {
if (i == 0) {
keyStore.deleteEntry(alias);
FileOutputStream fos = new FileOutputStream(
- SecurityUtil.getTrustedCertsFilename());
- keyStore.store(fos, SecurityUtil.getTrustedCertsPassword());
+ KeyStores.getKeyStoreLocation(currentKeyStoreLevel, currentKeyStoreType));
+ keyStore.store(fos, KeyStores.getPassword());
fos.close();
}
}
- repopulateTable();
+ repopulateTables();
}
} catch (Exception ex) {
// TODO
@@ -317,6 +458,13 @@ public class CertificatePane extends JPanel {
*/
public void actionPerformed(ActionEvent e) {
+ JTable table = null;
+ if (currentKeyStoreLevel == Level.USER) {
+ table = userTable;
+ } else {
+ table = systemTable;
+ }
+
int selectedRow = table.getSelectedRow();
if (selectedRow != -1 && selectedRow >= 0) {
X509Certificate c = certs.get(selectedRow);
diff --git a/netx/net/sourceforge/jnlp/security/viewer/CertificateViewer.java b/netx/net/sourceforge/jnlp/security/viewer/CertificateViewer.java
index 403472c..c7135f1 100644
--- a/netx/net/sourceforge/jnlp/security/viewer/CertificateViewer.java
+++ b/netx/net/sourceforge/jnlp/security/viewer/CertificateViewer.java
@@ -48,6 +48,8 @@ import java.awt.event.WindowEvent;
import javax.swing.JDialog;
import javax.swing.UIManager;
+import net.sourceforge.jnlp.runtime.JNLPRuntime;
+
public class CertificateViewer extends JDialog {
private boolean initialized = false;
@@ -97,6 +99,7 @@ public class CertificateViewer extends JDialog {
public static void showCertificateViewer() throws Exception {
+ JNLPRuntime.initialize(true);
setSystemLookAndFeel();
CertificateViewer cv = new CertificateViewer();
diff --git a/netx/net/sourceforge/jnlp/tools/KeyTool.java b/netx/net/sourceforge/jnlp/tools/KeyTool.java
index f7780c4..2e4a0a1 100644
--- a/netx/net/sourceforge/jnlp/tools/KeyTool.java
+++ b/netx/net/sourceforge/jnlp/tools/KeyTool.java
@@ -32,7 +32,9 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
+import java.math.BigInteger;
import java.security.KeyStore;
+import java.security.KeyStoreException;
import java.security.MessageDigest;
import java.security.PublicKey;
import java.security.cert.Certificate;
@@ -117,6 +119,43 @@ public class KeyTool {
return importCert((Certificate)cert);
}
+ /**
+ * Adds the X509Certficate in the file to the KeyStore
+ */
+ public final void addToKeyStore(File file, KeyStore ks) throws CertificateException,
+ IOException, KeyStoreException {
+ BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
+ CertificateFactory cf = CertificateFactory.getInstance("X509");
+ X509Certificate cert = null;
+
+ try {
+ cert = (X509Certificate) cf.generateCertificate(bis);
+ } catch (ClassCastException cce) {
+ throw new CertificateException("Input file is not an X509 Certificate", cce);
+ }
+
+ addToKeyStore(cert, ks);
+
+ }
+
+ /**
+ * Adds an X509Certificate to the KeyStore
+ */
+ public final void addToKeyStore(X509Certificate cert, KeyStore ks) throws KeyStoreException {
+ String alias = null;
+ Random random = new Random();
+ alias = ks.getCertificateAlias(cert);
+ // already in keystore; done
+ if (alias != null) {
+ return;
+ }
+
+ do {
+ alias = new BigInteger(20, random).toString();
+ } while (ks.getCertificate(alias) != null);
+ ks.setCertificateEntry(alias, cert);
+ }
+
/**
* Adds a trusted certificate to the user's keystore.
* @return true if the add was successful, false otherwise.