Ejemplo n.º 1
0
/*
 * FUNCTION: PKIX_PL_CRL_VerifyUpdateTime (see comments in pkix_pl_pki.h)
 */
PKIX_Error *
PKIX_PL_CRL_VerifyUpdateTime(
    PKIX_PL_CRL *crl,
    PKIX_PL_Date *date,
    PKIX_Boolean *pResult,
    void *plContext)
{
    PRTime timeToCheck;
    PRTime nextUpdate;
    PRTime lastUpdate;
    SECStatus status;
    CERTCrl *nssCrl = NULL;
    SECItem *nextUpdateDer = NULL;
    PKIX_Boolean haveNextUpdate = PR_FALSE;

    PKIX_ENTER(CRL, "PKIX_PL_CRL_VerifyUpdateTime");
    PKIX_NULLCHECK_FOUR(crl, crl->nssSignedCrl, date, pResult);

    nssCrl = &(crl->nssSignedCrl->crl);

    PKIX_CRL_DEBUG("\t\tCalling DER_DecodeTimeChoice on date\n");
    status = DER_DecodeTimeChoice(&timeToCheck, &(date->nssTime));
    if (status != SECSuccess) {
        PKIX_ERROR(PKIX_DERDECODETIMECHOICEFAILED);
    }

    /* nextUpdate can be NULL. Checking before using it */
    nextUpdateDer = &nssCrl->nextUpdate;
    if (nextUpdateDer->data && nextUpdateDer->len) {
        haveNextUpdate = PR_TRUE;
        status = DER_DecodeTimeChoice(&nextUpdate, nextUpdateDer);
        if (status != SECSuccess) {
            PKIX_ERROR(PKIX_DERDECODETIMECHOICEFORNEXTUPDATEFAILED);
        }
    }

    status = DER_DecodeTimeChoice(&lastUpdate, &(nssCrl->lastUpdate));
    if (status != SECSuccess) {
        PKIX_ERROR(PKIX_DERDECODETIMECHOICEFORLASTUPDATEFAILED);
    }

    if (!haveNextUpdate || nextUpdate < timeToCheck) {
        *pResult = PKIX_FALSE;
        goto cleanup;
    }

    if (lastUpdate <= timeToCheck) {
        *pResult = PKIX_TRUE;
    } else {
        *pResult = PKIX_FALSE;
    }

cleanup:

    PKIX_RETURN(CRL);
}
Ejemplo n.º 2
0
/*
 * FUNCTION: pkix_pl_CollectionCertStore_GetCRL
 * DESCRIPTION:
 *
 *  Retrieve CRL's in a list of PKIX_PL_CRL object.
 *
 * PARAMETERS:
 *  "colCertStoreContext"
 *      The object CertStore is passed in by checker call.
 *  "crlSelector"
 *      CRLSelector specifies criteria for chosing CRL's
 *  "pNBIOContext"
 *      Address where platform-dependent information is returned for CertStores
 *      that use non-blocking I/O. Must be non-NULL.
 *  "pCrlList"
 *      Address where object pointer will be returned. 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_CollectionCertStore_GetCRL(
        PKIX_CertStore *certStore,
        PKIX_CRLSelector *selector,
        void **pNBIOContext,
        PKIX_List **pCrlList,
        void *plContext)
{
        PKIX_PL_CollectionCertStoreContext *colCertStoreContext = NULL;
        PKIX_List *selectCrl = NULL;

        PKIX_ENTER(CERTSTORE, "pkix_pl_CollectionCertStore_GetCRL");
        PKIX_NULLCHECK_FOUR(certStore, selector, pNBIOContext, pCrlList);

        *pNBIOContext = NULL;   /* We don't use non-blocking I/O */

        PKIX_CHECK(PKIX_CertStore_GetCertStoreContext
                    (certStore,
                    (PKIX_PL_Object **) &colCertStoreContext,
                    plContext),
                    PKIX_CERTSTOREGETCERTSTORECONTEXTFAILED);

        if (colCertStoreContext->crlList == NULL) {

                PKIX_OBJECT_LOCK(colCertStoreContext);

                /*
                 * CRLs in the directory are cached based on the
                 * assumption that the directory contents won't be
                 * changed dynamically.
                 */
                if (colCertStoreContext->crlList == NULL){
                    PKIX_CHECK(pkix_pl_CollectionCertStoreContext_PopulateCRL
                            (colCertStoreContext, plContext),
                            PKIX_COLLECTIONCERTSTORECONTEXTPOPULATECRLFAILED);
                }

                PKIX_OBJECT_UNLOCK(colCertStoreContext);

        }

        PKIX_CHECK(pkix_pl_CollectionCertStoreContext_GetSelectedCRL
                    (colCertStoreContext->crlList,
                    selector,
                    &selectCrl,
                    plContext),
                    PKIX_COLLECTIONCERTSTORECONTEXTGETSELECTCRLFAILED);

        *pCrlList = selectCrl;

cleanup:
	PKIX_OBJECT_UNLOCK(lockedObject);
        PKIX_DECREF(colCertStoreContext);
        PKIX_RETURN(CERTSTORE);
}
Ejemplo n.º 3
0
/*
 * FUNCTION: PKIX_CertStore_CrlContinue (see comments in pkix_certstore.h)
 */
PKIX_Error *
PKIX_CertStore_CrlContinue(
        PKIX_CertStore *store,
        PKIX_CRLSelector *selector,
        void **pNBIOContext,
        PKIX_List **pCrlList,
        void *plContext)
{
        PKIX_ENTER(CERTSTORE, "PKIX_CertStore_CrlContinue");
        PKIX_NULLCHECK_FOUR(store, selector, pNBIOContext, pCrlList);

        PKIX_CHECK(store->crlContinue
                (store, selector, pNBIOContext, pCrlList, plContext),
                PKIX_CERTSTORECRLCONTINUEFAILED);

cleanup:

        PKIX_RETURN(CERTSTORE);
}
Ejemplo n.º 4
0
/*
 * FUNCTION: PKIX_CertStore_CertContinue (see comments in pkix_certstore.h)
 */
