Back to index

lightning-sunbird  0.9+nobinonly
Functions
ocsp.h File Reference
#include "plarena.h"
#include "seccomon.h"
#include "secoidt.h"
#include "keyt.h"
#include "certt.h"
#include "ocspt.h"
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

SEC_BEGIN_PROTOS SECStatus SEC_RegisterDefaultHttpClient (const SEC_HttpClientFcn *fcnTable)
SECStatus CERT_OCSPCacheSettings (PRInt32 maxCacheEntries, PRUint32 minimumSecondsToNextFetchAttempt, PRUint32 maximumSecondsToNextFetchAttempt)
SECStatus CERT_SetOCSPFailureMode (SEC_OcspFailureMode ocspFailureMode)
SECStatus CERT_ClearOCSPCache (void)
SECStatus CERT_EnableOCSPChecking (CERTCertDBHandle *handle)
SECStatus CERT_DisableOCSPChecking (CERTCertDBHandle *handle)
SECStatus CERT_SetOCSPDefaultResponder (CERTCertDBHandle *handle, const char *url, const char *name)
SECStatus CERT_EnableOCSPDefaultResponder (CERTCertDBHandle *handle)
SECStatus CERT_DisableOCSPDefaultResponder (CERTCertDBHandle *handle)
CERTOCSPRequest * CERT_CreateOCSPRequest (CERTCertList *certList, int64 time, PRBool addServiceLocator, CERTCertificate *signerCert)
SECStatus CERT_AddOCSPAcceptableResponses (CERTOCSPRequest *request, SECOidTag responseType0,...)
SECItem * CERT_EncodeOCSPRequest (PRArenaPool *arena, CERTOCSPRequest *request, void *pwArg)
CERTOCSPRequest * CERT_DecodeOCSPRequest (SECItem *src)
void CERT_DestroyOCSPRequest (CERTOCSPRequest *request)
CERTOCSPResponse * CERT_DecodeOCSPResponse (SECItem *src)
void CERT_DestroyOCSPResponse (CERTOCSPResponse *response)
SECItem * CERT_GetEncodedOCSPResponse (PRArenaPool *arena, CERTCertList *certList, char *location, int64 time, PRBool addServiceLocator, CERTCertificate *signerCert, void *pwArg, CERTOCSPRequest **pRequest)
SECStatus CERT_VerifyOCSPResponseSignature (CERTOCSPResponse *response, CERTCertDBHandle *handle, void *pwArg, CERTCertificate **pSignerCert, CERTCertificate *issuerCert)
char * CERT_GetOCSPAuthorityInfoAccessLocation (CERTCertificate *cert)
SECStatus CERT_CheckOCSPStatus (CERTCertDBHandle *handle, CERTCertificate *cert, int64 time, void *pwArg)
SECStatus CERT_GetOCSPStatusForCertID (CERTCertDBHandle *handle, CERTOCSPResponse *response, CERTOCSPCertID *certID, CERTCertificate *signerCert, int64 time)
SECStatus CERT_GetOCSPResponseStatus (CERTOCSPResponse *response)
CERTOCSPCertID * CERT_CreateOCSPCertID (CERTCertificate *cert, int64 time)
SECStatus CERT_DestroyOCSPCertID (CERTOCSPCertID *certID)

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;
}
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;

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;
}
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;
}
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;
}
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;
}
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;
}
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);
}
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);
       }
    }
}
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;
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;
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;
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;
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);
}
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);
}
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;
SECStatus CERT_GetOCSPResponseStatus ( CERTOCSPResponse *  response)
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;
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;

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 *  issuerCert 
)

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;
}