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