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

io.netty.handler.ssl.ReferenceCountedOpenSslServerContext Maven / Gradle / Ivy

Go to download

This artifact provides a single jar that contains all classes required to use remote Jakarta Enterprise Beans and Jakarta Messaging, including all dependencies. It is intended for use by those not using maven, maven users should just import the Jakarta Enterprise Beans and Jakarta Messaging BOM's instead (shaded JAR's cause lots of problems with maven, as it is very easy to inadvertently end up with different versions on classes on the class path).

There is a newer version: 35.0.0.Beta1
Show newest version
/*
 * Copyright 2016 The Netty Project
 *
 * The Netty Project licenses this file to you 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 io.netty.handler.ssl;

import io.netty.buffer.ByteBufAllocator;
import io.netty.internal.tcnative.SSL;
import io.netty.internal.tcnative.SSLContext;
import io.netty.internal.tcnative.SniHostNameMatcher;
import io.netty.util.CharsetUtil;
import io.netty.util.internal.PlatformDependent;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;

import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLException;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509ExtendedTrustManager;
import javax.net.ssl.X509TrustManager;

import static io.netty.util.internal.ObjectUtil.checkNotNull;

/**
 * A server-side {@link SslContext} which uses OpenSSL's SSL/TLS implementation.
 * 

Instances of this class must be {@link #release() released} or else native memory will leak! * *

Instances of this class must not be released before any {@link ReferenceCountedOpenSslEngine} * which depends upon the instance of this class is released. Otherwise if any method of * {@link ReferenceCountedOpenSslEngine} is called which uses this class's JNI resources the JVM may crash. */ public final class ReferenceCountedOpenSslServerContext extends ReferenceCountedOpenSslContext { private static final InternalLogger logger = InternalLoggerFactory.getInstance(ReferenceCountedOpenSslServerContext.class); private static final byte[] ID = {'n', 'e', 't', 't', 'y'}; private final OpenSslServerSessionContext sessionContext; private final OpenSslKeyMaterialManager keyMaterialManager; ReferenceCountedOpenSslServerContext( X509Certificate[] trustCertCollection, TrustManagerFactory trustManagerFactory, X509Certificate[] keyCertChain, PrivateKey key, String keyPassword, KeyManagerFactory keyManagerFactory, Iterable ciphers, CipherSuiteFilter cipherFilter, ApplicationProtocolConfig apn, long sessionCacheSize, long sessionTimeout, ClientAuth clientAuth, String[] protocols, boolean startTls, boolean enableOcsp) throws SSLException { this(trustCertCollection, trustManagerFactory, keyCertChain, key, keyPassword, keyManagerFactory, ciphers, cipherFilter, toNegotiator(apn), sessionCacheSize, sessionTimeout, clientAuth, protocols, startTls, enableOcsp); } private ReferenceCountedOpenSslServerContext( X509Certificate[] trustCertCollection, TrustManagerFactory trustManagerFactory, X509Certificate[] keyCertChain, PrivateKey key, String keyPassword, KeyManagerFactory keyManagerFactory, Iterable ciphers, CipherSuiteFilter cipherFilter, OpenSslApplicationProtocolNegotiator apn, long sessionCacheSize, long sessionTimeout, ClientAuth clientAuth, String[] protocols, boolean startTls, boolean enableOcsp) throws SSLException { super(ciphers, cipherFilter, apn, sessionCacheSize, sessionTimeout, SSL.SSL_MODE_SERVER, keyCertChain, clientAuth, protocols, startTls, enableOcsp, true); // Create a new SSL_CTX and configure it. boolean success = false; try { ServerContext context = newSessionContext(this, ctx, engineMap, trustCertCollection, trustManagerFactory, keyCertChain, key, keyPassword, keyManagerFactory); sessionContext = context.sessionContext; keyMaterialManager = context.keyMaterialManager; success = true; } finally { if (!success) { release(); } } } @Override public OpenSslServerSessionContext sessionContext() { return sessionContext; } @Override OpenSslKeyMaterialManager keyMaterialManager() { return keyMaterialManager; } static final class ServerContext { OpenSslServerSessionContext sessionContext; OpenSslKeyMaterialManager keyMaterialManager; } static ServerContext newSessionContext(ReferenceCountedOpenSslContext thiz, long ctx, OpenSslEngineMap engineMap, X509Certificate[] trustCertCollection, TrustManagerFactory trustManagerFactory, X509Certificate[] keyCertChain, PrivateKey key, String keyPassword, KeyManagerFactory keyManagerFactory) throws SSLException { ServerContext result = new ServerContext(); OpenSslKeyMaterialProvider keyMaterialProvider = null; try { try { SSLContext.setVerify(ctx, SSL.SSL_CVERIFY_NONE, VERIFY_DEPTH); if (!OpenSsl.useKeyManagerFactory()) { if (keyManagerFactory != null) { throw new IllegalArgumentException( "KeyManagerFactory not supported"); } checkNotNull(keyCertChain, "keyCertChain"); setKeyMaterial(ctx, keyCertChain, key, keyPassword); } else { // javadocs state that keyManagerFactory has precedent over keyCertChain, and we must have a // keyManagerFactory for the server so build one if it is not specified. if (keyManagerFactory == null) { char[] keyPasswordChars = keyStorePassword(keyPassword); KeyStore ks = buildKeyStore(keyCertChain, key, keyPasswordChars); if (ks.aliases().hasMoreElements()) { keyManagerFactory = new OpenSslX509KeyManagerFactory(); } else { keyManagerFactory = new OpenSslCachingX509KeyManagerFactory( KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm())); } keyManagerFactory.init(ks, keyPasswordChars); } keyMaterialProvider = providerFor(keyManagerFactory, keyPassword); result.keyMaterialManager = new OpenSslKeyMaterialManager(keyMaterialProvider); } } catch (Exception e) { throw new SSLException("failed to set certificate and key", e); } try { if (trustCertCollection != null) { trustManagerFactory = buildTrustManagerFactory(trustCertCollection, trustManagerFactory); } else if (trustManagerFactory == null) { // Mimic the way SSLContext.getInstance(KeyManager[], null, null) works trustManagerFactory = TrustManagerFactory.getInstance( TrustManagerFactory.getDefaultAlgorithm()); trustManagerFactory.init((KeyStore) null); } final X509TrustManager manager = chooseTrustManager(trustManagerFactory.getTrustManagers()); // IMPORTANT: The callbacks set for verification must be static to prevent memory leak as // otherwise the context can never be collected. This is because the JNI code holds // a global reference to the callbacks. // // See https://github.com/netty/netty/issues/5372 // Use this to prevent an error when running on java < 7 if (useExtendedTrustManager(manager)) { SSLContext.setCertVerifyCallback(ctx, new ExtendedTrustManagerVerifyCallback(engineMap, (X509ExtendedTrustManager) manager)); } else { SSLContext.setCertVerifyCallback(ctx, new TrustManagerVerifyCallback(engineMap, manager)); } X509Certificate[] issuers = manager.getAcceptedIssuers(); if (issuers != null && issuers.length > 0) { long bio = 0; try { bio = toBIO(ByteBufAllocator.DEFAULT, issuers); if (!SSLContext.setCACertificateBio(ctx, bio)) { throw new SSLException("unable to setup accepted issuers for trustmanager " + manager); } } finally { freeBio(bio); } } if (PlatformDependent.javaVersion() >= 8) { // Only do on Java8+ as SNIMatcher is not supported in earlier releases. // IMPORTANT: The callbacks set for hostname matching must be static to prevent memory leak as // otherwise the context can never be collected. This is because the JNI code holds // a global reference to the matcher. SSLContext.setSniHostnameMatcher(ctx, new OpenSslSniHostnameMatcher(engineMap)); } } catch (SSLException e) { throw e; } catch (Exception e) { throw new SSLException("unable to setup trustmanager", e); } result.sessionContext = new OpenSslServerSessionContext(thiz, keyMaterialProvider); result.sessionContext.setSessionIdContext(ID); keyMaterialProvider = null; return result; } finally { if (keyMaterialProvider != null) { keyMaterialProvider.destroy(); } } } private static final class TrustManagerVerifyCallback extends AbstractCertificateVerifier { private final X509TrustManager manager; TrustManagerVerifyCallback(OpenSslEngineMap engineMap, X509TrustManager manager) { super(engineMap); this.manager = manager; } @Override void verify(ReferenceCountedOpenSslEngine engine, X509Certificate[] peerCerts, String auth) throws Exception { manager.checkClientTrusted(peerCerts, auth); } } private static final class ExtendedTrustManagerVerifyCallback extends AbstractCertificateVerifier { private final X509ExtendedTrustManager manager; ExtendedTrustManagerVerifyCallback(OpenSslEngineMap engineMap, X509ExtendedTrustManager manager) { super(engineMap); this.manager = manager; } @Override void verify(ReferenceCountedOpenSslEngine engine, X509Certificate[] peerCerts, String auth) throws Exception { manager.checkClientTrusted(peerCerts, auth, engine); } } private static final class OpenSslSniHostnameMatcher implements SniHostNameMatcher { private final OpenSslEngineMap engineMap; OpenSslSniHostnameMatcher(OpenSslEngineMap engineMap) { this.engineMap = engineMap; } @Override public boolean match(long ssl, String hostname) { ReferenceCountedOpenSslEngine engine = engineMap.get(ssl); if (engine != null) { // TODO: In the next release of tcnative we should pass the byte[] directly in and not use a String. return engine.checkSniHostnameMatch(hostname.getBytes(CharsetUtil.UTF_8)); } logger.warn("No ReferenceCountedOpenSslEngine found for SSL pointer: {}", ssl); return false; } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy