Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(418)

Side by Side Diff: nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_pk11certstore.c

Issue 2078763002: Delete bundled copy of NSS and replace with README. (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/nss@master
Patch Set: Delete bundled copy of NSS and replace with README. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 /*
5 * pkix_pl_pk11certstore.c
6 *
7 * PKCS11CertStore Function Definitions
8 *
9 */
10
11 #include "pkix_pl_pk11certstore.h"
12
13 /*
14 * PKIX_DEFAULT_MAX_RESPONSE_LENGTH (64 * 1024) is too small for downloading
15 * CRLs. We observed CRLs of sizes 338759 and 439035 in practice. So we
16 * need to use a higher max response length for CRLs.
17 */
18 #define PKIX_DEFAULT_MAX_CRL_RESPONSE_LENGTH (512 * 1024)
19
20 /* --Private-Pk11CertStore-Functions---------------------------------- */
21
22 /*
23 * FUNCTION: pkix_pl_Pk11CertStore_CheckTrust
24 * DESCRIPTION:
25 * This function checks the trust status of this "cert" that was retrieved
26 * from the CertStore "store" and returns its trust status at "pTrusted".
27 *
28 * PARAMETERS:
29 * "store"
30 * Address of the CertStore. Must be non-NULL.
31 * "cert"
32 * Address of the Cert. Must be non-NULL.
33 * "pTrusted"
34 * Address of PKIX_Boolean where the "cert" trust status is returned.
35 * Must be non-NULL.
36 * "plContext"
37 * Platform-specific context pointer
38 * THREAD SAFETY:
39 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
40 * RETURNS:
41 * Returns NULL if the function succeeds.
42 * Returns a CertStore Error if the function fails in a non-fatal way.
43 * Returns a Fatal Error if the function fails in an unrecoverable way.
44 */
45 static PKIX_Error *
46 pkix_pl_Pk11CertStore_CheckTrust(
47 PKIX_CertStore *store,
48 PKIX_PL_Cert *cert,
49 PKIX_Boolean *pTrusted,
50 void *plContext)
51 {
52 SECStatus rv = SECFailure;
53 PKIX_Boolean trusted = PKIX_FALSE;
54 SECCertUsage certUsage = 0;
55 SECCertificateUsage certificateUsage;
56 unsigned int requiredFlags;
57 SECTrustType trustType;
58 CERTCertTrust trust;
59
60 PKIX_ENTER(CERTSTORE, "pkix_pl_Pk11CertStore_CheckTrust");
61 PKIX_NULLCHECK_THREE(store, cert, pTrusted);
62 PKIX_NULLCHECK_ONE(cert->nssCert);
63
64 certificateUsage = ((PKIX_PL_NssContext*)plContext)->certificateUsage;
65
66 /* ensure we obtained a single usage bit only */
67 PORT_Assert(!(certificateUsage & (certificateUsage - 1)));
68
69 /* convert SECertificateUsage (bit mask) to SECCertUsage (enum) */
70 while (0 != (certificateUsage = certificateUsage >> 1)) { certUsage++; }
71
72 rv = CERT_TrustFlagsForCACertUsage(certUsage, &requiredFlags, &trustType );
73 if (rv == SECSuccess) {
74 rv = CERT_GetCertTrust(cert->nssCert, &trust);
75 }
76
77 if (rv == SECSuccess) {
78 unsigned int certFlags;
79
80 if (certUsage != certUsageAnyCA &&
81 certUsage != certUsageStatusResponder) {
82 CERTCertificate *nssCert = cert->nssCert;
83
84 if (certUsage == certUsageVerifyCA) {
85 if (nssCert->nsCertType & NS_CERT_TYPE_EMAIL_CA) {
86 trustType = trustEmail;
87 } else if (nssCert->nsCertType & NS_CERT_TYPE_SSL_CA) {
88 trustType = trustSSL;
89 } else {
90 trustType = trustObjectSigning;
91 }
92 }
93
94 certFlags = SEC_GET_TRUST_FLAGS((&trust), trustType);
95 if ((certFlags & requiredFlags) == requiredFlags) {
96 trusted = PKIX_TRUE;
97 }
98 } else {
99 for (trustType = trustSSL; trustType < trustTypeNone;
100 trustType++) {
101 certFlags =
102 SEC_GET_TRUST_FLAGS((&trust), trustType);
103 if ((certFlags & requiredFlags) == requiredFlags) {
104 trusted = PKIX_TRUE;
105 break;
106 }
107 }
108 }
109 }
110
111 *pTrusted = trusted;
112
113 PKIX_RETURN(CERTSTORE);
114 }
115
116 /*
117 * FUNCTION: pkix_pl_Pk11CertStore_CertQuery
118 * DESCRIPTION:
119 *
120 * This function obtains from the database the Certs specified by the
121 * ComCertSelParams pointed to by "params" and stores the resulting
122 * List at "pSelected". If no matching Certs are found, a NULL pointer
123 * will be stored.
124 *
125 * This function uses a "smart" database query if the Subject has been set
126 * in ComCertSelParams. Otherwise, it uses a very inefficient call to
127 * retrieve all Certs in the database (and run them through the selector).
128 *
129 * PARAMETERS:
130 * "params"
131 * Address of the ComCertSelParams. Must be non-NULL.
132 * "pSelected"
133 * Address at which List will be stored. Must be non-NULL.
134 * "plContext"
135 * Platform-specific context pointer
136 * THREAD SAFETY:
137 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
138 * RETURNS:
139 * Returns NULL if the function succeeds.
140 * Returns a CertStore Error if the function fails in a non-fatal way.
141 * Returns a Fatal Error if the function fails in an unrecoverable way.
142 */
143 static PKIX_Error *
144 pkix_pl_Pk11CertStore_CertQuery(
145 PKIX_ComCertSelParams *params,
146 PKIX_List **pSelected,
147 void *plContext)
148 {
149 PRBool validOnly = PR_FALSE;
150 PRTime prtime = 0;
151 PKIX_PL_X500Name *subjectName = NULL;
152 PKIX_PL_Date *certValid = NULL;
153 PKIX_List *certList = NULL;
154 PKIX_PL_Cert *cert = NULL;
155 CERTCertList *pk11CertList = NULL;
156 CERTCertListNode *node = NULL;
157 CERTCertificate *nssCert = NULL;
158 CERTCertDBHandle *dbHandle = NULL;
159
160 PLArenaPool *arena = NULL;
161 SECItem *nameItem = NULL;
162 void *wincx = NULL;
163
164 PKIX_ENTER(CERTSTORE, "pkix_pl_Pk11CertStore_CertQuery");
165 PKIX_NULLCHECK_TWO(params, pSelected);
166
167 /* avoid multiple calls to retrieve a constant */
168 PKIX_PL_NSSCALLRV(CERTSTORE, dbHandle, CERT_GetDefaultCertDB, ());
169
170 /*
171 * Any of the ComCertSelParams may be obtained and used to constrain
172 * the database query, to allow the use of a "smart" query. See
173 * pkix_certsel.h for a list of the PKIX_ComCertSelParams_Get*
174 * calls available. No corresponding "smart" queries exist at present,
175 * except for CERT_CreateSubjectCertList based on Subject. When others
176 * are added, corresponding code should be added to
177 * pkix_pl_Pk11CertStore_CertQuery to use them when appropriate
178 * selector parameters have been set.
179 */
180
181 PKIX_CHECK(PKIX_ComCertSelParams_GetSubject
182 (params, &subjectName, plContext),
183 PKIX_COMCERTSELPARAMSGETSUBJECTFAILED);
184
185 PKIX_CHECK(PKIX_ComCertSelParams_GetCertificateValid
186 (params, &certValid, plContext),
187 PKIX_COMCERTSELPARAMSGETCERTIFICATEVALIDFAILED);
188
189 /* If caller specified a Date, convert it to PRTime */
190 if (certValid) {
191 PKIX_CHECK(pkix_pl_Date_GetPRTime
192 (certValid, &prtime, plContext),
193 PKIX_DATEGETPRTIMEFAILED);
194 validOnly = PR_TRUE;
195 }
196
197 /*
198 * If we have the subject name for the desired subject,
199 * ask the database for Certs with that subject. Otherwise
200 * ask the database for all Certs.
201 */
202 if (subjectName) {
203 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
204 if (arena) {
205
206 PKIX_CHECK(pkix_pl_X500Name_GetDERName
207 (subjectName, arena, &nameItem, plContext),
208 PKIX_X500NAMEGETSECNAMEFAILED);
209
210 if (nameItem) {
211
212 PKIX_PL_NSSCALLRV
213 (CERTSTORE,
214 pk11CertList,
215 CERT_CreateSubjectCertList,
216 (NULL, dbHandle, nameItem, prtime, validOnly));
217 }
218 PKIX_PL_NSSCALL
219 (CERTSTORE, PORT_FreeArena, (arena, PR_FALSE));
220 arena = NULL;
221 }
222
223 } else {
224
225 PKIX_CHECK(pkix_pl_NssContext_GetWincx
226 ((PKIX_PL_NssContext *)plContext, &wincx),
227 PKIX_NSSCONTEXTGETWINCXFAILED);
228
229 PKIX_PL_NSSCALLRV
230 (CERTSTORE,
231 pk11CertList,
232 PK11_ListCerts,
233 (PK11CertListAll, wincx));
234 }
235
236 if (pk11CertList) {
237
238 PKIX_CHECK(PKIX_List_Create(&certList, plContext),
239 PKIX_LISTCREATEFAILED);
240
241 for (node = CERT_LIST_HEAD(pk11CertList);
242 !(CERT_LIST_END(node, pk11CertList));
243 node = CERT_LIST_NEXT(node)) {
244
245 PKIX_PL_NSSCALLRV
246 (CERTSTORE,
247 nssCert,
248 CERT_DupCertificate,
249 (node->cert));
250
251 if (!nssCert) {
252 continue; /* just skip bad certs */
253 }
254
255 PKIX_CHECK_ONLY_FATAL(pkix_pl_Cert_CreateWithNSSCert
256 (nssCert, &cert, plContext),
257 PKIX_CERTCREATEWITHNSSCERTFAILED);
258
259 if (PKIX_ERROR_RECEIVED) {
260 CERT_DestroyCertificate(nssCert);
261 nssCert = NULL;
262 continue; /* just skip bad certs */
263 }
264
265 PKIX_CHECK_ONLY_FATAL(PKIX_List_AppendItem
266 (certList, (PKIX_PL_Object *)cert, plContext),
267 PKIX_LISTAPPENDITEMFAILED);
268
269 PKIX_DECREF(cert);
270
271 }
272
273 /* Don't throw away the list if one cert was bad! */
274 pkixTempErrorReceived = PKIX_FALSE;
275 }
276
277 *pSelected = certList;
278 certList = NULL;
279
280 cleanup:
281
282 if (pk11CertList) {
283 CERT_DestroyCertList(pk11CertList);
284 }
285 if (arena) {
286 PORT_FreeArena(arena, PR_FALSE);
287 }
288
289 PKIX_DECREF(subjectName);
290 PKIX_DECREF(certValid);
291 PKIX_DECREF(cert);
292 PKIX_DECREF(certList);
293
294 PKIX_RETURN(CERTSTORE);
295 }
296
297 /*
298 * FUNCTION: pkix_pl_Pk11CertStore_ImportCrl
299 * DESCRIPTION:
300 *
301 * PARAMETERS:
302 * "params"
303 * Address of the ComCRLSelParams. Must be non-NULL.
304 * "pSelected"
305 * Address at which List will be stored. Must be non-NULL.
306 * "plContext"
307 * Platform-specific context pointer
308 * THREAD SAFETY:
309 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
310 * RETURNS:
311 * Returns NULL if the function succeeds.
312 * Returns a CertStore Error if the function fails in a non-fatal way.
313 * Returns a Fatal Error if the function fails in an unrecoverable way.
314 */
315 static PKIX_Error *
316 pkix_pl_Pk11CertStore_ImportCrl(
317 PKIX_CertStore *store,
318 PKIX_PL_X500Name *issuerName,
319 PKIX_List *crlList,
320 void *plContext)
321 {
322 CERTCertDBHandle *certHandle = CERT_GetDefaultCertDB();
323 PKIX_PL_CRL *crl = NULL;
324 SECItem *derCrl = NULL;
325
326 PKIX_ENTER(CERTSTORE, "pkix_pl_Pk11CertStore_ImportCrl");
327 PKIX_NULLCHECK_TWO(store, plContext);
328
329 if (!crlList) {
330 goto cleanup;
331 }
332 while (crlList->length > 0) {
333 PKIX_CHECK(
334 PKIX_List_GetItem(crlList, 0, (PKIX_PL_Object**)&crl,
335 plContext),
336 PKIX_LISTGETITEMFAILED);
337
338 /* Delete crl from the list to keep controll of the
339 * last reference. crl need to be destroyed right after
340 * it released the ownership of the crl der. */
341 PKIX_CHECK(
342 PKIX_List_DeleteItem(crlList, 0, plContext),
343 PKIX_LISTDELETEITEMFAILED);
344
345 /* acquire the crlder ownership */
346 pkixErrorResult =
347 PKIX_PL_CRL_ReleaseDerCrl(crl, &derCrl, plContext);
348 PORT_Assert(!pkixErrorResult && derCrl);
349 if (pkixErrorResult || !derCrl) {
350 /* All pkix delivered crls should be able to
351 * release their ders. */
352 PKIX_DECREF(pkixErrorResult);
353 PKIX_DECREF(crl);
354 continue;
355 }
356 cert_CacheCRLByGeneralName(certHandle, derCrl,
357 crl->derGenName);
358 /* Do not check the status. If it is a SECFailure,
359 * derCrl is already destroyed. */
360 derCrl = NULL;
361 PKIX_DECREF(crl);
362 }
363
364 cleanup:
365 PKIX_DECREF(crl);
366
367 PKIX_RETURN(CERTSTORE);
368 }
369
370 static PKIX_Error *
371 NameCacheHasFetchedCrlInfo(PKIX_PL_Cert *pkixCert,
372 PRTime time,
373 PKIX_Boolean *pHasFetchedCrlInCache,
374 void *plContext)
375 {
376 /* Returning true result in this case will mean, that case info
377 * is currect and should used as is. */
378 NamedCRLCache* nameCrlCache = NULL;
379 PKIX_Boolean hasFetchedCrlInCache = PKIX_TRUE;
380 PKIX_List *dpList = NULL;
381 pkix_pl_CrlDp *dp = NULL;
382 PKIX_UInt32 dpIndex = 0;
383 SECStatus rv = SECSuccess;
384 PRTime reloadDelay = 0, badCrlInvalDelay = 0;
385
386 PKIX_ENTER(CERTSTORE, "ChechCacheHasFetchedCrl");
387
388 reloadDelay =
389 ((PKIX_PL_NssContext*)plContext)->crlReloadDelay *
390 PR_USEC_PER_SEC;
391 badCrlInvalDelay =
392 ((PKIX_PL_NssContext*)plContext)->badDerCrlReloadDelay *
393 PR_USEC_PER_SEC;
394 if (!time) {
395 time = PR_Now();
396 }
397 /* If we already download the crl and inserted into the cache, then
398 * there is no need to check for fetched crl. We have what we have. */
399 PKIX_CHECK(
400 PKIX_PL_Cert_GetCrlDp(pkixCert, &dpList, plContext),
401 PKIX_CERTGETCRLDPFAILED);
402 if (dpList && dpList->length) {
403 hasFetchedCrlInCache = PKIX_FALSE;
404 rv = cert_AcquireNamedCRLCache(&nameCrlCache);
405 if (rv != SECSuccess) {
406 PKIX_DECREF(dpList);
407 }
408 } else {
409 /* If no dp then treat it as if we already have
410 * a fetched crl. */
411 PKIX_DECREF(dpList);
412 }
413 for (;!hasFetchedCrlInCache &&
414 dpList && dpIndex < dpList->length;dpIndex++) {
415 SECItem **derDpNames = NULL;
416 pkixErrorResult =
417 PKIX_List_GetItem(dpList, dpIndex, (PKIX_PL_Object **)&dp,
418 plContext);
419 if (pkixErrorResult) {
420 PKIX_DECREF(pkixErrorResult);
421 continue;
422 }
423 if (dp->nssdp->distPointType == generalName) {
424 /* dp can only be created from nssdp. */
425 derDpNames = dp->nssdp->derFullName;
426 }
427 while (derDpNames && *derDpNames != NULL) {
428 NamedCRLCacheEntry* cacheEntry = NULL;
429 const SECItem *derDpName = *derDpNames++;
430 rv = cert_FindCRLByGeneralName(nameCrlCache, derDpName,
431 &cacheEntry);
432 if (rv == SECSuccess && cacheEntry) {
433 if ((cacheEntry->inCRLCache &&
434 (cacheEntry->successfulInsertionTime + reloadDelay > time ||
435 (cacheEntry->dupe &&
436 cacheEntry->lastAttemptTime + reloadDelay > time))) ||
437 (cacheEntry->badDER &&
438 cacheEntry->lastAttemptTime + badCrlInvalDelay > time)) {
439 hasFetchedCrlInCache = PKIX_TRUE;
440 break;
441 }
442 }
443 }
444 PKIX_DECREF(dp);
445 }
446 cleanup:
447 *pHasFetchedCrlInCache = hasFetchedCrlInCache;
448 if (nameCrlCache) {
449 cert_ReleaseNamedCRLCache(nameCrlCache);
450 }
451 PKIX_DECREF(dpList);
452
453 PKIX_RETURN(CERTSTORE);
454 }
455
456 /*
457 * FUNCTION: pkix_pl_Pk11CertStore_CheckCrl
458 * DESCRIPTION:
459 *
460 * PARAMETERS:
461 * "params"
462 * Address of the ComCRLSelParams. Must be non-NULL.
463 * "pSelected"
464 * Address at which List will be stored. Must be non-NULL.
465 * "plContext"
466 * Platform-specific context pointer
467 * THREAD SAFETY:
468 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
469 * RETURNS:
470 * Returns NULL if the function succeeds.
471 * Returns a CertStore Error if the function fails in a non-fatal way.
472 * Returns a Fatal Error if the function fails in an unrecoverable way.
473 */
474 static PKIX_Error *
475 pkix_pl_Pk11CertStore_CheckRevByCrl(
476 PKIX_CertStore *store,
477 PKIX_PL_Cert *pkixCert,
478 PKIX_PL_Cert *pkixIssuer,
479 PKIX_PL_Date *date,
480 PKIX_Boolean crlDownloadDone,
481 CERTCRLEntryReasonCode *pReasonCode,
482 PKIX_RevocationStatus *pStatus,
483 void *plContext)
484 {
485 PKIX_RevocationStatus pkixRevStatus = PKIX_RevStatus_NoInfo;
486 CERTRevocationStatus revStatus = certRevocationStatusUnknown;
487 PKIX_Boolean hasFetchedCrlInCache = PKIX_TRUE;
488 CERTCertificate *cert = NULL, *issuer = NULL;
489 SECStatus rv = SECSuccess;
490 void *wincx = NULL;
491 PRTime time = 0;
492
493 PKIX_ENTER(CERTSTORE, "pkix_pl_Pk11CertStore_CheckRevByCrl");
494 PKIX_NULLCHECK_FOUR(store, pkixCert, pkixIssuer, plContext);
495
496 cert = pkixCert->nssCert;
497 issuer = pkixIssuer->nssCert;
498 if (date) {
499 PKIX_CHECK(
500 pkix_pl_Date_GetPRTime(date, &time, plContext),
501 PKIX_DATEGETPRTIMEFAILED);
502 }
503 PKIX_CHECK(
504 pkix_pl_NssContext_GetWincx((PKIX_PL_NssContext*)plContext,
505 &wincx),
506 PKIX_NSSCONTEXTGETWINCXFAILED);
507 /* No need to check any cDPs, since partitioned crls are not
508 * supported. If a ds does not point to partitioned crl, then
509 * the crl should be in issuer cache that is unrelated to any
510 * dp. Using NULL as a dp pointer to check it.*/
511 rv = cert_CheckCertRevocationStatus(cert, issuer, NULL,
512 /* Will not validate the signature
513 * on the crl if time is not specified.* /
514 time, wincx, &revStatus, pReasonCode);
515 if (rv == SECFailure) {
516 pkixRevStatus = PKIX_RevStatus_Revoked;
517 goto cleanup;
518 }
519 if (crlDownloadDone) {
520 if (revStatus == certRevocationStatusRevoked) {
521 pkixRevStatus = PKIX_RevStatus_Revoked;
522 } else if (revStatus == certRevocationStatusValid) {
523 pkixRevStatus = PKIX_RevStatus_Success;
524 }
525 } else {
526 pkixErrorResult =
527 NameCacheHasFetchedCrlInfo(pkixCert, time, &hasFetchedCrlInCache,
528 plContext);
529 if (pkixErrorResult) {
530 goto cleanup;
531 }
532 if (revStatus == certRevocationStatusRevoked &&
533 (hasFetchedCrlInCache ||
534 *pReasonCode != crlEntryReasoncertificatedHold)) {
535 pkixRevStatus = PKIX_RevStatus_Revoked;
536 } else if (revStatus == certRevocationStatusValid &&
537 hasFetchedCrlInCache) {
538 pkixRevStatus = PKIX_RevStatus_Success;
539 }
540 }
541 cleanup:
542 *pStatus = pkixRevStatus;
543
544 PKIX_RETURN(CERTSTORE);
545 }
546
547
548 /*
549 * FUNCTION: pkix_pl_Pk11CertStore_GetCert
550 * (see description of PKIX_CertStore_CertCallback in pkix_certstore.h)
551 */
552 PKIX_Error *
553 pkix_pl_Pk11CertStore_GetCert(
554 PKIX_CertStore *store,
555 PKIX_CertSelector *selector,
556 PKIX_VerifyNode *parentVerifyNode,
557 void **pNBIOContext,
558 PKIX_List **pCertList,
559 void *plContext)
560 {
561 PKIX_UInt32 i = 0;
562 PKIX_UInt32 numFound = 0;
563 PKIX_PL_Cert *candidate = NULL;
564 PKIX_List *selected = NULL;
565 PKIX_List *filtered = NULL;
566 PKIX_CertSelector_MatchCallback selectorCallback = NULL;
567 PKIX_CertStore_CheckTrustCallback trustCallback = NULL;
568 PKIX_ComCertSelParams *params = NULL;
569 PKIX_Boolean cacheFlag = PKIX_FALSE;
570 PKIX_VerifyNode *verifyNode = NULL;
571 PKIX_Error *selectorError = NULL;
572
573 PKIX_ENTER(CERTSTORE, "pkix_pl_Pk11CertStore_GetCert");
574 PKIX_NULLCHECK_FOUR(store, selector, pNBIOContext, pCertList);
575
576 *pNBIOContext = NULL; /* We don't use non-blocking I/O */
577
578 PKIX_CHECK(PKIX_CertSelector_GetMatchCallback
579 (selector, &selectorCallback, plContext),
580 PKIX_CERTSELECTORGETMATCHCALLBACKFAILED);
581
582 PKIX_CHECK(PKIX_CertSelector_GetCommonCertSelectorParams
583 (selector, &params, plContext),
584 PKIX_CERTSELECTORGETCOMCERTSELPARAMSFAILED);
585
586 PKIX_CHECK(pkix_pl_Pk11CertStore_CertQuery
587 (params, &selected, plContext),
588 PKIX_PK11CERTSTORECERTQUERYFAILED);
589
590 if (selected) {
591 PKIX_CHECK(PKIX_List_GetLength(selected, &numFound, plContext),
592 PKIX_LISTGETLENGTHFAILED);
593 }
594
595 PKIX_CHECK(PKIX_CertStore_GetCertStoreCacheFlag
596 (store, &cacheFlag, plContext),
597 PKIX_CERTSTOREGETCERTSTORECACHEFLAGFAILED);
598
599 PKIX_CHECK(PKIX_CertStore_GetTrustCallback
600 (store, &trustCallback, plContext),
601 PKIX_CERTSTOREGETTRUSTCALLBACKFAILED);
602
603 PKIX_CHECK(PKIX_List_Create(&filtered, plContext),
604 PKIX_LISTCREATEFAILED);
605
606 for (i = 0; i < numFound; i++) {
607 PKIX_CHECK_ONLY_FATAL(PKIX_List_GetItem
608 (selected,
609 i,
610 (PKIX_PL_Object **)&candidate,
611 plContext),
612 PKIX_LISTGETITEMFAILED);
613
614 if (PKIX_ERROR_RECEIVED) {
615 continue; /* just skip bad certs */
616 }
617
618 selectorError =
619 selectorCallback(selector, candidate, plContext);
620 if (!selectorError) {
621 PKIX_CHECK(PKIX_PL_Cert_SetCacheFlag
622 (candidate, cacheFlag, plContext),
623 PKIX_CERTSETCACHEFLAGFAILED);
624
625 if (trustCallback) {
626 PKIX_CHECK(PKIX_PL_Cert_SetTrustCertStore
627 (candidate, store, plContext),
628 PKIX_CERTSETTRUSTCERTSTOREFAILED);
629 }
630
631 PKIX_CHECK_ONLY_FATAL(PKIX_List_AppendItem
632 (filtered,
633 (PKIX_PL_Object *)candidate,
634 plContext),
635 PKIX_LISTAPPENDITEMFAILED);
636 } else if (parentVerifyNode) {
637 PKIX_CHECK_FATAL(
638 pkix_VerifyNode_Create(candidate, 0, selectorError,
639 &verifyNode, plContext),
640 PKIX_VERIFYNODECREATEFAILED);
641 PKIX_CHECK_FATAL(
642 pkix_VerifyNode_AddToTree(parentVerifyNode,
643 verifyNode,
644 plContext),
645 PKIX_VERIFYNODEADDTOTREEFAILED);
646 PKIX_DECREF(verifyNode);
647 }
648 PKIX_DECREF(selectorError);
649 PKIX_DECREF(candidate);
650 }
651
652 /* Don't throw away the list if one cert was bad! */
653 pkixTempErrorReceived = PKIX_FALSE;
654
655 *pCertList = filtered;
656 filtered = NULL;
657
658 cleanup:
659 fatal:
660 PKIX_DECREF(filtered);
661 PKIX_DECREF(candidate);
662 PKIX_DECREF(selected);
663 PKIX_DECREF(params);
664 PKIX_DECREF(verifyNode);
665 PKIX_DECREF(selectorError);
666
667 PKIX_RETURN(CERTSTORE);
668 }
669
670 static PKIX_Error *
671 RemovePartitionedDpsFromList(PKIX_List *dpList, PKIX_PL_Date *date,
672 void *plContext)
673 {
674 NamedCRLCache* nameCrlCache = NULL;
675 pkix_pl_CrlDp *dp = NULL;
676 unsigned int dpIndex = 0;
677 PRTime time;
678 PRTime reloadDelay = 0, badCrlInvalDelay = 0;
679 SECStatus rv;
680
681 PKIX_ENTER(CERTSTORE, "pkix_pl_Pk11CertStore_ListRemovePrtDp");
682
683 if (!dpList || !dpList->length) {
684 PKIX_RETURN(CERTSTORE);
685 }
686 reloadDelay =
687 ((PKIX_PL_NssContext*)plContext)->crlReloadDelay *
688 PR_USEC_PER_SEC;
689 badCrlInvalDelay =
690 ((PKIX_PL_NssContext*)plContext)->badDerCrlReloadDelay *
691 PR_USEC_PER_SEC;
692 PKIX_CHECK(pkix_pl_Date_GetPRTime(date, &time, plContext),
693 PKIX_DATEGETPRTIMEFAILED);
694 rv = cert_AcquireNamedCRLCache(&nameCrlCache);
695 if (rv == SECFailure) {
696 /* Baling out. Wont find out any thing useful. */
697 PKIX_RETURN(CERTSTORE);
698 }
699 while (dpIndex < dpList->length) {
700 SECItem **derDpNames = NULL;
701 PKIX_Boolean removeDp = PKIX_FALSE;
702
703 PKIX_CHECK(
704 PKIX_List_GetItem(dpList, dpIndex, (PKIX_PL_Object **)&dp,
705 plContext),
706 PKIX_LISTGETITEMFAILED);
707 if (!dp->isPartitionedByReasonCode) {
708 /* See if we know about this dp anything why we should
709 * not use it to download a crl. */
710 if (dp->nssdp->distPointType == generalName) {
711 /* dp can only be created from nssdp. */
712 derDpNames = dp->nssdp->derFullName;
713 } else {
714 removeDp = PKIX_TRUE;
715 }
716 while (derDpNames && *derDpNames != NULL) {
717 NamedCRLCacheEntry* cacheEntry = NULL;
718 const SECItem *derDpName = *derDpNames++;
719 /* Removing from the list all dps that we know about. */
720 rv = cert_FindCRLByGeneralName(nameCrlCache, derDpName,
721 &cacheEntry);
722 if (rv && cacheEntry) {
723 if (cacheEntry->unsupported ||
724 (cacheEntry->inCRLCache &&
725 (cacheEntry->successfulInsertionTime + reloadDelay > ti me ||
726 (cacheEntry->dupe &&
727 cacheEntry->lastAttemptTime + reloadDelay > time))) | |
728 (cacheEntry->badDER &&
729 cacheEntry->lastAttemptTime + badCrlInvalDelay > time )) {
730 removeDp = PKIX_TRUE;
731 }
732 }
733 }
734 } else {
735 /* Remove dp that point to a partitioned crl . RFC 5280
736 * recommends against crl partitioned by reason code.
737 * Will skip such crls */
738 removeDp = PKIX_TRUE;
739 }
740 if (removeDp) {
741 PKIX_CHECK_ONLY_FATAL(
742 pkix_List_Remove(dpList,(PKIX_PL_Object*)dp,
743 plContext),
744 PKIX_LISTGETITEMFAILED);
745 } else {
746 dpIndex += 1;
747 }
748 PKIX_DECREF(dp);
749 }
750
751 cleanup:
752 if (nameCrlCache) {
753 cert_ReleaseNamedCRLCache(nameCrlCache);
754 }
755 PKIX_DECREF(dp);
756
757 PKIX_RETURN(CERTSTORE);
758 }
759
760 /*
761 * FUNCTION: pkix_pl_Pk11CertStore_DownloadCrl
762 */
763 static PKIX_Error *
764 DownloadCrl(pkix_pl_CrlDp *dp, PKIX_PL_CRL **crl,
765 const SEC_HttpClientFcnV1 *hcv1, void *plContext)
766 {
767 char *location = NULL;
768 char *hostname = NULL;
769 char *path = NULL;
770 PRUint16 port;
771 SEC_HTTP_SERVER_SESSION pServerSession = NULL;
772 SEC_HTTP_REQUEST_SESSION pRequestSession = NULL;
773 PRUint16 myHttpResponseCode;
774 const char *myHttpResponseData = NULL;
775 PRUint32 myHttpResponseDataLen;
776 SECItem *uri = NULL;
777 SECItem *derCrlCopy = NULL;
778 CERTSignedCrl *nssCrl = NULL;
779 CERTGeneralName *genName = NULL;
780 SECItem **derGenNames = NULL;
781 SECItem *derGenName = NULL;
782
783 PKIX_ENTER(CERTSTORE, "pkix_pl_Pk11CertStore_DownloadCrl");
784
785 /* Do not support dps others than a one with GeneralName
786 * name type. */
787 if (dp->distPointType != generalName ||
788 !dp->nssdp->derFullName) {
789 PKIX_ERROR(PKIX_UNSUPPORTEDCRLDPTYPE);
790 }
791 genName = dp->name.fullName;
792 derGenNames = dp->nssdp->derFullName;
793 do {
794 derGenName = *derGenNames;
795 do {
796 if (!derGenName ||
797 !genName->name.other.data) {
798 /* get to next name if no data. */
799 break;
800 }
801 uri = &genName->name.other;
802 location = (char*)PR_Malloc(1 + uri->len);
803 if (!location) {
804 break;
805 }
806 PORT_Memcpy(location, uri->data, uri->len);
807 location[uri->len] = 0;
808 if (CERT_ParseURL(location, &hostname,
809 &port, &path) != SECSuccess) {
810 PORT_SetError(SEC_ERROR_BAD_CRL_DP_URL);
811 break;
812 }
813
814 PORT_Assert(hostname != NULL);
815 PORT_Assert(path != NULL);
816
817 if ((*hcv1->createSessionFcn)(hostname, port,
818 &pServerSession) != SECSuccess) {
819 PORT_SetError(SEC_ERROR_BAD_CRL_DP_URL);
820 break;
821 }
822
823 if ((*hcv1->createFcn)(pServerSession, "http", path, "GET",
824 /* Users with slow connections might not get CRL revocation
825 checking for certs that use big CRLs because of the timeout
826 We absolutely need code that limits our retry attempts.
827 */
828 PR_SecondsToInterval(
829 ((PKIX_PL_NssContext*)plContext)->timeoutSeconds),
830 &pRequestSession) != SECSuccess) {
831 break;
832 }
833
834 myHttpResponseDataLen =
835 ((PKIX_PL_NssContext*)plContext)->maxResponseLength;
836 if (myHttpResponseDataLen < PKIX_DEFAULT_MAX_CRL_RESPONSE_LENGTH)
837 myHttpResponseDataLen = PKIX_DEFAULT_MAX_CRL_RESPONSE_LENGTH;
838
839 /* We use a non-zero timeout, which means:
840 - the client will use blocking I/O
841 - TryFcn will not return WOULD_BLOCK nor a poll descriptor
842 - it's sufficient to call TryFcn once
843 */
844 /* we don't want result objects larger than this: */
845 if ((*hcv1->trySendAndReceiveFcn)(
846 pRequestSession,
847 NULL,
848 &myHttpResponseCode,
849 NULL,
850 NULL,
851 &myHttpResponseData,
852 &myHttpResponseDataLen) != SECSuccess) {
853 break;
854 }
855
856 if (myHttpResponseCode != 200) {
857 break;
858 }
859 } while(0);
860 if (!myHttpResponseData) {
861 /* Going to the next one. */
862 genName = CERT_GetNextGeneralName(genName);
863 derGenNames++;
864 }
865 /* Staing in the loop through all the names until
866 * we have a successful download. */
867 } while (!myHttpResponseData && *derGenNames &&
868 genName != dp->name.fullName);
869 /* Need this name to track the crl source location. */
870 PORT_Assert(derGenName);
871
872 if (!myHttpResponseData) {
873 /* Generating fake bad CRL to keep track of this dp */
874 SECItem derCrl = {siBuffer, (void*)"BadCrl", 6 };
875
876 derCrlCopy = SECITEM_DupItem(&derCrl);
877 if (!derCrlCopy) {
878 PKIX_ERROR(PKIX_ALLOCERROR);
879 }
880 derGenName = *dp->nssdp->derFullName;
881 } else {
882 SECItem derCrl = { siBuffer,
883 (void*)myHttpResponseData,
884 myHttpResponseDataLen };
885 derCrlCopy = SECITEM_DupItem(&derCrl);
886 if (!derCrlCopy) {
887 PKIX_ERROR(PKIX_ALLOCERROR);
888 }
889 /* crl will be based on derCrlCopy, but will not own the der. */
890 nssCrl =
891 CERT_DecodeDERCrlWithFlags(NULL, derCrlCopy, SEC_CRL_TYPE,
892 CRL_DECODE_DONT_COPY_DER |
893 CRL_DECODE_SKIP_ENTRIES);
894 }
895 /* pkix crl owns the der. */
896 PKIX_CHECK(
897 pkix_pl_CRL_CreateWithSignedCRL(nssCrl, derCrlCopy,
898 derGenName,
899 crl, plContext),
900 PKIX_CRLCREATEWITHSIGNEDCRLFAILED);
901 /* pkix crl now own both objects. */
902 derCrlCopy = NULL;
903 nssCrl = NULL;
904
905 cleanup:
906 if (derCrlCopy)
907 PORT_Free(derCrlCopy);
908 if (nssCrl)
909 SEC_DestroyCrl(nssCrl);
910 if (pRequestSession != NULL)
911 (*hcv1->freeFcn)(pRequestSession);
912 if (pServerSession != NULL)
913 (*hcv1->freeSessionFcn)(pServerSession);
914 if (path != NULL)
915 PORT_Free(path);
916 if (hostname != NULL)
917 PORT_Free(hostname);
918 if (location) {
919 PORT_Free(location);
920 }
921
922 PKIX_RETURN(CERTSTORE);
923 }
924
925 /*
926 * FUNCTION: pkix_pl_Pk11CertStore_GetCRL
927 * (see description of PKIX_CertStore_CRLCallback in pkix_certstore.h)
928 */
929 static PKIX_Error *
930 pkix_pl_Pk11CertStore_GetCRL(
931 PKIX_CertStore *store,
932 PKIX_CRLSelector *selector,
933 void **pNBIOContext,
934 PKIX_List **pCrlList,
935 void *plContext)
936 {
937 PKIX_UInt32 dpIndex = 0;
938 PKIX_PL_CRL *crl = NULL;
939 PKIX_List *crlList = NULL;
940 PKIX_List *dpList = NULL;
941 pkix_pl_CrlDp *dp = NULL;
942 PKIX_PL_Date *date = NULL;
943 const SEC_HttpClientFcn *registeredHttpClient = NULL;
944
945 PKIX_ENTER(CERTSTORE, "pkix_pl_Pk11CertStore_GetCRL");
946 PKIX_NULLCHECK_THREE(store, pNBIOContext, pCrlList);
947 PKIX_NULLCHECK_TWO(selector, selector->params);
948
949 registeredHttpClient = SEC_GetRegisteredHttpClient();
950 if (!registeredHttpClient || registeredHttpClient->version != 1) {
951 goto cleanup;
952 }
953 dpList = selector->params->crldpList;
954 date = selector->params->date;
955 PKIX_CHECK(
956 RemovePartitionedDpsFromList(dpList, date,
957 plContext),
958 PKIX_FAILTOREMOVEDPFROMLIST);
959 for (;dpIndex < dpList->length;dpIndex++) {
960 PKIX_DECREF(dp);
961 pkixErrorResult =
962 PKIX_List_GetItem(dpList, dpIndex,
963 (PKIX_PL_Object **)&dp,
964 plContext);
965 if (pkixErrorResult) {
966 PKIX_DECREF(pkixErrorResult);
967 continue;
968 }
969 pkixErrorResult =
970 DownloadCrl(dp, &crl,
971 &registeredHttpClient->fcnTable.ftable1,
972 plContext);
973 if (pkixErrorResult || !crl) {
974 /* continue to next dp in case of unsuccesfull
975 * download attempt. */
976 PKIX_DECREF(pkixErrorResult);
977 continue;
978 }
979 if (!crlList) {
980 PKIX_CHECK(PKIX_List_Create(&crlList, plContext),
981 PKIX_LISTCREATEFAILED);
982 }
983 pkixErrorResult =
984 PKIX_List_AppendItem(crlList, (PKIX_PL_Object *)crl,
985 plContext);
986 if (pkixErrorResult) {
987 PKIX_DECREF(pkixErrorResult);
988 }
989 PKIX_DECREF(crl);
990 }
991 *pCrlList = crlList;
992 crlList = NULL;
993
994 cleanup:
995 PKIX_DECREF(dp);
996 PKIX_DECREF(crl);
997 PKIX_DECREF(crlList);
998
999 PKIX_RETURN(CERTSTORE);
1000 }
1001
1002
1003 /* --Public-Pk11CertStore-Functions----------------------------------- */
1004
1005 /*
1006 * FUNCTION: PKIX_PL_Pk11CertStore_Create
1007 * (see comments in pkix_samples_modules.h)
1008 */
1009 PKIX_Error *
1010 PKIX_PL_Pk11CertStore_Create(
1011 PKIX_CertStore **pCertStore,
1012 void *plContext)
1013 {
1014 PKIX_CertStore *certStore = NULL;
1015
1016 PKIX_ENTER(CERTSTORE, "PKIX_PL_Pk11CertStore_Create");
1017 PKIX_NULLCHECK_ONE(pCertStore);
1018
1019 PKIX_CHECK(PKIX_CertStore_Create
1020 (pkix_pl_Pk11CertStore_GetCert,
1021 pkix_pl_Pk11CertStore_GetCRL,
1022 NULL, /* getCertContinue */
1023 NULL, /* getCrlContinue */
1024 pkix_pl_Pk11CertStore_CheckTrust,
1025 pkix_pl_Pk11CertStore_ImportCrl,
1026 pkix_pl_Pk11CertStore_CheckRevByCrl,
1027 NULL,
1028 PKIX_TRUE, /* cache flag */
1029 PKIX_TRUE, /* local - no network I/O */
1030 &certStore,
1031 plContext),
1032 PKIX_CERTSTORECREATEFAILED);
1033
1034 *pCertStore = certStore;
1035
1036 cleanup:
1037
1038 PKIX_RETURN(CERTSTORE);
1039 }
OLDNEW
« no previous file with comments | « nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_pk11certstore.h ('k') | nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_socket.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698