PKIX_ProcessingParams *
createProcessingParams(
        char *dirName,
        char *firstAnchorFileName,
        char *secondAnchorFileName,
        char *dateAscii,
        PKIX_List *initialPolicies, /* List of PKIX_PL_OID */
        PKIX_Boolean isCrlEnabled,
        void *plContext)
{

        PKIX_TrustAnchor *firstAnchor = NULL;
        PKIX_TrustAnchor *secondAnchor = NULL;
        PKIX_List *anchorsList = NULL;
        PKIX_ProcessingParams *procParams = NULL;
        PKIX_PL_String *dateString = NULL;
        PKIX_PL_Date *testDate = NULL;

        PKIX_TEST_STD_VARS();

        PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&anchorsList, plContext));

        firstAnchor = createTrustAnchor
                (dirName, firstAnchorFileName, PKIX_FALSE, plContext);

        PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
                                    (anchorsList,
                                    (PKIX_PL_Object *)firstAnchor,
                                    plContext));

        if (secondAnchorFileName){
                secondAnchor =
                        createTrustAnchor
                        (dirName, secondAnchorFileName, PKIX_FALSE, plContext);

                PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
                                            (anchorsList,
                                            (PKIX_PL_Object *)secondAnchor,
                                            plContext));
        }

        PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_Create
                                    (anchorsList, &procParams, plContext));

        if (dateAscii){
                PKIX_TEST_EXPECT_NO_ERROR
                        (PKIX_PL_String_Create
                        (PKIX_ESCASCII,
                        dateAscii,
                        0,
                        &dateString,
                        plContext));

                PKIX_TEST_EXPECT_NO_ERROR
                        (PKIX_PL_Date_Create_UTCTime
                        (dateString, &testDate, plContext));

                PKIX_TEST_EXPECT_NO_ERROR
                        (PKIX_ProcessingParams_SetDate
                        (procParams, testDate, plContext));
        }

        PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetInitialPolicies
                (procParams, initialPolicies, plContext));

        PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetRevocationEnabled
                                    (procParams, isCrlEnabled, plContext));

cleanup:

        if (PKIX_TEST_ERROR_RECEIVED){
                PKIX_TEST_DECREF_AC(procParams);
        }

        PKIX_TEST_DECREF_AC(dateString);
        PKIX_TEST_DECREF_AC(testDate);
        PKIX_TEST_DECREF_AC(anchorsList);
        PKIX_TEST_DECREF_AC(firstAnchor);
        PKIX_TEST_DECREF_AC(secondAnchor);

        PKIX_TEST_RETURN();

        return (procParams);
}
static PKIX_Error *
testDefaultMultipleCertStores(PKIX_ValidateParams *valParams,
                        char *crlDir1,
                        char *crlDir2)
{
        PKIX_PL_String *dirString1 = NULL;
        PKIX_PL_String *dirString2 = NULL;
        PKIX_CertStore *certStore1 = NULL;
        PKIX_CertStore *certStore2 = NULL;
        PKIX_List *certStoreList = NULL;
        PKIX_ProcessingParams *procParams = NULL;

        PKIX_TEST_STD_VARS();

        subTest("PKIX_PL_CollectionCertStore_Create");

        /* Create CollectionCertStore */

        PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create
                                    (PKIX_ESCASCII,
                                    crlDir1,
                                    0,
                                    &dirString1,
                                    plContext));

        PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CollectionCertStore_Create
                                    (dirString1,
                                    &certStore1,
                                    plContext));

        PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create
                                    (PKIX_ESCASCII,
                                    crlDir2,
                                    0,
                                    &dirString2,
                                    plContext));

        PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CollectionCertStore_Create
                                    (dirString2,
                                    &certStore2,
                                    plContext));

        PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateParams_GetProcessingParams
                                    (valParams, &procParams, plContext));

        /* Add multiple CollectionCertStores */

        subTest("PKIX_ProcessingParams_SetCertStores");
        PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&certStoreList, plContext));
        PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
                    (certStoreList, (PKIX_PL_Object *)certStore1, plContext));
        PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetCertStores
                    (procParams, certStoreList, plContext));

        subTest("PKIX_ProcessingParams_AddCertStore");
        PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_AddCertStore
                    (procParams, certStore2, plContext));

        subTest("PKIX_ProcessingParams_SetRevocationEnabled");
        PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetRevocationEnabled
                                    (procParams, PKIX_TRUE, plContext));

cleanup:

        PKIX_TEST_DECREF_AC(dirString1);
        PKIX_TEST_DECREF_AC(dirString2);
        PKIX_TEST_DECREF_AC(certStore1);
        PKIX_TEST_DECREF_AC(certStore2);
        PKIX_TEST_DECREF_AC(certStoreList);
        PKIX_TEST_DECREF_AC(procParams);

        PKIX_TEST_RETURN();

        return (0);
}
/*
 * 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);
}
/*
 * 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_GetCert
 *  (see description of PKIX_CertStore_CertCallback in pkix_certstore.h)
 */
PKIX_Error *
pkix_pl_LdapCertStore_GetCert(
        PKIX_CertStore *store,
        PKIX_CertSelector *selector,
        PKIX_VerifyNode *verifyNode,
        void **pNBIOContext,
        PKIX_List **pCertList,
        void *plContext)
{
        PLArenaPool *requestArena = NULL;
        LDAPRequestParams requestParams;
        void *pollDesc = NULL;
        PKIX_Int32 minPathLen = 0;
        PKIX_Boolean cacheFlag = PKIX_FALSE;
        PKIX_ComCertSelParams *params = NULL;
        PKIX_PL_LdapCertStoreContext *lcs = NULL;
        PKIX_List *responses = NULL;
        PKIX_List *unfilteredCerts = NULL;
        PKIX_List *filteredCerts = NULL;
        PKIX_PL_X500Name *subjectName = 0;

        PKIX_ENTER(CERTSTORE, "pkix_pl_LdapCertStore_GetCert");
        PKIX_NULLCHECK_THREE(store, selector, pCertList);

        requestParams.baseObject = "c=US";
        requestParams.scope = WHOLE_SUBTREE;
        requestParams.derefAliases = NEVER_DEREF;
        requestParams.sizeLimit = 0;
        requestParams.timeLimit = 0;

        /* Prepare elements for request filter */

        /*
         * Get a short-lived arena. We'll be done with this space once
         * the request is encoded.
         */
        requestArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
        if (!requestArena) {
                PKIX_ERROR_FATAL(PKIX_OUTOFMEMORY);
        }

        PKIX_CHECK(PKIX_CertSelector_GetCommonCertSelectorParams
                (selector, &params, plContext),
                PKIX_CERTSELECTORGETCOMCERTSELPARAMSFAILED);

        /*
         * If we have the subject name for the desired subject,
         * ask the server for Certs with that subject.
         */
        PKIX_CHECK(PKIX_ComCertSelParams_GetSubject
                (params, &subjectName, plContext),
                PKIX_COMCERTSELPARAMSGETSUBJECTFAILED);

        PKIX_CHECK(PKIX_ComCertSelParams_GetBasicConstraints
                (params, &minPathLen, plContext),
                PKIX_COMCERTSELPARAMSGETBASICCONSTRAINTSFAILED);

        if (subjectName) {
                PKIX_CHECK(pkix_pl_LdapCertStore_MakeNameAVAList
                        (requestArena,
                        subjectName,
                        &(requestParams.nc),
                        plContext),
                        PKIX_LDAPCERTSTOREMAKENAMEAVALISTFAILED);

                if (*requestParams.nc == NULL) {
                        /*
                         * The subjectName may not include any components
                         * that we know how to encode. We do not return
                         * an error, because the caller did not necessarily
                         * do anything wrong, but we return an empty List.
                         */
                        PKIX_PL_NSSCALL(CERTSTORE, PORT_FreeArena,
                                (requestArena, PR_FALSE));

                        PKIX_CHECK(PKIX_List_Create(&filteredCerts, plContext),
                                PKIX_LISTCREATEFAILED);

                        PKIX_CHECK(PKIX_List_SetImmutable
                                (filteredCerts, plContext),
                                PKIX_LISTSETIMMUTABLEFAILED);

                        *pNBIOContext = NULL;
                        *pCertList = filteredCerts;
                        filteredCerts = NULL;
                        goto cleanup;
                }
        } else {
                PKIX_ERROR(PKIX_INSUFFICIENTCRITERIAFORCERTQUERY);
        }

        /* Prepare attribute field of request */

        requestParams.attributes = 0;

        if (minPathLen < 0) {
                requestParams.attributes |= LDAPATTR_USERCERT;
        }

        if (minPathLen > -2) {
                requestParams.attributes |=
                        LDAPATTR_CACERT | LDAPATTR_CROSSPAIRCERT;
        }

        /* All request fields are done */

        PKIX_CHECK(PKIX_CertStore_GetCertStoreContext
                (store, (PKIX_PL_Object **)&lcs, plContext),
                PKIX_CERTSTOREGETCERTSTORECONTEXTFAILED);

        PKIX_CHECK(PKIX_PL_LdapClient_InitiateRequest
                ((PKIX_PL_LdapClient *)lcs,
                &requestParams,
                &pollDesc,
                &responses,
                plContext),
                PKIX_LDAPCLIENTINITIATEREQUESTFAILED);

        PKIX_CHECK(pkix_pl_LdapCertStore_DestroyAVAList
                (requestParams.nc, plContext),
                PKIX_LDAPCERTSTOREDESTROYAVALISTFAILED);

        if (requestArena) {
                PKIX_PL_NSSCALL(CERTSTORE, PORT_FreeArena,
                        (requestArena, PR_FALSE));
                requestArena = NULL;
        }

        if (pollDesc != NULL) {
                /* client is waiting for non-blocking I/O to complete */
                *pNBIOContext = (void *)pollDesc;
                *pCertList = NULL;
                goto cleanup;
        }
        /* LdapClient has given us a response! */

        if (responses) {
                PKIX_CHECK(PKIX_CertStore_GetCertStoreCacheFlag
                        (store, &cacheFlag, plContext),
                        PKIX_CERTSTOREGETCERTSTORECACHEFLAGFAILED);

                PKIX_CHECK(pkix_pl_LdapCertStore_BuildCertList
                        (responses, &unfilteredCerts, plContext),
                        PKIX_LDAPCERTSTOREBUILDCERTLISTFAILED);

                PKIX_CHECK(pkix_CertSelector_Select
                        (selector, unfilteredCerts, &filteredCerts, plContext),
                        PKIX_CERTSELECTORSELECTFAILED);
        }

        *pNBIOContext = NULL;
        *pCertList = filteredCerts;
        filteredCerts = NULL;

cleanup:

        PKIX_DECREF(params);
        PKIX_DECREF(subjectName);
        PKIX_DECREF(responses);
        PKIX_DECREF(unfilteredCerts);
        PKIX_DECREF(filteredCerts);
        PKIX_DECREF(lcs);

        PKIX_RETURN(CERTSTORE);
}
Exemple #6
0
/*
 * 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);
}
int test_certchainchecker(int argc, char *argv[]) {

        PKIX_UInt32 actualMinorVersion;
        PKIX_PL_OID *bcOID = NULL;
        PKIX_PL_OID *ncOID = NULL;
        PKIX_PL_OID *cpOID = NULL;
        PKIX_PL_OID *pmOID = NULL;
        PKIX_PL_OID *pcOID = NULL;
        PKIX_PL_OID *iaOID = NULL;
        PKIX_CertChainChecker *dummyChecker = NULL;
        PKIX_List *supportedExtensions = NULL;
        PKIX_PL_Object *initialState = NULL;
        PKIX_UInt32 j = 0;

        PKIX_TEST_STD_VARS();

        startTests("CertChainChecker");

        PKIX_TEST_EXPECT_NO_ERROR(
            PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));

        PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create
                (&supportedExtensions, plContext));

        PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create
                (PKIX_BASICCONSTRAINTS_OID, &bcOID, plContext));
        PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
                (supportedExtensions, (PKIX_PL_Object *)bcOID, plContext));

        PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create
                (PKIX_NAMECONSTRAINTS_OID, &ncOID, plContext));
        PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
                (supportedExtensions, (PKIX_PL_Object *)ncOID, plContext));

        PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create
                (PKIX_CERTIFICATEPOLICIES_OID, &cpOID, plContext));
        PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
                (supportedExtensions, (PKIX_PL_Object *)cpOID, plContext));

        PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create
                (PKIX_POLICYMAPPINGS_OID, &pmOID, plContext));
        PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
                (supportedExtensions, (PKIX_PL_Object *)pmOID, plContext));

        PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create
                (PKIX_POLICYCONSTRAINTS_OID, &pcOID, plContext));
        PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
                (supportedExtensions, (PKIX_PL_Object *)pcOID, plContext));

        PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create
                (PKIX_INHIBITANYPOLICY_OID, &iaOID, plContext));
        PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
                (supportedExtensions, (PKIX_PL_Object *)iaOID, plContext));

        PKIX_TEST_DECREF_BC(bcOID);
        PKIX_TEST_DECREF_BC(ncOID);
        PKIX_TEST_DECREF_BC(cpOID);
        PKIX_TEST_DECREF_BC(pmOID);
        PKIX_TEST_DECREF_BC(pcOID);
        PKIX_TEST_DECREF_BC(iaOID);

        PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_IncRef
                ((PKIX_PL_Object *)supportedExtensions, plContext));

        initialState = (PKIX_PL_Object *)supportedExtensions;

        subTest("CertChainChecker_Create");
        PKIX_TEST_EXPECT_NO_ERROR(PKIX_CertChainChecker_Create
                (dummyChecker_Check, /* PKIX_CertChainChecker_CheckCallback */
                PKIX_FALSE,          /* forwardCheckingSupported */
                PKIX_FALSE,          /* forwardDirectionExpected */
                supportedExtensions,
                NULL,                /* PKIX_PL_Object *initialState */
                &dummyChecker,
                plContext));

        PKIX_TEST_EXPECT_NO_ERROR
                (PKIX_CertChainChecker_SetCertChainCheckerState
                (dummyChecker, initialState, plContext));

        test_CertChainChecker_Duplicate(dummyChecker);

        subTest("CertChainChecker_Destroy");
        PKIX_TEST_DECREF_BC(dummyChecker);

