Switch to netty-tcnative 2.0.0 which uses different package names

Motivation:

Previous versions of netty-tcnative used the org.apache.tomcat namespace which could lead to problems when a user tried to use tomcat and netty in the same app.

Modifications:

Use netty-tcnative which now uses a different namespace and adjust code to some API changes.

Result:

Its now possible to use netty-tcnative even when running together with tomcat.
This commit is contained in:
Norman Maurer 2016-08-10 08:55:30 +02:00
parent 3482651e0c
commit 1d128c7a65
14 changed files with 64 additions and 110 deletions

View File

@ -24,23 +24,16 @@ import io.netty.util.internal.NativeLibraryLoader;
import io.netty.util.internal.SystemPropertyUtil; import io.netty.util.internal.SystemPropertyUtil;
import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory; import io.netty.util.internal.logging.InternalLoggerFactory;
import org.apache.tomcat.Apr; import io.netty.tcnative.jni.Buffer;
import org.apache.tomcat.jni.Buffer; import io.netty.tcnative.jni.Library;
import org.apache.tomcat.jni.Library; import io.netty.tcnative.jni.SSL;
import org.apache.tomcat.jni.Pool; import io.netty.tcnative.jni.SSLContext;
import org.apache.tomcat.jni.SSL;
import org.apache.tomcat.jni.SSLContext;
import java.io.IOException;
import java.io.InputStream;
import java.security.AccessController; import java.security.AccessController;
import java.security.PrivilegedAction; import java.security.PrivilegedAction;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.Locale; import java.util.Locale;
import java.util.Properties;
import java.util.Set; import java.util.Set;
/** /**
@ -75,7 +68,7 @@ public final class OpenSsl {
// Test if netty-tcnative is in the classpath first. // Test if netty-tcnative is in the classpath first.
try { try {
Class.forName("org.apache.tomcat.jni.SSL", false, OpenSsl.class.getClassLoader()); Class.forName("io.netty.tcnative.jni.SSL", false, OpenSsl.class.getClassLoader());
} catch (ClassNotFoundException t) { } catch (ClassNotFoundException t) {
cause = t; cause = t;
logger.debug( logger.debug(
@ -115,21 +108,14 @@ public final class OpenSsl {
} }
} }
if (cause == null && !isNettyTcnative()) {
logger.debug("incompatible tcnative in the classpath; "
+ OpenSslEngine.class.getSimpleName() + " will be unavailable.");
cause = new ClassNotFoundException("incompatible tcnative in the classpath");
}
UNAVAILABILITY_CAUSE = cause; UNAVAILABILITY_CAUSE = cause;
if (cause == null) { if (cause == null) {
final Set<String> availableOpenSslCipherSuites = new LinkedHashSet<String>(128); final Set<String> availableOpenSslCipherSuites = new LinkedHashSet<String>(128);
boolean supportsKeyManagerFactory = false; boolean supportsKeyManagerFactory = false;
boolean useKeyManagerFactory = false; boolean useKeyManagerFactory = false;
final long aprPool = Pool.create(0);
try { try {
final long sslCtx = SSLContext.make(aprPool, SSL.SSL_PROTOCOL_ALL, SSL.SSL_MODE_SERVER); final long sslCtx = SSLContext.make(SSL.SSL_PROTOCOL_ALL, SSL.SSL_MODE_SERVER);
long privateKeyBio = 0; long privateKeyBio = 0;
long certBio = 0; long certBio = 0;
try { try {
@ -173,8 +159,6 @@ public final class OpenSsl {
} }
} catch (Exception e) { } catch (Exception e) {
logger.warn("Failed to get the list of available OpenSSL cipher suites.", e); logger.warn("Failed to get the list of available OpenSSL cipher suites.", e);
} finally {
Pool.destroy(aprPool);
} }
AVAILABLE_OPENSSL_CIPHER_SUITES = Collections.unmodifiableSet(availableOpenSslCipherSuites); AVAILABLE_OPENSSL_CIPHER_SUITES = Collections.unmodifiableSet(availableOpenSslCipherSuites);
@ -199,30 +183,25 @@ public final class OpenSsl {
SUPPORTS_KEYMANAGER_FACTORY = supportsKeyManagerFactory; SUPPORTS_KEYMANAGER_FACTORY = supportsKeyManagerFactory;
USE_KEYMANAGER_FACTORY = useKeyManagerFactory; USE_KEYMANAGER_FACTORY = useKeyManagerFactory;
final long pool = Pool.create(0);
Set<String> protocols = new LinkedHashSet<String>(6); Set<String> protocols = new LinkedHashSet<String>(6);
// Seems like there is no way to explicitly disable SSLv2Hello in openssl so it is always enabled // Seems like there is no way to explicitly disable SSLv2Hello in openssl so it is always enabled
protocols.add(PROTOCOL_SSL_V2_HELLO); protocols.add(PROTOCOL_SSL_V2_HELLO);
try { if (doesSupportProtocol(SSL.SSL_PROTOCOL_SSLV2)) {
if (doesSupportProtocol(pool, SSL.SSL_PROTOCOL_SSLV2)) { protocols.add(PROTOCOL_SSL_V2);
protocols.add(PROTOCOL_SSL_V2);
}
if (doesSupportProtocol(pool, SSL.SSL_PROTOCOL_SSLV3)) {
protocols.add(PROTOCOL_SSL_V3);
}
if (doesSupportProtocol(pool, SSL.SSL_PROTOCOL_TLSV1)) {
protocols.add(PROTOCOL_TLS_V1);
}
if (doesSupportProtocol(pool, SSL.SSL_PROTOCOL_TLSV1_1)) {
protocols.add(PROTOCOL_TLS_V1_1);
}
if (doesSupportProtocol(pool, SSL.SSL_PROTOCOL_TLSV1_2)) {
protocols.add(PROTOCOL_TLS_V1_2);
}
} finally {
Pool.destroy(aprPool);
} }
if (doesSupportProtocol(SSL.SSL_PROTOCOL_SSLV3)) {
protocols.add(PROTOCOL_SSL_V3);
}
if (doesSupportProtocol(SSL.SSL_PROTOCOL_TLSV1)) {
protocols.add(PROTOCOL_TLS_V1);
}
if (doesSupportProtocol(SSL.SSL_PROTOCOL_TLSV1_1)) {
protocols.add(PROTOCOL_TLS_V1_1);
}
if (doesSupportProtocol(SSL.SSL_PROTOCOL_TLSV1_2)) {
protocols.add(PROTOCOL_TLS_V1_2);
}
SUPPORTED_PROTOCOLS_SET = Collections.unmodifiableSet(protocols); SUPPORTED_PROTOCOLS_SET = Collections.unmodifiableSet(protocols);
} else { } else {
AVAILABLE_OPENSSL_CIPHER_SUITES = Collections.emptySet(); AVAILABLE_OPENSSL_CIPHER_SUITES = Collections.emptySet();
@ -234,10 +213,10 @@ public final class OpenSsl {
} }
} }
private static boolean doesSupportProtocol(long aprPool, int protocol) { private static boolean doesSupportProtocol(int protocol) {
long sslCtx = -1; long sslCtx = -1;
try { try {
sslCtx = SSLContext.make(aprPool, protocol, SSL.SSL_MODE_COMBINED); sslCtx = SSLContext.make(protocol, SSL.SSL_MODE_COMBINED);
return true; return true;
} catch (Exception ignore) { } catch (Exception ignore) {
return false; return false;
@ -248,32 +227,6 @@ public final class OpenSsl {
} }
} }
private static boolean isNettyTcnative() {
return AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
@Override
public Boolean run() {
InputStream is = null;
try {
is = Apr.class.getResourceAsStream("/org/apache/tomcat/apr.properties");
Properties props = new Properties();
props.load(is);
String info = props.getProperty("tcn.info");
return info != null && info.startsWith("netty-tcnative");
} catch (Throwable ignore) {
return false;
} finally {
if (is != null) {
try {
is.close();
} catch (IOException ignore) {
// ignore
}
}
}
}
});
}
/** /**
* Returns {@code true} if and only if * Returns {@code true} if and only if
* <a href="http://netty.io/wiki/forked-tomcat-native.html">{@code netty-tcnative}</a> and its OpenSSL support * <a href="http://netty.io/wiki/forked-tomcat-native.html">{@code netty-tcnative}</a> and its OpenSSL support
@ -413,9 +366,8 @@ public final class OpenSsl {
libNames.toArray(new String[libNames.size()])); libNames.toArray(new String[libNames.size()]));
} }
private static void initializeTcNative() throws Exception { private static boolean initializeTcNative() throws Exception {
Library.initialize("provided"); return Library.initialize();
SSL.initialize(null);
} }
private static String normalizeOs(String value) { private static String normalizeOs(String value) {

View File

@ -15,7 +15,7 @@
*/ */
package io.netty.handler.ssl; package io.netty.handler.ssl;
import org.apache.tomcat.jni.CertificateVerifier; import io.netty.tcnative.jni.CertificateVerifier;
import java.security.cert.CertificateException; import java.security.cert.CertificateException;

