Skip to content

Commit

Permalink
bug 1470030 - convert manually-written nsINSSComponent definition to …
Browse files Browse the repository at this point in the history
…idl r=fkiefer

Defining nsINSSComponent in idl rather than manually in a header file allows us
to make full use of the machinery that already exists to process and generate
the correct definitions. Furthermore, it enables us to define JS-accessible APIs
on nsINSSComponent, which enables us to build frontend features that can work
directly with the data and functionality the underlying implementation has
access to.

MozReview-Commit-ID: JFI9s12wmRE

--HG--
extra : rebase_source : 16b660e37db681c8823cbb6b7ff59dd0d35f7e73
  • Loading branch information
mozkeeler committed Jun 20, 2018
1 parent 2ae8017 commit 9b69a30
Show file tree
Hide file tree
Showing 7 changed files with 186 additions and 125 deletions.
4 changes: 2 additions & 2 deletions netwerk/protocol/http/nsHttpHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2474,15 +2474,15 @@ CanEnableSpeculativeConnect()
// Check if any 3rd party PKCS#11 module are installed, as they may produce
// client certificates
bool activeSmartCards = false;
nsresult rv = component->HasActiveSmartCards(activeSmartCards);
nsresult rv = component->HasActiveSmartCards(&activeSmartCards);
if (NS_FAILED(rv) || activeSmartCards) {
return false;
}

// If there are any client certificates installed, we can't enable speculative
// connect, as it may pop up the certificate chooser at any time.
bool hasUserCerts = false;
rv = component->HasUserCertsInstalled(hasUserCerts);
rv = component->HasUserCertsInstalled(&hasUserCerts);
if (NS_FAILED(rv) || hasUserCerts) {
return false;
}
Expand Down
2 changes: 1 addition & 1 deletion security/certverifier/CertVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ IsCertBuiltInRoot(CERTCertificate* cert, bool& result)
if (!component) {
return Result::FATAL_ERROR_LIBRARY_FAILURE;
}
nsresult rv = component->IsCertTestBuiltInRoot(cert, result);
nsresult rv = component->IsCertTestBuiltInRoot(cert, &result);
if (NS_FAILED(rv)) {
return Result::FATAL_ERROR_LIBRARY_FAILURE;
}
Expand Down
2 changes: 1 addition & 1 deletion security/manager/ssl/CSTrustDomain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ CSTrustDomain::GetCertTrust(EndEntityOrCA endEntityOrCA,
if (!component) {
return Result::FATAL_ERROR_LIBRARY_FAILURE;
}
nsrv = component->IsCertContentSigningRoot(candidateCert.get(), isRoot);
nsrv = component->IsCertContentSigningRoot(candidateCert.get(), &isRoot);
if (NS_FAILED(nsrv)) {
return Result::FATAL_ERROR_LIBRARY_FAILURE;
}
Expand Down
1 change: 1 addition & 0 deletions security/manager/ssl/moz.build
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ XPIDL_SOURCES += [
'nsIKeygenThread.idl',
'nsIKeyModule.idl',
'nsILocalCertService.idl',
'nsINSSComponent.idl',
'nsINSSErrorsService.idl',
'nsINSSVersion.idl',
'nsIPK11Token.idl',
Expand Down
110 changes: 110 additions & 0 deletions security/manager/ssl/nsINSSComponent.idl
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/* -*- 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 "nsISupports.idl"

%{C++
#include "cert.h"
#include "SharedCertVerifier.h"
#define PSM_COMPONENT_CONTRACTID "@mozilla.org/psm;1"
%}

interface nsIX509CertList;

[ptr] native CERTCertificatePtr(CERTCertificate);
[ptr] native SharedCertVerifierPtr(mozilla::psm::SharedCertVerifier);

[scriptable, uuid(a0a8f52b-ea18-4abc-a3ca-eccf704ffe63)]
interface nsINSSComponent : nsISupports {
/**
* When we log out of a PKCS#11 token, any TLS connections that may have
* involved a client certificate stored on that token must be closed. Since we
* don't have a fine-grained way to do this, we basically cancel everything.
* More speficially, this clears all temporary certificate exception overrides
* and any remembered client authentication certificate decisions, and then
* cancels all network connections (strictly speaking, this last part is
* overzealous - we only need to cancel all https connections (see bug
* 1446645)).
*/
[noscript] void logoutAuthenticatedPK11();

/**
* Used to determine if the given CERTCertificate is the certificate we use in
* tests to simulate a built-in root certificate. Returns false in non-debug
* builds.
*/
[noscript] bool isCertTestBuiltInRoot(in CERTCertificatePtr cert);

/**
* Used to determine if the given CERTCertificate is the content signing root
* certificate.
*/
[noscript] bool isCertContentSigningRoot(in CERTCertificatePtr cert);

/**
* If enabled by the preference "security.enterprise_roots.enabled", returns
* an nsIX509CertList representing the imported enterprise root certificates
* (i.e. root certificates gleaned from the OS certificate store). Returns
* null otherwise.
* Currently this is only implemented on Windows, so this function returns
* null on all other platforms.
*/
[noscript] nsIX509CertList getEnterpriseRoots();

/**
* During initialization, nsINSSComponent collects any 3rd party root
* certificates from the OS that may be relevant (e.g. enterprise roots, the
* Family Safety root on Windows 8). However, to prevent opening a PKCS#11
* login prompt and potentially re-entering initialization, the component
* delays trusting these roots until a later event tick. This is the function
* that enables that.
*/
[noscript] void trustLoaded3rdPartyRoots();

/**
* For performance reasons, the builtin roots module is loaded on a background
* thread. When any code that depends on the builtin roots module runs, it
* must first wait for the module to be loaded.
*/
[noscript] void blockUntilLoadableRootsLoaded();

/**
* In theory a token on a PKCS#11 module can be inserted or removed at any
* time. Operations that may depend on resources on external tokens should
* call this to ensure they have a recent view of the token.
*/
[noscript] void checkForSmartCardChanges();

/**
* Used to potentially detect when a user's internet connection is being
* intercepted. When doing an update ping, if certificate verification fails,
* we make a note of the issuer distinguished name of that certificate.
* If a subsequent certificate verification fails, we compare issuer
* distinguished names. If they match, something may be intercepting the
* user's traffic (if they don't match, the server is likely misconfigured).
* This function succeeds if the given DN matches the noted DN and fails
* otherwise (e.g. if the update ping never failed).
*/
[noscript] void issuerMatchesMitmCanary(in string certIssuer);

/**
* Returns true if the user has a PKCS#11 module with removable slots.
* Main thread only.
*/
[noscript] bool hasActiveSmartCards();

/**
* Returns true if the user has any client authentication certificates.
* Main thread only.
*/
[noscript] bool hasUserCertsInstalled();

/**
* Returns an already-adrefed handle to the currently configured shared
* certificate verifier.
*/
[noscript] SharedCertVerifierPtr getDefaultCertVerifier();
};
118 changes: 66 additions & 52 deletions security/manager/ssl/nsNSSComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -731,34 +731,6 @@ nsNSSComponent::UnloadEnterpriseRoots()
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("unloaded enterprise roots"));
}

