PageRenderTime 48ms CodeModel.GetById 8ms app.highlight 33ms RepoModel.GetById 1ms app.codeStats 0ms

/security/nss/lib/libpkix/pkix/results/pkix_verifynode.c

http://github.com/zpao/v8monkey
C | 1215 lines | 635 code | 184 blank | 396 comment | 45 complexity | 98c19d94b0d5aa969f8c921f58a3611a MD5 | raw file
   1/* ***** BEGIN LICENSE BLOCK *****
   2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
   3 *
   4 * The contents of this file are subject to the Mozilla Public License Version
   5 * 1.1 (the "License"); you may not use this file except in compliance with
   6 * the License. You may obtain a copy of the License at
   7 * http://www.mozilla.org/MPL/
   8 *
   9 * Software distributed under the License is distributed on an "AS IS" basis,
  10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11 * for the specific language governing rights and limitations under the
  12 * License.
  13 *
  14 * The Original Code is the PKIX-C library.
  15 *
  16 * The Initial Developer of the Original Code is
  17 * Sun Microsystems, Inc.
  18 * Portions created by the Initial Developer are
  19 * Copyright 2004-2007 Sun Microsystems, Inc.  All Rights Reserved.
  20 *
  21 * Contributor(s):
  22 *   Sun Microsystems, Inc.
  23 *
  24 * Alternatively, the contents of this file may be used under the terms of
  25 * either the GNU General Public License Version 2 or later (the "GPL"), or
  26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  27 * in which case the provisions of the GPL or the LGPL are applicable instead
  28 * of those above. If you wish to allow use of your version of this file only
  29 * under the terms of either the GPL or the LGPL, and not to allow others to
  30 * use your version of this file under the terms of the MPL, indicate your
  31 * decision by deleting the provisions above and replace them with the notice
  32 * and other provisions required by the GPL or the LGPL. If you do not delete
  33 * the provisions above, a recipient may use your version of this file under
  34 * the terms of any one of the MPL, the GPL or the LGPL.
  35 *
  36 * ***** END LICENSE BLOCK ***** */
  37/*
  38 * pkix_verifynode.c
  39 *
  40 * Verify Node Object Type Definition
  41 *
  42 */
  43
  44#include "pkix_verifynode.h"
  45
  46/* --Private-VerifyNode-Functions---------------------------------- */
  47
  48/*
  49 * FUNCTION: pkix_VerifyNode_Create
  50 * DESCRIPTION:
  51 *
  52 *  This function creates a VerifyNode using the Cert pointed to by "cert",
  53 *  the depth given by "depth", and the Error pointed to by "error", storing
  54 *  the result at "pObject".
  55 *
  56 * PARAMETERS
  57 *  "cert"
  58 *      Address of Cert for the node. Must be non-NULL
  59 *  "depth"
  60 *      UInt32 value of the depth for this node.
  61 *  "error"
  62 *      Address of Error for the node.
  63 *  "pObject"
  64 *      Address where the VerifyNode pointer will be stored. Must be non-NULL.
  65 *  "plContext"
  66 *      Platform-specific context pointer.
  67 * THREAD SAFETY:
  68 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
  69 * RETURNS:
  70 *  Returns NULL if the function succeeds.
  71 *  Returns a Fatal Error if the function fails in an unrecoverable way.
  72 */
  73PKIX_Error *
  74pkix_VerifyNode_Create(
  75        PKIX_PL_Cert *cert,
  76        PKIX_UInt32 depth,
  77        PKIX_Error *error,
  78        PKIX_VerifyNode **pObject,
  79        void *plContext)
  80{
  81        PKIX_VerifyNode *node = NULL;
  82
  83        PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_Create");
  84        PKIX_NULLCHECK_TWO(cert, pObject);
  85
  86        PKIX_CHECK(PKIX_PL_Object_Alloc
  87                (PKIX_VERIFYNODE_TYPE,
  88                sizeof (PKIX_VerifyNode),
  89                (PKIX_PL_Object **)&node,
  90                plContext),
  91                PKIX_COULDNOTCREATEVERIFYNODEOBJECT);
  92
  93        PKIX_INCREF(cert);
  94        node->verifyCert = cert;
  95
  96        PKIX_INCREF(error);
  97        node->error = error;
  98
  99        node->depth = depth;
 100
 101        node->children = NULL;
 102
 103        *pObject = node;
 104        node = NULL;
 105
 106cleanup:
 107
 108        PKIX_DECREF(node);
 109
 110        PKIX_RETURN(VERIFYNODE);
 111}
 112
 113/*
 114 * FUNCTION: pkix_VerifyNode_AddToChain
 115 * DESCRIPTION:
 116 *
 117 *  Adds the VerifyNode pointed to by "child", at the appropriate depth, to the
 118 *  List of children of the VerifyNode pointed to by "parentNode". The chain of
 119 *  VerifyNodes is traversed until a VerifyNode is found at a depth one less
 120 *  than that specified in "child". An Error is returned if there is no parent
 121 *  at a suitable depth.
 122 *
 123 *  If "parentNode" has a NULL pointer for the List of children, a new List is
 124 *  created containing "child". Otherwise "child" is appended to the existing
 125 *  List.
 126 *
 127 *  Depth, in this context, means distance from the root node, which
 128 *  is at depth zero.
 129 *
 130 * PARAMETERS:
 131 *  "parentNode"
 132 *      Address of VerifyNode whose List of child VerifyNodes is to be
 133 *      created or appended to. Must be non-NULL.
 134 *  "child"
 135 *      Address of VerifyNode to be added to parentNode's List. Must be
 136 *      non-NULL.
 137 *  "plContext"
 138 *      Platform-specific context pointer.
 139 * THREAD SAFETY:
 140 *  Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
 141 * RETURNS:
 142 *  Returns NULL if the function succeeds.
 143 *  Returns a VerifyNode Error if the function fails in a non-fatal way.
 144 *  Returns a Fatal Error if the function fails in an unrecoverable way.
 145 */
 146PKIX_Error *
 147pkix_VerifyNode_AddToChain(
 148        PKIX_VerifyNode *parentNode,
 149        PKIX_VerifyNode *child,
 150        void *plContext)
 151{
 152        PKIX_VerifyNode *successor = NULL;
 153        PKIX_List *listOfChildren = NULL;
 154        PKIX_UInt32 numChildren = 0;
 155        PKIX_UInt32 parentDepth = 0;
 156
 157        PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_AddToChain");
 158        PKIX_NULLCHECK_TWO(parentNode, child);
 159
 160        parentDepth = parentNode->depth;
 161        listOfChildren = parentNode->children;
 162        if (listOfChildren == NULL) {
 163
 164                if (parentDepth != (child->depth - 1)) {
 165                        PKIX_ERROR(PKIX_NODESMISSINGFROMCHAIN);
 166                }
 167
 168                PKIX_CHECK(PKIX_List_Create(&listOfChildren, plContext),
 169                        PKIX_LISTCREATEFAILED);
 170
 171                PKIX_CHECK(PKIX_List_AppendItem
 172                        (listOfChildren, (PKIX_PL_Object *)child, plContext),
 173                        PKIX_COULDNOTAPPENDCHILDTOPARENTSVERIFYNODELIST);
 174
 175                parentNode->children = listOfChildren;
 176        } else {
 177                /* get number of children */
 178                PKIX_CHECK(PKIX_List_GetLength
 179                        (listOfChildren, &numChildren, plContext),
 180                        PKIX_LISTGETLENGTHFAILED);
 181
 182                if (numChildren != 1) {
 183                        PKIX_ERROR(PKIX_AMBIGUOUSPARENTAGEOFVERIFYNODE);
 184                }
 185
 186                /* successor = listOfChildren[0] */
 187                PKIX_CHECK(PKIX_List_GetItem
 188                        (listOfChildren,
 189                        0,
 190                        (PKIX_PL_Object **)&successor,
 191                        plContext),
 192                        PKIX_LISTGETITEMFAILED);
 193
 194                PKIX_CHECK(pkix_VerifyNode_AddToChain
 195                        (successor, child, plContext),
 196                        PKIX_VERIFYNODEADDTOCHAINFAILED);
 197        }
 198
 199        PKIX_CHECK(PKIX_PL_Object_InvalidateCache
 200                ((PKIX_PL_Object *)parentNode, plContext),
 201                PKIX_OBJECTINVALIDATECACHEFAILED);
 202
 203cleanup:
 204        PKIX_DECREF(successor);
 205
 206        PKIX_RETURN(VERIFYNODE);
 207}
 208
 209/*
 210 * FUNCTION: pkix_VerifyNode_SetDepth
 211 * DESCRIPTION:
 212 *
 213 *  The function sets the depth field of each VerifyNode in the List "children"
 214 *  to the value given by "depth", and recursively sets the depth of any
 215 *  successive generations to the successive values.
 216 *
 217 * PARAMETERS:
 218 *  "children"
 219 *      The List of VerifyNodes. Must be non-NULL.
 220 *  "depth"
 221 *      The value of the depth field to be set in members of the List.
 222 *  "plContext"
 223 *      Platform-specific context pointer.
 224 * THREAD SAFETY:
 225 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
 226 * RETURNS:
 227 *  Returns NULL if the function succeeds.
 228 *  Returns a Fatal Error if the function fails in an unrecoverable way.
 229 */
 230static PKIX_Error *
 231pkix_VerifyNode_SetDepth(PKIX_List *children,
 232        PKIX_UInt32 depth,
 233        void *plContext)
 234{
 235        PKIX_UInt32 numChildren = 0;
 236        PKIX_UInt32 chIx = 0;
 237        PKIX_VerifyNode *child = NULL;
 238
 239        PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_SetDepth");
 240        PKIX_NULLCHECK_ONE(children);
 241
 242        PKIX_CHECK(PKIX_List_GetLength(children, &numChildren, plContext),
 243                PKIX_LISTGETLENGTHFAILED);
 244
 245        for (chIx = 0; chIx < numChildren; chIx++) {
 246               PKIX_CHECK(PKIX_List_GetItem
 247                        (children, chIx, (PKIX_PL_Object **)&child, plContext),
 248                        PKIX_LISTGETITEMFAILED);
 249
 250                child->depth = depth;
 251
 252                if (child->children != NULL) {
 253                        PKIX_CHECK(pkix_VerifyNode_SetDepth
 254                                (child->children, depth + 1, plContext),
 255                                PKIX_VERIFYNODESETDEPTHFAILED);
 256                }
 257
 258                PKIX_DECREF(child);
 259        }
 260
 261cleanup:
 262
 263        PKIX_DECREF(child);
 264
 265        PKIX_RETURN(VERIFYNODE);
 266}
 267
 268/*
 269 * FUNCTION: pkix_VerifyNode_AddToTree
 270 * DESCRIPTION:
 271 *
 272 *  Adds the VerifyNode pointed to by "child" to the List of children of the
 273 *  VerifyNode pointed to by "parentNode". If "parentNode" has a NULL pointer
 274 *  for the List of children, a new List is created containing "child".
 275 *  Otherwise "child" is appended to the existing List. The depth field of
 276 *  "child" is set to one more than the corresponding value in "parent", and
 277 *  if the "child" itself has child nodes, their depth fields are updated
 278 *  accordingly.
 279 *
 280 *  Depth, in this context, means distance from the root node, which
 281 *  is at depth zero.
 282 *
 283 * PARAMETERS:
 284 *  "parentNode"
 285 *      Address of VerifyNode whose List of child VerifyNodes is to be
 286 *      created or appended to. Must be non-NULL.
 287 *  "child"
 288 *      Address of VerifyNode to be added to parentNode's List. Must be
 289 *      non-NULL.
 290 *  "plContext"
 291 *      Platform-specific context pointer.
 292 * THREAD SAFETY:
 293 *  Not Thread Safe (see Thread Safety Definitions in Programmer's Guide)
 294 * RETURNS:
 295 *  Returns NULL if the function succeeds.
 296 *  Returns a Fatal Error if the function fails in an unrecoverable way.
 297 */
 298PKIX_Error *
 299pkix_VerifyNode_AddToTree(
 300        PKIX_VerifyNode *parentNode,
 301        PKIX_VerifyNode *child,
 302        void *plContext)
 303{
 304        PKIX_List *listOfChildren = NULL;
 305        PKIX_UInt32 parentDepth = 0;
 306
 307        PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_AddToTree");
 308        PKIX_NULLCHECK_TWO(parentNode, child);
 309
 310        parentDepth = parentNode->depth;
 311        listOfChildren = parentNode->children;
 312        if (listOfChildren == NULL) {
 313
 314                PKIX_CHECK(PKIX_List_Create(&listOfChildren, plContext),
 315                        PKIX_LISTCREATEFAILED);
 316
 317                parentNode->children = listOfChildren;
 318        }
 319
 320        child->depth = parentDepth + 1;
 321
 322        PKIX_CHECK(PKIX_List_AppendItem
 323                (parentNode->children, (PKIX_PL_Object *)child, plContext),
 324                PKIX_COULDNOTAPPENDCHILDTOPARENTSVERIFYNODELIST);
 325
 326        if (child->children != NULL) {
 327                PKIX_CHECK(pkix_VerifyNode_SetDepth
 328                        (child->children, child->depth + 1, plContext),
 329                        PKIX_VERIFYNODESETDEPTHFAILED);
 330        }
 331
 332
 333cleanup:
 334
 335        PKIX_RETURN(VERIFYNODE);
 336}
 337
 338/*
 339 * FUNCTION: pkix_SingleVerifyNode_ToString
 340 * DESCRIPTION:
 341 *
 342 *  Creates a String representation of the attributes of the VerifyNode pointed
 343 *  to by "node", other than its children, and stores the result at "pString".
 344 *
 345 * PARAMETERS:
 346 *  "node"
 347 *      Address of VerifyNode to be described by the string. Must be non-NULL.
 348 *  "pString"
 349 *      Address where object pointer will be stored. Must be non-NULL.
 350 *  "plContext"
 351 *      Platform-specific context pointer.
 352 * THREAD SAFETY:
 353 *  Conditionally Thread Safe
 354 *  (see Thread Safety Definitions in Programmer's Guide)
 355 * RETURNS:
 356 *  Returns NULL if function succeeds
 357 *  Returns a VerifyNode Error if the function fails in a non-fatal way.
 358 *  Returns a Fatal Error if the function fails in a fatal way
 359 */
 360PKIX_Error *
 361pkix_SingleVerifyNode_ToString(
 362        PKIX_VerifyNode *node,
 363        PKIX_PL_String **pString,
 364        void *plContext)
 365{
 366        PKIX_PL_String *fmtString = NULL;
 367        PKIX_PL_String *errorString = NULL;
 368        PKIX_PL_String *outString = NULL;
 369
 370        PKIX_PL_X500Name *issuerName = NULL;
 371        PKIX_PL_X500Name *subjectName = NULL;
 372        PKIX_PL_String *issuerString = NULL;
 373        PKIX_PL_String *subjectString = NULL;
 374
 375        PKIX_ENTER(VERIFYNODE, "pkix_SingleVerifyNode_ToString");
 376        PKIX_NULLCHECK_THREE(node, pString, node->verifyCert);
 377
 378        PKIX_TOSTRING(node->error, &errorString, plContext,
 379                PKIX_ERRORTOSTRINGFAILED);
 380
 381        PKIX_CHECK(PKIX_PL_Cert_GetIssuer
 382                (node->verifyCert, &issuerName, plContext),
 383                PKIX_CERTGETISSUERFAILED);
 384
 385        PKIX_TOSTRING(issuerName, &issuerString, plContext,
 386                PKIX_X500NAMETOSTRINGFAILED);
 387
 388        PKIX_CHECK(PKIX_PL_Cert_GetSubject
 389                (node->verifyCert, &subjectName, plContext),
 390                PKIX_CERTGETSUBJECTFAILED);
 391
 392        PKIX_TOSTRING(subjectName, &subjectString, plContext,
 393                PKIX_X500NAMETOSTRINGFAILED);
 394
 395        PKIX_CHECK(PKIX_PL_String_Create
 396                (PKIX_ESCASCII,
 397                "CERT[Issuer:%s, Subject:%s], depth=%d, error=%s",
 398                0,
 399                &fmtString,
 400                plContext),
 401                PKIX_CANTCREATESTRING);
 402
 403        PKIX_CHECK(PKIX_PL_Sprintf
 404                (&outString,
 405                plContext,
 406                fmtString,
 407                issuerString,
 408                subjectString,
 409                node->depth,
 410                errorString),
 411                PKIX_SPRINTFFAILED);
 412
 413        *pString = outString;
 414
 415cleanup:
 416
 417        PKIX_DECREF(fmtString);
 418        PKIX_DECREF(errorString);
 419        PKIX_DECREF(issuerName);
 420        PKIX_DECREF(subjectName);
 421        PKIX_DECREF(issuerString);
 422        PKIX_DECREF(subjectString);
 423        PKIX_RETURN(VERIFYNODE);
 424}
 425
 426/*
 427 * FUNCTION: pkix_VerifyNode_ToString_Helper
 428 * DESCRIPTION:
 429 *
 430 *  Produces a String representation of a VerifyNode tree below the VerifyNode
 431 *  pointed to by "rootNode", with each line of output prefixed by the String
 432 *  pointed to by "indent", and stores the result at "pTreeString". It is
 433 *  called recursively, with ever-increasing indentation, for successively
 434 *  lower nodes on the tree.
 435 *
 436 * PARAMETERS:
 437 *  "rootNode"
 438 *      Address of VerifyNode subtree. Must be non-NULL.
 439 *  "indent"
 440 *      Address of String to be prefixed to each line of output. May be NULL
 441 *      if no indentation is desired
 442 *  "pTreeString"
 443 *      Address where the resulting String will be stored; must be non-NULL
 444 *  "plContext"
 445 *      Platform-specific context pointer.
 446 * THREAD SAFETY:
 447 *  Conditionally Thread Safe
 448 *  (see Thread Safety Definitions in Programmer's Guide)
 449 * RETURNS:
 450 *  Returns NULL if the function succeeds.
 451 *  Returns a VerifyNode Error if the function fails in a non-fatal way.
 452 *  Returns a Fatal Error if the function fails in an unrecoverable way.
 453 */
 454static PKIX_Error *
 455pkix_VerifyNode_ToString_Helper(
 456        PKIX_VerifyNode *rootNode,
 457        PKIX_PL_String *indent,
 458        PKIX_PL_String **pTreeString,
 459        void *plContext)
 460{
 461        PKIX_PL_String *nextIndentFormat = NULL;
 462        PKIX_PL_String *thisNodeFormat = NULL;
 463        PKIX_PL_String *childrenFormat = NULL;
 464        PKIX_PL_String *nextIndentString = NULL;
 465        PKIX_PL_String *resultString = NULL;
 466        PKIX_PL_String *thisItemString = NULL;
 467        PKIX_PL_String *childString = NULL;
 468        PKIX_VerifyNode *childNode = NULL;
 469        PKIX_UInt32 numberOfChildren = 0;
 470        PKIX_UInt32 childIndex = 0;
 471
 472        PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_ToString_Helper");
 473
 474        PKIX_NULLCHECK_TWO(rootNode, pTreeString);
 475
 476        /* Create a string for this node */
 477        PKIX_CHECK(pkix_SingleVerifyNode_ToString
 478                (rootNode, &thisItemString, plContext),
 479                PKIX_ERRORINSINGLEVERIFYNODETOSTRING);
 480
 481        if (indent) {
 482                PKIX_CHECK(PKIX_PL_String_Create
 483                        (PKIX_ESCASCII,
 484                        "%s%s",
 485                        0,
 486                        &thisNodeFormat,
 487                        plContext),
 488                        PKIX_ERRORCREATINGFORMATSTRING);
 489
 490                PKIX_CHECK(PKIX_PL_Sprintf
 491                        (&resultString,
 492                        plContext,
 493                        thisNodeFormat,
 494                        indent,
 495                        thisItemString),
 496                        PKIX_ERRORINSPRINTF);
 497        } else {
 498                PKIX_CHECK(PKIX_PL_String_Create
 499                        (PKIX_ESCASCII,
 500                        "%s",
 501                        0,
 502                        &thisNodeFormat,
 503                        plContext),
 504                        PKIX_ERRORCREATINGFORMATSTRING);
 505
 506                PKIX_CHECK(PKIX_PL_Sprintf
 507                        (&resultString,
 508                        plContext,
 509                        thisNodeFormat,
 510                        thisItemString),
 511                        PKIX_ERRORINSPRINTF);
 512        }
 513
 514        PKIX_DECREF(thisItemString);
 515        thisItemString = resultString;
 516
 517        /* if no children, we are done */
 518        if (rootNode->children) {
 519                PKIX_CHECK(PKIX_List_GetLength
 520                        (rootNode->children, &numberOfChildren, plContext),
 521                        PKIX_LISTGETLENGTHFAILED);
 522        }
 523
 524        if (numberOfChildren != 0) {
 525                /*
 526                 * We create a string for each child in turn,
 527                 * concatenating them to thisItemString.
 528                 */
 529
 530                /* Prepare an indent string for each child */
 531                if (indent) {
 532                        PKIX_CHECK(PKIX_PL_String_Create
 533                                (PKIX_ESCASCII,
 534                                "%s. ",
 535                                0,
 536                                &nextIndentFormat,
 537                                plContext),
 538                                PKIX_ERRORCREATINGFORMATSTRING);
 539
 540                        PKIX_CHECK(PKIX_PL_Sprintf
 541                                (&nextIndentString,
 542                                plContext,
 543                                nextIndentFormat,
 544                                indent),
 545                                PKIX_ERRORINSPRINTF);
 546                } else {
 547                        PKIX_CHECK(PKIX_PL_String_Create
 548                                (PKIX_ESCASCII,
 549                                ". ",
 550                                0,
 551                                &nextIndentString,
 552                                plContext),
 553                                PKIX_ERRORCREATINGINDENTSTRING);
 554                }
 555
 556                /* Prepare the format for concatenation. */
 557                PKIX_CHECK(PKIX_PL_String_Create
 558                        (PKIX_ESCASCII,
 559                        "%s\n%s",
 560                        0,
 561                        &childrenFormat,
 562                        plContext),
 563                        PKIX_ERRORCREATINGFORMATSTRING);
 564
 565                for (childIndex = 0;
 566                        childIndex < numberOfChildren;
 567                        childIndex++) {
 568                        PKIX_CHECK(PKIX_List_GetItem
 569                                (rootNode->children,
 570                                childIndex,
 571                                (PKIX_PL_Object **)&childNode,
 572                                plContext),
 573                                PKIX_LISTGETITEMFAILED);
 574
 575                        PKIX_CHECK(pkix_VerifyNode_ToString_Helper
 576                                (childNode,
 577                                nextIndentString,
 578                                &childString,
 579                                plContext),
 580                                PKIX_ERRORCREATINGCHILDSTRING);
 581
 582
 583                        PKIX_CHECK(PKIX_PL_Sprintf
 584                                (&resultString,
 585                                plContext,
 586                                childrenFormat,
 587                                thisItemString,
 588                                childString),
 589                        PKIX_ERRORINSPRINTF);
 590
 591                        PKIX_DECREF(childNode);
 592                        PKIX_DECREF(childString);
 593                        PKIX_DECREF(thisItemString);
 594
 595                        thisItemString = resultString;
 596                }
 597        }
 598
 599        *pTreeString = thisItemString;
 600
 601cleanup:
 602        if (PKIX_ERROR_RECEIVED) {
 603                PKIX_DECREF(thisItemString);
 604        }
 605
 606        PKIX_DECREF(nextIndentFormat);
 607        PKIX_DECREF(thisNodeFormat);
 608        PKIX_DECREF(childrenFormat);
 609        PKIX_DECREF(nextIndentString);
 610        PKIX_DECREF(childString);
 611        PKIX_DECREF(childNode);
 612
 613        PKIX_RETURN(VERIFYNODE);
 614}
 615
 616/*
 617 * FUNCTION: pkix_VerifyNode_ToString
 618 * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
 619 */
 620static PKIX_Error *
 621pkix_VerifyNode_ToString(
 622        PKIX_PL_Object *object,
 623        PKIX_PL_String **pTreeString,
 624        void *plContext)
 625{
 626        PKIX_VerifyNode *rootNode = NULL;
 627        PKIX_PL_String *resultString = NULL;
 628
 629        PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_ToString");
 630
 631        PKIX_NULLCHECK_TWO(object, pTreeString);
 632
 633        PKIX_CHECK(pkix_CheckType(object, PKIX_VERIFYNODE_TYPE, plContext),
 634                PKIX_OBJECTNOTVERIFYNODE);
 635
 636        rootNode = (PKIX_VerifyNode *)object;
 637
 638        PKIX_CHECK(pkix_VerifyNode_ToString_Helper
 639                (rootNode, NULL, &resultString, plContext),
 640                PKIX_ERRORCREATINGSUBTREESTRING);
 641
 642        *pTreeString = resultString;
 643
 644cleanup:
 645
 646        PKIX_RETURN(VERIFYNODE);
 647}
 648
 649/*
 650 * FUNCTION: pkix_VerifyNode_Destroy
 651 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
 652 */
 653static PKIX_Error *
 654pkix_VerifyNode_Destroy(
 655        PKIX_PL_Object *object,
 656        void *plContext)
 657{
 658        PKIX_VerifyNode *node = NULL;
 659
 660        PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_Destroy");
 661
 662        PKIX_NULLCHECK_ONE(object);
 663
 664        PKIX_CHECK(pkix_CheckType(object, PKIX_VERIFYNODE_TYPE, plContext),
 665                PKIX_OBJECTNOTVERIFYNODE);
 666
 667        node = (PKIX_VerifyNode*)object;
 668
 669        PKIX_DECREF(node->verifyCert);
 670        PKIX_DECREF(node->children);
 671        PKIX_DECREF(node->error);
 672
 673        node->depth = 0;
 674
 675cleanup:
 676
 677        PKIX_RETURN(VERIFYNODE);
 678}
 679
 680/*
 681 * FUNCTION: pkix_SingleVerifyNode_Hashcode
 682 * DESCRIPTION:
 683 *
 684 *  Computes the hashcode of the attributes of the VerifyNode pointed to by
 685 *  "node", other than its parents and children, and stores the result at
 686 *  "pHashcode".
 687 *
 688 * PARAMETERS:
 689 *  "node"
 690 *      Address of VerifyNode to be hashcoded; must be non-NULL
 691 *  "pHashcode"
 692 *      Address where UInt32 result will be stored; must be non-NULL
 693 *  "plContext"
 694 *      Platform-specific context pointer.
 695 * THREAD SAFETY:
 696 *  Conditionally Thread Safe
 697 *  (see Thread Safety Definitions in Programmer's Guide)
 698 * RETURNS:
 699 *  Returns NULL if function succeeds
 700 *  Returns a VerifyNode Error if the function fails in a non-fatal way.
 701 *  Returns a Fatal Error if the function fails in a fatal way
 702 */
 703static PKIX_Error *
 704pkix_SingleVerifyNode_Hashcode(
 705        PKIX_VerifyNode *node,
 706        PKIX_UInt32 *pHashcode,
 707        void *plContext)
 708{
 709        PKIX_UInt32 errorHash = 0;
 710        PKIX_UInt32 nodeHash = 0;
 711
 712        PKIX_ENTER(VERIFYNODE, "pkix_SingleVerifyNode_Hashcode");
 713        PKIX_NULLCHECK_TWO(node, pHashcode);
 714
 715        PKIX_HASHCODE
 716                (node->verifyCert,
 717                &nodeHash,
 718                plContext,
 719                PKIX_FAILUREHASHINGCERT);
 720
 721        PKIX_CHECK(PKIX_PL_Object_Hashcode
 722                ((PKIX_PL_Object *)node->error,
 723                &errorHash,
 724                plContext),
 725                PKIX_FAILUREHASHINGERROR);
 726
 727        nodeHash = 31*nodeHash + errorHash;
 728        *pHashcode = nodeHash;
 729
 730cleanup:
 731
 732        PKIX_RETURN(VERIFYNODE);
 733}
 734
 735/*
 736 * FUNCTION: pkix_VerifyNode_Hashcode
 737 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
 738 */
 739static PKIX_Error *
 740pkix_VerifyNode_Hashcode(
 741        PKIX_PL_Object *object,
 742        PKIX_UInt32 *pHashcode,
 743        void *plContext)
 744{
 745        PKIX_VerifyNode *node = NULL;
 746        PKIX_UInt32 childrenHash = 0;
 747        PKIX_UInt32 nodeHash = 0;
 748
 749        PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_Hashcode");
 750        PKIX_NULLCHECK_TWO(object, pHashcode);
 751
 752        PKIX_CHECK(pkix_CheckType
 753                (object, PKIX_VERIFYNODE_TYPE, plContext),
 754                PKIX_OBJECTNOTVERIFYNODE);
 755
 756        node = (PKIX_VerifyNode *)object;
 757
 758        PKIX_CHECK(pkix_SingleVerifyNode_Hashcode
 759                (node, &nodeHash, plContext),
 760                PKIX_SINGLEVERIFYNODEHASHCODEFAILED);
 761
 762        PKIX_HASHCODE
 763                (node->children,
 764                &childrenHash,
 765                plContext,
 766                PKIX_OBJECTHASHCODEFAILED);
 767
 768        nodeHash = 31*nodeHash + childrenHash;
 769
 770        *pHashcode = nodeHash;
 771
 772cleanup:
 773
 774        PKIX_RETURN(VERIFYNODE);
 775}
 776
 777/*
 778 * FUNCTION: pkix_SingleVerifyNode_Equals
 779 * DESCRIPTION:
 780 *
 781 *  Compares for equality the components of the VerifyNode pointed to by
 782 *  "firstPN", other than its parents and children, with those of the
 783 *  VerifyNode pointed to by "secondPN" and stores the result at "pResult"
 784 *  (PKIX_TRUE if equal; PKIX_FALSE if not).
 785 *
 786 * PARAMETERS:
 787 *  "firstPN"
 788 *      Address of first of the VerifyNodes to be compared; must be non-NULL
 789 *  "secondPN"
 790 *      Address of second of the VerifyNodes to be compared; must be non-NULL
 791 *  "pResult"
 792 *      Address where Boolean will be stored; must be non-NULL
 793 *  "plContext"
 794 *      Platform-specific context pointer.
 795 * THREAD SAFETY:
 796 *  Conditionally Thread Safe
 797 *  (see Thread Safety Definitions in Programmer's Guide)
 798 * RETURNS:
 799 *  Returns NULL if function succeeds
 800 *  Returns a VerifyNode Error if the function fails in a non-fatal way.
 801 *  Returns a Fatal Error if the function fails in a fatal way
 802 */
 803static PKIX_Error *
 804pkix_SingleVerifyNode_Equals(
 805        PKIX_VerifyNode *firstVN,
 806        PKIX_VerifyNode *secondVN,
 807        PKIX_Boolean *pResult,
 808        void *plContext)
 809{
 810        PKIX_Boolean compResult = PKIX_FALSE;
 811
 812        PKIX_ENTER(VERIFYNODE, "pkix_SingleVerifyNode_Equals");
 813        PKIX_NULLCHECK_THREE(firstVN, secondVN, pResult);
 814
 815        /* If both references are identical, they must be equal */
 816        if (firstVN == secondVN) {
 817                compResult = PKIX_TRUE;
 818                goto cleanup;
 819        }
 820
 821        /*
 822         * It seems we have to do the comparisons. Do
 823         * the easiest ones first.
 824         */
 825        if ((firstVN->depth) != (secondVN->depth)) {
 826                goto cleanup;
 827        }
 828
 829        /* These fields must be non-NULL */
 830        PKIX_NULLCHECK_TWO(firstVN->verifyCert, secondVN->verifyCert);
 831
 832        PKIX_EQUALS
 833                (firstVN->verifyCert,
 834                secondVN->verifyCert,
 835                &compResult,
 836                plContext,
 837                PKIX_OBJECTEQUALSFAILED);
 838
 839        if (compResult == PKIX_FALSE) {
 840                goto cleanup;
 841        }
 842
 843        PKIX_EQUALS
 844                (firstVN->error,
 845                secondVN->error,
 846                &compResult,
 847                plContext,
 848                PKIX_OBJECTEQUALSFAILED);
 849
 850cleanup:
 851
 852        *pResult = compResult;
 853
 854        PKIX_RETURN(VERIFYNODE);
 855}
 856
 857/*
 858 * FUNCTION: pkix_VerifyNode_Equals
 859 * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
 860 */
 861static PKIX_Error *
 862pkix_VerifyNode_Equals(
 863        PKIX_PL_Object *firstObject,
 864        PKIX_PL_Object *secondObject,
 865        PKIX_Boolean *pResult,
 866        void *plContext)
 867{
 868        PKIX_VerifyNode *firstVN = NULL;
 869        PKIX_VerifyNode *secondVN = NULL;
 870        PKIX_UInt32 secondType;
 871        PKIX_Boolean compResult = PKIX_FALSE;
 872
 873        PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_Equals");
 874        PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
 875
 876        /* test that firstObject is a VerifyNode */
 877        PKIX_CHECK(pkix_CheckType
 878                (firstObject, PKIX_VERIFYNODE_TYPE, plContext),
 879                PKIX_FIRSTOBJECTNOTVERIFYNODE);
 880
 881        /*
 882         * Since we know firstObject is a VerifyNode,
 883         * if both references are identical, they must be equal
 884         */
 885        if (firstObject == secondObject){
 886                compResult = PKIX_TRUE;
 887                goto cleanup;
 888        }
 889
 890        /*
 891         * If secondObject isn't a VerifyNode, we
 892         * don't throw an error. We simply return FALSE.
 893         */
 894        PKIX_CHECK(PKIX_PL_Object_GetType
 895                    (secondObject, &secondType, plContext),
 896                    PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
 897
 898        if (secondType != PKIX_VERIFYNODE_TYPE) {
 899                goto cleanup;
 900        }
 901
 902        /*
 903         * Oh, well, we have to do the comparisons. Do
 904         * the easiest ones first.
 905         */
 906        firstVN = (PKIX_VerifyNode *)firstObject;
 907        secondVN = (PKIX_VerifyNode *)secondObject;
 908
 909        PKIX_CHECK(pkix_SingleVerifyNode_Equals
 910                (firstVN, secondVN, &compResult, plContext),
 911                PKIX_SINGLEVERIFYNODEEQUALSFAILED);
 912
 913        if (compResult == PKIX_FALSE) {
 914                goto cleanup;
 915        }
 916
 917        PKIX_EQUALS
 918                (firstVN->children,
 919                secondVN->children,
 920                &compResult,
 921                plContext,
 922                PKIX_OBJECTEQUALSFAILEDONCHILDREN);
 923
 924cleanup:
 925
 926        *pResult = compResult;
 927
 928        PKIX_RETURN(VERIFYNODE);
 929}
 930
 931/*
 932 * FUNCTION: pkix_VerifyNode_DuplicateHelper
 933 * DESCRIPTION:
 934 *
 935 *  Duplicates the VerifyNode whose address is pointed to by "original",
 936 *  and stores the result at "pNewNode", if a non-NULL pointer is provided
 937 *  for "pNewNode". In addition, the created VerifyNode is added as a child
 938 *  to "parent", if a non-NULL pointer is provided for "parent". Then this
 939 *  function is called recursively to duplicate each of the children of
 940 *  "original". At the top level this function is called with a null
 941 *  "parent" and a non-NULL "pNewNode". Below the top level "parent" will
 942 *  be non-NULL and "pNewNode" will be NULL.
 943 *
 944 * PARAMETERS:
 945 *  "original"
 946 *      Address of VerifyNode to be copied; must be non-NULL
 947 *  "parent"
 948 *      Address of VerifyNode to which the created node is to be added as a
 949 *      child; NULL for the top-level call and non-NULL below the top level
 950 *  "pNewNode"
 951 *      Address to store the node created; should be NULL if "parent" is
 952 *      non-NULL and vice versa
 953 *  "plContext"
 954 *      Platform-specific context pointer.
 955 * THREAD SAFETY:
 956 *  Conditionally Thread Safe
 957 *  (see Thread Safety Definitions in Programmer's Guide)
 958 * RETURNS:
 959 *  Returns NULL if function succeeds
 960 *  Returns a VerifyNode Error if the function fails in a non-fatal way.
 961 *  Returns a Fatal Error if the function fails in a fatal way
 962 */
 963static PKIX_Error *
 964pkix_VerifyNode_DuplicateHelper(
 965        PKIX_VerifyNode *original,
 966        PKIX_VerifyNode *parent,
 967        PKIX_VerifyNode **pNewNode,
 968        void *plContext)
 969{
 970        PKIX_UInt32 numChildren = 0;
 971        PKIX_UInt32 childIndex = 0;
 972        PKIX_List *children = NULL; /* List of PKIX_VerifyNode */
 973        PKIX_VerifyNode *copy = NULL;
 974        PKIX_VerifyNode *child = NULL;
 975
 976        PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_DuplicateHelper");
 977
 978        PKIX_NULLCHECK_TWO
 979                (original, original->verifyCert);
 980
 981        /*
 982         * These components are immutable, so copying the pointers
 983         * is sufficient. The create function increments the reference
 984         * counts as it stores the pointers into the new object.
 985         */
 986        PKIX_CHECK(pkix_VerifyNode_Create
 987                (original->verifyCert,
 988                original->depth,
 989                original->error,
 990                &copy,
 991                plContext),
 992                PKIX_VERIFYNODECREATEFAILED);
 993
 994        /* Are there any children to duplicate? */
 995        children = original->children;
 996
 997        if (children) {
 998            PKIX_CHECK(PKIX_List_GetLength(children, &numChildren, plContext),
 999                PKIX_LISTGETLENGTHFAILED);
1000        }
1001
1002        for (childIndex = 0; childIndex < numChildren; childIndex++) {
1003                PKIX_CHECK(PKIX_List_GetItem
1004                        (children,
1005                        childIndex,
1006                        (PKIX_PL_Object **)&child,
1007                        plContext),
1008                        PKIX_LISTGETITEMFAILED);
1009
1010                PKIX_CHECK(pkix_VerifyNode_DuplicateHelper
1011                        (child, copy, NULL, plContext),
1012                        PKIX_VERIFYNODEDUPLICATEHELPERFAILED);
1013
1014                PKIX_DECREF(child);
1015        }
1016
1017        if (pNewNode) {
1018                *pNewNode = copy;
1019                copy = NULL; /* no DecRef if we give our handle away */
1020        }
1021
1022cleanup:
1023        PKIX_DECREF(copy);
1024        PKIX_DECREF(child);
1025
1026        PKIX_RETURN(VERIFYNODE);
1027}
1028
1029/*
1030 * FUNCTION: pkix_VerifyNode_Duplicate
1031 * (see comments for PKIX_PL_Duplicate_Callback in pkix_pl_system.h)
1032 */
1033static PKIX_Error *
1034pkix_VerifyNode_Duplicate(
1035        PKIX_PL_Object *object,
1036        PKIX_PL_Object **pNewObject,
1037        void *plContext)
1038{
1039        PKIX_VerifyNode *original = NULL;
1040        PKIX_VerifyNode *copy = NULL;
1041
1042        PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_Duplicate");
1043
1044        PKIX_NULLCHECK_TWO(object, pNewObject);
1045
1046        PKIX_CHECK(pkix_CheckType
1047                (object, PKIX_VERIFYNODE_TYPE, plContext),
1048                PKIX_OBJECTNOTVERIFYNODE);
1049
1050        original = (PKIX_VerifyNode *)object;
1051
1052        PKIX_CHECK(pkix_VerifyNode_DuplicateHelper
1053                (original, NULL, &copy, plContext),
1054                PKIX_VERIFYNODEDUPLICATEHELPERFAILED);
1055
1056        *pNewObject = (PKIX_PL_Object *)copy;
1057
1058cleanup:
1059
1060        PKIX_RETURN(VERIFYNODE);
1061}
1062
1063/*
1064 * FUNCTION: pkix_VerifyNode_RegisterSelf
1065 * DESCRIPTION:
1066 *
1067 *  Registers PKIX_VERIFYNODE_TYPE and its related
1068 *  functions with systemClasses[]
1069 *
1070 * THREAD SAFETY:
1071 *  Not Thread Safe - for performance and complexity reasons
1072 *
1073 *  Since this function is only called by PKIX_PL_Initialize,
1074 *  which should only be called once, it is acceptable that
1075 *  this function is not thread-safe.
1076 */
1077PKIX_Error *
1078pkix_VerifyNode_RegisterSelf(void *plContext)
1079{
1080
1081        extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
1082        pkix_ClassTable_Entry entry;
1083
1084        PKIX_ENTER(VERIFYNODE, "pkix_VerifyNode_RegisterSelf");
1085
1086        entry.description = "VerifyNode";
1087        entry.objCounter = 0;
1088        entry.typeObjectSize = sizeof(PKIX_VerifyNode);
1089        entry.destructor = pkix_VerifyNode_Destroy;
1090        entry.equalsFunction = pkix_VerifyNode_Equals;
1091        entry.hashcodeFunction = pkix_VerifyNode_Hashcode;
1092        entry.toStringFunction = pkix_VerifyNode_ToString;
1093        entry.comparator = NULL;
1094        entry.duplicateFunction = pkix_VerifyNode_Duplicate;
1095
1096        systemClasses[PKIX_VERIFYNODE_TYPE] = entry;
1097
1098        PKIX_RETURN(VERIFYNODE);
1099}
1100
1101/* --Public-VerifyNode-Functions----------------------------------- */
1102
1103/*
1104 * FUNCTION: PKIX_VerifyNode_SetError
1105 * DESCRIPTION:
1106 *
1107 *  This function sets the Error field of the VerifyNode pointed to by "node"
1108 *  to contain the Error pointed to by "error".
1109 *
1110 * PARAMETERS:
1111 *  "node"
1112 *      The address of the VerifyNode to be modified. Must be non-NULL.
1113 *  "error"
1114 *      The address of the Error to be stored.
1115 *  "plContext"
1116 *      Platform-specific context pointer.
1117 * THREAD SAFETY:
1118 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
1119 * RETURNS:
1120 *  Returns NULL if the function succeeds.
1121 *  Returns a Fatal Error if the function fails in an unrecoverable way.
1122 */
1123PKIX_Error *
1124pkix_VerifyNode_SetError(
1125        PKIX_VerifyNode *node,
1126        PKIX_Error *error,
1127        void *plContext)
1128{
1129
1130        PKIX_ENTER(VERIFYNODE, "PKIX_VerifyNode_SetError");
1131
1132        PKIX_NULLCHECK_TWO(node, error);
1133
1134        PKIX_DECREF(node->error); /* should have been NULL */
1135        PKIX_INCREF(error);
1136        node->error = error;
1137
1138cleanup:
1139        PKIX_RETURN(VERIFYNODE);
1140}
1141
1142/*
1143 * FUNCTION: PKIX_VerifyNode_FindError
1144 * DESCRIPTION:
1145 *
1146 * Finds meaningful error in the log. For now, just returns the first
1147 * error it finds in. In the future the function should be changed to
1148 * return a top priority error.
1149 *
1150 * PARAMETERS:
1151 *  "node"
1152 *      The address of the VerifyNode to be modified. Must be non-NULL.
1153 *  "error"
1154 *      The address of a pointer the error will be returned to.
1155 *  "plContext"
1156 *      Platform-specific context pointer.
1157 * THREAD SAFETY:
1158 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
1159 * RETURNS:
1160 *  Returns NULL if the function succeeds.
1161 *  Returns a Fatal Error if the function fails in an unrecoverable way.
1162 */
1163PKIX_Error *
1164pkix_VerifyNode_FindError(
1165        PKIX_VerifyNode *node,
1166        PKIX_Error **error,
1167        void *plContext)
1168{
1169    PKIX_VerifyNode *childNode = NULL;
1170
1171    PKIX_ENTER(VERIFYNODE, "PKIX_VerifyNode_FindError");
1172
1173    /* Make sure the return address is initialized with NULL */
1174    PKIX_DECREF(*error);
1175
1176    if (!node)
1177        goto cleanup;
1178    
1179    /* First, try to get error from lowest level. */
1180    if (node->children) {
1181        PKIX_UInt32 length = 0;
1182        PKIX_UInt32 index = 0;
1183
1184        PKIX_CHECK(
1185            PKIX_List_GetLength(node->children, &length,
1186                                plContext),
1187            PKIX_LISTGETLENGTHFAILED);
1188        for (index = 0;index < length;index++) {
1189            PKIX_CHECK(
1190                PKIX_List_GetItem(node->children, index,
1191                                  (PKIX_PL_Object**)&childNode, plContext),
1192                PKIX_LISTGETITEMFAILED);
1193            if (!childNode)
1194                continue;
1195            PKIX_CHECK(
1196                pkix_VerifyNode_FindError(childNode, error,
1197                                          plContext),
1198                PKIX_VERIFYNODEFINDERRORFAILED);
1199            PKIX_DECREF(childNode);
1200            if (*error) {
1201                goto cleanup;
1202            }
1203        }
1204    }
1205    
1206    if (node->error && node->error->plErr) {
1207        PKIX_INCREF(node->error);
1208        *error = node->error;
1209    }
1210
1211cleanup:
1212    PKIX_DECREF(childNode);
1213    
1214    PKIX_RETURN(VERIFYNODE);
1215}