andre@0: /* This Source Code Form is subject to the terms of the Mozilla Public andre@0: * License, v. 2.0. If a copy of the MPL was not distributed with this andre@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ andre@0: /* andre@0: * pkix_pl_lifecycle.c andre@0: * andre@0: * Lifecycle Functions for the PKIX PL library. andre@0: * andre@0: */ andre@0: andre@0: #include "pkix_pl_lifecycle.h" andre@0: andre@0: PKIX_Boolean pkix_pl_initialized = PKIX_FALSE; andre@0: pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; andre@0: PRLock *classTableLock; andre@0: PRLogModuleInfo *pkixLog = NULL; andre@0: andre@0: /* andre@0: * PKIX_ALLOC_ERROR is a special error object hard-coded into the andre@0: * pkix_error.o object file. It is thrown if system memory cannot be andre@0: * allocated. PKIX_ALLOC_ERROR is immutable. andre@0: * IncRef, DecRef, and Settor functions cannot be called. andre@0: */ andre@0: andre@0: /* Keep this structure definition here for its is used only once here */ andre@0: struct PKIX_Alloc_Error_ObjectStruct { andre@0: PKIX_PL_Object header; andre@0: PKIX_Error error; andre@0: }; andre@0: typedef struct PKIX_Alloc_Error_ObjectStruct PKIX_Alloc_Error_Object; andre@0: andre@0: static const PKIX_Alloc_Error_Object pkix_Alloc_Error_Data = { andre@0: { andre@0: PKIX_MAGIC_HEADER, /* PRUint64 magicHeader */ andre@0: (PKIX_UInt32)PKIX_ERROR_TYPE, /* PKIX_UInt32 type */ andre@0: (PKIX_UInt32)1, /* PKIX_UInt32 references */ andre@0: /* Warning! Cannot Ref Count with NULL lock */ andre@0: (void *)0, /* PRLock *lock */ andre@0: (PKIX_PL_String *)0, /* PKIX_PL_String *stringRep */ andre@0: (PKIX_UInt32)0, /* PKIX_UInt32 hashcode */ andre@0: (PKIX_Boolean)PKIX_FALSE, /* PKIX_Boolean hashcodeCached */ andre@0: }, { andre@0: (PKIX_ERRORCODE)0, /* PKIX_ERRORCODE errCode; */ andre@0: (PKIX_ERRORCLASS)PKIX_FATAL_ERROR,/* PKIX_ERRORCLASS errClass */ andre@0: (PKIX_UInt32)SEC_ERROR_LIBPKIX_INTERNAL, /* default PL Error Code */ andre@0: (PKIX_Error *)0, /* PKIX_Error *cause */ andre@0: (PKIX_PL_Object *)0, /* PKIX_PL_Object *info */ andre@0: } andre@0: }; andre@0: andre@0: PKIX_Error* PKIX_ALLOC_ERROR(void) andre@0: { andre@0: return (PKIX_Error *)&pkix_Alloc_Error_Data.error; andre@0: } andre@0: andre@0: #ifdef PKIX_OBJECT_LEAK_TEST andre@0: SECStatus andre@0: pkix_pl_lifecycle_ObjectTableUpdate(int *objCountTable) andre@0: { andre@0: int typeCounter = 0; andre@0: andre@0: for (; typeCounter < PKIX_NUMTYPES; typeCounter++) { andre@0: pkix_ClassTable_Entry *entry = &systemClasses[typeCounter]; andre@0: andre@0: objCountTable[typeCounter] = entry->objCounter; andre@0: } andre@0: andre@0: return SECSuccess; andre@0: } andre@0: #endif /* PKIX_OBJECT_LEAK_TEST */ andre@0: andre@0: andre@0: PKIX_UInt32 andre@0: pkix_pl_lifecycle_ObjectLeakCheck(int *initObjCountTable) andre@0: { andre@0: int typeCounter = 0; andre@0: PKIX_UInt32 numObjects = 0; andre@0: char classNameBuff[128]; andre@0: char *className = NULL; andre@0: andre@0: for (; typeCounter < PKIX_NUMTYPES; typeCounter++) { andre@0: pkix_ClassTable_Entry *entry = &systemClasses[typeCounter]; andre@0: PKIX_UInt32 objCountDiff = entry->objCounter; andre@0: andre@0: if (initObjCountTable) { andre@0: PKIX_UInt32 initialCount = initObjCountTable[typeCounter]; andre@0: objCountDiff = (entry->objCounter > initialCount) ? andre@0: entry->objCounter - initialCount : 0; andre@0: } andre@0: andre@0: numObjects += objCountDiff; andre@0: andre@0: if (!pkixLog || !objCountDiff) { andre@0: continue; andre@0: } andre@0: className = entry->description; andre@0: if (!className) { andre@0: className = classNameBuff; andre@0: PR_snprintf(className, 128, "Unknown(ref %d)", andre@0: entry->objCounter); andre@0: } andre@0: andre@0: PR_LOG(pkixLog, 1, ("Class %s leaked %d objects of " andre@0: "size %d bytes, total = %d bytes\n", className, andre@0: objCountDiff, entry->typeObjectSize, andre@0: objCountDiff * entry->typeObjectSize)); andre@0: } andre@0: andre@0: return numObjects; andre@0: } andre@0: andre@0: /* andre@0: * PKIX_PL_Initialize (see comments in pkix_pl_system.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_Initialize( andre@0: PKIX_Boolean platformInitNeeded, andre@0: PKIX_Boolean useArenas, andre@0: void **pPlContext) andre@0: { andre@0: void *plContext = NULL; andre@0: andre@0: PKIX_ENTER(OBJECT, "PKIX_PL_Initialize"); andre@0: andre@0: /* andre@0: * This function can only be called once. If it has already been andre@0: * called, we return a positive status. andre@0: */ andre@0: if (pkix_pl_initialized) { andre@0: PKIX_RETURN(OBJECT); andre@0: } andre@0: andre@0: classTableLock = PR_NewLock(); andre@0: if (classTableLock == NULL) { andre@0: return PKIX_ALLOC_ERROR(); andre@0: } andre@0: andre@0: if (PR_GetEnv("NSS_STRICT_SHUTDOWN")) { andre@0: pkixLog = PR_NewLogModule("pkix"); andre@0: } andre@0: /* andre@0: * Register Object, it is the base object of all other objects. andre@0: */ andre@0: pkix_pl_Object_RegisterSelf(plContext); andre@0: andre@0: /* andre@0: * Register Error and String, since they will be needed if andre@0: * there is a problem in registering any other type. andre@0: */ andre@0: pkix_Error_RegisterSelf(plContext); andre@0: pkix_pl_String_RegisterSelf(plContext); andre@0: andre@0: andre@0: /* andre@0: * We register all other system types andre@0: * (They don't need to be in order, but it's andre@0: * easier to keep track of what types are registered andre@0: * if we register them in the same order as their andre@0: * numbers, defined in pkixt.h. andre@0: */ andre@0: pkix_pl_BigInt_RegisterSelf(plContext); /* 1-10 */ andre@0: pkix_pl_ByteArray_RegisterSelf(plContext); andre@0: pkix_pl_HashTable_RegisterSelf(plContext); andre@0: pkix_List_RegisterSelf(plContext); andre@0: pkix_Logger_RegisterSelf(plContext); andre@0: pkix_pl_Mutex_RegisterSelf(plContext); andre@0: pkix_pl_OID_RegisterSelf(plContext); andre@0: pkix_pl_RWLock_RegisterSelf(plContext); andre@0: andre@0: pkix_pl_CertBasicConstraints_RegisterSelf(plContext); /* 11-20 */ andre@0: pkix_pl_Cert_RegisterSelf(plContext); andre@0: pkix_pl_CRL_RegisterSelf(plContext); andre@0: pkix_pl_CRLEntry_RegisterSelf(plContext); andre@0: pkix_pl_Date_RegisterSelf(plContext); andre@0: pkix_pl_GeneralName_RegisterSelf(plContext); andre@0: pkix_pl_CertNameConstraints_RegisterSelf(plContext); andre@0: pkix_pl_PublicKey_RegisterSelf(plContext); andre@0: pkix_TrustAnchor_RegisterSelf(plContext); andre@0: andre@0: pkix_pl_X500Name_RegisterSelf(plContext); /* 21-30 */ andre@0: pkix_pl_HttpCertStoreContext_RegisterSelf(plContext); andre@0: pkix_BuildResult_RegisterSelf(plContext); andre@0: pkix_ProcessingParams_RegisterSelf(plContext); andre@0: pkix_ValidateParams_RegisterSelf(plContext); andre@0: pkix_ValidateResult_RegisterSelf(plContext); andre@0: pkix_CertStore_RegisterSelf(plContext); andre@0: pkix_CertChainChecker_RegisterSelf(plContext); andre@0: pkix_RevocationChecker_RegisterSelf(plContext); andre@0: pkix_CertSelector_RegisterSelf(plContext); andre@0: andre@0: pkix_ComCertSelParams_RegisterSelf(plContext); /* 31-40 */ andre@0: pkix_CRLSelector_RegisterSelf(plContext); andre@0: pkix_ComCRLSelParams_RegisterSelf(plContext); andre@0: pkix_pl_CertPolicyInfo_RegisterSelf(plContext); andre@0: pkix_pl_CertPolicyQualifier_RegisterSelf(plContext); andre@0: pkix_pl_CertPolicyMap_RegisterSelf(plContext); andre@0: pkix_PolicyNode_RegisterSelf(plContext); andre@0: pkix_TargetCertCheckerState_RegisterSelf(plContext); andre@0: pkix_BasicConstraintsCheckerState_RegisterSelf(plContext); andre@0: pkix_PolicyCheckerState_RegisterSelf(plContext); andre@0: andre@0: pkix_pl_CollectionCertStoreContext_RegisterSelf(plContext); /* 41-50 */ andre@0: pkix_CrlChecker_RegisterSelf(plContext); andre@0: pkix_ForwardBuilderState_RegisterSelf(plContext); andre@0: pkix_SignatureCheckerState_RegisterSelf(plContext); andre@0: pkix_NameConstraintsCheckerState_RegisterSelf(plContext); andre@0: #ifndef NSS_PKIX_NO_LDAP andre@0: pkix_pl_LdapRequest_RegisterSelf(plContext); andre@0: pkix_pl_LdapResponse_RegisterSelf(plContext); andre@0: pkix_pl_LdapDefaultClient_RegisterSelf(plContext); andre@0: #endif andre@0: pkix_pl_Socket_RegisterSelf(plContext); andre@0: andre@0: pkix_ResourceLimits_RegisterSelf(plContext); /* 51-59 */ andre@0: pkix_pl_MonitorLock_RegisterSelf(plContext); andre@0: pkix_pl_InfoAccess_RegisterSelf(plContext); andre@0: pkix_pl_AIAMgr_RegisterSelf(plContext); andre@0: pkix_OcspChecker_RegisterSelf(plContext); andre@0: pkix_pl_OcspCertID_RegisterSelf(plContext); andre@0: pkix_pl_OcspRequest_RegisterSelf(plContext); andre@0: pkix_pl_OcspResponse_RegisterSelf(plContext); andre@0: pkix_pl_HttpDefaultClient_RegisterSelf(plContext); andre@0: pkix_VerifyNode_RegisterSelf(plContext); andre@0: pkix_EkuChecker_RegisterSelf(plContext); andre@0: pkix_pl_CrlDp_RegisterSelf(plContext); andre@0: andre@0: if (pPlContext) { andre@0: PKIX_CHECK(PKIX_PL_NssContext_Create andre@0: (0, useArenas, NULL, &plContext), andre@0: PKIX_NSSCONTEXTCREATEFAILED); andre@0: andre@0: *pPlContext = plContext; andre@0: } andre@0: andre@0: pkix_pl_initialized = PKIX_TRUE; andre@0: andre@0: cleanup: andre@0: andre@0: PKIX_RETURN(OBJECT); andre@0: } andre@0: andre@0: /* andre@0: * PKIX_PL_Shutdown (see comments in pkix_pl_system.h) andre@0: */ andre@0: PKIX_Error * andre@0: PKIX_PL_Shutdown(void *plContext) andre@0: { andre@0: PKIX_UInt32 numLeakedObjects = 0; andre@0: andre@0: PKIX_ENTER(OBJECT, "PKIX_PL_Shutdown"); andre@0: andre@0: if (!pkix_pl_initialized) { andre@0: /* The library was not initilized */ andre@0: PKIX_RETURN(OBJECT); andre@0: } andre@0: andre@0: PR_DestroyLock(classTableLock); andre@0: andre@0: pkix_pl_HttpCertStore_Shutdown(plContext); andre@0: andre@0: numLeakedObjects = pkix_pl_lifecycle_ObjectLeakCheck(NULL); andre@0: if (PR_GetEnv("NSS_STRICT_SHUTDOWN")) { andre@0: PORT_Assert(numLeakedObjects == 0); andre@0: } andre@0: andre@0: if (plContext != NULL) { andre@0: PKIX_PL_NssContext_Destroy(plContext); andre@0: } andre@0: andre@0: pkix_pl_initialized = PKIX_FALSE; andre@0: andre@0: PKIX_RETURN(OBJECT); andre@0: }