View File

@ -15,7 +15,7 @@
*/ */
package io.netty.handler.ssl; package io.netty.handler.ssl;
import org.apache.tomcat.jni.SSL; import io.netty.tcnative.jni.SSL;
import java.io.File; import java.io.File;
import java.security.PrivateKey; import java.security.PrivateKey;

View File

@ -16,8 +16,8 @@
package io.netty.handler.ssl; package io.netty.handler.ssl;
import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.ByteBufAllocator;
import org.apache.tomcat.jni.CertificateRequestedCallback; import io.netty.tcnative.jni.CertificateRequestedCallback;
import org.apache.tomcat.jni.SSL; import io.netty.tcnative.jni.SSL;
import javax.net.ssl.SSLException; import javax.net.ssl.SSLException;
import javax.net.ssl.X509KeyManager; import javax.net.ssl.X509KeyManager;

View File

@ -16,7 +16,7 @@
package io.netty.handler.ssl; package io.netty.handler.ssl;
import io.netty.handler.ssl.ReferenceCountedOpenSslServerContext.ServerContext; import io.netty.handler.ssl.ReferenceCountedOpenSslServerContext.ServerContext;
import org.apache.tomcat.jni.SSL; import io.netty.tcnative.jni.SSL;
import java.io.File; import java.io.File;
import java.security.PrivateKey; import java.security.PrivateKey;

