⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ocsp.c

📁 ipsec vpn
💻 C
📖 第 1 页 / 共 4 页
字号:
	    extn_oid = known_oid(object);	    break;	case BASIC_RESPONSE_CRITICAL:	    critical = object.len && *object.ptr;	    DBG(DBG_PARSING,		DBG_log("  %s",(critical)?"TRUE":"FALSE");	    )	    break;	case BASIC_RESPONSE_EXT_VALUE:	    if (extn_oid == OID_NONCE)		res->nonce = object;	    break;	case BASIC_RESPONSE_ALGORITHM:	    res->algorithm = parse_algorithmIdentifier(object, level+1);	    break;	case BASIC_RESPONSE_SIGNATURE:	    res->signature = object;	    break;	case BASIC_RESPONSE_CERTIFICATE:	    {		chunk_t blob;		x509cert_t *cert = alloc_thing(x509cert_t, "ocspcert");		clonetochunk(blob, object.ptr, object.len, "ocspcert blob");		*cert = empty_x509cert;                if (parse_x509cert(blob, level+1, cert)                    && cert->isOcspSigner                    && trust_authcert_candidate(cert, NULL))		{		    add_authcert(cert, AUTH_OCSP);		}		else		{		    DBG(DBG_CONTROL | DBG_PARSING,			DBG_log("embedded ocsp certificate rejected")		    )		    free_x509cert(cert);		}	    }	    break;	}	objectID++;    }    return TRUE;}/* * parse an ocsp response and return the result as a response_t struct */static response_statusparse_ocsp_response(chunk_t blob, response_t * res){    asn1_ctx_t ctx;    chunk_t object;    u_int level;    int objectID = 0;    response_status rStatus = STATUS_INTERNALERROR;    u_int ocspResponseType = 0;    asn1_init(&ctx, blob, 0, FALSE, DBG_RAW);    while (objectID < OCSP_RESPONSE_ROOF)    {	if (!extract_object(ocspResponseObjects, &objectID, &object, &level, &ctx))	    return STATUS_INTERNALERROR;	switch (objectID) {	case OCSP_RESPONSE_STATUS:	    rStatus = (response_status) *object.ptr;	    switch (rStatus)	    {	    case STATUS_SUCCESSFUL:		break;	    case STATUS_MALFORMEDREQUEST:	    case STATUS_INTERNALERROR:	    case STATUS_TRYLATER:	    case STATUS_SIGREQUIRED:	    case STATUS_UNAUTHORIZED:		plog("ocsp response: server said '%s'"		    , response_status_names[rStatus]);		return rStatus;	    default:		return STATUS_INTERNALERROR;	    }	    break;	case OCSP_RESPONSE_TYPE:	    ocspResponseType = known_oid(object);	    break;	case OCSP_RESPONSE:	    {		switch (ocspResponseType) {		case OID_BASIC:		    if (!parse_basic_ocsp_response(object, level+1, res))			return STATUS_INTERNALERROR;		    break;		default:		    DBG(DBG_CONTROL,			DBG_log("ocsp response is not of type BASIC");			DBG_dump_chunk("ocsp response OID: ", object);		    )		    return STATUS_INTERNALERROR;		}	    }	    break;	}	objectID++;    }    return rStatus;}/* * parse a basic OCSP response */static boolparse_ocsp_single_response(chunk_t blob, int level0, single_response_t *sres){    u_int level, extn_oid;    asn1_ctx_t ctx;    bool critical;    chunk_t object;    int objectID = 0;    asn1_init(&ctx, blob, level0, FALSE, DBG_RAW);    while (objectID < SINGLE_RESPONSE_ROOF)    {	if (!extract_object(singleResponseObjects, &objectID, &object, &level, &ctx))	    return FALSE;	switch (objectID)	{	case SINGLE_RESPONSE_ALGORITHM:	    sres->hash_algorithm = parse_algorithmIdentifier(object, level+1);	    break;	case SINGLE_RESPONSE_ISSUER_NAME_HASH:	    sres->issuer_name_hash = object;	    break;	case SINGLE_RESPONSE_ISSUER_KEY_HASH:	    sres->issuer_key_hash = object;	    break;	case SINGLE_RESPONSE_SERIAL_NUMBER:	    sres->serialNumber = object;	    break;	case SINGLE_RESPONSE_CERT_STATUS_GOOD:	    sres->status = CERT_GOOD;	    break;	case SINGLE_RESPONSE_CERT_STATUS_REVOKED:	    sres->status = CERT_REVOKED;	    break;	case SINGLE_RESPONSE_CERT_STATUS_REVOCATION_TIME:	    sres->revocation_time = asn1totime(&object, ASN1_GENERALIZEDTIME);	    break;	case SINGLE_RESPONSE_CERT_STATUS_CRL_REASON:	    sres->reason = *object.ptr;	    break;	case SINGLE_RESPONSE_CERT_STATUS_UNKNOWN:	    sres->status = CERT_UNKNOWN;	    break;	case SINGLE_RESPONSE_THIS_UPDATE:	    sres->thisUpdate = asn1totime(&object, ASN1_GENERALIZEDTIME);	    break;	case SINGLE_RESPONSE_NEXT_UPDATE:	    sres->nextUpdate = asn1totime(&object, ASN1_GENERALIZEDTIME);	    break;	case SINGLE_RESPONSE_EXT_ID:	    extn_oid = known_oid(object);	    break;	case SINGLE_RESPONSE_CRITICAL:	    critical = object.len && *object.ptr;	    DBG(DBG_PARSING,		DBG_log("  %s",(critical)?"TRUE":"FALSE");	    )	case SINGLE_RESPONSE_EXT_VALUE:	    break;	}	objectID++;    }    return TRUE;}/* * add an ocsp location to a chained list */ocsp_location_t*add_ocsp_location(const ocsp_location_t *loc, ocsp_location_t **chain){    ocsp_location_t *location = alloc_thing(ocsp_location_t, "ocsp location");    /* unshare location fields */    clonetochunk(location->issuer		, loc->issuer.ptr, loc->issuer.len		, "ocsp issuer");    clonetochunk(location->authNameID		, loc->authNameID.ptr, loc->authNameID.len		, "ocsp authNameID");    if (loc->authKeyID.ptr == NULL)	location->authKeyID = empty_chunk;    else	clonetochunk(location->authKeyID		, loc->authKeyID.ptr, loc->authKeyID.len		, "ocsp authKeyID");    if (loc->authKeySerialNumber.ptr == NULL)	location->authKeySerialNumber = empty_chunk;    else	clonetochunk(location->authKeySerialNumber    		, loc->authKeySerialNumber.ptr, loc->authKeySerialNumber.len		, "ocsp authKeySerialNumber");    clonetochunk(location->uri		, loc->uri.ptr, loc->uri.len		, "ocsp uri");    location->certinfo = NULL;    /* insert new ocsp location in front of chain */    location->next = *chain;    *chain = location;    DBG(DBG_CONTROL,	DBG_log("new ocsp location added")    )    return location;}/* * add a certinfo struct to a chained list */voidadd_certinfo(ocsp_location_t *loc, ocsp_certinfo_t *info, ocsp_location_t **chain    , bool request){    ocsp_location_t *location;    ocsp_certinfo_t *certinfo, **certinfop;    char buf[BUF_LEN];    time_t now;    int cmp = -1;    location = get_ocsp_location(loc, *chain);    if (location == NULL)	location = add_ocsp_location(loc, chain);    /* traverse list of certinfos in increasing order */    certinfop = &location->certinfo;    certinfo = *certinfop;    while (certinfo != NULL)    {	cmp = cmp_chunk(info->serialNumber, certinfo->serialNumber);	if (cmp <= 0)	    break;	certinfop = &certinfo->next;	certinfo = *certinfop;    }    if (cmp != 0)    {	/* add a new certinfo entry */	ocsp_certinfo_t *cnew = alloc_thing(ocsp_certinfo_t, "ocsp certinfo");	clonetochunk(cnew->serialNumber, info->serialNumber.ptr	    , info->serialNumber.len, "serialNumber");	cnew->next = certinfo;	*certinfop = cnew;	certinfo = cnew;    }	    DBG(DBG_CONTROL,	datatot(info->serialNumber.ptr, info->serialNumber.len, ':'	    , buf, BUF_LEN);	DBG_log("ocsp %s for serial %s %s"	    , request?"fetch request":"certinfo"	    , buf	    , (cmp == 0)? (request?"already exists":"updated"):"added")    )    time(&now);       if (request)    {	certinfo->status = CERT_UNDEFINED;		if (cmp != 0)	    certinfo->thisUpdate = now;	certinfo->nextUpdate = UNDEFINED_TIME;    }    else    {	certinfo->status = info->status;	certinfo->thisUpdate = (info->thisUpdate != UNDEFINED_TIME)?	    info->thisUpdate : now;	certinfo->once = (info->nextUpdate == UNDEFINED_TIME);	certinfo->nextUpdate = (certinfo->once)?	    (now + OCSP_DEFAULT_VALID_TIME) : info->nextUpdate;    }}/* * process received ocsp single response and add it to ocsp cache */static voidprocess_single_response(ocsp_location_t *location, single_response_t *sres){    ocsp_certinfo_t *certinfo, **certinfop;    int cmp = 0;    if (sres->hash_algorithm != OID_SHA1)    {	plog("only SHA-1 hash supported in OCSP single response");	return;    }    if (!(same_chunk(sres->issuer_name_hash, location->authNameID)    &&   same_chunk(sres->issuer_key_hash, location->authKeyID)))    {	plog("ocsp single response has wrong issuer");	return;    }        /* traverse list of certinfos in increasing order */    certinfop = &location->certinfo;    certinfo = *certinfop;    while (certinfo != NULL)    {	cmp = cmp_chunk(sres->serialNumber, certinfo->serialNumber);	if (cmp <= 0)	    break;	certinfop = &certinfo->next;	certinfo = *certinfop;    }    if (cmp != 0)    {	plog("received unrequested cert status from ocsp server");	return;    }    /* unlink cert from ocsp fetch request list */    *certinfop = certinfo->next;        /* update certinfo using the single response information */    certinfo->thisUpdate = sres->thisUpdate;    certinfo->nextUpdate = sres->nextUpdate;    certinfo->status = sres->status;        /* add or update certinfo in ocsp cache */    lock_ocsp_cache("process_single_response");    add_certinfo(location, certinfo, &ocsp_cache, FALSE);    unlock_ocsp_cache("process_single_response");    /* free certinfo unlinked from ocsp fetch request list */    free_certinfo(certinfo);}/* *  parse and verify ocsp response and update the ocsp cache */voidparse_ocsp(ocsp_location_t *location, chunk_t blob){    response_t res = empty_response;    /* parse the ocsp response without looking at the single responses yet */    response_status status = parse_ocsp_response(blob, &res);    if (status != STATUS_SUCCESSFUL)    {	plog("error in ocsp response");	return;    }    /* check if there was a nonce in the request */    if (location->nonce.ptr != NULL && res.nonce.ptr == NULL)    {	plog("ocsp response contains no nonce, replay attack possible");    }    /* check if the nonce is identical */    if (res.nonce.ptr != NULL && !same_chunk(res.nonce, location->nonce))    {	plog("invalid nonce in ocsp response");	return;    }    /* check if the response is signed by a trusted key */    if (!valid_ocsp_response(&res))    {	plog("invalid ocsp response");	return;    }    DBG(DBG_CONTROL,	DBG_log("valid ocsp response")    )    /* now parse the single responses one at a time */    {	u_int level;	asn1_ctx_t ctx;	chunk_t object;	int objectID = 0;	asn1_init(&ctx, res.responses, 0, FALSE, DBG_RAW);	while (objectID < RESPONSES_ROOF)	{	    if (!extract_object(responsesObjects, &objectID, &object, &level, &ctx))		return;	    	    if (objectID == RESPONSES_SINGLE_RESPONSE)	    {		single_response_t sres = empty_single_response;		if (parse_ocsp_single_response(object, level+1, &sres))		{		    process_single_response(location, &sres);		}	    }	    objectID++;	}    }}/* * Local Variables: * c-basic-offset:4 * c-style: pluto * End: */

⌨️ 快捷键说明

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