Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.openehealth.ipf.commons.audit.CustomTlsParameters Maven / Gradle / Ivy
/*
* Copyright 2020 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.openehealth.ipf.commons.audit;
import io.vertx.core.net.JksOptions;
import io.vertx.core.net.NetClientOptions;
import io.vertx.core.net.PfxOptions;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SNIHostName;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLContextSpi;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSessionContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509ExtendedKeyManager;
import javax.net.ssl.X509KeyManager;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.Principal;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.openehealth.ipf.commons.audit.protocol.AuditTransmissionProtocol.HTTPS_CIPHERSUITES;
import static org.openehealth.ipf.commons.audit.protocol.AuditTransmissionProtocol.JAVAX_NET_SSL_KEYSTORE;
import static org.openehealth.ipf.commons.audit.protocol.AuditTransmissionProtocol.JAVAX_NET_SSL_KEYSTORE_PASSWORD;
import static org.openehealth.ipf.commons.audit.protocol.AuditTransmissionProtocol.JAVAX_NET_SSL_KEYSTORE_TYPE;
import static org.openehealth.ipf.commons.audit.protocol.AuditTransmissionProtocol.JAVAX_NET_SSL_TRUSTSTORE;
import static org.openehealth.ipf.commons.audit.protocol.AuditTransmissionProtocol.JAVAX_NET_SSL_TRUSTSTORE_PASSWORD;
import static org.openehealth.ipf.commons.audit.protocol.AuditTransmissionProtocol.JDK_TLS_CLIENT_PROTOCOLS;
/**
* {@link TlsParameters} that can be set independently of the javax.net.ssl system
* properties. Still, a newly instantiated instance of this class defaults to these
* properties.
*/
public class CustomTlsParameters implements VertxTlsParameters {
private String provider = "SunJSSE";
private String tlsProtocol = "TLSv1.2";
private String certificateType = "SunX509";
private String certAlias;
private String keyStoreType;
private String trustStoreType;
private String keyStoreFile;
private String keyStorePassword;
private String trustStoreFile;
private String trustStorePassword;
private String enabledCipherSuites;
private String enabledProtocols;
private int sessionTimeout;
private boolean performDomainValidation;
private final List sniHostnames = new ArrayList<>();
public void setProvider(String provider) {
this.provider = provider;
}
public void setTlsProtocol(String tlsProtocol) {
this.tlsProtocol = tlsProtocol;
}
public void setKeyStoreType(String keyStoreType) {
this.keyStoreType = keyStoreType;
}
public void setTrustStoreType(String trustStoreType) {
this.trustStoreType = trustStoreType;
}
public void setCertificateType(String certificateType) {
this.certificateType = certificateType;
}
public void setCertAlias(String certAlias) {
this.certAlias = certAlias;
}
public void setKeyStoreFile(String keyStoreFile) {
this.keyStoreFile = keyStoreFile;
}
public void setKeyStorePassword(String keyStorePassword) {
this.keyStorePassword = keyStorePassword;
}
public void setTrustStoreFile(String trustStoreFile) {
this.trustStoreFile = trustStoreFile;
}
public void setTrustStorePassword(String trustStorePassword) {
this.trustStorePassword = trustStorePassword;
}
public void setEnabledCipherSuites(String enabledCipherSuites) {
this.enabledCipherSuites = enabledCipherSuites;
}
public void setEnabledProtocols(String enabledProtocols) {
this.enabledProtocols = enabledProtocols;
}
public void setSessionTimeout(int sessionTimeout) {
this.sessionTimeout = sessionTimeout;
}
public void setPerformDomainValidation(boolean performDomainValidation) {
this.performDomainValidation = performDomainValidation;
}
public List getSniHostnames() {
return sniHostnames;
}
public CustomTlsParameters() {
keyStoreType = System.getProperty(JAVAX_NET_SSL_KEYSTORE_TYPE, KeyStore.getDefaultType());
trustStoreType = keyStoreType;
keyStoreFile = System.getProperty(JAVAX_NET_SSL_KEYSTORE);
keyStorePassword = System.getProperty(JAVAX_NET_SSL_KEYSTORE_PASSWORD);
trustStoreFile = System.getProperty(JAVAX_NET_SSL_TRUSTSTORE);
trustStorePassword = System.getProperty(JAVAX_NET_SSL_TRUSTSTORE_PASSWORD);
enabledCipherSuites = System.getProperty(HTTPS_CIPHERSUITES);
enabledProtocols = System.getProperty(JDK_TLS_CLIENT_PROTOCOLS, "TLSv1.2");
}
private Function sslSocketFactoryConfigurer() {
return sslSocketFactory -> new SSLSocketFactoryDecorator(sslSocketFactory, sslSocketConfigurer());
}
private Function sslSocketConfigurer() {
return sslSocket -> {
if (enabledCipherSuites != null) {
sslSocket.setEnabledCipherSuites(split(enabledCipherSuites));
}
if (enabledProtocols != null) {
sslSocket.setEnabledProtocols(split(enabledProtocols));
}
if (sniHostnames.isEmpty()) {
SSLParameters sslParameters = sslSocket.getSSLParameters();
sslParameters.setServerNames(sniHostnames.stream()
.map(SNIHostName::new)
.collect(Collectors.toList()));
sslSocket.setSSLParameters(sslParameters);
}
if (performDomainValidation) {
SSLParameters sslParameters = sslSocket.getSSLParameters();
sslParameters.setEndpointIdentificationAlgorithm("HTTPS");
sslSocket.setSSLParameters(sslParameters);
}
return sslSocket;
};
}
private Function sslEngineConfigurer() {
return sslEngine -> {
if (enabledCipherSuites != null) {
sslEngine.setEnabledCipherSuites(split(enabledCipherSuites));
}
if (enabledProtocols != null) {
sslEngine.setEnabledProtocols(split(enabledProtocols));
}
return sslEngine;
};
}
private String[] split(String s) {
return s.split("\\s*,\\s*");
}
@Override
public SSLContext getSSLContext() {
try {
KeyStore keyStore = getKeyStore(keyStoreType, keyStoreFile, keyStorePassword);
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(certificateType, provider);
keyManagerFactory.init(keyStore, keyStorePassword.toCharArray());
KeyManager[] keyManagers = keyManagerFactory.getKeyManagers();
if (keyManagers != null && certAlias != null) {
for (int i = 0; i < keyManagers.length; i++) {
if (keyManagers[i] instanceof X509KeyManager) {
keyManagers[i] = new AliasX509ExtendedKeyManager((X509KeyManager) keyManagers[i], certAlias);
}
}
}
KeyStore trustStore = getKeyStore(trustStoreType, trustStoreFile, trustStorePassword);
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(certificateType, provider);
trustManagerFactory.init(trustStore);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
SecureRandom secureRandom = new SecureRandom();
SSLContext sslContext = SSLContext.getInstance(tlsProtocol, provider);
sslContext.init(keyManagers, trustManagers, secureRandom);
if (sessionTimeout > 0) {
sslContext.getClientSessionContext().setSessionTimeout(sessionTimeout);
}
return new CustomSSLContext(new SSLContextSpiDecorator(
sslContext,
sslEngineConfigurer(),
sslSocketFactoryConfigurer()));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public void initNetClientOptions(NetClientOptions options) {
if ("JKS".equalsIgnoreCase(keyStoreType)) {
options.setKeyStoreOptions(new JksOptions()
.setPath(keyStoreFile)
.setPassword(keyStorePassword));
} else {
options.setPfxKeyCertOptions(new PfxOptions()
.setPath(keyStoreFile)
.setPassword(keyStorePassword));
}
if ("JKS".equalsIgnoreCase(trustStoreType)) {
options.setTrustStoreOptions(new JksOptions()
.setPath(trustStoreFile)
.setPassword(trustStorePassword));
} else {
options.setPfxTrustOptions(new PfxOptions()
.setPath(trustStoreFile)
.setPassword(trustStorePassword));
}
Stream.of(split(enabledProtocols))
.forEach(options::addEnabledSecureTransportProtocol);
if (enabledCipherSuites != null) {
Stream.of(split(enabledCipherSuites))
.forEach(options::addEnabledCipherSuite);
}
}
private KeyStore getKeyStore(String type, String storePath, String password) throws Exception {
KeyStore keyStore = KeyStore.getInstance(type);
try (InputStream in = Files.newInputStream(Paths.get(storePath))) {
keyStore.load(in, password.toCharArray());
return keyStore;
}
}
private static final class CustomSSLContext extends SSLContext {
CustomSSLContext(SSLContextSpiDecorator sslContextSpiDecorator) {
super(sslContextSpiDecorator,
sslContextSpiDecorator.getDelegate().getProvider(),
sslContextSpiDecorator.getDelegate().getProtocol());
}
}
private static final class SSLContextSpiDecorator extends SSLContextSpi {
private final SSLContext sslContext;
private final Function sslEngineConfigurer;
private final Function sslSocketFactoryConfigurer;
public SSLContextSpiDecorator(SSLContext sslContext,
Function sslEngineConfigurer,
Function sslSocketFactoryConfigurer) {
this.sslContext = sslContext;
this.sslEngineConfigurer = sslEngineConfigurer;
this.sslSocketFactoryConfigurer = sslSocketFactoryConfigurer;
}
SSLContext getDelegate() {
return sslContext;
}
@Override
protected void engineInit(KeyManager[] keyManagers,
TrustManager[] trustManagers,
SecureRandom secureRandom) throws KeyManagementException {
sslContext.init(keyManagers, trustManagers, secureRandom);
}
@Override
protected SSLSocketFactory engineGetSocketFactory() {
SSLSocketFactory factory = sslContext.getSocketFactory();
return sslSocketFactoryConfigurer.apply(factory);
}
@Override
protected SSLServerSocketFactory engineGetServerSocketFactory() {
throw new UnsupportedOperationException();
}
@Override
protected SSLEngine engineCreateSSLEngine() {
SSLEngine engine = sslContext.createSSLEngine();
return sslEngineConfigurer.apply(engine);
}
@Override
protected SSLEngine engineCreateSSLEngine(String host, int port) {
SSLEngine engine = sslContext.createSSLEngine(host, port);
return sslEngineConfigurer.apply(engine);
}
@Override
protected SSLSessionContext engineGetServerSessionContext() {
return sslContext.getServerSessionContext();
}
@Override
protected SSLSessionContext engineGetClientSessionContext() {
return sslContext.getClientSessionContext();
}
}
private static final class SSLSocketFactoryDecorator extends SSLSocketFactory {
private final SSLSocketFactory delegate;
private final Function sslSocketConfigurer;
public SSLSocketFactoryDecorator(SSLSocketFactory delegate, Function sslSocketConfigurer) {
this.delegate = delegate;
this.sslSocketConfigurer = sslSocketConfigurer;
}
@Override
public String[] getDefaultCipherSuites() {
return delegate.getDefaultCipherSuites();
}
@Override
public String[] getSupportedCipherSuites() {
return delegate.getSupportedCipherSuites();
}
@Override
public Socket createSocket() throws IOException {
return configureSocket(delegate.createSocket());
}
@Override
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
return configureSocket(delegate.createSocket(s, host, port, autoClose));
}
@Override
public Socket createSocket(String host, int port) throws IOException {
return configureSocket(delegate.createSocket(host, port));
}
@Override
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException {
return configureSocket(delegate.createSocket(host, port, localHost, localPort));
}
@Override
public Socket createSocket(InetAddress host, int port) throws IOException {
return configureSocket(delegate.createSocket(host, port));
}
@Override
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
return configureSocket(delegate.createSocket(address, port, localAddress, localPort));
}
public SSLSocketFactory getDelegate() {
return this.delegate;
}
private Socket configureSocket(Socket s) {
SSLSocket socket = (SSLSocket) s;
return sslSocketConfigurer.apply(socket);
}
}
private static final class AliasX509ExtendedKeyManager extends X509ExtendedKeyManager {
private final String certAlias;
private final X509KeyManager keyManager;
public AliasX509ExtendedKeyManager(X509KeyManager keyManager, String certAlias) {
this.keyManager = keyManager;
this.certAlias = certAlias;
}
public String chooseClientAlias(String[] keyTypes, Principal[] issuers, Socket socket) {
return certAlias != null ? certAlias : keyManager.chooseClientAlias(keyTypes, issuers, socket);
}
public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket) {
return certAlias != null ? certAlias : keyManager.chooseServerAlias(keyType, issuers, socket);
}
@Override
public String chooseEngineServerAlias(String keyType, Principal[] issuers, SSLEngine engine) {
return certAlias != null ? certAlias : super.chooseEngineServerAlias(keyType, issuers, engine);
}
@Override
public String chooseEngineClientAlias(String[] keyTypes, Principal[] issuers, SSLEngine engine) {
return certAlias != null ? certAlias : super.chooseEngineClientAlias(keyTypes, issuers, engine);
}
public String[] getClientAliases(String keyType, Principal[] issuers) {
return keyManager.getClientAliases(keyType, issuers);
}
public String[] getServerAliases(String keyType, Principal[] issuers) {
return keyManager.getServerAliases(keyType, issuers);
}
public X509Certificate[] getCertificateChain(String alias) {
return keyManager.getCertificateChain(alias);
}
public PrivateKey getPrivateKey(String alias) {
return keyManager.getPrivateKey(alias);
}
}
}