cleanup:

        PKIX_TEST_DECREF_AC(dummyChecker);
        PKIX_TEST_DECREF_AC(initialState);
        PKIX_TEST_DECREF_AC(supportedExtensions);

        PKIX_Shutdown(plContext);

        PKIX_TEST_RETURN();

        endTests("CertChainChecker");

        return (0);
}
/*
 * FUNCTION: pkix_DefaultCRLChecker_CheckCRLs
 *
 * DESCRIPTION:
 *  Check validity of "cert" based on CRLs at "crlList" that has correct
 *  signature verification with "publicKey".
 *
 * PARAMETERS
 *  "cert"
 *      Address of Cert which has the certificate data. Must be non-NULL.
 *  "certIssuer"
 *      Address of Issuer that associates with the Cert. Must be non-NULL.
 *  "certSerialNumber"
 *      Address of Serial Number that associates with the Cert. Must be 
 *      non-NULL.
 *  "publicKey"
 *      Address of Public Key that associates with the Cert Issuer.
 *      Must be non-NULL.
 *  "crlList"
 *      A List CRLs that the certificate is verified upon. Must be non-NULL.
 *  "state"
 *      Address of DefaultCRLCheckerState which keeps dynamic state data.
 *      Must be non-NULL.
 *  "pCrlEntryList"
 *      Address of PKIX_PL_CrlEntry List that contains valid CrlEntries for
 *      this Cert. May be 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 CertChainChecker Error if the function fails in a non-fatal way.
 *  Returns a Fatal Error
 */
static PKIX_Error *
pkix_DefaultCRLChecker_CheckCRLs(
        PKIX_PL_Cert *cert,
        PKIX_PL_X500Name *certIssuer,
        PKIX_PL_BigInt *certSerialNumber,
        PKIX_PL_PublicKey *publicKey,
        PKIX_List *crlList,
        pkix_DefaultCRLCheckerState *state,
        PKIX_List **pCrlEntryList,
        void *plContext)
{
        PKIX_PL_CRL *crl = NULL;
        PKIX_PL_CRLEntry *crlEntry = NULL;
        PKIX_PL_PublicKey *pKey = NULL;
        PKIX_List *unresCrlCritExtOIDs = NULL;
        PKIX_List *unresCrlEntryCritExtOIDs = NULL;
        PKIX_List *crlEntryList = NULL;
        PKIX_Error *verifyFail = NULL;
        PKIX_UInt32 numCrls = 0;
        PKIX_UInt32 numKeys = 0;
        PKIX_UInt32 numCritExtOIDs = 0;
        PKIX_Boolean crlVerified = PKIX_FALSE;
        PKIX_Boolean crlRevoking = PKIX_FALSE;
        PKIX_Int32 reasonCode = 0;
        PKIX_UInt32 i;
        PKIX_Int32 j;

        PKIX_ENTER(CERTCHAINCHECKER,
                    "pkix_DefaultCRLChecker_CheckCRLs");
        PKIX_NULLCHECK_FOUR(cert, publicKey, crlList, state);

        PKIX_CHECK(PKIX_List_GetLength(crlList, &numCrls, plContext),
                    PKIX_LISTGETLENGTHFAILED);

        if (state->prevPublicKeyList != NULL) {

                PKIX_CHECK(PKIX_List_GetLength
                    (state->prevPublicKeyList, &numKeys, plContext),
                    PKIX_LISTGETLENGTHFAILED);
        }

        /* Check if Cert is not revoked by any the the CRLs */

        for (i = 0; i < numCrls; i++){

                PKIX_CHECK(PKIX_List_GetItem
                            (crlList, i, (PKIX_PL_Object **)&crl, plContext),
                            PKIX_LISTGETITEMFAILED);

                /*
                 * Checking serial number (issuer done in selector) then
                 * verify signature. If matches, get the CRL reason(s).
                 */

                if (state->prevCertCrlSign == PKIX_TRUE) {
                        verifyFail = PKIX_PL_CRL_VerifySignature
                                (crl, publicKey, plContext);
                        if (verifyFail == NULL) {
                                crlVerified = PKIX_TRUE;
                        } else {
                                crlVerified = PKIX_FALSE;
                                PKIX_DECREF(verifyFail);
                        }
                }

                if (crlVerified == PKIX_FALSE) {

                    /* Verify from old key(s) on the list */
                    for (j = numKeys - 1; j >= 0; j--) {

                            PKIX_CHECK(PKIX_List_GetItem
                                (state->prevPublicKeyList,
                                j,
                                (PKIX_PL_Object **) &pKey,
                                plContext),
                                PKIX_LISTGETITEMFAILED);

                            verifyFail = PKIX_PL_CRL_VerifySignature
                                (crl, pKey, plContext);

                            if (verifyFail == NULL) {
                                crlVerified = PKIX_TRUE;
                                break;
                            } else {
                                crlVerified = PKIX_FALSE;
                                PKIX_DECREF(verifyFail);
                            }

                            PKIX_DECREF(pKey);
                    }
                }

                if (crlVerified == PKIX_FALSE) {
                    /* try next one ... */
                    goto cleanup_loop;
                }

                state->certHasValidCrl = PKIX_TRUE;

                PKIX_CHECK(PKIX_PL_CRL_GetCriticalExtensionOIDs
                            (crl, &unresCrlCritExtOIDs, plContext),
                            PKIX_CRLGETCRITICALEXTENSIONOIDSFAILED);

                /*
                 * XXX Advanced CRL work - should put a
                 * Loop here to process and remove critical
                 * extension oids.
                 */

                if (unresCrlCritExtOIDs) {

                    PKIX_CHECK(PKIX_List_GetLength(unresCrlCritExtOIDs,
                        &numCritExtOIDs,
                        plContext),
                        PKIX_LISTGETLENGTHFAILED);

                    if (numCritExtOIDs != 0) {
                        PKIX_DEFAULTCRLCHECKERSTATE_DEBUG
                                (PKIX_CRLCRITICALEXTENSIONOIDSNOTPROCESSED);
                        /*
                         * Uncomment this after we have implemented
                         * checkers for all the critical extensions.
                         *
                         * PKIX_ERROR
                         *      ("Unrecognized CRL Critical Extension");
                         */
                    }
                }

                PKIX_CHECK(PKIX_PL_CRL_GetCRLEntryForSerialNumber
                            (crl, certSerialNumber, &crlEntry, plContext),
                            PKIX_CRLGETCRLENTRYFORSERIALNUMBERFAILED);

                if (crlEntry == NULL) {
                    goto cleanup_loop;
                }

                crlRevoking = PKIX_TRUE;

                PKIX_CHECK(PKIX_PL_CRLEntry_GetCRLEntryReasonCode
                            (crlEntry,
                            &reasonCode,
                            plContext),
                            PKIX_CRLENTRYGETCRLENTRYREASONCODEFAILED);

                /* This is a valid CRLEntry, return it for caching */
                if (crlEntryList == NULL) {
                    PKIX_CHECK(PKIX_List_Create(&crlEntryList, plContext),
                            PKIX_LISTCREATEFAILED);

                }

                PKIX_CHECK(PKIX_List_AppendItem
                        (crlEntryList, (PKIX_PL_Object *) crlEntry, plContext),
                        PKIX_LISTAPPENDITEMFAILED);

                /* Set reason code in state for advance CRL reviewing */

                if (reasonCode >= 0) {
                    if (reasonCode >= numReasonCodes) 
		        reasonCode = 0;

                    state->reasonCodeMask |= 1 << reasonCode;
                    PKIX_DEFAULTCRLCHECKERSTATE_DEBUG_ARG
                        ("CRL revocation Reason: %s\n ",
                        reasonCodeMsgString[reasonCode]);

                } else {
                    PKIX_DEFAULTCRLCHECKERSTATE_DEBUG
                        ("Revoked by Unknown CRL ReasonCode");
                }

                PKIX_CHECK(PKIX_PL_CRLEntry_GetCriticalExtensionOIDs
                            (crlEntry, &unresCrlEntryCritExtOIDs, plContext),
                            PKIX_CRLENTRYGETCRITICALEXTENSIONOIDSFAILED);
                if (unresCrlEntryCritExtOIDs) {

                    PKIX_CHECK(pkix_List_Remove
                            (unresCrlEntryCritExtOIDs,
                            (PKIX_PL_Object *) state->crlReasonCodeOID,
                            plContext),
                            PKIX_LISTREMOVEFAILED);

                    PKIX_CHECK(PKIX_List_GetLength(unresCrlEntryCritExtOIDs,
                        &numCritExtOIDs,
                        plContext),
                        PKIX_LISTGETLENGTHFAILED);

                    if (numCritExtOIDs != 0) {

                        PKIX_DEFAULTCRLCHECKERSTATE_DEBUG
                            (PKIX_CRLENTRYCRITICALEXTENSIONWASNOTPROCESSED);
                        PKIX_ERROR(PKIX_UNRECOGNIZEDCRLENTRYCRITICALEXTENSION);
                    }
                }

        cleanup_loop:

                PKIX_DECREF(pKey);
                PKIX_DECREF(verifyFail);
                PKIX_DECREF(pKey);
                PKIX_DECREF(crlEntry);
                PKIX_DECREF(crl);
                PKIX_DECREF(unresCrlCritExtOIDs);
                PKIX_DECREF(unresCrlEntryCritExtOIDs);
        }

        *pCrlEntryList = crlEntryList;

        if (crlRevoking == PKIX_TRUE) {

                PKIX_ERROR(PKIX_CERTIFICATEREVOKEDBYCRL);
        }

cleanup:

        PKIX_DECREF(pKey);
        PKIX_DECREF(verifyFail);
        PKIX_DECREF(crlEntry);
        PKIX_DECREF(crl);
        PKIX_DECREF(unresCrlCritExtOIDs);
        PKIX_DECREF(unresCrlEntryCritExtOIDs);

        PKIX_RETURN(CERTCHAINCHECKER);
}
/*
 * FUNCTION: pkix_DefaultCRLChecker_Check
 *
 * 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.
 *  "unresolvedCriticalExtensions"
 *      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
 */
