Fix NETTY-445 Memory leak in SslHandler

* Ensure SSLEngine.closeInbound() and closeOutbound() is called on
handshake failure.
* Ensure connection is closed when a closure request is issued and
handshake failed.
This commit is contained in:
Trustin Lee 2011-10-21 13:54:07 -07:00
parent 8fb34a4717
commit 68c9b0feeb

View File

@ -878,11 +878,7 @@ public class SslHandler extends FrameDecoder
handshake(); handshake();
} }
try { result = engine.unwrap(inNetBuf, outAppBuf);
result = engine.unwrap(inNetBuf, outAppBuf);
} catch (SSLException e) {
throw e;
}
final HandshakeStatus handshakeStatus = result.getHandshakeStatus(); final HandshakeStatus handshakeStatus = result.getHandshakeStatus();
handleRenegotiation(handshakeStatus); handleRenegotiation(handshakeStatus);
@ -1042,29 +1038,59 @@ public class SslHandler extends FrameDecoder
if (handshakeFuture == null) { if (handshakeFuture == null) {
handshakeFuture = future(channel); handshakeFuture = future(channel);
} }
// Release all resources such as internal buffers that SSLEngine
// is managing.
engine.closeOutbound();
try {
engine.closeInbound();
} catch (SSLException e) {
logger.debug(
"SSLEngine.closeInbound() raised an exception after " +
"a handshake failure.", e);
}
} }
handshakeFuture.setFailure(cause); handshakeFuture.setFailure(cause);
} }
private void closeOutboundAndChannel( private void closeOutboundAndChannel(
final ChannelHandlerContext context, final ChannelStateEvent e) throws SSLException { final ChannelHandlerContext context, final ChannelStateEvent e) {
if (!e.getChannel().isConnected()) { if (!e.getChannel().isConnected()) {
context.sendDownstream(e); context.sendDownstream(e);
return; return;
} }
unwrap(context, e.getChannel(), ChannelBuffers.EMPTY_BUFFER, 0, 0); boolean success = false;
if (!engine.isInboundDone()) { try {
if (sentCloseNotify.compareAndSet(false, true)) { try {
engine.closeOutbound(); unwrap(context, e.getChannel(), ChannelBuffers.EMPTY_BUFFER, 0, 0);
ChannelFuture closeNotifyFuture = wrapNonAppData(context, e.getChannel()); } catch (SSLException ex) {
closeNotifyFuture.addListener( logger.debug("Failed to unwrap before sending a close_notify message", ex);
new ClosingChannelFutureListener(context, e)); }
return;
if (!engine.isInboundDone()) {
if (sentCloseNotify.compareAndSet(false, true)) {
engine.closeOutbound();
try {
ChannelFuture closeNotifyFuture = wrapNonAppData(context, e.getChannel());
closeNotifyFuture.addListener(
new ClosingChannelFutureListener(context, e));
success = true;
} catch (SSLException ex) {
logger.debug("Failed to encode a close_notify message", ex);
}
}
} else {
success = true;
}
} finally {
if (!success) {
context.sendDownstream(e);
} }
} }
context.sendDownstream(e);
} }
private static final class PendingWrite { private static final class PendingWrite {