SSL : Download certificate chain from a remote host and add the certificates to a local keystore
// /*
// * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved.
// *
// * Redistribution and use in source and binary forms, with or without
// * modification, are permitted provided that the following conditions
// * are met:
// *
// * - Redistributions of source code must retain the above copyright
// * notice, this list of conditions and the following disclaimer.
// *
// * - Redistributions in binary form must reproduce the above copyright
// * notice, this list of conditions and the following disclaimer in the
// * documentation and/or other materials provided with the distribution.
// *
// * - Neither the name of Sun Microsystems nor the names of its
// * contributors may be used to endorse or promote products derived
// * from this software without specific prior written permission.
// *
// * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
// * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// */
1 2 import java.io.*; 3 import java.net.URL; 4 5 import java.security.*; 6 import java.security.cert.*; 7 8 import javax.net.ssl.*; 9 10 public class InstallCert { 11 12 public static void main(String[] args) throws Exception { 13 String host; 14 int port; 15 char[] passphrase; 16 if ((args.length == 1) || (args.length == 2)) { 17 String[] c = args[0].split(":"); 18 host = c[0]; 19 port = (c.length == 1) ? 443 : Integer.parseInt(c[1]); 20 String p = (args.length == 1) ? "changeit" : args[1]; 21 passphrase = p.toCharArray(); 22 } else { 23 System.out.println("Usage: java InstallCert <host>[:port] [passphrase]"); 24 return; 25 } 26 27 File file = new File("jssecacerts"); 28 if (file.isFile() == false) { 29 char SEP = File.separatorChar; 30 File dir = new File(System.getProperty("java.home") + SEP 31 + "lib" + SEP + "security"); 32 file = new File(dir, "jssecacerts"); 33 if (file.isFile() == false) { 34 file = new File(dir, "cacerts"); 35 } 36 } 37 System.out.println("Loading KeyStore " + file + "..."); 38 InputStream in = new FileInputStream(file); 39 KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); 40 ks.load(in, passphrase); 41 in.close(); 42 43 SSLContext context = SSLContext.getInstance("TLS"); 44 TrustManagerFactory tmf = 45 TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); 46 tmf.init(ks); 47 X509TrustManager defaultTrustManager = (X509TrustManager)tmf.getTrustManagers()[0]; 48 SavingTrustManager tm = new SavingTrustManager(defaultTrustManager); 49 context.init(null, new TrustManager[] {tm}, null); 50 SSLSocketFactory factory = context.getSocketFactory(); 51 52 System.out.println("Opening connection to " + host + ":" + port + "..."); 53 SSLSocket socket = (SSLSocket)factory.createSocket(host, port); 54 socket.setSoTimeout(10000); 55 try { 56 System.out.println("Starting SSL handshake..."); 57 socket.startHandshake(); 58 socket.close(); 59 System.out.println(); 60 System.out.println("No errors, certificate is already trusted"); 61 } catch (SSLException e) { 62 System.out.println(); 63 e.printStackTrace(System.out); 64 } 65 66 X509Certificate[] chain = tm.chain; 67 if (chain == null) { 68 System.out.println("Could not obtain server certificate chain"); 69 return; 70 } 71 72 BufferedReader reader = 73 new BufferedReader(new InputStreamReader(System.in)); 74 75 System.out.println(); 76 System.out.println("Server sent " + chain.length + " certificate(s):"); 77 System.out.println(); 78 MessageDigest sha1 = MessageDigest.getInstance("SHA1"); 79 MessageDigest md5 = MessageDigest.getInstance("MD5"); 80 for (int i = 0; i < chain.length; i++) { 81 X509Certificate cert = chain[i]; 82 System.out.println 83 (" " + (i + 1) + " Subject " + cert.getSubjectDN()); 84 System.out.println(" Issuer " + cert.getIssuerDN()); 85 sha1.update(cert.getEncoded()); 86 System.out.println(" sha1 " + toHexString(sha1.digest())); 87 md5.update(cert.getEncoded()); 88 System.out.println(" md5 " + toHexString(md5.digest())); 89 System.out.println(); 90 } 91 92 System.out.println("Enter certificate to add to trusted keystore or 'q' to quit: [1]"); 93 String line = reader.readLine().trim(); 94 int k; 95 try { 96 k = (line.length() == 0) ? 0 : Integer.parseInt(line) - 1; 97 } catch (NumberFormatException e) { 98 System.out.println("KeyStore not changed"); 99 return; 100 } 101 102 X509Certificate cert = chain[k]; 103 String alias = host + "-" + (k + 1); 104 ks.setCertificateEntry(alias, cert); 105 106 OutputStream out = new FileOutputStream("jssecacerts"); 107 ks.store(out, passphrase); 108 out.close(); 109 110 System.out.println(); 111 System.out.println(cert); 112 System.out.println(); 113 System.out.println 114 ("Added certificate to keystore 'jssecacerts' using alias '" 115 + alias + "'"); 116 } 117 118 private static final char[] HEXDIGITS = "0123456789abcdef".toCharArray(); 119 120 private static String toHexString(byte[] bytes) { 121 StringBuilder sb = new StringBuilder(bytes.length * 3); 122 for (int b : bytes) { 123 b &= 0xff; 124 sb.append(HEXDIGITS[b >> 4]); 125 sb.append(HEXDIGITS[b & 15]); 126 sb.append(' '); 127 } 128 return sb.toString(); 129 } 130 131 private static class SavingTrustManager implements X509TrustManager { 132 133 private final X509TrustManager tm; 134 private X509Certificate[] chain; 135 136 SavingTrustManager(X509TrustManager tm) { 137 this.tm = tm; 138 } 139 140 public X509Certificate[] getAcceptedIssuers() { 141 throw new UnsupportedOperationException(); 142 } 143 144 public void checkClientTrusted(X509Certificate[] chain, String authType) 145 throws CertificateException { 146 throw new UnsupportedOperationException(); 147 } 148 149 public void checkServerTrusted(X509Certificate[] chain, String authType) 150 throws CertificateException { 151 this.chain = chain; 152 tm.checkServerTrusted(chain, authType); 153 } 154 } 155 156 }