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
d2b50aea1e
commit
b462421409
@ -462,39 +462,37 @@ public class ReferenceCountedOpenSslEngine extends SSLEngine implements Referenc
|
||||
// Flush any data that may have been written implicitly during the handshake by OpenSSL.
|
||||
bytesProduced = SSL.bioFlushByteBuffer(networkBIO);
|
||||
|
||||
// Check to see if the engine wrote data into the network BIO.
|
||||
if (bytesProduced > 0) {
|
||||
if (bytesProduced > 0 && handshakeException != null) {
|
||||
// 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
|
||||
// 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);
|
||||
}
|
||||
|
||||
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) {
|
||||
// Signal if the outbound is done or not.
|
||||
return isOutboundDone() ? NEED_UNWRAP_CLOSED : NEED_UNWRAP_OK;
|
||||
|
Loading…
Reference in New Issue
Block a user