Bug 1791633 - separate nsITLSSocketControl from nsITransportSecurityInfo r=necko-reviewers,kershaw,jschanck

Depends on D160311

Differential Revision: https://phabricator.services.mozilla.com/D160313
This commit is contained in:
Dana Keeler 2022-11-15 20:03:29 +00:00
Родитель 21ac70dabe
Коммит 0a13b94a8f
41 изменённых файлов: 1472 добавлений и 1507 удалений

Просмотреть файл

@ -6,6 +6,7 @@
#include "ipc/IPCMessageUtils.h"
#include "mozilla/psm/TransportSecurityInfo.h"
#include "nsNSSCertificate.h"
namespace IPC {

Просмотреть файл

@ -5,6 +5,7 @@
#ifndef mozilla_ipc_TransportSecurityInfoUtils_h
#define mozilla_ipc_TransportSecurityInfoUtils_h
#include "ipc/EnumSerializer.h"
#include "mozilla/RefPtr.h"
#include "nsITransportSecurityInfo.h"
#include "nsIX509Cert.h"
@ -30,6 +31,13 @@ struct ParamTraits<nsIX509Cert*> {
static bool Read(MessageReader* aReader, RefPtr<nsIX509Cert>* aResult);
};
template <>
struct ParamTraits<nsITransportSecurityInfo::OverridableErrorCategory>
: public ContiguousEnumSerializerInclusive<
nsITransportSecurityInfo::OverridableErrorCategory,
nsITransportSecurityInfo::OverridableErrorCategory::ERROR_UNSET,
nsITransportSecurityInfo::OverridableErrorCategory::ERROR_TIME> {};
} // namespace IPC
#endif // mozilla_ipc_TransportSecurityInfoUtils_h

Просмотреть файл

@ -1,366 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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/. */
#include "FuzzySecurityInfo.h"
#include "mozilla/Logging.h"
#include "mozilla/OriginAttributes.h"
#include "nsITlsHandshakeListener.h"
#include "nsThreadManager.h"
namespace mozilla {
namespace net {
FuzzySecurityInfo::FuzzySecurityInfo() {}
FuzzySecurityInfo::~FuzzySecurityInfo() {}
NS_IMPL_ISUPPORTS(FuzzySecurityInfo, nsITransportSecurityInfo,
nsIInterfaceRequestor, nsITLSSocketControl)
NS_IMETHODIMP
FuzzySecurityInfo::GetErrorCode(int32_t* state) {
*state = 0;
return NS_OK;
}
NS_IMETHODIMP
FuzzySecurityInfo::GetSecurityState(uint32_t* state) {
*state = 0;
return NS_OK;
}
NS_IMETHODIMP
FuzzySecurityInfo::GetErrorCodeString(nsAString& aErrorString) {
MOZ_CRASH("Unused");
return NS_OK;
}
NS_IMETHODIMP
FuzzySecurityInfo::GetFailedCertChain(
nsTArray<RefPtr<nsIX509Cert>>& aFailedCertChain) {
MOZ_CRASH("Unused");
return NS_OK;
}
NS_IMETHODIMP
FuzzySecurityInfo::GetServerCert(nsIX509Cert** aServerCert) {
NS_ENSURE_ARG_POINTER(aServerCert);
// This method is called by nsHttpChannel::ProcessSSLInformation()
// in order to display certain information in the console.
// Returning NULL is okay here and handled by the caller.
*aServerCert = NULL;
return NS_OK;
}
NS_IMETHODIMP
FuzzySecurityInfo::GetSucceededCertChain(
nsTArray<RefPtr<nsIX509Cert>>& aSucceededCertChain) {
MOZ_CRASH("Unused");
return NS_OK;
}
NS_IMETHODIMP
FuzzySecurityInfo::GetCipherName(nsACString& aCipherName) {
MOZ_CRASH("Unused");
return NS_OK;
}
NS_IMETHODIMP
FuzzySecurityInfo::GetKeyLength(uint32_t* aKeyLength) {
MOZ_CRASH("Unused");
return NS_OK;
}
NS_IMETHODIMP
FuzzySecurityInfo::GetSecretKeyLength(uint32_t* aSecretKeyLength) {
MOZ_CRASH("Unused");
*aSecretKeyLength = 4096;
return NS_OK;
}
NS_IMETHODIMP
FuzzySecurityInfo::GetKeaGroupName(nsACString& aKeaGroup) {
MOZ_CRASH("Unused");
return NS_OK;
}
NS_IMETHODIMP
FuzzySecurityInfo::GetSignatureSchemeName(nsACString& aSignatureScheme) {
MOZ_CRASH("Unused");
return NS_OK;
}
NS_IMETHODIMP
FuzzySecurityInfo::GetProtocolVersion(uint16_t* aProtocolVersion) {
NS_ENSURE_ARG_POINTER(aProtocolVersion);
// Must be >= TLS 1.2 for HTTP2
*aProtocolVersion = nsITransportSecurityInfo::TLS_VERSION_1_2;
return NS_OK;
}
NS_IMETHODIMP
FuzzySecurityInfo::GetCertificateTransparencyStatus(
uint16_t* aCertificateTransparencyStatus) {
NS_ENSURE_ARG_POINTER(aCertificateTransparencyStatus);
MOZ_CRASH("Unused");
return NS_OK;
}
NS_IMETHODIMP
FuzzySecurityInfo::GetOverridableErrorCategory(
OverridableErrorCategory* aOverridableErrorCode) {
NS_ENSURE_ARG_POINTER(aOverridableErrorCode);
*aOverridableErrorCode = OverridableErrorCategory::ERROR_UNSET;
return NS_OK;
}
NS_IMETHODIMP
FuzzySecurityInfo::GetIsExtendedValidation(bool* aIsEV) {
NS_ENSURE_ARG_POINTER(aIsEV);
*aIsEV = true;
return NS_OK;
}
NS_IMETHODIMP
FuzzySecurityInfo::GetIsDelegatedCredential(bool* aIsDelegCred) {
NS_ENSURE_ARG_POINTER(aIsDelegCred);
*aIsDelegCred = false;
return NS_OK;
}
NS_IMETHODIMP
FuzzySecurityInfo::GetIsAcceptedEch(bool* aIsAcceptedEch) {
NS_ENSURE_ARG_POINTER(aIsAcceptedEch);
*aIsAcceptedEch = false;
return NS_OK;
}
NS_IMETHODIMP
FuzzySecurityInfo::GetInterface(const nsIID& uuid, void** result) {
if (!NS_IsMainThread()) {
MOZ_CRASH("FuzzySecurityInfo::GetInterface called off the main thread");
return NS_ERROR_NOT_SAME_THREAD;
}
nsresult rv = NS_ERROR_NO_INTERFACE;
if (mCallbacks) {
rv = mCallbacks->GetInterface(uuid, result);
}
return rv;
}
NS_IMETHODIMP
FuzzySecurityInfo::GetNotificationCallbacks(
nsIInterfaceRequestor** aCallbacks) {
nsCOMPtr<nsIInterfaceRequestor> ir(mCallbacks);
ir.forget(aCallbacks);
return NS_OK;
}
NS_IMETHODIMP
FuzzySecurityInfo::SetNotificationCallbacks(nsIInterfaceRequestor* aCallbacks) {
mCallbacks = aCallbacks;
return NS_OK;
}
NS_IMETHODIMP
FuzzySecurityInfo::GetProviderFlags(uint32_t* aProviderFlags) {
MOZ_CRASH("Unused");
return NS_OK;
}
NS_IMETHODIMP
FuzzySecurityInfo::GetProviderTlsFlags(uint32_t* aProviderTlsFlags) {
MOZ_CRASH("Unused");
return NS_OK;
}
NS_IMETHODIMP
FuzzySecurityInfo::GetKEAUsed(int16_t* aKea) {
// Can be ssl_kea_dh or ssl_kea_ecdh for HTTP2
*aKea = ssl_kea_ecdh;
return NS_OK;
}
NS_IMETHODIMP
FuzzySecurityInfo::GetKEAKeyBits(uint32_t* aKeyBits) {
// Must be >= 224 for ecdh and >= 2048 for dh when using HTTP2
*aKeyBits = 256;
return NS_OK;
}
NS_IMETHODIMP
FuzzySecurityInfo::GetSSLVersionUsed(int16_t* aSSLVersionUsed) {
// Must be >= TLS 1.2 for HTTP2
*aSSLVersionUsed = nsITLSSocketControl::TLS_VERSION_1_2;
return NS_OK;
}
NS_IMETHODIMP
FuzzySecurityInfo::GetSSLVersionOffered(int16_t* aSSLVersionOffered) {
*aSSLVersionOffered = nsITLSSocketControl::TLS_VERSION_1_2;
return NS_OK;
}
NS_IMETHODIMP
FuzzySecurityInfo::GetMACAlgorithmUsed(int16_t* aMac) {
// The only valid choice for HTTP2 is SSL_MAC_AEAD
*aMac = nsITLSSocketControl::SSL_MAC_AEAD;
return NS_OK;
}
bool FuzzySecurityInfo::GetDenyClientCert() { return false; }
void FuzzySecurityInfo::SetDenyClientCert(bool aDenyClientCert) {
// Called by mozilla::net::nsHttpConnection::StartSpdy
}
NS_IMETHODIMP
FuzzySecurityInfo::GetClientCertSent(bool* arg) {
*arg = false;
return NS_OK;
}
NS_IMETHODIMP
FuzzySecurityInfo::GetFailedVerification(bool* arg) {
*arg = false;
return NS_OK;
}
NS_IMETHODIMP
FuzzySecurityInfo::ToString(nsACString& aResult) {
MOZ_CRASH("Unused");
return NS_OK;
}
NS_IMETHODIMP
FuzzySecurityInfo::GetNegotiatedNPN(nsACString& aNegotiatedNPN) {
aNegotiatedNPN = "h2";
return NS_OK;
}
NS_IMETHODIMP
FuzzySecurityInfo::GetAlpnEarlySelection(nsACString& aAlpnSelected) {
// TODO: For now we don't support early selection
return NS_ERROR_NOT_AVAILABLE;
}
NS_IMETHODIMP
FuzzySecurityInfo::GetEarlyDataAccepted(bool* aAccepted) {
*aAccepted = false;
return NS_OK;
}
NS_IMETHODIMP
FuzzySecurityInfo::GetResumed(bool* aResumed) {
*aResumed = false;
return NS_OK;
}
NS_IMETHODIMP
FuzzySecurityInfo::DriveHandshake() { return NS_OK; }
NS_IMETHODIMP
FuzzySecurityInfo::IsAcceptableForHost(const nsACString& hostname,
bool* _retval) {
NS_ENSURE_ARG(_retval);
*_retval = true;
return NS_OK;
}
NS_IMETHODIMP
FuzzySecurityInfo::TestJoinConnection(const nsACString& npnProtocol,
const nsACString& hostname, int32_t port,
bool* _retval) {
*_retval = false;
return NS_OK;
}
NS_IMETHODIMP
FuzzySecurityInfo::JoinConnection(const nsACString& npnProtocol,
const nsACString& hostname, int32_t port,
bool* _retval) {
*_retval = false;
return NS_OK;
}
NS_IMETHODIMP
FuzzySecurityInfo::ProxyStartSSL() { return NS_OK; }
NS_IMETHODIMP
FuzzySecurityInfo::StartTLS() { return NS_OK; }
NS_IMETHODIMP
FuzzySecurityInfo::SetNPNList(nsTArray<nsCString>& protocolArray) {
return NS_OK;
}
NS_IMETHODIMP
FuzzySecurityInfo::GetEsniTxt(nsACString& aEsniTxt) { return NS_OK; }
NS_IMETHODIMP
FuzzySecurityInfo::SetEsniTxt(const nsACString& aEsniTxt) {
MOZ_CRASH("Unused");
return NS_OK;
}
NS_IMETHODIMP
FuzzySecurityInfo::GetEchConfig(nsACString& aEchConfig) { return NS_OK; }
NS_IMETHODIMP
FuzzySecurityInfo::SetEchConfig(const nsACString& aEchConfig) {
MOZ_CRASH("Unused");
return NS_OK;
}
NS_IMETHODIMP
FuzzySecurityInfo::GetRetryEchConfig(nsACString& aEchConfig) { return NS_OK; }
void FuzzySecurityInfo::SerializeToIPC(IPC::MessageWriter* aWriter) {
MOZ_CRASH("Unused");
}
NS_IMETHODIMP
FuzzySecurityInfo::GetPeerId(nsACString& aResult) {
aResult.Assign(""_ns);
return NS_OK;
}
NS_IMETHODIMP FuzzySecurityInfo::SetIsBuiltCertChainRootBuiltInRoot(
bool aIsBuiltInRoot) {
return NS_OK;
}
NS_IMETHODIMP FuzzySecurityInfo::GetIsBuiltCertChainRootBuiltInRoot(
bool* aIsBuiltInRoot) {
*aIsBuiltInRoot = false;
return NS_OK;
}
NS_IMETHODIMP
FuzzySecurityInfo::GetUsedPrivateDNS(bool* aUsedPrivateDNS) {
*aUsedPrivateDNS = false;
return NS_OK;
}
NS_IMETHODIMP
FuzzySecurityInfo::GetMadeOCSPRequests(bool* aMadeOCSPRequests) {
*aMadeOCSPRequests = false;
return NS_OK;
}
NS_IMETHODIMP FuzzySecurityInfo::DisableEarlyData(void) { return NS_OK; }
NS_IMETHODIMP FuzzySecurityInfo::SetHandshakeCallbackListener(
nsITlsHandshakeCallbackListener* callback) {
if (callback) {
callback->HandshakeDone();
}
return NS_OK;
}
} // namespace net
} // namespace mozilla

Просмотреть файл

@ -1,43 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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/. */
#ifndef FuzzySecurityInfo_h__
#define FuzzySecurityInfo_h__
#include "nsCOMPtr.h"
#include "nsIInterfaceRequestor.h"
#include "nsITLSSocketControl.h"
#include "nsITransportSecurityInfo.h"
#include "prerror.h"
#include "sslproto.h"
#include "sslt.h"
namespace mozilla {
namespace net {
class FuzzySecurityInfo final : public nsITransportSecurityInfo,
public nsIInterfaceRequestor,
public nsITLSSocketControl {
public:
FuzzySecurityInfo();
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSITRANSPORTSECURITYINFO
NS_DECL_NSIINTERFACEREQUESTOR
NS_DECL_NSISSLSOCKETCONTROL
protected:
virtual ~FuzzySecurityInfo();
private:
nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
}; // class FuzzySecurityInfo
} // namespace net
} // namespace mozilla
#endif // FuzzySecurityInfo_h__

Просмотреть файл

@ -0,0 +1,180 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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/. */
#include "FuzzySocketControl.h"
#include "ipc/IPCMessageUtils.h"
#include "nsITlsHandshakeListener.h"
#include "sslt.h"
namespace mozilla {
namespace net {
FuzzySocketControl::FuzzySocketControl() {}
FuzzySocketControl::~FuzzySocketControl() {}
NS_IMPL_ISUPPORTS(FuzzySocketControl, nsITLSSocketControl)
NS_IMETHODIMP
FuzzySocketControl::GetProviderFlags(uint32_t* aProviderFlags) {
MOZ_CRASH("Unused");
return NS_OK;
}
NS_IMETHODIMP
FuzzySocketControl::GetKEAUsed(int16_t* aKea) {
// Can be ssl_kea_dh or ssl_kea_ecdh for HTTP2
*aKea = ssl_kea_ecdh;
return NS_OK;
}
NS_IMETHODIMP
FuzzySocketControl::GetKEAKeyBits(uint32_t* aKeyBits) {
// Must be >= 224 for ecdh and >= 2048 for dh when using HTTP2
*aKeyBits = 256;
return NS_OK;
}
NS_IMETHODIMP
FuzzySocketControl::GetSSLVersionUsed(int16_t* aSSLVersionUsed) {
// Must be >= TLS 1.2 for HTTP2
*aSSLVersionUsed = nsITLSSocketControl::TLS_VERSION_1_2;
return NS_OK;
}
NS_IMETHODIMP
FuzzySocketControl::GetSSLVersionOffered(int16_t* aSSLVersionOffered) {
*aSSLVersionOffered = nsITLSSocketControl::TLS_VERSION_1_2;
return NS_OK;
}
NS_IMETHODIMP
FuzzySocketControl::GetMACAlgorithmUsed(int16_t* aMac) {
// The only valid choice for HTTP2 is SSL_MAC_AEAD
*aMac = nsITLSSocketControl::SSL_MAC_AEAD;
return NS_OK;
}
bool FuzzySocketControl::GetDenyClientCert() { return false; }
void FuzzySocketControl::SetDenyClientCert(bool aDenyClientCert) {
// Called by mozilla::net::nsHttpConnection::StartSpdy
}
NS_IMETHODIMP
FuzzySocketControl::GetClientCertSent(bool* arg) {
*arg = false;
return NS_OK;
}
NS_IMETHODIMP
FuzzySocketControl::GetFailedVerification(bool* arg) {
*arg = false;
return NS_OK;
}
NS_IMETHODIMP
FuzzySocketControl::GetAlpnEarlySelection(nsACString& aAlpnSelected) {
// TODO: For now we don't support early selection
return NS_ERROR_NOT_AVAILABLE;
}
NS_IMETHODIMP
FuzzySocketControl::GetEarlyDataAccepted(bool* aAccepted) {
*aAccepted = false;
return NS_OK;
}
NS_IMETHODIMP
FuzzySocketControl::DriveHandshake() { return NS_OK; }
NS_IMETHODIMP
FuzzySocketControl::IsAcceptableForHost(const nsACString& hostname,
bool* _retval) {
NS_ENSURE_ARG(_retval);
*_retval = true;
return NS_OK;
}
NS_IMETHODIMP
FuzzySocketControl::TestJoinConnection(const nsACString& npnProtocol,
const nsACString& hostname, int32_t port,
bool* _retval) {
*_retval = false;
return NS_OK;
}
NS_IMETHODIMP
FuzzySocketControl::JoinConnection(const nsACString& npnProtocol,
const nsACString& hostname, int32_t port,
bool* _retval) {
*_retval = false;
return NS_OK;
}
NS_IMETHODIMP
FuzzySocketControl::ProxyStartSSL() { return NS_OK; }
NS_IMETHODIMP
FuzzySocketControl::StartTLS() { return NS_OK; }
NS_IMETHODIMP
FuzzySocketControl::SetNPNList(nsTArray<nsCString>& protocolArray) {
return NS_OK;
}
NS_IMETHODIMP
FuzzySocketControl::GetEsniTxt(nsACString& aEsniTxt) { return NS_OK; }
NS_IMETHODIMP
FuzzySocketControl::SetEsniTxt(const nsACString& aEsniTxt) {
MOZ_CRASH("Unused");
return NS_OK;
}
NS_IMETHODIMP
FuzzySocketControl::GetEchConfig(nsACString& aEchConfig) { return NS_OK; }
NS_IMETHODIMP
FuzzySocketControl::SetEchConfig(const nsACString& aEchConfig) {
MOZ_CRASH("Unused");
return NS_OK;
}
NS_IMETHODIMP
FuzzySocketControl::GetRetryEchConfig(nsACString& aEchConfig) { return NS_OK; }
NS_IMETHODIMP
FuzzySocketControl::GetPeerId(nsACString& aResult) {
aResult.Assign(""_ns);
return NS_OK;
}
NS_IMETHODIMP FuzzySocketControl::SetHandshakeCallbackListener(
nsITlsHandshakeCallbackListener* callback) {
if (callback) {
callback->HandshakeDone();
}
return NS_OK;
}
NS_IMETHODIMP
FuzzySocketControl::DisableEarlyData(void) { return NS_ERROR_NOT_IMPLEMENTED; }
NS_IMETHODIMP FuzzySocketControl::GetSecurityInfo(
nsITransportSecurityInfo** aSecurityInfo) {
*aSecurityInfo = nullptr;
return NS_OK;
}
NS_IMETHODIMP
FuzzySocketControl::AsyncGetSecurityInfo(JSContext* aCx,
mozilla::dom::Promise** aPromise) {
return NS_ERROR_NOT_IMPLEMENTED;
}
} // namespace net
} // namespace mozilla

