protected SSLEngine createSSLEngine(String sniHostName, List<Cipher> clientRequestedCiphers) {
    SSLHostConfig sslHostConfig = getSSLHostConfig(sniHostName);

    SSLHostConfigCertificate certificate = selectCertificate(sslHostConfig, clientRequestedCiphers);

    SSLContextWrapper sslContextWrapper = certificate.getSslContextWrapper();
    if (sslContextWrapper == null) {
      throw new IllegalStateException(sm.getString("endpoint.jsse.noSslContext", sniHostName));
    }

    SSLEngine engine = sslContextWrapper.getSSLContext().createSSLEngine();
    switch (sslHostConfig.getCertificateVerification()) {
      case NONE:
        engine.setNeedClientAuth(false);
        engine.setWantClientAuth(false);
        break;
      case OPTIONAL:
      case OPTIONAL_NO_CA:
        engine.setWantClientAuth(true);
        break;
      case REQUIRED:
        engine.setNeedClientAuth(true);
        break;
    }
    engine.setUseClientMode(false);
    engine.setEnabledCipherSuites(sslContextWrapper.getEnabledCiphers());
    engine.setEnabledProtocols(sslContextWrapper.getEnabledProtocols());

    SSLParameters sslParameters = engine.getSSLParameters();
    sslParameters.setUseCipherSuitesOrder(sslHostConfig.getHonorCipherOrder());
    // In case the getter returns a defensive copy
    engine.setSSLParameters(sslParameters);

    return engine;
  }
Exemple #2
0
  /**
   * Tests opening an SSL/TLS connection to redis using the loopback address of 127.0.0.1. This test
   * should fail because "127.0.0.1" does not match the certificate subject common name and there
   * are no subject alternative names in the certificate.
   *
   * <p>NOTE: This test relies on a feature that is only available as of Java 7 and later. It is
   * commented out but not removed in case support for Java 6 is dropped or we find a way to have
   * the CI run a specific set of tests on Java 7 and above.
   */
  @Test
  public void connectWithShardInfoByIpAddress() throws Exception {
    final URI uri = URI.create("rediss://127.0.0.1:6390");
    final SSLSocketFactory sslSocketFactory = createTrustStoreSslSocketFactory();
    // These SSL parameters ensure that we use the same hostname verifier used
    // for HTTPS.
    // Note: this options is only available in Java 7.
    final SSLParameters sslParameters = new SSLParameters();
    sslParameters.setEndpointIdentificationAlgorithm("HTTPS");

    JedisShardInfo shardInfo = new JedisShardInfo(uri, sslSocketFactory, sslParameters, null);
    shardInfo.setPassword("foobared");

    Jedis jedis = new Jedis(shardInfo);
    try {
      jedis.get("foo");
      Assert.fail("The code did not throw the expected JedisConnectionException.");
    } catch (JedisConnectionException e) {
      Assert.assertEquals(
          "Unexpected first inner exception.",
          SSLHandshakeException.class,
          e.getCause().getClass());
      Assert.assertEquals(
          "Unexpected second inner exception.",
          CertificateException.class,
          e.getCause().getCause().getClass());
    }

    try {
      jedis.close();
    } catch (Throwable e1) {
      // Expected.
    }
  }
  /**
   * Returns server ssl engine.
   *
   * @param context - SSLContext to get SSLEngine from.
   * @param useSNI - flag used to enable or disable using SNI extension. Needed for Kerberos.
   */
  public static SSLEngine getServerSSLEngine(SSLContext context, boolean useSNI) {

    SSLEngine serverEngine = context.createSSLEngine();
    serverEngine.setUseClientMode(false);
    if (useSNI) {
      SNIMatcher matcher = SNIHostName.createSNIMatcher(SNI_PATTERN);
      List<SNIMatcher> matchers = new ArrayList<>();
      matchers.add(matcher);
      SSLParameters params = serverEngine.getSSLParameters();
      params.setSNIMatchers(matchers);
      serverEngine.setSSLParameters(params);
    }
    return serverEngine;
  }
  /**
   * Returns client ssl engine.
   *
   * @param context - SSLContext to get SSLEngine from.
   * @param useSNI - flag used to enable or disable using SNI extension. Needed for Kerberos.
   */
  public static SSLEngine getClientSSLEngine(SSLContext context, boolean useSNI) {

    SSLEngine clientEngine = context.createSSLEngine(HOST, 80);
    clientEngine.setUseClientMode(true);
    if (useSNI) {
      SNIHostName serverName = new SNIHostName(SERVER_NAME);
      List<SNIServerName> serverNames = new ArrayList<>();
      serverNames.add(serverName);
      SSLParameters params = clientEngine.getSSLParameters();
      params.setServerNames(serverNames);
      clientEngine.setSSLParameters(params);
    }
    return clientEngine;
  }
