/* * FUNCTION: pkix_List_RemoveItems * DESCRIPTION: * * Traverses the List pointed to by "list", to find and delete an entry * that is equal to the Object in the "deleteList". If no such entry * is found the function does not return an error. * * PARAMETERS: * "list" * Object in "list" is checked for object in "deleteList" and deleted if * found; may be empty; must be non-NULL * "deleteList" * List of objects to be searched ; may be empty; 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 Validate Error if the functions fails in a non-fatal way * Returns a Fatal Error if the function fails in an unrecoverable way */ PKIX_Error * pkix_List_RemoveItems( PKIX_List *list, PKIX_List *deleteList, void *plContext) { PKIX_PL_Object *current = NULL; PKIX_UInt32 numEntries = 0; PKIX_UInt32 index = 0; PKIX_ENTER(LIST, "pkix_List_RemoveItems"); PKIX_NULLCHECK_TWO(list, deleteList); PKIX_CHECK(PKIX_List_GetLength(deleteList, &numEntries, plContext), PKIX_LISTGETLENGTHFAILED); for (index = 0; index < numEntries; index++) { PKIX_CHECK(PKIX_List_GetItem (deleteList, index, ¤t, plContext), PKIX_LISTGETITEMFAILED); if (current) { PKIX_CHECK(pkix_List_Remove (list, current, plContext), PKIX_OBJECTEQUALSFAILED); PKIX_DECREF(current); } } cleanup: PKIX_DECREF(current); PKIX_RETURN(LIST); }
/* * FUNCTION: PKIX_List_ReverseList (see comments in pkix_util.h) */ PKIX_Error * PKIX_List_ReverseList( PKIX_List *list, PKIX_List **pReversedList, void *plContext) { PKIX_List *reversedList = NULL; PKIX_PL_Object *item = NULL; PKIX_PL_Object *duplicateItem = NULL; PKIX_UInt32 length, i; PKIX_ENTER(LIST, "pkix_List_ReverseList"); PKIX_NULLCHECK_TWO(list, pReversedList); if (!list->isHeader){ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER); } length = list->length; /* Create a new list object */ PKIX_CHECK(PKIX_List_Create(&reversedList, plContext), PKIX_LISTCREATEINTERNALFAILED); /* * Starting with the last item and traversing backwards (from * the original list), append each item to the reversed list */ for (i = 1; i <= length; i++){ PKIX_CHECK(PKIX_List_GetItem (list, (length - i), &item, plContext), PKIX_LISTGETITEMFAILED); PKIX_CHECK(PKIX_PL_Object_Duplicate (item, &duplicateItem, plContext), PKIX_LISTDUPLICATEFAILED); PKIX_CHECK(PKIX_List_AppendItem (reversedList, duplicateItem, plContext), PKIX_LISTAPPENDITEMFAILED); PKIX_DECREF(item); PKIX_DECREF(duplicateItem); } *pReversedList = reversedList; cleanup: PKIX_DECREF(item); PKIX_DECREF(duplicateItem); if (PKIX_ERROR_RECEIVED){ PKIX_DECREF(reversedList); } PKIX_RETURN(LIST); }
/* * FUNCTION: PKIX_VerifyNode_FindError * DESCRIPTION: * * Finds meaningful error in the log. For now, just returns the first * error it finds in. In the future the function should be changed to * return a top priority error. * * PARAMETERS: * "node" * The address of the VerifyNode to be modified. Must be non-NULL. * "error" * The address of a pointer the error will be returned to. * "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_VerifyNode_FindError( PKIX_VerifyNode *node, PKIX_Error **error, void *plContext) { PKIX_VerifyNode *childNode = NULL; PKIX_ENTER(VERIFYNODE, "PKIX_VerifyNode_FindError"); /* Make sure the return address is initialized with NULL */ PKIX_DECREF(*error); if (!node) goto cleanup; /* First, try to get error from lowest level. */ if (node->children) { PKIX_UInt32 length = 0; PKIX_UInt32 index = 0; PKIX_CHECK( PKIX_List_GetLength(node->children, &length, plContext), PKIX_LISTGETLENGTHFAILED); for (index = 0;index < length;index++) { PKIX_CHECK( PKIX_List_GetItem(node->children, index, (PKIX_PL_Object**)&childNode, plContext), PKIX_LISTGETITEMFAILED); if (!childNode) continue; PKIX_CHECK( pkix_VerifyNode_FindError(childNode, error, plContext), PKIX_VERIFYNODEFINDERRORFAILED); PKIX_DECREF(childNode); if (*error) { goto cleanup; } } } if (node->error) { PKIX_INCREF(node->error); *error = node->error; } cleanup: PKIX_DECREF(childNode); PKIX_RETURN(VERIFYNODE); }
/* * FUNCTION: pkix_List_Hashcode * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) */ static PKIX_Error * pkix_List_Hashcode( PKIX_PL_Object *object, PKIX_UInt32 *pHashcode, void *plContext) { PKIX_List *list = NULL; PKIX_PL_Object *element = NULL; PKIX_UInt32 hash = 0; PKIX_UInt32 tempHash = 0; PKIX_UInt32 length, i; PKIX_ENTER(LIST, "pkix_List_Hashcode"); PKIX_NULLCHECK_TWO(object, pHashcode); PKIX_CHECK(pkix_CheckType(object, PKIX_LIST_TYPE, plContext), PKIX_OBJECTNOTLIST); list = (PKIX_List *)object; if (!list->isHeader){ PKIX_ERROR(PKIX_INPUTLISTMUSTBEHEADER); } length = list->length; for (i = 0; i < length; i++){ PKIX_CHECK(PKIX_List_GetItem(list, i, &element, plContext), PKIX_LISTGETITEMFAILED); if (!element){ tempHash = 100; } else { PKIX_CHECK(PKIX_PL_Object_Hashcode (element, &tempHash, plContext), PKIX_LISTHASHCODEFAILED); } hash = 31 * hash + tempHash; PKIX_DECREF(element); } *pHashcode = hash; cleanup: PKIX_DECREF(element); PKIX_RETURN(LIST); }
/* * FUNCTION: pkix_List_AppendList * DESCRIPTION: * * Append items on "fromList" to the "toList". Item reference count on * "toList" is not incremented, but items appended from "fromList" are * incremented. * * PARAMETERS: * "toList" * Address of list to be appended to. Must be non-NULL. * "fromList" * Address of list to be appended from. May be NULL or empty. * "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 List Error if the functions fails in a non-fatal way * Returns a Fatal Error if the function fails in an unrecoverable way */ PKIX_Error * pkix_List_AppendList( PKIX_List *toList, PKIX_List *fromList, void *plContext) { PKIX_PL_Object *item = NULL; PKIX_UInt32 numItems = 0; PKIX_UInt32 i; PKIX_ENTER(LIST, "pkix_List_AppendList"); PKIX_NULLCHECK_ONE(toList); /* if fromList is NULL or is an empty list, no action */ if (fromList == NULL) { goto cleanup; } PKIX_CHECK(PKIX_List_GetLength(fromList, &numItems, plContext), PKIX_LISTGETLENGTHFAILED); if (numItems == 0) { goto cleanup; } for (i = 0; i < numItems; i++) { PKIX_CHECK(PKIX_List_GetItem (fromList, i, &item, plContext), PKIX_LISTGETITEMFAILED); PKIX_CHECK(PKIX_List_AppendItem(toList, item, plContext), PKIX_LISTAPPENDITEMFAILED); PKIX_DECREF(item); } cleanup: PKIX_DECREF(item); PKIX_RETURN(LIST); }
static void test_CreateOIDList(PKIX_List *certPolicyInfos, PKIX_List **pPolicyOIDs) { PKIX_UInt32 i = 0; PKIX_UInt32 numInfos = 0; PKIX_PL_CertPolicyInfo *certPolicyInfo = NULL; PKIX_PL_OID *policyOID = NULL; PKIX_List *certPolicies = NULL; PKIX_TEST_STD_VARS(); /* Convert from List of CertPolicyInfos to List of OIDs */ if (certPolicyInfos) { PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength (certPolicyInfos, &numInfos, plContext)); } if (numInfos > 0) { PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create (&certPolicies, plContext)); } for (i = 0; i < numInfos; i++) { PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem (certPolicyInfos, i, (PKIX_PL_Object **)&certPolicyInfo, plContext)); PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CertPolicyInfo_GetPolicyId (certPolicyInfo, &policyOID, plContext)); PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem (certPolicies, (PKIX_PL_Object *)policyOID, plContext)); PKIX_TEST_DECREF_BC(certPolicyInfo); PKIX_TEST_DECREF_BC(policyOID); } *pPolicyOIDs = certPolicies; cleanup: PKIX_TEST_DECREF_AC(certPolicyInfo); PKIX_TEST_DECREF_AC(policyOID); PKIX_TEST_RETURN(); }
/* * FUNCTION: pkix_List_Remove * DESCRIPTION: * * Traverses the List pointed to by "list", to find and delete an entry * that is equal to the Object pointed to by "object". If no such entry * is found the function does not return an error. * * PARAMETERS: * "list" * List to be searched; may be empty; must be non-NULL * "object" * Object to be checked for and deleted, if found; 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 Validate Error if the functions fails in a non-fatal way * Returns a Fatal Error if the function fails in an unrecoverable way */ PKIX_Error * pkix_List_Remove( PKIX_List *list, PKIX_PL_Object *object, void *plContext) { PKIX_PL_Object *current = NULL; PKIX_UInt32 numEntries = 0; PKIX_UInt32 index = 0; PKIX_Boolean match = PKIX_FALSE; PKIX_ENTER(LIST, "pkix_List_Remove"); PKIX_NULLCHECK_TWO(list, object); PKIX_CHECK(PKIX_List_GetLength(list, &numEntries, plContext), PKIX_LISTGETLENGTHFAILED); for (index = 0; index < numEntries; index++) { PKIX_CHECK(PKIX_List_GetItem (list, index, ¤t, plContext), PKIX_LISTGETITEMFAILED); if (current) { PKIX_CHECK(PKIX_PL_Object_Equals (object, current, &match, plContext), PKIX_OBJECTEQUALSFAILED); PKIX_DECREF(current); } if (match) { PKIX_CHECK(PKIX_List_DeleteItem (list, index, plContext), PKIX_LISTDELETEITEMFAILED); break; } } cleanup: PKIX_DECREF(current); PKIX_RETURN(LIST); }
/* * FUNCTION: pkix_List_AppendUnique * DESCRIPTION: * * Adds each Object in the List pointed to by "fromList" to the List pointed * to by "toList", if it is not already a member of that List. In other words, * "toList" becomes the union of the two sets. * * PARAMETERS: * "toList" * Address of a List of Objects to be augmented by "fromList". Must be * non-NULL, but may be empty. * "fromList" * Address of a List of Objects to be added, if not already present, to * "toList". Must be non-NULL, but may be empty. * "plContext" * Platform-specific context pointer. * THREAD SAFETY: * Not Thread Safe - assumes exclusive access to "toList" * (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_List_AppendUnique( PKIX_List *toList, PKIX_List *fromList, void *plContext) { PKIX_Boolean isContained = PKIX_FALSE; PKIX_UInt32 listLen = 0; PKIX_UInt32 listIx = 0; PKIX_PL_Object *object = NULL; PKIX_ENTER(BUILD, "pkix_List_AppendUnique"); PKIX_NULLCHECK_TWO(fromList, toList); PKIX_CHECK(PKIX_List_GetLength(fromList, &listLen, plContext), PKIX_LISTGETLENGTHFAILED); for (listIx = 0; listIx < listLen; listIx++) { PKIX_CHECK(PKIX_List_GetItem (fromList, listIx, &object, plContext), PKIX_LISTGETITEMFAILED); PKIX_CHECK(pkix_List_Contains (toList, object, &isContained, plContext), PKIX_LISTCONTAINSFAILED); if (isContained == PKIX_FALSE) { PKIX_CHECK(PKIX_List_AppendItem (toList, object, plContext), PKIX_LISTAPPENDITEMFAILED); } PKIX_DECREF(object); } cleanup: PKIX_DECREF(object); PKIX_RETURN(LIST); }
/* * FUNCTION: pkix_VerifyNode_SetDepth * DESCRIPTION: * * The function sets the depth field of each VerifyNode in the List "children" * to the value given by "depth", and recursively sets the depth of any * successive generations to the successive values. * * PARAMETERS: * "children" * The List of VerifyNodes. Must be non-NULL. * "depth" * The value of the depth field to be set in members of the List. * "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_VerifyNode_SetDepth(PKIX_List *children, PKIX_UInt32 depth, void *plContext) { PKIX_UInt32 numChildren = 0; PKIX_UInt32 chIx = 0; PKIX_VerifyNode *child = NULL; PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_SetDepth"); PKIX_NULLCHECK_ONE(children); PKIX_CHECK(PKIX_List_GetLength(children, &numChildren, plContext), PKIX_LISTGETLENGTHFAILED); for (chIx = 0; chIx < numChildren; chIx++) { PKIX_CHECK(PKIX_List_GetItem (children, chIx, (PKIX_PL_Object **)&child, plContext), PKIX_LISTGETITEMFAILED); child->depth = depth; if (child->children != NULL) { PKIX_CHECK(pkix_VerifyNode_SetDepth (child->children, depth + 1, plContext), PKIX_VERIFYNODESETDEPTHFAILED); } PKIX_DECREF(child); } cleanup: PKIX_DECREF(child); PKIX_RETURN(VERIFYNODE); }
/* * FUNCTION: PKIX_PL_AIAMgr_GetAIACerts (see description in pkix_pl_pki.h) */ PKIX_Error * PKIX_PL_AIAMgr_GetAIACerts( PKIX_PL_AIAMgr *aiaMgr, PKIX_PL_Cert *prevCert, void **pNBIOContext, PKIX_List **pCerts, void *plContext) { PKIX_UInt32 numAias = 0; PKIX_UInt32 aiaIndex = 0; PKIX_UInt32 iaType = PKIX_INFOACCESS_LOCATION_UNKNOWN; PKIX_List *certs = NULL; PKIX_PL_InfoAccess *ia = NULL; void *nbio = NULL; PKIX_ENTER(AIAMGR, "PKIX_PL_AIAMgr_GetAIACerts"); PKIX_NULLCHECK_FOUR(aiaMgr, prevCert, pNBIOContext, pCerts); nbio = *pNBIOContext; *pCerts = NULL; *pNBIOContext = NULL; if (nbio == NULL) { /* a new request */ /* Does this Cert have an AIA extension? */ PKIX_CHECK(PKIX_PL_Cert_GetAuthorityInfoAccess (prevCert, &aiaMgr->aia, plContext), PKIX_CERTGETAUTHORITYINFOACCESSFAILED); if (aiaMgr->aia != NULL) { PKIX_CHECK(PKIX_List_GetLength (aiaMgr->aia, &numAias, plContext), PKIX_LISTGETLENGTHFAILED); } /* And if so, does it have any entries? */ if ((aiaMgr->aia == NULL) || (numAias == 0)) { *pCerts = NULL; goto cleanup; } aiaMgr->aiaIndex = 0; aiaMgr->numAias = numAias; aiaMgr->results = NULL; } for (aiaIndex = aiaMgr->aiaIndex; aiaIndex < aiaMgr->numAias; aiaIndex ++) { PKIX_UInt32 method = 0; PKIX_CHECK(PKIX_List_GetItem (aiaMgr->aia, aiaIndex, (PKIX_PL_Object **)&ia, plContext), PKIX_LISTGETITEMFAILED); PKIX_CHECK(PKIX_PL_InfoAccess_GetMethod (ia, &method, plContext), PKIX_INFOACCESSGETMETHODFAILED); if (method != PKIX_INFOACCESS_CA_ISSUERS && method != PKIX_INFOACCESS_CA_REPOSITORY) { PKIX_DECREF(ia); continue; } PKIX_CHECK(PKIX_PL_InfoAccess_GetLocationType (ia, &iaType, plContext), PKIX_INFOACCESSGETLOCATIONTYPEFAILED); if (iaType == PKIX_INFOACCESS_LOCATION_HTTP) { PKIX_CHECK(pkix_pl_AIAMgr_GetHTTPCerts (aiaMgr, ia, &nbio, &certs, plContext), PKIX_AIAMGRGETHTTPCERTSFAILED); } else if (iaType == PKIX_INFOACCESS_LOCATION_LDAP) { PKIX_CHECK(pkix_pl_AIAMgr_GetLDAPCerts (aiaMgr, ia, &nbio, &certs, plContext), PKIX_AIAMGRGETLDAPCERTSFAILED); } else { /* We only support http and ldap requests. */ PKIX_DECREF(ia); continue; } if (nbio != NULL) { /* WOULDBLOCK */ aiaMgr->aiaIndex = aiaIndex; *pNBIOContext = nbio; *pCerts = NULL; goto cleanup; } /* * We can't just use and modify the List we received. * Because it's cached, it's set immutable. */ if (aiaMgr->results == NULL) { PKIX_CHECK(PKIX_List_Create (&(aiaMgr->results), plContext), PKIX_LISTCREATEFAILED); } PKIX_CHECK(pkix_List_AppendList (aiaMgr->results, certs, plContext), PKIX_APPENDLISTFAILED); PKIX_DECREF(certs); PKIX_DECREF(ia); } PKIX_DECREF(aiaMgr->aia); *pNBIOContext = NULL; *pCerts = aiaMgr->results; aiaMgr->results = NULL; cleanup: if (PKIX_ERROR_RECEIVED) { PKIX_DECREF(aiaMgr->aia); PKIX_DECREF(aiaMgr->results); PKIX_DECREF(aiaMgr->client.ldapClient); } PKIX_DECREF(certs); PKIX_DECREF(ia); PKIX_RETURN(AIAMGR); }
/* * FUNCTION: pkix_VerifyNode_AddToChain * DESCRIPTION: * * Adds the VerifyNode pointed to by "child", at the appropriate depth, to the * List of children of the VerifyNode pointed to by "parentNode". The chain of * VerifyNodes is traversed until a VerifyNode is found at a depth one less * than that specified in "child". An Error is returned if there is no parent * at a suitable depth. * * If "parentNode" has a NULL pointer for the List of children, a new List is * created containing "child". Otherwise "child" is appended to the existing * List. * * Depth, in this context, means distance from the root node, which * is at depth zero. * * PARAMETERS: * "parentNode" * Address of VerifyNode whose List of child VerifyNodes is to be * created or appended to. Must be non-NULL. * "child" * Address of VerifyNode to be added to parentNode's List. Must be * non-NULL. * "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 VerifyNode 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_VerifyNode_AddToChain( PKIX_VerifyNode *parentNode, PKIX_VerifyNode *child, void *plContext) { PKIX_VerifyNode *successor = NULL; PKIX_List *listOfChildren = NULL; PKIX_UInt32 numChildren = 0; PKIX_UInt32 parentDepth = 0; PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_AddToChain"); PKIX_NULLCHECK_TWO(parentNode, child); parentDepth = parentNode->depth; listOfChildren = parentNode->children; if (listOfChildren == NULL) { if (parentDepth != (child->depth - 1)) { PKIX_ERROR(PKIX_NODESMISSINGFROMCHAIN); } PKIX_CHECK(PKIX_List_Create(&listOfChildren, plContext), PKIX_LISTCREATEFAILED); PKIX_CHECK(PKIX_List_AppendItem (listOfChildren, (PKIX_PL_Object *)child, plContext), PKIX_COULDNOTAPPENDCHILDTOPARENTSVERIFYNODELIST); parentNode->children = listOfChildren; } else { /* get number of children */ PKIX_CHECK(PKIX_List_GetLength (listOfChildren, &numChildren, plContext), PKIX_LISTGETLENGTHFAILED); if (numChildren != 1) { PKIX_ERROR(PKIX_AMBIGUOUSPARENTAGEOFVERIFYNODE); } /* successor = listOfChildren[0] */ PKIX_CHECK(PKIX_List_GetItem (listOfChildren, 0, (PKIX_PL_Object **)&successor, plContext), PKIX_LISTGETITEMFAILED); PKIX_CHECK(pkix_VerifyNode_AddToChain (successor, child, plContext), PKIX_VERIFYNODEADDTOCHAINFAILED); } PKIX_CHECK(PKIX_PL_Object_InvalidateCache ((PKIX_PL_Object *)parentNode, plContext), PKIX_OBJECTINVALIDATECACHEFAILED); cleanup: PKIX_DECREF(successor); PKIX_RETURN(VERIFYNODE); }
/* * 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); }
int test_buildchain_uchecker(int argc, char *argv[]) { PKIX_BuildResult *buildResult = NULL; PKIX_ComCertSelParams *certSelParams = NULL; PKIX_CertSelector *certSelector = NULL; PKIX_TrustAnchor *anchor = NULL; PKIX_List *anchors = NULL; PKIX_List *certs = NULL; PKIX_PL_Cert *cert = NULL; PKIX_ProcessingParams *procParams = NULL; PKIX_CertChainChecker *checker = NULL; char *dirName = NULL; PKIX_PL_String *dirNameString = NULL; PKIX_PL_Cert *trustedCert = NULL; PKIX_PL_Cert *targetCert = NULL; PKIX_UInt32 numCerts = 0; PKIX_UInt32 i = 0; PKIX_UInt32 j = 0; PKIX_UInt32 k = 0; PKIX_UInt32 chainLength = 0; PKIX_CertStore *certStore = NULL; PKIX_List *certStores = NULL; char * asciiResult = NULL; PKIX_Boolean result; PKIX_Boolean testValid = PKIX_TRUE; PKIX_Boolean supportForward = PKIX_FALSE; PKIX_List *expectedCerts = NULL; PKIX_List *userOIDs = NULL; PKIX_PL_OID *oid = NULL; PKIX_PL_Cert *dirCert = NULL; PKIX_PL_String *actualCertsString = NULL; PKIX_PL_String *expectedCertsString = NULL; char *actualCertsAscii = NULL; char *expectedCertsAscii = NULL; char *oidString = NULL; void *buildState = NULL; /* needed by pkix_build for non-blocking I/O */ void *nbioContext = NULL; /* needed by pkix_build for non-blocking I/O */ PKIX_TEST_STD_VARS(); if (argc < 5){ printUsage(); return (0); } startTests("BuildChain_UserChecker"); PKIX_TEST_EXPECT_NO_ERROR( PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext)); /* ENE = expect no error; EE = expect error */ if (PORT_Strcmp(argv[2+j], "ENE") == 0) { testValid = PKIX_TRUE; } else if (PORT_Strcmp(argv[2+j], "EE") == 0) { testValid = PKIX_FALSE; } else { printUsage(); return (0); } /* OID specified at argv[3+j] */ if (*argv[3+j] != '-') { if (*argv[3+j] == 'F') { supportForward = PKIX_TRUE; oidString = argv[3+j]+1; } else { oidString = argv[3+j]; } PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create (&userOIDs, plContext)); PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create (oidString, &oid, plContext)); PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem (userOIDs, (PKIX_PL_Object *)oid, plContext)); PKIX_TEST_DECREF_BC(oid); } subTest(argv[1+j]); dirName = argv[4+j]; PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&expectedCerts, plContext)); chainLength = argc - j - 5; for (k = 0; k < chainLength; k++){ dirCert = createCert(dirName, argv[5+k+j], plContext); if (k == (chainLength - 1)){ PKIX_TEST_EXPECT_NO_ERROR (PKIX_PL_Object_IncRef ((PKIX_PL_Object *)dirCert, plContext)); trustedCert = dirCert; } else { PKIX_TEST_EXPECT_NO_ERROR (PKIX_List_AppendItem (expectedCerts, (PKIX_PL_Object *)dirCert, plContext)); if (k == 0){ PKIX_TEST_EXPECT_NO_ERROR (PKIX_PL_Object_IncRef ((PKIX_PL_Object *)dirCert, plContext)); targetCert = dirCert; } } PKIX_TEST_DECREF_BC(dirCert); } /* create processing params with list of trust anchors */ PKIX_TEST_EXPECT_NO_ERROR(PKIX_TrustAnchor_CreateWithCert (trustedCert, &anchor, plContext)); PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&anchors, plContext)); PKIX_TEST_EXPECT_NO_ERROR (PKIX_List_AppendItem (anchors, (PKIX_PL_Object *)anchor, plContext)); PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_Create (anchors, &procParams, plContext)); /* create CertSelector with target certificate in params */ PKIX_TEST_EXPECT_NO_ERROR (PKIX_ComCertSelParams_Create(&certSelParams, plContext)); PKIX_TEST_EXPECT_NO_ERROR (PKIX_ComCertSelParams_SetCertificate (certSelParams, targetCert, plContext)); PKIX_TEST_EXPECT_NO_ERROR (PKIX_CertSelector_Create (NULL, NULL, &certSelector, plContext)); PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams (certSelector, certSelParams, plContext)); PKIX_TEST_EXPECT_NO_ERROR (PKIX_ProcessingParams_SetTargetCertConstraints (procParams, certSelector, plContext)); PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertChainChecker_Create (testUserChecker, supportForward, PKIX_FALSE, userOIDs, NULL, &checker, plContext)); PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_AddCertChainChecker (procParams, checker, plContext)); /* create CertStores */ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create (PKIX_ESCASCII, dirName, 0, &dirNameString, plContext)); PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CollectionCertStore_Create (dirNameString, &certStore, plContext)); #if 0 PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Pk11CertStore_Create (&certStore, plContext)); #endif PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&certStores, plContext)); PKIX_TEST_EXPECT_NO_ERROR (PKIX_List_AppendItem (certStores, (PKIX_PL_Object *)certStore, plContext)); PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetCertStores (procParams, certStores, plContext)); /* build cert chain using processing params and return buildResult */ pkixTestErrorResult = PKIX_BuildChain (procParams, &nbioContext, &buildState, &buildResult, NULL, plContext); if (testValid == PKIX_TRUE) { /* ENE */ if (pkixTestErrorResult){ (void) printf("UNEXPECTED RESULT RECEIVED!\n"); } else { (void) printf("EXPECTED RESULT RECEIVED!\n"); PKIX_TEST_DECREF_BC(pkixTestErrorResult); } } else { /* EE */ if (pkixTestErrorResult){ (void) printf("EXPECTED RESULT RECEIVED!\n"); PKIX_TEST_DECREF_BC(pkixTestErrorResult); } else { testError("UNEXPECTED RESULT RECEIVED"); } } if (buildResult){ PKIX_TEST_EXPECT_NO_ERROR (PKIX_BuildResult_GetCertChain (buildResult, &certs, NULL)); PKIX_TEST_EXPECT_NO_ERROR (PKIX_List_GetLength(certs, &numCerts, plContext)); printf("\n"); for (i = 0; i < numCerts; i++){ PKIX_TEST_EXPECT_NO_ERROR (PKIX_List_GetItem (certs, i, (PKIX_PL_Object**)&cert, plContext)); asciiResult = PKIX_Cert2ASCII(cert); printf("CERT[%d]:\n%s\n", i, asciiResult); PKIX_TEST_EXPECT_NO_ERROR (PKIX_PL_Free(asciiResult, plContext)); asciiResult = NULL; PKIX_TEST_DECREF_BC(cert); } PKIX_TEST_EXPECT_NO_ERROR (PKIX_PL_Object_Equals ((PKIX_PL_Object*)certs, (PKIX_PL_Object*)expectedCerts, &result, plContext)); if (!result){ testError("BUILT CERTCHAIN IS " "NOT THE ONE THAT WAS EXPECTED"); PKIX_TEST_EXPECT_NO_ERROR (PKIX_PL_Object_ToString ((PKIX_PL_Object *)certs, &actualCertsString, plContext)); actualCertsAscii = PKIX_String2ASCII (actualCertsString, plContext); if (actualCertsAscii == NULL){ pkixTestErrorMsg = "PKIX_String2ASCII Failed"; goto cleanup; } PKIX_TEST_EXPECT_NO_ERROR (PKIX_PL_Object_ToString ((PKIX_PL_Object *)expectedCerts, &expectedCertsString, plContext)); expectedCertsAscii = PKIX_String2ASCII (expectedCertsString, plContext); if (expectedCertsAscii == NULL){ pkixTestErrorMsg = "PKIX_String2ASCII Failed"; goto cleanup; } (void) printf("Actual value:\t%s\n", actualCertsAscii); (void) printf("Expected value:\t%s\n", expectedCertsAscii); if (chainLength - 1 != numUserCheckerCalled) { pkixTestErrorMsg = "PKIX user defined checker not called"; } goto cleanup; } } cleanup: PKIX_PL_Free(asciiResult, plContext); PKIX_PL_Free(actualCertsAscii, plContext); PKIX_PL_Free(expectedCertsAscii, plContext); PKIX_TEST_DECREF_AC(actualCertsString); PKIX_TEST_DECREF_AC(expectedCertsString); PKIX_TEST_DECREF_AC(expectedCerts); PKIX_TEST_DECREF_AC(certs); PKIX_TEST_DECREF_AC(cert); PKIX_TEST_DECREF_AC(certStore); PKIX_TEST_DECREF_AC(certStores); PKIX_TEST_DECREF_AC(dirNameString); PKIX_TEST_DECREF_AC(trustedCert); PKIX_TEST_DECREF_AC(targetCert); PKIX_TEST_DECREF_AC(anchor); PKIX_TEST_DECREF_AC(anchors); PKIX_TEST_DECREF_AC(procParams); PKIX_TEST_DECREF_AC(certSelParams); PKIX_TEST_DECREF_AC(certSelector); PKIX_TEST_DECREF_AC(buildResult); PKIX_TEST_DECREF_AC(procParams); PKIX_TEST_DECREF_AC(userOIDs); PKIX_TEST_DECREF_AC(checker); PKIX_TEST_RETURN(); PKIX_Shutdown(plContext); endTests("BuildChain_UserChecker"); return (0); }
/* * FUNCTION: pkix_pl_LdapCertStore_BuildCertList * DESCRIPTION: * * This function takes a List of LdapResponse objects pointed to by * "responseList" and extracts and decodes the Certificates in those responses, * storing the List of those Certificates at "pCerts". If none of the objects * can be decoded into a Cert, the returned List is empty. * * PARAMETERS: * "responseList" * The address of the List of LdapResponses. Must be non-NULL. * "pCerts" * The address at which the result is 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 CertStore 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_LdapCertStore_BuildCertList( PKIX_List *responseList, PKIX_List **pCerts, void *plContext) { PKIX_UInt32 numResponses = 0; PKIX_UInt32 respIx = 0; LdapAttrMask attrBits = 0; PKIX_PL_LdapResponse *response = NULL; PKIX_List *certList = NULL; LDAPMessage *message = NULL; LDAPSearchResponseEntry *sre = NULL; LDAPSearchResponseAttr **sreAttrArray = NULL; LDAPSearchResponseAttr *sreAttr = NULL; SECItem *attrType = NULL; SECItem **attrVal = NULL; SECItem *derCertItem = NULL; PKIX_ENTER(CERTSTORE, "pkix_pl_LdapCertStore_BuildCertList"); PKIX_NULLCHECK_TWO(responseList, pCerts); PKIX_CHECK(PKIX_List_Create(&certList, plContext), PKIX_LISTCREATEFAILED); /* extract certs from response */ PKIX_CHECK(PKIX_List_GetLength (responseList, &numResponses, plContext), PKIX_LISTGETLENGTHFAILED); for (respIx = 0; respIx < numResponses; respIx++) { PKIX_CHECK(PKIX_List_GetItem (responseList, respIx, (PKIX_PL_Object **)&response, plContext), PKIX_LISTGETITEMFAILED); PKIX_CHECK(pkix_pl_LdapResponse_GetMessage (response, &message, plContext), PKIX_LDAPRESPONSEGETMESSAGEFAILED); sre = &(message->protocolOp.op.searchResponseEntryMsg); sreAttrArray = sre->attributes; /* Get next element of null-terminated array */ sreAttr = *sreAttrArray++; while (sreAttr != NULL) { attrType = &(sreAttr->attrType); PKIX_CHECK(pkix_pl_LdapRequest_AttrTypeToBit (attrType, &attrBits, plContext), PKIX_LDAPREQUESTATTRTYPETOBITFAILED); /* Is this attrVal a Certificate? */ if (((LDAPATTR_CACERT | LDAPATTR_USERCERT) & attrBits) == attrBits) { attrVal = sreAttr->val; derCertItem = *attrVal++; while (derCertItem != 0) { /* create a PKIX_PL_Cert from derCert */ PKIX_CHECK(pkix_pl_Cert_CreateToList (derCertItem, certList, plContext), PKIX_CERTCREATETOLISTFAILED); derCertItem = *attrVal++; } } else if ((LDAPATTR_CROSSPAIRCERT & attrBits) == attrBits){ /* Is this attrVal a CrossPairCertificate? */ attrVal = sreAttr->val; derCertItem = *attrVal++; while (derCertItem != 0) { /* create PKIX_PL_Certs from derCert */ PKIX_CHECK(pkix_pl_LdapCertStore_DecodeCrossCertPair (derCertItem, certList, plContext), PKIX_LDAPCERTSTOREDECODECROSSCERTPAIRFAILED); derCertItem = *attrVal++; } } sreAttr = *sreAttrArray++; } PKIX_DECREF(response); } *pCerts = certList; cleanup: if (PKIX_ERROR_RECEIVED) { PKIX_DECREF(certList); } PKIX_DECREF(response); PKIX_RETURN(CERTSTORE); }
/* * FUNCTION: pkix_pl_LdapCertStore_BuildCrlList * DESCRIPTION: * * This function takes a List of LdapResponse objects pointed to by * "responseList" and extracts and decodes the CRLs in those responses, storing * the List of those CRLs at "pCrls". If none of the objects can be decoded * into a CRL, the returned List is empty. * * PARAMETERS: * "responseList" * The address of the List of LdapResponses. Must be non-NULL. * "pCrls" * The address at which the result is 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 CertStore 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_LdapCertStore_BuildCrlList( PKIX_List *responseList, PKIX_List **pCrls, void *plContext) { PKIX_UInt32 numResponses = 0; PKIX_UInt32 respIx = 0; LdapAttrMask attrBits = 0; CERTSignedCrl *nssCrl = NULL; PKIX_PL_LdapResponse *response = NULL; PKIX_List *crlList = NULL; PKIX_PL_CRL *crl = NULL; LDAPMessage *message = NULL; LDAPSearchResponseEntry *sre = NULL; LDAPSearchResponseAttr **sreAttrArray = NULL; LDAPSearchResponseAttr *sreAttr = NULL; SECItem *attrType = NULL; SECItem **attrVal = NULL; SECItem *derCrlCopy = NULL; SECItem *derCrlItem = NULL; PKIX_ENTER(CERTSTORE, "pkix_pl_LdapCertStore_BuildCrlList"); PKIX_NULLCHECK_TWO(responseList, pCrls); PKIX_CHECK(PKIX_List_Create(&crlList, plContext), PKIX_LISTCREATEFAILED); /* extract crls from response */ PKIX_CHECK(PKIX_List_GetLength (responseList, &numResponses, plContext), PKIX_LISTGETLENGTHFAILED); for (respIx = 0; respIx < numResponses; respIx++) { PKIX_CHECK(PKIX_List_GetItem (responseList, respIx, (PKIX_PL_Object **)&response, plContext), PKIX_LISTGETITEMFAILED); PKIX_CHECK(pkix_pl_LdapResponse_GetMessage (response, &message, plContext), PKIX_LDAPRESPONSEGETMESSAGEFAILED); sre = &(message->protocolOp.op.searchResponseEntryMsg); sreAttrArray = sre->attributes; /* Get next element of null-terminated array */ sreAttr = *sreAttrArray++; while (sreAttr != NULL) { attrType = &(sreAttr->attrType); PKIX_CHECK(pkix_pl_LdapRequest_AttrTypeToBit (attrType, &attrBits, plContext), PKIX_LDAPREQUESTATTRTYPETOBITFAILED); /* Is this attrVal a Revocation List? */ if (((LDAPATTR_CERTREVLIST | LDAPATTR_AUTHREVLIST) & attrBits) == attrBits) { attrVal = sreAttr->val; derCrlItem = *attrVal++; while (derCrlItem != 0) { /* create a PKIX_PL_Crl from derCrl */ derCrlCopy = SECITEM_DupItem(derCrlItem); if (!derCrlCopy) { PKIX_ERROR(PKIX_ALLOCERROR); } /* crl will be based on derCrlCopy, but wont * own the der. */ nssCrl = CERT_DecodeDERCrlWithFlags(NULL, derCrlCopy, SEC_CRL_TYPE, CRL_DECODE_DONT_COPY_DER | CRL_DECODE_SKIP_ENTRIES); if (!nssCrl) { SECITEM_FreeItem(derCrlCopy, PKIX_TRUE); continue; } /* pkix crl own the der. */ PKIX_CHECK( pkix_pl_CRL_CreateWithSignedCRL(nssCrl, derCrlCopy, NULL, &crl, plContext), PKIX_CRLCREATEWITHSIGNEDCRLFAILED); /* Left control over memory pointed by derCrlCopy and * nssCrl to pkix crl. */ derCrlCopy = NULL; nssCrl = NULL; PKIX_CHECK(PKIX_List_AppendItem (crlList, (PKIX_PL_Object *) crl, plContext), PKIX_LISTAPPENDITEMFAILED); PKIX_DECREF(crl); derCrlItem = *attrVal++; } /* Clean up after PKIX_CHECK_ONLY_FATAL */ pkixTempErrorReceived = PKIX_FALSE; } sreAttr = *sreAttrArray++; } PKIX_DECREF(response); } *pCrls = crlList; crlList = NULL; cleanup: if (derCrlCopy) { SECITEM_FreeItem(derCrlCopy, PKIX_TRUE); } if (nssCrl) { SEC_DestroyCrl(nssCrl); } PKIX_DECREF(crl); PKIX_DECREF(crlList); PKIX_DECREF(response); PKIX_RETURN(CERTSTORE); }
/* * FUNCTION: pkix_TargetCertChecker_Check * (see comments for PKIX_CertChainChecker_CheckCallback in pkix_checker.h) */ PKIX_Error * pkix_TargetCertChecker_Check( PKIX_CertChainChecker *checker, PKIX_PL_Cert *cert, PKIX_List *unresolvedCriticalExtensions, void **pNBIOContext, void *plContext) { pkix_TargetCertCheckerState *state = NULL; PKIX_CertSelector_MatchCallback certSelectorMatch = NULL; PKIX_PL_CertNameConstraints *nameConstraints = NULL; PKIX_List *certSubjAltNames = NULL; PKIX_List *certExtKeyUsageList = NULL; PKIX_PL_GeneralName *name = NULL; PKIX_PL_X500Name *certSubjectName = NULL; PKIX_Boolean checkPassed = PKIX_FALSE; PKIX_UInt32 numItems, i; PKIX_UInt32 matchCount = 0; PKIX_ENTER(CERTCHAINCHECKER, "pkix_TargetCertChecker_Check"); PKIX_NULLCHECK_THREE(checker, cert, pNBIOContext); *pNBIOContext = NULL; /* we never block on pending I/O */ PKIX_CHECK(PKIX_CertChainChecker_GetCertChainCheckerState (checker, (PKIX_PL_Object **)&state, plContext), PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED); (state->certsRemaining)--; if (state->pathToNameList != NULL) { PKIX_CHECK(PKIX_PL_Cert_GetNameConstraints (cert, &nameConstraints, plContext), PKIX_CERTGETNAMECONSTRAINTSFAILED); /* * XXX We should either make the following call a public one * so it is legal to call from the portability layer or we * should try to create pathToNameList as CertNameConstraints * then call the existing check function. */ PKIX_CHECK(PKIX_PL_CertNameConstraints_CheckNamesInNameSpace (state->pathToNameList, nameConstraints, &checkPassed, plContext), PKIX_CERTNAMECONSTRAINTSCHECKNAMEINNAMESPACEFAILED); if (checkPassed != PKIX_TRUE) { PKIX_ERROR(PKIX_VALIDATIONFAILEDPATHTONAMECHECKFAILED); } } PKIX_CHECK(PKIX_PL_Cert_GetSubjectAltNames (cert, &certSubjAltNames, plContext), PKIX_CERTGETSUBJALTNAMESFAILED); if (state->subjAltNameList != NULL && certSubjAltNames != NULL) { PKIX_CHECK(PKIX_List_GetLength (state->subjAltNameList, &numItems, plContext), PKIX_LISTGETLENGTHFAILED); for (i = 0; i < numItems; i++) { PKIX_CHECK(PKIX_List_GetItem (state->subjAltNameList, i, (PKIX_PL_Object **) &name, plContext), PKIX_LISTGETITEMFAILED); PKIX_CHECK(pkix_List_Contains (certSubjAltNames, (PKIX_PL_Object *) name, &checkPassed, plContext), PKIX_LISTCONTAINSFAILED); PKIX_DECREF(name); if (checkPassed == PKIX_TRUE) { if (state->subjAltNameMatchAll == PKIX_FALSE) { matchCount = numItems; break; } else { /* else continue checking next */ matchCount++; } } } if (matchCount != numItems) { PKIX_ERROR(PKIX_SUBJALTNAMECHECKFAILED); } } if (state->certsRemaining == 0) { if (state->certSelector != NULL) { PKIX_CHECK(PKIX_CertSelector_GetMatchCallback (state->certSelector, &certSelectorMatch, plContext), PKIX_CERTSELECTORGETMATCHCALLBACKFAILED); PKIX_CHECK(certSelectorMatch (state->certSelector, cert, plContext), PKIX_CERTSELECTORMATCHFAILED); } else { /* Check at least cert/key usages if target cert selector * is not set. */ PKIX_CHECK(PKIX_PL_Cert_VerifyCertAndKeyType(cert, PKIX_FALSE /* is chain cert*/, plContext), PKIX_CERTVERIFYCERTTYPEFAILED); } /* * There are two Extended Key Usage Checkings * available : * 1) here at the targetcertchecker where we * verify the Extended Key Usage OIDs application * specifies via ComCertSelParams are included * in Cert's Extended Key Usage OID's. Note, * this is an OID to OID comparison and only last * Cert is checked. * 2) at user defined ekuchecker where checking * is applied to all Certs on the chain and * the NSS Extended Key Usage algorithm is * used. In order to invoke this checking, not * only does the ComCertSelparams needs to be * set, the EKU initialize call is required to * activate the checking. * * XXX We use the same ComCertSelParams Set/Get * functions to set the parameters for both cases. * We may want to separate them in the future. */ PKIX_CHECK(PKIX_PL_Cert_GetExtendedKeyUsage (cert, &certExtKeyUsageList, plContext), PKIX_CERTGETEXTENDEDKEYUSAGEFAILED); if (state->extKeyUsageList != NULL && certExtKeyUsageList != NULL) { PKIX_CHECK(PKIX_List_GetLength (state->extKeyUsageList, &numItems, plContext), PKIX_LISTGETLENGTHFAILED); for (i = 0; i < numItems; i++) { PKIX_CHECK(PKIX_List_GetItem (state->extKeyUsageList, i, (PKIX_PL_Object **) &name, plContext), PKIX_LISTGETITEMFAILED); PKIX_CHECK(pkix_List_Contains (certExtKeyUsageList, (PKIX_PL_Object *) name, &checkPassed, plContext), PKIX_LISTCONTAINSFAILED); PKIX_DECREF(name); if (checkPassed != PKIX_TRUE) { PKIX_ERROR (PKIX_EXTENDEDKEYUSAGECHECKINGFAILED); } } } } else { /* Check key usage and cert type based on certificate usage. */ PKIX_CHECK(PKIX_PL_Cert_VerifyCertAndKeyType(cert, PKIX_TRUE, plContext), PKIX_CERTVERIFYCERTTYPEFAILED); } /* Remove Critical Extension OID from list */ if (unresolvedCriticalExtensions != NULL) { PKIX_CHECK(pkix_List_Remove (unresolvedCriticalExtensions, (PKIX_PL_Object *) state->extKeyUsageOID, plContext), PKIX_LISTREMOVEFAILED); PKIX_CHECK(PKIX_PL_Cert_GetSubject (cert, &certSubjectName, plContext), PKIX_CERTGETSUBJECTFAILED); if (certSubjAltNames != NULL) { PKIX_CHECK(pkix_List_Remove (unresolvedCriticalExtensions, (PKIX_PL_Object *) state->subjAltNameOID, plContext), PKIX_LISTREMOVEFAILED); } } cleanup: PKIX_DECREF(name); PKIX_DECREF(nameConstraints); PKIX_DECREF(certSubjAltNames); PKIX_DECREF(certExtKeyUsageList); PKIX_DECREF(certSubjectName); PKIX_DECREF(state); PKIX_RETURN(CERTCHAINCHECKER); }
/* * FUNCTION: pkix_pl_CollectionCertStoreContext_GetSelectedCRL * DESCRIPTION: * * Finds the CRLs that match the criterion of the CRLSelector pointed * to by "selector" using the List of CRLs pointed to by "crlList" and * stores the matching CRLs at "pSelectedCrlList". * * Not recursive to sub-directory. * * PARAMETERS * "crlList" - Address of List of CRLs to be searched. Must be non-NULL * "selector" - CRLSelector for chosing CRL based on Params set * "pSelectedCrlList" - CRLs that qualified by selector. * "plContext" - Platform-specific context pointer. * * THREAD SAFETY: * Not Thread Safe - A lock at top level is required. * * RETURNS: * Returns NULL if the function succeeds. * Returns a CollectionCertStoreContext 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_CollectionCertStoreContext_GetSelectedCRL( PKIX_List *crlList, PKIX_CRLSelector *selector, PKIX_List **pSelectedCrlList, void *plContext) { PKIX_List *selectCrlList = NULL; PKIX_PL_CRL *crlItem = NULL; PKIX_CRLSelector_MatchCallback crlSelectorMatch = NULL; PKIX_UInt32 numCrls = 0; PKIX_UInt32 i = 0; PKIX_Boolean match = PKIX_FALSE; PKIX_ENTER(COLLECTIONCERTSTORECONTEXT, "pkix_pl_CollectionCertStoreContext_GetSelectedCRL"); PKIX_NULLCHECK_THREE(crlList, selector, pSelectedCrlList); PKIX_CHECK(PKIX_CRLSelector_GetMatchCallback (selector, &crlSelectorMatch, plContext), PKIX_CRLSELECTORGETMATCHCALLBACKFAILED); PKIX_CHECK(PKIX_List_GetLength(crlList, &numCrls, plContext), PKIX_LISTGETLENGTHFAILED); if (crlSelectorMatch) { PKIX_CHECK(PKIX_List_Create(&selectCrlList, plContext), PKIX_LISTCREATEFAILED); for (i = 0; i < numCrls; i++) { PKIX_CHECK_ONLY_FATAL(PKIX_List_GetItem (crlList, i, (PKIX_PL_Object **) &crlItem, plContext), PKIX_LISTGETITEMFAILED); if (!PKIX_ERROR_RECEIVED){ PKIX_CHECK_ONLY_FATAL (crlSelectorMatch (selector, crlItem, &match, plContext), PKIX_CRLSELECTORMATCHFAILED); if (!(PKIX_ERROR_RECEIVED) && match) { PKIX_CHECK_ONLY_FATAL (PKIX_List_AppendItem (selectCrlList, (PKIX_PL_Object *)crlItem, plContext), PKIX_LISTAPPENDITEMFAILED); } } PKIX_DECREF(crlItem); } } else { PKIX_INCREF(crlList); selectCrlList = crlList; } /* Don't throw away the list if one CRL was bad! */ pkixTempErrorReceived = PKIX_FALSE; *pSelectedCrlList = selectCrlList; cleanup: PKIX_RETURN(COLLECTIONCERTSTORECONTEXT); }
int test_buildchain(int argc, char *argv[]) { PKIX_BuildResult *buildResult = NULL; PKIX_ComCertSelParams *certSelParams = NULL; PKIX_CertSelector *certSelector = NULL; PKIX_TrustAnchor *anchor = NULL; PKIX_PL_PublicKey *trustedPubKey = NULL; PKIX_List *anchors = NULL; PKIX_List *certs = NULL; PKIX_RevocationChecker *revChecker = NULL; PKIX_PL_Cert *cert = NULL; PKIX_ProcessingParams *procParams = NULL; char *dirName = NULL; PKIX_PL_String *dirNameString = NULL; PKIX_PL_Cert *trustedCert = NULL; PKIX_PL_Cert *targetCert = NULL; PKIX_UInt32 actualMinorVersion = 0; PKIX_UInt32 numCerts = 0; PKIX_UInt32 i = 0; PKIX_UInt32 j = 0; PKIX_UInt32 k = 0; PKIX_CertStore *ldapCertStore = NULL; PRIntervalTime timeout = PR_INTERVAL_NO_TIMEOUT; /* blocking */ /* PRIntervalTime timeout = PR_INTERVAL_NO_WAIT; =0 for non-blocking */ PKIX_CertStore *certStore = NULL; PKIX_List *certStores = NULL; PKIX_List *revCheckers = NULL; char *asciiResult = NULL; PKIX_Boolean result = PKIX_FALSE; PKIX_Boolean testValid = PKIX_TRUE; PKIX_List *expectedCerts = NULL; PKIX_PL_Cert *dirCert = NULL; PKIX_VerifyNode *verifyTree = NULL; PKIX_PL_String *verifyString = NULL; PKIX_PL_String *actualCertsString = NULL; PKIX_PL_String *expectedCertsString = NULL; void *state = NULL; char *actualCertsAscii = NULL; char *expectedCertsAscii = NULL; PRPollDesc *pollDesc = NULL; PKIX_TEST_STD_VARS(); if (argc < 5) { printUsage(); return (0); } startTests("BuildChain"); PKIX_TEST_EXPECT_NO_ERROR( PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext)); /* * arguments: * [optional] -arenas * [optional] usebind * servername or servername:port ( - for no server) * testname * EE or ENE * cert directory * target cert (end entity) * intermediate certs * trust anchor */ /* optional argument "usebind" for Ldap CertStore */ if (argv[j + 1]) { if (PORT_Strcmp(argv[j + 1], "usebind") == 0) { usebind = PKIX_TRUE; j++; } } if (PORT_Strcmp(argv[++j], "-") == 0) { useLDAP = PKIX_FALSE; } else { serverName = argv[j]; useLDAP = PKIX_TRUE; } subTest(argv[++j]); /* ENE = expect no error; EE = expect error */ if (PORT_Strcmp(argv[++j], "ENE") == 0) { testValid = PKIX_TRUE; } else if (PORT_Strcmp(argv[j], "EE") == 0) { testValid = PKIX_FALSE; } else { printUsage(); return (0); } dirName = argv[++j]; PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&expectedCerts, plContext)); for (k = ++j; k < (PKIX_UInt32)argc; k++) { dirCert = createCert(dirName, argv[k], plContext); if (k == (PKIX_UInt32)(argc - 1)) { PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_IncRef((PKIX_PL_Object *)dirCert, plContext)); trustedCert = dirCert; } else { PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(expectedCerts, (PKIX_PL_Object *)dirCert, plContext)); if (k == j) { PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_IncRef((PKIX_PL_Object *)dirCert, plContext)); targetCert = dirCert; } } PKIX_TEST_DECREF_BC(dirCert); } /* create processing params with list of trust anchors */ PKIX_TEST_EXPECT_NO_ERROR(PKIX_TrustAnchor_CreateWithCert(trustedCert, &anchor, plContext)); PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&anchors, plContext)); PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(anchors, (PKIX_PL_Object *)anchor, plContext)); PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_Create(anchors, &procParams, plContext)); /* create CertSelector with target certificate in params */ PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&certSelParams, plContext)); PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetCertificate(certSelParams, targetCert, plContext)); PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_Create(NULL, NULL, &certSelector, plContext)); PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertSelector_SetCommonCertSelectorParams(certSelector, certSelParams, plContext)); PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetTargetCertConstraints(procParams, certSelector, plContext)); /* create CertStores */ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII, dirName, 0, &dirNameString, plContext)); PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&certStores, plContext)); if (useLDAP == PKIX_TRUE) { PKIX_TEST_EXPECT_NO_ERROR(createLdapCertStore(serverName, timeout, &ldapCertStore, plContext)); PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(certStores, (PKIX_PL_Object *)ldapCertStore, plContext)); } else { PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CollectionCertStore_Create(dirNameString, &certStore, plContext)); PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(certStores, (PKIX_PL_Object *)certStore, plContext)); } PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetCertStores(procParams, certStores, plContext)); PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&revCheckers, plContext)); PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubjectPublicKey(trustedCert, &trustedPubKey, plContext)); PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(expectedCerts, &numCerts, plContext)); PKIX_TEST_EXPECT_NO_ERROR(pkix_DefaultRevChecker_Initialize(certStores, NULL, /* testDate, may be NULL */ trustedPubKey, numCerts, &revChecker, plContext)); PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(revCheckers, (PKIX_PL_Object *)revChecker, plContext)); PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetRevocationCheckers(procParams, revCheckers, plContext)); #ifdef debuggingWithoutRevocation PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetRevocationEnabled(procParams, PKIX_FALSE, plContext)); #endif /* build cert chain using processing params and return buildResult */ pkixTestErrorResult = PKIX_BuildChain(procParams, (void **)&pollDesc, &state, &buildResult, &verifyTree, plContext); while (pollDesc != NULL) { if (PR_Poll(pollDesc, 1, 0) < 0) { testError("PR_Poll failed"); } pkixTestErrorResult = PKIX_BuildChain(procParams, (void **)&pollDesc, &state, &buildResult, &verifyTree, plContext); } if (pkixTestErrorResult) { if (testValid == PKIX_FALSE) { /* EE */ (void)printf("EXPECTED ERROR RECEIVED!\n"); } else { /* ENE */ testError("UNEXPECTED ERROR RECEIVED"); } } else { if (testValid == PKIX_TRUE) { /* ENE */ (void)printf("EXPECTED NON-ERROR RECEIVED!\n"); } else { /* EE */ (void)printf("UNEXPECTED NON-ERROR RECEIVED!\n"); } } subTest("Displaying VerifyNode objects"); if (verifyTree == NULL) { PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII, "(null)", 0, &verifyString, plContext)); } else { PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)verifyTree, &verifyString, plContext)); } (void)printf("verifyTree is\n%s\n", verifyString->escAsciiString); if (pkixTestErrorResult) { PKIX_TEST_DECREF_BC(pkixTestErrorResult); goto cleanup; } if (buildResult) { PKIX_TEST_EXPECT_NO_ERROR(PKIX_BuildResult_GetCertChain(buildResult, &certs, plContext)); PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(certs, &numCerts, plContext)); printf("\n"); for (i = 0; i < numCerts; i++) { PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(certs, i, (PKIX_PL_Object **)&cert, plContext)); asciiResult = PKIX_Cert2ASCII(cert); printf("CERT[%d]:\n%s\n", i, asciiResult); /* PKIX_Cert2ASCII used PKIX_PL_Malloc(...,,NULL) */ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(asciiResult, NULL)); asciiResult = NULL; PKIX_TEST_DECREF_BC(cert); } PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals((PKIX_PL_Object *)certs, (PKIX_PL_Object *)expectedCerts, &result, plContext)); if (!result) { testError("BUILT CERTCHAIN IS " "NOT THE ONE THAT WAS EXPECTED"); PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)certs, &actualCertsString, plContext)); actualCertsAscii = PKIX_String2ASCII(actualCertsString, plContext); if (actualCertsAscii == NULL) { pkixTestErrorMsg = "PKIX_String2ASCII Failed"; goto cleanup; } PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)expectedCerts, &expectedCertsString, plContext)); expectedCertsAscii = PKIX_String2ASCII(expectedCertsString, plContext); if (expectedCertsAscii == NULL) { pkixTestErrorMsg = "PKIX_String2ASCII Failed"; goto cleanup; } (void)printf("Actual value:\t%s\n", actualCertsAscii); (void)printf("Expected value:\t%s\n", expectedCertsAscii); } } cleanup: PKIX_TEST_DECREF_AC(verifyString); PKIX_TEST_DECREF_AC(verifyTree); PKIX_PL_Free(asciiResult, NULL); PKIX_PL_Free(actualCertsAscii, plContext); PKIX_PL_Free(expectedCertsAscii, plContext); PKIX_TEST_DECREF_AC(state); PKIX_TEST_DECREF_AC(actualCertsString); PKIX_TEST_DECREF_AC(expectedCertsString); PKIX_TEST_DECREF_AC(expectedCerts); PKIX_TEST_DECREF_AC(buildResult); PKIX_TEST_DECREF_AC(procParams); PKIX_TEST_DECREF_AC(certStores); PKIX_TEST_DECREF_AC(revCheckers); PKIX_TEST_DECREF_AC(revChecker); PKIX_TEST_DECREF_AC(ldapCertStore); PKIX_TEST_DECREF_AC(certStore); PKIX_TEST_DECREF_AC(dirNameString); PKIX_TEST_DECREF_AC(certSelParams); PKIX_TEST_DECREF_AC(certSelector); PKIX_TEST_DECREF_AC(anchors); PKIX_TEST_DECREF_AC(anchor); PKIX_TEST_DECREF_AC(trustedCert); PKIX_TEST_DECREF_AC(trustedPubKey); PKIX_TEST_DECREF_AC(certs); PKIX_TEST_DECREF_AC(cert); PKIX_TEST_DECREF_AC(targetCert); PKIX_TEST_RETURN(); PKIX_Shutdown(plContext); endTests("BuildChain"); return (0); }
/* * FUNCTION: pkix_CrlChecker_CheckLocal * * 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_CheckLocal( PKIX_PL_Cert *cert, PKIX_PL_Cert *issuer, PKIX_PL_Date *date, pkix_RevocationMethod *checkerObject, PKIX_ProcessingParams *procParams, PKIX_UInt32 methodFlags, PKIX_Boolean chainVerificationState, PKIX_RevocationStatus *pRevStatus, PKIX_UInt32 *pReasonCode, void *plContext) { PKIX_CertStore_CheckRevokationByCrlCallback storeCheckRevocationFn; PKIX_CertStore *certStore = NULL; pkix_CrlChecker *state = NULL; PKIX_UInt32 reasonCode = 0; PKIX_UInt32 crlStoreIndex = 0; PKIX_UInt32 numCrlStores = 0; PKIX_Boolean storeIsLocal = PKIX_FALSE; PKIX_RevocationStatus revStatus = PKIX_RevStatus_NoInfo; PKIX_ENTER(CERTCHAINCHECKER, "pkix_CrlChecker_CheckLocal"); PKIX_NULLCHECK_FOUR(cert, issuer, checkerObject, checkerObject); state = (pkix_CrlChecker*)checkerObject; PKIX_CHECK( PKIX_List_GetLength(state->certStores, &numCrlStores, plContext), PKIX_LISTGETLENGTHFAILED); 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_GetCrlCheckerFn(certStore, &storeCheckRevocationFn, plContext), PKIX_CERTSTOREGETCHECKREVBYCRLFAILED); if (storeCheckRevocationFn) { PKIX_CHECK( (*storeCheckRevocationFn)(certStore, cert, issuer, /* delay sig check if building * a chain by not specifying the time*/ chainVerificationState ? date : NULL, /* crl downloading is not done. */ PKIX_FALSE, &reasonCode, &revStatus, plContext), PKIX_CERTSTORECRLCHECKFAILED); if (revStatus == PKIX_RevStatus_Revoked) { break; } } } PKIX_DECREF(certStore); } /* while */ cleanup: *pRevStatus = revStatus; PKIX_DECREF(certStore); PKIX_RETURN(CERTCHAINCHECKER); }
/* * FUNCTION: pkix_VerifyNode_ToString_Helper * DESCRIPTION: * * Produces a String representation of a VerifyNode tree below the VerifyNode * pointed to by "rootNode", with each line of output prefixed by the String * pointed to by "indent", and stores the result at "pTreeString". It is * called recursively, with ever-increasing indentation, for successively * lower nodes on the tree. * * PARAMETERS: * "rootNode" * Address of VerifyNode subtree. Must be non-NULL. * "indent" * Address of String to be prefixed to each line of output. May be NULL * if no indentation is desired * "pTreeString" * Address where the resulting String will be stored; must be non-NULL * "plContext" * Platform-specific context pointer. * THREAD SAFETY: * Conditionally Thread Safe * (see Thread Safety Definitions in Programmer's Guide) * RETURNS: * Returns NULL if the function succeeds. * Returns a VerifyNode 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_VerifyNode_ToString_Helper( PKIX_VerifyNode *rootNode, PKIX_PL_String *indent, PKIX_PL_String **pTreeString, void *plContext) { PKIX_PL_String *nextIndentFormat = NULL; PKIX_PL_String *thisNodeFormat = NULL; PKIX_PL_String *childrenFormat = NULL; PKIX_PL_String *nextIndentString = NULL; PKIX_PL_String *resultString = NULL; PKIX_PL_String *thisItemString = NULL; PKIX_PL_String *childString = NULL; PKIX_VerifyNode *childNode = NULL; PKIX_UInt32 numberOfChildren = 0; PKIX_UInt32 childIndex = 0; PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_ToString_Helper"); PKIX_NULLCHECK_TWO(rootNode, pTreeString); /* Create a string for this node */ PKIX_CHECK(pkix_SingleVerifyNode_ToString (rootNode, &thisItemString, plContext), PKIX_ERRORINSINGLEVERIFYNODETOSTRING); if (indent) { PKIX_CHECK(PKIX_PL_String_Create (PKIX_ESCASCII, "%s%s", 0, &thisNodeFormat, plContext), PKIX_ERRORCREATINGFORMATSTRING); PKIX_CHECK(PKIX_PL_Sprintf (&resultString, plContext, thisNodeFormat, indent, thisItemString), PKIX_ERRORINSPRINTF); } else { PKIX_CHECK(PKIX_PL_String_Create (PKIX_ESCASCII, "%s", 0, &thisNodeFormat, plContext), PKIX_ERRORCREATINGFORMATSTRING); PKIX_CHECK(PKIX_PL_Sprintf (&resultString, plContext, thisNodeFormat, thisItemString), PKIX_ERRORINSPRINTF); } PKIX_DECREF(thisItemString); thisItemString = resultString; /* if no children, we are done */ if (rootNode->children) { PKIX_CHECK(PKIX_List_GetLength (rootNode->children, &numberOfChildren, plContext), PKIX_LISTGETLENGTHFAILED); } if (numberOfChildren != 0) { /* * We create a string for each child in turn, * concatenating them to thisItemString. */ /* Prepare an indent string for each child */ if (indent) { PKIX_CHECK(PKIX_PL_String_Create (PKIX_ESCASCII, "%s. ", 0, &nextIndentFormat, plContext), PKIX_ERRORCREATINGFORMATSTRING); PKIX_CHECK(PKIX_PL_Sprintf (&nextIndentString, plContext, nextIndentFormat, indent), PKIX_ERRORINSPRINTF); } else { PKIX_CHECK(PKIX_PL_String_Create (PKIX_ESCASCII, ". ", 0, &nextIndentString, plContext), PKIX_ERRORCREATINGINDENTSTRING); } /* Prepare the format for concatenation. */ PKIX_CHECK(PKIX_PL_String_Create (PKIX_ESCASCII, "%s\n%s", 0, &childrenFormat, plContext), PKIX_ERRORCREATINGFORMATSTRING); for (childIndex = 0; childIndex < numberOfChildren; childIndex++) { PKIX_CHECK(PKIX_List_GetItem (rootNode->children, childIndex, (PKIX_PL_Object **)&childNode, plContext), PKIX_LISTGETITEMFAILED); PKIX_CHECK(pkix_VerifyNode_ToString_Helper (childNode, nextIndentString, &childString, plContext), PKIX_ERRORCREATINGCHILDSTRING); PKIX_CHECK(PKIX_PL_Sprintf (&resultString, plContext, childrenFormat, thisItemString, childString), PKIX_ERRORINSPRINTF); PKIX_DECREF(childNode); PKIX_DECREF(childString); PKIX_DECREF(thisItemString); thisItemString = resultString; } } *pTreeString = thisItemString; cleanup: if (PKIX_ERROR_RECEIVED) { PKIX_DECREF(thisItemString); } PKIX_DECREF(nextIndentFormat); PKIX_DECREF(thisNodeFormat); PKIX_DECREF(childrenFormat); PKIX_DECREF(nextIndentString); PKIX_DECREF(childString); PKIX_DECREF(childNode); PKIX_RETURN(VERIFYNODE); }
/* * FUNCTION: pkix_List_QuickSort * DESCRIPTION: * * Sorts List of Objects "fromList" using "comparatorCallback"'s result as * comasrison key and returns the sorted List at "pSortedList". The sorting * algorithm used is quick sort (n*logn). * * PARAMETERS: * "fromList" * Address of a List of Objects to be sorted. Must be non-NULL, but may be * empty. * "comparatorCallback" * Address of callback function that will compare two Objects on the List. * It should return -1 for less, 0 for equal and 1 for greater. The * callback implementation chooses what in Objects to be compared. Must be * non-NULL. * "pSortedList" * Address of a List of Objects that shall be sorted and returned. Must be * non-NULL, but may be empty. * "plContext" * Platform-specific context pointer. * THREAD SAFETY: * Not Thread Safe - assumes exclusive access to "toList" * (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_List_QuickSort( PKIX_List *fromList, PKIX_List_SortComparatorCallback comparator, PKIX_List **pSortedList, void *plContext) { PKIX_List *sortedList = NULL; PKIX_List *lessList = NULL; PKIX_List *greaterList = NULL; PKIX_List *sortedLessList = NULL; PKIX_List *sortedGreaterList = NULL; PKIX_PL_Object *object = NULL; PKIX_PL_Object *cmpObj = NULL; PKIX_Int32 cmpResult = 0; PKIX_UInt32 size = 0; PKIX_UInt32 i; PKIX_ENTER(BUILD, "pkix_List_QuickSort"); PKIX_NULLCHECK_THREE(fromList, comparator, pSortedList); PKIX_CHECK(PKIX_List_GetLength(fromList, &size, plContext), PKIX_LISTGETLENGTHFAILED); PKIX_CHECK(PKIX_List_Create(&lessList, plContext), PKIX_LISTCREATEFAILED); PKIX_CHECK(PKIX_List_Create(&greaterList, plContext), PKIX_LISTCREATEFAILED); PKIX_CHECK(PKIX_List_GetItem (fromList, 0, &object, plContext), PKIX_LISTGETITEMFAILED); /* * Pick the first item on the list as the one to be compared. * Separate rest of the itmes into two lists: less-than or greater- * than lists. Sort those two lists recursively. Insert sorted * less-than list before the picked item and append the greater- * than list after the picked item. */ for (i = 1; i < size; i++) { PKIX_CHECK(PKIX_List_GetItem (fromList, i, &cmpObj, plContext), PKIX_LISTGETITEMFAILED); PKIX_CHECK(comparator(object, cmpObj, &cmpResult, plContext), PKIX_COMPARATORCALLBACKFAILED); if (cmpResult >= 0) { PKIX_CHECK(PKIX_List_AppendItem (lessList, cmpObj, plContext), PKIX_LISTAPPENDITEMFAILED); } else { PKIX_CHECK(PKIX_List_AppendItem (greaterList, cmpObj, plContext), PKIX_LISTAPPENDITEMFAILED); } PKIX_DECREF(cmpObj); } PKIX_CHECK(PKIX_List_Create(&sortedList, plContext), PKIX_LISTCREATEFAILED); PKIX_CHECK(PKIX_List_GetLength(lessList, &size, plContext), PKIX_LISTGETLENGTHFAILED); if (size > 1) { PKIX_CHECK(pkix_List_QuickSort (lessList, comparator, &sortedLessList, plContext), PKIX_LISTQUICKSORTFAILED); PKIX_CHECK(pkix_List_AppendList (sortedList, sortedLessList, plContext), PKIX_LISTAPPENDLISTFAILED); } else { PKIX_CHECK(pkix_List_AppendList (sortedList, lessList, plContext), PKIX_LISTAPPENDLISTFAILED); } PKIX_CHECK(PKIX_List_AppendItem(sortedList, object, plContext), PKIX_LISTAPPENDFAILED); PKIX_CHECK(PKIX_List_GetLength(greaterList, &size, plContext), PKIX_LISTGETLENGTHFAILED); if (size > 1) { PKIX_CHECK(pkix_List_QuickSort (greaterList, comparator, &sortedGreaterList, plContext), PKIX_LISTQUICKSORTFAILED); PKIX_CHECK(pkix_List_AppendList (sortedList, sortedGreaterList, plContext), PKIX_LISTAPPENDLISTFAILED); } else { PKIX_CHECK(pkix_List_AppendList (sortedList, greaterList, plContext), PKIX_LISTAPPENDLISTFAILED); } *pSortedList = sortedList; cleanup: PKIX_DECREF(cmpObj); PKIX_DECREF(object); PKIX_DECREF(sortedGreaterList); PKIX_DECREF(sortedLessList); PKIX_DECREF(greaterList); PKIX_DECREF(lessList); PKIX_RETURN(LIST); }
/* * FUNCTION: pkix_List_MergeLists * DESCRIPTION: * * Creates a new list consisting of the items from "firstList", followed by * the items on "secondList", returns the new list at "pMergedList". If * both input lists are NULL or empty, the result is an empty list. If an error * occurs, the result is NULL. * * PARAMETERS: * "firstList" * Address of list to be merged from. May be NULL or empty. * "secondList" * Address of list to be merged from. May be NULL or empty. * "pMergedList" * Address where returned object is stored. * "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 List Error if the functions fails in a non-fatal way * Returns a Fatal Error if the function fails in an unrecoverable way */ PKIX_Error * pkix_List_MergeLists( PKIX_List *firstList, PKIX_List *secondList, PKIX_List **pMergedList, void *plContext) { PKIX_List *list = NULL; PKIX_PL_Object *item = NULL; PKIX_UInt32 numItems = 0; PKIX_UInt32 i; PKIX_ENTER(LIST, "pkix_List_MergeLists"); PKIX_NULLCHECK_ONE(pMergedList); *pMergedList = NULL; PKIX_CHECK(PKIX_List_Create(&list, plContext), PKIX_LISTCREATEFAILED); if (firstList != NULL) { PKIX_CHECK(PKIX_List_GetLength(firstList, &numItems, plContext), PKIX_LISTGETLENGTHFAILED); } for (i = 0; i < numItems; i++) { PKIX_CHECK(PKIX_List_GetItem(firstList, i, &item, plContext), PKIX_LISTGETITEMFAILED); PKIX_CHECK(PKIX_List_AppendItem(list, item, plContext), PKIX_LISTAPPENDITEMFAILED); PKIX_DECREF(item); } numItems = 0; if (secondList != NULL) { PKIX_CHECK(PKIX_List_GetLength (secondList, &numItems, plContext), PKIX_LISTGETLENGTHFAILED); } for (i = 0; i < numItems; i++) { PKIX_CHECK(PKIX_List_GetItem (secondList, i, &item, plContext), PKIX_LISTGETITEMFAILED); PKIX_CHECK(PKIX_List_AppendItem (list, item, plContext), PKIX_LISTAPPENDITEMFAILED); PKIX_DECREF(item); } *pMergedList = list; list = NULL; cleanup: PKIX_DECREF(list); PKIX_DECREF(item); PKIX_RETURN(LIST); }
/* * FUNCTION: pkix_List_BubbleSort * DESCRIPTION: * * Sorts List of Objects "fromList" using "comparatorCallback"'s result as * comasrison key and returns the sorted List at "pSortedList". The sorting * algorithm used is bubble sort (n*n). * * PARAMETERS: * "fromList" * Address of a List of Objects to be sorted. Must be non-NULL, but may be * empty. * "comparatorCallback" * Address of callback function that will compare two Objects on the List. * It should return -1 for less, 0 for equal and 1 for greater. The * callback implementation chooses what in Objects to be compared. Must be * non-NULL. * "pSortedList" * Address of a List of Objects that shall be sorted and returned. Must be * non-NULL, but may be empty. * "plContext" * Platform-specific context pointer. * THREAD SAFETY: * Not Thread Safe - assumes exclusive access to "toList" * (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_List_BubbleSort( PKIX_List *fromList, PKIX_List_SortComparatorCallback comparator, PKIX_List **pSortedList, void *plContext) { PKIX_List *sortedList = NULL; PKIX_PL_Object *cmpObj = NULL; PKIX_PL_Object *leastObj = NULL; PKIX_Int32 cmpResult = 0; PKIX_UInt32 size = 0; PKIX_UInt32 i, j; PKIX_ENTER(BUILD, "pkix_List_BubbleSort"); PKIX_NULLCHECK_THREE(fromList, comparator, pSortedList); if (fromList->immutable) { PKIX_ERROR(PKIX_CANNOTSORTIMMUTABLELIST); } PKIX_CHECK(pkix_List_Duplicate ((PKIX_PL_Object *) fromList, (PKIX_PL_Object **) &sortedList, plContext), PKIX_LISTDUPLICATEFAILED); PKIX_CHECK(PKIX_List_GetLength(sortedList, &size, plContext), PKIX_LISTGETLENGTHFAILED); if (size > 1) { /* * Move from the first of the item on the list, For each iteration, * compare and swap the least value to the head of the comparisoning * sub-list. */ for (i = 0; i < size - 1; i++) { PKIX_CHECK(PKIX_List_GetItem (sortedList, i, &leastObj, plContext), PKIX_LISTGETITEMFAILED); for (j = i + 1; j < size; j++) { PKIX_CHECK(PKIX_List_GetItem (sortedList, j, &cmpObj, plContext), PKIX_LISTGETITEMFAILED); PKIX_CHECK(comparator (leastObj, cmpObj, &cmpResult, plContext), PKIX_COMPARATORCALLBACKFAILED); if (cmpResult > 0) { PKIX_CHECK(PKIX_List_SetItem (sortedList, j, leastObj, plContext), PKIX_LISTSETITEMFAILED); PKIX_DECREF(leastObj); leastObj = cmpObj; cmpObj = NULL; } else { PKIX_DECREF(cmpObj); } } PKIX_CHECK(PKIX_List_SetItem (sortedList, i, leastObj, plContext), PKIX_LISTSETITEMFAILED); PKIX_DECREF(leastObj); } } *pSortedList = sortedList; sortedList = NULL; cleanup: PKIX_DECREF(sortedList); PKIX_DECREF(leastObj); PKIX_DECREF(cmpObj); PKIX_RETURN(LIST); }
/* * FUNCTION: pkix_List_Equals * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h) */ static PKIX_Error * pkix_List_Equals( PKIX_PL_Object *first, PKIX_PL_Object *second, PKIX_Boolean *pResult, void *plContext) { PKIX_UInt32 secondType; PKIX_Boolean cmpResult; PKIX_List *firstList = NULL; PKIX_List *secondList = NULL; PKIX_UInt32 firstLength = 0; PKIX_UInt32 secondLength = 0; PKIX_PL_Object *firstItem = NULL; PKIX_PL_Object *secondItem = NULL; PKIX_UInt32 i = 0; PKIX_ENTER(LIST, "pkix_List_Equals"); PKIX_NULLCHECK_THREE(first, second, pResult); /* test that first is a List */ PKIX_CHECK(pkix_CheckType(first, PKIX_LIST_TYPE, plContext), PKIX_FIRSTOBJECTNOTLIST); /* * Since we know first is a List, if both references are * identical, they must be equal */ if (first == second){ *pResult = PKIX_TRUE; goto cleanup; } /* * If second isn't a List, we don't throw an error. * We simply return a Boolean result of FALSE */ *pResult = PKIX_FALSE; PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext), PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); if (secondType != PKIX_LIST_TYPE) goto cleanup; firstList = (PKIX_List *)first; secondList = (PKIX_List *)second; if ((!firstList->isHeader) && (!secondList->isHeader)){ PKIX_ERROR(PKIX_INPUTLISTSMUSTBELISTHEADERS); } firstLength = firstList->length; secondLength = secondList->length; cmpResult = PKIX_FALSE; if (firstLength == secondLength){ for (i = 0, cmpResult = PKIX_TRUE; ((i < firstLength) && cmpResult); i++){ PKIX_CHECK(PKIX_List_GetItem (firstList, i, &firstItem, plContext), PKIX_LISTGETITEMFAILED); PKIX_CHECK(PKIX_List_GetItem (secondList, i, &secondItem, plContext), PKIX_LISTGETITEMFAILED); if ((!firstItem && secondItem) || (firstItem && !secondItem)){ cmpResult = PKIX_FALSE; } else if (!firstItem && !secondItem){ continue; } else { PKIX_CHECK(PKIX_PL_Object_Equals (firstItem, secondItem, &cmpResult, plContext), PKIX_OBJECTEQUALSFAILED); PKIX_DECREF(firstItem); PKIX_DECREF(secondItem); } } } *pResult = cmpResult; cleanup: PKIX_DECREF(firstItem); PKIX_DECREF(secondItem); PKIX_RETURN(LIST); }
/* * FUNCTION: pkix_VerifyNode_DuplicateHelper * DESCRIPTION: * * Duplicates the VerifyNode whose address is pointed to by "original", * and stores the result at "pNewNode", if a non-NULL pointer is provided * for "pNewNode". In addition, the created VerifyNode is added as a child * to "parent", if a non-NULL pointer is provided for "parent". Then this * function is called recursively to duplicate each of the children of * "original". At the top level this function is called with a null * "parent" and a non-NULL "pNewNode". Below the top level "parent" will * be non-NULL and "pNewNode" will be NULL. * * PARAMETERS: * "original" * Address of VerifyNode to be copied; must be non-NULL * "parent" * Address of VerifyNode to which the created node is to be added as a * child; NULL for the top-level call and non-NULL below the top level * "pNewNode" * Address to store the node created; should be NULL if "parent" is * non-NULL and vice versa * "plContext" * Platform-specific context pointer. * THREAD SAFETY: * Conditionally Thread Safe * (see Thread Safety Definitions in Programmer's Guide) * RETURNS: * Returns NULL if function succeeds * Returns a VerifyNode Error if the function fails in a non-fatal way. * Returns a Fatal Error if the function fails in a fatal way */ static PKIX_Error * pkix_VerifyNode_DuplicateHelper( PKIX_VerifyNode *original, PKIX_VerifyNode *parent, PKIX_VerifyNode **pNewNode, void *plContext) { PKIX_UInt32 numChildren = 0; PKIX_UInt32 childIndex = 0; PKIX_List *children = NULL; /* List of PKIX_VerifyNode */ PKIX_VerifyNode *copy = NULL; PKIX_VerifyNode *child = NULL; PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_DuplicateHelper"); PKIX_NULLCHECK_TWO (original, original->verifyCert); /* * These components are immutable, so copying the pointers * is sufficient. The create function increments the reference * counts as it stores the pointers into the new object. */ PKIX_CHECK(pkix_VerifyNode_Create (original->verifyCert, original->depth, original->error, ©, plContext), PKIX_VERIFYNODECREATEFAILED); /* Are there any children to duplicate? */ children = original->children; if (children) { PKIX_CHECK(PKIX_List_GetLength(children, &numChildren, plContext), PKIX_LISTGETLENGTHFAILED); } for (childIndex = 0; childIndex < numChildren; childIndex++) { PKIX_CHECK(PKIX_List_GetItem (children, childIndex, (PKIX_PL_Object **)&child, plContext), PKIX_LISTGETITEMFAILED); PKIX_CHECK(pkix_VerifyNode_DuplicateHelper (child, copy, NULL, plContext), PKIX_VERIFYNODEDUPLICATEHELPERFAILED); PKIX_DECREF(child); } if (pNewNode) { *pNewNode = copy; copy = NULL; /* no DecRef if we give our handle away */ } cleanup: PKIX_DECREF(copy); PKIX_DECREF(child); PKIX_RETURN(VERIFYNODE); }
/* * FUNCTION: pkix_EkuChecker_Check * DESCRIPTION: * * This function determines the Extended Key Usage OIDs specified by the * application is included in the Extended Key Usage OIDs of this "cert". * * 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. * "unresolvedCriticalExtensions" * A List OIDs. The OID for Extended Key Usage is removed. * "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 UserDefinedModules 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_EkuChecker_Check( PKIX_CertChainChecker *checker, PKIX_PL_Cert *cert, PKIX_List *unresolvedCriticalExtensions, void **pNBIOContext, void *plContext) { pkix_EkuChecker *state = NULL; PKIX_List *requiredExtKeyUsageList = NULL; PKIX_List *certExtKeyUsageList = NULL; PKIX_PL_OID *ekuOid = NULL; PKIX_Boolean isContained = PKIX_FALSE; PKIX_UInt32 numItems = 0; PKIX_UInt32 i; PKIX_Boolean checkResult = PKIX_TRUE; PKIX_ENTER(EKUCHECKER, "pkix_EkuChecker_Check"); PKIX_NULLCHECK_THREE(checker, cert, pNBIOContext); *pNBIOContext = NULL; /* no non-blocking IO */ PKIX_CHECK( PKIX_CertChainChecker_GetCertChainCheckerState (checker, (PKIX_PL_Object **)&state, plContext), PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED); requiredExtKeyUsageList = state->requiredExtKeyUsageOids; if (requiredExtKeyUsageList == NULL) { goto cleanup; } PKIX_CHECK( PKIX_List_GetLength(requiredExtKeyUsageList, &numItems, plContext), PKIX_LISTGETLENGTHFAILED); if (numItems == 0) { goto cleanup; } PKIX_CHECK( PKIX_PL_Cert_GetExtendedKeyUsage(cert, &certExtKeyUsageList, plContext), PKIX_CERTGETEXTENDEDKEYUSAGEFAILED); if (certExtKeyUsageList == NULL) { goto cleanup; } for (i = 0; i < numItems; i++) { PKIX_CHECK( PKIX_List_GetItem(requiredExtKeyUsageList, i, (PKIX_PL_Object **)&ekuOid, plContext), PKIX_LISTGETITEMFAILED); PKIX_CHECK( pkix_List_Contains(certExtKeyUsageList, (PKIX_PL_Object *)ekuOid, &isContained, plContext), PKIX_LISTCONTAINSFAILED); PKIX_DECREF(ekuOid); if (isContained != PKIX_TRUE) { checkResult = PKIX_FALSE; goto cleanup; } } cleanup: if (!pkixErrorResult && checkResult == PKIX_FALSE) { pkixErrorReceived = PKIX_TRUE; pkixErrorCode = PKIX_EXTENDEDKEYUSAGECHECKINGFAILED; } PKIX_DECREF(ekuOid); PKIX_DECREF(certExtKeyUsageList); PKIX_DECREF(state); PKIX_RETURN(EKUCHECKER); }
/* * FUNCTION: PKIX_RevocationChecker_Check */ PKIX_Error * PKIX_RevocationChecker_Check( PKIX_PL_Cert *cert, PKIX_PL_Cert *issuer, PKIX_RevocationChecker *revChecker, PKIX_ProcessingParams *procParams, PKIX_Boolean chainVerificationState, PKIX_Boolean testingLeafCert, PKIX_RevocationStatus *pRevStatus, PKIX_UInt32 *pReasonCode, void **pNbioContext, void *plContext) { PKIX_RevocationStatus overallStatus = PKIX_RevStatus_NoInfo; PKIX_RevocationStatus methodStatus[PKIX_RevocationMethod_MAX]; PKIX_Boolean onlyUseRemoteMethods = PKIX_FALSE; PKIX_UInt32 revFlags = 0; PKIX_List *revList = NULL; PKIX_PL_Date *date = NULL; pkix_RevocationMethod *method = NULL; void *nbioContext; int tries; PKIX_ENTER(REVOCATIONCHECKER, "PKIX_RevocationChecker_Check"); PKIX_NULLCHECK_TWO(revChecker, procParams); nbioContext = *pNbioContext; *pNbioContext = NULL; if (testingLeafCert) { revList = revChecker->leafMethodList; revFlags = revChecker->leafMethodListFlags; } else { revList = revChecker->chainMethodList; revFlags = revChecker->chainMethodListFlags; } if (!revList) { /* Return NoInfo status */ goto cleanup; } PORT_Memset(methodStatus, PKIX_RevStatus_NoInfo, sizeof(PKIX_RevocationStatus) * PKIX_RevocationMethod_MAX); date = procParams->date; /* Need to have two loops if we testing all local info first: * first we are going to test all local(cached) info * second, all remote info(fetching) */ for (tries = 0;tries < 2;tries++) { int methodNum = 0; for (;methodNum < revList->length;methodNum++) { PKIX_UInt32 methodFlags = 0; PKIX_DECREF(method); PKIX_CHECK( PKIX_List_GetItem(revList, methodNum, (PKIX_PL_Object**)&method, plContext), PKIX_LISTGETITEMFAILED); methodFlags = method->flags; if (!(methodFlags & PKIX_REV_M_TEST_USING_THIS_METHOD)) { /* Will not check with this method. Skipping... */ continue; } if (!onlyUseRemoteMethods && methodStatus[methodNum] == PKIX_RevStatus_NoInfo) { PKIX_RevocationStatus revStatus = PKIX_RevStatus_NoInfo; PKIX_CHECK_NO_GOTO( (*method->localRevChecker)(cert, issuer, date, method, procParams, methodFlags, chainVerificationState, &revStatus, pReasonCode, plContext), PKIX_REVCHECKERCHECKFAILED); methodStatus[methodNum] = revStatus; if (revStatus == PKIX_RevStatus_Revoked) { /* if error was generated use it as final error. */ overallStatus = PKIX_RevStatus_Revoked; goto cleanup; } if (pkixErrorResult) { /* Disregard errors. Only returned revStatus matters. */ PKIX_PL_Object_DecRef((PKIX_PL_Object*)pkixErrorResult, plContext); pkixErrorResult = NULL; } } if ((!(revFlags & PKIX_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST) || onlyUseRemoteMethods) && chainVerificationState && methodStatus[methodNum] == PKIX_RevStatus_NoInfo) { if (!(methodFlags & PKIX_REV_M_FORBID_NETWORK_FETCHING)) { PKIX_RevocationStatus revStatus = PKIX_RevStatus_NoInfo; PKIX_CHECK_NO_GOTO( (*method->externalRevChecker)(cert, issuer, date, method, procParams, methodFlags, &revStatus, pReasonCode, &nbioContext, plContext), PKIX_REVCHECKERCHECKFAILED); methodStatus[methodNum] = revStatus; if (revStatus == PKIX_RevStatus_Revoked) { /* if error was generated use it as final error. */ overallStatus = PKIX_RevStatus_Revoked; goto cleanup; } if (pkixErrorResult) { /* Disregard errors. Only returned revStatus matters. */ PKIX_PL_Object_DecRef((PKIX_PL_Object*)pkixErrorResult, plContext); pkixErrorResult = NULL; } } else if (methodFlags & PKIX_REV_M_FAIL_ON_MISSING_FRESH_INFO) { /* Info is not in the local cache. Network fetching is not * allowed. If need to fail on missing fresh info for the * the method, then we should fail right here.*/ overallStatus = PKIX_RevStatus_Revoked; goto cleanup; } } /* If success and we should not check the next method, then * return a success. */ if (methodStatus[methodNum] == PKIX_RevStatus_Success && !(methodFlags & PKIX_REV_M_CONTINUE_TESTING_ON_FRESH_INFO)) { overallStatus = PKIX_RevStatus_Success; goto cleanup; } } /* inner loop */ if (!onlyUseRemoteMethods && revFlags & PKIX_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST && chainVerificationState) { onlyUseRemoteMethods = PKIX_TRUE; continue; } break; } /* outer loop */ if (overallStatus == PKIX_RevStatus_NoInfo && chainVerificationState) { /* The following check makes sence only for chain * validation step, sinse we do not fetch info while * in the process of finding trusted anchor. * For chain building step it is enough to know, that * the cert was not directly revoked by any of the * methods. */ /* Still have no info. But one of the method could * have returned success status(possible if CONTINUE * TESTING ON FRESH INFO flag was used). * If any of the methods have returned Success status, * the overallStatus should be success. */ int methodNum = 0; for (;methodNum < PKIX_RevocationMethod_MAX;methodNum++) { if (methodStatus[methodNum] == PKIX_RevStatus_Success) { overallStatus = PKIX_RevStatus_Success; goto cleanup; } } if (revFlags & PKIX_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE) { overallStatus = PKIX_RevStatus_Revoked; } } cleanup: *pRevStatus = overallStatus; PKIX_DECREF(method); PKIX_RETURN(REVOCATIONCHECKER); }
static void Test_BuildResult( PKIX_ProcessingParams *procParams, PKIX_Boolean testValid, PKIX_List *expectedCerts, void *plContext) { PKIX_PL_Cert *cert = NULL; PKIX_List *certs = NULL; PKIX_PL_String *actualCertsString = NULL; PKIX_PL_String *expectedCertsString = NULL; PKIX_BuildResult *buildResult = NULL; PKIX_Boolean result; PKIX_Boolean supportForward = PKIX_FALSE; PKIX_UInt32 numCerts, i; char *asciiResult = NULL; char *actualCertsAscii = NULL; char *expectedCertsAscii = NULL; void *state = NULL; PRPollDesc *pollDesc = NULL; PKIX_TEST_STD_VARS(); pkixTestErrorResult = PKIX_BuildChain(procParams, (void **)&pollDesc, &state, &buildResult, NULL, plContext); while (pollDesc != NULL) { if (PR_Poll(pollDesc, 1, 0) < 0) { testError("PR_Poll failed"); } pkixTestErrorResult = PKIX_BuildChain(procParams, (void **)&pollDesc, &state, &buildResult, NULL, plContext); } if (pkixTestErrorResult) { if (testValid == PKIX_FALSE) { /* EE */ (void)printf("EXPECTED ERROR RECEIVED!\n"); } else { /* ENE */ testError("UNEXPECTED ERROR RECEIVED!\n"); } PKIX_TEST_DECREF_BC(pkixTestErrorResult); goto cleanup; } if (testValid == PKIX_TRUE) { /* ENE */ (void)printf("EXPECTED NON-ERROR RECEIVED!\n"); } else { /* EE */ testError("UNEXPECTED NON-ERROR RECEIVED!\n"); } if (buildResult) { PKIX_TEST_EXPECT_NO_ERROR(PKIX_BuildResult_GetCertChain(buildResult, &certs, NULL)); PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetLength(certs, &numCerts, plContext)); printf("\n"); for (i = 0; i < numCerts; i++) { PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(certs, i, (PKIX_PL_Object **)&cert, plContext)); asciiResult = PKIX_Cert2ASCII(cert); printf("CERT[%d]:\n%s\n", i, asciiResult); /* PKIX_Cert2ASCII used PKIX_PL_Malloc(...,,NULL) */ PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(asciiResult, NULL)); asciiResult = NULL; PKIX_TEST_DECREF_BC(cert); } PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Equals((PKIX_PL_Object *)certs, (PKIX_PL_Object *)expectedCerts, &result, plContext)); if (!result) { testError("BUILT CERTCHAIN IS " "NOT THE ONE THAT WAS EXPECTED"); PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)certs, &actualCertsString, plContext)); actualCertsAscii = PKIX_String2ASCII(actualCertsString, plContext); if (actualCertsAscii == NULL) { pkixTestErrorMsg = "PKIX_String2ASCII Failed"; goto cleanup; } PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)expectedCerts, &expectedCertsString, plContext)); expectedCertsAscii = PKIX_String2ASCII(expectedCertsString, plContext); if (expectedCertsAscii == NULL) { pkixTestErrorMsg = "PKIX_String2ASCII Failed"; goto cleanup; } (void)printf("Actual value:\t%s\n", actualCertsAscii); (void)printf("Expected value:\t%s\n", expectedCertsAscii); } } cleanup: PKIX_PL_Free(asciiResult, NULL); PKIX_PL_Free(actualCertsAscii, plContext); PKIX_PL_Free(expectedCertsAscii, plContext); PKIX_TEST_DECREF_AC(state); PKIX_TEST_DECREF_AC(buildResult); PKIX_TEST_DECREF_AC(certs); PKIX_TEST_DECREF_AC(cert); PKIX_TEST_DECREF_AC(actualCertsString); PKIX_TEST_DECREF_AC(expectedCertsString); PKIX_TEST_RETURN(); }
/* * 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_CollectionCertStoreContext_GetSelectedCert * DESCRIPTION: * * Finds the Certs that match the criterion of the CertSelector pointed * to by "selector" using the List of Certs pointed to by "certList" and * stores the matching Certs at "pSelectedCertList". * * Not recursive to sub-directory. * * PARAMETERS * "certList" - Address of List of Certs to be searched. Must be non-NULL. * "colCertStoreContext" - Address of CollectionCertStoreContext * where the cached Certs are stored. * "selector" - CertSelector for chosing Cert based on Params set * "pSelectedCertList" - Certs that qualified by selector. * "plContext" - Platform-specific context pointer. * * THREAD SAFETY: * Not Thread Safe - A lock at top level is required. * * RETURNS: * Returns NULL if the function succeeds. * Returns a CollectionCertStoreContext 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_CollectionCertStoreContext_GetSelectedCert( PKIX_List *certList, PKIX_CertSelector *selector, PKIX_List **pSelectedCertList, void *plContext) { PKIX_List *selectCertList = NULL; PKIX_PL_Cert *certItem = NULL; PKIX_CertSelector_MatchCallback certSelectorMatch = NULL; PKIX_UInt32 numCerts = 0; PKIX_UInt32 i = 0; PKIX_ENTER(COLLECTIONCERTSTORECONTEXT, "pkix_pl_CollectionCertStoreContext_GetSelectedCert"); PKIX_NULLCHECK_THREE(certList, selector, pSelectedCertList); PKIX_CHECK(PKIX_CertSelector_GetMatchCallback (selector, &certSelectorMatch, plContext), PKIX_CERTSELECTORGETMATCHCALLBACKFAILED); PKIX_CHECK(PKIX_List_GetLength(certList, &numCerts, plContext), PKIX_LISTGETLENGTHFAILED); if (certSelectorMatch) { PKIX_CHECK(PKIX_List_Create(&selectCertList, plContext), PKIX_LISTCREATEFAILED); for (i = 0; i < numCerts; i++) { PKIX_CHECK_ONLY_FATAL (PKIX_List_GetItem (certList, i, (PKIX_PL_Object **) &certItem, plContext), PKIX_LISTGETITEMFAILED); if (!PKIX_ERROR_RECEIVED){ PKIX_CHECK_ONLY_FATAL (certSelectorMatch (selector, certItem, plContext), PKIX_CERTSELECTORMATCHFAILED); if (!PKIX_ERROR_RECEIVED){ PKIX_CHECK_ONLY_FATAL (PKIX_List_AppendItem (selectCertList, (PKIX_PL_Object *)certItem, plContext), PKIX_LISTAPPENDITEMFAILED); } } PKIX_DECREF(certItem); } } else { PKIX_INCREF(certList); selectCertList = certList; } *pSelectedCertList = selectCertList; cleanup: PKIX_RETURN(COLLECTIONCERTSTORECONTEXT); }