Implement SSLSession.invalidate() and isValid() for OpenSSLEngine.

Motivation:

The SSLSession allows to invalidate a SSLSession and so disallow resume of a session. We should support this for OpenSSLEngine as well.

Modifications:

- Correctly implement SSLSession.isValid() and invalidate() in OpenSSLEngine
- Add unit test.

Result:

Invalidate of SSL sessions is supported when using OpenSSL now.
This commit is contained in:
Norman Maurer 2015-09-30 10:14:29 +02:00
parent 0555b0aefd
commit 4aa19a09bd
4 changed files with 93 additions and 2 deletions

View File

@ -1411,11 +1411,20 @@ public final class OpenSslEngine extends SSLEngine {
@Override
public void invalidate() {
// NOOP
synchronized (OpenSslEngine.this) {
if (!isDestroyed()) {
SSL.setTimeout(ssl, 0);
}
}
}
@Override
public boolean isValid() {
synchronized (OpenSslEngine.this) {
if (!isDestroyed()) {
return System.currentTimeMillis() - (SSL.getTimeout(ssl) * 1000L) < (SSL.getTime(ssl) * 1000L);
}
}
return false;
}

View File

@ -48,6 +48,12 @@ public class OpenSslEngineTest extends SSLEngineTest {
super.testGetCreationTime();
}
@Override
public void testSessionInvalidate() throws Exception {
assumeTrue(OpenSsl.isAvailable());
super.testSessionInvalidate();
}
@Override
protected SslProvider sslProvider() {
return SslProvider.OPENSSL;

View File

@ -30,6 +30,8 @@ import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
import io.netty.handler.ssl.util.SelfSignedCertificate;
import io.netty.util.NetUtil;
import io.netty.util.concurrent.Future;
import org.junit.After;
@ -40,10 +42,13 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLEngineResult;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.SSLSession;
import java.io.File;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@ -294,5 +299,76 @@ public abstract class SSLEngineTest {
assertTrue(engine.getSession().getCreationTime() <= System.currentTimeMillis());
}
@Test
public void testSessionInvalidate() throws Exception {
final SslContext clientContext = SslContextBuilder.forClient()
.trustManager(InsecureTrustManagerFactory.INSTANCE)
.sslProvider(sslProvider())
.build();
SelfSignedCertificate ssc = new SelfSignedCertificate();
SslContext serverContext = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey())
.sslProvider(sslProvider())
.build();
SSLEngine clientEngine = clientContext.newEngine(UnpooledByteBufAllocator.DEFAULT);
SSLEngine serverEngine = serverContext.newEngine(UnpooledByteBufAllocator.DEFAULT);
handshake(clientEngine, serverEngine);
SSLSession session = serverEngine.getSession();
assertTrue(session.isValid());
session.invalidate();
assertFalse(session.isValid());
}
private static void handshake(SSLEngine clientEngine, SSLEngine serverEngine) throws SSLException {
int netBufferSize = 17 * 1024;
ByteBuffer cTOs = ByteBuffer.allocateDirect(netBufferSize);
ByteBuffer sTOc = ByteBuffer.allocateDirect(netBufferSize);
ByteBuffer serverAppReadBuffer = ByteBuffer.allocateDirect(
serverEngine.getSession().getApplicationBufferSize());
ByteBuffer clientAppReadBuffer = ByteBuffer.allocateDirect(
clientEngine.getSession().getApplicationBufferSize());
clientEngine.beginHandshake();
serverEngine.beginHandshake();
ByteBuffer empty = ByteBuffer.allocate(0);
SSLEngineResult clientResult;
SSLEngineResult serverResult;
do {
clientResult = clientEngine.wrap(empty, cTOs);
runDelegatedTasks(clientResult, clientEngine);
serverResult = serverEngine.wrap(empty, sTOc);
runDelegatedTasks(serverResult, serverEngine);
cTOs.flip();
sTOc.flip();
clientResult = clientEngine.unwrap(sTOc, clientAppReadBuffer);
runDelegatedTasks(clientResult, clientEngine);
serverResult = serverEngine.unwrap(cTOs, serverAppReadBuffer);
runDelegatedTasks(serverResult, serverEngine);
cTOs.compact();
sTOc.compact();
} while (isHandshaking(clientResult) && isHandshaking(serverResult));
}
private static boolean isHandshaking(SSLEngineResult result) {
return result.getHandshakeStatus() != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING &&
result.getHandshakeStatus() != SSLEngineResult.HandshakeStatus.FINISHED;
}
private static void runDelegatedTasks(SSLEngineResult result, SSLEngine engine) {
if (result.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_TASK) {
for (;;) {
Runnable task = engine.getDelegatedTask();
if (task == null) {
break;
}
task.run();
}
}
}
protected abstract SslProvider sslProvider();
}

View File

@ -701,7 +701,7 @@
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>netty-tcnative</artifactId>
<version>1.1.33.Fork9</version>
<version>1.1.33.Fork10</version>
<classifier>${tcnative.classifier}</classifier>
<scope>compile</scope>
<optional>true</optional>