1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #include "nsNSSModule.h"
8
9 #include "ContentSignatureVerifier.h"
10 #include "NSSErrorsService.h"
11 #include "OSKeyStore.h"
12 #include "OSReauthenticator.h"
13 #include "PKCS11ModuleDB.h"
14 #include "SecretDecoderRing.h"
15 #include "TransportSecurityInfo.h"
16 #include "mozilla/MacroArgs.h"
17 #include "mozilla/ModuleUtils.h"
18 #include "mozilla/SyncRunnable.h"
19 #include "nsCURILoader.h"
20 #include "nsCryptoHash.h"
21 #include "nsKeyModule.h"
22 #include "nsNSSCertificate.h"
23 #include "nsNSSCertificateDB.h"
24 #include "nsNSSComponent.h"
25 #include "nsNSSVersion.h"
26 #include "nsNetCID.h"
27 #include "nsPK11TokenDB.h"
28 #include "nsPKCS11Slot.h"
29 #include "nsRandomGenerator.h"
30 #include "nsSecureBrowserUI.h"
31 #include "nsXULAppAPI.h"
32
33 #ifdef MOZ_XUL
34 # include "nsCertTree.h"
35 #endif
36
37 namespace mozilla {
38 namespace psm {
39
40 // Many of the implementations in this module call NSS functions and as a result
41 // require that PSM has successfully initialized NSS before being used.
42 // Additionally, some of the implementations have various restrictions on which
43 // process and threads they can be used on (e.g. some can only be used in the
44 // parent process and some must be initialized only on the main thread).
45 // The following initialization framework allows these requirements to be
46 // succinctly expressed and implemented.
47
48 template <class InstanceClass, nsresult (InstanceClass::*InitMethod)()>
Instantiate(REFNSIID aIID,void ** aResult)49 MOZ_ALWAYS_INLINE static nsresult Instantiate(REFNSIID aIID, void** aResult) {
50 InstanceClass* inst = new InstanceClass();
51 NS_ADDREF(inst);
52 nsresult rv = InitMethod != nullptr ? (inst->*InitMethod)() : NS_OK;
53 if (NS_SUCCEEDED(rv)) {
54 rv = inst->QueryInterface(aIID, aResult);
55 }
56 NS_RELEASE(inst);
57 return rv;
58 }
59
60 enum class ThreadRestriction {
61 // must be initialized on the main thread (but can be used on any thread)
62 MainThreadOnly,
63 // can be initialized and used on any thread
64 AnyThread,
65 };
66
67 enum class ProcessRestriction {
68 ParentProcessOnly,
69 AnyProcess,
70 };
71
72 template <class InstanceClass,
73 nsresult (InstanceClass::*InitMethod)() = nullptr,
74 ProcessRestriction processRestriction =
75 ProcessRestriction::ParentProcessOnly,
76 ThreadRestriction threadRestriction = ThreadRestriction::AnyThread>
Constructor(nsISupports * aOuter,REFNSIID aIID,void ** aResult)77 static nsresult Constructor(nsISupports* aOuter, REFNSIID aIID,
78 void** aResult) {
79 *aResult = nullptr;
80 if (aOuter != nullptr) {
81 return NS_ERROR_NO_AGGREGATION;
82 }
83
84 if (processRestriction == ProcessRestriction::ParentProcessOnly &&
85 !XRE_IsParentProcess()) {
86 return NS_ERROR_NOT_AVAILABLE;
87 }
88
89 if (!EnsureNSSInitializedChromeOrContent()) {
90 return NS_ERROR_FAILURE;
91 }
92
93 if (threadRestriction == ThreadRestriction::MainThreadOnly &&
94 !NS_IsMainThread()) {
95 return NS_ERROR_NOT_SAME_THREAD;
96 }
97
98 return Instantiate<InstanceClass, InitMethod>(aIID, aResult);
99 }
100
101 #define IMPL(type, ...) \
102 template <> \
103 nsresult NSSConstructor<type>(nsISupports * aOuter, const nsIID& aIID, \
104 void** aResult) { \
105 return Constructor<type, __VA_ARGS__>(aOuter, aIID, aResult); \
106 }
107
108 // Components that require main thread initialization could cause a deadlock
109 // in necko code (bug 1418752). To prevent it we initialize all such components
110 // on main thread in advance in net_EnsurePSMInit(). Update that function when
111 // new component with ThreadRestriction::MainThreadOnly is added.
112 IMPL(SecretDecoderRing, nullptr)
113 IMPL(nsPK11TokenDB, nullptr)
114 IMPL(PKCS11ModuleDB, nullptr)
115 IMPL(nsNSSCertificate, nullptr, ProcessRestriction::AnyProcess)
116 IMPL(nsNSSCertificateDB, nullptr)
117 #ifdef MOZ_XUL
118 IMPL(nsCertTree, nullptr)
119 #endif
120 IMPL(nsCryptoHash, nullptr, ProcessRestriction::AnyProcess)
121 IMPL(nsCryptoHMAC, nullptr, ProcessRestriction::AnyProcess)
122 IMPL(nsKeyObject, nullptr, ProcessRestriction::AnyProcess)
123 IMPL(nsKeyObjectFactory, nullptr, ProcessRestriction::AnyProcess)
124 IMPL(ContentSignatureVerifier, nullptr)
125 IMPL(nsRandomGenerator, nullptr, ProcessRestriction::AnyProcess)
126 IMPL(TransportSecurityInfo, nullptr, ProcessRestriction::AnyProcess)
127 IMPL(OSKeyStore, nullptr, ProcessRestriction::ParentProcessOnly,
128 ThreadRestriction::MainThreadOnly)
129 IMPL(OSReauthenticator, nullptr, ProcessRestriction::ParentProcessOnly,
130 ThreadRestriction::MainThreadOnly)
131 #undef IMPL
132
133 } // namespace psm
134 } // namespace mozilla
135