static PKIX_Error *
pkix_DefaultCRLChecker_Check(
        PKIX_CertChainChecker *checker,
        PKIX_PL_Cert *cert,
        PKIX_List *unresolvedCriticalExtensions,
        void **pNBIOContext,
        void *plContext)
{
        pkix_DefaultCRLCheckerState *state = NULL;
        PKIX_PL_PublicKey *publicKey = NULL;
        PKIX_PL_PublicKey *newPublicKey = NULL;
        PKIX_Error *checkKeyUsageFail = NULL;
        PKIX_Boolean selfIssued = PKIX_FALSE;
        void *nbioContext = NULL;

        PKIX_ENTER(CERTCHAINCHECKER, "pkix_DefaultCRLChecker_Check");
        PKIX_NULLCHECK_THREE(checker, cert, pNBIOContext);

        nbioContext = *pNBIOContext;
        *pNBIOContext = NULL; /* prepare for Error exit */

        PKIX_CHECK(PKIX_CertChainChecker_GetCertChainCheckerState
                    (checker, (PKIX_PL_Object **)&state, plContext),
                    PKIX_CERTCHAINCHECKERGETCERTCHAINCHECKERSTATEFAILED);

        PKIX_CHECK(PKIX_PL_Cert_GetSubjectPublicKey
                    (cert, &publicKey, plContext),
                    PKIX_CERTGETSUBJECTPUBLICKEYFAILED);

        /*
         * If we already have a selector, we were in the middle of checking
         * when a certStore returned with non-blocking I/O pendning.
         */
        if ((state->crlSelector) == NULL) {
                state->certsRemaining--;

                PKIX_NULLCHECK_ONE(state->prevPublicKey);

                if (state->prevCertCrlSign == PKIX_FALSE) {
                        PKIX_ERROR
                                (PKIX_KEYUSAGEKEYCRLSIGNBITNOTON);
                }

                /* Set up CRLSelector */
                PKIX_CHECK(pkix_DefaultCRLChecker_Check_SetSelector
                        (cert, state, plContext),
                        PKIX_DEFAULTCRLCHECKERCHECKSETSELECTORFAILED);

        }

        PKIX_CHECK(pkix_DefaultCRLChecker_Check_Helper
                    (checker,
                    cert,
                    state->prevPublicKey,
                    state,
                    unresolvedCriticalExtensions,
                    PKIX_FALSE,
                    &nbioContext,
                    plContext),
                    PKIX_DEFAULTCRLCHECKERCHECKHELPERFAILED);

        if (nbioContext != NULL) {
                *pNBIOContext = nbioContext;
                goto cleanup;
        }

        PKIX_DECREF(state->crlSelector);

        /*
         * Some NIST test case in 4.5.* use different publicKeys for
         * Cert and its CRL on the chain. Self-issued Certs are used
         * to speciy multiple keys for those cases. That is why we apply
         * the following algorithm:
         *
         * Check if Cert is self-issued. If so, the public key of the Cert
         * that issues this Cert (old key) can be used together with this
         * current key (new key) for key verification. If there are multiple
         * self-issued certs, keys of those Certs (old keys) can also be used
         * for key verification. Old key(s) is saved in a list (PrevPublickKey-
         * List) and cleared when a Cert is no longer self-issued.
         * PrevPublicKey keep key of the previous Cert.
         * PrevPublicKeyList keep key(s) of Cert before the previous one.
         */
        PKIX_CHECK(pkix_IsCertSelfIssued(cert, &selfIssued, plContext),
                    PKIX_ISCERTSELFISSUEFAILED);

        if (selfIssued == PKIX_TRUE) {

                if (state->prevPublicKeyList == NULL) {

                        PKIX_CHECK(PKIX_List_Create
                            (&state->prevPublicKeyList, plContext),
                            PKIX_LISTCREATEFAILED);

                }

                PKIX_CHECK(PKIX_List_AppendItem
                            (state->prevPublicKeyList,
                            (PKIX_PL_Object *) state->prevPublicKey,
                            plContext),
                            PKIX_LISTAPPENDITEMFAILED);

        } else {
                /* Not self-issued Cert any more, clear old key(s) saved */
                PKIX_DECREF(state->prevPublicKeyList);
        }

        /* Make inheritance and save current Public Key */
        PKIX_CHECK(PKIX_PL_PublicKey_MakeInheritedDSAPublicKey
                    (publicKey, state->prevPublicKey, &newPublicKey, plContext),
                    PKIX_PUBLICKEYMAKEINHERITEDDSAPUBLICKEYFAILED);

        if (newPublicKey == NULL){
                PKIX_INCREF(publicKey);
                newPublicKey = publicKey;
        }

        PKIX_DECREF(state->prevPublicKey);
        PKIX_INCREF(newPublicKey);
        state->prevPublicKey = newPublicKey;

        /* Save current Cert's crlSign bit for CRL checking later */
        if (state->certsRemaining != 0) {
                checkKeyUsageFail = PKIX_PL_Cert_VerifyKeyUsage
                        (cert, PKIX_CRL_SIGN, plContext);

                state->prevCertCrlSign = (checkKeyUsageFail == NULL)?
                        PKIX_TRUE : PKIX_FALSE;

                PKIX_DECREF(checkKeyUsageFail);
        }

/*
        PKIX_CHECK(PKIX_CertChainChecker_SetCertChainCheckerState
                (checker, (PKIX_PL_Object *)state, plContext),
                PKIX_CERTCHAINCHECKERSETCERTCHAINCHECKERSTATEFAILED);
 */

cleanup:

        PKIX_DECREF(state);
        PKIX_DECREF(publicKey);
        PKIX_DECREF(newPublicKey);
        PKIX_DECREF(checkKeyUsageFail);

        PKIX_RETURN(CERTCHAINCHECKER);
}
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_RevocationChecker_CreateAndAddMethod
 */
PKIX_Error *
PKIX_RevocationChecker_CreateAndAddMethod(
    PKIX_RevocationChecker *revChecker,
    PKIX_ProcessingParams *params,
    PKIX_RevocationMethodType methodType,
    PKIX_UInt32 flags,
    PKIX_UInt32 priority,
    PKIX_PL_VerifyCallback verificationFn,
    PKIX_Boolean isLeafMethod,
    void *plContext)
{
    PKIX_List **methodList = NULL;
    PKIX_List  *unsortedList = NULL;
    PKIX_List  *certStores = NULL;
    pkix_RevocationMethod *method = NULL;
    pkix_LocalRevocationCheckFn *localRevChecker = NULL;
    pkix_ExternalRevocationCheckFn *externRevChecker = NULL;
    PKIX_UInt32 miFlags;
    
    PKIX_ENTER(REVOCATIONCHECKER, "PKIX_RevocationChecker_CreateAndAddMethod");
    PKIX_NULLCHECK_ONE(revChecker);

    /* If the caller has said "Either one is sufficient, then don't let the 
     * absence of any one method's info lead to an overall failure.
     */
    miFlags = isLeafMethod ? revChecker->leafMethodListFlags 
	                   : revChecker->chainMethodListFlags;
    if (miFlags & PKIX_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE)
	flags &= ~PKIX_REV_M_FAIL_ON_MISSING_FRESH_INFO;

    switch (methodType) {
    case PKIX_RevocationMethod_CRL:
        localRevChecker = pkix_CrlChecker_CheckLocal;
        externRevChecker = pkix_CrlChecker_CheckExternal;
        PKIX_CHECK(
            PKIX_ProcessingParams_GetCertStores(params, &certStores,
                                                plContext),
            PKIX_PROCESSINGPARAMSGETCERTSTORESFAILED);
        PKIX_CHECK(
            pkix_CrlChecker_Create(methodType, flags, priority,
                                   localRevChecker, externRevChecker,
                                   certStores, verificationFn,
                                   &method,
                                   plContext),
            PKIX_COULDNOTCREATECRLCHECKEROBJECT);
        break;
    case PKIX_RevocationMethod_OCSP:
        localRevChecker = pkix_OcspChecker_CheckLocal;
        externRevChecker = pkix_OcspChecker_CheckExternal;
        PKIX_CHECK(
            pkix_OcspChecker_Create(methodType, flags, priority,
                                    localRevChecker, externRevChecker,
                                    verificationFn,
                                    &method,
                                    plContext),
            PKIX_COULDNOTCREATEOCSPCHECKEROBJECT);
        break;
    default:
        PKIX_ERROR(PKIX_INVALIDREVOCATIONMETHOD);
    }

    if (isLeafMethod) {
        methodList = &revChecker->leafMethodList;
    } else {
        methodList = &revChecker->chainMethodList;
    }
    
    if (*methodList == NULL) {
        PKIX_CHECK(
            PKIX_List_Create(methodList, plContext),
            PKIX_LISTCREATEFAILED);
    }
    unsortedList = *methodList;
    PKIX_CHECK(
        PKIX_List_AppendItem(unsortedList, (PKIX_PL_Object*)method, plContext),
        PKIX_LISTAPPENDITEMFAILED);
    PKIX_CHECK(
        pkix_List_BubbleSort(unsortedList, 
                             pkix_RevocationChecker_SortComparator,
                             methodList, plContext),
        PKIX_LISTBUBBLESORTFAILED);

cleanup:
    PKIX_DECREF(method);
    PKIX_DECREF(unsortedList);
    PKIX_DECREF(certStores);
    
    PKIX_RETURN(REVOCATIONCHECKER);
}
Exemple #12
0
int
test_list2(int argc, char *argv[])
{

    PKIX_List *list;
    char *temp;
    PKIX_UInt32 i = 0;
    PKIX_UInt32 j = 0;
    PKIX_Int32 cmpResult;
    PKIX_PL_OID *testOID;
    PKIX_PL_String *testString;
    PKIX_PL_Object *obj, *obj2;
    PKIX_UInt32 size = 10;
    char *testOIDString[10] = {
        "2.9.999.1.20",
        "1.2.3.4.5.6.7",
        "0.1",
        "1.2.3.5",
        "0.39",
        "1.2.3.4.7",
        "1.2.3.4.6",
        "0.39.1",
        "1.2.3.4.5",
        "0.39.1.300"
    };
    PKIX_UInt32 actualMinorVersion;

    PKIX_TEST_STD_VARS();

    startTests("List Sorting");

    PKIX_TEST_EXPECT_NO_ERROR(
        PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));

    subTest("Creating Unsorted Lists");
    PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&list, plContext));
    for (i = 0; i < size; i++) {
        /* Create a new OID object */
        PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create(
            testOIDString[i],
            &testOID,
            plContext));
        /* Insert it into the list */
        PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(list, (PKIX_PL_Object *)testOID, plContext));
        /* Decref the string object */
        PKIX_TEST_DECREF_BC(testOID);
    }

    subTest("Outputting Unsorted List");

    PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)list,
                                                      &testString,
                                                      plContext));
    temp = PKIX_String2ASCII(testString, plContext);
    if (temp) {
        (void)printf("%s \n", temp);
        PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
    }
    PKIX_TEST_DECREF_BC(testString);

    subTest("Performing Bubble Sort");

    for (i = 0; i < size; i++)
        for (j = 9; j > i; j--) {
            PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(list, j, &obj, plContext));
            PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem(list, j -
                                                                  1,
                                                        &obj2, plContext));

            PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_Compare(obj, obj2, &cmpResult, plContext));
            if (cmpResult < 0) {
                /* Exchange the items */
                PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_SetItem(list, j, obj2, plContext));
                PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_SetItem(list, j -
                                                                      1,
                                                            obj, plContext));
            }
            /* DecRef objects */
            PKIX_TEST_DECREF_BC(obj);
            PKIX_TEST_DECREF_BC(obj2);
        }

    subTest("Outputting Sorted List");
    PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString((PKIX_PL_Object *)list,
                                                      &testString,
                                                      plContext));
    temp = PKIX_String2ASCII(testString, plContext);
    if (temp) {
        (void)printf("%s \n", temp);
        PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(temp, plContext));
    }

cleanup:

    PKIX_TEST_DECREF_AC(testString);
    PKIX_TEST_DECREF_AC(list);

    PKIX_Shutdown(plContext);

    PKIX_TEST_RETURN();

    endTests("List Sorting");

    return (0);
}
static PKIX_Error *
testDefaultCertStore(PKIX_ValidateParams *valParams, char *crlDir)
{
        PKIX_PL_String *dirString = NULL;
        PKIX_CertStore *certStore = NULL;
        PKIX_ProcessingParams *procParams = NULL;
        PKIX_PL_Date *validity = NULL; 
        PKIX_List *revCheckers = NULL;
        PKIX_RevocationChecker *ocspChecker = NULL;

        PKIX_TEST_STD_VARS();

        subTest("PKIX_PL_CollectionCertStoreContext_Create");

        /* Create CollectionCertStore */

        PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create
                (PKIX_ESCASCII, crlDir, 0, &dirString, plContext));

        PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CollectionCertStore_Create
                (dirString, &certStore, plContext));

        /* Create CertStore */

        PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateParams_GetProcessingParams
                (valParams, &procParams, plContext));

        subTest("PKIX_ProcessingParams_AddCertStore");
        PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_AddCertStore
                (procParams, certStore, plContext));

        subTest("PKIX_ProcessingParams_SetRevocationEnabled");

        PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetRevocationEnabled
                (procParams, PKIX_TRUE, plContext));

        /* create current Date */
        PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_Date_CreateFromPRTime
                (PR_Now(), &validity, plContext));

        PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&revCheckers, plContext));

        /* create revChecker */
        PKIX_TEST_EXPECT_NO_ERROR(PKIX_OcspChecker_Initialize
                (validity,
                NULL,        /* pwArg */
                NULL,        /* Use default responder */
                &ocspChecker,
                plContext));

        PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
                (revCheckers, (PKIX_PL_Object *)ocspChecker, plContext));

        PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetRevocationCheckers
                (procParams, revCheckers, plContext));

