Back to index

lightning-sunbird  0.9+nobinonly
Classes | Defines | Typedefs | Functions | Variables
ocsp.c File Reference
#include "prerror.h"
#include "prprf.h"
#include "plarena.h"
#include "prnetdb.h"
#include "seccomon.h"
#include "secitem.h"
#include "secoidt.h"
#include "secasn1.h"
#include "secder.h"
#include "cert.h"
#include "xconst.h"
#include "secerr.h"
#include "secoid.h"
#include "hasht.h"
#include "sechash.h"
#include "keyhi.h"
#include "cryptohi.h"
#include "ocsp.h"
#include "ocspti.h"
#include "genname.h"
#include "certxutl.h"
#include "pk11func.h"
#include <stdarg.h>
#include <plhash.h>

Go to the source code of this file.

Classes

struct  OCSPCacheItemStr
struct  OCSPCacheDataStr
struct  OCSPGlobalStruct
struct  ocspCheckingContextStr

Defines

#define DEFAULT_OCSP_CACHE_SIZE   1000
#define DEFAULT_MINIMUM_SECONDS_TO_NEXT_OCSP_FETCH_ATTEMPT   1*60*60L
#define DEFAULT_MAXIMUM_SECONDS_TO_NEXT_OCSP_FETCH_ATTEMPT   24*60*60L
#define MICROSECONDS_PER_SECOND   1000000L
#define OCSP_TRACE(msg)
#define OCSP_TRACE_TIME(msg, time)
#define OCSP_TRACE_CERT(cert)
#define OCSP_BUFSIZE   1024
#define AbortHttpDecode(error)
#define MAX_WANTED_OCSP_RESPONSE_LEN   64*1024
#define OCSP_ALLOWABLE_LAPSE_SECONDS   (24L * 60L * 60L)
#define OCSP_SLOP

Typedefs

typedef struct OCSPCacheItemStr
typedef struct OCSPCacheDataStr
typedef struct
ocspCheckingContextStr 
ocspCheckingContext

Functions

static SECItem * ocsp_GetEncodedOCSPResponseFromRequest (PRArenaPool *arena, CERTOCSPRequest *request, char *location, int64 time, PRBool addServiceLocator, void *pwArg, CERTOCSPRequest **pRequest)
static SECStatus ocsp_GetOCSPStatusFromNetwork (CERTCertDBHandle *handle, CERTOCSPCertID *certID, CERTCertificate *cert, int64 time, void *pwArg, PRBool *certIDWasConsumed, SECStatus *rv_ocsp)
static SECStatus ocsp_GetVerifiedSingleResponseForCertID (CERTCertDBHandle *handle, CERTOCSPResponse *response, CERTOCSPCertID *certID, CERTCertificate *signerCert, int64 time, CERTOCSPSingleResponse **pSingleResponse)
SECStatus SEC_RegisterDefaultHttpClient (const SEC_HttpClientFcn *fcnTable)
static PLHashNumber PR_CALLBACK ocsp_CacheKeyHashFunction (const void *key)
static PRIntn PR_CALLBACK ocsp_CacheKeyCompareFunction (const void *v1, const void *v2)
static SECStatus ocsp_CopyRevokedInfo (PRArenaPool *arena, ocspCertStatus *dest, ocspRevokedInfo *src)
static SECStatus ocsp_CopyCertStatus (PRArenaPool *arena, ocspCertStatus *dest, ocspCertStatus *src)
static void ocsp_AddCacheItemToLinkedList (OCSPCacheData *cache, OCSPCacheItem *new_most_recent)
static void ocsp_RemoveCacheItemFromLinkedList (OCSPCacheData *cache, OCSPCacheItem *item)
static void ocsp_MakeCacheEntryMostRecent (OCSPCacheData *cache, OCSPCacheItem *new_most_recent)
static PRBool ocsp_IsCacheDisabled ()
static OCSPCacheItem * ocsp_FindCacheEntry (OCSPCacheData *cache, CERTOCSPCertID *certID)
static void ocsp_FreeCacheItem (OCSPCacheItem *item)
static void ocsp_RemoveCacheItem (OCSPCacheData *cache, OCSPCacheItem *item)
static void ocsp_CheckCacheSize (OCSPCacheData *cache)
SECStatus CERT_ClearOCSPCache ()
static SECStatus ocsp_CreateCacheItemAndConsumeCertID (OCSPCacheData *cache, CERTOCSPCertID *certID, OCSPCacheItem **pCacheItem)
static SECStatus ocsp_SetCacheItemResponse (OCSPCacheItem *item, const CERTOCSPSingleResponse *response)
static void ocsp_FreshenCacheItemNextFetchAttemptTime (OCSPCacheItem *cacheItem)
static PRBool ocsp_IsCacheItemFresh (OCSPCacheItem *cacheItem)
static SECStatus ocsp_CreateOrUpdateCacheEntry (OCSPCacheData *cache, CERTOCSPCertID *certID, CERTOCSPSingleResponse *single, PRBool *certIDWasConsumed)
SECStatus CERT_SetOCSPFailureMode (SEC_OcspFailureMode ocspFailureMode)
SECStatus CERT_OCSPCacheSettings (PRInt32 maxCacheEntries, PRUint32 minimumSecondsToNextFetchAttempt, PRUint32 maximumSecondsToNextFetchAttempt)
SECStatus OCSP_InitGlobal (void)
SECStatus OCSP_ShutdownCache (void)
static const SEC_HttpClientFcnGetRegisteredHttpClient ()
SECItem * CERT_EncodeOCSPRequest (PRArenaPool *arena, CERTOCSPRequest *request, void *pwArg)
CERTOCSPRequest * CERT_DecodeOCSPRequest (SECItem *src)
SECStatus CERT_DestroyOCSPCertID (CERTOCSPCertID *certID)
static SECItem * ocsp_DigestValue (PRArenaPool *arena, SECOidTag digestAlg, SECItem *fill, const SECItem *src)
SECItem * cert_GetSPKIDigest (PRArenaPool *arena, const CERTCertificate *cert, SECOidTag digestAlg, SECItem *fill)
static SECItem * cert_GetSubjectNameDigest (PRArenaPool *arena, const CERTCertificate *cert, SECOidTag digestAlg, SECItem *fill)
static CERTOCSPCertID * ocsp_CreateCertID (PRArenaPool *arena, CERTCertificate *cert, int64 time)
CERTOCSPCertID * CERT_CreateOCSPCertID (CERTCertificate *cert, int64 time)
void SetSingleReqExts (void *object, CERTCertExtension **exts)
static SECStatus ocsp_AddServiceLocatorExtension (ocspSingleRequest *singleRequest, CERTCertificate *cert)
static ocspSingleRequest ** ocsp_CreateSingleRequestList (PRArenaPool *arena, CERTCertList *certList, int64 time, PRBool includeLocator)
static ocspSingleRequest ** ocsp_CreateRequestFromCert (PRArenaPool *arena, CERTOCSPCertID *certID, CERTCertificate *singleCert, int64 time, PRBool includeLocator)
static CERTOCSPRequest * ocsp_prepareEmptyOCSPRequest ()
static CERTOCSPRequest * cert_CreateSingleCertOCSPRequest (CERTOCSPCertID *certID, CERTCertificate *singleCert, int64 time, PRBool addServiceLocator)
CERTOCSPRequest * CERT_CreateOCSPRequest (CERTCertList *certList, int64 time, PRBool addServiceLocator, CERTCertificate *signerCert)
void SetRequestExts (void *object, CERTCertExtension **exts)
SECStatus CERT_AddOCSPAcceptableResponses (CERTOCSPRequest *request, SECOidTag responseType0,...)
void CERT_DestroyOCSPRequest (CERTOCSPRequest *request)
static const SEC_ASN1Templateocsp_ResponderIDTemplateByType (ocspResponderIDType responderIDType)
static const SEC_ASN1Templateocsp_CertStatusTemplateByType (ocspCertStatusType certStatusType)
static ocspCertStatusType ocsp_CertStatusTypeByTag (int derTag)
static SECStatus ocsp_FinishDecodingSingleResponses (PRArenaPool *arena, CERTOCSPSingleResponse **responses)
static ocspResponderIDType ocsp_ResponderIDTypeByTag (int derTag)
static ocspBasicOCSPResponse * ocsp_DecodeBasicOCSPResponse (PRArenaPool *arena, SECItem *src)
static SECStatus ocsp_DecodeResponseBytes (PRArenaPool *arena, ocspResponseBytes *rbytes)
CERTOCSPResponse * CERT_DecodeOCSPResponse (SECItem *src)
static ocspResponseData * ocsp_GetResponseData (CERTOCSPResponse *response, SECItem **tbsResponseDataDER)
static ocspSignature * ocsp_GetResponseSignature (CERTOCSPResponse *response)
void CERT_DestroyOCSPResponse (CERTOCSPResponse *response)
static SECStatus ocsp_ParseURL (char *url, char **pHostname, PRUint16 *pPort, char **pPath)
static PRFileDescocsp_ConnectToHost (const char *host, PRUint16 port)
static PRFileDescocsp_SendEncodedRequest (char *location, SECItem *encodedRequest)
static int ocsp_read (PRFileDesc *fd, char *buf, int toread, PRIntervalTime timeout)
static SECItem * ocsp_GetEncodedResponse (PRArenaPool *arena, PRFileDesc *sock)
static SECItem * fetchOcspHttpClientV1 (PRArenaPool *arena, const SEC_HttpClientFcnV1 *hcv1, char *location, SECItem *encodedRequest)
SECItem * CERT_GetEncodedOCSPResponse (PRArenaPool *arena, CERTCertList *certList, char *location, int64 time, PRBool addServiceLocator, CERTCertificate *signerCert, void *pwArg, CERTOCSPRequest **pRequest)
static SECItem * ocsp_GetEncodedOCSPResponseForSingleCert (PRArenaPool *arena, CERTOCSPCertID *certID, CERTCertificate *singleCert, char *location, int64 time, PRBool addServiceLocator, void *pwArg, CERTOCSPRequest **pRequest)
static PRBool ocsp_CertIsOCSPDesignatedResponder (CERTCertificate *cert)
static PRBool ocsp_matchcert (SECItem *certIndex, CERTCertificate *testCert)
static PRBool ocsp_CertIsOCSPDefaultResponder (CERTCertDBHandle *handle, CERTCertificate *cert)
static CERTCertificate * ocsp_CertGetDefaultResponder (CERTCertDBHandle *handle, CERTOCSPCertID *certID)
SECStatus CERT_VerifyOCSPResponseSignature (CERTOCSPResponse *response, CERTCertDBHandle *handle, void *pwArg, CERTCertificate **pSignerCert, CERTCertificate *issuer)
static PRBool ocsp_CertIDsMatch (CERTCertDBHandle *handle, CERTOCSPCertID *requestCertID, CERTOCSPCertID *responseCertID)
static CERTOCSPSingleResponse * ocsp_GetSingleResponseForCertID (CERTOCSPSingleResponse **responses, CERTCertDBHandle *handle, CERTOCSPCertID *certID)
static ocspCheckingContextocsp_GetCheckingContext (CERTCertDBHandle *handle)
static PRBool ocsp_AuthorizedResponderForCertID (CERTCertDBHandle *handle, CERTCertificate *signerCert, CERTOCSPCertID *certID, int64 thisUpdate)
static PRBool ocsp_TimeIsRecent (int64 checkTime)
static SECStatus ocsp_VerifySingleResponse (CERTOCSPSingleResponse *single, CERTCertDBHandle *handle, CERTCertificate *signerCert, int64 producedAt)
char * CERT_GetOCSPAuthorityInfoAccessLocation (CERTCertificate *cert)
static char * ocsp_GetResponderLocation (CERTCertDBHandle *handle, CERTCertificate *cert, PRBool *isDefault)
static SECStatus ocsp_CertRevokedAfter (ocspRevokedInfo *revokedInfo, int64 time)
static SECStatus ocsp_CertHasGoodStatus (ocspCertStatus *status, int64 time)
static SECStatus ocsp_SingleResponseCertHasGoodStatus (CERTOCSPSingleResponse *single, int64 time)
static SECStatus ocsp_GetCachedOCSPResponseStatusIfFresh (CERTOCSPCertID *certID, int64 time, SECStatus *rv_ocsp)
SECStatus CERT_CheckOCSPStatus (CERTCertDBHandle *handle, CERTCertificate *cert, int64 time, void *pwArg)
SECStatus CERT_GetOCSPStatusForCertID (CERTCertDBHandle *handle, CERTOCSPResponse *response, CERTOCSPCertID *certID, CERTCertificate *signerCert, int64 time)
static SECStatus ocsp_DestroyStatusChecking (CERTStatusConfig *statusConfig)
SECStatus CERT_DisableOCSPChecking (CERTCertDBHandle *handle)
static SECStatus ocsp_InitStatusChecking (CERTCertDBHandle *handle)
SECStatus CERT_EnableOCSPChecking (CERTCertDBHandle *handle)
SECStatus CERT_SetOCSPDefaultResponder (CERTCertDBHandle *handle, const char *url, const char *name)
SECStatus CERT_EnableOCSPDefaultResponder (CERTCertDBHandle *handle)
SECStatus CERT_DisableOCSPDefaultResponder (CERTCertDBHandle *handle)
SECStatus CERT_GetOCSPResponseStatus (CERTOCSPResponse *response)

Variables

static struct OCSPGlobalStruct OCSP_Global
const SEC_ASN1Template ocsp_CertIDTemplate []
const SEC_ASN1Template ocsp_PointerToSignatureTemplate []
const SEC_ASN1Template ocsp_PointerToResponseBytesTemplate []
const SEC_ASN1Template ocsp_ResponseDataTemplate []
const SEC_ASN1Template ocsp_RevokedInfoTemplate []
const SEC_ASN1Template ocsp_SingleRequestTemplate []
const SEC_ASN1Template ocsp_SingleResponseTemplate []
const SEC_ASN1Template ocsp_TBSRequestTemplate []
static const SEC_ASN1Template ocsp_OCSPRequestTemplate []
static const SEC_ASN1Template ocsp_SignatureTemplate []
static const SEC_ASN1Template ocsp_OCSPResponseTemplate []
static const SEC_ASN1Template ocsp_ResponseBytesTemplate []
static const SEC_ASN1Template ocsp_BasicOCSPResponseTemplate []
static const SEC_ASN1Template ocsp_ResponderIDByNameTemplate []
static const SEC_ASN1Template ocsp_ResponderIDByKeyTemplate []
static const SEC_ASN1Template ocsp_ResponderIDOtherTemplate []
static const SEC_ASN1Template ocsp_ResponderIDDerNameTemplate []
static const SEC_ASN1Template ocsp_CertStatusGoodTemplate []
static const SEC_ASN1Template ocsp_CertStatusRevokedTemplate []
static const SEC_ASN1Template ocsp_CertStatusUnknownTemplate []
static const SEC_ASN1Template ocsp_CertStatusOtherTemplate []
static const SEC_ASN1Template ocsp_ServiceLocatorTemplate []
static PRUint32 ocspsloptime = OCSP_SLOP

Class Documentation

struct OCSPCacheItemStr

Definition at line 80 of file ocsp.c.

Collaboration diagram for OCSPCacheItemStr:
Class Members
CERTOCSPCertID * certID
ocspCertStatus certStatus
PRArenaPool * certStatusArena
PRPackedBool haveNextUpdate
PRPackedBool haveThisUpdate
OCSPCacheItem * lessRecent
OCSPCacheItem * moreRecent
PRTime nextFetchAttemptTime
PRTime nextUpdate
PRTime thisUpdate
struct OCSPCacheDataStr

Definition at line 102 of file ocsp.c.

Collaboration diagram for OCSPCacheDataStr:
Class Members
PLHashTable * entries
OCSPCacheItem * LRUitem
OCSPCacheItem * MRUitem
PRUint32 numberOfEntries
struct OCSPGlobalStruct

Definition at line 109 of file ocsp.c.

Collaboration diagram for OCSPGlobalStruct:
Class Members
OCSPCacheData cache
const SEC_HttpClientFcn * defaultHttpClientFcn
PRLock * lock
PRInt32 maxCacheEntries
PRUint32 maximumSecondsToNextFetchAttempt
PRUint32 minimumSecondsToNextFetchAttempt
PRMonitor * monitor
SEC_OcspFailureMode ocspFailureMode
struct ocspCheckingContextStr

Definition at line 921 of file ocsp.c.

Class Members
CERTCertificate * defaultResponderCert
char * defaultResponderNickname
char * defaultResponderURI
PRBool useDefaultResponder

Define Documentation

Value:
{ \
        if (inBuffer) \
            PORT_Free(inBuffer); \
        PORT_SetError(error); \
        return NULL; \
}

Definition at line 2923 of file ocsp.c.

Definition at line 74 of file ocsp.c.

Definition at line 73 of file ocsp.c.

Definition at line 72 of file ocsp.c.

Definition at line 3169 of file ocsp.c.

Definition at line 75 of file ocsp.c.

#define OCSP_ALLOWABLE_LAPSE_SECONDS   (24L * 60L * 60L)

Definition at line 4128 of file ocsp.c.

#define OCSP_BUFSIZE   1024

Definition at line 2921 of file ocsp.c.

Value:
(5L*60L) /* OCSP responses are allowed to be 5 minutes
                              in the future by default */

Definition at line 4147 of file ocsp.c.

Definition at line 151 of file ocsp.c.

Definition at line 153 of file ocsp.c.

#define OCSP_TRACE_TIME (   msg,
  time 
)

Definition at line 152 of file ocsp.c.


Typedef Documentation

typedef struct OCSPCacheDataStr

Definition at line 78 of file ocsp.c.

typedef struct OCSPCacheItemStr

Definition at line 77 of file ocsp.c.


Function Documentation

SECStatus CERT_AddOCSPAcceptableResponses ( CERTOCSPRequest *  request,
SECOidTag  responseType0,
  ... 
)

Definition at line 2036 of file ocsp.c.

{
    void *extHandle;
    va_list ap;
    int i, count;
    SECOidTag responseType;
    SECOidData *responseOid;
    SECItem **acceptableResponses = NULL;
    SECStatus rv = SECFailure;

    extHandle = request->tbsRequest->extensionHandle;
    if (extHandle == NULL) {
       extHandle = cert_StartExtensions(request, request->arena, SetRequestExts);
       if (extHandle == NULL)
           goto loser;
    }

    /* Count number of OIDS going into the extension value. */
    count = 1;
    if (responseType0 != SEC_OID_PKIX_OCSP_BASIC_RESPONSE) {
       va_start(ap, responseType0);
       do {
           count++;
           responseType = va_arg(ap, SECOidTag);
       } while (responseType != SEC_OID_PKIX_OCSP_BASIC_RESPONSE);
       va_end(ap);
    }

    acceptableResponses = PORT_NewArray(SECItem *, count + 1);
    if (acceptableResponses == NULL)
       goto loser;

    i = 0;
    responseOid = SECOID_FindOIDByTag(responseType0);
    acceptableResponses[i++] = &(responseOid->oid);
    if (count > 1) {
       va_start(ap, responseType0);
       for ( ; i < count; i++) {
           responseType = va_arg(ap, SECOidTag);
           responseOid = SECOID_FindOIDByTag(responseType);
           acceptableResponses[i] = &(responseOid->oid);
       }
       va_end(ap);
    }
    acceptableResponses[i] = NULL;

    rv = CERT_EncodeAndAddExtension(extHandle, SEC_OID_PKIX_OCSP_RESPONSE,
                                &acceptableResponses, PR_FALSE,
                                SEC_SequenceOfObjectIDTemplate);
    if (rv != SECSuccess)
       goto loser;

    PORT_Free(acceptableResponses);
    if (request->tbsRequest->extensionHandle == NULL)
       request->tbsRequest->extensionHandle = extHandle;
    return SECSuccess;

loser:
    if (acceptableResponses != NULL)
       PORT_Free(acceptableResponses);
    if (extHandle != NULL)
       (void) CERT_FinishExtensions(extHandle);
    return rv;
}

