[icedtea-web] RFC: integrate multiple KeyStore support into CertificateViewer
Andrew Su
asu at redhat.com
Mon Nov 8 12:15:07 PST 2010
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.
> + 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.
> + }
> +
> /**
> * Adds a trusted certificate to the user's keystore.
> * @return true if the add was successful, false otherwise.
Everything else seems okay to me.
Cheers,
Andrew
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.openjdk.java.net/pipermail/distro-pkg-dev/attachments/20101108/44bfe812/attachment.html
More information about the distro-pkg-dev
mailing list