cleanup:

        PKIX_TEST_DECREF_AC(dirString);
        PKIX_TEST_DECREF_AC(procParams);
        PKIX_TEST_DECREF_AC(certStore);
        PKIX_TEST_DECREF_AC(revCheckers);
        PKIX_TEST_DECREF_AC(ocspChecker);

        PKIX_TEST_RETURN();

        return (0);
}
int test_validatechain(int argc, char *argv[]){

        PKIX_ValidateParams *valParams = NULL;
        PKIX_ValidateResult *valResult = NULL;
        PKIX_UInt32 actualMinorVersion;
        PKIX_UInt32 j = 0;
        PKIX_UInt32 k = 0;
        PKIX_UInt32 chainLength = 0;
        PKIX_Boolean testValid = PKIX_TRUE;
        PKIX_List *chainCerts = NULL;
        PKIX_PL_Cert *dirCert = NULL;
	PKIX_VerifyNode *verifyTree = NULL;
	PKIX_PL_String *verifyString = NULL;
        char *dirCertName = NULL;
        char *anchorCertName = NULL;
        char *dirName = NULL;

        PKIX_TEST_STD_VARS();

        if (argc < 5) {
                printUsage();
                return (0);
        }

        startTests("ValidateChain");

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

        subTest(argv[1+j]);

        dirName = argv[3+j];

        chainLength = argc - j - 5;

        PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&chainCerts, plContext));

        for (k = 0; k < chainLength; k++) {

                dirCert = createCert(dirName, argv[5+k+j], plContext);

                PKIX_TEST_EXPECT_NO_ERROR
                        (PKIX_List_AppendItem
                        (chainCerts, (PKIX_PL_Object *)dirCert, plContext));

                PKIX_TEST_DECREF_BC(dirCert);
        }

        valParams = createValidateParams
                (dirName,
                argv[4+j],
                NULL,
                NULL,
                NULL,
                PKIX_FALSE,
                PKIX_FALSE,
                PKIX_FALSE,
                PKIX_FALSE,
                chainCerts,
                plContext);

        testDefaultCertStore(valParams, dirName);

        if (testValid == PKIX_TRUE) {
                PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateChain
                        (valParams, &valResult, &verifyTree, plContext));
        } else {
                PKIX_TEST_EXPECT_ERROR(PKIX_ValidateChain
                        (valParams, &valResult, &verifyTree, plContext));
        }

        subTest("Displaying VerifyNode objects");

        PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString
                ((PKIX_PL_Object*)verifyTree, &verifyString, plContext));
        (void) printf("verifyTree is\n%s\n", verifyString->escAsciiString);

cleanup:
        PKIX_TEST_DECREF_AC(verifyString);
        PKIX_TEST_DECREF_AC(verifyTree);

        PKIX_TEST_DECREF_AC(chainCerts);
        PKIX_TEST_DECREF_AC(valParams);
        PKIX_TEST_DECREF_AC(valResult);

        PKIX_Shutdown(plContext);

        PKIX_TEST_RETURN();

        endTests("ValidateChain");

        return (0);
}
/*
 * 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);
}
int test_validatechain_NB(int argc, char *argv[]){

        PKIX_ValidateParams *valParams = NULL;
        PKIX_ValidateResult *valResult = NULL;
        PKIX_UInt32 actualMinorVersion;
        PKIX_UInt32 j = 0;
        PKIX_UInt32 k = 0;
        PKIX_UInt32 chainLength = 0;
        PKIX_Boolean testValid = PKIX_TRUE;
        PKIX_List *chainCerts = NULL;
        PKIX_PL_Cert *dirCert = NULL;
        char *dirCertName = NULL;
        char *anchorCertName = NULL;
        char *dirName = NULL;
        PKIX_UInt32 certIndex = 0;
        PKIX_UInt32 anchorIndex = 0;
        PKIX_UInt32 checkerIndex = 0;
        PKIX_Boolean revChecking = PKIX_FALSE;
        PKIX_List *checkers = NULL;
        PRPollDesc *pollDesc = NULL;
        PRErrorCode errorCode = 0;
        PKIX_PL_Socket *socket = NULL;
        char *ldapName = NULL;
	PKIX_VerifyNode *verifyTree = NULL;
	PKIX_PL_String *verifyString = NULL;

        PKIX_List *loggers = NULL;
        PKIX_Logger *logger = NULL;
        char *logging = NULL;
        PKIX_PL_String *component = NULL;

        PKIX_TEST_STD_VARS();

        if (argc < 5) {
                printUsage();
                return (0);
        }

        startTests("ValidateChain_NB");

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

        subTest(argv[1+j]);

        dirName = argv[3+j];

        chainLength = argc - j - 5;

        PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&chainCerts, plContext));

        for (k = 0; k < chainLength; k++){

                dirCert = createCert(dirName, argv[5+k+j], plContext);

                PKIX_TEST_EXPECT_NO_ERROR
                        (PKIX_List_AppendItem
                        (chainCerts, (PKIX_PL_Object *)dirCert, plContext));

                PKIX_TEST_DECREF_BC(dirCert);
        }

        valParams = createValidateParams
                (dirName,
                argv[4+j],
                NULL,
                NULL,
                NULL,
                PKIX_FALSE,
                PKIX_FALSE,
                PKIX_FALSE,
                PKIX_FALSE,
                chainCerts,
                plContext);

        ldapName = PR_GetEnv("LDAP");
        /* Is LDAP set in the environment? */
        if ((ldapName == NULL) || (*ldapName == '\0')) {
                testError("LDAP not set in environment");
                goto cleanup;
        }

        pkixTestErrorResult = pkix_pl_Socket_CreateByName
                (PKIX_FALSE,       /* isServer */
                PR_SecondsToInterval(30), /* try 30 secs for connect */
                ldapName,
                &errorCode,
                &socket,
                plContext);

        if (pkixTestErrorResult != NULL) {
                PKIX_PL_Object_DecRef
                        ((PKIX_PL_Object *)pkixTestErrorResult, plContext);
                pkixTestErrorResult = NULL;
                testError("Unable to connect to LDAP Server");
                goto cleanup;
        }

        PKIX_TEST_DECREF_BC(socket);

        testSetupCertStore(valParams, ldapName);

        logging = PR_GetEnv("LOGGING");
        /* Is LOGGING set in the environment? */
        if ((logging != NULL) && (*logging != '\0')) {

                PKIX_TEST_EXPECT_NO_ERROR
                        (PKIX_List_Create(&loggers, plContext));

		testLogErrors
			(PKIX_VALIDATE_ERROR, 2, loggers, plContext);
		testLogErrors
			(PKIX_CERTCHAINCHECKER_ERROR, 2, loggers, plContext);
		testLogErrors
			(PKIX_LDAPDEFAULTCLIENT_ERROR, 2, loggers, plContext);
		testLogErrors
			(PKIX_CERTSTORE_ERROR, 2, loggers, plContext);

                PKIX_TEST_EXPECT_NO_ERROR(PKIX_SetLoggers(loggers, plContext));

        }

        pkixTestErrorResult = PKIX_ValidateChain_NB
                (valParams,
                &certIndex,
                &anchorIndex,
                &checkerIndex,
                &revChecking,
                &checkers,
                (void **)&pollDesc,
                &valResult,
		&verifyTree,
                plContext);

        while (pollDesc != NULL) {

                if (PR_Poll(pollDesc, 1, 0) < 0) {
                        testError("PR_Poll failed");
                }

                pkixTestErrorResult = PKIX_ValidateChain_NB
                        (valParams,
                        &certIndex,
                        &anchorIndex,
                        &checkerIndex,
                        &revChecking,
                        &checkers,
                        (void **)&pollDesc,
                        &valResult,
			&verifyTree,
                        plContext);
        }

        if (pkixTestErrorResult) {
                if (testValid == PKIX_FALSE) { /* EE */
                        (void) printf("EXPECTED ERROR RECEIVED!\n");
                } else { /* ENE */
                        testError("UNEXPECTED ERROR RECEIVED");
                }
                PKIX_TEST_DECREF_BC(pkixTestErrorResult);
        } else {

	        if (testValid == PKIX_TRUE) { /* ENE */
        	        (void) printf("EXPECTED NON-ERROR RECEIVED!\n");
	        } else { /* EE */
        	        (void) printf("UNEXPECTED NON-ERROR RECEIVED!\n");
	        }
        }

cleanup:

	if (verifyTree) {
	        PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString
        	    ((PKIX_PL_Object*)verifyTree, &verifyString, plContext));
	        (void) printf("verifyTree is\n%s\n",
		    verifyString->escAsciiString);
	}

        PKIX_TEST_DECREF_AC(verifyString);
        PKIX_TEST_DECREF_AC(verifyTree);
        PKIX_TEST_DECREF_AC(checkers);
        PKIX_TEST_DECREF_AC(chainCerts);
        PKIX_TEST_DECREF_AC(valParams);
        PKIX_TEST_DECREF_AC(valResult);

        PKIX_Shutdown(plContext);

        PKIX_TEST_RETURN();

        endTests("ValidateChain_NB");

        return (0);
}
int
validate_chain(int argc, char *argv[])
{
    PKIX_TrustAnchor *anchor = NULL;
    PKIX_List *anchors = NULL;
    PKIX_List *certs = NULL;
    PKIX_ProcessingParams *procParams = NULL;
    PKIX_ValidateParams *valParams = NULL;
    PKIX_ValidateResult *valResult = NULL;
    PKIX_PL_X500Name *subject = NULL;
    PKIX_ComCertSelParams *certSelParams = NULL;
    PKIX_CertSelector *certSelector = NULL;
    PKIX_VerifyNode *verifyTree = NULL;
    PKIX_PL_String *verifyString = NULL;

    char *trustedCertFile = NULL;
    char *chainCertFile = NULL;
    PKIX_PL_Cert *trustedCert = NULL;
    PKIX_PL_Cert *chainCert = NULL;
    PKIX_UInt32 chainLength = 0;
    PKIX_UInt32 i = 0;
    PKIX_UInt32 j = 0;
    PKIX_UInt32 actualMinorVersion;

    PKIX_TEST_STD_VARS();

    if (argc < 3) {
        printUsage();
        return (0);
    }

    PKIX_TEST_EXPECT_NO_ERROR(
        PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));

    chainLength = (argc - j) - 2;

    /* create processing params with list of trust anchors */
    trustedCertFile = argv[1 + j];
    trustedCert = createCert(trustedCertFile);

    PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetSubject(trustedCert, &subject, plContext));

    PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_Create(&certSelParams, plContext));

#if 0
        PKIX_TEST_EXPECT_NO_ERROR(PKIX_ComCertSelParams_SetSubject
                                    (certSelParams, subject, plContext));
#endif

    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_DECREF_BC(subject);
    PKIX_TEST_DECREF_BC(certSelParams);

    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));

    PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetTargetCertConstraints(procParams, certSelector, plContext));

    PKIX_TEST_DECREF_BC(certSelector);

    /* create cert chain */
    PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&certs, plContext));
    for (i = 0; i < chainLength; i++) {
        chainCertFile = argv[(i + j) + 2];
        chainCert = createCert(chainCertFile);

        PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem(certs,
                                                       (PKIX_PL_Object *)chainCert,
                                                       plContext));

        PKIX_TEST_DECREF_BC(chainCert);
        chainCert = NULL;
    }
    /* create validate params with processing params and cert chain */
    PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateParams_Create(procParams, certs, &valParams, plContext));

    PKIX_TEST_DECREF_BC(trustedCert);
    trustedCert = NULL;
    PKIX_TEST_DECREF_BC(anchor);
    anchor = NULL;
    PKIX_TEST_DECREF_BC(anchors);
    anchors = NULL;
    PKIX_TEST_DECREF_BC(certs);
    certs = NULL;
    PKIX_TEST_DECREF_BC(procParams);
    procParams = NULL;

    /* validate cert chain using processing params and return valResult */

    PKIX_TEST_EXPECT_NO_ERROR(PKIX_ValidateChain(valParams, &valResult, &verifyTree, plContext));

    if (valResult != NULL) {
        (void)printf("SUCCESSFULLY VALIDATED\n");
    }

