зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1577643 - Implement a security info class for the quic transport. r=keeler
Differential Revision: https://phabricator.services.mozilla.com/D44073 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
5f2cea9512
Коммит
1d40d354bd
|
@ -0,0 +1,104 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "QuicSocketControl.h"
|
||||
#include "SharedCertVerifier.h"
|
||||
#include "nsNSSComponent.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "sslt.h"
|
||||
#include "ssl.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED(QuicSocketControl, TransportSecurityInfo,
|
||||
nsISSLSocketControl, QuicSocketControl)
|
||||
|
||||
QuicSocketControl::QuicSocketControl(uint32_t aProviderFlags)
|
||||
: CommonSocketControl(aProviderFlags) {}
|
||||
|
||||
void QuicSocketControl::SetCertVerificationResult(PRErrorCode errorCode) {
|
||||
if (errorCode) {
|
||||
mFailedVerification = true;
|
||||
SetCanceled(errorCode);
|
||||
}
|
||||
|
||||
if (OnSocketThread()) {
|
||||
CallAuthenticated();
|
||||
} else {
|
||||
DebugOnly<nsresult> rv = gSocketTransportService->Dispatch(
|
||||
NewRunnableMethod("QuicSocketControl::CallAuthenticated", this,
|
||||
&QuicSocketControl::CallAuthenticated),
|
||||
NS_DISPATCH_NORMAL);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
QuicSocketControl::GetSSLVersionOffered(int16_t* aSSLVersionOffered) {
|
||||
*aSSLVersionOffered = nsISSLSocketControl::TLS_VERSION_1_3;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void QuicSocketControl::CallAuthenticated() {
|
||||
// // Will be added when Http3 lands
|
||||
/* if (mHttp3Session) {
|
||||
RefPtr<Http3Session> http3Session = do_QueryReferent(mHttp3Session);
|
||||
http3Session->Authenticated(GetErrorCode());
|
||||
}
|
||||
mHttp3Session = nullptr;*/
|
||||
}
|
||||
|
||||
// Will be added when Http3 lands
|
||||
// void QuicSocketControl::SetAuthenticationCallback(Http3Session
|
||||
// *aHttp3Session) {
|
||||
// mHttp3Session = do_GetWeakReference(
|
||||
// static_cast<nsISupportsWeakReference*>(aHttp3Session));
|
||||
//}
|
||||
|
||||
void QuicSocketControl::HandshakeCompleted() {
|
||||
psm::RememberCertErrorsTable::GetInstance().LookupCertErrorBits(this);
|
||||
|
||||
uint32_t state = nsIWebProgressListener::STATE_IS_SECURE;
|
||||
|
||||
bool distrustImminent;
|
||||
nsresult srv =
|
||||
IsCertificateDistrustImminent(mSucceededCertChain, distrustImminent);
|
||||
if (NS_SUCCEEDED(srv) && distrustImminent) {
|
||||
state |= nsIWebProgressListener::STATE_CERT_DISTRUST_IMMINENT;
|
||||
}
|
||||
|
||||
// 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 (mIsDomainMismatch || mIsUntrusted || mIsNotValidAtThisTime) {
|
||||
state |= nsIWebProgressListener::STATE_CERT_USER_OVERRIDDEN;
|
||||
}
|
||||
|
||||
SetSecurityState(state);
|
||||
mHandshakeCompleted = true;
|
||||
}
|
||||
|
||||
void QuicSocketControl::SetNegotiatedNPN(const nsACString& aValue) {
|
||||
mNegotiatedNPN = aValue;
|
||||
mNPNCompleted = true;
|
||||
}
|
||||
|
||||
void QuicSocketControl::SetInfo(uint16_t aCipherSuite,
|
||||
uint16_t aProtocolVersion,
|
||||
uint16_t aKeaGroup,
|
||||
uint16_t aSignatureScheme) {
|
||||
SSLCipherSuiteInfo cipherInfo;
|
||||
if (SSL_GetCipherSuiteInfo(aCipherSuite, &cipherInfo, sizeof cipherInfo) ==
|
||||
SECSuccess) {
|
||||
mHaveCipherSuiteAndProtocol = true;
|
||||
mCipherSuite = aCipherSuite;
|
||||
mProtocolVersion = aProtocolVersion & 0xFF;
|
||||
mKeaGroup = getKeaGroupName(aKeaGroup);
|
||||
mSignatureSchemeName = getSignatureName(aSignatureScheme);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,59 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef QuicSocketControl_h
|
||||
#define QuicSocketControl_h
|
||||
|
||||
#include "CommonSocketControl.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
// Will be added when Http3 lands.
|
||||
// class Http3Session;
|
||||
|
||||
// IID for the QuicSocketControl interface
|
||||
#define NS_QUICSOCKETCONTROL_IID \
|
||||
{ \
|
||||
0xdbc67fd0, 0x1ac6, 0x457b, { \
|
||||
0x91, 0x4e, 0x4c, 0x86, 0x60, 0xff, 0x00, 0x69 \
|
||||
} \
|
||||
}
|
||||
|
||||
class QuicSocketControl final : public CommonSocketControl {
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_QUICSOCKETCONTROL_IID)
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
NS_IMETHOD GetSSLVersionOffered(int16_t* aSSLVersionOffered) override;
|
||||
|
||||
explicit QuicSocketControl(uint32_t providerFlags);
|
||||
|
||||
void SetNegotiatedNPN(const nsACString& aValue);
|
||||
void SetInfo(uint16_t aCipherSuite, uint16_t aProtocolVersion,
|
||||
uint16_t aKeaGroup, uint16_t aSignatureScheme);
|
||||
|
||||
// Will be added when Http3 lands.
|
||||
// void SetAuthenticationCallback(Http3Session *aHttp3Session);
|
||||
void CallAuthenticated();
|
||||
|
||||
void HandshakeCompleted();
|
||||
void SetCertVerificationResult(PRErrorCode errorCode) override;
|
||||
|
||||
private:
|
||||
~QuicSocketControl() = default;
|
||||
|
||||
// For Authentication done callback.
|
||||
nsWeakPtr mHttp3Session;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(QuicSocketControl, NS_QUICSOCKETCONTROL_IID)
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // QuicSocketControl_h
|
|
@ -108,6 +108,7 @@ UNIFIED_SOURCES += [
|
|||
'NullHttpChannel.cpp',
|
||||
'NullHttpTransaction.cpp',
|
||||
'ParentChannelListener.cpp',
|
||||
'QuicSocketControl.cpp',
|
||||
'TunnelUtils.cpp',
|
||||
]
|
||||
|
||||
|
|
|
@ -0,0 +1,277 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "CommonSocketControl.h"
|
||||
#include "SharedCertVerifier.h"
|
||||
#include "nsNSSComponent.h"
|
||||
#include "sslt.h"
|
||||
#include "ssl.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED(CommonSocketControl, TransportSecurityInfo,
|
||||
nsISSLSocketControl)
|
||||
|
||||
CommonSocketControl::CommonSocketControl(uint32_t aProviderFlags)
|
||||
: mNPNCompleted(false),
|
||||
mHandshakeCompleted(false),
|
||||
mJoined(false),
|
||||
mSentClientCert(false),
|
||||
mFailedVerification(false),
|
||||
mResumed(false),
|
||||
mSSLVersionUsed(nsISSLSocketControl::SSL_VERSION_UNKNOWN),
|
||||
mProviderFlags(aProviderFlags) {}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CommonSocketControl::GetNotificationCallbacks(
|
||||
nsIInterfaceRequestor** aCallbacks) {
|
||||
*aCallbacks = mCallbacks;
|
||||
NS_IF_ADDREF(*aCallbacks);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CommonSocketControl::SetNotificationCallbacks(
|
||||
nsIInterfaceRequestor* aCallbacks) {
|
||||
mCallbacks = aCallbacks;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CommonSocketControl::ProxyStartSSL(void) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CommonSocketControl::StartTLS(void) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CommonSocketControl::SetNPNList(nsTArray<nsCString> & aNPNList) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CommonSocketControl::GetNegotiatedNPN(nsACString& aNegotiatedNPN) {
|
||||
if (!mNPNCompleted) {
|
||||
return NS_ERROR_NOT_CONNECTED;
|
||||
}
|
||||
|
||||
aNegotiatedNPN = mNegotiatedNPN;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CommonSocketControl::GetAlpnEarlySelection(nsACString& _retval) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CommonSocketControl::GetEarlyDataAccepted(bool *aEarlyDataAccepted) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CommonSocketControl::DriveHandshake(void) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CommonSocketControl::JoinConnection(const nsACString& npnProtocol,
|
||||
const nsACString& hostname, int32_t port,
|
||||
bool* _retval) {
|
||||
nsresult rv = TestJoinConnection(npnProtocol, hostname, port, _retval);
|
||||
if (NS_SUCCEEDED(rv) && *_retval) {
|
||||
// All tests pass - this is joinable
|
||||
mJoined = true;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CommonSocketControl::TestJoinConnection(const nsACString& npnProtocol,
|
||||
const nsACString& hostname,
|
||||
int32_t port, bool* _retval) {
|
||||
*_retval = false;
|
||||
|
||||
// Different ports may not be joined together
|
||||
if (port != GetPort()) 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
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CommonSocketControl::IsAcceptableForHost(const nsACString& hostname,
|
||||
bool* _retval) {
|
||||
NS_ENSURE_ARG(_retval);
|
||||
|
||||
*_retval = false;
|
||||
|
||||
// If this is the same hostname then the certicate status does not
|
||||
// need to be considered. They are joinable.
|
||||
if (hostname.Equals(GetHostName())) {
|
||||
*_retval = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Before checking the server certificate we need to make sure the
|
||||
// handshake has completed.
|
||||
if (!mHandshakeCompleted || !HasServerCert()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// 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) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// If the connection is using client certificates then do not join
|
||||
// because the user decides on whether to send client certs to hosts on a
|
||||
// per-domain basis.
|
||||
if (mSentClientCert) return NS_OK;
|
||||
|
||||
// Ensure that the server certificate covers the hostname that would
|
||||
// like to join this connection
|
||||
|
||||
UniqueCERTCertificate nssCert;
|
||||
|
||||
nsCOMPtr<nsIX509Cert> cert;
|
||||
if (NS_FAILED(GetServerCert(getter_AddRefs(cert)))) {
|
||||
return NS_OK;
|
||||
}
|
||||
if (cert) {
|
||||
nssCert.reset(cert->GetCert());
|
||||
}
|
||||
|
||||
if (!nssCert) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Attempt to verify the joinee's certificate using the joining hostname.
|
||||
// This ensures that any hostname-specific verification logic (e.g. key
|
||||
// pinning) is satisfied by the joinee's certificate chain.
|
||||
// This verification only uses local information; since we're on the network
|
||||
// thread, we would be blocking on ourselves if we attempted any network i/o.
|
||||
// TODO(bug 1056935): The certificate chain built by this verification may be
|
||||
// different than the certificate chain originally built during the joined
|
||||
// connection's TLS handshake. Consequently, we may report a wrong and/or
|
||||
// misleading certificate chain for HTTP transactions coalesced onto this
|
||||
// connection. This may become problematic in the future. For example,
|
||||
// if/when we begin relying on intermediate certificates being stored in the
|
||||
// securityInfo of a cached HTTPS response, that cached certificate chain may
|
||||
// actually be the wrong chain. We should consider having JoinConnection
|
||||
// return the certificate chain built here, so that the calling Necko code
|
||||
// can associate the correct certificate chain with the HTTP transactions it
|
||||
// is trying to join onto this connection.
|
||||
RefPtr<psm::SharedCertVerifier> certVerifier(psm::GetDefaultCertVerifier());
|
||||
if (!certVerifier) {
|
||||
return NS_OK;
|
||||
}
|
||||
psm::CertVerifier::Flags flags = psm::CertVerifier::FLAG_LOCAL_ONLY;
|
||||
UniqueCERTCertList unusedBuiltChain;
|
||||
mozilla::pkix::Result result = certVerifier->VerifySSLServerCert(
|
||||
nssCert,
|
||||
Maybe<nsTArray<uint8_t>>(), // stapledOCSPResponse
|
||||
Maybe<nsTArray<uint8_t>>(), // sctsFromTLSExtension
|
||||
mozilla::pkix::Now(),
|
||||
nullptr, // pinarg
|
||||
hostname, unusedBuiltChain,
|
||||
false, // save intermediates
|
||||
flags);
|
||||
if (result != mozilla::pkix::Success) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// All tests pass
|
||||
*_retval = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CommonSocketControl::GetKEAUsed(int16_t *aKEAUsed) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CommonSocketControl::GetKEAKeyBits(uint32_t *aKEAKeyBits) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CommonSocketControl::GetProviderFlags(uint32_t* aProviderFlags) {
|
||||
*aProviderFlags = mProviderFlags;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CommonSocketControl::GetProviderTlsFlags(uint32_t *aProviderTlsFlags) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CommonSocketControl::GetSSLVersionUsed(int16_t* aSSLVersionUsed) {
|
||||
*aSSLVersionUsed = mSSLVersionUsed;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CommonSocketControl::GetSSLVersionOffered(int16_t* aSSLVersionOffered) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CommonSocketControl::GetMACAlgorithmUsed(int16_t *aMACAlgorithmUsed) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
bool CommonSocketControl::GetDenyClientCert() { return true; }
|
||||
|
||||
void CommonSocketControl::SetDenyClientCert(bool aDenyClientCert) {}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CommonSocketControl::GetClientCert(nsIX509Cert **aClientCert) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CommonSocketControl::SetClientCert(nsIX509Cert *aClientCert) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CommonSocketControl::GetClientCertSent(bool* arg) {
|
||||
*arg = mSentClientCert;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CommonSocketControl::GetFailedVerification(bool* arg) {
|
||||
*arg = mFailedVerification;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CommonSocketControl::GetEsniTxt(nsACString& aEsniTxt) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CommonSocketControl::SetEsniTxt(const nsACString& aEsniTxt) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CommonSocketControl::GetResumed(bool* aResumed) {
|
||||
*aResumed = mResumed;
|
||||
return NS_OK;
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef CommonSocketControl_h
|
||||
#define CommonSocketControl_h
|
||||
|
||||
#include "nsISSLSocketControl.h"
|
||||
#include "TransportSecurityInfo.h"
|
||||
|
||||
class CommonSocketControl : public mozilla::psm::TransportSecurityInfo,
|
||||
public nsISSLSocketControl {
|
||||
public:
|
||||
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSISSLSOCKETCONTROL
|
||||
|
||||
explicit CommonSocketControl(uint32_t providerFlags);
|
||||
|
||||
uint32_t GetProviderFlags() const { return mProviderFlags; }
|
||||
void SetSSLVersionUsed(int16_t version) { mSSLVersionUsed = version; }
|
||||
void SetResumed(bool aResumed) { mResumed = aResumed; }
|
||||
|
||||
protected:
|
||||
~CommonSocketControl() = default;
|
||||
nsCString mNegotiatedNPN;
|
||||
bool mNPNCompleted;
|
||||
bool mHandshakeCompleted;
|
||||
bool mJoined;
|
||||
bool mSentClientCert;
|
||||
bool mFailedVerification;
|
||||
mozilla::Atomic<bool, mozilla::Relaxed> mResumed;
|
||||
uint16_t mSSLVersionUsed;
|
||||
uint32_t mProviderFlags;
|
||||
};
|
||||
|
||||
#endif // CommonSocketControl_h
|
|
@ -116,6 +116,7 @@ class TransportSecurityInfo : public nsITransportSecurityInfo,
|
|||
|
||||
protected:
|
||||
nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
|
||||
nsCOMPtr<nsIX509CertList> mSucceededCertChain;
|
||||
|
||||
private:
|
||||
uint32_t mSecurityState;
|
||||
|
@ -127,7 +128,6 @@ class TransportSecurityInfo : public nsITransportSecurityInfo,
|
|||
OriginAttributes mOriginAttributes;
|
||||
|
||||
nsCOMPtr<nsIX509Cert> mServerCert;
|
||||
nsCOMPtr<nsIX509CertList> mSucceededCertChain;
|
||||
|
||||
/* Peer cert chain for failed connections (for error reporting) */
|
||||
nsCOMPtr<nsIX509CertList> mFailedCertChain;
|
||||
|
|
|
@ -59,6 +59,7 @@ EXTRA_JS_MODULES.psm += [
|
|||
]
|
||||
|
||||
EXPORTS += [
|
||||
'CommonSocketControl.h',
|
||||
'CryptoTask.h',
|
||||
'EnterpriseRoots.h',
|
||||
'nsClientAuthRemember.h',
|
||||
|
@ -74,6 +75,7 @@ EXPORTS += [
|
|||
'RootCertificateTelemetryUtils.h',
|
||||
'ScopedNSSTypes.h',
|
||||
'SharedCertVerifier.h',
|
||||
'TransportSecurityInfo.h',
|
||||
]
|
||||
|
||||
EXPORTS.mozilla += [
|
||||
|
@ -92,6 +94,7 @@ EXPORTS.ipc += [
|
|||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'CommonSocketControl.cpp',
|
||||
'ContentSignatureVerifier.cpp',
|
||||
'CryptoTask.cpp',
|
||||
'CSTrustDomain.cpp',
|
||||
|
|
|
@ -594,7 +594,7 @@ char* PK11PasswordPrompt(PK11SlotInfo* slot, PRBool /*retry*/, void* arg) {
|
|||
return runnable->mResult;
|
||||
}
|
||||
|
||||
static nsCString getKeaGroupName(uint32_t aKeaGroup) {
|
||||
nsCString getKeaGroupName(uint32_t aKeaGroup) {
|
||||
nsCString groupName;
|
||||
switch (aKeaGroup) {
|
||||
case ssl_grp_ec_secp256r1:
|
||||
|
@ -631,7 +631,7 @@ static nsCString getKeaGroupName(uint32_t aKeaGroup) {
|
|||
return groupName;
|
||||
}
|
||||
|
||||
static nsCString getSignatureName(uint32_t aSignatureScheme) {
|
||||
nsCString getSignatureName(uint32_t aSignatureScheme) {
|
||||
nsCString signatureName;
|
||||
switch (aSignatureScheme) {
|
||||
case ssl_sig_none:
|
||||
|
@ -1107,7 +1107,7 @@ static void RebuildVerifiedCertificateInformation(PRFileDesc* fd,
|
|||
}
|
||||
}
|
||||
|
||||
static nsresult IsCertificateDistrustImminent(nsIX509CertList* aCertList,
|
||||
nsresult IsCertificateDistrustImminent(nsIX509CertList* aCertList,
|
||||
/* out */ bool& isDistrusted) {
|
||||
if (!aCertList) {
|
||||
return NS_ERROR_INVALID_POINTER;
|
||||
|
|
|
@ -22,6 +22,7 @@ using mozilla::TimeDuration;
|
|||
using mozilla::Vector;
|
||||
|
||||
class nsILoadGroup;
|
||||
class nsIX509CertList;
|
||||
|
||||
char* PK11PasswordPrompt(PK11SlotInfo* slot, PRBool retry, void* arg);
|
||||
|
||||
|
@ -35,4 +36,9 @@ mozilla::pkix::Result DoOCSPRequest(
|
|||
size_t ocspRequestLength, TimeDuration timeout,
|
||||
/*out*/ Vector<uint8_t>& result);
|
||||
|
||||
nsCString getKeaGroupName(uint32_t aKeaGroup);
|
||||
nsCString getSignatureName(uint32_t aSignatureScheme);
|
||||
nsresult IsCertificateDistrustImminent(nsIX509CertList* aCertList,
|
||||
/* out */ bool& isDistrusted);
|
||||
|
||||
#endif // nsNSSCallbacks_h
|
||||
|
|
|
@ -111,32 +111,25 @@ extern LazyLogModule gPIPNSSLog;
|
|||
|
||||
nsNSSSocketInfo::nsNSSSocketInfo(SharedSSLState& aState, uint32_t providerFlags,
|
||||
uint32_t providerTlsFlags)
|
||||
: mFd(nullptr),
|
||||
: CommonSocketControl(providerFlags),
|
||||
mFd(nullptr),
|
||||
mCertVerificationState(before_cert_verification),
|
||||
mSharedState(aState),
|
||||
mForSTARTTLS(false),
|
||||
mHandshakePending(true),
|
||||
mPreliminaryHandshakeDone(false),
|
||||
mNPNCompleted(false),
|
||||
mEarlyDataAccepted(false),
|
||||
mDenyClientCert(false),
|
||||
mFalseStartCallbackCalled(false),
|
||||
mFalseStarted(false),
|
||||
mIsFullHandshake(false),
|
||||
mHandshakeCompleted(false),
|
||||
mJoined(false),
|
||||
mSentClientCert(false),
|
||||
mNotedTimeUntilReady(false),
|
||||
mFailedVerification(false),
|
||||
mResumed(false),
|
||||
mIsShortWritePending(false),
|
||||
mShortWritePendingByte(0),
|
||||
mShortWriteOriginalAmount(-1),
|
||||
mKEAUsed(nsISSLSocketControl::KEY_EXCHANGE_UNKNOWN),
|
||||
mKEAKeyBits(0),
|
||||
mSSLVersionUsed(nsISSLSocketControl::SSL_VERSION_UNKNOWN),
|
||||
mMACAlgorithmUsed(nsISSLSocketControl::SSL_MAC_UNKNOWN),
|
||||
mProviderFlags(providerFlags),
|
||||
mProviderTlsFlags(providerTlsFlags),
|
||||
mSocketCreationTimestamp(TimeStamp::Now()),
|
||||
mPlaintextBytesRead(0),
|
||||
|
@ -150,12 +143,6 @@ nsNSSSocketInfo::~nsNSSSocketInfo() {}
|
|||
NS_IMPL_ISUPPORTS_INHERITED(nsNSSSocketInfo, TransportSecurityInfo,
|
||||
nsISSLSocketControl)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNSSSocketInfo::GetProviderFlags(uint32_t* aProviderFlags) {
|
||||
*aProviderFlags = mProviderFlags;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNSSSocketInfo::GetProviderTlsFlags(uint32_t* aProviderTlsFlags) {
|
||||
*aProviderTlsFlags = mProviderTlsFlags;
|
||||
|
@ -174,12 +161,6 @@ nsNSSSocketInfo::GetKEAKeyBits(uint32_t* aKeyBits) {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNSSSocketInfo::GetSSLVersionUsed(int16_t* aSSLVersionUsed) {
|
||||
*aSSLVersionUsed = mSSLVersionUsed;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNSSSocketInfo::GetSSLVersionOffered(int16_t* aSSLVersionOffered) {
|
||||
*aSSLVersionOffered = mTLSVersionRange.max;
|
||||
|
@ -206,31 +187,6 @@ nsNSSSocketInfo::SetClientCert(nsIX509Cert* aClientCert) {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNSSSocketInfo::GetClientCertSent(bool* arg) {
|
||||
*arg = mSentClientCert;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNSSSocketInfo::GetFailedVerification(bool* arg) {
|
||||
*arg = mFailedVerification;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNSSSocketInfo::GetNotificationCallbacks(nsIInterfaceRequestor** aCallbacks) {
|
||||
nsCOMPtr<nsIInterfaceRequestor> ir(mCallbacks);
|
||||
ir.forget(aCallbacks);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNSSSocketInfo::SetNotificationCallbacks(nsIInterfaceRequestor* aCallbacks) {
|
||||
mCallbacks = aCallbacks;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void nsNSSSocketInfo::NoteTimeUntilReady() {
|
||||
if (mNotedTimeUntilReady) return;
|
||||
|
||||
|
@ -302,14 +258,6 @@ void nsNSSSocketInfo::SetNegotiatedNPN(const char* value, uint32_t length) {
|
|||
mNPNCompleted = true;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNSSSocketInfo::GetNegotiatedNPN(nsACString& aNegotiatedNPN) {
|
||||
if (!mNPNCompleted) return NS_ERROR_NOT_CONNECTED;
|
||||
|
||||
aNegotiatedNPN = mNegotiatedNPN;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNSSSocketInfo::GetAlpnEarlySelection(nsACString& aAlpnSelected) {
|
||||
aAlpnSelected.Truncate();
|
||||
|
@ -348,14 +296,6 @@ void nsNSSSocketInfo::SetEarlyDataAccepted(bool aAccepted) {
|
|||
mEarlyDataAccepted = aAccepted;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNSSSocketInfo::GetResumed(bool* aResumed) {
|
||||
*aResumed = mResumed;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void nsNSSSocketInfo::SetResumed(bool aResumed) { mResumed = aResumed; }
|
||||
|
||||
bool nsNSSSocketInfo::GetDenyClientCert() { return mDenyClientCert; }
|
||||
|
||||
void nsNSSSocketInfo::SetDenyClientCert(bool aDenyClientCert) {
|
||||
|
@ -386,123 +326,6 @@ nsNSSSocketInfo::DriveHandshake() {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNSSSocketInfo::IsAcceptableForHost(const nsACString& hostname,
|
||||
bool* _retval) {
|
||||
NS_ENSURE_ARG(_retval);
|
||||
|
||||
*_retval = false;
|
||||
|
||||
// If this is the same hostname then the certicate status does not
|
||||
// need to be considered. They are joinable.
|
||||
if (hostname.Equals(GetHostName())) {
|
||||
*_retval = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Before checking the server certificate we need to make sure the
|
||||
// handshake has completed.
|
||||
if (!mHandshakeCompleted || !HasServerCert()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// 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) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// If the connection is using client certificates then do not join
|
||||
// because the user decides on whether to send client certs to hosts on a
|
||||
// per-domain basis.
|
||||
if (mSentClientCert) return NS_OK;
|
||||
|
||||
// Ensure that the server certificate covers the hostname that would
|
||||
// like to join this connection
|
||||
|
||||
UniqueCERTCertificate nssCert;
|
||||
|
||||
nsCOMPtr<nsIX509Cert> cert;
|
||||
if (NS_FAILED(GetServerCert(getter_AddRefs(cert)))) {
|
||||
return NS_OK;
|
||||
}
|
||||
if (cert) {
|
||||
nssCert.reset(cert->GetCert());
|
||||
}
|
||||
|
||||
if (!nssCert) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Attempt to verify the joinee's certificate using the joining hostname.
|
||||
// This ensures that any hostname-specific verification logic (e.g. key
|
||||
// pinning) is satisfied by the joinee's certificate chain.
|
||||
// This verification only uses local information; since we're on the network
|
||||
// thread, we would be blocking on ourselves if we attempted any network i/o.
|
||||
// TODO(bug 1056935): The certificate chain built by this verification may be
|
||||
// different than the certificate chain originally built during the joined
|
||||
// connection's TLS handshake. Consequently, we may report a wrong and/or
|
||||
// misleading certificate chain for HTTP transactions coalesced onto this
|
||||
// connection. This may become problematic in the future. For example,
|
||||
// if/when we begin relying on intermediate certificates being stored in the
|
||||
// securityInfo of a cached HTTPS response, that cached certificate chain may
|
||||
// actually be the wrong chain. We should consider having JoinConnection
|
||||
// return the certificate chain built here, so that the calling Necko code
|
||||
// can associate the correct certificate chain with the HTTP transactions it
|
||||
// is trying to join onto this connection.
|
||||
RefPtr<SharedCertVerifier> certVerifier(GetDefaultCertVerifier());
|
||||
if (!certVerifier) {
|
||||
return NS_OK;
|
||||
}
|
||||
CertVerifier::Flags flags = CertVerifier::FLAG_LOCAL_ONLY;
|
||||
UniqueCERTCertList unusedBuiltChain;
|
||||
mozilla::pkix::Result result = certVerifier->VerifySSLServerCert(
|
||||
nssCert,
|
||||
Maybe<nsTArray<uint8_t>>(), // stapledOCSPResponse
|
||||
Maybe<nsTArray<uint8_t>>(), // sctsFromTLSExtension
|
||||
mozilla::pkix::Now(),
|
||||
nullptr, // pinarg
|
||||
hostname, unusedBuiltChain,
|
||||
false, // save intermediates
|
||||
flags);
|
||||
if (result != mozilla::pkix::Success) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// All tests pass
|
||||
*_retval = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNSSSocketInfo::TestJoinConnection(const nsACString& npnProtocol,
|
||||
const nsACString& hostname, int32_t port,
|
||||
bool* _retval) {
|
||||
*_retval = false;
|
||||
|
||||
// Different ports may not be joined together
|
||||
if (port != GetPort()) 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
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNSSSocketInfo::JoinConnection(const nsACString& npnProtocol,
|
||||
const nsACString& hostname, int32_t port,
|
||||
bool* _retval) {
|
||||
nsresult rv = TestJoinConnection(npnProtocol, hostname, port, _retval);
|
||||
if (NS_SUCCEEDED(rv) && *_retval) {
|
||||
// All tests pass - this is joinable
|
||||
mJoined = true;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
bool nsNSSSocketInfo::GetForSTARTTLS() { return mForSTARTTLS; }
|
||||
|
||||
void nsNSSSocketInfo::SetForSTARTTLS(bool aForSTARTTLS) {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#ifndef nsNSSIOLayer_h
|
||||
#define nsNSSIOLayer_h
|
||||
|
||||
#include "TransportSecurityInfo.h"
|
||||
#include "CommonSocketControl.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
@ -31,14 +31,12 @@ using mozilla::OriginAttributes;
|
|||
|
||||
class nsIObserver;
|
||||
|
||||
class nsNSSSocketInfo final : public mozilla::psm::TransportSecurityInfo,
|
||||
public nsISSLSocketControl {
|
||||
class nsNSSSocketInfo final : public CommonSocketControl {
|
||||
public:
|
||||
nsNSSSocketInfo(mozilla::psm::SharedSSLState& aState, uint32_t providerFlags,
|
||||
uint32_t providerTlsFlags);
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSISSLSOCKETCONTROL
|
||||
|
||||
void SetForSTARTTLS(bool aForSTARTTLS);
|
||||
bool GetForSTARTTLS();
|
||||
|
@ -52,13 +50,31 @@ class nsNSSSocketInfo final : public mozilla::psm::TransportSecurityInfo,
|
|||
void SetTLSVersionRange(SSLVersionRange range) { mTLSVersionRange = range; }
|
||||
SSLVersionRange GetTLSVersionRange() const { return mTLSVersionRange; };
|
||||
|
||||
// From nsISSLSocketControl.
|
||||
NS_IMETHOD ProxyStartSSL(void) override;
|
||||
NS_IMETHOD StartTLS(void) override;
|
||||
NS_IMETHOD SetNPNList(nsTArray<nsCString> & aNPNList) override;
|
||||
NS_IMETHOD GetAlpnEarlySelection(nsACString& _retval) override;
|
||||
NS_IMETHOD GetEarlyDataAccepted(bool *aEarlyDataAccepted) override;
|
||||
NS_IMETHOD DriveHandshake(void) override;
|
||||
using nsISSLSocketControl::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;
|
||||
void SetDenyClientCert(bool aDenyClientCert) override;
|
||||
NS_IMETHOD GetClientCert(nsIX509Cert **aClientCert) override;
|
||||
NS_IMETHOD SetClientCert(nsIX509Cert *aClientCert) override;
|
||||
NS_IMETHOD GetEsniTxt(nsACString& aEsniTxt) override;
|
||||
NS_IMETHOD SetEsniTxt(const nsACString& aEsniTxt) override;
|
||||
|
||||
PRStatus CloseSocketAndDestroy();
|
||||
|
||||
void SetNegotiatedNPN(const char* value, uint32_t length);
|
||||
void SetEarlyDataAccepted(bool aAccepted);
|
||||
|
||||
void SetResumed(bool aResumed);
|
||||
|
||||
void SetHandshakeCompleted();
|
||||
bool IsHandshakeCompleted() const { return mHandshakeCompleted; }
|
||||
void NoteTimeUntilReady();
|
||||
|
@ -74,7 +90,6 @@ class nsNSSSocketInfo final : public mozilla::psm::TransportSecurityInfo,
|
|||
bool GetJoined() { return mJoined; }
|
||||
void SetSentClientCert() { mSentClientCert = true; }
|
||||
|
||||
uint32_t GetProviderFlags() const { return mProviderFlags; }
|
||||
uint32_t GetProviderTlsFlags() const { return mProviderTlsFlags; }
|
||||
|
||||
mozilla::psm::SharedSSLState& SharedState();
|
||||
|
@ -102,8 +117,6 @@ class nsNSSSocketInfo final : public mozilla::psm::TransportSecurityInfo,
|
|||
|
||||
void SetKEAKeyBits(uint32_t keaBits) { mKEAKeyBits = keaBits; }
|
||||
|
||||
void SetSSLVersionUsed(int16_t version) { mSSLVersionUsed = version; }
|
||||
|
||||
void SetMACAlgorithmUsed(int16_t mac) { mMACAlgorithmUsed = mac; }
|
||||
|
||||
void SetShortWritePending(int32_t amount, unsigned char data) {
|
||||
|
@ -161,20 +174,13 @@ class nsNSSSocketInfo final : public mozilla::psm::TransportSecurityInfo,
|
|||
|
||||
nsresult ActivateSSL();
|
||||
|
||||
nsCString mNegotiatedNPN;
|
||||
nsCString mEsniTxt;
|
||||
bool mNPNCompleted;
|
||||
bool mEarlyDataAccepted;
|
||||
bool mDenyClientCert;
|
||||
bool mFalseStartCallbackCalled;
|
||||
bool mFalseStarted;
|
||||
bool mIsFullHandshake;
|
||||
bool mHandshakeCompleted;
|
||||
bool mJoined;
|
||||
bool mSentClientCert;
|
||||
bool mNotedTimeUntilReady;
|
||||
bool mFailedVerification;
|
||||
mozilla::Atomic<bool, mozilla::Relaxed> mResumed;
|
||||
|
||||
// True when SSL layer has indicated an "SSL short write", i.e. need
|
||||
// to call on send one or more times to push all pending data to write.
|
||||
|
@ -198,10 +204,8 @@ class nsNSSSocketInfo final : public mozilla::psm::TransportSecurityInfo,
|
|||
// Values are from nsISSLSocketControl
|
||||
int16_t mKEAUsed;
|
||||
uint32_t mKEAKeyBits;
|
||||
int16_t mSSLVersionUsed;
|
||||
int16_t mMACAlgorithmUsed;
|
||||
|
||||
uint32_t mProviderFlags;
|
||||
uint32_t mProviderTlsFlags;
|
||||
mozilla::TimeStamp mSocketCreationTimestamp;
|
||||
uint64_t mPlaintextBytesRead;
|
||||
|
|
Загрузка…
Ссылка в новой задаче