PKIX_Error *
PKIX_CertStore_CertContinue(
        PKIX_CertStore *store,
        PKIX_CertSelector *selector,
        PKIX_VerifyNode *verifyNode,
        void **pNBIOContext,
        PKIX_List **pCertList,
        void *plContext)
{
        PKIX_ENTER(CERTSTORE, "PKIX_CertStore_CertContinue");
        PKIX_NULLCHECK_FOUR(store, selector, pNBIOContext, pCertList);

        PKIX_CHECK(store->certContinue
                   (store, selector, verifyNode,
                    pNBIOContext, pCertList, plContext),
                PKIX_CERTSTORECERTCONTINUEFUNCTIONFAILED);

cleanup:

        PKIX_RETURN(CERTSTORE);
}
Ejemplo n.º 5
0
PKIX_Error *
pkix_pl_OcspResponse_GetStatus(
        PKIX_PL_OcspResponse *response,
        PKIX_Boolean *pPassed,
        SECErrorCodes *pReturnCode,
        void *plContext)
{
        SECStatus rv = SECFailure;

        PKIX_ENTER(OCSPRESPONSE, "PKIX_PL_OcspResponse_GetStatus");
        PKIX_NULLCHECK_FOUR(response, response->nssOCSPResponse, pPassed, pReturnCode);

        rv = CERT_GetOCSPResponseStatus(response->nssOCSPResponse);

	if (rv == SECSuccess) {
                *pPassed = PKIX_TRUE;
                *pReturnCode = 0;
        } else {
                *pPassed = PKIX_FALSE;
                *pReturnCode = PORT_GetError();
        }

        PKIX_RETURN(OCSPRESPONSE);
}
/*
 * FUNCTION: pkix_CrlChecker_CheckRemote
 *
 * DESCRIPTION:
 *  Check if the Cert has been revoked based the CRLs data.  This function
 *  maintains the checker state to be current.
 *
 * PARAMETERS
 *  "checker"
 *      Address of CertChainChecker which has the state data.
 *      Must be non-NULL.
 *  "cert"
 *      Address of Certificate that is to be validated. Must be non-NULL.
 *  "unreslvdCrtExts"
 *      A List OIDs. Not **yet** used in this checker function.
 *  "plContext"
 *      Platform-specific context pointer.
 *
 * THREAD SAFETY:
 *  Not Thread Safe
 *      (see Thread Safety Definitions in Programmer's Guide)
 *
 * RETURNS:
 *  Returns NULL if the function succeeds.
 *  Returns a CertChainChecker Error if the function fails in a non-fatal way.
 *  Returns a Fatal Error
 */
PKIX_Error *
pkix_CrlChecker_CheckExternal(
        PKIX_PL_Cert *cert,
        PKIX_PL_Cert *issuer,
        PKIX_PL_Date *date,
        pkix_RevocationMethod *checkerObject,
        PKIX_ProcessingParams *procParams,
        PKIX_UInt32 methodFlags,
        PKIX_RevocationStatus *pRevStatus,
        PKIX_UInt32 *pReasonCode,
        void **pNBIOContext,
        void *plContext)
{
    PKIX_CertStore_CheckRevokationByCrlCallback storeCheckRevocationFn = NULL;
    PKIX_CertStore_ImportCrlCallback storeImportCrlFn = NULL;
    PKIX_RevocationStatus revStatus = PKIX_RevStatus_NoInfo;
    PKIX_CertStore *certStore = NULL;
    PKIX_CertStore *localStore = NULL;
    PKIX_CRLSelector *crlSelector = NULL;
    PKIX_PL_X500Name *issuerName = NULL;
    pkix_CrlChecker *state = NULL; 
    PKIX_UInt32 reasonCode = 0;
    PKIX_UInt32 crlStoreIndex = 0;
    PKIX_UInt32 numCrlStores = 0;
    PKIX_Boolean storeIsLocal = PKIX_FALSE;
    PKIX_List *crlList = NULL;
    PKIX_List *dpList = NULL;
    void *nbioContext = NULL;

    PKIX_ENTER(CERTCHAINCHECKER, "pkix_CrlChecker_CheckExternal");
    PKIX_NULLCHECK_FOUR(cert, issuer, checkerObject, pNBIOContext);
    
    nbioContext = *pNBIOContext;
    *pNBIOContext = NULL; /* prepare for Error exit */

    state = (pkix_CrlChecker*)checkerObject;
    
    PKIX_CHECK(
        PKIX_List_GetLength(state->certStores, &numCrlStores, plContext),
        PKIX_LISTGETLENGTHFAILED);

    /* Find a cert store that is capable of storing crls */
    for (;crlStoreIndex < numCrlStores;crlStoreIndex++) {
        PKIX_CHECK(
            PKIX_List_GetItem(state->certStores, crlStoreIndex,
                              (PKIX_PL_Object **)&certStore,
                              plContext),
            PKIX_LISTGETITEMFAILED);
        
        PKIX_CHECK(
            PKIX_CertStore_GetLocalFlag(certStore, &storeIsLocal,
                                        plContext),
            PKIX_CERTSTOREGETLOCALFLAGFAILED);
        if (storeIsLocal) {
            PKIX_CHECK(
                PKIX_CertStore_GetImportCrlCallback(certStore,
                                                    &storeImportCrlFn,
                                                    plContext),
                PKIX_CERTSTOREGETCHECKREVBYCRLFAILED);
            
            PKIX_CHECK(
                PKIX_CertStore_GetCrlCheckerFn(certStore,
                                               &storeCheckRevocationFn,
                                               plContext),
                PKIX_CERTSTOREGETCHECKREVBYCRLFAILED);
            
            if (storeImportCrlFn && storeCheckRevocationFn) {
                localStore = certStore;
                certStore = NULL;
                break;
            }
        }
        PKIX_DECREF(certStore);
    } /* while */

    /* Report unknown status if we can not check crl in one of the
     * local stores. */
    if (!localStore) {
        PKIX_ERROR_FATAL(PKIX_CRLCHECKERNOLOCALCERTSTOREFOUND);
    }
    PKIX_CHECK(
        PKIX_PL_Cert_VerifyKeyUsage(issuer, PKIX_CRL_SIGN, plContext),
        PKIX_CERTCHECKKEYUSAGEFAILED);
    PKIX_CHECK(
        PKIX_PL_Cert_GetCrlDp(cert, &dpList, plContext),
        PKIX_CERTGETCRLDPFAILED);
    if (!(methodFlags & PKIX_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE) &&
        (!dpList || !dpList->length)) {
        goto cleanup;
    }
    PKIX_CHECK(
        PKIX_PL_Cert_GetIssuer(cert, &issuerName, plContext),
        PKIX_CERTGETISSUERFAILED);
    PKIX_CHECK(
        PKIX_CRLSelector_Create(issuer, dpList, date, &crlSelector, plContext),
        PKIX_CRLCHECKERSETSELECTORFAILED);
    /* Fetch crl and store in a local cert store */
    for (crlStoreIndex = 0;crlStoreIndex < numCrlStores;crlStoreIndex++) {
        PKIX_CertStore_CRLCallback getCrlsFn;

        PKIX_CHECK(
            PKIX_List_GetItem(state->certStores, crlStoreIndex,
                              (PKIX_PL_Object **)&certStore,
                              plContext),
            PKIX_LISTGETITEMFAILED);
        
        PKIX_CHECK(
            PKIX_CertStore_GetCRLCallback(certStore, &getCrlsFn,
                                          plContext),
            PKIX_CERTSTOREGETCRLCALLBACKFAILED);
        
        PKIX_CHECK(
            (*getCrlsFn)(certStore, crlSelector, &nbioContext,
                      &crlList, plContext),
            PKIX_GETCRLSFAILED);

        PKIX_CHECK(
            (*storeImportCrlFn)(localStore, issuerName, crlList, plContext),
            PKIX_CERTSTOREFAILTOIMPORTCRLLIST);
        
        PKIX_CHECK(
            (*storeCheckRevocationFn)(certStore, cert, issuer, date,
                                      /* done with crl downloading */
                                      PKIX_TRUE,
                                      &reasonCode, &revStatus, plContext),
            PKIX_CERTSTORECRLCHECKFAILED);
        if (revStatus != PKIX_RevStatus_NoInfo) {
            break;
        }
        PKIX_DECREF(crlList);
        PKIX_DECREF(certStore);
    } /* while */

cleanup:
    /* Update return flags */
    if (revStatus == PKIX_RevStatus_NoInfo && 
	((dpList && dpList->length > 0) ||
	 (methodFlags & PKIX_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE)) &&
        methodFlags & PKIX_REV_M_FAIL_ON_MISSING_FRESH_INFO) {
        revStatus = PKIX_RevStatus_Revoked;
    }
    *pRevStatus = revStatus;

    PKIX_DECREF(dpList);
    PKIX_DECREF(crlList);
    PKIX_DECREF(certStore);
    PKIX_DECREF(issuerName);
    PKIX_DECREF(localStore);
    PKIX_DECREF(crlSelector);

    PKIX_RETURN(CERTCHAINCHECKER);
}
/*
 * FUNCTION: pkix_CrlChecker_CheckLocal
 *
 * DESCRIPTION:
 *  Check if the Cert has been revoked based the CRLs data.  This function
 *  maintains the checker state to be current.
 *
 * PARAMETERS
 *  "checker"
 *      Address of CertChainChecker which has the state data.
 *      Must be non-NULL.
 *  "cert"
 *      Address of Certificate that is to be validated. Must be non-NULL.
 *  "unreslvdCrtExts"
 *      A List OIDs. Not **yet** used in this checker function.
 *  "plContext"
 *      Platform-specific context pointer.
 *
 * THREAD SAFETY:
 *  Not Thread Safe
 *      (see Thread Safety Definitions in Programmer's Guide)
 *
 * RETURNS:
 *  Returns NULL if the function succeeds.
 *  Returns a CertChainChecker Error if the function fails in a non-fatal way.
 *  Returns a Fatal Error
 */