cleanup:

    if (PKIX_TEST_ERROR_RECEIVED) {
        (void)printf("FAILED TO VALIDATE\n");
        (void)PKIX_PL_Object_ToString((PKIX_PL_Object *)verifyTree, &verifyString, plContext);
        (void)printf("verifyTree is\n%s\n", verifyString->escAsciiString);
        PKIX_TEST_DECREF_AC(verifyString);
    }

    PKIX_TEST_DECREF_AC(verifyTree);
    PKIX_TEST_DECREF_AC(valResult);
    PKIX_TEST_DECREF_AC(valParams);

    PKIX_TEST_RETURN();

    PKIX_Shutdown(plContext);

    return (0);
}
Exemple #19
0
/*
 * 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);
}
int test_policynode(int argc, char *argv[]) {

        /*
         * Create a tree with parent = anyPolicy,
         * child1 with Nist1+Nist2, child2 with Nist1.
         * Give each child another child, with policies Nist2
         * and Nist1, respectively. Pruning with a depth of two
         * should have no effect. Give one of the children
         * another child. Then pruning with a depth of three
         * should reduce the tree to a single strand, as child1
         * and child3 are removed.
         *
         *              parent (anyPolicy)
         *          /                   \
         *      child1(Nist1+Nist2)     child2(Nist1)
         *          |                       |
         *      child3(Nist2)           child4(Nist1)
         *                                  |
         *                              child5(Nist1)
         *
         */
        char *asciiAnyPolicy = "2.5.29.32.0";
        PKIX_PL_Cert *cert = NULL;
        PKIX_PL_CertPolicyInfo *nist1Policy = NULL;
        PKIX_PL_CertPolicyInfo *nist2Policy = NULL;
        PKIX_List *policyQualifierList = NULL;
        PKIX_PL_OID *oidAnyPolicy = NULL;
        PKIX_PL_OID *oidNist1Policy = NULL;
        PKIX_PL_OID *oidNist2Policy = NULL;
        PKIX_List *expectedAnyList = NULL;
        PKIX_List *expectedNist1List = NULL;
        PKIX_List *expectedNist2List = NULL;
        PKIX_List *expectedNist1Nist2List = NULL;
        PKIX_List *emptyList = NULL;
        PKIX_PolicyNode *parentNode = NULL;
        PKIX_PolicyNode *childNode1 = NULL;
        PKIX_PolicyNode *childNode2 = NULL;
        PKIX_PolicyNode *childNode3 = NULL;
        PKIX_PolicyNode *childNode4 = NULL;
        PKIX_PolicyNode *childNode5 = NULL;
        PKIX_PL_String *parentString = NULL;
        PKIX_Boolean pDelete = PKIX_FALSE;
        char *expectedParentAscii =
                "{2.16.840.1.101.3.2.1.48.2,(1.3.6.1.5.5.7.2.2:[30 5C "
                "1A 5A 71 31 3A 20 20 54 68 69 73 20 69 73 20 74 68 65"
                " 20 75 73 65 72 20 6E 6F 74 69 63 65 20 66 72 6F 6D 2"
                "0 71 75 61 6C 69 66 69 65 72 20 31 2E 20 20 54 68 69 "
                "73 20 63 65 72 74 69 66 69 63 61 74 65 20 69 73 20 66"
                " 6F 72 20 74 65 73 74 20 70 75 72 70 6F 73 65 73 20 6"
                "F 6E 6C 79]),Critical,(2.16.840.1.101.3.2.1.48.1[(1.3"
                ".6.1.5.5.7.2.2:[30 5C 1A 5A 71 31 3A 20 20 54 68 69 7"
                "3 20 69 73 20 74 68 65 20 75 73 65 72 20 6E 6F 74 69 "
                "63 65 20 66 72 6F 6D 20 71 75 61 6C 69 66 69 65 72 20"
                " 31 2E 20 20 54 68 69 73 20 63 65 72 74 69 66 69 63 6"
                "1 74 65 20 69 73 20 66 6F 72 20 74 65 73 74 20 70 75 "
                "72 70 6F 73 65 73 20 6F 6E 6C 79])], 2.16.840.1.101.3"
                ".2.1.48.2[(1.3.6.1.5.5.7.2.2:[30 5A 1A 58 71 32 3A 20"
                " 20 54 68 69 73 20 69 73 20 74 68 65 20 75 73 65 72 2"
                "0 6E 6F 74 69 63 65 20 66 72 6F 6D 20 71 75 61 6C 69 "
                "66 69 65 72 20 32 2E 20 20 54 68 69 73 20 75 73 65 72"
                " 20 6E 6F 74 69 63 65 20 73 68 6F 75 6C 64 20 6E 6F 7"
                "4 20 62 65 20 64 69 73 70 6C 61 79 65 64])]),1}\n"
                ". {2.16.840.1.101.3.2.1.48.2,(1.3.6.1.5.5.7.2.2:[30 5"
                "C 1A 5A 71 31 3A 20 20 54 68 69 73 20 69 73 20 74 68 "
                "65 20 75 73 65 72 20 6E 6F 74 69 63 65 20 66 72 6F 6D"
                " 20 71 75 61 6C 69 66 69 65 72 20 31 2E 20 20 54 68 6"
                "9 73 20 63 65 72 74 69 66 69 63 61 74 65 20 69 73 20 "
                "66 6F 72 20 74 65 73 74 20 70 75 72 70 6F 73 65 73 20"
                " 6F 6E 6C 79]),Critical,(2.16.840.1.101.3.2.1.48.2),2}";
        char *expectedValidAscii =
                "2.16.840.1.101.3.2.1.48.2";
        char *expectedQualifiersAscii =
                /* "(1.3.6.1.5.5.7.2.2)"; */
                "(1.3.6.1.5.5.7.2.2:[30 5C 1A 5A 71 31 3A 20 20 54 68 "
                "69 73 20 69 73 20 74 68 65 20 75 73 65 72 20 6E 6F 74"
                " 69 63 65 20 66 72 6F 6D 20 71 75 61 6C 69 66 69 65 7"
                "2 20 31 2E 20 20 54 68 69 73 20 63 65 72 74 69 66 69 "
                "63 61 74 65 20 69 73 20 66 6F 72 20 74 65 73 74 20 70"
                " 75 72 70 6F 73 65 73 20 6F 6E 6C 79])";
        char *expectedPoliciesAscii =
                "(2.16.840.1.101.3.2.1.48.1)";
        char *expectedTree =
                "{2.5.29.32.0,{},Critical,(2.5.29.32.0),0}\n"
                ". {2.16.840.1.101.3.2.1.48.2,(1.3.6.1.5.5.7.2.2:[30 5"
                "C 1A 5A 71 31 3A 20 20 54 68 69 73 20 69 73 20 74 68 "
                "65 20 75 73 65 72 20 6E 6F 74 69 63 65 20 66 72 6F 6D"
                " 20 71 75 61 6C 69 66 69 65 72 20 31 2E 20 20 54 68 6"
                "9 73 20 63 65 72 74 69 66 69 63 61 74 65 20 69 73 20 "
                "66 6F 72 20 74 65 73 74 20 70 75 72 70 6F 73 65 73 20"
                " 6F 6E 6C 79]),Critical,(2.16.840.1.101.3.2.1.48.1[(1"
                ".3.6.1.5.5.7.2.2:[30 5C 1A 5A 71 31 3A 20 20 54 68 69"
                " 73 20 69 73 20 74 68 65 20 75 73 65 72 20 6E 6F 74 6"
                "9 63 65 20 66 72 6F 6D 20 71 75 61 6C 69 66 69 65 72 "
                "20 31 2E 20 20 54 68 69 73 20 63 65 72 74 69 66 69 63"
                " 61 74 65 20 69 73 20 66 6F 72 20 74 65 73 74 20 70 7"
                "5 72 70 6F 73 65 73 20 6F 6E 6C 79])], 2.16.840.1.101"
                ".3.2.1.48.2[(1.3.6.1.5.5.7.2.2:[30 5A 1A 58 71 32 3A "
                "20 20 54 68 69 73 20 69 73 20 74 68 65 20 75 73 65 72"
                " 20 6E 6F 74 69 63 65 20 66 72 6F 6D 20 71 75 61 6C 6"
                "9 66 69 65 72 20 32 2E 20 20 54 68 69 73 20 75 73 65 "
                "72 20 6E 6F 74 69 63 65 20 73 68 6F 75 6C 64 20 6E 6F"
                " 74 20 62 65 20 64 69 73 70 6C 61 79 65 64])]"
                "),1}\n"
                ". . {2.16.840.1.101.3.2.1.48.2,(1.3.6.1.5.5.7.2.2:[30"
                " 5C 1A 5A 71 31 3A 20 20 54 68 69 73 20 69 73 20 74 6"
                "8 65 20 75 73 65 72 20 6E 6F 74 69 63 65 20 66 72 6F "
                "6D 20 71 75 61 6C 69 66 69 65 72 20 31 2E 20 20 54 68"
                " 69 73 20 63 65 72 74 69 66 69 63 61 74 65 20 69 73 2"
                "0 66 6F 72 20 74 65 73 74 20 70 75 72 70 6F 73 65 73 "
                "20 6F 6E 6C 79]),Critical,(2.16.840.1.101.3.2.1.48.2)"
                ",2}\n"
                ". {2.16.840.1.101.3.2.1.48.1,(1.3.6.1.5.5.7.2.2:[30 5"
                "C 1A 5A 71 31 3A 20 20 54 68 69 73 20 69 73 20 74 68 "
                "65 20 75 73 65 72 20 6E 6F 74 69 63 65 20 66 72 6F 6D"
                " 20 71 75 61 6C 69 66 69 65 72 20 31 2E 20 20 54 68 6"
                "9 73 20 63 65 72 74 69 66 69 63 61 74 65 20 69 73 20 "
                "66 6F 72 20 74 65 73 74 20 70 75 72 70 6F 73 65 73 20"
                " 6F 6E 6C 79]),Critical,(2.16.840.1.101.3.2.1.48.1),1}\n"
                ". . {2.16.840.1.101.3.2.1.48.1,(EMPTY),Not Critical,"
                "(2.16.840.1.101.3.2.1.48.1),2}\n"
                ". . . {2.16.840.1.101.3.2.1.48.1,{},Critical,(2.16.84"
                "0.1.101.3.2.1.48.1),3}";
        char *expectedPrunedTree =
                "{2.5.29.32.0,{},Critical,(2.5.29.32.0),0}\n"
                ". {2.16.840.1.101.3.2.1.48.1,(1.3.6.1.5.5.7.2.2:[30 5"
                "C 1A 5A 71 31 3A 20 20 54 68 69 73 20 69 73 20 74 68 "
                "65 20 75 73 65 72 20 6E 6F 74 69 63 65 20 66 72 6F 6D"
                " 20 71 75 61 6C 69 66 69 65 72 20 31 2E 20 20 54 68 6"
                "9 73 20 63 65 72 74 69 66 69 63 61 74 65 20 69 73 20 "
                "66 6F 72 20 74 65 73 74 20 70 75 72 70 6F 73 65 73 20"
                " 6F 6E 6C 79]),Critical,(2.16.840.1.101.3.2.1.48.1),1}\n"
                ". . {2.16.840.1.101.3.2.1.48.1,(EMPTY),Not Critical,"
                "(2.16.840.1.101.3.2.1.48.1),2}\n"
                ". . . {2.16.840.1.101.3.2.1.48.1,{},Critical,(2.16.84"
                "0.1.101.3.2.1.48.1),3}";

        PKIX_UInt32 actualMinorVersion;
        PKIX_UInt32 j = 0;
        char *dirName = NULL;

        PKIX_TEST_STD_VARS();

        if (argc < 2) {
                printUsage();
                return (0);
        }

        startTests("PolicyNode");

        PKIX_TEST_EXPECT_NO_ERROR(
            PKIX_PL_NssContext_Create(0, PKIX_FALSE, NULL, &plContext));

        dirName = argv[j+1];

        subTest("Creating OID objects");
        PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_OID_Create
                (asciiAnyPolicy, &oidAnyPolicy, plContext));

        /* Read certificates to get real policies, qualifiers */

        cert = createCert
                (dirName, "UserNoticeQualifierTest16EE.crt", plContext);

        PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Cert_GetPolicyInformation
                (cert, &expectedNist1Nist2List, plContext));
        PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem
                (expectedNist1Nist2List,
                0,
                (PKIX_PL_Object **)&nist1Policy,
                plContext));
        PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_GetItem
                (expectedNist1Nist2List,
                1,
                (PKIX_PL_Object **)&nist2Policy,
                plContext));

        PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CertPolicyInfo_GetPolQualifiers
                (nist1Policy, &policyQualifierList, plContext));

        PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CertPolicyInfo_GetPolicyId
                (nist1Policy, &oidNist1Policy, plContext));

        PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CertPolicyInfo_GetPolicyId
                (nist2Policy, &oidNist2Policy, plContext));

        subTest("Creating expectedPolicy List objects");

        PKIX_TEST_EXPECT_NO_ERROR
                (PKIX_List_Create(&expectedAnyList, plContext));

        PKIX_TEST_EXPECT_NO_ERROR
                (PKIX_List_Create(&expectedNist1List, plContext));

        PKIX_TEST_EXPECT_NO_ERROR
                (PKIX_List_Create(&expectedNist2List, plContext));


        subTest("Populating expectedPolicy List objects");

        PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
                (expectedAnyList, (PKIX_PL_Object *)oidAnyPolicy, plContext));

        PKIX_TEST_EXPECT_NO_ERROR
                (PKIX_List_AppendItem
                (expectedNist1List,
                (PKIX_PL_Object *)oidNist1Policy,
                plContext));

        PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_AppendItem
                                    (expectedNist2List,
                                    (PKIX_PL_Object *)oidNist2Policy,
                                    plContext));

        subTest("Creating PolicyNode objects");

        PKIX_TEST_EXPECT_NO_ERROR(PKIX_List_Create(&emptyList, plContext));

        PKIX_TEST_EXPECT_NO_ERROR(pkix_PolicyNode_Create
                (oidAnyPolicy,
                NULL,
                PKIX_TRUE,
                expectedAnyList,
                &parentNode,
                plContext));

        PKIX_TEST_EXPECT_NO_ERROR(pkix_PolicyNode_Create
                (oidNist2Policy,
                policyQualifierList,
                PKIX_TRUE,
                expectedNist1Nist2List,
                &childNode1,
                plContext));

        PKIX_TEST_EXPECT_NO_ERROR(pkix_PolicyNode_Create
                (oidNist1Policy,
                policyQualifierList,
                PKIX_TRUE,
                expectedNist1List,
                &childNode2,
                plContext));

        PKIX_TEST_EXPECT_NO_ERROR(pkix_PolicyNode_Create
                (oidNist2Policy,
                policyQualifierList,
                PKIX_TRUE,
                expectedNist2List,
                &childNode3,
                plContext));

        PKIX_TEST_EXPECT_NO_ERROR(pkix_PolicyNode_Create
                (oidNist1Policy,
                emptyList,
                PKIX_FALSE,
                expectedNist1List,
                &childNode4,
                plContext));

        PKIX_TEST_EXPECT_NO_ERROR(pkix_PolicyNode_Create
                (oidNist1Policy,
                NULL,
                PKIX_TRUE,
                expectedNist1List,
                &childNode5,
                plContext));

        subTest("Creating the PolicyNode tree");

        PKIX_TEST_EXPECT_NO_ERROR(pkix_PolicyNode_AddToParent
                (parentNode, childNode1, plContext));
        PKIX_TEST_EXPECT_NO_ERROR(pkix_PolicyNode_AddToParent
                (parentNode, childNode2, plContext));

        PKIX_TEST_EXPECT_NO_ERROR(pkix_PolicyNode_AddToParent
                (childNode1, childNode3, plContext));

        PKIX_TEST_EXPECT_NO_ERROR(pkix_PolicyNode_AddToParent
                (childNode2, childNode4, plContext));

        PKIX_TEST_EXPECT_NO_ERROR(pkix_PolicyNode_AddToParent
                (childNode4, childNode5, plContext));

        subTest("Displaying PolicyNode objects");

        PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_Object_ToString
                ((PKIX_PL_Object*)parentNode, &parentString, plContext));
        (void) printf("parentNode is\n\t%s\n", parentString->escAsciiString);

        testToStringHelper
                ((PKIX_PL_Object*)parentNode, expectedTree, plContext);

        test_DuplicateHelper(parentNode, plContext);

        test_GetParent(childNode3, childNode3, childNode4, expectedParentAscii);
        test_GetValidPolicy
                (childNode1, childNode3, parentNode, expectedValidAscii);
        test_GetPolicyQualifiers
                (childNode1, childNode3, childNode4, expectedQualifiersAscii);
        test_GetExpectedPolicies
                (childNode2, childNode4, childNode3, expectedPoliciesAscii);
        test_IsCritical(childNode1, childNode2, childNode4);
        test_GetDepth(childNode2, childNode4, childNode5);

        subTest("pkix_PolicyNode_Prune");

        PKIX_TEST_EXPECT_NO_ERROR(pkix_PolicyNode_Prune
                (parentNode, 2, &pDelete, plContext));

        testToStringHelper
                ((PKIX_PL_Object*)parentNode, expectedTree, plContext);

        PKIX_TEST_EXPECT_NO_ERROR(pkix_PolicyNode_Prune
                (parentNode, 3, &pDelete, plContext));

        testToStringHelper
                ((PKIX_PL_Object*)parentNode, expectedPrunedTree, plContext);

        test_GetChildren(parentNode, parentNode, childNode2);

