1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 /*
5  * pkix_pl_lifecycle.c
6  *
7  * Lifecycle Functions for the PKIX PL library.
8  *
9  */
10 
11 #include "pkix_pl_lifecycle.h"
12 
13 PKIX_Boolean pkix_pl_initialized = PKIX_FALSE;
14 pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
15 PRLock *classTableLock;
16 PRLogModuleInfo *pkixLog = NULL;
17 
18 /*
19  * PKIX_ALLOC_ERROR is a special error object hard-coded into the
20  * pkix_error.o object file. It is thrown if system memory cannot be
21  * allocated. PKIX_ALLOC_ERROR is immutable.
22  * IncRef, DecRef, and Settor functions cannot be called.
23  */
24 
25 /* Keep this structure definition here for its is used only once here */
26 struct PKIX_Alloc_Error_ObjectStruct {
27         PKIX_PL_Object header;
28         PKIX_Error error;
29 };
30 typedef struct PKIX_Alloc_Error_ObjectStruct PKIX_Alloc_Error_Object;
31 
32 static const PKIX_Alloc_Error_Object pkix_Alloc_Error_Data = {
33     {
34         PKIX_MAGIC_HEADER, 		/* PRUint64    magicHeader */
35         (PKIX_UInt32)PKIX_ERROR_TYPE,   /* PKIX_UInt32 type */
36         (PKIX_UInt32)1,                 /* PKIX_UInt32 references */
37         /* Warning! Cannot Ref Count with NULL lock */
38         (void *)0,                      /* PRLock *lock */
39         (PKIX_PL_String *)0,            /* PKIX_PL_String *stringRep */
40         (PKIX_UInt32)0,                 /* PKIX_UInt32 hashcode */
41         (PKIX_Boolean)PKIX_FALSE,       /* PKIX_Boolean hashcodeCached */
42     }, {
43         (PKIX_ERRORCODE)0,              /* PKIX_ERRORCODE errCode; */
44         (PKIX_ERRORCLASS)PKIX_FATAL_ERROR,/* PKIX_ERRORCLASS errClass */
45         (PKIX_UInt32)SEC_ERROR_LIBPKIX_INTERNAL, /* default PL Error Code */
46         (PKIX_Error *)0,                /* PKIX_Error *cause */
47         (PKIX_PL_Object *)0,            /* PKIX_PL_Object *info */
48    }
49 };
50 
PKIX_ALLOC_ERROR(void)51 PKIX_Error* PKIX_ALLOC_ERROR(void)
52 {
53     return (PKIX_Error *)&pkix_Alloc_Error_Data.error;
54 }
55 
56 #ifdef PKIX_OBJECT_LEAK_TEST
57 SECStatus
pkix_pl_lifecycle_ObjectTableUpdate(int * objCountTable)58 pkix_pl_lifecycle_ObjectTableUpdate(int *objCountTable)
59 {
60     int   typeCounter = 0;
61 
62     for (; typeCounter < PKIX_NUMTYPES; typeCounter++) {
63         pkix_ClassTable_Entry *entry = &systemClasses[typeCounter];
64 
65         objCountTable[typeCounter] = entry->objCounter;
66     }
67 
68     return SECSuccess;
69 }
70 #endif /* PKIX_OBJECT_LEAK_TEST */
71 
72 
73 PKIX_UInt32
pkix_pl_lifecycle_ObjectLeakCheck(int * initObjCountTable)74 pkix_pl_lifecycle_ObjectLeakCheck(int *initObjCountTable)
75 {
76         unsigned int typeCounter = 0;
77         PKIX_UInt32 numObjects = 0;
78         char  classNameBuff[128];
79         char *className = NULL;
80 
81         for (; typeCounter < PKIX_NUMTYPES; typeCounter++) {
82                 pkix_ClassTable_Entry *entry = &systemClasses[typeCounter];
83                 PKIX_UInt32 objCountDiff = entry->objCounter;
84 
85                 if (initObjCountTable) {
86                     PKIX_UInt32 initialCount = initObjCountTable[typeCounter];
87                     objCountDiff = (entry->objCounter > initialCount) ?
88                         entry->objCounter - initialCount : 0;
89                 }
90 
91                 numObjects += objCountDiff;
92 
93                 if (!pkixLog || !objCountDiff) {
94                     continue;
95                 }
96                 className = entry->description;
97                 if (!className) {
98                     className = classNameBuff;
99                     PR_snprintf(className, 128, "Unknown(ref %d)",
100                             entry->objCounter);
101                 }
102 
103                 PR_LOG(pkixLog, 1, ("Class %s leaked %d objects of "
104                         "size %d bytes, total = %d bytes\n", className,
105                         objCountDiff, entry->typeObjectSize,
106                         objCountDiff * entry->typeObjectSize));
107         }
108 
109         return numObjects;
110 }
111 
112 /*
113  * PKIX_PL_Initialize (see comments in pkix_pl_system.h)
114  */
115 PKIX_Error *
PKIX_PL_Initialize(PKIX_Boolean platformInitNeeded,PKIX_Boolean useArenas,void ** pPlContext)116 PKIX_PL_Initialize(
117         PKIX_Boolean platformInitNeeded,
118         PKIX_Boolean useArenas,
119         void **pPlContext)
120 {
121         void *plContext = NULL;
122 
123         PKIX_ENTER(OBJECT, "PKIX_PL_Initialize");
124 
125         /*
126          * This function can only be called once. If it has already been
127          * called, we return a positive status.
128          */
129         if (pkix_pl_initialized) {
130             PKIX_RETURN(OBJECT);
131         }
132 
133         classTableLock = PR_NewLock();
134         if (classTableLock == NULL) {
135             return PKIX_ALLOC_ERROR();
136         }
137 
138         if (PR_GetEnvSecure("NSS_STRICT_SHUTDOWN")) {
139             pkixLog = PR_NewLogModule("pkix");
140         }
141         /*
142          * Register Object, it is the base object of all other objects.
143          */
144         pkix_pl_Object_RegisterSelf(plContext);
145 
146         /*
147          * Register Error and String, since they will be needed if
148          * there is a problem in registering any other type.
149          */
150         pkix_Error_RegisterSelf(plContext);
151         pkix_pl_String_RegisterSelf(plContext);
152 
153 
154         /*
155          * We register all other system types
156          * (They don't need to be in order, but it's
157          * easier to keep track of what types are registered
158          * if we register them in the same order as their
159          * numbers, defined in pkixt.h.
160          */
161         pkix_pl_BigInt_RegisterSelf(plContext);   /* 1-10 */
162         pkix_pl_ByteArray_RegisterSelf(plContext);
163         pkix_pl_HashTable_RegisterSelf(plContext);
164         pkix_List_RegisterSelf(plContext);
165         pkix_Logger_RegisterSelf(plContext);
166         pkix_pl_Mutex_RegisterSelf(plContext);
167         pkix_pl_OID_RegisterSelf(plContext);
168         pkix_pl_RWLock_RegisterSelf(plContext);
169 
170         pkix_pl_CertBasicConstraints_RegisterSelf(plContext); /* 11-20 */
171         pkix_pl_Cert_RegisterSelf(plContext);
172         pkix_pl_CRL_RegisterSelf(plContext);
173         pkix_pl_CRLEntry_RegisterSelf(plContext);
174         pkix_pl_Date_RegisterSelf(plContext);
175         pkix_pl_GeneralName_RegisterSelf(plContext);
176         pkix_pl_CertNameConstraints_RegisterSelf(plContext);
177         pkix_pl_PublicKey_RegisterSelf(plContext);
178         pkix_TrustAnchor_RegisterSelf(plContext);
179 
180         pkix_pl_X500Name_RegisterSelf(plContext);   /* 21-30 */
181         pkix_pl_HttpCertStoreContext_RegisterSelf(plContext);
182         pkix_BuildResult_RegisterSelf(plContext);
183         pkix_ProcessingParams_RegisterSelf(plContext);
184         pkix_ValidateParams_RegisterSelf(plContext);
185         pkix_ValidateResult_RegisterSelf(plContext);
186         pkix_CertStore_RegisterSelf(plContext);
187         pkix_CertChainChecker_RegisterSelf(plContext);
188         pkix_RevocationChecker_RegisterSelf(plContext);
189         pkix_CertSelector_RegisterSelf(plContext);
190 
191         pkix_ComCertSelParams_RegisterSelf(plContext);   /* 31-40 */
192         pkix_CRLSelector_RegisterSelf(plContext);
193         pkix_ComCRLSelParams_RegisterSelf(plContext);
194         pkix_pl_CertPolicyInfo_RegisterSelf(plContext);
195         pkix_pl_CertPolicyQualifier_RegisterSelf(plContext);
196         pkix_pl_CertPolicyMap_RegisterSelf(plContext);
197         pkix_PolicyNode_RegisterSelf(plContext);
198         pkix_TargetCertCheckerState_RegisterSelf(plContext);
199         pkix_BasicConstraintsCheckerState_RegisterSelf(plContext);
200         pkix_PolicyCheckerState_RegisterSelf(plContext);
201 
202         pkix_pl_CollectionCertStoreContext_RegisterSelf(plContext); /* 41-50 */
203         pkix_CrlChecker_RegisterSelf(plContext);
204         pkix_ForwardBuilderState_RegisterSelf(plContext);
205         pkix_SignatureCheckerState_RegisterSelf(plContext);
206         pkix_NameConstraintsCheckerState_RegisterSelf(plContext);
207 #ifndef NSS_PKIX_NO_LDAP
208         pkix_pl_LdapRequest_RegisterSelf(plContext);
209         pkix_pl_LdapResponse_RegisterSelf(plContext);
210         pkix_pl_LdapDefaultClient_RegisterSelf(plContext);
211 #endif
212         pkix_pl_Socket_RegisterSelf(plContext);
213 
214         pkix_ResourceLimits_RegisterSelf(plContext); /* 51-59 */
215         pkix_pl_MonitorLock_RegisterSelf(plContext);
216         pkix_pl_InfoAccess_RegisterSelf(plContext);
217         pkix_pl_AIAMgr_RegisterSelf(plContext);
218         pkix_OcspChecker_RegisterSelf(plContext);
219         pkix_pl_OcspCertID_RegisterSelf(plContext);
220         pkix_pl_OcspRequest_RegisterSelf(plContext);
221         pkix_pl_OcspResponse_RegisterSelf(plContext);
222         pkix_pl_HttpDefaultClient_RegisterSelf(plContext);
223         pkix_VerifyNode_RegisterSelf(plContext);
224         pkix_EkuChecker_RegisterSelf(plContext);
225         pkix_pl_CrlDp_RegisterSelf(plContext);
226 
227         if (pPlContext) {
228             PKIX_CHECK(PKIX_PL_NssContext_Create
229                        (0, useArenas, NULL, &plContext),
230                        PKIX_NSSCONTEXTCREATEFAILED);
231 
232             *pPlContext = plContext;
233         }
234 
235         pkix_pl_initialized = PKIX_TRUE;
236 
237 cleanup:
238 
239         PKIX_RETURN(OBJECT);
240 }
241 
242 /*
243  * PKIX_PL_Shutdown (see comments in pkix_pl_system.h)
244  */
245 PKIX_Error *
PKIX_PL_Shutdown(void * plContext)246 PKIX_PL_Shutdown(void *plContext)
247 {
248 #ifdef DEBUG
249         PKIX_UInt32 numLeakedObjects = 0;
250 #endif
251 
252         PKIX_ENTER(OBJECT, "PKIX_PL_Shutdown");
253 
254         if (!pkix_pl_initialized) {
255             /* The library was not initilized */
256             PKIX_RETURN(OBJECT);
257         }
258 
259         PR_DestroyLock(classTableLock);
260 
261         pkix_pl_HttpCertStore_Shutdown(plContext);
262 
263 #ifdef DEBUG
264         numLeakedObjects = pkix_pl_lifecycle_ObjectLeakCheck(NULL);
265         if (PR_GetEnvSecure("NSS_STRICT_SHUTDOWN")) {
266            PORT_Assert(numLeakedObjects == 0);
267         }
268 #else
269         pkix_pl_lifecycle_ObjectLeakCheck(NULL);
270 #endif
271 
272         if (plContext != NULL) {
273                 PKIX_PL_NssContext_Destroy(plContext);
274         }
275 
276         pkix_pl_initialized = PKIX_FALSE;
277 
278         PKIX_RETURN(OBJECT);
279 }
280