OmniSciDB  dfae7c3b14
SockTransportProperties.java
Go to the documentation of this file.
1 package com.mapd.common;
2 
3 import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
4 import org.apache.http.conn.ssl.SSLSocketFactory;
5 import org.apache.http.conn.ssl.X509HostnameVerifier;
6 import org.apache.http.impl.client.CloseableHttpClient;
7 import org.apache.http.impl.client.HttpClients;
8 import org.apache.http.ssl.SSLContextBuilder;
9 import org.apache.http.ssl.SSLContexts;
10 import org.apache.thrift.transport.THttpClient;
11 import org.apache.thrift.transport.TSSLTransportFactory;
12 import org.apache.thrift.transport.TServerSocket;
13 import org.apache.thrift.transport.TServerTransport;
14 import org.apache.thrift.transport.TSocket;
15 import org.apache.thrift.transport.TTransport;
16 import org.slf4j.LoggerFactory;
17 
18 import java.io.File;
19 import java.nio.file.Path;
20 import java.nio.file.Paths;
21 import java.security.GeneralSecurityException;
22 import java.security.KeyStore;
23 import java.security.cert.CertificateException;
24 import java.security.cert.X509Certificate;
25 import java.util.Arrays;
26 
27 import javax.net.ssl.KeyManager;
28 import javax.net.ssl.SSLContext;
29 import javax.net.ssl.SSLSocket;
30 import javax.net.ssl.TrustManager;
31 import javax.net.ssl.TrustManagerFactory;
32 import javax.net.ssl.X509TrustManager;
33 
35  final static org.slf4j.Logger MAPDLOGGER =
36  LoggerFactory.getLogger(SockTransportProperties.class);
37 
38  /*
39  * The following static 'factory' methods have been added to make usage of this
40  * class simpler. The previously defined constructors have been left public to
41  * limit the scope of the current change, though ideally they should be removed
42  * and the calling code replaced with use of these static methods.
43  */
44 
46  static public SockTransportProperties getUnencryptedClient() throws Exception {
47  boolean validate_server_name = false;
48  return new SockTransportProperties(
49  TransportType.unencryptedClient, validate_server_name);
50  }
53  boolean validate_server_name) throws Exception {
54  return new SockTransportProperties(
55  TransportType.encryptedClientDefaultTrustStore, validate_server_name);
56  }
57 
58  // TODO for simplicity this method should be removed
60  String trustStoreName, String trustStorePassword) throws Exception {
62  trustStoreName, trustStorePassword, true);
63  }
65  String trustStoreName, String trustStorePassword, boolean validate_server_name)
66  throws Exception {
68  trustStoreName,
69  trustStorePassword,
70  validate_server_name);
71  }
72 
75  String keyStoreName, String keyStorePassword) throws Exception {
76  boolean validate_server_name = false;
77  if (keyStoreName == null || keyStorePassword == null) {
78  String errStr = new String(
79  "Invalid null parameter(s) used for getEncryptedServer. Both keyStoreName and keyStorePassword must be specified");
80  RuntimeException rE = new RuntimeException(errStr);
81  MAPDLOGGER.error(errStr, rE);
82  throw(rE);
83  }
85  keyStoreName,
86  keyStorePassword,
87  validate_server_name);
88  }
89 
90  static public SockTransportProperties getUnecryptedServer() throws Exception {
91  boolean validate_server_name = false;
92  return new SockTransportProperties(
93  TransportType.unencryptedServer, validate_server_name);
94  }
97  // There are nominally 5 different 'types' of this class.
98  private enum TransportType {
103  encryptedClientSpecifiedTrustStore
104  }
105 
107  public SockTransportProperties(String truststore_name, String truststore_passwd)
108  throws Exception {
110  truststore_name,
111  truststore_passwd,
112  true);
113  }
114 
117  String store_name,
118  String passwd,
119  boolean validate_server_name) throws Exception {
120  x509HostnameVerifier_ = (validate_server_name == true)
121  ? SSLConnectionSocketFactory.STRICT_HOSTNAME_VERIFIER
122  : SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;
123  transportType = tT;
124 
125  char[] store_password = "".toCharArray();
126  if (passwd != null && !passwd.isEmpty()) {
127  store_password = passwd.toCharArray();
128  }
129  switch (transportType) {
130  case encryptedServer: {
131  key_store_password = store_password;
132  key_store_name = store_name;
133  break;
134  }
135  case encryptedClientSpecifiedTrustStore: {
136  if (store_name == null) {
138  } else {
139  KeyStore trust_store = KeyStore.getInstance(KeyStore.getDefaultType());
140  try {
141  java.io.FileInputStream fis = new java.io.FileInputStream(store_name);
142  trust_store.load(fis, store_password);
143  } catch (Exception eX) {
144  String err_str =
145  new String("Error loading key/trust store [" + store_name + "]");
146  MAPDLOGGER.error(err_str, eX);
147  throw(eX);
148  }
149  initializeAcceptedIssuers(trust_store);
150  }
151  break;
152  }
153  default: {
154  String errStr = new String(
155  "Invalid transportType [" + transportType + "] used in constructor");
156  RuntimeException rE = new RuntimeException(errStr);
157  MAPDLOGGER.error(errStr, rE);
158  throw(rE);
159  }
160  }
161  }
162 
164  TransportType transportType, boolean validate_server_name) throws Exception {
165  x509HostnameVerifier_ = (validate_server_name == true)
166  ? SSLConnectionSocketFactory.STRICT_HOSTNAME_VERIFIER
167  : SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;
168  this.transportType = transportType;
169  switch (transportType) {
170  case encryptedClientDefaultTrustStore:
171  // load default trust_store
172  initializeAcceptedIssuers((KeyStore) null);
173  break;
174  case unencryptedClient:
175  case unencryptedServer:
176  break;
177  default:
178  String errStr = new String(
179  "Invalid transportType [" + transportType + "] used in constructor");
180  RuntimeException rE = new RuntimeException(errStr);
181  MAPDLOGGER.error(errStr, rE);
182  throw(rE);
183  }
184  }
187  private void initializeAcceptedIssuers(KeyStore trust_store) throws Exception {
188  // Initialize a trust manager to either the trust store already loaded or the
189  // default trust store. Order of searching for default is:
190  // 1. system property javax.net.ssl.trustStore
191  // 2. <java-home>/lib/security/jssecacerts
192  // 3. <java-home</lib/security/cacerts
193 
194  TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("PKIX");
195  // If trust_store is null init will load the default trust_store
196  trustManagerFactory.init(trust_store);
197  trustManagers = trustManagerFactory.getTrustManagers();
198  }
199 
200  /*
201  * public client open transport methods
202  *
203  * openClientTransport opensHttpClientTransport, openHttpsClientTransport
204  *
205  */
206 
207  public TTransport openClientTransport(String server_host, int port)
208  throws org.apache.thrift.TException {
209  TTransport tTransport = null;
210  switch (transportType) {
211  case encryptedClientDefaultTrustStore:
212  case encryptedClientSpecifiedTrustStore:
213  tTransport = openBinaryEncrypted(server_host, port);
214  break;
215  case unencryptedClient:
216  tTransport = new TSocket(server_host, port);
217  break;
218  default:
219  String errStr = new String("Invalid transportType [" + transportType
220  + "] used in openClientTransport");
221  RuntimeException rE = new RuntimeException(errStr);
222  MAPDLOGGER.error(errStr, rE);
223  throw(rE);
224  }
225  return tTransport;
226  }
227 
228  private TTransport openBinaryEncrypted(String server_host, int port)
229  throws org.apache.thrift.TException {
230  // Used to set Socket.setSoTimeout ms. 0 == inifinite.
231  int socket_so_timeout_ms = 0;
232  TSocket tsocket = null;
233  try {
234  SSLContext sc = SSLContext.getInstance("TLS");
235  sc.init(null, trustManagers, new java.security.SecureRandom());
236 
237  SSLSocket sx = (SSLSocket) sc.getSocketFactory().createSocket(server_host, port);
238  sx.setSoTimeout(socket_so_timeout_ms);
239  tsocket = new TSocket(sx);
240  } catch (Exception ex) {
241  String errStr = new String("Error openBinaryEncrypted [" + server_host + ":" + port
242  + "] used in openClientTransport - ");
243  errStr += ex.toString();
244  RuntimeException rE = new RuntimeException(errStr);
245  MAPDLOGGER.error(errStr, rE);
246  throw(rE);
247  }
248  return tsocket;
249  }
250 
251  public TTransport openHttpsClientTransport(String server_host, int port)
252  throws Exception {
255  String errStr = new String("Invalid transportType [" + transportType
256  + "] used in openHttpsClientTransport");
257  RuntimeException rE = new RuntimeException(errStr);
258  MAPDLOGGER.error(errStr, rE);
259  throw(rE);
260  }
261  TTransport transport = null;
262 
263  try {
264  SSLContext sc = SSLContext.getInstance("TLS");
265  sc.init(null, trustManagers, new java.security.SecureRandom());
266  SSLConnectionSocketFactory sslConnectionSocketFactory = null;
267  sslConnectionSocketFactory =
268  new SSLConnectionSocketFactory(sc, x509HostnameVerifier_);
269 
270  CloseableHttpClient closeableHttpClient =
271  HttpClients.custom()
272  .setSSLSocketFactory(sslConnectionSocketFactory)
273  .build();
274  transport =
275  new THttpClient("https://" + server_host + ":" + port, closeableHttpClient);
276 
277  } catch (Exception ex) {
278  String err_str = new String("Exception:" + ex.getClass().getCanonicalName()
279  + " thrown. Unable to create Secure socket for the HTTPS connection");
280  MAPDLOGGER.error(err_str, ex);
281  throw ex;
282  }
283 
284  return transport;
285  }
286 
287  public TTransport openHttpClientTransport(String server_host, int port)
288  throws org.apache.thrift.TException {
290  String errStr = new String("Invalid transportType [" + transportType
291  + "] used in openHttpClientTransport");
292  RuntimeException rE = new RuntimeException(errStr);
293  MAPDLOGGER.error(errStr, rE);
294  throw(rE);
295  }
296 
297  String url = "http://" + server_host + ":" + port;
298  return (new THttpClient(url));
299  }
300 
301  /*
302  * open Binary Server transport ***
303  */
304  public TServerTransport openServerTransport(int port)
305  throws org.apache.thrift.TException {
307  return openServerTransportEncrypted(port);
309  return (new TServerSocket(port));
310  } else {
311  String errStr = new String("Invalid transportType [" + transportType
312  + "] used in openServerTransport");
313  RuntimeException rE = new RuntimeException(errStr);
314  MAPDLOGGER.error(errStr, rE);
315  throw(rE);
316  }
317  }
318 
319  private TServerTransport openServerTransportEncrypted(int port)
320  throws org.apache.thrift.TException {
321  // Used to set Socket.setSoTimeout ms. 0 == inifinite.
322  int socket_so_timeout_ms = 0;
323  TSSLTransportFactory.TSSLTransportParameters params =
324  new TSSLTransportFactory.TSSLTransportParameters();
325  params.setKeyStore(key_store_name,
326  (key_store_password != null) ? new String(key_store_password) : null);
327  params.requireClientAuth(false);
328 
329  // return TSSLTransportFactory.getClientSocket(server_host, port,
330  // socket_so_timeout_ms, params);
331  TServerTransport t = TSSLTransportFactory.getServerSocket(
332  port, socket_so_timeout_ms, null, params);
333  return t;
334  }
335 
336  private TrustManager[] trustManagers;
337  private TransportType transportType = null;
338  private KeyManager[] keyManagers;
339  private String key_store_name = null;
340  private char[] key_store_password = null;
341  X509HostnameVerifier x509HostnameVerifier_ =
342  SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER;
343 }
static SockTransportProperties getEncryptedClientSpecifiedTrustStore(String trustStoreName, String trustStorePassword)
TTransport openHttpClientTransport(String server_host, int port)
TTransport openHttpsClientTransport(String server_host, int port)
static SockTransportProperties getUnecryptedServer()
static SockTransportProperties getEncryptedClientSpecifiedTrustStore(String trustStoreName, String trustStorePassword, boolean validate_server_name)
SockTransportProperties(String truststore_name, String truststore_passwd)
TServerTransport openServerTransportEncrypted(int port)
TTransport openClientTransport(String server_host, int port)
static SockTransportProperties getEncryptedServer(String keyStoreName, String keyStorePassword)
SockTransportProperties(TransportType tT, String store_name, String passwd, boolean validate_server_name)
TTransport openBinaryEncrypted(String server_host, int port)
static SockTransportProperties getUnencryptedClient()
url
Definition: setup.py:39
static SockTransportProperties getEncryptedClientDefaultTrustStore(boolean validate_server_name)
SockTransportProperties(TransportType transportType, boolean validate_server_name)