| /* 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); |
| } |