PKIX_Error *
pkix_CrlChecker_CheckLocal(
        PKIX_PL_Cert *cert,
        PKIX_PL_Cert *issuer,
        PKIX_PL_Date *date,
        pkix_RevocationMethod *checkerObject,
        PKIX_ProcessingParams *procParams,
        PKIX_UInt32 methodFlags,
        PKIX_Boolean chainVerificationState,
        PKIX_RevocationStatus *pRevStatus,
        PKIX_UInt32 *pReasonCode,
        void *plContext)
{
    PKIX_CertStore_CheckRevokationByCrlCallback storeCheckRevocationFn;
    PKIX_CertStore *certStore = NULL;
    pkix_CrlChecker *state = NULL;
    PKIX_UInt32 reasonCode = 0;
    PKIX_UInt32 crlStoreIndex = 0;
    PKIX_UInt32 numCrlStores = 0;
    PKIX_Boolean storeIsLocal = PKIX_FALSE;
    PKIX_RevocationStatus revStatus = PKIX_RevStatus_NoInfo;

    PKIX_ENTER(CERTCHAINCHECKER, "pkix_CrlChecker_CheckLocal");
    PKIX_NULLCHECK_FOUR(cert, issuer, checkerObject, checkerObject);
    
    state = (pkix_CrlChecker*)checkerObject;

    PKIX_CHECK(
        PKIX_List_GetLength(state->certStores, &numCrlStores, plContext),
        PKIX_LISTGETLENGTHFAILED);

    for (;crlStoreIndex < numCrlStores;crlStoreIndex++) {
        PKIX_CHECK(
            PKIX_List_GetItem(state->certStores, crlStoreIndex,
                              (PKIX_PL_Object **)&certStore,
                              plContext),
            PKIX_LISTGETITEMFAILED);
        
        PKIX_CHECK(
            PKIX_CertStore_GetLocalFlag(certStore, &storeIsLocal,
                                        plContext),
            PKIX_CERTSTOREGETLOCALFLAGFAILED);
        if (storeIsLocal) {
            PKIX_CHECK(
                PKIX_CertStore_GetCrlCheckerFn(certStore,
                                               &storeCheckRevocationFn,
                                               plContext),
                PKIX_CERTSTOREGETCHECKREVBYCRLFAILED);

            if (storeCheckRevocationFn) {
                PKIX_CHECK(
                    (*storeCheckRevocationFn)(certStore, cert, issuer,
                                         /* delay sig check if building
                                          * a chain by not specifying the time*/
                                          chainVerificationState ? date : NULL,
                                         /* crl downloading is not done. */
                                          PKIX_FALSE,   
                                          &reasonCode, &revStatus, plContext),
                    PKIX_CERTSTORECRLCHECKFAILED);
                if (revStatus == PKIX_RevStatus_Revoked) {
                    break;
                }
            }
        }
        PKIX_DECREF(certStore);
    } /* while */

cleanup:
    *pRevStatus = revStatus;
    PKIX_DECREF(certStore);

    PKIX_RETURN(CERTCHAINCHECKER);
}
/*
 * FUNCTION: pkix_pl_LdapCertStore_GetCRLContinue
 *  (see description of PKIX_CertStore_CRLCallback in pkix_certstore.h)
 */
