SslHandler should fail handshake / close promise and notify pipeline on removal (#10161)
Motivation: If the SslHandler is removed from the pipeline we also need to ensure we fail the handshake / close promise if it was not notified before as otherwise we may never do so. Modifications: - Correctly fail promise and notify pipeline if handshake was not done yet when the SslHandler is removed - Add unit test Result: Fix https://github.com/netty/netty/issues/10158
This commit is contained in:
parent
db39b10249
commit
21f375fa90
@ -68,6 +68,7 @@ import javax.net.ssl.SSLEngineResult;
|
|||||||
import javax.net.ssl.SSLEngineResult.HandshakeStatus;
|
import javax.net.ssl.SSLEngineResult.HandshakeStatus;
|
||||||
import javax.net.ssl.SSLEngineResult.Status;
|
import javax.net.ssl.SSLEngineResult.Status;
|
||||||
import javax.net.ssl.SSLException;
|
import javax.net.ssl.SSLException;
|
||||||
|
import javax.net.ssl.SSLHandshakeException;
|
||||||
import javax.net.ssl.SSLSession;
|
import javax.net.ssl.SSLSession;
|
||||||
|
|
||||||
import static io.netty.buffer.ByteBufUtil.ensureWritableSuccess;
|
import static io.netty.buffer.ByteBufUtil.ensureWritableSuccess;
|
||||||
@ -691,6 +692,24 @@ public class SslHandler extends ByteToMessageDecoder implements ChannelOutboundH
|
|||||||
new ChannelException("Pending write on removal of SslHandler"));
|
new ChannelException("Pending write on removal of SslHandler"));
|
||||||
}
|
}
|
||||||
pendingUnencryptedWrites = null;
|
pendingUnencryptedWrites = null;
|
||||||
|
|
||||||
|
SSLHandshakeException cause = null;
|
||||||
|
|
||||||
|
// If the handshake is not done yet we should fail the handshake promise and notify the rest of the
|
||||||
|
// pipeline.
|
||||||
|
if (!handshakePromise.isDone()) {
|
||||||
|
cause = new SSLHandshakeException("SslHandler removed before handshake completed");
|
||||||
|
if (handshakePromise.tryFailure(cause)) {
|
||||||
|
ctx.fireUserEventTriggered(new SslHandshakeCompletionEvent(cause));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!sslClosePromise.isDone()) {
|
||||||
|
if (cause == null) {
|
||||||
|
cause = new SSLHandshakeException("SslHandler removed before handshake completed");
|
||||||
|
}
|
||||||
|
notifyClosePromise(cause);
|
||||||
|
}
|
||||||
|
|
||||||
if (engine instanceof ReferenceCounted) {
|
if (engine instanceof ReferenceCounted) {
|
||||||
((ReferenceCounted) engine).release();
|
((ReferenceCounted) engine).release();
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,6 @@ import org.junit.Test;
|
|||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.nio.channels.ClosedChannelException;
|
import java.nio.channels.ClosedChannelException;
|
||||||
import java.security.KeyStore;
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.cert.CertificateException;
|
import java.security.cert.CertificateException;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
@ -85,12 +84,10 @@ import java.util.concurrent.TimeUnit;
|
|||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
import javax.net.ssl.ManagerFactoryParameters;
|
|
||||||
import javax.net.ssl.SSLContext;
|
import javax.net.ssl.SSLContext;
|
||||||
import javax.net.ssl.SSLEngine;
|
import javax.net.ssl.SSLEngine;
|
||||||
import javax.net.ssl.SSLException;
|
import javax.net.ssl.SSLException;
|
||||||
import javax.net.ssl.SSLProtocolException;
|
import javax.net.ssl.SSLProtocolException;
|
||||||
import javax.net.ssl.TrustManager;
|
|
||||||
import javax.net.ssl.X509ExtendedTrustManager;
|
import javax.net.ssl.X509ExtendedTrustManager;
|
||||||
|
|
||||||
import static io.netty.buffer.Unpooled.wrappedBuffer;
|
import static io.netty.buffer.Unpooled.wrappedBuffer;
|
||||||
@ -255,6 +252,43 @@ public class SslHandlerTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 5000L)
|
||||||
|
public void testHandshakeAndClosePromiseFailedOnRemoval() throws Exception {
|
||||||
|
SSLEngine engine = SSLContext.getDefault().createSSLEngine();
|
||||||
|
engine.setUseClientMode(true);
|
||||||
|
SslHandler handler = new SslHandler(engine);
|
||||||
|
final AtomicReference<Throwable> handshakeRef = new AtomicReference<Throwable>();
|
||||||
|
final AtomicReference<Throwable> closeRef = new AtomicReference<Throwable>();
|
||||||
|
EmbeddedChannel ch = new EmbeddedChannel(handler, new ChannelInboundHandlerAdapter() {
|
||||||
|
@Override
|
||||||
|
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
|
||||||
|
if (evt instanceof SslHandshakeCompletionEvent) {
|
||||||
|
handshakeRef.set(((SslHandshakeCompletionEvent) evt).cause());
|
||||||
|
} else if (evt instanceof SslCloseCompletionEvent) {
|
||||||
|
closeRef.set(((SslCloseCompletionEvent) evt).cause());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
assertFalse(handler.handshakeFuture().isDone());
|
||||||
|
assertFalse(handler.sslCloseFuture().isDone());
|
||||||
|
|
||||||
|
ch.pipeline().remove(handler);
|
||||||
|
|
||||||
|
try {
|
||||||
|
while (!handler.handshakeFuture().isDone() || handshakeRef.get() == null
|
||||||
|
|| !handler.sslCloseFuture().isDone() || closeRef.get() == null) {
|
||||||
|
Thread.sleep(10);
|
||||||
|
// Continue running all pending tasks until we notified for everything.
|
||||||
|
ch.runPendingTasks();
|
||||||
|
}
|
||||||
|
|
||||||
|
assertSame(handler.handshakeFuture().cause(), handshakeRef.get());
|
||||||
|
assertSame(handler.sslCloseFuture().cause(), closeRef.get());
|
||||||
|
} finally {
|
||||||
|
ch.finishAndReleaseAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTruncatedPacket() throws Exception {
|
public void testTruncatedPacket() throws Exception {
|
||||||
SSLEngine engine = newServerModeSSLEngine();
|
SSLEngine engine = newServerModeSSLEngine();
|
||||||
|
Loading…
Reference in New Issue
Block a user