/hg/icedtea-web: Add support for client authentication certificates

omajid at icedtea.classpath.org omajid at icedtea.classpath.org
Mon Sep 26 08:44:17 PDT 2011


changeset 6e78f0a85d4b in /hg/icedtea-web
details: http://icedtea.classpath.org/hg/icedtea-web?cmd=changeset;node=6e78f0a85d4b
author: Lars Herschke <lhersch at dssgmbh.de>
date: Mon Sep 26 11:43:40 2011 -0400

	Add support for client authentication certificates

	2011-09-26 Lars Herschke <lhersch at dssgmbh.de>

	 * netx/net/sourceforge/jnlp/resources/Messages.properties: Add
	CVExportPasswordMessage, CVImportPasswordMessage and
	CVPasswordTitle.
	    * netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java (initialize):
	Initialize SSLContext with the user's client certificates.
	    * netx/net/sourceforge/jnlp/security/CertificateUtils.java
	(addPKCS12ToKeyStore, addPKCS12ToKeyStore, dumpPKCS12): New methods.
	    * netx/net/sourceforge/jnlp/security/viewer/CertificatePane.java
	(getPasswords): New method.
	(ImportButtonListener.actionPerformed): Import client certificates
	in PKCS12 format. (ExportButtonListener.actionPerformed): Export
	client certificates in PKCS12 format.


diffstat:

 ChangeLog                                                      |  16 +++
 NEWS                                                           |   1 +
 netx/net/sourceforge/jnlp/resources/Messages.properties        |   3 +
 netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java             |   6 +-
 netx/net/sourceforge/jnlp/security/CertificateUtils.java       |  49 ++++++++++
 netx/net/sourceforge/jnlp/security/viewer/CertificatePane.java |  38 ++++++-
 6 files changed, 108 insertions(+), 5 deletions(-)

diffs (227 lines):

diff -r 16c81f4dcf12 -r 6e78f0a85d4b ChangeLog
--- a/ChangeLog	Fri Sep 23 12:05:43 2011 -0400
+++ b/ChangeLog	Mon Sep 26 11:43:40 2011 -0400
@@ -1,3 +1,19 @@
+2011-09-26  Lars Herschke  <lhersch at dssgmbh.de>
+
+	* netx/net/sourceforge/jnlp/resources/Messages.properties: Add
+	CVExportPasswordMessage, CVImportPasswordMessage and
+	CVPasswordTitle.
+	* netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java (initialize):
+	Initialize SSLContext with the user's client certificates.
+	* netx/net/sourceforge/jnlp/security/CertificateUtils.java
+	(addPKCS12ToKeyStore, addPKCS12ToKeyStore, dumpPKCS12): New methods.
+	* netx/net/sourceforge/jnlp/security/viewer/CertificatePane.java
+	(getPasswords): New method.
+	(ImportButtonListener.actionPerformed): Import client certificates
+	in PKCS12 format.
+	(ExportButtonListener.actionPerformed): Export client certificates
+	in PKCS12 format.
+
 2011-09-23  Omair Majid  <omajid at redhat.com>
 
 	RH738814: Access denied at ssl handshake
diff -r 16c81f4dcf12 -r 6e78f0a85d4b NEWS
--- a/NEWS	Fri Sep 23 12:05:43 2011 -0400
+++ b/NEWS	Mon Sep 26 11:43:40 2011 -0400
@@ -27,6 +27,7 @@
   - PR789: typo in jrunscript.sh
   - RH734081: Javaws cannot use proxy settings from Firefox
   - RH738814: Access denied at ssl handshake
+  - Support for authenticating using client certificates
 
 New in release 1.1 (2011-XX-XX):
 * Security updates
diff -r 16c81f4dcf12 -r 6e78f0a85d4b netx/net/sourceforge/jnlp/resources/Messages.properties
--- a/netx/net/sourceforge/jnlp/resources/Messages.properties	Fri Sep 23 12:05:43 2011 -0400
+++ b/netx/net/sourceforge/jnlp/resources/Messages.properties	Mon Sep 26 11:43:40 2011 -0400
@@ -242,9 +242,12 @@
 CVCertificateType=Certificate Type
 CVDetails=Details
 CVExport=Export
