View Javadoc

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