cleanup:

        PKIX_TEST_DECREF_AC(cert);
        PKIX_TEST_DECREF_AC(nist1Policy);
        PKIX_TEST_DECREF_AC(nist2Policy);
        PKIX_TEST_DECREF_AC(policyQualifierList);
        PKIX_TEST_DECREF_AC(oidAnyPolicy);
        PKIX_TEST_DECREF_AC(oidNist1Policy);
        PKIX_TEST_DECREF_AC(oidNist2Policy);
        PKIX_TEST_DECREF_AC(expectedAnyList);
        PKIX_TEST_DECREF_AC(expectedNist1List);
        PKIX_TEST_DECREF_AC(expectedNist2List);
        PKIX_TEST_DECREF_AC(expectedNist1Nist2List);
        PKIX_TEST_DECREF_AC(emptyList);
        PKIX_TEST_DECREF_AC(parentNode);
        PKIX_TEST_DECREF_AC(childNode1);
        PKIX_TEST_DECREF_AC(childNode2);
        PKIX_TEST_DECREF_AC(childNode3);
        PKIX_TEST_DECREF_AC(childNode4);
        PKIX_TEST_DECREF_AC(childNode5);
        PKIX_TEST_DECREF_AC(parentString);

        PKIX_Shutdown(plContext);

        PKIX_TEST_RETURN();

        endTests("PolicyNode");

        return (0);
}
int
test_buildchain_resourcelimits(int argc, char *argv[])
{
    PKIX_ComCertSelParams *certSelParams = NULL;
    PKIX_CertSelector *certSelector = NULL;
    PKIX_TrustAnchor *anchor = NULL;
    PKIX_List *anchors = NULL;
    PKIX_ProcessingParams *procParams = NULL;
    PKIX_CertChainChecker *checker = NULL;
    PKIX_ResourceLimits *resourceLimits = NULL;
    char *dirName = NULL;
    PKIX_PL_String *dirNameString = NULL;
    PKIX_PL_Cert *trustedCert = NULL;
    PKIX_PL_Cert *targetCert = NULL;
    PKIX_PL_Cert *dirCert = NULL;
    PKIX_UInt32 actualMinorVersion = 0;
    PKIX_UInt32 j = 0;
    PKIX_UInt32 k = 0;
    PKIX_CertStore *ldapCertStore = NULL;
    PRIntervalTime timeout = 0; /* 0 for non-blocking */
    PKIX_CertStore *certStore = NULL;
    PKIX_List *certStores = NULL;
    PKIX_List *expectedCerts = NULL;
    PKIX_Boolean testValid = PKIX_FALSE;
    PKIX_Boolean usebind = PKIX_FALSE;
    PKIX_Boolean useLDAP = PKIX_FALSE;

    PKIX_TEST_STD_VARS();

    if (argc < 5) {
        printUsage();
        return (0);
    }

    startTests("BuildChain_ResourceLimits");

    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];
    }

    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 < argc; k++) {

        dirCert = createCert(dirName, argv[k], plContext);

        if (k == (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_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));

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

    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));

    /* set resource limits */

    PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_Create(&resourceLimits, plContext));

    /* need longer time when running dbx for memory leak checking */
    PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxTime(resourceLimits, 60, plContext));

    PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxFanout(resourceLimits, 2, plContext));

    PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxDepth(resourceLimits, 2, plContext));

    PKIX_TEST_EXPECT_NO_ERROR(PKIX_ProcessingParams_SetResourceLimits(procParams, resourceLimits, plContext));

    /* build cert chain using processing params and return buildResult */

    subTest("Testing ResourceLimits MaxFanout & MaxDepth - <pass>");
    Test_BuildResult(procParams,
                     testValid,
                     expectedCerts,
                     plContext);

    PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxFanout(resourceLimits, 1, plContext));

    subTest("Testing ResourceLimits MaxFanout - <fail>");
    Test_BuildResult(procParams,
                     PKIX_FALSE,
                     expectedCerts,
                     plContext);

    PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxFanout(resourceLimits, 2, plContext));
    PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxDepth(resourceLimits, 1, plContext));

    subTest("Testing ResourceLimits MaxDepth - <fail>");
    Test_BuildResult(procParams,
                     PKIX_FALSE,
                     expectedCerts,
                     plContext);

    PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxFanout(resourceLimits, 0, plContext));
    PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxDepth(resourceLimits, 0, plContext));
    PKIX_TEST_EXPECT_NO_ERROR(PKIX_ResourceLimits_SetMaxTime(resourceLimits, 0, plContext));

    subTest("Testing ResourceLimits No checking - <pass>");
    Test_BuildResult(procParams,
                     testValid,
                     expectedCerts,
                     plContext);

cleanup:

    PKIX_TEST_DECREF_AC(expectedCerts);
    PKIX_TEST_DECREF_AC(procParams);
    PKIX_TEST_DECREF_AC(procParams);
    PKIX_TEST_DECREF_AC(certStores);
    PKIX_TEST_DECREF_AC(certStore);
    PKIX_TEST_DECREF_AC(ldapCertStore);
    PKIX_TEST_DECREF_AC(dirNameString);
    PKIX_TEST_DECREF_AC(trustedCert);
    PKIX_TEST_DECREF_AC(targetCert);
    PKIX_TEST_DECREF_AC(anchors);
    PKIX_TEST_DECREF_AC(anchor);
    PKIX_TEST_DECREF_AC(certSelParams);
    PKIX_TEST_DECREF_AC(certSelector);
    PKIX_TEST_DECREF_AC(checker);
    PKIX_TEST_DECREF_AC(resourceLimits);

    PKIX_TEST_RETURN();

    PKIX_Shutdown(plContext);

    endTests("BuildChain_UserChecker");

    return (0);
}
Exemple #22
0
int
build_chain(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;
    char *trustedCertFile = NULL;
    char *targetCertFile = NULL;
    char *storeDirAscii = NULL;
    PKIX_PL_String *storeDirString = NULL;
    PKIX_PL_Cert *trustedCert = NULL;
    PKIX_PL_Cert *targetCert = NULL;
    PKIX_UInt32 actualMinorVersion, numCerts, i;
    PKIX_UInt32 j = 0;
    PKIX_CertStore *certStore = NULL;
    PKIX_List *certStores = NULL;
    char *asciiResult = NULL;
    PKIX_Boolean useArenas = PKIX_FALSE;
    void *buildState = NULL; /* needed by pkix_build for non-blocking I/O */
    void *nbioContext = NULL;

    PKIX_TEST_STD_VARS();

    if (argc < 4) {
        printUsage();
        return (0);
    }

    useArenas = PKIX_TEST_ARENAS_ARG(argv[1]);

    PKIX_TEST_EXPECT_NO_ERROR(PKIX_Initialize(PKIX_TRUE, /* nssInitNeeded */
                                              useArenas,
                                              PKIX_MAJOR_VERSION,
                                              PKIX_MINOR_VERSION,
                                              PKIX_MINOR_VERSION,
                                              &actualMinorVersion,
                                              &plContext));

    /* create processing params with list of trust anchors */
    trustedCertFile = argv[j + 1];
    trustedCert = createCert(trustedCertFile);

    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));

    targetCertFile = argv[j + 2];
    targetCert = createCert(targetCertFile);

    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 */

    storeDirAscii = argv[j + 3];

    PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_String_Create(PKIX_ESCASCII, storeDirAscii, 0, &storeDirString, plContext));

    PKIX_TEST_EXPECT_NO_ERROR(PKIX_PL_CollectionCertStore_Create(storeDirString, &certStore, plContext));
    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 */

    PKIX_TEST_EXPECT_NO_ERROR(PKIX_BuildChain(procParams,
                                              &nbioContext,
                                              &buildState,
                                              &buildResult,
                                              NULL,
                                              plContext));

    /*
         * As long as we use only CertStores with blocking I/O, we can omit
         * checking for completion with nbioContext.
         */

    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_TEST_EXPECT_NO_ERROR(PKIX_PL_Free(asciiResult, plContext));
        asciiResult = NULL;

        PKIX_TEST_DECREF_BC(cert);
    }

cleanup:

    if (PKIX_TEST_ERROR_RECEIVED) {
        (void)printf("FAILED TO BUILD CHAIN\n");
    } else {
        (void)printf("SUCCESSFULLY BUILT CHAIN\n");
    }

    PKIX_PL_Free(asciiResult, plContext);

    PKIX_TEST_DECREF_AC(certs);
    PKIX_TEST_DECREF_AC(cert);
    PKIX_TEST_DECREF_AC(certStore);
    PKIX_TEST_DECREF_AC(certStores);
    PKIX_TEST_DECREF_AC(storeDirString);
    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_RETURN();

    PKIX_Shutdown(plContext);

    return (0);
}
/*
 * 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_Logger_GetLoggers (see comments in pkix_util.h)
 */
PKIX_Error *
PKIX_GetLoggers(
        PKIX_List **pLoggers,  /* list of PKIX_Logger */
        void *plContext)
{
        PKIX_List *list = NULL;
        PKIX_List *savedPkixLoggersDebugTrace = NULL;
        PKIX_List *savedPkixLoggersErrors = NULL;
        PKIX_Logger *logger = NULL;
        PKIX_Logger *dupLogger = NULL;
        PKIX_UInt32 i, length;
        PKIX_Boolean locked = PKIX_FALSE;

        PKIX_ENTER(LOGGER, "PKIX_Logger_GetLoggers");
        PKIX_NULLCHECK_ONE(pLoggers);

        PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext),
                PKIX_MONITORLOCKENTERFAILED);
        locked = PKIX_TRUE;

        /*
         * Temporarily disable DEBUG/TRACE Logging to avoid possible
         * deadlock:
         * When the Logger List is being accessed, e.g. by PKIX_ENTER or
         * PKIX_DECREF, pkix_Logger_Check may check whether logging
         * is requested, creating a deadlock situation.
         */
        savedPkixLoggersDebugTrace = pkixLoggersDebugTrace;
        pkixLoggersDebugTrace = NULL;
        savedPkixLoggersErrors = pkixLoggersErrors;
        pkixLoggersErrors = NULL;

        if (pkixLoggers == NULL) {
                length = 0;
        } else {
                PKIX_CHECK(PKIX_List_GetLength
                    (pkixLoggers, &length, plContext),
                    PKIX_LISTGETLENGTHFAILED);
        }

        /* Create a list and copy the pkixLoggers item to the list */
        PKIX_CHECK(PKIX_List_Create(&list, plContext),
                    PKIX_LISTCREATEFAILED);

        for (i = 0; i < length; i++) {

            PKIX_CHECK(PKIX_List_GetItem
                        (pkixLoggers,
                        i,
                        (PKIX_PL_Object **) &logger,
                        plContext),
                        PKIX_LISTGETITEMFAILED);

            PKIX_CHECK(pkix_Logger_Duplicate
                        ((PKIX_PL_Object *)logger,
                        (PKIX_PL_Object **)&dupLogger,
                        plContext),
                        PKIX_LOGGERDUPLICATEFAILED);

            PKIX_CHECK(PKIX_List_AppendItem
                        (list,
                        (PKIX_PL_Object *) dupLogger,
                        plContext),
                        PKIX_LISTAPPENDITEMFAILED);

            PKIX_DECREF(logger);
            PKIX_DECREF(dupLogger);
        }

        /* Set the list to be immutable */
        PKIX_CHECK(PKIX_List_SetImmutable(list, plContext),
                        PKIX_LISTSETIMMUTABLEFAILED);

        *pLoggers = list;

cleanup:

        PKIX_DECREF(logger);

        /* Restore logging capability */
        pkixLoggersDebugTrace = savedPkixLoggersDebugTrace;
        pkixLoggersErrors = savedPkixLoggersErrors;

        if (locked) {
                PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext),
                        PKIX_MONITORLOCKEXITFAILED);
        }

        PKIX_RETURN(LOGGER);
}
/*
 * 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;
        PLArenaPool *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, &params, plContext),
                PKIX_CRLSELECTORGETCOMCERTSELPARAMSFAILED);

        PKIX_CHECK(PKIX_ComCRLSelParams_GetIssuerNames
                (params, &issuerNames, plContext),
                PKIX_COMCRLSELPARAMSGETISSUERNAMESFAILED);

        /*
         * The specification for PKIX_ComCRLSelParams_GetIssuerNames in
         * pkix_crlsel.h says that if the criterion is not set we get a null
         * pointer. If we get an empty List the criterion is impossible to
         * meet ("must match at least one of the names in the List").
         */
        if (issuerNames) {

                PKIX_CHECK(PKIX_List_GetLength
                        (issuerNames, &numNames, plContext),
                        PKIX_LISTGETLENGTHFAILED);

                if (numNames > 0) {
                        for (thisName = 0; thisName < numNames; thisName++) {
                                PKIX_CHECK(PKIX_List_GetItem
                                (issuerNames,
                                thisName,
                                (PKIX_PL_Object **)&issuer,
                                plContext),
                                PKIX_LISTGETITEMFAILED);

                                PKIX_CHECK
                                        (pkix_pl_LdapCertStore_MakeNameAVAList
                                        (requestArena,
                                        issuer,
                                        &(requestParams.nc),
                                        plContext),
                                        PKIX_LDAPCERTSTOREMAKENAMEAVALISTFAILED);

                                PKIX_DECREF(issuer);

                                if (*requestParams.nc == NULL) {
                                        /*
                                         * The issuer may not include any
                                         * components that we know how to
                                         * encode. We do not return an error,
                                         * because the caller did not
                                         * necessarily do anything wrong, but
                                         * we return an empty List.
                                         */
                                        PKIX_PL_NSSCALL
                                                (CERTSTORE, PORT_FreeArena,
                                                (requestArena, PR_FALSE));

                                        PKIX_CHECK(PKIX_List_Create
                                                (&filteredCRLs, plContext),
                                                PKIX_LISTCREATEFAILED);

                                        PKIX_CHECK(PKIX_List_SetImmutable
                                                (filteredCRLs, plContext),
                                               PKIX_LISTSETIMMUTABLEFAILED);

                                        *pNBIOContext = NULL;
                                        *pCrlList = filteredCRLs;
                                        goto cleanup;
                                }

                                /*
                                 * LDAP Servers don't seem to be able to handle
                                 * requests with more than more than one name.
                                 */
                                break;
                        }
                } else {
                        PKIX_ERROR(PKIX_IMPOSSIBLECRITERIONFORCRLQUERY);
                }
        } else {
                PKIX_ERROR(PKIX_IMPOSSIBLECRITERIONFORCRLQUERY);
        }

        /* All request fields are done */

        PKIX_CHECK(PKIX_CertStore_GetCertStoreContext
                (store, (PKIX_PL_Object **)&lcs, plContext),
                PKIX_CERTSTOREGETCERTSTORECONTEXTFAILED);

        PKIX_CHECK(PKIX_PL_LdapClient_InitiateRequest
                ((PKIX_PL_LdapClient *)lcs,
                &requestParams,
                &pollDesc,
                &responses,
                plContext),
                PKIX_LDAPCLIENTINITIATEREQUESTFAILED);

        PKIX_CHECK(pkix_pl_LdapCertStore_DestroyAVAList
                (requestParams.nc, plContext),
                PKIX_LDAPCERTSTOREDESTROYAVALISTFAILED);

        if (requestArena) {
                PKIX_PL_NSSCALL(CERTSTORE, PORT_FreeArena,
                        (requestArena, PR_FALSE));
        }

        if (pollDesc != NULL) {
                /* client is waiting for non-blocking I/O to complete */
                *pNBIOContext = (void *)pollDesc;
                *pCrlList = NULL;
                goto cleanup;
        }
        /* client has finished! */

        if (responses) {

                /*
                 * We have a List of LdapResponse objects that still have to be
                 * turned into Crls.
                 */
                PKIX_CHECK(pkix_pl_LdapCertStore_BuildCrlList
                        (responses, &unfilteredCRLs, plContext),
                        PKIX_LDAPCERTSTOREBUILDCRLLISTFAILED);

                PKIX_CHECK(pkix_CRLSelector_Select
                        (selector, unfilteredCRLs, &filteredCRLs, plContext),
                        PKIX_CRLSELECTORSELECTFAILED);

        }

        /* Don't throw away the list if one CRL was bad! */
        pkixTempErrorReceived = PKIX_FALSE;

        *pNBIOContext = NULL;
        *pCrlList = filteredCRLs;

cleanup:

        if (PKIX_ERROR_RECEIVED) {
                PKIX_DECREF(filteredCRLs);
        }

        PKIX_DECREF(params);
        PKIX_DECREF(issuerNames);
        PKIX_DECREF(issuer);
        PKIX_DECREF(candidate);
        PKIX_DECREF(responses);
        PKIX_DECREF(unfilteredCRLs);
        PKIX_DECREF(lcs);

        PKIX_RETURN(CERTSTORE);
}
/*
 * FUNCTION: PKIX_Logger_SetLoggers (see comments in pkix_util.h)
 */
PKIX_Error *
PKIX_SetLoggers(
        PKIX_List *loggers,  /* list of PKIX_Logger */
        void *plContext)
{
        PKIX_List *list = NULL;
        PKIX_List *savedPkixLoggersErrors = NULL;
        PKIX_List *savedPkixLoggersDebugTrace = NULL;
        PKIX_Logger *logger = NULL;
        PKIX_Logger *dupLogger = NULL;
        PKIX_Boolean locked = PKIX_FALSE;
        PKIX_UInt32 i, length;

        PKIX_ENTER(LOGGER, "PKIX_SetLoggers");

        PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext),
                PKIX_MONITORLOCKENTERFAILED);
        locked = PKIX_TRUE;

        /* Disable tracing, etc. to avoid recursion and deadlock */
        savedPkixLoggersDebugTrace = pkixLoggersDebugTrace;
        pkixLoggersDebugTrace = NULL;
        savedPkixLoggersErrors = pkixLoggersErrors;
        pkixLoggersErrors = NULL;

        /* discard any prior loggers */
        PKIX_DECREF(pkixLoggers);
        PKIX_DECREF(savedPkixLoggersErrors);
        PKIX_DECREF(savedPkixLoggersDebugTrace);

        if (loggers != NULL) {

                PKIX_CHECK(PKIX_List_Create(&list, plContext),
                    PKIX_LISTCREATEFAILED);

                PKIX_CHECK(PKIX_List_GetLength(loggers, &length, plContext),
                    PKIX_LISTGETLENGTHFAILED);

                for (i = 0; i < length; i++) {

                    PKIX_CHECK(PKIX_List_GetItem
                        (loggers,
                        i,
                        (PKIX_PL_Object **) &logger,
                        plContext),
                        PKIX_LISTGETITEMFAILED);

                    PKIX_CHECK(pkix_Logger_Duplicate
                        ((PKIX_PL_Object *)logger,
                        (PKIX_PL_Object **)&dupLogger,
                        plContext),
                        PKIX_LOGGERDUPLICATEFAILED);

                    PKIX_CHECK(PKIX_List_AppendItem
                        (list,
                        (PKIX_PL_Object *) dupLogger,
                        plContext),
                        PKIX_LISTAPPENDITEMFAILED);

                    /* Make two lists */

                    /* Put in pkixLoggersErrors in any case*/

                    if (savedPkixLoggersErrors == NULL) {

                        PKIX_CHECK(PKIX_List_Create
                                (&savedPkixLoggersErrors,
                                plContext),
                                PKIX_LISTCREATEFAILED);
                    }
        
                    PKIX_CHECK(PKIX_List_AppendItem
                            (savedPkixLoggersErrors,
                            (PKIX_PL_Object *) dupLogger,
                            plContext),
                            PKIX_LISTAPPENDITEMFAILED);

                    if (logger->maxLevel > PKIX_LOGGER_LEVEL_WARNING) {

                        /* Put in pkixLoggersDebugTrace */

                        if (savedPkixLoggersDebugTrace == NULL) {

                            PKIX_CHECK(PKIX_List_Create
                                    (&savedPkixLoggersDebugTrace,
                                    plContext),
                                    PKIX_LISTCREATEFAILED);
                        }
        
                        PKIX_CHECK(PKIX_List_AppendItem
                                (savedPkixLoggersDebugTrace,
                                (PKIX_PL_Object *) dupLogger,
                                plContext),
                                PKIX_LISTAPPENDITEMFAILED);
                    }
                    PKIX_DECREF(logger);
                    PKIX_DECREF(dupLogger);

                }

                pkixLoggers = list;
        }