PKIX_Error *
pkix_pl_LdapCertStore_GetCRLContinue(
        PKIX_CertStore *store,
        PKIX_CRLSelector *selector,
        void **pNBIOContext,
        PKIX_List **pCrlList,
        void *plContext)
{
        void *nbio = NULL;
        PKIX_PL_CRL *candidate = NULL;
        PKIX_List *responses = NULL;
        PKIX_PL_LdapCertStoreContext *lcs = NULL;
        PKIX_List *filteredCRLs = NULL;
        PKIX_List *unfilteredCRLs = NULL;

        PKIX_ENTER(CERTSTORE, "pkix_pl_LdapCertStore_GetCRLContinue");
        PKIX_NULLCHECK_FOUR(store, selector, pNBIOContext, pCrlList);

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

        PKIX_CHECK(PKIX_PL_LdapClient_ResumeRequest
                ((PKIX_PL_LdapClient *)lcs, &nbio, &responses, plContext),
                PKIX_LDAPCLIENTRESUMEREQUESTFAILED);

        if (nbio != NULL) {
                /* client is waiting for non-blocking I/O to complete */
                *pNBIOContext = (void *)nbio;
                *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);

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

        }

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

        *pCrlList = filteredCRLs;

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

        PKIX_DECREF(candidate);
        PKIX_DECREF(responses);
        PKIX_DECREF(unfilteredCRLs);
        PKIX_DECREF(lcs);

        PKIX_RETURN(CERTSTORE);
}
Ejemplo n.º 9
0
/*
 * FUNCTION: pkix_pl_PrimHashTable_Remove
 * DESCRIPTION:
 *
 *  Removes any objects with the key pointed to by "key" and hashCode value
 *  equal to "hashCode" from the PrimHashtable pointed to by "ht", using the
 *  function pointed to by "keyComp" to compare keys, and stores the object's
 *  value at "pResult". Assumes "key" is a PKIX_UInt32 or a PKIX_PL_Object.
 *  This function sets "pResult" to NULL if the key is not in the hashtable.
 *
 * PARAMETERS:
 *  "ht"
 *      Address of PrimHashtable to remove object. Must be non-NULL.
 *  "key"
 *      Address of key for lookup. Typically a PKIX_UInt32 or PKIX_PL_Object.
 *      Must be non-NULL.
 *  "value"
 *      Address of Object to be added to PrimHashtable. Must be non-NULL.
 *  "hashCode"
 *      Hashcode value of the key.
 *  "keyComp"
 *      Address of function used to determine if two keys are equal.
 *      If NULL, pkix_pl_KeyComparator_Default is used.
 *  "pResult"
 *      Address where value will be stored. Must be non-NULL.
 *  "plContext"
 *      Platform-specific context pointer.
 * THREAD SAFETY:
 *  Not Thread Safe - assumes exclusive access to "ht"
 *  (see Thread Safety Definitions in Programmer's Guide)
 * RETURNS:
 *  Returns NULL if the function succeeds.
 *  Returns a HashTable 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_PrimHashTable_Remove(
        pkix_pl_PrimHashTable *ht,
        void *key,
        PKIX_UInt32 hashCode,
        PKIX_PL_EqualsCallback keyComp,
        void **pKey,
        void **pValue,
        void *plContext)
{
        pkix_pl_HT_Elem *element = NULL;
        pkix_pl_HT_Elem *prior = NULL;
        PKIX_Boolean compResult;

        PKIX_ENTER(HASHTABLE, "pkix_pl_PrimHashTable_Remove");
        PKIX_NULLCHECK_FOUR(ht, key, pKey, pValue);

        *pKey = NULL;
        *pValue = NULL;

        for (element = ht->buckets[hashCode%ht->size], prior = element;
            (element != NULL);
            prior = element, element = element->next) {

                if (element->hashCode != hashCode){
                        /* no possibility of a match */
                        continue;
                }

                if (keyComp == NULL){
                        PKIX_CHECK(pkix_pl_KeyComparator_Default
                                ((PKIX_UInt32 *)key,
                                (PKIX_UInt32 *)(element->key),
                                &compResult,
                                plContext),
                                PKIX_COULDNOTTESTWHETHERKEYSEQUAL);
                } else {
                        PKIX_CHECK(keyComp
                                ((PKIX_PL_Object *)key,
                                (PKIX_PL_Object *)(element->key),
                                &compResult,
                                plContext),
                                PKIX_COULDNOTTESTWHETHERKEYSEQUAL);
                }

                if ((element->hashCode == hashCode) &&
                    (compResult == PKIX_TRUE)){
                        if (element != prior) {
                                prior->next = element->next;
                        } else {
                                ht->buckets[hashCode%ht->size] = element->next;
                        }
                        *pKey = element->key;
                        *pValue = element->value;
                        element->key = NULL;
                        element->value = NULL;
                        element->next = NULL;
                        PKIX_FREE(element);
                        goto cleanup;
                }
        }

