OpenSslEngine wrap may not consume all data
Motivation: If the OpenSslEngine has bytes pending in the non-application buffer and also generates wrapped data during the handshake then the handshake data will be missed. This will lead to a handshake stall and eventually timeout. This can occur if the non-application buffer becomes full due to a large certificate/hello message. Modification: - ReferenceCountedOpenSslEngine should not assume if no data is flushed from the non-application buffer that no data will be produced by the handshake. Result: New unit tests with larger certificate chains don't fail.
This commit is contained in:
parent
c521c72178
commit
d60e37cb3d
@ -483,39 +483,37 @@ public class ReferenceCountedOpenSslEngine extends SSLEngine implements Referenc
|
|||||||
// Flush any data that may have been written implicitly during the handshake by OpenSSL.
|
// Flush any data that may have been written implicitly during the handshake by OpenSSL.
|
||||||
bytesProduced = SSL.bioFlushByteBuffer(networkBIO);
|
bytesProduced = SSL.bioFlushByteBuffer(networkBIO);
|
||||||
|
|
||||||
// Check to see if the engine wrote data into the network BIO.
|
if (bytesProduced > 0 && handshakeException != null) {
|
||||||
if (bytesProduced > 0) {
|
|
||||||
// We produced / consumed some data during the handshake, signal back to the caller.
|
// We produced / consumed some data during the handshake, signal back to the caller.
|
||||||
// If there is a handshake exception and we have produced data, we should send the data before
|
// If there is a handshake exception and we have produced data, we should send the data before
|
||||||
// we allow handshake() to throw the handshake exception.
|
// we allow handshake() to throw the handshake exception.
|
||||||
if (handshakeException == null) {
|
|
||||||
status = handshake();
|
|
||||||
|
|
||||||
if (renegotiationPending && status == FINISHED) {
|
|
||||||
// If renegotiationPending is true that means when we attempted to start renegotiation
|
|
||||||
// the BIO buffer didn't have enough space to hold the HelloRequest which prompts the
|
|
||||||
// client to initiate a renegotiation. At this point the HelloRequest has been written
|
|
||||||
// so we can actually start the handshake process.
|
|
||||||
renegotiationPending = false;
|
|
||||||
SSL.setState(ssl, SSL.SSL_ST_ACCEPT);
|
|
||||||
handshakeState = HandshakeState.STARTED_EXPLICITLY;
|
|
||||||
status = handshake();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handshake may have generated more data, for example if the internal SSL buffer is small
|
|
||||||
// we may have freed up space by flushing above.
|
|
||||||
bytesProduced = bioLengthBefore - SSL.bioLengthByteBuffer(networkBIO);
|
|
||||||
|
|
||||||
// It's important we call this before wrapStatus() as wrapStatus() may shutdown the engine.
|
|
||||||
return newResult(mayFinishHandshake(status != FINISHED ?
|
|
||||||
getHandshakeStatus(SSL.bioLengthNonApplication(networkBIO)) : FINISHED),
|
|
||||||
0, bytesProduced);
|
|
||||||
}
|
|
||||||
return newResult(NEED_WRAP, 0, bytesProduced);
|
return newResult(NEED_WRAP, 0, bytesProduced);
|
||||||
}
|
}
|
||||||
|
|
||||||
status = handshake();
|
status = handshake();
|
||||||
|
|
||||||
|
if (renegotiationPending && status == FINISHED) {
|
||||||
|
// If renegotiationPending is true that means when we attempted to start renegotiation
|
||||||
|
// the BIO buffer didn't have enough space to hold the HelloRequest which prompts the
|
||||||
|
// client to initiate a renegotiation. At this point the HelloRequest has been written
|
||||||
|
// so we can actually start the handshake process.
|
||||||
|
renegotiationPending = false;
|
||||||
|
SSL.setState(ssl, SSL.SSL_ST_ACCEPT);
|
||||||
|
handshakeState = HandshakeState.STARTED_EXPLICITLY;
|
||||||
|
status = handshake();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handshake may have generated more data, for example if the internal SSL buffer is small
|
||||||
|
// we may have freed up space by flushing above.
|
||||||
|
bytesProduced = bioLengthBefore - SSL.bioLengthByteBuffer(networkBIO);
|
||||||
|
|
||||||
|
if (bytesProduced > 0) {
|
||||||
|
// It's important we call this before wrapStatus() as wrapStatus() may shutdown the engine.
|
||||||
|
return newResult(mayFinishHandshake(status != FINISHED ?
|
||||||
|
getHandshakeStatus(SSL.bioLengthNonApplication(networkBIO)) : FINISHED),
|
||||||
|
0, bytesProduced);
|
||||||
|
}
|
||||||
|
|
||||||
if (status == NEED_UNWRAP) {
|
if (status == NEED_UNWRAP) {
|
||||||
// Signal if the outbound is done or not.
|
// Signal if the outbound is done or not.
|
||||||
return isOutboundDone() ? NEED_UNWRAP_CLOSED : NEED_UNWRAP_OK;
|
return isOutboundDone() ? NEED_UNWRAP_CLOSED : NEED_UNWRAP_OK;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user