001package ca.uhn.hl7v2.hoh.sockets; 002 003import java.io.FileInputStream; 004import java.io.FileNotFoundException; 005import java.io.IOException; 006import java.net.ServerSocket; 007import java.net.Socket; 008import java.security.KeyManagementException; 009import java.security.KeyStore; 010import java.security.KeyStoreException; 011import java.security.NoSuchAlgorithmException; 012import java.security.UnrecoverableKeyException; 013import java.security.cert.CertificateException; 014 015import javax.net.ssl.KeyManager; 016import javax.net.ssl.KeyManagerFactory; 017import javax.net.ssl.SSLContext; 018import javax.net.ssl.SSLServerSocketFactory; 019import javax.net.ssl.SSLSocketFactory; 020import javax.net.ssl.TrustManager; 021import javax.net.ssl.TrustManagerFactory; 022 023/** 024 * Socket Factory which creates a TLS/SSL socket using a custom keystore and 025 * certificate. 026 */ 027public class CustomCertificateTlsSocketFactory implements ISocketFactory { 028 029 private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(CustomCertificateTlsSocketFactory.class); 030 private KeyStore myKeystore; 031 private String myKeystoreFilename; 032 private String myKeystorePassphrase; 033 private String myKeystoreType = "JKS"; 034 private SSLServerSocketFactory myServerSocketFactory; 035 036 private SSLSocketFactory mySocketFactory = null; 037 038 /** 039 * Constructor 040 */ 041 public CustomCertificateTlsSocketFactory() { 042 super(); 043 } 044 045 /** 046 * Constructor 047 * 048 * @throws NullPointerException 049 * If theKeystore is null 050 */ 051 public CustomCertificateTlsSocketFactory(KeyStore theKeystore, String theKeystorePass) { 052 if (theKeystore == null) { 053 throw new NullPointerException("KeyStore can not be null"); 054 } 055 myKeystore = theKeystore; 056 myKeystorePassphrase = theKeystorePass; 057 } 058 059 /** 060 * Constructor 061 * 062 * @param theKeystoreType 063 * The keystore type, e.g. "JKS" 064 * @param theKeystoreFilename 065 * The path to the keystore 066 * @param theKeystorePassphrase 067 * The password for the keystore 068 */ 069 public CustomCertificateTlsSocketFactory(String theKeystoreType, String theKeystoreFilename, String theKeystorePassphrase) { 070 super(); 071 myKeystoreType = theKeystoreType; 072 myKeystoreFilename = theKeystoreFilename; 073 myKeystorePassphrase = theKeystorePassphrase; 074 } 075 076 /** 077 * {@inheritDoc} 078 */ 079 public Socket createClientSocket() throws IOException { 080 initialize(); 081 ourLog.debug("Creating client socket"); 082 return mySocketFactory.createSocket(); 083 } 084 085 /** 086 * {@inheritDoc} 087 */ 088 public ServerSocket createServerSocket() throws IOException { 089 initialize(); 090 ourLog.debug("Creating server socket"); 091 return myServerSocketFactory.createServerSocket(); 092 } 093 094 private void initialize() throws IOException { 095 if (mySocketFactory != null) { 096 return; 097 } 098 099 try { 100 char[] passphrase = myKeystorePassphrase != null ? myKeystorePassphrase.toCharArray() : null; 101 if (myKeystore == null) { 102 103 myKeystore = KeyStore.getInstance(myKeystoreType); 104 105 try { 106 myKeystore.load(new FileInputStream(myKeystoreFilename), passphrase); 107 } catch (IOException e) { 108 throw new IOException("Failed to load keystore: " + myKeystoreFilename, e); 109 } 110 } 111 112 SSLContext ctx = SSLContext.getInstance("TLS"); 113 KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); 114 TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); 115 116 kmf.init(myKeystore, passphrase); 117 tmf.init(myKeystore); 118 TrustManager[] trustManagers = tmf.getTrustManagers(); 119 KeyManager[] keyManagers = kmf.getKeyManagers(); 120 ctx.init(keyManagers, trustManagers, null); 121 122 mySocketFactory = ctx.getSocketFactory(); 123 myServerSocketFactory = ctx.getServerSocketFactory(); 124 125 } catch (NoSuchAlgorithmException e) { 126 throw new IOException("Failed to initialize socket factory: " + e.getMessage(), e); 127 } catch (CertificateException e) { 128 throw new IOException("Failed to initialize socket factory: " + e.getMessage(), e); 129 } catch (FileNotFoundException e) { 130 throw new IOException("Failed to initialize socket factory: " + e.getMessage(), e); 131 } catch (UnrecoverableKeyException e) { 132 throw new IOException("Failed to initialize socket factory: " + e.getMessage(), e); 133 } catch (KeyStoreException e) { 134 throw new IOException("Failed to initialize socket factory: " + e.getMessage(), e); 135 } catch (KeyManagementException e) { 136 throw new IOException("Failed to initialize socket factory: " + e.getMessage(), e); 137 } 138 139 } 140 141 /** 142 * The filename to load as a keystore 143 */ 144 public void setKeystoreFilename(String theKeystoreFilename) { 145 myKeystoreFilename = theKeystoreFilename; 146 } 147 148 /** 149 * The passphrase for the keystore 150 */ 151 public void setKeystorePassphrase(String theKeystorePassphrase) { 152 myKeystorePassphrase = theKeystorePassphrase; 153 } 154 155 /** 156 * Sets the keystore type (e.g. JKS, JCEKS) 157 */ 158 public void setKeystoreType(String theKeystoreType) { 159 myKeystoreType = theKeystoreType; 160 } 161 162}