+CVExportPasswordMessage=Enter password to protect key file:
 CVImport=Import
+CVImportPasswordMessage=Enter password to access file:
 CVIssuedBy=Issued By
 CVIssuedTo=Issued To
+CVPasswordTitle=Authentication Required
 CVRemove=Remove
 CVRemoveConfirmMessage=Are you sure you want to remove the selected certificate?
 CVRemoveConfirmTitle=Confirmation - Remove Certificate?
diff -r 16c81f4dcf12 -r 6e78f0a85d4b netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java
--- a/netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java	Fri Sep 23 12:05:43 2011 -0400
+++ b/netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java	Mon Sep 26 11:43:40 2011 -0400
@@ -29,6 +29,7 @@
 import javax.jnlp.*;
 import javax.naming.ConfigurationException;
 import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.KeyManagerFactory;
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLSocketFactory;
 import javax.net.ssl.TrustManager;
@@ -225,8 +226,11 @@
         try {
             SSLSocketFactory sslSocketFactory;
             SSLContext context = SSLContext.getInstance("SSL");
+            KeyStore ks = KeyStores.getKeyStore(KeyStores.Level.USER, KeyStores.Type.CLIENT_CERTS);
+            KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
+            kmf.init(ks, KeyStores.getPassword());
             TrustManager[] trust = new TrustManager[] { VariableX509TrustManager.getInstance() };
-            context.init(null, trust, null);
+            context.init(kmf.getKeyManagers(), trust, null);
             sslSocketFactory = context.getSocketFactory();
 
             HttpsURLConnection.setDefaultSSLSocketFactory(sslSocketFactory);
diff -r 16c81f4dcf12 -r 6e78f0a85d4b netx/net/sourceforge/jnlp/security/CertificateUtils.java
--- a/netx/net/sourceforge/jnlp/security/CertificateUtils.java	Fri Sep 23 12:05:43 2011 -0400
+++ b/netx/net/sourceforge/jnlp/security/CertificateUtils.java	Mon Sep 26 11:43:40 2011 -0400
@@ -38,12 +38,15 @@
 package net.sourceforge.jnlp.security;
 
 import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
 import java.io.File;
 import java.io.FileInputStream;
+import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintStream;
 import java.math.BigInteger;
 import java.security.InvalidKeyException;
+import java.security.Key;
 import java.security.KeyStore;
 import java.security.KeyStoreException;
 import java.security.NoSuchAlgorithmException;
@@ -117,6 +120,41 @@
         ks.setCertificateEntry(alias, cert);
     }
 
