All Downloads are FREE. Search and download functionalities are using the official Maven repository.
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.
com.arangodb.shaded.vertx.core.net.impl.SSLHelper Maven / Gradle / Ivy
/*
* Copyright (c) 2011-2019 Contributors to the Eclipse Foundation
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
* which is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
*/
package com.arangodb.shaded.vertx.core.net.impl;
import com.arangodb.shaded.netty.handler.ssl.OpenSsl;
import com.arangodb.shaded.netty.handler.ssl.SslProvider;
import com.arangodb.shaded.vertx.core.Future;
import com.arangodb.shaded.vertx.core.Promise;
import com.arangodb.shaded.vertx.core.VertxException;
import com.arangodb.shaded.vertx.core.buffer.Buffer;
import com.arangodb.shaded.vertx.core.http.ClientAuth;
import com.arangodb.shaded.vertx.core.impl.ContextInternal;
import com.arangodb.shaded.vertx.core.net.ClientOptionsBase;
import com.arangodb.shaded.vertx.core.net.JdkSSLEngineOptions;
import com.arangodb.shaded.vertx.core.net.KeyCertOptions;
import com.arangodb.shaded.vertx.core.net.NetClientOptions;
import com.arangodb.shaded.vertx.core.net.NetServerOptions;
import com.arangodb.shaded.vertx.core.net.OpenSSLEngineOptions;
import com.arangodb.shaded.vertx.core.net.SSLEngineOptions;
import com.arangodb.shaded.vertx.core.net.SSLOptions;
import com.arangodb.shaded.vertx.core.net.TCPSSLOptions;
import com.arangodb.shaded.vertx.core.net.TrustOptions;
import com.arangodb.shaded.vertx.core.spi.tls.DefaultSslContextFactory;
import com.arangodb.shaded.vertx.core.spi.tls.SslContextFactory;
import javax.net.ssl.*;
import java.io.ByteArrayInputStream;
import java.security.cert.CRL;
import java.security.cert.CertificateFactory;
import java.util.*;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
/**
* @author Tim Fox
* @author Julien Viet
*/
public class SSLHelper {
static final EnumMap CLIENT_AUTH_MAPPING = new EnumMap<>(ClientAuth.class);
static {
CLIENT_AUTH_MAPPING.put(ClientAuth.REQUIRED, io.netty.handler.ssl.ClientAuth.REQUIRE);
CLIENT_AUTH_MAPPING.put(ClientAuth.REQUEST, io.netty.handler.ssl.ClientAuth.OPTIONAL);
CLIENT_AUTH_MAPPING.put(ClientAuth.NONE, io.netty.handler.ssl.ClientAuth.NONE);
}
/**
* Resolve the ssl engine options to use for properly running the configured options.
*/
public static SSLEngineOptions resolveEngineOptions(SSLEngineOptions engineOptions, boolean useAlpn) {
if (engineOptions == null) {
if (useAlpn) {
if (JdkSSLEngineOptions.isAlpnAvailable()) {
engineOptions = new JdkSSLEngineOptions();
} else if (OpenSSLEngineOptions.isAlpnAvailable()) {
engineOptions = new OpenSSLEngineOptions();
}
}
}
if (engineOptions == null) {
engineOptions = new JdkSSLEngineOptions();
} else if (engineOptions instanceof OpenSSLEngineOptions) {
if (!OpenSsl.isAvailable()) {
VertxException ex = new VertxException("OpenSSL is not available");
Throwable cause = OpenSsl.unavailabilityCause();
if (cause != null) {
ex.initCause(cause);
}
throw ex;
}
}
if (useAlpn) {
if (engineOptions instanceof JdkSSLEngineOptions) {
if (!JdkSSLEngineOptions.isAlpnAvailable()) {
throw new VertxException("ALPN not available for JDK SSL/TLS engine");
}
}
if (engineOptions instanceof OpenSSLEngineOptions) {
if (!OpenSSLEngineOptions.isAlpnAvailable()) {
throw new VertxException("ALPN is not available for OpenSSL SSL/TLS engine");
}
}
}
return engineOptions;
}
private final boolean ssl;
private final boolean sni;
private final boolean trustAll;
private final ClientAuth clientAuth;
private final boolean client;
private final boolean useAlpn;
private final String endpointIdentificationAlgorithm;
private final SSLEngineOptions sslEngineOptions;
private final List applicationProtocols;
private KeyManagerFactory keyManagerFactory;
private TrustManagerFactory trustManagerFactory;
private Function keyManagerFactoryMapper;
private Function trustManagerMapper;
private List crls;
public SSLHelper(TCPSSLOptions options, List applicationProtocols) {
this.sslEngineOptions = options.getSslEngineOptions();
this.ssl = options.isSsl();
this.useAlpn = options.isUseAlpn();
this.client = options instanceof ClientOptionsBase;
this.trustAll = options instanceof ClientOptionsBase && ((ClientOptionsBase)options).isTrustAll();
this.clientAuth = options instanceof NetServerOptions ? ((NetServerOptions)options).getClientAuth() : ClientAuth.NONE;
this.endpointIdentificationAlgorithm = options instanceof NetClientOptions ? ((NetClientOptions)options).getHostnameVerificationAlgorithm() : "";
this.sni = options instanceof NetServerOptions && ((NetServerOptions) options).isSni();
this.applicationProtocols = applicationProtocols;
}
private class EngineConfig {
private final SSLOptions sslOptions;
private final Supplier supplier;
private final boolean useWorkerPool;
public EngineConfig(SSLOptions sslOptions, Supplier supplier, boolean useWorkerPool) {
this.sslOptions = sslOptions;
this.supplier = supplier;
this.useWorkerPool = useWorkerPool;
}
SslContextProvider sslContextProvider() {
return new SslContextProvider(
clientAuth,
endpointIdentificationAlgorithm,
applicationProtocols,
sslOptions.getEnabledCipherSuites(),
sslOptions.getEnabledSecureTransportProtocols(),
keyManagerFactory,
keyManagerFactoryMapper,
trustManagerFactory,
trustManagerMapper,
crls,
supplier);
}
}
/**
* Initialize the helper, this loads and validates the configuration.
*
* @param ctx the context
* @return a future resolved when the helper is initialized
*/
public Future buildContextProvider(SSLOptions sslOptions, ContextInternal ctx) {
return build(new SSLOptions(sslOptions), ctx).map(EngineConfig::sslContextProvider);
}
/**
* Initialize the helper, this loads and validates the configuration.
*
* @param ctx the context
* @return a future resolved when the helper is initialized
*/
public Future buildChannelProvider(SSLOptions sslOptions, ContextInternal ctx) {
return build(new SSLOptions(sslOptions), ctx).map(c -> new SslChannelProvider(
c.sslContextProvider(), c.sslOptions.getSslHandshakeTimeout(), c.sslOptions.getSslHandshakeTimeoutUnit(), sni,
trustAll,
useAlpn,
ctx.owner().getInternalWorkerPool().executor(),
c.useWorkerPool
));
}
/**
* Initialize the helper, this loads and validates the configuration.
*
* @param ctx the context
* @return a future resolved when the helper is initialized
*/
private Future build(SSLOptions sslOptions, ContextInternal ctx) {
Future sslContextFactorySupplier;
KeyCertOptions keyCertOptions = sslOptions.getKeyCertOptions();
TrustOptions trustOptions = sslOptions.getTrustOptions();
if (keyCertOptions != null || trustOptions != null || trustAll || ssl) {
Promise promise = Promise.promise();
sslContextFactorySupplier = promise.future();
ctx.executeBlockingInternal(p -> {
try {
if (sslOptions.getKeyCertOptions() != null) {
keyManagerFactory = sslOptions.getKeyCertOptions().getKeyManagerFactory(ctx.owner());
keyManagerFactoryMapper = sslOptions.getKeyCertOptions().keyManagerFactoryMapper(ctx.owner());
}
if (sslOptions.getTrustOptions() != null) {
trustManagerFactory = sslOptions.getTrustOptions().getTrustManagerFactory(ctx.owner());
trustManagerMapper = sslOptions.getTrustOptions().trustManagerMapper(ctx.owner());
}
crls = new ArrayList<>();
List tmp = new ArrayList<>();
if (sslOptions.getCrlPaths() != null) {
tmp.addAll(sslOptions.getCrlPaths()
.stream()
.map(path -> ctx.owner().resolveFile(path).getAbsolutePath())
.map(ctx.owner().fileSystem()::readFileBlocking)
.collect(Collectors.toList()));
}
if (sslOptions.getCrlValues() != null) {
tmp.addAll(sslOptions.getCrlValues());
}
CertificateFactory certificatefactory = CertificateFactory.getInstance("X.509");
for (Buffer crlValue : tmp) {
crls.addAll(certificatefactory.generateCRLs(new ByteArrayInputStream(crlValue.getBytes())));
}
} catch (Exception e) {
p.fail(e);
return;
}
if (client || sslOptions.getKeyCertOptions() != null) {
p.complete();
} else {
p.fail("Key/certificate is mandatory for SSL");
}
}).compose(v2 -> ctx.executeBlockingInternal(p -> {
Supplier supplier;
boolean useWorkerPool;
try {
SSLEngineOptions resolvedEngineOptions = resolveEngineOptions(sslEngineOptions, useAlpn);
supplier = resolvedEngineOptions::sslContextFactory;
useWorkerPool = resolvedEngineOptions.getUseWorkerThread();
} catch (Exception e) {
p.fail(e);
return;
}
p.complete(new EngineConfig(sslOptions, supplier, useWorkerPool));
})).onComplete(promise);
} else {
sslContextFactorySupplier = Future.succeededFuture(new EngineConfig(sslOptions, () -> new DefaultSslContextFactory(SslProvider.JDK, false), SSLEngineOptions.DEFAULT_USE_WORKER_POOL));
}
return sslContextFactorySupplier;
}
}