cleanup:

        PKIX_RETURN(HASHTABLE);
}
/*
 * 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);
}
PKIX_Error *
pkix_pl_AIAMgr_GetLDAPCerts(
        PKIX_PL_AIAMgr *aiaMgr,
	PKIX_PL_InfoAccess *ia,
	void **pNBIOContext,
	PKIX_List **pCerts,
        void *plContext)
{
        PKIX_List *result = NULL;
        PKIX_PL_GeneralName *location = NULL;
        PKIX_PL_LdapClient *client = NULL;
        LDAPRequestParams request;
        PLArenaPool *arena = NULL;
        char *domainName = NULL;
	void *nbio = NULL;

        PKIX_ENTER(AIAMGR, "pkix_pl_AIAMgr_GetLDAPCerts");
        PKIX_NULLCHECK_FOUR(aiaMgr, ia, pNBIOContext, pCerts);

        nbio = *pNBIOContext;
        *pNBIOContext = NULL;
        *pCerts = NULL;

        if (nbio == NULL) { /* a new request */

                /* Initiate an LDAP request */

                request.scope = WHOLE_SUBTREE;
                request.derefAliases = NEVER_DEREF;
                request.sizeLimit = 0;
                request.timeLimit = 0;

                PKIX_CHECK(PKIX_PL_InfoAccess_GetLocation
                        (ia, &location, plContext),
                        PKIX_INFOACCESSGETLOCATIONFAILED);

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

                PKIX_CHECK(pkix_pl_InfoAccess_ParseLocation
                        (location, arena, &request, &domainName, plContext),
                        PKIX_INFOACCESSPARSELOCATIONFAILED);

                PKIX_DECREF(location);

                /* Find or create a connection to LDAP server */
                PKIX_CHECK(pkix_pl_AiaMgr_FindLDAPClient
                        (aiaMgr, domainName, &client, plContext),
                        PKIX_AIAMGRFINDLDAPCLIENTFAILED);

                aiaMgr->client.ldapClient = client;

                PKIX_CHECK(PKIX_PL_LdapClient_InitiateRequest
                        (aiaMgr->client.ldapClient,
			&request,
			&nbio,
			&result,
			plContext),
                        PKIX_LDAPCLIENTINITIATEREQUESTFAILED);

                PKIX_PL_NSSCALL(AIAMGR, PORT_FreeArena, (arena, PR_FALSE));

        } else {

                PKIX_CHECK(PKIX_PL_LdapClient_ResumeRequest
                        (aiaMgr->client.ldapClient, &nbio, &result, plContext),
                        PKIX_LDAPCLIENTRESUMEREQUESTFAILED);

        }

        if (nbio != NULL) { /* WOULDBLOCK */
                *pNBIOContext = nbio;
                *pCerts = NULL;
                goto cleanup;
        }

	PKIX_DECREF(aiaMgr->client.ldapClient);

	if (result == NULL) {
		*pCerts = NULL;
	} else {
		PKIX_CHECK(pkix_pl_LdapCertStore_BuildCertList
			(result, pCerts, plContext),
			PKIX_LDAPCERTSTOREBUILDCERTLISTFAILED);
	}

	*pNBIOContext = nbio;