Here is the caller graph for this function:

SECStatus CERT_CheckOCSPStatus ( CERTCertDBHandle *  handle,
CERTCertificate *  cert,
int64  time,
void pwArg 
)

Definition at line 4553 of file ocsp.c.

{
    CERTOCSPCertID *certID;
    PRBool certIDWasConsumed = PR_FALSE;
    SECStatus rv = SECFailure;
    SECStatus rv_ocsp;
  
    OCSP_TRACE_CERT(cert);
    OCSP_TRACE_TIME("## requested validity time:", time);
  
    certID = CERT_CreateOCSPCertID(cert, time);
    if (!certID)
        return SECFailure;
    rv = ocsp_GetCachedOCSPResponseStatusIfFresh(certID, time, &rv_ocsp);
    if (rv == SECSuccess) {
        CERT_DestroyOCSPCertID(certID);
        return rv_ocsp;
    }
    rv = ocsp_GetOCSPStatusFromNetwork(handle, certID, cert, time, pwArg, 
                                       &certIDWasConsumed, &rv_ocsp);
    if (rv != SECSuccess) {
        /* we were unable to obtain ocsp status */
        PR_EnterMonitor(OCSP_Global.monitor);
        if (OCSP_Global.ocspFailureMode ==
                ocspMode_FailureIsVerificationFailure) {
            rv_ocsp = SECFailure;
        } else {
            rv_ocsp = SECSuccess;
        }
        PR_ExitMonitor(OCSP_Global.monitor);
    }
    if (!certIDWasConsumed) {
        CERT_DestroyOCSPCertID(certID);
    }
    return rv_ocsp;

Here is the caller graph for this function:

Definition at line 562 of file ocsp.c.

{
    OCSP_TRACE(("OCSP CERT_ClearOCSPCache\n"));
    PR_EnterMonitor(OCSP_Global.monitor);
    while (OCSP_Global.cache.numberOfEntries > 0) {
        ocsp_RemoveCacheItem(&OCSP_Global.cache, 
                             OCSP_Global.cache.LRUitem);
    }
    PR_ExitMonitor(OCSP_Global.monitor);
    return SECSuccess;
}

Here is the call graph for this function:

Here is the caller graph for this function:

CERTOCSPCertID* CERT_CreateOCSPCertID ( CERTCertificate *  cert,
int64  time 
)

Definition at line 1673 of file ocsp.c.

{
    PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    CERTOCSPCertID *certID;
    PORT_Assert(arena != NULL);
    if (!arena)
       return NULL;
    
    certID = ocsp_CreateCertID(arena, cert, time);
    if (!certID) {
       PORT_FreeArena(arena, PR_FALSE);
       return NULL;
    }
    certID->poolp = arena;
    return certID;
}

Here is the caller graph for this function:

CERTOCSPRequest* CERT_CreateOCSPRequest ( CERTCertList *  certList,
int64  time,
PRBool  addServiceLocator,
CERTCertificate *  signerCert 
)

Definition at line 1969 of file ocsp.c.

{
    CERTOCSPRequest *request = NULL;

    if (!certList) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return NULL;
    }
    /*
     * XXX This should set an error, but since it is only temporary and
     * since PSM will not initially provide a way to turn on signing of
     * requests anyway, I figure we can just skip defining an error that
     * will be obsolete in the next release.  When we are prepared to
     * put signing of requests back in, this entire check will go away,
     * and later in this function we will need to allocate a signature
     * structure for the request, fill in the "derCerts" field in it,
     * save the signerCert there, as well as fill in the "requestorName"
     * field of the tbsRequest.
     */
    if (signerCert != NULL) {
        return NULL;
    }
    request = ocsp_prepareEmptyOCSPRequest();
    if (!request)
        return NULL;
    /*
     * Now create the list of single requests, one for each cert.
     */
    request->tbsRequest->requestList = 
        ocsp_CreateSingleRequestList(request->arena, 
                                     certList,
                                     time,
                                     addServiceLocator);
    if (request->tbsRequest->requestList == NULL) {
        PORT_FreeArena(request->arena, PR_FALSE);
        return NULL;
    }
    return request;
}

Here is the caller graph for this function:

static CERTOCSPRequest* cert_CreateSingleCertOCSPRequest ( CERTOCSPCertID *  certID,
CERTCertificate *  singleCert,
int64  time,
PRBool  addServiceLocator 
) [static]

Definition at line 1911 of file ocsp.c.

{
    CERTOCSPRequest *request;
    request = ocsp_prepareEmptyOCSPRequest();
    if (!request)
        return NULL;
    /*
     * Version 1 is the default, so we need not fill in a version number.
     * Now create the list of single requests, one for each cert.
     */
    request->tbsRequest->requestList = 
        ocsp_CreateRequestFromCert(request->arena, 
                                   certID,
                                   singleCert,
                                   time,
                                   addServiceLocator);
    if (request->tbsRequest->requestList == NULL) {
        PORT_FreeArena(request->arena, PR_FALSE);
        return NULL;
    }
    return request;
}

Here is the call graph for this function:

Here is the caller graph for this function:

CERTOCSPRequest* CERT_DecodeOCSPRequest ( SECItem *  src)

Definition at line 1411 of file ocsp.c.

{
    PRArenaPool *arena = NULL;
    SECStatus rv = SECFailure;
    CERTOCSPRequest *dest = NULL;
    int i;
    SECItem newSrc;

    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    if (arena == NULL) {
       goto loser;
    }
    dest = (CERTOCSPRequest *) PORT_ArenaZAlloc(arena, 
                                          sizeof(CERTOCSPRequest));
    if (dest == NULL) {
       goto loser;
    }
    dest->arena = arena;

    /* copy the DER into the arena, since Quick DER returns data that points
       into the DER input, which may get freed by the caller */
    rv = SECITEM_CopyItem(arena, &newSrc, src);
    if ( rv != SECSuccess ) {
       goto loser;
    }

    rv = SEC_QuickDERDecodeItem(arena, dest, ocsp_OCSPRequestTemplate, &newSrc);
    if (rv != SECSuccess) {
       if (PORT_GetError() == SEC_ERROR_BAD_DER)
           PORT_SetError(SEC_ERROR_OCSP_MALFORMED_REQUEST);
       goto loser;
    }

    /*
     * XXX I would like to find a way to get rid of the necessity
     * of doing this copying of the arena pointer.
     */
    for (i = 0; dest->tbsRequest->requestList[i] != NULL; i++) {
       dest->tbsRequest->requestList[i]->arena = arena;
    }

    return dest;

loser:
    if (arena != NULL) {
       PORT_FreeArena(arena, PR_FALSE);
    }
    return NULL;
}

Here is the caller graph for this function:

CERTOCSPResponse* CERT_DecodeOCSPResponse ( SECItem *  src)

Definition at line 2454 of file ocsp.c.

{
    PRArenaPool *arena = NULL;
    CERTOCSPResponse *response = NULL;
    SECStatus rv = SECFailure;
    ocspResponseStatus sv;
    SECItem newSrc;

    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    if (arena == NULL) {
       goto loser;
    }
    response = (CERTOCSPResponse *) PORT_ArenaZAlloc(arena,
                                               sizeof(CERTOCSPResponse));
    if (response == NULL) {
       goto loser;
    }
    response->arena = arena;

    /* copy the DER into the arena, since Quick DER returns data that points
       into the DER input, which may get freed by the caller */
    rv = SECITEM_CopyItem(arena, &newSrc, src);
    if ( rv != SECSuccess ) {
       goto loser;
    }

    rv = SEC_QuickDERDecodeItem(arena, response, ocsp_OCSPResponseTemplate, &newSrc);
    if (rv != SECSuccess) {
       if (PORT_GetError() == SEC_ERROR_BAD_DER)
           PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
       goto loser;
    }

    sv = (ocspResponseStatus) DER_GetInteger(&response->responseStatus);
    response->statusValue = sv;
    if (sv != ocspResponse_successful) {
       /*
        * If the response status is anything but successful, then we
        * are all done with decoding; the status is all there is.
        */
       return response;
    }

    /*
     * A successful response contains much more information, still encoded.
     * Now we need to decode that.
     */
    rv = ocsp_DecodeResponseBytes(arena, response->responseBytes);
    if (rv != SECSuccess) {
       goto loser;
    }

    return response;

loser:
    if (arena != NULL) {
       PORT_FreeArena(arena, PR_FALSE);
    }
    return NULL;
}

Here is the caller graph for this function:

SECStatus CERT_DestroyOCSPCertID ( CERTOCSPCertID *  certID)

Definition at line 1462 of file ocsp.c.

{
    if (certID->poolp) {
       PORT_FreeArena(certID->poolp, PR_FALSE);
       return SECSuccess;
    }
    return SECFailure;
}

Here is the caller graph for this function:

void CERT_DestroyOCSPRequest ( CERTOCSPRequest *  request)

Definition at line 2113 of file ocsp.c.

{
    if (request == NULL)
       return;

    if (request->tbsRequest != NULL) {
       if (request->tbsRequest->requestorName != NULL)
           CERT_DestroyGeneralNameList(request->tbsRequest->requestorName);
       if (request->tbsRequest->extensionHandle != NULL)
           (void) CERT_FinishExtensions(request->tbsRequest->extensionHandle);
    }

    if (request->optionalSignature != NULL) {
       if (request->optionalSignature->cert != NULL)
           CERT_DestroyCertificate(request->optionalSignature->cert);

       /*
        * XXX Need to free derCerts?  Or do they come out of arena?
        * (Currently we never fill in derCerts, which is why the
        * answer is not obvious.  Once we do, add any necessary code
        * here and remove this comment.)
        */
    }

    /*
     * We should actually never have a request without an arena,
     * but check just in case.  (If there isn't one, there is not
     * much we can do about it...)
     */
    PORT_Assert(request->arena != NULL);
    if (request->arena != NULL)
       PORT_FreeArena(request->arena, PR_FALSE);
}

Here is the caller graph for this function:

void CERT_DestroyOCSPResponse ( CERTOCSPResponse *  response)

Definition at line 2607 of file ocsp.c.

{
    if (response != NULL) {
       ocspSignature *signature = ocsp_GetResponseSignature(response);
       if (signature && signature->cert != NULL)
           CERT_DestroyCertificate(signature->cert);

       /*
        * We should actually never have a response without an arena,
        * but check just in case.  (If there isn't one, there is not
        * much we can do about it...)
        */
       PORT_Assert(response->arena != NULL);
       if (response->arena != NULL) {
           PORT_FreeArena(response->arena, PR_FALSE);
       }
    }
}

Here is the caller graph for this function:

SECStatus CERT_DisableOCSPChecking ( CERTCertDBHandle *  handle)

Definition at line 4863 of file ocsp.c.

