package water.network; import water.H2O; import water.util.Log; import javax.net.ssl.*; import java.io.FileInputStream; import java.io.IOException; import java.nio.channels.ByteChannel; import java.nio.channels.SocketChannel; import java.security.*; import java.security.cert.CertificateException; public class SSLSocketChannelFactory { private SSLContext sslContext = null; private SSLProperties properties = null; public SSLSocketChannelFactory() throws SSLContextException { try { SSLProperties props = new SSLProperties(); props.load(new FileInputStream(H2O.ARGS.internal_security_conf)); init(props); } catch (IOException e) { Log.err("Failed to initialized SSL context.", e); throw new SSLContextException("Failed to initialized SSL context.", e); } } public SSLSocketChannelFactory(SSLProperties props) throws SSLContextException { init(props); } private void init(SSLProperties props) throws SSLContextException { properties = props; try { if (requiredParamsPresent()) { this.sslContext = SSLContext.getInstance(properties.h2o_ssl_protocol()); this.sslContext.init(keyManager(), trustManager(), null); } else { this.sslContext = SSLContext.getDefault(); } } catch (NoSuchAlgorithmException e) { Log.err("Failed to initialized SSL context.", e); throw new SSLContextException("Failed to initialized SSL context.", e); } catch (IOException e) { Log.err("Failed to initialized SSL context.", e); throw new SSLContextException("Failed to initialized SSL context.", e); } catch (UnrecoverableKeyException e) { Log.err("Failed to initialized SSL context.", e); throw new SSLContextException("Failed to initialized SSL context.", e); } catch (KeyStoreException e) { Log.err("Failed to initialized SSL context.", e); throw new SSLContextException("Failed to initialized SSL context.", e); } catch (KeyManagementException e) { Log.err("Failed to initialized SSL context.", e); throw new SSLContextException("Failed to initialized SSL context.", e); } catch (CertificateException e) { Log.err("Failed to initialized SSL context.", e); throw new SSLContextException("Failed to initialized SSL context.", e); } } private boolean requiredParamsPresent() { return null != properties.h2o_ssl_jks_internal() && null != properties.h2o_ssl_jks_password(); } private TrustManager[] trustManager() throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException { KeyStore ksTrust = KeyStore.getInstance("JKS"); ksTrust.load( new FileInputStream(properties.h2o_ssl_jts()), properties.h2o_ssl_jts_password().toCharArray() ); TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); tmf.init(ksTrust); return tmf.getTrustManagers(); } private KeyManager[] keyManager() throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException, UnrecoverableKeyException { KeyStore ksKeys = KeyStore.getInstance("JKS"); ksKeys.load(new FileInputStream(properties.h2o_ssl_jks_internal()), properties.h2o_ssl_jks_password().toCharArray() ); KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); kmf.init(ksKeys, properties.h2o_ssl_jks_password().toCharArray()); return kmf.getKeyManagers(); } public ByteChannel wrapClientChannel( SocketChannel channel, String host, int port) throws IOException { SSLEngine sslEngine = sslContext.createSSLEngine(host, port); sslEngine.setUseClientMode(false); if (null != properties.h2o_ssl_enabled_algorithms()) { sslEngine.setEnabledCipherSuites(properties.h2o_ssl_enabled_algorithms()); } return new SSLSocketChannel(channel, sslEngine); } public ByteChannel wrapServerChannel(SocketChannel channel) throws IOException { SSLEngine sslEngine = sslContext.createSSLEngine(); sslEngine.setUseClientMode(true); if (null != properties.h2o_ssl_enabled_algorithms()) { sslEngine.setEnabledCipherSuites(properties.h2o_ssl_enabled_algorithms()); } return new SSLSocketChannel(channel, sslEngine); } }