View Javadoc
1   package ca.uhn.hl7v2.hoh.sockets;
2   
3   import java.io.FileInputStream;
4   import java.io.FileNotFoundException;
5   import java.io.IOException;
6   import java.net.ServerSocket;
7   import java.net.Socket;
8   import java.security.KeyManagementException;
9   import java.security.KeyStore;
10  import java.security.KeyStoreException;
11  import java.security.NoSuchAlgorithmException;
12  import java.security.UnrecoverableKeyException;
13  import java.security.cert.CertificateException;
14  
15  import javax.net.ssl.KeyManager;
16  import javax.net.ssl.KeyManagerFactory;
17  import javax.net.ssl.SSLContext;
18  import javax.net.ssl.SSLServerSocketFactory;
19  import javax.net.ssl.SSLSocketFactory;
20  import javax.net.ssl.TrustManager;
21  import javax.net.ssl.TrustManagerFactory;
22  
23  /**
24   * Socket Factory which creates a TLS/SSL socket using a custom keystore and
25   * certificate.
26   */
27  public class CustomCertificateTlsSocketFactory implements ISocketFactory {
28  
29  	private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(CustomCertificateTlsSocketFactory.class);
30  	private KeyStore myKeystore;
31  	private String myKeystoreFilename;
32  	private String myKeystorePassphrase;
33  	private String myKeystoreType = "JKS";
34  	private SSLServerSocketFactory myServerSocketFactory;
35  
36  	private SSLSocketFactory mySocketFactory = null;
37  
38  	/**
39  	 * Constructor
40  	 */
41  	public CustomCertificateTlsSocketFactory() {
42  		super();
43  	}
44  
45  	/**
46  	 * Constructor
47  	 * 
48  	 * @throws NullPointerException
49  	 *             If theKeystore is null
50  	 */
51  	public CustomCertificateTlsSocketFactory(KeyStore theKeystore, String theKeystorePass) {
52  		if (theKeystore == null) {
53  			throw new NullPointerException("KeyStore can not be null");
54  		}
55  		myKeystore = theKeystore;
56  		myKeystorePassphrase = theKeystorePass;
57  	}
58  
59  	/**
60  	 * Constructor
61  	 * 
62  	 * @param theKeystoreType
63  	 *            The keystore type, e.g. "JKS"
64  	 * @param theKeystoreFilename
65  	 *            The path to the keystore
66  	 * @param theKeystorePassphrase
67  	 *            The password for the keystore
68  	 */
69  	public CustomCertificateTlsSocketFactory(String theKeystoreType, String theKeystoreFilename, String theKeystorePassphrase) {
70  		super();
71  		myKeystoreType = theKeystoreType;
72  		myKeystoreFilename = theKeystoreFilename;
73  		myKeystorePassphrase = theKeystorePassphrase;
74  	}
75  
76  	/**
77  	 * {@inheritDoc}
78  	 */
79  	public Socket createClientSocket() throws IOException {
80  		initialize();
81  		ourLog.debug("Creating client socket");
82  		return mySocketFactory.createSocket();
83  	}
84  
85  	/**
86  	 * {@inheritDoc}
87  	 */
88  	public ServerSocket createServerSocket() throws IOException {
89  		initialize();
90  		ourLog.debug("Creating server socket");
91  		return myServerSocketFactory.createServerSocket();
92  	}
93  
94  	private void initialize() throws IOException {
95  		if (mySocketFactory != null) {
96  			return;
97  		}
98  
99  		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 | KeyManagementException | KeyStoreException | UnrecoverableKeyException | FileNotFoundException | CertificateException e) {
126 			throw new IOException("Failed to initialize socket factory: " + e.getMessage(), e);
127 		}
128 
129     }
130 
131 	/**
132 	 * The filename to load as a keystore
133 	 */
134 	public void setKeystoreFilename(String theKeystoreFilename) {
135 		myKeystoreFilename = theKeystoreFilename;
136 	}
137 
138 	/**
139 	 * The passphrase for the keystore
140 	 */
141 	public void setKeystorePassphrase(String theKeystorePassphrase) {
142 		myKeystorePassphrase = theKeystorePassphrase;
143 	}
144 
145 	/**
146 	 * Sets the keystore type (e.g. JKS, JCEKS)
147 	 */
148 	public void setKeystoreType(String theKeystoreType) {
149 		myKeystoreType = theKeystoreType;
150 	}
151 
152 }