1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
14 * The Original Code is the PKIX-C library.
16 * The Initial Developer of the Original Code is
17 * Sun Microsystems, Inc.
18 * Portions created by the Initial Developer are
19 * Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved.
22 * Sun Microsystems, Inc.
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 * pkix_pl_pk11certstore.c
40 * PKCS11CertStore Function Definitions
44 #include "pkix_pl_pk11certstore.h"
47 * PKIX_DEFAULT_MAX_RESPONSE_LENGTH (64 * 1024) is too small for downloading
48 * CRLs. We observed CRLs of sizes 338759 and 439035 in practice. So we
49 * need to use a higher max response length for CRLs.
51 #define PKIX_DEFAULT_MAX_CRL_RESPONSE_LENGTH (512 * 1024)
53 /* --Private-Pk11CertStore-Functions---------------------------------- */
56 * FUNCTION: pkix_pl_Pk11CertStore_CheckTrust
58 * This function checks the trust status of this "cert" that was retrieved
59 * from the CertStore "store" and returns its trust status at "pTrusted".
63 * Address of the CertStore. Must be non-NULL.
65 * Address of the Cert. Must be non-NULL.
67 * Address of PKIX_Boolean where the "cert" trust status is returned.
70 * Platform-specific context pointer
72 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
74 * Returns NULL if the function succeeds.
75 * Returns a CertStore Error if the function fails in a non-fatal way.
76 * Returns a Fatal Error if the function fails in an unrecoverable way.
79 pkix_pl_Pk11CertStore_CheckTrust(
80 PKIX_CertStore *store,
82 PKIX_Boolean *pTrusted,
85 SECStatus rv = SECFailure;
86 PKIX_Boolean trusted = PKIX_FALSE;
87 SECCertUsage certUsage = 0;
88 SECCertificateUsage certificateUsage;
89 unsigned int requiredFlags;
90 SECTrustType trustType;
93 PKIX_ENTER(CERTSTORE, "pkix_pl_Pk11CertStore_CheckTrust");
94 PKIX_NULLCHECK_THREE(store, cert, pTrusted);
95 PKIX_NULLCHECK_ONE(cert->nssCert);
97 certificateUsage = ((PKIX_PL_NssContext*)plContext)->certificateUsage;
99 /* ensure we obtained a single usage bit only */
100 PORT_Assert(!(certificateUsage & (certificateUsage - 1)));
102 /* convert SECertificateUsage (bit mask) to SECCertUsage (enum) */
103 while (0 != (certificateUsage = certificateUsage >> 1)) { certUsage++; }
105 rv = CERT_TrustFlagsForCACertUsage(certUsage, &requiredFlags, &trustType);
106 if (rv == SECSuccess) {
107 rv = CERT_GetCertTrust(cert->nssCert, &trust);
110 if (rv == SECSuccess) {
111 unsigned int certFlags;
113 if (certUsage != certUsageAnyCA &&
114 certUsage != certUsageStatusResponder) {
115 CERTCertificate *nssCert = cert->nssCert;
117 if (certUsage == certUsageVerifyCA) {
118 if (nssCert->nsCertType & NS_CERT_TYPE_EMAIL_CA) {
119 trustType = trustEmail;
120 } else if (nssCert->nsCertType & NS_CERT_TYPE_SSL_CA) {
121 trustType = trustSSL;
123 trustType = trustObjectSigning;
127 certFlags = SEC_GET_TRUST_FLAGS((&trust), trustType);
128 if ((certFlags & requiredFlags) == requiredFlags) {
132 for (trustType = trustSSL; trustType < trustTypeNone;
135 SEC_GET_TRUST_FLAGS((&trust), trustType);
136 if ((certFlags & requiredFlags) == requiredFlags) {
146 PKIX_RETURN(CERTSTORE);
150 * FUNCTION: pkix_pl_Pk11CertStore_CertQuery
153 * This function obtains from the database the Certs specified by the
154 * ComCertSelParams pointed to by "params" and stores the resulting
155 * List at "pSelected". If no matching Certs are found, a NULL pointer
158 * This function uses a "smart" database query if the Subject has been set
159 * in ComCertSelParams. Otherwise, it uses a very inefficient call to
160 * retrieve all Certs in the database (and run them through the selector).
164 * Address of the ComCertSelParams. Must be non-NULL.
166 * Address at which List will be stored. Must be non-NULL.
168 * Platform-specific context pointer
170 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
172 * Returns NULL if the function succeeds.
173 * Returns a CertStore Error if the function fails in a non-fatal way.
174 * Returns a Fatal Error if the function fails in an unrecoverable way.
177 pkix_pl_Pk11CertStore_CertQuery(
178 PKIX_ComCertSelParams *params,
179 PKIX_List **pSelected,
182 PRBool validOnly = PR_FALSE;
184 PKIX_PL_X500Name *subjectName = NULL;
185 PKIX_PL_Date *certValid = NULL;
186 PKIX_List *certList = NULL;
187 PKIX_PL_Cert *cert = NULL;
188 CERTCertList *pk11CertList = NULL;
189 CERTCertListNode *node = NULL;
190 CERTCertificate *nssCert = NULL;
191 CERTCertDBHandle *dbHandle = NULL;
193 PRArenaPool *arena = NULL;
194 SECItem *nameItem = NULL;
197 PKIX_ENTER(CERTSTORE, "pkix_pl_Pk11CertStore_CertQuery");
198 PKIX_NULLCHECK_TWO(params, pSelected);
200 /* avoid multiple calls to retrieve a constant */
201 PKIX_PL_NSSCALLRV(CERTSTORE, dbHandle, CERT_GetDefaultCertDB, ());
204 * Any of the ComCertSelParams may be obtained and used to constrain
205 * the database query, to allow the use of a "smart" query. See
206 * pkix_certsel.h for a list of the PKIX_ComCertSelParams_Get*
207 * calls available. No corresponding "smart" queries exist at present,
208 * except for CERT_CreateSubjectCertList based on Subject. When others
209 * are added, corresponding code should be added to
210 * pkix_pl_Pk11CertStore_CertQuery to use them when appropriate
211 * selector parameters have been set.
214 PKIX_CHECK(PKIX_ComCertSelParams_GetSubject
215 (params, &subjectName, plContext),
216 PKIX_COMCERTSELPARAMSGETSUBJECTFAILED);
218 PKIX_CHECK(PKIX_ComCertSelParams_GetCertificateValid
219 (params, &certValid, plContext),
220 PKIX_COMCERTSELPARAMSGETCERTIFICATEVALIDFAILED);
222 /* If caller specified a Date, convert it to PRTime */
224 PKIX_CHECK(pkix_pl_Date_GetPRTime
225 (certValid, &prtime, plContext),
226 PKIX_DATEGETPRTIMEFAILED);
231 * If we have the subject name for the desired subject,
232 * ask the database for Certs with that subject. Otherwise
233 * ask the database for all Certs.
236 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
239 PKIX_CHECK(pkix_pl_X500Name_GetDERName
240 (subjectName, arena, &nameItem, plContext),
241 PKIX_X500NAMEGETSECNAMEFAILED);
248 CERT_CreateSubjectCertList,
249 (NULL, dbHandle, nameItem, prtime, validOnly));
252 (CERTSTORE, PORT_FreeArena, (arena, PR_FALSE));
258 PKIX_CHECK(pkix_pl_NssContext_GetWincx
259 ((PKIX_PL_NssContext *)plContext, &wincx),
260 PKIX_NSSCONTEXTGETWINCXFAILED);
266 (PK11CertListAll, wincx));
271 PKIX_CHECK(PKIX_List_Create(&certList, plContext),
272 PKIX_LISTCREATEFAILED);
274 for (node = CERT_LIST_HEAD(pk11CertList);
275 !(CERT_LIST_END(node, pk11CertList));
276 node = CERT_LIST_NEXT(node)) {
281 CERT_NewTempCertificate,
283 &(node->cert->derCert),
286 PR_TRUE)); /* copyDER */
289 continue; /* just skip bad certs */
292 PKIX_CHECK_ONLY_FATAL(pkix_pl_Cert_CreateWithNSSCert
293 (nssCert, &cert, plContext),
294 PKIX_CERTCREATEWITHNSSCERTFAILED);
296 if (PKIX_ERROR_RECEIVED) {
297 CERT_DestroyCertificate(nssCert);
299 continue; /* just skip bad certs */
302 PKIX_CHECK_ONLY_FATAL(PKIX_List_AppendItem
303 (certList, (PKIX_PL_Object *)cert, plContext),
304 PKIX_LISTAPPENDITEMFAILED);
310 /* Don't throw away the list if one cert was bad! */
311 pkixTempErrorReceived = PKIX_FALSE;
314 *pSelected = certList;
320 CERT_DestroyCertList(pk11CertList);
323 PORT_FreeArena(arena, PR_FALSE);
326 PKIX_DECREF(subjectName);
327 PKIX_DECREF(certValid);
329 PKIX_DECREF(certList);
331 PKIX_RETURN(CERTSTORE);
335 * FUNCTION: pkix_pl_Pk11CertStore_ImportCrl
340 * Address of the ComCRLSelParams. Must be non-NULL.
342 * Address at which List will be stored. Must be non-NULL.
344 * Platform-specific context pointer
346 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
348 * Returns NULL if the function succeeds.
349 * Returns a CertStore Error if the function fails in a non-fatal way.
350 * Returns a Fatal Error if the function fails in an unrecoverable way.
353 pkix_pl_Pk11CertStore_ImportCrl(
354 PKIX_CertStore *store,
355 PKIX_PL_X500Name *issuerName,
359 CERTCertDBHandle *certHandle = CERT_GetDefaultCertDB();
360 PKIX_PL_CRL *crl = NULL;
361 SECItem *derCrl = NULL;
363 PKIX_ENTER(CERTSTORE, "pkix_pl_Pk11CertStore_ImportCrl");
364 PKIX_NULLCHECK_TWO(store, plContext);
369 while (crlList->length > 0) {
371 PKIX_List_GetItem(crlList, 0, (PKIX_PL_Object**)&crl,
373 PKIX_LISTGETITEMFAILED);
375 /* Delete crl from the list to keep controll of the
376 * last reference. crl need to be destroyed right after
377 * it released the ownership of the crl der. */
379 PKIX_List_DeleteItem(crlList, 0, plContext),
380 PKIX_LISTDELETEITEMFAILED);
382 /* acquire the crlder ownership */
384 PKIX_PL_CRL_ReleaseDerCrl(crl, &derCrl, plContext);
385 PORT_Assert(!pkixErrorResult && derCrl);
386 if (pkixErrorResult || !derCrl) {
387 /* All pkix delivered crls should be able to
388 * release their ders. */
389 PKIX_DECREF(pkixErrorResult);
393 cert_CacheCRLByGeneralName(certHandle, derCrl,
395 /* Do not check the status. If it is a SECFailure,
396 * derCrl is already destroyed. */
404 PKIX_RETURN(CERTSTORE);
408 NameCacheHasFetchedCrlInfo(PKIX_PL_Cert *pkixCert,
410 PKIX_Boolean *pHasFetchedCrlInCache,
413 /* Returning true result in this case will mean, that case info
414 * is currect and should used as is. */
415 NamedCRLCache* nameCrlCache = NULL;
416 PKIX_Boolean hasFetchedCrlInCache = PKIX_TRUE;
417 PKIX_List *dpList = NULL;
418 pkix_pl_CrlDp *dp = NULL;
419 CERTCertificate *cert;
420 PKIX_UInt32 dpIndex = 0;
421 SECStatus rv = SECSuccess;
422 PRTime reloadDelay = 0, badCrlInvalDelay = 0;
424 PKIX_ENTER(CERTSTORE, "ChechCacheHasFetchedCrl");
426 cert = pkixCert->nssCert;
428 ((PKIX_PL_NssContext*)plContext)->crlReloadDelay *
431 ((PKIX_PL_NssContext*)plContext)->badDerCrlReloadDelay *
436 /* If we already download the crl and inserted into the cache, then
437 * there is no need to check for fetched crl. We have what we have. */
439 PKIX_PL_Cert_GetCrlDp(pkixCert, &dpList, plContext),
440 PKIX_CERTGETCRLDPFAILED);
441 if (dpList && dpList->length) {
442 hasFetchedCrlInCache = PKIX_FALSE;
443 rv = cert_AcquireNamedCRLCache(&nameCrlCache);
444 if (rv != SECSuccess) {
448 /* If no dp then treat it as if we already have
452 for (;!hasFetchedCrlInCache &&
453 dpList && dpIndex < dpList->length;dpIndex++) {
454 SECItem **derDpNames = NULL;
456 PKIX_List_GetItem(dpList, dpIndex, (PKIX_PL_Object **)&dp,
458 if (pkixErrorResult) {
459 PKIX_DECREF(pkixErrorResult);
462 if (dp->nssdp->distPointType == generalName) {
463 /* dp can only be created from nssdp. */
464 derDpNames = dp->nssdp->derFullName;
466 while (derDpNames && *derDpNames != NULL) {
467 NamedCRLCacheEntry* cacheEntry = NULL;
468 const SECItem *derDpName = *derDpNames++;
469 rv = cert_FindCRLByGeneralName(nameCrlCache, derDpName,
471 if (rv == SECSuccess && cacheEntry) {
472 if ((cacheEntry->inCRLCache &&
473 (cacheEntry->successfulInsertionTime + reloadDelay > time ||
475 cacheEntry->lastAttemptTime + reloadDelay > time))) ||
476 (cacheEntry->badDER &&
477 cacheEntry->lastAttemptTime + badCrlInvalDelay > time)) {
478 hasFetchedCrlInCache = PKIX_TRUE;
486 *pHasFetchedCrlInCache = hasFetchedCrlInCache;
488 cert_ReleaseNamedCRLCache(nameCrlCache);
492 PKIX_RETURN(CERTSTORE);
496 * FUNCTION: pkix_pl_Pk11CertStore_CheckCrl
501 * Address of the ComCRLSelParams. Must be non-NULL.
503 * Address at which List will be stored. Must be non-NULL.
505 * Platform-specific context pointer
507 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
509 * Returns NULL if the function succeeds.
510 * Returns a CertStore Error if the function fails in a non-fatal way.
511 * Returns a Fatal Error if the function fails in an unrecoverable way.
514 pkix_pl_Pk11CertStore_CheckRevByCrl(
515 PKIX_CertStore *store,
516 PKIX_PL_Cert *pkixCert,
517 PKIX_PL_Cert *pkixIssuer,
519 PKIX_Boolean crlDownloadDone,
520 PKIX_UInt32 *pReasonCode,
521 PKIX_RevocationStatus *pStatus,
524 PKIX_RevocationStatus pkixRevStatus = PKIX_RevStatus_NoInfo;
525 CERTRevocationStatus revStatus = certRevocationStatusUnknown;
526 PKIX_Boolean hasFetchedCrlInCache = PKIX_TRUE;
527 CERTCertificate *cert = NULL, *issuer = NULL;
528 SECStatus rv = SECSuccess;
532 PKIX_ENTER(CERTSTORE, "pkix_pl_Pk11CertStore_CheckRevByCrl");
533 PKIX_NULLCHECK_FOUR(store, pkixCert, pkixIssuer, plContext);
535 cert = pkixCert->nssCert;
536 issuer = pkixIssuer->nssCert;
539 pkix_pl_Date_GetPRTime(date, &time, plContext),
540 PKIX_DATEGETPRTIMEFAILED);
543 pkix_pl_NssContext_GetWincx((PKIX_PL_NssContext*)plContext,
545 PKIX_NSSCONTEXTGETWINCXFAILED);
546 /* No need to check any cDPs, since partitioned crls are not
547 * supported. If a ds does not point to partitioned crl, then
548 * the crl should be in issuer cache that is unrelated to any
549 * dp. Using NULL as a dp pointer to check it.*/
550 rv = cert_CheckCertRevocationStatus(cert, issuer, NULL,
551 /* Will not validate the signature
552 * on the crl if time is not specified.*/
553 time, wincx, &revStatus, pReasonCode);
554 if (rv == SECFailure) {
555 pkixRevStatus = PKIX_RevStatus_Revoked;
558 if (crlDownloadDone) {
559 if (revStatus == certRevocationStatusRevoked) {
560 pkixRevStatus = PKIX_RevStatus_Revoked;
561 } else if (revStatus == certRevocationStatusValid) {
562 pkixRevStatus = PKIX_RevStatus_Success;
566 NameCacheHasFetchedCrlInfo(pkixCert, time, &hasFetchedCrlInCache,
568 if (pkixErrorResult) {
571 if (revStatus == certRevocationStatusRevoked &&
572 (hasFetchedCrlInCache ||
573 *pReasonCode != crlEntryReasoncertificatedHold)) {
574 pkixRevStatus = PKIX_RevStatus_Revoked;
575 } else if (revStatus == certRevocationStatusValid &&
576 hasFetchedCrlInCache) {
577 pkixRevStatus = PKIX_RevStatus_Success;
581 *pStatus = pkixRevStatus;
583 PKIX_RETURN(CERTSTORE);
588 * FUNCTION: pkix_pl_Pk11CertStore_GetCert
589 * (see description of PKIX_CertStore_CertCallback in pkix_certstore.h)
592 pkix_pl_Pk11CertStore_GetCert(
593 PKIX_CertStore *store,
594 PKIX_CertSelector *selector,
595 PKIX_VerifyNode *parentVerifyNode,
597 PKIX_List **pCertList,
601 PKIX_UInt32 numFound = 0;
602 PKIX_PL_Cert *candidate = NULL;
603 PKIX_List *selected = NULL;
604 PKIX_List *filtered = NULL;
605 PKIX_CertSelector_MatchCallback selectorCallback = NULL;
606 PKIX_CertStore_CheckTrustCallback trustCallback = NULL;
607 PKIX_ComCertSelParams *params = NULL;
608 PKIX_Boolean cacheFlag = PKIX_FALSE;
609 PKIX_VerifyNode *verifyNode = NULL;
610 PKIX_Error *selectorError = NULL;
612 PKIX_ENTER(CERTSTORE, "pkix_pl_Pk11CertStore_GetCert");
613 PKIX_NULLCHECK_FOUR(store, selector, pNBIOContext, pCertList);
615 *pNBIOContext = NULL; /* We don't use non-blocking I/O */
617 PKIX_CHECK(PKIX_CertSelector_GetMatchCallback
618 (selector, &selectorCallback, plContext),
619 PKIX_CERTSELECTORGETMATCHCALLBACKFAILED);
621 PKIX_CHECK(PKIX_CertSelector_GetCommonCertSelectorParams
622 (selector, ¶ms, plContext),
623 PKIX_CERTSELECTORGETCOMCERTSELPARAMSFAILED);
625 PKIX_CHECK(pkix_pl_Pk11CertStore_CertQuery
626 (params, &selected, plContext),
627 PKIX_PK11CERTSTORECERTQUERYFAILED);
630 PKIX_CHECK(PKIX_List_GetLength(selected, &numFound, plContext),
631 PKIX_LISTGETLENGTHFAILED);
634 PKIX_CHECK(PKIX_CertStore_GetCertStoreCacheFlag
635 (store, &cacheFlag, plContext),
636 PKIX_CERTSTOREGETCERTSTORECACHEFLAGFAILED);
638 PKIX_CHECK(PKIX_CertStore_GetTrustCallback
639 (store, &trustCallback, plContext),
640 PKIX_CERTSTOREGETTRUSTCALLBACKFAILED);
642 PKIX_CHECK(PKIX_List_Create(&filtered, plContext),
643 PKIX_LISTCREATEFAILED);
645 for (i = 0; i < numFound; i++) {
646 PKIX_CHECK_ONLY_FATAL(PKIX_List_GetItem
649 (PKIX_PL_Object **)&candidate,
651 PKIX_LISTGETITEMFAILED);
653 if (PKIX_ERROR_RECEIVED) {
654 continue; /* just skip bad certs */
658 selectorCallback(selector, candidate, plContext);
659 if (!selectorError) {
660 PKIX_CHECK(PKIX_PL_Cert_SetCacheFlag
661 (candidate, cacheFlag, plContext),
662 PKIX_CERTSETCACHEFLAGFAILED);
665 PKIX_CHECK(PKIX_PL_Cert_SetTrustCertStore
666 (candidate, store, plContext),
667 PKIX_CERTSETTRUSTCERTSTOREFAILED);
670 PKIX_CHECK_ONLY_FATAL(PKIX_List_AppendItem
672 (PKIX_PL_Object *)candidate,
674 PKIX_LISTAPPENDITEMFAILED);
675 } else if (parentVerifyNode) {
677 pkix_VerifyNode_Create(candidate, 0, selectorError,
678 &verifyNode, plContext),
679 PKIX_VERIFYNODECREATEFAILED);
681 pkix_VerifyNode_AddToTree(parentVerifyNode,
684 PKIX_VERIFYNODEADDTOTREEFAILED);
685 PKIX_DECREF(verifyNode);
687 PKIX_DECREF(selectorError);
688 PKIX_DECREF(candidate);
691 /* Don't throw away the list if one cert was bad! */
692 pkixTempErrorReceived = PKIX_FALSE;
694 *pCertList = filtered;
699 PKIX_DECREF(filtered);
700 PKIX_DECREF(candidate);
701 PKIX_DECREF(selected);
703 PKIX_DECREF(verifyNode);
704 PKIX_DECREF(selectorError);
706 PKIX_RETURN(CERTSTORE);
710 RemovePartitionedDpsFromList(PKIX_List *dpList, PKIX_PL_Date *date,
713 NamedCRLCache* nameCrlCache = NULL;
714 pkix_pl_CrlDp *dp = NULL;
717 PRTime reloadDelay = 0, badCrlInvalDelay = 0;
720 PKIX_ENTER(CERTSTORE, "pkix_pl_Pk11CertStore_ListRemovePrtDp");
722 if (!dpList || !dpList->length) {
723 PKIX_RETURN(CERTSTORE);
726 ((PKIX_PL_NssContext*)plContext)->crlReloadDelay *
729 ((PKIX_PL_NssContext*)plContext)->badDerCrlReloadDelay *
731 PKIX_CHECK(pkix_pl_Date_GetPRTime(date, &time, plContext),
732 PKIX_DATEGETPRTIMEFAILED);
733 rv = cert_AcquireNamedCRLCache(&nameCrlCache);
734 if (rv == SECFailure) {
735 /* Baling out. Wont find out any thing useful. */
736 PKIX_RETURN(CERTSTORE);
738 while (dpIndex < dpList->length) {
739 SECItem **derDpNames = NULL;
740 PKIX_Boolean removeDp = PKIX_FALSE;
743 PKIX_List_GetItem(dpList, dpIndex, (PKIX_PL_Object **)&dp,
745 PKIX_LISTGETITEMFAILED);
746 if (!dp->isPartitionedByReasonCode) {
747 /* See if we know about this dp anything why we should
748 * not use it to download a crl. */
749 if (dp->nssdp->distPointType == generalName) {
750 /* dp can only be created from nssdp. */
751 derDpNames = dp->nssdp->derFullName;
753 removeDp = PKIX_TRUE;
755 while (derDpNames && *derDpNames != NULL) {
756 NamedCRLCacheEntry* cacheEntry = NULL;
757 const SECItem *derDpName = *derDpNames++;
758 /* Removing from the list all dps that we know about. */
759 rv = cert_FindCRLByGeneralName(nameCrlCache, derDpName,
761 if (rv && cacheEntry) {
762 if (cacheEntry->unsupported ||
763 (cacheEntry->inCRLCache &&
764 (cacheEntry->successfulInsertionTime + reloadDelay > time ||
766 cacheEntry->lastAttemptTime + reloadDelay > time))) ||
767 (cacheEntry->badDER &&
768 cacheEntry->lastAttemptTime + badCrlInvalDelay > time)) {
769 removeDp = PKIX_TRUE;
774 /* Remove dp that point to a partitioned crl . RFC 5280
775 * recommends against crl partitioned by reason code.
776 * Will skip such crls */
777 removeDp = PKIX_TRUE;
780 PKIX_CHECK_ONLY_FATAL(
781 pkix_List_Remove(dpList,(PKIX_PL_Object*)dp,
783 PKIX_LISTGETITEMFAILED);
792 cert_ReleaseNamedCRLCache(nameCrlCache);
796 PKIX_RETURN(CERTSTORE);
800 * FUNCTION: pkix_pl_Pk11CertStore_DownloadCrl
803 DownloadCrl(pkix_pl_CrlDp *dp, PKIX_PL_CRL **crl,
804 const SEC_HttpClientFcnV1 *hcv1, void *plContext)
806 char *location = NULL;
807 char *hostname = NULL;
810 SEC_HTTP_SERVER_SESSION pServerSession = NULL;
811 SEC_HTTP_REQUEST_SESSION pRequestSession = NULL;
812 PRUint16 myHttpResponseCode;
813 const char *myHttpResponseData = NULL;
814 PRUint32 myHttpResponseDataLen;
816 SECItem *derCrlCopy = NULL;
817 CERTSignedCrl *nssCrl = NULL;
818 CERTGeneralName *genName = NULL;
819 PKIX_Int32 savedError = -1;
820 SECItem **derGenNames = NULL;
821 SECItem *derGenName = NULL;
823 PKIX_ENTER(CERTSTORE, "pkix_pl_Pk11CertStore_DownloadCrl");
825 /* Do not support dps others than a one with GeneralName
827 if (dp->distPointType != generalName ||
828 !dp->nssdp->derFullName) {
829 PKIX_ERROR(PKIX_UNSUPPORTEDCRLDPTYPE);
831 genName = dp->name.fullName;
832 derGenNames = dp->nssdp->derFullName;
834 derGenName = *derGenNames;
837 !genName->name.other.data) {
838 /* get to next name if no data. */
839 savedError = PKIX_UNSUPPORTEDCRLDPTYPE;
842 uri = &genName->name.other;
843 location = (char*)PR_Malloc(1 + uri->len);
845 savedError = PKIX_ALLOCERROR;
848 PORT_Memcpy(location, uri->data, uri->len);
849 location[uri->len] = 0;
850 if (CERT_ParseURL(location, &hostname,
851 &port, &path) != SECSuccess) {
852 PORT_SetError(SEC_ERROR_BAD_CRL_DP_URL);
853 savedError = PKIX_URLPARSINGFAILED;
857 PORT_Assert(hostname != NULL);
858 PORT_Assert(path != NULL);
860 if ((*hcv1->createSessionFcn)(hostname, port,
861 &pServerSession) != SECSuccess) {
862 PORT_SetError(SEC_ERROR_BAD_CRL_DP_URL);
863 savedError = PKIX_URLPARSINGFAILED;
867 if ((*hcv1->createFcn)(pServerSession, "http", path, "GET",
868 /* Users with slow connections might not get CRL revocation
869 checking for certs that use big CRLs because of the timeout
870 We absolutely need code that limits our retry attempts.
872 PR_SecondsToInterval(
873 ((PKIX_PL_NssContext*)plContext)->timeoutSeconds),
874 &pRequestSession) != SECSuccess) {
875 savedError = PKIX_HTTPSERVERERROR;
879 myHttpResponseDataLen =
880 ((PKIX_PL_NssContext*)plContext)->maxResponseLength;
881 if (myHttpResponseDataLen < PKIX_DEFAULT_MAX_CRL_RESPONSE_LENGTH)
882 myHttpResponseDataLen = PKIX_DEFAULT_MAX_CRL_RESPONSE_LENGTH;
884 /* We use a non-zero timeout, which means:
885 - the client will use blocking I/O
886 - TryFcn will not return WOULD_BLOCK nor a poll descriptor
887 - it's sufficient to call TryFcn once
889 /* we don't want result objects larger than this: */
890 if ((*hcv1->trySendAndReceiveFcn)(
897 &myHttpResponseDataLen) != SECSuccess) {
898 savedError = PKIX_HTTPSERVERERROR;
902 if (myHttpResponseCode != 200) {
903 savedError = PKIX_HTTPSERVERERROR;
907 if (!myHttpResponseData) {
908 /* Going to the next one. */
909 genName = CERT_GetNextGeneralName(genName);
912 /* Staing in the loop through all the names until
913 * we have a successful download. */
914 } while (!myHttpResponseData && *derGenNames &&
915 genName != dp->name.fullName);
916 /* Need this name to track the crl source location. */
917 PORT_Assert(derGenName);
919 if (!myHttpResponseData) {
920 /* Generating fake bad CRL to keep track of this dp */
921 SECItem derCrl = {siBuffer, (void*)"BadCrl", 6 };
923 derCrlCopy = SECITEM_DupItem(&derCrl);
925 PKIX_ERROR(PKIX_ALLOCERROR);
927 derGenName = *dp->nssdp->derFullName;
929 SECItem derCrl = { siBuffer,
930 (void*)myHttpResponseData,
931 myHttpResponseDataLen };
932 derCrlCopy = SECITEM_DupItem(&derCrl);
934 PKIX_ERROR(PKIX_ALLOCERROR);
936 /* crl will be based on derCrlCopy, but will not own the der. */
938 CERT_DecodeDERCrlWithFlags(NULL, derCrlCopy, SEC_CRL_TYPE,
939 CRL_DECODE_DONT_COPY_DER |
940 CRL_DECODE_SKIP_ENTRIES);
942 /* pkix crl owns the der. */
944 pkix_pl_CRL_CreateWithSignedCRL(nssCrl, derCrlCopy,
947 PKIX_CRLCREATEWITHSIGNEDCRLFAILED);
948 /* pkix crl now own both objects. */
954 PORT_Free(derCrlCopy);
956 SEC_DestroyCrl(nssCrl);
957 if (pRequestSession != NULL)
958 (*hcv1->freeFcn)(pRequestSession);
959 if (pServerSession != NULL)
960 (*hcv1->freeSessionFcn)(pServerSession);
963 if (hostname != NULL)
969 PKIX_RETURN(CERTSTORE);
973 * FUNCTION: pkix_pl_Pk11CertStore_GetCRL
974 * (see description of PKIX_CertStore_CRLCallback in pkix_certstore.h)
977 pkix_pl_Pk11CertStore_GetCRL(
978 PKIX_CertStore *store,
979 PKIX_CRLSelector *selector,
981 PKIX_List **pCrlList,
984 PKIX_UInt32 dpIndex = 0;
985 PKIX_PL_CRL *crl = NULL;
986 PKIX_List *crlList = NULL;
987 PKIX_List *dpList = NULL;
988 pkix_pl_CrlDp *dp = NULL;
989 PKIX_PL_Date *date = NULL;
990 const SEC_HttpClientFcn *registeredHttpClient = NULL;
992 PKIX_ENTER(CERTSTORE, "pkix_pl_Pk11CertStore_GetCRL");
993 PKIX_NULLCHECK_THREE(store, pNBIOContext, pCrlList);
994 PKIX_NULLCHECK_TWO(selector, selector->params);
996 registeredHttpClient = SEC_GetRegisteredHttpClient();
997 if (!registeredHttpClient || registeredHttpClient->version != 1) {
1000 dpList = selector->params->crldpList;
1001 date = selector->params->date;
1003 RemovePartitionedDpsFromList(dpList, date,
1005 PKIX_FAILTOREMOVEDPFROMLIST);
1006 for (;dpIndex < dpList->length;dpIndex++) {
1009 PKIX_List_GetItem(dpList, dpIndex,
1010 (PKIX_PL_Object **)&dp,
1012 if (pkixErrorResult) {
1013 PKIX_DECREF(pkixErrorResult);
1017 DownloadCrl(dp, &crl,
1018 ®isteredHttpClient->fcnTable.ftable1,
1020 if (pkixErrorResult || !crl) {
1021 /* continue to next dp in case of unsuccesfull
1022 * download attempt. */
1023 PKIX_DECREF(pkixErrorResult);
1027 PKIX_CHECK(PKIX_List_Create(&crlList, plContext),
1028 PKIX_LISTCREATEFAILED);
1031 PKIX_List_AppendItem(crlList, (PKIX_PL_Object *)crl,
1033 if (pkixErrorResult) {
1034 PKIX_DECREF(pkixErrorResult);
1038 *pCrlList = crlList;
1044 PKIX_DECREF(crlList);
1046 PKIX_RETURN(CERTSTORE);
1050 /* --Public-Pk11CertStore-Functions----------------------------------- */
1053 * FUNCTION: PKIX_PL_Pk11CertStore_Create
1054 * (see comments in pkix_samples_modules.h)
1057 PKIX_PL_Pk11CertStore_Create(
1058 PKIX_CertStore **pCertStore,
1061 PKIX_CertStore *certStore = NULL;
1063 PKIX_ENTER(CERTSTORE, "PKIX_PL_Pk11CertStore_Create");
1064 PKIX_NULLCHECK_ONE(pCertStore);
1066 PKIX_CHECK(PKIX_CertStore_Create
1067 (pkix_pl_Pk11CertStore_GetCert,
1068 pkix_pl_Pk11CertStore_GetCRL,
1069 NULL, /* getCertContinue */
1070 NULL, /* getCrlContinue */
1071 pkix_pl_Pk11CertStore_CheckTrust,
1072 pkix_pl_Pk11CertStore_ImportCrl,
1073 pkix_pl_Pk11CertStore_CheckRevByCrl,
1075 PKIX_TRUE, /* cache flag */
1076 PKIX_TRUE, /* local - no network I/O */
1079 PKIX_CERTSTORECREATEFAILED);
1081 *pCertStore = certStore;
1085 PKIX_RETURN(CERTSTORE);