/* * FUNCTION: pkix_UnlockObject * DESCRIPTION: * * Unlocks the object pointed to by "object". * * PARAMETERS: * "object" * Address of Object. Must be non-NULL * "plContext" * Platform-specific context pointer. * THREAD SAFETY: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) * RETURNS: * Returns NULL if the function succeeds. * Returns a Fatal Error if the function fails in an unrecoverable way. */ PKIX_Error * pkix_UnlockObject( PKIX_PL_Object *object, void *plContext) { PKIX_PL_Object *objectHeader; PRStatus result; PKIX_ENTER(OBJECT, "pkix_UnlockObject"); PKIX_NULLCHECK_ONE(object); if (object == (PKIX_PL_Object *)PKIX_ALLOC_ERROR()) { goto cleanup; } PKIX_OBJECT_DEBUG("\tShifting object pointer).\n"); /* The header is sizeof(PKIX_PL_Object) before the object pointer */ objectHeader = object-1; PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); result = PR_Unlock(objectHeader->lock); if (result == PR_FAILURE) { PKIX_OBJECT_DEBUG("\tPR_Unlock failed.).\n"); PKIX_ERROR_FATAL(PKIX_ERRORUNLOCKINGOBJECT); } cleanup: PKIX_RETURN(OBJECT); }
/* * FUNCTION: pkix_pl_CRL_GetSignatureAlgId * * DESCRIPTION: * Retrieves a pointer to the OID that represents the signature algorithm of * the CRL pointed to by "crl" and stores it at "pSignatureAlgId". * * AlgorithmIdentifier ::= SEQUENCE { * algorithm OBJECT IDENTIFIER, * parameters ANY DEFINED BY algorithm OPTIONAL } * * PARAMETERS: * "crl" * Address of CRL whose signature algorithm OID is to be stored. * Must be non-NULL. * "pSignatureAlgId" * Address where object pointer will be stored. Must be non-NULL. * "plContext" * Platform-specific context pointer. * THREAD SAFETY: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) * RETURNS: * Returns NULL if the function succeeds. * Returns a CRL Error if the function fails in a non-fatal way. * Returns a Fatal Error if the function fails in an unrecoverable way. */ static PKIX_Error * pkix_pl_CRL_GetSignatureAlgId( PKIX_PL_CRL *crl, PKIX_PL_OID **pSignatureAlgId, void *plContext) { CERTCrl *nssCrl = NULL; PKIX_PL_OID *signatureAlgId = NULL; SECAlgorithmID algorithm; SECItem algBytes; char *asciiOID = NULL; PKIX_ENTER(CRL, "pkix_pl_CRL_GetSignatureAlgId"); PKIX_NULLCHECK_THREE(crl, crl->nssSignedCrl, pSignatureAlgId); /* if we don't have a cached copy from before, we create one */ if (crl->signatureAlgId == NULL) { PKIX_OBJECT_LOCK(crl); if (crl->signatureAlgId == NULL) { nssCrl = &(crl->nssSignedCrl->crl); algorithm = nssCrl->signatureAlg; algBytes = algorithm.algorithm; PKIX_NULLCHECK_ONE(algBytes.data); if (algBytes.len == 0) { PKIX_ERROR_FATAL(PKIX_OIDBYTESLENGTH0); } PKIX_CHECK(pkix_pl_oidBytes2Ascii (&algBytes, &asciiOID, plContext), PKIX_OIDBYTES2ASCIIFAILED); PKIX_CHECK(PKIX_PL_OID_Create (asciiOID, &signatureAlgId, plContext), PKIX_OIDCREATEFAILED); /* save a cached copy in case it is asked for again */ crl->signatureAlgId = signatureAlgId; } PKIX_OBJECT_UNLOCK(crl); } PKIX_INCREF(crl->signatureAlgId); *pSignatureAlgId = crl->signatureAlgId; cleanup: PKIX_FREE(asciiOID); PKIX_RETURN(CRL); }
/* * FUNCTION: PKIX_PL_Object_IsTypeRegistered (see comments in pkix_pl_system.h) */ PKIX_Error * PKIX_PL_Object_IsTypeRegistered( PKIX_UInt32 objType, PKIX_Boolean *pBool, void *plContext) { #ifdef PKIX_USER_OBJECT_TYPE pkix_ClassTable_Entry *ctEntry = NULL; #endif PKIX_ENTER(OBJECT, "PKIX_PL_Object_IsTypeRegistered"); PKIX_NULLCHECK_ONE(pBool); /* first, we handle the system types */ if (objType < PKIX_NUMTYPES) { *pBool = PKIX_TRUE; goto cleanup; } #ifndef PKIX_USER_OBJECT_TYPE PORT_Assert (0); pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; pkixErrorClass = PKIX_FATAL_ERROR; #else PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); PR_Lock(classTableLock); pkixErrorResult = pkix_pl_PrimHashTable_Lookup (classTable, (void *)&objType, objType, NULL, (void **)&ctEntry, plContext); PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); PR_Unlock(classTableLock); if (pkixErrorResult){ PKIX_ERROR_FATAL(PKIX_COULDNOTLOOKUPINHASHTABLE); } *pBool = (ctEntry != NULL); #endif /* PKIX_USER_OBJECT_TYPE */ cleanup: PKIX_RETURN(OBJECT); }
/* * FUNCTION: pkix_pl_ipAddrBytes2Ascii * DESCRIPTION: * * Converts the DER encoding of an IPAddress pointed to by "secItem" to an * ASCII representation and stores the result at "pAscii". The ASCII * representation is guaranteed to end with a NUL character. The input * SECItem must contain non-NULL data and must have a positive length. * * The return value "pAscii" is not reference-counted and will need to * be freed with PKIX_PL_Free. * XXX this function assumes that IPv4 addresses are being used * XXX what about IPv6? can NSS tell the difference * * PARAMETERS * "secItem" * Address of SECItem which contains bytes and length of DER encoding. * Must be non-NULL. * "pAscii" * Address where object pointer will be stored. Must be non-NULL. * "plContext" * Platform-specific context pointer. * THREAD SAFETY: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) * RETURNS: * Returns NULL if the function succeeds. * Returns an Object Error if the function fails in a non-fatal way. * Returns a Fatal Error if the function fails in an unrecoverable way. */ PKIX_Error * pkix_pl_ipAddrBytes2Ascii( SECItem *secItem, char **pAscii, void *plContext) { char *data = NULL; PKIX_UInt32 *tokens = NULL; PKIX_UInt32 numTokens = 0; PKIX_UInt32 i = 0; char *asciiString = NULL; PKIX_ENTER(OBJECT, "pkix_pl_ipAddrBytes2Ascii"); PKIX_NULLCHECK_THREE(secItem, pAscii, secItem->data); if (secItem->len == 0) { PKIX_ERROR_FATAL(PKIX_IPADDRBYTES2ASCIIDATALENGTHZERO); } data = (char *)(secItem->data); numTokens = secItem->len; /* allocate space for array of integers */ PKIX_CHECK(PKIX_PL_Malloc (numTokens * sizeof (PKIX_UInt32), (void **)&tokens, plContext), PKIX_MALLOCFAILED); /* populate array of integers */ for (i = 0; i < numTokens; i++){ tokens[i] = data[i]; } /* convert array of integers to ASCII */ PKIX_CHECK(pkix_pl_helperBytes2Ascii (tokens, numTokens, &asciiString, plContext), PKIX_HELPERBYTES2ASCIIFAILED); *pAscii = asciiString; cleanup: PKIX_FREE(tokens); PKIX_RETURN(OBJECT); }
/* * FUNCTION: pkix_Destroy_Object * DESCRIPTION: * * Destroys and deallocates Object pointed to by "object". The caller is * assumed to hold the Object's lock, which is acquired in * PKIX_PL_Object_DecRef(). * * PARAMETERS: * "object" * Address of Object to destroy. Must be non-NULL. * "plContext" * Platform-specific context pointer. * THREAD SAFETY: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) * RETURNS: * Returns NULL if the function succeeds. * Returns a Fatal Error if the function fails in an unrecoverable way. */ static PKIX_Error * pkix_pl_Object_Destroy( PKIX_PL_Object *object, void *plContext) { PKIX_PL_Object *objectHeader = NULL; PKIX_ENTER(OBJECT, "pkix_pl_Object_Destroy"); PKIX_NULLCHECK_ONE(object); #ifdef PKIX_OBJECT_LEAK_TEST PKIX_CHECK_FATAL(pkix_pl_Object_GetHeader(object, &objectHeader, plContext), PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); #else PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext), PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); #endif /* PKIX_OBJECT_LEAK_TEST */ /* Attempt to delete an object still being used */ if (objectHeader->references != 0) { PKIX_ERROR_FATAL(PKIX_OBJECTSTILLREFERENCED); } PKIX_DECREF(objectHeader->stringRep); /* Destroy this object's lock */ PKIX_OBJECT_DEBUG("\tCalling PR_DestroyLock).\n"); PR_DestroyLock(objectHeader->lock); objectHeader->lock = NULL; object = NULL; objectHeader->magicHeader = PKIX_MAGIC_HEADER_DESTROYED; #ifdef PKIX_OBJECT_LEAK_TEST memset(objectHeader, 0xbf, systemClasses[PKIX_OBJECT_TYPE].typeObjectSize); #endif PKIX_FREE(objectHeader); cleanup: #ifdef PKIX_OBJECT_LEAK_TEST fatal: #endif PKIX_RETURN(OBJECT); }
/* * FUNCTION: pkix_pl_LdapCertStore_GetCert * (see description of PKIX_CertStore_CertCallback in pkix_certstore.h) */ PKIX_Error * pkix_pl_LdapCertStore_GetCert( PKIX_CertStore *store, PKIX_CertSelector *selector, PKIX_VerifyNode *verifyNode, void **pNBIOContext, PKIX_List **pCertList, void *plContext) { PRArenaPool *requestArena = NULL; LDAPRequestParams requestParams; void *pollDesc = NULL; PKIX_Int32 minPathLen = 0; PKIX_Boolean cacheFlag = PKIX_FALSE; PKIX_ComCertSelParams *params = NULL; PKIX_PL_LdapCertStoreContext *lcs = NULL; PKIX_List *responses = NULL; PKIX_List *unfilteredCerts = NULL; PKIX_List *filteredCerts = NULL; PKIX_PL_X500Name *subjectName = 0; PKIX_ENTER(CERTSTORE, "pkix_pl_LdapCertStore_GetCert"); PKIX_NULLCHECK_THREE(store, selector, pCertList); requestParams.baseObject = "c=US"; requestParams.scope = WHOLE_SUBTREE; requestParams.derefAliases = NEVER_DEREF; requestParams.sizeLimit = 0; requestParams.timeLimit = 0; /* Prepare elements for request filter */ /* * Get a short-lived arena. We'll be done with this space once * the request is encoded. */ requestArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (!requestArena) { PKIX_ERROR_FATAL(PKIX_OUTOFMEMORY); } PKIX_CHECK(PKIX_CertSelector_GetCommonCertSelectorParams (selector, ¶ms, plContext), PKIX_CERTSELECTORGETCOMCERTSELPARAMSFAILED); /* * If we have the subject name for the desired subject, * ask the server for Certs with that subject. */ PKIX_CHECK(PKIX_ComCertSelParams_GetSubject (params, &subjectName, plContext), PKIX_COMCERTSELPARAMSGETSUBJECTFAILED); PKIX_CHECK(PKIX_ComCertSelParams_GetBasicConstraints (params, &minPathLen, plContext), PKIX_COMCERTSELPARAMSGETBASICCONSTRAINTSFAILED); if (subjectName) { PKIX_CHECK(pkix_pl_LdapCertStore_MakeNameAVAList (requestArena, subjectName, &(requestParams.nc), plContext), PKIX_LDAPCERTSTOREMAKENAMEAVALISTFAILED); if (*requestParams.nc == NULL) { /* * The subjectName may not include any components * that we know how to encode. We do not return * an error, because the caller did not necessarily * do anything wrong, but we return an empty List. */ PKIX_PL_NSSCALL(CERTSTORE, PORT_FreeArena, (requestArena, PR_FALSE)); PKIX_CHECK(PKIX_List_Create(&filteredCerts, plContext), PKIX_LISTCREATEFAILED); PKIX_CHECK(PKIX_List_SetImmutable (filteredCerts, plContext), PKIX_LISTSETIMMUTABLEFAILED); *pNBIOContext = NULL; *pCertList = filteredCerts; filteredCerts = NULL; goto cleanup; } } else { PKIX_ERROR(PKIX_INSUFFICIENTCRITERIAFORCERTQUERY); } /* Prepare attribute field of request */ requestParams.attributes = 0; if (minPathLen < 0) { requestParams.attributes |= LDAPATTR_USERCERT; } if (minPathLen > -2) { requestParams.attributes |= LDAPATTR_CACERT | LDAPATTR_CROSSPAIRCERT; } /* All request fields are done */ PKIX_CHECK(PKIX_CertStore_GetCertStoreContext (store, (PKIX_PL_Object **)&lcs, plContext), PKIX_CERTSTOREGETCERTSTORECONTEXTFAILED); PKIX_CHECK(PKIX_PL_LdapClient_InitiateRequest ((PKIX_PL_LdapClient *)lcs, &requestParams, &pollDesc, &responses, plContext), PKIX_LDAPCLIENTINITIATEREQUESTFAILED); PKIX_CHECK(pkix_pl_LdapCertStore_DestroyAVAList (requestParams.nc, plContext), PKIX_LDAPCERTSTOREDESTROYAVALISTFAILED); if (requestArena) { PKIX_PL_NSSCALL(CERTSTORE, PORT_FreeArena, (requestArena, PR_FALSE)); requestArena = NULL; } if (pollDesc != NULL) { /* client is waiting for non-blocking I/O to complete */ *pNBIOContext = (void *)pollDesc; *pCertList = NULL; goto cleanup; } /* LdapClient has given us a response! */ if (responses) { PKIX_CHECK(PKIX_CertStore_GetCertStoreCacheFlag (store, &cacheFlag, plContext), PKIX_CERTSTOREGETCERTSTORECACHEFLAGFAILED); PKIX_CHECK(pkix_pl_LdapCertStore_BuildCertList (responses, &unfilteredCerts, plContext), PKIX_LDAPCERTSTOREBUILDCERTLISTFAILED); PKIX_CHECK(pkix_CertSelector_Select (selector, unfilteredCerts, &filteredCerts, plContext), PKIX_CERTSELECTORSELECTFAILED); } *pNBIOContext = NULL; *pCertList = filteredCerts; filteredCerts = NULL; cleanup: PKIX_DECREF(params); PKIX_DECREF(subjectName); PKIX_DECREF(responses); PKIX_DECREF(unfilteredCerts); PKIX_DECREF(filteredCerts); PKIX_DECREF(lcs); PKIX_RETURN(CERTSTORE); }
/* * FUNCTION: PKIX_PL_Object_Hashcode (see comments in pkix_pl_system.h) */ PKIX_Error * PKIX_PL_Object_Hashcode( PKIX_PL_Object *object, PKIX_UInt32 *pValue, void *plContext) { PKIX_PL_Object *objectHeader = NULL; PKIX_PL_HashcodeCallback func = NULL; pkix_ClassTable_Entry entry; PKIX_UInt32 objectHash; PKIX_ENTER(OBJECT, "PKIX_PL_Object_Hashcode"); PKIX_NULLCHECK_TWO(object, pValue); /* Shift pointer from user data to object header */ PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext), PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); /* if we don't have a cached copy from before, we create one */ if (!objectHeader->hashcodeCached){ PKIX_UInt32 objType = objectHeader->type; /* first, special handling for system types */ if (objType >= PKIX_NUMTYPES){ #ifdef PKIX_USER_OBJECT_TYPE pkix_ClassTable_Entry *ctEntry = NULL; PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); PR_Lock(classTableLock); pkixErrorResult = pkix_pl_PrimHashTable_Lookup (classTable, (void *)&objType, objType, NULL, (void **)&ctEntry, plContext); PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); PR_Unlock(classTableLock); if (pkixErrorResult){ PKIX_ERROR_FATAL (PKIX_ERRORGETTINGCLASSTABLEENTRY); } if ((ctEntry == NULL) || (ctEntry->hashcodeFunction == NULL)) { PKIX_ERROR_FATAL(PKIX_UNDEFINEDCALLBACK); } func = ctEntry->hashcodeFunction; #else PORT_Assert (0); pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; pkixErrorClass = PKIX_FATAL_ERROR; goto cleanup; #endif /* PKIX_USER_OBJECT_TYPE */ } else { entry = systemClasses[objType]; func = entry.hashcodeFunction; if (func == NULL){ func = pkix_pl_Object_Hashcode_Default; } } PKIX_CHECK(func(object, &objectHash, plContext), PKIX_OBJECTSPECIFICFUNCTIONFAILED); if (!objectHeader->hashcodeCached){ PKIX_CHECK(pkix_LockObject(object, plContext), PKIX_ERRORLOCKINGOBJECT); if (!objectHeader->hashcodeCached){ /* save cached copy in case we need it again */ objectHeader->hashcode = objectHash; objectHeader->hashcodeCached = PKIX_TRUE; } PKIX_CHECK(pkix_UnlockObject(object, plContext), PKIX_ERRORUNLOCKINGOBJECT); } } *pValue = objectHeader->hashcode; cleanup: PKIX_RETURN(OBJECT); }
/* * FUNCTION: pkix_pl_oidBytes2Ascii * DESCRIPTION: * * Converts the DER encoding of an OID pointed to by "secItem" to an ASCII * representation and stores it at "pAscii". The ASCII representation is * guaranteed to end with a NUL character. The input SECItem must contain * non-NULL data and must have a positive length. * * Example: the six bytes {2a 86 48 86 f7 0d} represent the * four integer tokens {1, 2, 840, 113549}, which we will convert * into ASCII yielding "1.2.840.113549" * * The return value "pAscii" is not reference-counted and will need to * be freed with PKIX_PL_Free. * * PARAMETERS * "secItem" * Address of SECItem which contains bytes and length of DER encoding. * Must be non-NULL. * "pAscii" * Address where object pointer will be stored. Must be non-NULL. * "plContext" * Platform-specific context pointer. * THREAD SAFETY: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) * RETURNS: * Returns NULL if the function succeeds. * Returns an OID Error if the function fails in a non-fatal way. * Returns a Fatal Error if the function fails in an unrecoverable way. */ PKIX_Error * pkix_pl_oidBytes2Ascii( SECItem *secItem, char **pAscii, void *plContext) { char *data = NULL; PKIX_UInt32 *tokens = NULL; PKIX_UInt32 token = 0; PKIX_UInt32 numBytes = 0; PKIX_UInt32 numTokens = 0; PKIX_UInt32 i = 0, x = 0, y = 0; PKIX_UInt32 index = 0; char *asciiString = NULL; PKIX_ENTER(OID, "pkix_pl_oidBytes2Ascii"); PKIX_NULLCHECK_THREE(secItem, pAscii, secItem->data); if (secItem->len == 0) { PKIX_ERROR_FATAL(PKIX_OIDBYTES2ASCIIDATALENGTHZERO); } data = (char *)(secItem->data); numBytes = secItem->len; numTokens = 0; /* calculate how many integer tokens are represented by the bytes. */ for (i = 0; i < numBytes; i++){ if ((data[i] & 0x080) == 0){ numTokens++; } } /* if we are unable to retrieve any tokens at all, we throw an error */ if (numTokens == 0){ PKIX_ERROR(PKIX_INVALIDDERENCODINGFOROID); } /* add one more token b/c the first byte always contains two tokens */ numTokens++; /* allocate space for array of integers */ PKIX_CHECK(PKIX_PL_Malloc (numTokens * sizeof (PKIX_UInt32), (void **)&tokens, plContext), PKIX_MALLOCFAILED); /* populate array of integers */ for (i = 0; i < numTokens; i++){ /* retrieve integer token */ PKIX_CHECK(pkix_pl_getOIDToken (data, index, &token, &index, plContext), PKIX_GETOIDTOKENFAILED); if (i == 0){ /* * special case: the first DER-encoded byte represents * two tokens. We take advantage of fact that first * token must be 0, 1, or 2; and second token must be * between {0, 39} inclusive if first token is 0 or 1. */ if (token < 40) x = 0; else if (token < 80) x = 1; else x = 2; y = token - (x * 40); tokens[0] = x; tokens[1] = y; i++; } else { tokens[i] = token; } } /* convert array of integers to ASCII */ PKIX_CHECK(pkix_pl_helperBytes2Ascii (tokens, numTokens, &asciiString, plContext), PKIX_HELPERBYTES2ASCIIFAILED); *pAscii = asciiString; cleanup: PKIX_FREE(tokens); PKIX_RETURN(OID); }
/* * FUNCTION: pkix_pl_helperBytes2Ascii * DESCRIPTION: * * Converts an array of integers pointed to by "tokens" with a length of * "numTokens", to an ASCII string consisting of those integers with dots in * between them and stores the result at "pAscii". The ASCII representation is * guaranteed to end with a NUL character. This is particularly useful for * OID's and IP Addresses. * * The return value "pAscii" is not reference-counted and will need to * be freed with PKIX_PL_Free. * * PARAMETERS * "tokens" * Address of array of integers. Must be non-NULL. * "numTokens" * Length of array of integers. Must be non-zero. * "pAscii" * Address where object pointer will be stored. Must be non-NULL. * "plContext" * Platform-specific context pointer. * THREAD SAFETY: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) * RETURNS: * Returns NULL if the function succeeds. * Returns an Object Error if the function fails in a non-fatal way. * Returns a Fatal Error if the function fails in an unrecoverable way. */ PKIX_Error * pkix_pl_helperBytes2Ascii( PKIX_UInt32 *tokens, PKIX_UInt32 numTokens, char **pAscii, void *plContext) { char *tempString = NULL; char *outputString = NULL; char *format = "%d"; PKIX_UInt32 i = 0; PKIX_UInt32 outputLen = 0; PKIX_Int32 error; PKIX_ENTER(OBJECT, "pkix_pl_helperBytes2Ascii"); PKIX_NULLCHECK_TWO(tokens, pAscii); if (numTokens == 0) { PKIX_ERROR_FATAL(PKIX_HELPERBYTES2ASCIINUMTOKENSZERO); } /* * tempString will hold the string representation of a PKIX_UInt32 type * The maximum value that can be held by an unsigned 32-bit integer * is (2^32 - 1) = 4294967295 (which is ten digits long) * Since tempString will hold the string representation of a * PKIX_UInt32, we allocate 11 bytes for it (1 byte for '\0') */ PKIX_CHECK(PKIX_PL_Malloc (MAX_DIGITS_32 + 1, (void **)&tempString, plContext), PKIX_MALLOCFAILED); for (i = 0; i < numTokens; i++){ PKIX_OBJECT_DEBUG("\tCalling PR_snprintf).\n"); error = PR_snprintf(tempString, MAX_DIGITS_32 + 1, format, tokens[i]); if (error == -1){ PKIX_ERROR(PKIX_PRSNPRINTFFAILED); } PKIX_OBJECT_DEBUG("\tCalling PL_strlen).\n"); outputLen += PL_strlen(tempString); /* Include a dot to separate each number */ outputLen++; } /* Allocate space for the destination string */ PKIX_CHECK(PKIX_PL_Malloc (outputLen, (void **)&outputString, plContext), PKIX_MALLOCFAILED); *outputString = '\0'; /* Concatenate all strings together */ for (i = 0; i < numTokens; i++){ PKIX_OBJECT_DEBUG("\tCalling PR_snprintf).\n"); error = PR_snprintf(tempString, MAX_DIGITS_32 + 1, format, tokens[i]); if (error == -1){ PKIX_ERROR(PKIX_PRSNPRINTFFAILED); } PKIX_OBJECT_DEBUG("\tCalling PL_strcat).\n"); (void) PL_strcat(outputString, tempString); /* we don't want to put a "." at the very end */ if (i < (numTokens - 1)){ PKIX_OBJECT_DEBUG("\tCalling PL_strcat).\n"); (void) PL_strcat(outputString, "."); } } /* Ensure output string ends with terminating null */ outputString[outputLen-1] = '\0'; *pAscii = outputString; outputString = NULL; cleanup: PKIX_FREE(outputString); PKIX_FREE(tempString); PKIX_RETURN(OBJECT); }
PKIX_Error * pkix_pl_AIAMgr_GetLDAPCerts( PKIX_PL_AIAMgr *aiaMgr, PKIX_PL_InfoAccess *ia, void **pNBIOContext, PKIX_List **pCerts, void *plContext) { PKIX_List *result = NULL; PKIX_PL_GeneralName *location = NULL; PKIX_PL_LdapClient *client = NULL; LDAPRequestParams request; PLArenaPool *arena = NULL; char *domainName = NULL; void *nbio = NULL; PKIX_ENTER(AIAMGR, "pkix_pl_AIAMgr_GetLDAPCerts"); PKIX_NULLCHECK_FOUR(aiaMgr, ia, pNBIOContext, pCerts); nbio = *pNBIOContext; *pNBIOContext = NULL; *pCerts = NULL; if (nbio == NULL) { /* a new request */ /* Initiate an LDAP request */ request.scope = WHOLE_SUBTREE; request.derefAliases = NEVER_DEREF; request.sizeLimit = 0; request.timeLimit = 0; PKIX_CHECK(PKIX_PL_InfoAccess_GetLocation (ia, &location, plContext), PKIX_INFOACCESSGETLOCATIONFAILED); /* * Get a short-lived arena. We'll be done with * this space once the request is encoded. */ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (!arena) { PKIX_ERROR_FATAL(PKIX_OUTOFMEMORY); } PKIX_CHECK(pkix_pl_InfoAccess_ParseLocation (location, arena, &request, &domainName, plContext), PKIX_INFOACCESSPARSELOCATIONFAILED); PKIX_DECREF(location); /* Find or create a connection to LDAP server */ PKIX_CHECK(pkix_pl_AiaMgr_FindLDAPClient (aiaMgr, domainName, &client, plContext), PKIX_AIAMGRFINDLDAPCLIENTFAILED); aiaMgr->client.ldapClient = client; PKIX_CHECK(PKIX_PL_LdapClient_InitiateRequest (aiaMgr->client.ldapClient, &request, &nbio, &result, plContext), PKIX_LDAPCLIENTINITIATEREQUESTFAILED); PKIX_PL_NSSCALL(AIAMGR, PORT_FreeArena, (arena, PR_FALSE)); } else { PKIX_CHECK(PKIX_PL_LdapClient_ResumeRequest (aiaMgr->client.ldapClient, &nbio, &result, plContext), PKIX_LDAPCLIENTRESUMEREQUESTFAILED); } if (nbio != NULL) { /* WOULDBLOCK */ *pNBIOContext = nbio; *pCerts = NULL; goto cleanup; } PKIX_DECREF(aiaMgr->client.ldapClient); if (result == NULL) { *pCerts = NULL; } else { PKIX_CHECK(pkix_pl_LdapCertStore_BuildCertList (result, pCerts, plContext), PKIX_LDAPCERTSTOREBUILDCERTLISTFAILED); } *pNBIOContext = nbio; cleanup: if (arena && (PKIX_ERROR_RECEIVED)) { PKIX_PL_NSSCALL(AIAMGR, PORT_FreeArena, (arena, PR_FALSE)); } if (PKIX_ERROR_RECEIVED) { PKIX_DECREF(aiaMgr->client.ldapClient); } PKIX_DECREF(location); PKIX_RETURN(AIAMGR); }
/* * FUNCTION: PKIX_PL_Object_Equals (see comments in pkix_pl_system.h) */ PKIX_Error * PKIX_PL_Object_Equals( PKIX_PL_Object *firstObject, PKIX_PL_Object *secondObject, PKIX_Boolean *pResult, void *plContext) { PKIX_PL_Object *firstObjectHeader = NULL; PKIX_PL_Object *secondObjectHeader = NULL; PKIX_PL_EqualsCallback func = NULL; pkix_ClassTable_Entry entry; PKIX_UInt32 objType; PKIX_ENTER(OBJECT, "PKIX_PL_Object_Equals"); PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); PKIX_CHECK(pkix_pl_Object_GetHeader (firstObject, &firstObjectHeader, plContext), PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); PKIX_CHECK(pkix_pl_Object_GetHeader (secondObject, &secondObjectHeader, plContext), PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); /* if hashcodes are cached but not equal, objects can't be equal */ if (firstObjectHeader->hashcodeCached && secondObjectHeader->hashcodeCached){ if (firstObjectHeader->hashcode != secondObjectHeader->hashcode){ *pResult = PKIX_FALSE; goto cleanup; } } objType = firstObjectHeader->type; if (objType >= PKIX_NUMTYPES) { #ifdef PKIX_USER_OBJECT_TYPE pkix_ClassTable_Entry *ctEntry = NULL; PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); PR_Lock(classTableLock); pkixErrorResult = pkix_pl_PrimHashTable_Lookup (classTable, (void *)&firstObjectHeader->type, firstObjectHeader->type, NULL, (void **)&ctEntry, plContext); PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); PR_Unlock(classTableLock); if (pkixErrorResult){ PKIX_ERROR_FATAL(PKIX_ERRORGETTINGCLASSTABLEENTRY); } if ((ctEntry == NULL) || (ctEntry->equalsFunction == NULL)) { PKIX_ERROR_FATAL(PKIX_UNDEFINEDCALLBACK); } else { func = ctEntry->equalsFunction; } #else PORT_Assert (0); pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; pkixErrorClass = PKIX_FATAL_ERROR; goto cleanup; #endif /* PKIX_USER_OBJECT_TYPE */ } else { entry = systemClasses[objType]; func = entry.equalsFunction; if (func == NULL){ func = pkix_pl_Object_Equals_Default; } } PKIX_CHECK(func(firstObject, secondObject, pResult, plContext), PKIX_OBJECTSPECIFICFUNCTIONFAILED); cleanup: PKIX_RETURN(OBJECT); }
/* * FUNCTION: PKIX_PL_Object_Duplicate (see comments in pkix_pl_system.h) */ PKIX_Error * PKIX_PL_Object_Duplicate( PKIX_PL_Object *firstObject, PKIX_PL_Object **pNewObject, void *plContext) { PKIX_PL_Object *firstObjectHeader = NULL; PKIX_PL_DuplicateCallback func = NULL; pkix_ClassTable_Entry entry; PKIX_UInt32 objType; PKIX_ENTER(OBJECT, "PKIX_PL_Object_Duplicate"); PKIX_NULLCHECK_TWO(firstObject, pNewObject); PKIX_CHECK(pkix_pl_Object_GetHeader (firstObject, &firstObjectHeader, plContext), PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); objType = firstObjectHeader->type; if (objType >= PKIX_NUMTYPES) { #ifdef PKIX_USER_OBJECT_TYPE pkix_ClassTable_Entry *ctEntry = NULL; PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); PR_Lock(classTableLock); pkixErrorResult = pkix_pl_PrimHashTable_Lookup (classTable, (void *)&objType, objType, NULL, (void **)&ctEntry, plContext); PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); PR_Unlock(classTableLock); if (pkixErrorResult){ PKIX_ERROR_FATAL(PKIX_ERRORGETTINGCLASSTABLEENTRY); } if ((ctEntry == NULL) || (ctEntry->duplicateFunction == NULL)) { PKIX_ERROR_FATAL(PKIX_UNDEFINEDCALLBACK); } else { func = ctEntry->duplicateFunction; } #else PORT_Assert (0); pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; pkixErrorClass = PKIX_FATAL_ERROR; goto cleanup; #endif /* PKIX_USER_OBJECT_TYPE */ } else { entry = systemClasses[objType]; func = entry.duplicateFunction; if (!func){ PKIX_ERROR_FATAL(PKIX_UNDEFINEDDUPLICATEFUNCTION); } } PKIX_CHECK(func(firstObject, pNewObject, plContext), PKIX_OBJECTSPECIFICFUNCTIONFAILED); cleanup: PKIX_RETURN(OBJECT); }
/* * FUNCTION: pkix_pl_LdapCertStore_GetCRL * (see description of PKIX_CertStore_CRLCallback in pkix_certstore.h) */ PKIX_Error * pkix_pl_LdapCertStore_GetCRL( PKIX_CertStore *store, PKIX_CRLSelector *selector, void **pNBIOContext, PKIX_List **pCrlList, void *plContext) { LDAPRequestParams requestParams; void *pollDesc = NULL; PRArenaPool *requestArena = NULL; PKIX_UInt32 numNames = 0; PKIX_UInt32 thisName = 0; PKIX_PL_CRL *candidate = NULL; PKIX_List *responses = NULL; PKIX_List *issuerNames = NULL; PKIX_List *filteredCRLs = NULL; PKIX_List *unfilteredCRLs = NULL; PKIX_PL_X500Name *issuer = NULL; PKIX_PL_LdapCertStoreContext *lcs = NULL; PKIX_ComCRLSelParams *params = NULL; PKIX_ENTER(CERTSTORE, "pkix_pl_LdapCertStore_GetCRL"); PKIX_NULLCHECK_THREE(store, selector, pCrlList); requestParams.baseObject = "c=US"; requestParams.scope = WHOLE_SUBTREE; requestParams.derefAliases = NEVER_DEREF; requestParams.sizeLimit = 0; requestParams.timeLimit = 0; requestParams.attributes = LDAPATTR_CERTREVLIST | LDAPATTR_AUTHREVLIST; /* Prepare elements for request filter */ /* XXX Place CRLDP code here. Handle the case when */ /* RFC 5280. Paragraph: 4.2.1.13: */ /* If the distributionPoint field contains a directoryName, the entry */ /* for that directoryName contains the current CRL for the associated */ /* reasons and the CRL is issued by the associated cRLIssuer. The CRL */ /* may be stored in either the certificateRevocationList or */ /* authorityRevocationList attribute. The CRL is to be obtained by the */ /* application from whatever directory server is locally configured. */ /* The protocol the application uses to access the directory (e.g., DAP */ /* or LDAP) is a local matter. */ /* * Get a short-lived arena. We'll be done with this space once * the request is encoded. */ PKIX_PL_NSSCALLRV (CERTSTORE, requestArena, PORT_NewArena, (DER_DEFAULT_CHUNKSIZE)); if (!requestArena) { PKIX_ERROR_FATAL(PKIX_OUTOFMEMORY); } PKIX_CHECK(PKIX_CRLSelector_GetCommonCRLSelectorParams (selector, ¶ms, plContext), PKIX_CRLSELECTORGETCOMCERTSELPARAMSFAILED); PKIX_CHECK(PKIX_ComCRLSelParams_GetIssuerNames (params, &issuerNames, plContext), PKIX_COMCRLSELPARAMSGETISSUERNAMESFAILED); /* * The specification for PKIX_ComCRLSelParams_GetIssuerNames in * pkix_crlsel.h says that if the criterion is not set we get a null * pointer. If we get an empty List the criterion is impossible to * meet ("must match at least one of the names in the List"). */ if (issuerNames) { PKIX_CHECK(PKIX_List_GetLength (issuerNames, &numNames, plContext), PKIX_LISTGETLENGTHFAILED); if (numNames > 0) { for (thisName = 0; thisName < numNames; thisName++) { PKIX_CHECK(PKIX_List_GetItem (issuerNames, thisName, (PKIX_PL_Object **)&issuer, plContext), PKIX_LISTGETITEMFAILED); PKIX_CHECK (pkix_pl_LdapCertStore_MakeNameAVAList (requestArena, issuer, &(requestParams.nc), plContext), PKIX_LDAPCERTSTOREMAKENAMEAVALISTFAILED); PKIX_DECREF(issuer); if (*requestParams.nc == NULL) { /* * The issuer may not include any * components that we know how to * encode. We do not return an error, * because the caller did not * necessarily do anything wrong, but * we return an empty List. */ PKIX_PL_NSSCALL (CERTSTORE, PORT_FreeArena, (requestArena, PR_FALSE)); PKIX_CHECK(PKIX_List_Create (&filteredCRLs, plContext), PKIX_LISTCREATEFAILED); PKIX_CHECK(PKIX_List_SetImmutable (filteredCRLs, plContext), PKIX_LISTSETIMMUTABLEFAILED); *pNBIOContext = NULL; *pCrlList = filteredCRLs; goto cleanup; } /* * LDAP Servers don't seem to be able to handle * requests with more than more than one name. */ break; } } else { PKIX_ERROR(PKIX_IMPOSSIBLECRITERIONFORCRLQUERY); } } else { PKIX_ERROR(PKIX_IMPOSSIBLECRITERIONFORCRLQUERY); } /* All request fields are done */ PKIX_CHECK(PKIX_CertStore_GetCertStoreContext (store, (PKIX_PL_Object **)&lcs, plContext), PKIX_CERTSTOREGETCERTSTORECONTEXTFAILED); PKIX_CHECK(PKIX_PL_LdapClient_InitiateRequest ((PKIX_PL_LdapClient *)lcs, &requestParams, &pollDesc, &responses, plContext), PKIX_LDAPCLIENTINITIATEREQUESTFAILED); PKIX_CHECK(pkix_pl_LdapCertStore_DestroyAVAList (requestParams.nc, plContext), PKIX_LDAPCERTSTOREDESTROYAVALISTFAILED); if (requestArena) { PKIX_PL_NSSCALL(CERTSTORE, PORT_FreeArena, (requestArena, PR_FALSE)); } if (pollDesc != NULL) { /* client is waiting for non-blocking I/O to complete */ *pNBIOContext = (void *)pollDesc; *pCrlList = NULL; goto cleanup; } /* client has finished! */ if (responses) { /* * We have a List of LdapResponse objects that still have to be * turned into Crls. */ PKIX_CHECK(pkix_pl_LdapCertStore_BuildCrlList (responses, &unfilteredCRLs, plContext), PKIX_LDAPCERTSTOREBUILDCRLLISTFAILED); PKIX_CHECK(pkix_CRLSelector_Select (selector, unfilteredCRLs, &filteredCRLs, plContext), PKIX_CRLSELECTORSELECTFAILED); } /* Don't throw away the list if one CRL was bad! */ pkixTempErrorReceived = PKIX_FALSE; *pNBIOContext = NULL; *pCrlList = filteredCRLs; cleanup: if (PKIX_ERROR_RECEIVED) { PKIX_DECREF(filteredCRLs); } PKIX_DECREF(params); PKIX_DECREF(issuerNames); PKIX_DECREF(issuer); PKIX_DECREF(candidate); PKIX_DECREF(responses); PKIX_DECREF(unfilteredCRLs); PKIX_DECREF(lcs); PKIX_RETURN(CERTSTORE); }
/* * FUNCTION: pkix_pl_Object_GetHeader * DESCRIPTION: * * Shifts Object pointed to by "object" by the sizeof(PKIX_PL_Object) and * stores the value at "pObjectHeader". * * PARAMETERS: * "object" * Address of Object to shift. Must be non-NULL. * "pObjectHeader" * Address where object pointer will be stored. Must be non-NULL. * "plContext" * Platform-specific context pointer. * THREAD SAFETY: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) * RETURNS: * Returns NULL if the function succeeds. * Returns a Fatal Error if the function fails in an unrecoverable way. */ static PKIX_Error * pkix_pl_Object_GetHeader( PKIX_PL_Object *object, PKIX_PL_Object **pObjectHeader, void *plContext) { PKIX_PL_Object *header = NULL; PKIX_UInt32 objType; PKIX_ENTER(OBJECT, "pkix_pl_Object_GetHeader"); PKIX_NULLCHECK_TWO(object, pObjectHeader); PKIX_OBJECT_DEBUG("\tShifting object pointer).\n"); /* The header is sizeof(PKIX_PL_Object) before the object pointer */ header = (PKIX_PL_Object *)((char *)object - sizeof(PKIX_PL_Object)); objType = header->type; if (objType >= PKIX_NUMTYPES) { /* if this is a user-defined type */ #ifdef PKIX_USER_OBJECT_TYPE pkix_ClassTable_Entry *ctEntry = NULL; PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); PR_Lock(classTableLock); PKIX_CHECK(pkix_pl_PrimHashTable_Lookup (classTable, (void *)&objType, objType, NULL, (void **)&ctEntry, plContext), PKIX_ERRORGETTINGCLASSTABLEENTRY); PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); PR_Unlock(classTableLock); if (ctEntry == NULL) { PKIX_ERROR_FATAL(PKIX_UNKNOWNOBJECTTYPE); } #else PORT_Assert(objType < PKIX_NUMTYPES); pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; pkixErrorClass = PKIX_FATAL_ERROR; goto cleanup; #endif /* PKIX_USER_OBJECT_TYPE */ } #ifdef PKIX_OBJECT_LEAK_TEST PORT_Assert(header && header->magicHeader == PKIX_MAGIC_HEADER); #endif /* PKIX_OBJECT_LEAK_TEST */ if ((header == NULL)|| (header->magicHeader != PKIX_MAGIC_HEADER)) { PKIX_ERROR_ALLOC_ERROR(); } *pObjectHeader = header; cleanup: PKIX_RETURN(OBJECT); }
/* * FUNCTION: PKIX_PL_Object_Alloc (see comments in pkix_pl_system.h) */ PKIX_Error * PKIX_PL_Object_Alloc( PKIX_TYPENUM objType, PKIX_UInt32 size, PKIX_PL_Object **pObject, void *plContext) { PKIX_PL_Object *object = NULL; pkix_ClassTable_Entry *ctEntry = NULL; PKIX_ENTER(OBJECT, "PKIX_PL_Object_Alloc"); PKIX_NULLCHECK_ONE(pObject); /* * We need to ensure that user-defined types have been registered. * All system types have already been registered by PKIX_PL_Initialize. */ if (objType >= PKIX_NUMTYPES) { /* i.e. if this is a user-defined type */ #ifdef PKIX_USER_OBJECT_TYPE PKIX_Boolean typeRegistered; PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); PR_Lock(classTableLock); pkixErrorResult = pkix_pl_PrimHashTable_Lookup (classTable, (void *)&objType, objType, NULL, (void **)&ctEntry, plContext); PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); PR_Unlock(classTableLock); if (pkixErrorResult){ PKIX_ERROR_FATAL(PKIX_COULDNOTLOOKUPINHASHTABLE); } typeRegistered = (ctEntry != NULL); if (!typeRegistered) { PKIX_ERROR_FATAL(PKIX_UNKNOWNTYPEARGUMENT); } #else PORT_Assert (0); pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; pkixErrorClass = PKIX_FATAL_ERROR; goto cleanup; #endif /* PKIX_USER_OBJECT_TYPE */ } else { ctEntry = &systemClasses[objType]; } PORT_Assert(size == ctEntry->typeObjectSize); /* Allocate space for the object header and the requested size */ #ifdef PKIX_OBJECT_LEAK_TEST PKIX_CHECK(PKIX_PL_Calloc (1, ((PKIX_UInt32)sizeof (PKIX_PL_Object))+size, (void **)&object, plContext), PKIX_MALLOCFAILED); #else PKIX_CHECK(PKIX_PL_Malloc (((PKIX_UInt32)sizeof (PKIX_PL_Object))+size, (void **)&object, plContext), PKIX_MALLOCFAILED); #endif /* PKIX_OBJECT_LEAK_TEST */ /* Initialize all object fields */ object->magicHeader = PKIX_MAGIC_HEADER; object->type = objType; object->references = 1; /* Default to a single reference */ object->stringRep = NULL; object->hashcode = 0; object->hashcodeCached = 0; /* Cannot use PKIX_PL_Mutex because it depends on Object */ /* Using NSPR Locks instead */ PKIX_OBJECT_DEBUG("\tCalling PR_NewLock).\n"); object->lock = PR_NewLock(); if (object->lock == NULL) { PKIX_ERROR_ALLOC_ERROR(); } PKIX_OBJECT_DEBUG("\tShifting object pointer).\n"); /* Return a pointer to the user data. Need to offset by object size */ *pObject = object + 1; object = NULL; /* Atomically increment object counter */ PR_ATOMIC_INCREMENT(&ctEntry->objCounter); cleanup: PKIX_FREE(object); PKIX_RETURN(OBJECT); }
/* * FUNCTION: pkix_pl_Object_ToString_Default * DESCRIPTION: * * Default Object_ToString callback: Creates a string consisting of the * typename and address of the Object pointed to by "object" and stores * the result at "pString". The format for the string is * "TypeName@Address: <address>", where the default typename is "Object". * * PARAMETERS: * "object" * Address of Object to convert to a string. Must be non-NULL. * "pString" * Address where object pointer will be stored. Must be non-NULL. * "plContext" * Platform-specific context pointer. * THREAD SAFETY: * Thread Safe (see Thread Safety Definitions in Programmer's Guide) * RETURNS: * Returns NULL if the function succeeds. * Returns an Object Error if the function fails in a non-fatal way. * Returns a Fatal Error if the function fails in an unrecoverable way. */ static PKIX_Error * pkix_pl_Object_ToString_Default( PKIX_PL_Object *object, PKIX_PL_String **pString, void *plContext) { PKIX_PL_String *formatString = NULL; PKIX_PL_String *descString = NULL; char *format = "%s@Address: %x"; char *description = NULL; PKIX_UInt32 objType; PKIX_ENTER(OBJECT, "pkix_pl_Object_ToString_Default"); PKIX_NULLCHECK_TWO(object, pString); PKIX_CHECK(PKIX_PL_Object_GetType(object, &objType, plContext), PKIX_OBJECTGETTYPEFAILED); if (objType >= PKIX_NUMTYPES){ #ifdef PKIX_USER_OBJECT_TYPE pkix_ClassTable_Entry *ctEntry = NULL; PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); PR_Lock(classTableLock); pkixErrorResult = pkix_pl_PrimHashTable_Lookup (classTable, (void *)&objType, objType, NULL, (void **)&ctEntry, plContext); PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); PR_Unlock(classTableLock); if (pkixErrorResult){ PKIX_ERROR_FATAL(PKIX_ERRORGETTINGCLASSTABLEENTRY); } if (ctEntry == NULL){ PKIX_ERROR_FATAL(PKIX_UNDEFINEDCLASSTABLEENTRY); } else { description = ctEntry->description; if (description == NULL) { description = "User Type Object"; } } #else PORT_Assert (0); pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; pkixErrorClass = PKIX_FATAL_ERROR; goto cleanup; #endif /* PKIX_USER_OBJECT_TYPE */ } else { description = systemClasses[objType].description; } PKIX_CHECK(PKIX_PL_String_Create (PKIX_ESCASCII, (void *)format, 0, &formatString, plContext), PKIX_STRINGCREATEFAILED); PKIX_CHECK(PKIX_PL_String_Create (PKIX_ESCASCII, (void *)description, 0, &descString, plContext), PKIX_STRINGCREATEFAILED); PKIX_CHECK(PKIX_PL_Sprintf (pString, plContext, formatString, descString, object), PKIX_SPRINTFFAILED); cleanup: PKIX_DECREF(formatString); PKIX_DECREF(descString); PKIX_RETURN(OBJECT); }
/* * FUNCTION: PKIX_PL_Object_Compare (see comments in pkix_pl_system.h) */ PKIX_Error * PKIX_PL_Object_Compare( PKIX_PL_Object *firstObject, PKIX_PL_Object *secondObject, PKIX_Int32 *pResult, void *plContext) { PKIX_PL_Object *firstObjectHeader = NULL; PKIX_PL_Object *secondObjectHeader = NULL; PKIX_PL_ComparatorCallback func = NULL; pkix_ClassTable_Entry entry; PKIX_UInt32 objType; PKIX_ENTER(OBJECT, "PKIX_PL_Object_Compare"); PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); /* Shift pointer from user data to object header */ PKIX_CHECK(pkix_pl_Object_GetHeader (firstObject, &firstObjectHeader, plContext), PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); /* Shift pointer from user data to object header */ PKIX_CHECK(pkix_pl_Object_GetHeader (secondObject, &secondObjectHeader, plContext), PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); objType = firstObjectHeader->type; if (objType >= PKIX_NUMTYPES){ #ifdef PKIX_USER_OBJECT_TYPE pkix_ClassTable_Entry *ctEntry = NULL; PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); PR_Lock(classTableLock); pkixErrorResult = pkix_pl_PrimHashTable_Lookup (classTable, (void *)&objType, objType, NULL, (void **)&ctEntry, plContext); PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); PR_Unlock(classTableLock); if (pkixErrorResult){ PKIX_ERROR_FATAL(PKIX_ERRORGETTINGCLASSTABLEENTRY); } if ((ctEntry == NULL) || (ctEntry->comparator == NULL)) { PKIX_ERROR_FATAL(PKIX_UNDEFINEDCOMPARATOR); } func = ctEntry->comparator; #else PORT_Assert (0); pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; pkixErrorClass = PKIX_FATAL_ERROR; goto cleanup; #endif /* PKIX_USER_OBJECT_TYPE */ } else { /* special handling for system types */ entry = systemClasses[objType]; func = entry.comparator; if (!func){ PKIX_ERROR(PKIX_UNDEFINEDCOMPARATOR); } } PKIX_CHECK(func(firstObject, secondObject, pResult, plContext), PKIX_OBJECTSPECIFICFUNCTIONFAILED); cleanup: PKIX_RETURN(OBJECT); }
/* * FUNCTION: PKIX_PL_Object_ToString (see comments in pkix_pl_system.h) */ PKIX_Error * PKIX_PL_Object_ToString( PKIX_PL_Object *object, PKIX_PL_String **pString, void *plContext) { PKIX_PL_Object *objectHeader = NULL; PKIX_PL_ToStringCallback func = NULL; pkix_ClassTable_Entry entry; PKIX_PL_String *objectString = NULL; PKIX_ENTER(OBJECT, "PKIX_PL_Object_ToString"); PKIX_NULLCHECK_TWO(object, pString); /* Shift pointer from user data to object header */ PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext), PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); /* if we don't have a cached copy from before, we create one */ if (!objectHeader->stringRep){ PKIX_UInt32 objType = objectHeader->type; if (objType >= PKIX_NUMTYPES){ #ifdef PKIX_USER_OBJECT_TYPE pkix_ClassTable_Entry *ctEntry = NULL; PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); PR_Lock(classTableLock); pkixErrorResult = pkix_pl_PrimHashTable_Lookup (classTable, (void *)&objType, objType, NULL, (void **)&ctEntry, plContext); PKIX_OBJECT_DEBUG("\tCalling PR_Unlock).\n"); PR_Unlock(classTableLock); if (pkixErrorResult){ PKIX_ERROR_FATAL (PKIX_ERRORGETTINGCLASSTABLEENTRY); } if ((ctEntry == NULL) || (ctEntry->toStringFunction == NULL)) { PKIX_ERROR_FATAL(PKIX_UNDEFINEDCALLBACK); } func = ctEntry->toStringFunction; #else PORT_Assert (0); pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; pkixErrorClass = PKIX_FATAL_ERROR; goto cleanup; #endif /* PKIX_USER_OBJECT_TYPE */ } else { entry = systemClasses[objType]; func = entry.toStringFunction; if (func == NULL){ func = pkix_pl_Object_ToString_Default; } } PKIX_CHECK(func(object, &objectString, plContext), PKIX_OBJECTSPECIFICFUNCTIONFAILED); if (!objectHeader->stringRep){ PKIX_CHECK(pkix_LockObject(object, plContext), PKIX_ERRORLOCKINGOBJECT); if (!objectHeader->stringRep){ /* save a cached copy */ objectHeader->stringRep = objectString; objectString = NULL; } PKIX_CHECK(pkix_UnlockObject(object, plContext), PKIX_ERRORUNLOCKINGOBJECT); } } *pString = objectHeader->stringRep; objectHeader->stringRep = NULL; cleanup: if (objectHeader) { PKIX_DECREF(objectHeader->stringRep); } PKIX_DECREF(objectString); PKIX_RETURN(OBJECT); }
/* * FUNCTION: pkix_CrlChecker_CheckRemote * * DESCRIPTION: * Check if the Cert has been revoked based the CRLs data. This function * maintains the checker state to be current. * * PARAMETERS * "checker" * Address of CertChainChecker which has the state data. * Must be non-NULL. * "cert" * Address of Certificate that is to be validated. Must be non-NULL. * "unreslvdCrtExts" * A List OIDs. Not **yet** used in this checker function. * "plContext" * Platform-specific context pointer. * * THREAD SAFETY: * Not Thread Safe * (see Thread Safety Definitions in Programmer's Guide) * * RETURNS: * Returns NULL if the function succeeds. * Returns a CertChainChecker Error if the function fails in a non-fatal way. * Returns a Fatal Error */ PKIX_Error * pkix_CrlChecker_CheckExternal( PKIX_PL_Cert *cert, PKIX_PL_Cert *issuer, PKIX_PL_Date *date, pkix_RevocationMethod *checkerObject, PKIX_ProcessingParams *procParams, PKIX_UInt32 methodFlags, PKIX_RevocationStatus *pRevStatus, PKIX_UInt32 *pReasonCode, void **pNBIOContext, void *plContext) { PKIX_CertStore_CheckRevokationByCrlCallback storeCheckRevocationFn = NULL; PKIX_CertStore_ImportCrlCallback storeImportCrlFn = NULL; PKIX_RevocationStatus revStatus = PKIX_RevStatus_NoInfo; PKIX_CertStore *certStore = NULL; PKIX_CertStore *localStore = NULL; PKIX_CRLSelector *crlSelector = NULL; PKIX_PL_X500Name *issuerName = NULL; pkix_CrlChecker *state = NULL; PKIX_UInt32 reasonCode = 0; PKIX_UInt32 crlStoreIndex = 0; PKIX_UInt32 numCrlStores = 0; PKIX_Boolean storeIsLocal = PKIX_FALSE; PKIX_List *crlList = NULL; PKIX_List *dpList = NULL; void *nbioContext = NULL; PKIX_ENTER(CERTCHAINCHECKER, "pkix_CrlChecker_CheckExternal"); PKIX_NULLCHECK_FOUR(cert, issuer, checkerObject, pNBIOContext); nbioContext = *pNBIOContext; *pNBIOContext = NULL; /* prepare for Error exit */ state = (pkix_CrlChecker*)checkerObject; PKIX_CHECK( PKIX_List_GetLength(state->certStores, &numCrlStores, plContext), PKIX_LISTGETLENGTHFAILED); /* Find a cert store that is capable of storing crls */ for (;crlStoreIndex < numCrlStores;crlStoreIndex++) { PKIX_CHECK( PKIX_List_GetItem(state->certStores, crlStoreIndex, (PKIX_PL_Object **)&certStore, plContext), PKIX_LISTGETITEMFAILED); PKIX_CHECK( PKIX_CertStore_GetLocalFlag(certStore, &storeIsLocal, plContext), PKIX_CERTSTOREGETLOCALFLAGFAILED); if (storeIsLocal) { PKIX_CHECK( PKIX_CertStore_GetImportCrlCallback(certStore, &storeImportCrlFn, plContext), PKIX_CERTSTOREGETCHECKREVBYCRLFAILED); PKIX_CHECK( PKIX_CertStore_GetCrlCheckerFn(certStore, &storeCheckRevocationFn, plContext), PKIX_CERTSTOREGETCHECKREVBYCRLFAILED); if (storeImportCrlFn && storeCheckRevocationFn) { localStore = certStore; certStore = NULL; break; } } PKIX_DECREF(certStore); } /* while */ /* Report unknown status if we can not check crl in one of the * local stores. */ if (!localStore) { PKIX_ERROR_FATAL(PKIX_CRLCHECKERNOLOCALCERTSTOREFOUND); } PKIX_CHECK( PKIX_PL_Cert_VerifyKeyUsage(issuer, PKIX_CRL_SIGN, plContext), PKIX_CERTCHECKKEYUSAGEFAILED); PKIX_CHECK( PKIX_PL_Cert_GetCrlDp(cert, &dpList, plContext), PKIX_CERTGETCRLDPFAILED); if (!(methodFlags & PKIX_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE) && (!dpList || !dpList->length)) { goto cleanup; } PKIX_CHECK( PKIX_PL_Cert_GetIssuer(cert, &issuerName, plContext), PKIX_CERTGETISSUERFAILED); PKIX_CHECK( PKIX_CRLSelector_Create(issuer, dpList, date, &crlSelector, plContext), PKIX_CRLCHECKERSETSELECTORFAILED); /* Fetch crl and store in a local cert store */ for (crlStoreIndex = 0;crlStoreIndex < numCrlStores;crlStoreIndex++) { PKIX_CertStore_CRLCallback getCrlsFn; PKIX_CHECK( PKIX_List_GetItem(state->certStores, crlStoreIndex, (PKIX_PL_Object **)&certStore, plContext), PKIX_LISTGETITEMFAILED); PKIX_CHECK( PKIX_CertStore_GetCRLCallback(certStore, &getCrlsFn, plContext), PKIX_CERTSTOREGETCRLCALLBACKFAILED); PKIX_CHECK( (*getCrlsFn)(certStore, crlSelector, &nbioContext, &crlList, plContext), PKIX_GETCRLSFAILED); PKIX_CHECK( (*storeImportCrlFn)(localStore, issuerName, crlList, plContext), PKIX_CERTSTOREFAILTOIMPORTCRLLIST); PKIX_CHECK( (*storeCheckRevocationFn)(certStore, cert, issuer, date, /* done with crl downloading */ PKIX_TRUE, &reasonCode, &revStatus, plContext), PKIX_CERTSTORECRLCHECKFAILED); if (revStatus != PKIX_RevStatus_NoInfo) { break; } PKIX_DECREF(crlList); PKIX_DECREF(certStore); } /* while */ cleanup: /* Update return flags */ if (revStatus == PKIX_RevStatus_NoInfo && ((dpList && dpList->length > 0) || (methodFlags & PKIX_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE)) && methodFlags & PKIX_REV_M_FAIL_ON_MISSING_FRESH_INFO) { revStatus = PKIX_RevStatus_Revoked; } *pRevStatus = revStatus; PKIX_DECREF(dpList); PKIX_DECREF(crlList); PKIX_DECREF(certStore); PKIX_DECREF(issuerName); PKIX_DECREF(localStore); PKIX_DECREF(crlSelector); PKIX_RETURN(CERTCHAINCHECKER); }
/* * FUNCTION: PKIX_PL_Object_DecRef (see comments in pkix_pl_system.h) */ PKIX_Error * PKIX_PL_Object_DecRef( PKIX_PL_Object *object, void *plContext) { PKIX_Int32 refCount = 0; PKIX_PL_Object *objectHeader = NULL; PKIX_PL_NssContext *context = NULL; PKIX_ENTER(OBJECT, "PKIX_PL_Object_DecRef"); PKIX_NULLCHECK_ONE(object); if (plContext){ /* * PKIX_PL_NssContext is not a complete PKIX Type, it doesn't * have a header therefore we cannot verify its type before * casting. */ context = (PKIX_PL_NssContext *) plContext; if (context->arena != NULL) { goto cleanup; } } if (object == (PKIX_PL_Object*)PKIX_ALLOC_ERROR()) { goto cleanup; } /* Shift pointer from user data to object header */ PKIX_CHECK(pkix_pl_Object_GetHeader(object, &objectHeader, plContext), PKIX_RECEIVEDCORRUPTEDOBJECTARGUMENT); refCount = PR_ATOMIC_DECREMENT(&objectHeader->references); if (refCount == 0) { PKIX_PL_DestructorCallback destructor = NULL; pkix_ClassTable_Entry *ctEntry = NULL; PKIX_UInt32 objType = objectHeader->type; /* first, special handling for system types */ if (objType >= PKIX_NUMTYPES){ #ifdef PKIX_USER_OBJECT_TYPE PKIX_OBJECT_DEBUG("\tCalling PR_Lock).\n"); PR_Lock(classTableLock); pkixErrorResult = pkix_pl_PrimHashTable_Lookup (classTable, (void *)&objType, objType, NULL, (void **)&ctEntry, plContext); PKIX_OBJECT_DEBUG ("\tCalling PR_Unlock).\n"); PR_Unlock(classTableLock); if (pkixErrorResult){ PKIX_ERROR_FATAL (PKIX_ERRORINGETTINGDESTRUCTOR); } if (ctEntry != NULL){ destructor = ctEntry->destructor; } #else PORT_Assert (0); pkixErrorCode = PKIX_UNKNOWNOBJECTTYPE; pkixErrorClass = PKIX_FATAL_ERROR; goto cleanup; #endif /* PKIX_USER_OBJECT_TYPE */ } else { ctEntry = &systemClasses[objType]; destructor = ctEntry->destructor; } if (destructor != NULL){ /* Call destructor on user data if necessary */ pkixErrorResult = destructor(object, plContext); if (pkixErrorResult) { pkixErrorClass = PKIX_FATAL_ERROR; PKIX_DoAddError(stdVarsPtr, pkixErrorResult, plContext); pkixErrorResult = NULL; } } /* Atomically decrement object counter */ PR_ATOMIC_DECREMENT(&ctEntry->objCounter); /* pkix_pl_Object_Destroy assumes the lock is held */ /* It will call unlock and destroy the object */ pkixErrorResult = pkix_pl_Object_Destroy(object, plContext); goto cleanup; } if (refCount < 0) { PKIX_ERROR_ALLOC_ERROR(); } cleanup: PKIX_RETURN(OBJECT); }