ocsp.c

来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 2,187 行 · 第 1/5 页

C
2,187
字号
     * 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;    }    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 */    /*     * Now create the list of single requests, one for each cert.     */    tbsRequest->requestList = ocsp_CreateSingleRequestList(arena, certList,							   time,							   addServiceLocator);    if (tbsRequest->requestList == NULL) {	goto loser;    }    return request;loser:    if (arena != NULL) {	PORT_FreeArena(arena, PR_FALSE);    }    return NULL;}/* * FUNCTION: CERT_AddOCSPAcceptableResponses *   Add the AcceptableResponses extension to an OCSP Request. * INPUTS: *   CERTOCSPRequest *request *     The request to which the extension should be added. *   ... *     A list (of one or more) of SECOidTag -- each of the response types *     to be added.  The last OID *must* be SEC_OID_PKIX_OCSP_BASIC_RESPONSE. *     (This marks the end of the list, and it must be specified because a *     client conforming to the OCSP standard is required to handle the basic *     response type.)  The OIDs are not checked in any way. * RETURN: *   SECSuccess if the extension is added; SECFailure if anything goes wrong. *   All errors are internal or low-level problems (e.g. no memory). */void SetRequestExts(void *object, CERTCertExtension **exts){  CERTOCSPRequest *request = (CERTOCSPRequest *)object;  request->tbsRequest->requestExtensions = exts;}SECStatusCERT_AddOCSPAcceptableResponses(CERTOCSPRequest *request, ...){    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 = 0;    va_start(ap, request);    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;    va_start(ap, request);    for (i = 0; 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;}/* * FUNCTION: CERT_DestroyOCSPRequest *   Frees an OCSP Request structure. * INPUTS: *   CERTOCSPRequest *request *     Pointer to CERTOCSPRequest to be freed. * RETURN: *   No return value; no errors. */voidCERT_DestroyOCSPRequest(CERTOCSPRequest *request){    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);}/* * RESPONSE SUPPORT FUNCTIONS (encode/create/decode/destroy): *//* * Helper function for encoding or decoding a ResponderID -- based on the * given type, return the associated template for that choice. */static const SEC_ASN1Template *ocsp_ResponderIDTemplateByType(ocspResponderIDType responderIDType){    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;}/* * Helper function for encoding or decoding a CertStatus -- based on the * given type, return the associated template for that choice. */static const SEC_ASN1Template *ocsp_CertStatusTemplateByType(ocspCertStatusType certStatusType){    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;}/* * Helper function for decoding a certStatus -- turn the actual DER tag * into our local translation. */static ocspCertStatusTypeocsp_CertStatusTypeByTag(int derTag){    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;}/* * Helper function for decoding SingleResponses -- they each contain * a status which is encoded as CHOICE, which needs to be decoded "by hand". * * Note -- on error, this routine does not release the memory it may * have allocated; it expects its caller to do that. */static SECStatusocsp_FinishDecodingSingleResponses(PRArenaPool *arena,				   CERTOCSPSingleResponse **responses){    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;}/* * Helper function for decoding a responderID -- turn the actual DER tag * into our local translation. */static ocspResponderIDTypeocsp_ResponderIDTypeByTag(int derTag){    ocspResponderIDType responderIDType;    switch (derTag) {	case 1:	    responderIDType = ocspResponderID_byName;	    break;	case 2:	    responderIDType = ocspResponderID_byKey;	    break;	default:	    responderIDType = ocspResponderID_other;	    break;    }    return responderIDType;}/* * Decode "src" as a BasicOCSPResponse, returning the result. */static ocspBasicOCSPResponse *ocsp_DecodeBasicOCSPResponse(PRArenaPool *arena, SECItem *src){    void *mark;    ocspBasicOCSPResponse *basicResponse;    ocspResponseData *responseData;    ocspResponderID *responderID;    ocspResponderIDType responderIDType;    const SEC_ASN1Template *responderIDTemplate;    int derTag;    SECStatus rv;    mark = PORT_ArenaMark(arena);    basicResponse = PORT_ArenaZAlloc(arena, sizeof(ocspBasicOCSPResponse));    if (basicResponse == NULL) {	goto loser;    }    rv = SEC_ASN1DecodeItem(arena, basicResponse,			    ocsp_BasicOCSPResponseTemplate, src);    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_ASN1DecodeItem(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;}/* * Decode the responseBytes based on the responseType found in "rbytes", * leaving the resulting translated/decoded information in there as well. */static SECStatusocsp_DecodeResponseBytes(PRArenaPool *arena, ocspResponseBytes *rbytes){    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) {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?