View File

@ -15,8 +15,8 @@
*/ */
package io.netty.handler.ssl; package io.netty.handler.ssl;
import org.apache.tomcat.jni.SSL; import io.netty.tcnative.jni.SSL;
import org.apache.tomcat.jni.SSLContext; import io.netty.tcnative.jni.SSLContext;
/** /**

View File

@ -16,12 +16,13 @@
package io.netty.handler.ssl; package io.netty.handler.ssl;
import io.netty.util.internal.ObjectUtil; import io.netty.util.internal.ObjectUtil;
import org.apache.tomcat.jni.SSL; import io.netty.tcnative.jni.SSL;
import org.apache.tomcat.jni.SSLContext; import io.netty.tcnative.jni.SSLContext;
import org.apache.tomcat.jni.SessionTicketKey; import io.netty.tcnative.jni.SessionTicketKey;
import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSessionContext; import javax.net.ssl.SSLSessionContext;
import java.util.Arrays;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
@ -62,9 +63,21 @@ public abstract class OpenSslSessionContext implements SSLSessionContext {
*/ */
@Deprecated @Deprecated
public void setTicketKeys(byte[] keys) { public void setTicketKeys(byte[] keys) {
ObjectUtil.checkNotNull(keys, "keys"); if (keys.length % SessionTicketKey.TICKET_KEY_SIZE != 0) {
throw new IllegalArgumentException("keys.length % " + SessionTicketKey.TICKET_KEY_SIZE + " != 0");
}
SessionTicketKey[] tickets = new SessionTicketKey[keys.length / SessionTicketKey.TICKET_KEY_SIZE];
for (int i = 0, a = 0; i < tickets.length; i++) {
byte[] name = Arrays.copyOfRange(keys, a, SessionTicketKey.NAME_SIZE);
a += SessionTicketKey.NAME_SIZE;
byte[] hmacKey = Arrays.copyOfRange(keys, a, SessionTicketKey.HMAC_KEY_SIZE);
i += SessionTicketKey.HMAC_KEY_SIZE;
byte[] aesKey = Arrays.copyOfRange(keys, a, SessionTicketKey.AES_KEY_SIZE);
a += SessionTicketKey.AES_KEY_SIZE;
tickets[i] = new SessionTicketKey(name, hmacKey, aesKey);
}
SSLContext.clearOptions(context.ctx, SSL.SSL_OP_NO_TICKET); SSLContext.clearOptions(context.ctx, SSL.SSL_OP_NO_TICKET);
SSLContext.setSessionTicketKeys(context.ctx, keys); SSLContext.setSessionTicketKeys(context.ctx, tickets);
} }
/** /**

View File

@ -16,7 +16,7 @@
package io.netty.handler.ssl; package io.netty.handler.ssl;
import org.apache.tomcat.jni.SSLContext; import io.netty.tcnative.jni.SSLContext;
/** /**
* Stats exposed by an OpenSSL session context. * Stats exposed by an OpenSSL session context.

View File

@ -15,7 +15,7 @@
*/ */
package io.netty.handler.ssl; package io.netty.handler.ssl;
import org.apache.tomcat.jni.SessionTicketKey; import io.netty.tcnative.jni.SessionTicketKey;
/** /**
* Session Ticket Key * Session Ticket Key

View File

@ -17,9 +17,9 @@ package io.netty.handler.ssl;
import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory; import io.netty.util.internal.logging.InternalLoggerFactory;
import org.apache.tomcat.jni.CertificateRequestedCallback; import io.netty.tcnative.jni.CertificateRequestedCallback;
import org.apache.tomcat.jni.SSL; import io.netty.tcnative.jni.SSL;
import org.apache.tomcat.jni.SSLContext; import io.netty.tcnative.jni.SSLContext;
import java.security.KeyStore; import java.security.KeyStore;
import java.security.PrivateKey; import java.security.PrivateKey;

View File

@ -27,10 +27,9 @@ import io.netty.util.internal.StringUtil;
import io.netty.util.internal.SystemPropertyUtil; import io.netty.util.internal.SystemPropertyUtil;
import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory; import io.netty.util.internal.logging.InternalLoggerFactory;
import org.apache.tomcat.jni.CertificateVerifier; import io.netty.tcnative.jni.CertificateVerifier;
import org.apache.tomcat.jni.Pool; import io.netty.tcnative.jni.SSL;
import org.apache.tomcat.jni.SSL; import io.netty.tcnative.jni.SSLContext;
import org.apache.tomcat.jni.SSLContext;
import java.security.AccessController; import java.security.AccessController;
import java.security.PrivateKey; import java.security.PrivateKey;
@ -98,7 +97,6 @@ public abstract class ReferenceCountedOpenSslContext extends SslContext implemen
* The OpenSSL SSL_CTX object * The OpenSSL SSL_CTX object
*/ */
protected volatile long ctx; protected volatile long ctx;
long aprPool;
@SuppressWarnings({ "unused", "FieldMayBeFinal" }) @SuppressWarnings({ "unused", "FieldMayBeFinal" })
private volatile int aprPoolDestroyed; private volatile int aprPoolDestroyed;
private final List<String> unmodifiableCiphers; private final List<String> unmodifiableCiphers;
@ -250,15 +248,12 @@ public abstract class ReferenceCountedOpenSslContext extends SslContext implemen
this.apn = checkNotNull(apn, "apn"); this.apn = checkNotNull(apn, "apn");
// Allocate a new APR pool.
aprPool = Pool.create(0);
// Create a new SSL_CTX and configure it. // Create a new SSL_CTX and configure it.
boolean success = false; boolean success = false;
try { try {
synchronized (ReferenceCountedOpenSslContext.class) { synchronized (ReferenceCountedOpenSslContext.class) {
try { try {
ctx = SSLContext.make(aprPool, SSL.SSL_PROTOCOL_ALL, mode); ctx = SSLContext.make(SSL.SSL_PROTOCOL_ALL, mode);
} catch (Exception e) { } catch (Exception e) {
throw new SSLException("failed to create an SSL_CTX", e); throw new SSLException("failed to create an SSL_CTX", e);
} }
@ -466,12 +461,6 @@ public abstract class ReferenceCountedOpenSslContext extends SslContext implemen
SSLContext.free(ctx); SSLContext.free(ctx);
ctx = 0; ctx = 0;
} }
// Guard against multiple destroyPools() calls triggered by construction exception and finalize() later
if (aprPool != 0) {
Pool.destroy(aprPool);
aprPool = 0;
}
} }
} }

View File

@ -29,8 +29,8 @@ import io.netty.util.internal.StringUtil;
import io.netty.util.internal.ThrowableUtil; import io.netty.util.internal.ThrowableUtil;
import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory; import io.netty.util.internal.logging.InternalLoggerFactory;
import org.apache.tomcat.jni.Buffer; import io.netty.tcnative.jni.Buffer;
import org.apache.tomcat.jni.SSL; import io.netty.tcnative.jni.SSL;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;

View File

@ -15,8 +15,8 @@
*/ */
package io.netty.handler.ssl; package io.netty.handler.ssl;
import org.apache.tomcat.jni.SSL; import io.netty.tcnative.jni.SSL;
import org.apache.tomcat.jni.SSLContext; import io.netty.tcnative.jni.SSLContext;
import java.security.KeyStore; import java.security.KeyStore;
import java.security.PrivateKey; import java.security.PrivateKey;

View File

@ -244,7 +244,7 @@
<!-- Fedora-"like" systems. This is currently only used for the netty-tcnative dependency --> <!-- Fedora-"like" systems. This is currently only used for the netty-tcnative dependency -->
<os.detection.classifierWithLikes>fedora</os.detection.classifierWithLikes> <os.detection.classifierWithLikes>fedora</os.detection.classifierWithLikes>
<tcnative.artifactId>netty-tcnative</tcnative.artifactId> <tcnative.artifactId>netty-tcnative</tcnative.artifactId>
<tcnative.version>1.1.33.Fork26</tcnative.version> <tcnative.version>2.0.0.Beta1</tcnative.version>
<tcnative.classifier>${os.detected.classifier}</tcnative.classifier> <tcnative.classifier>${os.detected.classifier}</tcnative.classifier>
<epoll.classifier>${os.detected.name}-${os.detected.arch}</epoll.classifier> <epoll.classifier>${os.detected.name}-${os.detected.arch}</epoll.classifier>
<logging.config>${project.basedir}/../common/src/test/resources/logback-test.xml</logging.config> <logging.config>${project.basedir}/../common/src/test/resources/logback-test.xml</logging.config>