cleanup:

        if (arena && (PKIX_ERROR_RECEIVED)) {
                PKIX_PL_NSSCALL(AIAMGR, PORT_FreeArena, (arena, PR_FALSE));
        }

        if (PKIX_ERROR_RECEIVED) {
	        PKIX_DECREF(aiaMgr->client.ldapClient);
	}

        PKIX_DECREF(location);

        PKIX_RETURN(AIAMGR);
}
PKIX_Error *
pkix_pl_AIAMgr_GetHTTPCerts(
        PKIX_PL_AIAMgr *aiaMgr,
	PKIX_PL_InfoAccess *ia,
	void **pNBIOContext,
	PKIX_List **pCerts,
        void *plContext)
{
        PKIX_PL_GeneralName *location = NULL;
        PKIX_PL_String *locationString = NULL;
	PKIX_UInt32 len = 0;
	PRUint16 port = 0;
	const SEC_HttpClientFcn *httpClient = NULL;
	const SEC_HttpClientFcnV1 *hcv1 = NULL;
	SECStatus rv = SECFailure;
	SEC_HTTP_SERVER_SESSION serverSession = NULL;
	SEC_HTTP_REQUEST_SESSION requestSession = NULL;	
	char *path = NULL;
	char *hostname = NULL;
	char *locationAscii = NULL;
	void *nbio = NULL;
	PRUint16 responseCode = 0;
	const char *responseContentType = NULL;
	const char *responseData = NULL;

        PKIX_ENTER(AIAMGR, "pkix_pl_AIAMgr_GetHTTPCerts");
        PKIX_NULLCHECK_FOUR(aiaMgr, ia, pNBIOContext, pCerts);

        nbio = *pNBIOContext;
        *pNBIOContext = NULL;
        *pCerts = NULL;

        if (nbio == NULL) { /* a new request */

                PKIX_CHECK(PKIX_PL_InfoAccess_GetLocation
                        (ia, &location, plContext),
                       PKIX_INFOACCESSGETLOCATIONFAILED);

                /* find or create httpClient = default client */
		httpClient = SEC_GetRegisteredHttpClient();
		aiaMgr->client.hdata.httpClient = httpClient;
		if (!httpClient)
		    PKIX_ERROR(PKIX_OUTOFMEMORY);

		if (httpClient->version == 1) {

                        PKIX_UInt32 timeout =
                             ((PKIX_PL_NssContext*)plContext)->timeoutSeconds;

			hcv1 = &(httpClient->fcnTable.ftable1);

			/* create server session */
			PKIX_TOSTRING(location, &locationString, plContext,
				PKIX_GENERALNAMETOSTRINGFAILED);

			PKIX_CHECK(PKIX_PL_String_GetEncoded
				(locationString,
				PKIX_ESCASCII,
				(void **)&locationAscii,
				&len,
				plContext),
				PKIX_STRINGGETENCODEDFAILED);

                        rv = CERT_ParseURL(locationAscii, &hostname, &port,
                                            &path);
			if ((rv != SECSuccess) ||
			    (hostname == NULL) ||
			    (path == NULL)) {
				PKIX_ERROR(PKIX_URLPARSINGFAILED);
			}

                        rv = (*hcv1->createSessionFcn)(hostname, port, 
                                                       &serverSession);
	                if (rv != SECSuccess) {
				PKIX_ERROR(PKIX_HTTPCLIENTCREATESESSIONFAILED);
			}

			aiaMgr->client.hdata.serverSession = serverSession;

			/* create request session */
                        rv = (*hcv1->createFcn)(serverSession, "http", path,
                        	"GET", PR_SecondsToInterval(timeout),
                                 &requestSession);
                	if (rv != SECSuccess) {
                        	PKIX_ERROR(PKIX_HTTPSERVERERROR);
                	}

			aiaMgr->client.hdata.requestSession = requestSession;
		} else {
			PKIX_ERROR(PKIX_UNSUPPORTEDVERSIONOFHTTPCLIENT);
		}
	}

	httpClient = aiaMgr->client.hdata.httpClient;

	if (httpClient->version == 1) {
                PRUint32 responseDataLen = 
                   ((PKIX_PL_NssContext*)plContext)->maxResponseLength;

		hcv1 = &(httpClient->fcnTable.ftable1);
		requestSession = aiaMgr->client.hdata.requestSession;

		/* trySendAndReceive */
                rv = (*hcv1->trySendAndReceiveFcn)(requestSession,
                                 (PRPollDesc **)&nbio,
                                 &responseCode,
                                 (const char **)&responseContentType,
                                 NULL, /* &responseHeaders */
                                 (const char **)&responseData,
                                 &responseDataLen);

                if (rv != SECSuccess) {
                        PKIX_ERROR(PKIX_HTTPSERVERERROR);
                }

                if (nbio != 0) {
                        *pNBIOContext = nbio;
                        goto cleanup;
                }

		PKIX_CHECK(pkix_pl_HttpCertStore_ProcessCertResponse
	                (responseCode,
	                responseContentType,
	                responseData,
	                responseDataLen,
	                pCerts,
	                plContext),
	                PKIX_HTTPCERTSTOREPROCESSCERTRESPONSEFAILED);
                
                /* Session and request cleanup in case of success */
                if (aiaMgr->client.hdata.requestSession != NULL) {
                    (*hcv1->freeFcn)(aiaMgr->client.hdata.requestSession);
                    aiaMgr->client.hdata.requestSession = NULL;
                }
                if (aiaMgr->client.hdata.serverSession != NULL) {
                    (*hcv1->freeSessionFcn)(aiaMgr->client.hdata.serverSession);
                    aiaMgr->client.hdata.serverSession = NULL;
                }
                aiaMgr->client.hdata.httpClient = 0; /* callback fn */

        } else  {
		PKIX_ERROR(PKIX_UNSUPPORTEDVERSIONOFHTTPCLIENT);
	}

cleanup:
        /* Session and request cleanup in case of error. Passing through without cleanup
         * if interrupted by blocked IO. */
        if (PKIX_ERROR_RECEIVED && aiaMgr) {
            if (aiaMgr->client.hdata.requestSession != NULL) {
                (*hcv1->freeFcn)(aiaMgr->client.hdata.requestSession);
                aiaMgr->client.hdata.requestSession = NULL;
            }
            if (aiaMgr->client.hdata.serverSession != NULL) {
                (*hcv1->freeSessionFcn)(aiaMgr->client.hdata.serverSession);
                aiaMgr->client.hdata.serverSession = NULL;
            }
            aiaMgr->client.hdata.httpClient = 0; /* callback fn */
        }

        PKIX_DECREF(location);
        PKIX_DECREF(locationString);

        if (locationAscii) {
            PORT_Free(locationAscii);
        }
        if (hostname) {
            PORT_Free(hostname);
        }
        if (path) {
            PORT_Free(path);
        }

        PKIX_RETURN(AIAMGR);
}
Ejemplo n.º 13
0
/*
 * FUNCTION: pkix_pl_OcspResponse_VerifySignature
 * DESCRIPTION:
 *
 *  This function verifies the ocspResponse signature field in the OcspResponse
 *  pointed to by "response", storing PKIX_TRUE at "pPassed" if verification
 *  is successful and PKIX_FALSE otherwise. If verification is unsuccessful an
 *  error code (an enumeration of type SECErrorCodes) is stored at *pReturnCode.
 *
 * PARAMETERS
 *  "response"
 *      The address of the OcspResponse whose signature field is to be
 *      retrieved. Must be non-NULL.
 *  "cert"
 *      The address of the Cert for which the OCSP query was made. Must be
 *      non-NULL.
 *  "procParams"
 *      Address of ProcessingParams used to initialize the ExpirationChecker
 *      and TargetCertChecker. Must be non-NULL.
 *  "pPassed"
 *      Address at which the Boolean result is stored. Must be non-NULL.
 *  "pNBIOContext"
 *      Address at which the NBIOContext is stored indicating whether the
 *      checking is complete. 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 an OcspResponse 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_OcspResponse_VerifySignature(
        PKIX_PL_OcspResponse *response,
        PKIX_PL_Cert *cert,
        PKIX_ProcessingParams *procParams,
        PKIX_Boolean *pPassed,
        void **pNBIOContext,
        void *plContext)
{
        SECStatus rv = SECFailure;
        CERTOCSPResponse *nssOCSPResponse = NULL;
        CERTCertificate *issuerCert = NULL;
        PKIX_BuildResult *buildResult = NULL;
        void *nbio = NULL;
        void *state = NULL;

        ocspSignature *signature = NULL;
        ocspResponseData *tbsData = NULL;
        SECItem *tbsResponseDataDER = NULL;


        PKIX_ENTER(OCSPRESPONSE, "pkix_pl_OcspResponse_VerifySignature");
        PKIX_NULLCHECK_FOUR(response, cert, pPassed,  pNBIOContext);

        nbio = *pNBIOContext;
        *pNBIOContext = NULL;

        nssOCSPResponse = response->nssOCSPResponse;
        if (nssOCSPResponse == NULL) {
            PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
            goto cleanup;
        }

        tbsData =
            ocsp_GetResponseData(nssOCSPResponse, &tbsResponseDataDER);
        
        signature = ocsp_GetResponseSignature(nssOCSPResponse);


        /* Are we resuming after a WOULDBLOCK response? */
        if (nbio == NULL) {
            /* No, this is a new query */

            issuerCert = CERT_FindCertIssuer(cert->nssCert, PR_Now(),
                                             certUsageAnyCA);
            
            /*
             * If this signature has already gone through verification,
             * just return the cached result.
             */
            if (signature->wasChecked) {
                if (signature->status == SECSuccess) {
                    response->signerCert =
                        CERT_DupCertificate(signature->cert);
                } else {
                    PORT_SetError(signature->failureReason);
                    goto cleanup;
                }
            }
            
            response->signerCert = 
                ocsp_GetSignerCertificate(response->handle, tbsData,
                                          signature, issuerCert);
            
            if (response->signerCert == NULL) {
                PORT_SetError(SEC_ERROR_UNKNOWN_SIGNER);
                goto cleanup;
            }
            
            PKIX_CHECK( 
                PKIX_PL_Cert_CreateFromCERTCertificate(response->signerCert,
                                                       &(response->pkixSignerCert),
                                                       plContext),
                PKIX_CERTCREATEWITHNSSCERTFAILED);
            
            /*
             * We could mark this true at the top of this function, or
             * always below at "finish", but if the problem was just that
             * we could not find the signer's cert, leave that as if the
             * signature hasn't been checked. Maybe a subsequent call will
             * have better luck.
             */
            signature->wasChecked = PR_TRUE;
            
            /*
             * We are about to verify the signer certificate; we need to
             * specify *when* that certificate must be valid -- for our
             * purposes we expect it to be valid when the response was
             * signed. The value of "producedAt" is the signing time.
             */
            rv = DER_GeneralizedTimeToTime(&response->producedAt,
                                           &tbsData->producedAt);
            if (rv != SECSuccess) {
                PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
                goto cleanup;
            }
            
            /*
             * We need producedAtDate and pkixSignerCert if we are calling a
             * user-supplied verification function. Let's put their
             * creation before the code that gets repeated when
             * non-blocking I/O is used.
             */
            
            PKIX_CHECK(
                pkix_pl_Date_CreateFromPRTime((PRTime)response->producedAt,
                                              &(response->producedAtDate),
                                              plContext),
                PKIX_DATECREATEFROMPRTIMEFAILED);
            
	}
        
        /*
         * Just because we have a cert does not mean it is any good; check
         * it for validity, trust and usage. Use the caller-supplied
         * verification function, if one was supplied.
         */
        if (ocsp_CertIsOCSPDefaultResponder(response->handle,
                                            response->signerCert)) {
            rv = SECSuccess;
        } else {
            SECCertUsage certUsage;
            if (CERT_IsCACert(response->signerCert, NULL)) {
                certUsage = certUsageAnyCA;
            } else {
                certUsage = certUsageStatusResponder;
            }
            PKIX_CHECK_ONLY_FATAL(
                pkix_pl_OcspResponse_VerifyResponse(response, procParams,
                                                    certUsage, &state,
                                                    &buildResult, &nbio,
                                                    plContext),
                PKIX_CERTVERIFYKEYUSAGEFAILED);
            if (pkixTempErrorReceived) {
                rv = SECFailure;
                goto cleanup;
            }
            if (nbio != NULL) {
                *pNBIOContext = nbio;
                goto cleanup;
            }            
        }

        rv = ocsp_VerifyResponseSignature(response->signerCert, signature,
                                          tbsResponseDataDER, NULL);
        
