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