001 package railo.runtime.net.http; 002 003 004 import java.io.IOException; 005 import java.io.InputStream; 006 import java.io.OutputStream; 007 import java.security.GeneralSecurityException; 008 import java.security.KeyStore; 009 import java.security.KeyStoreException; 010 import java.security.NoSuchAlgorithmException; 011 import java.security.cert.CertificateException; 012 import java.security.cert.X509Certificate; 013 014 import javax.net.ssl.SSLContext; 015 import javax.net.ssl.SSLSocket; 016 import javax.net.ssl.SSLSocketFactory; 017 import javax.net.ssl.TrustManager; 018 import javax.net.ssl.TrustManagerFactory; 019 import javax.net.ssl.X509TrustManager; 020 021 import railo.commons.io.IOUtil; 022 import railo.commons.io.res.Resource; 023 024 public class CertificateInstaller { 025 026 027 028 029 030 private String host; 031 private int port; 032 private char[] passphrase; 033 private Resource source; 034 private TrustManagerFactory tmf; 035 private SavingTrustManager tm; 036 private SSLContext context; 037 private KeyStore ks; 038 039 040 public CertificateInstaller(Resource source,String host, int port) throws IOException, KeyStoreException, GeneralSecurityException { 041 this(source,host,port,"changeit".toCharArray()); 042 } 043 044 public CertificateInstaller(Resource source,String host, int port, char[] passphrase) throws IOException, KeyStoreException, GeneralSecurityException { 045 this.source=source; 046 this.host=host; 047 this.port=port; 048 this.passphrase=passphrase; 049 050 051 ks=null; 052 InputStream in = source.getInputStream(); 053 try{ 054 ks = KeyStore.getInstance(KeyStore.getDefaultType()); 055 ks.load(in, passphrase); 056 } 057 finally{ 058 IOUtil.closeEL(in); 059 } 060 061 context = SSLContext.getInstance("TLS"); 062 tmf = 063 TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); 064 tmf.init(ks); 065 X509TrustManager defaultTrustManager = (X509TrustManager)tmf.getTrustManagers()[0]; 066 tm = new SavingTrustManager(defaultTrustManager); 067 context.init(null, new TrustManager[] {tm}, null); 068 069 checkCertificate(); 070 071 if (tm.chain == null) 072 throw new IOException("Could not obtain server certificate chain"); 073 074 075 076 077 078 079 } 080 081 public void installAll() throws IOException, KeyStoreException, NoSuchAlgorithmException, CertificateException { 082 for(int i=0;i<tm.chain.length;i++){ 083 install(i); 084 } 085 } 086 087 public void install(int index) throws IOException, KeyStoreException, NoSuchAlgorithmException, CertificateException { 088 089 X509Certificate cert = tm.chain[index]; 090 String alias = host + "-" + (index + 1); 091 ks.setCertificateEntry(alias, cert); 092 093 OutputStream os = source.getOutputStream(); 094 try{ 095 ks.store(os, passphrase); 096 } 097 finally{ 098 IOUtil.closeEL(os); 099 } 100 /* 101 System.out.println(); 102 System.out.println(cert); 103 System.out.println(); 104 System.out.println 105 ("Added certificate to keystore 'jssecacerts' using alias '" 106 + alias + "'"); 107 */ 108 } 109 110 /** 111 * checks if a certificate is installed for given host:port 112 * @param context 113 * @param host 114 * @param port 115 * @return 116 */ 117 public IOException checkCertificate() { 118 SSLSocketFactory factory = context.getSocketFactory(); 119 //System.out.println("Opening connection to " + host + ":" + port + "..."); 120 121 try { 122 SSLSocket socket = (SSLSocket)factory.createSocket(host, port); 123 socket.setSoTimeout(10000); 124 socket.startHandshake(); 125 socket.close(); 126 return null; 127 } 128 catch (IOException e) { 129 return e; 130 } 131 } 132 133 public void printCertificates() { 134 System.out.println("Server sent " + tm.chain.length + " certificate(s):"); 135 for (int i = 0; i < tm.chain.length; i++) { 136 X509Certificate cert = tm.chain[i]; 137 System.out.println 138 (" " + (i + 1) + " Subject " + cert.getSubjectDN()); 139 System.out.println(" Issuer " + cert.getIssuerDN()); 140 System.out.println(); 141 } 142 } 143 144 public X509Certificate[] getCertificates() { 145 return tm.chain; 146 } 147 148 149 150 private static class SavingTrustManager implements X509TrustManager { 151 152 private final X509TrustManager tm; 153 private X509Certificate[] chain; 154 155 SavingTrustManager(X509TrustManager tm) { 156 this.tm = tm; 157 } 158 159 public X509Certificate[] getAcceptedIssuers() { 160 throw new UnsupportedOperationException(); 161 } 162 163 public void checkClientTrusted(X509Certificate[] chain, String authType) 164 throws CertificateException { 165 throw new UnsupportedOperationException(); 166 } 167 168 public void checkServerTrusted(X509Certificate[] chain, String authType) 169 throws CertificateException { 170 this.chain = chain; 171 tm.checkServerTrusted(chain, authType); 172 } 173 } 174 175 /* 176 public static void main(String[] args) throws Exception { 177 //String host="jira.jboss.org"; 178 179 String host="sso.vogel.de"; 180 int port=443; 181 char[] passphrase="changeit".toCharArray(); 182 183 ResourceProvider frp = ResourcesImpl.getFileResourceProvider(); 184 Resource source = frp.getResource("/Users/mic/Temp/cacerts"); 185 186 187 CertificateInstaller util = new CertificateInstaller(source,host,port,passphrase); 188 util.printCertificates(); 189 util.installAll(); 190 191 } 192 */ 193 194 }