cleanup:

        if (PKIX_ERROR_RECEIVED){
                PKIX_DECREF(list);
                PKIX_DECREF(savedPkixLoggersErrors);
                PKIX_DECREF(savedPkixLoggersDebugTrace);
                pkixLoggers = NULL;
        }

        PKIX_DECREF(logger);

        /* Reenable logging capability with new lists */
        pkixLoggersErrors = savedPkixLoggersErrors;
        pkixLoggersDebugTrace = savedPkixLoggersDebugTrace;

        if (locked) {
                PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext),
                        PKIX_MONITORLOCKEXITFAILED);
        }

        PKIX_RETURN(LOGGER);
}
/*
 * FUNCTION: pkix_pl_CollectionCertStoreContext_PopulateCRL
 * DESCRIPTION:
 *
 *  Create list of CRLs from *.crl files at directory specified in dirName,
 *  Not recursive to sub-dirctory. Also assume the directory contents are
 *  not changed dynamically.
 *
 * PARAMETERS
 *  "colCertStoreContext" - Address of CollectionCertStoreContext
 *              where the dirName is specified and where the return
 *              CRLs are stored as a list. Must be non-NULL.
 *  "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_PopulateCRL(
        PKIX_PL_CollectionCertStoreContext *colCertStoreContext,
        void *plContext)
{
        PKIX_List *crlList = NULL;
        PKIX_PL_CRL *crlItem = NULL;
        char *dirName = NULL;
        char *pathName = NULL;
        PKIX_UInt32 dirNameLen = 0;
        PRErrorCode prError = 0;
        PRDir *dir = NULL;
        PRDirEntry *dirEntry = NULL;

        PKIX_ENTER(COLLECTIONCERTSTORECONTEXT,
                    "pkix_pl_CollectionCertStoreContext_PopulateCRL");
        PKIX_NULLCHECK_ONE(colCertStoreContext);

        /* convert directory to ascii */

        PKIX_CHECK(PKIX_PL_String_GetEncoded
                    (colCertStoreContext->storeDir,
                    PKIX_ESCASCII,
                    (void **)&dirName,
                    &dirNameLen,
                    plContext),
                    PKIX_STRINGGETENCODEDFAILED);

        /* create CRL list, if no CRL file, should return an empty list */

        PKIX_CHECK(PKIX_List_Create(&crlList, plContext),
                    PKIX_LISTCREATEFAILED);

        /* open directory and read in .crl files */

        PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG("\t\t Calling PR_OpenDir.\n");
        dir = PR_OpenDir(dirName);

        if (!dir) {
                PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG_ARG
                        ("\t\t Directory Name:%s\n", dirName);
                PKIX_ERROR(PKIX_CANNOTOPENCOLLECTIONCERTSTORECONTEXTDIRECTORY);
        }

        PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG("\t\t Calling PR_ReadDir.\n");
        dirEntry = PR_ReadDir(dir, PR_SKIP_HIDDEN | PR_SKIP_BOTH);

        if (!dirEntry) {
                PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG
                        ("\t\t Empty directory.\n");
                PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG
                        ("\t\t Calling PR_GetError.\n");
                prError = PR_GetError();
        }

        PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG("\t\t Calling PR_SetError.\n");
        PR_SetError(0, 0);

        while (dirEntry != NULL && prError == 0) {
                if (PL_strrstr(dirEntry->name, ".crl") ==
                    dirEntry->name + PL_strlen(dirEntry->name) - 4) {

                        PKIX_CHECK_ONLY_FATAL
                                (PKIX_PL_Malloc
                                (dirNameLen + PL_strlen(dirEntry->name) + 2,
                                (void **)&pathName,
                                plContext),
                                PKIX_MALLOCFAILED);

                        if ((!PKIX_ERROR_RECEIVED) && (pathName != NULL)){

                                PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG
                                    ("\t\t Calling PL_strcpy for dirName.\n");
                                PL_strcpy(pathName, dirName);
                                PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG
                                    ("\t\t Calling PL_strcat for dirName.\n");
                                PL_strcat(pathName, "/");
                                PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG
                                        ("\t\t Calling PL_strcat for /.\n");
                                PL_strcat(pathName, dirEntry->name);

                        PKIX_CHECK_ONLY_FATAL
                                (pkix_pl_CollectionCertStoreContext_CreateCRL
                                (pathName, &crlItem, plContext),
                                PKIX_COLLECTIONCERTSTORECONTEXTCREATECRLFAILED);

                                if (!PKIX_ERROR_RECEIVED){
                                        PKIX_CHECK_ONLY_FATAL
                                                (PKIX_List_AppendItem
                                                (crlList,
                                                (PKIX_PL_Object *)crlItem,
                                                plContext),
                                                PKIX_LISTAPPENDITEMFAILED);
                                }
                        }

                        PKIX_DECREF(crlItem);
                        PKIX_FREE(pathName);
                }

                PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG
                        ("\t\t Calling PR_SetError.\n");
                PR_SetError(0, 0);

                PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG
                        ("\t\t Calling PR_ReadDir.\n");
                dirEntry = PR_ReadDir(dir, PR_SKIP_HIDDEN | PR_SKIP_BOTH);

                if (!dirEntry) {
                    PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG
                        ("\t\t Calling PR_GetError.\n");
                    prError = PR_GetError();
                }
        }

        if ((prError != 0) && (prError != PR_NO_MORE_FILES_ERROR)) {
                PKIX_ERROR(PKIX_COLLECTIONCERTSTORECONTEXTGETSELECTCRLFAILED);
        }

        PKIX_CHECK(PKIX_List_SetImmutable(crlList, plContext),
                    PKIX_LISTSETIMMUTABLEFAILED);

        PKIX_INCREF(crlList);
        colCertStoreContext->crlList = crlList;

cleanup:
        if (dir) {
                PKIX_COLLECTIONCERTSTORECONTEXT_DEBUG
                        ("\t\t Calling PR_CloseDir.\n");
                PR_CloseDir(dir);
        }

        PKIX_FREE(pathName);
        PKIX_FREE(dirName);

        if (PKIX_ERROR_RECEIVED){
                PKIX_DECREF(crlList);
        }

        PKIX_DECREF(crlItem);
        PKIX_DECREF(crlList);

        PKIX_RETURN(COLLECTIONCERTSTORECONTEXT);
}
/*
 * FUNCTION: PKIX_Logger_AddLogger (see comments in pkix_util.h)
 */
PKIX_Error *
PKIX_AddLogger(
        PKIX_Logger *logger,
        void *plContext)
{
        PKIX_Logger *dupLogger = NULL;
        PKIX_Logger *addLogger = NULL;
        PKIX_List *savedPkixLoggersErrors = NULL;
        PKIX_List *savedPkixLoggersDebugTrace = NULL;
        PKIX_Boolean locked = PKIX_FALSE;
        PKIX_UInt32 i, length;

        PKIX_ENTER(LOGGER, "PKIX_Logger_AddLogger");
        PKIX_NULLCHECK_ONE(logger);

        PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext),
                PKIX_MONITORLOCKENTERFAILED);
        locked = PKIX_TRUE;

        savedPkixLoggersDebugTrace = pkixLoggersDebugTrace;
        pkixLoggersDebugTrace = NULL;
        savedPkixLoggersErrors = pkixLoggersErrors;
        pkixLoggersErrors = NULL;

        PKIX_DECREF(savedPkixLoggersErrors);
        PKIX_DECREF(savedPkixLoggersDebugTrace);

        if (pkixLoggers == NULL) {

            PKIX_CHECK(PKIX_List_Create(&pkixLoggers, plContext),
                    PKIX_LISTCREATEFAILED);
        }

        PKIX_CHECK(pkix_Logger_Duplicate
                    ((PKIX_PL_Object *)logger,
                    (PKIX_PL_Object **)&dupLogger,
                    plContext),
                    PKIX_LOGGERDUPLICATEFAILED);

        PKIX_CHECK(PKIX_List_AppendItem
                    (pkixLoggers,
                    (PKIX_PL_Object *) dupLogger,
                    plContext),
                    PKIX_LISTAPPENDITEMFAILED);

        PKIX_CHECK(PKIX_List_GetLength(pkixLoggers, &length, plContext),
                    PKIX_LISTGETLENGTHFAILED);

        /* Reconstruct pkixLoggersErrors and pkixLoggersDebugTrace */
        for (i = 0; i < length; i++) {

                PKIX_CHECK(PKIX_List_GetItem
                        (pkixLoggers,
                        i,
                        (PKIX_PL_Object **) &addLogger,
                        plContext),
                        PKIX_LISTGETITEMFAILED);


                /* Put in pkixLoggersErrors */

                if (savedPkixLoggersErrors == NULL) {

                        PKIX_CHECK(PKIX_List_Create
                                    (&savedPkixLoggersErrors,
                                    plContext),
                                    PKIX_LISTCREATEFAILED);
                }
        
                PKIX_CHECK(PKIX_List_AppendItem
                        (savedPkixLoggersErrors,
                        (PKIX_PL_Object *) addLogger,
                        plContext),
                        PKIX_LISTAPPENDITEMFAILED);
                            
                if (addLogger->maxLevel > PKIX_LOGGER_LEVEL_WARNING) {

                        /* Put in pkixLoggersDebugTrace */

                        if (savedPkixLoggersDebugTrace == NULL) {

                            PKIX_CHECK(PKIX_List_Create
                                    (&savedPkixLoggersDebugTrace,
                                    plContext),
                                    PKIX_LISTCREATEFAILED);
                        }

                        PKIX_CHECK(PKIX_List_AppendItem
                                (savedPkixLoggersDebugTrace,
                                (PKIX_PL_Object *) addLogger,
                                plContext),
                                PKIX_LISTAPPENDITEMFAILED);
                }

                PKIX_DECREF(addLogger);

        }

cleanup:

        PKIX_DECREF(dupLogger);
        PKIX_DECREF(addLogger);

        /* Restore logging capability */
        pkixLoggersErrors = savedPkixLoggersErrors;
        pkixLoggersDebugTrace = savedPkixLoggersDebugTrace;

        if (locked) {
                PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext),
                        PKIX_MONITORLOCKEXITFAILED);
        }

       PKIX_RETURN(LOGGER);
}
/*
 * 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);
}
/*
 * FUNCTION: pkix_pl_HttpCertStore_ProcessCrlResponse
 * DESCRIPTION:
 *
 *  This function verifies that the response code pointed to by "responseCode"
 *  and the content type pointed to by "responseContentType" are as expected,
 *  and then decodes the data pointed to by "responseData", of length
 *  "responseDataLen", into a List of Crls, possibly empty, which is returned
 *  at "pCrlList".
 *
 * PARAMETERS:
 *  "responseCode"
 *      The value of the HTTP response code.
 *  "responseContentType"
 *      The address of the Content-type string. Must be non-NULL.
 *  "responseData"
 *      The address of the message data. Must be non-NULL.
 *  "responseDataLen"
 *      The length of the message data.
 *  "pCrlList"
 *      The address of the List that is created. 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 HttpCertStore 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_HttpCertStore_ProcessCrlResponse(
        PRUint16 responseCode,
        const char *responseContentType,
        const char *responseData,
        PRUint32 responseDataLen,
        PKIX_List **pCrlList,
        void *plContext)
{
        PRArenaPool *arena = NULL;
        SECItem *encodedResponse = NULL;
        PRInt16 compareVal = 0;
        PKIX_List *crls = NULL;

        PKIX_ENTER
                (HTTPCERTSTORECONTEXT,
                "pkix_pl_HttpCertStore_ProcessCrlResponse");
        PKIX_NULLCHECK_ONE(pCrlList);

        if (responseCode != 200) {
                PKIX_ERROR(PKIX_BADHTTPRESPONSE);
        }

        /* check that response type is application/pkix-crl */
        if (responseContentType == NULL) {
                PKIX_ERROR(PKIX_NOCONTENTTYPEINHTTPRESPONSE);
        }

        compareVal = PORT_Strcasecmp(responseContentType,
                                     "application/pkix-crl");
        if (compareVal != 0) {
                PKIX_ERROR(PKIX_CONTENTTYPENOTPKIXCRL);
        }

        /* Make a SECItem of the response data */
        arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
        if (arena == NULL) {
                PKIX_ERROR(PKIX_OUTOFMEMORY);
        }

        if (responseData == NULL) {
                PKIX_ERROR(PKIX_NORESPONSEDATAINHTTPRESPONSE);
        }

        encodedResponse = SECITEM_AllocItem(arena, NULL, responseDataLen);
        if (encodedResponse == NULL) {
                PKIX_ERROR(PKIX_OUTOFMEMORY);
        }

        PORT_Memcpy(encodedResponse->data, responseData, responseDataLen);

        PKIX_CHECK(PKIX_List_Create(&crls, plContext),
                PKIX_LISTCREATEFAILED);

        PKIX_CHECK(pkix_pl_CRL_CreateToList
                (encodedResponse, crls, plContext),
                PKIX_CRLCREATETOLISTFAILED);

        *pCrlList = crls;

cleanup:
        if (PKIX_ERROR_RECEIVED) {
                PKIX_DECREF(crls);
        }

        if (arena != NULL) {
                PKIX_PL_NSSCALL(CERTSTORE, PORT_FreeArena, (arena, PR_FALSE));
        }


        PKIX_RETURN(HTTPCERTSTORECONTEXT);
}