summaryrefslogtreecommitdiffstats
path: root/security/manager/ssl/nsNSSModule.cpp
blob: 2fa628ad58ce17e3c729cbfa2e2b5362baccf3d1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/* -*- 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 "nsNSSModule.h"

#include "ContentSignatureVerifier.h"
#include "NSSErrorsService.h"
#include "OSKeyStore.h"
#include "OSReauthenticator.h"
#include "PKCS11ModuleDB.h"
#include "SecretDecoderRing.h"
#include "TransportSecurityInfo.h"
#include "mozilla/MacroArgs.h"
#include "mozilla/ModuleUtils.h"
#include "mozilla/SyncRunnable.h"
#include "nsCURILoader.h"
#include "nsCryptoHash.h"
#include "nsKeyModule.h"
#include "nsNSSCertificate.h"
#include "nsNSSCertificateDB.h"
#include "nsNSSComponent.h"
#include "nsNSSVersion.h"
#include "nsNetCID.h"
#include "nsPK11TokenDB.h"
#include "nsPKCS11Slot.h"
#include "nsRandomGenerator.h"
#include "nsSecureBrowserUI.h"
#include "nsXULAppAPI.h"

#ifdef MOZ_XUL
#  include "nsCertTree.h"
#endif

namespace mozilla {
namespace psm {

// Many of the implementations in this module call NSS functions and as a result
// require that PSM has successfully initialized NSS before being used.
// Additionally, some of the implementations have various restrictions on which
// process and threads they can be used on (e.g. some can only be used in the
// parent process and some must be initialized only on the main thread).
// The following initialization framework allows these requirements to be
// succinctly expressed and implemented.

template <class InstanceClass, nsresult (InstanceClass::*InitMethod)()>
MOZ_ALWAYS_INLINE static nsresult Instantiate(REFNSIID aIID, void** aResult) {
  InstanceClass* inst = new InstanceClass();
  NS_ADDREF(inst);
  nsresult rv = InitMethod != nullptr ? (inst->*InitMethod)() : NS_OK;
  if (NS_SUCCEEDED(rv)) {
    rv = inst->QueryInterface(aIID, aResult);
  }
  NS_RELEASE(inst);
  return rv;
}

enum class ThreadRestriction {
  // must be initialized on the main thread (but can be used on any thread)
  MainThreadOnly,
  // can be initialized and used on any thread
  AnyThread,
};

enum class ProcessRestriction {
  ParentProcessOnly,
  AnyProcess,
};

template <class InstanceClass,
          nsresult (InstanceClass::*InitMethod)() = nullptr,
          ProcessRestriction processRestriction =
              ProcessRestriction::ParentProcessOnly,
          ThreadRestriction threadRestriction = ThreadRestriction::AnyThread>
static nsresult Constructor(nsISupports* aOuter, REFNSIID aIID,
                            void** aResult) {
  *aResult = nullptr;
  if (aOuter != nullptr) {
    return NS_ERROR_NO_AGGREGATION;
  }

  if (processRestriction == ProcessRestriction::ParentProcessOnly &&
      !XRE_IsParentProcess()) {
    return NS_ERROR_NOT_AVAILABLE;
  }

  if (!EnsureNSSInitializedChromeOrContent()) {
    return NS_ERROR_FAILURE;
  }

  if (threadRestriction == ThreadRestriction::MainThreadOnly &&
      !NS_IsMainThread()) {
    return NS_ERROR_NOT_SAME_THREAD;
  }

  return Instantiate<InstanceClass, InitMethod>(aIID, aResult);
}

#define IMPL(type, ...)                                                  \
  template <>                                                            \
  nsresult NSSConstructor<type>(nsISupports * aOuter, const nsIID& aIID, \
                                void** aResult) {                        \
    return Constructor<type, __VA_ARGS__>(aOuter, aIID, aResult);        \
  }

// Components that require main thread initialization could cause a deadlock
// in necko code (bug 1418752). To prevent it we initialize all such components
// on main thread in advance in net_EnsurePSMInit(). Update that function when
// new component with ThreadRestriction::MainThreadOnly is added.
IMPL(SecretDecoderRing, nullptr)
IMPL(nsPK11TokenDB, nullptr)
IMPL(PKCS11ModuleDB, nullptr)
IMPL(nsNSSCertificate, nullptr, ProcessRestriction::AnyProcess)
IMPL(nsNSSCertificateDB, nullptr)
#ifdef MOZ_XUL
IMPL(nsCertTree, nullptr)
#endif
IMPL(nsCryptoHash, nullptr, ProcessRestriction::AnyProcess)
IMPL(nsCryptoHMAC, nullptr, ProcessRestriction::AnyProcess)
IMPL(nsKeyObject, nullptr, ProcessRestriction::AnyProcess)
IMPL(nsKeyObjectFactory, 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,
     ThreadRestriction::MainThreadOnly)
#undef IMPL

}  // namespace psm
}  // namespace mozilla