66
67
#include "certxutl.h"
67
68
#include "pk11func.h" /* for PK11_HashBuf */
68
69
#include <stdarg.h>
72
#define DEFAULT_OCSP_CACHE_SIZE 1000
73
#define DEFAULT_MINIMUM_SECONDS_TO_NEXT_OCSP_FETCH_ATTEMPT 1*60*60L
74
#define DEFAULT_MAXIMUM_SECONDS_TO_NEXT_OCSP_FETCH_ATTEMPT 24*60*60L
75
#define MICROSECONDS_PER_SECOND 1000000L
77
typedef struct OCSPCacheItemStr OCSPCacheItem;
78
typedef struct OCSPCacheDataStr OCSPCacheData;
80
struct OCSPCacheItemStr {
82
OCSPCacheItem *moreRecent;
83
OCSPCacheItem *lessRecent;
86
CERTOCSPCertID *certID;
87
/* CertID's arena also used to allocate "this" cache item */
89
/* cache control information */
90
PRTime nextFetchAttemptTime;
92
/* Cached contents. Use a separate arena, because lifetime is different */
93
PRArenaPool *certStatusArena; /* NULL means: no cert status cached */
94
ocspCertStatus certStatus;
96
PRPackedBool haveThisUpdate;
97
PRPackedBool haveNextUpdate;
102
struct OCSPCacheDataStr {
103
PLHashTable *entries;
104
PRUint32 numberOfEntries;
105
OCSPCacheItem *MRUitem; /* most recently used cache item */
106
OCSPCacheItem *LRUitem; /* least recently used cache item */
71
109
static struct OCSPGlobalStruct {
73
111
const SEC_HttpClientFcn *defaultHttpClientFcn;
74
} OCSP_Global = { NULL, NULL };
112
PRInt32 maxCacheEntries;
113
PRUint32 minimumSecondsToNextFetchAttempt;
114
PRUint32 maximumSecondsToNextFetchAttempt;
116
SEC_OcspFailureMode ocspFailureMode;
117
} OCSP_Global = { NULL,
119
DEFAULT_OCSP_CACHE_SIZE,
120
DEFAULT_MINIMUM_SECONDS_TO_NEXT_OCSP_FETCH_ATTEMPT,
121
DEFAULT_MAXIMUM_SECONDS_TO_NEXT_OCSP_FETCH_ATTEMPT,
122
{NULL, 0, NULL, NULL},
123
ocspMode_FailureIsVerificationFailure
126
/* Forward declarations */
128
ocsp_GetEncodedOCSPResponseFromRequest(PRArenaPool *arena,
129
CERTOCSPRequest *request,
130
char *location, int64 time,
131
PRBool addServiceLocator,
133
CERTOCSPRequest **pRequest);
135
ocsp_GetOCSPStatusFromNetwork(CERTCertDBHandle *handle,
136
CERTOCSPCertID *certID,
137
CERTCertificate *cert,
140
PRBool *certIDWasConsumed,
143
ocsp_GetVerifiedSingleResponseForCertID(CERTCertDBHandle *handle,
144
CERTOCSPResponse *response,
145
CERTOCSPCertID *certID,
146
CERTCertificate *signerCert,
148
CERTOCSPSingleResponse **pSingleResponse);
151
#define OCSP_TRACE(msg)
152
#define OCSP_TRACE_TIME(msg, time)
153
#define OCSP_TRACE_CERT(cert)
155
#define OCSP_TRACE(msg) ocsp_Trace msg
156
#define OCSP_TRACE_TIME(msg, time) ocsp_dumpStringWithTime(msg, time)
157
#define OCSP_TRACE_CERT(cert) dumpCertificate(cert)
159
#if (defined(XP_UNIX) || defined(XP_WIN32) || defined(XP_BEOS) \
160
|| defined(XP_MACOSX)) && !defined(_WIN32_WCE)
161
#define NSS_HAVE_GETENV 1
164
static PRBool wantOcspTrace()
166
static PRBool firstTime = PR_TRUE;
167
static PRBool wantTrace = PR_FALSE;
169
#ifdef NSS_HAVE_GETENV
171
char *ev = getenv("NSS_TRACE_OCSP");
175
firstTime = PR_FALSE;
182
ocsp_Trace(const char *format, ...)
187
if (!wantOcspTrace())
189
va_start(args, format);
190
PR_vsnprintf(buf, sizeof(buf), format, args);
192
PR_LogPrint("%s", buf);
196
ocsp_dumpStringWithTime(const char *str, int64 time)
198
PRExplodedTime timePrintable;
201
if (!wantOcspTrace())
203
PR_ExplodeTime(time, PR_GMTParameters, &timePrintable);
204
PR_FormatTime(timestr, 100, "%a %b %d %H:%M:%S %Y",
206
ocsp_Trace("OCSP %s %s\n", str, timestr);
210
printHexString(const char *prefix, SECItem *hexval)
215
for (i = 0; i < hexval->len; i++) {
216
if (i != hexval->len - 1) {
217
PR_sprintf_append(hexbuf, "%02x:", hexval->data[i]);
219
PR_sprintf_append(hexbuf, "%02x", hexval->data[i]);
223
ocsp_Trace("%s %s\n", prefix, hexbuf);
224
PR_smprintf_free(hexbuf);
229
dumpCertificate(CERTCertificate *cert)
231
if (!wantOcspTrace())
234
ocsp_Trace("OCSP ----------------\n");
235
ocsp_Trace("OCSP ## SUBJECT: %s\n", cert->subjectName);
237
int64 timeBefore, timeAfter;
238
PRExplodedTime beforePrintable, afterPrintable;
239
char beforestr[100], afterstr[100];
240
DER_DecodeTimeChoice(&timeBefore, &cert->validity.notBefore);
241
DER_DecodeTimeChoice(&timeAfter, &cert->validity.notAfter);
242
PR_ExplodeTime(timeBefore, PR_GMTParameters, &beforePrintable);
243
PR_ExplodeTime(timeAfter, PR_GMTParameters, &afterPrintable);
244
PR_FormatTime(beforestr, 100, "%a %b %d %H:%M:%S %Y",
246
PR_FormatTime(afterstr, 100, "%a %b %d %H:%M:%S %Y",
248
ocsp_Trace("OCSP ## VALIDITY: %s to %s\n", beforestr, afterstr);
250
ocsp_Trace("OCSP ## ISSUER: %s\n", cert->issuerName);
251
printHexString("OCSP ## SERIAL NUMBER:", &cert->serialNumber);
77
256
SEC_RegisterDefaultHttpClient(const SEC_HttpClientFcn *fcnTable)
79
if (!OCSP_Global.lock) {
258
if (!OCSP_Global.monitor) {
80
259
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
81
260
return SECFailure;
84
PR_Lock(OCSP_Global.lock);
263
PR_EnterMonitor(OCSP_Global.monitor);
85
264
OCSP_Global.defaultHttpClientFcn = fcnTable;
86
PR_Unlock(OCSP_Global.lock);
265
PR_ExitMonitor(OCSP_Global.monitor);
88
267
return SECSuccess;
270
static PLHashNumber PR_CALLBACK
271
ocsp_CacheKeyHashFunction(const void *key)
273
CERTOCSPCertID *cid = (CERTOCSPCertID *)key;
274
PLHashNumber hash = 0;
278
/* a very simple hash calculation for the initial coding phase */
279
walk = (unsigned char*)cid->issuerNameHash.data;
280
for (i=0; i < cid->issuerNameHash.len; ++i, ++walk) {
283
walk = (unsigned char*)cid->issuerKeyHash.data;
284
for (i=0; i < cid->issuerKeyHash.len; ++i, ++walk) {
287
walk = (unsigned char*)cid->serialNumber.data;
288
for (i=0; i < cid->serialNumber.len; ++i, ++walk) {
294
static PRIntn PR_CALLBACK
295
ocsp_CacheKeyCompareFunction(const void *v1, const void *v2)
297
CERTOCSPCertID *cid1 = (CERTOCSPCertID *)v1;
298
CERTOCSPCertID *cid2 = (CERTOCSPCertID *)v2;
300
return (SECEqual == SECITEM_CompareItem(&cid1->issuerNameHash,
301
&cid2->issuerNameHash)
302
&& SECEqual == SECITEM_CompareItem(&cid1->issuerKeyHash,
303
&cid2->issuerKeyHash)
304
&& SECEqual == SECITEM_CompareItem(&cid1->serialNumber,
305
&cid2->serialNumber));
309
ocsp_CopyRevokedInfo(PRArenaPool *arena, ocspCertStatus *dest,
310
ocspRevokedInfo *src)
312
SECStatus rv = SECFailure;
315
mark = PORT_ArenaMark(arena);
317
dest->certStatusInfo.revokedInfo =
318
(ocspRevokedInfo *) PORT_ArenaZAlloc(arena, sizeof(ocspRevokedInfo));
319
if (!dest->certStatusInfo.revokedInfo) {
323
rv = SECITEM_CopyItem(arena,
324
&dest->certStatusInfo.revokedInfo->revocationTime,
325
&src->revocationTime);
326
if (rv != SECSuccess) {
330
if (src->revocationReason) {
331
dest->certStatusInfo.revokedInfo->revocationReason =
332
SECITEM_ArenaDupItem(arena, src->revocationReason);
333
if (!dest->certStatusInfo.revokedInfo->revocationReason) {
337
dest->certStatusInfo.revokedInfo->revocationReason = NULL;
340
PORT_ArenaUnmark(arena, mark);
344
PORT_ArenaRelease(arena, mark);
349
ocsp_CopyCertStatus(PRArenaPool *arena, ocspCertStatus *dest,
352
SECStatus rv = SECFailure;
353
dest->certStatusType = src->certStatusType;
355
switch (src->certStatusType) {
356
case ocspCertStatus_good:
357
dest->certStatusInfo.goodInfo =
358
SECITEM_ArenaDupItem(arena, src->certStatusInfo.goodInfo);
359
if (dest->certStatusInfo.goodInfo != NULL) {
363
case ocspCertStatus_revoked:
364
rv = ocsp_CopyRevokedInfo(arena, dest,
365
src->certStatusInfo.revokedInfo);
367
case ocspCertStatus_unknown:
368
dest->certStatusInfo.unknownInfo =
369
SECITEM_ArenaDupItem(arena, src->certStatusInfo.unknownInfo);
370
if (dest->certStatusInfo.unknownInfo != NULL) {
374
case ocspCertStatus_other:
376
PORT_Assert(src->certStatusType == ocspCertStatus_other);
377
dest->certStatusInfo.otherInfo =
378
SECITEM_ArenaDupItem(arena, src->certStatusInfo.otherInfo);
379
if (dest->certStatusInfo.otherInfo != NULL) {
388
ocsp_AddCacheItemToLinkedList(OCSPCacheData *cache, OCSPCacheItem *new_most_recent)
390
PR_EnterMonitor(OCSP_Global.monitor);
392
if (!cache->LRUitem) {
393
cache->LRUitem = new_most_recent;
395
new_most_recent->lessRecent = cache->MRUitem;
396
new_most_recent->moreRecent = NULL;
398
if (cache->MRUitem) {
399
cache->MRUitem->moreRecent = new_most_recent;
401
cache->MRUitem = new_most_recent;
403
PR_ExitMonitor(OCSP_Global.monitor);
407
ocsp_RemoveCacheItemFromLinkedList(OCSPCacheData *cache, OCSPCacheItem *item)
409
PR_EnterMonitor(OCSP_Global.monitor);
411
if (!item->lessRecent && !item->moreRecent) {
413
* Fail gracefully on attempts to remove an item from the list,
414
* which is currently not part of the list.
415
* But check for the edge case it is the single entry in the list.
417
if (item == cache->LRUitem &&
418
item == cache->MRUitem) {
419
/* remove the single entry */
420
PORT_Assert(cache->numberOfEntries == 1);
421
PORT_Assert(item->moreRecent == NULL);
422
cache->MRUitem = NULL;
423
cache->LRUitem = NULL;
425
PR_ExitMonitor(OCSP_Global.monitor);
429
PORT_Assert(cache->numberOfEntries > 1);
431
if (item == cache->LRUitem) {
432
PORT_Assert(item != cache->MRUitem);
433
PORT_Assert(item->lessRecent == NULL);
434
PORT_Assert(item->moreRecent != NULL);
435
PORT_Assert(item->moreRecent->lessRecent == item);
436
cache->LRUitem = item->moreRecent;
437
cache->LRUitem->lessRecent = NULL;
439
else if (item == cache->MRUitem) {
440
PORT_Assert(item->moreRecent == NULL);
441
PORT_Assert(item->lessRecent != NULL);
442
PORT_Assert(item->lessRecent->moreRecent == item);
443
cache->MRUitem = item->lessRecent;
444
cache->MRUitem->moreRecent = NULL;
446
/* remove an entry in the middle of the list */
447
PORT_Assert(item->moreRecent != NULL);
448
PORT_Assert(item->lessRecent != NULL);
449
PORT_Assert(item->lessRecent->moreRecent == item);
450
PORT_Assert(item->moreRecent->lessRecent == item);
451
item->moreRecent->lessRecent = item->lessRecent;
452
item->lessRecent->moreRecent = item->moreRecent;
455
item->lessRecent = NULL;
456
item->moreRecent = NULL;
458
PR_ExitMonitor(OCSP_Global.monitor);
462
ocsp_MakeCacheEntryMostRecent(OCSPCacheData *cache, OCSPCacheItem *new_most_recent)
464
OCSP_TRACE(("OCSP ocsp_MakeCacheEntryMostRecent THREADID %p\n",
465
PR_GetCurrentThread()));
466
PR_EnterMonitor(OCSP_Global.monitor);
467
if (cache->MRUitem == new_most_recent) {
468
OCSP_TRACE(("OCSP ocsp_MakeCacheEntryMostRecent ALREADY MOST\n"));
469
PR_ExitMonitor(OCSP_Global.monitor);
472
OCSP_TRACE(("OCSP ocsp_MakeCacheEntryMostRecent NEW entry\n"));
473
ocsp_RemoveCacheItemFromLinkedList(cache, new_most_recent);
474
ocsp_AddCacheItemToLinkedList(cache, new_most_recent);
475
PR_ExitMonitor(OCSP_Global.monitor);
479
ocsp_IsCacheDisabled()
482
* maxCacheEntries == 0 means unlimited cache entries
483
* maxCacheEntries < 0 means cache is disabled
486
PR_EnterMonitor(OCSP_Global.monitor);
487
retval = (OCSP_Global.maxCacheEntries < 0);
488
PR_ExitMonitor(OCSP_Global.monitor);
492
static OCSPCacheItem *
493
ocsp_FindCacheEntry(OCSPCacheData *cache, CERTOCSPCertID *certID)
495
OCSPCacheItem *found_ocsp_item = NULL;
496
OCSP_TRACE(("OCSP ocsp_FindCacheEntry\n"));
497
PR_EnterMonitor(OCSP_Global.monitor);
498
if (ocsp_IsCacheDisabled())
501
found_ocsp_item = (OCSPCacheItem *)PL_HashTableLookup(
502
cache->entries, certID);
503
if (!found_ocsp_item)
506
OCSP_TRACE(("OCSP ocsp_FindCacheEntry FOUND!\n"));
507
ocsp_MakeCacheEntryMostRecent(cache, found_ocsp_item);
510
PR_ExitMonitor(OCSP_Global.monitor);
511
return found_ocsp_item;
515
ocsp_FreeCacheItem(OCSPCacheItem *item)
517
OCSP_TRACE(("OCSP ocsp_FreeCacheItem\n"));
518
if (item->certStatusArena) {
519
PORT_FreeArena(item->certStatusArena, PR_FALSE);
521
if (item->certID->poolp) {
522
/* freeing this poolp arena will also free item */
523
PORT_FreeArena(item->certID->poolp, PR_FALSE);
528
ocsp_RemoveCacheItem(OCSPCacheData *cache, OCSPCacheItem *item)
530
/* The item we're removing could be either the least recently used item,
531
* or it could be an item that couldn't get updated with newer status info
532
* because of an allocation failure, or it could get removed because we're
535
PRBool couldRemoveFromHashTable;
536
OCSP_TRACE(("OCSP ocsp_RemoveCacheItem, THREADID %p\n", PR_GetCurrentThread()));
537
PR_EnterMonitor(OCSP_Global.monitor);
539
ocsp_RemoveCacheItemFromLinkedList(cache, item);
540
couldRemoveFromHashTable = PL_HashTableRemove(cache->entries,
542
PORT_Assert(couldRemoveFromHashTable);
543
--cache->numberOfEntries;
544
ocsp_FreeCacheItem(item);
545
PR_ExitMonitor(OCSP_Global.monitor);
549
ocsp_CheckCacheSize(OCSPCacheData *cache)
551
OCSP_TRACE(("OCSP ocsp_CheckCacheSize\n"));
552
PR_EnterMonitor(OCSP_Global.monitor);
553
if (OCSP_Global.maxCacheEntries <= 0) /* disabled or unlimited */
555
while (cache->numberOfEntries > OCSP_Global.maxCacheEntries) {
556
ocsp_RemoveCacheItem(cache, cache->LRUitem);
558
PR_ExitMonitor(OCSP_Global.monitor);
562
CERT_ClearOCSPCache()
564
OCSP_TRACE(("OCSP CERT_ClearOCSPCache\n"));
565
PR_EnterMonitor(OCSP_Global.monitor);
566
while (OCSP_Global.cache.numberOfEntries > 0) {
567
ocsp_RemoveCacheItem(&OCSP_Global.cache,
568
OCSP_Global.cache.LRUitem);
570
PR_ExitMonitor(OCSP_Global.monitor);
575
ocsp_CreateCacheItemAndConsumeCertID(OCSPCacheData *cache,
576
CERTOCSPCertID *certID,
577
OCSPCacheItem **pCacheItem)
581
PLHashEntry *new_hash_entry;
584
PORT_Assert(pCacheItem != NULL);
587
PR_EnterMonitor(OCSP_Global.monitor);
588
arena = certID->poolp;
589
mark = PORT_ArenaMark(arena);
591
/* ZAlloc will init all Bools to False and all Pointers to NULL */
592
item = (OCSPCacheItem *)PORT_ArenaZAlloc(certID->poolp,
593
sizeof(OCSPCacheItem));
597
item->certID = certID;
598
new_hash_entry = PL_HashTableAdd(cache->entries, item->certID,
600
if (!new_hash_entry) {
603
++cache->numberOfEntries;
604
PORT_ArenaUnmark(arena, mark);
605
ocsp_AddCacheItemToLinkedList(cache, item);
608
PR_ExitMonitor(OCSP_Global.monitor);
612
PORT_ArenaRelease(arena, mark);
613
PR_ExitMonitor(OCSP_Global.monitor);
618
ocsp_SetCacheItemResponse(OCSPCacheItem *item,
619
const CERTOCSPSingleResponse *response)
621
if (item->certStatusArena) {
622
PORT_FreeArena(item->certStatusArena, PR_FALSE);
623
item->certStatusArena = NULL;
625
item->haveThisUpdate = item->haveNextUpdate = PR_FALSE;
628
item->certStatusArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
629
if (item->certStatusArena == NULL) {
632
rv = ocsp_CopyCertStatus(item->certStatusArena, &item->certStatus,
633
response->certStatus);
634
if (rv != SECSuccess) {
635
PORT_FreeArena(item->certStatusArena, PR_FALSE);
636
item->certStatusArena = NULL;
639
rv = DER_GeneralizedTimeToTime(&item->thisUpdate,
640
&response->thisUpdate);
641
item->haveThisUpdate = (rv == SECSuccess);
642
if (response->nextUpdate) {
643
rv = DER_GeneralizedTimeToTime(&item->nextUpdate,
644
response->nextUpdate);
645
item->haveNextUpdate = (rv == SECSuccess);
647
item->haveNextUpdate = PR_FALSE;
654
ocsp_FreshenCacheItemNextFetchAttemptTime(OCSPCacheItem *cacheItem)
657
PRTime earliestAllowedNextFetchAttemptTime;
658
PRTime latestTimeWhenResponseIsConsideredFresh;
660
OCSP_TRACE(("OCSP ocsp_FreshenCacheItemNextFetchAttemptTime\n"));
662
PR_EnterMonitor(OCSP_Global.monitor);
665
OCSP_TRACE_TIME("now:", now);
667
if (cacheItem->haveThisUpdate) {
668
OCSP_TRACE_TIME("thisUpdate:", cacheItem->thisUpdate);
669
latestTimeWhenResponseIsConsideredFresh = cacheItem->thisUpdate +
670
OCSP_Global.maximumSecondsToNextFetchAttempt *
671
MICROSECONDS_PER_SECOND;
672
OCSP_TRACE_TIME("latestTimeWhenResponseIsConsideredFresh:",
673
latestTimeWhenResponseIsConsideredFresh);
675
latestTimeWhenResponseIsConsideredFresh = now +
676
OCSP_Global.minimumSecondsToNextFetchAttempt *
677
MICROSECONDS_PER_SECOND;
678
OCSP_TRACE_TIME("no thisUpdate, "
679
"latestTimeWhenResponseIsConsideredFresh:",
680
latestTimeWhenResponseIsConsideredFresh);
683
if (cacheItem->haveNextUpdate) {
684
OCSP_TRACE_TIME("have nextUpdate:", cacheItem->thisUpdate);
687
if (cacheItem->haveNextUpdate &&
688
cacheItem->nextUpdate < latestTimeWhenResponseIsConsideredFresh) {
689
latestTimeWhenResponseIsConsideredFresh = cacheItem->nextUpdate;
690
OCSP_TRACE_TIME("nextUpdate is smaller than latestFresh, setting "
691
"latestTimeWhenResponseIsConsideredFresh:",
692
latestTimeWhenResponseIsConsideredFresh);
695
earliestAllowedNextFetchAttemptTime = now +
696
OCSP_Global.minimumSecondsToNextFetchAttempt *
697
MICROSECONDS_PER_SECOND;
698
OCSP_TRACE_TIME("earliestAllowedNextFetchAttemptTime:",
699
earliestAllowedNextFetchAttemptTime);
701
if (latestTimeWhenResponseIsConsideredFresh <
702
earliestAllowedNextFetchAttemptTime) {
703
latestTimeWhenResponseIsConsideredFresh =
704
earliestAllowedNextFetchAttemptTime;
705
OCSP_TRACE_TIME("latest < earliest, setting latest to:",
706
latestTimeWhenResponseIsConsideredFresh);
709
cacheItem->nextFetchAttemptTime =
710
latestTimeWhenResponseIsConsideredFresh;
711
OCSP_TRACE_TIME("nextFetchAttemptTime",
712
latestTimeWhenResponseIsConsideredFresh);
714
PR_ExitMonitor(OCSP_Global.monitor);
718
ocsp_IsCacheItemFresh(OCSPCacheItem *cacheItem)
723
PR_EnterMonitor(OCSP_Global.monitor);
725
retval = (cacheItem->nextFetchAttemptTime > now);
726
OCSP_TRACE(("OCSP ocsp_IsCacheItemFresh: %d\n", retval));
727
PR_ExitMonitor(OCSP_Global.monitor);
732
* Status in *certIDWasConsumed will always be correct, regardless of
736
ocsp_CreateOrUpdateCacheEntry(OCSPCacheData *cache,
737
CERTOCSPCertID *certID,
738
CERTOCSPSingleResponse *single,
739
PRBool *certIDWasConsumed)
742
OCSPCacheItem *cacheItem;
743
OCSP_TRACE(("OCSP ocsp_CreateOrUpdateCacheEntry\n"));
745
if (!certIDWasConsumed) {
746
PORT_SetError(SEC_ERROR_INVALID_ARGS);
749
*certIDWasConsumed = PR_FALSE;
751
PR_EnterMonitor(OCSP_Global.monitor);
752
PORT_Assert(OCSP_Global.maxCacheEntries >= 0);
754
cacheItem = ocsp_FindCacheEntry(cache, certID);
756
rv = ocsp_CreateCacheItemAndConsumeCertID(cache, certID,
758
if (rv != SECSuccess) {
759
PR_ExitMonitor(OCSP_Global.monitor);
762
*certIDWasConsumed = PR_TRUE;
765
rv = ocsp_SetCacheItemResponse(cacheItem, single);
766
if (rv != SECSuccess) {
767
ocsp_RemoveCacheItem(cache, cacheItem);
768
PR_ExitMonitor(OCSP_Global.monitor);
772
ocsp_FreshenCacheItemNextFetchAttemptTime(cacheItem);
773
ocsp_CheckCacheSize(cache);
775
PR_ExitMonitor(OCSP_Global.monitor);
780
CERT_SetOCSPFailureMode(SEC_OcspFailureMode ocspFailureMode)
782
switch (ocspFailureMode) {
783
case ocspMode_FailureIsVerificationFailure:
784
case ocspMode_FailureIsNotAVerificationFailure:
787
PORT_SetError(SEC_ERROR_INVALID_ARGS);
791
PR_EnterMonitor(OCSP_Global.monitor);
792
OCSP_Global.ocspFailureMode = ocspFailureMode;
793
PR_ExitMonitor(OCSP_Global.monitor);
798
CERT_OCSPCacheSettings(PRInt32 maxCacheEntries,
799
PRUint32 minimumSecondsToNextFetchAttempt,
800
PRUint32 maximumSecondsToNextFetchAttempt)
802
if (minimumSecondsToNextFetchAttempt > maximumSecondsToNextFetchAttempt
803
|| maxCacheEntries < -1) {
804
PORT_SetError(SEC_ERROR_INVALID_ARGS);
808
PR_EnterMonitor(OCSP_Global.monitor);
810
if (maxCacheEntries < 0) {
811
OCSP_Global.maxCacheEntries = -1; /* disable cache */
812
} else if (maxCacheEntries == 0) {
813
OCSP_Global.maxCacheEntries = 0; /* unlimited cache entries */
815
OCSP_Global.maxCacheEntries = maxCacheEntries;
818
if (minimumSecondsToNextFetchAttempt <
819
OCSP_Global.minimumSecondsToNextFetchAttempt
820
|| maximumSecondsToNextFetchAttempt <
821
OCSP_Global.maximumSecondsToNextFetchAttempt) {
823
* Ensure our existing cache entries are not used longer than the
824
* new settings allow, we're lazy and just clear the cache
826
CERT_ClearOCSPCache();
829
OCSP_Global.minimumSecondsToNextFetchAttempt =
830
minimumSecondsToNextFetchAttempt;
831
OCSP_Global.maximumSecondsToNextFetchAttempt =
832
maximumSecondsToNextFetchAttempt;
833
ocsp_CheckCacheSize(&OCSP_Global.cache);
835
PR_ExitMonitor(OCSP_Global.monitor);
91
839
/* this function is called at NSS initialization time */
92
SECStatus InitOCSPGlobal(void)
94
if (OCSP_Global.lock != NULL) {
95
/* already initialized */
840
SECStatus OCSP_InitGlobal(void)
842
SECStatus rv = SECFailure;
844
if (OCSP_Global.monitor == NULL) {
845
OCSP_Global.monitor = PR_NewMonitor();
847
if (!OCSP_Global.monitor)
850
PR_EnterMonitor(OCSP_Global.monitor);
851
if (!OCSP_Global.cache.entries) {
852
OCSP_Global.cache.entries =
854
ocsp_CacheKeyHashFunction,
855
ocsp_CacheKeyCompareFunction,
859
OCSP_Global.ocspFailureMode = ocspMode_FailureIsVerificationFailure;
860
OCSP_Global.cache.numberOfEntries = 0;
861
OCSP_Global.cache.MRUitem = NULL;
862
OCSP_Global.cache.LRUitem = NULL;
865
* NSS might call this function twice while attempting to init.
866
* But it's not allowed to call this again after any activity.
868
PORT_Assert(OCSP_Global.cache.numberOfEntries == 0);
869
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
871
if (OCSP_Global.cache.entries)
873
PR_ExitMonitor(OCSP_Global.monitor);
877
SECStatus OCSP_ShutdownCache(void)
879
if (!OCSP_Global.monitor)
882
PR_EnterMonitor(OCSP_Global.monitor);
883
if (OCSP_Global.cache.entries) {
884
CERT_ClearOCSPCache();
885
PL_HashTableDestroy(OCSP_Global.cache.entries);
886
OCSP_Global.cache.entries = NULL;
888
PORT_Assert(OCSP_Global.cache.numberOfEntries == 0);
889
OCSP_Global.cache.MRUitem = NULL;
890
OCSP_Global.cache.LRUitem = NULL;
891
PR_ExitMonitor(OCSP_Global.monitor);
96
892
return SECSuccess;
99
OCSP_Global.lock = PR_NewLock();
101
return (OCSP_Global.lock) ? SECSuccess : SECFailure;