diff --git a/handler/src/main/java/io/netty/handler/ssl/OpenSslEngine.java b/handler/src/main/java/io/netty/handler/ssl/OpenSslEngine.java index ca1a7dbcfb..a735f93628 100644 --- a/handler/src/main/java/io/netty/handler/ssl/OpenSslEngine.java +++ b/handler/src/main/java/io/netty/handler/ssl/OpenSslEngine.java @@ -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; } diff --git a/handler/src/test/java/io/netty/handler/ssl/OpenSslEngineTest.java b/handler/src/test/java/io/netty/handler/ssl/OpenSslEngineTest.java index ee29db235f..bea2559d59 100644 --- a/handler/src/test/java/io/netty/handler/ssl/OpenSslEngineTest.java +++ b/handler/src/test/java/io/netty/handler/ssl/OpenSslEngineTest.java @@ -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; diff --git a/handler/src/test/java/io/netty/handler/ssl/SSLEngineTest.java b/handler/src/test/java/io/netty/handler/ssl/SSLEngineTest.java index 3a9936e5d4..e712fb34dc 100644 --- a/handler/src/test/java/io/netty/handler/ssl/SSLEngineTest.java +++ b/handler/src/test/java/io/netty/handler/ssl/SSLEngineTest.java @@ -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(); } diff --git a/pom.xml b/pom.xml index 34d4f4e5ab..2b1828681d 100644 --- a/pom.xml +++ b/pom.xml @@ -687,7 +687,7 @@ ${project.groupId} netty-tcnative - 1.1.33.Fork9 + 1.1.33.Fork10 ${tcnative.classifier} compile true