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

org.glassfish.tyrus.client.SslEngineConfigurator Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2008, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package org.glassfish.tyrus.client;

import java.util.ArrayList;
import java.util.Arrays;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;

/**
 * SSLEngineConfigurator class from Grizzly project.
 * 

* Utility class, which helps to configure {@link SSLEngine}. Should be passed to client via configuration properties. * Example: *

 *      SslContextConfigurator sslContextConfigurator = new SslContextConfigurator();
 *      sslContextConfigurator.setTrustStoreFile("...");
 *      sslContextConfigurator.setTrustStorePassword("...");
 *      sslContextConfigurator.setTrustStoreType("...");
 *      sslContextConfigurator.setKeyStoreFile("...");
 *      sslContextConfigurator.setKeyStorePassword("...");
 *      sslContextConfigurator.setKeyStoreType("...");
 *      SslEngineConfigurator sslEngineConfigurator = new SslEngineConfigurator(sslContextConfigurator, true, false,
 * false);
 *      client.getProperties().put(ClientManager.SSL_ENGINE_CONFIGURATOR, sslEngineConfigurator);
 * 
* * @author Alexey Stashok */ public class SslEngineConfigurator { private final Object sync = new Object(); protected volatile SslContextConfigurator sslContextConfiguration; protected volatile SSLContext sslContext; /** * The list of cipher suites. */ protected String[] enabledCipherSuites = null; /** * The list of protocols. */ protected String[] enabledProtocols = null; /** * Client mode when handshaking. */ protected boolean clientMode; /** * Require client Authentication. */ protected boolean needClientAuth; /** * True when requesting authentication. */ protected boolean wantClientAuth; /** * Has the enabled protocol configured. */ private boolean isProtocolConfigured = false; /** * Has the enabled Cipher configured. */ private boolean isCipherConfigured = false; /** * {@code true} if host should be verified. */ private boolean hostVerificationEnabled = true; /** * A custom hostname verifier. */ private HostnameVerifier hostnameVerifier = null; /** * Create SSL Engine configuration basing on passed {@link SSLContext}. * * @param sslContext {@link SSLContext}. */ public SslEngineConfigurator(SSLContext sslContext) { this(sslContext, true, false, false); } /** * Create SSL Engine configuration based on passed {@link SSLContext}, * using passed client mode, need/want client auth parameters. * * @param sslContext {@link SSLContext}. * @param clientMode will be configured to work in client mode. * @param needClientAuth client authentication is required. * @param wantClientAuth client should authenticate. */ public SslEngineConfigurator(final SSLContext sslContext, final boolean clientMode, final boolean needClientAuth, final boolean wantClientAuth) { if (sslContext == null) { throw new IllegalArgumentException("SSLContext can not be null"); } this.sslContextConfiguration = null; this.sslContext = sslContext; this.clientMode = clientMode; this.needClientAuth = needClientAuth; this.wantClientAuth = wantClientAuth; } /** * Create SSL Engine configuration based on passed {@link SslContextConfigurator}. * This constructor makes possible to initialize SSLEngine and SSLContext in lazy * fashion on first {@link #createSSLEngine(String)} call. * * @param sslContextConfiguration {@link SslContextConfigurator}. */ public SslEngineConfigurator(SslContextConfigurator sslContextConfiguration) { this(sslContextConfiguration, true, false, false); } /** * Create SSL Engine configuration basing on passed {@link SslContextConfigurator}. * This constructor makes possible to initialize SSLEngine and SSLContext in lazy * fashion on first {@link #createSSLEngine(String)} call. * * @param sslContextConfiguration {@link SslContextConfigurator}. * @param clientMode will be configured to work in client mode. * @param needClientAuth client authentication is required. * @param wantClientAuth client should authenticate. */ public SslEngineConfigurator(SslContextConfigurator sslContextConfiguration, boolean clientMode, boolean needClientAuth, boolean wantClientAuth) { if (sslContextConfiguration == null) { throw new IllegalArgumentException("SSLContextConfigurator can not be null"); } this.sslContextConfiguration = sslContextConfiguration; this.clientMode = clientMode; this.needClientAuth = needClientAuth; this.wantClientAuth = wantClientAuth; } /** * Copy constructor. * * @param original original {@link SslEngineConfigurator} instance to be copied. */ public SslEngineConfigurator(SslEngineConfigurator original) { this.sslContextConfiguration = original.sslContextConfiguration; this.sslContext = original.sslContext; this.clientMode = original.clientMode; this.needClientAuth = original.needClientAuth; this.wantClientAuth = original.wantClientAuth; this.enabledCipherSuites = original.enabledCipherSuites; this.enabledProtocols = original.enabledProtocols; this.isCipherConfigured = original.isCipherConfigured; this.isProtocolConfigured = original.isProtocolConfigured; } /** * Default constructor. */ protected SslEngineConfigurator() { } /** * Create and configure {@link SSLEngine}, based on current settings. * * @param serverHost server host, which will be used to verify authenticity of the server (the provided host name * will * compared to the host in the certificate provided by the server). * @return {@link SSLEngine}. */ public SSLEngine createSSLEngine(String serverHost) { if (sslContext == null) { synchronized (sync) { if (sslContext == null) { sslContext = sslContextConfiguration.createSSLContext(); } } } /* the port is not part of host name verification, it is present in the constructor because of Kerberos (which is not supported by Tyrus) */ final SSLEngine sslEngine = sslContext.createSSLEngine(serverHost, -1); configure(sslEngine); return sslEngine; } /** * Configure passed {@link SSLEngine}, using current configurator settings, excluding Hostname Verification. * * @param sslEngine {@link SSLEngine} to configure. * @return configured {@link SSLEngine}. */ public SSLEngine configure(final SSLEngine sslEngine) { if (enabledCipherSuites != null) { if (!isCipherConfigured) { enabledCipherSuites = configureEnabledCiphers(sslEngine, enabledCipherSuites); isCipherConfigured = true; } sslEngine.setEnabledCipherSuites(enabledCipherSuites); } if (enabledProtocols != null) { if (!isProtocolConfigured) { enabledProtocols = configureEnabledProtocols(sslEngine, enabledProtocols); isProtocolConfigured = true; } sslEngine.setEnabledProtocols(enabledProtocols); } sslEngine.setUseClientMode(clientMode); if (wantClientAuth) { sslEngine.setWantClientAuth(true); } if (needClientAuth) { sslEngine.setNeedClientAuth(true); } return sslEngine; } /** * Will {@link SSLEngine} be configured to work in client mode. * * @return true, if {@link SSLEngine} will be configured to work * in client mode, or false for server mode. */ public boolean isClientMode() { return clientMode; } /** * Set {@link SSLEngine} to be configured to work in client mode. * * @param clientMode true, if {@link SSLEngine} will be configured * to work in client mode, or false for server * mode. * @return updated {@link SslEngineConfigurator}. */ public SslEngineConfigurator setClientMode(boolean clientMode) { this.clientMode = clientMode; return this; } /** * Get "need client auth" property. * * @return need client auth property value; */ public boolean isNeedClientAuth() { return needClientAuth; } /** * Set "need client auth" property. * * @param needClientAuth value to be set. * @return updated {@link SslEngineConfigurator}. */ public SslEngineConfigurator setNeedClientAuth(boolean needClientAuth) { this.needClientAuth = needClientAuth; return this; } /** * Get "want client auth" property. * * @return need client auth property value; */ public boolean isWantClientAuth() { return wantClientAuth; } /** * Set "want client auth" property. * * @param wantClientAuth value to be set. * @return updated {@link SslEngineConfigurator}. */ public SslEngineConfigurator setWantClientAuth(boolean wantClientAuth) { this.wantClientAuth = wantClientAuth; return this; } /** * Get enabled cipher suites. * * @return {@link String} array with enabled cipher suites. */ public String[] getEnabledCipherSuites() { return enabledCipherSuites.clone(); } /** * Set enabled cipher suites. * * @param enabledCipherSuites {@link String} array with cipher suites. * @return updated {@link SslEngineConfigurator}. */ public SslEngineConfigurator setEnabledCipherSuites(String[] enabledCipherSuites) { this.enabledCipherSuites = enabledCipherSuites.clone(); return this; } /** * Get enabled protocols. * * @return {@link String} array with enabled protocols. */ public String[] getEnabledProtocols() { return enabledProtocols.clone(); } /** * Set enabled protocols. * * @param enabledProtocols {@link String} array with protocols. * @return updated {@link SslEngineConfigurator}. */ public SslEngineConfigurator setEnabledProtocols(String[] enabledProtocols) { this.enabledProtocols = enabledProtocols.clone(); return this; } public boolean isCipherConfigured() { return isCipherConfigured; } public SslEngineConfigurator setCipherConfigured(boolean isCipherConfigured) { this.isCipherConfigured = isCipherConfigured; return this; } public boolean isProtocolConfigured() { return isProtocolConfigured; } public SslEngineConfigurator setProtocolConfigured(boolean isProtocolConfigured) { this.isProtocolConfigured = isProtocolConfigured; return this; } /** * Get the hostname verification state. * * @return {@code true} if the hostname verification is enabled, {@code false} otherwise. */ public boolean isHostVerificationEnabled() { return hostVerificationEnabled; } /** * Set hostname verification. * * @param hostVerificationEnabled when {@code true}, servers hostname will be verified using JDK default * {@link HostnameVerifier}. When {@code false}, hostname verification won't be * performed unless custom {@link HostnameVerifier} is set. * @return updated {@link SslEngineConfigurator}. * @see #setHostnameVerifier(HostnameVerifier) */ public SslEngineConfigurator setHostVerificationEnabled(boolean hostVerificationEnabled) { this.hostVerificationEnabled = hostVerificationEnabled; return this; } /** * Get custom hostname verifier. * * @return user provided hostname verifier instance. */ public HostnameVerifier getHostnameVerifier() { return hostnameVerifier; } /** * Set custom hostname verifier. *

* When custom {@link HostnameVerifier} instance is registered, it will be used to perform hostname verification, * no matter on the state of hostname verification flag (see {@link #isHostVerificationEnabled()}) and JDK default * hostname verifier won't be used. * * @param hostnameVerifier custom hostname verifier. * @return updated {@link SslEngineConfigurator}. */ public SslEngineConfigurator setHostnameVerifier(HostnameVerifier hostnameVerifier) { this.hostnameVerifier = hostnameVerifier; return this; } /** * Create {@link SSLContext} and store it for further invocation of this method. * * @return created ssl context. */ public SSLContext getSslContext() { if (sslContext == null) { synchronized (sync) { if (sslContext == null) { sslContext = sslContextConfiguration.createSSLContext(); } } } return sslContext; } /** * Return the list of allowed protocol. * * @param sslEngine ssl engine. * @param requestedProtocols requested protocols. * @return String[] an array of supported protocols. */ private static String[] configureEnabledProtocols(SSLEngine sslEngine, String[] requestedProtocols) { String[] supportedProtocols = sslEngine.getSupportedProtocols(); String[] protocols = null; ArrayList list = null; for (String supportedProtocol : supportedProtocols) { /* * Check to see if the requested protocol is among the * supported protocols, i.e., may be enabled */ for (String protocol : requestedProtocols) { protocol = protocol.trim(); if (supportedProtocol.equals(protocol)) { if (list == null) { list = new ArrayList(); } list.add(protocol); break; } } } if (list != null) { protocols = list.toArray(new String[list.size()]); } return protocols; } /** * Determines the SSL cipher suites to be enabled. * * @param sslEngine ssl engine. * @param requestedCiphers requested ciphers. * @return Array of SSL cipher suites to be enabled, or null if none of the * requested ciphers are supported. */ private static String[] configureEnabledCiphers(SSLEngine sslEngine, String[] requestedCiphers) { String[] supportedCiphers = sslEngine.getSupportedCipherSuites(); String[] ciphers = null; ArrayList list = null; for (String supportedCipher : supportedCiphers) { /* * Check to see if the requested protocol is among the * supported protocols, i.e., may be enabled */ for (String cipher : requestedCiphers) { cipher = cipher.trim(); if (supportedCipher.equals(cipher)) { if (list == null) { list = new ArrayList(); } list.add(cipher); break; } } } if (list != null) { ciphers = list.toArray(new String[list.size()]); } return ciphers; } @Override public String toString() { final StringBuilder sb = new StringBuilder(); sb.append("SSLEngineConfigurator"); sb.append("{clientMode=").append(clientMode); sb.append(", enabledCipherSuites=") .append(enabledCipherSuites == null ? "null" : Arrays.asList(enabledCipherSuites).toString()); sb.append(", enabledProtocols=") .append(enabledProtocols == null ? "null" : Arrays.asList(enabledProtocols).toString()); sb.append(", needClientAuth=").append(needClientAuth); sb.append(", wantClientAuth=").append(wantClientAuth); sb.append(", isProtocolConfigured=").append(isProtocolConfigured); sb.append(", isCipherConfigured=").append(isCipherConfigured); sb.append(", hostVerificationEnabled=").append(hostVerificationEnabled); sb.append('}'); return sb.toString(); } public SslEngineConfigurator copy() { return new SslEngineConfigurator(this); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy