/*
 * FUNCTION: pkix_pl_LdapCertStore_DecodeCrossCertPair
 * DESCRIPTION:
 *
 *  This function decodes a DER-encoded CrossCertPair pointed to by
 *  "responseList" and extracts and decodes the Certificates in that pair,
 *  adding the resulting Certs, if the decoding was successful, to the List
 *  (possibly empty) pointed to by "certList". If none of the objects
 *  can be decoded into a Cert, the List is returned unchanged.
 *
 * PARAMETERS:
 *  "derCCPItem"
 *      The address of the SECItem containing the DER representation of the
 *      CrossCertPair. Must be non-NULL.
 *  "certList"
 *      The address of the List to which the decoded Certs are added. May be
 *      empty, but 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_DecodeCrossCertPair(
        SECItem *derCCPItem,
        PKIX_List *certList,
        void *plContext)
{
        LDAPCertPair certPair = {{ siBuffer, NULL, 0 }, { siBuffer, NULL, 0 }};
        SECStatus rv = SECFailure;

        PRArenaPool *tempArena = NULL;

        PKIX_ENTER(CERTSTORE, "pkix_pl_LdapCertStore_DecodeCrossCertPair");
        PKIX_NULLCHECK_TWO(derCCPItem, certList);

        tempArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
        if (!tempArena) {
            PKIX_ERROR(PKIX_OUTOFMEMORY);
        }

        rv = SEC_ASN1DecodeItem(tempArena, &certPair, PKIX_PL_LDAPCrossCertPairTemplate,
                                derCCPItem);
        if (rv != SECSuccess) {
                goto cleanup;
        }

        if (certPair.forward.data != NULL) {

            PKIX_CHECK(
                pkix_pl_Cert_CreateToList(&certPair.forward, certList,
                                          plContext),
                PKIX_CERTCREATETOLISTFAILED);
        }

        if (certPair.reverse.data != NULL) {

            PKIX_CHECK(
                pkix_pl_Cert_CreateToList(&certPair.reverse, certList,
                                          plContext),
                PKIX_CERTCREATETOLISTFAILED);
        }

cleanup:
        if (tempArena) {
            PORT_FreeArena(tempArena, PR_FALSE);
        }

        PKIX_RETURN(CERTSTORE);
}
예제 #2
0
/*
 * FUNCTION: certCallback
 * DESCRIPTION:
 *
 *  This function processes the null-terminated array of SECItems produced by
 *  extracting the contents of a signedData message received in response to an
 *  HTTP cert query. Its address is supplied as a callback function to
 *  CERT_DecodeCertPackage; it is not expected to be called directly.
 *
 *  Note that it does not conform to the libpkix API standard of returning
 *  a PKIX_Error*. It returns a SECStatus.
 *
 * PARAMETERS:
 *  "arg"
 *      The address of the callbackContext provided as a void* argument to
 *      CERT_DecodeCertPackage. Must be non-NULL.
 *  "secitemCerts"
 *      The address of the null-terminated array of SECItems. Must be non-NULL.
 *  "numcerts"
 *      The number of SECItems found in the signedData. Must be non-NULL.
 *  "plContext"
 *      Platform-specific context pointer.
 * THREAD SAFETY:
 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
 * RETURNS:
 *  Returns SECSuccess if the function succeeds.
 *  Returns SECFailure if the function fails.
 */
static SECStatus
certCallback(void *arg, SECItem **secitemCerts, int numcerts)
{
        callbackContext *cbContext;
        PKIX_List *pkixCertList = NULL;
        PKIX_Error *error = NULL;
        void *plContext = NULL;
        int itemNum = 0;

        if ((arg == NULL) || (secitemCerts == NULL)) {
                return (SECFailure);
        }

        cbContext = (callbackContext *)arg;
        plContext = cbContext->plContext;
        pkixCertList = cbContext->pkixCertList;

        for (; itemNum < numcerts; itemNum++ ) {
                error = pkix_pl_Cert_CreateToList(secitemCerts[itemNum],
                                                  pkixCertList, plContext);
                if (error != NULL) {
                    if (error->errClass == PKIX_FATAL_ERROR) {
                        cbContext->error = error;
                        return SECFailure;
                    } 
                    /* reuse "error" since we could not destruct the old *
                     * value */
                    error = PKIX_PL_Object_DecRef((PKIX_PL_Object *)error,
                                                        plContext);
                    if (error) {
                        /* Treat decref failure as a fatal error.
                         * In this case will leak error, but can not do
                         * anything about it. */
                        error->errClass = PKIX_FATAL_ERROR;
                        cbContext->error = error;
                        return SECFailure;
                    }
                }
        }

        return SECSuccess;
}
/*
 * 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);
}