]> git.proxmox.com Git - ceph.git/blame - ceph/src/jaegertracing/thrift/lib/java/src/org/apache/thrift/transport/TSSLTransportFactory.java
buildsys: switch source download to quincy
[ceph.git] / ceph / src / jaegertracing / thrift / lib / java / src / org / apache / thrift / transport / TSSLTransportFactory.java
CommitLineData
f67539c2
TL
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20package org.apache.thrift.transport;
21
22import java.io.FileInputStream;
23import java.io.FileNotFoundException;
24import java.io.InputStream;
25import java.io.IOException;
26import java.net.InetAddress;
27import java.net.URL;
28import java.net.MalformedURLException;
29import java.security.KeyStore;
30import java.util.Arrays;
31
32import javax.net.ssl.KeyManagerFactory;
33import javax.net.ssl.SSLContext;
34import javax.net.ssl.SSLServerSocket;
35import javax.net.ssl.SSLServerSocketFactory;
36import javax.net.ssl.SSLSocket;
37import javax.net.ssl.SSLSocketFactory;
38import javax.net.ssl.TrustManagerFactory;
39
40import org.slf4j.Logger;
41import org.slf4j.LoggerFactory;
42
43/**
44 * A Factory for providing and setting up Client and Server SSL wrapped
45 * TSocket and TServerSocket
46 */
47public class TSSLTransportFactory {
48
49 private static final Logger LOGGER =
50 LoggerFactory.getLogger(TSSLTransportFactory.class);
51
52 /**
53 * Get a SSL wrapped TServerSocket bound to the specified port. In this
54 * configuration the default settings are used. Default settings are retrieved
55 * from System properties that are set.
56 *
57 * Example system properties:
58 * -Djavax.net.ssl.trustStore=<truststore location>
59 * -Djavax.net.ssl.trustStorePassword=password
60 * -Djavax.net.ssl.keyStore=<keystore location>
61 * -Djavax.net.ssl.keyStorePassword=password
62 *
63 * @param port
64 * @return A SSL wrapped TServerSocket
65 * @throws TTransportException
66 */
67 public static TServerSocket getServerSocket(int port) throws TTransportException {
68 return getServerSocket(port, 0);
69 }
70
71 /**
72 * Get a default SSL wrapped TServerSocket bound to the specified port
73 *
74 * @param port
75 * @param clientTimeout
76 * @return A SSL wrapped TServerSocket
77 * @throws TTransportException
78 */
79 public static TServerSocket getServerSocket(int port, int clientTimeout) throws TTransportException {
80 return getServerSocket(port, clientTimeout, false, null);
81 }
82
83 /**
84 * Get a default SSL wrapped TServerSocket bound to the specified port and interface
85 *
86 * @param port
87 * @param clientTimeout
88 * @param ifAddress
89 * @return A SSL wrapped TServerSocket
90 * @throws TTransportException
91 */
92 public static TServerSocket getServerSocket(int port, int clientTimeout, boolean clientAuth, InetAddress ifAddress) throws TTransportException {
93 SSLServerSocketFactory factory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
94 return createServer(factory, port, clientTimeout, clientAuth, ifAddress, null);
95 }
96
97 /**
98 * Get a configured SSL wrapped TServerSocket bound to the specified port and interface.
99 * Here the TSSLTransportParameters are used to set the values for the algorithms, keystore,
100 * truststore and other settings
101 *
102 * @param port
103 * @param clientTimeout
104 * @param ifAddress
105 * @param params
106 * @return A SSL wrapped TServerSocket
107 * @throws TTransportException
108 */
109 public static TServerSocket getServerSocket(int port, int clientTimeout, InetAddress ifAddress, TSSLTransportParameters params) throws TTransportException {
110 if (params == null || !(params.isKeyStoreSet || params.isTrustStoreSet)) {
111 throw new TTransportException("Either one of the KeyStore or TrustStore must be set for SSLTransportParameters");
112 }
113
114 SSLContext ctx = createSSLContext(params);
115 return createServer(ctx.getServerSocketFactory(), port, clientTimeout, params.clientAuth, ifAddress, params);
116 }
117
118 private static TServerSocket createServer(SSLServerSocketFactory factory, int port, int timeout, boolean clientAuth,
119 InetAddress ifAddress, TSSLTransportParameters params) throws TTransportException {
120 try {
121 SSLServerSocket serverSocket = (SSLServerSocket) factory.createServerSocket(port, 100, ifAddress);
122 serverSocket.setSoTimeout(timeout);
123 serverSocket.setNeedClientAuth(clientAuth);
124 if (params != null && params.cipherSuites != null) {
125 serverSocket.setEnabledCipherSuites(params.cipherSuites);
126 }
127 return new TServerSocket(new TServerSocket.ServerSocketTransportArgs().
128 serverSocket(serverSocket).clientTimeout(timeout));
129 } catch (Exception e) {
130 throw new TTransportException("Could not bind to port " + port, e);
131 }
132 }
133
134 /**
135 * Get a default SSL wrapped TSocket connected to the specified host and port. All
136 * the client methods return a bound connection. So there is no need to call open() on the
137 * TTransport.
138 *
139 * @param host
140 * @param port
141 * @param timeout
142 * @return A SSL wrapped TSocket
143 * @throws TTransportException
144 */
145 public static TSocket getClientSocket(String host, int port, int timeout) throws TTransportException {
146 SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
147 return createClient(factory, host, port, timeout);
148 }
149
150 /**
151 * Get a default SSL wrapped TSocket connected to the specified host and port.
152 *
153 * @param host
154 * @param port
155 * @return A SSL wrapped TSocket
156 * @throws TTransportException
157 */
158 public static TSocket getClientSocket(String host, int port) throws TTransportException {
159 return getClientSocket(host, port, 0);
160 }
161
162 /**
163 * Get a custom configured SSL wrapped TSocket. The SSL settings are obtained from the
164 * passed in TSSLTransportParameters.
165 *
166 * @param host
167 * @param port
168 * @param timeout
169 * @param params
170 * @return A SSL wrapped TSocket
171 * @throws TTransportException
172 */
173 public static TSocket getClientSocket(String host, int port, int timeout, TSSLTransportParameters params) throws TTransportException {
174 if (params == null || !(params.isKeyStoreSet || params.isTrustStoreSet)) {
175 throw new TTransportException("Either one of the KeyStore or TrustStore must be set for SSLTransportParameters");
176 }
177
178 SSLContext ctx = createSSLContext(params);
179 return createClient(ctx.getSocketFactory(), host, port, timeout);
180 }
181
182 private static SSLContext createSSLContext(TSSLTransportParameters params) throws TTransportException {
183 SSLContext ctx;
184 InputStream in = null;
185 InputStream is = null;
186
187 try {
188 ctx = SSLContext.getInstance(params.protocol);
189 TrustManagerFactory tmf = null;
190 KeyManagerFactory kmf = null;
191
192 if (params.isTrustStoreSet) {
193 tmf = TrustManagerFactory.getInstance(params.trustManagerType);
194 KeyStore ts = KeyStore.getInstance(params.trustStoreType);
195 if (params.trustStoreStream != null) {
196 in = params.trustStoreStream;
197 } else {
198 in = getStoreAsStream(params.trustStore);
199 }
200 ts.load(in,
201 (params.trustPass != null ? params.trustPass.toCharArray() : null));
202 tmf.init(ts);
203 }
204
205 if (params.isKeyStoreSet) {
206 kmf = KeyManagerFactory.getInstance(params.keyManagerType);
207 KeyStore ks = KeyStore.getInstance(params.keyStoreType);
208 if (params.keyStoreStream != null) {
209 is = params.keyStoreStream;
210 } else {
211 is = getStoreAsStream(params.keyStore);
212 }
213 ks.load(is, params.keyPass.toCharArray());
214 kmf.init(ks, params.keyPass.toCharArray());
215 }
216
217 if (params.isKeyStoreSet && params.isTrustStoreSet) {
218 ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
219 }
220 else if (params.isKeyStoreSet) {
221 ctx.init(kmf.getKeyManagers(), null, null);
222 }
223 else {
224 ctx.init(null, tmf.getTrustManagers(), null);
225 }
226
227 } catch (Exception e) {
228 throw new TTransportException("Error creating the transport", e);
229 } finally {
230 if (in != null) {
231 try {
232 in.close();
233 } catch (IOException e) {
234 LOGGER.warn("Unable to close stream", e);
235 }
236 }
237 if (is != null) {
238 try {
239 is.close();
240 } catch (IOException e) {
241 LOGGER.warn("Unable to close stream", e);
242 }
243 }
244 }
245
246 return ctx;
247 }
248
249 private static InputStream getStoreAsStream(String store) throws IOException {
250 try {
251 return new FileInputStream(store);
252 } catch(FileNotFoundException e) {
253 }
254
255 InputStream storeStream = null;
256 try {
257 storeStream = new URL(store).openStream();
258 if (storeStream != null) {
259 return storeStream;
260 }
261 } catch(MalformedURLException e) {
262 }
263
264 storeStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(store);
265
266 if (storeStream != null) {
267 return storeStream;
268 } else {
269 throw new IOException("Could not load file: " + store);
270 }
271 }
272
273 private static TSocket createClient(SSLSocketFactory factory, String host, int port, int timeout) throws TTransportException {
274 try {
275 SSLSocket socket = (SSLSocket) factory.createSocket(host, port);
276 socket.setSoTimeout(timeout);
277 return new TSocket(socket);
278 } catch (Exception e) {
279 throw new TTransportException("Could not connect to " + host + " on port " + port, e);
280 }
281 }
282
283
284 /**
285 * A Class to hold all the SSL parameters
286 */
287 public static class TSSLTransportParameters {
288 protected String protocol = "TLS";
289 protected String keyStore;
290 protected InputStream keyStoreStream;
291 protected String keyPass;
292 protected String keyManagerType = KeyManagerFactory.getDefaultAlgorithm();
293 protected String keyStoreType = "JKS";
294 protected String trustStore;
295 protected InputStream trustStoreStream;
296 protected String trustPass;
297 protected String trustManagerType = TrustManagerFactory.getDefaultAlgorithm();
298 protected String trustStoreType = "JKS";
299 protected String[] cipherSuites;
300 protected boolean clientAuth = false;
301 protected boolean isKeyStoreSet = false;
302 protected boolean isTrustStoreSet = false;
303
304 public TSSLTransportParameters() {}
305
306 /**
307 * Create parameters specifying the protocol and cipher suites
308 *
309 * @param protocol The specific protocol (TLS/SSL) can be specified with versions
310 * @param cipherSuites
311 */
312 public TSSLTransportParameters(String protocol, String[] cipherSuites) {
313 this(protocol, cipherSuites, false);
314 }
315
316 /**
317 * Create parameters specifying the protocol, cipher suites and if client authentication
318 * is required
319 *
320 * @param protocol The specific protocol (TLS/SSL) can be specified with versions
321 * @param cipherSuites
322 * @param clientAuth
323 */
324 public TSSLTransportParameters(String protocol, String[] cipherSuites, boolean clientAuth) {
325 if (protocol != null) {
326 this.protocol = protocol;
327 }
328 this.cipherSuites = cipherSuites != null ? Arrays.copyOf(cipherSuites, cipherSuites.length) : null;
329 this.clientAuth = clientAuth;
330 }
331
332 /**
333 * Set the keystore, password, certificate type and the store type
334 *
335 * @param keyStore Location of the Keystore on disk
336 * @param keyPass Keystore password
337 * @param keyManagerType The default is X509
338 * @param keyStoreType The default is JKS
339 */
340 public void setKeyStore(String keyStore, String keyPass, String keyManagerType, String keyStoreType) {
341 this.keyStore = keyStore;
342 this.keyPass = keyPass;
343 if (keyManagerType != null) {
344 this.keyManagerType = keyManagerType;
345 }
346 if (keyStoreType != null) {
347 this.keyStoreType = keyStoreType;
348 }
349 isKeyStoreSet = true;
350 }
351
352 /**
353 * Set the keystore, password, certificate type and the store type
354 *
355 * @param keyStoreStream Keystore content input stream
356 * @param keyPass Keystore password
357 * @param keyManagerType The default is X509
358 * @param keyStoreType The default is JKS
359 */
360 public void setKeyStore(InputStream keyStoreStream, String keyPass, String keyManagerType, String keyStoreType) {
361 this.keyStoreStream = keyStoreStream;
362 setKeyStore("", keyPass, keyManagerType, keyStoreType);
363 }
364
365 /**
366 * Set the keystore and password
367 *
368 * @param keyStore Location of the Keystore on disk
369 * @param keyPass Keystore password
370 */
371 public void setKeyStore(String keyStore, String keyPass) {
372 setKeyStore(keyStore, keyPass, null, null);
373 }
374
375 /**
376 * Set the keystore and password
377 *
378 * @param keyStoreStream Keystore content input stream
379 * @param keyPass Keystore password
380 */
381 public void setKeyStore(InputStream keyStoreStream, String keyPass) {
382 setKeyStore(keyStoreStream, keyPass, null, null);
383 }
384
385 /**
386 * Set the truststore, password, certificate type and the store type
387 *
388 * @param trustStore Location of the Truststore on disk
389 * @param trustPass Truststore password
390 * @param trustManagerType The default is X509
391 * @param trustStoreType The default is JKS
392 */
393 public void setTrustStore(String trustStore, String trustPass, String trustManagerType, String trustStoreType) {
394 this.trustStore = trustStore;
395 this.trustPass = trustPass;
396 if (trustManagerType != null) {
397 this.trustManagerType = trustManagerType;
398 }
399 if (trustStoreType != null) {
400 this.trustStoreType = trustStoreType;
401 }
402 isTrustStoreSet = true;
403 }
404
405 /**
406 * Set the truststore, password, certificate type and the store type
407 *
408 * @param trustStoreStream Truststore content input stream
409 * @param trustPass Truststore password
410 * @param trustManagerType The default is X509
411 * @param trustStoreType The default is JKS
412 */
413 public void setTrustStore(InputStream trustStoreStream, String trustPass, String trustManagerType, String trustStoreType) {
414 this.trustStoreStream = trustStoreStream;
415 setTrustStore("", trustPass, trustManagerType, trustStoreType);
416 }
417
418 /**
419 * Set the truststore and password
420 *
421 * @param trustStore Location of the Truststore on disk
422 * @param trustPass Truststore password
423 */
424 public void setTrustStore(String trustStore, String trustPass) {
425 setTrustStore(trustStore, trustPass, null, null);
426 }
427
428 /**
429 * Set the truststore and password
430 *
431 * @param trustStoreStream Truststore content input stream
432 * @param trustPass Truststore password
433 */
434 public void setTrustStore(InputStream trustStoreStream, String trustPass) {
435 setTrustStore(trustStoreStream, trustPass, null, null);
436 }
437
438 /**
439 * Set if client authentication is required
440 *
441 * @param clientAuth
442 */
443 public void requireClientAuth(boolean clientAuth) {
444 this.clientAuth = clientAuth;
445 }
446 }
447}