Exemple #5
0
  /**
   * Get a <code>List</code> of available <code>Version</code> objects. The list will be sorted in
   * ascending order, so currently "TLSv1.2" will be the last element.
   *
   * @return a sorted list of supported <code>Version</code>s
   */
  private static List<Version> getVersions() {
    SSLParameters sslParams;
    List<Version> versions = new ArrayList<Version>();
    try {
      sslParams = SSLContext.getDefault().getSupportedSSLParameters();
      String[] protocols = sslParams.getProtocols();
      for (int i = 0; i < protocols.length; ++i) {
        if (protocols[i].startsWith("TLS")) versions.add(new Version(protocols[i]));
      }

      Collections.sort(versions);
    } catch (NoSuchAlgorithmException e) {
      e.printStackTrace();
      System.err.println("this client does not support TLS 1.2");
    }

    return versions;
  }
Exemple #6
0
  /**
   * Tests opening an SSL/TLS connection to redis. NOTE: This test relies on a feature that is only
   * available as of Java 7 and later. It is commented out but not removed in case support for Java
   * 6 is dropped or we find a way to have the CI run a specific set of tests on Java 7 and above.
   */
  @Test
  public void connectWithShardInfo() throws Exception {
    final URI uri = URI.create("rediss://localhost:6390");
    final SSLSocketFactory sslSocketFactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
    // These SSL parameters ensure that we use the same hostname verifier used
    // for HTTPS.
    // Note: this options is only available in Java 7.
    final SSLParameters sslParameters = new SSLParameters();
    sslParameters.setEndpointIdentificationAlgorithm("HTTPS");

    JedisShardInfo shardInfo = new JedisShardInfo(uri, sslSocketFactory, sslParameters, null);
    shardInfo.setPassword("foobared");

    Jedis jedis = new Jedis(shardInfo);
    jedis.get("foo");
    jedis.disconnect();
    jedis.close();
  }
