Mercurial > hg > release > icedtea-web-1.6
changeset 297:6e78f0a85d4b
Add support for client authentication certificates
2011-09-26 Lars Herschke <lhersch@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.
author | Lars Herschke <lhersch@dssgmbh.de> |
---|---|
date | Mon, 26 Sep 2011 11:43:40 -0400 |
parents | 16c81f4dcf12 |
children | 477780fe79ae |
files | ChangeLog NEWS netx/net/sourceforge/jnlp/resources/Messages.properties netx/net/sourceforge/jnlp/runtime/JNLPRuntime.java netx/net/sourceforge/jnlp/security/CertificateUtils.java netx/net/sourceforge/jnlp/security/viewer/CertificatePane.java |
diffstat | 6 files changed, 108 insertions(+), 5 deletions(-) [+] |
line wrap: on
line diff
--- 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@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@redhat.com> RH738814: Access denied at ssl handshake
--- 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
--- 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?
--- 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);
--- 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); + } }
--- 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(); } }