tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ocsp.c (203268B)


      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 /*
      6 * Implementation of OCSP services, for both client and server.
      7 * (XXX, really, mostly just for client right now, but intended to do both.)
      8 */
      9 
     10 #include "prerror.h"
     11 #include "prprf.h"
     12 #include "plarena.h"
     13 #include "prnetdb.h"
     14 
     15 #include "seccomon.h"
     16 #include "secitem.h"
     17 #include "secoidt.h"
     18 #include "secasn1.h"
     19 #include "secder.h"
     20 #include "cert.h"
     21 #include "certi.h"
     22 #include "xconst.h"
     23 #include "secerr.h"
     24 #include "secoid.h"
     25 #include "hasht.h"
     26 #include "sechash.h"
     27 #include "secasn1.h"
     28 #include "plbase64.h"
     29 #include "keyhi.h"
     30 #include "cryptohi.h"
     31 #include "ocsp.h"
     32 #include "ocspti.h"
     33 #include "ocspi.h"
     34 #include "genname.h"
     35 #include "certxutl.h"
     36 #include "pk11func.h" /* for PK11_HashBuf */
     37 #include <stdarg.h>
     38 #include <plhash.h>
     39 
     40 #define DEFAULT_OCSP_CACHE_SIZE 1000
     41 #define DEFAULT_MINIMUM_SECONDS_TO_NEXT_OCSP_FETCH_ATTEMPT 1 * 60 * 60L
     42 #define DEFAULT_MAXIMUM_SECONDS_TO_NEXT_OCSP_FETCH_ATTEMPT 24 * 60 * 60L
     43 #define DEFAULT_OSCP_TIMEOUT_SECONDS 60
     44 #define MICROSECONDS_PER_SECOND 1000000L
     45 
     46 typedef struct OCSPCacheItemStr OCSPCacheItem;
     47 typedef struct OCSPCacheDataStr OCSPCacheData;
     48 
     49 struct OCSPCacheItemStr {
     50    /* LRU linking */
     51    OCSPCacheItem *moreRecent;
     52    OCSPCacheItem *lessRecent;
     53 
     54    /* key */
     55    CERTOCSPCertID *certID;
     56    /* CertID's arena also used to allocate "this" cache item */
     57 
     58    /* cache control information */
     59    PRTime nextFetchAttemptTime;
     60 
     61    /* Cached contents. Use a separate arena, because lifetime is different */
     62    PLArenaPool *certStatusArena; /* NULL means: no cert status cached */
     63    ocspCertStatus certStatus;
     64 
     65    /* This may contain an error code when no OCSP response is available. */
     66    SECErrorCodes missingResponseError;
     67 
     68    PRPackedBool haveThisUpdate;
     69    PRPackedBool haveNextUpdate;
     70    PRTime thisUpdate;
     71    PRTime nextUpdate;
     72 };
     73 
     74 struct OCSPCacheDataStr {
     75    PLHashTable *entries;
     76    PRUint32 numberOfEntries;
     77    OCSPCacheItem *MRUitem; /* most recently used cache item */
     78    OCSPCacheItem *LRUitem; /* least recently used cache item */
     79 };
     80 
     81 static struct OCSPGlobalStruct {
     82    PRMonitor *monitor;
     83    const SEC_HttpClientFcn *defaultHttpClientFcn;
     84    PRInt32 maxCacheEntries;
     85    PRUint32 minimumSecondsToNextFetchAttempt;
     86    PRUint32 maximumSecondsToNextFetchAttempt;
     87    PRUint32 timeoutSeconds;
     88    OCSPCacheData cache;
     89    SEC_OcspFailureMode ocspFailureMode;
     90    CERT_StringFromCertFcn alternateOCSPAIAFcn;
     91    PRBool forcePost;
     92 } OCSP_Global = { NULL,
     93                  NULL,
     94                  DEFAULT_OCSP_CACHE_SIZE,
     95                  DEFAULT_MINIMUM_SECONDS_TO_NEXT_OCSP_FETCH_ATTEMPT,
     96                  DEFAULT_MAXIMUM_SECONDS_TO_NEXT_OCSP_FETCH_ATTEMPT,
     97                  DEFAULT_OSCP_TIMEOUT_SECONDS,
     98                  { NULL, 0, NULL, NULL },
     99                  ocspMode_FailureIsVerificationFailure,
    100                  NULL,
    101                  PR_FALSE };
    102 
    103 /* Forward declarations */
    104 static SECItem *
    105 ocsp_GetEncodedOCSPResponseFromRequest(PLArenaPool *arena,
    106                                       CERTOCSPRequest *request,
    107                                       const char *location,
    108                                       const char *method,
    109                                       PRTime time,
    110                                       PRBool addServiceLocator,
    111                                       void *pwArg,
    112                                       CERTOCSPRequest **pRequest);
    113 static SECStatus
    114 ocsp_GetOCSPStatusFromNetwork(CERTCertDBHandle *handle,
    115                              CERTOCSPCertID *certID,
    116                              CERTCertificate *cert,
    117                              PRTime time,
    118                              void *pwArg,
    119                              PRBool *certIDWasConsumed,
    120                              SECStatus *rv_ocsp);
    121 
    122 static SECStatus
    123 ocsp_GetDecodedVerifiedSingleResponseForID(CERTCertDBHandle *handle,
    124                                           CERTOCSPCertID *certID,
    125                                           CERTCertificate *cert,
    126                                           PRTime time,
    127                                           void *pwArg,
    128                                           const SECItem *encodedResponse,
    129                                           CERTOCSPResponse **pDecodedResponse,
    130                                           CERTOCSPSingleResponse **pSingle);
    131 
    132 static SECStatus
    133 ocsp_CertRevokedAfter(ocspRevokedInfo *revokedInfo, PRTime time);
    134 
    135 static CERTOCSPCertID *
    136 cert_DupOCSPCertID(const CERTOCSPCertID *src);
    137 
    138 #ifndef DEBUG
    139 #define OCSP_TRACE(msg)
    140 #define OCSP_TRACE_TIME(msg, time)
    141 #define OCSP_TRACE_CERT(cert)
    142 #define OCSP_TRACE_CERTID(certid)
    143 #else
    144 #define OCSP_TRACE(msg) ocsp_Trace msg
    145 #define OCSP_TRACE_TIME(msg, time) ocsp_dumpStringWithTime(msg, time)
    146 #define OCSP_TRACE_CERT(cert) dumpCertificate(cert)
    147 #define OCSP_TRACE_CERTID(certid) dumpCertID(certid)
    148 
    149 #if defined(XP_UNIX) || defined(XP_WIN32) || defined(XP_MACOSX)
    150 #define NSS_HAVE_GETENV 1
    151 #endif
    152 
    153 static PRBool
    154 wantOcspTrace(void)
    155 {
    156    static PRBool firstTime = PR_TRUE;
    157    static PRBool wantTrace = PR_FALSE;
    158 
    159 #ifdef NSS_HAVE_GETENV
    160    if (firstTime) {
    161        char *ev = PR_GetEnvSecure("NSS_TRACE_OCSP");
    162        if (ev && ev[0]) {
    163            wantTrace = PR_TRUE;
    164        }
    165        firstTime = PR_FALSE;
    166    }
    167 #endif
    168    return wantTrace;
    169 }
    170 
    171 static void
    172 ocsp_Trace(const char *format, ...)
    173 {
    174    char buf[2000];
    175    va_list args;
    176 
    177    if (!wantOcspTrace())
    178        return;
    179    va_start(args, format);
    180    PR_vsnprintf(buf, sizeof(buf), format, args);
    181    va_end(args);
    182    PR_LogPrint("%s", buf);
    183 }
    184 
    185 static void
    186 ocsp_dumpStringWithTime(const char *str, PRTime time)
    187 {
    188    PRExplodedTime timePrintable;
    189    char timestr[256];
    190 
    191    if (!wantOcspTrace())
    192        return;
    193    PR_ExplodeTime(time, PR_GMTParameters, &timePrintable);
    194    if (PR_FormatTime(timestr, 256, "%a %b %d %H:%M:%S %Y", &timePrintable)) {
    195        ocsp_Trace("OCSP %s %s\n", str, timestr);
    196    }
    197 }
    198 
    199 static void
    200 printHexString(const char *prefix, SECItem *hexval)
    201 {
    202    unsigned int i;
    203    char *hexbuf = NULL;
    204 
    205    for (i = 0; i < hexval->len; i++) {
    206        if (i != hexval->len - 1) {
    207            hexbuf = PR_sprintf_append(hexbuf, "%02x:", hexval->data[i]);
    208        } else {
    209            hexbuf = PR_sprintf_append(hexbuf, "%02x", hexval->data[i]);
    210        }
    211    }
    212    if (hexbuf) {
    213        ocsp_Trace("%s %s\n", prefix, hexbuf);
    214        PR_smprintf_free(hexbuf);
    215    }
    216 }
    217 
    218 static void
    219 dumpCertificate(CERTCertificate *cert)
    220 {
    221    if (!wantOcspTrace())
    222        return;
    223 
    224    ocsp_Trace("OCSP ----------------\n");
    225    ocsp_Trace("OCSP ## SUBJECT:  %s\n", cert->subjectName);
    226    {
    227        PRTime timeBefore, timeAfter;
    228        PRExplodedTime beforePrintable, afterPrintable;
    229        char beforestr[256], afterstr[256];
    230        PRStatus rv1, rv2;
    231        DER_DecodeTimeChoice(&timeBefore, &cert->validity.notBefore);
    232        DER_DecodeTimeChoice(&timeAfter, &cert->validity.notAfter);
    233        PR_ExplodeTime(timeBefore, PR_GMTParameters, &beforePrintable);
    234        PR_ExplodeTime(timeAfter, PR_GMTParameters, &afterPrintable);
    235        rv1 = PR_FormatTime(beforestr, 256, "%a %b %d %H:%M:%S %Y",
    236                            &beforePrintable);
    237        rv2 = PR_FormatTime(afterstr, 256, "%a %b %d %H:%M:%S %Y",
    238                            &afterPrintable);
    239        ocsp_Trace("OCSP ## VALIDITY:  %s to %s\n", rv1 ? beforestr : "",
    240                   rv2 ? afterstr : "");
    241    }
    242    ocsp_Trace("OCSP ## ISSUER:  %s\n", cert->issuerName);
    243    printHexString("OCSP ## SERIAL NUMBER:", &cert->serialNumber);
    244 }
    245 
    246 static void
    247 dumpCertID(CERTOCSPCertID *certID)
    248 {
    249    if (!wantOcspTrace())
    250        return;
    251 
    252    printHexString("OCSP certID issuer", &certID->issuerNameHash);
    253    printHexString("OCSP certID serial", &certID->serialNumber);
    254 }
    255 #endif
    256 
    257 SECStatus
    258 SEC_RegisterDefaultHttpClient(const SEC_HttpClientFcn *fcnTable)
    259 {
    260    if (!OCSP_Global.monitor) {
    261        PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
    262        return SECFailure;
    263    }
    264 
    265    PR_EnterMonitor(OCSP_Global.monitor);
    266    OCSP_Global.defaultHttpClientFcn = fcnTable;
    267    PR_ExitMonitor(OCSP_Global.monitor);
    268 
    269    return SECSuccess;
    270 }
    271 
    272 SECStatus
    273 CERT_RegisterAlternateOCSPAIAInfoCallBack(
    274    CERT_StringFromCertFcn newCallback,
    275    CERT_StringFromCertFcn *oldCallback)
    276 {
    277    CERT_StringFromCertFcn old;
    278 
    279    if (!OCSP_Global.monitor) {
    280        PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
    281        return SECFailure;
    282    }
    283 
    284    PR_EnterMonitor(OCSP_Global.monitor);
    285    old = OCSP_Global.alternateOCSPAIAFcn;
    286    OCSP_Global.alternateOCSPAIAFcn = newCallback;
    287    PR_ExitMonitor(OCSP_Global.monitor);
    288    if (oldCallback)
    289        *oldCallback = old;
    290    return SECSuccess;
    291 }
    292 
    293 static PLHashNumber PR_CALLBACK
    294 ocsp_CacheKeyHashFunction(const void *key)
    295 {
    296    CERTOCSPCertID *cid = (CERTOCSPCertID *)key;
    297    PLHashNumber hash = 0;
    298    unsigned int i;
    299    unsigned char *walk;
    300 
    301    /* a very simple hash calculation for the initial coding phase */
    302    walk = (unsigned char *)cid->issuerNameHash.data;
    303    for (i = 0; i < cid->issuerNameHash.len; ++i, ++walk) {
    304        hash += *walk;
    305    }
    306    walk = (unsigned char *)cid->issuerKeyHash.data;
    307    for (i = 0; i < cid->issuerKeyHash.len; ++i, ++walk) {
    308        hash += *walk;
    309    }
    310    walk = (unsigned char *)cid->serialNumber.data;
    311    for (i = 0; i < cid->serialNumber.len; ++i, ++walk) {
    312        hash += *walk;
    313    }
    314    return hash;
    315 }
    316 
    317 static PRIntn PR_CALLBACK
    318 ocsp_CacheKeyCompareFunction(const void *v1, const void *v2)
    319 {
    320    CERTOCSPCertID *cid1 = (CERTOCSPCertID *)v1;
    321    CERTOCSPCertID *cid2 = (CERTOCSPCertID *)v2;
    322 
    323    return (SECEqual == SECITEM_CompareItem(&cid1->issuerNameHash,
    324                                            &cid2->issuerNameHash) &&
    325            SECEqual == SECITEM_CompareItem(&cid1->issuerKeyHash,
    326                                            &cid2->issuerKeyHash) &&
    327            SECEqual == SECITEM_CompareItem(&cid1->serialNumber,
    328                                            &cid2->serialNumber));
    329 }
    330 
    331 static SECStatus
    332 ocsp_CopyRevokedInfo(PLArenaPool *arena, ocspCertStatus *dest,
    333                     ocspRevokedInfo *src)
    334 {
    335    SECStatus rv = SECFailure;
    336    void *mark;
    337 
    338    mark = PORT_ArenaMark(arena);
    339 
    340    dest->certStatusInfo.revokedInfo =
    341        (ocspRevokedInfo *)PORT_ArenaZAlloc(arena, sizeof(ocspRevokedInfo));
    342    if (!dest->certStatusInfo.revokedInfo) {
    343        goto loser;
    344    }
    345 
    346    rv = SECITEM_CopyItem(arena,
    347                          &dest->certStatusInfo.revokedInfo->revocationTime,
    348                          &src->revocationTime);
    349    if (rv != SECSuccess) {
    350        goto loser;
    351    }
    352 
    353    if (src->revocationReason) {
    354        dest->certStatusInfo.revokedInfo->revocationReason =
    355            SECITEM_ArenaDupItem(arena, src->revocationReason);
    356        if (!dest->certStatusInfo.revokedInfo->revocationReason) {
    357            goto loser;
    358        }
    359    } else {
    360        dest->certStatusInfo.revokedInfo->revocationReason = NULL;
    361    }
    362 
    363    PORT_ArenaUnmark(arena, mark);
    364    return SECSuccess;
    365 
    366 loser:
    367    PORT_ArenaRelease(arena, mark);
    368    return SECFailure;
    369 }
    370 
    371 static SECStatus
    372 ocsp_CopyCertStatus(PLArenaPool *arena, ocspCertStatus *dest,
    373                    ocspCertStatus *src)
    374 {
    375    SECStatus rv = SECFailure;
    376    dest->certStatusType = src->certStatusType;
    377 
    378    switch (src->certStatusType) {
    379        case ocspCertStatus_good:
    380            dest->certStatusInfo.goodInfo =
    381                SECITEM_ArenaDupItem(arena, src->certStatusInfo.goodInfo);
    382            if (dest->certStatusInfo.goodInfo != NULL) {
    383                rv = SECSuccess;
    384            }
    385            break;
    386        case ocspCertStatus_revoked:
    387            rv = ocsp_CopyRevokedInfo(arena, dest,
    388                                      src->certStatusInfo.revokedInfo);
    389            break;
    390        case ocspCertStatus_unknown:
    391            dest->certStatusInfo.unknownInfo =
    392                SECITEM_ArenaDupItem(arena, src->certStatusInfo.unknownInfo);
    393            if (dest->certStatusInfo.unknownInfo != NULL) {
    394                rv = SECSuccess;
    395            }
    396            break;
    397        case ocspCertStatus_other:
    398        default:
    399            PORT_Assert(src->certStatusType == ocspCertStatus_other);
    400            dest->certStatusInfo.otherInfo =
    401                SECITEM_ArenaDupItem(arena, src->certStatusInfo.otherInfo);
    402            if (dest->certStatusInfo.otherInfo != NULL) {
    403                rv = SECSuccess;
    404            }
    405            break;
    406    }
    407    return rv;
    408 }
    409 
    410 static void
    411 ocsp_AddCacheItemToLinkedList(OCSPCacheData *cache, OCSPCacheItem *new_most_recent)
    412 {
    413    PR_EnterMonitor(OCSP_Global.monitor);
    414 
    415    if (!cache->LRUitem) {
    416        cache->LRUitem = new_most_recent;
    417    }
    418    new_most_recent->lessRecent = cache->MRUitem;
    419    new_most_recent->moreRecent = NULL;
    420 
    421    if (cache->MRUitem) {
    422        cache->MRUitem->moreRecent = new_most_recent;
    423    }
    424    cache->MRUitem = new_most_recent;
    425 
    426    PR_ExitMonitor(OCSP_Global.monitor);
    427 }
    428 
    429 static void
    430 ocsp_RemoveCacheItemFromLinkedList(OCSPCacheData *cache, OCSPCacheItem *item)
    431 {
    432    PR_EnterMonitor(OCSP_Global.monitor);
    433 
    434    if (!item->lessRecent && !item->moreRecent) {
    435        /*
    436         * Fail gracefully on attempts to remove an item from the list,
    437         * which is currently not part of the list.
    438         * But check for the edge case it is the single entry in the list.
    439         */
    440        if (item == cache->LRUitem &&
    441            item == cache->MRUitem) {
    442            /* remove the single entry */
    443            PORT_Assert(cache->numberOfEntries == 1);
    444            PORT_Assert(item->moreRecent == NULL);
    445            cache->MRUitem = NULL;
    446            cache->LRUitem = NULL;
    447        }
    448        PR_ExitMonitor(OCSP_Global.monitor);
    449        return;
    450    }
    451 
    452    PORT_Assert(cache->numberOfEntries > 1);
    453 
    454    if (item == cache->LRUitem) {
    455        PORT_Assert(item != cache->MRUitem);
    456        PORT_Assert(item->lessRecent == NULL);
    457        PORT_Assert(item->moreRecent != NULL);
    458        PORT_Assert(item->moreRecent->lessRecent == item);
    459        cache->LRUitem = item->moreRecent;
    460        cache->LRUitem->lessRecent = NULL;
    461    } else if (item == cache->MRUitem) {
    462        PORT_Assert(item->moreRecent == NULL);
    463        PORT_Assert(item->lessRecent != NULL);
    464        PORT_Assert(item->lessRecent->moreRecent == item);
    465        cache->MRUitem = item->lessRecent;
    466        cache->MRUitem->moreRecent = NULL;
    467    } else {
    468        /* remove an entry in the middle of the list */
    469        PORT_Assert(item->moreRecent != NULL);
    470        PORT_Assert(item->lessRecent != NULL);
    471        PORT_Assert(item->lessRecent->moreRecent == item);
    472        PORT_Assert(item->moreRecent->lessRecent == item);
    473        item->moreRecent->lessRecent = item->lessRecent;
    474        item->lessRecent->moreRecent = item->moreRecent;
    475    }
    476 
    477    item->lessRecent = NULL;
    478    item->moreRecent = NULL;
    479 
    480    PR_ExitMonitor(OCSP_Global.monitor);
    481 }
    482 
    483 static void
    484 ocsp_MakeCacheEntryMostRecent(OCSPCacheData *cache, OCSPCacheItem *new_most_recent)
    485 {
    486    OCSP_TRACE(("OCSP ocsp_MakeCacheEntryMostRecent THREADID %p\n",
    487                PR_GetCurrentThread()));
    488    PR_EnterMonitor(OCSP_Global.monitor);
    489    if (cache->MRUitem == new_most_recent) {
    490        OCSP_TRACE(("OCSP ocsp_MakeCacheEntryMostRecent ALREADY MOST\n"));
    491        PR_ExitMonitor(OCSP_Global.monitor);
    492        return;
    493    }
    494    OCSP_TRACE(("OCSP ocsp_MakeCacheEntryMostRecent NEW entry\n"));
    495    ocsp_RemoveCacheItemFromLinkedList(cache, new_most_recent);
    496    ocsp_AddCacheItemToLinkedList(cache, new_most_recent);
    497    PR_ExitMonitor(OCSP_Global.monitor);
    498 }
    499 
    500 static PRBool
    501 ocsp_IsCacheDisabled(void)
    502 {
    503    /*
    504     * maxCacheEntries == 0 means unlimited cache entries
    505     * maxCacheEntries  < 0 means cache is disabled
    506     */
    507    PRBool retval;
    508    PR_EnterMonitor(OCSP_Global.monitor);
    509    retval = (OCSP_Global.maxCacheEntries < 0);
    510    PR_ExitMonitor(OCSP_Global.monitor);
    511    return retval;
    512 }
    513 
    514 static OCSPCacheItem *
    515 ocsp_FindCacheEntry(OCSPCacheData *cache, CERTOCSPCertID *certID)
    516 {
    517    OCSPCacheItem *found_ocsp_item = NULL;
    518    OCSP_TRACE(("OCSP ocsp_FindCacheEntry\n"));
    519    OCSP_TRACE_CERTID(certID);
    520    PR_EnterMonitor(OCSP_Global.monitor);
    521    if (ocsp_IsCacheDisabled())
    522        goto loser;
    523 
    524    found_ocsp_item = (OCSPCacheItem *)PL_HashTableLookup(
    525        cache->entries, certID);
    526    if (!found_ocsp_item)
    527        goto loser;
    528 
    529    OCSP_TRACE(("OCSP ocsp_FindCacheEntry FOUND!\n"));
    530    ocsp_MakeCacheEntryMostRecent(cache, found_ocsp_item);
    531 
    532 loser:
    533    PR_ExitMonitor(OCSP_Global.monitor);
    534    return found_ocsp_item;
    535 }
    536 
    537 static void
    538 ocsp_FreeCacheItem(OCSPCacheItem *item)
    539 {
    540    OCSP_TRACE(("OCSP ocsp_FreeCacheItem\n"));
    541    if (item->certStatusArena) {
    542        PORT_FreeArena(item->certStatusArena, PR_FALSE);
    543    }
    544    if (item->certID->poolp) {
    545        /* freeing this poolp arena will also free item */
    546        PORT_FreeArena(item->certID->poolp, PR_FALSE);
    547    }
    548 }
    549 
    550 static void
    551 ocsp_RemoveCacheItem(OCSPCacheData *cache, OCSPCacheItem *item)
    552 {
    553    /* The item we're removing could be either the least recently used item,
    554     * or it could be an item that couldn't get updated with newer status info
    555     * because of an allocation failure, or it could get removed because we're
    556     * cleaning up.
    557     */
    558    OCSP_TRACE(("OCSP ocsp_RemoveCacheItem, THREADID %p\n", PR_GetCurrentThread()));
    559    PR_EnterMonitor(OCSP_Global.monitor);
    560 
    561    ocsp_RemoveCacheItemFromLinkedList(cache, item);
    562 #ifdef DEBUG
    563    {
    564        PRBool couldRemoveFromHashTable = PL_HashTableRemove(cache->entries,
    565                                                             item->certID);
    566        PORT_Assert(couldRemoveFromHashTable);
    567    }
    568 #else
    569    PL_HashTableRemove(cache->entries, item->certID);
    570 #endif
    571    --cache->numberOfEntries;
    572    ocsp_FreeCacheItem(item);
    573    PR_ExitMonitor(OCSP_Global.monitor);
    574 }
    575 
    576 static void
    577 ocsp_CheckCacheSize(OCSPCacheData *cache)
    578 {
    579    OCSP_TRACE(("OCSP ocsp_CheckCacheSize\n"));
    580    PR_EnterMonitor(OCSP_Global.monitor);
    581    if (OCSP_Global.maxCacheEntries > 0) {
    582        /* Cache is not disabled. Number of cache entries is limited.
    583         * The monitor ensures that maxCacheEntries remains positive.
    584         */
    585        while (cache->numberOfEntries >
    586               (PRUint32)OCSP_Global.maxCacheEntries) {
    587            ocsp_RemoveCacheItem(cache, cache->LRUitem);
    588        }
    589    }
    590    PR_ExitMonitor(OCSP_Global.monitor);
    591 }
    592 
    593 SECStatus
    594 CERT_ClearOCSPCache(void)
    595 {
    596    OCSP_TRACE(("OCSP CERT_ClearOCSPCache\n"));
    597    PR_EnterMonitor(OCSP_Global.monitor);
    598    while (OCSP_Global.cache.numberOfEntries > 0) {
    599        ocsp_RemoveCacheItem(&OCSP_Global.cache,
    600                             OCSP_Global.cache.LRUitem);
    601    }
    602    PR_ExitMonitor(OCSP_Global.monitor);
    603    return SECSuccess;
    604 }
    605 
    606 static SECStatus
    607 ocsp_CreateCacheItemAndConsumeCertID(OCSPCacheData *cache,
    608                                     CERTOCSPCertID *certID,
    609                                     OCSPCacheItem **pCacheItem)
    610 {
    611    PLArenaPool *arena;
    612    void *mark;
    613    PLHashEntry *new_hash_entry;
    614    OCSPCacheItem *item;
    615 
    616    PORT_Assert(pCacheItem != NULL);
    617    *pCacheItem = NULL;
    618 
    619    PR_EnterMonitor(OCSP_Global.monitor);
    620    arena = certID->poolp;
    621    mark = PORT_ArenaMark(arena);
    622 
    623    /* ZAlloc will init all Bools to False and all Pointers to NULL
    624       and all error codes to zero/good. */
    625    item = (OCSPCacheItem *)PORT_ArenaZAlloc(certID->poolp,
    626                                             sizeof(OCSPCacheItem));
    627    if (!item) {
    628        goto loser;
    629    }
    630    item->certID = certID;
    631    new_hash_entry = PL_HashTableAdd(cache->entries, item->certID,
    632                                     item);
    633    if (!new_hash_entry) {
    634        goto loser;
    635    }
    636    ++cache->numberOfEntries;
    637    PORT_ArenaUnmark(arena, mark);
    638    ocsp_AddCacheItemToLinkedList(cache, item);
    639    *pCacheItem = item;
    640 
    641    PR_ExitMonitor(OCSP_Global.monitor);
    642    return SECSuccess;
    643 
    644 loser:
    645    PORT_ArenaRelease(arena, mark);
    646    PR_ExitMonitor(OCSP_Global.monitor);
    647    return SECFailure;
    648 }
    649 
    650 static SECStatus
    651 ocsp_SetCacheItemResponse(OCSPCacheItem *item,
    652                          const CERTOCSPSingleResponse *response)
    653 {
    654    if (item->certStatusArena) {
    655        PORT_FreeArena(item->certStatusArena, PR_FALSE);
    656        item->certStatusArena = NULL;
    657    }
    658    item->haveThisUpdate = item->haveNextUpdate = PR_FALSE;
    659    if (response) {
    660        SECStatus rv;
    661        item->certStatusArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    662        if (item->certStatusArena == NULL) {
    663            return SECFailure;
    664        }
    665        rv = ocsp_CopyCertStatus(item->certStatusArena, &item->certStatus,
    666                                 response->certStatus);
    667        if (rv != SECSuccess) {
    668            PORT_FreeArena(item->certStatusArena, PR_FALSE);
    669            item->certStatusArena = NULL;
    670            return rv;
    671        }
    672        item->missingResponseError = 0;
    673        rv = DER_GeneralizedTimeToTime(&item->thisUpdate,
    674                                       &response->thisUpdate);
    675        item->haveThisUpdate = (rv == SECSuccess);
    676        if (response->nextUpdate) {
    677            rv = DER_GeneralizedTimeToTime(&item->nextUpdate,
    678                                           response->nextUpdate);
    679            item->haveNextUpdate = (rv == SECSuccess);
    680        } else {
    681            item->haveNextUpdate = PR_FALSE;
    682        }
    683    }
    684    return SECSuccess;
    685 }
    686 
    687 static void
    688 ocsp_FreshenCacheItemNextFetchAttemptTime(OCSPCacheItem *cacheItem)
    689 {
    690    PRTime now;
    691    PRTime earliestAllowedNextFetchAttemptTime;
    692    PRTime latestTimeWhenResponseIsConsideredFresh;
    693 
    694    OCSP_TRACE(("OCSP ocsp_FreshenCacheItemNextFetchAttemptTime\n"));
    695 
    696    PR_EnterMonitor(OCSP_Global.monitor);
    697 
    698    now = PR_Now();
    699    OCSP_TRACE_TIME("now:", now);
    700 
    701    if (cacheItem->haveThisUpdate) {
    702        OCSP_TRACE_TIME("thisUpdate:", cacheItem->thisUpdate);
    703        latestTimeWhenResponseIsConsideredFresh = cacheItem->thisUpdate +
    704                                                  OCSP_Global.maximumSecondsToNextFetchAttempt *
    705                                                      MICROSECONDS_PER_SECOND;
    706        OCSP_TRACE_TIME("latestTimeWhenResponseIsConsideredFresh:",
    707                        latestTimeWhenResponseIsConsideredFresh);
    708    } else {
    709        latestTimeWhenResponseIsConsideredFresh = now +
    710                                                  OCSP_Global.minimumSecondsToNextFetchAttempt *
    711                                                      MICROSECONDS_PER_SECOND;
    712        OCSP_TRACE_TIME("no thisUpdate, "
    713                        "latestTimeWhenResponseIsConsideredFresh:",
    714                        latestTimeWhenResponseIsConsideredFresh);
    715    }
    716 
    717    if (cacheItem->haveNextUpdate) {
    718        OCSP_TRACE_TIME("have nextUpdate:", cacheItem->nextUpdate);
    719    }
    720 
    721    if (cacheItem->haveNextUpdate &&
    722        cacheItem->nextUpdate < latestTimeWhenResponseIsConsideredFresh) {
    723        latestTimeWhenResponseIsConsideredFresh = cacheItem->nextUpdate;
    724        OCSP_TRACE_TIME("nextUpdate is smaller than latestFresh, setting "
    725                        "latestTimeWhenResponseIsConsideredFresh:",
    726                        latestTimeWhenResponseIsConsideredFresh);
    727    }
    728 
    729    earliestAllowedNextFetchAttemptTime = now +
    730                                          OCSP_Global.minimumSecondsToNextFetchAttempt *
    731                                              MICROSECONDS_PER_SECOND;
    732    OCSP_TRACE_TIME("earliestAllowedNextFetchAttemptTime:",
    733                    earliestAllowedNextFetchAttemptTime);
    734 
    735    if (latestTimeWhenResponseIsConsideredFresh <
    736        earliestAllowedNextFetchAttemptTime) {
    737        latestTimeWhenResponseIsConsideredFresh =
    738            earliestAllowedNextFetchAttemptTime;
    739        OCSP_TRACE_TIME("latest < earliest, setting latest to:",
    740                        latestTimeWhenResponseIsConsideredFresh);
    741    }
    742 
    743    cacheItem->nextFetchAttemptTime =
    744        latestTimeWhenResponseIsConsideredFresh;
    745    OCSP_TRACE_TIME("nextFetchAttemptTime",
    746                    latestTimeWhenResponseIsConsideredFresh);
    747 
    748    PR_ExitMonitor(OCSP_Global.monitor);
    749 }
    750 
    751 static PRBool
    752 ocsp_IsCacheItemFresh(OCSPCacheItem *cacheItem)
    753 {
    754    PRTime now;
    755    PRBool fresh;
    756 
    757    now = PR_Now();
    758 
    759    fresh = cacheItem->nextFetchAttemptTime > now;
    760 
    761    /* Work around broken OCSP responders that return unknown responses for
    762     * certificates, especially certificates that were just recently issued.
    763     */
    764    if (fresh && cacheItem->certStatusArena &&
    765        cacheItem->certStatus.certStatusType == ocspCertStatus_unknown) {
    766        fresh = PR_FALSE;
    767    }
    768 
    769    OCSP_TRACE(("OCSP ocsp_IsCacheItemFresh: %d\n", fresh));
    770 
    771    return fresh;
    772 }
    773 
    774 /*
    775 * Status in *certIDWasConsumed will always be correct, regardless of
    776 * return value.
    777 * If the caller is unable to transfer ownership of certID,
    778 * then the caller must set certIDWasConsumed to NULL,
    779 * and this function will potentially duplicate the certID object.
    780 */
    781 static SECStatus
    782 ocsp_CreateOrUpdateCacheEntry(OCSPCacheData *cache,
    783                              CERTOCSPCertID *certID,
    784                              CERTOCSPSingleResponse *single,
    785                              PRBool *certIDWasConsumed)
    786 {
    787    SECStatus rv;
    788    OCSPCacheItem *cacheItem;
    789    OCSP_TRACE(("OCSP ocsp_CreateOrUpdateCacheEntry\n"));
    790 
    791    if (certIDWasConsumed)
    792        *certIDWasConsumed = PR_FALSE;
    793 
    794    PR_EnterMonitor(OCSP_Global.monitor);
    795    PORT_Assert(OCSP_Global.maxCacheEntries >= 0);
    796 
    797    cacheItem = ocsp_FindCacheEntry(cache, certID);
    798 
    799    /* Don't replace an unknown or revoked entry with an error entry, even if
    800     * the existing entry is expired. Instead, we'll continue to use the
    801     * existing (possibly expired) cache entry until we receive a valid signed
    802     * response to replace it.
    803     */
    804    if (!single && cacheItem && cacheItem->certStatusArena &&
    805        (cacheItem->certStatus.certStatusType == ocspCertStatus_revoked ||
    806         cacheItem->certStatus.certStatusType == ocspCertStatus_unknown)) {
    807        PR_ExitMonitor(OCSP_Global.monitor);
    808        return SECSuccess;
    809    }
    810 
    811    if (!cacheItem) {
    812        CERTOCSPCertID *myCertID;
    813        if (certIDWasConsumed) {
    814            myCertID = certID;
    815            *certIDWasConsumed = PR_TRUE;
    816        } else {
    817            myCertID = cert_DupOCSPCertID(certID);
    818            if (!myCertID) {
    819                PR_ExitMonitor(OCSP_Global.monitor);
    820                PORT_SetError(PR_OUT_OF_MEMORY_ERROR);
    821                return SECFailure;
    822            }
    823        }
    824 
    825        rv = ocsp_CreateCacheItemAndConsumeCertID(cache, myCertID,
    826                                                  &cacheItem);
    827        if (rv != SECSuccess) {
    828            PR_ExitMonitor(OCSP_Global.monitor);
    829            return rv;
    830        }
    831    }
    832    if (single) {
    833        PRTime thisUpdate;
    834        rv = DER_GeneralizedTimeToTime(&thisUpdate, &single->thisUpdate);
    835 
    836        if (!cacheItem->haveThisUpdate ||
    837            (rv == SECSuccess && cacheItem->thisUpdate < thisUpdate)) {
    838            rv = ocsp_SetCacheItemResponse(cacheItem, single);
    839            if (rv != SECSuccess) {
    840                ocsp_RemoveCacheItem(cache, cacheItem);
    841                PR_ExitMonitor(OCSP_Global.monitor);
    842                return rv;
    843            }
    844        } else {
    845            OCSP_TRACE(("Not caching response because the response is not "
    846                        "newer than the cache"));
    847        }
    848    } else {
    849        cacheItem->missingResponseError = PORT_GetError();
    850        if (cacheItem->certStatusArena) {
    851            PORT_FreeArena(cacheItem->certStatusArena, PR_FALSE);
    852            cacheItem->certStatusArena = NULL;
    853        }
    854    }
    855    ocsp_FreshenCacheItemNextFetchAttemptTime(cacheItem);
    856    ocsp_CheckCacheSize(cache);
    857 
    858    PR_ExitMonitor(OCSP_Global.monitor);
    859    return SECSuccess;
    860 }
    861 
    862 extern SECStatus
    863 CERT_SetOCSPFailureMode(SEC_OcspFailureMode ocspFailureMode)
    864 {
    865    switch (ocspFailureMode) {
    866        case ocspMode_FailureIsVerificationFailure:
    867        case ocspMode_FailureIsNotAVerificationFailure:
    868            break;
    869        default:
    870            PORT_SetError(SEC_ERROR_INVALID_ARGS);
    871            return SECFailure;
    872    }
    873 
    874    PR_EnterMonitor(OCSP_Global.monitor);
    875    OCSP_Global.ocspFailureMode = ocspFailureMode;
    876    PR_ExitMonitor(OCSP_Global.monitor);
    877    return SECSuccess;
    878 }
    879 
    880 SECStatus
    881 CERT_OCSPCacheSettings(PRInt32 maxCacheEntries,
    882                       PRUint32 minimumSecondsToNextFetchAttempt,
    883                       PRUint32 maximumSecondsToNextFetchAttempt)
    884 {
    885    if (minimumSecondsToNextFetchAttempt > maximumSecondsToNextFetchAttempt ||
    886        maxCacheEntries < -1) {
    887        PORT_SetError(SEC_ERROR_INVALID_ARGS);
    888        return SECFailure;
    889    }
    890 
    891    PR_EnterMonitor(OCSP_Global.monitor);
    892 
    893    if (maxCacheEntries < 0) {
    894        OCSP_Global.maxCacheEntries = -1; /* disable cache */
    895    } else if (maxCacheEntries == 0) {
    896        OCSP_Global.maxCacheEntries = 0; /* unlimited cache entries */
    897    } else {
    898        OCSP_Global.maxCacheEntries = maxCacheEntries;
    899    }
    900 
    901    if (minimumSecondsToNextFetchAttempt <
    902            OCSP_Global.minimumSecondsToNextFetchAttempt ||
    903        maximumSecondsToNextFetchAttempt <
    904            OCSP_Global.maximumSecondsToNextFetchAttempt) {
    905        /*
    906         * Ensure our existing cache entries are not used longer than the
    907         * new settings allow, we're lazy and just clear the cache
    908         */
    909        CERT_ClearOCSPCache();
    910    }
    911 
    912    OCSP_Global.minimumSecondsToNextFetchAttempt =
    913        minimumSecondsToNextFetchAttempt;
    914    OCSP_Global.maximumSecondsToNextFetchAttempt =
    915        maximumSecondsToNextFetchAttempt;
    916    ocsp_CheckCacheSize(&OCSP_Global.cache);
    917 
    918    PR_ExitMonitor(OCSP_Global.monitor);
    919    return SECSuccess;
    920 }
    921 
    922 SECStatus
    923 CERT_SetOCSPTimeout(PRUint32 seconds)
    924 {
    925    /* no locking, see bug 406120 */
    926    OCSP_Global.timeoutSeconds = seconds;
    927    return SECSuccess;
    928 }
    929 
    930 /* this function is called at NSS initialization time */
    931 SECStatus
    932 OCSP_InitGlobal(void)
    933 {
    934    SECStatus rv = SECFailure;
    935 
    936    if (OCSP_Global.monitor == NULL) {
    937        OCSP_Global.monitor = PR_NewMonitor();
    938    }
    939    if (!OCSP_Global.monitor)
    940        return SECFailure;
    941 
    942    PR_EnterMonitor(OCSP_Global.monitor);
    943    if (!OCSP_Global.cache.entries) {
    944        OCSP_Global.cache.entries =
    945            PL_NewHashTable(0,
    946                            ocsp_CacheKeyHashFunction,
    947                            ocsp_CacheKeyCompareFunction,
    948                            PL_CompareValues,
    949                            NULL,
    950                            NULL);
    951        OCSP_Global.ocspFailureMode = ocspMode_FailureIsVerificationFailure;
    952        OCSP_Global.cache.numberOfEntries = 0;
    953        OCSP_Global.cache.MRUitem = NULL;
    954        OCSP_Global.cache.LRUitem = NULL;
    955    } else {
    956        /*
    957         * NSS might call this function twice while attempting to init.
    958         * But it's not allowed to call this again after any activity.
    959         */
    960        PORT_Assert(OCSP_Global.cache.numberOfEntries == 0);
    961        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
    962    }
    963    if (OCSP_Global.cache.entries)
    964        rv = SECSuccess;
    965    PR_ExitMonitor(OCSP_Global.monitor);
    966    return rv;
    967 }
    968 
    969 SECStatus
    970 OCSP_ShutdownGlobal(void)
    971 {
    972    if (!OCSP_Global.monitor)
    973        return SECSuccess;
    974 
    975    PR_EnterMonitor(OCSP_Global.monitor);
    976    if (OCSP_Global.cache.entries) {
    977        CERT_ClearOCSPCache();
    978        PL_HashTableDestroy(OCSP_Global.cache.entries);
    979        OCSP_Global.cache.entries = NULL;
    980    }
    981    PORT_Assert(OCSP_Global.cache.numberOfEntries == 0);
    982    OCSP_Global.cache.MRUitem = NULL;
    983    OCSP_Global.cache.LRUitem = NULL;
    984 
    985    OCSP_Global.defaultHttpClientFcn = NULL;
    986    OCSP_Global.maxCacheEntries = DEFAULT_OCSP_CACHE_SIZE;
    987    OCSP_Global.minimumSecondsToNextFetchAttempt =
    988        DEFAULT_MINIMUM_SECONDS_TO_NEXT_OCSP_FETCH_ATTEMPT;
    989    OCSP_Global.maximumSecondsToNextFetchAttempt =
    990        DEFAULT_MAXIMUM_SECONDS_TO_NEXT_OCSP_FETCH_ATTEMPT;
    991    OCSP_Global.ocspFailureMode =
    992        ocspMode_FailureIsVerificationFailure;
    993    PR_ExitMonitor(OCSP_Global.monitor);
    994 
    995    PR_DestroyMonitor(OCSP_Global.monitor);
    996    OCSP_Global.monitor = NULL;
    997    return SECSuccess;
    998 }
    999 
   1000 /*
   1001 * A return value of NULL means:
   1002 *   The application did not register it's own HTTP client.
   1003 */
   1004 const SEC_HttpClientFcn *
   1005 SEC_GetRegisteredHttpClient(void)
   1006 {
   1007    const SEC_HttpClientFcn *retval;
   1008 
   1009    if (!OCSP_Global.monitor) {
   1010        PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
   1011        return NULL;
   1012    }
   1013 
   1014    PR_EnterMonitor(OCSP_Global.monitor);
   1015    retval = OCSP_Global.defaultHttpClientFcn;
   1016    PR_ExitMonitor(OCSP_Global.monitor);
   1017 
   1018    return retval;
   1019 }
   1020 
   1021 /*
   1022 * The following structure is only used internally.  It is allocated when
   1023 * someone turns on OCSP checking, and hangs off of the status-configuration
   1024 * structure in the certdb structure.  We use it to keep configuration
   1025 * information specific to OCSP checking.
   1026 */
   1027 typedef struct ocspCheckingContextStr {
   1028    PRBool useDefaultResponder;
   1029    char *defaultResponderURI;
   1030    char *defaultResponderNickname;
   1031    CERTCertificate *defaultResponderCert;
   1032 } ocspCheckingContext;
   1033 
   1034 SEC_ASN1_MKSUB(SEC_AnyTemplate)
   1035 SEC_ASN1_MKSUB(SEC_IntegerTemplate)
   1036 SEC_ASN1_MKSUB(SEC_NullTemplate)
   1037 SEC_ASN1_MKSUB(SEC_OctetStringTemplate)
   1038 SEC_ASN1_MKSUB(SEC_PointerToAnyTemplate)
   1039 SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
   1040 SEC_ASN1_MKSUB(SEC_SequenceOfAnyTemplate)
   1041 SEC_ASN1_MKSUB(SEC_PointerToGeneralizedTimeTemplate)
   1042 SEC_ASN1_MKSUB(SEC_PointerToEnumeratedTemplate)
   1043 
   1044 /*
   1045 * Forward declarations of sub-types, so I can lay out the types in the
   1046 * same order as the ASN.1 is laid out in the OCSP spec itself.
   1047 *
   1048 * These are in alphabetical order (case-insensitive); please keep it that way!
   1049 */
   1050 extern const SEC_ASN1Template ocsp_CertIDTemplate[];
   1051 extern const SEC_ASN1Template ocsp_PointerToSignatureTemplate[];
   1052 extern const SEC_ASN1Template ocsp_PointerToResponseBytesTemplate[];
   1053 extern const SEC_ASN1Template ocsp_ResponseDataTemplate[];
   1054 extern const SEC_ASN1Template ocsp_RevokedInfoTemplate[];
   1055 extern const SEC_ASN1Template ocsp_SingleRequestTemplate[];
   1056 extern const SEC_ASN1Template ocsp_SingleResponseTemplate[];
   1057 extern const SEC_ASN1Template ocsp_TBSRequestTemplate[];
   1058 
   1059 /*
   1060 * Request-related templates...
   1061 */
   1062 
   1063 /*
   1064 * OCSPRequest	::=	SEQUENCE {
   1065 *	tbsRequest		TBSRequest,
   1066 *	optionalSignature	[0] EXPLICIT Signature OPTIONAL }
   1067 */
   1068 static const SEC_ASN1Template ocsp_OCSPRequestTemplate[] = {
   1069    { SEC_ASN1_SEQUENCE,
   1070      0, NULL, sizeof(CERTOCSPRequest) },
   1071    { SEC_ASN1_POINTER,
   1072      offsetof(CERTOCSPRequest, tbsRequest),
   1073      ocsp_TBSRequestTemplate },
   1074    { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
   1075          SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
   1076      offsetof(CERTOCSPRequest, optionalSignature),
   1077      ocsp_PointerToSignatureTemplate },
   1078    { 0 }
   1079 };
   1080 
   1081 /*
   1082 * TBSRequest	::=	SEQUENCE {
   1083 *	version			[0] EXPLICIT Version DEFAULT v1,
   1084 *	requestorName		[1] EXPLICIT GeneralName OPTIONAL,
   1085 *	requestList		SEQUENCE OF Request,
   1086 *	requestExtensions	[2] EXPLICIT Extensions OPTIONAL }
   1087 *
   1088 * Version	::=	INTEGER { v1(0) }
   1089 *
   1090 * Note: this should be static but the AIX compiler doesn't like it (because it
   1091 * was forward-declared above); it is not meant to be exported, but this
   1092 * is the only way it will compile.
   1093 */
   1094 const SEC_ASN1Template ocsp_TBSRequestTemplate[] = {
   1095    { SEC_ASN1_SEQUENCE,
   1096      0, NULL, sizeof(ocspTBSRequest) },
   1097    { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | /* XXX DER_DEFAULT */
   1098          SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0,
   1099      offsetof(ocspTBSRequest, version),
   1100      SEC_ASN1_SUB(SEC_IntegerTemplate) },
   1101    { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
   1102          SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 1,
   1103      offsetof(ocspTBSRequest, derRequestorName),
   1104      SEC_ASN1_SUB(SEC_PointerToAnyTemplate) },
   1105    { SEC_ASN1_SEQUENCE_OF,
   1106      offsetof(ocspTBSRequest, requestList),
   1107      ocsp_SingleRequestTemplate },
   1108    { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
   1109          SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 2,
   1110      offsetof(ocspTBSRequest, requestExtensions),
   1111      CERT_SequenceOfCertExtensionTemplate },
   1112    { 0 }
   1113 };
   1114 
   1115 /*
   1116 * Signature	::=	SEQUENCE {
   1117 *	signatureAlgorithm	AlgorithmIdentifier,
   1118 *	signature		BIT STRING,
   1119 *	certs			[0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
   1120 */
   1121 static const SEC_ASN1Template ocsp_SignatureTemplate[] = {
   1122    { SEC_ASN1_SEQUENCE,
   1123      0, NULL, sizeof(ocspSignature) },
   1124    { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
   1125      offsetof(ocspSignature, signatureAlgorithm),
   1126      SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
   1127    { SEC_ASN1_BIT_STRING,
   1128      offsetof(ocspSignature, signature) },
   1129    { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
   1130          SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0,
   1131      offsetof(ocspSignature, derCerts),
   1132      SEC_ASN1_SUB(SEC_SequenceOfAnyTemplate) },
   1133    { 0 }
   1134 };
   1135 
   1136 /*
   1137 * This template is just an extra level to use in an explicitly-tagged
   1138 * reference to a Signature.
   1139 *
   1140 * Note: this should be static but the AIX compiler doesn't like it (because it
   1141 * was forward-declared above); it is not meant to be exported, but this
   1142 * is the only way it will compile.
   1143 */
   1144 const SEC_ASN1Template ocsp_PointerToSignatureTemplate[] = {
   1145    { SEC_ASN1_POINTER, 0, ocsp_SignatureTemplate }
   1146 };
   1147 
   1148 /*
   1149 * Request	::=	SEQUENCE {
   1150 *	reqCert			CertID,
   1151 *	singleRequestExtensions	[0] EXPLICIT Extensions OPTIONAL }
   1152 *
   1153 * Note: this should be static but the AIX compiler doesn't like it (because it
   1154 * was forward-declared above); it is not meant to be exported, but this
   1155 * is the only way it will compile.
   1156 */
   1157 const SEC_ASN1Template ocsp_SingleRequestTemplate[] = {
   1158    { SEC_ASN1_SEQUENCE,
   1159      0, NULL, sizeof(ocspSingleRequest) },
   1160    { SEC_ASN1_POINTER,
   1161      offsetof(ocspSingleRequest, reqCert),
   1162      ocsp_CertIDTemplate },
   1163    { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
   1164          SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
   1165      offsetof(ocspSingleRequest, singleRequestExtensions),
   1166      CERT_SequenceOfCertExtensionTemplate },
   1167    { 0 }
   1168 };
   1169 
   1170 /*
   1171 * This data structure and template (CertID) is used by both OCSP
   1172 * requests and responses.  It is the only one that is shared.
   1173 *
   1174 * CertID	::=	SEQUENCE {
   1175 *	hashAlgorithm		AlgorithmIdentifier,
   1176 *	issuerNameHash		OCTET STRING,	-- Hash of Issuer DN
   1177 *	issuerKeyHash		OCTET STRING,	-- Hash of Issuer public key
   1178 *	serialNumber		CertificateSerialNumber }
   1179 *
   1180 * CertificateSerialNumber ::=	INTEGER
   1181 *
   1182 * Note: this should be static but the AIX compiler doesn't like it (because it
   1183 * was forward-declared above); it is not meant to be exported, but this
   1184 * is the only way it will compile.
   1185 */
   1186 const SEC_ASN1Template ocsp_CertIDTemplate[] = {
   1187    { SEC_ASN1_SEQUENCE,
   1188      0, NULL, sizeof(CERTOCSPCertID) },
   1189    { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
   1190      offsetof(CERTOCSPCertID, hashAlgorithm),
   1191      SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
   1192    { SEC_ASN1_OCTET_STRING,
   1193      offsetof(CERTOCSPCertID, issuerNameHash) },
   1194    { SEC_ASN1_OCTET_STRING,
   1195      offsetof(CERTOCSPCertID, issuerKeyHash) },
   1196    { SEC_ASN1_INTEGER,
   1197      offsetof(CERTOCSPCertID, serialNumber) },
   1198    { 0 }
   1199 };
   1200 
   1201 /*
   1202 * Response-related templates...
   1203 */
   1204 
   1205 /*
   1206 * OCSPResponse	::=	SEQUENCE {
   1207 *	responseStatus		OCSPResponseStatus,
   1208 *	responseBytes		[0] EXPLICIT ResponseBytes OPTIONAL }
   1209 */
   1210 const SEC_ASN1Template ocsp_OCSPResponseTemplate[] = {
   1211    { SEC_ASN1_SEQUENCE,
   1212      0, NULL, sizeof(CERTOCSPResponse) },
   1213    { SEC_ASN1_ENUMERATED,
   1214      offsetof(CERTOCSPResponse, responseStatus) },
   1215    { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
   1216          SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
   1217      offsetof(CERTOCSPResponse, responseBytes),
   1218      ocsp_PointerToResponseBytesTemplate },
   1219    { 0 }
   1220 };
   1221 
   1222 /*
   1223 * ResponseBytes	::=	SEQUENCE {
   1224 *	responseType		OBJECT IDENTIFIER,
   1225 *	response		OCTET STRING }
   1226 */
   1227 const SEC_ASN1Template ocsp_ResponseBytesTemplate[] = {
   1228    { SEC_ASN1_SEQUENCE,
   1229      0, NULL, sizeof(ocspResponseBytes) },
   1230    { SEC_ASN1_OBJECT_ID,
   1231      offsetof(ocspResponseBytes, responseType) },
   1232    { SEC_ASN1_OCTET_STRING,
   1233      offsetof(ocspResponseBytes, response) },
   1234    { 0 }
   1235 };
   1236 
   1237 /*
   1238 * This template is just an extra level to use in an explicitly-tagged
   1239 * reference to a ResponseBytes.
   1240 *
   1241 * Note: this should be static but the AIX compiler doesn't like it (because it
   1242 * was forward-declared above); it is not meant to be exported, but this
   1243 * is the only way it will compile.
   1244 */
   1245 const SEC_ASN1Template ocsp_PointerToResponseBytesTemplate[] = {
   1246    { SEC_ASN1_POINTER, 0, ocsp_ResponseBytesTemplate }
   1247 };
   1248 
   1249 /*
   1250 * BasicOCSPResponse	::=	SEQUENCE {
   1251 *	tbsResponseData		ResponseData,
   1252 *	signatureAlgorithm	AlgorithmIdentifier,
   1253 *	signature		BIT STRING,
   1254 *	certs			[0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
   1255 */
   1256 static const SEC_ASN1Template ocsp_BasicOCSPResponseTemplate[] = {
   1257    { SEC_ASN1_SEQUENCE,
   1258      0, NULL, sizeof(ocspBasicOCSPResponse) },
   1259    { SEC_ASN1_ANY | SEC_ASN1_SAVE,
   1260      offsetof(ocspBasicOCSPResponse, tbsResponseDataDER) },
   1261    { SEC_ASN1_POINTER,
   1262      offsetof(ocspBasicOCSPResponse, tbsResponseData),
   1263      ocsp_ResponseDataTemplate },
   1264    { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
   1265      offsetof(ocspBasicOCSPResponse, responseSignature.signatureAlgorithm),
   1266      SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
   1267    { SEC_ASN1_BIT_STRING,
   1268      offsetof(ocspBasicOCSPResponse, responseSignature.signature) },
   1269    { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
   1270          SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0,
   1271      offsetof(ocspBasicOCSPResponse, responseSignature.derCerts),
   1272      SEC_ASN1_SUB(SEC_SequenceOfAnyTemplate) },
   1273    { 0 }
   1274 };
   1275 
   1276 /*
   1277 * ResponseData	::=	SEQUENCE {
   1278 *	version			[0] EXPLICIT Version DEFAULT v1,
   1279 *	responderID		ResponderID,
   1280 *	producedAt		GeneralizedTime,
   1281 *	responses		SEQUENCE OF SingleResponse,
   1282 *	responseExtensions	[1] EXPLICIT Extensions OPTIONAL }
   1283 *
   1284 * Note: this should be static but the AIX compiler doesn't like it (because it
   1285 * was forward-declared above); it is not meant to be exported, but this
   1286 * is the only way it will compile.
   1287 */
   1288 const SEC_ASN1Template ocsp_ResponseDataTemplate[] = {
   1289    { SEC_ASN1_SEQUENCE,
   1290      0, NULL, sizeof(ocspResponseData) },
   1291    { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT | /* XXX DER_DEFAULT */
   1292          SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0,
   1293      offsetof(ocspResponseData, version),
   1294      SEC_ASN1_SUB(SEC_IntegerTemplate) },
   1295    { SEC_ASN1_ANY,
   1296      offsetof(ocspResponseData, derResponderID) },
   1297    { SEC_ASN1_GENERALIZED_TIME,
   1298      offsetof(ocspResponseData, producedAt) },
   1299    { SEC_ASN1_SEQUENCE_OF,
   1300      offsetof(ocspResponseData, responses),
   1301      ocsp_SingleResponseTemplate },
   1302    { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
   1303          SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
   1304      offsetof(ocspResponseData, responseExtensions),
   1305      CERT_SequenceOfCertExtensionTemplate },
   1306    { 0 }
   1307 };
   1308 
   1309 /*
   1310 * ResponderID	::=	CHOICE {
   1311 *	byName			[1] EXPLICIT Name,
   1312 *	byKey			[2] EXPLICIT KeyHash }
   1313 *
   1314 * KeyHash ::=	OCTET STRING -- SHA-1 hash of responder's public key
   1315 * (excluding the tag and length fields)
   1316 *
   1317 * XXX Because the ASN.1 encoder and decoder currently do not provide
   1318 * a way to automatically handle a CHOICE, we need to do it in two
   1319 * steps, looking at the type tag and feeding the exact choice back
   1320 * to the ASN.1 code.  Hopefully that will change someday and this
   1321 * can all be simplified down into a single template.  Anyway, for
   1322 * now we list each choice as its own template:
   1323 */
   1324 const SEC_ASN1Template ocsp_ResponderIDByNameTemplate[] = {
   1325    { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
   1326      offsetof(ocspResponderID, responderIDValue.name),
   1327      CERT_NameTemplate }
   1328 };
   1329 const SEC_ASN1Template ocsp_ResponderIDByKeyTemplate[] = {
   1330    { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
   1331          SEC_ASN1_XTRN | 2,
   1332      offsetof(ocspResponderID, responderIDValue.keyHash),
   1333      SEC_ASN1_SUB(SEC_OctetStringTemplate) }
   1334 };
   1335 static const SEC_ASN1Template ocsp_ResponderIDOtherTemplate[] = {
   1336    { SEC_ASN1_ANY,
   1337      offsetof(ocspResponderID, responderIDValue.other) }
   1338 };
   1339 
   1340 /* Decode choice container, but leave x509 name object encoded */
   1341 static const SEC_ASN1Template ocsp_ResponderIDDerNameTemplate[] = {
   1342    { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
   1343          SEC_ASN1_XTRN | 1,
   1344      0, SEC_ASN1_SUB(SEC_AnyTemplate) }
   1345 };
   1346 
   1347 /*
   1348 * SingleResponse	::=	SEQUENCE {
   1349 *	certID			CertID,
   1350 *	certStatus		CertStatus,
   1351 *	thisUpdate		GeneralizedTime,
   1352 *	nextUpdate		[0] EXPLICIT GeneralizedTime OPTIONAL,
   1353 *	singleExtensions	[1] EXPLICIT Extensions OPTIONAL }
   1354 *
   1355 * Note: this should be static but the AIX compiler doesn't like it (because it
   1356 * was forward-declared above); it is not meant to be exported, but this
   1357 * is the only way it will compile.
   1358 */
   1359 const SEC_ASN1Template ocsp_SingleResponseTemplate[] = {
   1360    { SEC_ASN1_SEQUENCE,
   1361      0, NULL, sizeof(CERTOCSPSingleResponse) },
   1362    { SEC_ASN1_POINTER,
   1363      offsetof(CERTOCSPSingleResponse, certID),
   1364      ocsp_CertIDTemplate },
   1365    { SEC_ASN1_ANY,
   1366      offsetof(CERTOCSPSingleResponse, derCertStatus) },
   1367    { SEC_ASN1_GENERALIZED_TIME,
   1368      offsetof(CERTOCSPSingleResponse, thisUpdate) },
   1369    { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
   1370          SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0,
   1371      offsetof(CERTOCSPSingleResponse, nextUpdate),
   1372      SEC_ASN1_SUB(SEC_PointerToGeneralizedTimeTemplate) },
   1373    { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
   1374          SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
   1375      offsetof(CERTOCSPSingleResponse, singleExtensions),
   1376      CERT_SequenceOfCertExtensionTemplate },
   1377    { 0 }
   1378 };
   1379 
   1380 /*
   1381 * CertStatus	::=	CHOICE {
   1382 *	good			[0] IMPLICIT NULL,
   1383 *	revoked			[1] IMPLICIT RevokedInfo,
   1384 *	unknown			[2] IMPLICIT UnknownInfo }
   1385 *
   1386 * Because the ASN.1 encoder and decoder currently do not provide
   1387 * a way to automatically handle a CHOICE, we need to do it in two
   1388 * steps, looking at the type tag and feeding the exact choice back
   1389 * to the ASN.1 code.  Hopefully that will change someday and this
   1390 * can all be simplified down into a single template.  Anyway, for
   1391 * now we list each choice as its own template:
   1392 */
   1393 static const SEC_ASN1Template ocsp_CertStatusGoodTemplate[] = {
   1394    { SEC_ASN1_POINTER | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0,
   1395      offsetof(ocspCertStatus, certStatusInfo.goodInfo),
   1396      SEC_ASN1_SUB(SEC_NullTemplate) }
   1397 };
   1398 static const SEC_ASN1Template ocsp_CertStatusRevokedTemplate[] = {
   1399    { SEC_ASN1_POINTER | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
   1400      offsetof(ocspCertStatus, certStatusInfo.revokedInfo),
   1401      ocsp_RevokedInfoTemplate }
   1402 };
   1403 static const SEC_ASN1Template ocsp_CertStatusUnknownTemplate[] = {
   1404    { SEC_ASN1_POINTER | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 2,
   1405      offsetof(ocspCertStatus, certStatusInfo.unknownInfo),
   1406      SEC_ASN1_SUB(SEC_NullTemplate) }
   1407 };
   1408 static const SEC_ASN1Template ocsp_CertStatusOtherTemplate[] = {
   1409    { SEC_ASN1_POINTER | SEC_ASN1_XTRN,
   1410      offsetof(ocspCertStatus, certStatusInfo.otherInfo),
   1411      SEC_ASN1_SUB(SEC_AnyTemplate) }
   1412 };
   1413 
   1414 /*
   1415 * RevokedInfo	::=	SEQUENCE {
   1416 *	revocationTime		GeneralizedTime,
   1417 *	revocationReason	[0] EXPLICIT CRLReason OPTIONAL }
   1418 *
   1419 * Note: this should be static but the AIX compiler doesn't like it (because it
   1420 * was forward-declared above); it is not meant to be exported, but this
   1421 * is the only way it will compile.
   1422 */
   1423 const SEC_ASN1Template ocsp_RevokedInfoTemplate[] = {
   1424    { SEC_ASN1_SEQUENCE,
   1425      0, NULL, sizeof(ocspRevokedInfo) },
   1426    { SEC_ASN1_GENERALIZED_TIME,
   1427      offsetof(ocspRevokedInfo, revocationTime) },
   1428    { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
   1429          SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC |
   1430          SEC_ASN1_XTRN | 0,
   1431      offsetof(ocspRevokedInfo, revocationReason),
   1432      SEC_ASN1_SUB(SEC_PointerToEnumeratedTemplate) },
   1433    { 0 }
   1434 };
   1435 
   1436 /*
   1437 * OCSP-specific extension templates:
   1438 */
   1439 
   1440 /*
   1441 * ServiceLocator	::=	SEQUENCE {
   1442 *	issuer			Name,
   1443 *	locator			AuthorityInfoAccessSyntax OPTIONAL }
   1444 */
   1445 static const SEC_ASN1Template ocsp_ServiceLocatorTemplate[] = {
   1446    { SEC_ASN1_SEQUENCE,
   1447      0, NULL, sizeof(ocspServiceLocator) },
   1448    { SEC_ASN1_POINTER,
   1449      offsetof(ocspServiceLocator, issuer),
   1450      CERT_NameTemplate },
   1451    { SEC_ASN1_OPTIONAL | SEC_ASN1_ANY,
   1452      offsetof(ocspServiceLocator, locator) },
   1453    { 0 }
   1454 };
   1455 
   1456 /*
   1457 * REQUEST SUPPORT FUNCTIONS (encode/create/decode/destroy):
   1458 */
   1459 
   1460 /*
   1461 * FUNCTION: CERT_EncodeOCSPRequest
   1462 *   DER encodes an OCSP Request, possibly adding a signature as well.
   1463 *   XXX Signing is not yet supported, however; see comments in code.
   1464 * INPUTS:
   1465 *   PLArenaPool *arena
   1466 *     The return value is allocated from here.
   1467 *     If a NULL is passed in, allocation is done from the heap instead.
   1468 *   CERTOCSPRequest *request
   1469 *     The request to be encoded.
   1470 *   void *pwArg
   1471 *     Pointer to argument for password prompting, if needed.  (Definitely
   1472 *     not needed if not signing.)
   1473 * RETURN:
   1474 *   Returns a NULL on error and a pointer to the SECItem with the
   1475 *   encoded value otherwise.  Any error is likely to be low-level
   1476 *   (e.g. no memory).
   1477 */
   1478 SECItem *
   1479 CERT_EncodeOCSPRequest(PLArenaPool *arena, CERTOCSPRequest *request,
   1480                       void *pwArg)
   1481 {
   1482    SECStatus rv;
   1483 
   1484    /* XXX All of these should generate errors if they fail. */
   1485    PORT_Assert(request);
   1486    PORT_Assert(request->tbsRequest);
   1487 
   1488    if (request->tbsRequest->extensionHandle != NULL) {
   1489        rv = CERT_FinishExtensions(request->tbsRequest->extensionHandle);
   1490        request->tbsRequest->extensionHandle = NULL;
   1491        if (rv != SECSuccess)
   1492            return NULL;
   1493    }
   1494 
   1495    /*
   1496     * XXX When signed requests are supported and request->optionalSignature
   1497     * is not NULL:
   1498     *  - need to encode tbsRequest->requestorName
   1499     *  - need to encode tbsRequest
   1500     *  - need to sign that encoded result (using cert in sig), filling in the
   1501     *    request->optionalSignature structure with the result, the signing
   1502     *    algorithm and (perhaps?) the cert (and its chain?) in derCerts
   1503     */
   1504 
   1505    return SEC_ASN1EncodeItem(arena, NULL, request, ocsp_OCSPRequestTemplate);
   1506 }
   1507 
   1508 /*
   1509 * FUNCTION: CERT_DecodeOCSPRequest
   1510 *   Decode a DER encoded OCSP Request.
   1511 * INPUTS:
   1512 *   SECItem *src
   1513 *     Pointer to a SECItem holding DER encoded OCSP Request.
   1514 * RETURN:
   1515 *   Returns a pointer to a CERTOCSPRequest containing the decoded request.
   1516 *   On error, returns NULL.  Most likely error is trouble decoding
   1517 *   (SEC_ERROR_OCSP_MALFORMED_REQUEST), or low-level problem (no memory).
   1518 */
   1519 CERTOCSPRequest *
   1520 CERT_DecodeOCSPRequest(const SECItem *src)
   1521 {
   1522    PLArenaPool *arena = NULL;
   1523    SECStatus rv = SECFailure;
   1524    CERTOCSPRequest *dest = NULL;
   1525    int i;
   1526    SECItem newSrc;
   1527 
   1528    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   1529    if (arena == NULL) {
   1530        goto loser;
   1531    }
   1532    dest = (CERTOCSPRequest *)PORT_ArenaZAlloc(arena,
   1533                                               sizeof(CERTOCSPRequest));
   1534    if (dest == NULL) {
   1535        goto loser;
   1536    }
   1537    dest->arena = arena;
   1538 
   1539    /* copy the DER into the arena, since Quick DER returns data that points
   1540       into the DER input, which may get freed by the caller */
   1541    rv = SECITEM_CopyItem(arena, &newSrc, src);
   1542    if (rv != SECSuccess) {
   1543        goto loser;
   1544    }
   1545 
   1546    rv = SEC_QuickDERDecodeItem(arena, dest, ocsp_OCSPRequestTemplate, &newSrc);
   1547    if (rv != SECSuccess) {
   1548        if (PORT_GetError() == SEC_ERROR_BAD_DER)
   1549            PORT_SetError(SEC_ERROR_OCSP_MALFORMED_REQUEST);
   1550        goto loser;
   1551    }
   1552 
   1553    /*
   1554     * XXX I would like to find a way to get rid of the necessity
   1555     * of doing this copying of the arena pointer.
   1556     */
   1557    for (i = 0; dest->tbsRequest->requestList[i] != NULL; i++) {
   1558        dest->tbsRequest->requestList[i]->arena = arena;
   1559    }
   1560 
   1561    return dest;
   1562 
   1563 loser:
   1564    if (arena != NULL) {
   1565        PORT_FreeArena(arena, PR_FALSE);
   1566    }
   1567    return NULL;
   1568 }
   1569 
   1570 SECStatus
   1571 CERT_DestroyOCSPCertID(CERTOCSPCertID *certID)
   1572 {
   1573    if (certID && certID->poolp) {
   1574        PORT_FreeArena(certID->poolp, PR_FALSE);
   1575        return SECSuccess;
   1576    }
   1577    PORT_SetError(SEC_ERROR_INVALID_ARGS);
   1578    return SECFailure;
   1579 }
   1580 
   1581 /*
   1582 * Digest data using the specified algorithm.
   1583 * The necessary storage for the digest data is allocated.  If "fill" is
   1584 * non-null, the data is put there, otherwise a SECItem is allocated.
   1585 * Allocation from "arena" if it is non-null, heap otherwise.  Any problem
   1586 * results in a NULL being returned (and an appropriate error set).
   1587 */
   1588 
   1589 SECItem *
   1590 ocsp_DigestValue(PLArenaPool *arena, SECOidTag digestAlg,
   1591                 SECItem *fill, const SECItem *src)
   1592 {
   1593    const SECHashObject *digestObject;
   1594    SECItem *result = NULL;
   1595    void *mark = NULL;
   1596    void *digestBuff = NULL;
   1597 
   1598    if (arena != NULL) {
   1599        mark = PORT_ArenaMark(arena);
   1600    }
   1601 
   1602    digestObject = HASH_GetHashObjectByOidTag(digestAlg);
   1603    if (digestObject == NULL) {
   1604        goto loser;
   1605    }
   1606 
   1607    if (fill == NULL || fill->data == NULL) {
   1608        result = SECITEM_AllocItem(arena, fill, digestObject->length);
   1609        if (result == NULL) {
   1610            goto loser;
   1611        }
   1612        digestBuff = result->data;
   1613    } else {
   1614        if (fill->len < digestObject->length) {
   1615            PORT_SetError(SEC_ERROR_INVALID_ARGS);
   1616            goto loser;
   1617        }
   1618        digestBuff = fill->data;
   1619    }
   1620 
   1621    if (PK11_HashBuf(digestAlg, digestBuff,
   1622                     src->data, src->len) != SECSuccess) {
   1623        goto loser;
   1624    }
   1625 
   1626    if (arena != NULL) {
   1627        PORT_ArenaUnmark(arena, mark);
   1628    }
   1629 
   1630    if (result == NULL) {
   1631        result = fill;
   1632    }
   1633    return result;
   1634 
   1635 loser:
   1636    if (arena != NULL) {
   1637        PORT_ArenaRelease(arena, mark);
   1638    } else {
   1639        if (result != NULL) {
   1640            SECITEM_FreeItem(result, (fill == NULL) ? PR_TRUE : PR_FALSE);
   1641        }
   1642    }
   1643    return (NULL);
   1644 }
   1645 
   1646 /*
   1647 * Digest the cert's subject public key using the specified algorithm.
   1648 * The necessary storage for the digest data is allocated.  If "fill" is
   1649 * non-null, the data is put there, otherwise a SECItem is allocated.
   1650 * Allocation from "arena" if it is non-null, heap otherwise.  Any problem
   1651 * results in a NULL being returned (and an appropriate error set).
   1652 */
   1653 SECItem *
   1654 CERT_GetSubjectPublicKeyDigest(PLArenaPool *arena, const CERTCertificate *cert,
   1655                               SECOidTag digestAlg, SECItem *fill)
   1656 {
   1657    SECItem spk;
   1658 
   1659    /*
   1660     * Copy just the length and data pointer (nothing needs to be freed)
   1661     * of the subject public key so we can convert the length from bits
   1662     * to bytes, which is what the digest function expects.
   1663     */
   1664    spk = cert->subjectPublicKeyInfo.subjectPublicKey;
   1665    DER_ConvertBitString(&spk);
   1666 
   1667    return ocsp_DigestValue(arena, digestAlg, fill, &spk);
   1668 }
   1669 
   1670 /*
   1671 * Digest the cert's subject name using the specified algorithm.
   1672 */
   1673 SECItem *
   1674 CERT_GetSubjectNameDigest(PLArenaPool *arena, const CERTCertificate *cert,
   1675                          SECOidTag digestAlg, SECItem *fill)
   1676 {
   1677    SECItem name;
   1678 
   1679    /*
   1680     * Copy just the length and data pointer (nothing needs to be freed)
   1681     * of the subject name
   1682     */
   1683    name = cert->derSubject;
   1684 
   1685    return ocsp_DigestValue(arena, digestAlg, fill, &name);
   1686 }
   1687 
   1688 /*
   1689 * Create and fill-in a CertID.  This function fills in the hash values
   1690 * (issuerNameHash and issuerKeyHash), and is hardwired to use SHA1.
   1691 * Someday it might need to be more flexible about hash algorithm, but
   1692 * for now we have no intention/need to create anything else.
   1693 *
   1694 * Error causes a null to be returned; most likely cause is trouble
   1695 * finding the certificate issuer (SEC_ERROR_UNKNOWN_ISSUER).
   1696 * Other errors are low-level problems (no memory, bad database, etc.).
   1697 */
   1698 static CERTOCSPCertID *
   1699 ocsp_CreateCertID(PLArenaPool *arena, CERTCertificate *cert, PRTime time)
   1700 {
   1701    CERTOCSPCertID *certID;
   1702    CERTCertificate *issuerCert = NULL;
   1703    void *mark = PORT_ArenaMark(arena);
   1704    SECStatus rv;
   1705 
   1706    PORT_Assert(arena != NULL);
   1707 
   1708    certID = PORT_ArenaZNew(arena, CERTOCSPCertID);
   1709    if (certID == NULL) {
   1710        goto loser;
   1711    }
   1712 
   1713    rv = SECOID_SetAlgorithmID(arena, &certID->hashAlgorithm, SEC_OID_SHA1,
   1714                               NULL);
   1715    if (rv != SECSuccess) {
   1716        goto loser;
   1717    }
   1718 
   1719    issuerCert = CERT_FindCertIssuer(cert, time, certUsageAnyCA);
   1720    if (issuerCert == NULL) {
   1721        goto loser;
   1722    }
   1723 
   1724    if (CERT_GetSubjectNameDigest(arena, issuerCert, SEC_OID_SHA1,
   1725                                  &(certID->issuerNameHash)) == NULL) {
   1726        goto loser;
   1727    }
   1728    certID->issuerSHA1NameHash.data = certID->issuerNameHash.data;
   1729    certID->issuerSHA1NameHash.len = certID->issuerNameHash.len;
   1730 
   1731    if (CERT_GetSubjectNameDigest(arena, issuerCert, SEC_OID_MD5,
   1732                                  &(certID->issuerMD5NameHash)) == NULL) {
   1733        goto loser;
   1734    }
   1735 
   1736    if (CERT_GetSubjectNameDigest(arena, issuerCert, SEC_OID_MD2,
   1737                                  &(certID->issuerMD2NameHash)) == NULL) {
   1738        goto loser;
   1739    }
   1740 
   1741    if (CERT_GetSubjectPublicKeyDigest(arena, issuerCert, SEC_OID_SHA1,
   1742                                       &certID->issuerKeyHash) == NULL) {
   1743        goto loser;
   1744    }
   1745    certID->issuerSHA1KeyHash.data = certID->issuerKeyHash.data;
   1746    certID->issuerSHA1KeyHash.len = certID->issuerKeyHash.len;
   1747    /* cache the other two hash algorithms as well */
   1748    if (CERT_GetSubjectPublicKeyDigest(arena, issuerCert, SEC_OID_MD5,
   1749                                       &certID->issuerMD5KeyHash) == NULL) {
   1750        goto loser;
   1751    }
   1752    if (CERT_GetSubjectPublicKeyDigest(arena, issuerCert, SEC_OID_MD2,
   1753                                       &certID->issuerMD2KeyHash) == NULL) {
   1754        goto loser;
   1755    }
   1756 
   1757    /* now we are done with issuerCert */
   1758    CERT_DestroyCertificate(issuerCert);
   1759    issuerCert = NULL;
   1760 
   1761    rv = SECITEM_CopyItem(arena, &certID->serialNumber, &cert->serialNumber);
   1762    if (rv != SECSuccess) {
   1763        goto loser;
   1764    }
   1765 
   1766    PORT_ArenaUnmark(arena, mark);
   1767    return certID;
   1768 
   1769 loser:
   1770    if (issuerCert != NULL) {
   1771        CERT_DestroyCertificate(issuerCert);
   1772    }
   1773    PORT_ArenaRelease(arena, mark);
   1774    return NULL;
   1775 }
   1776 
   1777 CERTOCSPCertID *
   1778 CERT_CreateOCSPCertID(CERTCertificate *cert, PRTime time)
   1779 {
   1780    PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   1781    CERTOCSPCertID *certID;
   1782    PORT_Assert(arena != NULL);
   1783    if (!arena)
   1784        return NULL;
   1785 
   1786    certID = ocsp_CreateCertID(arena, cert, time);
   1787    if (!certID) {
   1788        PORT_FreeArena(arena, PR_FALSE);
   1789        return NULL;
   1790    }
   1791    certID->poolp = arena;
   1792    return certID;
   1793 }
   1794 
   1795 static CERTOCSPCertID *
   1796 cert_DupOCSPCertID(const CERTOCSPCertID *src)
   1797 {
   1798    CERTOCSPCertID *dest;
   1799    PLArenaPool *arena = NULL;
   1800 
   1801    if (!src) {
   1802        PORT_SetError(SEC_ERROR_INVALID_ARGS);
   1803        return NULL;
   1804    }
   1805 
   1806    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   1807    if (!arena)
   1808        goto loser;
   1809 
   1810    dest = PORT_ArenaZNew(arena, CERTOCSPCertID);
   1811    if (!dest)
   1812        goto loser;
   1813 
   1814 #define DUPHELP(element)                                          \
   1815    if (src->element.data &&                                      \
   1816        SECITEM_CopyItem(arena, &dest->element, &src->element) != \
   1817            SECSuccess) {                                         \
   1818        goto loser;                                               \
   1819    }
   1820 
   1821    DUPHELP(hashAlgorithm.algorithm)
   1822    DUPHELP(hashAlgorithm.parameters)
   1823    DUPHELP(issuerNameHash)
   1824    DUPHELP(issuerKeyHash)
   1825    DUPHELP(serialNumber)
   1826    DUPHELP(issuerSHA1NameHash)
   1827    DUPHELP(issuerMD5NameHash)
   1828    DUPHELP(issuerMD2NameHash)
   1829    DUPHELP(issuerSHA1KeyHash)
   1830    DUPHELP(issuerMD5KeyHash)
   1831    DUPHELP(issuerMD2KeyHash)
   1832 
   1833    dest->poolp = arena;
   1834    return dest;
   1835 
   1836 loser:
   1837    if (arena)
   1838        PORT_FreeArena(arena, PR_FALSE);
   1839    PORT_SetError(PR_OUT_OF_MEMORY_ERROR);
   1840    return NULL;
   1841 }
   1842 
   1843 /*
   1844 * Callback to set Extensions in request object
   1845 */
   1846 void
   1847 SetSingleReqExts(void *object, CERTCertExtension **exts)
   1848 {
   1849    ocspSingleRequest *singleRequest =
   1850        (ocspSingleRequest *)object;
   1851 
   1852    singleRequest->singleRequestExtensions = exts;
   1853 }
   1854 
   1855 /*
   1856 * Add the Service Locator extension to the singleRequestExtensions
   1857 * for the given singleRequest.
   1858 *
   1859 * All errors are internal or low-level problems (e.g. no memory).
   1860 */
   1861 static SECStatus
   1862 ocsp_AddServiceLocatorExtension(ocspSingleRequest *singleRequest,
   1863                                CERTCertificate *cert)
   1864 {
   1865    ocspServiceLocator *serviceLocator = NULL;
   1866    void *extensionHandle = NULL;
   1867    SECStatus rv = SECFailure;
   1868 
   1869    serviceLocator = PORT_ZNew(ocspServiceLocator);
   1870    if (serviceLocator == NULL)
   1871        goto loser;
   1872 
   1873    /*
   1874     * Normally it would be a bad idea to do a direct reference like
   1875     * this rather than allocate and copy the name *or* at least dup
   1876     * a reference of the cert.  But all we need is to be able to read
   1877     * the issuer name during the encoding we are about to do, so a
   1878     * copy is just a waste of time.
   1879     */
   1880    serviceLocator->issuer = &cert->issuer;
   1881 
   1882    rv = CERT_FindCertExtension(cert, SEC_OID_X509_AUTH_INFO_ACCESS,
   1883                                &serviceLocator->locator);
   1884    if (rv != SECSuccess) {
   1885        if (PORT_GetError() != SEC_ERROR_EXTENSION_NOT_FOUND)
   1886            goto loser;
   1887    }
   1888 
   1889    /* prepare for following loser gotos */
   1890    rv = SECFailure;
   1891    PORT_SetError(0);
   1892 
   1893    extensionHandle = cert_StartExtensions(singleRequest,
   1894                                           singleRequest->arena, SetSingleReqExts);
   1895    if (extensionHandle == NULL)
   1896        goto loser;
   1897 
   1898    rv = CERT_EncodeAndAddExtension(extensionHandle,
   1899                                    SEC_OID_PKIX_OCSP_SERVICE_LOCATOR,
   1900                                    serviceLocator, PR_FALSE,
   1901                                    ocsp_ServiceLocatorTemplate);
   1902 
   1903 loser:
   1904    if (extensionHandle != NULL) {
   1905        /*
   1906         * Either way we have to finish out the extension context (so it gets
   1907         * freed).  But careful not to override any already-set bad status.
   1908         */
   1909        SECStatus tmprv = CERT_FinishExtensions(extensionHandle);
   1910        if (rv == SECSuccess)
   1911            rv = tmprv;
   1912    }
   1913 
   1914    /*
   1915     * Finally, free the serviceLocator structure itself and we are done.
   1916     */
   1917    if (serviceLocator != NULL) {
   1918        if (serviceLocator->locator.data != NULL)
   1919            SECITEM_FreeItem(&serviceLocator->locator, PR_FALSE);
   1920        PORT_Free(serviceLocator);
   1921    }
   1922 
   1923    return rv;
   1924 }
   1925 
   1926 /*
   1927 * Creates an array of ocspSingleRequest based on a list of certs.
   1928 * Note that the code which later compares the request list with the
   1929 * response expects this array to be in the exact same order as the
   1930 * certs are found in the list.  It would be harder to change that
   1931 * order than preserve it, but since the requirement is not obvious,
   1932 * it deserves to be mentioned.
   1933 *
   1934 * Any problem causes a null return and error set:
   1935 *      SEC_ERROR_UNKNOWN_ISSUER
   1936 * Other errors are low-level problems (no memory, bad database, etc.).
   1937 */
   1938 static ocspSingleRequest **
   1939 ocsp_CreateSingleRequestList(PLArenaPool *arena, CERTCertList *certList,
   1940                             PRTime time, PRBool includeLocator)
   1941 {
   1942    ocspSingleRequest **requestList = NULL;
   1943    CERTCertListNode *node = NULL;
   1944    int i, count;
   1945    void *mark = PORT_ArenaMark(arena);
   1946 
   1947    node = CERT_LIST_HEAD(certList);
   1948    for (count = 0; !CERT_LIST_END(node, certList); count++) {
   1949        node = CERT_LIST_NEXT(node);
   1950    }
   1951 
   1952    if (count == 0)
   1953        goto loser;
   1954 
   1955    requestList = PORT_ArenaNewArray(arena, ocspSingleRequest *, count + 1);
   1956    if (requestList == NULL)
   1957        goto loser;
   1958 
   1959    node = CERT_LIST_HEAD(certList);
   1960    for (i = 0; !CERT_LIST_END(node, certList); i++) {
   1961        requestList[i] = PORT_ArenaZNew(arena, ocspSingleRequest);
   1962        if (requestList[i] == NULL)
   1963            goto loser;
   1964 
   1965        OCSP_TRACE(("OCSP CERT_CreateOCSPRequest %s\n", node->cert->subjectName));
   1966        requestList[i]->arena = arena;
   1967        requestList[i]->reqCert = ocsp_CreateCertID(arena, node->cert, time);
   1968        if (requestList[i]->reqCert == NULL)
   1969            goto loser;
   1970 
   1971        if (includeLocator == PR_TRUE) {
   1972            SECStatus rv;
   1973 
   1974            rv = ocsp_AddServiceLocatorExtension(requestList[i], node->cert);
   1975            if (rv != SECSuccess)
   1976                goto loser;
   1977        }
   1978 
   1979        node = CERT_LIST_NEXT(node);
   1980    }
   1981 
   1982    PORT_Assert(i == count);
   1983 
   1984    PORT_ArenaUnmark(arena, mark);
   1985    requestList[i] = NULL;
   1986    return requestList;
   1987 
   1988 loser:
   1989    PORT_ArenaRelease(arena, mark);
   1990    return NULL;
   1991 }
   1992 
   1993 static ocspSingleRequest **
   1994 ocsp_CreateRequestFromCert(PLArenaPool *arena,
   1995                           CERTOCSPCertID *certID,
   1996                           CERTCertificate *singleCert,
   1997                           PRTime time,
   1998                           PRBool includeLocator)
   1999 {
   2000    ocspSingleRequest **requestList = NULL;
   2001    void *mark = PORT_ArenaMark(arena);
   2002    PORT_Assert(certID != NULL && singleCert != NULL);
   2003 
   2004    /* meaning of value 2: one entry + one end marker */
   2005    requestList = PORT_ArenaNewArray(arena, ocspSingleRequest *, 2);
   2006    if (requestList == NULL)
   2007        goto loser;
   2008    requestList[0] = PORT_ArenaZNew(arena, ocspSingleRequest);
   2009    if (requestList[0] == NULL)
   2010        goto loser;
   2011    requestList[0]->arena = arena;
   2012    /* certID will live longer than the request */
   2013    requestList[0]->reqCert = certID;
   2014 
   2015    if (includeLocator == PR_TRUE) {
   2016        SECStatus rv;
   2017        rv = ocsp_AddServiceLocatorExtension(requestList[0], singleCert);
   2018        if (rv != SECSuccess)
   2019            goto loser;
   2020    }
   2021 
   2022    PORT_ArenaUnmark(arena, mark);
   2023    requestList[1] = NULL;
   2024    return requestList;
   2025 
   2026 loser:
   2027    PORT_ArenaRelease(arena, mark);
   2028    return NULL;
   2029 }
   2030 
   2031 static CERTOCSPRequest *
   2032 ocsp_prepareEmptyOCSPRequest(void)
   2033 {
   2034    PLArenaPool *arena = NULL;
   2035    CERTOCSPRequest *request = NULL;
   2036    ocspTBSRequest *tbsRequest = NULL;
   2037 
   2038    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   2039    if (arena == NULL) {
   2040        goto loser;
   2041    }
   2042    request = PORT_ArenaZNew(arena, CERTOCSPRequest);
   2043    if (request == NULL) {
   2044        goto loser;
   2045    }
   2046    request->arena = arena;
   2047 
   2048    tbsRequest = PORT_ArenaZNew(arena, ocspTBSRequest);
   2049    if (tbsRequest == NULL) {
   2050        goto loser;
   2051    }
   2052    request->tbsRequest = tbsRequest;
   2053    /* version 1 is the default, so we need not fill in a version number */
   2054    return request;
   2055 
   2056 loser:
   2057    if (arena != NULL) {
   2058        PORT_FreeArena(arena, PR_FALSE);
   2059    }
   2060    return NULL;
   2061 }
   2062 
   2063 CERTOCSPRequest *
   2064 cert_CreateSingleCertOCSPRequest(CERTOCSPCertID *certID,
   2065                                 CERTCertificate *singleCert,
   2066                                 PRTime time,
   2067                                 PRBool addServiceLocator,
   2068                                 CERTCertificate *signerCert)
   2069 {
   2070    CERTOCSPRequest *request;
   2071    OCSP_TRACE(("OCSP cert_CreateSingleCertOCSPRequest %s\n", singleCert->subjectName));
   2072 
   2073    /* XXX Support for signerCert may be implemented later,
   2074     * see also the comment in CERT_CreateOCSPRequest.
   2075     */
   2076    if (signerCert != NULL) {
   2077        PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
   2078        return NULL;
   2079    }
   2080 
   2081    request = ocsp_prepareEmptyOCSPRequest();
   2082    if (!request)
   2083        return NULL;
   2084    /*
   2085     * Version 1 is the default, so we need not fill in a version number.
   2086     * Now create the list of single requests, one for each cert.
   2087     */
   2088    request->tbsRequest->requestList =
   2089        ocsp_CreateRequestFromCert(request->arena,
   2090                                   certID,
   2091                                   singleCert,
   2092                                   time,
   2093                                   addServiceLocator);
   2094    if (request->tbsRequest->requestList == NULL) {
   2095        PORT_FreeArena(request->arena, PR_FALSE);
   2096        return NULL;
   2097    }
   2098    return request;
   2099 }
   2100 
   2101 /*
   2102 * FUNCTION: CERT_CreateOCSPRequest
   2103 *   Creates a CERTOCSPRequest, requesting the status of the certs in
   2104 *   the given list.
   2105 * INPUTS:
   2106 *   CERTCertList *certList
   2107 *     A list of certs for which status will be requested.
   2108 *     Note that all of these certificates should have the same issuer,
   2109 *     or it's expected the response will be signed by a trusted responder.
   2110 *     If the certs need to be broken up into multiple requests, that
   2111 *     must be handled by the caller (and thus by having multiple calls
   2112 *     to this routine), who knows about where the request(s) are being
   2113 *     sent and whether there are any trusted responders in place.
   2114 *   PRTime time
   2115 *     Indicates the time for which the certificate status is to be
   2116 *     determined -- this may be used in the search for the cert's issuer
   2117 *     but has no effect on the request itself.
   2118 *   PRBool addServiceLocator
   2119 *     If true, the Service Locator extension should be added to the
   2120 *     single request(s) for each cert.
   2121 *   CERTCertificate *signerCert
   2122 *     If non-NULL, means sign the request using this cert.  Otherwise,
   2123 *     do not sign.
   2124 *     XXX note that request signing is not yet supported; see comment in code
   2125 * RETURN:
   2126 *   A pointer to a CERTOCSPRequest structure containing an OCSP request
   2127 *   for the cert list.  On error, null is returned, with an error set
   2128 *   indicating the reason.  This is likely SEC_ERROR_UNKNOWN_ISSUER.
   2129 *   (The issuer is needed to create a request for the certificate.)
   2130 *   Other errors are low-level problems (no memory, bad database, etc.).
   2131 */
   2132 CERTOCSPRequest *
   2133 CERT_CreateOCSPRequest(CERTCertList *certList, PRTime time,
   2134                       PRBool addServiceLocator,
   2135                       CERTCertificate *signerCert)
   2136 {
   2137    CERTOCSPRequest *request = NULL;
   2138 
   2139    if (!certList) {
   2140        PORT_SetError(SEC_ERROR_INVALID_ARGS);
   2141        return NULL;
   2142    }
   2143    /*
   2144     * XXX When we are prepared to put signing of requests back in,
   2145     * we will need to allocate a signature
   2146     * structure for the request, fill in the "derCerts" field in it,
   2147     * save the signerCert there, as well as fill in the "requestorName"
   2148     * field of the tbsRequest.
   2149     */
   2150    if (signerCert != NULL) {
   2151        PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
   2152        return NULL;
   2153    }
   2154    request = ocsp_prepareEmptyOCSPRequest();
   2155    if (!request)
   2156        return NULL;
   2157    /*
   2158     * Now create the list of single requests, one for each cert.
   2159     */
   2160    request->tbsRequest->requestList =
   2161        ocsp_CreateSingleRequestList(request->arena,
   2162                                     certList,
   2163                                     time,
   2164                                     addServiceLocator);
   2165    if (request->tbsRequest->requestList == NULL) {
   2166        PORT_FreeArena(request->arena, PR_FALSE);
   2167        return NULL;
   2168    }
   2169    return request;
   2170 }
   2171 
   2172 /*
   2173 * FUNCTION: CERT_AddOCSPAcceptableResponses
   2174 *   Add the AcceptableResponses extension to an OCSP Request.
   2175 * INPUTS:
   2176 *   CERTOCSPRequest *request
   2177 *     The request to which the extension should be added.
   2178 *   ...
   2179 *     A list (of one or more) of SECOidTag -- each of the response types
   2180 *     to be added.  The last OID *must* be SEC_OID_PKIX_OCSP_BASIC_RESPONSE.
   2181 *     (This marks the end of the list, and it must be specified because a
   2182 *     client conforming to the OCSP standard is required to handle the basic
   2183 *     response type.)  The OIDs are not checked in any way.
   2184 * RETURN:
   2185 *   SECSuccess if the extension is added; SECFailure if anything goes wrong.
   2186 *   All errors are internal or low-level problems (e.g. no memory).
   2187 */
   2188 
   2189 void
   2190 SetRequestExts(void *object, CERTCertExtension **exts)
   2191 {
   2192    CERTOCSPRequest *request = (CERTOCSPRequest *)object;
   2193 
   2194    request->tbsRequest->requestExtensions = exts;
   2195 }
   2196 
   2197 #if defined(__GNUC__) && !defined(NSS_NO_GCC48)
   2198 #pragma GCC diagnostic push
   2199 #pragma GCC diagnostic ignored "-Wvarargs"
   2200 #endif
   2201 SECStatus
   2202 CERT_AddOCSPAcceptableResponses(CERTOCSPRequest *request,
   2203                                SECOidTag responseType0, ...)
   2204 {
   2205    void *extHandle;
   2206    va_list ap;
   2207    int i, count;
   2208    SECOidTag responseType;
   2209    SECOidData *responseOid;
   2210    SECItem **acceptableResponses = NULL;
   2211    SECStatus rv = SECFailure;
   2212 
   2213    extHandle = request->tbsRequest->extensionHandle;
   2214    if (extHandle == NULL) {
   2215        extHandle = cert_StartExtensions(request, request->arena, SetRequestExts);
   2216        if (extHandle == NULL)
   2217            goto loser;
   2218    }
   2219 
   2220    /* Count number of OIDS going into the extension value. */
   2221    count = 1;
   2222    if (responseType0 != SEC_OID_PKIX_OCSP_BASIC_RESPONSE) {
   2223        va_start(ap, responseType0);
   2224        do {
   2225            count++;
   2226            responseType = va_arg(ap, SECOidTag);
   2227        } while (responseType != SEC_OID_PKIX_OCSP_BASIC_RESPONSE);
   2228        va_end(ap);
   2229    }
   2230 
   2231    acceptableResponses = PORT_NewArray(SECItem *, count + 1);
   2232    if (acceptableResponses == NULL)
   2233        goto loser;
   2234 
   2235    i = 0;
   2236    responseOid = SECOID_FindOIDByTag(responseType0);
   2237    acceptableResponses[i++] = &(responseOid->oid);
   2238    if (count > 1) {
   2239        va_start(ap, responseType0);
   2240        for (; i < count; i++) {
   2241            responseType = va_arg(ap, SECOidTag);
   2242            responseOid = SECOID_FindOIDByTag(responseType);
   2243            acceptableResponses[i] = &(responseOid->oid);
   2244        }
   2245        va_end(ap);
   2246    }
   2247    acceptableResponses[i] = NULL;
   2248 
   2249    rv = CERT_EncodeAndAddExtension(extHandle, SEC_OID_PKIX_OCSP_RESPONSE,
   2250                                    &acceptableResponses, PR_FALSE,
   2251                                    SEC_ASN1_GET(SEC_SequenceOfObjectIDTemplate));
   2252    if (rv != SECSuccess)
   2253        goto loser;
   2254 
   2255    PORT_Free(acceptableResponses);
   2256    if (request->tbsRequest->extensionHandle == NULL)
   2257        request->tbsRequest->extensionHandle = extHandle;
   2258    return SECSuccess;
   2259 
   2260 loser:
   2261    if (acceptableResponses != NULL)
   2262        PORT_Free(acceptableResponses);
   2263    if (extHandle != NULL)
   2264        (void)CERT_FinishExtensions(extHandle);
   2265    return rv;
   2266 }
   2267 #if defined(__GNUC__) && !defined(NSS_NO_GCC48)
   2268 #pragma GCC diagnostic pop
   2269 #endif
   2270 
   2271 /*
   2272 * FUNCTION: CERT_DestroyOCSPRequest
   2273 *   Frees an OCSP Request structure.
   2274 * INPUTS:
   2275 *   CERTOCSPRequest *request
   2276 *     Pointer to CERTOCSPRequest to be freed.
   2277 * RETURN:
   2278 *   No return value; no errors.
   2279 */
   2280 void
   2281 CERT_DestroyOCSPRequest(CERTOCSPRequest *request)
   2282 {
   2283    if (request == NULL)
   2284        return;
   2285 
   2286    if (request->tbsRequest != NULL) {
   2287        if (request->tbsRequest->requestorName != NULL)
   2288            CERT_DestroyGeneralNameList(request->tbsRequest->requestorName);
   2289        if (request->tbsRequest->extensionHandle != NULL)
   2290            (void)CERT_FinishExtensions(request->tbsRequest->extensionHandle);
   2291    }
   2292 
   2293    if (request->optionalSignature != NULL) {
   2294        if (request->optionalSignature->cert != NULL)
   2295            CERT_DestroyCertificate(request->optionalSignature->cert);
   2296 
   2297        /*
   2298         * XXX Need to free derCerts?  Or do they come out of arena?
   2299         * (Currently we never fill in derCerts, which is why the
   2300         * answer is not obvious.  Once we do, add any necessary code
   2301         * here and remove this comment.)
   2302         */
   2303    }
   2304 
   2305    /*
   2306     * We should actually never have a request without an arena,
   2307     * but check just in case.  (If there isn't one, there is not
   2308     * much we can do about it...)
   2309     */
   2310    PORT_Assert(request->arena != NULL);
   2311    if (request->arena != NULL)
   2312        PORT_FreeArena(request->arena, PR_FALSE);
   2313 }
   2314 
   2315 /*
   2316 * RESPONSE SUPPORT FUNCTIONS (encode/create/decode/destroy):
   2317 */
   2318 
   2319 /*
   2320 * Helper function for encoding or decoding a ResponderID -- based on the
   2321 * given type, return the associated template for that choice.
   2322 */
   2323 static const SEC_ASN1Template *
   2324 ocsp_ResponderIDTemplateByType(CERTOCSPResponderIDType responderIDType)
   2325 {
   2326    const SEC_ASN1Template *responderIDTemplate;
   2327 
   2328    switch (responderIDType) {
   2329        case ocspResponderID_byName:
   2330            responderIDTemplate = ocsp_ResponderIDByNameTemplate;
   2331            break;
   2332        case ocspResponderID_byKey:
   2333            responderIDTemplate = ocsp_ResponderIDByKeyTemplate;
   2334            break;
   2335        case ocspResponderID_other:
   2336        default:
   2337            PORT_Assert(responderIDType == ocspResponderID_other);
   2338            responderIDTemplate = ocsp_ResponderIDOtherTemplate;
   2339            break;
   2340    }
   2341 
   2342    return responderIDTemplate;
   2343 }
   2344 
   2345 /*
   2346 * Helper function for encoding or decoding a CertStatus -- based on the
   2347 * given type, return the associated template for that choice.
   2348 */
   2349 static const SEC_ASN1Template *
   2350 ocsp_CertStatusTemplateByType(ocspCertStatusType certStatusType)
   2351 {
   2352    const SEC_ASN1Template *certStatusTemplate;
   2353 
   2354    switch (certStatusType) {
   2355        case ocspCertStatus_good:
   2356            certStatusTemplate = ocsp_CertStatusGoodTemplate;
   2357            break;
   2358        case ocspCertStatus_revoked:
   2359            certStatusTemplate = ocsp_CertStatusRevokedTemplate;
   2360            break;
   2361        case ocspCertStatus_unknown:
   2362            certStatusTemplate = ocsp_CertStatusUnknownTemplate;
   2363            break;
   2364        case ocspCertStatus_other:
   2365        default:
   2366            PORT_Assert(certStatusType == ocspCertStatus_other);
   2367            certStatusTemplate = ocsp_CertStatusOtherTemplate;
   2368            break;
   2369    }
   2370 
   2371    return certStatusTemplate;
   2372 }
   2373 
   2374 /*
   2375 * Helper function for decoding a certStatus -- turn the actual DER tag
   2376 * into our local translation.
   2377 */
   2378 static ocspCertStatusType
   2379 ocsp_CertStatusTypeByTag(int derTag)
   2380 {
   2381    ocspCertStatusType certStatusType;
   2382 
   2383    switch (derTag) {
   2384        case 0:
   2385            certStatusType = ocspCertStatus_good;
   2386            break;
   2387        case 1:
   2388            certStatusType = ocspCertStatus_revoked;
   2389            break;
   2390        case 2:
   2391            certStatusType = ocspCertStatus_unknown;
   2392            break;
   2393        default:
   2394            certStatusType = ocspCertStatus_other;
   2395            break;
   2396    }
   2397 
   2398    return certStatusType;
   2399 }
   2400 
   2401 /*
   2402 * Helper function for decoding SingleResponses -- they each contain
   2403 * a status which is encoded as CHOICE, which needs to be decoded "by hand".
   2404 *
   2405 * Note -- on error, this routine does not release the memory it may
   2406 * have allocated; it expects its caller to do that.
   2407 */
   2408 static SECStatus
   2409 ocsp_FinishDecodingSingleResponses(PLArenaPool *reqArena,
   2410                                   CERTOCSPSingleResponse **responses)
   2411 {
   2412    ocspCertStatus *certStatus;
   2413    ocspCertStatusType certStatusType;
   2414    const SEC_ASN1Template *certStatusTemplate;
   2415    int derTag;
   2416    int i;
   2417    SECStatus rv = SECFailure;
   2418 
   2419    if (!reqArena) {
   2420        PORT_SetError(SEC_ERROR_INVALID_ARGS);
   2421        return SECFailure;
   2422    }
   2423 
   2424    if (responses == NULL) /* nothing to do */
   2425        return SECSuccess;
   2426 
   2427    for (i = 0; responses[i] != NULL; i++) {
   2428        SECItem *newStatus;
   2429        /*
   2430         * The following assert points out internal errors (problems in
   2431         * the template definitions or in the ASN.1 decoder itself, etc.).
   2432         */
   2433        PORT_Assert(responses[i]->derCertStatus.data != NULL);
   2434 
   2435        derTag = responses[i]->derCertStatus.data[0] & SEC_ASN1_TAGNUM_MASK;
   2436        certStatusType = ocsp_CertStatusTypeByTag(derTag);
   2437        certStatusTemplate = ocsp_CertStatusTemplateByType(certStatusType);
   2438 
   2439        certStatus = PORT_ArenaZAlloc(reqArena, sizeof(ocspCertStatus));
   2440        if (certStatus == NULL) {
   2441            goto loser;
   2442        }
   2443        newStatus = SECITEM_ArenaDupItem(reqArena, &responses[i]->derCertStatus);
   2444        if (!newStatus) {
   2445            goto loser;
   2446        }
   2447        rv = SEC_QuickDERDecodeItem(reqArena, certStatus, certStatusTemplate,
   2448                                    newStatus);
   2449        if (rv != SECSuccess) {
   2450            if (PORT_GetError() == SEC_ERROR_BAD_DER)
   2451                PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
   2452            goto loser;
   2453        }
   2454 
   2455        certStatus->certStatusType = certStatusType;
   2456        responses[i]->certStatus = certStatus;
   2457    }
   2458 
   2459    return SECSuccess;
   2460 
   2461 loser:
   2462    return rv;
   2463 }
   2464 
   2465 /*
   2466 * Helper function for decoding a responderID -- turn the actual DER tag
   2467 * into our local translation.
   2468 */
   2469 static CERTOCSPResponderIDType
   2470 ocsp_ResponderIDTypeByTag(int derTag)
   2471 {
   2472    CERTOCSPResponderIDType responderIDType;
   2473 
   2474    switch (derTag) {
   2475        case 1:
   2476            responderIDType = ocspResponderID_byName;
   2477            break;
   2478        case 2:
   2479            responderIDType = ocspResponderID_byKey;
   2480            break;
   2481        default:
   2482            responderIDType = ocspResponderID_other;
   2483            break;
   2484    }
   2485 
   2486    return responderIDType;
   2487 }
   2488 
   2489 /*
   2490 * Decode "src" as a BasicOCSPResponse, returning the result.
   2491 */
   2492 static ocspBasicOCSPResponse *
   2493 ocsp_DecodeBasicOCSPResponse(PLArenaPool *arena, SECItem *src)
   2494 {
   2495    void *mark;
   2496    ocspBasicOCSPResponse *basicResponse;
   2497    ocspResponseData *responseData;
   2498    ocspResponderID *responderID;
   2499    CERTOCSPResponderIDType responderIDType;
   2500    const SEC_ASN1Template *responderIDTemplate;
   2501    int derTag;
   2502    SECStatus rv;
   2503    SECItem newsrc;
   2504 
   2505    mark = PORT_ArenaMark(arena);
   2506 
   2507    basicResponse = PORT_ArenaZAlloc(arena, sizeof(ocspBasicOCSPResponse));
   2508    if (basicResponse == NULL) {
   2509        goto loser;
   2510    }
   2511 
   2512    /* copy the DER into the arena, since Quick DER returns data that points
   2513       into the DER input, which may get freed by the caller */
   2514    rv = SECITEM_CopyItem(arena, &newsrc, src);
   2515    if (rv != SECSuccess) {
   2516        goto loser;
   2517    }
   2518 
   2519    rv = SEC_QuickDERDecodeItem(arena, basicResponse,
   2520                                ocsp_BasicOCSPResponseTemplate, &newsrc);
   2521    if (rv != SECSuccess) {
   2522        if (PORT_GetError() == SEC_ERROR_BAD_DER)
   2523            PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
   2524        goto loser;
   2525    }
   2526 
   2527    responseData = basicResponse->tbsResponseData;
   2528 
   2529    /*
   2530     * The following asserts point out internal errors (problems in
   2531     * the template definitions or in the ASN.1 decoder itself, etc.).
   2532     */
   2533    PORT_Assert(responseData != NULL);
   2534    PORT_Assert(responseData->derResponderID.data != NULL);
   2535 
   2536    /*
   2537     * XXX Because responderID is a CHOICE, which is not currently handled
   2538     * by our ASN.1 decoder, we have to decode it "by hand".
   2539     */
   2540    derTag = responseData->derResponderID.data[0] & SEC_ASN1_TAGNUM_MASK;
   2541    responderIDType = ocsp_ResponderIDTypeByTag(derTag);
   2542    responderIDTemplate = ocsp_ResponderIDTemplateByType(responderIDType);
   2543 
   2544    responderID = PORT_ArenaZAlloc(arena, sizeof(ocspResponderID));
   2545    if (responderID == NULL) {
   2546        goto loser;
   2547    }
   2548 
   2549    rv = SEC_QuickDERDecodeItem(arena, responderID, responderIDTemplate,
   2550                                &responseData->derResponderID);
   2551    if (rv != SECSuccess) {
   2552        if (PORT_GetError() == SEC_ERROR_BAD_DER)
   2553            PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
   2554        goto loser;
   2555    }
   2556 
   2557    responderID->responderIDType = responderIDType;
   2558    responseData->responderID = responderID;
   2559 
   2560    /*
   2561     * XXX Each SingleResponse also contains a CHOICE, which has to be
   2562     * fixed up by hand.
   2563     */
   2564    rv = ocsp_FinishDecodingSingleResponses(arena, responseData->responses);
   2565    if (rv != SECSuccess) {
   2566        goto loser;
   2567    }
   2568 
   2569    PORT_ArenaUnmark(arena, mark);
   2570    return basicResponse;
   2571 
   2572 loser:
   2573    PORT_ArenaRelease(arena, mark);
   2574    return NULL;
   2575 }
   2576 
   2577 /*
   2578 * Decode the responseBytes based on the responseType found in "rbytes",
   2579 * leaving the resulting translated/decoded information in there as well.
   2580 */
   2581 static SECStatus
   2582 ocsp_DecodeResponseBytes(PLArenaPool *arena, ocspResponseBytes *rbytes)
   2583 {
   2584    if (rbytes == NULL) {
   2585        PORT_SetError(SEC_ERROR_OCSP_UNKNOWN_RESPONSE_TYPE);
   2586        return SECFailure;
   2587    }
   2588 
   2589    rbytes->responseTypeTag = SECOID_FindOIDTag(&rbytes->responseType);
   2590    switch (rbytes->responseTypeTag) {
   2591        case SEC_OID_PKIX_OCSP_BASIC_RESPONSE: {
   2592            ocspBasicOCSPResponse *basicResponse;
   2593 
   2594            basicResponse = ocsp_DecodeBasicOCSPResponse(arena,
   2595                                                         &rbytes->response);
   2596            if (basicResponse == NULL)
   2597                return SECFailure;
   2598 
   2599            rbytes->decodedResponse.basic = basicResponse;
   2600        } break;
   2601 
   2602            /*
   2603             * Add new/future response types here.
   2604             */
   2605 
   2606        default:
   2607            PORT_SetError(SEC_ERROR_OCSP_UNKNOWN_RESPONSE_TYPE);
   2608            return SECFailure;
   2609    }
   2610 
   2611    return SECSuccess;
   2612 }
   2613 
   2614 /*
   2615 * FUNCTION: CERT_DecodeOCSPResponse
   2616 *   Decode a DER encoded OCSP Response.
   2617 * INPUTS:
   2618 *   SECItem *src
   2619 *     Pointer to a SECItem holding DER encoded OCSP Response.
   2620 * RETURN:
   2621 *   Returns a pointer to a CERTOCSPResponse (the decoded OCSP Response);
   2622 *   the caller is responsible for destroying it.  Or NULL if error (either
   2623 *   response could not be decoded (SEC_ERROR_OCSP_MALFORMED_RESPONSE),
   2624 *   it was of an unexpected type (SEC_ERROR_OCSP_UNKNOWN_RESPONSE_TYPE),
   2625 *   or a low-level or internal error occurred).
   2626 */
   2627 CERTOCSPResponse *
   2628 CERT_DecodeOCSPResponse(const SECItem *src)
   2629 {
   2630    PLArenaPool *arena = NULL;
   2631    CERTOCSPResponse *response = NULL;
   2632    SECStatus rv = SECFailure;
   2633    ocspResponseStatus sv;
   2634    SECItem newSrc;
   2635 
   2636    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   2637    if (arena == NULL) {
   2638        goto loser;
   2639    }
   2640    response = (CERTOCSPResponse *)PORT_ArenaZAlloc(arena,
   2641                                                    sizeof(CERTOCSPResponse));
   2642    if (response == NULL) {
   2643        goto loser;
   2644    }
   2645    response->arena = arena;
   2646 
   2647    /* copy the DER into the arena, since Quick DER returns data that points
   2648       into the DER input, which may get freed by the caller */
   2649    rv = SECITEM_CopyItem(arena, &newSrc, src);
   2650    if (rv != SECSuccess) {
   2651        goto loser;
   2652    }
   2653 
   2654    rv = SEC_QuickDERDecodeItem(arena, response, ocsp_OCSPResponseTemplate, &newSrc);
   2655    if (rv != SECSuccess) {
   2656        if (PORT_GetError() == SEC_ERROR_BAD_DER)
   2657            PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
   2658        goto loser;
   2659    }
   2660 
   2661    sv = (ocspResponseStatus)DER_GetInteger(&response->responseStatus);
   2662    response->statusValue = sv;
   2663    if (sv != ocspResponse_successful) {
   2664        /*
   2665         * If the response status is anything but successful, then we
   2666         * are all done with decoding; the status is all there is.
   2667         */
   2668        return response;
   2669    }
   2670 
   2671    /*
   2672     * A successful response contains much more information, still encoded.
   2673     * Now we need to decode that.
   2674     */
   2675    rv = ocsp_DecodeResponseBytes(arena, response->responseBytes);
   2676    if (rv != SECSuccess) {
   2677        goto loser;
   2678    }
   2679 
   2680    return response;
   2681 
   2682 loser:
   2683    if (arena != NULL) {
   2684        PORT_FreeArena(arena, PR_FALSE);
   2685    }
   2686    return NULL;
   2687 }
   2688 
   2689 /*
   2690 * The way an OCSPResponse is defined, there are many levels to descend
   2691 * before getting to the actual response information.  And along the way
   2692 * we need to check that the response *type* is recognizable, which for
   2693 * now means that it is a BasicOCSPResponse, because that is the only
   2694 * type currently defined.  Rather than force all routines to perform
   2695 * a bunch of sanity checking every time they want to work on a response,
   2696 * this function isolates that and gives back the interesting part.
   2697 * Note that no copying is done, this just returns a pointer into the
   2698 * substructure of the response which is passed in.
   2699 *
   2700 * XXX This routine only works when a valid response structure is passed
   2701 * into it; this is checked with many assertions.  Assuming the response
   2702 * was creating by decoding, it wouldn't make it this far without being
   2703 * okay.  That is a sufficient assumption since the entire OCSP interface
   2704 * is only used internally.  When this interface is officially exported,
   2705 * each assertion below will need to be followed-up with setting an error
   2706 * and returning (null).
   2707 *
   2708 * FUNCTION: ocsp_GetResponseData
   2709 *   Returns ocspResponseData structure and a pointer to tbs response
   2710 *   data DER from a valid ocsp response.
   2711 * INPUTS:
   2712 *   CERTOCSPResponse *response
   2713 *     structure of a valid ocsp response
   2714 * RETURN:
   2715 *   Returns a pointer to ocspResponseData structure: decoded OCSP response
   2716 *   data, and a pointer(tbsResponseDataDER) to its undecoded data DER.
   2717 */
   2718 ocspResponseData *
   2719 ocsp_GetResponseData(CERTOCSPResponse *response, SECItem **tbsResponseDataDER)
   2720 {
   2721    ocspBasicOCSPResponse *basic;
   2722    ocspResponseData *responseData;
   2723 
   2724    PORT_Assert(response != NULL);
   2725 
   2726    PORT_Assert(response->responseBytes != NULL);
   2727 
   2728    PORT_Assert(response->responseBytes->responseTypeTag ==
   2729                SEC_OID_PKIX_OCSP_BASIC_RESPONSE);
   2730 
   2731    basic = response->responseBytes->decodedResponse.basic;
   2732    PORT_Assert(basic != NULL);
   2733 
   2734    responseData = basic->tbsResponseData;
   2735    PORT_Assert(responseData != NULL);
   2736 
   2737    if (tbsResponseDataDER) {
   2738        *tbsResponseDataDER = &basic->tbsResponseDataDER;
   2739 
   2740        PORT_Assert((*tbsResponseDataDER)->data != NULL);
   2741        PORT_Assert((*tbsResponseDataDER)->len != 0);
   2742    }
   2743 
   2744    return responseData;
   2745 }
   2746 
   2747 /*
   2748 * Much like the routine above, except it returns the response signature.
   2749 * Again, no copy is done.
   2750 */
   2751 ocspSignature *
   2752 ocsp_GetResponseSignature(CERTOCSPResponse *response)
   2753 {
   2754    ocspBasicOCSPResponse *basic;
   2755 
   2756    PORT_Assert(response != NULL);
   2757    if (NULL == response->responseBytes) {
   2758        return NULL;
   2759    }
   2760    if (response->responseBytes->responseTypeTag !=
   2761        SEC_OID_PKIX_OCSP_BASIC_RESPONSE) {
   2762        return NULL;
   2763    }
   2764    basic = response->responseBytes->decodedResponse.basic;
   2765    PORT_Assert(basic != NULL);
   2766 
   2767    return &(basic->responseSignature);
   2768 }
   2769 
   2770 /*
   2771 * FUNCTION: CERT_DestroyOCSPResponse
   2772 *   Frees an OCSP Response structure.
   2773 * INPUTS:
   2774 *   CERTOCSPResponse *request
   2775 *     Pointer to CERTOCSPResponse to be freed.
   2776 * RETURN:
   2777 *   No return value; no errors.
   2778 */
   2779 void
   2780 CERT_DestroyOCSPResponse(CERTOCSPResponse *response)
   2781 {
   2782    if (response != NULL) {
   2783        ocspSignature *signature = ocsp_GetResponseSignature(response);
   2784        if (signature && signature->cert != NULL)
   2785            CERT_DestroyCertificate(signature->cert);
   2786 
   2787        /*
   2788         * We should actually never have a response without an arena,
   2789         * but check just in case.  (If there isn't one, there is not
   2790         * much we can do about it...)
   2791         */
   2792        PORT_Assert(response->arena != NULL);
   2793        if (response->arena != NULL) {
   2794            PORT_FreeArena(response->arena, PR_FALSE);
   2795        }
   2796    }
   2797 }
   2798 
   2799 /*
   2800 * OVERALL OCSP CLIENT SUPPORT (make and send a request, verify a response):
   2801 */
   2802 
   2803 /*
   2804 * Pick apart a URL, saving the important things in the passed-in pointers.
   2805 *
   2806 * We expect to find "http://<hostname>[:<port>]/[path]", though we will
   2807 * tolerate that final slash character missing, as well as beginning and
   2808 * trailing whitespace, and any-case-characters for "http".  All of that
   2809 * tolerance is what complicates this routine.  What we want is just to
   2810 * pick out the hostname, the port, and the path.
   2811 *
   2812 * On a successful return, the caller will need to free the output pieces
   2813 * of hostname and path, which are copies of the values found in the url.
   2814 */
   2815 static SECStatus
   2816 ocsp_ParseURL(const char *url, char **pHostname, PRUint16 *pPort, char **pPath)
   2817 {
   2818    unsigned short port = 80; /* default, in case not in url */
   2819    char *hostname = NULL;
   2820    char *path = NULL;
   2821    const char *save;
   2822    char c;
   2823    int len;
   2824 
   2825    if (url == NULL)
   2826        goto loser;
   2827 
   2828    /*
   2829     * Skip beginning whitespace.
   2830     */
   2831    c = *url;
   2832    while ((c == ' ' || c == '\t') && c != '\0') {
   2833        url++;
   2834        c = *url;
   2835    }
   2836    if (c == '\0')
   2837        goto loser;
   2838 
   2839    /*
   2840     * Confirm, then skip, protocol.  (Since we only know how to do http,
   2841     * that is all we will accept).
   2842     */
   2843    if (PORT_Strncasecmp(url, "http://", 7) != 0)
   2844        goto loser;
   2845    url += 7;
   2846 
   2847    /*
   2848     * Whatever comes next is the hostname (or host IP address).  We just
   2849     * save it aside and then search for its end so we can determine its
   2850     * length and copy it.
   2851     *
   2852     * XXX Note that because we treat a ':' as a terminator character
   2853     * (and below, we expect that to mean there is a port specification
   2854     * immediately following), we will not handle IPv6 addresses.  That is
   2855     * apparently an acceptable limitation, for the time being.  Some day,
   2856     * when there is a clear way to specify a URL with an IPv6 address that
   2857     * can be parsed unambiguously, this code should be made to do that.
   2858     */
   2859    save = url;
   2860    c = *url;
   2861    while (c != '/' && c != ':' && c != '\0' && c != ' ' && c != '\t') {
   2862        url++;
   2863        c = *url;
   2864    }
   2865    len = url - save;
   2866    hostname = PORT_Alloc(len + 1);
   2867    if (hostname == NULL)
   2868        goto loser;
   2869    PORT_Memcpy(hostname, save, len);
   2870    hostname[len] = '\0';
   2871 
   2872    /*
   2873     * Now we figure out if there was a port specified or not.
   2874     * If so, we need to parse it (as a number) and skip it.
   2875     */
   2876    if (c == ':') {
   2877        url++;
   2878        port = (unsigned short)PORT_Atoi(url);
   2879        c = *url;
   2880        while (c != '/' && c != '\0' && c != ' ' && c != '\t') {
   2881            if (c < '0' || c > '9')
   2882                goto loser;
   2883            url++;
   2884            c = *url;
   2885        }
   2886    }
   2887 
   2888    /*
   2889     * Last thing to find is a path.  There *should* be a slash,
   2890     * if nothing else -- but if there is not we provide one.
   2891     */
   2892    if (c == '/') {
   2893        save = url;
   2894        while (c != '\0' && c != ' ' && c != '\t') {
   2895            url++;
   2896            c = *url;
   2897        }
   2898        len = url - save;
   2899        path = PORT_Alloc(len + 1);
   2900        if (path == NULL)
   2901            goto loser;
   2902        PORT_Memcpy(path, save, len);
   2903        path[len] = '\0';
   2904    } else {
   2905        path = PORT_Strdup("/");
   2906        if (path == NULL)
   2907            goto loser;
   2908    }
   2909 
   2910    *pHostname = hostname;
   2911    *pPort = port;
   2912    *pPath = path;
   2913    return SECSuccess;
   2914 
   2915 loser:
   2916    if (hostname != NULL)
   2917        PORT_Free(hostname);
   2918    PORT_SetError(SEC_ERROR_CERT_BAD_ACCESS_LOCATION);
   2919    return SECFailure;
   2920 }
   2921 
   2922 /*
   2923 * Open a socket to the specified host on the specified port, and return it.
   2924 * The host is either a hostname or an IP address.
   2925 */
   2926 static PRFileDesc *
   2927 ocsp_ConnectToHost(const char *host, PRUint16 port)
   2928 {
   2929 #ifdef MOZ_PROXY_BYPASS_PROTECTION
   2930    return NULL;
   2931 #else
   2932    PRFileDesc *sock = NULL;
   2933    PRIntervalTime timeout;
   2934    PRNetAddr addr;
   2935    char *netdbbuf = NULL;
   2936 
   2937    sock = PR_NewTCPSocket();
   2938    if (sock == NULL)
   2939        goto loser;
   2940 
   2941    /* XXX Some day need a way to set (and get?) the following value */
   2942    timeout = PR_SecondsToInterval(30);
   2943 
   2944    /*
   2945     * If the following converts an IP address string in "dot notation"
   2946     * into a PRNetAddr.  If it fails, we assume that is because we do not
   2947     * have such an address, but instead a host *name*.  In that case we
   2948     * then lookup the host by name.  Using the NSPR function this way
   2949     * means we do not have to have our own logic for distinguishing a
   2950     * valid numerical IP address from a hostname.
   2951     */
   2952    if (PR_StringToNetAddr(host, &addr) != PR_SUCCESS) {
   2953        PRIntn hostIndex;
   2954        PRHostEnt hostEntry;
   2955 
   2956        netdbbuf = PORT_Alloc(PR_NETDB_BUF_SIZE);
   2957        if (netdbbuf == NULL)
   2958            goto loser;
   2959 
   2960        if (PR_GetHostByName(host, netdbbuf, PR_NETDB_BUF_SIZE,
   2961                             &hostEntry) != PR_SUCCESS)
   2962            goto loser;
   2963 
   2964        hostIndex = 0;
   2965        do {
   2966            hostIndex = PR_EnumerateHostEnt(hostIndex, &hostEntry, port, &addr);
   2967            if (hostIndex <= 0)
   2968                goto loser;
   2969        } while (PR_Connect(sock, &addr, timeout) != PR_SUCCESS);
   2970 
   2971        PORT_Free(netdbbuf);
   2972    } else {
   2973        /*
   2974         * First put the port into the address, then connect.
   2975         */
   2976        if (PR_InitializeNetAddr(PR_IpAddrNull, port, &addr) != PR_SUCCESS)
   2977            goto loser;
   2978        if (PR_Connect(sock, &addr, timeout) != PR_SUCCESS)
   2979            goto loser;
   2980    }
   2981 
   2982    return sock;
   2983 
   2984 loser:
   2985    if (sock != NULL)
   2986        PR_Close(sock);
   2987    if (netdbbuf != NULL)
   2988        PORT_Free(netdbbuf);
   2989    return NULL;
   2990 #endif
   2991 }
   2992 
   2993 /*
   2994 * Sends an encoded OCSP request to the server identified by "location",
   2995 * and returns the socket on which it was sent (so can listen for the reply).
   2996 * "location" is expected to be a valid URL -- an error parsing it produces
   2997 * SEC_ERROR_CERT_BAD_ACCESS_LOCATION.  Other errors are likely problems
   2998 * connecting to it, or writing to it, or allocating memory, and the low-level
   2999 * errors appropriate to the problem will be set.
   3000 * if (encodedRequest == NULL)
   3001 *   then location MUST already include the full request,
   3002 *        including base64 and urlencode,
   3003 *        and the request will be sent with GET
   3004 * if (encodedRequest != NULL)
   3005 *   then the request will be sent with POST
   3006 */
   3007 static PRFileDesc *
   3008 ocsp_SendEncodedRequest(const char *location, const SECItem *encodedRequest)
   3009 {
   3010    char *hostname = NULL;
   3011    char *path = NULL;
   3012    PRUint16 port;
   3013    SECStatus rv;
   3014    PRFileDesc *sock = NULL;
   3015    PRFileDesc *returnSock = NULL;
   3016    char *header = NULL;
   3017    char portstr[16];
   3018 
   3019    /*
   3020     * Take apart the location, getting the hostname, port, and path.
   3021     */
   3022    rv = ocsp_ParseURL(location, &hostname, &port, &path);
   3023    if (rv != SECSuccess)
   3024        goto loser;
   3025 
   3026    PORT_Assert(hostname != NULL);
   3027    PORT_Assert(path != NULL);
   3028 
   3029    sock = ocsp_ConnectToHost(hostname, port);
   3030    if (sock == NULL)
   3031        goto loser;
   3032 
   3033    portstr[0] = '\0';
   3034    if (port != 80) {
   3035        PR_snprintf(portstr, sizeof(portstr), ":%d", port);
   3036    }
   3037 
   3038    if (!encodedRequest) {
   3039        header = PR_smprintf("GET %s HTTP/1.0\r\n"
   3040                             "Host: %s%s\r\n\r\n",
   3041                             path, hostname, portstr);
   3042        if (header == NULL)
   3043            goto loser;
   3044 
   3045        /*
   3046         * The NSPR documentation promises that if it can, it will write the full
   3047         * amount; this will not return a partial value expecting us to loop.
   3048         */
   3049        if (PR_Write(sock, header, (PRInt32)PORT_Strlen(header)) < 0)
   3050            goto loser;
   3051    } else {
   3052        header = PR_smprintf("POST %s HTTP/1.0\r\n"
   3053                             "Host: %s%s\r\n"
   3054                             "Content-Type: application/ocsp-request\r\n"
   3055                             "Content-Length: %u\r\n\r\n",
   3056                             path, hostname, portstr, encodedRequest->len);
   3057        if (header == NULL)
   3058            goto loser;
   3059 
   3060        /*
   3061         * The NSPR documentation promises that if it can, it will write the full
   3062         * amount; this will not return a partial value expecting us to loop.
   3063         */
   3064        if (PR_Write(sock, header, (PRInt32)PORT_Strlen(header)) < 0)
   3065            goto loser;
   3066 
   3067        if (PR_Write(sock, encodedRequest->data,
   3068                     (PRInt32)encodedRequest->len) < 0)
   3069            goto loser;
   3070    }
   3071 
   3072    returnSock = sock;
   3073    sock = NULL;
   3074 
   3075 loser:
   3076    if (header != NULL)
   3077        PORT_Free(header);
   3078    if (sock != NULL)
   3079        PR_Close(sock);
   3080    if (path != NULL)
   3081        PORT_Free(path);
   3082    if (hostname != NULL)
   3083        PORT_Free(hostname);
   3084 
   3085    return returnSock;
   3086 }
   3087 
   3088 /*
   3089 * Read from "fd" into "buf" -- expect/attempt to read a given number of bytes
   3090 * Obviously, stop if hit end-of-stream. Timeout is passed in.
   3091 */
   3092 
   3093 static int
   3094 ocsp_read(PRFileDesc *fd, char *buf, int toread, PRIntervalTime timeout)
   3095 {
   3096    int total = 0;
   3097 
   3098    while (total < toread) {
   3099        PRInt32 got;
   3100 
   3101        got = PR_Recv(fd, buf + total, (PRInt32)(toread - total), 0, timeout);
   3102        if (got < 0) {
   3103            if (0 == total) {
   3104                total = -1; /* report the error if we didn't read anything yet */
   3105            }
   3106            break;
   3107        } else if (got == 0) { /* EOS */
   3108            break;
   3109        }
   3110 
   3111        total += got;
   3112    }
   3113 
   3114    return total;
   3115 }
   3116 
   3117 #define OCSP_BUFSIZE 1024
   3118 
   3119 #define AbortHttpDecode(error)   \
   3120    {                            \
   3121        if (inBuffer)            \
   3122            PORT_Free(inBuffer); \
   3123        PORT_SetError(error);    \
   3124        return NULL;             \
   3125    }
   3126 
   3127 /*
   3128 * Reads on the given socket and returns an encoded response when received.
   3129 * Properly formatted HTTP/1.0 response headers are expected to be read
   3130 * from the socket, preceding a binary-encoded OCSP response.  Problems
   3131 * with parsing cause the error SEC_ERROR_OCSP_BAD_HTTP_RESPONSE to be
   3132 * set; any other problems are likely low-level i/o or memory allocation
   3133 * errors.
   3134 */
   3135 static SECItem *
   3136 ocsp_GetEncodedResponse(PLArenaPool *arena, PRFileDesc *sock)
   3137 {
   3138    /* first read HTTP status line and headers */
   3139 
   3140    char *inBuffer = NULL;
   3141    PRInt32 offset = 0;
   3142    PRInt32 inBufsize = 0;
   3143    const PRInt32 bufSizeIncrement = OCSP_BUFSIZE;   /* 1 KB at a time */
   3144    const PRInt32 maxBufSize = 8 * bufSizeIncrement; /* 8 KB max */
   3145    const char *CRLF = "\r\n";
   3146    const PRInt32 CRLFlen = strlen(CRLF);
   3147    const char *headerEndMark = "\r\n\r\n";
   3148    const PRInt32 markLen = strlen(headerEndMark);
   3149    const PRIntervalTime ocsptimeout =
   3150        PR_SecondsToInterval(30); /* hardcoded to 30s for now */
   3151    char *headerEnd = NULL;
   3152    PRBool EOS = PR_FALSE;
   3153    const char *httpprotocol = "HTTP/";
   3154    const PRInt32 httplen = strlen(httpprotocol);
   3155    const char *httpcode = NULL;
   3156    const char *contenttype = NULL;
   3157    PRInt32 contentlength = 0;
   3158    PRInt32 bytesRead = 0;
   3159    char *statusLineEnd = NULL;
   3160    char *space = NULL;
   3161    char *nextHeader = NULL;
   3162    SECItem *result = NULL;
   3163 
   3164    /* read up to at least the end of the HTTP headers */
   3165    do {
   3166        inBufsize += bufSizeIncrement;
   3167        inBuffer = PORT_Realloc(inBuffer, inBufsize + 1);
   3168        if (NULL == inBuffer) {
   3169            AbortHttpDecode(SEC_ERROR_NO_MEMORY);
   3170        }
   3171        bytesRead = ocsp_read(sock, inBuffer + offset, bufSizeIncrement,
   3172                              ocsptimeout);
   3173        if (bytesRead > 0) {
   3174            PRInt32 searchOffset = (offset - markLen) > 0 ? offset - markLen : 0;
   3175            offset += bytesRead;
   3176            *(inBuffer + offset) = '\0'; /* NULL termination */
   3177            headerEnd = strstr((const char *)inBuffer + searchOffset, headerEndMark);
   3178            if (bytesRead < bufSizeIncrement) {
   3179                /* we read less data than requested, therefore we are at
   3180                   EOS or there was a read error */
   3181                EOS = PR_TRUE;
   3182            }
   3183        } else {
   3184            /* recv error or EOS */
   3185            EOS = PR_TRUE;
   3186        }
   3187    } while ((!headerEnd) && (PR_FALSE == EOS) &&
   3188             (inBufsize < maxBufSize));
   3189 
   3190    if (!headerEnd) {
   3191        AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE);
   3192    }
   3193 
   3194    /* parse the HTTP status line  */
   3195    statusLineEnd = strstr((const char *)inBuffer, CRLF);
   3196    if (!statusLineEnd) {
   3197        AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE);
   3198    }
   3199    *statusLineEnd = '\0';
   3200 
   3201    /* check for HTTP/ response */
   3202    space = strchr((const char *)inBuffer, ' ');
   3203    if (!space || PORT_Strncasecmp((const char *)inBuffer, httpprotocol, httplen) != 0) {
   3204        AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE);
   3205    }
   3206 
   3207    /* check the HTTP status code of 200 */
   3208    httpcode = space + 1;
   3209    space = strchr(httpcode, ' ');
   3210    if (!space) {
   3211        AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE);
   3212    }
   3213    *space = 0;
   3214    if (0 != strcmp(httpcode, "200")) {
   3215        AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE);
   3216    }
   3217 
   3218    /* parse the HTTP headers in the buffer . We only care about
   3219       content-type and content-length
   3220    */
   3221 
   3222    nextHeader = statusLineEnd + CRLFlen;
   3223    *headerEnd = '\0'; /* terminate */
   3224    do {
   3225        char *thisHeaderEnd = NULL;
   3226        char *value = NULL;
   3227        char *colon = strchr(nextHeader, ':');
   3228 
   3229        if (!colon) {
   3230            AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE);
   3231        }
   3232 
   3233        *colon = '\0';
   3234        value = colon + 1;
   3235 
   3236        /* jpierre - note : the following code will only handle the basic form
   3237           of HTTP/1.0 response headers, of the form "name: value" . Headers
   3238           split among multiple lines are not supported. This is not common
   3239           and should not be an issue, but it could become one in the
   3240           future */
   3241 
   3242        if (*value != ' ') {
   3243            AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE);
   3244        }
   3245 
   3246        value++;
   3247        thisHeaderEnd = strstr(value, CRLF);
   3248        if (thisHeaderEnd) {
   3249            *thisHeaderEnd = '\0';
   3250        }
   3251 
   3252        if (0 == PORT_Strcasecmp(nextHeader, "content-type")) {
   3253            contenttype = value;
   3254        } else if (0 == PORT_Strcasecmp(nextHeader, "content-length")) {
   3255            contentlength = atoi(value);
   3256        }
   3257 
   3258        if (thisHeaderEnd) {
   3259            nextHeader = thisHeaderEnd + CRLFlen;
   3260        } else {
   3261            nextHeader = NULL;
   3262        }
   3263 
   3264    } while (nextHeader && (nextHeader < (headerEnd + CRLFlen)));
   3265 
   3266    /* check content-type */
   3267    if (!contenttype ||
   3268        (0 != PORT_Strcasecmp(contenttype, "application/ocsp-response"))) {
   3269        AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE);
   3270    }
   3271 
   3272    /* read the body of the OCSP response */
   3273    offset = offset - (PRInt32)(headerEnd - (const char *)inBuffer) - markLen;
   3274    if (offset) {
   3275        /* move all data to the beginning of the buffer */
   3276        PORT_Memmove(inBuffer, headerEnd + markLen, offset);
   3277    }
   3278 
   3279    /* resize buffer to only what's needed to hold the current response */
   3280    inBufsize = (1 + (offset - 1) / bufSizeIncrement) * bufSizeIncrement;
   3281 
   3282    while ((PR_FALSE == EOS) &&
   3283           ((contentlength == 0) || (offset < contentlength)) &&
   3284           (inBufsize < maxBufSize)) {
   3285        /* we still need to receive more body data */
   3286        inBufsize += bufSizeIncrement;
   3287        inBuffer = PORT_Realloc(inBuffer, inBufsize + 1);
   3288        if (NULL == inBuffer) {
   3289            AbortHttpDecode(SEC_ERROR_NO_MEMORY);
   3290        }
   3291        bytesRead = ocsp_read(sock, inBuffer + offset, bufSizeIncrement,
   3292                              ocsptimeout);
   3293        if (bytesRead > 0) {
   3294            offset += bytesRead;
   3295            if (bytesRead < bufSizeIncrement) {
   3296                /* we read less data than requested, therefore we are at
   3297                   EOS or there was a read error */
   3298                EOS = PR_TRUE;
   3299            }
   3300        } else {
   3301            /* recv error or EOS */
   3302            EOS = PR_TRUE;
   3303        }
   3304    }
   3305 
   3306    if (0 == offset) {
   3307        AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE);
   3308    }
   3309 
   3310    /*
   3311     * Now allocate the item to hold the data.
   3312     */
   3313    result = SECITEM_AllocItem(arena, NULL, offset);
   3314    if (NULL == result) {
   3315        AbortHttpDecode(SEC_ERROR_NO_MEMORY);
   3316    }
   3317 
   3318    /*
   3319     * And copy the data left in the buffer.
   3320     */
   3321    PORT_Memcpy(result->data, inBuffer, offset);
   3322 
   3323    /* and free the temporary buffer */
   3324    PORT_Free(inBuffer);
   3325    return result;
   3326 }
   3327 
   3328 SECStatus
   3329 CERT_ParseURL(const char *url, char **pHostname, PRUint16 *pPort, char **pPath)
   3330 {
   3331    return ocsp_ParseURL(url, pHostname, pPort, pPath);
   3332 }
   3333 
   3334 /*
   3335 * Limit the size of http responses we are willing to accept.
   3336 */
   3337 #define MAX_WANTED_OCSP_RESPONSE_LEN 64 * 1024
   3338 
   3339 /* if (encodedRequest == NULL)
   3340 *   then location MUST already include the full request,
   3341 *        including base64 and urlencode,
   3342 *        and the request will be sent with GET
   3343 * if (encodedRequest != NULL)
   3344 *   then the request will be sent with POST
   3345 */
   3346 static SECItem *
   3347 fetchOcspHttpClientV1(PLArenaPool *arena,
   3348                      const SEC_HttpClientFcnV1 *hcv1,
   3349                      const char *location,
   3350                      const SECItem *encodedRequest)
   3351 {
   3352    char *hostname = NULL;
   3353    char *path = NULL;
   3354    PRUint16 port;
   3355    SECItem *encodedResponse = NULL;
   3356    SEC_HTTP_SERVER_SESSION pServerSession = NULL;
   3357    SEC_HTTP_REQUEST_SESSION pRequestSession = NULL;
   3358    PRUint16 myHttpResponseCode;
   3359    const char *myHttpResponseData;
   3360    PRUint32 myHttpResponseDataLen;
   3361 
   3362    if (ocsp_ParseURL(location, &hostname, &port, &path) == SECFailure) {
   3363        PORT_SetError(SEC_ERROR_OCSP_MALFORMED_REQUEST);
   3364        goto loser;
   3365    }
   3366 
   3367    PORT_Assert(hostname != NULL);
   3368    PORT_Assert(path != NULL);
   3369 
   3370    if ((*hcv1->createSessionFcn)(
   3371            hostname,
   3372            port,
   3373            &pServerSession) != SECSuccess) {
   3374        PORT_SetError(SEC_ERROR_OCSP_SERVER_ERROR);
   3375        goto loser;
   3376    }
   3377 
   3378    /* We use a non-zero timeout, which means:
   3379       - the client will use blocking I/O
   3380       - TryFcn will not return WOULD_BLOCK nor a poll descriptor
   3381       - it's sufficient to call TryFcn once
   3382       No lock for accessing OCSP_Global.timeoutSeconds, bug 406120
   3383    */
   3384 
   3385    if ((*hcv1->createFcn)(
   3386            pServerSession,
   3387            "http",
   3388            path,
   3389            encodedRequest ? "POST" : "GET",
   3390            PR_TicksPerSecond() * OCSP_Global.timeoutSeconds,
   3391            &pRequestSession) != SECSuccess) {
   3392        PORT_SetError(SEC_ERROR_OCSP_SERVER_ERROR);
   3393        goto loser;
   3394    }
   3395 
   3396    if (encodedRequest &&
   3397        (*hcv1->setPostDataFcn)(
   3398            pRequestSession,
   3399            (char *)encodedRequest->data,
   3400            encodedRequest->len,
   3401            "application/ocsp-request") != SECSuccess) {
   3402        PORT_SetError(SEC_ERROR_OCSP_SERVER_ERROR);
   3403        goto loser;
   3404    }
   3405 
   3406    /* we don't want result objects larger than this: */
   3407    myHttpResponseDataLen = MAX_WANTED_OCSP_RESPONSE_LEN;
   3408 
   3409    OCSP_TRACE(("OCSP trySendAndReceive %s\n", location));
   3410 
   3411    if ((*hcv1->trySendAndReceiveFcn)(
   3412            pRequestSession,
   3413            NULL,
   3414            &myHttpResponseCode,
   3415            NULL,
   3416            NULL,
   3417            &myHttpResponseData,
   3418            &myHttpResponseDataLen) != SECSuccess) {
   3419        PORT_SetError(SEC_ERROR_OCSP_SERVER_ERROR);
   3420        goto loser;
   3421    }
   3422 
   3423    OCSP_TRACE(("OCSP trySendAndReceive result http %d\n", myHttpResponseCode));
   3424 
   3425    if (myHttpResponseCode != 200) {
   3426        PORT_SetError(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE);
   3427        goto loser;
   3428    }
   3429 
   3430    encodedResponse = SECITEM_AllocItem(arena, NULL, myHttpResponseDataLen);
   3431 
   3432    if (!encodedResponse) {
   3433        PORT_SetError(SEC_ERROR_NO_MEMORY);
   3434        goto loser;
   3435    }
   3436 
   3437    PORT_Memcpy(encodedResponse->data, myHttpResponseData, myHttpResponseDataLen);
   3438 
   3439 loser:
   3440    if (pRequestSession != NULL)
   3441        (*hcv1->freeFcn)(pRequestSession);
   3442    if (pServerSession != NULL)
   3443        (*hcv1->freeSessionFcn)(pServerSession);
   3444    if (path != NULL)
   3445        PORT_Free(path);
   3446    if (hostname != NULL)
   3447        PORT_Free(hostname);
   3448 
   3449    return encodedResponse;
   3450 }
   3451 
   3452 /*
   3453 * FUNCTION: CERT_GetEncodedOCSPResponseByMethod
   3454 *   Creates and sends a request to an OCSP responder, then reads and
   3455 *   returns the (encoded) response.
   3456 * INPUTS:
   3457 *   PLArenaPool *arena
   3458 *     Pointer to arena from which return value will be allocated.
   3459 *     If NULL, result will be allocated from the heap (and thus should
   3460 *     be freed via SECITEM_FreeItem).
   3461 *   CERTCertList *certList
   3462 *     A list of certs for which status will be requested.
   3463 *     Note that all of these certificates should have the same issuer,
   3464 *     or it's expected the response will be signed by a trusted responder.
   3465 *     If the certs need to be broken up into multiple requests, that
   3466 *     must be handled by the caller (and thus by having multiple calls
   3467 *     to this routine), who knows about where the request(s) are being
   3468 *     sent and whether there are any trusted responders in place.
   3469 *   const char *location
   3470 *     The location of the OCSP responder (a URL).
   3471 *   const char *method
   3472 *     The protocol method used when retrieving the OCSP response.
   3473 *     Currently support: "GET" (http GET) and "POST" (http POST).
   3474 *     Additionals methods for http or other protocols might be added
   3475 *     in the future.
   3476 *   PRTime time
   3477 *     Indicates the time for which the certificate status is to be
   3478 *     determined -- this may be used in the search for the cert's issuer
   3479 *     but has no other bearing on the operation.
   3480 *   PRBool addServiceLocator
   3481 *     If true, the Service Locator extension should be added to the
   3482 *     single request(s) for each cert.
   3483 *   CERTCertificate *signerCert
   3484 *     If non-NULL, means sign the request using this cert.  Otherwise,
   3485 *     do not sign.
   3486 *   void *pwArg
   3487 *     Pointer to argument for password prompting, if needed.  (Definitely
   3488 *     not needed if not signing.)
   3489 * OUTPUTS:
   3490 *   CERTOCSPRequest **pRequest
   3491 *     Pointer in which to store the OCSP request created for the given
   3492 *     list of certificates.  It is only filled in if the entire operation
   3493 *     is successful and the pointer is not null -- and in that case the
   3494 *     caller is then reponsible for destroying it.
   3495 * RETURN:
   3496 *   Returns a pointer to the SECItem holding the response.
   3497 *   On error, returns null with error set describing the reason:
   3498 *	SEC_ERROR_UNKNOWN_ISSUER
   3499 *	SEC_ERROR_CERT_BAD_ACCESS_LOCATION
   3500 *	SEC_ERROR_OCSP_BAD_HTTP_RESPONSE
   3501 *   Other errors are low-level problems (no memory, bad database, etc.).
   3502 */
   3503 SECItem *
   3504 CERT_GetEncodedOCSPResponseByMethod(PLArenaPool *arena, CERTCertList *certList,
   3505                                    const char *location, const char *method,
   3506                                    PRTime time, PRBool addServiceLocator,
   3507                                    CERTCertificate *signerCert, void *pwArg,
   3508                                    CERTOCSPRequest **pRequest)
   3509 {
   3510    CERTOCSPRequest *request;
   3511    request = CERT_CreateOCSPRequest(certList, time, addServiceLocator,
   3512                                     signerCert);
   3513    if (!request)
   3514        return NULL;
   3515    return ocsp_GetEncodedOCSPResponseFromRequest(arena, request, location,
   3516                                                  method, time, addServiceLocator,
   3517                                                  pwArg, pRequest);
   3518 }
   3519 
   3520 /*
   3521 * FUNCTION: CERT_GetEncodedOCSPResponse
   3522 *   Creates and sends a request to an OCSP responder, then reads and
   3523 *   returns the (encoded) response.
   3524 *
   3525 * This is a legacy API that behaves identically to
   3526 * CERT_GetEncodedOCSPResponseByMethod using the "POST" method.
   3527 */
   3528 SECItem *
   3529 CERT_GetEncodedOCSPResponse(PLArenaPool *arena, CERTCertList *certList,
   3530                            const char *location, PRTime time,
   3531                            PRBool addServiceLocator,
   3532                            CERTCertificate *signerCert, void *pwArg,
   3533                            CERTOCSPRequest **pRequest)
   3534 {
   3535    return CERT_GetEncodedOCSPResponseByMethod(arena, certList, location,
   3536                                               "POST", time, addServiceLocator,
   3537                                               signerCert, pwArg, pRequest);
   3538 }
   3539 
   3540 /* URL encode a buffer that consists of base64-characters, only,
   3541 * which means we can use a simple encoding logic.
   3542 *
   3543 * No output buffer size checking is performed.
   3544 * You should call the function twice, to calculate the required buffer size.
   3545 *
   3546 * If the outpufBuf parameter is NULL, the function will calculate the
   3547 * required size, including the trailing zero termination char.
   3548 *
   3549 * The function returns the number of bytes calculated or produced.
   3550 */
   3551 size_t
   3552 ocsp_UrlEncodeBase64Buf(const char *base64Buf, char *outputBuf)
   3553 {
   3554    const char *walkInput = NULL;
   3555    char *walkOutput = outputBuf;
   3556    size_t count = 0;
   3557 
   3558    for (walkInput = base64Buf; *walkInput; ++walkInput) {
   3559        char c = *walkInput;
   3560        if (isspace((unsigned char)c))
   3561            continue;
   3562        switch (c) {
   3563            case '+':
   3564                if (outputBuf) {
   3565                    strcpy(walkOutput, "%2B");
   3566                    walkOutput += 3;
   3567                }
   3568                count += 3;
   3569                break;
   3570            case '/':
   3571                if (outputBuf) {
   3572                    strcpy(walkOutput, "%2F");
   3573                    walkOutput += 3;
   3574                }
   3575                count += 3;
   3576                break;
   3577            case '=':
   3578                if (outputBuf) {
   3579                    strcpy(walkOutput, "%3D");
   3580                    walkOutput += 3;
   3581                }
   3582                count += 3;
   3583                break;
   3584            default:
   3585                if (outputBuf) {
   3586                    *walkOutput = *walkInput;
   3587                    ++walkOutput;
   3588                }
   3589                ++count;
   3590                break;
   3591        }
   3592    }
   3593    if (outputBuf) {
   3594        *walkOutput = 0;
   3595    }
   3596    ++count;
   3597    return count;
   3598 }
   3599 
   3600 enum { max_get_request_size = 255 }; /* defined by RFC2560 */
   3601 
   3602 static SECItem *
   3603 cert_GetOCSPResponse(PLArenaPool *arena, const char *location,
   3604                     const SECItem *encodedRequest);
   3605 
   3606 static SECItem *
   3607 ocsp_GetEncodedOCSPResponseFromRequest(PLArenaPool *arena,
   3608                                       CERTOCSPRequest *request,
   3609                                       const char *location,
   3610                                       const char *method,
   3611                                       PRTime time,
   3612                                       PRBool addServiceLocator,
   3613                                       void *pwArg,
   3614                                       CERTOCSPRequest **pRequest)
   3615 {
   3616    SECItem *encodedRequest = NULL;
   3617    SECItem *encodedResponse = NULL;
   3618    SECStatus rv;
   3619 
   3620    if (!location || !*location) /* location should be at least one byte */
   3621        goto loser;
   3622 
   3623    rv = CERT_AddOCSPAcceptableResponses(request,
   3624                                         SEC_OID_PKIX_OCSP_BASIC_RESPONSE);
   3625    if (rv != SECSuccess)
   3626        goto loser;
   3627 
   3628    encodedRequest = CERT_EncodeOCSPRequest(NULL, request, pwArg);
   3629    if (encodedRequest == NULL)
   3630        goto loser;
   3631 
   3632    if (!strcmp(method, "GET")) {
   3633        encodedResponse = cert_GetOCSPResponse(arena, location, encodedRequest);
   3634    } else if (!strcmp(method, "POST")) {
   3635        encodedResponse = CERT_PostOCSPRequest(arena, location, encodedRequest);
   3636    } else {
   3637        goto loser;
   3638    }
   3639 
   3640    if (encodedResponse != NULL && pRequest != NULL) {
   3641        *pRequest = request;
   3642        request = NULL; /* avoid destroying below */
   3643    }
   3644 
   3645 loser:
   3646    if (request != NULL)
   3647        CERT_DestroyOCSPRequest(request);
   3648    if (encodedRequest != NULL)
   3649        SECITEM_FreeItem(encodedRequest, PR_TRUE);
   3650    return encodedResponse;
   3651 }
   3652 
   3653 static SECItem *
   3654 cert_FetchOCSPResponse(PLArenaPool *arena, const char *location,
   3655                       const SECItem *encodedRequest);
   3656 
   3657 /* using HTTP GET method */
   3658 static SECItem *
   3659 cert_GetOCSPResponse(PLArenaPool *arena, const char *location,
   3660                     const SECItem *encodedRequest)
   3661 {
   3662    char *walkOutput = NULL;
   3663    char *fullGetPath = NULL;
   3664    size_t pathLength;
   3665    PRInt32 urlEncodedBufLength;
   3666    size_t base64size;
   3667    char b64ReqBuf[max_get_request_size + 1];
   3668    size_t slashLengthIfNeeded = 0;
   3669    size_t getURLLength;
   3670    SECItem *item;
   3671 
   3672    if (!location || !*location) {
   3673        return NULL;
   3674    }
   3675 
   3676    pathLength = strlen(location);
   3677    if (location[pathLength - 1] != '/') {
   3678        slashLengthIfNeeded = 1;
   3679    }
   3680 
   3681    /* Calculation as documented by PL_Base64Encode function.
   3682     * Use integer conversion to avoid having to use function ceil().
   3683     */
   3684    base64size = (((encodedRequest->len + 2) / 3) * 4);
   3685    if (base64size > max_get_request_size) {
   3686        return NULL;
   3687    }
   3688    memset(b64ReqBuf, 0, sizeof(b64ReqBuf));
   3689    PL_Base64Encode((const char *)encodedRequest->data, encodedRequest->len,
   3690                    b64ReqBuf);
   3691 
   3692    urlEncodedBufLength = ocsp_UrlEncodeBase64Buf(b64ReqBuf, NULL);
   3693    getURLLength = pathLength + urlEncodedBufLength + slashLengthIfNeeded;
   3694 
   3695    /* urlEncodedBufLength already contains room for the zero terminator.
   3696     * Add another if we must add the '/' char.
   3697     */
   3698    if (arena) {
   3699        fullGetPath = (char *)PORT_ArenaAlloc(arena, getURLLength);
   3700    } else {
   3701        fullGetPath = (char *)PORT_Alloc(getURLLength);
   3702    }
   3703    if (!fullGetPath) {
   3704        return NULL;
   3705    }
   3706 
   3707    strcpy(fullGetPath, location);
   3708    walkOutput = fullGetPath + pathLength;
   3709 
   3710    if (walkOutput > fullGetPath && slashLengthIfNeeded) {
   3711        strcpy(walkOutput, "/");
   3712        ++walkOutput;
   3713    }
   3714    ocsp_UrlEncodeBase64Buf(b64ReqBuf, walkOutput);
   3715 
   3716    item = cert_FetchOCSPResponse(arena, fullGetPath, NULL);
   3717    if (!arena) {
   3718        PORT_Free(fullGetPath);
   3719    }
   3720    return item;
   3721 }
   3722 
   3723 SECItem *
   3724 CERT_PostOCSPRequest(PLArenaPool *arena, const char *location,
   3725                     const SECItem *encodedRequest)
   3726 {
   3727    return cert_FetchOCSPResponse(arena, location, encodedRequest);
   3728 }
   3729 
   3730 SECItem *
   3731 cert_FetchOCSPResponse(PLArenaPool *arena, const char *location,
   3732                       const SECItem *encodedRequest)
   3733 {
   3734    const SEC_HttpClientFcn *registeredHttpClient;
   3735    SECItem *encodedResponse = NULL;
   3736 
   3737    registeredHttpClient = SEC_GetRegisteredHttpClient();
   3738 
   3739    if (registeredHttpClient && registeredHttpClient->version == 1) {
   3740        encodedResponse = fetchOcspHttpClientV1(
   3741            arena,
   3742            &registeredHttpClient->fcnTable.ftable1,
   3743            location,
   3744            encodedRequest);
   3745    } else {
   3746        /* use internal http client */
   3747        PRFileDesc *sock = ocsp_SendEncodedRequest(location, encodedRequest);
   3748        if (sock) {
   3749            encodedResponse = ocsp_GetEncodedResponse(arena, sock);
   3750            PR_Close(sock);
   3751        }
   3752    }
   3753 
   3754    return encodedResponse;
   3755 }
   3756 
   3757 static SECItem *
   3758 ocsp_GetEncodedOCSPResponseForSingleCert(PLArenaPool *arena,
   3759                                         CERTOCSPCertID *certID,
   3760                                         CERTCertificate *singleCert,
   3761                                         const char *location,
   3762                                         const char *method,
   3763                                         PRTime time,
   3764                                         PRBool addServiceLocator,
   3765                                         void *pwArg,
   3766                                         CERTOCSPRequest **pRequest)
   3767 {
   3768    CERTOCSPRequest *request;
   3769    request = cert_CreateSingleCertOCSPRequest(certID, singleCert, time,
   3770                                               addServiceLocator, NULL);
   3771    if (!request)
   3772        return NULL;
   3773    return ocsp_GetEncodedOCSPResponseFromRequest(arena, request, location,
   3774                                                  method, time, addServiceLocator,
   3775                                                  pwArg, pRequest);
   3776 }
   3777 
   3778 /* Checks a certificate for the key usage extension of OCSP signer. */
   3779 static PRBool
   3780 ocsp_CertIsOCSPDesignatedResponder(CERTCertificate *cert)
   3781 {
   3782    SECStatus rv;
   3783    SECItem extItem;
   3784    SECItem **oids;
   3785    SECItem *oid;
   3786    SECOidTag oidTag;
   3787    PRBool retval;
   3788    CERTOidSequence *oidSeq = NULL;
   3789 
   3790    extItem.data = NULL;
   3791    rv = CERT_FindCertExtension(cert, SEC_OID_X509_EXT_KEY_USAGE, &extItem);
   3792    if (rv != SECSuccess) {
   3793        goto loser;
   3794    }
   3795 
   3796    oidSeq = CERT_DecodeOidSequence(&extItem);
   3797    if (oidSeq == NULL) {
   3798        goto loser;
   3799    }
   3800 
   3801    oids = oidSeq->oids;
   3802    while (*oids != NULL) {
   3803        oid = *oids;
   3804 
   3805        oidTag = SECOID_FindOIDTag(oid);
   3806 
   3807        if (oidTag == SEC_OID_OCSP_RESPONDER) {
   3808            goto success;
   3809        }
   3810 
   3811        oids++;
   3812    }
   3813 
   3814 loser:
   3815    retval = PR_FALSE;
   3816    PORT_SetError(SEC_ERROR_OCSP_INVALID_SIGNING_CERT);
   3817    goto done;
   3818 success:
   3819    retval = PR_TRUE;
   3820 done:
   3821    if (extItem.data != NULL) {
   3822        PORT_Free(extItem.data);
   3823    }
   3824    if (oidSeq != NULL) {
   3825        CERT_DestroyOidSequence(oidSeq);
   3826    }
   3827 
   3828    return (retval);
   3829 }
   3830 
   3831 #ifdef LATER /*                                                    \
   3832              * XXX This function is not currently used, but will  \
   3833              * be needed later when we do revocation checking of  \
   3834              * the responder certificate.  Of course, it may need \
   3835              * revising then, if the cert extension interface has \
   3836              * changed.  (Hopefully it will!)                     \
   3837              */
   3838 
   3839 /* Checks a certificate to see if it has the OCSP no check extension. */
   3840 static PRBool
   3841 ocsp_CertHasNoCheckExtension(CERTCertificate *cert)
   3842 {
   3843    SECStatus rv;
   3844 
   3845    rv = CERT_FindCertExtension(cert, SEC_OID_PKIX_OCSP_NO_CHECK,
   3846                                NULL);
   3847    if (rv == SECSuccess) {
   3848        return PR_TRUE;
   3849    }
   3850    return PR_FALSE;
   3851 }
   3852 #endif /* LATER */
   3853 
   3854 static PRBool
   3855 ocsp_matchcert(SECItem *certIndex, CERTCertificate *testCert)
   3856 {
   3857    SECItem item;
   3858    unsigned char buf[HASH_LENGTH_MAX];
   3859 
   3860    item.data = buf;
   3861    item.len = SHA1_LENGTH;
   3862 
   3863    if (CERT_GetSubjectPublicKeyDigest(NULL, testCert, SEC_OID_SHA1,
   3864                                       &item) == NULL) {
   3865        return PR_FALSE;
   3866    }
   3867    if (SECITEM_ItemsAreEqual(certIndex, &item)) {
   3868        return PR_TRUE;
   3869    }
   3870    if (CERT_GetSubjectPublicKeyDigest(NULL, testCert, SEC_OID_MD5,
   3871                                       &item) == NULL) {
   3872        return PR_FALSE;
   3873    }
   3874    if (SECITEM_ItemsAreEqual(certIndex, &item)) {
   3875        return PR_TRUE;
   3876    }
   3877    if (CERT_GetSubjectPublicKeyDigest(NULL, testCert, SEC_OID_MD2,
   3878                                       &item) == NULL) {
   3879        return PR_FALSE;
   3880    }
   3881    if (SECITEM_ItemsAreEqual(certIndex, &item)) {
   3882        return PR_TRUE;
   3883    }
   3884 
   3885    return PR_FALSE;
   3886 }
   3887 
   3888 static CERTCertificate *
   3889 ocsp_CertGetDefaultResponder(CERTCertDBHandle *handle, CERTOCSPCertID *certID);
   3890 
   3891 CERTCertificate *
   3892 ocsp_GetSignerCertificate(CERTCertDBHandle *handle, ocspResponseData *tbsData,
   3893                          ocspSignature *signature, CERTCertificate *issuer)
   3894 {
   3895    CERTCertificate **certs = NULL;
   3896    CERTCertificate *signerCert = NULL;
   3897    SECStatus rv = SECFailure;
   3898    PRBool lookupByName = PR_TRUE;
   3899    void *certIndex = NULL;
   3900    int certCount = 0;
   3901 
   3902    PORT_Assert(tbsData->responderID != NULL);
   3903    switch (tbsData->responderID->responderIDType) {
   3904        case ocspResponderID_byName:
   3905            lookupByName = PR_TRUE;
   3906            certIndex = &tbsData->derResponderID;
   3907            break;
   3908        case ocspResponderID_byKey:
   3909            lookupByName = PR_FALSE;
   3910            certIndex = &tbsData->responderID->responderIDValue.keyHash;
   3911            break;
   3912        case ocspResponderID_other:
   3913        default:
   3914            PORT_Assert(0);
   3915            PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
   3916            return NULL;
   3917    }
   3918 
   3919    /*
   3920     * If the signature contains some certificates as well, temporarily
   3921     * import them in case they are needed for verification.
   3922     *
   3923     * Note that the result of this is that each cert in "certs" needs
   3924     * to be destroyed.
   3925     */
   3926    if (signature->derCerts != NULL) {
   3927        for (; signature->derCerts[certCount] != NULL; certCount++) {
   3928            /* just counting */
   3929        }
   3930        rv = CERT_ImportCerts(handle, certUsageStatusResponder, certCount,
   3931                              signature->derCerts, &certs,
   3932                              PR_FALSE, PR_FALSE, NULL);
   3933        if (rv != SECSuccess)
   3934            goto finish;
   3935    }
   3936 
   3937    /*
   3938     * Now look up the certificate that did the signing.
   3939     * The signer can be specified either by name or by key hash.
   3940     */
   3941    if (lookupByName) {
   3942        SECItem *crIndex = (SECItem *)certIndex;
   3943        SECItem encodedName;
   3944        PLArenaPool *arena;
   3945 
   3946        arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   3947        if (arena != NULL) {
   3948 
   3949            rv = SEC_QuickDERDecodeItem(arena, &encodedName,
   3950                                        ocsp_ResponderIDDerNameTemplate,
   3951                                        crIndex);
   3952            if (rv != SECSuccess) {
   3953                if (PORT_GetError() == SEC_ERROR_BAD_DER)
   3954                    PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
   3955            } else {
   3956                signerCert = CERT_FindCertByName(handle, &encodedName);
   3957            }
   3958            PORT_FreeArena(arena, PR_FALSE);
   3959        }
   3960    } else {
   3961        /*
   3962         * The signer is either 1) a known issuer CA we passed in,
   3963         * 2) the default OCSP responder, or 3) an intermediate CA
   3964         * passed in the cert list to use. Figure out which it is.
   3965         */
   3966        int i;
   3967        CERTCertificate *responder =
   3968            ocsp_CertGetDefaultResponder(handle, NULL);
   3969        if (responder && ocsp_matchcert(certIndex, responder)) {
   3970            signerCert = CERT_DupCertificate(responder);
   3971        } else if (issuer && ocsp_matchcert(certIndex, issuer)) {
   3972            signerCert = CERT_DupCertificate(issuer);
   3973        }
   3974        for (i = 0; (signerCert == NULL) && (i < certCount); i++) {
   3975            if (ocsp_matchcert(certIndex, certs[i])) {
   3976                signerCert = CERT_DupCertificate(certs[i]);
   3977            }
   3978        }
   3979        if (signerCert == NULL) {
   3980            PORT_SetError(SEC_ERROR_UNKNOWN_CERT);
   3981        }
   3982    }
   3983 
   3984 finish:
   3985    if (certs != NULL) {
   3986        CERT_DestroyCertArray(certs, certCount);
   3987    }
   3988 
   3989    return signerCert;
   3990 }
   3991 
   3992 SECStatus
   3993 ocsp_VerifyResponseSignature(CERTCertificate *signerCert,
   3994                             ocspSignature *signature,
   3995                             SECItem *tbsResponseDataDER,
   3996                             void *pwArg)
   3997 {
   3998    SECKEYPublicKey *signerKey = NULL;
   3999    SECStatus rv = SECFailure;
   4000    CERTSignedData signedData;
   4001 
   4002    /*
   4003     * Now get the public key from the signer's certificate; we need
   4004     * it to perform the verification.
   4005     */
   4006    signerKey = CERT_ExtractPublicKey(signerCert);
   4007    if (signerKey == NULL) {
   4008        return SECFailure;
   4009    }
   4010 
   4011    /*
   4012     * We copy the signature data *pointer* and length, so that we can
   4013     * modify the length without damaging the original copy.  This is a
   4014     * simple copy, not a dup, so no destroy/free is necessary.
   4015     */
   4016    signedData.signature = signature->signature;
   4017    signedData.signatureAlgorithm = signature->signatureAlgorithm;
   4018    signedData.data = *tbsResponseDataDER;
   4019 
   4020    rv = CERT_VerifySignedDataWithPublicKey(&signedData, signerKey, pwArg);
   4021    if (rv != SECSuccess &&
   4022        (PORT_GetError() == SEC_ERROR_BAD_SIGNATURE ||
   4023         PORT_GetError() == SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED)) {
   4024        PORT_SetError(SEC_ERROR_OCSP_BAD_SIGNATURE);
   4025    }
   4026 
   4027    if (signerKey != NULL) {
   4028        SECKEY_DestroyPublicKey(signerKey);
   4029    }
   4030 
   4031    return rv;
   4032 }
   4033 
   4034 /*
   4035 * FUNCTION: CERT_VerifyOCSPResponseSignature
   4036 *   Check the signature on an OCSP Response.  Will also perform a
   4037 *   verification of the signer's certificate.  Note, however, that a
   4038 *   successful verification does not make any statement about the
   4039 *   signer's *authority* to provide status for the certificate(s),
   4040 *   that must be checked individually for each certificate.
   4041 * INPUTS:
   4042 *   CERTOCSPResponse *response
   4043 *     Pointer to response structure with signature to be checked.
   4044 *   CERTCertDBHandle *handle
   4045 *     Pointer to CERTCertDBHandle for certificate DB to use for verification.
   4046 *   void *pwArg
   4047 *     Pointer to argument for password prompting, if needed.
   4048 * OUTPUTS:
   4049 *   CERTCertificate **pSignerCert
   4050 *     Pointer in which to store signer's certificate; only filled-in if
   4051 *     non-null.
   4052 * RETURN:
   4053 *   Returns SECSuccess when signature is valid, anything else means invalid.
   4054 *   Possible errors set:
   4055 *	SEC_ERROR_OCSP_MALFORMED_RESPONSE - unknown type of ResponderID
   4056 *	SEC_ERROR_INVALID_TIME - bad format of "ProducedAt" time
   4057 *	SEC_ERROR_UNKNOWN_SIGNER - signer's cert could not be found
   4058 *	SEC_ERROR_BAD_SIGNATURE - the signature did not verify
   4059 *   Other errors are any of the many possible failures in cert verification
   4060 *   (e.g. SEC_ERROR_REVOKED_CERTIFICATE, SEC_ERROR_UNTRUSTED_ISSUER) when
   4061 *   verifying the signer's cert, or low-level problems (no memory, etc.)
   4062 */
   4063 SECStatus
   4064 CERT_VerifyOCSPResponseSignature(CERTOCSPResponse *response,
   4065                                 CERTCertDBHandle *handle, void *pwArg,
   4066                                 CERTCertificate **pSignerCert,
   4067                                 CERTCertificate *issuer)
   4068 {
   4069    SECItem *tbsResponseDataDER;
   4070    CERTCertificate *signerCert = NULL;
   4071    SECStatus rv = SECFailure;
   4072    PRTime producedAt;
   4073 
   4074    /* ocsp_DecodeBasicOCSPResponse will fail if asn1 decoder is unable
   4075     * to properly decode tbsData (see the function and
   4076     * ocsp_BasicOCSPResponseTemplate). Thus, tbsData can not be
   4077     * equal to null */
   4078    ocspResponseData *tbsData = ocsp_GetResponseData(response,
   4079                                                     &tbsResponseDataDER);
   4080    ocspSignature *signature = ocsp_GetResponseSignature(response);
   4081 
   4082    if (!signature) {
   4083        PORT_SetError(SEC_ERROR_OCSP_BAD_SIGNATURE);
   4084        return SECFailure;
   4085    }
   4086 
   4087    /*
   4088     * If this signature has already gone through verification, just
   4089     * return the cached result.
   4090     */
   4091    if (signature->wasChecked) {
   4092        if (signature->status == SECSuccess) {
   4093            if (pSignerCert != NULL)
   4094                *pSignerCert = CERT_DupCertificate(signature->cert);
   4095        } else {
   4096            PORT_SetError(signature->failureReason);
   4097        }
   4098        return signature->status;
   4099    }
   4100 
   4101    signerCert = ocsp_GetSignerCertificate(handle, tbsData,
   4102                                           signature, issuer);
   4103    if (signerCert == NULL) {
   4104        rv = SECFailure;
   4105        if (PORT_GetError() == SEC_ERROR_UNKNOWN_CERT) {
   4106            /* Make the error a little more specific. */
   4107            PORT_SetError(SEC_ERROR_OCSP_INVALID_SIGNING_CERT);
   4108        }
   4109        goto finish;
   4110    }
   4111 
   4112    /*
   4113     * We could mark this true at the top of this function, or always
   4114     * below at "finish", but if the problem was just that we could not
   4115     * find the signer's cert, leave that as if the signature hasn't
   4116     * been checked in case a subsequent call might have better luck.
   4117     */
   4118    signature->wasChecked = PR_TRUE;
   4119 
   4120    /*
   4121     * The function will also verify the signer certificate; we
   4122     * need to tell it *when* that certificate must be valid -- for our
   4123     * purposes we expect it to be valid when the response was signed.
   4124     * The value of "producedAt" is the signing time.
   4125     */
   4126    rv = DER_GeneralizedTimeToTime(&producedAt, &tbsData->producedAt);
   4127    if (rv != SECSuccess)
   4128        goto finish;
   4129 
   4130    /*
   4131     * Just because we have a cert does not mean it is any good; check
   4132     * it for validity, trust and usage.
   4133     */
   4134    if (!ocsp_CertIsOCSPDefaultResponder(handle, signerCert)) {
   4135        SECCertUsage certUsage;
   4136        if (CERT_IsCACert(signerCert, NULL)) {
   4137            certUsage = certUsageAnyCA;
   4138        } else {
   4139            certUsage = certUsageStatusResponder;
   4140        }
   4141        rv = cert_VerifyCertWithFlags(handle, signerCert, PR_TRUE, certUsage,
   4142                                      producedAt, CERT_VERIFYCERT_SKIP_OCSP,
   4143                                      pwArg, NULL);
   4144        if (rv != SECSuccess) {
   4145            PORT_SetError(SEC_ERROR_OCSP_INVALID_SIGNING_CERT);
   4146            goto finish;
   4147        }
   4148    }
   4149 
   4150    rv = ocsp_VerifyResponseSignature(signerCert, signature,
   4151                                      tbsResponseDataDER,
   4152                                      pwArg);
   4153 
   4154 finish:
   4155    if (signature->wasChecked)
   4156        signature->status = rv;
   4157 
   4158    if (rv != SECSuccess) {
   4159        signature->failureReason = PORT_GetError();
   4160        if (signerCert != NULL)
   4161            CERT_DestroyCertificate(signerCert);
   4162    } else {
   4163        /*
   4164         * Save signer's certificate in signature.
   4165         */
   4166        signature->cert = signerCert;
   4167        if (pSignerCert != NULL) {
   4168            /*
   4169             * Pass pointer to signer's certificate back to our caller,
   4170             * who is also now responsible for destroying it.
   4171             */
   4172            *pSignerCert = CERT_DupCertificate(signerCert);
   4173        }
   4174    }
   4175 
   4176    return rv;
   4177 }
   4178 
   4179 /*
   4180 * See if the request's certID and the single response's certID match.
   4181 * This can be easy or difficult, depending on whether the same hash
   4182 * algorithm was used.
   4183 */
   4184 static PRBool
   4185 ocsp_CertIDsMatch(CERTOCSPCertID *requestCertID,
   4186                  CERTOCSPCertID *responseCertID)
   4187 {
   4188    PRBool match = PR_FALSE;
   4189    SECOidTag hashAlg;
   4190    SECItem *keyHash = NULL;
   4191    SECItem *nameHash = NULL;
   4192 
   4193    /*
   4194     * In order to match, they must have the same issuer and the same
   4195     * serial number.
   4196     *
   4197     * We just compare the easier things first.
   4198     */
   4199    if (SECITEM_CompareItem(&requestCertID->serialNumber,
   4200                            &responseCertID->serialNumber) != SECEqual) {
   4201        goto done;
   4202    }
   4203 
   4204    /*
   4205     * Make sure the "parameters" are not too bogus.  Since we encoded
   4206     * requestCertID->hashAlgorithm, we don't need to check it.
   4207     */
   4208    if (responseCertID->hashAlgorithm.parameters.len > 2) {
   4209        goto done;
   4210    }
   4211    if (SECITEM_CompareItem(&requestCertID->hashAlgorithm.algorithm,
   4212                            &responseCertID->hashAlgorithm.algorithm) ==
   4213        SECEqual) {
   4214        /*
   4215         * If the hash algorithms match then we can do a simple compare
   4216         * of the hash values themselves.
   4217         */
   4218        if ((SECITEM_CompareItem(&requestCertID->issuerNameHash,
   4219                                 &responseCertID->issuerNameHash) == SECEqual) &&
   4220            (SECITEM_CompareItem(&requestCertID->issuerKeyHash,
   4221                                 &responseCertID->issuerKeyHash) == SECEqual)) {
   4222            match = PR_TRUE;
   4223        }
   4224        goto done;
   4225    }
   4226 
   4227    hashAlg = SECOID_FindOIDTag(&responseCertID->hashAlgorithm.algorithm);
   4228    switch (hashAlg) {
   4229        case SEC_OID_SHA1:
   4230            keyHash = &requestCertID->issuerSHA1KeyHash;
   4231            nameHash = &requestCertID->issuerSHA1NameHash;
   4232            break;
   4233        case SEC_OID_MD5:
   4234            keyHash = &requestCertID->issuerMD5KeyHash;
   4235            nameHash = &requestCertID->issuerMD5NameHash;
   4236            break;
   4237        case SEC_OID_MD2:
   4238            keyHash = &requestCertID->issuerMD2KeyHash;
   4239            nameHash = &requestCertID->issuerMD2NameHash;
   4240            break;
   4241        default:
   4242            PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
   4243            return PR_FALSE;
   4244    }
   4245 
   4246    if ((keyHash != NULL) &&
   4247        (SECITEM_CompareItem(nameHash,
   4248                             &responseCertID->issuerNameHash) == SECEqual) &&
   4249        (SECITEM_CompareItem(keyHash,
   4250                             &responseCertID->issuerKeyHash) == SECEqual)) {
   4251        match = PR_TRUE;
   4252    }
   4253 
   4254 done:
   4255    return match;
   4256 }
   4257 
   4258 /*
   4259 * Find the single response for the cert specified by certID.
   4260 * No copying is done; this just returns a pointer to the appropriate
   4261 * response within responses, if it is found (and null otherwise).
   4262 * This is fine, of course, since this function is internal-use only.
   4263 */
   4264 static CERTOCSPSingleResponse *
   4265 ocsp_GetSingleResponseForCertID(CERTOCSPSingleResponse **responses,
   4266                                CERTCertDBHandle *handle,
   4267                                CERTOCSPCertID *certID)
   4268 {
   4269    CERTOCSPSingleResponse *single;
   4270    int i;
   4271 
   4272    if (responses == NULL)
   4273        return NULL;
   4274 
   4275    for (i = 0; responses[i] != NULL; i++) {
   4276        single = responses[i];
   4277        if (ocsp_CertIDsMatch(certID, single->certID)) {
   4278            return single;
   4279        }
   4280    }
   4281 
   4282    /*
   4283     * The OCSP server should have included a response even if it knew
   4284     * nothing about the certificate in question.  Since it did not,
   4285     * this will make it look as if it had.
   4286     *
   4287     * XXX Should we make this a separate error to notice the server's
   4288     * bad behavior?
   4289     */
   4290    PORT_SetError(SEC_ERROR_OCSP_UNKNOWN_CERT);
   4291    return NULL;
   4292 }
   4293 
   4294 static ocspCheckingContext *
   4295 ocsp_GetCheckingContext(CERTCertDBHandle *handle)
   4296 {
   4297    CERTStatusConfig *statusConfig;
   4298    ocspCheckingContext *ocspcx = NULL;
   4299 
   4300    statusConfig = CERT_GetStatusConfig(handle);
   4301    if (statusConfig != NULL) {
   4302        ocspcx = statusConfig->statusContext;
   4303 
   4304        /*
   4305         * This is actually an internal error, because we should never
   4306         * have a good statusConfig without a good statusContext, too.
   4307         * For lack of anything better, though, we just assert and use
   4308         * the same error as if there were no statusConfig (set below).
   4309         */
   4310        PORT_Assert(ocspcx != NULL);
   4311    }
   4312 
   4313    if (ocspcx == NULL)
   4314        PORT_SetError(SEC_ERROR_OCSP_NOT_ENABLED);
   4315 
   4316    return ocspcx;
   4317 }
   4318 
   4319 /*
   4320 * Return cert reference if the given signerCert is the default responder for
   4321 * the given certID.  If not, or if any error, return NULL.
   4322 */
   4323 static CERTCertificate *
   4324 ocsp_CertGetDefaultResponder(CERTCertDBHandle *handle, CERTOCSPCertID *certID)
   4325 {
   4326    ocspCheckingContext *ocspcx;
   4327 
   4328    ocspcx = ocsp_GetCheckingContext(handle);
   4329    if (ocspcx == NULL)
   4330        goto loser;
   4331 
   4332    /*
   4333     * Right now we have only one default responder.  It applies to
   4334     * all certs when it is used, so the check is simple and certID
   4335     * has no bearing on the answer.  Someday in the future we may
   4336     * allow configuration of different responders for different
   4337     * issuers, and then we would have to use the issuer specified
   4338     * in certID to determine if signerCert is the right one.
   4339     */
   4340    if (ocspcx->useDefaultResponder) {
   4341        PORT_Assert(ocspcx->defaultResponderCert != NULL);
   4342        return ocspcx->defaultResponderCert;
   4343    }
   4344 
   4345 loser:
   4346    return NULL;
   4347 }
   4348 
   4349 /*
   4350 * Return true if the cert is one of the default responders configured for
   4351 * ocsp context. If not, or if any error, return false.
   4352 */
   4353 PRBool
   4354 ocsp_CertIsOCSPDefaultResponder(CERTCertDBHandle *handle, CERTCertificate *cert)
   4355 {
   4356    ocspCheckingContext *ocspcx;
   4357 
   4358    ocspcx = ocsp_GetCheckingContext(handle);
   4359    if (ocspcx == NULL)
   4360        return PR_FALSE;
   4361 
   4362    /*
   4363     * Right now we have only one default responder.  It applies to
   4364     * all certs when it is used, so the check is simple and certID
   4365     * has no bearing on the answer.  Someday in the future we may
   4366     * allow configuration of different responders for different
   4367     * issuers, and then we would have to use the issuer specified
   4368     * in certID to determine if signerCert is the right one.
   4369     */
   4370    if (ocspcx->useDefaultResponder &&
   4371        CERT_CompareCerts(ocspcx->defaultResponderCert, cert)) {
   4372        return PR_TRUE;
   4373    }
   4374 
   4375    return PR_FALSE;
   4376 }
   4377 
   4378 /*
   4379 * Check that the given signer certificate is authorized to sign status
   4380 * information for the given certID.  Return true if it is, false if not
   4381 * (or if there is any error along the way).  If false is returned because
   4382 * the signer is not authorized, the following error will be set:
   4383 *	SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE
   4384 * Other errors are low-level problems (no memory, bad database, etc.).
   4385 *
   4386 * There are three ways to be authorized.  In the order in which we check,
   4387 * using the terms used in the OCSP spec, the signer must be one of:
   4388 *  1.  A "trusted responder" -- it matches a local configuration
   4389 *      of OCSP signing authority for the certificate in question.
   4390 *  2.  The CA who issued the certificate in question.
   4391 *  3.  A "CA designated responder", aka an "authorized responder" -- it
   4392 *      must be represented by a special cert issued by the CA who issued
   4393 *      the certificate in question.
   4394 */
   4395 static PRBool
   4396 ocsp_AuthorizedResponderForCertID(CERTCertDBHandle *handle,
   4397                                  CERTCertificate *signerCert,
   4398                                  CERTOCSPCertID *certID,
   4399                                  PRTime thisUpdate)
   4400 {
   4401    CERTCertificate *issuerCert = NULL, *defRespCert;
   4402    SECItem *keyHash = NULL;
   4403    SECItem *nameHash = NULL;
   4404    SECOidTag hashAlg;
   4405    PRBool keyHashEQ = PR_FALSE, nameHashEQ = PR_FALSE;
   4406 
   4407    /*
   4408     * Check first for a trusted responder, which overrides everything else.
   4409     */
   4410    if ((defRespCert = ocsp_CertGetDefaultResponder(handle, certID)) &&
   4411        CERT_CompareCerts(defRespCert, signerCert)) {
   4412        return PR_TRUE;
   4413    }
   4414 
   4415    /*
   4416     * In the other two cases, we need to do an issuer comparison.
   4417     * How we do it depends on whether the signer certificate has the
   4418     * special extension (for a designated responder) or not.
   4419     *
   4420     * First, lets check if signer of the response is the actual issuer
   4421     * of the cert. For that we will use signer cert key hash and cert subj
   4422     * name hash and will compare them with already calculated issuer key
   4423     * hash and issuer name hash. The hash algorithm is picked from response
   4424     * certID hash to avoid second hash calculation.
   4425     */
   4426 
   4427    hashAlg = SECOID_FindOIDTag(&certID->hashAlgorithm.algorithm);
   4428 
   4429    keyHash = CERT_GetSubjectPublicKeyDigest(NULL, signerCert, hashAlg, NULL);
   4430    if (keyHash != NULL) {
   4431 
   4432        keyHashEQ =
   4433            (SECITEM_CompareItem(keyHash,
   4434                                 &certID->issuerKeyHash) == SECEqual);
   4435        SECITEM_FreeItem(keyHash, PR_TRUE);
   4436    }
   4437    if (keyHashEQ &&
   4438        (nameHash = CERT_GetSubjectNameDigest(NULL, signerCert,
   4439                                              hashAlg, NULL))) {
   4440        nameHashEQ =
   4441            (SECITEM_CompareItem(nameHash,
   4442                                 &certID->issuerNameHash) == SECEqual);
   4443 
   4444        SECITEM_FreeItem(nameHash, PR_TRUE);
   4445        if (nameHashEQ) {
   4446            /* The issuer of the cert is the the signer of the response */
   4447            return PR_TRUE;
   4448        }
   4449    }
   4450 
   4451    keyHashEQ = PR_FALSE;
   4452    nameHashEQ = PR_FALSE;
   4453 
   4454    if (!ocsp_CertIsOCSPDesignatedResponder(signerCert)) {
   4455        PORT_SetError(SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE);
   4456        return PR_FALSE;
   4457    }
   4458 
   4459    /*
   4460     * The signer is a designated responder.  Its issuer must match
   4461     * the issuer of the cert being checked.
   4462     */
   4463    issuerCert = CERT_FindCertIssuer(signerCert, thisUpdate,
   4464                                     certUsageAnyCA);
   4465    if (issuerCert == NULL) {
   4466        /*
   4467         * We could leave the SEC_ERROR_UNKNOWN_ISSUER error alone,
   4468         * but the following will give slightly more information.
   4469         * Once we have an error stack, things will be much better.
   4470         */
   4471        PORT_SetError(SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE);
   4472        return PR_FALSE;
   4473    }
   4474 
   4475    keyHash = CERT_GetSubjectPublicKeyDigest(NULL, issuerCert, hashAlg, NULL);
   4476    nameHash = CERT_GetSubjectNameDigest(NULL, issuerCert, hashAlg, NULL);
   4477 
   4478    CERT_DestroyCertificate(issuerCert);
   4479 
   4480    if (keyHash != NULL && nameHash != NULL) {
   4481        keyHashEQ =
   4482            (SECITEM_CompareItem(keyHash,
   4483                                 &certID->issuerKeyHash) == SECEqual);
   4484 
   4485        nameHashEQ =
   4486            (SECITEM_CompareItem(nameHash,
   4487                                 &certID->issuerNameHash) == SECEqual);
   4488    }
   4489 
   4490    if (keyHash) {
   4491        SECITEM_FreeItem(keyHash, PR_TRUE);
   4492    }
   4493    if (nameHash) {
   4494        SECITEM_FreeItem(nameHash, PR_TRUE);
   4495    }
   4496 
   4497    if (keyHashEQ && nameHashEQ) {
   4498        return PR_TRUE;
   4499    }
   4500 
   4501    PORT_SetError(SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE);
   4502    return PR_FALSE;
   4503 }
   4504 
   4505 /*
   4506 * We need to check that a responder gives us "recent" information.
   4507 * Since a responder can pre-package responses, we need to pick an amount
   4508 * of time that is acceptable to us, and reject any response that is
   4509 * older than that.
   4510 *
   4511 * XXX This *should* be based on some configuration parameter, so that
   4512 * different usages could specify exactly what constitutes "sufficiently
   4513 * recent".  But that is not going to happen right away.  For now, we
   4514 * want something from within the last 24 hours.  This macro defines that
   4515 * number in seconds.
   4516 */
   4517 #define OCSP_ALLOWABLE_LAPSE_SECONDS (24L * 60L * 60L)
   4518 
   4519 static PRBool
   4520 ocsp_TimeIsRecent(PRTime checkTime)
   4521 {
   4522    PRTime now = PR_Now();
   4523    PRTime lapse, tmp;
   4524 
   4525    LL_I2L(lapse, OCSP_ALLOWABLE_LAPSE_SECONDS);
   4526    LL_I2L(tmp, PR_USEC_PER_SEC);
   4527    LL_MUL(lapse, lapse, tmp); /* allowable lapse in microseconds */
   4528 
   4529    LL_ADD(checkTime, checkTime, lapse);
   4530    if (LL_CMP(now, >, checkTime))
   4531        return PR_FALSE;
   4532 
   4533    return PR_TRUE;
   4534 }
   4535 
   4536 #define OCSP_SLOP (5L * 60L) /* OCSP responses are allowed to be 5 minutes \
   4537                                in the future by default */
   4538 
   4539 static PRUint32 ocspsloptime = OCSP_SLOP; /* seconds */
   4540 
   4541 /*
   4542 * If an old response contains the revoked certificate status, we want
   4543 * to return SECSuccess so the response will be used.
   4544 */
   4545 static SECStatus
   4546 ocsp_HandleOldSingleResponse(CERTOCSPSingleResponse *single, PRTime time)
   4547 {
   4548    SECStatus rv;
   4549    ocspCertStatus *status = single->certStatus;
   4550    if (status->certStatusType == ocspCertStatus_revoked) {
   4551        rv = ocsp_CertRevokedAfter(status->certStatusInfo.revokedInfo, time);
   4552        if (rv != SECSuccess &&
   4553            PORT_GetError() == SEC_ERROR_REVOKED_CERTIFICATE) {
   4554            /*
   4555             * Return SECSuccess now.  The subsequent ocsp_CertRevokedAfter
   4556             * call in ocsp_CertHasGoodStatus will cause
   4557             * ocsp_CertHasGoodStatus to fail with
   4558             * SEC_ERROR_REVOKED_CERTIFICATE.
   4559             */
   4560            return SECSuccess;
   4561        }
   4562    }
   4563    PORT_SetError(SEC_ERROR_OCSP_OLD_RESPONSE);
   4564    return SECFailure;
   4565 }
   4566 
   4567 /*
   4568 * Check that this single response is okay.  A return of SECSuccess means:
   4569 *   1. The signer (represented by "signerCert") is authorized to give status
   4570 *	for the cert represented by the individual response in "single".
   4571 *   2. The value of thisUpdate is earlier than now.
   4572 *   3. The value of producedAt is later than or the same as thisUpdate.
   4573 *   4. If nextUpdate is given:
   4574 *	- The value of nextUpdate is later than now.
   4575 *	- The value of producedAt is earlier than nextUpdate.
   4576 *	Else if no nextUpdate:
   4577 *	- The value of thisUpdate is fairly recent.
   4578 *	- The value of producedAt is fairly recent.
   4579 *	However we do not need to perform an explicit check for this last
   4580 *	constraint because it is already guaranteed by checking that
   4581 *	producedAt is later than thisUpdate and thisUpdate is recent.
   4582 * Oh, and any responder is "authorized" to say that a cert is unknown to it.
   4583 *
   4584 * If any of those checks fail, SECFailure is returned and an error is set:
   4585 *	SEC_ERROR_OCSP_FUTURE_RESPONSE
   4586 *	SEC_ERROR_OCSP_OLD_RESPONSE
   4587 *	SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE
   4588 * Other errors are low-level problems (no memory, bad database, etc.).
   4589 */
   4590 static SECStatus
   4591 ocsp_VerifySingleResponse(CERTOCSPSingleResponse *single,
   4592                          CERTCertDBHandle *handle,
   4593                          CERTCertificate *signerCert,
   4594                          PRTime producedAt)
   4595 {
   4596    CERTOCSPCertID *certID = single->certID;
   4597    PRTime now, thisUpdate, nextUpdate, tmstamp, tmp;
   4598    SECStatus rv;
   4599 
   4600    OCSP_TRACE(("OCSP ocsp_VerifySingleResponse, nextUpdate: %d\n",
   4601                ((single->nextUpdate) != 0)));
   4602    /*
   4603     * If all the responder said was that the given cert was unknown to it,
   4604     * that is a valid response.  Not very interesting to us, of course,
   4605     * but all this function is concerned with is validity of the response,
   4606     * not the status of the cert.
   4607     */
   4608    PORT_Assert(single->certStatus != NULL);
   4609    if (single->certStatus->certStatusType == ocspCertStatus_unknown)
   4610        return SECSuccess;
   4611 
   4612    /*
   4613     * We need to extract "thisUpdate" for use below and to pass along
   4614     * to AuthorizedResponderForCertID in case it needs it for doing an
   4615     * issuer look-up.
   4616     */
   4617    rv = DER_GeneralizedTimeToTime(&thisUpdate, &single->thisUpdate);
   4618    if (rv != SECSuccess)
   4619        return rv;
   4620 
   4621    /*
   4622     * First confirm that signerCert is authorized to give this status.
   4623     */
   4624    if (ocsp_AuthorizedResponderForCertID(handle, signerCert, certID,
   4625                                          thisUpdate) != PR_TRUE)
   4626        return SECFailure;
   4627 
   4628    /*
   4629     * Now check the time stuff, as described above.
   4630     */
   4631    now = PR_Now();
   4632    /* allow slop time for future response */
   4633    LL_UI2L(tmstamp, ocspsloptime); /* get slop time in seconds */
   4634    LL_UI2L(tmp, PR_USEC_PER_SEC);
   4635    LL_MUL(tmp, tmstamp, tmp); /* convert the slop time to PRTime */
   4636    LL_ADD(tmstamp, tmp, now); /* add current time to it */
   4637 
   4638    if (LL_CMP(thisUpdate, >, tmstamp) || LL_CMP(producedAt, <, thisUpdate)) {
   4639        PORT_SetError(SEC_ERROR_OCSP_FUTURE_RESPONSE);
   4640        return SECFailure;
   4641    }
   4642    if (single->nextUpdate != NULL) {
   4643        rv = DER_GeneralizedTimeToTime(&nextUpdate, single->nextUpdate);
   4644        if (rv != SECSuccess)
   4645            return rv;
   4646 
   4647        LL_ADD(tmp, tmp, nextUpdate);
   4648        if (LL_CMP(tmp, <, now) || LL_CMP(producedAt, >, nextUpdate))
   4649            return ocsp_HandleOldSingleResponse(single, now);
   4650    } else if (ocsp_TimeIsRecent(thisUpdate) != PR_TRUE) {
   4651        return ocsp_HandleOldSingleResponse(single, now);
   4652    }
   4653 
   4654    return SECSuccess;
   4655 }
   4656 
   4657 /*
   4658 * FUNCTION: CERT_GetOCSPAuthorityInfoAccessLocation
   4659 *   Get the value of the URI of the OCSP responder for the given cert.
   4660 *   This is found in the (optional) Authority Information Access extension
   4661 *   in the cert.
   4662 * INPUTS:
   4663 *   CERTCertificate *cert
   4664 *     The certificate being examined.
   4665 * RETURN:
   4666 *   char *
   4667 *     A copy of the URI for the OCSP method, if found.  If either the
   4668 *     extension is not present or it does not contain an entry for OCSP,
   4669 *     SEC_ERROR_CERT_BAD_ACCESS_LOCATION will be set and a NULL returned.
   4670 *     Any other error will also result in a NULL being returned.
   4671 *
   4672 *     This result should be freed (via PORT_Free) when no longer in use.
   4673 */
   4674 char *
   4675 CERT_GetOCSPAuthorityInfoAccessLocation(const CERTCertificate *cert)
   4676 {
   4677    CERTGeneralName *locname = NULL;
   4678    SECItem *location = NULL;
   4679    SECItem *encodedAuthInfoAccess = NULL;
   4680    CERTAuthInfoAccess **authInfoAccess = NULL;
   4681    char *locURI = NULL;
   4682    PLArenaPool *arena = NULL;
   4683    SECStatus rv;
   4684    int i;
   4685 
   4686    /*
   4687     * Allocate this one from the heap because it will get filled in
   4688     * by CERT_FindCertExtension which will also allocate from the heap,
   4689     * and we can free the entire thing on our way out.
   4690     */
   4691    encodedAuthInfoAccess = SECITEM_AllocItem(NULL, NULL, 0);
   4692    if (encodedAuthInfoAccess == NULL)
   4693        goto loser;
   4694 
   4695    rv = CERT_FindCertExtension(cert, SEC_OID_X509_AUTH_INFO_ACCESS,
   4696                                encodedAuthInfoAccess);
   4697    if (rv == SECFailure) {
   4698        PORT_SetError(SEC_ERROR_CERT_BAD_ACCESS_LOCATION);
   4699        goto loser;
   4700    }
   4701 
   4702    /*
   4703     * The rest of the things allocated in the routine will come out of
   4704     * this arena, which is temporary just for us to decode and get at the
   4705     * AIA extension.  The whole thing will be destroyed on our way out,
   4706     * after we have copied the location string (url) itself (if found).
   4707     */
   4708    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   4709    if (arena == NULL)
   4710        goto loser;
   4711 
   4712    authInfoAccess = CERT_DecodeAuthInfoAccessExtension(arena,
   4713                                                        encodedAuthInfoAccess);
   4714    if (authInfoAccess == NULL)
   4715        goto loser;
   4716 
   4717    for (i = 0; authInfoAccess[i] != NULL; i++) {
   4718        if (SECOID_FindOIDTag(&authInfoAccess[i]->method) == SEC_OID_PKIX_OCSP)
   4719            locname = authInfoAccess[i]->location;
   4720    }
   4721 
   4722    /*
   4723     * If we found an AIA extension, but it did not include an OCSP method,
   4724     * that should look to our caller as if we did not find the extension
   4725     * at all, because it is only an OCSP method that we care about.
   4726     * So set the same error that would be set if the AIA extension was
   4727     * not there at all.
   4728     */
   4729    if (locname == NULL) {
   4730        PORT_SetError(SEC_ERROR_CERT_BAD_ACCESS_LOCATION);
   4731        goto loser;
   4732    }
   4733 
   4734    /*
   4735     * The following is just a pointer back into locname (i.e. not a copy);
   4736     * thus it should not be freed.
   4737     */
   4738    location = CERT_GetGeneralNameByType(locname, certURI, PR_FALSE);
   4739    if (location == NULL) {
   4740        /*
   4741         * XXX Appears that CERT_GetGeneralNameByType does not set an
   4742         * error if there is no name by that type.  For lack of anything
   4743         * better, act as if the extension was not found.  In the future
   4744         * this should probably be something more like the extension was
   4745         * badly formed.
   4746         */
   4747        PORT_SetError(SEC_ERROR_CERT_BAD_ACCESS_LOCATION);
   4748        goto loser;
   4749    }
   4750 
   4751    /*
   4752     * That location is really a string, but it has a specified length
   4753     * without a null-terminator.  We need a real string that does have
   4754     * a null-terminator, and we need a copy of it anyway to return to
   4755     * our caller -- so allocate and copy.
   4756     */
   4757    locURI = PORT_Alloc(location->len + 1);
   4758    if (locURI == NULL) {
   4759        goto loser;
   4760    }
   4761    PORT_Memcpy(locURI, location->data, location->len);
   4762    locURI[location->len] = '\0';
   4763 
   4764 loser:
   4765    if (arena != NULL)
   4766        PORT_FreeArena(arena, PR_FALSE);
   4767 
   4768    if (encodedAuthInfoAccess != NULL)
   4769        SECITEM_FreeItem(encodedAuthInfoAccess, PR_TRUE);
   4770 
   4771    return locURI;
   4772 }
   4773 
   4774 /*
   4775 * Figure out where we should go to find out the status of the given cert
   4776 * via OCSP.  If allowed to use a default responder uri and a default
   4777 * responder is set up, then that is our answer.
   4778 * If not, see if the certificate has an Authority Information Access (AIA)
   4779 * extension for OCSP, and return the value of that.  Otherwise return NULL.
   4780 * We also let our caller know whether or not the responder chosen was
   4781 * a default responder or not through the output variable isDefault;
   4782 * its value has no meaning unless a good (non-null) value is returned
   4783 * for the location.
   4784 *
   4785 * The result needs to be freed (PORT_Free) when no longer in use.
   4786 */
   4787 char *
   4788 ocsp_GetResponderLocation(CERTCertDBHandle *handle, CERTCertificate *cert,
   4789                          PRBool canUseDefault, PRBool *isDefault)
   4790 {
   4791    ocspCheckingContext *ocspcx = NULL;
   4792    char *ocspUrl = NULL;
   4793 
   4794    if (canUseDefault) {
   4795        ocspcx = ocsp_GetCheckingContext(handle);
   4796    }
   4797    if (ocspcx != NULL && ocspcx->useDefaultResponder) {
   4798        /*
   4799         * A default responder wins out, if specified.
   4800         * XXX Someday this may be a more complicated determination based
   4801         * on the cert's issuer.  (That is, we could have different default
   4802         * responders configured for different issuers.)
   4803         */
   4804        PORT_Assert(ocspcx->defaultResponderURI != NULL);
   4805        *isDefault = PR_TRUE;
   4806        return (PORT_Strdup(ocspcx->defaultResponderURI));
   4807    }
   4808 
   4809    /*
   4810     * No default responder set up, so go see if we can find an AIA
   4811     * extension that has a value for OCSP, and get the url from that.
   4812     */
   4813    *isDefault = PR_FALSE;
   4814    ocspUrl = CERT_GetOCSPAuthorityInfoAccessLocation(cert);
   4815    if (!ocspUrl) {
   4816        CERT_StringFromCertFcn altFcn;
   4817 
   4818        PR_EnterMonitor(OCSP_Global.monitor);
   4819        altFcn = OCSP_Global.alternateOCSPAIAFcn;
   4820        PR_ExitMonitor(OCSP_Global.monitor);
   4821        if (altFcn) {
   4822            ocspUrl = (*altFcn)(cert);
   4823            if (ocspUrl)
   4824                *isDefault = PR_TRUE;
   4825        }
   4826    }
   4827    return ocspUrl;
   4828 }
   4829 
   4830 /*
   4831 * Return SECSuccess if the cert was revoked *after* "time",
   4832 * SECFailure otherwise.
   4833 */
   4834 static SECStatus
   4835 ocsp_CertRevokedAfter(ocspRevokedInfo *revokedInfo, PRTime time)
   4836 {
   4837    PRTime revokedTime;
   4838    SECStatus rv;
   4839 
   4840    rv = DER_GeneralizedTimeToTime(&revokedTime, &revokedInfo->revocationTime);
   4841    if (rv != SECSuccess)
   4842        return rv;
   4843 
   4844    /*
   4845     * Set the error even if we will return success; someone might care.
   4846     */
   4847    PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE);
   4848 
   4849    if (LL_CMP(revokedTime, >, time))
   4850        return SECSuccess;
   4851 
   4852    return SECFailure;
   4853 }
   4854 
   4855 /*
   4856 * See if the cert represented in the single response had a good status
   4857 * at the specified time.
   4858 */
   4859 SECStatus
   4860 ocsp_CertHasGoodStatus(ocspCertStatus *status, PRTime time)
   4861 {
   4862    SECStatus rv;
   4863    switch (status->certStatusType) {
   4864        case ocspCertStatus_good:
   4865            rv = SECSuccess;
   4866            break;
   4867        case ocspCertStatus_revoked:
   4868            rv = ocsp_CertRevokedAfter(status->certStatusInfo.revokedInfo, time);
   4869            break;
   4870        case ocspCertStatus_unknown:
   4871            PORT_SetError(SEC_ERROR_OCSP_UNKNOWN_CERT);
   4872            rv = SECFailure;
   4873            break;
   4874        case ocspCertStatus_other:
   4875        default:
   4876            PORT_Assert(0);
   4877            PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
   4878            rv = SECFailure;
   4879            break;
   4880    }
   4881    return rv;
   4882 }
   4883 
   4884 static SECStatus
   4885 ocsp_SingleResponseCertHasGoodStatus(CERTOCSPSingleResponse *single,
   4886                                     PRTime time)
   4887 {
   4888    return ocsp_CertHasGoodStatus(single->certStatus, time);
   4889 }
   4890 
   4891 /* SECFailure means the arguments were invalid.
   4892 * On SECSuccess, the out parameters contain the OCSP status.
   4893 * rvOcsp contains the overall result of the OCSP operation.
   4894 * Depending on input parameter ignoreGlobalOcspFailureSetting,
   4895 * a soft failure might be converted into *rvOcsp=SECSuccess.
   4896 * If the cached attempt to obtain OCSP information had resulted
   4897 * in a failure, missingResponseError shows the error code of
   4898 * that failure.
   4899 * cacheFreshness is ocspMissing if no entry was found,
   4900 *                   ocspFresh if a fresh entry was found, or
   4901 *                   ocspStale if a stale entry was found.
   4902 */
   4903 SECStatus
   4904 ocsp_GetCachedOCSPResponseStatus(CERTOCSPCertID *certID,
   4905                                 PRTime time,
   4906                                 PRBool ignoreGlobalOcspFailureSetting,
   4907                                 SECStatus *rvOcsp,
   4908                                 SECErrorCodes *missingResponseError,
   4909                                 OCSPFreshness *cacheFreshness)
   4910 {
   4911    OCSPCacheItem *cacheItem = NULL;
   4912 
   4913    if (!certID || !missingResponseError || !rvOcsp || !cacheFreshness) {
   4914        PORT_SetError(SEC_ERROR_INVALID_ARGS);
   4915        return SECFailure;
   4916    }
   4917    *rvOcsp = SECFailure;
   4918    *missingResponseError = 0;
   4919    *cacheFreshness = ocspMissing;
   4920 
   4921    PR_EnterMonitor(OCSP_Global.monitor);
   4922    cacheItem = ocsp_FindCacheEntry(&OCSP_Global.cache, certID);
   4923    if (cacheItem) {
   4924        *cacheFreshness = ocsp_IsCacheItemFresh(cacheItem) ? ocspFresh
   4925                                                           : ocspStale;
   4926        /* having an arena means, we have a cached certStatus */
   4927        if (cacheItem->certStatusArena) {
   4928            *rvOcsp = ocsp_CertHasGoodStatus(&cacheItem->certStatus, time);
   4929            if (*rvOcsp != SECSuccess) {
   4930                *missingResponseError = PORT_GetError();
   4931            }
   4932        } else {
   4933            /*
   4934             * No status cached, the previous attempt failed.
   4935             * If OCSP is required, we never decide based on a failed attempt
   4936             * However, if OCSP is optional, a recent OCSP failure is
   4937             * an allowed good state.
   4938             */
   4939            if (*cacheFreshness == ocspFresh &&
   4940                !ignoreGlobalOcspFailureSetting &&
   4941                OCSP_Global.ocspFailureMode ==
   4942                    ocspMode_FailureIsNotAVerificationFailure) {
   4943                *rvOcsp = SECSuccess;
   4944            }
   4945            *missingResponseError = cacheItem->missingResponseError;
   4946        }
   4947    }
   4948    PR_ExitMonitor(OCSP_Global.monitor);
   4949    return SECSuccess;
   4950 }
   4951 
   4952 PRBool
   4953 ocsp_FetchingFailureIsVerificationFailure(void)
   4954 {
   4955    PRBool isFailure;
   4956 
   4957    PR_EnterMonitor(OCSP_Global.monitor);
   4958    isFailure =
   4959        OCSP_Global.ocspFailureMode == ocspMode_FailureIsVerificationFailure;
   4960    PR_ExitMonitor(OCSP_Global.monitor);
   4961    return isFailure;
   4962 }
   4963 
   4964 /*
   4965 * FUNCTION: CERT_CheckOCSPStatus
   4966 *   Checks the status of a certificate via OCSP.  Will only check status for
   4967 *   a certificate that has an AIA (Authority Information Access) extension
   4968 *   for OCSP *or* when a "default responder" is specified and enabled.
   4969 *   (If no AIA extension for OCSP and no default responder in place, the
   4970 *   cert is considered to have a good status and SECSuccess is returned.)
   4971 * INPUTS:
   4972 *   CERTCertDBHandle *handle
   4973 *     certificate DB of the cert that is being checked
   4974 *   CERTCertificate *cert
   4975 *     the certificate being checked
   4976 *   XXX in the long term also need a boolean parameter that specifies
   4977 *	whether to check the cert chain, as well; for now we check only
   4978 *	the leaf (the specified certificate)
   4979 *   PRTime time
   4980 *     time for which status is to be determined
   4981 *   void *pwArg
   4982 *     argument for password prompting, if needed
   4983 * RETURN:
   4984 *   Returns SECSuccess if an approved OCSP responder "knows" the cert
   4985 *   *and* returns a non-revoked status for it; SECFailure otherwise,
   4986 *   with an error set describing the reason:
   4987 *
   4988 *	SEC_ERROR_OCSP_BAD_HTTP_RESPONSE
   4989 *	SEC_ERROR_OCSP_FUTURE_RESPONSE
   4990 *	SEC_ERROR_OCSP_MALFORMED_REQUEST
   4991 *	SEC_ERROR_OCSP_MALFORMED_RESPONSE
   4992 *	SEC_ERROR_OCSP_OLD_RESPONSE
   4993 *	SEC_ERROR_OCSP_REQUEST_NEEDS_SIG
   4994 *	SEC_ERROR_OCSP_SERVER_ERROR
   4995 *	SEC_ERROR_OCSP_TRY_SERVER_LATER
   4996 *	SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST
   4997 *	SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE
   4998 *	SEC_ERROR_OCSP_UNKNOWN_CERT
   4999 *	SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS
   5000 *	SEC_ERROR_OCSP_UNKNOWN_RESPONSE_TYPE
   5001 *
   5002 *	SEC_ERROR_BAD_SIGNATURE
   5003 *	SEC_ERROR_CERT_BAD_ACCESS_LOCATION
   5004 *	SEC_ERROR_INVALID_TIME
   5005 *	SEC_ERROR_REVOKED_CERTIFICATE
   5006 *	SEC_ERROR_UNKNOWN_ISSUER
   5007 *	SEC_ERROR_UNKNOWN_SIGNER
   5008 *
   5009 *   Other errors are any of the many possible failures in cert verification
   5010 *   (e.g. SEC_ERROR_REVOKED_CERTIFICATE, SEC_ERROR_UNTRUSTED_ISSUER) when
   5011 *   verifying the signer's cert, or low-level problems (error allocating
   5012 *   memory, error performing ASN.1 decoding, etc.).
   5013 */
   5014 SECStatus
   5015 CERT_CheckOCSPStatus(CERTCertDBHandle *handle, CERTCertificate *cert,
   5016                     PRTime time, void *pwArg)
   5017 {
   5018    CERTOCSPCertID *certID;
   5019    PRBool certIDWasConsumed = PR_FALSE;
   5020    SECStatus rv;
   5021    SECStatus rvOcsp;
   5022    SECErrorCodes cachedErrorCode;
   5023    OCSPFreshness cachedResponseFreshness;
   5024 
   5025    OCSP_TRACE_CERT(cert);
   5026    OCSP_TRACE_TIME("## requested validity time:", time);
   5027 
   5028    certID = CERT_CreateOCSPCertID(cert, time);
   5029    if (!certID)
   5030        return SECFailure;
   5031    rv = ocsp_GetCachedOCSPResponseStatus(
   5032        certID, time, PR_FALSE, /* ignoreGlobalOcspFailureSetting */
   5033        &rvOcsp, &cachedErrorCode, &cachedResponseFreshness);
   5034    if (rv != SECSuccess) {
   5035        CERT_DestroyOCSPCertID(certID);
   5036        return SECFailure;
   5037    }
   5038    if (cachedResponseFreshness == ocspFresh) {
   5039        CERT_DestroyOCSPCertID(certID);
   5040        if (rvOcsp != SECSuccess) {
   5041            PORT_SetError(cachedErrorCode);
   5042        }
   5043        return rvOcsp;
   5044    }
   5045 
   5046    rv = ocsp_GetOCSPStatusFromNetwork(handle, certID, cert, time, pwArg,
   5047                                       &certIDWasConsumed,
   5048                                       &rvOcsp);
   5049    if (rv != SECSuccess) {
   5050        PRErrorCode err = PORT_GetError();
   5051        if (ocsp_FetchingFailureIsVerificationFailure()) {
   5052            PORT_SetError(err);
   5053            rvOcsp = SECFailure;
   5054        } else if (cachedResponseFreshness == ocspStale &&
   5055                   (cachedErrorCode == SEC_ERROR_OCSP_UNKNOWN_CERT ||
   5056                    cachedErrorCode == SEC_ERROR_REVOKED_CERTIFICATE)) {
   5057            /* If we couldn't get a response for a certificate that the OCSP
   5058             * responder previously told us was bad, then assume it is still
   5059             * bad until we hear otherwise, as it is very unlikely that the
   5060             * certificate status has changed from "revoked" to "good" and it
   5061             * is also unlikely that the certificate status has changed from
   5062             * "unknown" to "good", except for some buggy OCSP responders.
   5063             */
   5064            PORT_SetError(cachedErrorCode);
   5065            rvOcsp = SECFailure;
   5066        } else {
   5067            rvOcsp = SECSuccess;
   5068        }
   5069    }
   5070    if (!certIDWasConsumed) {
   5071        CERT_DestroyOCSPCertID(certID);
   5072    }
   5073    return rvOcsp;
   5074 }
   5075 
   5076 /*
   5077 * FUNCTION: CERT_CacheOCSPResponseFromSideChannel
   5078 *   First, this function checks the OCSP cache to see if a good response
   5079 *   for the given certificate already exists. If it does, then the function
   5080 *   returns successfully.
   5081 *
   5082 *   If not, then it validates that the given OCSP response is a valid,
   5083 *   good response for the given certificate and inserts it into the
   5084 *   cache.
   5085 *
   5086 *   This function is intended for use when OCSP responses are provided via a
   5087 *   side-channel, i.e. TLS OCSP stapling (a.k.a. the status_request extension).
   5088 *
   5089 * INPUTS:
   5090 *   CERTCertDBHandle *handle
   5091 *     certificate DB of the cert that is being checked
   5092 *   CERTCertificate *cert
   5093 *     the certificate being checked
   5094 *   PRTime time
   5095 *     time for which status is to be determined
   5096 *   SECItem *encodedResponse
   5097 *     the DER encoded bytes of the OCSP response
   5098 *   void *pwArg
   5099 *     argument for password prompting, if needed
   5100 * RETURN:
   5101 *   SECSuccess if the cert was found in the cache, or if the OCSP response was
   5102 *   found to be valid and inserted into the cache. SECFailure otherwise.
   5103 */
   5104 SECStatus
   5105 CERT_CacheOCSPResponseFromSideChannel(CERTCertDBHandle *handle,
   5106                                      CERTCertificate *cert,
   5107                                      PRTime time,
   5108                                      const SECItem *encodedResponse,
   5109                                      void *pwArg)
   5110 {
   5111    CERTOCSPCertID *certID = NULL;
   5112    PRBool certIDWasConsumed = PR_FALSE;
   5113    SECStatus rv = SECFailure;
   5114    SECStatus rvOcsp = SECFailure;
   5115    SECErrorCodes dummy_error_code; /* we ignore this */
   5116    CERTOCSPResponse *decodedResponse = NULL;
   5117    CERTOCSPSingleResponse *singleResponse = NULL;
   5118    OCSPFreshness freshness;
   5119 
   5120    /* The OCSP cache can be in three states regarding this certificate:
   5121     *    + Good (cached, timely, 'good' response, or revoked in the future)
   5122     *    + Revoked (cached, timely, but doesn't fit in the last category)
   5123     *    + Miss (no knowledge)
   5124     *
   5125     * Likewise, the side-channel information can be
   5126     *    + Good (timely, 'good' response, or revoked in the future)
   5127     *    + Revoked (timely, but doesn't fit in the last category)
   5128     *    + Invalid (bad syntax, bad signature, not timely etc)
   5129     *
   5130     * The common case is that the cache result is Good and so is the
   5131     * side-channel information. We want to save processing time in this case
   5132     * so we say that any time we see a Good result from the cache we return
   5133     * early.
   5134     *
   5135     *                       Cache result
   5136     *      | Good             Revoked               Miss
   5137     *   ---+--------------------------------------------
   5138     *    G |  noop           Cache more           Cache it
   5139     * S    |                 recent result
   5140     * i    |
   5141     * d    |
   5142     * e    |
   5143     *    R |  noop           Cache more           Cache it
   5144     * C    |                 recent result
   5145     * h    |
   5146     * a    |
   5147     * n    |
   5148     * n  I |  noop           Noop                  Noop
   5149     * e    |
   5150     * l    |
   5151     *
   5152     * When we fetch from the network we might choose to cache a negative
   5153     * result when the response is invalid. This saves us hammering, uselessly,
   5154     * at a broken responder. However, side channels are commonly attacker
   5155     * controlled and so we must not cache a negative result for an Invalid
   5156     * side channel.
   5157     */
   5158 
   5159    if (!cert || !encodedResponse) {
   5160        PORT_SetError(SEC_ERROR_INVALID_ARGS);
   5161        return SECFailure;
   5162    }
   5163    certID = CERT_CreateOCSPCertID(cert, time);
   5164    if (!certID)
   5165        return SECFailure;
   5166 
   5167    /* We pass PR_TRUE for ignoreGlobalOcspFailureSetting so that a cached
   5168     * error entry is not interpreted as being a 'Good' entry here.
   5169     */
   5170    rv = ocsp_GetCachedOCSPResponseStatus(
   5171        certID, time, PR_TRUE, /* ignoreGlobalOcspFailureSetting */
   5172        &rvOcsp, &dummy_error_code, &freshness);
   5173    if (rv == SECSuccess && rvOcsp == SECSuccess && freshness == ocspFresh) {
   5174        /* The cached value is good. We don't want to waste time validating
   5175         * this OCSP response. This is the first column in the table above. */
   5176        CERT_DestroyOCSPCertID(certID);
   5177        return rv;
   5178    }
   5179 
   5180    /* The logic for caching the more recent response is handled in
   5181     * ocsp_CacheSingleResponse. */
   5182 
   5183    rv = ocsp_GetDecodedVerifiedSingleResponseForID(handle, certID, cert,
   5184                                                    time, pwArg,
   5185                                                    encodedResponse,
   5186                                                    &decodedResponse,
   5187                                                    &singleResponse);
   5188    if (rv == SECSuccess) {
   5189        rvOcsp = ocsp_SingleResponseCertHasGoodStatus(singleResponse, time);
   5190        /* Cache any valid singleResponse, regardless of status. */
   5191        ocsp_CacheSingleResponse(certID, singleResponse, &certIDWasConsumed);
   5192    }
   5193    if (decodedResponse) {
   5194        CERT_DestroyOCSPResponse(decodedResponse);
   5195    }
   5196    if (!certIDWasConsumed) {
   5197        CERT_DestroyOCSPCertID(certID);
   5198    }
   5199    return rv == SECSuccess ? rvOcsp : rv;
   5200 }
   5201 
   5202 /*
   5203 * Status in *certIDWasConsumed will always be correct, regardless of
   5204 * return value.
   5205 */
   5206 static SECStatus
   5207 ocsp_GetOCSPStatusFromNetwork(CERTCertDBHandle *handle,
   5208                              CERTOCSPCertID *certID,
   5209                              CERTCertificate *cert,
   5210                              PRTime time,
   5211                              void *pwArg,
   5212                              PRBool *certIDWasConsumed,
   5213                              SECStatus *rv_ocsp)
   5214 {
   5215    char *location = NULL;
   5216    PRBool locationIsDefault;
   5217    SECItem *encodedResponse = NULL;
   5218    CERTOCSPRequest *request = NULL;
   5219    SECStatus rv = SECFailure;
   5220 
   5221    CERTOCSPResponse *decodedResponse = NULL;
   5222    CERTOCSPSingleResponse *singleResponse = NULL;
   5223    enum { stageGET,
   5224           stagePOST } currentStage;
   5225    PRBool retry = PR_FALSE;
   5226 
   5227    if (!certIDWasConsumed || !rv_ocsp) {
   5228        PORT_SetError(SEC_ERROR_INVALID_ARGS);
   5229        return SECFailure;
   5230    }
   5231    *certIDWasConsumed = PR_FALSE;
   5232    *rv_ocsp = SECFailure;
   5233 
   5234    if (!OCSP_Global.monitor) {
   5235        PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
   5236        return SECFailure;
   5237    }
   5238    PR_EnterMonitor(OCSP_Global.monitor);
   5239    if (OCSP_Global.forcePost) {
   5240        currentStage = stagePOST;
   5241    } else {
   5242        currentStage = stageGET;
   5243    }
   5244    PR_ExitMonitor(OCSP_Global.monitor);
   5245 
   5246    /*
   5247     * The first thing we need to do is find the location of the responder.
   5248     * This will be the value of the default responder (if enabled), else
   5249     * it will come out of the AIA extension in the cert (if present).
   5250     * If we have no such location, then this cert does not "deserve" to
   5251     * be checked -- that is, we consider it a success and just return.
   5252     * The way we tell that is by looking at the error number to see if
   5253     * the problem was no AIA extension was found; any other error was
   5254     * a true failure that we unfortunately have to treat as an overall
   5255     * failure here.
   5256     */
   5257    location = ocsp_GetResponderLocation(handle, cert, PR_TRUE,
   5258                                         &locationIsDefault);
   5259    if (location == NULL) {
   5260        int err = PORT_GetError();
   5261        if (err == SEC_ERROR_EXTENSION_NOT_FOUND ||
   5262            err == SEC_ERROR_CERT_BAD_ACCESS_LOCATION) {
   5263            PORT_SetError(0);
   5264            *rv_ocsp = SECSuccess;
   5265            return SECSuccess;
   5266        }
   5267        return SECFailure;
   5268    }
   5269 
   5270    /*
   5271     * XXX In the fullness of time, we will want/need to handle a
   5272     * certificate chain.  This will be done either when a new parameter
   5273     * tells us to, or some configuration variable tells us to.  In any
   5274     * case, handling it is complicated because we may need to send as
   5275     * many requests (and receive as many responses) as we have certs
   5276     * in the chain.  If we are going to talk to a default responder,
   5277     * and we only support one default responder, we can put all of the
   5278     * certs together into one request.  Otherwise, we must break them up
   5279     * into multiple requests.  (Even if all of the requests will go to
   5280     * the same location, the signature on each response will be different,
   5281     * because each issuer is different.  Carefully read the OCSP spec
   5282     * if you do not understand this.)
   5283     */
   5284 
   5285    /*
   5286     * XXX If/when signing of requests is supported, that second NULL
   5287     * should be changed to be the signer certificate.  Not sure if that
   5288     * should be passed into this function or retrieved via some operation
   5289     * on the handle/context.
   5290     */
   5291 
   5292    do {
   5293        const char *method;
   5294        PRBool validResponseWithAccurateInfo = PR_FALSE;
   5295        retry = PR_FALSE;
   5296        *rv_ocsp = SECFailure;
   5297 
   5298        if (currentStage == stageGET) {
   5299            method = "GET";
   5300        } else {
   5301            PORT_Assert(currentStage == stagePOST);
   5302            method = "POST";
   5303        }
   5304 
   5305        encodedResponse =
   5306            ocsp_GetEncodedOCSPResponseForSingleCert(NULL, certID, cert,
   5307                                                     location, method,
   5308                                                     time, locationIsDefault,
   5309                                                     pwArg, &request);
   5310 
   5311        if (encodedResponse) {
   5312            rv = ocsp_GetDecodedVerifiedSingleResponseForID(handle, certID, cert,
   5313                                                            time, pwArg,
   5314                                                            encodedResponse,
   5315                                                            &decodedResponse,
   5316                                                            &singleResponse);
   5317            if (rv == SECSuccess) {
   5318                switch (singleResponse->certStatus->certStatusType) {
   5319                    case ocspCertStatus_good:
   5320                    case ocspCertStatus_revoked:
   5321                        validResponseWithAccurateInfo = PR_TRUE;
   5322                        break;
   5323                    default:
   5324                        break;
   5325                }
   5326                *rv_ocsp = ocsp_SingleResponseCertHasGoodStatus(singleResponse, time);
   5327            }
   5328        }
   5329 
   5330        if (currentStage == stageGET) {
   5331            /* only accept GET response if good or revoked */
   5332            if (validResponseWithAccurateInfo) {
   5333                ocsp_CacheSingleResponse(certID, singleResponse,
   5334                                         certIDWasConsumed);
   5335            } else {
   5336                retry = PR_TRUE;
   5337                currentStage = stagePOST;
   5338            }
   5339        } else {
   5340            /* cache the POST respone, regardless of status */
   5341            if (!singleResponse) {
   5342                cert_RememberOCSPProcessingFailure(certID, certIDWasConsumed);
   5343            } else {
   5344                ocsp_CacheSingleResponse(certID, singleResponse,
   5345                                         certIDWasConsumed);
   5346            }
   5347        }
   5348 
   5349        if (encodedResponse) {
   5350            SECITEM_FreeItem(encodedResponse, PR_TRUE);
   5351            encodedResponse = NULL;
   5352        }
   5353        if (request) {
   5354            CERT_DestroyOCSPRequest(request);
   5355            request = NULL;
   5356        }
   5357        if (decodedResponse) {
   5358            CERT_DestroyOCSPResponse(decodedResponse);
   5359            decodedResponse = NULL;
   5360        }
   5361        singleResponse = NULL;
   5362 
   5363    } while (retry);
   5364 
   5365    PORT_Free(location);
   5366    return rv;
   5367 }
   5368 
   5369 /*
   5370 * FUNCTION: ocsp_GetDecodedVerifiedSingleResponseForID
   5371 *   This function decodes an OCSP response and checks for a valid response
   5372 *   concerning the given certificate.
   5373 *
   5374 *   Note: a 'valid' response is one that parses successfully, is not an OCSP
   5375 *   exception (see RFC 2560 Section 2.3), is correctly signed and is current.
   5376 *   A 'good' response is a valid response that attests that the certificate
   5377 *   is not currently revoked (see RFC 2560 Section 2.2).
   5378 *
   5379 * INPUTS:
   5380 *   CERTCertDBHandle *handle
   5381 *     certificate DB of the cert that is being checked
   5382 *   CERTOCSPCertID *certID
   5383 *     the cert ID corresponding to |cert|
   5384 *   CERTCertificate *cert
   5385 *     the certificate being checked
   5386 *   PRTime time
   5387 *     time for which status is to be determined
   5388 *   void *pwArg
   5389 *     the opaque argument to the password prompting function.
   5390 *   SECItem *encodedResponse
   5391 *     the DER encoded bytes of the OCSP response
   5392 *   CERTOCSPResponse **pDecodedResponse
   5393 *     (output) The caller must ALWAYS check for this output parameter,
   5394 *     and if it's non-null, must destroy it using CERT_DestroyOCSPResponse.
   5395 *   CERTOCSPSingleResponse **pSingle
   5396 *     (output) on success, this points to the single response that corresponds
   5397 *     to the certID parameter. Points to the inside of pDecodedResponse.
   5398 *     It isn't a copy, don't free it.
   5399 * RETURN:
   5400 *   SECSuccess iff the response is valid.
   5401 */
   5402 static SECStatus
   5403 ocsp_GetDecodedVerifiedSingleResponseForID(CERTCertDBHandle *handle,
   5404                                           CERTOCSPCertID *certID,
   5405                                           CERTCertificate *cert,
   5406                                           PRTime time,
   5407                                           void *pwArg,
   5408                                           const SECItem *encodedResponse,
   5409                                           CERTOCSPResponse **pDecodedResponse,
   5410                                           CERTOCSPSingleResponse **pSingle)
   5411 {
   5412    CERTCertificate *signerCert = NULL;
   5413    CERTCertificate *issuerCert = NULL;
   5414    SECStatus rv = SECFailure;
   5415 
   5416    if (!pSingle || !pDecodedResponse) {
   5417        return SECFailure;
   5418    }
   5419    *pSingle = NULL;
   5420    *pDecodedResponse = CERT_DecodeOCSPResponse(encodedResponse);
   5421    if (!*pDecodedResponse) {
   5422        return SECFailure;
   5423    }
   5424 
   5425    /*
   5426     * Okay, we at least have a response that *looks* like a response!
   5427     * Now see if the overall response status value is good or not.
   5428     * If not, we set an error and give up.  (It means that either the
   5429     * server had a problem, or it didn't like something about our
   5430     * request.  Either way there is nothing to do but give up.)
   5431     * Otherwise, we continue to find the actual per-cert status
   5432     * in the response.
   5433     */
   5434    if (CERT_GetOCSPResponseStatus(*pDecodedResponse) != SECSuccess) {
   5435        goto loser;
   5436    }
   5437 
   5438    /*
   5439     * If we've made it this far, we expect a response with a good signature.
   5440     * So, check for that.
   5441     */
   5442    issuerCert = CERT_FindCertIssuer(cert, time, certUsageAnyCA);
   5443    rv = CERT_VerifyOCSPResponseSignature(*pDecodedResponse, handle, pwArg,
   5444                                          &signerCert, issuerCert);
   5445    if (rv != SECSuccess) {
   5446        goto loser;
   5447    }
   5448 
   5449    PORT_Assert(signerCert != NULL); /* internal consistency check */
   5450    /* XXX probably should set error, return failure if signerCert is null */
   5451 
   5452    /*
   5453     * Again, we are only doing one request for one cert.
   5454     * XXX When we handle cert chains, the following code will obviously
   5455     * have to be modified, in coordation with the code above that will
   5456     * have to determine how to make multiple requests, etc.
   5457     */
   5458    rv = ocsp_GetVerifiedSingleResponseForCertID(handle, *pDecodedResponse, certID,
   5459                                                 signerCert, time, pSingle);
   5460 loser:
   5461    if (issuerCert != NULL)
   5462        CERT_DestroyCertificate(issuerCert);
   5463    if (signerCert != NULL)
   5464        CERT_DestroyCertificate(signerCert);
   5465    return rv;
   5466 }
   5467 
   5468 /*
   5469 * FUNCTION: ocsp_CacheSingleResponse
   5470 *   This function requires that the caller has checked that the response
   5471 *   is valid and verified.
   5472 *   The (positive or negative) valid response will be used to update the cache.
   5473 * INPUTS:
   5474 *   CERTOCSPCertID *certID
   5475 *     the cert ID corresponding to |cert|
   5476 *   PRBool *certIDWasConsumed
   5477 *     (output) on return, this is true iff |certID| was consumed by this
   5478 *     function.
   5479 */
   5480 void
   5481 ocsp_CacheSingleResponse(CERTOCSPCertID *certID,
   5482                         CERTOCSPSingleResponse *single,
   5483                         PRBool *certIDWasConsumed)
   5484 {
   5485    if (single != NULL) {
   5486        PR_EnterMonitor(OCSP_Global.monitor);
   5487        if (OCSP_Global.maxCacheEntries >= 0) {
   5488            ocsp_CreateOrUpdateCacheEntry(&OCSP_Global.cache, certID, single,
   5489                                          certIDWasConsumed);
   5490            /* ignore cache update failures */
   5491        }
   5492        PR_ExitMonitor(OCSP_Global.monitor);
   5493    }
   5494 }
   5495 
   5496 SECStatus
   5497 ocsp_GetVerifiedSingleResponseForCertID(CERTCertDBHandle *handle,
   5498                                        CERTOCSPResponse *response,
   5499                                        CERTOCSPCertID *certID,
   5500                                        CERTCertificate *signerCert,
   5501                                        PRTime time,
   5502                                        CERTOCSPSingleResponse
   5503                                            **pSingleResponse)
   5504 {
   5505    SECStatus rv;
   5506    ocspResponseData *responseData;
   5507    PRTime producedAt;
   5508    CERTOCSPSingleResponse *single;
   5509 
   5510    /*
   5511     * The ResponseData part is the real guts of the response.
   5512     */
   5513    responseData = ocsp_GetResponseData(response, NULL);
   5514    if (responseData == NULL) {
   5515        rv = SECFailure;
   5516        goto loser;
   5517    }
   5518 
   5519    /*
   5520     * There is one producedAt time for the entire response (and a separate
   5521     * thisUpdate time for each individual single response).  We need to
   5522     * compare them, so get the overall time to pass into the check of each
   5523     * single response.
   5524     */
   5525    rv = DER_GeneralizedTimeToTime(&producedAt, &responseData->producedAt);
   5526    if (rv != SECSuccess)
   5527        goto loser;
   5528 
   5529    single = ocsp_GetSingleResponseForCertID(responseData->responses,
   5530                                             handle, certID);
   5531    if (single == NULL) {
   5532        rv = SECFailure;
   5533        goto loser;
   5534    }
   5535 
   5536    rv = ocsp_VerifySingleResponse(single, handle, signerCert, producedAt);
   5537    if (rv != SECSuccess)
   5538        goto loser;
   5539    *pSingleResponse = single;
   5540 
   5541 loser:
   5542    return rv;
   5543 }
   5544 
   5545 SECStatus
   5546 CERT_GetOCSPStatusForCertID(CERTCertDBHandle *handle,
   5547                            CERTOCSPResponse *response,
   5548                            CERTOCSPCertID *certID,
   5549                            CERTCertificate *signerCert,
   5550                            PRTime time)
   5551 {
   5552    /*
   5553     * We do not update the cache, because:
   5554     *
   5555     * CERT_GetOCSPStatusForCertID is an old exported API that was introduced
   5556     * before the OCSP cache got implemented.
   5557     *
   5558     * The implementation of helper function cert_ProcessOCSPResponse
   5559     * requires the ability to transfer ownership of the the given certID to
   5560     * the cache. The external API doesn't allow us to prevent the caller from
   5561     * destroying the certID. We don't have the original certificate available,
   5562     * therefore we are unable to produce another certID object (that could
   5563     * be stored in the cache).
   5564     *
   5565     * Should we ever implement code to produce a deep copy of certID,
   5566     * then this could be changed to allow updating the cache.
   5567     * The duplication would have to be done in
   5568     * cert_ProcessOCSPResponse, if the out parameter to indicate
   5569     * a transfer of ownership is NULL.
   5570     */
   5571    return cert_ProcessOCSPResponse(handle, response, certID,
   5572                                    signerCert, time,
   5573                                    NULL, NULL);
   5574 }
   5575 
   5576 /*
   5577 * The first 5 parameters match the definition of CERT_GetOCSPStatusForCertID.
   5578 */
   5579 SECStatus
   5580 cert_ProcessOCSPResponse(CERTCertDBHandle *handle,
   5581                         CERTOCSPResponse *response,
   5582                         CERTOCSPCertID *certID,
   5583                         CERTCertificate *signerCert,
   5584                         PRTime time,
   5585                         PRBool *certIDWasConsumed,
   5586                         SECStatus *cacheUpdateStatus)
   5587 {
   5588    SECStatus rv;
   5589    SECStatus rv_cache = SECSuccess;
   5590    CERTOCSPSingleResponse *single = NULL;
   5591 
   5592    rv = ocsp_GetVerifiedSingleResponseForCertID(handle, response, certID,
   5593                                                 signerCert, time, &single);
   5594    if (rv == SECSuccess) {
   5595        /*
   5596         * Check whether the status says revoked, and if so
   5597         * how that compares to the time value passed into this routine.
   5598         */
   5599        rv = ocsp_SingleResponseCertHasGoodStatus(single, time);
   5600    }
   5601 
   5602    if (certIDWasConsumed) {
   5603        /*
   5604         * We don't have copy-of-certid implemented. In order to update
   5605         * the cache, the caller must supply an out variable
   5606         * certIDWasConsumed, allowing us to return ownership status.
   5607         */
   5608 
   5609        PR_EnterMonitor(OCSP_Global.monitor);
   5610        if (OCSP_Global.maxCacheEntries >= 0) {
   5611            /* single == NULL means: remember response failure */
   5612            rv_cache =
   5613                ocsp_CreateOrUpdateCacheEntry(&OCSP_Global.cache, certID,
   5614                                              single, certIDWasConsumed);
   5615        }
   5616        PR_ExitMonitor(OCSP_Global.monitor);
   5617        if (cacheUpdateStatus) {
   5618            *cacheUpdateStatus = rv_cache;
   5619        }
   5620    }
   5621 
   5622    return rv;
   5623 }
   5624 
   5625 SECStatus
   5626 cert_RememberOCSPProcessingFailure(CERTOCSPCertID *certID,
   5627                                   PRBool *certIDWasConsumed)
   5628 {
   5629    SECStatus rv = SECSuccess;
   5630    PR_EnterMonitor(OCSP_Global.monitor);
   5631    if (OCSP_Global.maxCacheEntries >= 0) {
   5632        rv = ocsp_CreateOrUpdateCacheEntry(&OCSP_Global.cache, certID, NULL,
   5633                                           certIDWasConsumed);
   5634    }
   5635    PR_ExitMonitor(OCSP_Global.monitor);
   5636    return rv;
   5637 }
   5638 
   5639 /*
   5640 * Disable status checking and destroy related structures/data.
   5641 */
   5642 static SECStatus
   5643 ocsp_DestroyStatusChecking(CERTStatusConfig *statusConfig)
   5644 {
   5645    ocspCheckingContext *statusContext;
   5646 
   5647    /*
   5648     * Disable OCSP checking
   5649     */
   5650    statusConfig->statusChecker = NULL;
   5651 
   5652    statusContext = statusConfig->statusContext;
   5653    PORT_Assert(statusContext != NULL);
   5654    if (statusContext == NULL)
   5655        return SECFailure;
   5656 
   5657    if (statusContext->defaultResponderURI != NULL)
   5658        PORT_Free(statusContext->defaultResponderURI);
   5659    if (statusContext->defaultResponderNickname != NULL)
   5660        PORT_Free(statusContext->defaultResponderNickname);
   5661 
   5662    PORT_Free(statusContext);
   5663    statusConfig->statusContext = NULL;
   5664 
   5665    PORT_Free(statusConfig);
   5666 
   5667    return SECSuccess;
   5668 }
   5669 
   5670 /*
   5671 * FUNCTION: CERT_DisableOCSPChecking
   5672 *   Turns off OCSP checking for the given certificate database.
   5673 *   This routine disables OCSP checking.  Though it will return
   5674 *   SECFailure if OCSP checking is not enabled, it is "safe" to
   5675 *   call it that way and just ignore the return value, if it is
   5676 *   easier to just call it than to "remember" whether it is enabled.
   5677 * INPUTS:
   5678 *   CERTCertDBHandle *handle
   5679 *     Certificate database for which OCSP checking will be disabled.
   5680 * RETURN:
   5681 *   Returns SECFailure if an error occurred (usually means that OCSP
   5682 *   checking was not enabled or status contexts were not initialized --
   5683 *   error set will be SEC_ERROR_OCSP_NOT_ENABLED); SECSuccess otherwise.
   5684 */
   5685 SECStatus
   5686 CERT_DisableOCSPChecking(CERTCertDBHandle *handle)
   5687 {
   5688    CERTStatusConfig *statusConfig;
   5689    ocspCheckingContext *statusContext;
   5690 
   5691    if (handle == NULL) {
   5692        PORT_SetError(SEC_ERROR_INVALID_ARGS);
   5693        return SECFailure;
   5694    }
   5695 
   5696    statusConfig = CERT_GetStatusConfig(handle);
   5697    statusContext = ocsp_GetCheckingContext(handle);
   5698    if (statusContext == NULL)
   5699        return SECFailure;
   5700 
   5701    if (statusConfig->statusChecker != CERT_CheckOCSPStatus) {
   5702        /*
   5703         * Status configuration is present, but either not currently
   5704         * enabled or not for OCSP.
   5705         */
   5706        PORT_SetError(SEC_ERROR_OCSP_NOT_ENABLED);
   5707        return SECFailure;
   5708    }
   5709 
   5710    /* cache no longer necessary */
   5711    CERT_ClearOCSPCache();
   5712 
   5713    /*
   5714     * This is how we disable status checking.  Everything else remains
   5715     * in place in case we are enabled again.
   5716     */
   5717    statusConfig->statusChecker = NULL;
   5718 
   5719    return SECSuccess;
   5720 }
   5721 
   5722 /*
   5723 * Allocate and initialize the informational structures for status checking.
   5724 * This is done when some configuration of OCSP is being done or when OCSP
   5725 * checking is being turned on, whichever comes first.
   5726 */
   5727 static SECStatus
   5728 ocsp_InitStatusChecking(CERTCertDBHandle *handle)
   5729 {
   5730    CERTStatusConfig *statusConfig = NULL;
   5731    ocspCheckingContext *statusContext = NULL;
   5732 
   5733    PORT_Assert(CERT_GetStatusConfig(handle) == NULL);
   5734    if (CERT_GetStatusConfig(handle) != NULL) {
   5735        /* XXX or call statusConfig->statusDestroy and continue? */
   5736        return SECFailure;
   5737    }
   5738 
   5739    statusConfig = PORT_ZNew(CERTStatusConfig);
   5740    if (statusConfig == NULL)
   5741        goto loser;
   5742 
   5743    statusContext = PORT_ZNew(ocspCheckingContext);
   5744    if (statusContext == NULL)
   5745        goto loser;
   5746 
   5747    statusConfig->statusDestroy = ocsp_DestroyStatusChecking;
   5748    statusConfig->statusContext = statusContext;
   5749 
   5750    CERT_SetStatusConfig(handle, statusConfig);
   5751 
   5752    return SECSuccess;
   5753 
   5754 loser:
   5755    if (statusConfig != NULL)
   5756        PORT_Free(statusConfig);
   5757    return SECFailure;
   5758 }
   5759 
   5760 /*
   5761 * FUNCTION: CERT_EnableOCSPChecking
   5762 *   Turns on OCSP checking for the given certificate database.
   5763 * INPUTS:
   5764 *   CERTCertDBHandle *handle
   5765 *     Certificate database for which OCSP checking will be enabled.
   5766 * RETURN:
   5767 *   Returns SECFailure if an error occurred (likely only problem
   5768 *   allocating memory); SECSuccess otherwise.
   5769 */
   5770 SECStatus
   5771 CERT_EnableOCSPChecking(CERTCertDBHandle *handle)
   5772 {
   5773    CERTStatusConfig *statusConfig;
   5774 
   5775    SECStatus rv;
   5776 
   5777    if (handle == NULL) {
   5778        PORT_SetError(SEC_ERROR_INVALID_ARGS);
   5779        return SECFailure;
   5780    }
   5781 
   5782    statusConfig = CERT_GetStatusConfig(handle);
   5783    if (statusConfig == NULL) {
   5784        rv = ocsp_InitStatusChecking(handle);
   5785        if (rv != SECSuccess)
   5786            return rv;
   5787 
   5788        /* Get newly established value */
   5789        statusConfig = CERT_GetStatusConfig(handle);
   5790        PORT_Assert(statusConfig != NULL);
   5791    }
   5792 
   5793    /*
   5794     * Setting the checker function is what really enables the checking
   5795     * when each cert verification is done.
   5796     */
   5797    statusConfig->statusChecker = CERT_CheckOCSPStatus;
   5798 
   5799    return SECSuccess;
   5800 }
   5801 
   5802 /*
   5803 * FUNCTION: CERT_SetOCSPDefaultResponder
   5804 *   Specify the location and cert of the default responder.
   5805 *   If OCSP checking is already enabled *and* use of a default responder
   5806 *   is also already enabled, all OCSP checking from now on will go directly
   5807 *   to the specified responder.  If OCSP checking is not enabled, or if
   5808 *   it is but use of a default responder is not enabled, the information
   5809 *   will be recorded and take effect whenever both are enabled.
   5810 * INPUTS:
   5811 *   CERTCertDBHandle *handle
   5812 *     Cert database on which OCSP checking should use the default responder.
   5813 *   char *url
   5814 *     The location of the default responder (e.g. "http://foo.com:80/ocsp")
   5815 *     Note that the location will not be tested until the first attempt
   5816 *     to send a request there.
   5817 *   char *name
   5818 *     The nickname of the cert to trust (expected) to sign the OCSP responses.
   5819 *     If the corresponding cert cannot be found, SECFailure is returned.
   5820 * RETURN:
   5821 *   Returns SECFailure if an error occurred; SECSuccess otherwise.
   5822 *   The most likely error is that the cert for "name" could not be found
   5823 *   (probably SEC_ERROR_UNKNOWN_CERT).  Other errors are low-level (no memory,
   5824 *   bad database, etc.).
   5825 */
   5826 SECStatus
   5827 CERT_SetOCSPDefaultResponder(CERTCertDBHandle *handle,
   5828                             const char *url, const char *name)
   5829 {
   5830    CERTCertificate *cert;
   5831    ocspCheckingContext *statusContext;
   5832    char *url_copy = NULL;
   5833    char *name_copy = NULL;
   5834    SECStatus rv;
   5835 
   5836    if (handle == NULL || url == NULL || name == NULL) {
   5837        /*
   5838         * XXX When interface is exported, probably want better errors;
   5839         * perhaps different one for each parameter.
   5840         */
   5841        PORT_SetError(SEC_ERROR_INVALID_ARGS);
   5842        return SECFailure;
   5843    }
   5844 
   5845    /*
   5846     * Find the certificate for the specified nickname.  Do this first
   5847     * because it seems the most likely to fail.
   5848     *
   5849     * XXX Shouldn't need that cast if the FindCertByNickname interface
   5850     * used const to convey that it does not modify the name.  Maybe someday.
   5851     */
   5852    cert = CERT_FindCertByNickname(handle, (char *)name);
   5853    if (cert == NULL) {
   5854        /*
   5855         * look for the cert on an external token.
   5856         */
   5857        cert = PK11_FindCertFromNickname((char *)name, NULL);
   5858    }
   5859    if (cert == NULL)
   5860        return SECFailure;
   5861 
   5862    /*
   5863     * Make a copy of the url and nickname.
   5864     */
   5865    url_copy = PORT_Strdup(url);
   5866    name_copy = PORT_Strdup(name);
   5867    if (url_copy == NULL || name_copy == NULL) {
   5868        rv = SECFailure;
   5869        goto loser;
   5870    }
   5871 
   5872    statusContext = ocsp_GetCheckingContext(handle);
   5873 
   5874    /*
   5875     * Allocate and init the context if it doesn't already exist.
   5876     */
   5877    if (statusContext == NULL) {
   5878        rv = ocsp_InitStatusChecking(handle);
   5879        if (rv != SECSuccess)
   5880            goto loser;
   5881 
   5882        statusContext = ocsp_GetCheckingContext(handle);
   5883        PORT_Assert(statusContext != NULL); /* extreme paranoia */
   5884    }
   5885 
   5886    /*
   5887     * Note -- we do not touch the status context until after all of
   5888     * the steps which could cause errors.  If something goes wrong,
   5889     * we want to leave things as they were.
   5890     */
   5891 
   5892    /*
   5893     * Get rid of old url and name if there.
   5894     */
   5895    if (statusContext->defaultResponderNickname != NULL)
   5896        PORT_Free(statusContext->defaultResponderNickname);
   5897    if (statusContext->defaultResponderURI != NULL)
   5898        PORT_Free(statusContext->defaultResponderURI);
   5899 
   5900    /*
   5901     * And replace them with the new ones.
   5902     */
   5903    statusContext->defaultResponderURI = url_copy;
   5904    statusContext->defaultResponderNickname = name_copy;
   5905 
   5906    /*
   5907     * If there was already a cert in place, get rid of it and replace it.
   5908     * Otherwise, we are not currently enabled, so we don't want to save it;
   5909     * it will get re-found and set whenever use of a default responder is
   5910     * enabled.
   5911     */
   5912    if (statusContext->defaultResponderCert != NULL) {
   5913        CERT_DestroyCertificate(statusContext->defaultResponderCert);
   5914        statusContext->defaultResponderCert = cert;
   5915        /*OCSP enabled, switching responder: clear cache*/
   5916        CERT_ClearOCSPCache();
   5917    } else {
   5918        PORT_Assert(statusContext->useDefaultResponder == PR_FALSE);
   5919        CERT_DestroyCertificate(cert);
   5920        /*OCSP currently not enabled, no need to clear cache*/
   5921    }
   5922 
   5923    return SECSuccess;
   5924 
   5925 loser:
   5926    CERT_DestroyCertificate(cert);
   5927    if (url_copy != NULL)
   5928        PORT_Free(url_copy);
   5929    if (name_copy != NULL)
   5930        PORT_Free(name_copy);
   5931    return rv;
   5932 }
   5933 
   5934 /*
   5935 * FUNCTION: CERT_EnableOCSPDefaultResponder
   5936 *   Turns on use of a default responder when OCSP checking.
   5937 *   If OCSP checking is already enabled, this will make subsequent checks
   5938 *   go directly to the default responder.  (The location of the responder
   5939 *   and the nickname of the responder cert must already be specified.)
   5940 *   If OCSP checking is not enabled, this will be recorded and take effect
   5941 *   whenever it is enabled.
   5942 * INPUTS:
   5943 *   CERTCertDBHandle *handle
   5944 *     Cert database on which OCSP checking should use the default responder.
   5945 * RETURN:
   5946 *   Returns SECFailure if an error occurred; SECSuccess otherwise.
   5947 *   No errors are especially likely unless the caller did not previously
   5948 *   perform a successful call to SetOCSPDefaultResponder (in which case
   5949 *   the error set will be SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER).
   5950 */
   5951 SECStatus
   5952 CERT_EnableOCSPDefaultResponder(CERTCertDBHandle *handle)
   5953 {
   5954    ocspCheckingContext *statusContext;
   5955    CERTCertificate *cert;
   5956    SECStatus rv;
   5957    SECCertificateUsage usage;
   5958 
   5959    if (handle == NULL) {
   5960        PORT_SetError(SEC_ERROR_INVALID_ARGS);
   5961        return SECFailure;
   5962    }
   5963 
   5964    statusContext = ocsp_GetCheckingContext(handle);
   5965 
   5966    if (statusContext == NULL) {
   5967        /*
   5968         * Strictly speaking, the error already set is "correct",
   5969         * but cover over it with one more helpful in this context.
   5970         */
   5971        PORT_SetError(SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER);
   5972        return SECFailure;
   5973    }
   5974 
   5975    if (statusContext->defaultResponderURI == NULL) {
   5976        PORT_SetError(SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER);
   5977        return SECFailure;
   5978    }
   5979 
   5980    if (statusContext->defaultResponderNickname == NULL) {
   5981        PORT_SetError(SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER);
   5982        return SECFailure;
   5983    }
   5984 
   5985    /*
   5986     * Find the cert for the nickname.
   5987     */
   5988    cert = CERT_FindCertByNickname(handle,
   5989                                   statusContext->defaultResponderNickname);
   5990    if (cert == NULL) {
   5991        cert = PK11_FindCertFromNickname(statusContext->defaultResponderNickname,
   5992                                         NULL);
   5993    }
   5994    /*
   5995     * We should never have trouble finding the cert, because its
   5996     * existence should have been proven by SetOCSPDefaultResponder.
   5997     */
   5998    PORT_Assert(cert != NULL);
   5999    if (cert == NULL)
   6000        return SECFailure;
   6001 
   6002    /*
   6003     * Supplied cert should at least have  a signing capability in order for us
   6004     * to use it as a trusted responder cert. Ability to sign is guaranteed  if
   6005     * cert is validated to have any set of the usages below.
   6006     */
   6007    rv = CERT_VerifyCertificateNow(handle, cert, PR_TRUE,
   6008                                   certificateUsageCheckAllUsages,
   6009                                   NULL, &usage);
   6010    if (rv != SECSuccess || (usage & (certificateUsageSSLClient | certificateUsageSSLServer | certificateUsageSSLServerWithStepUp | certificateUsageEmailSigner | certificateUsageObjectSigner | certificateUsageStatusResponder | certificateUsageSSLCA)) == 0) {
   6011        PORT_SetError(SEC_ERROR_OCSP_RESPONDER_CERT_INVALID);
   6012        return SECFailure;
   6013    }
   6014 
   6015    /*
   6016     * And hang onto it.
   6017     */
   6018    statusContext->defaultResponderCert = cert;
   6019 
   6020    /* we don't allow a mix of cache entries from different responders */
   6021    CERT_ClearOCSPCache();
   6022 
   6023    /*
   6024     * Finally, record the fact that we now have a default responder enabled.
   6025     */
   6026    statusContext->useDefaultResponder = PR_TRUE;
   6027    return SECSuccess;
   6028 }
   6029 
   6030 /*
   6031 * FUNCTION: CERT_DisableOCSPDefaultResponder
   6032 *   Turns off use of a default responder when OCSP checking.
   6033 *   (Does nothing if use of a default responder is not enabled.)
   6034 * INPUTS:
   6035 *   CERTCertDBHandle *handle
   6036 *     Cert database on which OCSP checking should stop using a default
   6037 *     responder.
   6038 * RETURN:
   6039 *   Returns SECFailure if an error occurred; SECSuccess otherwise.
   6040 *   Errors very unlikely (like random memory corruption...).
   6041 */
   6042 SECStatus
   6043 CERT_DisableOCSPDefaultResponder(CERTCertDBHandle *handle)
   6044 {
   6045    CERTStatusConfig *statusConfig;
   6046    ocspCheckingContext *statusContext;
   6047    CERTCertificate *tmpCert;
   6048 
   6049    if (handle == NULL) {
   6050        PORT_SetError(SEC_ERROR_INVALID_ARGS);
   6051        return SECFailure;
   6052    }
   6053 
   6054    statusConfig = CERT_GetStatusConfig(handle);
   6055    if (statusConfig == NULL)
   6056        return SECSuccess;
   6057 
   6058    statusContext = ocsp_GetCheckingContext(handle);
   6059    PORT_Assert(statusContext != NULL);
   6060    if (statusContext == NULL)
   6061        return SECFailure;
   6062 
   6063    tmpCert = statusContext->defaultResponderCert;
   6064    if (tmpCert) {
   6065        statusContext->defaultResponderCert = NULL;
   6066        CERT_DestroyCertificate(tmpCert);
   6067        /* we don't allow a mix of cache entries from different responders */
   6068        CERT_ClearOCSPCache();
   6069    }
   6070 
   6071    /*
   6072     * Finally, record the fact.
   6073     */
   6074    statusContext->useDefaultResponder = PR_FALSE;
   6075    return SECSuccess;
   6076 }
   6077 
   6078 SECStatus
   6079 CERT_ForcePostMethodForOCSP(PRBool forcePost)
   6080 {
   6081    if (!OCSP_Global.monitor) {
   6082        PORT_SetError(SEC_ERROR_NOT_INITIALIZED);
   6083        return SECFailure;
   6084    }
   6085 
   6086    PR_EnterMonitor(OCSP_Global.monitor);
   6087    OCSP_Global.forcePost = forcePost;
   6088    PR_ExitMonitor(OCSP_Global.monitor);
   6089 
   6090    return SECSuccess;
   6091 }
   6092 
   6093 SECStatus
   6094 CERT_GetOCSPResponseStatus(CERTOCSPResponse *response)
   6095 {
   6096    PORT_Assert(response);
   6097    if (response->statusValue == ocspResponse_successful)
   6098        return SECSuccess;
   6099 
   6100    switch (response->statusValue) {
   6101        case ocspResponse_malformedRequest:
   6102            PORT_SetError(SEC_ERROR_OCSP_MALFORMED_REQUEST);
   6103            break;
   6104        case ocspResponse_internalError:
   6105            PORT_SetError(SEC_ERROR_OCSP_SERVER_ERROR);
   6106            break;
   6107        case ocspResponse_tryLater:
   6108            PORT_SetError(SEC_ERROR_OCSP_TRY_SERVER_LATER);
   6109            break;
   6110        case ocspResponse_sigRequired:
   6111            /* XXX We *should* retry with a signature, if possible. */
   6112            PORT_SetError(SEC_ERROR_OCSP_REQUEST_NEEDS_SIG);
   6113            break;
   6114        case ocspResponse_unauthorized:
   6115            PORT_SetError(SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST);
   6116            break;
   6117        case ocspResponse_unused:
   6118        default:
   6119            PORT_SetError(SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS);
   6120            break;
   6121    }
   6122    return SECFailure;
   6123 }