[icedtea-web] RFC: integrate multiple KeyStore support into CertificateViewer
Deepak Bhole
dbhole at redhat.com
Mon Nov 8 12:57:58 PST 2010
* Omair Majid <omajid at redhat.com> [2010-11-08 15:36]:
> Hi Andrew,
>
> On 11/08/2010 03:15 PM, Andrew Su wrote:
> >Hi,
> >
> >On 11/04/2010 04:15 PM, Omair Majid wrote:
> >>Hi,
> >>
> >>The attached patch starts integrating some of the security certificate
> >>configuration into Netx.
> >>
> >>It adds a new class KeyStores that is used to access the different
> >>types of KeyStore that Netx supports - per user and per system
> >>variants of trusted CA KeyStore, trusted certificate store, JSSE CA
> >>store, and JSSE certificates store.
> >>
> >>It also fixes up the certificate viewer (javaws -viewer) to use these
> >>multiple certificate stores.
> >>
> >>ChangeLog
> >>2010-11-04 Omair Majid <omajid at redhat.com>
> >>
> >>* 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.
> >>
> >>
> >>Any thoughts or comments?
> >>
> >>Thanks,
> >>Omair
> >>icedtea-web-integrate-configuration-security-files-05.patch
> >>
> >>
> >>diff -r 2405cef22921 netx/net/sourceforge/jnlp/runtime/DeploymentConfiguration.java
> >>--- a/netx/net/sourceforge/jnlp/runtime/DeploymentConfiguration.java Wed Nov 03 23:06:23 2010 +0000
> >>+++ b/netx/net/sourceforge/jnlp/runtime/DeploymentConfiguration.java Thu Nov 04 15:57:40 2010 -0400
> >>@@ -142,6 +142,18 @@
> >> */
> >> 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 @@
> >> { 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 -r 2405cef22921 netx/net/sourceforge/jnlp/security/KeyStores.java
> >>--- /dev/null Thu Jan 01 00:00:00 1970 +0000
> >>+++ b/netx/net/sourceforge/jnlp/security/KeyStores.java Thu Nov 04 15:57:40 2010 -0400
> >>@@ -0,0 +1,300 @@
> >>+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()) {
> >According to mkdirs() some of the parent directories may get created.
> >Maybe clean up if attempt failed.
>
> The problem is that we dont know which directories were created. We
> could keep track of all the parent directories which did not exist
> and try deleting them, but IMHO the cleanup is unnecessary.
>
> >>+ 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 -r 2405cef22921 netx/net/sourceforge/jnlp/security/viewer/CertificatePane.java
> >>--- a/netx/net/sourceforge/jnlp/security/viewer/CertificatePane.java Wed Nov 03 23:06:23 2010 +0000
> >>+++ b/netx/net/sourceforge/jnlp/security/viewer/CertificatePane.java Thu Nov 04 15:57:40 2010 -0400
> >>@@ -44,93 +44,153 @@
> >> 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),
> >>+ };
> >>+
> >>+ 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));
> >>+ 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));
> >>
> >>- JTabbedPane tabbedPane = new JTabbedPane();
> >>- tabbedPane.addTab("User", tablePane);
> >>+ // 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 @@
> >> 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 @@
> >> 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 @@
> >> }
> >> } catch (Exception e) {
> >> //TODO
> >>+ e.printStackTrace();
> >> }
> >> }
> >>
> >>@@ -211,14 +277,16 @@
> >> * 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 @@
> >> }
> >> }
> >>
> >>+ /** 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 @@
> >> 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 @@
> >>
> >> 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 @@
> >> Certificate c = keyStore.getCertificate(alias);
> >> PrintStream ps = new PrintStream(chooser.getSelectedFile().getAbsolutePath());
> >> KeyTool.dumpCert(c, ps);
> >>- repopulateTable();
> >>+ repopulateTables();
> >> }
> >> }
> >> }
> >>@@ -281,6 +416,12 @@
> >> */
> >> 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 @@
> >> 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 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 -r 2405cef22921 netx/net/sourceforge/jnlp/security/viewer/CertificateViewer.java
> >>--- a/netx/net/sourceforge/jnlp/security/viewer/CertificateViewer.java Wed Nov 03 23:06:23 2010 +0000
> >>+++ b/netx/net/sourceforge/jnlp/security/viewer/CertificateViewer.java Thu Nov 04 15:57:40 2010 -0400
> >>@@ -48,6 +48,8 @@
> >> 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 static void showCertificateViewer() throws Exception {
> >>+ JNLPRuntime.initialize(true);
> >> setSystemLookAndFeel();
> >>
> >> CertificateViewer cv = new CertificateViewer();
> >>diff -r 2405cef22921 netx/net/sourceforge/jnlp/tools/KeyTool.java
> >>--- a/netx/net/sourceforge/jnlp/tools/KeyTool.java Wed Nov 03 23:06:23 2010 +0000
> >>+++ b/netx/net/sourceforge/jnlp/tools/KeyTool.java Thu Nov 04 15:57:40 2010 -0400
> >>@@ -32,7 +32,9 @@
> >> 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,47 @@
> >> 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;
> >>+ }
> >>+
> >>+ boolean aliasFound = false;
> >>+ do {
> >>+ alias = new BigInteger(20, random).toString();
> >>+ if (ks.getCertificate(alias) == null) {
> >>+ aliasFound = true;
> >>+ }
> >>+ } while (!aliasFound);
> >>+ ks.setCertificateEntry(alias, cert);
> >aliasFound is a bit confusing for name.
> >
> >this can be changed to:
> >
> >do{
> >alias = new BigInteger(20, random).toString();
> >} while (ks.getCertificate(alias) != null);
> >
> >to avoid using aliasFound.
> >
>
> Fixed.
>
> >>+ }
> >>+
> >> /**
> >> * Adds a trusted certificate to the user's keystore.
> >> * @return true if the add was successful, false otherwise.
> >Everything else seems okay to me.
> >
>
> Thanks for reviewing the patch. Ok to commit?
>
Speaking only for myself and not Andrew, OK from me for HEAD.
Cheers,
Deepak
> Thanks,
> Omair
More information about the distro-pkg-dev
mailing list