NS_IMETHODIMP
nsNSSComponent::GetEnterpriseRoots(nsIX509CertList** enterpriseRoots)
{
MutexAutoLock nsNSSComponentLock(mMutex);
MOZ_ASSERT(NS_IsMainThread());
if (!NS_IsMainThread()) {
return NS_ERROR_NOT_SAME_THREAD;
}
NS_ENSURE_ARG_POINTER(enterpriseRoots);

if (!mEnterpriseRoots) {
*enterpriseRoots = nullptr;
return NS_OK;
}
UniqueCERTCertList enterpriseRootsCopy(
nsNSSCertList::DupCertList(mEnterpriseRoots));
if (!enterpriseRootsCopy) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIX509CertList> enterpriseRootsCertList(
new nsNSSCertList(std::move(enterpriseRootsCopy)));
if (!enterpriseRootsCertList) {
return NS_ERROR_FAILURE;
}
enterpriseRootsCertList.forget(enterpriseRoots);
return NS_OK;
}

static const char* kEnterpriseRootModePref = "security.enterprise_roots.enabled";

void
Expand Down Expand Up @@ -874,6 +846,7 @@ nsNSSComponent::ImportEnterpriseRootsForLocation(
}
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, ("imported %u roots", numImported));
}
#endif // XP_WIN

NS_IMETHODIMP
nsNSSComponent::TrustLoaded3rdPartyRoots()
Expand Down Expand Up @@ -901,15 +874,44 @@ nsNSSComponent::TrustLoaded3rdPartyRoots()
}
}
}
#ifdef XP_WIN
if (mFamilySafetyRoot &&
ChangeCertTrustWithPossibleAuthentication(mFamilySafetyRoot, trust,
nullptr) != SECSuccess) {
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
("couldn't trust family safety certificate for TLS server auth"));
}
#endif
return NS_OK;
}

NS_IMETHODIMP
nsNSSComponent::GetEnterpriseRoots(nsIX509CertList** enterpriseRoots)
{
MutexAutoLock nsNSSComponentLock(mMutex);
MOZ_ASSERT(NS_IsMainThread());
if (!NS_IsMainThread()) {
return NS_ERROR_NOT_SAME_THREAD;
}
NS_ENSURE_ARG_POINTER(enterpriseRoots);

if (!mEnterpriseRoots) {
*enterpriseRoots = nullptr;
return NS_OK;
}
UniqueCERTCertList enterpriseRootsCopy(
nsNSSCertList::DupCertList(mEnterpriseRoots));
if (!enterpriseRootsCopy) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIX509CertList> enterpriseRootsCertList(
new nsNSSCertList(std::move(enterpriseRootsCopy)));
if (!enterpriseRootsCertList) {
return NS_ERROR_FAILURE;
}
enterpriseRootsCertList.forget(enterpriseRoots);
return NS_OK;
}
#endif // XP_WIN

class LoadLoadableRootsTask final : public Runnable
{
Expand Down Expand Up @@ -1002,9 +1004,10 @@ LoadLoadableRootsTask::Run()
return NS_DispatchToMainThread(this);
}

