mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 22:32:46 +00:00
Break up OCSP so that 3rd party apps can send off an OCSP request and parse
it.
This commit is contained in:
parent
3c19a51662
commit
1f078c5776
@ -35,7 +35,7 @@
|
||||
* Implementation of OCSP services, for both client and server.
|
||||
* (XXX, really, mostly just for client right now, but intended to do both.)
|
||||
*
|
||||
* $Id: ocsp.c,v 1.7 2002/06/06 01:05:40 jpierre%netscape.com Exp $
|
||||
* $Id: ocsp.c,v 1.8 2002/07/03 00:02:34 javi%netscape.com Exp $
|
||||
*/
|
||||
|
||||
#include "prerror.h"
|
||||
@ -596,6 +596,14 @@ loser:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
CERT_DestroyOCSPCertID(CERTOCSPCertID* certID)
|
||||
{
|
||||
if (certID->poolp)
|
||||
PORT_FreeArena(certID->poolp, PR_FALSE);
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Create and fill-in a CertID. This function fills in the hash values
|
||||
@ -718,6 +726,21 @@ loser:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CERTOCSPCertID*
|
||||
CERT_CreateOCSPCertID(CERTCertificate *cert, int64 time)
|
||||
{
|
||||
PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
||||
CERTOCSPCertID *certID;
|
||||
PORT_Assert(arena != NULL);
|
||||
if (!arena)
|
||||
return NULL;
|
||||
|
||||
certID = ocsp_CreateCertID(arena, cert, time);
|
||||
certID->poolp = arena;
|
||||
return certID;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Callback to set Extensions in request object
|
||||
@ -1391,7 +1414,7 @@ CERT_DecodeOCSPResponse(SECItem *src)
|
||||
PRArenaPool *arena = NULL;
|
||||
CERTOCSPResponse *response = NULL;
|
||||
SECStatus rv = SECFailure;
|
||||
ocspResponseStatus sv;
|
||||
OCSPResponseStatus sv;
|
||||
|
||||
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
||||
if (arena == NULL) {
|
||||
@ -1411,9 +1434,9 @@ CERT_DecodeOCSPResponse(SECItem *src)
|
||||
goto loser;
|
||||
}
|
||||
|
||||
sv = (ocspResponseStatus) DER_GetInteger(&response->responseStatus);
|
||||
sv = (OCSPResponseStatus) DER_GetInteger(&response->responseStatus);
|
||||
response->statusValue = sv;
|
||||
if (sv != ocspResponse_successful) {
|
||||
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.
|
||||
@ -3225,10 +3248,7 @@ CERT_CheckOCSPStatus(CERTCertDBHandle *handle, CERTCertificate *cert,
|
||||
CERTOCSPResponse *response = NULL;
|
||||
CERTCertificate *signerCert = NULL;
|
||||
CERTCertificate *issuerCert = NULL;
|
||||
ocspResponseData *responseData;
|
||||
int64 producedAt;
|
||||
CERTOCSPCertID *certID;
|
||||
CERTOCSPSingleResponse *single;
|
||||
SECStatus rv = SECFailure;
|
||||
|
||||
|
||||
@ -3308,27 +3328,27 @@ CERT_CheckOCSPStatus(CERTCertDBHandle *handle, CERTCertificate *cert,
|
||||
* Otherwise, we continue to find the actual per-cert status
|
||||
* in the response.
|
||||
*/
|
||||
switch (response->statusValue) {
|
||||
case ocspResponse_successful:
|
||||
switch (CERT_GetStatusValue(response)) {
|
||||
case OCSPResponse_successful:
|
||||
break;
|
||||
case ocspResponse_malformedRequest:
|
||||
case OCSPResponse_malformedRequest:
|
||||
PORT_SetError(SEC_ERROR_OCSP_MALFORMED_REQUEST);
|
||||
goto loser;
|
||||
case ocspResponse_internalError:
|
||||
case OCSPResponse_internalError:
|
||||
PORT_SetError(SEC_ERROR_OCSP_SERVER_ERROR);
|
||||
goto loser;
|
||||
case ocspResponse_tryLater:
|
||||
case OCSPResponse_tryLater:
|
||||
PORT_SetError(SEC_ERROR_OCSP_TRY_SERVER_LATER);
|
||||
goto loser;
|
||||
case ocspResponse_sigRequired:
|
||||
case OCSPResponse_sigRequired:
|
||||
/* XXX We *should* retry with a signature, if possible. */
|
||||
PORT_SetError(SEC_ERROR_OCSP_REQUEST_NEEDS_SIG);
|
||||
goto loser;
|
||||
case ocspResponse_unauthorized:
|
||||
case OCSPResponse_unauthorized:
|
||||
PORT_SetError(SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST);
|
||||
goto loser;
|
||||
case ocspResponse_other:
|
||||
case ocspResponse_unused:
|
||||
case OCSPResponse_other:
|
||||
case OCSPResponse_unused:
|
||||
default:
|
||||
PORT_SetError(SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS);
|
||||
goto loser;
|
||||
@ -3347,6 +3367,57 @@ CERT_CheckOCSPStatus(CERTCertDBHandle *handle, CERTCertificate *cert,
|
||||
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. It will need
|
||||
* to loop, and for each certID in the request, find the matching
|
||||
* single response and check the status specified by it.
|
||||
*
|
||||
* We are helped here in that we know that the requests are made with
|
||||
* the request list in the same order as the order of the certs we hand
|
||||
* to it. This is why I can directly access the first member of the
|
||||
* single request array for the one cert I care about.
|
||||
*/
|
||||
|
||||
certID = request->tbsRequest->requestList[0]->reqCert;
|
||||
rv = CERT_GetOCSPStatusForCertID(handle, response, certID,
|
||||
signerCert, time);
|
||||
/*
|
||||
* Add back the loser clause and corresponding free's...
|
||||
*/
|
||||
loser:
|
||||
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 (certList != NULL)
|
||||
CERT_DestroyCertList(certList);
|
||||
if (location != NULL)
|
||||
PORT_Free(location);
|
||||
return rv;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
CERT_GetOCSPStatusForCertID(CERTCertDBHandle *handle,
|
||||
CERTOCSPResponse *response,
|
||||
CERTOCSPCertID *certID,
|
||||
CERTCertificate *signerCert,
|
||||
int64 time)
|
||||
{
|
||||
SECStatus rv;
|
||||
ocspResponseData *responseData;
|
||||
int64 producedAt;
|
||||
CERTOCSPSingleResponse *single;
|
||||
|
||||
/*
|
||||
* The ResponseData part is the real guts of the response.
|
||||
*/
|
||||
@ -3366,25 +3437,12 @@ CERT_CheckOCSPStatus(CERTCertDBHandle *handle, CERTCertificate *cert,
|
||||
if (rv != SECSuccess)
|
||||
goto loser;
|
||||
|
||||
/*
|
||||
* 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. It will need
|
||||
* to loop, and for each certID in the request, find the matching
|
||||
* single response and check the status specified by it.
|
||||
*
|
||||
* We are helped here in that we know that the requests are made with
|
||||
* the request list in the same order as the order of the certs we hand
|
||||
* to it. This is why I can directly access the first member of the
|
||||
* single request array for the one cert I care about.
|
||||
*/
|
||||
|
||||
certID = request->tbsRequest->requestList[0]->reqCert;
|
||||
single = ocsp_GetSingleResponseForCertID(responseData->responses,
|
||||
handle, certID);
|
||||
if (single == NULL)
|
||||
if (single == NULL) {
|
||||
rv = SECFailure;
|
||||
goto loser;
|
||||
}
|
||||
|
||||
rv = ocsp_VerifySingleResponse(single, handle, signerCert, producedAt);
|
||||
if (rv != SECSuccess)
|
||||
@ -3396,23 +3454,7 @@ CERT_CheckOCSPStatus(CERTCertDBHandle *handle, CERTCertificate *cert,
|
||||
*/
|
||||
|
||||
rv = ocsp_CertHasGoodStatus(single, time);
|
||||
|
||||
loser:
|
||||
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 (certList != NULL)
|
||||
CERT_DestroyCertList(certList);
|
||||
if (location != NULL)
|
||||
PORT_Free(location);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -3927,4 +3969,9 @@ loser:
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
|
||||
OCSPResponseStatus
|
||||
CERT_GetStatusValue(CERTOCSPResponse *response)
|
||||
{
|
||||
PORT_Assert(response);
|
||||
return response->statusValue;
|
||||
}
|
||||
|
@ -34,7 +34,7 @@
|
||||
/*
|
||||
* Interface to the OCSP implementation.
|
||||
*
|
||||
* $Id: ocsp.h,v 1.2 2001/11/08 00:14:45 relyea%netscape.com Exp $
|
||||
* $Id: ocsp.h,v 1.3 2002/07/03 00:02:34 javi%netscape.com Exp $
|
||||
*/
|
||||
|
||||
#ifndef _OCSP_H_
|
||||
@ -449,6 +449,50 @@ CERT_GetOCSPAuthorityInfoAccessLocation(CERTCertificate *cert);
|
||||
extern SECStatus
|
||||
CERT_CheckOCSPStatus(CERTCertDBHandle *handle, CERTCertificate *cert,
|
||||
int64 time, void *pwArg);
|
||||
/*
|
||||
* FUNCTION: CERT_GetOCSPStatusForCertID
|
||||
* Returns the OCSP status contained in the passed in paramter response
|
||||
* that corresponds to the certID passed in.
|
||||
* INPUTS:
|
||||
* CERTCertDBHandle *handle
|
||||
* certificate DB of the cert that is being checked
|
||||
* CERTOCSPResponse *response
|
||||
* the OCSP response we want to retrieve status from.
|
||||
* CERTOCSPCertID *certID
|
||||
* the ID we want to look for from the response.
|
||||
* CERTCertificate *signerCert
|
||||
* the certificate that was used to sign the OCSP response.
|
||||
* must be obtained via a call to CERT_VerifyOCSPResponseSignature.
|
||||
* int64 time
|
||||
* The time at which we're checking the status for.
|
||||
* RETURN:
|
||||
* Return values are the same as those for CERT_CheckOCSPStatus
|
||||
*/
|
||||
extern SECStatus
|
||||
CERT_GetOCSPStatusForCertID(CERTCertDBHandle *handle,
|
||||
CERTOCSPResponse *response,
|
||||
CERTOCSPCertID *certID,
|
||||
CERTCertificate *signerCert,
|
||||
int64 time);
|
||||
|
||||
/*
|
||||
* FUNCTION CERT_GetStatusValue
|
||||
* Returns the response status for the response passed.
|
||||
* INPUTS:
|
||||
* CERTOCSPResponse *response
|
||||
* The response to query for status
|
||||
* RETURN:
|
||||
* OCSPResponseStatus an enumeration corresponding to the possible
|
||||
* return values listed in the OCSP spec.
|
||||
*/
|
||||
extern OCSPResponseStatus
|
||||
CERT_GetStatusValue(CERTOCSPResponse *response);
|
||||
|
||||
extern CERTOCSPCertID*
|
||||
CERT_CreateOCSPCertID(CERTCertificate *cert, int64 time);
|
||||
|
||||
extern SECStatus
|
||||
CERT_DestroyOCSPCertID(CERTOCSPCertID* certID);
|
||||
/************************************************************************/
|
||||
SEC_END_PROTOS
|
||||
|
||||
|
@ -34,7 +34,7 @@
|
||||
/*
|
||||
* Public header for exported OCSP types.
|
||||
*
|
||||
* $Id: ocspt.h,v 1.1 2000/03/31 19:43:03 relyea%netscape.com Exp $
|
||||
* $Id: ocspt.h,v 1.2 2002/07/03 00:02:34 javi%netscape.com Exp $
|
||||
*/
|
||||
|
||||
#ifndef _OCSPT_H_
|
||||
@ -56,4 +56,33 @@ typedef struct CERTOCSPCertIDStr CERTOCSPCertID;
|
||||
typedef struct CERTOCSPCertStatusStr CERTOCSPCertStatus;
|
||||
typedef struct CERTOCSPSingleResponseStr CERTOCSPSingleResponse;
|
||||
|
||||
/*
|
||||
* Making these types public so that it is possible for 3rpd party
|
||||
* apps to parse and look at the fields of an OCSP response.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This describes the value of the responseStatus field in an OCSPResponse.
|
||||
* The corresponding ASN.1 definition is:
|
||||
*
|
||||
* OCSPResponseStatus ::= ENUMERATED {
|
||||
* successful (0), --Response has valid confirmations
|
||||
* malformedRequest (1), --Illegal confirmation request
|
||||
* internalError (2), --Internal error in issuer
|
||||
* tryLater (3), --Try again later
|
||||
* --(4) is not used
|
||||
* sigRequired (5), --Must sign the request
|
||||
* unauthorized (6), --Request unauthorized
|
||||
* }
|
||||
*/
|
||||
typedef enum {
|
||||
OCSPResponse_successful = 0,
|
||||
OCSPResponse_malformedRequest = 1,
|
||||
OCSPResponse_internalError = 2,
|
||||
OCSPResponse_tryLater = 3,
|
||||
OCSPResponse_unused = 4,
|
||||
OCSPResponse_sigRequired = 5,
|
||||
OCSPResponse_unauthorized = 6,
|
||||
OCSPResponse_other /* unknown/unrecognized value */
|
||||
} OCSPResponseStatus;
|
||||
#endif /* _OCSPT_H_ */
|
||||
|
@ -34,7 +34,7 @@
|
||||
/*
|
||||
* Private header defining OCSP types.
|
||||
*
|
||||
* $Id: ocspti.h,v 1.2 2001/11/08 00:14:45 relyea%netscape.com Exp $
|
||||
* $Id: ocspti.h,v 1.3 2002/07/03 00:02:35 javi%netscape.com Exp $
|
||||
*/
|
||||
|
||||
#ifndef _OCSPTI_H_
|
||||
@ -200,44 +200,20 @@ struct CERTOCSPCertIDStr {
|
||||
SECItem issuerSHA1KeyHash; /* keep other hashes around when */
|
||||
SECItem issuerMD5KeyHash; /* we have them */
|
||||
SECItem issuerMD2KeyHash;
|
||||
PRArenaPool *poolp;
|
||||
};
|
||||
|
||||
/*
|
||||
* This describes the value of the responseStatus field in an OCSPResponse.
|
||||
* The corresponding ASN.1 definition is:
|
||||
*
|
||||
* OCSPResponseStatus ::= ENUMERATED {
|
||||
* successful (0), --Response has valid confirmations
|
||||
* malformedRequest (1), --Illegal confirmation request
|
||||
* internalError (2), --Internal error in issuer
|
||||
* tryLater (3), --Try again later
|
||||
* --(4) is not used
|
||||
* sigRequired (5), --Must sign the request
|
||||
* unauthorized (6), --Request unauthorized
|
||||
* }
|
||||
*/
|
||||
typedef enum {
|
||||
ocspResponse_successful = 0,
|
||||
ocspResponse_malformedRequest = 1,
|
||||
ocspResponse_internalError = 2,
|
||||
ocspResponse_tryLater = 3,
|
||||
ocspResponse_unused = 4,
|
||||
ocspResponse_sigRequired = 5,
|
||||
ocspResponse_unauthorized = 6,
|
||||
ocspResponse_other /* unknown/unrecognized value */
|
||||
} ocspResponseStatus;
|
||||
|
||||
/*
|
||||
* An OCSPResponse is what is sent (encoded) by an OCSP responder.
|
||||
*
|
||||
* The field "responseStatus" is the ASN.1 encoded value; the field
|
||||
* "statusValue" is simply that same value translated into our local
|
||||
* type ocspResponseStatus.
|
||||
* type OCSPResponseStatus.
|
||||
*/
|
||||
struct CERTOCSPResponseStr {
|
||||
PRArenaPool *arena; /* local; not part of encoding */
|
||||
SECItem responseStatus; /* an ENUMERATED, see above */
|
||||
ocspResponseStatus statusValue; /* local; not part of encoding */
|
||||
OCSPResponseStatus statusValue; /* local; not part of encoding */
|
||||
ocspResponseBytes *responseBytes; /* only when status is successful */
|
||||
};
|
||||
|
||||
|
@ -685,6 +685,16 @@ SECMOD_CanDeleteInternalModule;
|
||||
PK11_GetPBEIV;
|
||||
PK11_SaveContextAlloc;
|
||||
CERT_VerifyCertChain;
|
||||
CERT_DestroyOCSPRequest;
|
||||
CERT_EncodeOCSPRequest;
|
||||
CERT_AddOCSPAcceptableResponses;
|
||||
CERT_CreateOCSPRequest;
|
||||
CERT_GetOCSPStatusForCertID;
|
||||
CERT_DecodeOCSPResponse;
|
||||
CERT_VerifyOCSPResponseSignature;
|
||||
CERT_GetStatusValue;
|
||||
CERT_DestroyOCSPCertID;
|
||||
CERT_CreateOCSPCertID;
|
||||
;+ local:
|
||||
;+ *;
|
||||
;+};
|
||||
|
Loading…
Reference in New Issue
Block a user