Bug 450280: Remove timeout logic for TLS intolerance, r=honzab

This commit is contained in:
Brian Smith 2013-10-15 01:14:50 -07:00
parent 28b78c172b
commit 098fe5e9a2
4 changed files with 19 additions and 114 deletions

View File

@ -1164,11 +1164,6 @@ AuthCertificateHook(void *arg, PRFileDesc *fd, PRBool checkSig, PRBool isServer)
nsNSSSocketInfo *socketInfo = static_cast<nsNSSSocketInfo*>(arg);
if (socketInfo) {
// This is the first callback during full handshakes.
socketInfo->SetFirstServerHelloReceived();
}
ScopedCERTCertificate serverCert(SSL_PeerCertificate(fd));
if (!checkSig || isServer || !socketInfo || !serverCert) {
@ -1176,6 +1171,8 @@ AuthCertificateHook(void *arg, PRFileDesc *fd, PRBool checkSig, PRBool isServer)
return SECFailure;
}
socketInfo->SetFullHandshake();
if (BlockServerCertChangeForSpdy(socketInfo, serverCert) != SECSuccess)
return SECFailure;

View File

@ -854,7 +854,6 @@ PreliminaryHandshakeDone(PRFileDesc* fd)
return;
infoObject->SetPreliminaryHandshakeDone();
infoObject->SetFirstServerHelloReceived();
// Get the NPN value.
SSLNextProtoState state;
@ -1028,10 +1027,11 @@ void HandshakeCallback(PRFileDesc* fd, void* client_data) {
nsNSSSocketInfo* infoObject = (nsNSSSocketInfo*) fd->higher->secret;
// certificate validation sets FirstServerHelloReceived, so if that flag
// certificate validation sets IsFullHandshake, so if that flag
// is absent at handshake time we have a resumed session. Check this before
// PreliminaryHandshakeDone() because that function also sets that flag.
bool isResumedSession = !(infoObject->GetFirstServerHelloReceived());
bool isResumedSession = !infoObject->IsFullHandshake();
// Do the bookkeeping that needs to be done after the
// server's ServerHello...ServerHelloDone have been processed, but that doesn't
// need the handshake to be completed.

View File

@ -89,13 +89,10 @@ nsNSSSocketInfo::nsNSSSocketInfo(SharedSSLState& aState, uint32_t providerFlags)
mForSTARTTLS(false),
mHandshakePending(true),
mHasCleartextPhase(false),
mHandshakeInProgress(false),
mAllowTLSIntoleranceTimeout(true),
mRememberClientAuthCertificate(false),
mPreliminaryHandshakeDone(false),
mHandshakeStartTime(0),
mFirstServerHelloReceived(false),
mNPNCompleted(false),
mIsFullHandshake(false),
mHandshakeCompleted(false),
mJoined(false),
mSentClientCert(false),
@ -165,20 +162,6 @@ nsNSSSocketInfo::SetSymmetricCipherExpected(int16_t aSymmetricCipher)
return NS_OK;
}
nsresult
nsNSSSocketInfo::GetHandshakePending(bool *aHandshakePending)
{
*aHandshakePending = mHandshakePending;
return NS_OK;
}
nsresult
nsNSSSocketInfo::SetHandshakePending(bool aHandshakePending)
{
mHandshakePending = aHandshakePending;
return NS_OK;
}
NS_IMETHODIMP nsNSSSocketInfo::GetRememberClientAuthCertificate(bool *aRememberClientAuthCertificate)
{
NS_ENSURE_ARG_POINTER(aRememberClientAuthCertificate);
@ -297,6 +280,8 @@ nsNSSSocketInfo::SetHandshakeCompleted(bool aResumedSession)
PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
("[%p] nsNSSSocketInfo::SetHandshakeCompleted\n", (void*)mFd));
mIsFullHandshake = false; // reset for next handshake on this connection
}
}
@ -555,52 +540,11 @@ nsNSSSocketInfo::SetCertVerificationResult(PRErrorCode errorCode,
mCertVerificationState = after_cert_verification;
}
void nsNSSSocketInfo::SetHandshakeInProgress(bool aIsIn)
{
mHandshakeInProgress = aIsIn;
if (mHandshakeInProgress && !mHandshakeStartTime)
{
mHandshakeStartTime = PR_IntervalNow();
}
}
void nsNSSSocketInfo::SetAllowTLSIntoleranceTimeout(bool aAllow)
{
mAllowTLSIntoleranceTimeout = aAllow;
}
SharedSSLState& nsNSSSocketInfo::SharedState()
{
return mSharedState;
}
bool nsNSSSocketInfo::HandshakeTimeout()
{
if (!mAllowTLSIntoleranceTimeout)
return false;
if (!mHandshakeInProgress)
return false; // have not even sent client hello yet
if (mFirstServerHelloReceived)
return false;
// Now we know we are in the first handshake, and haven't received the
// ServerHello+Certificate sequence or the
// ServerHello+ChangeCipherSpec+Finished sequence.
//
// XXX: Bug 754356 - waiting to receive the Certificate or Finished messages
// may cause us to time out in cases where we shouldn't.
static const PRIntervalTime handshakeTimeoutInterval
= PR_SecondsToInterval(25);
PRIntervalTime now = PR_IntervalNow();
bool result = (now - mHandshakeStartTime) > handshakeTimeoutInterval;
return result;
}
void nsSSLIOLayerHelpers::Cleanup()
{
mTLSIntoleranceInfo.Clear();
@ -1040,25 +984,12 @@ int32_t checkHandshake(int32_t bytesTransfered, bool wasReading,
// there are enough broken servers out there that such a gross work-around
// is necessary. :(
// Additional comment added in August 2006:
// When we begun to use TLS hello extensions, we encountered a new class of
// broken server, which simply stall for a very long time.
// We would like to shorten the timeout, but limit this shorter timeout
// to the handshake phase.
// When we arrive here for the first time (for a given socket),
// we know the connection is established, and the application code
// tried the first read or write. This triggers the beginning of the
// SSL handshake phase at the SSL FD level.
// We'll make a note of the current time,
// and use this to measure the elapsed time since handshake begin.
// Do NOT assume TLS intolerance on a closed connection after bad cert ui was shown.
// Simply retry.
// This depends on the fact that Cert UI will not be shown again,
// should the user override the bad cert.
bool handleHandshakeResultNow;
socketInfo->GetHandshakePending(&handleHandshakeResultNow);
bool handleHandshakeResultNow = socketInfo->IsHandshakePending();
bool wantRetry = false;
@ -1067,7 +998,6 @@ int32_t checkHandshake(int32_t bytesTransfered, bool wasReading,
if (handleHandshakeResultNow) {
if (PR_WOULD_BLOCK_ERROR == err) {
socketInfo->SetHandshakeInProgress(true);
return bytesTransfered;
}
@ -1129,8 +1059,7 @@ int32_t checkHandshake(int32_t bytesTransfered, bool wasReading,
// set the HandshakePending attribute to false so that we don't try the logic
// above again in a subsequent transfer.
if (handleHandshakeResultNow) {
socketInfo->SetHandshakePending(false);
socketInfo->SetHandshakeInProgress(false);
socketInfo->SetHandshakeNotPending();
}
return bytesTransfered;
@ -1177,17 +1106,6 @@ nsSSLIOLayerPoll(PRFileDesc * fd, int16_t in_flags, int16_t *out_flags)
: "[%p] poll SSL socket using lower %d\n",
fd, (int) in_flags));
// See comments in HandshakeTimeout before moving and/or changing this block
if (socketInfo->HandshakeTimeout()) {
NS_WARNING("SSL handshake timed out");
PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("[%p] handshake timed out\n", fd));
NS_ASSERTION(in_flags & PR_POLL_EXCEPT,
"caller did not poll for EXCEPT (handshake timeout)");
*out_flags = in_flags | PR_POLL_EXCEPT;
socketInfo->SetCanceled(PR_CONNECT_RESET_ERROR, PlainErrorMessage);
return in_flags;
}
// We want the handshake to continue during certificate validation, so we
// don't need to do anything special here. libssl automatically blocks when
// it reaches any point that would be unsafe to send/receive something before
@ -2651,12 +2569,6 @@ nsSSLIOLayerSetOptions(PRFileDesc *fd, bool forSTARTTLS,
}
infoObject->SetTLSVersionRange(range);
// If min == max, then we don't need the intolerance timeout since we have no
// lower version to fall back to.
if (range.min == range.max) {
infoObject->SetAllowTLSIntoleranceTimeout(false);
}
bool enabled = infoObject->SharedState().IsOCSPStaplingEnabled();
if (SECSuccess != SSL_OptionSet(fd, SSL_ENABLE_OCSP_STAPLING, enabled)) {
return NS_ERROR_FAILURE;
@ -2770,7 +2682,7 @@ nsSSLIOLayerAddToSocket(int32_t family,
// We are going use a clear connection first //
if (forSTARTTLS || proxyHost) {
infoObject->SetHandshakePending(false);
infoObject->SetHandshakeNotPending();
}
infoObject->SharedState().NoteSocketCreated();

View File

@ -41,22 +41,14 @@ public:
nsresult GetFileDescPtr(PRFileDesc** aFilePtr);
nsresult SetFileDescPtr(PRFileDesc* aFilePtr);
nsresult GetHandshakePending(bool *aHandshakePending);
nsresult SetHandshakePending(bool aHandshakePending);
bool IsHandshakePending() const { return mHandshakePending; }
void SetHandshakeNotPending() { mHandshakePending = false; }
void GetPreviousCert(nsIX509Cert** _result);
void SetHasCleartextPhase(bool aHasCleartextPhase);
bool GetHasCleartextPhase();
void SetHandshakeInProgress(bool aIsIn);
bool GetHandshakeInProgress() { return mHandshakeInProgress; }
void SetFirstServerHelloReceived() { mFirstServerHelloReceived = true; }
bool GetFirstServerHelloReceived() { return mFirstServerHelloReceived; }
bool HandshakeTimeout();
void SetAllowTLSIntoleranceTimeout(bool aAllow);
void SetTLSVersionRange(SSLVersionRange range) { mTLSVersionRange = range; }
SSLVersionRange GetTLSVersionRange() const { return mTLSVersionRange; };
@ -67,6 +59,11 @@ public:
void SetHandshakeCompleted(bool aResumedSession);
void NoteTimeUntilReady();
// Note that this is only valid *during* a handshake; at the end of the handshake,
// it gets reset back to false.
void SetFullHandshake() { mIsFullHandshake = true; }
bool IsFullHandshake() const { return mIsFullHandshake; }
bool GetJoined() { return mJoined; }
void SetSentClientCert() { mSentClientCert = true; }
@ -126,8 +123,6 @@ private:
SSLVersionRange mTLSVersionRange;
bool mHandshakePending;
bool mHasCleartextPhase;
bool mHandshakeInProgress;
bool mAllowTLSIntoleranceTimeout;
bool mRememberClientAuthCertificate;
bool mPreliminaryHandshakeDone; // after false start items are complete
PRIntervalTime mHandshakeStartTime;
@ -137,6 +132,7 @@ private:
nsCString mNegotiatedNPN;
bool mNPNCompleted;
bool mIsFullHandshake;
bool mHandshakeCompleted;
bool mJoined;
bool mSentClientCert;