nsresult
nsNSSComponent::HasActiveSmartCards(bool& result)
NS_IMETHODIMP
nsNSSComponent::HasActiveSmartCards(bool* result)
{
NS_ENSURE_ARG_POINTER(result);
MOZ_ASSERT(NS_IsMainThread(), "Main thread only");
if (!NS_IsMainThread()) {
return NS_ERROR_NOT_SAME_THREAD;
Expand All @@ -1017,19 +1020,20 @@ nsNSSComponent::HasActiveSmartCards(bool& result)
SECMODModuleList* list = SECMOD_GetDefaultModuleList();
while (list) {
if (SECMOD_HasRemovableSlots(list->module)) {
result = true;
*result = true;
return NS_OK;
}
list = list->next;
}
#endif
result = false;
*result = false;
return NS_OK;
}

nsresult
nsNSSComponent::HasUserCertsInstalled(bool& result)
NS_IMETHODIMP
nsNSSComponent::HasUserCertsInstalled(bool* result)
{
NS_ENSURE_ARG_POINTER(result);
MOZ_ASSERT(NS_IsMainThread(), "Main thread only");
if (!NS_IsMainThread()) {
return NS_ERROR_NOT_SAME_THREAD;
Expand All @@ -1041,7 +1045,7 @@ nsNSSComponent::HasUserCertsInstalled(bool& result)
return NS_ERROR_NOT_INITIALIZED;
}

result = false;
*result = false;
UniqueCERTCertList certList(
CERT_FindUserCertsByUsage(CERT_GetDefaultCertDB(), certUsageSSLClient,
false, true, nullptr));
Expand All @@ -1055,7 +1059,7 @@ nsNSSComponent::HasUserCertsInstalled(bool& result)
}

// The list is not empty, meaning at least one cert is installed
result = true;
*result = true;
return NS_OK;
}

Expand Down Expand Up @@ -2322,12 +2326,14 @@ nsNSSComponent::RegisterObservers()
return NS_OK;
}

#ifdef DEBUG
NS_IMETHODIMP
nsNSSComponent::IsCertTestBuiltInRoot(CERTCertificate* cert, bool& result)
nsNSSComponent::IsCertTestBuiltInRoot(CERTCertificate* cert, bool* result)
{
result = false;
NS_ENSURE_ARG_POINTER(cert);
NS_ENSURE_ARG_POINTER(result);
*result = false;

#ifdef DEBUG
RefPtr<nsNSSCertificate> nsc = nsNSSCertificate::Create(cert);
if (!nsc) {
return NS_ERROR_FAILURE;
Expand All @@ -2344,15 +2350,17 @@ nsNSSComponent::IsCertTestBuiltInRoot(CERTCertificate* cert, bool& result)
return NS_OK;
}

result = mTestBuiltInRootHash.Equals(certHash);
*result = mTestBuiltInRootHash.Equals(certHash);
#endif // DEBUG

return NS_OK;
}
#endif // DEBUG

NS_IMETHODIMP
nsNSSComponent::IsCertContentSigningRoot(CERTCertificate* cert, bool& result)
nsNSSComponent::IsCertContentSigningRoot(CERTCertificate* cert, bool* result)
{
result = false;
NS_ENSURE_ARG_POINTER(result);
*result = false;

RefPtr<nsNSSCertificate> nsc = nsNSSCertificate::Create(cert);
if (!nsc) {
Expand All @@ -2374,7 +2382,7 @@ nsNSSComponent::IsCertContentSigningRoot(CERTCertificate* cert, bool& result)
return NS_ERROR_FAILURE;
}

result = mContentSigningRootHash.Equals(certHash);
*result = mContentSigningRootHash.Equals(certHash);
return NS_OK;
}

Expand All @@ -2394,13 +2402,15 @@ nsNSSComponent::IssuerMatchesMitmCanary(const char* aCertIssuer)

SharedCertVerifier::~SharedCertVerifier() { }

already_AddRefed<SharedCertVerifier>
nsNSSComponent::GetDefaultCertVerifier()
NS_IMETHODIMP
nsNSSComponent::GetDefaultCertVerifier(SharedCertVerifier** result)
{
MutexAutoLock lock(mMutex);
MOZ_ASSERT(mNSSInitialized);
NS_ENSURE_ARG_POINTER(result);
RefPtr<SharedCertVerifier> certVerifier(mDefaultCertVerifier);
return certVerifier.forget();
certVerifier.forget(result);
return NS_OK;
}

namespace mozilla { namespace psm {
Expand All @@ -2411,11 +2421,15 @@ GetDefaultCertVerifier()
static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);

nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID));
if (nssComponent) {
return nssComponent->GetDefaultCertVerifier();
if (!nssComponent) {
return nullptr;
}

return nullptr;
RefPtr<SharedCertVerifier> result;
nsresult rv = nssComponent->GetDefaultCertVerifier(getter_AddRefs(result));
if (NS_FAILED(rv)) {
return nullptr;
}
return result.forget();
}

} } // namespace mozilla::psm
Expand Down
Loading

0 comments on commit 9b69a30

Please sign in to comment.