Index: mozilla/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_pk11certstore.c |
=================================================================== |
--- mozilla/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_pk11certstore.c (revision 191424) |
+++ mozilla/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_pk11certstore.c (working copy) |
@@ -1,1049 +0,0 @@ |
-/* This Source Code Form is subject to the terms of the Mozilla Public |
- * License, v. 2.0. If a copy of the MPL was not distributed with this |
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
-/* |
- * pkix_pl_pk11certstore.c |
- * |
- * PKCS11CertStore Function Definitions |
- * |
- */ |
- |
-#include "pkix_pl_pk11certstore.h" |
- |
-/* |
- * PKIX_DEFAULT_MAX_RESPONSE_LENGTH (64 * 1024) is too small for downloading |
- * CRLs. We observed CRLs of sizes 338759 and 439035 in practice. So we |
- * need to use a higher max response length for CRLs. |
- */ |
-#define PKIX_DEFAULT_MAX_CRL_RESPONSE_LENGTH (512 * 1024) |
- |
-/* --Private-Pk11CertStore-Functions---------------------------------- */ |
- |
-/* |
- * FUNCTION: pkix_pl_Pk11CertStore_CheckTrust |
- * DESCRIPTION: |
- * This function checks the trust status of this "cert" that was retrieved |
- * from the CertStore "store" and returns its trust status at "pTrusted". |
- * |
- * PARAMETERS: |
- * "store" |
- * Address of the CertStore. Must be non-NULL. |
- * "cert" |
- * Address of the Cert. Must be non-NULL. |
- * "pTrusted" |
- * Address of PKIX_Boolean where the "cert" trust status is 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. |
- */ |
-static PKIX_Error * |
-pkix_pl_Pk11CertStore_CheckTrust( |
- PKIX_CertStore *store, |
- PKIX_PL_Cert *cert, |
- PKIX_Boolean *pTrusted, |
- void *plContext) |
-{ |
- SECStatus rv = SECFailure; |
- PKIX_Boolean trusted = PKIX_FALSE; |
- SECCertUsage certUsage = 0; |
- SECCertificateUsage certificateUsage; |
- unsigned int requiredFlags; |
- SECTrustType trustType; |
- CERTCertTrust trust; |
- |
- PKIX_ENTER(CERTSTORE, "pkix_pl_Pk11CertStore_CheckTrust"); |
- PKIX_NULLCHECK_THREE(store, cert, pTrusted); |
- PKIX_NULLCHECK_ONE(cert->nssCert); |
- |
- certificateUsage = ((PKIX_PL_NssContext*)plContext)->certificateUsage; |
- |
- /* ensure we obtained a single usage bit only */ |
- PORT_Assert(!(certificateUsage & (certificateUsage - 1))); |
- |
- /* convert SECertificateUsage (bit mask) to SECCertUsage (enum) */ |
- while (0 != (certificateUsage = certificateUsage >> 1)) { certUsage++; } |
- |
- rv = CERT_TrustFlagsForCACertUsage(certUsage, &requiredFlags, &trustType); |
- if (rv == SECSuccess) { |
- rv = CERT_GetCertTrust(cert->nssCert, &trust); |
- } |
- |
- if (rv == SECSuccess) { |
- unsigned int certFlags; |
- |
- if (certUsage != certUsageAnyCA && |
- certUsage != certUsageStatusResponder) { |
- CERTCertificate *nssCert = cert->nssCert; |
- |
- if (certUsage == certUsageVerifyCA) { |
- if (nssCert->nsCertType & NS_CERT_TYPE_EMAIL_CA) { |
- trustType = trustEmail; |
- } else if (nssCert->nsCertType & NS_CERT_TYPE_SSL_CA) { |
- trustType = trustSSL; |
- } else { |
- trustType = trustObjectSigning; |
- } |
- } |
- |
- certFlags = SEC_GET_TRUST_FLAGS((&trust), trustType); |
- if ((certFlags & requiredFlags) == requiredFlags) { |
- trusted = PKIX_TRUE; |
- } |
- } else { |
- for (trustType = trustSSL; trustType < trustTypeNone; |
- trustType++) { |
- certFlags = |
- SEC_GET_TRUST_FLAGS((&trust), trustType); |
- if ((certFlags & requiredFlags) == requiredFlags) { |
- trusted = PKIX_TRUE; |
- break; |
- } |
- } |
- } |
- } |
- |
- *pTrusted = trusted; |
- |
- PKIX_RETURN(CERTSTORE); |
-} |
- |
-/* |
- * FUNCTION: pkix_pl_Pk11CertStore_CertQuery |
- * DESCRIPTION: |
- * |
- * This function obtains from the database the Certs specified by the |
- * ComCertSelParams pointed to by "params" and stores the resulting |
- * List at "pSelected". If no matching Certs are found, a NULL pointer |
- * will be stored. |
- * |
- * This function uses a "smart" database query if the Subject has been set |
- * in ComCertSelParams. Otherwise, it uses a very inefficient call to |
- * retrieve all Certs in the database (and run them through the selector). |
- * |
- * PARAMETERS: |
- * "params" |
- * Address of the ComCertSelParams. Must be non-NULL. |
- * "pSelected" |
- * Address at which List will be stored. Must be non-NULL. |
- * "plContext" |
- * Platform-specific context pointer |
- * THREAD SAFETY: |
- * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
- * RETURNS: |
- * Returns NULL if the function succeeds. |
- * Returns a CertStore Error if the function fails in a non-fatal way. |
- * Returns a Fatal Error if the function fails in an unrecoverable way. |
- */ |
-static PKIX_Error * |
-pkix_pl_Pk11CertStore_CertQuery( |
- PKIX_ComCertSelParams *params, |
- PKIX_List **pSelected, |
- void *plContext) |
-{ |
- PRBool validOnly = PR_FALSE; |
- PRTime prtime = 0; |
- PKIX_PL_X500Name *subjectName = NULL; |
- PKIX_PL_Date *certValid = NULL; |
- PKIX_List *certList = NULL; |
- PKIX_PL_Cert *cert = NULL; |
- CERTCertList *pk11CertList = NULL; |
- CERTCertListNode *node = NULL; |
- CERTCertificate *nssCert = NULL; |
- CERTCertDBHandle *dbHandle = NULL; |
- |
- PRArenaPool *arena = NULL; |
- SECItem *nameItem = NULL; |
- void *wincx = NULL; |
- |
- PKIX_ENTER(CERTSTORE, "pkix_pl_Pk11CertStore_CertQuery"); |
- PKIX_NULLCHECK_TWO(params, pSelected); |
- |
- /* avoid multiple calls to retrieve a constant */ |
- PKIX_PL_NSSCALLRV(CERTSTORE, dbHandle, CERT_GetDefaultCertDB, ()); |
- |
- /* |
- * Any of the ComCertSelParams may be obtained and used to constrain |
- * the database query, to allow the use of a "smart" query. See |
- * pkix_certsel.h for a list of the PKIX_ComCertSelParams_Get* |
- * calls available. No corresponding "smart" queries exist at present, |
- * except for CERT_CreateSubjectCertList based on Subject. When others |
- * are added, corresponding code should be added to |
- * pkix_pl_Pk11CertStore_CertQuery to use them when appropriate |
- * selector parameters have been set. |
- */ |
- |
- PKIX_CHECK(PKIX_ComCertSelParams_GetSubject |
- (params, &subjectName, plContext), |
- PKIX_COMCERTSELPARAMSGETSUBJECTFAILED); |
- |
- PKIX_CHECK(PKIX_ComCertSelParams_GetCertificateValid |
- (params, &certValid, plContext), |
- PKIX_COMCERTSELPARAMSGETCERTIFICATEVALIDFAILED); |
- |
- /* If caller specified a Date, convert it to PRTime */ |
- if (certValid) { |
- PKIX_CHECK(pkix_pl_Date_GetPRTime |
- (certValid, &prtime, plContext), |
- PKIX_DATEGETPRTIMEFAILED); |
- validOnly = PR_TRUE; |
- } |
- |
- /* |
- * If we have the subject name for the desired subject, |
- * ask the database for Certs with that subject. Otherwise |
- * ask the database for all Certs. |
- */ |
- if (subjectName) { |
- arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
- if (arena) { |
- |
- PKIX_CHECK(pkix_pl_X500Name_GetDERName |
- (subjectName, arena, &nameItem, plContext), |
- PKIX_X500NAMEGETSECNAMEFAILED); |
- |
- if (nameItem) { |
- |
- PKIX_PL_NSSCALLRV |
- (CERTSTORE, |
- pk11CertList, |
- CERT_CreateSubjectCertList, |
- (NULL, dbHandle, nameItem, prtime, validOnly)); |
- } |
- PKIX_PL_NSSCALL |
- (CERTSTORE, PORT_FreeArena, (arena, PR_FALSE)); |
- arena = NULL; |
- } |
- |
- } else { |
- |
- PKIX_CHECK(pkix_pl_NssContext_GetWincx |
- ((PKIX_PL_NssContext *)plContext, &wincx), |
- PKIX_NSSCONTEXTGETWINCXFAILED); |
- |
- PKIX_PL_NSSCALLRV |
- (CERTSTORE, |
- pk11CertList, |
- PK11_ListCerts, |
- (PK11CertListAll, wincx)); |
- } |
- |
- if (pk11CertList) { |
- |
- PKIX_CHECK(PKIX_List_Create(&certList, plContext), |
- PKIX_LISTCREATEFAILED); |
- |
- for (node = CERT_LIST_HEAD(pk11CertList); |
- !(CERT_LIST_END(node, pk11CertList)); |
- node = CERT_LIST_NEXT(node)) { |
- |
- PKIX_PL_NSSCALLRV |
- (CERTSTORE, |
- nssCert, |
- CERT_DupCertificate, |
- (node->cert)); |
- |
- if (!nssCert) { |
- continue; /* just skip bad certs */ |
- } |
- |
- PKIX_CHECK_ONLY_FATAL(pkix_pl_Cert_CreateWithNSSCert |
- (nssCert, &cert, plContext), |
- PKIX_CERTCREATEWITHNSSCERTFAILED); |
- |
- if (PKIX_ERROR_RECEIVED) { |
- CERT_DestroyCertificate(nssCert); |
- nssCert = NULL; |
- continue; /* just skip bad certs */ |
- } |
- |
- PKIX_CHECK_ONLY_FATAL(PKIX_List_AppendItem |
- (certList, (PKIX_PL_Object *)cert, plContext), |
- PKIX_LISTAPPENDITEMFAILED); |
- |
- PKIX_DECREF(cert); |
- |
- } |
- |
- /* Don't throw away the list if one cert was bad! */ |
- pkixTempErrorReceived = PKIX_FALSE; |
- } |
- |
- *pSelected = certList; |
- certList = NULL; |
- |
-cleanup: |
- |
- if (pk11CertList) { |
- CERT_DestroyCertList(pk11CertList); |
- } |
- if (arena) { |
- PORT_FreeArena(arena, PR_FALSE); |
- } |
- |
- PKIX_DECREF(subjectName); |
- PKIX_DECREF(certValid); |
- PKIX_DECREF(cert); |
- PKIX_DECREF(certList); |
- |
- PKIX_RETURN(CERTSTORE); |
-} |
- |
-/* |
- * FUNCTION: pkix_pl_Pk11CertStore_ImportCrl |
- * DESCRIPTION: |
- * |
- * PARAMETERS: |
- * "params" |
- * Address of the ComCRLSelParams. Must be non-NULL. |
- * "pSelected" |
- * Address at which List will be stored. Must be non-NULL. |
- * "plContext" |
- * Platform-specific context pointer |
- * THREAD SAFETY: |
- * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
- * RETURNS: |
- * Returns NULL if the function succeeds. |
- * Returns a CertStore Error if the function fails in a non-fatal way. |
- * Returns a Fatal Error if the function fails in an unrecoverable way. |
- */ |
-static PKIX_Error * |
-pkix_pl_Pk11CertStore_ImportCrl( |
- PKIX_CertStore *store, |
- PKIX_PL_X500Name *issuerName, |
- PKIX_List *crlList, |
- void *plContext) |
-{ |
- CERTCertDBHandle *certHandle = CERT_GetDefaultCertDB(); |
- PKIX_PL_CRL *crl = NULL; |
- SECItem *derCrl = NULL; |
- |
- PKIX_ENTER(CERTSTORE, "pkix_pl_Pk11CertStore_ImportCrl"); |
- PKIX_NULLCHECK_TWO(store, plContext); |
- |
- if (!crlList) { |
- goto cleanup; |
- } |
- while (crlList->length > 0) { |
- PKIX_CHECK( |
- PKIX_List_GetItem(crlList, 0, (PKIX_PL_Object**)&crl, |
- plContext), |
- PKIX_LISTGETITEMFAILED); |
- |
- /* Delete crl from the list to keep controll of the |
- * last reference. crl need to be destroyed right after |
- * it released the ownership of the crl der. */ |
- PKIX_CHECK( |
- PKIX_List_DeleteItem(crlList, 0, plContext), |
- PKIX_LISTDELETEITEMFAILED); |
- |
- /* acquire the crlder ownership */ |
- pkixErrorResult = |
- PKIX_PL_CRL_ReleaseDerCrl(crl, &derCrl, plContext); |
- PORT_Assert(!pkixErrorResult && derCrl); |
- if (pkixErrorResult || !derCrl) { |
- /* All pkix delivered crls should be able to |
- * release their ders. */ |
- PKIX_DECREF(pkixErrorResult); |
- PKIX_DECREF(crl); |
- continue; |
- } |
- cert_CacheCRLByGeneralName(certHandle, derCrl, |
- crl->derGenName); |
- /* Do not check the status. If it is a SECFailure, |
- * derCrl is already destroyed. */ |
- derCrl = NULL; |
- PKIX_DECREF(crl); |
- } |
- |
-cleanup: |
- PKIX_DECREF(crl); |
- |
- PKIX_RETURN(CERTSTORE); |
-} |
- |
-static PKIX_Error * |
-NameCacheHasFetchedCrlInfo(PKIX_PL_Cert *pkixCert, |
- PRTime time, |
- PKIX_Boolean *pHasFetchedCrlInCache, |
- void *plContext) |
-{ |
- /* Returning true result in this case will mean, that case info |
- * is currect and should used as is. */ |
- NamedCRLCache* nameCrlCache = NULL; |
- PKIX_Boolean hasFetchedCrlInCache = PKIX_TRUE; |
- PKIX_List *dpList = NULL; |
- pkix_pl_CrlDp *dp = NULL; |
- CERTCertificate *cert; |
- PKIX_UInt32 dpIndex = 0; |
- SECStatus rv = SECSuccess; |
- PRTime reloadDelay = 0, badCrlInvalDelay = 0; |
- |
- PKIX_ENTER(CERTSTORE, "ChechCacheHasFetchedCrl"); |
- |
- cert = pkixCert->nssCert; |
- reloadDelay = |
- ((PKIX_PL_NssContext*)plContext)->crlReloadDelay * |
- PR_USEC_PER_SEC; |
- badCrlInvalDelay = |
- ((PKIX_PL_NssContext*)plContext)->badDerCrlReloadDelay * |
- PR_USEC_PER_SEC; |
- if (!time) { |
- time = PR_Now(); |
- } |
- /* If we already download the crl and inserted into the cache, then |
- * there is no need to check for fetched crl. We have what we have. */ |
- PKIX_CHECK( |
- PKIX_PL_Cert_GetCrlDp(pkixCert, &dpList, plContext), |
- PKIX_CERTGETCRLDPFAILED); |
- if (dpList && dpList->length) { |
- hasFetchedCrlInCache = PKIX_FALSE; |
- rv = cert_AcquireNamedCRLCache(&nameCrlCache); |
- if (rv != SECSuccess) { |
- PKIX_DECREF(dpList); |
- } |
- } else { |
- /* If no dp then treat it as if we already have |
- * a fetched crl. */ |
- PKIX_DECREF(dpList); |
- } |
- for (;!hasFetchedCrlInCache && |
- dpList && dpIndex < dpList->length;dpIndex++) { |
- SECItem **derDpNames = NULL; |
- pkixErrorResult = |
- PKIX_List_GetItem(dpList, dpIndex, (PKIX_PL_Object **)&dp, |
- plContext); |
- if (pkixErrorResult) { |
- PKIX_DECREF(pkixErrorResult); |
- continue; |
- } |
- if (dp->nssdp->distPointType == generalName) { |
- /* dp can only be created from nssdp. */ |
- derDpNames = dp->nssdp->derFullName; |
- } |
- while (derDpNames && *derDpNames != NULL) { |
- NamedCRLCacheEntry* cacheEntry = NULL; |
- const SECItem *derDpName = *derDpNames++; |
- rv = cert_FindCRLByGeneralName(nameCrlCache, derDpName, |
- &cacheEntry); |
- if (rv == SECSuccess && cacheEntry) { |
- if ((cacheEntry->inCRLCache && |
- (cacheEntry->successfulInsertionTime + reloadDelay > time || |
- (cacheEntry->dupe && |
- cacheEntry->lastAttemptTime + reloadDelay > time))) || |
- (cacheEntry->badDER && |
- cacheEntry->lastAttemptTime + badCrlInvalDelay > time)) { |
- hasFetchedCrlInCache = PKIX_TRUE; |
- break; |
- } |
- } |
- } |
- PKIX_DECREF(dp); |
- } |
-cleanup: |
- *pHasFetchedCrlInCache = hasFetchedCrlInCache; |
- if (nameCrlCache) { |
- cert_ReleaseNamedCRLCache(nameCrlCache); |
- } |
- PKIX_DECREF(dpList); |
- |
- PKIX_RETURN(CERTSTORE); |
-} |
- |
-/* |
- * FUNCTION: pkix_pl_Pk11CertStore_CheckCrl |
- * DESCRIPTION: |
- * |
- * PARAMETERS: |
- * "params" |
- * Address of the ComCRLSelParams. Must be non-NULL. |
- * "pSelected" |
- * Address at which List will be stored. Must be non-NULL. |
- * "plContext" |
- * Platform-specific context pointer |
- * THREAD SAFETY: |
- * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
- * RETURNS: |
- * Returns NULL if the function succeeds. |
- * Returns a CertStore Error if the function fails in a non-fatal way. |
- * Returns a Fatal Error if the function fails in an unrecoverable way. |
- */ |
-static PKIX_Error * |
-pkix_pl_Pk11CertStore_CheckRevByCrl( |
- PKIX_CertStore *store, |
- PKIX_PL_Cert *pkixCert, |
- PKIX_PL_Cert *pkixIssuer, |
- PKIX_PL_Date *date, |
- PKIX_Boolean crlDownloadDone, |
- PKIX_UInt32 *pReasonCode, |
- PKIX_RevocationStatus *pStatus, |
- void *plContext) |
-{ |
- PKIX_RevocationStatus pkixRevStatus = PKIX_RevStatus_NoInfo; |
- CERTRevocationStatus revStatus = certRevocationStatusUnknown; |
- PKIX_Boolean hasFetchedCrlInCache = PKIX_TRUE; |
- CERTCertificate *cert = NULL, *issuer = NULL; |
- SECStatus rv = SECSuccess; |
- void *wincx = NULL; |
- PRTime time = 0; |
- |
- PKIX_ENTER(CERTSTORE, "pkix_pl_Pk11CertStore_CheckRevByCrl"); |
- PKIX_NULLCHECK_FOUR(store, pkixCert, pkixIssuer, plContext); |
- |
- cert = pkixCert->nssCert; |
- issuer = pkixIssuer->nssCert; |
- if (date) { |
- PKIX_CHECK( |
- pkix_pl_Date_GetPRTime(date, &time, plContext), |
- PKIX_DATEGETPRTIMEFAILED); |
- } |
- PKIX_CHECK( |
- pkix_pl_NssContext_GetWincx((PKIX_PL_NssContext*)plContext, |
- &wincx), |
- PKIX_NSSCONTEXTGETWINCXFAILED); |
- /* No need to check any cDPs, since partitioned crls are not |
- * supported. If a ds does not point to partitioned crl, then |
- * the crl should be in issuer cache that is unrelated to any |
- * dp. Using NULL as a dp pointer to check it.*/ |
- rv = cert_CheckCertRevocationStatus(cert, issuer, NULL, |
- /* Will not validate the signature |
- * on the crl if time is not specified.*/ |
- time, wincx, &revStatus, pReasonCode); |
- if (rv == SECFailure) { |
- pkixRevStatus = PKIX_RevStatus_Revoked; |
- goto cleanup; |
- } |
- if (crlDownloadDone) { |
- if (revStatus == certRevocationStatusRevoked) { |
- pkixRevStatus = PKIX_RevStatus_Revoked; |
- } else if (revStatus == certRevocationStatusValid) { |
- pkixRevStatus = PKIX_RevStatus_Success; |
- } |
- } else { |
- pkixErrorResult = |
- NameCacheHasFetchedCrlInfo(pkixCert, time, &hasFetchedCrlInCache, |
- plContext); |
- if (pkixErrorResult) { |
- goto cleanup; |
- } |
- if (revStatus == certRevocationStatusRevoked && |
- (hasFetchedCrlInCache || |
- *pReasonCode != crlEntryReasoncertificatedHold)) { |
- pkixRevStatus = PKIX_RevStatus_Revoked; |
- } else if (revStatus == certRevocationStatusValid && |
- hasFetchedCrlInCache) { |
- pkixRevStatus = PKIX_RevStatus_Success; |
- } |
- } |
-cleanup: |
- *pStatus = pkixRevStatus; |
- |
- PKIX_RETURN(CERTSTORE); |
-} |
- |
- |
-/* |
- * FUNCTION: pkix_pl_Pk11CertStore_GetCert |
- * (see description of PKIX_CertStore_CertCallback in pkix_certstore.h) |
- */ |
-PKIX_Error * |
-pkix_pl_Pk11CertStore_GetCert( |
- PKIX_CertStore *store, |
- PKIX_CertSelector *selector, |
- PKIX_VerifyNode *parentVerifyNode, |
- void **pNBIOContext, |
- PKIX_List **pCertList, |
- void *plContext) |
-{ |
- PKIX_UInt32 i = 0; |
- PKIX_UInt32 numFound = 0; |
- PKIX_PL_Cert *candidate = NULL; |
- PKIX_List *selected = NULL; |
- PKIX_List *filtered = NULL; |
- PKIX_CertSelector_MatchCallback selectorCallback = NULL; |
- PKIX_CertStore_CheckTrustCallback trustCallback = NULL; |
- PKIX_ComCertSelParams *params = NULL; |
- PKIX_Boolean cacheFlag = PKIX_FALSE; |
- PKIX_VerifyNode *verifyNode = NULL; |
- PKIX_Error *selectorError = NULL; |
- |
- PKIX_ENTER(CERTSTORE, "pkix_pl_Pk11CertStore_GetCert"); |
- PKIX_NULLCHECK_FOUR(store, selector, pNBIOContext, pCertList); |
- |
- *pNBIOContext = NULL; /* We don't use non-blocking I/O */ |
- |
- PKIX_CHECK(PKIX_CertSelector_GetMatchCallback |
- (selector, &selectorCallback, plContext), |
- PKIX_CERTSELECTORGETMATCHCALLBACKFAILED); |
- |
- PKIX_CHECK(PKIX_CertSelector_GetCommonCertSelectorParams |
- (selector, ¶ms, plContext), |
- PKIX_CERTSELECTORGETCOMCERTSELPARAMSFAILED); |
- |
- PKIX_CHECK(pkix_pl_Pk11CertStore_CertQuery |
- (params, &selected, plContext), |
- PKIX_PK11CERTSTORECERTQUERYFAILED); |
- |
- if (selected) { |
- PKIX_CHECK(PKIX_List_GetLength(selected, &numFound, plContext), |
- PKIX_LISTGETLENGTHFAILED); |
- } |
- |
- PKIX_CHECK(PKIX_CertStore_GetCertStoreCacheFlag |
- (store, &cacheFlag, plContext), |
- PKIX_CERTSTOREGETCERTSTORECACHEFLAGFAILED); |
- |
- PKIX_CHECK(PKIX_CertStore_GetTrustCallback |
- (store, &trustCallback, plContext), |
- PKIX_CERTSTOREGETTRUSTCALLBACKFAILED); |
- |
- PKIX_CHECK(PKIX_List_Create(&filtered, plContext), |
- PKIX_LISTCREATEFAILED); |
- |
- for (i = 0; i < numFound; i++) { |
- PKIX_CHECK_ONLY_FATAL(PKIX_List_GetItem |
- (selected, |
- i, |
- (PKIX_PL_Object **)&candidate, |
- plContext), |
- PKIX_LISTGETITEMFAILED); |
- |
- if (PKIX_ERROR_RECEIVED) { |
- continue; /* just skip bad certs */ |
- } |
- |
- selectorError = |
- selectorCallback(selector, candidate, plContext); |
- if (!selectorError) { |
- PKIX_CHECK(PKIX_PL_Cert_SetCacheFlag |
- (candidate, cacheFlag, plContext), |
- PKIX_CERTSETCACHEFLAGFAILED); |
- |
- if (trustCallback) { |
- PKIX_CHECK(PKIX_PL_Cert_SetTrustCertStore |
- (candidate, store, plContext), |
- PKIX_CERTSETTRUSTCERTSTOREFAILED); |
- } |
- |
- PKIX_CHECK_ONLY_FATAL(PKIX_List_AppendItem |
- (filtered, |
- (PKIX_PL_Object *)candidate, |
- plContext), |
- PKIX_LISTAPPENDITEMFAILED); |
- } else if (parentVerifyNode) { |
- PKIX_CHECK_FATAL( |
- pkix_VerifyNode_Create(candidate, 0, selectorError, |
- &verifyNode, plContext), |
- PKIX_VERIFYNODECREATEFAILED); |
- PKIX_CHECK_FATAL( |
- pkix_VerifyNode_AddToTree(parentVerifyNode, |
- verifyNode, |
- plContext), |
- PKIX_VERIFYNODEADDTOTREEFAILED); |
- PKIX_DECREF(verifyNode); |
- } |
- PKIX_DECREF(selectorError); |
- PKIX_DECREF(candidate); |
- } |
- |
- /* Don't throw away the list if one cert was bad! */ |
- pkixTempErrorReceived = PKIX_FALSE; |
- |
- *pCertList = filtered; |
- filtered = NULL; |
- |
-cleanup: |
-fatal: |
- PKIX_DECREF(filtered); |
- PKIX_DECREF(candidate); |
- PKIX_DECREF(selected); |
- PKIX_DECREF(params); |
- PKIX_DECREF(verifyNode); |
- PKIX_DECREF(selectorError); |
- |
- PKIX_RETURN(CERTSTORE); |
-} |
- |
-static PKIX_Error * |
-RemovePartitionedDpsFromList(PKIX_List *dpList, PKIX_PL_Date *date, |
- void *plContext) |
-{ |
- NamedCRLCache* nameCrlCache = NULL; |
- pkix_pl_CrlDp *dp = NULL; |
- int dpIndex = 0; |
- PRTime time; |
- PRTime reloadDelay = 0, badCrlInvalDelay = 0; |
- SECStatus rv; |
- |
- PKIX_ENTER(CERTSTORE, "pkix_pl_Pk11CertStore_ListRemovePrtDp"); |
- |
- if (!dpList || !dpList->length) { |
- PKIX_RETURN(CERTSTORE); |
- } |
- reloadDelay = |
- ((PKIX_PL_NssContext*)plContext)->crlReloadDelay * |
- PR_USEC_PER_SEC; |
- badCrlInvalDelay = |
- ((PKIX_PL_NssContext*)plContext)->badDerCrlReloadDelay * |
- PR_USEC_PER_SEC; |
- PKIX_CHECK(pkix_pl_Date_GetPRTime(date, &time, plContext), |
- PKIX_DATEGETPRTIMEFAILED); |
- rv = cert_AcquireNamedCRLCache(&nameCrlCache); |
- if (rv == SECFailure) { |
- /* Baling out. Wont find out any thing useful. */ |
- PKIX_RETURN(CERTSTORE); |
- } |
- while (dpIndex < dpList->length) { |
- SECItem **derDpNames = NULL; |
- PKIX_Boolean removeDp = PKIX_FALSE; |
- |
- PKIX_CHECK( |
- PKIX_List_GetItem(dpList, dpIndex, (PKIX_PL_Object **)&dp, |
- plContext), |
- PKIX_LISTGETITEMFAILED); |
- if (!dp->isPartitionedByReasonCode) { |
- /* See if we know about this dp anything why we should |
- * not use it to download a crl. */ |
- if (dp->nssdp->distPointType == generalName) { |
- /* dp can only be created from nssdp. */ |
- derDpNames = dp->nssdp->derFullName; |
- } else { |
- removeDp = PKIX_TRUE; |
- } |
- while (derDpNames && *derDpNames != NULL) { |
- NamedCRLCacheEntry* cacheEntry = NULL; |
- const SECItem *derDpName = *derDpNames++; |
- /* Removing from the list all dps that we know about. */ |
- rv = cert_FindCRLByGeneralName(nameCrlCache, derDpName, |
- &cacheEntry); |
- if (rv && cacheEntry) { |
- if (cacheEntry->unsupported || |
- (cacheEntry->inCRLCache && |
- (cacheEntry->successfulInsertionTime + reloadDelay > time || |
- (cacheEntry->dupe && |
- cacheEntry->lastAttemptTime + reloadDelay > time))) || |
- (cacheEntry->badDER && |
- cacheEntry->lastAttemptTime + badCrlInvalDelay > time)) { |
- removeDp = PKIX_TRUE; |
- } |
- } |
- } |
- } else { |
- /* Remove dp that point to a partitioned crl . RFC 5280 |
- * recommends against crl partitioned by reason code. |
- * Will skip such crls */ |
- removeDp = PKIX_TRUE; |
- } |
- if (removeDp) { |
- PKIX_CHECK_ONLY_FATAL( |
- pkix_List_Remove(dpList,(PKIX_PL_Object*)dp, |
- plContext), |
- PKIX_LISTGETITEMFAILED); |
- } else { |
- dpIndex += 1; |
- } |
- PKIX_DECREF(dp); |
- } |
- |
-cleanup: |
- if (nameCrlCache) { |
- cert_ReleaseNamedCRLCache(nameCrlCache); |
- } |
- PKIX_DECREF(dp); |
- |
- PKIX_RETURN(CERTSTORE); |
-} |
- |
-/* |
- * FUNCTION: pkix_pl_Pk11CertStore_DownloadCrl |
- */ |
-static PKIX_Error * |
-DownloadCrl(pkix_pl_CrlDp *dp, PKIX_PL_CRL **crl, |
- const SEC_HttpClientFcnV1 *hcv1, void *plContext) |
-{ |
- char *location = NULL; |
- char *hostname = NULL; |
- char *path = NULL; |
- PRUint16 port; |
- SEC_HTTP_SERVER_SESSION pServerSession = NULL; |
- SEC_HTTP_REQUEST_SESSION pRequestSession = NULL; |
- PRUint16 myHttpResponseCode; |
- const char *myHttpResponseData = NULL; |
- PRUint32 myHttpResponseDataLen; |
- SECItem *uri = NULL; |
- SECItem *derCrlCopy = NULL; |
- CERTSignedCrl *nssCrl = NULL; |
- CERTGeneralName *genName = NULL; |
- PKIX_Int32 savedError = -1; |
- SECItem **derGenNames = NULL; |
- SECItem *derGenName = NULL; |
- |
- PKIX_ENTER(CERTSTORE, "pkix_pl_Pk11CertStore_DownloadCrl"); |
- |
- /* Do not support dps others than a one with GeneralName |
- * name type. */ |
- if (dp->distPointType != generalName || |
- !dp->nssdp->derFullName) { |
- PKIX_ERROR(PKIX_UNSUPPORTEDCRLDPTYPE); |
- } |
- genName = dp->name.fullName; |
- derGenNames = dp->nssdp->derFullName; |
- do { |
- derGenName = *derGenNames; |
- do { |
- if (!derGenName || |
- !genName->name.other.data) { |
- /* get to next name if no data. */ |
- savedError = PKIX_UNSUPPORTEDCRLDPTYPE; |
- break; |
- } |
- uri = &genName->name.other; |
- location = (char*)PR_Malloc(1 + uri->len); |
- if (!location) { |
- savedError = PKIX_ALLOCERROR; |
- break; |
- } |
- PORT_Memcpy(location, uri->data, uri->len); |
- location[uri->len] = 0; |
- if (CERT_ParseURL(location, &hostname, |
- &port, &path) != SECSuccess) { |
- PORT_SetError(SEC_ERROR_BAD_CRL_DP_URL); |
- savedError = PKIX_URLPARSINGFAILED; |
- break; |
- } |
- |
- PORT_Assert(hostname != NULL); |
- PORT_Assert(path != NULL); |
- |
- if ((*hcv1->createSessionFcn)(hostname, port, |
- &pServerSession) != SECSuccess) { |
- PORT_SetError(SEC_ERROR_BAD_CRL_DP_URL); |
- savedError = PKIX_URLPARSINGFAILED; |
- break; |
- } |
- |
- if ((*hcv1->createFcn)(pServerSession, "http", path, "GET", |
- /* Users with slow connections might not get CRL revocation |
- checking for certs that use big CRLs because of the timeout |
- We absolutely need code that limits our retry attempts. |
- */ |
- PR_SecondsToInterval( |
- ((PKIX_PL_NssContext*)plContext)->timeoutSeconds), |
- &pRequestSession) != SECSuccess) { |
- savedError = PKIX_HTTPSERVERERROR; |
- break; |
- } |
- |
- myHttpResponseDataLen = |
- ((PKIX_PL_NssContext*)plContext)->maxResponseLength; |
- if (myHttpResponseDataLen < PKIX_DEFAULT_MAX_CRL_RESPONSE_LENGTH) |
- myHttpResponseDataLen = PKIX_DEFAULT_MAX_CRL_RESPONSE_LENGTH; |
- |
- /* We use a non-zero timeout, which means: |
- - the client will use blocking I/O |
- - TryFcn will not return WOULD_BLOCK nor a poll descriptor |
- - it's sufficient to call TryFcn once |
- */ |
- /* we don't want result objects larger than this: */ |
- if ((*hcv1->trySendAndReceiveFcn)( |
- pRequestSession, |
- NULL, |
- &myHttpResponseCode, |
- NULL, |
- NULL, |
- &myHttpResponseData, |
- &myHttpResponseDataLen) != SECSuccess) { |
- savedError = PKIX_HTTPSERVERERROR; |
- break; |
- } |
- |
- if (myHttpResponseCode != 200) { |
- savedError = PKIX_HTTPSERVERERROR; |
- break; |
- } |
- } while(0); |
- if (!myHttpResponseData) { |
- /* Going to the next one. */ |
- genName = CERT_GetNextGeneralName(genName); |
- derGenNames++; |
- } |
- /* Staing in the loop through all the names until |
- * we have a successful download. */ |
- } while (!myHttpResponseData && *derGenNames && |
- genName != dp->name.fullName); |
- /* Need this name to track the crl source location. */ |
- PORT_Assert(derGenName); |
- |
- if (!myHttpResponseData) { |
- /* Generating fake bad CRL to keep track of this dp */ |
- SECItem derCrl = {siBuffer, (void*)"BadCrl", 6 }; |
- |
- derCrlCopy = SECITEM_DupItem(&derCrl); |
- if (!derCrlCopy) { |
- PKIX_ERROR(PKIX_ALLOCERROR); |
- } |
- derGenName = *dp->nssdp->derFullName; |
- } else { |
- SECItem derCrl = { siBuffer, |
- (void*)myHttpResponseData, |
- myHttpResponseDataLen }; |
- derCrlCopy = SECITEM_DupItem(&derCrl); |
- if (!derCrlCopy) { |
- PKIX_ERROR(PKIX_ALLOCERROR); |
- } |
- /* crl will be based on derCrlCopy, but will not own the der. */ |
- nssCrl = |
- CERT_DecodeDERCrlWithFlags(NULL, derCrlCopy, SEC_CRL_TYPE, |
- CRL_DECODE_DONT_COPY_DER | |
- CRL_DECODE_SKIP_ENTRIES); |
- } |
- /* pkix crl owns the der. */ |
- PKIX_CHECK( |
- pkix_pl_CRL_CreateWithSignedCRL(nssCrl, derCrlCopy, |
- derGenName, |
- crl, plContext), |
- PKIX_CRLCREATEWITHSIGNEDCRLFAILED); |
- /* pkix crl now own both objects. */ |
- derCrlCopy = NULL; |
- nssCrl = NULL; |
- |
-cleanup: |
- if (derCrlCopy) |
- PORT_Free(derCrlCopy); |
- if (nssCrl) |
- SEC_DestroyCrl(nssCrl); |
- if (pRequestSession != NULL) |
- (*hcv1->freeFcn)(pRequestSession); |
- if (pServerSession != NULL) |
- (*hcv1->freeSessionFcn)(pServerSession); |
- if (path != NULL) |
- PORT_Free(path); |
- if (hostname != NULL) |
- PORT_Free(hostname); |
- if (location) { |
- PORT_Free(location); |
- } |
- |
- PKIX_RETURN(CERTSTORE); |
-} |
- |
-/* |
- * FUNCTION: pkix_pl_Pk11CertStore_GetCRL |
- * (see description of PKIX_CertStore_CRLCallback in pkix_certstore.h) |
- */ |
-static PKIX_Error * |
-pkix_pl_Pk11CertStore_GetCRL( |
- PKIX_CertStore *store, |
- PKIX_CRLSelector *selector, |
- void **pNBIOContext, |
- PKIX_List **pCrlList, |
- void *plContext) |
-{ |
- PKIX_UInt32 dpIndex = 0; |
- PKIX_PL_CRL *crl = NULL; |
- PKIX_List *crlList = NULL; |
- PKIX_List *dpList = NULL; |
- pkix_pl_CrlDp *dp = NULL; |
- PKIX_PL_Date *date = NULL; |
- const SEC_HttpClientFcn *registeredHttpClient = NULL; |
- |
- PKIX_ENTER(CERTSTORE, "pkix_pl_Pk11CertStore_GetCRL"); |
- PKIX_NULLCHECK_THREE(store, pNBIOContext, pCrlList); |
- PKIX_NULLCHECK_TWO(selector, selector->params); |
- |
- registeredHttpClient = SEC_GetRegisteredHttpClient(); |
- if (!registeredHttpClient || registeredHttpClient->version != 1) { |
- goto cleanup; |
- } |
- dpList = selector->params->crldpList; |
- date = selector->params->date; |
- PKIX_CHECK( |
- RemovePartitionedDpsFromList(dpList, date, |
- plContext), |
- PKIX_FAILTOREMOVEDPFROMLIST); |
- for (;dpIndex < dpList->length;dpIndex++) { |
- PKIX_DECREF(dp); |
- pkixErrorResult = |
- PKIX_List_GetItem(dpList, dpIndex, |
- (PKIX_PL_Object **)&dp, |
- plContext); |
- if (pkixErrorResult) { |
- PKIX_DECREF(pkixErrorResult); |
- continue; |
- } |
- pkixErrorResult = |
- DownloadCrl(dp, &crl, |
- ®isteredHttpClient->fcnTable.ftable1, |
- plContext); |
- if (pkixErrorResult || !crl) { |
- /* continue to next dp in case of unsuccesfull |
- * download attempt. */ |
- PKIX_DECREF(pkixErrorResult); |
- continue; |
- } |
- if (!crlList) { |
- PKIX_CHECK(PKIX_List_Create(&crlList, plContext), |
- PKIX_LISTCREATEFAILED); |
- } |
- pkixErrorResult = |
- PKIX_List_AppendItem(crlList, (PKIX_PL_Object *)crl, |
- plContext); |
- if (pkixErrorResult) { |
- PKIX_DECREF(pkixErrorResult); |
- } |
- PKIX_DECREF(crl); |
- } |
- *pCrlList = crlList; |
- crlList = NULL; |
- |
-cleanup: |
- PKIX_DECREF(dp); |
- PKIX_DECREF(crl); |
- PKIX_DECREF(crlList); |
- |
- PKIX_RETURN(CERTSTORE); |
-} |
- |
- |
-/* --Public-Pk11CertStore-Functions----------------------------------- */ |
- |
-/* |
- * FUNCTION: PKIX_PL_Pk11CertStore_Create |
- * (see comments in pkix_samples_modules.h) |
- */ |
-PKIX_Error * |
-PKIX_PL_Pk11CertStore_Create( |
- PKIX_CertStore **pCertStore, |
- void *plContext) |
-{ |
- PKIX_CertStore *certStore = NULL; |
- |
- PKIX_ENTER(CERTSTORE, "PKIX_PL_Pk11CertStore_Create"); |
- PKIX_NULLCHECK_ONE(pCertStore); |
- |
- PKIX_CHECK(PKIX_CertStore_Create |
- (pkix_pl_Pk11CertStore_GetCert, |
- pkix_pl_Pk11CertStore_GetCRL, |
- NULL, /* getCertContinue */ |
- NULL, /* getCrlContinue */ |
- pkix_pl_Pk11CertStore_CheckTrust, |
- pkix_pl_Pk11CertStore_ImportCrl, |
- pkix_pl_Pk11CertStore_CheckRevByCrl, |
- NULL, |
- PKIX_TRUE, /* cache flag */ |
- PKIX_TRUE, /* local - no network I/O */ |
- &certStore, |
- plContext), |
- PKIX_CERTSTORECREATEFAILED); |
- |
- *pCertStore = certStore; |
- |
-cleanup: |
- |
- PKIX_RETURN(CERTSTORE); |
-} |