[#915] [#923] Expanded scope of the handshake locks in SSLHandler to avoid possible negotiation after the first SSLEngine wrap

This commit is contained in:
Aaron 2013-01-10 09:57:37 -08:00 committed by Norman Maurer
parent 974d47f3c4
commit 011ef5dae8

View File

@ -327,43 +327,52 @@ public class SslHandler extends FrameDecoder
* succeeds or fails.
*/
public ChannelFuture handshake() {
if (handshaken && !isEnableRenegotiation()) {
throw new IllegalStateException("renegotiation disabled");
}
ChannelHandlerContext ctx = this.ctx;
Channel channel = ctx.getChannel();
ChannelFuture handshakeFuture;
Exception exception = null;
synchronized (handshakeLock) {
if (handshaken && !isEnableRenegotiation()) {
throw new IllegalStateException("renegotiation disabled");
}
final ChannelHandlerContext ctx = this.ctx;
final Channel channel = ctx.getChannel();
ChannelFuture handshakeFuture;
Exception exception = null;
if (handshaking) {
return this.handshakeFuture;
} else {
handshaking = true;
try {
engine.beginHandshake();
runDelegatedTasks();
handshakeFuture = this.handshakeFuture = future(channel);
} catch (Exception e) {
handshakeFuture = this.handshakeFuture = failedFuture(channel, e);
exception = e;
}
}
}
if (exception == null) { // Began handshake successfully.
handshaking = true;
try {
wrapNonAppData(ctx, channel);
} catch (SSLException e) {
fireExceptionCaught(ctx, e);
handshakeFuture.setFailure(e);
engine.beginHandshake();
runDelegatedTasks();
handshakeFuture = this.handshakeFuture = future(channel);
} catch (Exception e) {
handshakeFuture = this.handshakeFuture = failedFuture(channel, e);
exception = e;
}
} else { // Failed to initiate handshake.
fireExceptionCaught(ctx, exception);
}
return handshakeFuture;
if (exception == null) { // Began handshake successfully.
try {
final ChannelFuture hsFuture = handshakeFuture;
wrapNonAppData(ctx, channel).addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture future) throws Exception {
if (!future.isSuccess()) {
Throwable cause = future.getCause();
hsFuture.setFailure(cause);
fireExceptionCaught(ctx, cause);
}
}
});
} catch (SSLException e) {
handshakeFuture.setFailure(e);
fireExceptionCaught(ctx, e);
}
} else { // Failed to initiate handshake.
fireExceptionCaught(ctx, exception);
}
return handshakeFuture;
}
}
/**
@ -965,19 +974,19 @@ public class SslHandler extends FrameDecoder
}
private void handleRenegotiation(HandshakeStatus handshakeStatus) {
if (handshakeStatus == HandshakeStatus.NOT_HANDSHAKING ||
handshakeStatus == HandshakeStatus.FINISHED) {
// Not handshaking
return;
}
if (!handshaken) {
// Not renegotiation
return;
}
final boolean renegotiate;
synchronized (handshakeLock) {
if (handshakeStatus == HandshakeStatus.NOT_HANDSHAKING ||
handshakeStatus == HandshakeStatus.FINISHED) {
// Not handshaking
return;
}
if (!handshaken) {
// Not renegotiation
return;
}
final boolean renegotiate;
if (handshaking) {
// Renegotiation in progress or failed already.
// i.e. Renegotiation check has been done already below.
@ -998,20 +1007,20 @@ public class SslHandler extends FrameDecoder
// Prevent reentrance of this method.
handshaking = true;
}
}
if (renegotiate) {
// Renegotiate.
handshake();
} else {
// Raise an exception.
fireExceptionCaught(
ctx, new SSLException(
"renegotiation attempted by peer; " +
"closing the connection"));
if (renegotiate) {
// Renegotiate.
handshake();
} else {
// Raise an exception.
fireExceptionCaught(
ctx, new SSLException(
"renegotiation attempted by peer; " +
"closing the connection"));
// Close the connection to stop renegotiation.
Channels.close(ctx, succeededFuture(ctx.getChannel()));
// Close the connection to stop renegotiation.
Channels.close(ctx, succeededFuture(ctx.getChannel()));
}
}
}