ReferenceCountedOpenSslEngine unwrap handshake complete status fix (#11210)

Motivation:
ReferenceCountedOpenSslEngine may unwrap data and complete the handshake
in a single unwrap() call. However it may return HanshakeStatus of
HandshakeStatus of NEED_UNWRAP instead of FINISHED. This may result in
the SslHandler sending the unwrapped data up the pipeline before
notifying that the handshake has completed, and result in out-of-order
events.

Modifications:
- if ReferenceCountedOpenSslEngine handshake status is NEED_UNWRAP and
  produced data, or NEED_WRAP and consumed some data, we should call
  handshake() to get the current state.

Result:
ReferenceCountedOpenSslEngine correctly indicates when the handshake has
finished if at the same time data was produced or consumed.
This commit is contained in:
Scott Mitchell 2021-04-29 00:56:01 -07:00 committed by Norman Maurer
parent bf721c84f4
commit 382885538f

View File

@ -70,8 +70,8 @@ import static io.netty.handler.ssl.SslUtils.PROTOCOL_TLS_V1_1;
import static io.netty.handler.ssl.SslUtils.PROTOCOL_TLS_V1_2; import static io.netty.handler.ssl.SslUtils.PROTOCOL_TLS_V1_2;
import static io.netty.handler.ssl.SslUtils.PROTOCOL_TLS_V1_3; import static io.netty.handler.ssl.SslUtils.PROTOCOL_TLS_V1_3;
import static io.netty.handler.ssl.SslUtils.SSL_RECORD_HEADER_LENGTH; import static io.netty.handler.ssl.SslUtils.SSL_RECORD_HEADER_LENGTH;
import static io.netty.util.internal.ObjectUtil.checkNotNullWithIAE;
import static io.netty.util.internal.ObjectUtil.checkNotNullArrayParam; import static io.netty.util.internal.ObjectUtil.checkNotNullArrayParam;
import static io.netty.util.internal.ObjectUtil.checkNotNullWithIAE;
import static java.lang.Integer.MAX_VALUE; import static java.lang.Integer.MAX_VALUE;
import static java.lang.Math.min; import static java.lang.Math.min;
import static java.util.Objects.requireNonNull; import static java.util.Objects.requireNonNull;
@ -1023,15 +1023,13 @@ public class ReferenceCountedOpenSslEngine extends SSLEngine implements Referenc
private SSLEngineResult newResultMayFinishHandshake(SSLEngineResult.HandshakeStatus hs, private SSLEngineResult newResultMayFinishHandshake(SSLEngineResult.HandshakeStatus hs,
int bytesConsumed, int bytesProduced) throws SSLException { int bytesConsumed, int bytesProduced) throws SSLException {
return newResult(mayFinishHandshake(hs != FINISHED ? getHandshakeStatus() : FINISHED), return newResult(mayFinishHandshake(hs, bytesConsumed, bytesProduced), bytesConsumed, bytesProduced);
bytesConsumed, bytesProduced);
} }
private SSLEngineResult newResultMayFinishHandshake(SSLEngineResult.Status status, private SSLEngineResult newResultMayFinishHandshake(SSLEngineResult.Status status,
SSLEngineResult.HandshakeStatus hs, SSLEngineResult.HandshakeStatus hs,
int bytesConsumed, int bytesProduced) throws SSLException { int bytesConsumed, int bytesProduced) throws SSLException {
return newResult(status, mayFinishHandshake(hs != FINISHED ? getHandshakeStatus() : FINISHED), return newResult(status, mayFinishHandshake(hs, bytesConsumed, bytesProduced), bytesConsumed, bytesProduced);
bytesConsumed, bytesProduced);
} }
/** /**
@ -1922,6 +1920,12 @@ public class ReferenceCountedOpenSslEngine extends SSLEngine implements Referenc
return FINISHED; return FINISHED;
} }
private SSLEngineResult.HandshakeStatus mayFinishHandshake(
SSLEngineResult.HandshakeStatus hs, int bytesConsumed, int bytesProduced) throws SSLException {
return hs == NEED_UNWRAP && bytesProduced > 0 || hs == NEED_WRAP && bytesConsumed > 0 ?
handshake() : mayFinishHandshake(hs != FINISHED ? getHandshakeStatus() : FINISHED);
}
private SSLEngineResult.HandshakeStatus mayFinishHandshake(SSLEngineResult.HandshakeStatus status) private SSLEngineResult.HandshakeStatus mayFinishHandshake(SSLEngineResult.HandshakeStatus status)
throws SSLException { throws SSLException {
if (status == NOT_HANDSHAKING && handshakeState != HandshakeState.FINISHED) { if (status == NOT_HANDSHAKING && handshakeState != HandshakeState.FINISHED) {