Package org.vertx.java.core.net.impl

Source Code of org.vertx.java.core.net.impl.TCPSSLHelper

/*
* Copyright 2011-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.vertx.java.core.net.impl;

import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.buffer.UnpooledByteBufAllocator;
import io.netty.channel.ChannelOption;
import org.vertx.java.core.file.impl.PathAdjuster;
import org.vertx.java.core.impl.VertxInternal;
import org.vertx.java.core.logging.Logger;
import org.vertx.java.core.logging.impl.LoggerFactory;

import javax.net.ssl.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

/**
* Helper class for TCP and SSL attributes
*
* @author <a href="http://tfox.org">Tim Fox</a>
*/
public class TCPSSLHelper {

  private static final Logger log = LoggerFactory.getLogger(TCPSSLHelper.class);

  private boolean ssl;
  private boolean verifyHost = true;
  private String keyStorePath;
  private String keyStorePassword;
  private String trustStorePath;
  private String trustStorePassword;
  private boolean trustAll;
  private ClientAuth clientAuth = ClientAuth.NONE;

  private static SocketDefaults defaults = SocketDefaults.instance;

  private boolean tcpNoDelay = true;
  private int tcpSendBufferSize = defaults.getTcpSendBufferSize();
  private int tcpReceiveBufferSize = defaults.getTcpReceiveBufferSize();
  private boolean tcpKeepAlive = defaults.isTcpKeepAlive();
  private boolean reuseAddress = defaults.isReuseAddress();
  private int soLinger = defaults.getSoLinger();
  private int trafficClass = defaults.getTrafficClass();
  private int acceptBackLog = 1024;
  private int connectTimeout = 60000;
  private boolean usePooledBuffers = false;

  private SSLContext sslContext;

  public TCPSSLHelper() {
  }

  public void checkSSL(VertxInternal vertx) {
    if (ssl) {
      sslContext = createContext(vertx, keyStorePath, keyStorePassword, trustStorePath, trustStorePassword, trustAll);
    }
  }

  public enum ClientAuth {
    NONE, REQUEST, REQUIRED
  }

  public void applyConnectionOptions(ServerBootstrap bootstrap) {
    bootstrap.childOption(ChannelOption.TCP_NODELAY, tcpNoDelay);
    bootstrap.childOption(ChannelOption.SO_SNDBUF, tcpSendBufferSize);
    bootstrap.childOption(ChannelOption.SO_RCVBUF, tcpReceiveBufferSize);
    bootstrap.option(ChannelOption.SO_LINGER, soLinger);
    bootstrap.childOption(ChannelOption.IP_TOS, trafficClass);
    if (usePooledBuffers) {
      bootstrap.childOption(ChannelOption.ALLOCATOR, new PooledByteBufAllocator());
    } else {
      bootstrap.childOption(ChannelOption.ALLOCATOR, UnpooledByteBufAllocator.DEFAULT);
    }
    bootstrap.childOption(ChannelOption.SO_KEEPALIVE, tcpKeepAlive);
    bootstrap.option(ChannelOption.SO_REUSEADDR, reuseAddress);
    bootstrap.option(ChannelOption.SO_BACKLOG, acceptBackLog);
  }

