diff options
Diffstat (limited to '')
-rw-r--r-- | security/manager/ssl/VerifySSLServerCertParent.cpp | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/security/manager/ssl/VerifySSLServerCertParent.cpp b/security/manager/ssl/VerifySSLServerCertParent.cpp new file mode 100644 index 0000000000..7216c571d1 --- /dev/null +++ b/security/manager/ssl/VerifySSLServerCertParent.cpp @@ -0,0 +1,185 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set sw=2 ts=8 et tw=80 : */ + +/* 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 "VerifySSLServerCertParent.h" + +#include "cert.h" +#include "nsNSSComponent.h" +#include "secerr.h" +#include "SharedCertVerifier.h" +#include "NSSCertDBTrustDomain.h" +#include "SSLServerCertVerification.h" +#include "nsNSSIOLayer.h" +#include "nsISocketProvider.h" +#include "mozilla/ipc/BackgroundParent.h" +#include "mozilla/Unused.h" + +extern mozilla::LazyLogModule gPIPNSSLog; + +using mozilla::ipc::AssertIsOnBackgroundThread; +using mozilla::ipc::IsOnBackgroundThread; + +using namespace mozilla::pkix; + +namespace mozilla { +namespace psm { + +VerifySSLServerCertParent::VerifySSLServerCertParent() {} + +void VerifySSLServerCertParent::OnVerifiedSSLServerCert( + const nsTArray<ByteArray>& aBuiltCertChain, + uint16_t aCertificateTransparencyStatus, uint8_t aEVStatus, bool aSucceeded, + PRErrorCode aFinalError, uint32_t aOverridableErrorCategory, + bool aIsBuiltCertChainRootBuiltInRoot, bool aMadeOCSPRequests) { + AssertIsOnBackgroundThread(); + + if (!CanSend()) { + return; + } + + if (aSucceeded) { + Unused << SendOnVerifiedSSLServerCertSuccess( + aBuiltCertChain, aCertificateTransparencyStatus, aEVStatus, + aIsBuiltCertChainRootBuiltInRoot, aMadeOCSPRequests); + } else { + Unused << SendOnVerifiedSSLServerCertFailure( + aFinalError, aOverridableErrorCategory, aMadeOCSPRequests); + } + Unused << Send__delete__(this); +} + +namespace { + +class IPCServerCertVerificationResult final + : public BaseSSLServerCertVerificationResult { + public: + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(IPCServerCertVerificationResult, + override) + + IPCServerCertVerificationResult(nsIEventTarget* aTarget, + VerifySSLServerCertParent* aParent) + : mTarget(aTarget), mParent(aParent) {} + + void Dispatch(nsTArray<nsTArray<uint8_t>>&& aBuiltChain, + nsTArray<nsTArray<uint8_t>>&& aPeerCertChain, + uint16_t aCertificateTransparencyStatus, EVStatus aEVStatus, + bool aSucceeded, PRErrorCode aFinalError, + nsITransportSecurityInfo::OverridableErrorCategory + aOverridableErrorCategory, + bool aIsBuiltCertChainRootBuiltInRoot, uint32_t aProviderFlags, + bool aMadeOCSPRequests) override; + + private: + ~IPCServerCertVerificationResult() = default; + + nsCOMPtr<nsIEventTarget> mTarget; + RefPtr<VerifySSLServerCertParent> mParent; +}; + +void IPCServerCertVerificationResult::Dispatch( + nsTArray<nsTArray<uint8_t>>&& aBuiltChain, + nsTArray<nsTArray<uint8_t>>&& aPeerCertChain, + uint16_t aCertificateTransparencyStatus, EVStatus aEVStatus, + bool aSucceeded, PRErrorCode aFinalError, + nsITransportSecurityInfo::OverridableErrorCategory + aOverridableErrorCategory, + bool aIsBuiltCertChainRootBuiltInRoot, uint32_t aProviderFlags, + bool aMadeOCSPRequests) { + nsTArray<ByteArray> builtCertChain; + if (aSucceeded) { + for (auto& cert : aBuiltChain) { + builtCertChain.AppendElement(ByteArray(cert)); + } + } + + nsresult nrv = mTarget->Dispatch( + NS_NewRunnableFunction( + "psm::VerifySSLServerCertParent::OnVerifiedSSLServerCert", + [parent(mParent), builtCertChain{std::move(builtCertChain)}, + aCertificateTransparencyStatus, aEVStatus, aSucceeded, aFinalError, + aOverridableErrorCategory, aIsBuiltCertChainRootBuiltInRoot, + aMadeOCSPRequests, aProviderFlags]() { + if (aSucceeded && + !(aProviderFlags & nsISocketProvider::NO_PERMANENT_STORAGE)) { + nsTArray<nsTArray<uint8_t>> certBytesArray; + for (const auto& cert : builtCertChain) { + certBytesArray.AppendElement(cert.data().Clone()); + } + // This dispatches an event that will run when the socket thread + // is idle. + SaveIntermediateCerts(certBytesArray); + } + parent->OnVerifiedSSLServerCert( + builtCertChain, aCertificateTransparencyStatus, + static_cast<uint8_t>(aEVStatus), aSucceeded, aFinalError, + static_cast<uint32_t>(aOverridableErrorCategory), + aIsBuiltCertChainRootBuiltInRoot, aMadeOCSPRequests); + }), + NS_DISPATCH_NORMAL); + MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(nrv)); + Unused << nrv; +} + +} // anonymous namespace + +bool VerifySSLServerCertParent::Dispatch( + nsTArray<ByteArray>&& aPeerCertChain, const nsACString& aHostName, + const int32_t& aPort, const OriginAttributes& aOriginAttributes, + const Maybe<ByteArray>& aStapledOCSPResponse, + const Maybe<ByteArray>& aSctsFromTLSExtension, + const Maybe<DelegatedCredentialInfoArg>& aDcInfo, + const uint32_t& aProviderFlags, const uint32_t& aCertVerifierFlags) { + MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("VerifySSLServerCertParent::Dispatch")); + AssertIsOnBackgroundThread(); + + mBackgroundThread = NS_GetCurrentThread(); + + nsTArray<nsTArray<uint8_t>> peerCertBytes; + for (auto& certBytes : aPeerCertChain) { + nsTArray<uint8_t> bytes; + peerCertBytes.AppendElement(std::move(certBytes.data())); + } + + Maybe<nsTArray<uint8_t>> stapledOCSPResponse; + if (aStapledOCSPResponse) { + stapledOCSPResponse.emplace(aStapledOCSPResponse->data().Clone()); + } + + Maybe<nsTArray<uint8_t>> sctsFromTLSExtension; + if (aSctsFromTLSExtension) { + sctsFromTLSExtension.emplace(aSctsFromTLSExtension->data().Clone()); + } + + Maybe<DelegatedCredentialInfo> dcInfo; + if (aDcInfo) { + dcInfo.emplace(); + dcInfo->scheme = static_cast<SSLSignatureScheme>(aDcInfo->scheme()); + dcInfo->authKeyBits = aDcInfo->authKeyBits(); + } + + RefPtr<IPCServerCertVerificationResult> resultTask = + new IPCServerCertVerificationResult(mBackgroundThread, this); + SECStatus status = SSLServerCertVerificationJob::Dispatch( + 0, nullptr, std::move(peerCertBytes), aHostName, aPort, aOriginAttributes, + stapledOCSPResponse, sctsFromTLSExtension, dcInfo, aProviderFlags, Now(), + aCertVerifierFlags, resultTask); + + if (status != SECWouldBlock) { + MOZ_LOG(gPIPNSSLog, LogLevel::Debug, + ("VerifySSLServerCertParent::Dispatch - dispatch failed")); + return false; + } + + return true; +} + +void VerifySSLServerCertParent::ActorDestroy(ActorDestroyReason aWhy) {} + +VerifySSLServerCertParent::~VerifySSLServerCertParent() = default; + +} // namespace psm +} // namespace mozilla |