+    public static void addPKCS12ToKeyStore(File file, KeyStore ks, char[] password)
+            throws Exception {
+        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
+        KeyStore keyStore = KeyStore.getInstance("PKCS12");
+        keyStore.load(bis, password);
+
+        Enumeration<String> aliasList = keyStore.aliases();
+
+        while (aliasList.hasMoreElements()) {
+            String alias = aliasList.nextElement();
+            Certificate[] certChain = keyStore.getCertificateChain(alias);
+            Key key = keyStore.getKey(alias, password);
+            addPKCS12ToKeyStore(certChain, key, ks);
+        }
+    }
+
+    public static void addPKCS12ToKeyStore(Certificate[] certChain, Key key, KeyStore ks)
+            throws KeyStoreException {
+        String alias = null;
+
+        // does this certificate already exist?
+        alias = ks.getCertificateAlias(certChain[0]);
+        if (alias != null) {
+            return;
+        }
+
+        // create a unique alias for this new certificate
+        Random random = new Random();
+        do {
+            alias = new BigInteger(20, random).toString();
+        } while (ks.getCertificate(alias) != null);
+
+        ks.setKeyEntry(alias, key, KeyStores.getPassword(), certChain);
+    }
+
     /**
      * Checks whether an X509Certificate is already in one of the keystores
      * @param c the certificate
@@ -177,4 +215,15 @@
         encoder.encodeBuffer(cert.getEncoded(), out);
         out.println(X509Factory.END_CERT);
     }
+
+    public static void dumpPKCS12(String alias, File file, KeyStore ks, char[] password)
+            throws Exception {
+        Certificate[] certChain = ks.getCertificateChain(alias);
+        Key key = ks.getKey(alias, KeyStores.getPassword());
+        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
+        KeyStore keyStore = KeyStore.getInstance("PKCS12");
+        keyStore.load(null, null);
+        keyStore.setKeyEntry(alias, key, password, certChain);
+        keyStore.store(bos, password);
+    }
 }
diff -r 16c81f4dcf12 -r 6e78f0a85d4b netx/net/sourceforge/jnlp/security/viewer/CertificatePane.java
--- a/netx/net/sourceforge/jnlp/security/viewer/CertificatePane.java	Fri Sep 23 12:05:43 2011 -0400
+++ b/netx/net/sourceforge/jnlp/security/viewer/CertificatePane.java	Mon Sep 26 11:43:40 2011 -0400
@@ -66,6 +66,7 @@
 import javax.swing.JLabel;
 import javax.swing.JOptionPane;
 import javax.swing.JPanel;
+import javax.swing.JPasswordField;
 import javax.swing.JScrollPane;
 import javax.swing.JTabbedPane;
 import javax.swing.JTable;
@@ -100,6 +101,7 @@
             new CertificateType(KeyStores.Type.JSSE_CA_CERTS),
             new CertificateType(KeyStores.Type.CERTS),
             new CertificateType(KeyStores.Type.JSSE_CERTS),
+            new CertificateType(KeyStores.Type.CLIENT_CERTS)
         };
 
     JTabbedPane tabbedPane;
@@ -301,6 +303,18 @@
         }
     }
 
+    private char[] getPassword(final String label) {
+        JPasswordField jpf = new JPasswordField();
+        int result = JOptionPane.showConfirmDialog(parent,
+                                new Object[]{label, jpf},  R("CVPasswordTitle"),
+                                JOptionPane.OK_CANCEL_OPTION,
+                                JOptionPane.INFORMATION_MESSAGE);
+        if (result == JOptionPane.OK_OPTION)
+            return jpf.getPassword();
+        else
+            return null;
+    }
+
     /** Allows storing KeyStores.Types in a JComponent */
     private static class CertificateType {
         private final KeyStores.Type type;
@@ -364,7 +378,17 @@
             if (returnVal == JFileChooser.APPROVE_OPTION) {
                 try {
                     KeyStore ks = keyStore;
-                    CertificateUtils.addToKeyStore(chooser.getSelectedFile(), ks);
+                    if (currentKeyStoreType == KeyStores.Type.CLIENT_CERTS) {
+                        char[] password = getPassword(R("CVImportPasswordMessage"));
+                        if (password != null) {
+                            CertificateUtils.addPKCS12ToKeyStore(
+                                       chooser.getSelectedFile(), ks, password);
+                        } else {
+                            return;
+                        }
+                    } else {
+                        CertificateUtils.addToKeyStore(chooser.getSelectedFile(), ks);
+                    }
                     File keyStoreFile = new File(KeyStores
                                         .getKeyStoreLocation(currentKeyStoreLevel, currentKeyStoreType));
                     if (!keyStoreFile.isFile()) {
@@ -408,9 +432,15 @@
                         String alias = keyStore.getCertificateAlias(certs
                                                         .get(selectedRow));
                         if (alias != null) {
-                            Certificate c = keyStore.getCertificate(alias);
-                            PrintStream ps = new PrintStream(chooser.getSelectedFile().getAbsolutePath());
-                            CertificateUtils.dump(c, ps);
+                            if (currentKeyStoreType == KeyStores.Type.CLIENT_CERTS) {
+                                char[] password = getPassword(R("CVExportPasswordMessage"));
+                                if (password != null)
+                                    CertificateUtils.dumpPKCS12(alias, chooser.getSelectedFile(), keyStore, password);
+                            } else {
+                                Certificate c = keyStore.getCertificate(alias);
+                                PrintStream ps = new PrintStream(chooser.getSelectedFile().getAbsolutePath());
+                                CertificateUtils.dump(c, ps);
+                            }
                             repopulateTables();
                         }
                     }



More information about the distro-pkg-dev mailing list