All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.logstash.netty.SslSimpleBuilder Maven / Gradle / Ivy

package org.logstash.netty;

import io.netty.buffer.ByteBufAllocator;
import io.netty.handler.ssl.OpenSsl;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.SslHandler;
import java.io.*;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.net.ssl.SSLEngine;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

/** Created by ph on 2016-05-27. */
public class SslSimpleBuilder {

  public static enum SslClientVerifyMode {
    VERIFY_PEER,
    FORCE_PEER,
  }

  private static final Logger logger = LogManager.getLogger(SslSimpleBuilder.class);

  private File sslKeyFile;
  private File sslCertificateFile;
  private SslClientVerifyMode verifyMode = SslClientVerifyMode.FORCE_PEER;

  private long handshakeTimeoutMilliseconds = 10000;

  /*
  Mordern Ciphers List from
  https://wiki.mozilla.org/Security/Server_Side_TLS
  This list require the OpenSSl engine for netty.
  */
  public static final String[] DEFAULT_CIPHERS =
      new String[] {
        "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
        "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
        "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
        "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
        "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
        "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
        "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
        "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"
      };

  private String[] ciphers = DEFAULT_CIPHERS;
  private String[] protocols = new String[] {"TLSv1.2"};
  private String[] certificateAuthorities;
  private String passPhrase;

  public SslSimpleBuilder(String sslCertificateFilePath, String sslKeyFilePath, String pass)
      throws FileNotFoundException {
    sslCertificateFile = new File(sslCertificateFilePath);
    sslKeyFile = new File(sslKeyFilePath);
    passPhrase = pass;
    ciphers = DEFAULT_CIPHERS;
  }

  public SslSimpleBuilder setProtocols(String[] protocols) {
    this.protocols = protocols;
    return this;
  }

  public SslSimpleBuilder setCipherSuites(String[] ciphersSuite) throws IllegalArgumentException {
    for (String cipher : ciphersSuite) {
      if (!OpenSsl.isCipherSuiteAvailable(cipher)) {
        throw new IllegalArgumentException("Cipher `" + cipher + "` is not available");
      } else {
        logger.debug("Cipher is supported: " + cipher);
      }
    }

    ciphers = ciphersSuite;
    return this;
  }

  public SslSimpleBuilder setCertificateAuthorities(String[] cert) {
    certificateAuthorities = cert;
    return this;
  }

  public SslSimpleBuilder setHandshakeTimeoutMilliseconds(int timeout) {
    handshakeTimeoutMilliseconds = timeout;
    return this;
  }

  public SslSimpleBuilder setVerifyMode(SslClientVerifyMode mode) {
    verifyMode = mode;
    return this;
  }

  public File getSslKeyFile() {
    return sslKeyFile;
  }

  public File getSslCertificateFile() {
    return sslCertificateFile;
  }

  public SslHandler build(ByteBufAllocator bufferAllocator)
      throws IOException, NoSuchAlgorithmException, CertificateException {
    SslContextBuilder builder =
        SslContextBuilder.forServer(sslCertificateFile, sslKeyFile, passPhrase);

    if (logger.isDebugEnabled())
      logger.debug(
          "Available ciphers:" + Arrays.toString(OpenSsl.availableOpenSslCipherSuites().toArray()));
    logger.debug("Ciphers:  " + Arrays.toString(ciphers));

    builder.ciphers(Arrays.asList(ciphers));

    if (requireClientAuth()) {
      if (logger.isDebugEnabled())
        logger.debug("Certificate Authorities: " + Arrays.toString(certificateAuthorities));

      builder.trustManager(loadCertificateCollection(certificateAuthorities));
    }

    SslContext context = builder.build();
    SslHandler sslHandler = context.newHandler(bufferAllocator);

    if (logger.isDebugEnabled()) logger.debug("TLS: " + Arrays.toString(protocols));

    SSLEngine engine = sslHandler.engine();
    engine.setEnabledProtocols(protocols);

    if (requireClientAuth()) {
      // server is doing the handshake
      engine.setUseClientMode(false);

      if (verifyMode == SslClientVerifyMode.FORCE_PEER) {
        // Explicitely require a client certificate
        engine.setNeedClientAuth(true);
      } else if (verifyMode == SslClientVerifyMode.VERIFY_PEER) {
        // If the client supply a client certificate we will verify it.
        engine.setWantClientAuth(true);
      }
    }

    sslHandler.setHandshakeTimeoutMillis(handshakeTimeoutMilliseconds);

    return sslHandler;
  }

  private X509Certificate[] loadCertificateCollection(String[] certificates)
      throws IOException, CertificateException {
    logger.debug("Load certificates collection");
    CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");

    List collections = new ArrayList();

    for (int i = 0; i < certificates.length; i++) {
      String certificate = certificates[i];

      logger.debug("Loading certificates from file " + certificate);

      try (InputStream in = new FileInputStream(certificate)) {
        List certificatesChains =
            (List) certificateFactory.generateCertificates(in);
        collections.addAll(certificatesChains);
      }
    }
    return collections.toArray(new X509Certificate[collections.size()]);
  }

  private boolean requireClientAuth() {
    if (certificateAuthorities != null) {
      return true;
    }

    return false;
  }

  private FileInputStream createFileInputStream(String filepath) throws FileNotFoundException {
    return new FileInputStream(filepath);
  }

  /**
   * Get the supported protocols
   *
   * @return a defensive copy of the supported protocols
   */
  String[] getProtocols() {
    return protocols.clone();
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy