Allow to enable session cache when using OpenSsl
Motivation: At the moment it is not possible to make use of the session cache when OpenSsl is used. This should be possible when server mode is used. Modifications: - Add OpenSslSessionContext (implements SSLSessionContext) which exposes all the methods to modify the session cache. - Add various extra methods to OpenSslSessionContext for extra functionality - Return OpenSslSessionContext when OpenSslEngine.getSession().getContext() is called. - Add sessionContext() to SslContext - Move OpenSsl specific session operations to OpenSslSessionContext and mark the old methods @deprecated Result: It's now possible to use session cache with OpenSsl
This commit is contained in:
parent
61a5e60513
commit
8282b12b6a
@ -16,7 +16,6 @@
|
||||
package io.netty.handler.ssl;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufAllocator;
|
||||
import io.netty.buffer.ByteBufInputStream;
|
||||
import io.netty.util.internal.logging.InternalLogger;
|
||||
import io.netty.util.internal.logging.InternalLoggerFactory;
|
||||
@ -24,7 +23,6 @@ import org.apache.tomcat.jni.CertificateVerifier;
|
||||
import org.apache.tomcat.jni.SSL;
|
||||
import org.apache.tomcat.jni.SSLContext;
|
||||
|
||||
import javax.net.ssl.SSLEngine;
|
||||
import javax.net.ssl.SSLException;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
@ -37,13 +35,13 @@ import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A client-side {@link SslContext} which uses OpenSSL's SSL/TLS implementation.
|
||||
*/
|
||||
public final class OpenSslClientContext extends OpenSslContext {
|
||||
private static final InternalLogger logger = InternalLoggerFactory.getInstance(OpenSslClientContext.class);
|
||||
private final OpenSslSessionContext sessionContext;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
@ -151,6 +149,7 @@ public final class OpenSslClientContext extends OpenSslContext {
|
||||
throw new SSLException("unable to setup trustmanager", e);
|
||||
}
|
||||
}
|
||||
sessionContext = new OpenSslClientSessionContext(ctx);
|
||||
success = true;
|
||||
} finally {
|
||||
if (!success) {
|
||||
@ -182,12 +181,38 @@ public final class OpenSslClientContext extends OpenSslContext {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SSLEngine newEngine(ByteBufAllocator alloc) {
|
||||
List<String> protos = applicationProtocolNegotiator().protocols();
|
||||
if (protos.isEmpty()) {
|
||||
return new OpenSslEngine(ctx, alloc, null, isClient());
|
||||
} else {
|
||||
return new OpenSslEngine(ctx, alloc, protos.get(protos.size() - 1), isClient());
|
||||
public OpenSslSessionContext sessionContext() {
|
||||
return sessionContext;
|
||||
}
|
||||
|
||||
// No cache is currently supported for client side mode.
|
||||
private static final class OpenSslClientSessionContext extends OpenSslSessionContext {
|
||||
private OpenSslClientSessionContext(long context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSessionTimeout(int seconds) {
|
||||
if (seconds < 0) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSessionTimeout() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSessionCacheSize(int size) {
|
||||
if (size < 0) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSessionCacheSize() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -55,7 +55,6 @@ public abstract class OpenSslContext extends SslContext {
|
||||
/** The OpenSSL SSL_CTX object */
|
||||
protected final long ctx;
|
||||
private final int mode;
|
||||
private final OpenSslSessionStats stats;
|
||||
|
||||
static {
|
||||
List<String> ciphers = new ArrayList<String>();
|
||||
@ -191,8 +190,6 @@ public abstract class OpenSslContext extends SslContext {
|
||||
destroyPools();
|
||||
}
|
||||
}
|
||||
|
||||
stats = new OpenSslSessionStats(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -225,6 +222,19 @@ public abstract class OpenSslContext extends SslContext {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new server-side {@link javax.net.ssl.SSLEngine} with the current configuration.
|
||||
*/
|
||||
@Override
|
||||
public final SSLEngine newEngine(ByteBufAllocator alloc) {
|
||||
List<String> protos = applicationProtocolNegotiator().protocols();
|
||||
if (protos.isEmpty()) {
|
||||
return new OpenSslEngine(ctx, alloc, null, isClient(), sessionContext());
|
||||
} else {
|
||||
return new OpenSslEngine(ctx, alloc, protos.get(protos.size() - 1), isClient(), sessionContext());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@code SSL_CTX} object of this context.
|
||||
*/
|
||||
@ -234,9 +244,11 @@ public abstract class OpenSslContext extends SslContext {
|
||||
|
||||
/**
|
||||
* Returns the stats of this context.
|
||||
* @deprecated use {@link #sessionContext#stats()}
|
||||
*/
|
||||
@Deprecated
|
||||
public final OpenSslSessionStats stats() {
|
||||
return stats;
|
||||
return sessionContext().stats();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -254,14 +266,16 @@ public abstract class OpenSslContext extends SslContext {
|
||||
|
||||
/**
|
||||
* Sets the SSL session ticket keys of this context.
|
||||
* @deprecated use {@link OpenSslSessionContext#setTicketKeys(byte[])}
|
||||
*/
|
||||
@Deprecated
|
||||
public final void setTicketKeys(byte[] keys) {
|
||||
if (keys == null) {
|
||||
throw new NullPointerException("keys");
|
||||
}
|
||||
SSLContext.setSessionTicketKeys(ctx, keys);
|
||||
sessionContext().setTicketKeys(keys);
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract OpenSslSessionContext sessionContext();
|
||||
|
||||
protected final void destroyPools() {
|
||||
// Guard against multiple destroyPools() calls triggered by construction exception and finalize() later
|
||||
if (aprPool != 0 && DESTROY_UPDATER.compareAndSet(this, 0, 1)) {
|
||||
|
@ -129,6 +129,7 @@ public final class OpenSslEngine extends SSLEngine {
|
||||
private final boolean clientMode;
|
||||
private final ByteBufAllocator alloc;
|
||||
private final String fallbackApplicationProtocol;
|
||||
private final OpenSslSessionContext sessionContext;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private volatile SSLSession session;
|
||||
@ -141,7 +142,7 @@ public final class OpenSslEngine extends SSLEngine {
|
||||
*/
|
||||
@Deprecated
|
||||
public OpenSslEngine(long sslCtx, ByteBufAllocator alloc, String fallbackApplicationProtocol) {
|
||||
this(sslCtx, alloc, fallbackApplicationProtocol, false);
|
||||
this(sslCtx, alloc, fallbackApplicationProtocol, false, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -150,9 +151,10 @@ public final class OpenSslEngine extends SSLEngine {
|
||||
* @param sslCtx an OpenSSL {@code SSL_CTX} object
|
||||
* @param alloc the {@link ByteBufAllocator} that will be used by this engine
|
||||
* @param clientMode {@code true} if this is used for clients, {@code false} otherwise
|
||||
* @param sessionContext the {@link OpenSslSessionContext} this {@link SSLEngine} belongs to.
|
||||
*/
|
||||
OpenSslEngine(long sslCtx, ByteBufAllocator alloc, String fallbackApplicationProtocol,
|
||||
boolean clientMode) {
|
||||
boolean clientMode, OpenSslSessionContext sessionContext) {
|
||||
OpenSsl.ensureAvailability();
|
||||
if (sslCtx == 0) {
|
||||
throw new NullPointerException("sslContext");
|
||||
@ -166,6 +168,7 @@ public final class OpenSslEngine extends SSLEngine {
|
||||
networkBIO = SSL.makeNetworkBIO(ssl);
|
||||
this.fallbackApplicationProtocol = fallbackApplicationProtocol;
|
||||
this.clientMode = clientMode;
|
||||
this.sessionContext = sessionContext;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -717,7 +720,7 @@ public final class OpenSslEngine extends SSLEngine {
|
||||
|
||||
@Override
|
||||
public SSLSessionContext getSessionContext() {
|
||||
return null;
|
||||
return sessionContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -16,7 +16,6 @@
|
||||
package io.netty.handler.ssl;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufAllocator;
|
||||
import io.netty.buffer.ByteBufInputStream;
|
||||
import io.netty.util.internal.logging.InternalLogger;
|
||||
import io.netty.util.internal.logging.InternalLoggerFactory;
|
||||
@ -24,7 +23,6 @@ import org.apache.tomcat.jni.CertificateVerifier;
|
||||
import org.apache.tomcat.jni.SSL;
|
||||
import org.apache.tomcat.jni.SSLContext;
|
||||
|
||||
import javax.net.ssl.SSLEngine;
|
||||
import javax.net.ssl.SSLException;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
@ -48,6 +46,8 @@ import static io.netty.util.internal.ObjectUtil.*;
|
||||
public final class OpenSslServerContext extends OpenSslContext {
|
||||
private static final InternalLogger logger = InternalLoggerFactory.getInstance(OpenSslServerContext.class);
|
||||
|
||||
private final OpenSslSessionContext sessionContext;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
@ -275,6 +275,7 @@ public final class OpenSslServerContext extends OpenSslContext {
|
||||
throw new SSLException("unable to setup trustmanager", e);
|
||||
}
|
||||
}
|
||||
sessionContext = new OpenSslServerSessionContext(ctx);
|
||||
success = true;
|
||||
} finally {
|
||||
if (!success) {
|
||||
@ -284,12 +285,39 @@ public final class OpenSslServerContext extends OpenSslContext {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SSLEngine newEngine(ByteBufAllocator alloc) {
|
||||
List<String> protos = applicationProtocolNegotiator().protocols();
|
||||
if (protos.isEmpty()) {
|
||||
return new OpenSslEngine(ctx, alloc, null, isClient());
|
||||
} else {
|
||||
return new OpenSslEngine(ctx, alloc, protos.get(protos.size() - 1), isClient());
|
||||
public OpenSslSessionContext sessionContext() {
|
||||
return sessionContext;
|
||||
}
|
||||
|
||||
private static final class OpenSslServerSessionContext extends OpenSslSessionContext {
|
||||
private OpenSslServerSessionContext(long context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSessionTimeout(int seconds) {
|
||||
if (seconds < 0) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
SSLContext.setSessionCacheTimeout(context, seconds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSessionTimeout() {
|
||||
return (int) SSLContext.getSessionCacheTimeout(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSessionCacheSize(int size) {
|
||||
if (size < 0) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
SSLContext.setSessionCacheSize(context, size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSessionCacheSize() {
|
||||
return (int) SSLContext.getSessionCacheSize(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright 2014 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 org.apache.tomcat.jni.SSLContext;
|
||||
|
||||
import javax.net.ssl.SSLSession;
|
||||
import javax.net.ssl.SSLSessionContext;
|
||||
import java.util.Enumeration;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
/**
|
||||
* OpenSSL specific {@link SSLSessionContext} implementation.
|
||||
*/
|
||||
public abstract class OpenSslSessionContext implements SSLSessionContext {
|
||||
private static final Enumeration<byte[]> EMPTY = new EmptyEnumeration();
|
||||
|
||||
private final OpenSslSessionStats stats;
|
||||
final long context;
|
||||
|
||||
OpenSslSessionContext(long context) {
|
||||
this.context = context;
|
||||
stats = new OpenSslSessionStats(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SSLSession getSession(byte[] bytes) {
|
||||
if (bytes == null) {
|
||||
throw new NullPointerException("bytes");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<byte[]> getIds() {
|
||||
return EMPTY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the SSL session ticket keys of this context.
|
||||
*/
|
||||
public void setTicketKeys(byte[] keys) {
|
||||
if (keys == null) {
|
||||
throw new NullPointerException("keys");
|
||||
}
|
||||
SSLContext.setSessionTicketKeys(context, keys);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the stats of this context.
|
||||
*/
|
||||
public OpenSslSessionStats stats() {
|
||||
return stats;
|
||||
}
|
||||
|
||||
private static final class EmptyEnumeration implements Enumeration<byte[]> {
|
||||
@Override
|
||||
public boolean hasMoreElements() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] nextElement() {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
}
|
||||
}
|
@ -34,6 +34,7 @@ import javax.crypto.spec.PBEKeySpec;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLEngine;
|
||||
import javax.net.ssl.SSLException;
|
||||
import javax.net.ssl.SSLSessionContext;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
import java.io.File;
|
||||
@ -731,6 +732,11 @@ public abstract class SslContext {
|
||||
*/
|
||||
public abstract SSLEngine newEngine(ByteBufAllocator alloc, String peerHost, int peerPort);
|
||||
|
||||
/**
|
||||
* Returns the {@link SSLSessionContext} object held by this context.
|
||||
*/
|
||||
public abstract SSLSessionContext sessionContext();
|
||||
|
||||
/**
|
||||
* Creates a new {@link SslHandler}.
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user