cleanup:
        if (rv == SECSuccess) {
            *pPassed = PKIX_TRUE;
        } else {
            *pPassed = PKIX_FALSE;
        }
        
        if (signature) {
            if (signature->wasChecked) {
                signature->status = rv;
            }
            
            if (rv != SECSuccess) {
                signature->failureReason = PORT_GetError();
                if (response->signerCert != NULL) {
                    CERT_DestroyCertificate(response->signerCert);
                    response->signerCert = NULL;
                }
            } else {
                /* Save signer's certificate in signature. */
                signature->cert = CERT_DupCertificate(response->signerCert);
            }
        }

	if (issuerCert)
	    CERT_DestroyCertificate(issuerCert);
        
        PKIX_RETURN(OCSPRESPONSE);
}
/*
 * 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);
}
Ejemplo n.º 15
0
/*
 * FUNCTION: pkix_pl_HttpCertStore_GetCRLContinue
 *  (see description of PKIX_CertStore_CRLCallback in pkix_certstore.h)
 */
PKIX_Error *
pkix_pl_HttpCertStore_GetCRLContinue(
        PKIX_CertStore *store,
        PKIX_CRLSelector *selector,
        void **pNBIOContext,
        PKIX_List **pCrlList,
        void *plContext)
{
        const SEC_HttpClientFcnV1 *hcv1 = NULL;
        PKIX_PL_HttpCertStoreContext *context = NULL;
        void *nbioContext = NULL;
        SECStatus rv = SECFailure;
        PRUint16 responseCode = 0;
        const char *responseContentType = NULL;
        const char *responseData = NULL;
        PRUint32 responseDataLen = 0;
        PKIX_List *crlList = NULL;

        PKIX_ENTER(CERTSTORE, "pkix_pl_HttpCertStore_GetCRLContinue");
        PKIX_NULLCHECK_FOUR(store, selector, pNBIOContext, pCrlList);

        nbioContext = *pNBIOContext;
        *pNBIOContext = NULL;

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

        if (context->client->version != 1) {
            PKIX_ERROR(PKIX_UNSUPPORTEDVERSIONOFHTTPCLIENT);
        }
        hcv1 = &(context->client->fcnTable.ftable1);
                
        PKIX_CHECK(pkix_pl_HttpCertStore_CreateRequestSession
                   (context, plContext),
                   PKIX_HTTPCERTSTORECREATEREQUESTSESSIONFAILED);
        
        responseDataLen = 
            ((PKIX_PL_NssContext*)plContext)->maxResponseLength;

        rv = (*hcv1->trySendAndReceiveFcn)(context->requestSession,
                        (PRPollDesc **)&nbioContext,
                        &responseCode,
                        (const char **)&responseContentType,
                        NULL, /* &responseHeaders */
                        (const char **)&responseData,
                        &responseDataLen);
        
        if (rv != SECSuccess) {
            PKIX_ERROR(PKIX_HTTPSERVERERROR);
        }
        
        if (nbioContext != 0) {
            *pNBIOContext = nbioContext;
            goto cleanup;
        }

        PKIX_CHECK(pkix_pl_HttpCertStore_ProcessCrlResponse
                (responseCode,
                responseContentType,
                responseData,
                responseDataLen,
                &crlList,
                plContext),
                PKIX_HTTPCERTSTOREPROCESSCRLRESPONSEFAILED);

        *pCrlList = crlList;

cleanup:
        PKIX_DECREF(context);

        PKIX_RETURN(CERTSTORE);
}
Ejemplo n.º 16
0
/*
 * The OCSPChecker is created in an idle state, and remains in this state until
 * either (a) the default Responder has been set and enabled, and a Check
 * request is received with no responder specified, or (b) a Check request is
 * received with a specified responder. A request message is constructed and
 * given to the HttpClient. If non-blocking I/O is used the client may return
 * with WOULDBLOCK, in which case the OCSPChecker returns the WOULDBLOCK
 * condition to its caller in turn. On a subsequent call the I/O is resumed.
 * When a response is received it is decoded and the results provided to the
 * caller.
 *
 */