  public void applyConnectionOptions(Bootstrap bootstrap) {
    bootstrap.option(ChannelOption.TCP_NODELAY, tcpNoDelay);
    bootstrap.option(ChannelOption.SO_SNDBUF, tcpSendBufferSize);
    bootstrap.option(ChannelOption.SO_RCVBUF, tcpReceiveBufferSize);
    bootstrap.option(ChannelOption.SO_LINGER, soLinger);
    bootstrap.option(ChannelOption.IP_TOS, trafficClass);
    bootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, connectTimeout);
    bootstrap.option(ChannelOption.ALLOCATOR, new PooledByteBufAllocator());
    bootstrap.option(ChannelOption.ALLOCATOR, UnpooledByteBufAllocator.DEFAULT);
  }

  public boolean isTCPNoDelay() {
    return tcpNoDelay;
  }

  public int getSendBufferSize() {
    return tcpSendBufferSize;
  }

  public int getReceiveBufferSize() {
    return tcpReceiveBufferSize;
  }

  public boolean isTCPKeepAlive() {
    return tcpKeepAlive;
  }

  public boolean isReuseAddress() {
    return reuseAddress;
  }

  public int getSoLinger() {
    return soLinger;
  }

  public int getTrafficClass() {
    return trafficClass;
  }

  public void setTCPNoDelay(boolean tcpNoDelay) {
    this.tcpNoDelay = tcpNoDelay;
  }

  public void setSendBufferSize(int size) {
    if (size < 1) {
      throw new IllegalArgumentException("TCP send buffer size must be >= 1");
    }
    this.tcpSendBufferSize = size;
  }

  public void setReceiveBufferSize(int size) {
    if (size < 1) {
      throw new IllegalArgumentException("TCP receive buffer size must be >= 1");
    }
    this.tcpReceiveBufferSize = size;
  }

  public void setTCPKeepAlive(boolean keepAlive) {
    this.tcpKeepAlive = keepAlive;
  }

  public void setReuseAddress(boolean reuse) {
    this.reuseAddress = reuse;
  }

  public void setSoLinger(int linger) {
    this.soLinger = linger;
  }

  public void setTrafficClass(int trafficClass) {
    this.trafficClass = trafficClass;
  }

  public boolean isSSL() {
    return ssl;
  }

  public boolean isVerifyHost() {
    return verifyHost;
  }

  public String getKeyStorePath() {
    return keyStorePath;
  }

  public String getKeyStorePassword() {
    return keyStorePassword;
  }

  public String getTrustStorePath() {
    return trustStorePath;
  }

  public String getTrustStorePassword() {
    return trustStorePassword;
  }

  public ClientAuth getClientAuth() {
    return clientAuth;
  }

  public boolean isTrustAll() {
    return trustAll;
  }

  public SSLContext getSSLContext() {
    return sslContext;
  }

  public void setSSL(boolean ssl) {
    this.ssl = ssl;
  }

  public void setVerifyHost(boolean verifyHost) {
    this.verifyHost = verifyHost;
  }

  public void setKeyStorePath(String path) {
    this.keyStorePath = path;
  }

  public void setKeyStorePassword(String pwd) {
    this.keyStorePassword = pwd;
  }

  public void setTrustStorePath(String path) {
    this.trustStorePath = path;
  }

  public void setTrustStorePassword(String pwd) {
    this.trustStorePassword = pwd;
  }

  public void setClientAuthRequired(boolean required) {
    clientAuth = required ? ClientAuth.REQUIRED : ClientAuth.NONE;
  }

  public void setTrustAll(boolean trustAll) {
    this.trustAll = trustAll;
  }

  public int getAcceptBacklog() {
    return acceptBackLog;
  }

  public int getConnectTimeout() {
    return connectTimeout;
  }

  public void setConnectTimeout(int connectTimeout) {
    if (connectTimeout < 0) {
      throw new IllegalArgumentException("connectTimeout must be >= 0");
    }
    this.connectTimeout = connectTimeout;
  }

  public void setAcceptBacklog(int acceptBackLog) {
    if (acceptBackLog < 0) {
      throw new IllegalArgumentException("acceptBackLog must be >= 0");
    }
    this.acceptBackLog = acceptBackLog;
  }

  public void setUsePooledBuffers(boolean usePooledBuffers) {
    this.usePooledBuffers = usePooledBuffers;
  }

  public boolean isUsePooledBuffers() {
    return usePooledBuffers;
  }

  /*
  If you don't specify a trust store, and you haven't set system properties, the system will try to use either a file
  called jsssecacerts or cacerts in the JDK/JRE security directory.
  You can override this by specifying the javax.echo.ssl.trustStore system property

  If you don't specify a key store, and don't specify a system property no key store will be used
  You can override this by specifying the javax.echo.ssl.keyStore system property
   */
  public SSLContext createContext(VertxInternal vertx, final String ksPath,
                                   final String ksPassword,
                                   final String tsPath,
                                   final String tsPassword,
                                   final boolean trustAll) {
    try {
      SSLContext context = SSLContext.getInstance("TLS");
      KeyManager[] keyMgrs = ksPath == null ? null : getKeyMgrs(vertx, ksPath, ksPassword);
      TrustManager[] trustMgrs;
      if (trustAll) {
        trustMgrs = new TrustManager[]{createTrustAllTrustManager()};
      } else {
        trustMgrs = tsPath == null ? null : getTrustMgrs(vertx, tsPath, tsPassword);
      }
      context.init(keyMgrs, trustMgrs, new SecureRandom());
      return context;
    } catch (Exception e) {
      //TODO better logging
      log.error("Failed to create context", e);
      throw new RuntimeException(e.getMessage());
    }
  }

  // Create a TrustManager which trusts everything
  private TrustManager createTrustAllTrustManager() {
    return new X509TrustManager() {
      @Override
      public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
      }

      @Override
      public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
      }

      @Override
      public X509Certificate[] getAcceptedIssuers() {
        return new X509Certificate[0];
      }
    };
  }

  private TrustManager[] getTrustMgrs(VertxInternal vertx, final String tsPath,
                                             final String tsPassword) throws Exception {
    TrustManagerFactory fact = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    KeyStore ts = loadStore(vertx, tsPath, tsPassword);
    fact.init(ts);
    return fact.getTrustManagers();
  }

  private KeyManager[] getKeyMgrs(VertxInternal vertx, final String ksPath, final String ksPassword) throws Exception {
    KeyManagerFactory fact = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
    KeyStore ks = loadStore(vertx, ksPath, ksPassword);
    fact.init(ks, ksPassword != null ? ksPassword.toCharArray(): null);
    return fact.getKeyManagers();
  }

  private KeyStore loadStore(VertxInternal vertx, String path, final String ksPassword) throws Exception {
    final String ksPath = PathAdjuster.adjust(vertx, path);
    KeyStore ks = KeyStore.getInstance("JKS");
    InputStream in = null;
    try {
      in = new FileInputStream(new File(ksPath));
      ks.load(in, ksPassword != null ? ksPassword.toCharArray(): null);
    } finally {
      if (in != null) {
        try {
          in.close();
        } catch (IOException ignore) {
        }
      }
    }
    return ks;
  }
}
TOP

Related Classes of org.vertx.java.core.net.impl.TCPSSLHelper

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.