| /* This Source Code Form is subject to the terms of the Mozilla Public |
| * License, v. 2.0. If a copy of the MPL was not distributed with this |
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
| /* |
| * pkix_verifynode.c |
| * |
| * Verify Node Object Type Definition |
| * |
| */ |
| |
| #include "pkix_verifynode.h" |
| |
| /* --Private-VerifyNode-Functions---------------------------------- */ |
| |
| /* |
| * FUNCTION: pkix_VerifyNode_Create |
| * DESCRIPTION: |
| * |
| * This function creates a VerifyNode using the Cert pointed to by "cert", |
| * the depth given by "depth", and the Error pointed to by "error", storing |
| * the result at "pObject". |
| * |
| * PARAMETERS |
| * "cert" |
| * Address of Cert for the node. Must be non-NULL |
| * "depth" |
| * UInt32 value of the depth for this node. |
| * "error" |
| * Address of Error for the node. |
| * "pObject" |
| * Address where the VerifyNode pointer will be stored. Must be non-NULL. |
| * "plContext" |
| * Platform-specific context pointer. |
| * THREAD SAFETY: |
| * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
| * RETURNS: |
| * Returns NULL if the function succeeds. |
| * Returns a Fatal Error if the function fails in an unrecoverable way. |
| */ |
| PKIX_Error * |
| pkix_VerifyNode_Create( |
| PKIX_PL_Cert *cert, |
| PKIX_UInt32 depth, |
| PKIX_Error *error, |
| PKIX_VerifyNode **pObject, |
| void *plContext) |
| { |
| PKIX_VerifyNode *node = NULL; |
| |
| PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_Create"); |
| PKIX_NULLCHECK_TWO(cert, pObject); |
| |
| PKIX_CHECK(PKIX_PL_Object_Alloc |
| (PKIX_VERIFYNODE_TYPE, |
| sizeof (PKIX_VerifyNode), |
| (PKIX_PL_Object **)&node, |
| plContext), |
| PKIX_COULDNOTCREATEVERIFYNODEOBJECT); |
| |
| PKIX_INCREF(cert); |
| node->verifyCert = cert; |
| |
| PKIX_INCREF(error); |
| node->error = error; |
| |
| node->depth = depth; |
| |
| node->children = NULL; |
| |
| *pObject = node; |
| node = NULL; |
| |
| cleanup: |
| |
| PKIX_DECREF(node); |
| |
| PKIX_RETURN(VERIFYNODE); |
| } |
| |
| /* |
| * 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_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_VerifyNode_AddToTree |
| * DESCRIPTION: |
| * |
| * Adds the VerifyNode pointed to by "child" to the List of children of the |
| * VerifyNode pointed to by "parentNode". 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. The depth field of |
| * "child" is set to one more than the corresponding value in "parent", and |
| * if the "child" itself has child nodes, their depth fields are updated |
| * accordingly. |
| * |
| * 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 Fatal Error if the function fails in an unrecoverable way. |
| */ |
| PKIX_Error * |
| pkix_VerifyNode_AddToTree( |
| PKIX_VerifyNode *parentNode, |
| PKIX_VerifyNode *child, |
| void *plContext) |
| { |
| PKIX_List *listOfChildren = NULL; |
| PKIX_UInt32 parentDepth = 0; |
| |
| PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_AddToTree"); |
| PKIX_NULLCHECK_TWO(parentNode, child); |
| |
| parentDepth = parentNode->depth; |
| listOfChildren = parentNode->children; |
| if (listOfChildren == NULL) { |
| |
| PKIX_CHECK(PKIX_List_Create(&listOfChildren, plContext), |
| PKIX_LISTCREATEFAILED); |
| |
| parentNode->children = listOfChildren; |
| } |
| |
| child->depth = parentDepth + 1; |
| |
| PKIX_CHECK(PKIX_List_AppendItem |
| (parentNode->children, (PKIX_PL_Object *)child, plContext), |
| PKIX_COULDNOTAPPENDCHILDTOPARENTSVERIFYNODELIST); |
| |
| if (child->children != NULL) { |
| PKIX_CHECK(pkix_VerifyNode_SetDepth |
| (child->children, child->depth + 1, plContext), |
| PKIX_VERIFYNODESETDEPTHFAILED); |
| } |
| |
| |
| cleanup: |
| |
| PKIX_RETURN(VERIFYNODE); |
| } |
| |
| /* |
| * FUNCTION: pkix_SingleVerifyNode_ToString |
| * DESCRIPTION: |
| * |
| * Creates a String representation of the attributes of the VerifyNode pointed |
| * to by "node", other than its children, and stores the result at "pString". |
| * |
| * PARAMETERS: |
| * "node" |
| * Address of VerifyNode to be described by the string. Must be non-NULL. |
| * "pString" |
| * Address where object pointer 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 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 |
| */ |
| PKIX_Error * |
| pkix_SingleVerifyNode_ToString( |
| PKIX_VerifyNode *node, |
| PKIX_PL_String **pString, |
| void *plContext) |
| { |
| PKIX_PL_String *fmtString = NULL; |
| PKIX_PL_String *errorString = NULL; |
| PKIX_PL_String *outString = NULL; |
| |
| PKIX_PL_X500Name *issuerName = NULL; |
| PKIX_PL_X500Name *subjectName = NULL; |
| PKIX_PL_String *issuerString = NULL; |
| PKIX_PL_String *subjectString = NULL; |
| |
| PKIX_ENTER(VERIFYNODE, "pkix_SingleVerifyNode_ToString"); |
| PKIX_NULLCHECK_THREE(node, pString, node->verifyCert); |
| |
| PKIX_TOSTRING(node->error, &errorString, plContext, |
| PKIX_ERRORTOSTRINGFAILED); |
| |
| PKIX_CHECK(PKIX_PL_Cert_GetIssuer |
| (node->verifyCert, &issuerName, plContext), |
| PKIX_CERTGETISSUERFAILED); |
| |
| PKIX_TOSTRING(issuerName, &issuerString, plContext, |
| PKIX_X500NAMETOSTRINGFAILED); |
| |
| PKIX_CHECK(PKIX_PL_Cert_GetSubject |
| (node->verifyCert, &subjectName, plContext), |
| PKIX_CERTGETSUBJECTFAILED); |
| |
| PKIX_TOSTRING(subjectName, &subjectString, plContext, |
| PKIX_X500NAMETOSTRINGFAILED); |
| |
| PKIX_CHECK(PKIX_PL_String_Create |
| (PKIX_ESCASCII, |
| "CERT[Issuer:%s, Subject:%s], depth=%d, error=%s", |
| 0, |
| &fmtString, |
| plContext), |
| PKIX_CANTCREATESTRING); |
| |
| PKIX_CHECK(PKIX_PL_Sprintf |
| (&outString, |
| plContext, |
| fmtString, |
| issuerString, |
| subjectString, |
| node->depth, |
| errorString), |
| PKIX_SPRINTFFAILED); |
| |
| *pString = outString; |
| |
| cleanup: |
| |
| PKIX_DECREF(fmtString); |
| PKIX_DECREF(errorString); |
| PKIX_DECREF(issuerName); |
| PKIX_DECREF(subjectName); |
| PKIX_DECREF(issuerString); |
| PKIX_DECREF(subjectString); |
| PKIX_RETURN(VERIFYNODE); |
| } |
| |
| /* |
| * 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_VerifyNode_ToString |
| * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) |
| */ |
| static PKIX_Error * |
| pkix_VerifyNode_ToString( |
| PKIX_PL_Object *object, |
| PKIX_PL_String **pTreeString, |
| void *plContext) |
| { |
| PKIX_VerifyNode *rootNode = NULL; |
| PKIX_PL_String *resultString = NULL; |
| |
| PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_ToString"); |
| |
| PKIX_NULLCHECK_TWO(object, pTreeString); |
| |
| PKIX_CHECK(pkix_CheckType(object, PKIX_VERIFYNODE_TYPE, plContext), |
| PKIX_OBJECTNOTVERIFYNODE); |
| |
| rootNode = (PKIX_VerifyNode *)object; |
| |
| PKIX_CHECK(pkix_VerifyNode_ToString_Helper |
| (rootNode, NULL, &resultString, plContext), |
| PKIX_ERRORCREATINGSUBTREESTRING); |
| |
| *pTreeString = resultString; |
| |
| cleanup: |
| |
| PKIX_RETURN(VERIFYNODE); |
| } |
| |
| /* |
| * FUNCTION: pkix_VerifyNode_Destroy |
| * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) |
| */ |
| static PKIX_Error * |
| pkix_VerifyNode_Destroy( |
| PKIX_PL_Object *object, |
| void *plContext) |
| { |
| PKIX_VerifyNode *node = NULL; |
| |
| PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_Destroy"); |
| |
| PKIX_NULLCHECK_ONE(object); |
| |
| PKIX_CHECK(pkix_CheckType(object, PKIX_VERIFYNODE_TYPE, plContext), |
| PKIX_OBJECTNOTVERIFYNODE); |
| |
| node = (PKIX_VerifyNode*)object; |
| |
| PKIX_DECREF(node->verifyCert); |
| PKIX_DECREF(node->children); |
| PKIX_DECREF(node->error); |
| |
| node->depth = 0; |
| |
| cleanup: |
| |
| PKIX_RETURN(VERIFYNODE); |
| } |
| |
| /* |
| * FUNCTION: pkix_SingleVerifyNode_Hashcode |
| * DESCRIPTION: |
| * |
| * Computes the hashcode of the attributes of the VerifyNode pointed to by |
| * "node", other than its parents and children, and stores the result at |
| * "pHashcode". |
| * |
| * PARAMETERS: |
| * "node" |
| * Address of VerifyNode to be hashcoded; must be non-NULL |
| * "pHashcode" |
| * Address where UInt32 result 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 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_SingleVerifyNode_Hashcode( |
| PKIX_VerifyNode *node, |
| PKIX_UInt32 *pHashcode, |
| void *plContext) |
| { |
| PKIX_UInt32 errorHash = 0; |
| PKIX_UInt32 nodeHash = 0; |
| |
| PKIX_ENTER(VERIFYNODE, "pkix_SingleVerifyNode_Hashcode"); |
| PKIX_NULLCHECK_TWO(node, pHashcode); |
| |
| PKIX_HASHCODE |
| (node->verifyCert, |
| &nodeHash, |
| plContext, |
| PKIX_FAILUREHASHINGCERT); |
| |
| PKIX_CHECK(PKIX_PL_Object_Hashcode |
| ((PKIX_PL_Object *)node->error, |
| &errorHash, |
| plContext), |
| PKIX_FAILUREHASHINGERROR); |
| |
| nodeHash = 31*nodeHash + errorHash; |
| *pHashcode = nodeHash; |
| |
| cleanup: |
| |
| PKIX_RETURN(VERIFYNODE); |
| } |
| |
| /* |
| * FUNCTION: pkix_VerifyNode_Hashcode |
| * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) |
| */ |
| static PKIX_Error * |
| pkix_VerifyNode_Hashcode( |
| PKIX_PL_Object *object, |
| PKIX_UInt32 *pHashcode, |
| void *plContext) |
| { |
| PKIX_VerifyNode *node = NULL; |
| PKIX_UInt32 childrenHash = 0; |
| PKIX_UInt32 nodeHash = 0; |
| |
| PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_Hashcode"); |
| PKIX_NULLCHECK_TWO(object, pHashcode); |
| |
| PKIX_CHECK(pkix_CheckType |
| (object, PKIX_VERIFYNODE_TYPE, plContext), |
| PKIX_OBJECTNOTVERIFYNODE); |
| |
| node = (PKIX_VerifyNode *)object; |
| |
| PKIX_CHECK(pkix_SingleVerifyNode_Hashcode |
| (node, &nodeHash, plContext), |
| PKIX_SINGLEVERIFYNODEHASHCODEFAILED); |
| |
| PKIX_HASHCODE |
| (node->children, |
| &childrenHash, |
| plContext, |
| PKIX_OBJECTHASHCODEFAILED); |
| |
| nodeHash = 31*nodeHash + childrenHash; |
| |
| *pHashcode = nodeHash; |
| |
| cleanup: |
| |
| PKIX_RETURN(VERIFYNODE); |
| } |
| |
| /* |
| * FUNCTION: pkix_SingleVerifyNode_Equals |
| * DESCRIPTION: |
| * |
| * Compares for equality the components of the VerifyNode pointed to by |
| * "firstPN", other than its parents and children, with those of the |
| * VerifyNode pointed to by "secondPN" and stores the result at "pResult" |
| * (PKIX_TRUE if equal; PKIX_FALSE if not). |
| * |
| * PARAMETERS: |
| * "firstPN" |
| * Address of first of the VerifyNodes to be compared; must be non-NULL |
| * "secondPN" |
| * Address of second of the VerifyNodes to be compared; must be non-NULL |
| * "pResult" |
| * Address where Boolean 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 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_SingleVerifyNode_Equals( |
| PKIX_VerifyNode *firstVN, |
| PKIX_VerifyNode *secondVN, |
| PKIX_Boolean *pResult, |
| void *plContext) |
| { |
| PKIX_Boolean compResult = PKIX_FALSE; |
| |
| PKIX_ENTER(VERIFYNODE, "pkix_SingleVerifyNode_Equals"); |
| PKIX_NULLCHECK_THREE(firstVN, secondVN, pResult); |
| |
| /* If both references are identical, they must be equal */ |
| if (firstVN == secondVN) { |
| compResult = PKIX_TRUE; |
| goto cleanup; |
| } |
| |
| /* |
| * It seems we have to do the comparisons. Do |
| * the easiest ones first. |
| */ |
| if ((firstVN->depth) != (secondVN->depth)) { |
| goto cleanup; |
| } |
| |
| /* These fields must be non-NULL */ |
| PKIX_NULLCHECK_TWO(firstVN->verifyCert, secondVN->verifyCert); |
| |
| PKIX_EQUALS |
| (firstVN->verifyCert, |
| secondVN->verifyCert, |
| &compResult, |
| plContext, |
| PKIX_OBJECTEQUALSFAILED); |
| |
| if (compResult == PKIX_FALSE) { |
| goto cleanup; |
| } |
| |
| PKIX_EQUALS |
| (firstVN->error, |
| secondVN->error, |
| &compResult, |
| plContext, |
| PKIX_OBJECTEQUALSFAILED); |
| |
| cleanup: |
| |
| *pResult = compResult; |
| |
| PKIX_RETURN(VERIFYNODE); |
| } |
| |
| /* |
| * FUNCTION: pkix_VerifyNode_Equals |
| * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h) |
| */ |
| static PKIX_Error * |
| pkix_VerifyNode_Equals( |
| PKIX_PL_Object *firstObject, |
| PKIX_PL_Object *secondObject, |
| PKIX_Boolean *pResult, |
| void *plContext) |
| { |
| PKIX_VerifyNode *firstVN = NULL; |
| PKIX_VerifyNode *secondVN = NULL; |
| PKIX_UInt32 secondType; |
| PKIX_Boolean compResult = PKIX_FALSE; |
| |
| PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_Equals"); |
| PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); |
| |
| /* test that firstObject is a VerifyNode */ |
| PKIX_CHECK(pkix_CheckType |
| (firstObject, PKIX_VERIFYNODE_TYPE, plContext), |
| PKIX_FIRSTOBJECTNOTVERIFYNODE); |
| |
| /* |
| * Since we know firstObject is a VerifyNode, |
| * if both references are identical, they must be equal |
| */ |
| if (firstObject == secondObject){ |
| compResult = PKIX_TRUE; |
| goto cleanup; |
| } |
| |
| /* |
| * If secondObject isn't a VerifyNode, we |
| * don't throw an error. We simply return FALSE. |
| */ |
| PKIX_CHECK(PKIX_PL_Object_GetType |
| (secondObject, &secondType, plContext), |
| PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); |
| |
| if (secondType != PKIX_VERIFYNODE_TYPE) { |
| goto cleanup; |
| } |
| |
| /* |
| * Oh, well, we have to do the comparisons. Do |
| * the easiest ones first. |
| */ |
| firstVN = (PKIX_VerifyNode *)firstObject; |
| secondVN = (PKIX_VerifyNode *)secondObject; |
| |
| PKIX_CHECK(pkix_SingleVerifyNode_Equals |
| (firstVN, secondVN, &compResult, plContext), |
| PKIX_SINGLEVERIFYNODEEQUALSFAILED); |
| |
| if (compResult == PKIX_FALSE) { |
| goto cleanup; |
| } |
| |
| PKIX_EQUALS |
| (firstVN->children, |
| secondVN->children, |
| &compResult, |
| plContext, |
| PKIX_OBJECTEQUALSFAILEDONCHILDREN); |
| |
| cleanup: |
| |
| *pResult = compResult; |
| |
| PKIX_RETURN(VERIFYNODE); |
| } |
| |
| /* |
| * 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_VerifyNode_Duplicate |
| * (see comments for PKIX_PL_Duplicate_Callback in pkix_pl_system.h) |
| */ |
| static PKIX_Error * |
| pkix_VerifyNode_Duplicate( |
| PKIX_PL_Object *object, |
| PKIX_PL_Object **pNewObject, |
| void *plContext) |
| { |
| PKIX_VerifyNode *original = NULL; |
| PKIX_VerifyNode *copy = NULL; |
| |
| PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_Duplicate"); |
| |
| PKIX_NULLCHECK_TWO(object, pNewObject); |
| |
| PKIX_CHECK(pkix_CheckType |
| (object, PKIX_VERIFYNODE_TYPE, plContext), |
| PKIX_OBJECTNOTVERIFYNODE); |
| |
| original = (PKIX_VerifyNode *)object; |
| |
| PKIX_CHECK(pkix_VerifyNode_DuplicateHelper |
| (original, NULL, ©, plContext), |
| PKIX_VERIFYNODEDUPLICATEHELPERFAILED); |
| |
| *pNewObject = (PKIX_PL_Object *)copy; |
| |
| cleanup: |
| |
| PKIX_RETURN(VERIFYNODE); |
| } |
| |
| /* |
| * FUNCTION: pkix_VerifyNode_RegisterSelf |
| * DESCRIPTION: |
| * |
| * Registers PKIX_VERIFYNODE_TYPE and its related |
| * functions with systemClasses[] |
| * |
| * THREAD SAFETY: |
| * Not Thread Safe - for performance and complexity reasons |
| * |
| * Since this function is only called by PKIX_PL_Initialize, |
| * which should only be called once, it is acceptable that |
| * this function is not thread-safe. |
| */ |
| PKIX_Error * |
| pkix_VerifyNode_RegisterSelf(void *plContext) |
| { |
| |
| extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; |
| pkix_ClassTable_Entry entry; |
| |
| PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_RegisterSelf"); |
| |
| entry.description = "VerifyNode"; |
| entry.objCounter = 0; |
| entry.typeObjectSize = sizeof(PKIX_VerifyNode); |
| entry.destructor = pkix_VerifyNode_Destroy; |
| entry.equalsFunction = pkix_VerifyNode_Equals; |
| entry.hashcodeFunction = pkix_VerifyNode_Hashcode; |
| entry.toStringFunction = pkix_VerifyNode_ToString; |
| entry.comparator = NULL; |
| entry.duplicateFunction = pkix_VerifyNode_Duplicate; |
| |
| systemClasses[PKIX_VERIFYNODE_TYPE] = entry; |
| |
| PKIX_RETURN(VERIFYNODE); |
| } |
| |
| /* --Public-VerifyNode-Functions----------------------------------- */ |
| |
| /* |
| * FUNCTION: PKIX_VerifyNode_SetError |
| * DESCRIPTION: |
| * |
| * This function sets the Error field of the VerifyNode pointed to by "node" |
| * to contain the Error pointed to by "error". |
| * |
| * PARAMETERS: |
| * "node" |
| * The address of the VerifyNode to be modified. Must be non-NULL. |
| * "error" |
| * The address of the Error to be 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 Fatal Error if the function fails in an unrecoverable way. |
| */ |
| PKIX_Error * |
| pkix_VerifyNode_SetError( |
| PKIX_VerifyNode *node, |
| PKIX_Error *error, |
| void *plContext) |
| { |
| |
| PKIX_ENTER(VERIFYNODE, "PKIX_VerifyNode_SetError"); |
| |
| PKIX_NULLCHECK_TWO(node, error); |
| |
| PKIX_DECREF(node->error); /* should have been NULL */ |
| PKIX_INCREF(error); |
| node->error = error; |
| |
| cleanup: |
| PKIX_RETURN(VERIFYNODE); |
| } |
| |
| /* |
| * 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 && node->error->plErr) { |
| PKIX_INCREF(node->error); |
| *error = node->error; |
| } |
| |
| cleanup: |
| PKIX_DECREF(childNode); |
| |
| PKIX_RETURN(VERIFYNODE); |
| } |