diff options
author | Omair Majid <[email protected]> | 2010-11-08 16:36:17 -0500 |
---|---|---|
committer | Omair Majid <[email protected]> | 2010-11-08 16:36:17 -0500 |
commit | fe0ca6144db1e34521813d103fe6d65954ebe10c (patch) | |
tree | c44be19763c573bce8c310c5e77a523c59333c38 /netx/net/sourceforge | |
parent | 66292226de4b8120307cf4a5fd283260963e0e6f (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')
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. |