Просмотреть файл

@ -0,0 +1,29 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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/. */
#ifndef FuzzySocketControl_h__
#define FuzzySocketControl_h__
#include "nsITLSSocketControl.h"
namespace mozilla {
namespace net {
class FuzzySocketControl final : public nsITLSSocketControl {
public:
FuzzySocketControl();
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSITLSSOCKETCONTROL
protected:
virtual ~FuzzySocketControl();
}; // class FuzzySocketControl
} // namespace net
} // namespace mozilla
#endif // FuzzySocketControl_h__

Просмотреть файл

@ -3,13 +3,14 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "SSLTokensCache.h"
#include "mozilla/ArrayAlgorithm.h"
#include "mozilla/Preferences.h"
#include "mozilla/Logging.h"
#include "nsIOService.h"
#include "nsNSSIOLayer.h"
#include "TransportSecurityInfo.h"
#include "CertVerifier.h"
#include "CommonSocketControl.h"
#include "TransportSecurityInfo.h"
#include "mozilla/ArrayAlgorithm.h"
#include "mozilla/Logging.h"
#include "mozilla/Preferences.h"
#include "nsIOService.h"
#include "ssl.h"
#include "sslexp.h"
@ -192,7 +193,7 @@ SSLTokensCache::~SSLTokensCache() { LOG(("SSLTokensCache::~SSLTokensCache")); }
// static
nsresult SSLTokensCache::Put(const nsACString& aKey, const uint8_t* aToken,
uint32_t aTokenLen,
nsITransportSecurityInfo* aSecInfo) {
CommonSocketControl* aSocketControl) {
PRUint32 expirationTime;
SSLResumptionTokenInfo tokenInfo;
if (SSL_GetResumptionTokenInfo(aToken, aTokenLen, &tokenInfo,
@ -205,13 +206,13 @@ nsresult SSLTokensCache::Put(const nsACString& aKey, const uint8_t* aToken,
expirationTime = tokenInfo.expirationTime;
SSL_DestroyResumptionTokenInfo(&tokenInfo);
return Put(aKey, aToken, aTokenLen, aSecInfo, expirationTime);
return Put(aKey, aToken, aTokenLen, aSocketControl, expirationTime);
}
// static
nsresult SSLTokensCache::Put(const nsACString& aKey, const uint8_t* aToken,
uint32_t aTokenLen,
nsITransportSecurityInfo* aSecInfo,
CommonSocketControl* aSocketControl,
PRUint32 aExpirationTime) {
StaticMutexAutoLock lock(sLock);
@ -223,25 +224,30 @@ nsresult SSLTokensCache::Put(const nsACString& aKey, const uint8_t* aToken,
return NS_ERROR_NOT_INITIALIZED;
}
if (!aSecInfo) {
if (!aSocketControl) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsITransportSecurityInfo> securityInfo;
nsresult rv = aSocketControl->GetSecurityInfo(getter_AddRefs(securityInfo));
if (NS_FAILED(rv)) {
return rv;
}
nsCOMPtr<nsIX509Cert> cert;
aSecInfo->GetServerCert(getter_AddRefs(cert));
securityInfo->GetServerCert(getter_AddRefs(cert));
if (!cert) {
return NS_ERROR_FAILURE;
}
nsTArray<uint8_t> certBytes;
nsresult rv = cert->GetRawDER(certBytes);
rv = cert->GetRawDER(certBytes);
if (NS_FAILED(rv)) {
return rv;
}
Maybe<nsTArray<nsTArray<uint8_t>>> succeededCertChainBytes;
nsTArray<RefPtr<nsIX509Cert>> succeededCertArray;
rv = aSecInfo->GetSucceededCertChain(succeededCertArray);
rv = securityInfo->GetSucceededCertChain(succeededCertArray);
if (NS_FAILED(rv)) {
return rv;
}
@ -259,7 +265,7 @@ nsresult SSLTokensCache::Put(const nsACString& aKey, const uint8_t* aToken,
}
bool builtInRoot = false;
rv = aSecInfo->GetIsBuiltCertChainRootBuiltInRoot(&builtInRoot);
rv = securityInfo->GetIsBuiltCertChainRootBuiltInRoot(&builtInRoot);
if (NS_FAILED(rv)) {
return rv;
}
@ -267,27 +273,27 @@ nsresult SSLTokensCache::Put(const nsACString& aKey, const uint8_t* aToken,
}
bool isEV;
rv = aSecInfo->GetIsExtendedValidation(&isEV);
rv = securityInfo->GetIsExtendedValidation(&isEV);
if (NS_FAILED(rv)) {
return rv;
}
uint16_t certificateTransparencyStatus;
rv = aSecInfo->GetCertificateTransparencyStatus(
rv = securityInfo->GetCertificateTransparencyStatus(
&certificateTransparencyStatus);
if (NS_FAILED(rv)) {
return rv;
}
nsITransportSecurityInfo::OverridableErrorCategory overridableErrorCategory;
rv = aSecInfo->GetOverridableErrorCategory(&overridableErrorCategory);
rv = securityInfo->GetOverridableErrorCategory(&overridableErrorCategory);
if (NS_FAILED(rv)) {
return rv;
}
Maybe<nsTArray<nsTArray<uint8_t>>> failedCertChainBytes;
nsTArray<RefPtr<nsIX509Cert>> failedCertArray;
rv = aSecInfo->GetFailedCertChain(failedCertArray);
rv = securityInfo->GetFailedCertChain(failedCertArray);
if (NS_FAILED(rv)) {
return rv;
}

Просмотреть файл

@ -6,17 +6,19 @@
#define SSLTokensCache_h_
#include "CertVerifier.h" // For EVStatus
#include "TransportSecurityInfo.h"
#include "mozilla/Maybe.h"
#include "mozilla/StaticMutex.h"
#include "mozilla/StaticPrefs_network.h"
#include "mozilla/StaticPtr.h"
#include "nsClassHashtable.h"
#include "nsIMemoryReporter.h"
#include "nsITransportSecurityInfo.h"
#include "nsTArray.h"
#include "nsTHashMap.h"
#include "nsXULAppAPI.h"
class CommonSocketControl;
namespace mozilla {
namespace net {
@ -44,9 +46,9 @@ class SSLTokensCache : public nsIMemoryReporter {
static nsresult Shutdown();
static nsresult Put(const nsACString& aKey, const uint8_t* aToken,
uint32_t aTokenLen, nsITransportSecurityInfo* aSecInfo);
uint32_t aTokenLen, CommonSocketControl* aSocketControl);
static nsresult Put(const nsACString& aKey, const uint8_t* aToken,
uint32_t aTokenLen, nsITransportSecurityInfo* aSecInfo,
uint32_t aTokenLen, CommonSocketControl* aSocketControl,
PRUint32 aExpirationTime);
static nsresult Get(const nsACString& aKey, nsTArray<uint8_t>& aToken,
SessionCacheInfo& aResult, uint64_t* aTokenId = nullptr);

Просмотреть файл

@ -247,7 +247,7 @@ UNIFIED_SOURCES += [
if CONFIG["FUZZING"]:
SOURCES += [
"FuzzyLayer.cpp",
"FuzzySecurityInfo.cpp",
"FuzzySocketControl.cpp",
]
if CONFIG["FUZZING_INTERFACES"] and CONFIG["LIBFUZZER"]:

Просмотреть файл

@ -47,7 +47,7 @@
#if defined(FUZZING)
# include "FuzzyLayer.h"
# include "FuzzySecurityInfo.h"
# include "FuzzySocketControl.h"
# include "mozilla/StaticPrefs_fuzzing.h"
#endif
@ -1173,19 +1173,13 @@ nsresult nsSocketTransport::BuildSocket(PRFileDesc*& fd, bool& proxyTransparent,
// info
bool isSSL = mTypes[i].EqualsLiteral("ssl");
if (isSSL || mTypes[i].EqualsLiteral("starttls")) {
// remember security info and give notification callbacks to PSM...
nsCOMPtr<nsIInterfaceRequestor> callbacks;
// remember security info
{
MutexAutoLock lock(mLock);
mTLSSocketControl = tlsSocketControl;
callbacks = mCallbacks;
SOCKET_LOG((" [tlsSocketControl=%p callbacks=%p]\n",
mTLSSocketControl.get(), mCallbacks.get()));
}
// don't call into PSM while holding mLock!!
if (tlsSocketControl) {
tlsSocketControl->SetNotificationCallbacks(callbacks);
}
// remember if socket type is SSL so we can ProxyStartSSL if need be.
usingSSL = isSSL;
} else if (mTypes[i].EqualsLiteral("socks") ||
@ -1335,7 +1329,7 @@ nsresult nsSocketTransport::InitiateSocket() {
SOCKET_LOG(("Successfully attached fuzzing IOLayer.\n"));
if (usingSSL) {
mTLSSocketControl = new FuzzySecurityInfo();
mTLSSocketControl = new FuzzySocketControl();
}
}
#endif
@ -2233,13 +2227,6 @@ void nsSocketTransport::OnSocketDetached(PRFileDesc* fd) {
mDNSRecord->ReportUnusable(SocketPort());
}
// break any potential reference cycle between the security info object
// and ourselves by resetting its notification callbacks object. see
// bug 285991 for details.
if (mTLSSocketControl) {
mTLSSocketControl->SetNotificationCallbacks(nullptr);
}
// finally, release our reference to the socket (must do this within
// the transport lock) possibly closing the socket. Also release our
// listeners to break potential refcount cycles.
@ -2420,22 +2407,10 @@ nsSocketTransport::SetSecurityCallbacks(nsIInterfaceRequestor* callbacks) {
NS_NewNotificationCallbacksAggregation(callbacks, nullptr,
GetCurrentEventTarget(),
getter_AddRefs(threadsafeCallbacks));
nsCOMPtr<nsITLSSocketControl> tlsSocketControl;
{
MutexAutoLock lock(mLock);
mCallbacks = threadsafeCallbacks;
SOCKET_LOG(("Reset callbacks for tlsSocketInfo=%p callbacks=%p\n",
mTLSSocketControl.get(), mCallbacks.get()));
tlsSocketControl = mTLSSocketControl;
}
// don't call into PSM while holding mLock!!
if (tlsSocketControl) {
tlsSocketControl->SetNotificationCallbacks(threadsafeCallbacks);
}
MutexAutoLock lock(mLock);
mCallbacks = threadsafeCallbacks;
SOCKET_LOG(("Reset callbacks for tlsSocketInfo=%p callbacks=%p\n",
mTLSSocketControl.get(), mCallbacks.get()));
return NS_OK;
}

Просмотреть файл

@ -3,11 +3,12 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/Mutex.h"
#include "nsTransportUtils.h"
#include "nsCOMPtr.h"
#include "nsITransport.h"
#include "nsProxyRelease.h"
#include "nsSocketTransportService2.h"
#include "nsThreadUtils.h"
#include "nsCOMPtr.h"
#include "nsTransportUtils.h"
using namespace mozilla;
@ -55,7 +56,17 @@ class nsTransportStatusEvent : public Runnable {
mProgress(progress),
mProgressMax(progressMax) {}
~nsTransportStatusEvent() = default;
~nsTransportStatusEvent() {
auto ReleaseTransport = [transport(std::move(mTransport))]() mutable {
transport = nullptr;
};
if (OnSocketThread()) {
ReleaseTransport();
} else {
gSocketTransportService->Dispatch(NS_NewRunnableFunction(
"nsHttpConnection::~nsHttpConnection", ReleaseTransport));
}
}
NS_IMETHOD Run() override {
// since this event is being handled, we need to clear the proxy's ref.

Просмотреть файл

@ -62,4 +62,6 @@ LOCAL_INCLUDES += [
"/netwerk/cache",
]
include("/ipc/chromium/chromium-config.mozbuild")
FINAL_LIBRARY = "xul"

Просмотреть файл

@ -30,7 +30,7 @@
#include "prio.h"
#if defined(FUZZING)
# include "FuzzySecurityInfo.h"
# include "FuzzySocketControl.h"
# include "mozilla/StaticPrefs_fuzzing.h"
#endif
@ -666,7 +666,7 @@ OutputStreamShim::AsyncWait(nsIOutputStreamCallback* callback,
// target is on the socket thread. That's all we really care about.
nsCOMPtr<nsIEventTarget> sts =
do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID);
MOZ_ASSERT((!target && !callback) || (target == sts));
MOZ_ASSERT(!target || (target == sts));
if (target && (target != sts)) {
return NS_ERROR_FAILURE;
}
@ -891,7 +891,7 @@ InputStreamShim::AsyncWait(nsIInputStreamCallback* callback, unsigned int flags,
// target is on the socket thread. That's all we really care about.
nsCOMPtr<nsIEventTarget> sts =
do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID);
MOZ_ASSERT((!target && !callback) || (target == sts));
MOZ_ASSERT(!target || (target == sts));
if (target && (target != sts)) {
return NS_ERROR_FAILURE;
}

Просмотреть файл

@ -2398,12 +2398,11 @@ nsresult Http2Session::RecvContinuation(Http2Session* self) {
class UpdateAltSvcEvent : public Runnable {
public:
UpdateAltSvcEvent(const nsCString& header, const nsCString& aOrigin,
nsHttpConnectionInfo* aCI, nsIInterfaceRequestor* callbacks)
nsHttpConnectionInfo* aCI)
: Runnable("net::UpdateAltSvcEvent"),
mHeader(header),
mOrigin(aOrigin),
mCI(aCI),
mCallbacks(callbacks) {}
mCI(aCI) {}
NS_IMETHOD Run() override {
MOZ_ASSERT(NS_IsMainThread());
@ -2424,7 +2423,7 @@ class UpdateAltSvcEvent : public Runnable {
if (XRE_IsSocketProcess()) {
AltServiceChild::ProcessHeader(
mHeader, originScheme, originHost, originPort, mCI->GetUsername(),
mCI->GetPrivate(), mCallbacks, mCI->ProxyInfo(), 0,
mCI->GetPrivate(), nullptr, mCI->ProxyInfo(), 0,
mCI->GetOriginAttributes());
return NS_OK;
}
@ -2593,15 +2592,8 @@ nsresult Http2Session::RecvAltSvc(Http2Session* self) {
}
}
nsCOMPtr<nsITLSSocketControl> tlsSocketControl;
self->mConnection->GetTLSSocketControl(getter_AddRefs(tlsSocketControl));
nsCOMPtr<nsIInterfaceRequestor> callbacks;
if (tlsSocketControl) {
tlsSocketControl->GetNotificationCallbacks(getter_AddRefs(callbacks));
}
RefPtr<UpdateAltSvcEvent> event =
new UpdateAltSvcEvent(altSvcFieldValue, origin, ci, callbacks);
new UpdateAltSvcEvent(altSvcFieldValue, origin, ci);
NS_DispatchToMainThread(event);
self->ResetDownstreamState();
return NS_OK;

Просмотреть файл

@ -96,14 +96,10 @@ nsresult Http3Session::Init(const nsHttpConnectionInfo* aConnInfo,
aConnInfo->ProxyInfo() ? aConnInfo->ProxyInfo()->IsHTTPS() : false;
// Create security control and info object for quic.
mSocketControl = new QuicSocketControl(controlFlags, this);
mSocketControl->SetHostName(httpsProxy ? aConnInfo->ProxyInfo()->Host().get()
: aConnInfo->GetOrigin().get());
mSocketControl->SetPort(httpsProxy ? aConnInfo->ProxyInfo()->Port()
: aConnInfo->OriginPort());
// don't call into PSM while holding mLock!!
mSocketControl->SetNotificationCallbacks(callbacks);
mSocketControl = new QuicSocketControl(
httpsProxy ? aConnInfo->ProxyInfo()->Host() : aConnInfo->GetOrigin(),
httpsProxy ? aConnInfo->ProxyInfo()->Port() : aConnInfo->OriginPort(),
controlFlags, this);
NetAddr selfAddr;
MOZ_ALWAYS_SUCCEEDS(aSelfAddr->GetNetAddr(&selfAddr));
@ -1904,7 +1900,7 @@ void Http3Session::CallCertVerification(Maybe<nsCString> aEchPublicName) {
const nsACString& hostname =
verifyToEchPublicName ? *aEchPublicName : mSocketControl->GetHostName();
SECStatus rv = AuthCertificateHookWithInfo(
SECStatus rv = psm::AuthCertificateHookWithInfo(
mSocketControl, hostname, static_cast<const void*>(this),
std::move(certInfo.certs), stapledOCSPResponse, sctsFromTLSExtension,
providerFlags);

Просмотреть файл

@ -7,17 +7,18 @@
#ifndef Http3Session_H__
#define Http3Session_H__
#include "nsISupportsImpl.h"
#include "nsITimer.h"
#include "nsIUDPSocket.h"
#include "mozilla/net/NeqoHttp3Conn.h"
#include "nsAHttpConnection.h"
#include "nsRefPtrHashtable.h"
#include "nsWeakReference.h"
#include "HttpTrafficAnalyzer.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/WeakPtr.h"
#include "mozilla/net/NeqoHttp3Conn.h"
#include "nsAHttpConnection.h"
#include "nsDeque.h"
#include "nsISupportsImpl.h"
#include "nsITimer.h"
#include "nsIUDPSocket.h"
#include "nsRefPtrHashtable.h"
#include "nsTHashMap.h"
#include "nsWeakReference.h"
/*
* WebTransport

Просмотреть файл

@ -415,9 +415,6 @@ HttpTransactionChild::OnStartRequest(nsIRequest* aRequest) {
!protocol.IsEmpty()) {
mProtocolVersion.Assign(protocol);
}
// Make sure peerId is generated.
nsAutoCString unused;
securityInfo->GetPeerId(unused);
}
UniquePtr<nsHttpResponseHead> head(mTransaction->TakeResponseHead());

Просмотреть файл

@ -11,7 +11,6 @@
#include "nsISocketProvider.h"
#include "nsIWebProgressListener.h"
#include "nsNSSComponent.h"
#include "nsWeakReference.h"
#include "nsSocketTransportService2.h"
#include "nsThreadUtils.h"
#include "sslt.h"
@ -20,19 +19,17 @@
namespace mozilla {
namespace net {
NS_IMPL_ISUPPORTS_INHERITED(QuicSocketControl, TransportSecurityInfo,
nsITLSSocketControl, QuicSocketControl)
QuicSocketControl::QuicSocketControl(uint32_t aProviderFlags,
QuicSocketControl::QuicSocketControl(const nsCString& aHostName, int32_t aPort,
uint32_t aProviderFlags,
Http3Session* aHttp3Session)
: CommonSocketControl(aProviderFlags) {
MOZ_ASSERT(OnSocketThread());
: CommonSocketControl(aHostName, aPort, aProviderFlags) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
mHttp3Session = do_GetWeakReference(
static_cast<nsISupportsWeakReference*>(aHttp3Session));
mSocketThread = NS_GetCurrentThread();
}
void QuicSocketControl::SetCertVerificationResult(PRErrorCode errorCode) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
SetUsedPrivateDNS(GetProviderFlags() & nsISocketProvider::USED_PRIVATE_DNS);
if (errorCode) {
@ -40,28 +37,18 @@ void QuicSocketControl::SetCertVerificationResult(PRErrorCode errorCode) {
SetCanceled(errorCode);
}
if (OnSocketThread()) {
CallAuthenticated();
} else {
DebugOnly<nsresult> rv = gSocketTransportService->Dispatch(
NewRunnableMethod("QuicSocketControl::CallAuthenticated", this,
&QuicSocketControl::CallAuthenticated),
NS_DISPATCH_NORMAL);
}
}
QuicSocketControl::~QuicSocketControl() {
NS_ProxyRelease("QuicSocketControl::~QuicSocketControl", mSocketThread,
mHttp3Session.forget());
CallAuthenticated();
}
NS_IMETHODIMP
QuicSocketControl::GetSSLVersionOffered(int16_t* aSSLVersionOffered) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
*aSSLVersionOffered = nsITLSSocketControl::TLS_VERSION_1_3;
return NS_OK;
}
void QuicSocketControl::CallAuthenticated() {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
RefPtr<Http3Session> http3Session = do_QueryReferent(mHttp3Session);
if (http3Session) {
http3Session->Authenticated(GetErrorCode());
@ -69,14 +56,15 @@ void QuicSocketControl::CallAuthenticated() {
}
void QuicSocketControl::HandshakeCompleted() {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
uint32_t state = nsIWebProgressListener::STATE_IS_SECURE;
MutexAutoLock lock(mMutex);
// If we're here, the TLS handshake has succeeded. If the overridable error
// category is nonzero, the user has added an override for a certificate
// error.
if (mOverridableErrorCategory != OverridableErrorCategory::ERROR_UNSET) {
if (mOverridableErrorCategory.isSome() &&
*mOverridableErrorCategory !=
nsITransportSecurityInfo::OverridableErrorCategory::ERROR_UNSET) {
state |= nsIWebProgressListener::STATE_CERT_USER_OVERRIDDEN;
}
@ -85,64 +73,37 @@ void QuicSocketControl::HandshakeCompleted() {
}
void QuicSocketControl::SetNegotiatedNPN(const nsACString& aValue) {
MutexAutoLock lock(mMutex);
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
mNegotiatedNPN = aValue;
mNPNCompleted = true;
}
void QuicSocketControl::SetInfo(uint16_t aCipherSuite,
uint16_t aProtocolVersion, uint16_t aKeaGroup,
uint16_t aProtocolVersion,
uint16_t aKeaGroupName,
uint16_t aSignatureScheme, bool aEchAccepted) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
SSLCipherSuiteInfo cipherInfo;
if (SSL_GetCipherSuiteInfo(aCipherSuite, &cipherInfo, sizeof cipherInfo) ==
SECSuccess) {
MutexAutoLock lock(mMutex);
mHaveCipherSuiteAndProtocol = true;
mCipherSuite = aCipherSuite;
mProtocolVersion = aProtocolVersion & 0xFF;
mKeaGroup = getKeaGroupName(aKeaGroup);
mSignatureSchemeName = getSignatureName(aSignatureScheme);
mIsAcceptedEch = aEchAccepted;
mCipherSuite.emplace(aCipherSuite);
mProtocolVersion.emplace(aProtocolVersion & 0xFF);
mKeaGroupName.emplace(getKeaGroupName(aKeaGroupName));
mSignatureSchemeName.emplace(getSignatureName(aSignatureScheme));
mIsAcceptedEch.emplace(aEchAccepted);
}
}
NS_IMETHODIMP QuicSocketControl::GetPeerId(nsACString& aResult) {
MutexAutoLock lock(mMutex);
if (!mPeerId.IsEmpty()) {
aResult.Assign(mPeerId);
return NS_OK;
}
if (mProviderFlags &
nsISocketProvider::ANONYMOUS_CONNECT) { // See bug 466080
mPeerId.AppendLiteral("anon:");
}
if (mProviderFlags & nsISocketProvider::NO_PERMANENT_STORAGE) {
mPeerId.AppendLiteral("private:");
}
if (mProviderFlags & nsISocketProvider::BE_CONSERVATIVE) {
mPeerId.AppendLiteral("beConservative:");
}
mPeerId.Append(mHostName);
mPeerId.Append(':');
mPeerId.AppendInt(GetPort());
nsAutoCString suffix;
mOriginAttributes.CreateSuffix(suffix);
mPeerId.Append(suffix);
aResult.Assign(mPeerId);
return NS_OK;
}
NS_IMETHODIMP
QuicSocketControl::GetEchConfig(nsACString& aEchConfig) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
aEchConfig = mEchConfig;
return NS_OK;
}
NS_IMETHODIMP
QuicSocketControl::SetEchConfig(const nsACString& aEchConfig) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
mEchConfig = aEchConfig;
RefPtr<Http3Session> http3Session = do_QueryReferent(mHttp3Session);
if (http3Session) {
@ -153,11 +114,13 @@ QuicSocketControl::SetEchConfig(const nsACString& aEchConfig) {
NS_IMETHODIMP
QuicSocketControl::GetRetryEchConfig(nsACString& aEchConfig) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
aEchConfig = mRetryEchConfig;
return NS_OK;
}
void QuicSocketControl::SetRetryEchConfig(const nsACString& aEchConfig) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
mRetryEchConfig = aEchConfig;
}

Просмотреть файл

@ -25,14 +25,14 @@ class Http3Session;
class QuicSocketControl final : public CommonSocketControl {
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_QUICSOCKETCONTROL_IID)
NS_DECLARE_STATIC_IID_ACCESSOR(NS_QUICSOCKETCONTROL_IID);
NS_DECL_ISUPPORTS_INHERITED
NS_INLINE_DECL_REFCOUNTING_INHERITED(QuicSocketControl, CommonSocketControl);
NS_IMETHOD GetSSLVersionOffered(int16_t* aSSLVersionOffered) override;
explicit QuicSocketControl(uint32_t providerFlags,
Http3Session* aHttp3Session);
QuicSocketControl(const nsCString& aHostName, int32_t aPort,
uint32_t aProviderFlags, Http3Session* aHttp3Session);
void SetNegotiatedNPN(const nsACString& aValue);
void SetInfo(uint16_t aCipherSuite, uint16_t aProtocolVersion,
@ -44,19 +44,16 @@ class QuicSocketControl final : public CommonSocketControl {
void HandshakeCompleted();
void SetCertVerificationResult(PRErrorCode errorCode) override;
NS_IMETHOD GetPeerId(nsACString& aResult) override;
NS_IMETHOD GetEchConfig(nsACString& aEchConfig) override;
NS_IMETHOD SetEchConfig(const nsACString& aEchConfig) override;
NS_IMETHOD GetRetryEchConfig(nsACString& aEchConfig) override;
void SetRetryEchConfig(const nsACString& aEchConfig);
private:
~QuicSocketControl();
~QuicSocketControl() = default;
// For Authentication done callback and echConfig.
nsWeakPtr mHttp3Session;
nsCOMPtr<nsIEventTarget> mSocketThread;
nsCString mEchConfig;
nsCString mRetryEchConfig;

Просмотреть файл

@ -139,8 +139,18 @@ TLSTransportLayer::InputStreamWrapper::AsyncWait(
PRPollDesc pd;
pd.fd = mTransport->mFD;
pd.in_flags = PR_POLL_READ | PR_POLL_EXCEPT;
int32_t rv = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
LOG(("TLSTransportLayer::InputStreamWrapper::AsyncWait rv=%d", rv));
// Only run PR_Poll on the socket thread. Also, make sure this lives at least
// as long as that operation.
auto DoPoll = [self = RefPtr{this}, pd(pd)]() mutable {
int32_t rv = PR_Poll(&pd, 1, PR_INTERVAL_NO_TIMEOUT);
LOG(("TLSTransportLayer::InputStreamWrapper::AsyncWait rv=%d", rv));
};
if (OnSocketThread()) {
DoPoll();
} else {
gSocketTransportService->Dispatch(NS_NewRunnableFunction(
"TLSTransportLayer::InputStreamWrapper::AsyncWait", DoPoll));
}
return NS_OK;
}
@ -313,6 +323,7 @@ TLSTransportLayer::TLSTransportLayer(nsISocketTransport* aTransport,
}
TLSTransportLayer::~TLSTransportLayer() {
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
LOG(("TLSTransportLayer dtor this=[%p]", this));
if (mFD) {
PR_Close(mFD);

Просмотреть файл

@ -117,6 +117,17 @@ nsHttpConnection::~nsHttpConnection() {
mForceSendTimer->Cancel();
mForceSendTimer = nullptr;
}
auto ReleaseSocketTransport =
[socketTransport(std::move(mSocketTransport))]() mutable {
socketTransport = nullptr;
};
if (OnSocketThread()) {
ReleaseSocketTransport();
} else {
gSocketTransportService->Dispatch(NS_NewRunnableFunction(
"nsHttpConnection::~nsHttpConnection", ReleaseSocketTransport));
}
}
nsresult nsHttpConnection::Init(
@ -650,10 +661,10 @@ void nsHttpConnection::Close(nsresult reason, bool aIsShutdown) {
}
}
nsCOMPtr<nsITLSSocketControl> ssl;
GetTLSSocketControl(getter_AddRefs(ssl));
if (ssl) {
ssl->SetHandshakeCallbackListener(nullptr);
nsCOMPtr<nsITLSSocketControl> tlsSocketControl;
GetTLSSocketControl(getter_AddRefs(tlsSocketControl));
if (tlsSocketControl) {
tlsSocketControl->SetHandshakeCallbackListener(nullptr);
}
if (NS_FAILED(reason)) {
@ -811,7 +822,7 @@ bool nsHttpConnection::IsAlive() {
nsresult rv = mSocketTransport->IsAlive(&alive);
if (NS_FAILED(rv)) alive = false;
//#define TEST_RESTART_LOGIC
// #define TEST_RESTART_LOGIC
#ifdef TEST_RESTART_LOGIC
if (!alive) {
LOG(("pretending socket is still alive to test restart logic\n"));
@ -1193,7 +1204,7 @@ void nsHttpConnection::UpdateTCPKeepalive(nsITimer* aTimer, void* aClosure) {
void nsHttpConnection::GetTLSSocketControl(
nsITLSSocketControl** tlsSocketControl) {
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
LOG(("nsHttpConnection::GetSecurityInfo trans=%p socket=%p\n",
LOG(("nsHttpConnection::GetTLSSocketControl trans=%p socket=%p\n",
mTransaction.get(), mSocketTransport.get()));
*tlsSocketControl = nullptr;
@ -1422,24 +1433,28 @@ void nsHttpConnection::CloseTransaction(nsAHttpTransaction* trans,
bool nsHttpConnection::CheckCanWrite0RTTData() {
MOZ_ASSERT(mTlsHandshaker->EarlyDataAvailable());
nsCOMPtr<nsITLSSocketControl> ssl;
GetTLSSocketControl(getter_AddRefs(ssl));
if (!ssl) {
nsCOMPtr<nsITLSSocketControl> tlsSocketControl;
GetTLSSocketControl(getter_AddRefs(tlsSocketControl));
if (!tlsSocketControl) {
return false;
}
nsCOMPtr<nsITransportSecurityInfo> info(do_QueryInterface(ssl));
if (!info) {
nsCOMPtr<nsITransportSecurityInfo> securityInfo;
if (NS_FAILED(
tlsSocketControl->GetSecurityInfo(getter_AddRefs(securityInfo)))) {
return false;
}
if (!securityInfo) {
return false;
}
nsAutoCString negotiatedNPN;
// If the following code fails means that the handshake is not done
// yet, so continue writing 0RTT data.
nsresult rv = info->GetNegotiatedNPN(negotiatedNPN);
nsresult rv = securityInfo->GetNegotiatedNPN(negotiatedNPN);
if (NS_FAILED(rv)) {
return true;
}
bool earlyDataAccepted = false;
rv = ssl->GetEarlyDataAccepted(&earlyDataAccepted);
rv = tlsSocketControl->GetEarlyDataAccepted(&earlyDataAccepted);
// If 0RTT data is accepted we can continue writing data,
// if it is reject stop writing more data.
return NS_SUCCEEDED(rv) && earlyDataAccepted;
@ -2260,27 +2275,33 @@ void nsHttpConnection::HandshakeDoneInternal() {
return;
}
nsCOMPtr<nsITLSSocketControl> ssl;
GetTLSSocketControl(getter_AddRefs(ssl));
if (!ssl) {
nsCOMPtr<nsITLSSocketControl> tlsSocketControl;
GetTLSSocketControl(getter_AddRefs(tlsSocketControl));
if (!tlsSocketControl) {
mTlsHandshaker->FinishNPNSetup(false, false);
return;
}
nsCOMPtr<nsITransportSecurityInfo> info(do_QueryInterface(ssl));
if (!info) {
nsCOMPtr<nsITransportSecurityInfo> securityInfo;
if (NS_FAILED(
tlsSocketControl->GetSecurityInfo(getter_AddRefs(securityInfo)))) {
mTlsHandshaker->FinishNPNSetup(false, false);
return;
}
if (!securityInfo) {
mTlsHandshaker->FinishNPNSetup(false, false);
return;
}
nsAutoCString negotiatedNPN;
DebugOnly<nsresult> rvDebug = info->GetNegotiatedNPN(negotiatedNPN);
DebugOnly<nsresult> rvDebug = securityInfo->GetNegotiatedNPN(negotiatedNPN);
MOZ_ASSERT(NS_SUCCEEDED(rvDebug));
bool earlyDataAccepted = false;
if (mTlsHandshaker->EarlyDataUsed()) {
// Check if early data has been accepted.
nsresult rvEarlyData = ssl->GetEarlyDataAccepted(&earlyDataAccepted);
nsresult rvEarlyData =
tlsSocketControl->GetEarlyDataAccepted(&earlyDataAccepted);
LOG(
("nsHttpConnection::HandshakeDone [this=%p] - early data "
"that was sent during 0RTT %s been accepted [rv=%" PRIx32 "].",
@ -2319,7 +2340,7 @@ void nsHttpConnection::HandshakeDoneInternal() {
}
int16_t tlsVersion;
ssl->GetSSLVersionUsed(&tlsVersion);
tlsSocketControl->GetSSLVersionUsed(&tlsVersion);
mConnInfo->SetLessThanTls13(
(tlsVersion < nsITLSSocketControl::TLS_VERSION_1_3) &&
(tlsVersion != nsITLSSocketControl::SSL_VERSION_UNKNOWN));
@ -2337,18 +2358,19 @@ void nsHttpConnection::HandshakeDoneInternal() {
const SpdyInformation* info = gHttpHandler->SpdyInfo();
if (negotiatedNPN.Equals(info->VersionString)) {
if (mTransaction) {
StartSpdy(ssl, info->Version);
StartSpdy(tlsSocketControl, info->Version);
} else {
LOG(
("nsHttpConnection::HandshakeDone [this=%p] set "
"mContinueHandshakeDone",
this));
RefPtr<nsHttpConnection> self = this;
mContinueHandshakeDone = [self = RefPtr{this}, ssl(ssl),
mContinueHandshakeDone = [self = RefPtr{this},
tlsSocketControl(tlsSocketControl),
info(info->Version)]() {
LOG(("nsHttpConnection do mContinueHandshakeDone [this=%p]",
self.get()));
self->StartSpdy(ssl, info);
self->StartSpdy(tlsSocketControl, info);
self->mTlsHandshaker->FinishNPNSetup(true, true);
};
return;
@ -2367,7 +2389,7 @@ void nsHttpConnection::HandshakeDoneInternal() {
("nsHttpConnection::HandshakeDone [this=%p] - finishing "
"StartSpdy for 0rtt spdy session %p",
this, mSpdySession.get()));
StartSpdy(ssl, mSpdySession->SpdyVersion());
StartSpdy(tlsSocketControl, mSpdySession->SpdyVersion());
}
}

Просмотреть файл

@ -15,7 +15,10 @@
#include <algorithm>
#include <utility>
#include "ConnectionHandle.h"
#include "HttpConnectionUDP.h"
#include "NullHttpTransaction.h"
#include "SpeculativeTransaction.h"
#include "mozilla/Components.h"
#include "mozilla/SpinEventLoopUntil.h"
#include "mozilla/StaticPrefs_network.h"
@ -28,10 +31,11 @@
#include "nsHttpHandler.h"
#include "nsIClassOfService.h"
#include "nsIDNSByTypeRecord.h"
#include "nsIDNSRecord.h"
#include "nsIDNSListener.h"
#include "nsIDNSRecord.h"
#include "nsIDNSService.h"
#include "nsIHttpChannelInternal.h"
#include "nsIPipe.h"
#include "nsIRequestContext.h"
#include "nsISocketTransport.h"
#include "nsISocketTransportService.h"
@ -39,11 +43,11 @@
#include "nsIXPConnect.h"
#include "nsInterfaceRequestorAgg.h"
#include "nsNetCID.h"
#include "nsNetSegmentUtils.h"
#include "nsNetUtil.h"
#include "nsQueryObject.h"
#include "ConnectionHandle.h"
#include "HttpConnectionUDP.h"
#include "SpeculativeTransaction.h"
#include "nsSocketTransportService2.h"
#include "nsStreamUtils.h"
namespace mozilla::net {
@ -2475,8 +2479,42 @@ void nsHttpConnectionMgr::OnMsgCompleteUpgrade(int32_t, ARefBase* param) {
}
RefPtr<nsCompleteUpgradeData> upgradeData(data);
auto transportAvailableFunc = [upgradeData{std::move(upgradeData)},
aRv(rv)]() {
nsCOMPtr<nsIAsyncInputStream> socketIn;
nsCOMPtr<nsIAsyncOutputStream> socketOut;
// If this is for JS, the input and output sockets need to be piped over the
// socket thread. Otherwise, the JS may attempt to read and/or write the
// sockets on the main thread, which could cause network I/O on the main
// thread. This is particularly bad in the case of TLS connections, because
// PSM and NSS rely on those connections only being used on the socket
// thread.
if (data->mJsWrapped) {
nsCOMPtr<nsIAsyncInputStream> pipeIn;
uint32_t segsize = 0;
uint32_t segcount = 0;
net_ResolveSegmentParams(segsize, segcount);
if (NS_SUCCEEDED(rv)) {
NS_NewPipe2(getter_AddRefs(pipeIn), getter_AddRefs(socketOut), true, true,
segsize, segcount);
rv = NS_AsyncCopy(pipeIn, data->mSocketOut, gSocketTransportService,
NS_ASYNCCOPY_VIA_READSEGMENTS, segsize);
}
nsCOMPtr<nsIAsyncOutputStream> pipeOut;
if (NS_SUCCEEDED(rv)) {
NS_NewPipe2(getter_AddRefs(socketIn), getter_AddRefs(pipeOut), true, true,
segsize, segcount);
rv = NS_AsyncCopy(data->mSocketIn, pipeOut, gSocketTransportService,
NS_ASYNCCOPY_VIA_WRITESEGMENTS, segsize);
}
} else {
socketIn = upgradeData->mSocketIn;
socketOut = upgradeData->mSocketOut;
}
auto transportAvailableFunc = [upgradeData{std::move(upgradeData)}, socketIn,
socketOut, aRv(rv)]() {
// Handle any potential previous errors first
// and call OnUpgradeFailed if necessary.
nsresult rv = aRv;
@ -2493,8 +2531,7 @@ void nsHttpConnectionMgr::OnMsgCompleteUpgrade(int32_t, ARefBase* param) {
}
rv = upgradeData->mUpgradeListener->OnTransportAvailable(
upgradeData->mSocketTransport, upgradeData->mSocketIn,
upgradeData->mSocketOut);
upgradeData->mSocketTransport, socketIn, socketOut);
if (NS_FAILED(rv)) {
LOG(
("nsHttpConnectionMgr::OnMsgCompleteUpgrade OnTransportAvailable "

Просмотреть файл

@ -746,8 +746,10 @@ nsresult nsHttpTransaction::ReadSegments(nsAHttpSegmentReader* reader,
mConnected = true;
nsCOMPtr<nsITLSSocketControl> tlsSocketControl;
mConnection->GetTLSSocketControl(getter_AddRefs(tlsSocketControl));
MutexAutoLock lock(mLock);
mTLSSocketControl = tlsSocketControl;
if (tlsSocketControl) {
MutexAutoLock lock(mLock);
tlsSocketControl->GetSecurityInfo(getter_AddRefs(mSecurityInfo));
}
}
mDeferredSendProgress = false;
@ -989,9 +991,7 @@ bool nsHttpTransaction::DataSentToChildProcess() { return false; }
already_AddRefed<nsITransportSecurityInfo> nsHttpTransaction::SecurityInfo() {
MutexAutoLock lock(mLock);
nsCOMPtr<nsITransportSecurityInfo> securityInfo(
do_QueryInterface(mTLSSocketControl));
return securityInfo.forget();
return do_AddRef(mSecurityInfo);
}
bool nsHttpTransaction::HasStickyConnection() const {
@ -1333,19 +1333,16 @@ bool nsHttpTransaction::ShouldRestartOn0RttError(nsresult reason) {
mEarlyDataWasAvailable && SecurityErrorThatMayNeedRestart(reason);
}
static void MaybeRemoveSSLToken(nsITLSSocketControl* aSocketControl) {
static void MaybeRemoveSSLToken(nsITransportSecurityInfo* aSecurityInfo) {
if (!StaticPrefs::
network_http_remove_resumption_token_when_early_data_failed()) {
return;
}
nsCOMPtr<nsITransportSecurityInfo> info(do_QueryInterface(aSocketControl));
if (!info) {
if (!aSecurityInfo) {
return;
}
nsAutoCString key;
info->GetPeerId(key);
aSecurityInfo->GetPeerId(key);
nsresult rv = SSLTokensCache::RemoveAll(key);
LOG(("RemoveSSLToken [key=%s, rv=%" PRIx32 "]", key.get(),
static_cast<uint32_t>(rv)));
@ -1415,8 +1412,10 @@ void nsHttpTransaction::Close(nsresult reason) {
// Try to get TLSSocketControl for this transaction.
nsCOMPtr<nsITLSSocketControl> tlsSocketControl;
mConnection->GetTLSSocketControl(getter_AddRefs(tlsSocketControl));
MutexAutoLock lock(mLock);
mTLSSocketControl = tlsSocketControl;
if (tlsSocketControl) {
MutexAutoLock lock(mLock);
tlsSocketControl->GetSecurityInfo(getter_AddRefs(mSecurityInfo));
}
}
}
mConnected = false;
@ -1781,13 +1780,14 @@ nsresult nsHttpTransaction::Restart() {
if (seekable) seekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
if (mDoNotTryEarlyData) {
MaybeRemoveSSLToken(mTLSSocketControl);
MutexAutoLock lock(mLock);
MaybeRemoveSSLToken(mSecurityInfo);
}
// clear old connection state...
{
MutexAutoLock lock(mLock);
mTLSSocketControl = nullptr;
mSecurityInfo = nullptr;
}
if (mConnection) {
@ -2991,8 +2991,10 @@ nsresult nsHttpTransaction::Finish0RTT(bool aRestart,
mConnected = true;
nsCOMPtr<nsITLSSocketControl> tlsSocketControl;
mConnection->GetTLSSocketControl(getter_AddRefs(tlsSocketControl));
MutexAutoLock lock(mLock);
mTLSSocketControl = tlsSocketControl;
if (tlsSocketControl) {
MutexAutoLock lock(mLock);
tlsSocketControl->GetSecurityInfo(getter_AddRefs(mSecurityInfo));
}
}
return NS_OK;
}

Просмотреть файл

@ -314,7 +314,7 @@ class nsHttpTransaction final : public nsAHttpTransaction,
nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
nsCOMPtr<nsITransportEventSink> mTransportSink;
nsCOMPtr<nsIEventTarget> mConsumerTarget;
nsCOMPtr<nsITLSSocketControl> mTLSSocketControl;
nsCOMPtr<nsITransportSecurityInfo> mSecurityInfo;
nsCOMPtr<nsIAsyncInputStream> mPipeIn;
nsCOMPtr<nsIAsyncOutputStream> mPipeOut;
nsCOMPtr<nsIRequestContext> mRequestContext;

Просмотреть файл

@ -1,40 +1,45 @@
#include "gtest/gtest.h"
#include <numeric>
#include "CertVerifier.h"
#include "CommonSocketControl.h"
#include "SSLTokensCache.h"
#include "TransportSecurityInfo.h"
#include "gtest/gtest.h"
#include "mozilla/Preferences.h"
#include "nsITransportSecurityInfo.h"
#include "SSLTokensCache.h"
#include "nsIWebProgressListener.h"
#include "nsIX509Cert.h"
#include "nsIX509CertDB.h"
#include "nsServiceManagerUtils.h"
#include "sslproto.h"
static already_AddRefed<nsITransportSecurityInfo> createDummySecInfo() {
// clang-format off
nsCString base64Serialization(
"FnhllAKWRHGAlo+ESXykKAAAAAAAAAAAwAAAAAAAAEaphjojH6pBabDSgSnsfLHeAAQAAgAAAAAAAAAAAAAAAAAAAAA"
"B4vFIJp5wRkeyPxAQ9RJGKPqbqVvKO0mKuIl8ec8o/uhmCjImkVxP+7sgiYWmMt8F+O2DZM7ZTG6GukivU8OT5gAAAAIAAAWpMII"
"FpTCCBI2gAwIBAgIQD4svsaKEC+QtqtsU2TF8ITANBgkqhkiG9w0BAQsFADBwMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUN"
"lcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMS8wLQYDVQQDEyZEaWdpQ2VydCBTSEEyIEhpZ2ggQXNzdXJhbmNlIFN"
"lcnZlciBDQTAeFw0xNTAyMjMwMDAwMDBaFw0xNjAzMDIxMjAwMDBaMGoxCzAJBgNVBAYTAlVTMRYwFAYDVQQHEw1TYW4gRnJhbmN"
"pc2NvMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRUwEwYDVQQKEwxGYXN0bHksIEluYy4xFzAVBgNVBAMTDnd3dy5naXRodWIuY29tMII"
"BIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+9WUCgrgUNwP/JC3cUefLAXeDpq8Ko/U8p8IRvny0Ri0I6Uq0t+RP/nF0LJ"
"Avda8QHYujdgeDTePepBX7+OiwBFhA0YO+rM3C2Z8IRaN/i9eLln+Yyc68+1z+E10s1EXdZrtDGvN6MHqygGsdfkXKfBLUJ1BZEh"
"s9sBnfcjq3kh5gZdBArdG9l5NpdmQhtceaFGsPiWuJxGxRzS4i95veUHWkhMpEYDEEBdcDGxqArvQCvzSlngdttQCfx8OUkBTb3B"
"A2okpTwwJfqPsxVetA6qR7UNc+fVb6KHwvm0bzi2rQ3xw3D/syRHwdMkpoVDQPCk43H9WufgfBKRen87dFwIDAQABo4ICPzCCAjs"
"wHwYDVR0jBBgwFoAUUWj/kK8CB3U8zNllZGKiErhZcjswHQYDVR0OBBYEFGS/RLNGCZvPWh1xSaIEcouINIQjMHsGA1UdEQR0MHK"
"CDnd3dy5naXRodWIuY29tggpnaXRodWIuY29tggwqLmdpdGh1Yi5jb22CCyouZ2l0aHViLmlvgglnaXRodWIuaW+CFyouZ2l0aHV"
"idXNlcmNvbnRlbnQuY29tghVnaXRodWJ1c2VyY29udGVudC5jb20wDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwM"
"BBggrBgEFBQcDAjB1BgNVHR8EbjBsMDSgMqAwhi5odHRwOi8vY3JsMy5kaWdpY2VydC5jb20vc2hhMi1oYS1zZXJ2ZXItZzMuY3J"
"sMDSgMqAwhi5odHRwOi8vY3JsNC5kaWdpY2VydC5jb20vc2hhMi1oYS1zZXJ2ZXItZzMuY3JsMEIGA1UdIAQ7MDkwNwYJYIZIAYb"
"9bAEBMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwgYMGCCsGAQUFBwEBBHcwdTAkBggrBgEFBQc"
"wAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tME0GCCsGAQUFBzAChkFodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUN"
"lcnRTSEEySGlnaEFzc3VyYW5jZVNlcnZlckNBLmNydDAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3DQEBCwUAA4IBAQAc4dbVmuKvyI7"
"KZ4Txk+ZqcAYToJGKUIVaPL94e5SZGweUisjaCbplAOihnf6Mxt8n6vnuH2IsCaz2NRHqhdcosjT3CwAiJpJNkXPKWVL/txgdSTV"
"2cqB1GG4esFOalvI52dzn+J4fTIYZvNF+AtGyHSLm2XRXYZCw455laUKf6Sk9RDShDgUvzhOKL4GXfTwKXv12MyMknJybH8UCpjC"
"HZmFBVHMcUN/87HsQo20PdOekeEvkjrrMIxW+gxw22Yb67yF/qKgwrWr+43bLN709iyw+LWiU7sQcHL2xk9SYiWQDj2tYz2soObV"
"QYTJm0VUZMEVFhtALq46cx92Zu4vFwC8AAwAAAAABAQAA");
// clang-format on
nsCOMPtr<nsITransportSecurityInfo> securityInfo;
EXPECT_TRUE(NS_SUCCEEDED(mozilla::psm::TransportSecurityInfo::Read(
base64Serialization, getter_AddRefs(securityInfo))));
return securityInfo.forget();
static already_AddRefed<CommonSocketControl> createDummySocketControl() {
nsCOMPtr<nsIX509CertDB> certDB(do_GetService(NS_X509CERTDB_CONTRACTID));
EXPECT_TRUE(certDB);
nsLiteralCString base64(
"MIIBbjCCARWgAwIBAgIUOyCxVVqw03yUxKSfSojsMF8K/"
"ikwCgYIKoZIzj0EAwIwHTEbMBkGA1UEAwwScm9vdF9zZWNwMjU2azFfMjU2MCIYDzIwMjAxM"
"TI3MDAwMDAwWhgPMjAyMzAyMDUwMDAwMDBaMC8xLTArBgNVBAMMJGludF9zZWNwMjU2cjFfM"
"jU2LXJvb3Rfc2VjcDI1NmsxXzI1NjBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABE+/"
"u7th4Pj5saYKWayHBOLsBQtCPjz3LpI/"
"LE95S0VcKmnSM0VsNsQRnQcG4A7tyNGTkNeZG3stB6ME6qBKpsCjHTAbMAwGA1UdEwQFMAMB"
"Af8wCwYDVR0PBAQDAgEGMAoGCCqGSM49BAMCA0cAMEQCIFuwodUwyOUnIR4KN5ZCSrU7y4iz"
"4/1EWRdHm5kWKi8dAiB6Ixn9sw3uBVbyxnQKYqGnOwM+qLOkJK0W8XkIE3n5sg==");
nsCOMPtr<nsIX509Cert> cert;
EXPECT_TRUE(NS_SUCCEEDED(
certDB->ConstructX509FromBase64(base64, getter_AddRefs(cert))));
EXPECT_TRUE(cert);
nsTArray<nsTArray<uint8_t>> succeededCertChain;
for (size_t i = 0; i < 3; i++) {
nsTArray<uint8_t> certDER;
EXPECT_TRUE(NS_SUCCEEDED(cert->GetRawDER(certDER)));
succeededCertChain.AppendElement(std::move(certDER));
}
RefPtr<CommonSocketControl> socketControl(
new CommonSocketControl(nsLiteralCString("example.com"), 433, 0));
socketControl->SetServerCert(cert, mozilla::psm::EVStatus::NotEV);
socketControl->SetSucceededCertChain(std::move(succeededCertChain));
return socketControl.forget();
}
static auto MakeTestData(const size_t aDataSize) {
@ -45,10 +50,10 @@ static auto MakeTestData(const size_t aDataSize) {
}
static void putToken(const nsACString& aKey, uint32_t aSize) {
nsCOMPtr<nsITransportSecurityInfo> secInfo = createDummySecInfo();
RefPtr<CommonSocketControl> socketControl = createDummySocketControl();
nsTArray<uint8_t> token = MakeTestData(aSize);
nsresult rv = mozilla::net::SSLTokensCache::Put(aKey, token.Elements(), aSize,
secInfo, aSize);
socketControl, aSize);
ASSERT_EQ(rv, NS_OK);
}

Просмотреть файл

@ -255,7 +255,9 @@ function socketAccepted(socket, transport) {
streamIn = transport
.openInputStream(0, SEGMENT_SIZE, SEGMENT_COUNT)
.QueryInterface(Ci.nsIAsyncInputStream);
streamOut = transport.openOutputStream(0, 0, 0);
streamOut = transport
.openOutputStream(0, 0, 0)
.QueryInterface(Ci.nsIAsyncOutputStream);
streamIn.asyncWait(connectHandler, 0, 0, threadManager.mainThread);
} catch (e) {

Просмотреть файл

@ -8,44 +8,127 @@
#include "PublicKeyPinningService.h"
#include "SharedCertVerifier.h"
#include "nsNSSComponent.h"
#include "SharedSSLState.h"
#include "sslt.h"
#include "ssl.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/StaticPrefs_network.h"
#include "mozilla/dom/Promise.h"
#include "nsICertOverrideService.h"
#include "nsISocketProvider.h"
#include "nsITlsHandshakeListener.h"
#include "nsNSSComponent.h"
#include "nsNSSHelper.h"
#include "ssl.h"
#include "sslt.h"
using namespace mozilla;
extern LazyLogModule gPIPNSSLog;
NS_IMPL_ISUPPORTS_INHERITED(CommonSocketControl, TransportSecurityInfo,
nsITLSSocketControl)
NS_IMPL_ISUPPORTS(CommonSocketControl, nsITLSSocketControl)
CommonSocketControl::CommonSocketControl(uint32_t aProviderFlags)
: mHandshakeCompleted(false),
CommonSocketControl::CommonSocketControl(const nsCString& aHostName,
int32_t aPort, uint32_t aProviderFlags)
: mHostName(aHostName),
mPort(aPort),
mOriginAttributes(),
mCanceled(false),
mSessionCacheInfo(),
mHandshakeCompleted(false),
mJoined(false),
mSentClientCert(false),
mFailedVerification(false),
mSSLVersionUsed(nsITLSSocketControl::SSL_VERSION_UNKNOWN),
mProviderFlags(aProviderFlags) {}
NS_IMETHODIMP
CommonSocketControl::GetNotificationCallbacks(
nsIInterfaceRequestor** aCallbacks) {
MutexAutoLock lock(mMutex);
*aCallbacks = mCallbacks;
NS_IF_ADDREF(*aCallbacks);
return NS_OK;
mProviderFlags(aProviderFlags),
mSecurityState(0),
mErrorCode(0),
mFailedCertChain(),
mServerCert(nullptr),
mSucceededCertChain(),
mCipherSuite(),
mKeaGroupName(),
mSignatureSchemeName(),
mProtocolVersion(),
mCertificateTransparencyStatus(0),
mIsAcceptedEch(),
mIsDelegatedCredential(),
mOverridableErrorCategory(),
mMadeOCSPRequests(false),
mUsedPrivateDNS(false),
mIsEV(),
mNPNCompleted(false),
mNegotiatedNPN(),
mResumed(false),
mIsBuiltCertChainRootBuiltInRoot(false),
mPeerId() {
#ifdef DEBUG
mOwningThread = PR_GetCurrentThread();
#endif
}
NS_IMETHODIMP
CommonSocketControl::SetNotificationCallbacks(
nsIInterfaceRequestor* aCallbacks) {
MutexAutoLock lock(mMutex);
mCallbacks = aCallbacks;
return NS_OK;
void CommonSocketControl::SetStatusErrorBits(
const nsCOMPtr<nsIX509Cert>& cert,
nsITransportSecurityInfo::OverridableErrorCategory
overridableErrorCategory) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
SetServerCert(cert, mozilla::psm::EVStatus::NotEV);
mOverridableErrorCategory = Some(overridableErrorCategory);
}
static void CreateCertChain(nsTArray<RefPtr<nsIX509Cert>>& aOutput,
nsTArray<nsTArray<uint8_t>>&& aCertList) {
nsTArray<nsTArray<uint8_t>> certList = std::move(aCertList);
aOutput.Clear();
for (auto& certBytes : certList) {
RefPtr<nsIX509Cert> cert = new nsNSSCertificate(std::move(certBytes));
aOutput.AppendElement(cert);
}
}
void CommonSocketControl::SetServerCert(
const nsCOMPtr<nsIX509Cert>& aServerCert,
mozilla::psm::EVStatus aEVStatus) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
mServerCert = aServerCert;
mIsEV = Some(aEVStatus == mozilla::psm::EVStatus::EV);
}
void CommonSocketControl::SetSucceededCertChain(
nsTArray<nsTArray<uint8_t>>&& aCertList) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
return CreateCertChain(mSucceededCertChain, std::move(aCertList));
}
void CommonSocketControl::SetFailedCertChain(
nsTArray<nsTArray<uint8_t>>&& aCertList) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
return CreateCertChain(mFailedCertChain, std::move(aCertList));
}
void CommonSocketControl::SetCanceled(PRErrorCode errorCode) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
MOZ_ASSERT(errorCode != 0);
if (errorCode == 0) {
errorCode = SEC_ERROR_LIBRARY_FAILURE;
}
mErrorCode = errorCode;
mCanceled = true;
}
// NB: GetErrorCode may be called before an error code is set (if ever). In that
// case, this returns 0, which is treated as a successful value.
int32_t CommonSocketControl::GetErrorCode() {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
// We're in an inconsistent state if we think we've been canceled but no error
// code was set or we haven't been canceled but an error code was set.
MOZ_ASSERT(
!((mCanceled && mErrorCode == 0) || (!mCanceled && mErrorCode != 0)));
if ((mCanceled && mErrorCode == 0) || (!mCanceled && mErrorCode != 0)) {
mCanceled = true;
mErrorCode = SEC_ERROR_LIBRARY_FAILURE;
}
return mErrorCode;
}
NS_IMETHODIMP
@ -76,6 +159,7 @@ NS_IMETHODIMP
CommonSocketControl::JoinConnection(const nsACString& npnProtocol,
const nsACString& hostname, int32_t port,
bool* _retval) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
nsresult rv = TestJoinConnection(npnProtocol, hostname, port, _retval);
if (NS_SUCCEEDED(rv) && *_retval) {
// All tests pass - this is joinable
@ -88,15 +172,15 @@ NS_IMETHODIMP
CommonSocketControl::TestJoinConnection(const nsACString& npnProtocol,
const nsACString& hostname,
int32_t port, bool* _retval) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
*_retval = false;
// Different ports may not be joined together
if (port != GetPort()) return NS_OK;
{
MutexAutoLock lock(mMutex);
// Make sure NPN has been completed and matches requested npnProtocol
if (!mNPNCompleted || !mNegotiatedNPN.Equals(npnProtocol)) return NS_OK;
// Make sure NPN has been completed and matches requested npnProtocol
if (!mNPNCompleted || !mNegotiatedNPN.Equals(npnProtocol)) {
return NS_OK;
}
IsAcceptableForHost(hostname, _retval); // sets _retval
@ -106,6 +190,7 @@ CommonSocketControl::TestJoinConnection(const nsACString& npnProtocol,
NS_IMETHODIMP
CommonSocketControl::IsAcceptableForHost(const nsACString& hostname,
bool* _retval) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
NS_ENSURE_ARG(_retval);
*_retval = false;
@ -138,9 +223,7 @@ CommonSocketControl::IsAcceptableForHost(const nsACString& hostname,
}
// If the cert has error bits (e.g. it is untrusted) then do not join.
// The value of mHaveCertErrorBits is only reliable because we know that
// the handshake completed.
if (mHaveCertErrorBits) {
if (mOverridableErrorCategory.isSome()) {
return NS_OK;
}
@ -152,10 +235,7 @@ CommonSocketControl::IsAcceptableForHost(const nsACString& hostname,
// Ensure that the server certificate covers the hostname that would
// like to join this connection
nsCOMPtr<nsIX509Cert> cert;
if (NS_FAILED(GetServerCert(getter_AddRefs(cert)))) {
return NS_OK;
}
nsCOMPtr<nsIX509Cert> cert(GetServerCert());
if (!cert) {
return NS_OK;
}
@ -164,8 +244,6 @@ CommonSocketControl::IsAcceptableForHost(const nsACString& hostname,
return NS_OK;
}
MutexAutoLock lock(mMutex);
// An empty mSucceededCertChain means the server certificate verification
// failed before, so don't join in this case.
if (mSucceededCertChain.IsEmpty()) {
@ -224,6 +302,7 @@ CommonSocketControl::IsAcceptableForHost(const nsACString& hostname,
}
void CommonSocketControl::RebuildCertificateInfoFromSSLTokenCache() {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
if (!mSessionCacheInfo) {
MOZ_LOG(
gPIPNSSLog, LogLevel::Debug,
@ -235,7 +314,8 @@ void CommonSocketControl::RebuildCertificateInfoFromSSLTokenCache() {
mozilla::net::SessionCacheInfo& info = *mSessionCacheInfo;
nsCOMPtr<nsIX509Cert> cert(
new nsNSSCertificate(std::move(info.mServerCertBytes)));
if (info.mOverridableErrorCategory == OverridableErrorCategory::ERROR_UNSET) {
if (info.mOverridableErrorCategory ==
nsITransportSecurityInfo::OverridableErrorCategory::ERROR_UNSET) {
SetServerCert(cert, info.mEVStatus);
} else {
SetStatusErrorBits(cert, info.mOverridableErrorCategory);
@ -266,17 +346,14 @@ CommonSocketControl::GetKEAKeyBits(uint32_t* aKEAKeyBits) {
NS_IMETHODIMP
CommonSocketControl::GetProviderFlags(uint32_t* aProviderFlags) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
*aProviderFlags = mProviderFlags;
return NS_OK;
}
NS_IMETHODIMP
CommonSocketControl::GetProviderTlsFlags(uint32_t* aProviderTlsFlags) {
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP
CommonSocketControl::GetSSLVersionUsed(int16_t* aSSLVersionUsed) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
*aSSLVersionUsed = mSSLVersionUsed;
return NS_OK;
}
@ -297,12 +374,14 @@ void CommonSocketControl::SetDenyClientCert(bool aDenyClientCert) {}
NS_IMETHODIMP
CommonSocketControl::GetClientCertSent(bool* arg) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
*arg = mSentClientCert;
return NS_OK;
}
NS_IMETHODIMP
CommonSocketControl::GetFailedVerification(bool* arg) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
*arg = mFailedVerification;
return NS_OK;
}
@ -340,3 +419,102 @@ CommonSocketControl::SetHandshakeCallbackListener(
NS_IMETHODIMP
CommonSocketControl::DisableEarlyData(void) { return NS_ERROR_NOT_IMPLEMENTED; }
NS_IMETHODIMP
CommonSocketControl::GetPeerId(nsACString& aResult) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
if (!mPeerId.IsEmpty()) {
aResult.Assign(mPeerId);
return NS_OK;
}
if (mProviderFlags &
nsISocketProvider::ANONYMOUS_CONNECT) { // See bug 466080
mPeerId.AppendLiteral("anon:");
}
if (mProviderFlags & nsISocketProvider::NO_PERMANENT_STORAGE) {
mPeerId.AppendLiteral("private:");
}
if (mProviderFlags & nsISocketProvider::BE_CONSERVATIVE) {
mPeerId.AppendLiteral("beConservative:");
}
mPeerId.Append(mHostName);
mPeerId.Append(':');
mPeerId.AppendInt(GetPort());
nsAutoCString suffix;
mOriginAttributes.CreateSuffix(suffix);
mPeerId.Append(suffix);
aResult.Assign(mPeerId);
return NS_OK;
}
NS_IMETHODIMP
CommonSocketControl::GetSecurityInfo(nsITransportSecurityInfo** aSecurityInfo) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
// Make sure peerId is set.
nsAutoCString unused;
nsresult rv = GetPeerId(unused);
if (NS_FAILED(rv)) {
return rv;
}
nsCOMPtr<nsITransportSecurityInfo> securityInfo(new TransportSecurityInfo(
mSecurityState, mErrorCode, mFailedCertChain.Clone(), mServerCert,
mSucceededCertChain.Clone(), mCipherSuite, mKeaGroupName,
mSignatureSchemeName, mProtocolVersion, mCertificateTransparencyStatus,
mIsAcceptedEch, mIsDelegatedCredential, mOverridableErrorCategory,
mMadeOCSPRequests, mUsedPrivateDNS, mIsEV, mNPNCompleted, mNegotiatedNPN,
mResumed, mIsBuiltCertChainRootBuiltInRoot, mPeerId));
securityInfo.forget(aSecurityInfo);
return NS_OK;
}
NS_IMETHODIMP
CommonSocketControl::AsyncGetSecurityInfo(JSContext* aCx,
mozilla::dom::Promise** aPromise) {
MOZ_RELEASE_ASSERT(NS_IsMainThread());
NS_ENSURE_ARG_POINTER(aCx);
NS_ENSURE_ARG_POINTER(aPromise);
nsIGlobalObject* globalObject = xpc::CurrentNativeGlobal(aCx);
if (!globalObject) {
return NS_ERROR_UNEXPECTED;
}
ErrorResult result;
RefPtr<mozilla::dom::Promise> promise =
mozilla::dom::Promise::Create(globalObject, result);
if (result.Failed()) {
return result.StealNSResult();
}
nsCOMPtr<nsIRunnable> runnable(NS_NewRunnableFunction(
"CommonSocketControl::AsyncGetSecurityInfo",
[promise, self = RefPtr{this}]() mutable {
nsCOMPtr<nsITransportSecurityInfo> securityInfo;
nsresult rv = self->GetSecurityInfo(getter_AddRefs(securityInfo));
nsCOMPtr<nsIRunnable> runnable(NS_NewRunnableFunction(
"CommonSocketControl::AsyncGetSecurityInfoResolve",
[rv, promise = std::move(promise),
securityInfo = std::move(securityInfo)]() {
if (NS_FAILED(rv)) {
promise->MaybeReject(rv);
} else {
promise->MaybeResolve(securityInfo);
}
}));
NS_DispatchToMainThread(runnable.forget());
}));
nsCOMPtr<nsIEventTarget> target(
do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID));
if (!target) {
return NS_ERROR_FAILURE;
}
nsresult rv = target->Dispatch(runnable, NS_DISPATCH_NORMAL);
if (NS_FAILED(rv)) {
return rv;
}
promise.forget(aPromise);
return NS_OK;
}

Просмотреть файл

@ -7,30 +7,149 @@
#ifndef CommonSocketControl_h
#define CommonSocketControl_h
#include "CertVerifier.h"
#include "TransportSecurityInfo.h"
#include "mozilla/Maybe.h"
#include "mozilla/net/SSLTokensCache.h"
#include "nsIInterfaceRequestor.h"
#include "nsITLSSocketControl.h"
#include "nsSocketTransportService2.h"
class CommonSocketControl : public mozilla::psm::TransportSecurityInfo,
public nsITLSSocketControl {
#ifdef DEBUG
# include "prthread.h"
# define COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD() \
MOZ_ASSERT(mOwningThread == PR_GetCurrentThread())
#else
# define COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD() \
do { \
} while (false)
#endif
// CommonSocketControl is the base class that implements nsITLSSocketControl.
// Various concrete TLS socket control implementations inherit from this class.
// Currently these implementations consist of NSSSocketControl (a socket
// control for NSS) and QuicSocketControl (a socket control for quic).
// NB: these classes must only be used on the socket thread (the one exception
// being tests that incidentally use CommonSocketControl on the main thread
// (and only the main thread)). This is enforced via the macro
// COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD() that should be called at the
// beginning of every function in this class and all subclasses.
class CommonSocketControl : public nsITLSSocketControl {
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSITLSSOCKETCONTROL
explicit CommonSocketControl(uint32_t providerFlags);
CommonSocketControl(const nsCString& aHostName, int32_t aPort,
uint32_t aProviderFlags);
uint32_t GetProviderFlags() const { return mProviderFlags; }
void SetSSLVersionUsed(int16_t version) { mSSLVersionUsed = version; }
// Use "errorCode" 0 to indicate success.
virtual void SetCertVerificationResult(PRErrorCode errorCode) {
MOZ_ASSERT_UNREACHABLE("Subclasses must override this.");
}
const nsACString& GetHostName() {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
return mHostName;
}
int32_t GetPort() {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
return mPort;
}
void SetMadeOCSPRequests(bool aMadeOCSPRequests) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
mMadeOCSPRequests = aMadeOCSPRequests;
}
bool GetMadeOCSPRequests() {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
return mMadeOCSPRequests;
}
void SetUsedPrivateDNS(bool aUsedPrivateDNS) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
mUsedPrivateDNS = aUsedPrivateDNS;
}
bool GetUsedPrivateDNS() {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
return mUsedPrivateDNS;
}
void SetServerCert(const nsCOMPtr<nsIX509Cert>& aServerCert,
mozilla::psm::EVStatus aEVStatus);
already_AddRefed<nsIX509Cert> GetServerCert() {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
return do_AddRef(mServerCert);
}
bool HasServerCert() {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
return mServerCert != nullptr;
}
void SetStatusErrorBits(const nsCOMPtr<nsIX509Cert>& cert,
nsITransportSecurityInfo::OverridableErrorCategory
overridableErrorCategory);
bool HasUserOverriddenCertificateError() {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
return mOverridableErrorCategory.isSome() &&
*mOverridableErrorCategory !=
nsITransportSecurityInfo::OverridableErrorCategory::ERROR_UNSET;
}
void SetSucceededCertChain(nsTArray<nsTArray<uint8_t>>&& certList);
void SetFailedCertChain(nsTArray<nsTArray<uint8_t>>&& certList);
void SetIsBuiltCertChainRootBuiltInRoot(
bool aIsBuiltCertChainRootBuiltInRoot) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
mIsBuiltCertChainRootBuiltInRoot = aIsBuiltCertChainRootBuiltInRoot;
}
void SetCertificateTransparencyStatus(
uint16_t aCertificateTransparencyStatus) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
mCertificateTransparencyStatus = aCertificateTransparencyStatus;
}
void SetOriginAttributes(const mozilla::OriginAttributes& aOriginAttributes) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
mOriginAttributes = aOriginAttributes;
}
mozilla::OriginAttributes& GetOriginAttributes() {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
return mOriginAttributes;
}
void SetSecurityState(uint32_t aSecurityState) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
mSecurityState = aSecurityState;
}
void SetResumed(bool aResumed) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
mResumed = aResumed;
}
uint32_t GetProviderFlags() const {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
return mProviderFlags;
}
void SetSSLVersionUsed(uint16_t version) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
mSSLVersionUsed = version;
}
void SetSessionCacheInfo(mozilla::net::SessionCacheInfo&& aInfo) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
mSessionCacheInfo.reset();
mSessionCacheInfo.emplace(std::move(aInfo));
}
void RebuildCertificateInfoFromSSLTokenCache();
void SetCanceled(PRErrorCode errorCode);
bool IsCanceled() {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
return mCanceled;
}
int32_t GetErrorCode();
protected:
~CommonSocketControl() = default;
virtual ~CommonSocketControl() = default;
nsCString mHostName;
int32_t mPort;
mozilla::OriginAttributes mOriginAttributes;
bool mCanceled;
mozilla::Maybe<mozilla::net::SessionCacheInfo> mSessionCacheInfo;
bool mHandshakeCompleted;
bool mJoined;
@ -38,6 +157,35 @@ class CommonSocketControl : public mozilla::psm::TransportSecurityInfo,
bool mFailedVerification;
uint16_t mSSLVersionUsed;
uint32_t mProviderFlags;
// Fields used to build a TransportSecurityInfo
uint32_t mSecurityState;
PRErrorCode mErrorCode;
// Peer cert chain for failed connections.
nsTArray<RefPtr<nsIX509Cert>> mFailedCertChain;
nsCOMPtr<nsIX509Cert> mServerCert;
nsTArray<RefPtr<nsIX509Cert>> mSucceededCertChain;
mozilla::Maybe<uint16_t> mCipherSuite;
mozilla::Maybe<nsCString> mKeaGroupName;
mozilla::Maybe<nsCString> mSignatureSchemeName;
mozilla::Maybe<uint16_t> mProtocolVersion;
uint16_t mCertificateTransparencyStatus;
mozilla::Maybe<bool> mIsAcceptedEch;
mozilla::Maybe<bool> mIsDelegatedCredential;
mozilla::Maybe<nsITransportSecurityInfo::OverridableErrorCategory>
mOverridableErrorCategory;
bool mMadeOCSPRequests;
bool mUsedPrivateDNS;
mozilla::Maybe<bool> mIsEV;
bool mNPNCompleted;
nsCString mNegotiatedNPN;
bool mResumed;
bool mIsBuiltCertChainRootBuiltInRoot;
nsCString mPeerId;
#ifdef DEBUG
const PRThread* mOwningThread;
#endif
};
#endif // CommonSocketControl_h

Просмотреть файл

@ -6,18 +6,19 @@
#include "NSSSocketControl.h"
#include "nsISocketProvider.h"
#include "ssl.h"
#include "sslexp.h"
NSSSocketControl::NSSSocketControl(SharedSSLState& aState,
NSSSocketControl::NSSSocketControl(const nsCString& aHostName, int32_t aPort,
SharedSSLState& aState,
uint32_t providerFlags,
uint32_t providerTlsFlags)
: CommonSocketControl(providerFlags),
: CommonSocketControl(aHostName, aPort, providerFlags),
mFd(nullptr),
mCertVerificationState(before_cert_verification),
mSharedState(aState),
mForSTARTTLS(false),
mTLSVersionRange{0, 0},
mHandshakePending(true),
mPreliminaryHandshakeDone(false),
mEarlyDataAccepted(false),
@ -35,50 +36,41 @@ NSSSocketControl::NSSSocketControl(SharedSSLState& aState,
mMACAlgorithmUsed(nsITLSSocketControl::SSL_MAC_UNKNOWN),
mProviderTlsFlags(providerTlsFlags),
mSocketCreationTimestamp(TimeStamp::Now()),
mPlaintextBytesRead(0) {
mTLSVersionRange.min = 0;
mTLSVersionRange.max = 0;
}
NSSSocketControl::~NSSSocketControl() = default;
NS_IMPL_ISUPPORTS_INHERITED(NSSSocketControl, TransportSecurityInfo,
nsITLSSocketControl)
NS_IMETHODIMP
NSSSocketControl::GetProviderTlsFlags(uint32_t* aProviderTlsFlags) {
*aProviderTlsFlags = mProviderTlsFlags;
return NS_OK;
}
mPlaintextBytesRead(0) {}
NS_IMETHODIMP
NSSSocketControl::GetKEAUsed(int16_t* aKea) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
*aKea = mKEAUsed;
return NS_OK;
}
NS_IMETHODIMP
NSSSocketControl::GetKEAKeyBits(uint32_t* aKeyBits) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
*aKeyBits = mKEAKeyBits;
return NS_OK;
}
NS_IMETHODIMP
NSSSocketControl::GetSSLVersionOffered(int16_t* aSSLVersionOffered) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
*aSSLVersionOffered = mTLSVersionRange.max;
return NS_OK;
}
NS_IMETHODIMP
NSSSocketControl::GetMACAlgorithmUsed(int16_t* aMac) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
*aMac = mMACAlgorithmUsed;
return NS_OK;
}
void NSSSocketControl::NoteTimeUntilReady() {
MutexAutoLock lock(mMutex);
if (mNotedTimeUntilReady) return;
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
if (mNotedTimeUntilReady) {
return;
}
mNotedTimeUntilReady = true;
auto timestampNow = TimeStamp::Now();
@ -113,6 +105,7 @@ void NSSSocketControl::NoteTimeUntilReady() {
}
void NSSSocketControl::SetHandshakeCompleted() {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
if (!mHandshakeCompleted) {
enum HandshakeType {
Resumption = 1,
@ -126,11 +119,12 @@ void NSSSocketControl::SetHandshakeCompleted() {
: mFalseStartCallbackCalled
? ChoseNotToFalseStart
: NotAllowedToFalseStart;
MutexAutoLock lock(mMutex);
// This will include TCP and proxy tunnel wait time
Telemetry::AccumulateTimeDelta(
Telemetry::SSL_TIME_UNTIL_HANDSHAKE_FINISHED_KEYED_BY_KA, mKeaGroup,
mSocketCreationTimestamp, TimeStamp::Now());
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.
@ -167,7 +161,7 @@ void NSSSocketControl::SetHandshakeCompleted() {
}
void NSSSocketControl::SetNegotiatedNPN(const char* value, uint32_t length) {
MutexAutoLock lock(mMutex);
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
if (!value) {
mNegotiatedNPN.Truncate();
} else {
@ -180,6 +174,7 @@ void NSSSocketControl::SetNegotiatedNPN(const char* value, uint32_t length) {
NS_IMETHODIMP
NSSSocketControl::GetAlpnEarlySelection(nsACString& aAlpnSelected) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
aAlpnSelected.Truncate();
SSLPreliminaryChannelInfo info;
@ -208,22 +203,29 @@ NSSSocketControl::GetAlpnEarlySelection(nsACString& aAlpnSelected) {
NS_IMETHODIMP
NSSSocketControl::GetEarlyDataAccepted(bool* aAccepted) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
*aAccepted = mEarlyDataAccepted;
return NS_OK;
}
void NSSSocketControl::SetEarlyDataAccepted(bool aAccepted) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
mEarlyDataAccepted = aAccepted;
}
bool NSSSocketControl::GetDenyClientCert() { return mDenyClientCert; }
bool NSSSocketControl::GetDenyClientCert() {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
return mDenyClientCert;
}
void NSSSocketControl::SetDenyClientCert(bool aDenyClientCert) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
mDenyClientCert = aDenyClientCert;
}
NS_IMETHODIMP
NSSSocketControl::DriveHandshake() {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
if (!mFd) {
return NS_ERROR_FAILURE;
}
@ -254,20 +256,31 @@ NSSSocketControl::DriveHandshake() {
return NS_OK;
}
bool NSSSocketControl::GetForSTARTTLS() { return mForSTARTTLS; }
bool NSSSocketControl::GetForSTARTTLS() {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
return mForSTARTTLS;
}
void NSSSocketControl::SetForSTARTTLS(bool aForSTARTTLS) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
mForSTARTTLS = aForSTARTTLS;
}
NS_IMETHODIMP
NSSSocketControl::ProxyStartSSL() { return ActivateSSL(); }
NSSSocketControl::ProxyStartSSL() {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
return ActivateSSL();
}
NS_IMETHODIMP
NSSSocketControl::StartTLS() { return ActivateSSL(); }
NSSSocketControl::StartTLS() {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
return ActivateSSL();
}
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.
@ -290,6 +303,7 @@ NSSSocketControl::SetNPNList(nsTArray<nsCString>& protocolArray) {
}
nsresult NSSSocketControl::ActivateSSL() {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
if (SECSuccess != SSL_OptionSet(mFd, SSL_SECURITY, true))
return NS_ERROR_FAILURE;
if (SECSuccess != SSL_ResetHandshake(mFd, false)) return NS_ERROR_FAILURE;
@ -300,16 +314,19 @@ nsresult NSSSocketControl::ActivateSSL() {
}
nsresult NSSSocketControl::GetFileDescPtr(PRFileDesc** aFilePtr) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
*aFilePtr = mFd;
return NS_OK;
}
nsresult NSSSocketControl::SetFileDescPtr(PRFileDesc* aFilePtr) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
mFd = aFilePtr;
return NS_OK;
}
void NSSSocketControl::SetCertVerificationWaiting() {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
// mCertVerificationState may be before_cert_verification for the first
// handshake on the connection, or after_cert_verification for subsequent
// renegotiation handshakes.
@ -323,6 +340,7 @@ void NSSSocketControl::SetCertVerificationWaiting() {
// 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 == waiting_for_cert_verification,
"Invalid state transition to cert_verification_finished");
@ -358,6 +376,7 @@ void NSSSocketControl::SetCertVerificationResult(PRErrorCode errorCode) {
void NSSSocketControl::ClientAuthCertificateSelected(
nsTArray<uint8_t>& certBytes, nsTArray<nsTArray<uint8_t>>& certChainBytes) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
// If mFd is nullptr, the connection has been closed already, so we don't
// need to do anything here.
if (!mFd) {
@ -406,14 +425,19 @@ void NSSSocketControl::ClientAuthCertificateSelected(
sendingClientAuthCert ? cert.release() : nullptr);
}
SharedSSLState& NSSSocketControl::SharedState() { return mSharedState; }
SharedSSLState& NSSSocketControl::SharedState() {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
return mSharedState;
}
void NSSSocketControl::SetSharedOwningReference(SharedSSLState* aRef) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
mOwningSharedRef = aRef;
}
NS_IMETHODIMP
NSSSocketControl::DisableEarlyData() {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
if (!mFd) {
return NS_OK;
}
@ -430,11 +454,13 @@ NSSSocketControl::DisableEarlyData() {
NS_IMETHODIMP
NSSSocketControl::SetHandshakeCallbackListener(
nsITlsHandshakeCallbackListener* callback) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
mTlsHandshakeCallback = callback;
return NS_OK;
}
PRStatus NSSSocketControl::CloseSocketAndDestroy() {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
PRFileDesc* popped = PR_PopIOLayer(mFd, PR_TOP_IO_LAYER);
MOZ_ASSERT(
popped && popped->identity == nsSSLIOLayerHelpers::nsSSLIOLayerIdentity,
@ -476,12 +502,14 @@ PRStatus NSSSocketControl::CloseSocketAndDestroy() {
NS_IMETHODIMP
NSSSocketControl::GetEsniTxt(nsACString& aEsniTxt) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
aEsniTxt = mEsniTxt;
return NS_OK;
}
NS_IMETHODIMP
NSSSocketControl::SetEsniTxt(const nsACString& aEsniTxt) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
mEsniTxt = aEsniTxt;
if (mEsniTxt.Length()) {
@ -508,12 +536,14 @@ NSSSocketControl::SetEsniTxt(const nsACString& aEsniTxt) {
NS_IMETHODIMP
NSSSocketControl::GetEchConfig(nsACString& aEchConfig) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
aEchConfig = mEchConfig;
return NS_OK;
}
NS_IMETHODIMP
NSSSocketControl::SetEchConfig(const nsACString& aEchConfig) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
mEchConfig = aEchConfig;
if (mEchConfig.Length()) {
@ -533,6 +563,7 @@ NSSSocketControl::SetEchConfig(const nsACString& aEchConfig) {
NS_IMETHODIMP
NSSSocketControl::GetRetryEchConfig(nsACString& aEchConfig) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
if (!mFd) {
return NS_ERROR_FAILURE;
}
@ -549,7 +580,7 @@ NSSSocketControl::GetRetryEchConfig(nsACString& aEchConfig) {
NS_IMETHODIMP
NSSSocketControl::GetPeerId(nsACString& aResult) {
MutexAutoLock lock(mMutex);
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
if (!mPeerId.IsEmpty()) {
aResult.Assign(mPeerId);
return NS_OK;
@ -580,6 +611,7 @@ NSSSocketControl::GetPeerId(nsACString& aResult) {
}
nsresult NSSSocketControl::SetResumptionTokenFromExternalCache() {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
if (!mFd) {
return NS_ERROR_FAILURE;
}
@ -634,3 +666,15 @@ nsresult NSSSocketControl::SetResumptionTokenFromExternalCache() {
return NS_OK;
}
void NSSSocketControl::SetPreliminaryHandshakeInfo(
const SSLChannelInfo& channelInfo, const SSLCipherSuiteInfo& cipherInfo) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
mResumed = channelInfo.resumed;
mCipherSuite.emplace(channelInfo.cipherSuite);
mProtocolVersion.emplace(channelInfo.protocolVersion & 0xFF);
mKeaGroupName.emplace(getKeaGroupName(channelInfo.keaGroup));
mSignatureSchemeName.emplace(getSignatureName(channelInfo.signatureScheme));
mIsDelegatedCredential.emplace(channelInfo.peerDelegCred);
mIsAcceptedEch.emplace(channelInfo.echAccepted);
}

Просмотреть файл

@ -12,10 +12,11 @@
class NSSSocketControl final : public CommonSocketControl {
public:
NSSSocketControl(mozilla::psm::SharedSSLState& aState, uint32_t providerFlags,
NSSSocketControl(const nsCString& aHostName, int32_t aPort,
mozilla::psm::SharedSSLState& aState, uint32_t providerFlags,
uint32_t providerTlsFlags);
NS_DECL_ISUPPORTS_INHERITED
NS_INLINE_DECL_REFCOUNTING_INHERITED(NSSSocketControl, CommonSocketControl);
void SetForSTARTTLS(bool aForSTARTTLS);
bool GetForSTARTTLS();
@ -23,11 +24,23 @@ class NSSSocketControl final : public CommonSocketControl {
nsresult GetFileDescPtr(PRFileDesc** aFilePtr);
nsresult SetFileDescPtr(PRFileDesc* aFilePtr);
bool IsHandshakePending() const { return mHandshakePending; }
void SetHandshakeNotPending() { mHandshakePending = false; }
bool IsHandshakePending() const {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
return mHandshakePending;
}
void SetHandshakeNotPending() {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
mHandshakePending = false;
}
void SetTLSVersionRange(SSLVersionRange range) { mTLSVersionRange = range; }
SSLVersionRange GetTLSVersionRange() const { return mTLSVersionRange; };
void SetTLSVersionRange(SSLVersionRange range) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
mTLSVersionRange = range;
}
SSLVersionRange GetTLSVersionRange() const {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
return mTLSVersionRange;
};
// From nsITLSSocketControl.
NS_IMETHOD ProxyStartSSL(void) override;
@ -36,10 +49,8 @@ class NSSSocketControl final : public CommonSocketControl {
NS_IMETHOD GetAlpnEarlySelection(nsACString& _retval) override;
NS_IMETHOD GetEarlyDataAccepted(bool* aEarlyDataAccepted) override;
NS_IMETHOD DriveHandshake(void) override;
using nsITLSSocketControl::GetKEAUsed;
NS_IMETHOD GetKEAUsed(int16_t* aKEAUsed) override;
NS_IMETHOD GetKEAKeyBits(uint32_t* aKEAKeyBits) override;
NS_IMETHOD GetProviderTlsFlags(uint32_t* aProviderTlsFlags) override;
NS_IMETHOD GetSSLVersionOffered(int16_t* aSSLVersionOffered) override;
NS_IMETHOD GetMACAlgorithmUsed(int16_t* aMACAlgorithmUsed) override;
bool GetDenyClientCert() override;
@ -60,27 +71,50 @@ class NSSSocketControl final : public CommonSocketControl {
void SetEarlyDataAccepted(bool aAccepted);
void SetHandshakeCompleted();
bool IsHandshakeCompleted() const { return mHandshakeCompleted; }
bool IsHandshakeCompleted() const {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
return mHandshakeCompleted;
}
void NoteTimeUntilReady();
void SetFalseStartCallbackCalled() { mFalseStartCallbackCalled = true; }
void SetFalseStarted() { mFalseStarted = true; }
void SetFalseStartCallbackCalled() {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
mFalseStartCallbackCalled = true;
}
void SetFalseStarted() {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
mFalseStarted = true;
}
// 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; }
void SetFullHandshake() {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
mIsFullHandshake = true;
}
bool IsFullHandshake() const {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
return mIsFullHandshake;
}
void UpdateEchExtensionStatus(EchExtensionStatus aEchExtensionStatus) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
mEchExtensionStatus = std::max(aEchExtensionStatus, mEchExtensionStatus);
}
EchExtensionStatus GetEchExtensionStatus() const {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
return mEchExtensionStatus;
}
bool GetJoined() { return mJoined; }
bool GetJoined() {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
return mJoined;
}
uint32_t GetProviderTlsFlags() const { return mProviderTlsFlags; }
uint32_t GetProviderTlsFlags() const {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
return mProviderTlsFlags;
}
mozilla::psm::SharedSSLState& SharedState();
@ -100,32 +134,57 @@ class NSSSocketControl final : public CommonSocketControl {
// for logging only
PRBool IsWaitingForCertVerification() const {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
return mCertVerificationState == waiting_for_cert_verification;
}
void AddPlaintextBytesRead(uint64_t val) { mPlaintextBytesRead += val; }
void AddPlaintextBytesRead(uint64_t val) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
mPlaintextBytesRead += val;
}
bool IsPreliminaryHandshakeDone() const { return mPreliminaryHandshakeDone; }
void SetPreliminaryHandshakeDone() { mPreliminaryHandshakeDone = true; }
bool IsPreliminaryHandshakeDone() const {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
return mPreliminaryHandshakeDone;
}
void SetPreliminaryHandshakeDone() {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
mPreliminaryHandshakeDone = true;
}
void SetKEAUsed(uint16_t kea) { mKEAUsed = kea; }
void SetKEAUsed(int16_t kea) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
mKEAUsed = kea;
}
void SetKEAKeyBits(uint32_t keaBits) { mKEAKeyBits = keaBits; }
void SetKEAKeyBits(uint32_t keaBits) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
mKEAKeyBits = keaBits;
}
void SetMACAlgorithmUsed(int16_t mac) { mMACAlgorithmUsed = mac; }
void SetMACAlgorithmUsed(int16_t mac) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
mMACAlgorithmUsed = mac;
}
void SetShortWritePending(int32_t amount, unsigned char data) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
mIsShortWritePending = true;
mShortWriteOriginalAmount = amount;
mShortWritePendingByte = data;
}
bool IsShortWritePending() { return mIsShortWritePending; }
bool IsShortWritePending() {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
return mIsShortWritePending;
}
unsigned char const* GetShortWritePendingByteRef() {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
return &mShortWritePendingByte;
}
int32_t ResetShortWritePending() {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
mIsShortWritePending = false;
return mShortWriteOriginalAmount;
}
@ -135,11 +194,13 @@ class NSSSocketControl final : public CommonSocketControl {
// as it was previously when we hit the short-write. This is a measure
// to make sure we communicate correctly to the consumer.
void RememberShortWrittenBuffer(const unsigned char* data) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
mShortWriteBufferCheck =
mozilla::MakeUnique<char[]>(mShortWriteOriginalAmount);
memcpy(mShortWriteBufferCheck.get(), data, mShortWriteOriginalAmount);
}
void CheckShortWrittenBuffer(const unsigned char* data, int32_t amount) {
COMMON_SOCKET_CONTROL_ASSERT_ON_OWNING_THREAD();
if (!mShortWriteBufferCheck) return;
MOZ_ASSERT(amount >= mShortWriteOriginalAmount,
"unexpected amount length after short write");
@ -154,10 +215,11 @@ class NSSSocketControl final : public CommonSocketControl {
nsresult SetResumptionTokenFromExternalCache();
protected:
virtual ~NSSSocketControl();
void SetPreliminaryHandshakeInfo(const SSLChannelInfo& channelInfo,
const SSLCipherSuiteInfo& cipherInfo);
private:
~NSSSocketControl() = default;
PRFileDesc* mFd;
CertVerificationState mCertVerificationState;

Просмотреть файл

@ -65,11 +65,10 @@
//
// SSLServerCertVerificationResult must be dispatched to the socket transport
// thread because we must only call SSL_* functions on the socket transport
// thread since they may do I/O, because many parts of NSSSocketControl (the
// subclass of TransportSecurityInfo used when validating certificates during
// an SSL handshake) and the PSM NSS I/O layer are not thread-safe, and because
// we need the event to interrupt the PR_Poll that may waiting for I/O on the
// socket for which we are validating the cert.
// thread since they may do I/O, because many parts of NSSSocketControl and the
// PSM NSS I/O layer are not thread-safe, and because we need the event to
// interrupt the PR_Poll that may waiting for I/O on the socket for which we
// are validating the cert.
//
// When socket process is enabled, libssl is running on socket process. To
// perform certificate authentication with CertVerifier, we have to send all
@ -105,7 +104,6 @@
#include "ScopedNSSTypes.h"
#include "SharedCertVerifier.h"
#include "SharedSSLState.h"
#include "TransportSecurityInfo.h"
#include "VerifySSLServerCertChild.h"
#include "cert.h"
#include "mozilla/Assertions.h"
@ -383,16 +381,23 @@ static nsresult OverrideAllowedForHost(
// Prohibit changing the server cert only if we negotiated SPDY,
// in order to support SPDY's cross-origin connection pooling.
static SECStatus BlockServerCertChangeForSpdy(
NSSSocketControl* infoObject, const UniqueCERTCertificate& serverCert) {
if (!infoObject->IsHandshakeCompleted()) {
NSSSocketControl* socketControl, const UniqueCERTCertificate& serverCert) {
if (!socketControl->IsHandshakeCompleted()) {
// first handshake on this connection, not a
// renegotiation.
return SECSuccess;
}
// Filter out sockets that did not neogtiate SPDY via NPN
nsCOMPtr<nsITransportSecurityInfo> securityInfo;
nsresult rv = socketControl->GetSecurityInfo(getter_AddRefs(securityInfo));
MOZ_ASSERT(NS_SUCCEEDED(rv), "GetSecurityInfo() failed during renegotiation");
if (NS_FAILED(rv) || !securityInfo) {
PR_SetError(SEC_ERROR_LIBRARY_FAILURE, 0);
return SECFailure;
}
nsAutoCString negotiatedNPN;
nsresult rv = infoObject->GetNegotiatedNPN(negotiatedNPN);
rv = securityInfo->GetNegotiatedNPN(negotiatedNPN);
MOZ_ASSERT(NS_SUCCEEDED(rv),
"GetNegotiatedNPN() failed during renegotiation");
@ -407,8 +412,7 @@ static SECStatus BlockServerCertChangeForSpdy(
}
// Check to see if the cert has actually changed
nsCOMPtr<nsIX509Cert> cert;
infoObject->GetServerCert(getter_AddRefs(cert));
nsCOMPtr<nsIX509Cert> cert(socketControl->GetServerCert());
if (!cert) {
PR_SetError(SEC_ERROR_LIBRARY_FAILURE, 0);
return SECFailure;
@ -814,7 +818,7 @@ SSLServerCertVerificationJob::Run() {
// Takes information needed for cert verification, does some consistency
// checks and calls SSLServerCertVerificationJob::Dispatch.
SECStatus AuthCertificateHookInternal(
TransportSecurityInfo* infoObject, const void* aPtrForLogging,
CommonSocketControl* socketControl, const void* aPtrForLogging,
const nsACString& hostName, nsTArray<nsTArray<uint8_t>>&& peerCertChain,
Maybe<nsTArray<uint8_t>>& stapledOCSPResponse,
Maybe<nsTArray<uint8_t>>& sctsFromTLSExtension,
@ -825,7 +829,7 @@ SECStatus AuthCertificateHookInternal(
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
("[%p] starting AuthCertificateHookInternal\n", aPtrForLogging));
if (!infoObject || peerCertChain.IsEmpty()) {
if (!socketControl || peerCertChain.IsEmpty()) {
PR_SetError(PR_INVALID_STATE_ERROR, 0);
return SECFailure;
}
@ -853,12 +857,12 @@ SECStatus AuthCertificateHookInternal(
uint64_t addr = reinterpret_cast<uintptr_t>(aPtrForLogging);
RefPtr<SSLServerCertVerificationResult> resultTask =
new SSLServerCertVerificationResult(infoObject);
new SSLServerCertVerificationResult(socketControl);
if (XRE_IsSocketProcess()) {
return RemoteProcessCertVerification(
std::move(peerCertChain), hostName, infoObject->GetPort(),
infoObject->GetOriginAttributes(), stapledOCSPResponse,
std::move(peerCertChain), hostName, socketControl->GetPort(),
socketControl->GetOriginAttributes(), stapledOCSPResponse,
sctsFromTLSExtension, dcInfo, providerFlags, certVerifierFlags,
resultTask);
}
@ -868,8 +872,8 @@ SECStatus AuthCertificateHookInternal(
// and we *want* to do certificate verification on a background thread
// because of the performance benefits of doing so.
return SSLServerCertVerificationJob::Dispatch(
addr, infoObject, std::move(peerCertChain), hostName,
infoObject->GetPort(), infoObject->GetOriginAttributes(),
addr, socketControl, std::move(peerCertChain), hostName,
socketControl->GetPort(), socketControl->GetOriginAttributes(),
stapledOCSPResponse, sctsFromTLSExtension, dcInfo, providerFlags, Now(),
certVerifierFlags, resultTask);
}
@ -983,7 +987,7 @@ SECStatus AuthCertificateHook(void* arg, PRFileDesc* fd, PRBool checkSig,
// checks and calls SSLServerCertVerificationJob::Dispatch.
// This function is used for Quic.
SECStatus AuthCertificateHookWithInfo(
TransportSecurityInfo* infoObject, const nsACString& aHostName,
CommonSocketControl* socketControl, const nsACString& aHostName,
const void* aPtrForLogging, nsTArray<nsTArray<uint8_t>>&& peerCertChain,
Maybe<nsTArray<nsTArray<uint8_t>>>& stapledOCSPResponses,
Maybe<nsTArray<uint8_t>>& sctsFromTLSExtension, uint32_t providerFlags) {
@ -1011,7 +1015,7 @@ SECStatus AuthCertificateHookWithInfo(
// for Delegated Credentials.
Maybe<DelegatedCredentialInfo> dcInfo;
return AuthCertificateHookInternal(infoObject, aPtrForLogging, aHostName,
return AuthCertificateHookInternal(socketControl, aPtrForLogging, aHostName,
std::move(peerCertChain),
stapledOCSPResponse, sctsFromTLSExtension,
dcInfo, providerFlags, certVerifierFlags);
@ -1020,9 +1024,9 @@ SECStatus AuthCertificateHookWithInfo(
NS_IMPL_ISUPPORTS_INHERITED0(SSLServerCertVerificationResult, Runnable)
SSLServerCertVerificationResult::SSLServerCertVerificationResult(
TransportSecurityInfo* infoObject)
CommonSocketControl* socketControl)
: Runnable("psm::SSLServerCertVerificationResult"),
mInfoObject(infoObject),
mSocketControl(socketControl),
mCertificateTransparencyStatus(0),
mEVStatus(EVStatus::NotEV),
mSucceeded(false),
@ -1092,33 +1096,33 @@ SSLServerCertVerificationResult::Run() {
SaveIntermediateCerts(mBuiltChain);
}
mInfoObject->SetMadeOCSPRequest(mMadeOCSPRequests);
mSocketControl->SetMadeOCSPRequests(mMadeOCSPRequests);
if (mSucceeded) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
("SSLServerCertVerificationResult::Run setting NEW cert"));
nsTArray<uint8_t> certBytes(mBuiltChain.ElementAt(0).Clone());
nsCOMPtr<nsIX509Cert> cert(new nsNSSCertificate(std::move(certBytes)));
mInfoObject->SetServerCert(cert, mEVStatus);
mInfoObject->SetSucceededCertChain(std::move(mBuiltChain));
mSocketControl->SetServerCert(cert, mEVStatus);
mSocketControl->SetSucceededCertChain(std::move(mBuiltChain));
mInfoObject->SetIsBuiltCertChainRootBuiltInRoot(
mSocketControl->SetIsBuiltCertChainRootBuiltInRoot(
mIsBuiltCertChainRootBuiltInRoot);
mInfoObject->SetCertificateTransparencyStatus(
mSocketControl->SetCertificateTransparencyStatus(
mCertificateTransparencyStatus);
} else {
nsTArray<uint8_t> certBytes(mPeerCertChain.ElementAt(0).Clone());
nsCOMPtr<nsIX509Cert> cert(new nsNSSCertificate(std::move(certBytes)));
// Certificate validation failed; store the peer certificate chain on
// infoObject so it can be used for error reporting.
mInfoObject->SetFailedCertChain(std::move(mPeerCertChain));
// mSocketControl so it can be used for error reporting.
mSocketControl->SetFailedCertChain(std::move(mPeerCertChain));
if (mOverridableErrorCategory !=
nsITransportSecurityInfo::OverridableErrorCategory::ERROR_UNSET) {
mInfoObject->SetStatusErrorBits(cert, mOverridableErrorCategory);
mSocketControl->SetStatusErrorBits(cert, mOverridableErrorCategory);
}
}
mInfoObject->SetCertVerificationResult(mFinalError);
mSocketControl->SetCertVerificationResult(mFinalError);
return NS_OK;
}

Просмотреть файл

@ -7,6 +7,7 @@
#define _SSLSERVERCERTVERIFICATION_H
#include "CertVerifier.h"
#include "CommonSocketControl.h"
#include "ScopedNSSTypes.h"
#include "mozilla/Maybe.h"
#include "mozpkix/pkix.h"
@ -24,7 +25,6 @@ using namespace mozilla::pkix;
namespace mozilla {
namespace psm {
class TransportSecurityInfo;
enum class EVStatus : uint8_t;
SECStatus AuthCertificateHook(void* arg, PRFileDesc* fd, PRBool checkSig,
@ -34,7 +34,7 @@ SECStatus AuthCertificateHook(void* arg, PRFileDesc* fd, PRBool checkSig,
// asynchronous and the info object will be notified when the verification has
// completed via SetCertVerificationResult.
SECStatus AuthCertificateHookWithInfo(
TransportSecurityInfo* infoObject, const nsACString& aHostName,
CommonSocketControl* socketControl, const nsACString& aHostName,
const void* aPtrForLogging, nsTArray<nsTArray<uint8_t>>&& peerCertChain,
Maybe<nsTArray<nsTArray<uint8_t>>>& stapledOCSPResponses,
Maybe<nsTArray<uint8_t>>& sctsFromTLSExtension, uint32_t providerFlags);
@ -68,7 +68,7 @@ class SSLServerCertVerificationResult final
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIRUNNABLE
explicit SSLServerCertVerificationResult(TransportSecurityInfo* infoObject);
explicit SSLServerCertVerificationResult(CommonSocketControl* socketControl);
void Dispatch(nsTArray<nsTArray<uint8_t>>&& aBuiltChain,
nsTArray<nsTArray<uint8_t>>&& aPeerCertChain,
@ -82,7 +82,7 @@ class SSLServerCertVerificationResult final
private:
~SSLServerCertVerificationResult() = default;
const RefPtr<TransportSecurityInfo> mInfoObject;
const RefPtr<CommonSocketControl> mSocketControl;
nsTArray<nsTArray<uint8_t>> mBuiltChain;
nsTArray<nsTArray<uint8_t>> mPeerCertChain;
uint16_t mCertificateTransparencyStatus;

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -9,209 +9,87 @@
#include "CertVerifier.h" // For CertificateTransparencyInfo, EVStatus
#include "ScopedNSSTypes.h"
#include "certt.h"
#include "mozilla/Assertions.h"
#include "mozilla/BasePrincipal.h"
#include "mozilla/Mutex.h"
#include "mozilla/Components.h"
#include "mozilla/Maybe.h"
#include "mozilla/RefPtr.h"
#include "mozilla/ipc/TransportSecurityInfoUtils.h"
#include "mozpkix/pkixtypes.h"
#include "nsIObjectInputStream.h"
#include "nsIInterfaceRequestor.h"
#include "nsITransportSecurityInfo.h"
#include "nsNSSCertificate.h"
#include "nsIX509Cert.h"
#include "nsString.h"
namespace mozilla {
namespace psm {
class TransportSecurityInfo : public nsITransportSecurityInfo,
public nsIInterfaceRequestor {
protected:
virtual ~TransportSecurityInfo() = default;
// TransportSecurityInfo implements nsITransportSecurityInfo, which is a
// collection of attributes describing the outcome of a TLS handshake. It is
// constant - once created, it cannot be modified. It should probably not be
// instantiated directly, but rather accessed via
// nsITLSSocketControl.securityInfo.
class TransportSecurityInfo : public nsITransportSecurityInfo {
public:
TransportSecurityInfo();
TransportSecurityInfo(
uint32_t aSecurityState, PRErrorCode aErrorCode,
nsTArray<RefPtr<nsIX509Cert>>&& aFailedCertChain,
nsCOMPtr<nsIX509Cert>& aServerCert,
nsTArray<RefPtr<nsIX509Cert>>&& aSucceededCertChain,
Maybe<uint16_t> aCipherSuite, Maybe<nsCString> aKeaGroupName,
Maybe<nsCString> aSignatureSchemeName, Maybe<uint16_t> aProtocolVersion,
uint16_t aCertificateTransparencyStatus, Maybe<bool> aIsAcceptedEch,
Maybe<bool> aIsDelegatedCredential,
Maybe<OverridableErrorCategory> aOverridableErrorCategory,
bool aMadeOCSPRequests, bool aUsedPrivateDNS, Maybe<bool> aIsEV,
bool aNPNCompleted, const nsCString& aNegotiatedNPN, bool aResumed,
bool aIsBuiltCertChainRootBuiltInRoot, const nsCString& aPeerId);
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSITRANSPORTSECURITYINFO
NS_DECL_NSIINTERFACEREQUESTOR
static bool DeserializeFromIPC(IPC::MessageReader* aReader,
RefPtr<nsITransportSecurityInfo>* aResult);
static nsresult Read(const nsCString& aSerializedSecurityInfo,
nsITransportSecurityInfo** aResult);
void SetPreliminaryHandshakeInfo(const SSLChannelInfo& channelInfo,
const SSLCipherSuiteInfo& cipherInfo);
void SetSecurityState(uint32_t aState);
inline int32_t GetErrorCode() {
int32_t result;
mozilla::DebugOnly<nsresult> rv = GetErrorCode(&result);
MOZ_ASSERT(NS_SUCCEEDED(rv));
return result;
}
const nsACString& GetHostName() const {
MutexAutoLock lock(mMutex);
return mHostName;
}
void SetHostName(const char* host);
int32_t GetPort() const { return mPort; }
void SetPort(int32_t aPort);
const OriginAttributes& GetOriginAttributes() const {
MutexAutoLock lock(mMutex);
return mOriginAttributes;
}
const OriginAttributes& GetOriginAttributes(
MutexAutoLock& aProofOfLock) const {
return mOriginAttributes;
}
void SetOriginAttributes(const OriginAttributes& aOriginAttributes);
void SetCanceled(PRErrorCode errorCode);
bool IsCanceled();
void SetStatusErrorBits(const nsCOMPtr<nsIX509Cert>& cert,
OverridableErrorCategory overridableErrorCategory);
nsresult SetFailedCertChain(nsTArray<nsTArray<uint8_t>>&& certList);
void SetServerCert(const nsCOMPtr<nsIX509Cert>& aServerCert,
EVStatus aEVStatus);
nsresult SetSucceededCertChain(nsTArray<nsTArray<uint8_t>>&& certList);
bool HasServerCert() {
MutexAutoLock lock(mMutex);
return mServerCert != nullptr;
}
static uint16_t ConvertCertificateTransparencyInfoToStatus(
const mozilla::psm::CertificateTransparencyInfo& info);
// Use errorCode == 0 to indicate success;
virtual void SetCertVerificationResult(PRErrorCode errorCode){};
void SetCertificateTransparencyStatus(
uint16_t aCertificateTransparencyStatus) {
MutexAutoLock lock(mMutex);
mCertificateTransparencyStatus = aCertificateTransparencyStatus;
}
void SetMadeOCSPRequest(bool aMadeOCSPRequests) {
MutexAutoLock lock(mMutex);
mMadeOCSPRequests = aMadeOCSPRequests;
}
void SetUsedPrivateDNS(bool aUsedPrivateDNS) {
MutexAutoLock lock(mMutex);
mUsedPrivateDNS = aUsedPrivateDNS;
}
void SetResumed(bool aResumed);
Atomic<OverridableErrorCategory> mOverridableErrorCategory;
Atomic<bool> mIsEV;
Atomic<bool> mHasIsEVStatus;
Atomic<bool> mHaveCipherSuiteAndProtocol;
/* mHaveCertErrrorBits is relied on to determine whether or not a SPDY
connection is eligible for joining in NSSSocketControl::JoinConnection() */
Atomic<bool> mHaveCertErrorBits;
private:
// True if SetCanceled has been called (or if this was deserialized with a
// non-zero mErrorCode, which can only be the case if SetCanceled was called
// on the original TransportSecurityInfo).
Atomic<bool> mCanceled;
virtual ~TransportSecurityInfo() = default;
protected:
mutable ::mozilla::Mutex mMutex;
uint16_t mCipherSuite MOZ_GUARDED_BY(mMutex);
uint16_t mProtocolVersion MOZ_GUARDED_BY(mMutex);
uint16_t mCertificateTransparencyStatus MOZ_GUARDED_BY(mMutex);
nsCString mKeaGroup MOZ_GUARDED_BY(mMutex);
nsCString mSignatureSchemeName MOZ_GUARDED_BY(mMutex);
bool mIsAcceptedEch MOZ_GUARDED_BY(mMutex);
bool mIsDelegatedCredential MOZ_GUARDED_BY(mMutex);
bool mMadeOCSPRequests MOZ_GUARDED_BY(mMutex);
bool mUsedPrivateDNS MOZ_GUARDED_BY(mMutex);
nsCOMPtr<nsIInterfaceRequestor> mCallbacks MOZ_GUARDED_BY(mMutex);
nsTArray<RefPtr<nsIX509Cert>> mSucceededCertChain MOZ_GUARDED_BY(mMutex);
bool mNPNCompleted MOZ_GUARDED_BY(mMutex);
nsCString mNegotiatedNPN MOZ_GUARDED_BY(mMutex);
bool mResumed MOZ_GUARDED_BY(mMutex);
bool mIsBuiltCertChainRootBuiltInRoot MOZ_GUARDED_BY(mMutex);
nsCString mPeerId MOZ_GUARDED_BY(mMutex);
nsCString mHostName MOZ_GUARDED_BY(mMutex);
OriginAttributes mOriginAttributes MOZ_GUARDED_BY(mMutex);
private:
static nsresult ReadBoolAndSetAtomicFieldHelper(nsIObjectInputStream* stream,
Atomic<bool>& atomic) {
bool tmpBool;
nsresult rv = stream->ReadBoolean(&tmpBool);
if (NS_FAILED(rv)) {
return rv;
}
atomic = tmpBool;
return rv;
}
static nsresult ReadUint32AndSetAtomicFieldHelper(
nsIObjectInputStream* stream, Atomic<uint32_t>& atomic) {
uint32_t tmpInt;
nsresult rv = stream->Read32(&tmpInt);
if (NS_FAILED(rv)) {
return rv;
}
atomic = tmpInt;
return rv;
}
template <typename P>
static bool ReadParamAtomicHelper(IPC::MessageReader* aReader,
Atomic<P>& atomic) {
P tmpStore;
bool result = ReadParam(aReader, &tmpStore);
if (result == false) {
return result;
}
atomic = tmpStore;
return result;
}
Atomic<uint32_t> mSecurityState;
Atomic<PRErrorCode> mErrorCode;
Atomic<int32_t> mPort;
nsCOMPtr<nsIX509Cert> mServerCert MOZ_GUARDED_BY(mMutex);
/* Peer cert chain for failed connections (for error reporting) */
nsTArray<RefPtr<nsIX509Cert>> mFailedCertChain MOZ_GUARDED_BY(mMutex);
const uint32_t mSecurityState;
const PRErrorCode mErrorCode;
// Peer cert chain for failed connections.
const nsTArray<RefPtr<nsIX509Cert>> mFailedCertChain;
const nsCOMPtr<nsIX509Cert> mServerCert;
const nsTArray<RefPtr<nsIX509Cert>> mSucceededCertChain;
const mozilla::Maybe<uint16_t> mCipherSuite;
const mozilla::Maybe<nsCString> mKeaGroupName;
const mozilla::Maybe<nsCString> mSignatureSchemeName;
const mozilla::Maybe<uint16_t> mProtocolVersion;
const uint16_t mCertificateTransparencyStatus;
const mozilla::Maybe<bool> mIsAcceptedEch;
const mozilla::Maybe<bool> mIsDelegatedCredential;
const mozilla::Maybe<OverridableErrorCategory> mOverridableErrorCategory;
const bool mMadeOCSPRequests;
const bool mUsedPrivateDNS;
const mozilla::Maybe<bool> mIsEV;
const bool mNPNCompleted;
const nsCString mNegotiatedNPN;
const bool mResumed;
const bool mIsBuiltCertChainRootBuiltInRoot;
const nsCString mPeerId;
static nsresult ReadOldOverridableErrorBits(
nsIObjectInputStream* aStream,
OverridableErrorCategory& aOverridableErrorCategory);
static nsresult ReadSSLStatus(
nsIObjectInputStream* aStream, nsCOMPtr<nsIX509Cert>& aServerCert,
uint16_t& aCipherSuite, uint16_t& aProtocolVersion,
OverridableErrorCategory& aOverridableErrorCategory, bool& aIsEV,
bool& aHasIsEVStatus, bool& aHaveCipherSuiteAndProtocol,
bool& aHaveCertErrorBits, uint16_t& aCertificateTransparencyStatus,
nsCString& aKeaGroup, nsCString& aSignatureSchemeName,
Maybe<uint16_t>& aCipherSuite, Maybe<uint16_t>& aProtocolVersion,
Maybe<OverridableErrorCategory>& aOverridableErrorCategory,
Maybe<bool>& aIsEV, uint16_t& aCertificateTransparencyStatus,
Maybe<nsCString>& aKeaGroupName, Maybe<nsCString>& aSignatureSchemeName,
nsTArray<RefPtr<nsIX509Cert>>& aSucceededCertChain);
// This function is used to read the binary that are serialized

Просмотреть файл

@ -95,8 +95,6 @@ Classes = [
'cid': '{16786594-0296-4471-8096-8f84497ca428}',
'contract_ids': ['@mozilla.org/security/transportsecurityinfo;1'],
'type': 'mozilla::psm::TransportSecurityInfo',
'legacy_constructor':
'mozilla::psm::NSSConstructor<mozilla::psm::TransportSecurityInfo>',
},
{
'cid': '{16955eee-6c48-4152-9309-c42a465138a1}',

Просмотреть файл

@ -7,8 +7,9 @@
#include "nsISupports.idl"
interface nsIInterfaceRequestor;
interface nsIX509Cert;
interface nsITlsHandshakeCallbackListener;
interface nsITransportSecurityInfo;
interface nsIX509Cert;
%{C++
#include "nsStringFwd.h"
@ -16,10 +17,12 @@ interface nsITlsHandshakeCallbackListener;
%}
[ref] native nsCStringTArrayRef(nsTArray<nsCString>);
// An interface describing an object that controls and holds information about
// a TLS handshake.
// NB: The implementations of this interface may only be used on the socket
// thread (except for asyncGetSecurityInfo);
[scriptable, builtinclass, uuid(418265c8-654e-4fbb-ba62-4eed27de1f03)]
interface nsITLSSocketControl : nsISupports {
attribute nsIInterfaceRequestor notificationCallbacks;
void proxyStartSSL();
void StartTLS();
@ -92,11 +95,6 @@ interface nsITLSSocketControl : nsISupports {
*/
readonly attribute uint32_t providerFlags;
/*
* The original TLS flags from the socket provider.
*/
readonly attribute uint32_t providerTlsFlags;
/* These values are defined by TLS. */
const short SSL_VERSION_3 = 0x0300;
const short TLS_VERSION_1 = 0x0301;
@ -162,4 +160,23 @@ interface nsITLSSocketControl : nsISupports {
[noscript] void disableEarlyData();
[noscript] void setHandshakeCallbackListener(in nsITlsHandshakeCallbackListener callback);
/**
* The id used to uniquely identify the connection to the peer.
*/
readonly attribute ACString peerId;
/**
* The securityInfo of the TLS handshake.
*/
readonly attribute nsITransportSecurityInfo securityInfo;
/**
* Asynchronously obtain the securityInfo of the TLS handshake. Resolves
* with an nsITransportSecurityInfo. This should probably only be used in
* tests, where JS running on the main thread cannot access any of the
* other fields of nsITLSSocketControl.
*/
[implicit_jscontext, must_use]
Promise asyncGetSecurityInfo();
};

Просмотреть файл

@ -128,7 +128,7 @@ interface nsITransportSecurityInfo : nsISupports {
/**
* True iff the succeededCertChain is built in root.
*/
attribute boolean isBuiltCertChainRootBuiltInRoot;
readonly attribute boolean isBuiltCertChainRootBuiltInRoot;
/**
* The id used to uniquely identify the connection to the peer.

Просмотреть файл

@ -699,12 +699,15 @@ nsCString getSignatureName(uint32_t aSignatureScheme) {
return signatureName;
}
// call with shutdown prevention lock held
static void PreliminaryHandshakeDone(PRFileDesc* fd) {
NSSSocketControl* infoObject = (NSSSocketControl*)fd->higher->secret;
if (!infoObject) {
NSSSocketControl* socketControl = (NSSSocketControl*)fd->higher->secret;
if (!socketControl) {
return;
}
if (socketControl->IsPreliminaryHandshakeDone()) {
return;
}
SSLChannelInfo channelInfo;
if (SSL_GetChannelInfo(fd, &channelInfo, sizeof(channelInfo)) != SECSuccess) {
return;
@ -714,17 +717,12 @@ static void PreliminaryHandshakeDone(PRFileDesc* fd) {
sizeof(cipherInfo)) != SECSuccess) {
return;
}
infoObject->SetPreliminaryHandshakeInfo(channelInfo, cipherInfo);
infoObject->SetSSLVersionUsed(channelInfo.protocolVersion);
infoObject->SetEarlyDataAccepted(channelInfo.earlyDataAccepted);
infoObject->SetKEAUsed(channelInfo.keaType);
infoObject->SetKEAKeyBits(channelInfo.keaKeyBits);
infoObject->SetMACAlgorithmUsed(cipherInfo.macAlgorithm);
// Don't update NPN details on renegotiation.
if (infoObject->IsPreliminaryHandshakeDone()) {
return;
}
socketControl->SetPreliminaryHandshakeInfo(channelInfo, cipherInfo);
socketControl->SetSSLVersionUsed(channelInfo.protocolVersion);
socketControl->SetEarlyDataAccepted(channelInfo.earlyDataAccepted);
socketControl->SetKEAUsed(channelInfo.keaType);
socketControl->SetKEAKeyBits(channelInfo.keaKeyBits);
socketControl->SetMACAlgorithmUsed(cipherInfo.macAlgorithm);
// Get the NPN value.
SSLNextProtoState state;
@ -736,17 +734,17 @@ static void PreliminaryHandshakeDone(PRFileDesc* fd) {
SECSuccess) {
if (state == SSL_NEXT_PROTO_NEGOTIATED ||
state == SSL_NEXT_PROTO_SELECTED) {
infoObject->SetNegotiatedNPN(BitwiseCast<char*, unsigned char*>(npnbuf),
npnlen);
socketControl->SetNegotiatedNPN(
BitwiseCast<char*, unsigned char*>(npnbuf), npnlen);
} else {
infoObject->SetNegotiatedNPN(nullptr, 0);
socketControl->SetNegotiatedNPN(nullptr, 0);
}
mozilla::Telemetry::Accumulate(Telemetry::SSL_NPN_TYPE, state);
} else {
infoObject->SetNegotiatedNPN(nullptr, 0);
socketControl->SetNegotiatedNPN(nullptr, 0);
}
infoObject->SetPreliminaryHandshakeDone();
socketControl->SetPreliminaryHandshakeDone();
}
SECStatus CanFalseStartCallback(PRFileDesc* fd, void* client_data,
@ -1059,8 +1057,6 @@ void HandshakeCallback(PRFileDesc* fd, void* client_data) {
: Telemetry::SSL_KEY_EXCHANGE_ALGORITHM_RESUMED,
channelInfo.keaType);
MOZ_ASSERT(infoObject->GetKEAUsed() == channelInfo.keaType);
if (infoObject->IsFullHandshake()) {
switch (channelInfo.keaType) {
case ssl_kea_rsa:
@ -1148,13 +1144,8 @@ void HandshakeCallback(PRFileDesc* fd, void* client_data) {
infoObject->RebuildCertificateInfoFromSSLTokenCache();
}
nsITransportSecurityInfo::OverridableErrorCategory overridableErrorCategory;
// This returns NS_OK, so don't even bother checking the return value.
Unused << infoObject->GetOverridableErrorCategory(&overridableErrorCategory);
// If we're here, the TLS handshake has succeeded. Thus if any of these
// booleans are true, the user has added an override for a certificate error.
if (overridableErrorCategory !=
nsITransportSecurityInfo::OverridableErrorCategory::ERROR_UNSET) {
// Check if the user has added an override for a certificate error.
if (infoObject->HasUserOverriddenCertificateError()) {
state |= nsIWebProgressListener::STATE_CERT_USER_OVERRIDDEN;
}

Просмотреть файл

@ -578,21 +578,26 @@ static void reportHandshakeResult(int32_t bytesTransferred, bool wasReading,
Telemetry::Accumulate(Telemetry::SSL_HANDSHAKE_RESULT, bucket);
if (bucket == 0) {
nsCOMPtr<nsITransportSecurityInfo> securityInfo;
if (NS_FAILED(socketInfo->GetSecurityInfo(getter_AddRefs(securityInfo))) ||
!securityInfo) {
return;
}
// Web Privacy Telemetry for successful connections.
bool success = true;
bool usedPrivateDNS = false;
success &= socketInfo->GetUsedPrivateDNS(&usedPrivateDNS) == NS_OK;
success &= securityInfo->GetUsedPrivateDNS(&usedPrivateDNS) == NS_OK;
bool madeOCSPRequest = false;
success &= socketInfo->GetMadeOCSPRequests(&madeOCSPRequest) == NS_OK;
success &= securityInfo->GetMadeOCSPRequests(&madeOCSPRequest) == NS_OK;
uint16_t protocolVersion = 0;
success &= socketInfo->GetProtocolVersion(&protocolVersion) == NS_OK;
success &= securityInfo->GetProtocolVersion(&protocolVersion) == NS_OK;
bool usedTLS13 = protocolVersion == 4;
bool usedECH = false;
success &= socketInfo->GetIsAcceptedEch(&usedECH) == NS_OK;
success &= securityInfo->GetIsAcceptedEch(&usedECH) == NS_OK;
// As bucket is 0 we are reporting the results of a sucessful connection
// and so TransportSecurityInfo should be populated. However, this isn't
@ -1553,13 +1558,12 @@ nsresult nsSSLIOLayerAddToSocket(int32_t family, const char* host, int32_t port,
}
NSSSocketControl* infoObject =
new NSSSocketControl(*sharedState, providerFlags, providerTlsFlags);
new NSSSocketControl(nsDependentCString(host), port, *sharedState,
providerFlags, providerTlsFlags);
if (!infoObject) return NS_ERROR_FAILURE;
NS_ADDREF(infoObject);
infoObject->SetForSTARTTLS(forSTARTTLS);
infoObject->SetHostName(host);
infoObject->SetPort(port);
infoObject->SetOriginAttributes(originAttributes);
if (allocatedState) {
infoObject->SetSharedOwningReference(allocatedState);

Просмотреть файл

@ -11,7 +11,6 @@
#include "OSReauthenticator.h"
#include "PKCS11ModuleDB.h"
#include "SecretDecoderRing.h"
#include "TransportSecurityInfo.h"
#include "mozilla/MacroArgs.h"
#include "mozilla/ModuleUtils.h"
#include "mozilla/SyncRunnable.h"
@ -100,7 +99,6 @@ IMPL(nsCertTree, nullptr)
IMPL(nsCryptoHash, nullptr, ProcessRestriction::AnyProcess)
IMPL(ContentSignatureVerifier, nullptr)
IMPL(nsRandomGenerator, nullptr, ProcessRestriction::AnyProcess)
IMPL(TransportSecurityInfo, nullptr, ProcessRestriction::AnyProcess)
IMPL(OSKeyStore, nullptr, ProcessRestriction::ParentProcessOnly,
ThreadRestriction::MainThreadOnly)
IMPL(OSReauthenticator, nullptr, ProcessRestriction::ParentProcessOnly,

Просмотреть файл

@ -617,7 +617,7 @@ async function asyncConnectTo(
return connection.go();
}
return connectTo(aHost).then(function(conn) {
return connectTo(aHost).then(async function(conn) {
info("handling " + aHost);
let expectedNSResult =
aExpectedResult == PRErrorCodeSuccess
@ -630,9 +630,7 @@ async function asyncConnectTo(
);
if (aWithSecurityInfo) {
aWithSecurityInfo(
conn.transport.tlsSocketControl.QueryInterface(
Ci.nsITransportSecurityInfo
)
await conn.transport.tlsSocketControl.asyncGetSecurityInfo()
);
}
});