{
    CERTStatusConfig *statusConfig;
    ocspCheckingContext *statusContext;

    if (handle == NULL) {
       PORT_SetError(SEC_ERROR_INVALID_ARGS);
       return SECFailure;
    }

    statusConfig = CERT_GetStatusConfig(handle);
    statusContext = ocsp_GetCheckingContext(handle);
    if (statusContext == NULL)
       return SECFailure;

    if (statusConfig->statusChecker != CERT_CheckOCSPStatus) {
       /*
        * Status configuration is present, but either not currently
        * enabled or not for OCSP.
        */
       PORT_SetError(SEC_ERROR_OCSP_NOT_ENABLED);
       return SECFailure;
    }

    /* cache no longer necessary */
    CERT_ClearOCSPCache();

    /*
     * This is how we disable status checking.  Everything else remains
     * in place in case we are enabled again.
     */
    statusConfig->statusChecker = NULL;

    return SECSuccess;

Here is the caller graph for this function:

SECStatus CERT_DisableOCSPDefaultResponder ( CERTCertDBHandle *  handle)

Definition at line 5230 of file ocsp.c.

{
    CERTStatusConfig *statusConfig;
    ocspCheckingContext *statusContext;
    CERTCertificate *tmpCert;

    if (handle == NULL) {
       PORT_SetError(SEC_ERROR_INVALID_ARGS);
       return SECFailure;
    }

    statusConfig = CERT_GetStatusConfig(handle);
    if (statusConfig == NULL)
       return SECSuccess;

    statusContext = ocsp_GetCheckingContext(handle);
    PORT_Assert(statusContext != NULL);
    if (statusContext == NULL)
       return SECFailure;

    tmpCert = statusContext->defaultResponderCert;
    if (tmpCert) {
       statusContext->defaultResponderCert = NULL;
       CERT_DestroyCertificate(tmpCert);
        /* we don't allow a mix of cache entries from different responders */
        CERT_ClearOCSPCache();
    }

    /*
     * Finally, record the fact.
     */
    statusContext->useDefaultResponder = PR_FALSE;
    return SECSuccess;

Here is the caller graph for this function:

SECStatus CERT_EnableOCSPChecking ( CERTCertDBHandle *  handle)

Definition at line 4949 of file ocsp.c.

{
    CERTStatusConfig *statusConfig;
    
    SECStatus rv;

    if (handle == NULL) {
       PORT_SetError(SEC_ERROR_INVALID_ARGS);
       return SECFailure;
    }

    statusConfig = CERT_GetStatusConfig(handle);
    if (statusConfig == NULL) {
       rv = ocsp_InitStatusChecking(handle);
       if (rv != SECSuccess)
           return rv;

       /* Get newly established value */
       statusConfig = CERT_GetStatusConfig(handle);
       PORT_Assert(statusConfig != NULL);
    }

    /*
     * Setting the checker function is what really enables the checking
     * when each cert verification is done.
     */
    statusConfig->statusChecker = CERT_CheckOCSPStatus;

    return SECSuccess;

Here is the caller graph for this function:

SECStatus CERT_EnableOCSPDefaultResponder ( CERTCertDBHandle *  handle)

Definition at line 5132 of file ocsp.c.

{
    ocspCheckingContext *statusContext;
    CERTCertificate *cert;
    SECStatus rv;
    SECCertificateUsage usage;

    if (handle == NULL) {
       PORT_SetError(SEC_ERROR_INVALID_ARGS);
       return SECFailure;
    }

    statusContext = ocsp_GetCheckingContext(handle);

    if (statusContext == NULL) {
       /*
        * Strictly speaking, the error already set is "correct",
        * but cover over it with one more helpful in this context.
        */
       PORT_SetError(SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER);
       return SECFailure;
    }

    if (statusContext->defaultResponderURI == NULL) {
       PORT_SetError(SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER);
       return SECFailure;
    }

    if (statusContext->defaultResponderNickname == NULL) {
       PORT_SetError(SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER);
       return SECFailure;
    }

    /*
     * Find the cert for the nickname.
     */
    cert = CERT_FindCertByNickname(handle,
                               statusContext->defaultResponderNickname);
    if (cert == NULL) {
        cert = PK11_FindCertFromNickname(statusContext->defaultResponderNickname,
                                         NULL);
    }
    /*
     * We should never have trouble finding the cert, because its
     * existence should have been proven by SetOCSPDefaultResponder.
     */
    PORT_Assert(cert != NULL);
    if (cert == NULL)
       return SECFailure;

   /*
    * Supplied cert should at least have  a signing capability in order for us
    * to use it as a trusted responder cert. Ability to sign is guarantied  if
    * cert is validated to have any set of the usages below.
    */
    rv = CERT_VerifyCertificateNow(handle, cert, PR_TRUE,
                                   certificateUsageCheckAllUsages,
                                   NULL, &usage);
    if (rv != SECSuccess || (usage & (certificateUsageSSLClient |
                                      certificateUsageSSLServer |
                                      certificateUsageSSLServerWithStepUp |
                                      certificateUsageEmailSigner |
                                      certificateUsageObjectSigner |
                                      certificateUsageStatusResponder |
                                      certificateUsageSSLCA)) == 0) {
       PORT_SetError(SEC_ERROR_OCSP_RESPONDER_CERT_INVALID);
       return SECFailure;
    }

    /*
     * And hang onto it.
     */
    statusContext->defaultResponderCert = cert;

    /* we don't allow a mix of cache entries from different responders */
    CERT_ClearOCSPCache();

    /*
     * Finally, record the fact that we now have a default responder enabled.
     */
    statusContext->useDefaultResponder = PR_TRUE;
    return SECSuccess;

Here is the caller graph for this function:

SECItem* CERT_EncodeOCSPRequest ( PRArenaPool arena,
CERTOCSPRequest *  request,
void pwArg 
)

Definition at line 1366 of file ocsp.c.

{
    ocspTBSRequest *tbsRequest;
    SECStatus rv;

    /* XXX All of these should generate errors if they fail. */
    PORT_Assert(request);
    PORT_Assert(request->tbsRequest);

    tbsRequest = request->tbsRequest;

    if (request->tbsRequest->extensionHandle != NULL) {
       rv = CERT_FinishExtensions(request->tbsRequest->extensionHandle);
       request->tbsRequest->extensionHandle = NULL;
       if (rv != SECSuccess)
           return NULL;
    }

    /*
     * XXX When signed requests are supported and request->optionalSignature
     * is not NULL:
     *  - need to encode tbsRequest->requestorName
     *  - need to encode tbsRequest
     *  - need to sign that encoded result (using cert in sig), filling in the
     *    request->optionalSignature structure with the result, the signing
     *    algorithm and (perhaps?) the cert (and its chain?) in derCerts
     */

    return SEC_ASN1EncodeItem(arena, NULL, request, ocsp_OCSPRequestTemplate);
}

Here is the caller graph for this function:

SECItem* CERT_GetEncodedOCSPResponse ( PRArenaPool arena,
CERTCertList *  certList,
char *  location,
int64  time,
PRBool  addServiceLocator,
CERTCertificate *  signerCert,
void pwArg,
CERTOCSPRequest **  pRequest 
)

Definition at line 3318 of file ocsp.c.

{
    CERTOCSPRequest *request;
    request = CERT_CreateOCSPRequest(certList, time, addServiceLocator,
                                     signerCert);
    if (!request)
        return NULL;
    return ocsp_GetEncodedOCSPResponseFromRequest(arena, request, location, 
                                                  time, addServiceLocator, 
                                                  pwArg, pRequest);
}

Here is the caller graph for this function:

char* CERT_GetOCSPAuthorityInfoAccessLocation ( CERTCertificate *  cert)

Definition at line 4263 of file ocsp.c.

{
    CERTGeneralName *locname = NULL;
    SECItem *location = NULL;
    SECItem *encodedAuthInfoAccess = NULL;
    CERTAuthInfoAccess **authInfoAccess = NULL;
    char *locURI = NULL;
    PRArenaPool *arena = NULL;
    SECStatus rv;
    int i;

    /*
     * Allocate this one from the heap because it will get filled in
     * by CERT_FindCertExtension which will also allocate from the heap,
     * and we can free the entire thing on our way out.
     */
    encodedAuthInfoAccess = SECITEM_AllocItem(NULL, NULL, 0);
    if (encodedAuthInfoAccess == NULL)
       goto loser;

    rv = CERT_FindCertExtension(cert, SEC_OID_X509_AUTH_INFO_ACCESS,
                            encodedAuthInfoAccess);
    if (rv == SECFailure) {
       PORT_SetError(SEC_ERROR_CERT_BAD_ACCESS_LOCATION);
       goto loser;
    }

    /*
     * The rest of the things allocated in the routine will come out of
     * this arena, which is temporary just for us to decode and get at the
     * AIA extension.  The whole thing will be destroyed on our way out,
     * after we have copied the location string (url) itself (if found).
     */
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    if (arena == NULL)
       goto loser;

    authInfoAccess = CERT_DecodeAuthInfoAccessExtension(arena,
                                                 encodedAuthInfoAccess);
    if (authInfoAccess == NULL)
       goto loser;

    for (i = 0; authInfoAccess[i] != NULL; i++) {
       if (SECOID_FindOIDTag(&authInfoAccess[i]->method) == SEC_OID_PKIX_OCSP)
           locname = authInfoAccess[i]->location;
    }

    /*
     * If we found an AIA extension, but it did not include an OCSP method,
     * that should look to our caller as if we did not find the extension
     * at all, because it is only an OCSP method that we care about.
     * So set the same error that would be set if the AIA extension was
     * not there at all.
     */
    if (locname == NULL) {
       PORT_SetError(SEC_ERROR_CERT_BAD_ACCESS_LOCATION);
       goto loser;
    }

    /*
     * The following is just a pointer back into locname (i.e. not a copy);
     * thus it should not be freed.
     */
    location = CERT_GetGeneralNameByType(locname, certURI, PR_FALSE);
    if (location == NULL) {
       /*
        * XXX Appears that CERT_GetGeneralNameByType does not set an
        * error if there is no name by that type.  For lack of anything
        * better, act as if the extension was not found.  In the future
        * this should probably be something more like the extension was
        * badly formed.
        */
       PORT_SetError(SEC_ERROR_CERT_BAD_ACCESS_LOCATION);
       goto loser;
    }

    /*
     * That location is really a string, but it has a specified length
     * without a null-terminator.  We need a real string that does have
     * a null-terminator, and we need a copy of it anyway to return to
     * our caller -- so allocate and copy.
     */
    locURI = PORT_Alloc(location->len + 1);
    if (locURI == NULL) {
       goto loser;
    }
    PORT_Memcpy(locURI, location->data, location->len);
    locURI[location->len] = '\0';

loser:
    if (arena != NULL)
       PORT_FreeArena(arena, PR_FALSE);

    if (encodedAuthInfoAccess != NULL)
       SECITEM_FreeItem(encodedAuthInfoAccess, PR_TRUE);

    return locURI;

Here is the caller graph for this function:

SECStatus CERT_GetOCSPResponseStatus ( CERTOCSPResponse *  response)

Definition at line 5267 of file ocsp.c.

Here is the caller graph for this function:

SECStatus CERT_GetOCSPStatusForCertID ( CERTCertDBHandle *  handle,
CERTOCSPResponse *  response,
CERTOCSPCertID *  certID,
CERTCertificate *  signerCert,
int64  time 
)

Definition at line 4794 of file ocsp.c.

{
    SECStatus rv;
    CERTOCSPSingleResponse *single;

    rv = ocsp_GetVerifiedSingleResponseForCertID(handle, response, certID, 
                                                 signerCert, time, &single);
    if (rv != SECSuccess)
        return rv;
    /*
     * Okay, the last step is to check whether the status says revoked,
     * and if so how that compares to the time value passed into this routine.
     */
    rv = ocsp_SingleResponseCertHasGoodStatus(single, time);
    return rv;

Here is the caller graph for this function:

SECItem* cert_GetSPKIDigest ( PRArenaPool arena,
const CERTCertificate *  cert,
SECOidTag  digestAlg,
SECItem *  fill 
)

Definition at line 1544 of file ocsp.c.

{
    SECItem spk;

    /*
     * Copy just the length and data pointer (nothing needs to be freed)
     * of the subject public key so we can convert the length from bits
     * to bytes, which is what the digest function expects.
     */
    spk = cert->subjectPublicKeyInfo.subjectPublicKey;
    DER_ConvertBitString(&spk);

    return ocsp_DigestValue(arena, digestAlg, fill, &spk);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static SECItem* cert_GetSubjectNameDigest ( PRArenaPool arena,
const CERTCertificate *  cert,
SECOidTag  digestAlg,
SECItem *  fill 
) [static]

Definition at line 1564 of file ocsp.c.

{
    SECItem name;

    /*
     * Copy just the length and data pointer (nothing needs to be freed)
     * of the subject name
     */
    name = cert->derSubject;

    return ocsp_DigestValue(arena, digestAlg, fill, &name);
}

Here is the call graph for this function:

Here is the caller graph for this function:

SECStatus CERT_OCSPCacheSettings ( PRInt32  maxCacheEntries,
PRUint32  minimumSecondsToNextFetchAttempt,
PRUint32  maximumSecondsToNextFetchAttempt 
)

Definition at line 798 of file ocsp.c.

{
    if (minimumSecondsToNextFetchAttempt > maximumSecondsToNextFetchAttempt
        || maxCacheEntries < -1) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }
  
    PR_EnterMonitor(OCSP_Global.monitor);
  
    if (maxCacheEntries < 0) {
        OCSP_Global.maxCacheEntries = -1; /* disable cache */
    } else if (maxCacheEntries == 0) {
        OCSP_Global.maxCacheEntries = 0; /* unlimited cache entries */
    } else {
        OCSP_Global.maxCacheEntries = maxCacheEntries;
    }
  
    if (minimumSecondsToNextFetchAttempt < 
            OCSP_Global.minimumSecondsToNextFetchAttempt
        || maximumSecondsToNextFetchAttempt < 
            OCSP_Global.maximumSecondsToNextFetchAttempt) {
        /*
         * Ensure our existing cache entries are not used longer than the 
         * new settings allow, we're lazy and just clear the cache
         */
        CERT_ClearOCSPCache();
    }
  
    OCSP_Global.minimumSecondsToNextFetchAttempt = 
        minimumSecondsToNextFetchAttempt;
    OCSP_Global.maximumSecondsToNextFetchAttempt = 
        maximumSecondsToNextFetchAttempt;
    ocsp_CheckCacheSize(&OCSP_Global.cache);
  
    PR_ExitMonitor(OCSP_Global.monitor);
    return SECSuccess;
}

Here is the call graph for this function:

SECStatus CERT_SetOCSPDefaultResponder ( CERTCertDBHandle *  handle,
const char *  url,
const char *  name 
)

Definition at line 5006 of file ocsp.c.

{
    CERTCertificate *cert;
    ocspCheckingContext *statusContext;
    char *url_copy = NULL;
    char *name_copy = NULL;
    SECStatus rv;

    if (handle == NULL || url == NULL || name == NULL) {
       /*
        * XXX When interface is exported, probably want better errors;
        * perhaps different one for each parameter.
        */
       PORT_SetError(SEC_ERROR_INVALID_ARGS);
       return SECFailure;
    }

    /*
     * Find the certificate for the specified nickname.  Do this first
     * because it seems the most likely to fail.
     *
     * XXX Shouldn't need that cast if the FindCertByNickname interface
     * used const to convey that it does not modify the name.  Maybe someday.
     */
    cert = CERT_FindCertByNickname(handle, (char *) name);
    if (cert == NULL) {
      /*
       * look for the cert on an external token.
       */
      cert = PK11_FindCertFromNickname((char *)name, NULL);
    }
    if (cert == NULL)
       return SECFailure;

    /*
     * Make a copy of the url and nickname.
     */
    url_copy = PORT_Strdup(url);
    name_copy = PORT_Strdup(name);
    if (url_copy == NULL || name_copy == NULL) {
       rv = SECFailure;
       goto loser;
    }

    statusContext = ocsp_GetCheckingContext(handle);

    /*
     * Allocate and init the context if it doesn't already exist.
     */
    if (statusContext == NULL) {
       rv = ocsp_InitStatusChecking(handle);
       if (rv != SECSuccess)
           goto loser;

       statusContext = ocsp_GetCheckingContext(handle);
       PORT_Assert(statusContext != NULL);       /* extreme paranoia */
    }

    /*
     * Note -- we do not touch the status context until after all of
     * the steps which could cause errors.  If something goes wrong,
     * we want to leave things as they were.
     */

    /*
     * Get rid of old url and name if there.
     */
    if (statusContext->defaultResponderNickname != NULL)
       PORT_Free(statusContext->defaultResponderNickname);
    if (statusContext->defaultResponderURI != NULL)
       PORT_Free(statusContext->defaultResponderURI);

    /*
     * And replace them with the new ones.
     */
    statusContext->defaultResponderURI = url_copy;
    statusContext->defaultResponderNickname = name_copy;

    /*
     * If there was already a cert in place, get rid of it and replace it.
     * Otherwise, we are not currently enabled, so we don't want to save it;
     * it will get re-found and set whenever use of a default responder is
     * enabled.
     */
    if (statusContext->defaultResponderCert != NULL) {
       CERT_DestroyCertificate(statusContext->defaultResponderCert);
       statusContext->defaultResponderCert = cert;
        /*OCSP enabled, switching responder: clear cache*/
        CERT_ClearOCSPCache();
    } else {
       PORT_Assert(statusContext->useDefaultResponder == PR_FALSE);
       CERT_DestroyCertificate(cert);
        /*OCSP currently not enabled, no need to clear cache*/
    }

    return SECSuccess;

loser:
    CERT_DestroyCertificate(cert);
    if (url_copy != NULL)
       PORT_Free(url_copy);
    if (name_copy != NULL)
       PORT_Free(name_copy);
    return rv;

Here is the caller graph for this function:

Definition at line 780 of file ocsp.c.

Here is the call graph for this function:

SECStatus CERT_VerifyOCSPResponseSignature ( CERTOCSPResponse *  response,
CERTCertDBHandle *  handle,
void pwArg,
CERTCertificate **  pSignerCert,
CERTCertificate *  issuer 
)

Definition at line 3558 of file ocsp.c.

{
    SECItem rawSignature;
    SECItem *tbsResponseDataDER;
    CERTCertificate *responder = NULL;
    CERTCertificate *signerCert = NULL;
    SECKEYPublicKey *signerKey = NULL;
    CERTCertificate **certs = NULL;
    SECStatus rv = SECFailure;
    int certCount = 0;
    PRBool lookupByName;
    void *certIndex;
    int64 producedAt;

    /* ocsp_DecodeBasicOCSPResponse will fail if asn1 decoder is unable
     * to properly decode tbsData (see the function and
     * ocsp_BasicOCSPResponseTemplate). Thus, tbsData can not be
     * equal to null */
    ocspResponseData *tbsData = ocsp_GetResponseData(response,
                                                     &tbsResponseDataDER);
    ocspSignature *signature = ocsp_GetResponseSignature(response);

    if (!signature) {
        PORT_SetError(SEC_ERROR_OCSP_BAD_SIGNATURE);
        return SECFailure;
    }

    /*
     * If this signature has already gone through verification, just
     * return the cached result.
     */
    if (signature->wasChecked) {
       if (signature->status == SECSuccess) {
           if (pSignerCert != NULL)
              *pSignerCert = CERT_DupCertificate(signature->cert);
       } else {
           PORT_SetError(signature->failureReason);
       }
       return signature->status;
    }

    PORT_Assert(tbsData->responderID != NULL);
    switch (tbsData->responderID->responderIDType) {
    case ocspResponderID_byName:
       lookupByName = PR_TRUE;
       certIndex = &tbsData->derResponderID;
       break;
    case ocspResponderID_byKey:
       lookupByName = PR_FALSE;
       certIndex = &tbsData->responderID->responderIDValue.keyHash;
       break;
    case ocspResponderID_other:
    default:
       PORT_Assert(0);
       PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
       return SECFailure;
    }

    /*
     * If the signature contains some certificates as well, temporarily
     * import them in case they are needed for verification.
     *
     * Note that the result of this is that each cert in "certs" needs
     * to be destroyed.
     */
    if (signature->derCerts != NULL) {
       for (; signature->derCerts[certCount] != NULL; certCount++) {
           /* just counting */
       }
       rv = CERT_ImportCerts(handle, certUsageStatusResponder, certCount,
                             signature->derCerts, &certs,
                             PR_FALSE, PR_FALSE, NULL);
       if (rv != SECSuccess)
            goto finish;
    }

    /*
     * Now look up the certificate that did the signing.
     * The signer can be specified either by name or by key hash.
     */
    if (lookupByName) {
       SECItem *crIndex = (SECItem*)certIndex;
       SECItem encodedName;
       PLArenaPool *arena;

       arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
       if (arena != NULL) {

           rv = SEC_QuickDERDecodeItem(arena, &encodedName,
                                       ocsp_ResponderIDDerNameTemplate,
                                       crIndex);
           if (rv != SECSuccess) {
               if (PORT_GetError() == SEC_ERROR_BAD_DER)
                   PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
           } else {
                   signerCert = CERT_FindCertByName(handle, &encodedName);
           }
           PORT_FreeArena(arena, PR_FALSE);
       }
    } else {
       /*
        * The signer is either 1) a known issuer CA we passed in,
        * 2) the default OCSP responder, or 3) an intermediate CA
        * passed in the cert list to use. Figure out which it is.
        */
       int i;
       responder = ocsp_CertGetDefaultResponder(handle,NULL);
       if (responder && ocsp_matchcert(certIndex,responder)) {
           signerCert = CERT_DupCertificate(responder);
       } else if (issuer && ocsp_matchcert(certIndex,issuer)) {
           signerCert = CERT_DupCertificate(issuer);
       } 
       for (i=0; (signerCert == NULL) && (i < certCount); i++) {
           if (ocsp_matchcert(certIndex,certs[i])) {
              signerCert = CERT_DupCertificate(certs[i]);
           }
       }
    }

    if (signerCert == NULL) {
       rv = SECFailure;
       if (PORT_GetError() == SEC_ERROR_UNKNOWN_CERT) {
           /* Make the error a little more specific. */
           PORT_SetError(SEC_ERROR_OCSP_INVALID_SIGNING_CERT);
       }
       goto finish;
    }

    /*
     * We could mark this true at the top of this function, or always
     * below at "finish", but if the problem was just that we could not
     * find the signer's cert, leave that as if the signature hasn't
     * been checked in case a subsequent call might have better luck.
     */
    signature->wasChecked = PR_TRUE;

    /*
     * The function will also verify the signer certificate; we
     * need to tell it *when* that certificate must be valid -- for our
     * purposes we expect it to be valid when the response was signed.
     * The value of "producedAt" is the signing time.
     */
    rv = DER_GeneralizedTimeToTime(&producedAt, &tbsData->producedAt);
    if (rv != SECSuccess)
        goto finish;

    /*
     * Just because we have a cert does not mean it is any good; check
     * it for validity, trust and usage.
     */
    if (ocsp_CertIsOCSPDefaultResponder(handle, signerCert)) {
        rv = SECSuccess;
    } else {
        if (CERT_IsCACert(signerCert, NULL)) {
            rv = CERT_VerifyCert(handle, signerCert, PR_TRUE,
                                 certUsageVerifyCA,
                                 producedAt, pwArg, NULL);
        } else {
            rv = CERT_VerifyCert(handle, signerCert, PR_TRUE,
                                 certUsageStatusResponder,
                                 producedAt, pwArg, NULL);
        }
        if (rv != SECSuccess) {
            PORT_SetError(SEC_ERROR_OCSP_INVALID_SIGNING_CERT);
            goto finish;
        }
    }

    /*
     * Now get the public key from the signer's certificate; we need
     * it to perform the verification.
     */
    signerKey = CERT_ExtractPublicKey(signerCert);
    if (signerKey == NULL)
       goto finish;
    /*
     * We copy the signature data *pointer* and length, so that we can
     * modify the length without damaging the original copy.  This is a
     * simple copy, not a dup, so no destroy/free is necessary.
     */
    rawSignature = signature->signature;
    /*
     * The raw signature is a bit string, but we need to represent its
     * length in bytes, because that is what the verify function expects.
     */
    DER_ConvertBitString(&rawSignature);

    rv = VFY_VerifyDataWithAlgorithmID(tbsResponseDataDER->data,
                                       tbsResponseDataDER->len,
                                       signerKey, &rawSignature,
                                       &signature->signatureAlgorithm,
                                       NULL, pwArg);
    if (rv != SECSuccess && PORT_GetError() == SEC_ERROR_BAD_SIGNATURE) {
        PORT_SetError(SEC_ERROR_OCSP_BAD_SIGNATURE);
    }

finish:
    if (signature->wasChecked)
       signature->status = rv;

    if (rv != SECSuccess) {
       signature->failureReason = PORT_GetError();
       if (signerCert != NULL)
           CERT_DestroyCertificate(signerCert);
    } else {
       /*
        * Save signer's certificate in signature.
        */
       signature->cert = signerCert;
       if (pSignerCert != NULL) {
           /*
            * Pass pointer to signer's certificate back to our caller,
            * who is also now responsible for destroying it.
            */
           *pSignerCert = CERT_DupCertificate(signerCert);
       }
    }

    if (signerKey != NULL)
       SECKEY_DestroyPublicKey(signerKey);

    if (certs != NULL)
       CERT_DestroyCertArray(certs, certCount);
       /* Free CERTS from SPKDigest Table */

    return rv;
}

Here is the caller graph for this function:

static SECItem* fetchOcspHttpClientV1 ( PRArenaPool arena,
const SEC_HttpClientFcnV1 hcv1,
char *  location,
SECItem *  encodedRequest 
) [static]

Definition at line 3172 of file ocsp.c.

{
    char *hostname = NULL;
    char *path = NULL;
    PRUint16 port;
    SECItem *encodedResponse = NULL;
    SEC_HTTP_SERVER_SESSION pServerSession = NULL;
    SEC_HTTP_REQUEST_SESSION pRequestSession = NULL;
    PRUint16 myHttpResponseCode;
    const char *myHttpResponseData;
    PRUint32 myHttpResponseDataLen;

    if (ocsp_ParseURL(location, &hostname, &port, &path) == SECFailure) {
        PORT_SetError(SEC_ERROR_OCSP_MALFORMED_REQUEST);
        goto loser;
    }
    
    PORT_Assert(hostname != NULL);
    PORT_Assert(path != NULL);

    if ((*hcv1->createSessionFcn)(
            hostname, 
            port, 
            &pServerSession) != SECSuccess) {
        PORT_SetError(SEC_ERROR_OCSP_SERVER_ERROR);
        goto loser;
    }

    /* We use a non-zero timeout, which means:
       - the client will use blocking I/O
       - TryFcn will not return WOULD_BLOCK nor a poll descriptor
       - it's sufficient to call TryFcn once
    */

    if ((*hcv1->createFcn)(
            pServerSession,
            "http",
            path,
            "POST",
            PR_TicksPerSecond() * 60,
            &pRequestSession) != SECSuccess) {
        PORT_SetError(SEC_ERROR_OCSP_SERVER_ERROR);
        goto loser;
    }

    if ((*hcv1->setPostDataFcn)(
            pRequestSession, 
            (char*)encodedRequest->data,
            encodedRequest->len,
            "application/ocsp-request") != SECSuccess) {
        PORT_SetError(SEC_ERROR_OCSP_SERVER_ERROR);
        goto loser;
    }

    /* we don't want result objects larger than this: */
    myHttpResponseDataLen = MAX_WANTED_OCSP_RESPONSE_LEN;

    if ((*hcv1->trySendAndReceiveFcn)(
            pRequestSession, 
            NULL,
            &myHttpResponseCode,
            NULL,
            NULL,
            &myHttpResponseData,
            &myHttpResponseDataLen) != SECSuccess) {
        PORT_SetError(SEC_ERROR_OCSP_SERVER_ERROR);
        goto loser;
    }

    if (myHttpResponseCode != 200) {
        PORT_SetError(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE);
        goto loser;
    }

    encodedResponse = SECITEM_AllocItem(arena, NULL, myHttpResponseDataLen);

    if (!encodedResponse) {
        PORT_SetError(SEC_ERROR_NO_MEMORY);
        goto loser;
    }

    PORT_Memcpy(encodedResponse->data, myHttpResponseData, myHttpResponseDataLen);

loser:
    if (pRequestSession != NULL) 
        (*hcv1->freeFcn)(pRequestSession);
    if (pServerSession != NULL)
        (*hcv1->freeSessionFcn)(pServerSession);
    if (path != NULL)
       PORT_Free(path);
    if (hostname != NULL)
       PORT_Free(hostname);
    
    return encodedResponse;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 899 of file ocsp.c.

Here is the call graph for this function:

Here is the caller graph for this function:

static void ocsp_AddCacheItemToLinkedList ( OCSPCacheData *  cache,
OCSPCacheItem *  new_most_recent 
) [static]

Definition at line 388 of file ocsp.c.

{
    PR_EnterMonitor(OCSP_Global.monitor);

    if (!cache->LRUitem) {
        cache->LRUitem = new_most_recent;
    }
    new_most_recent->lessRecent = cache->MRUitem;
    new_most_recent->moreRecent = NULL;

    if (cache->MRUitem) {
        cache->MRUitem->moreRecent = new_most_recent;
    }
    cache->MRUitem = new_most_recent;

    PR_ExitMonitor(OCSP_Global.monitor);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static SECStatus ocsp_AddServiceLocatorExtension ( ocspSingleRequest *  singleRequest,
CERTCertificate *  cert 
) [static]

Definition at line 1710 of file ocsp.c.

{
    ocspServiceLocator *serviceLocator = NULL;
    void *extensionHandle = NULL;
    SECStatus rv = SECFailure;

    serviceLocator = PORT_ZNew(ocspServiceLocator);
    if (serviceLocator == NULL)
       goto loser;

    /*
     * Normally it would be a bad idea to do a direct reference like
     * this rather than allocate and copy the name *or* at least dup
     * a reference of the cert.  But all we need is to be able to read
     * the issuer name during the encoding we are about to do, so a
     * copy is just a waste of time.
     */
    serviceLocator->issuer = &cert->issuer;

    rv = CERT_FindCertExtension(cert, SEC_OID_X509_AUTH_INFO_ACCESS,
                            &serviceLocator->locator);
    if (rv != SECSuccess) {
       if (PORT_GetError() != SEC_ERROR_EXTENSION_NOT_FOUND)
           goto loser;
    }

    /* prepare for following loser gotos */
    rv = SECFailure;
    PORT_SetError(0);

    extensionHandle = cert_StartExtensions(singleRequest,
                       singleRequest->arena, SetSingleReqExts);
    if (extensionHandle == NULL)
       goto loser;

    rv = CERT_EncodeAndAddExtension(extensionHandle,
                                SEC_OID_PKIX_OCSP_SERVICE_LOCATOR,
                                serviceLocator, PR_FALSE,
                                ocsp_ServiceLocatorTemplate);

loser:
    if (extensionHandle != NULL) {
       /*
        * Either way we have to finish out the extension context (so it gets
        * freed).  But careful not to override any already-set bad status.
        */
       SECStatus tmprv = CERT_FinishExtensions(extensionHandle);
       if (rv == SECSuccess)
           rv = tmprv;
    }

    /*
     * Finally, free the serviceLocator structure itself and we are done.
     */
    if (serviceLocator != NULL) {
       if (serviceLocator->locator.data != NULL)
           SECITEM_FreeItem(&serviceLocator->locator, PR_FALSE);
       PORT_Free(serviceLocator);
    }

    return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static PRBool ocsp_AuthorizedResponderForCertID ( CERTCertDBHandle *  handle,
CERTCertificate *  signerCert,
CERTOCSPCertID *  certID,
int64  thisUpdate 
) [static]

Definition at line 4006 of file ocsp.c.

{
    CERTCertificate *issuerCert = NULL, *defRespCert;
    SECItem *keyHash = NULL;
    SECItem *nameHash = NULL;
    SECOidTag hashAlg;
    PRBool keyHashEQ = PR_FALSE, nameHashEQ = PR_FALSE;

    /*
     * Check first for a trusted responder, which overrides everything else.
     */
    if ((defRespCert = ocsp_CertGetDefaultResponder(handle, certID)) &&
        CERT_CompareCerts(defRespCert, signerCert)) {
        return PR_TRUE;
    }

    /*
     * In the other two cases, we need to do an issuer comparison.
     * How we do it depends on whether the signer certificate has the
     * special extension (for a designated responder) or not.
     *
     * First, lets check if signer of the response is the actual issuer
     * of the cert. For that we will use signer cert key hash and cert subj
     * name hash and will compare them with already calculated issuer key
     * hash and issuer name hash. The hash algorithm is picked from response
     * certID hash to avoid second hash calculation.
     */

    hashAlg = SECOID_FindOIDTag(&certID->hashAlgorithm.algorithm);

    keyHash = cert_GetSPKIDigest(NULL, signerCert, hashAlg, NULL);
    if (keyHash != NULL) {

        keyHashEQ =
            (SECITEM_CompareItem(keyHash,
                                 &certID->issuerKeyHash) == SECEqual);
        SECITEM_FreeItem(keyHash, PR_TRUE);
    }
    if (keyHashEQ &&
        (nameHash = cert_GetSubjectNameDigest(NULL, signerCert,
                                              hashAlg, NULL))) {
        nameHashEQ =
            (SECITEM_CompareItem(nameHash,
                                 &certID->issuerNameHash) == SECEqual);
            
        SECITEM_FreeItem(nameHash, PR_TRUE);
        if (nameHashEQ) {
            /* The issuer of the cert is the the signer of the response */
            return PR_TRUE;
        }
    }


    keyHashEQ = PR_FALSE;
    nameHashEQ = PR_FALSE;

    if (!ocsp_CertIsOCSPDesignatedResponder(signerCert)) {
        PORT_SetError(SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE);
        return PR_FALSE;
    }

    /*
     * The signer is a designated responder.  Its issuer must match
     * the issuer of the cert being checked.
     */
    issuerCert = CERT_FindCertIssuer(signerCert, thisUpdate,
                                     certUsageAnyCA);
    if (issuerCert == NULL) {
        /*
         * We could leave the SEC_ERROR_UNKNOWN_ISSUER error alone,
         * but the following will give slightly more information.
         * Once we have an error stack, things will be much better.
         */
        PORT_SetError(SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE);
        return PR_FALSE;
    }

    keyHash = cert_GetSPKIDigest(NULL, issuerCert, hashAlg, NULL);
    nameHash = cert_GetSubjectNameDigest(NULL, issuerCert, hashAlg, NULL);

    CERT_DestroyCertificate(issuerCert);

    if (keyHash != NULL && nameHash != NULL) {
        keyHashEQ = 
            (SECITEM_CompareItem(keyHash,
                                 &certID->issuerKeyHash) == SECEqual);

        nameHashEQ =
            (SECITEM_CompareItem(nameHash,
                                 &certID->issuerNameHash) == SECEqual);
    }

    if (keyHash) {
        SECITEM_FreeItem(keyHash, PR_TRUE);
    }
    if (nameHash) {
        SECITEM_FreeItem(nameHash, PR_TRUE);
    }

    if (keyHashEQ && nameHashEQ) {
        return PR_TRUE;
    }

    PORT_SetError(SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE);
    return PR_FALSE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static PRIntn PR_CALLBACK ocsp_CacheKeyCompareFunction ( const void v1,
const void v2 
) [static]

Definition at line 295 of file ocsp.c.

{
    CERTOCSPCertID *cid1 = (CERTOCSPCertID *)v1;
    CERTOCSPCertID *cid2 = (CERTOCSPCertID *)v2;
  
    return (SECEqual == SECITEM_CompareItem(&cid1->issuerNameHash, 
                                            &cid2->issuerNameHash)
            && SECEqual == SECITEM_CompareItem(&cid1->issuerKeyHash, 
                                               &cid2->issuerKeyHash)
            && SECEqual == SECITEM_CompareItem(&cid1->serialNumber, 
                                               &cid2->serialNumber));
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 271 of file ocsp.c.

{
    CERTOCSPCertID *cid = (CERTOCSPCertID *)key;
    PLHashNumber hash = 0;
    unsigned int i;
    unsigned char *walk;
  
    /* a very simple hash calculation for the initial coding phase */
    walk = (unsigned char*)cid->issuerNameHash.data;
    for (i=0; i < cid->issuerNameHash.len; ++i, ++walk) {
        hash += *walk;
    }
    walk = (unsigned char*)cid->issuerKeyHash.data;
    for (i=0; i < cid->issuerKeyHash.len; ++i, ++walk) {
        hash += *walk;
    }
    walk = (unsigned char*)cid->serialNumber.data;
    for (i=0; i < cid->serialNumber.len; ++i, ++walk) {
        hash += *walk;
    }
    return hash;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static CERTCertificate * ocsp_CertGetDefaultResponder ( CERTCertDBHandle *  handle,
CERTOCSPCertID *  certID 
) [static]

Definition at line 3934 of file ocsp.c.

{
    ocspCheckingContext *ocspcx;

    ocspcx = ocsp_GetCheckingContext(handle);
    if (ocspcx == NULL)
       goto loser;

   /*
    * Right now we have only one default responder.  It applies to
    * all certs when it is used, so the check is simple and certID
    * has no bearing on the answer.  Someday in the future we may
    * allow configuration of different responders for different
    * issuers, and then we would have to use the issuer specified
    * in certID to determine if signerCert is the right one.
    */
    if (ocspcx->useDefaultResponder) {
       PORT_Assert(ocspcx->defaultResponderCert != NULL);
       return ocspcx->defaultResponderCert;
    }

loser:
    return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static SECStatus ocsp_CertHasGoodStatus ( ocspCertStatus *  status,
int64  time 
) [static]

Definition at line 4432 of file ocsp.c.

{
    SECStatus rv;
    switch (status->certStatusType) {
    case ocspCertStatus_good:
        rv = SECSuccess;
        break;
    case ocspCertStatus_revoked:
        rv = ocsp_CertRevokedAfter(status->certStatusInfo.revokedInfo, time);
        break;
    case ocspCertStatus_unknown:
        PORT_SetError(SEC_ERROR_OCSP_UNKNOWN_CERT);
        rv = SECFailure;
        break;
    case ocspCertStatus_other:
    default:
        PORT_Assert(0);
        PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
        rv = SECFailure;
        break;
    }
    return rv;

Here is the call graph for this function:

Here is the caller graph for this function:

static PRBool ocsp_CertIDsMatch ( CERTCertDBHandle *  handle,
CERTOCSPCertID *  requestCertID,
CERTOCSPCertID *  responseCertID 
) [static]

Definition at line 3795 of file ocsp.c.

{
    PRBool match = PR_FALSE;
    SECOidTag hashAlg;
    SECItem *keyHash = NULL;
    SECItem *nameHash = NULL;

    /*
     * In order to match, they must have the same issuer and the same
     * serial number.
     *
     * We just compare the easier things first.
     */
    if (SECITEM_CompareItem(&requestCertID->serialNumber,
                         &responseCertID->serialNumber) != SECEqual) {
       goto done;
    }

    /*
     * Make sure the "parameters" are not too bogus.  Since we encoded
     * requestCertID->hashAlgorithm, we don't need to check it.
     */
    if (responseCertID->hashAlgorithm.parameters.len > 2) {
       goto done;
    }
    if (SECITEM_CompareItem(&requestCertID->hashAlgorithm.algorithm,
              &responseCertID->hashAlgorithm.algorithm) == SECEqual) {
       /*
        * If the hash algorithms match then we can do a simple compare
        * of the hash values themselves.
        */
       if ((SECITEM_CompareItem(&requestCertID->issuerNameHash,
                            &responseCertID->issuerNameHash) == SECEqual)
           && (SECITEM_CompareItem(&requestCertID->issuerKeyHash,
                            &responseCertID->issuerKeyHash) == SECEqual)) {
           match = PR_TRUE;
       }
       goto done;
    }

    hashAlg = SECOID_FindOIDTag(&responseCertID->hashAlgorithm.algorithm);
    switch (hashAlg) {
    case SEC_OID_SHA1:
       keyHash = &requestCertID->issuerSHA1KeyHash;
       nameHash = &requestCertID->issuerSHA1NameHash;
       break;
    case SEC_OID_MD5:
       keyHash = &requestCertID->issuerMD5KeyHash;
       nameHash = &requestCertID->issuerMD5NameHash;
       break;
    case SEC_OID_MD2:
       keyHash = &requestCertID->issuerMD2KeyHash;
       nameHash = &requestCertID->issuerMD2NameHash;
       break;
    default:
       PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
       return SECFailure;
    }

    if ((keyHash != NULL)
       && (SECITEM_CompareItem(nameHash,
                            &responseCertID->issuerNameHash) == SECEqual)
       && (SECITEM_CompareItem(keyHash,
                            &responseCertID->issuerKeyHash) == SECEqual)) {
       match = PR_TRUE;
    }

done:
    return match;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static PRBool ocsp_CertIsOCSPDefaultResponder ( CERTCertDBHandle *  handle,
CERTCertificate *  cert 
) [static]

Definition at line 3964 of file ocsp.c.

{
    ocspCheckingContext *ocspcx;

    ocspcx = ocsp_GetCheckingContext(handle);
    if (ocspcx == NULL)
       return PR_FALSE;

   /*
    * Right now we have only one default responder.  It applies to
    * all certs when it is used, so the check is simple and certID
    * has no bearing on the answer.  Someday in the future we may
    * allow configuration of different responders for different
    * issuers, and then we would have to use the issuer specified
    * in certID to determine if signerCert is the right one.
    */
    if (ocspcx->useDefaultResponder &&
        CERT_CompareCerts(ocspcx->defaultResponderCert, cert)) {
       return PR_TRUE;
    }

    return PR_FALSE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static PRBool ocsp_CertIsOCSPDesignatedResponder ( CERTCertificate *  cert) [static]

Definition at line 3415 of file ocsp.c.

{
    SECStatus rv;
    SECItem extItem;
    SECItem **oids;
    SECItem *oid;
    SECOidTag oidTag;
    PRBool retval;
    CERTOidSequence *oidSeq = NULL;


    extItem.data = NULL;
    rv = CERT_FindCertExtension(cert, SEC_OID_X509_EXT_KEY_USAGE, &extItem);
    if ( rv != SECSuccess ) {
       goto loser;
    }

    oidSeq = CERT_DecodeOidSequence(&extItem);
    if ( oidSeq == NULL ) {
       goto loser;
    }

    oids = oidSeq->oids;
    while ( *oids != NULL ) {
       oid = *oids;
       
       oidTag = SECOID_FindOIDTag(oid);
       
       if ( oidTag == SEC_OID_OCSP_RESPONDER ) {
           goto success;
       }
       
       oids++;
    }

loser:
    retval = PR_FALSE;
    PORT_SetError(SEC_ERROR_OCSP_INVALID_SIGNING_CERT);
    goto done;
success:
    retval = PR_TRUE;
done:
    if ( extItem.data != NULL ) {
       PORT_Free(extItem.data);
    }
    if ( oidSeq != NULL ) {
       CERT_DestroyOidSequence(oidSeq);
    }
    
    return(retval);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static SECStatus ocsp_CertRevokedAfter ( ocspRevokedInfo *  revokedInfo,
int64  time 
) [static]

Definition at line 4407 of file ocsp.c.

{
    int64 revokedTime;
    SECStatus rv;

    rv = DER_GeneralizedTimeToTime(&revokedTime, &revokedInfo->revocationTime);
    if (rv != SECSuccess)
       return rv;

    /*
     * Set the error even if we will return success; someone might care.
     */
    PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE);

    if (LL_CMP(revokedTime, >, time))
       return SECSuccess;

    return SECFailure;

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 2183 of file ocsp.c.

{
    const SEC_ASN1Template *certStatusTemplate;

    switch (certStatusType) {
       case ocspCertStatus_good:
           certStatusTemplate = ocsp_CertStatusGoodTemplate;
           break;
       case ocspCertStatus_revoked:
           certStatusTemplate = ocsp_CertStatusRevokedTemplate;
           break;
       case ocspCertStatus_unknown:
           certStatusTemplate = ocsp_CertStatusUnknownTemplate;
           break;
       case ocspCertStatus_other:
       default:
           PORT_Assert(certStatusType == ocspCertStatus_other);
           certStatusTemplate = ocsp_CertStatusOtherTemplate;
           break;
    }

    return certStatusTemplate;
}

Here is the caller graph for this function:

static ocspCertStatusType ocsp_CertStatusTypeByTag ( int  derTag) [static]

Definition at line 2212 of file ocsp.c.

{
    ocspCertStatusType certStatusType;

    switch (derTag) {
       case 0:
           certStatusType = ocspCertStatus_good;
           break;
       case 1:
           certStatusType = ocspCertStatus_revoked;
           break;
       case 2:
           certStatusType = ocspCertStatus_unknown;
           break;
       default:
           certStatusType = ocspCertStatus_other;
           break;
    }

    return certStatusType;
}

Here is the caller graph for this function:

static void ocsp_CheckCacheSize ( OCSPCacheData *  cache) [static]

Definition at line 549 of file ocsp.c.

{
    OCSP_TRACE(("OCSP ocsp_CheckCacheSize\n"));
    PR_EnterMonitor(OCSP_Global.monitor);
    if (OCSP_Global.maxCacheEntries <= 0) /* disabled or unlimited */
        return;
    while (cache->numberOfEntries > OCSP_Global.maxCacheEntries) {
        ocsp_RemoveCacheItem(cache, cache->LRUitem);
    }
    PR_ExitMonitor(OCSP_Global.monitor);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static PRFileDesc* ocsp_ConnectToHost ( const char *  host,
PRUint16  port 
) [static]

Definition at line 2756 of file ocsp.c.

{
    PRFileDesc *sock = NULL;
    PRIntervalTime timeout;
    PRNetAddr addr;
    char *netdbbuf = NULL;

    sock = PR_NewTCPSocket();
    if (sock == NULL)
       goto loser;

    /* XXX Some day need a way to set (and get?) the following value */
    timeout = PR_SecondsToInterval(30);

    /*
     * If the following converts an IP address string in "dot notation"
     * into a PRNetAddr.  If it fails, we assume that is because we do not
     * have such an address, but instead a host *name*.  In that case we
     * then lookup the host by name.  Using the NSPR function this way
     * means we do not have to have our own logic for distinguishing a
     * valid numerical IP address from a hostname.
     */
    if (PR_StringToNetAddr(host, &addr) != PR_SUCCESS) {
       PRIntn hostIndex;
       PRHostEnt hostEntry;

       netdbbuf = PORT_Alloc(PR_NETDB_BUF_SIZE);
       if (netdbbuf == NULL)
           goto loser;

       if (PR_GetHostByName(host, netdbbuf, PR_NETDB_BUF_SIZE,
                          &hostEntry) != PR_SUCCESS)
           goto loser;

       hostIndex = 0;
       do {
           hostIndex = PR_EnumerateHostEnt(hostIndex, &hostEntry, port, &addr);
           if (hostIndex <= 0)
              goto loser;
       } while (PR_Connect(sock, &addr, timeout) != PR_SUCCESS);

       PORT_Free(netdbbuf);
    } else {
       /*
        * First put the port into the address, then connect.
        */
       if (PR_InitializeNetAddr(PR_IpAddrNull, port, &addr) != PR_SUCCESS)
           goto loser;
       if (PR_Connect(sock, &addr, timeout) != PR_SUCCESS)
           goto loser;
    }

    return sock;

loser:
    if (sock != NULL)
       PR_Close(sock);
    if (netdbbuf != NULL)
       PORT_Free(netdbbuf);
    return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static SECStatus ocsp_CopyCertStatus ( PRArenaPool arena,
ocspCertStatus *  dest,
ocspCertStatus *  src 
) [static]

Definition at line 349 of file ocsp.c.

{
    SECStatus rv = SECFailure;
    dest->certStatusType = src->certStatusType;
  
    switch (src->certStatusType) {
    case ocspCertStatus_good:
        dest->certStatusInfo.goodInfo = 
            SECITEM_ArenaDupItem(arena, src->certStatusInfo.goodInfo);
        if (dest->certStatusInfo.goodInfo != NULL) {
            rv = SECSuccess;
        }
        break;
    case ocspCertStatus_revoked:
        rv = ocsp_CopyRevokedInfo(arena, dest, 
                                  src->certStatusInfo.revokedInfo);
        break;
    case ocspCertStatus_unknown:
        dest->certStatusInfo.unknownInfo = 
            SECITEM_ArenaDupItem(arena, src->certStatusInfo.unknownInfo);
        if (dest->certStatusInfo.unknownInfo != NULL) {
            rv = SECSuccess;
        }
        break;
    case ocspCertStatus_other:
    default:
        PORT_Assert(src->certStatusType == ocspCertStatus_other);
        dest->certStatusInfo.otherInfo = 
            SECITEM_ArenaDupItem(arena, src->certStatusInfo.otherInfo);
        if (dest->certStatusInfo.otherInfo != NULL) {
            rv = SECSuccess;
        }
        break;
    }
    return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static SECStatus ocsp_CopyRevokedInfo ( PRArenaPool arena,
ocspCertStatus *  dest,
ocspRevokedInfo *  src 
) [static]

Definition at line 309 of file ocsp.c.

{
    SECStatus rv = SECFailure;
    void *mark;
  
    mark = PORT_ArenaMark(arena);
  
    dest->certStatusInfo.revokedInfo = 
        (ocspRevokedInfo *) PORT_ArenaZAlloc(arena, sizeof(ocspRevokedInfo));
    if (!dest->certStatusInfo.revokedInfo) {
        goto loser;
    }
  
    rv = SECITEM_CopyItem(arena, 
                          &dest->certStatusInfo.revokedInfo->revocationTime, 
                          &src->revocationTime);
    if (rv != SECSuccess) {
        goto loser;
    }
  
    if (src->revocationReason) {
        dest->certStatusInfo.revokedInfo->revocationReason = 
            SECITEM_ArenaDupItem(arena, src->revocationReason);
        if (!dest->certStatusInfo.revokedInfo->revocationReason) {
            goto loser;
        }
    }  else {
        dest->certStatusInfo.revokedInfo->revocationReason = NULL;
    }
  
    PORT_ArenaUnmark(arena, mark);
    return SECSuccess;

loser:
    PORT_ArenaRelease(arena, mark);
    return SECFailure;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static SECStatus ocsp_CreateCacheItemAndConsumeCertID ( OCSPCacheData *  cache,
CERTOCSPCertID *  certID,
OCSPCacheItem **  pCacheItem 
) [static]

Definition at line 575 of file ocsp.c.

{
    PRArenaPool *arena;
    void *mark;
    PLHashEntry *new_hash_entry;
    OCSPCacheItem *item;
  
    PORT_Assert(pCacheItem != NULL);
    *pCacheItem = NULL;

    PR_EnterMonitor(OCSP_Global.monitor);
    arena = certID->poolp;
    mark = PORT_ArenaMark(arena);
  
    /* ZAlloc will init all Bools to False and all Pointers to NULL */
    item = (OCSPCacheItem *)PORT_ArenaZAlloc(certID->poolp, 
                                             sizeof(OCSPCacheItem));
    if (!item) {
        goto loser; 
    }
    item->certID = certID;
    new_hash_entry = PL_HashTableAdd(cache->entries, item->certID, 
                                     item);
    if (!new_hash_entry) {
        goto loser;
    }
    ++cache->numberOfEntries;
    PORT_ArenaUnmark(arena, mark);
    ocsp_AddCacheItemToLinkedList(cache, item);
    *pCacheItem = item;

    PR_ExitMonitor(OCSP_Global.monitor);
    return SECSuccess;
  
loser:
    PORT_ArenaRelease(arena, mark);
    PR_ExitMonitor(OCSP_Global.monitor);
    return SECFailure;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static CERTOCSPCertID* ocsp_CreateCertID ( PRArenaPool arena,
CERTCertificate *  cert,
int64  time 
) [static]

Definition at line 1589 of file ocsp.c.

{
    CERTOCSPCertID *certID;
    CERTCertificate *issuerCert = NULL;
    SECItem *tempItem = NULL;
    void *mark = PORT_ArenaMark(arena);
    SECStatus rv;

    PORT_Assert(arena != NULL);

    certID = PORT_ArenaZNew(arena, CERTOCSPCertID);
    if (certID == NULL) {
       goto loser;
    }

    rv = SECOID_SetAlgorithmID(arena, &certID->hashAlgorithm, SEC_OID_SHA1,
                            NULL);
    if (rv != SECSuccess) {
       goto loser; 
    }

    issuerCert = CERT_FindCertIssuer(cert, time, certUsageAnyCA);
    if (issuerCert == NULL) {
       goto loser;
    }

    if (cert_GetSubjectNameDigest(arena, issuerCert, SEC_OID_SHA1,
                                  &(certID->issuerNameHash)) == NULL) {
        goto loser;
    }
    certID->issuerSHA1NameHash.data = certID->issuerNameHash.data;
    certID->issuerSHA1NameHash.len = certID->issuerNameHash.len;

    if (cert_GetSubjectNameDigest(arena, issuerCert, SEC_OID_MD5,
                                  &(certID->issuerMD5NameHash)) == NULL) {
        goto loser;
    }

    if (cert_GetSubjectNameDigest(arena, issuerCert, SEC_OID_MD2,
                                  &(certID->issuerMD2NameHash)) == NULL) {
        goto loser;
    }

    if (cert_GetSPKIDigest(arena, issuerCert, SEC_OID_SHA1,
                               &(certID->issuerKeyHash)) == NULL) {
       goto loser;
    }
    certID->issuerSHA1KeyHash.data = certID->issuerKeyHash.data;
    certID->issuerSHA1KeyHash.len = certID->issuerKeyHash.len;
    /* cache the other two hash algorithms as well */
    if (cert_GetSPKIDigest(arena, issuerCert, SEC_OID_MD5,
                               &(certID->issuerMD5KeyHash)) == NULL) {
       goto loser;
    }
    if (cert_GetSPKIDigest(arena, issuerCert, SEC_OID_MD2,
                               &(certID->issuerMD2KeyHash)) == NULL) {
       goto loser;
    }


    /* now we are done with issuerCert */
    CERT_DestroyCertificate(issuerCert);
    issuerCert = NULL;

    rv = SECITEM_CopyItem(arena, &certID->serialNumber, &cert->serialNumber);
    if (rv != SECSuccess) {
       goto loser; 
    }

    PORT_ArenaUnmark(arena, mark);
    return certID;

loser:
    if (issuerCert != NULL) {
       CERT_DestroyCertificate(issuerCert);
    }
    if (tempItem != NULL) {
       SECITEM_FreeItem(tempItem, PR_TRUE);
    }
    PORT_ArenaRelease(arena, mark);
    return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static SECStatus ocsp_CreateOrUpdateCacheEntry ( OCSPCacheData *  cache,
CERTOCSPCertID *  certID,
CERTOCSPSingleResponse *  single,
PRBool certIDWasConsumed 
) [static]

Definition at line 736 of file ocsp.c.

{
    SECStatus rv;
    OCSPCacheItem *cacheItem;
    OCSP_TRACE(("OCSP ocsp_CreateOrUpdateCacheEntry\n"));
  
    if (!certIDWasConsumed) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }
    *certIDWasConsumed = PR_FALSE;
  
    PR_EnterMonitor(OCSP_Global.monitor);
    PORT_Assert(OCSP_Global.maxCacheEntries >= 0);
  
    cacheItem = ocsp_FindCacheEntry(cache, certID);
    if (!cacheItem) {
        rv = ocsp_CreateCacheItemAndConsumeCertID(cache, certID, 
                                                  &cacheItem);
        if (rv != SECSuccess) {
            PR_ExitMonitor(OCSP_Global.monitor);
            return rv;
        }
        *certIDWasConsumed = PR_TRUE;
    }
    if (single) {
        rv = ocsp_SetCacheItemResponse(cacheItem, single);
        if (rv != SECSuccess) {
            ocsp_RemoveCacheItem(cache, cacheItem);
            PR_ExitMonitor(OCSP_Global.monitor);
            return rv;
        }
    }
    ocsp_FreshenCacheItemNextFetchAttemptTime(cacheItem);
    ocsp_CheckCacheSize(cache);

    PR_ExitMonitor(OCSP_Global.monitor);
    return SECSuccess;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static ocspSingleRequest** ocsp_CreateRequestFromCert ( PRArenaPool arena,
CERTOCSPCertID *  certID,
CERTCertificate *  singleCert,
int64  time,
PRBool  includeLocator 
) [static]

Definition at line 1841 of file ocsp.c.

{
    ocspSingleRequest **requestList = NULL;
    void *mark = PORT_ArenaMark(arena);
    PORT_Assert(certID != NULL && singleCert != NULL);

    /* meaning of value 2: one entry + one end marker */
    requestList = PORT_ArenaNewArray(arena, ocspSingleRequest *, 2);
    if (requestList == NULL)
        goto loser;
    requestList[0] = PORT_ArenaZNew(arena, ocspSingleRequest);
    if (requestList[0] == NULL)
        goto loser;
    requestList[0]->arena = arena;
    /* certID will live longer than the request */
    requestList[0]->reqCert = certID; 

    if (includeLocator == PR_TRUE) {
        SECStatus rv;
        rv = ocsp_AddServiceLocatorExtension(requestList[0], singleCert);
        if (rv != SECSuccess)
            goto loser;
    }

    PORT_ArenaUnmark(arena, mark);
    requestList[1] = NULL;
    return requestList;

loser:
    PORT_ArenaRelease(arena, mark);
    return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static ocspSingleRequest** ocsp_CreateSingleRequestList ( PRArenaPool arena,
CERTCertList *  certList,
int64  time,
PRBool  includeLocator 
) [static]

Definition at line 1787 of file ocsp.c.

{
    ocspSingleRequest **requestList = NULL;
    CERTCertListNode *node = NULL;
    int i, count;
    void *mark = PORT_ArenaMark(arena);
 
    node = CERT_LIST_HEAD(certList);
    for (count = 0; !CERT_LIST_END(node, certList); count++) {
        node = CERT_LIST_NEXT(node);
    }

    if (count == 0)
       goto loser;

    requestList = PORT_ArenaNewArray(arena, ocspSingleRequest *, count + 1);
    if (requestList == NULL)
       goto loser;

    node = CERT_LIST_HEAD(certList);
    for (i = 0; !CERT_LIST_END(node, certList); i++) {
        requestList[i] = PORT_ArenaZNew(arena, ocspSingleRequest);
        if (requestList[i] == NULL)
            goto loser;

        requestList[i]->arena = arena;
        requestList[i]->reqCert = ocsp_CreateCertID(arena, node->cert, time);
        if (requestList[i]->reqCert == NULL)
            goto loser;

        if (includeLocator == PR_TRUE) {
            SECStatus rv;

            rv = ocsp_AddServiceLocatorExtension(requestList[i], node->cert);
            if (rv != SECSuccess)
                goto loser;
        }

        node = CERT_LIST_NEXT(node);
    }

    PORT_Assert(i == count);

    PORT_ArenaUnmark(arena, mark);
    requestList[i] = NULL;
    return requestList;

loser:
    PORT_ArenaRelease(arena, mark);
    return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static ocspBasicOCSPResponse* ocsp_DecodeBasicOCSPResponse ( PRArenaPool arena,
SECItem *  src 
) [static]

Definition at line 2316 of file ocsp.c.

{
    void *mark;
    ocspBasicOCSPResponse *basicResponse;
    ocspResponseData *responseData;
    ocspResponderID *responderID;
    ocspResponderIDType responderIDType;
    const SEC_ASN1Template *responderIDTemplate;
    int derTag;
    SECStatus rv;
    SECItem newsrc;

    mark = PORT_ArenaMark(arena);

    basicResponse = PORT_ArenaZAlloc(arena, sizeof(ocspBasicOCSPResponse));
    if (basicResponse == NULL) {
       goto loser;
    }

    /* copy the DER into the arena, since Quick DER returns data that points
       into the DER input, which may get freed by the caller */
    rv = SECITEM_CopyItem(arena, &newsrc, src);
    if ( rv != SECSuccess ) {
       goto loser;
    }

    rv = SEC_QuickDERDecodeItem(arena, basicResponse,
                         ocsp_BasicOCSPResponseTemplate, &newsrc);
    if (rv != SECSuccess) {
       if (PORT_GetError() == SEC_ERROR_BAD_DER)
           PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
       goto loser;
    }

    responseData = basicResponse->tbsResponseData;

    /*
     * The following asserts point out internal errors (problems in
     * the template definitions or in the ASN.1 decoder itself, etc.).
     */
    PORT_Assert(responseData != NULL);
    PORT_Assert(responseData->derResponderID.data != NULL);

    /*
     * XXX Because responderID is a CHOICE, which is not currently handled
     * by our ASN.1 decoder, we have to decode it "by hand".
     */
    derTag = responseData->derResponderID.data[0] & SEC_ASN1_TAGNUM_MASK;
    responderIDType = ocsp_ResponderIDTypeByTag(derTag);
    responderIDTemplate = ocsp_ResponderIDTemplateByType(responderIDType);

    responderID = PORT_ArenaZAlloc(arena, sizeof(ocspResponderID));
    if (responderID == NULL) {
       goto loser;
    }

    rv = SEC_QuickDERDecodeItem(arena, responderID, responderIDTemplate,
                         &responseData->derResponderID);
    if (rv != SECSuccess) {
       if (PORT_GetError() == SEC_ERROR_BAD_DER)
           PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
       goto loser;
    }

    responderID->responderIDType = responderIDType;
    responseData->responderID = responderID;

    /*
     * XXX Each SingleResponse also contains a CHOICE, which has to be
     * fixed up by hand.
     */
    rv = ocsp_FinishDecodingSingleResponses(arena, responseData->responses);
    if (rv != SECSuccess) {
       goto loser;
    }

    PORT_ArenaUnmark(arena, mark);
    return basicResponse;

loser:
    PORT_ArenaRelease(arena, mark);
    return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static SECStatus ocsp_DecodeResponseBytes ( PRArenaPool arena,
ocspResponseBytes *  rbytes 
) [static]

Definition at line 2406 of file ocsp.c.

{
    PORT_Assert(rbytes != NULL);          /* internal error, really */
    if (rbytes == NULL)
       PORT_SetError(SEC_ERROR_INVALID_ARGS);    /* XXX set better error? */

    rbytes->responseTypeTag = SECOID_FindOIDTag(&rbytes->responseType);
    switch (rbytes->responseTypeTag) {
       case SEC_OID_PKIX_OCSP_BASIC_RESPONSE:
           {
              ocspBasicOCSPResponse *basicResponse;

              basicResponse = ocsp_DecodeBasicOCSPResponse(arena,
                                                      &rbytes->response);
              if (basicResponse == NULL)
                  return SECFailure;

              rbytes->decodedResponse.basic = basicResponse;
           }
           break;

       /*
        * Add new/future response types here.
        */

       default:
           PORT_SetError(SEC_ERROR_OCSP_UNKNOWN_RESPONSE_TYPE);
           return SECFailure;
    }

    return SECSuccess;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static SECStatus ocsp_DestroyStatusChecking ( CERTStatusConfig *  statusConfig) [static]

Definition at line 4819 of file ocsp.c.

{
    ocspCheckingContext *statusContext;

    /*
     * Disable OCSP checking
     */
    statusConfig->statusChecker = NULL;

    statusContext = statusConfig->statusContext;
    PORT_Assert(statusContext != NULL);
    if (statusContext == NULL)
       return SECFailure;

    if (statusContext->defaultResponderURI != NULL)
       PORT_Free(statusContext->defaultResponderURI);
    if (statusContext->defaultResponderNickname != NULL)
       PORT_Free(statusContext->defaultResponderNickname);

    PORT_Free(statusContext);
    statusConfig->statusContext = NULL;

    PORT_Free(statusConfig);

    return SECSuccess;

Here is the call graph for this function:

Here is the caller graph for this function:

static SECItem* ocsp_DigestValue ( PRArenaPool arena,
SECOidTag  digestAlg,
SECItem *  fill,
const SECItem *  src 
) [static]

Definition at line 1480 of file ocsp.c.

{
    const SECHashObject *digestObject;
    SECItem *result = NULL;
    void *mark = NULL;
    void *digestBuff = NULL;

    if ( arena != NULL ) {
        mark = PORT_ArenaMark(arena);
    }

    digestObject = HASH_GetHashObjectByOidTag(digestAlg);
    if ( digestObject == NULL ) {
        goto loser;
    }

    if (fill == NULL || fill->data == NULL) {
       result = SECITEM_AllocItem(arena, fill, digestObject->length);
       if ( result == NULL ) {
          goto loser;
       }
       digestBuff = result->data;
    } else {
       if (fill->len < digestObject->length) {
           PORT_SetError(SEC_ERROR_INVALID_ARGS);
           goto loser;
       }
       digestBuff = fill->data;
    }

    if (PK11_HashBuf(digestAlg, digestBuff,
                     src->data, src->len) != SECSuccess) {
        goto loser;
    }

    if ( arena != NULL ) {
        PORT_ArenaUnmark(arena, mark);
    }

    if (result == NULL) {
        result = fill;
    }
    return result;

loser:
    if (arena != NULL) {
        PORT_ArenaRelease(arena, mark);
    } else {
        if (result != NULL) {
            SECITEM_FreeItem(result, (fill == NULL) ? PR_TRUE : PR_FALSE);
        }
    }
    return(NULL);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static OCSPCacheItem* ocsp_FindCacheEntry ( OCSPCacheData *  cache,
CERTOCSPCertID *  certID 
) [static]

Definition at line 493 of file ocsp.c.

{
    OCSPCacheItem *found_ocsp_item = NULL;
    OCSP_TRACE(("OCSP ocsp_FindCacheEntry\n"));
    PR_EnterMonitor(OCSP_Global.monitor);
    if (ocsp_IsCacheDisabled())
        goto loser;
  
    found_ocsp_item = (OCSPCacheItem *)PL_HashTableLookup(
                          cache->entries, certID);
    if (!found_ocsp_item)
        goto loser;
  
    OCSP_TRACE(("OCSP ocsp_FindCacheEntry FOUND!\n"));
    ocsp_MakeCacheEntryMostRecent(cache, found_ocsp_item);

loser:
    PR_ExitMonitor(OCSP_Global.monitor);
    return found_ocsp_item;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static SECStatus ocsp_FinishDecodingSingleResponses ( PRArenaPool arena,
CERTOCSPSingleResponse **  responses 
) [static]

Definition at line 2242 of file ocsp.c.

{
    ocspCertStatus *certStatus;
    ocspCertStatusType certStatusType;
    const SEC_ASN1Template *certStatusTemplate;
    int derTag;
    int i;
    SECStatus rv = SECFailure;

    if (responses == NULL)                /* nothing to do */
       return SECSuccess;

    for (i = 0; responses[i] != NULL; i++) {
       /*
        * The following assert points out internal errors (problems in
        * the template definitions or in the ASN.1 decoder itself, etc.).
        */
       PORT_Assert(responses[i]->derCertStatus.data != NULL);

       derTag = responses[i]->derCertStatus.data[0] & SEC_ASN1_TAGNUM_MASK;
       certStatusType = ocsp_CertStatusTypeByTag(derTag);
       certStatusTemplate = ocsp_CertStatusTemplateByType(certStatusType);

       certStatus = PORT_ArenaZAlloc(arena, sizeof(ocspCertStatus));
       if (certStatus == NULL) {
           goto loser;
       }
       rv = SEC_ASN1DecodeItem(arena, certStatus, certStatusTemplate,
                            &responses[i]->derCertStatus);
       if (rv != SECSuccess) {
           if (PORT_GetError() == SEC_ERROR_BAD_DER)
              PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
           goto loser;
       }

       certStatus->certStatusType = certStatusType;
       responses[i]->certStatus = certStatus;
    }

    return SECSuccess;

loser:
    return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void ocsp_FreeCacheItem ( OCSPCacheItem *  item) [static]

Definition at line 515 of file ocsp.c.

{
    OCSP_TRACE(("OCSP ocsp_FreeCacheItem\n"));
    if (item->certStatusArena) {
        PORT_FreeArena(item->certStatusArena, PR_FALSE);
    }
    if (item->certID->poolp) {
        /* freeing this poolp arena will also free item */
        PORT_FreeArena(item->certID->poolp, PR_FALSE);
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void ocsp_FreshenCacheItemNextFetchAttemptTime ( OCSPCacheItem *  cacheItem) [static]

Definition at line 654 of file ocsp.c.

{
    PRTime now;
    PRTime earliestAllowedNextFetchAttemptTime;
    PRTime latestTimeWhenResponseIsConsideredFresh;
  
    OCSP_TRACE(("OCSP ocsp_FreshenCacheItemNextFetchAttemptTime\n"));

    PR_EnterMonitor(OCSP_Global.monitor);
  
    now = PR_Now();
    OCSP_TRACE_TIME("now:", now);
  
    if (cacheItem->haveThisUpdate) {
        OCSP_TRACE_TIME("thisUpdate:", cacheItem->thisUpdate);
        latestTimeWhenResponseIsConsideredFresh = cacheItem->thisUpdate +
            OCSP_Global.maximumSecondsToNextFetchAttempt * 
                MICROSECONDS_PER_SECOND;
        OCSP_TRACE_TIME("latestTimeWhenResponseIsConsideredFresh:", 
                        latestTimeWhenResponseIsConsideredFresh);
    } else {
        latestTimeWhenResponseIsConsideredFresh = now +
            OCSP_Global.minimumSecondsToNextFetchAttempt *
                MICROSECONDS_PER_SECOND;
        OCSP_TRACE_TIME("no thisUpdate, "
                        "latestTimeWhenResponseIsConsideredFresh:", 
                        latestTimeWhenResponseIsConsideredFresh);
    }
  
    if (cacheItem->haveNextUpdate) {
        OCSP_TRACE_TIME("have nextUpdate:", cacheItem->thisUpdate);
    }
  
    if (cacheItem->haveNextUpdate &&
        cacheItem->nextUpdate < latestTimeWhenResponseIsConsideredFresh) {
        latestTimeWhenResponseIsConsideredFresh = cacheItem->nextUpdate;
        OCSP_TRACE_TIME("nextUpdate is smaller than latestFresh, setting "
                        "latestTimeWhenResponseIsConsideredFresh:", 
                        latestTimeWhenResponseIsConsideredFresh);
    }
  
    earliestAllowedNextFetchAttemptTime = now +
        OCSP_Global.minimumSecondsToNextFetchAttempt * 
            MICROSECONDS_PER_SECOND;
    OCSP_TRACE_TIME("earliestAllowedNextFetchAttemptTime:", 
                    earliestAllowedNextFetchAttemptTime);
  
    if (latestTimeWhenResponseIsConsideredFresh < 
        earliestAllowedNextFetchAttemptTime) {
        latestTimeWhenResponseIsConsideredFresh = 
            earliestAllowedNextFetchAttemptTime;
        OCSP_TRACE_TIME("latest < earliest, setting latest to:", 
                        latestTimeWhenResponseIsConsideredFresh);
    }
  
    cacheItem->nextFetchAttemptTime = 
        latestTimeWhenResponseIsConsideredFresh;
    OCSP_TRACE_TIME("nextFetchAttemptTime", 
        latestTimeWhenResponseIsConsideredFresh);

    PR_ExitMonitor(OCSP_Global.monitor);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static SECStatus ocsp_GetCachedOCSPResponseStatusIfFresh ( CERTOCSPCertID *  certID,
int64  time,
SECStatus rv_ocsp 
) [static]

Definition at line 4464 of file ocsp.c.

{
    OCSPCacheItem *cacheItem = NULL;
    SECStatus rv = SECFailure;
  
    if (!certID || !rv_ocsp) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }
    *rv_ocsp = SECFailure;
  
    PR_EnterMonitor(OCSP_Global.monitor);
    cacheItem = ocsp_FindCacheEntry(&OCSP_Global.cache, certID);
    if (cacheItem && ocsp_IsCacheItemFresh(cacheItem)) {
        /* having an arena means, we have a cached certStatus */
        if (cacheItem->certStatusArena) {
            *rv_ocsp = ocsp_CertHasGoodStatus(&cacheItem->certStatus, time);
            rv = SECSuccess;
        } else {
            /*
             * No status cached, the previous attempt failed.
             * If OCSP is required, we never decide based on a failed attempt 
             * However, if OCSP is optional, a recent OCSP failure is
             * an allowed good state.
             */
            if (OCSP_Global.ocspFailureMode == 
                    ocspMode_FailureIsNotAVerificationFailure) {
                rv = SECSuccess;
                *rv_ocsp = SECSuccess;
            }
        }
    }
    PR_ExitMonitor(OCSP_Global.monitor);
    return rv;

Here is the call graph for this function:

Here is the caller graph for this function:

static ocspCheckingContext* ocsp_GetCheckingContext ( CERTCertDBHandle *  handle) [static]

Definition at line 3905 of file ocsp.c.

{
    CERTStatusConfig *statusConfig;
    ocspCheckingContext *ocspcx = NULL;

    statusConfig = CERT_GetStatusConfig(handle);
    if (statusConfig != NULL) {
       ocspcx = statusConfig->statusContext;

       /*
        * This is actually an internal error, because we should never
        * have a good statusConfig without a good statusContext, too.
        * For lack of anything better, though, we just assert and use
        * the same error as if there were no statusConfig (set below).
        */
       PORT_Assert(ocspcx != NULL);
    }

    if (ocspcx == NULL)
       PORT_SetError(SEC_ERROR_OCSP_NOT_ENABLED);

    return ocspcx;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static SECItem* ocsp_GetEncodedOCSPResponseForSingleCert ( PRArenaPool arena,
CERTOCSPCertID *  certID,
CERTCertificate *  singleCert,
char *  location,
int64  time,
PRBool  addServiceLocator,
void pwArg,
CERTOCSPRequest **  pRequest 
) [static]

Definition at line 3395 of file ocsp.c.

{
    CERTOCSPRequest *request;
    request = cert_CreateSingleCertOCSPRequest(certID, singleCert, time, 
                                               addServiceLocator);
    if (!request)
        return NULL;
    return ocsp_GetEncodedOCSPResponseFromRequest(arena, request, location, 
                                                  time, addServiceLocator, 
                                                  pwArg, pRequest);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static SECItem * ocsp_GetEncodedOCSPResponseFromRequest ( PRArenaPool arena,
CERTOCSPRequest *  request,
char *  location,
int64  time,
PRBool  addServiceLocator,
void pwArg,
CERTOCSPRequest **  pRequest 
) [static]

Definition at line 3335 of file ocsp.c.

{
    SECItem *encodedRequest = NULL;
    SECItem *encodedResponse = NULL;
    PRFileDesc *sock = NULL;
    SECStatus rv;
    const SEC_HttpClientFcn *registeredHttpClient = NULL;

    rv = CERT_AddOCSPAcceptableResponses(request,
                                    SEC_OID_PKIX_OCSP_BASIC_RESPONSE);
    if (rv != SECSuccess)
       goto loser;

    encodedRequest = CERT_EncodeOCSPRequest(NULL, request, pwArg);
    if (encodedRequest == NULL)
       goto loser;

    registeredHttpClient = GetRegisteredHttpClient();

    if (registeredHttpClient
            &&
            registeredHttpClient->version == 1) {
        encodedResponse = fetchOcspHttpClientV1(
                              arena,
                              &registeredHttpClient->fcnTable.ftable1,
                              location,
                              encodedRequest);
    }
    else {
      /* use internal http client */
    
      sock = ocsp_SendEncodedRequest(location, encodedRequest);
      if (sock == NULL)
         goto loser;

      encodedResponse = ocsp_GetEncodedResponse(arena, sock);
    }

    if (encodedResponse != NULL && pRequest != NULL) {
       *pRequest = request;
       request = NULL;                    /* avoid destroying below */
    }

loser:
    if (request != NULL)
       CERT_DestroyOCSPRequest(request);
    if (encodedRequest != NULL)
       SECITEM_FreeItem(encodedRequest, PR_TRUE);
    if (sock != NULL)
       PR_Close(sock);

    return encodedResponse;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static SECItem* ocsp_GetEncodedResponse ( PRArenaPool arena,
PRFileDesc sock 
) [static]

Definition at line 2941 of file ocsp.c.

{
    /* first read HTTP status line and headers */

    char* inBuffer = NULL;
    PRInt32 offset = 0;
    PRInt32 inBufsize = 0;
    const PRInt32 bufSizeIncrement = OCSP_BUFSIZE; /* 1 KB at a time */
    const PRInt32 maxBufSize = 8 * bufSizeIncrement ; /* 8 KB max */
    const char* CRLF = "\r\n";
    const PRInt32 CRLFlen = strlen(CRLF);
    const char* headerEndMark = "\r\n\r\n";
    const PRInt32 markLen = strlen(headerEndMark);
    const PRIntervalTime ocsptimeout =
        PR_SecondsToInterval(30); /* hardcoded to 30s for now */
    char* headerEnd = NULL;
    PRBool EOS = PR_FALSE;
    const char* httpprotocol = "HTTP/";
    const PRInt32 httplen = strlen(httpprotocol);
    const char* httpcode = NULL;
    const char* contenttype = NULL;
    PRInt32 contentlength = 0;
    PRInt32 bytesRead = 0;
    char* statusLineEnd = NULL;
    char* space = NULL;
    char* nextHeader = NULL;
    SECItem* result = NULL;

    /* read up to at least the end of the HTTP headers */
    do
    {
        inBufsize += bufSizeIncrement;
        inBuffer = PORT_Realloc(inBuffer, inBufsize+1);
        if (NULL == inBuffer)
        {
            AbortHttpDecode(SEC_ERROR_NO_MEMORY);
        }
        bytesRead = ocsp_read(sock, inBuffer + offset, bufSizeIncrement,
            ocsptimeout);
        if (bytesRead > 0)
        {
            PRInt32 searchOffset = (offset - markLen) >0 ? offset-markLen : 0;
            offset += bytesRead;
            *(inBuffer + offset) = '\0'; /* NULL termination */
            headerEnd = strstr((const char*)inBuffer + searchOffset, headerEndMark);
            if (bytesRead < bufSizeIncrement)
            {
                /* we read less data than requested, therefore we are at
                   EOS or there was a read error */
                EOS = PR_TRUE;
            }
        }
        else
        {
            /* recv error or EOS */
            EOS = PR_TRUE;
        }
    } while ( (!headerEnd) && (PR_FALSE == EOS) &&
              (inBufsize < maxBufSize) );

    if (!headerEnd)
    {
        AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE);
    }

    /* parse the HTTP status line  */
    statusLineEnd = strstr((const char*)inBuffer, CRLF);
    if (!statusLineEnd)
    {
        AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE);
    }
    *statusLineEnd = '\0';

    /* check for HTTP/ response */
    space = strchr((const char*)inBuffer, ' ');
    if (!space || PORT_Strncasecmp((const char*)inBuffer, httpprotocol, httplen) != 0 )
    {
        AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE);
    }

    /* check the HTTP status code of 200 */
    httpcode = space +1;
    space = strchr(httpcode, ' ');
    if (!space)
    {
        AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE);
    }
    *space = 0;
    if (0 != strcmp(httpcode, "200"))
    {
        AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE);
    }

    /* parse the HTTP headers in the buffer . We only care about
       content-type and content-length
    */

    nextHeader = statusLineEnd + CRLFlen;
    *headerEnd = '\0'; /* terminate */
    do
    {
        char* thisHeaderEnd = NULL;
        char* value = NULL;
        char* colon = strchr(nextHeader, ':');
        
        if (!colon)
        {
            AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE);
        }

        *colon = '\0';
        value = colon + 1;

        /* jpierre - note : the following code will only handle the basic form
           of HTTP/1.0 response headers, of the form "name: value" . Headers
           split among multiple lines are not supported. This is not common
           and should not be an issue, but it could become one in the
           future */

        if (*value != ' ')
        {
            AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE);
        }

        value++;
        thisHeaderEnd  = strstr(value, CRLF);
        if (thisHeaderEnd )
        {
            *thisHeaderEnd  = '\0';
        }

        if (0 == PORT_Strcasecmp(nextHeader, "content-type"))
        {
            contenttype = value;
        }
        else
        if (0 == PORT_Strcasecmp(nextHeader, "content-length"))
        {
            contentlength = atoi(value);
        }

        if (thisHeaderEnd )
        {
            nextHeader = thisHeaderEnd + CRLFlen;
        }
        else
        {
            nextHeader = NULL;
        }

    } while (nextHeader && (nextHeader < (headerEnd + CRLFlen) ) );

    /* check content-type */
    if (!contenttype ||
        (0 != PORT_Strcasecmp(contenttype, "application/ocsp-response")) )
    {
        AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE);
    }

    /* read the body of the OCSP response */
    offset = offset - (PRInt32) (headerEnd - (const char*)inBuffer) - markLen;
    if (offset)
    {
        /* move all data to the beginning of the buffer */
        PORT_Memmove(inBuffer, headerEnd + markLen, offset);
    }

    /* resize buffer to only what's needed to hold the current response */
    inBufsize = (1 + (offset-1) / bufSizeIncrement ) * bufSizeIncrement ;

    while ( (PR_FALSE == EOS) &&
            ( (contentlength == 0) || (offset < contentlength) ) &&
            (inBufsize < maxBufSize)
            )
    {
        /* we still need to receive more body data */
        inBufsize += bufSizeIncrement;
        inBuffer = PORT_Realloc(inBuffer, inBufsize+1);
        if (NULL == inBuffer)
        {
            AbortHttpDecode(SEC_ERROR_NO_MEMORY);
        }
        bytesRead = ocsp_read(sock, inBuffer + offset, bufSizeIncrement,
                              ocsptimeout);
        if (bytesRead > 0)
        {
            offset += bytesRead;
            if (bytesRead < bufSizeIncrement)
            {
                /* we read less data than requested, therefore we are at
                   EOS or there was a read error */
                EOS = PR_TRUE;
            }
        }
        else
        {
            /* recv error or EOS */
            EOS = PR_TRUE;
        }
    }

    if (0 == offset)
    {
        AbortHttpDecode(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE);
    }

    /*
     * Now allocate the item to hold the data.
     */
    result = SECITEM_AllocItem(arena, NULL, offset);
    if (NULL == result)
    {
        AbortHttpDecode(SEC_ERROR_NO_MEMORY);
    }

    /*
     * And copy the data left in the buffer.
    */
    PORT_Memcpy(result->data, inBuffer, offset);

    /* and free the temporary buffer */
    PORT_Free(inBuffer);
    return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static SECStatus ocsp_GetOCSPStatusFromNetwork ( CERTCertDBHandle *  handle,
CERTOCSPCertID *  certID,
CERTCertificate *  cert,
int64  time,
void pwArg,
PRBool certIDWasConsumed,
SECStatus rv_ocsp 
) [static]

Definition at line 4596 of file ocsp.c.

{
    char *location = NULL;
    PRBool locationIsDefault;
    SECItem *encodedResponse = NULL;
    CERTOCSPRequest *request = NULL;
    CERTOCSPResponse *response = NULL;
    CERTCertificate *signerCert = NULL;
    CERTCertificate *issuerCert = NULL;
    SECStatus rv = SECFailure;
    CERTOCSPSingleResponse *single = NULL;

    if (!certIDWasConsumed || !rv_ocsp) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }
    *certIDWasConsumed = PR_FALSE;
    *rv_ocsp = SECFailure;

    /*
     * The first thing we need to do is find the location of the responder.
     * This will be the value of the default responder (if enabled), else
     * it will come out of the AIA extension in the cert (if present).
     * If we have no such location, then this cert does not "deserve" to
     * be checked -- that is, we consider it a success and just return.
     * The way we tell that is by looking at the error number to see if
     * the problem was no AIA extension was found; any other error was
     * a true failure that we unfortunately have to treat as an overall
     * failure here.
     */
    location = ocsp_GetResponderLocation(handle, cert, &locationIsDefault);
    if (location == NULL) {
       int err = PORT_GetError();
       if (err == SEC_ERROR_EXTENSION_NOT_FOUND ||
           err == SEC_ERROR_CERT_BAD_ACCESS_LOCATION) {
           PORT_SetError(0);
           *rv_ocsp = SECSuccess;
           return SECSuccess;
       }
       return SECFailure;
    }

    /*
     * XXX In the fullness of time, we will want/need to handle a
     * certificate chain.  This will be done either when a new parameter
     * tells us to, or some configuration variable tells us to.  In any
     * case, handling it is complicated because we may need to send as
     * many requests (and receive as many responses) as we have certs
     * in the chain.  If we are going to talk to a default responder,
     * and we only support one default responder, we can put all of the
     * certs together into one request.  Otherwise, we must break them up
     * into multiple requests.  (Even if all of the requests will go to
     * the same location, the signature on each response will be different,
     * because each issuer is different.  Carefully read the OCSP spec
     * if you do not understand this.)
     */

    /*
     * XXX If/when signing of requests is supported, that second NULL
     * should be changed to be the signer certificate.  Not sure if that
     * should be passed into this function or retrieved via some operation
     * on the handle/context.
     */
    encodedResponse = 
        ocsp_GetEncodedOCSPResponseForSingleCert(NULL, certID, cert, location,
                                                 time, locationIsDefault,
                                                 pwArg, &request);
    if (encodedResponse == NULL) {
        goto loser;
    }

    response = CERT_DecodeOCSPResponse(encodedResponse);
    if (response == NULL) {
       goto loser;
    }

    /*
     * Okay, we at least have a response that *looks* like a response!
     * Now see if the overall response status value is good or not.
     * If not, we set an error and give up.  (It means that either the
     * server had a problem, or it didn't like something about our
     * request.  Either way there is nothing to do but give up.)
     * Otherwise, we continue to find the actual per-cert status
     * in the response.
     */
    if (CERT_GetOCSPResponseStatus(response) != SECSuccess) {
       goto loser;
    }

    /*
     * If we've made it this far, we expect a response with a good signature.
     * So, check for that.
     */
    issuerCert = CERT_FindCertIssuer(cert, time, certUsageAnyCA);
    rv = CERT_VerifyOCSPResponseSignature(response, handle, pwArg, &signerCert,
                     issuerCert);
    if (rv != SECSuccess)
       goto loser;

    PORT_Assert(signerCert != NULL);      /* internal consistency check */
    /* XXX probably should set error, return failure if signerCert is null */


    /*
     * Again, we are only doing one request for one cert.
     * XXX When we handle cert chains, the following code will obviously
     * have to be modified, in coordation with the code above that will
     * have to determine how to make multiple requests, etc. 
     */

    rv = ocsp_GetVerifiedSingleResponseForCertID(handle, response, certID, 
                                                 signerCert, time, &single);
    if (rv != SECSuccess)
        goto loser;

    *rv_ocsp = ocsp_SingleResponseCertHasGoodStatus(single, time);

loser:
    PR_EnterMonitor(OCSP_Global.monitor);
    if (OCSP_Global.maxCacheEntries >= 0) {
        /* single == NULL means: remember response failure */
        ocsp_CreateOrUpdateCacheEntry(&OCSP_Global.cache, certID, single, 
                                      certIDWasConsumed);
        /* ignore cache update failures */
    }
    PR_ExitMonitor(OCSP_Global.monitor);

    if (issuerCert != NULL)
       CERT_DestroyCertificate(issuerCert);
    if (signerCert != NULL)
       CERT_DestroyCertificate(signerCert);
    if (response != NULL)
       CERT_DestroyOCSPResponse(response);
    if (request != NULL)
       CERT_DestroyOCSPRequest(request);
    if (encodedResponse != NULL)
       SECITEM_FreeItem(encodedResponse, PR_TRUE);
    if (location != NULL)
       PORT_Free(location);
    return rv;

Here is the call graph for this function:

Here is the caller graph for this function:

static char* ocsp_GetResponderLocation ( CERTCertDBHandle *  handle,
CERTCertificate *  cert,
PRBool isDefault 
) [static]

Definition at line 4376 of file ocsp.c.

{
    ocspCheckingContext *ocspcx;

    ocspcx = ocsp_GetCheckingContext(handle);
    if (ocspcx != NULL && ocspcx->useDefaultResponder) {
       /*
        * A default responder wins out, if specified.
        * XXX Someday this may be a more complicated determination based
        * on the cert's issuer.  (That is, we could have different default
        * responders configured for different issuers.)
        */
       PORT_Assert(ocspcx->defaultResponderURI != NULL);
       *isDefault = PR_TRUE;
       return (PORT_Strdup(ocspcx->defaultResponderURI));
    }

    /*
     * No default responder set up, so go see if we can find an AIA
     * extension that has a value for OCSP, and get the url from that.
     */
    *isDefault = PR_FALSE;
    return CERT_GetOCSPAuthorityInfoAccessLocation(cert);

Here is the call graph for this function:

Here is the caller graph for this function:

static ocspResponseData* ocsp_GetResponseData ( CERTOCSPResponse *  response,
SECItem **  tbsResponseDataDER 
) [static]

Definition at line 2545 of file ocsp.c.

{
    ocspBasicOCSPResponse *basic;
    ocspResponseData *responseData;

    PORT_Assert(response != NULL);

    PORT_Assert(response->responseBytes != NULL);

    PORT_Assert(response->responseBytes->responseTypeTag
              == SEC_OID_PKIX_OCSP_BASIC_RESPONSE);

    basic = response->responseBytes->decodedResponse.basic;
    PORT_Assert(basic != NULL);

    responseData = basic->tbsResponseData;
    PORT_Assert(responseData != NULL);

    if (tbsResponseDataDER) {
        *tbsResponseDataDER = &basic->tbsResponseDataDER;

        PORT_Assert((*tbsResponseDataDER)->data != NULL);
        PORT_Assert((*tbsResponseDataDER)->len != 0);
    }

    return responseData;
}

Here is the caller graph for this function:

static ocspSignature* ocsp_GetResponseSignature ( CERTOCSPResponse *  response) [static]

Definition at line 2578 of file ocsp.c.

{
    ocspBasicOCSPResponse *basic;

    PORT_Assert(response != NULL);
    if (NULL == response->responseBytes) {
        return NULL;
    }
    PORT_Assert(response->responseBytes != NULL);
    PORT_Assert(response->responseBytes->responseTypeTag
              == SEC_OID_PKIX_OCSP_BASIC_RESPONSE);

    basic = response->responseBytes->decodedResponse.basic;
    PORT_Assert(basic != NULL);

    return &(basic->responseSignature);
}

Here is the caller graph for this function:

static CERTOCSPSingleResponse* ocsp_GetSingleResponseForCertID ( CERTOCSPSingleResponse **  responses,
CERTCertDBHandle *  handle,
CERTOCSPCertID *  certID 
) [static]

Definition at line 3875 of file ocsp.c.

{
    CERTOCSPSingleResponse *single;
    int i;

    if (responses == NULL)
       return NULL;

    for (i = 0; responses[i] != NULL; i++) {
       single = responses[i];
       if (ocsp_CertIDsMatch(handle, certID, single->certID)) {
           return single;
       }
    }

    /*
     * The OCSP server should have included a response even if it knew
     * nothing about the certificate in question.  Since it did not,
     * this will make it look as if it had.
     * 
     * XXX Should we make this a separate error to notice the server's
     * bad behavior?
     */
    PORT_SetError(SEC_ERROR_OCSP_UNKNOWN_CERT);
    return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static SECStatus ocsp_GetVerifiedSingleResponseForCertID ( CERTCertDBHandle *  handle,
CERTOCSPResponse *  response,
CERTOCSPCertID *  certID,
CERTCertificate *  signerCert,
int64  time,
CERTOCSPSingleResponse **  pSingleResponse 
) [static]

Definition at line 4745 of file ocsp.c.

{
    SECStatus rv;
    ocspResponseData *responseData;
    int64 producedAt;
    CERTOCSPSingleResponse *single;

    /*
     * The ResponseData part is the real guts of the response.
     */
    responseData = ocsp_GetResponseData(response, NULL);
    if (responseData == NULL) {
        rv = SECFailure;
        goto loser;
    }

    /*
     * There is one producedAt time for the entire response (and a separate
     * thisUpdate time for each individual single response).  We need to
     * compare them, so get the overall time to pass into the check of each
     * single response.
     */
    rv = DER_GeneralizedTimeToTime(&producedAt, &responseData->producedAt);
    if (rv != SECSuccess)
        goto loser;

    single = ocsp_GetSingleResponseForCertID(responseData->responses,
                                             handle, certID);
    if (single == NULL) {
        rv = SECFailure;
        goto loser;
    }

    rv = ocsp_VerifySingleResponse(single, handle, signerCert, producedAt);
    if (rv != SECSuccess)
        goto loser;
    *pSingleResponse = single;

loser:
    return rv;

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 840 of file ocsp.c.

{
    SECStatus rv = SECFailure;

    if (OCSP_Global.monitor == NULL) {
        OCSP_Global.monitor = PR_NewMonitor();
    }
    if (!OCSP_Global.monitor)
        return SECFailure;

    PR_EnterMonitor(OCSP_Global.monitor);
    if (!OCSP_Global.cache.entries) {
        OCSP_Global.cache.entries = 
            PL_NewHashTable(0, 
                            ocsp_CacheKeyHashFunction, 
                            ocsp_CacheKeyCompareFunction, 
                            PL_CompareValues, 
                            NULL, 
                            NULL);
        OCSP_Global.ocspFailureMode = ocspMode_FailureIsVerificationFailure;
        OCSP_Global.cache.numberOfEntries = 0;
        OCSP_Global.cache.MRUitem = NULL;
        OCSP_Global.cache.LRUitem = NULL;
    } else {
        /*
         * NSS might call this function twice while attempting to init.
         * But it's not allowed to call this again after any activity.
         */
        PORT_Assert(OCSP_Global.cache.numberOfEntries == 0);
        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
    }
    if (OCSP_Global.cache.entries)
        rv = SECSuccess;
    PR_ExitMonitor(OCSP_Global.monitor);
    return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static SECStatus ocsp_InitStatusChecking ( CERTCertDBHandle *  handle) [static]

Definition at line 4905 of file ocsp.c.

{
    CERTStatusConfig *statusConfig = NULL;
    ocspCheckingContext *statusContext = NULL;

    PORT_Assert(CERT_GetStatusConfig(handle) == NULL);
    if (CERT_GetStatusConfig(handle) != NULL) {
       /* XXX or call statusConfig->statusDestroy and continue? */
       return SECFailure;
    }

    statusConfig = PORT_ZNew(CERTStatusConfig);
    if (statusConfig == NULL)
       goto loser;

    statusContext = PORT_ZNew(ocspCheckingContext);
    if (statusContext == NULL)
       goto loser;

    statusConfig->statusDestroy = ocsp_DestroyStatusChecking;
    statusConfig->statusContext = statusContext;

    CERT_SetStatusConfig(handle, statusConfig);

    return SECSuccess;

loser:
    if (statusConfig != NULL)
       PORT_Free(statusConfig);
    return SECFailure;

Here is the call graph for this function:

Here is the caller graph for this function:

static PRBool ocsp_IsCacheDisabled ( ) [static]

Definition at line 479 of file ocsp.c.

{
    /* 
     * maxCacheEntries == 0 means unlimited cache entries
     * maxCacheEntries  < 0 means cache is disabled
     */
    PRBool retval;
    PR_EnterMonitor(OCSP_Global.monitor);
    retval = (OCSP_Global.maxCacheEntries < 0);
    PR_ExitMonitor(OCSP_Global.monitor);
    return retval;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static PRBool ocsp_IsCacheItemFresh ( OCSPCacheItem *  cacheItem) [static]

Definition at line 718 of file ocsp.c.

{
    PRTime now;
    PRBool retval;

    PR_EnterMonitor(OCSP_Global.monitor);
    now = PR_Now();
    retval = (cacheItem->nextFetchAttemptTime > now);
    OCSP_TRACE(("OCSP ocsp_IsCacheItemFresh: %d\n", retval));
    PR_ExitMonitor(OCSP_Global.monitor);
    return retval;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void ocsp_MakeCacheEntryMostRecent ( OCSPCacheData *  cache,
OCSPCacheItem *  new_most_recent 
) [static]

Definition at line 462 of file ocsp.c.

{
    OCSP_TRACE(("OCSP ocsp_MakeCacheEntryMostRecent THREADID %p\n", 
                PR_GetCurrentThread()));
    PR_EnterMonitor(OCSP_Global.monitor);
    if (cache->MRUitem == new_most_recent) {
        OCSP_TRACE(("OCSP ocsp_MakeCacheEntryMostRecent ALREADY MOST\n"));
        PR_ExitMonitor(OCSP_Global.monitor);
        return;
    }
    OCSP_TRACE(("OCSP ocsp_MakeCacheEntryMostRecent NEW entry\n"));
    ocsp_RemoveCacheItemFromLinkedList(cache, new_most_recent);
    ocsp_AddCacheItemToLinkedList(cache, new_most_recent);
    PR_ExitMonitor(OCSP_Global.monitor);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static PRBool ocsp_matchcert ( SECItem *  certIndex,
CERTCertificate *  testCert 
) [static]

Definition at line 3492 of file ocsp.c.

{
    SECItem item;
    unsigned char buf[HASH_LENGTH_MAX];

    item.data = buf;
    item.len = SHA1_LENGTH;

    if (cert_GetSPKIDigest(NULL,testCert,SEC_OID_SHA1, &item) == NULL) {
       return PR_FALSE;
    }
    if  (SECITEM_ItemsAreEqual(certIndex,&item)) {
       return PR_TRUE;
    }
    if (cert_GetSPKIDigest(NULL,testCert,SEC_OID_MD5, &item) == NULL) {
       return PR_FALSE;
    }
    if  (SECITEM_ItemsAreEqual(certIndex,&item)) {
       return PR_TRUE;
    }
    if (cert_GetSPKIDigest(NULL,testCert,SEC_OID_MD2, &item) == NULL) {
       return PR_FALSE;
    }
    if  (SECITEM_ItemsAreEqual(certIndex,&item)) {
       return PR_TRUE;
    }

    return PR_FALSE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static SECStatus ocsp_ParseURL ( char *  url,
char **  pHostname,
PRUint16 pPort,
char **  pPath 
) [static]

Definition at line 2645 of file ocsp.c.

{
    unsigned short port = 80;             /* default, in case not in url */
    char *hostname = NULL;
    char *path = NULL;
    char *save;
    char c;
    int len;

    if (url == NULL)
       goto loser;

    /*
     * Skip beginning whitespace.
     */
    c = *url;
    while ((c == ' ' || c == '\t') && c != '\0') {
       url++;
       c = *url;
    }
    if (c == '\0')
       goto loser;

    /*
     * Confirm, then skip, protocol.  (Since we only know how to do http,
     * that is all we will accept).
     */
    if (PORT_Strncasecmp(url, "http://", 7) != 0)
       goto loser;
    url += 7;

    /*
     * Whatever comes next is the hostname (or host IP address).  We just
     * save it aside and then search for its end so we can determine its
     * length and copy it.
     *
     * XXX Note that because we treat a ':' as a terminator character
     * (and below, we expect that to mean there is a port specification
     * immediately following), we will not handle IPv6 addresses.  That is
     * apparently an acceptable limitation, for the time being.  Some day,
     * when there is a clear way to specify a URL with an IPv6 address that
     * can be parsed unambiguously, this code should be made to do that.
     */
    save = url;
    c = *url;
    while (c != '/' && c != ':' && c != '\0' && c != ' ' && c != '\t') {
       url++;
       c = *url;
    }
    len = url - save;
    hostname = PORT_Alloc(len + 1);
    if (hostname == NULL)
       goto loser;
    PORT_Memcpy(hostname, save, len);
    hostname[len] = '\0';

    /*
     * Now we figure out if there was a port specified or not.
     * If so, we need to parse it (as a number) and skip it.
     */
    if (c == ':') {
       url++;
       port = (unsigned short) PORT_Atoi(url);
       c = *url;
       while (c != '/' && c != '\0' && c != ' ' && c != '\t') {
           if (c < '0' || c > '9')
              goto loser;
           url++;
           c = *url;
       }
    }

    /*
     * Last thing to find is a path.  There *should* be a slash,
     * if nothing else -- but if there is not we provide one.
     */
    if (c == '/') {
       save = url;
       while (c != '\0' && c != ' ' && c != '\t') {
           url++;
           c = *url;
       }
       len = url - save;
       path = PORT_Alloc(len + 1);
       if (path == NULL)
           goto loser;
       PORT_Memcpy(path, save, len);
       path[len] = '\0';
    } else {
       path = PORT_Strdup("/");
       if (path == NULL)
           goto loser;
    }

    *pHostname = hostname;
    *pPort = port;
    *pPath = path;
    return SECSuccess;

loser:
    if (hostname != NULL)
       PORT_Free(hostname);
    PORT_SetError(SEC_ERROR_CERT_BAD_ACCESS_LOCATION);
    return SECFailure;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static CERTOCSPRequest* ocsp_prepareEmptyOCSPRequest ( ) [static]

Definition at line 1879 of file ocsp.c.

{
    PRArenaPool *arena = NULL;
    CERTOCSPRequest *request = NULL;
    ocspTBSRequest *tbsRequest = NULL;

    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    if (arena == NULL) {
        goto loser;
    }
    request = PORT_ArenaZNew(arena, CERTOCSPRequest);
    if (request == NULL) {
        goto loser;
    }
    request->arena = arena;

    tbsRequest = PORT_ArenaZNew(arena, ocspTBSRequest);
    if (tbsRequest == NULL) {
        goto loser;
    }
    request->tbsRequest = tbsRequest;
    /* version 1 is the default, so we need not fill in a version number */
    return request;

loser:
    if (arena != NULL) {
        PORT_FreeArena(arena, PR_FALSE);
    }
    return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int ocsp_read ( PRFileDesc fd,
char *  buf,
int  toread,
PRIntervalTime  timeout 
) [static]

Definition at line 2892 of file ocsp.c.

{
    int total = 0;

    while (total < toread)
    {
        PRInt32 got;

        got = PR_Recv(fd, buf + total, (PRInt32) (toread - total), 0, timeout);
        if (got < 0)
        {
            if (0 == total)
            {
                total = -1; /* report the error if we didn't read anything yet */
            }
            break;
        }
        else
        if (got == 0)
        {                   /* EOS */
            break;
        }

        total += got;
    }

    return total;
}

Here is the caller graph for this function:

static void ocsp_RemoveCacheItem ( OCSPCacheData *  cache,
OCSPCacheItem *  item 
) [static]

Definition at line 528 of file ocsp.c.

{
    /* The item we're removing could be either the least recently used item,
     * or it could be an item that couldn't get updated with newer status info
     * because of an allocation failure, or it could get removed because we're 
     * cleaning up.
     */
    PRBool couldRemoveFromHashTable;
    OCSP_TRACE(("OCSP ocsp_RemoveCacheItem, THREADID %p\n", PR_GetCurrentThread()));
    PR_EnterMonitor(OCSP_Global.monitor);

    ocsp_RemoveCacheItemFromLinkedList(cache, item);
    couldRemoveFromHashTable = PL_HashTableRemove(cache->entries, 
                                                  item->certID);
    PORT_Assert(couldRemoveFromHashTable);
    --cache->numberOfEntries;
    ocsp_FreeCacheItem(item);
    PR_ExitMonitor(OCSP_Global.monitor);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void ocsp_RemoveCacheItemFromLinkedList ( OCSPCacheData *  cache,
OCSPCacheItem *  item 
) [static]

Definition at line 407 of file ocsp.c.

{
    PR_EnterMonitor(OCSP_Global.monitor);

    if (!item->lessRecent && !item->moreRecent) {
        /*
         * Fail gracefully on attempts to remove an item from the list,
         * which is currently not part of the list.
         * But check for the edge case it is the single entry in the list.
         */
        if (item == cache->LRUitem &&
            item == cache->MRUitem) {
            /* remove the single entry */
            PORT_Assert(cache->numberOfEntries == 1);
            PORT_Assert(item->moreRecent == NULL);
            cache->MRUitem = NULL;
            cache->LRUitem = NULL;
        }
        PR_ExitMonitor(OCSP_Global.monitor);
        return;
    }

    PORT_Assert(cache->numberOfEntries > 1);
  
    if (item == cache->LRUitem) {
        PORT_Assert(item != cache->MRUitem);
        PORT_Assert(item->lessRecent == NULL);
        PORT_Assert(item->moreRecent != NULL);
        PORT_Assert(item->moreRecent->lessRecent == item);
        cache->LRUitem = item->moreRecent;
        cache->LRUitem->lessRecent = NULL;
    }
    else if (item == cache->MRUitem) {
        PORT_Assert(item->moreRecent == NULL);
        PORT_Assert(item->lessRecent != NULL);
        PORT_Assert(item->lessRecent->moreRecent == item);
        cache->MRUitem = item->lessRecent;
        cache->MRUitem->moreRecent = NULL;
    } else {
        /* remove an entry in the middle of the list */
        PORT_Assert(item->moreRecent != NULL);
        PORT_Assert(item->lessRecent != NULL);
        PORT_Assert(item->lessRecent->moreRecent == item);
        PORT_Assert(item->moreRecent->lessRecent == item);
        item->moreRecent->lessRecent = item->lessRecent;
        item->lessRecent->moreRecent = item->moreRecent;
    }

    item->lessRecent = NULL;
    item->moreRecent = NULL;

    PR_ExitMonitor(OCSP_Global.monitor);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 2157 of file ocsp.c.

{
    const SEC_ASN1Template *responderIDTemplate;

    switch (responderIDType) {
       case ocspResponderID_byName:
           responderIDTemplate = ocsp_ResponderIDByNameTemplate;
           break;
       case ocspResponderID_byKey:
           responderIDTemplate = ocsp_ResponderIDByKeyTemplate;
           break;
       case ocspResponderID_other:
       default:
           PORT_Assert(responderIDType == ocspResponderID_other);
           responderIDTemplate = ocsp_ResponderIDOtherTemplate;
           break;
    }

    return responderIDTemplate;
}

Here is the caller graph for this function:

static ocspResponderIDType ocsp_ResponderIDTypeByTag ( int  derTag) [static]

Definition at line 2293 of file ocsp.c.

{
    ocspResponderIDType responderIDType;

    switch (derTag) {
       case 1:
           responderIDType = ocspResponderID_byName;
           break;
       case 2:
           responderIDType = ocspResponderID_byKey;
           break;
       default:
           responderIDType = ocspResponderID_other;
           break;
    }

    return responderIDType;
}

Here is the caller graph for this function:

static PRFileDesc* ocsp_SendEncodedRequest ( char *  location,
SECItem *  encodedRequest 
) [static]

Definition at line 2827 of file ocsp.c.

{
    char *hostname = NULL;
    char *path = NULL;
    PRUint16 port;
    SECStatus rv;
    PRFileDesc *sock = NULL;
    PRFileDesc *returnSock = NULL;
    char *header = NULL;

    /*
     * Take apart the location, getting the hostname, port, and path.
     */
    rv = ocsp_ParseURL(location, &hostname, &port, &path);
    if (rv != SECSuccess)
       goto loser;

    PORT_Assert(hostname != NULL);
    PORT_Assert(path != NULL);

    sock = ocsp_ConnectToHost(hostname, port);
    if (sock == NULL)
       goto loser;

    header = PR_smprintf("POST %s HTTP/1.0\r\n"
                      "Host: %s:%d\r\n"
                      "Content-Type: application/ocsp-request\r\n"
                      "Content-Length: %u\r\n\r\n",
                      path, hostname, port, encodedRequest->len);
    if (header == NULL)
       goto loser;

    /*
     * The NSPR documentation promises that if it can, it will write the full
     * amount; this will not return a partial value expecting us to loop.
     */
    if (PR_Write(sock, header, (PRInt32) PORT_Strlen(header)) < 0)
       goto loser;

    if (PR_Write(sock, encodedRequest->data,
               (PRInt32) encodedRequest->len) < 0)
       goto loser;

    returnSock = sock;
    sock = NULL;

loser:
    if (header != NULL)
       PORT_Free(header);
    if (sock != NULL)
       PR_Close(sock);
    if (path != NULL)
       PORT_Free(path);
    if (hostname != NULL)
       PORT_Free(hostname);

    return returnSock;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static SECStatus ocsp_SetCacheItemResponse ( OCSPCacheItem *  item,
const CERTOCSPSingleResponse *  response 
) [static]

Definition at line 618 of file ocsp.c.

{
    if (item->certStatusArena) {
        PORT_FreeArena(item->certStatusArena, PR_FALSE);
        item->certStatusArena = NULL;
    }
    item->haveThisUpdate = item->haveNextUpdate = PR_FALSE;
    if (response) {
        SECStatus rv;
        item->certStatusArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
        if (item->certStatusArena == NULL) {
            return SECFailure;
        }
        rv = ocsp_CopyCertStatus(item->certStatusArena, &item->certStatus, 
                                 response->certStatus);
        if (rv != SECSuccess) {
            PORT_FreeArena(item->certStatusArena, PR_FALSE);
            item->certStatusArena = NULL;
            return rv;
        }
        rv = DER_GeneralizedTimeToTime(&item->thisUpdate, 
                                       &response->thisUpdate);
        item->haveThisUpdate = (rv == SECSuccess);
        if (response->nextUpdate) {
            rv = DER_GeneralizedTimeToTime(&item->nextUpdate, 
                                           response->nextUpdate);
            item->haveNextUpdate = (rv == SECSuccess);
        } else {
            item->haveNextUpdate = PR_FALSE;
        }
    }
    return SECSuccess;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 877 of file ocsp.c.

Here is the call graph for this function:

Here is the caller graph for this function:

static SECStatus ocsp_SingleResponseCertHasGoodStatus ( CERTOCSPSingleResponse *  single,
int64  time 
) [static]

Definition at line 4457 of file ocsp.c.

{
    return ocsp_CertHasGoodStatus(single->certStatus, time);

Here is the call graph for this function:

Here is the caller graph for this function:

static PRBool ocsp_TimeIsRecent ( int64  checkTime) [static]

Definition at line 4131 of file ocsp.c.

{
    int64 now = PR_Now();
    int64 lapse, tmp;

    LL_I2L(lapse, OCSP_ALLOWABLE_LAPSE_SECONDS);
    LL_I2L(tmp, PR_USEC_PER_SEC);
    LL_MUL(lapse, lapse, tmp);            /* allowable lapse in microseconds */

    LL_ADD(checkTime, checkTime, lapse);
    if (LL_CMP(now, >, checkTime))
       return PR_FALSE;

    return PR_TRUE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static SECStatus ocsp_VerifySingleResponse ( CERTOCSPSingleResponse *  single,
CERTCertDBHandle *  handle,
CERTCertificate *  signerCert,
int64  producedAt 
) [static]

Definition at line 4175 of file ocsp.c.

{
    CERTOCSPCertID *certID = single->certID;
    int64 now, thisUpdate, nextUpdate, tmstamp, tmp;
    SECStatus rv;

    OCSP_TRACE(("OCSP ocsp_VerifySingleResponse, nextUpdate: %d\n", 
               ((single->nextUpdate) != 0)));
    /*
     * If all the responder said was that the given cert was unknown to it,
     * that is a valid response.  Not very interesting to us, of course,
     * but all this function is concerned with is validity of the response,
     * not the status of the cert.
     */
    PORT_Assert(single->certStatus != NULL);
    if (single->certStatus->certStatusType == ocspCertStatus_unknown)
       return SECSuccess;

    /*
     * We need to extract "thisUpdate" for use below and to pass along
     * to AuthorizedResponderForCertID in case it needs it for doing an
     * issuer look-up.
     */
    rv = DER_GeneralizedTimeToTime(&thisUpdate, &single->thisUpdate);
    if (rv != SECSuccess)
       return rv;

    /*
     * First confirm that signerCert is authorized to give this status.
     */
    if (ocsp_AuthorizedResponderForCertID(handle, signerCert, certID,
                                     thisUpdate) != PR_TRUE)
       return SECFailure;

    /*
     * Now check the time stuff, as described above.
     */
    now = PR_Now();
    /* allow slop time for future response */
    LL_UI2L(tmstamp, ocspsloptime); /* get slop time in seconds */
    LL_UI2L(tmp, PR_USEC_PER_SEC);
    LL_MUL(tmp, tmstamp, tmp); /* convert the slop time to PRTime */
    LL_ADD(tmstamp, tmp, now); /* add current time to it */

    if (LL_CMP(thisUpdate, >, tmstamp) || LL_CMP(producedAt, <, thisUpdate)) {
       PORT_SetError(SEC_ERROR_OCSP_FUTURE_RESPONSE);
       return SECFailure;
    }
    if (single->nextUpdate != NULL) {
       rv = DER_GeneralizedTimeToTime(&nextUpdate, single->nextUpdate);
       if (rv != SECSuccess)
           return rv;

       LL_ADD(tmp, tmp, nextUpdate);
       if (LL_CMP(tmp, <, now) || LL_CMP(producedAt, >, nextUpdate)) {
           PORT_SetError(SEC_ERROR_OCSP_OLD_RESPONSE);
           return SECFailure;
       }
    } else if (ocsp_TimeIsRecent(thisUpdate) != PR_TRUE) {
       PORT_SetError(SEC_ERROR_OCSP_OLD_RESPONSE);
       return SECFailure;
    }

    return SECSuccess;

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 256 of file ocsp.c.

Here is the caller graph for this function:

void SetRequestExts ( void object,
CERTCertExtension **  exts 
)

Definition at line 2028 of file ocsp.c.

{
  CERTOCSPRequest *request = (CERTOCSPRequest *)object;

  request->tbsRequest->requestExtensions = exts;
}

Here is the caller graph for this function:

void SetSingleReqExts ( void object,
CERTCertExtension **  exts 
)

Definition at line 1695 of file ocsp.c.

{
  ocspSingleRequest *singleRequest =
    (ocspSingleRequest *)object;

  singleRequest->singleRequestExtensions = exts;
}

Here is the caller graph for this function:


Variable Documentation

Initial value:
 {
    { SEC_ASN1_SEQUENCE,
       0, NULL, sizeof(ocspBasicOCSPResponse) },
    { SEC_ASN1_ANY | SEC_ASN1_SAVE,
       offsetof(ocspBasicOCSPResponse, tbsResponseDataDER) },
    { SEC_ASN1_POINTER,
       offsetof(ocspBasicOCSPResponse, tbsResponseData),
       ocsp_ResponseDataTemplate },
    { SEC_ASN1_INLINE,
       offsetof(ocspBasicOCSPResponse, responseSignature.signatureAlgorithm),
       SECOID_AlgorithmIDTemplate },
    { SEC_ASN1_BIT_STRING,
       offsetof(ocspBasicOCSPResponse, responseSignature.signature) },
    { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
      SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
       offsetof(ocspBasicOCSPResponse, responseSignature.derCerts),
       SEC_SequenceOfAnyTemplate },
    { 0 }
}

Definition at line 1144 of file ocsp.c.

Initial value:
 {
    { SEC_ASN1_SEQUENCE, 
       0, NULL, sizeof(CERTOCSPCertID) },
    { SEC_ASN1_INLINE,
       offsetof(CERTOCSPCertID, hashAlgorithm),
       SECOID_AlgorithmIDTemplate },
    { SEC_ASN1_OCTET_STRING,
       offsetof(CERTOCSPCertID, issuerNameHash) },
    { SEC_ASN1_OCTET_STRING,
       offsetof(CERTOCSPCertID, issuerKeyHash) },
    { SEC_ASN1_INTEGER, 
       offsetof(CERTOCSPCertID, serialNumber) },
    { 0 }
}

Definition at line 1073 of file ocsp.c.

Initial value:
 {
    { SEC_ASN1_POINTER | SEC_ASN1_CONTEXT_SPECIFIC | 0,
       offsetof(ocspCertStatus, certStatusInfo.goodInfo),
       SEC_NullTemplate }
}

Definition at line 1279 of file ocsp.c.

Initial value:
 {
    { SEC_ASN1_POINTER,
       offsetof(ocspCertStatus, certStatusInfo.otherInfo),
       SEC_AnyTemplate }
}

Definition at line 1294 of file ocsp.c.

Initial value:
 {
    { SEC_ASN1_POINTER | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1, 
       offsetof(ocspCertStatus, certStatusInfo.revokedInfo),
       ocsp_RevokedInfoTemplate }
}

Definition at line 1284 of file ocsp.c.

Initial value:
 {
    { SEC_ASN1_POINTER | SEC_ASN1_CONTEXT_SPECIFIC | 2,
       offsetof(ocspCertStatus, certStatusInfo.unknownInfo),
       SEC_NullTemplate }
}

Definition at line 1289 of file ocsp.c.

struct OCSPGlobalStruct OCSP_Global [static]
Initial value:
 {
    { SEC_ASN1_SEQUENCE,
       0, NULL, sizeof(CERTOCSPRequest) },
    { SEC_ASN1_POINTER,
       offsetof(CERTOCSPRequest, tbsRequest),
       ocsp_TBSRequestTemplate },
    { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
      SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
       offsetof(CERTOCSPRequest, optionalSignature),
       ocsp_PointerToSignatureTemplate },
    { 0 }
}

Definition at line 954 of file ocsp.c.

Initial value:
 {
    { SEC_ASN1_SEQUENCE, 
       0, NULL, sizeof(CERTOCSPResponse) },
    { SEC_ASN1_ENUMERATED, 
       offsetof(CERTOCSPResponse, responseStatus) },
    { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
      SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
       offsetof(CERTOCSPResponse, responseBytes),
       ocsp_PointerToResponseBytesTemplate },
    { 0 }
}

Definition at line 1098 of file ocsp.c.

Initial value:

Definition at line 1133 of file ocsp.c.

Initial value:

Definition at line 1030 of file ocsp.c.

Initial value:
 {
    { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 2,
       offsetof(ocspResponderID, responderIDValue.keyHash),
       SEC_OctetStringTemplate }
}

Definition at line 1217 of file ocsp.c.

Initial value:
 {
    { SEC_ASN1_EXPLICIT | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
       offsetof(ocspResponderID, responderIDValue.name),
       CERT_NameTemplate }
}

Definition at line 1212 of file ocsp.c.

Initial value:

Definition at line 1228 of file ocsp.c.

Initial value:
 {
    { SEC_ASN1_ANY,
       offsetof(ocspResponderID, responderIDValue.other) }
}

Definition at line 1222 of file ocsp.c.

Initial value:
 {
    { SEC_ASN1_SEQUENCE,
       0, NULL, sizeof(ocspResponseBytes) },
    { SEC_ASN1_OBJECT_ID,
       offsetof(ocspResponseBytes, responseType) },
    { SEC_ASN1_OCTET_STRING,
       offsetof(ocspResponseBytes, response) },
    { 0 }
}

Definition at line 1115 of file ocsp.c.

Initial value:
 {
    { SEC_ASN1_SEQUENCE,
       0, NULL, sizeof(ocspResponseData) },
    { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |           
      SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
       offsetof(ocspResponseData, version),
       SEC_IntegerTemplate },
    { SEC_ASN1_ANY,
       offsetof(ocspResponseData, derResponderID) },
    { SEC_ASN1_GENERALIZED_TIME,
       offsetof(ocspResponseData, producedAt) },
    { SEC_ASN1_SEQUENCE_OF,
       offsetof(ocspResponseData, responses),
       ocsp_SingleResponseTemplate },
    { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
      SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
       offsetof(ocspResponseData, responseExtensions),
       CERT_SequenceOfCertExtensionTemplate },
    { 0 }
}

Definition at line 1176 of file ocsp.c.

Initial value:
 {
    { SEC_ASN1_SEQUENCE,
       0, NULL, sizeof(ocspRevokedInfo) },
    { SEC_ASN1_GENERALIZED_TIME,
       offsetof(ocspRevokedInfo, revocationTime) },
    { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
      SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
       offsetof(ocspRevokedInfo, revocationReason), 
       SEC_PointerToEnumeratedTemplate },
    { 0 }
}

Definition at line 1309 of file ocsp.c.

Initial value:
 {
    { SEC_ASN1_SEQUENCE,
       0, NULL, sizeof(ocspServiceLocator) },
    { SEC_ASN1_POINTER,
       offsetof(ocspServiceLocator, issuer),
       CERT_NameTemplate },
    { SEC_ASN1_OPTIONAL | SEC_ASN1_ANY,
       offsetof(ocspServiceLocator, locator) },
    { 0 }
}

Definition at line 1331 of file ocsp.c.

Initial value:
 {
    { SEC_ASN1_SEQUENCE,
       0, NULL, sizeof(ocspSignature) },
    { SEC_ASN1_INLINE,
       offsetof(ocspSignature, signatureAlgorithm),
       SECOID_AlgorithmIDTemplate },
    { SEC_ASN1_BIT_STRING,
       offsetof(ocspSignature, signature) },
    { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
      SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
       offsetof(ocspSignature, derCerts), 
       SEC_SequenceOfAnyTemplate },
    { 0 }
}

Definition at line 1007 of file ocsp.c.

Initial value:
 {
    { SEC_ASN1_SEQUENCE, 
       0, NULL, sizeof(ocspSingleRequest) },
    { SEC_ASN1_POINTER,
       offsetof(ocspSingleRequest, reqCert),
       ocsp_CertIDTemplate },
    { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
      SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
       offsetof(ocspSingleRequest, singleRequestExtensions),
       CERT_SequenceOfCertExtensionTemplate },
    { 0 }
}

Definition at line 1043 of file ocsp.c.

Initial value:
 {
    { SEC_ASN1_SEQUENCE,
       0, NULL, sizeof(CERTOCSPSingleResponse) },
    { SEC_ASN1_POINTER,
       offsetof(CERTOCSPSingleResponse, certID),
       ocsp_CertIDTemplate },
    { SEC_ASN1_ANY,
       offsetof(CERTOCSPSingleResponse, derCertStatus) },
    { SEC_ASN1_GENERALIZED_TIME,
       offsetof(CERTOCSPSingleResponse, thisUpdate) },
    { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
      SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
       offsetof(CERTOCSPSingleResponse, nextUpdate),
       SEC_PointerToGeneralizedTimeTemplate },
    { SEC_ASN1_OPTIONAL | SEC_ASN1_EXPLICIT |
      SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
       offsetof(CERTOCSPSingleResponse, singleExtensions),
       CERT_SequenceOfCertExtensionTemplate },
    { 0 }
}

Definition at line 1245 of file ocsp.c.

Definition at line 4149 of file ocsp.c.