Exemple #7
0
    /** {@inheritDoc} */
    public void configure(HttpsParameters params) {
      // initialise the SSL context
      SSLEngine engine = context.createSSLEngine();
      // get the default parameters
      SSLParameters defaultSSLParameters = context.getDefaultSSLParameters();

      // Cert authentication is delayed later to the ClientCertAuthenticator
      params.setWantClientAuth(serverConfig.useSslClientAuthentication());
      defaultSSLParameters.setWantClientAuth(serverConfig.useSslClientAuthentication());

      // Cipher Suites
      params.setCipherSuites(serverConfig.getSSLCipherSuites());
      defaultSSLParameters.setCipherSuites(serverConfig.getSSLCipherSuites());

      // Protocols
      params.setProtocols(serverConfig.getSSLProtocols());
      defaultSSLParameters.setProtocols(serverConfig.getSSLProtocols());

      params.setSSLParameters(defaultSSLParameters);
    }
  /**
   * Does the handshake of the two specified engines according to the {@code mode} specified.
   *
   * @param clientEngine - Client SSLEngine.
   * @param serverEngine - Server SSLEngine.
   * @param maxPacketSize - Maximum packet size for MFLN of zero for no limit.
   * @param mode - Handshake mode according to {@link HandshakeMode} enum.
   * @param enableReplicatedPacks - Set {@code true} to enable replicated packet sending.
   * @throws SSLException - thrown on engine errors.
   */
  public static void doHandshake(
      SSLEngine clientEngine,
      SSLEngine serverEngine,
      int maxPacketSize,
      HandshakeMode mode,
      boolean enableReplicatedPacks)
      throws SSLException {

    System.out.println("=============================================");
    System.out.println("Starting handshake " + mode.name());
    int loop = 0;
    if (maxPacketSize < 0) {
      throw new Error("Test issue: maxPacketSize is less than zero!");
    }
    SSLParameters params = clientEngine.getSSLParameters();
    params.setMaximumPacketSize(maxPacketSize);
    clientEngine.setSSLParameters(params);
    params = serverEngine.getSSLParameters();
    params.setMaximumPacketSize(maxPacketSize);
    serverEngine.setSSLParameters(params);
    SSLEngine firstEngine;
    SSLEngine secondEngine;
    switch (mode) {
      case INITIAL_HANDSHAKE:
        firstEngine = clientEngine;
        secondEngine = serverEngine;
        doUnwrapForNotHandshakingStatus = false;
        clientEngine.beginHandshake();
        serverEngine.beginHandshake();
        break;
      case REHANDSHAKE_BEGIN_CLIENT:
        firstEngine = clientEngine;
        secondEngine = serverEngine;
        doUnwrapForNotHandshakingStatus = true;
        clientEngine.beginHandshake();
        break;
      case REHANDSHAKE_BEGIN_SERVER:
        firstEngine = serverEngine;
        secondEngine = clientEngine;
        doUnwrapForNotHandshakingStatus = true;
        serverEngine.beginHandshake();
        break;
      default:
        throw new Error("Test issue: unknown handshake mode");
    }
    endHandshakeLoop = false;
    while (!endHandshakeLoop) {
      if (++loop > MAX_HANDSHAKE_LOOPS) {
        throw new Error("Too much loops for handshaking");
      }
      System.out.println("============================================");
      System.out.println("Handshake loop " + loop + ": round 1");
      System.out.println("==========================");
      handshakeProcess(firstEngine, secondEngine, maxPacketSize, enableReplicatedPacks);
      if (endHandshakeLoop) {
        break;
      }
      System.out.println("Handshake loop " + loop + ": round 2");
      System.out.println("==========================");
      handshakeProcess(secondEngine, firstEngine, maxPacketSize, enableReplicatedPacks);
    }
  }
    @Override
    protected void initChannel(Channel channel) throws Exception {
      SslContext sslContext;

      SSLParameters sslParams = new SSLParameters();

      if (redisURI.isVerifyPeer()) {
        sslContext = SslContext.newClientContext(SslProvider.JDK);
        if (JavaRuntime.AT_LEAST_JDK_7) {
          sslParams.setEndpointIdentificationAlgorithm("HTTPS");
        }
      } else {
        sslContext =
            SslContext.newClientContext(SslProvider.JDK, InsecureTrustManagerFactory.INSTANCE);
      }

      SSLEngine sslEngine =
          sslContext.newEngine(channel.alloc(), redisURI.getHost(), redisURI.getPort());
      sslEngine.setSSLParameters(sslParams);

      removeIfExists(channel.pipeline(), SslHandler.class);

      if (channel.pipeline().get("first") == null) {
        channel
            .pipeline()
            .addFirst(
                "first",
                new ChannelDuplexHandler() {

                  @Override
                  public void channelActive(ChannelHandlerContext ctx) throws Exception {
                    eventBus.publish(new ConnectedEvent(local(ctx), remote(ctx)));
                    super.channelActive(ctx);
                  }

                  @Override
                  public void channelInactive(ChannelHandlerContext ctx) throws Exception {
                    eventBus.publish(new DisconnectedEvent(local(ctx), remote(ctx)));
                    super.channelInactive(ctx);
                  }
                });
      }

      SslHandler sslHandler = new SslHandler(sslEngine, redisURI.isStartTls());
      channel.pipeline().addLast(sslHandler);
      if (channel.pipeline().get("channelActivator") == null) {
        channel
            .pipeline()
            .addLast(
                "channelActivator",
                new RedisChannelInitializerImpl() {

                  private Command<?, ?, ?> pingCommand;

                  @Override
                  public Future<Boolean> channelInitialized() {
                    return initializedFuture;
                  }

                  @Override
                  public void channelInactive(ChannelHandlerContext ctx) throws Exception {
                    initializedFuture = SettableFuture.create();
                    pingCommand = null;
                    super.channelInactive(ctx);
                  }

                  @Override
                  public void channelActive(ChannelHandlerContext ctx) throws Exception {
                    if (initializedFuture.isDone()) {
                      super.channelActive(ctx);
                    }
                  }

                  @Override
                  public void userEventTriggered(ChannelHandlerContext ctx, Object evt)
                      throws Exception {
                    if (evt instanceof SslHandshakeCompletionEvent && !initializedFuture.isDone()) {

                      SslHandshakeCompletionEvent event = (SslHandshakeCompletionEvent) evt;
                      if (event.isSuccess()) {
                        if (pingBeforeActivate) {
                          pingCommand = INITIALIZING_CMD_BUILDER.ping();
                          pingBeforeActivate(pingCommand, initializedFuture, ctx, handlers);
                        } else {
                          ctx.fireChannelActive();
                        }
                      } else {
                        initializedFuture.setException(event.cause());
                      }
                    }

                    if (evt instanceof ConnectionEvents.Close) {
                      if (ctx.channel().isOpen()) {
                        ctx.channel().close();
                      }
                    }

                    if (evt instanceof ConnectionEvents.Activated) {
                      if (!initializedFuture.isDone()) {
                        initializedFuture.set(true);
                        eventBus.publish(new ConnectionActivatedEvent(local(ctx), remote(ctx)));
                      }
                    }

                    super.userEventTriggered(ctx, evt);
                  }

                  @Override
                  public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
                      throws Exception {

                    if (!initializedFuture.isDone()) {
                      initializedFuture.setException(cause);
                    }
                    super.exceptionCaught(ctx, cause);
                  }
                });
      }

      for (ChannelHandler handler : handlers) {
        removeIfExists(channel.pipeline(), handler.getClass());
        channel.pipeline().addLast(handler);
      }
    }
  @Override
  public List<Attribute> getMonitorData() {
    ArrayList<Attribute> attrs = new ArrayList<>(13);

    attrs.add(createAttribute("javaVersion", System.getProperty("java.version")));
    attrs.add(createAttribute("javaVendor", System.getProperty("java.vendor")));
    attrs.add(createAttribute("jvmVersion", System.getProperty("java.vm.version")));
    attrs.add(createAttribute("jvmVendor", System.getProperty("java.vm.vendor")));
    attrs.add(createAttribute("javaHome", System.getProperty("java.home")));
    attrs.add(createAttribute("classPath", System.getProperty("java.class.path")));
    attrs.add(createAttribute("workingDirectory", System.getProperty("user.dir")));

    String osInfo =
        System.getProperty("os.name")
            + " "
            + System.getProperty("os.version")
            + " "
            + System.getProperty("os.arch");
    attrs.add(createAttribute("operatingSystem", osInfo));
    String sunOsArchDataModel = System.getProperty("sun.arch.data.model");
    if (sunOsArchDataModel != null) {
      String jvmArch = sunOsArchDataModel;
      if (!sunOsArchDataModel.toLowerCase().equals("unknown")) {
        jvmArch += "-bit";
      }
      attrs.add(createAttribute("jvmArchitecture", jvmArch));
    } else {
      attrs.add(createAttribute("jvmArchitecture", "unknown"));
    }

    try {
      attrs.add(createAttribute("systemName", InetAddress.getLocalHost().getCanonicalHostName()));
    } catch (Exception e) {
      logger.traceException(e);
    }

    Runtime runtime = Runtime.getRuntime();
    attrs.add(createAttribute("availableCPUs", runtime.availableProcessors()));
    attrs.add(createAttribute("maxMemory", runtime.maxMemory()));
    attrs.add(createAttribute("usedMemory", runtime.totalMemory()));
    attrs.add(createAttribute("freeUsedMemory", runtime.freeMemory()));
    String installPath = DirectoryServer.getServerRoot();
    if (installPath != null) {
      attrs.add(createAttribute("installPath", installPath));
    }
    String instancePath = DirectoryServer.getInstanceRoot();
    if (instancePath != null) {
      attrs.add(createAttribute("instancePath", instancePath));
    }

    // Get the JVM input arguments.
    RuntimeMXBean rtBean = ManagementFactory.getRuntimeMXBean();
    List<String> jvmArguments = rtBean.getInputArguments();
    if (jvmArguments != null && !jvmArguments.isEmpty()) {
      StringBuilder argList = new StringBuilder();
      for (String jvmArg : jvmArguments) {
        if (argList.length() > 0) {
          argList.append(" ");
        }

        argList.append("\"");
        argList.append(jvmArg);
        argList.append("\"");
      }

      attrs.add(createAttribute("jvmArguments", argList.toString()));
    }

    // Get the list of supported SSL protocols and ciphers.
    Collection<String> supportedTlsProtocols;
    Collection<String> supportedTlsCiphers;
    try {
      final SSLContext context = SSLContext.getDefault();
      final SSLParameters parameters = context.getSupportedSSLParameters();
      supportedTlsProtocols = Arrays.asList(parameters.getProtocols());
      supportedTlsCiphers = Arrays.asList(parameters.getCipherSuites());
    } catch (Exception e) {
      // A default SSL context should always be available.
      supportedTlsProtocols = Collections.emptyList();
      supportedTlsCiphers = Collections.emptyList();
    }

    addAttribute(attrs, ATTR_SUPPORTED_TLS_PROTOCOLS, supportedTlsProtocols);
    addAttribute(attrs, ATTR_SUPPORTED_TLS_CIPHERS, supportedTlsCiphers);

    return attrs;
  }