/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
auto timestampNow = TimeStamp::Now(); if (!(mProviderFlags & nsISocketProvider::IS_RETRY)) {
Telemetry::AccumulateTimeDelta(Telemetry::SSL_TIME_UNTIL_READY_FIRST_TRY,
mSocketCreationTimestamp, timestampNow);
}
if (mProviderFlags & nsISocketProvider::BE_CONSERVATIVE) {
Telemetry::AccumulateTimeDelta(Telemetry::SSL_TIME_UNTIL_READY_CONSERVATIVE,
mSocketCreationTimestamp, timestampNow);
}
switch (GetEchExtensionStatus()) { case EchExtensionStatus::kGREASE:
Telemetry::AccumulateTimeDelta(Telemetry::SSL_TIME_UNTIL_READY_ECH_GREASE,
mSocketCreationTimestamp, timestampNow); break; case EchExtensionStatus::kReal:
Telemetry::AccumulateTimeDelta(Telemetry::SSL_TIME_UNTIL_READY_ECH,
mSocketCreationTimestamp, timestampNow); break; default: break;
} // This will include TCP and proxy tunnel wait time
Telemetry::AccumulateTimeDelta(Telemetry::SSL_TIME_UNTIL_READY,
mSocketCreationTimestamp, timestampNow);
HandshakeType handshakeType = !IsFullHandshake() ? Resumption
: mFalseStarted ? FalseStarted
: mFalseStartCallbackCalled
? ChoseNotToFalseStart
: NotAllowedToFalseStart; // This will include TCP and proxy tunnel wait time if (mKeaGroupName.isSome()) {
Telemetry::AccumulateTimeDelta(
Telemetry::SSL_TIME_UNTIL_HANDSHAKE_FINISHED_KEYED_BY_KA,
*mKeaGroupName, mSocketCreationTimestamp, TimeStamp::Now());
}
// If the handshake is completed for the first time from just 1 callback // that means that TLS session resumption must have been used.
Telemetry::Accumulate(Telemetry::SSL_RESUMED_SESSION,
handshakeType == Resumption);
Telemetry::Accumulate(Telemetry::SSL_HANDSHAKE_TYPE, handshakeType);
}
// Remove the plaintext layer as it is not needed anymore. // The plaintext layer is not always present - so it's not a fatal error if it // cannot be removed. // Note that PR_PopIOLayer may modify its stack, so a pointer returned by // PR_GetIdentitiesLayer may not point to what we think it points to after // calling PR_PopIOLayer. We must operate on the pointer returned by // PR_PopIOLayer. if (PR_GetIdentitiesLayer(mFd,
nsSSLIOLayerHelpers::nsSSLPlaintextLayerIdentity)) {
PRFileDesc* poppedPlaintext =
PR_PopIOLayer(mFd, nsSSLIOLayerHelpers::nsSSLPlaintextLayerIdentity);
poppedPlaintext->dtor(poppedPlaintext);
}
NS_IMETHODIMP
NSSSocketControl::DriveHandshake() {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD(); if (!mFd) { return NS_ERROR_FAILURE;
} if (IsCanceled()) {
PRErrorCode errorCode = GetErrorCode();
MOZ_DIAGNOSTIC_ASSERT(errorCode, "handshake cancelled without error code"); return GetXPCOMFromNSSError(errorCode);
}
SECStatus rv = SSL_ForceHandshake(mFd);
if (rv != SECSuccess) {
PRErrorCode errorCode = PR_GetError();
MOZ_ASSERT(errorCode, "handshake failed without error code"); // There is a bug in NSS. Sometimes SSL_ForceHandshake will return // SECFailure without setting an error code. In these cases, cancel // the connection with SEC_ERROR_LIBRARY_FAILURE. if (!errorCode) {
errorCode = SEC_ERROR_LIBRARY_FAILURE;
} if (errorCode == PR_WOULD_BLOCK_ERROR) { return NS_BASE_STREAM_WOULD_BLOCK;
}
NS_IMETHODIMP
NSSSocketControl::SetNPNList(nsTArray<nsCString>& protocolArray) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD(); if (!mFd) return NS_ERROR_FAILURE;
// the npn list is a concatenated list of 8 bit byte strings.
nsCString npnList;
for (uint32_t index = 0; index < protocolArray.Length(); ++index) { if (protocolArray[index].IsEmpty() || protocolArray[index].Length() > 255) return NS_ERROR_ILLEGAL_VALUE;
void NSSSocketControl::SetCertVerificationWaiting() {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD(); // mCertVerificationState may be BeforeCertVerification for the first // handshake on the connection, or AfterCertVerification for subsequent // renegotiation handshakes.
MOZ_ASSERT(mCertVerificationState != WaitingForCertVerification, "Invalid state transition to WaitingForCertVerification");
mCertVerificationState = WaitingForCertVerification;
}
// Be careful that SetCertVerificationResult does NOT get called while we are // processing a SSL callback function, because SSL_AuthCertificateComplete will // attempt to acquire locks that are already held by libssl when it calls // callbacks. void NSSSocketControl::SetCertVerificationResult(PRErrorCode errorCode) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
SetUsedPrivateDNS(GetProviderFlags() & nsISocketProvider::USED_PRIVATE_DNS);
MOZ_ASSERT(mCertVerificationState == WaitingForCertVerification, "Invalid state transition to AfterCertVerification");
if (mFd) {
SECStatus rv = SSL_AuthCertificateComplete(mFd, errorCode); // Only replace errorCode if there was originally no error. // SSL_AuthCertificateComplete will return SECFailure with the error code // set to PR_WOULD_BLOCK_ERROR if there is a pending event to select a // client authentication certificate. This is not an error. if (rv != SECSuccess && PR_GetError() != PR_WOULD_BLOCK_ERROR &&
errorCode == 0) {
errorCode = PR_GetError(); if (errorCode == 0) {
NS_ERROR("SSL_AuthCertificateComplete didn't set error code");
errorCode = PR_INVALID_STATE_ERROR;
}
}
}
if (errorCode) {
mFailedVerification = true;
SetCanceled(errorCode);
}
if (mPlaintextBytesRead && !errorCode) {
Telemetry::Accumulate(Telemetry::SSL_BYTES_BEFORE_CERT_CALLBACK,
AssertedCast<uint32_t>(mPlaintextBytesRead));
}
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
("[%p] SetCertVerificationResult to AfterCertVerification, " "mTlsHandshakeCallback=%p",
(void*)mFd, mTlsHandshakeCallback.get()));
PRFileDesc* popped = PR_PopIOLayer(mFd, PR_TOP_IO_LAYER);
MOZ_ASSERT(
popped && popped->identity == nsSSLIOLayerHelpers::nsSSLIOLayerIdentity, "SSL Layer not on top of stack");
// The plaintext layer is not always present - so it's not a fatal error if it // cannot be removed. // Note that PR_PopIOLayer may modify its stack, so a pointer returned by // PR_GetIdentitiesLayer may not point to what we think it points to after // calling PR_PopIOLayer. We must operate on the pointer returned by // PR_PopIOLayer. if (PR_GetIdentitiesLayer(mFd,
nsSSLIOLayerHelpers::nsSSLPlaintextLayerIdentity)) {
PRFileDesc* poppedPlaintext =
PR_PopIOLayer(mFd, nsSSLIOLayerHelpers::nsSSLPlaintextLayerIdentity);
poppedPlaintext->dtor(poppedPlaintext);
}
// We need to clear the callback to make sure the ssl layer cannot call the // callback after mFD is nulled.
SSL_SetResumptionTokenCallback(mFd, nullptr, nullptr);
PRStatus status = mFd->methods->close(mFd);
// the NSSSocketControl instance can out-live the connection, so we need some // indication that the connection has been closed. mFd == nullptr is that // indication. This is needed, for example, when the connection is closed // before we have finished validating the server's certificate.
mFd = nullptr;
// If SSL_NO_CACHE option was set, we must not use the cache
PRIntn val; if (SSL_OptionGet(fd, SSL_NO_CACHE, &val) != SECSuccess) { return NS_ERROR_FAILURE;
}
uint64_t tokenId = 0;
mozilla::net::SessionCacheInfo info;
rv = mozilla::net::SSLTokensCache::Get(peerId, token, info, &tokenId); if (NS_FAILED(rv)) { if (rv == NS_ERROR_NOT_AVAILABLE) { // It's ok if we can't find the token. return NS_OK;
}
return rv;
}
SECStatus srv = SSL_SetResumptionToken(fd, token.Elements(), token.Length()); if (srv == SECFailure) {
PRErrorCode error = PR_GetError();
mozilla::net::SSLTokensCache::Remove(peerId, tokenId);
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
("Setting token failed with NSS error %d [id=%s]", error,
PromiseFlatCString(peerId).get())); // We don't consider SSL_ERROR_BAD_RESUMPTION_TOKEN_ERROR as a hard error, // since this error means this token is just expired or can't be decoded // correctly. if (error == SSL_ERROR_BAD_RESUMPTION_TOKEN_ERROR) { return NS_OK;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.