static PKIX_Error *
pkix_OcspChecker_Check(
    PKIX_PL_Object *checkerObject,
    PKIX_PL_Cert *cert,
    PKIX_ProcessingParams *procParams,
    void **pNBIOContext,
    PKIX_UInt32 *pResultCode,
    void *plContext)
{
    SECErrorCodes resultCode = SEC_ERROR_REVOKED_CERTIFICATE_OCSP;
    PKIX_Boolean uriFound = PKIX_FALSE;
    PKIX_Boolean passed = PKIX_FALSE;
    PKIX_OcspChecker *checker = NULL;
    PKIX_PL_OcspCertID *cid = NULL;
    PKIX_PL_OcspRequest *request = NULL;
    PKIX_PL_Date *validity = NULL;
    void *nbioContext = NULL;

    PKIX_ENTER(OCSPCHECKER, "pkix_OcspChecker_Check");
    PKIX_NULLCHECK_FOUR(checkerObject, cert, pNBIOContext, pResultCode);

    PKIX_CHECK(pkix_CheckType
               (checkerObject, PKIX_OCSPCHECKER_TYPE, plContext),
               PKIX_OBJECTNOTOCSPCHECKER);

    checker = (PKIX_OcspChecker *)checkerObject;

    nbioContext = *pNBIOContext;
    *pNBIOContext = 0;

    /* assert(checker->nbioContext == nbioContext) */

    if (nbioContext == 0) {
        /* We are initiating a check, not resuming previous I/O. */

        PKIX_Boolean hasFreshStatus = PKIX_FALSE;
        PKIX_Boolean statusIsGood = PKIX_FALSE;

        PKIX_CHECK(PKIX_PL_OcspCertID_Create
                   (cert,
                    validity,
                    &cid,
                    plContext),
                   PKIX_OCSPCERTIDCREATEFAILED);

        if (!cid) {
            goto cleanup;
        }

        PKIX_CHECK(PKIX_PL_OcspCertID_GetFreshCacheStatus
                   (cid,
                    validity,
                    &hasFreshStatus,
                    &statusIsGood,
                    &resultCode,
                    plContext),
                   PKIX_OCSPCERTIDGETFRESHCACHESTATUSFAILED);

        if (hasFreshStatus) {
            /* avoid updating the cache with a cached result... */
            passed = PKIX_TRUE;

            if (statusIsGood) {
                resultCode = 0;
            }
            goto cleanup;
        }
        PKIX_INCREF(cert);
        PKIX_DECREF(checker->cert);
        checker->cert = cert;

        /* create request */
        PKIX_CHECK(pkix_pl_OcspRequest_Create
                   (cert,
                    cid,
                    validity,
                    PKIX_FALSE,     /* PKIX_Boolean addServiceLocator */
                    NULL,           /* PKIX_PL_Cert *signerCert */
                    &uriFound,
                    &request,
                    plContext),
                   PKIX_OCSPREQUESTCREATEFAILED);

        /* No uri to check is considered passing! */
        if (uriFound == PKIX_FALSE) {
            /* no caching for certs lacking URI */
            passed = PKIX_TRUE;
            resultCode = 0;
            goto cleanup;
        }

    }

    /* Do we already have a response object? */
    if ((checker->response) == NULL) {
        /* send request and create a response object */
        PKIX_CHECK(pkix_pl_OcspResponse_Create
                   (request,
                    checker->responder,
                    checker->verifyFcn,
                    &nbioContext,
                    &(checker->response),
                    plContext),
                   PKIX_OCSPRESPONSECREATEFAILED);

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

        PKIX_CHECK(pkix_pl_OcspResponse_Decode
                   ((checker->response), &passed, &resultCode, plContext),
                   PKIX_OCSPRESPONSEDECODEFAILED);

        if (passed == PKIX_FALSE) {
            goto cleanup;
        }

        PKIX_CHECK(pkix_pl_OcspResponse_GetStatus
                   ((checker->response), &passed, &resultCode, plContext),
                   PKIX_OCSPRESPONSEGETSTATUSRETURNEDANERROR);

        if (passed == PKIX_FALSE) {
            goto cleanup;
        }
    }

    PKIX_CHECK(pkix_pl_OcspResponse_VerifySignature
               ((checker->response),
                cert,
                procParams,
                &passed,
                &nbioContext,
                plContext),
               PKIX_OCSPRESPONSEVERIFYSIGNATUREFAILED);

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

    if (passed == PKIX_FALSE) {
        resultCode = PORT_GetError();
        goto cleanup;
    }

    PKIX_CHECK(pkix_pl_OcspResponse_GetStatusForCert
               (cid, (checker->response), &passed, &resultCode, plContext),
               PKIX_OCSPRESPONSEGETSTATUSFORCERTFAILED);

cleanup:
    if (!passed && cid && cid->certID && !cid->certIDWasConsumed) {
        /* We still own the certID object, which means that
         * it did not get consumed to create a cache entry.
         * Let's make sure we create one.
         */
        PKIX_Error *err;
        err = PKIX_PL_OcspCertID_RememberOCSPProcessingFailure(
                  cid, plContext);
        if (err) {
            PKIX_PL_Object_DecRef((PKIX_PL_Object*)err, plContext);
        }
    }

    *pResultCode = (PKIX_UInt32)resultCode;

    PKIX_DECREF(cid);
    PKIX_DECREF(request);
    if (checker) {
        PKIX_DECREF(checker->response);
    }

    PKIX_RETURN(OCSPCHECKER);

}