示例#1
0
int
ikev2_pld_payloads(struct iked *env, struct iked_message *msg,
    off_t offset, size_t length, u_int payload, int quick)
{
	struct ikev2_payload	 pld;
	u_int			 e;
	int			 ret;
	u_int8_t		*msgbuf = ibuf_data(msg->msg_data);

	/* Check if message was decrypted in an E payload */
	e = msg->msg_e ? IKED_E : 0;

	if (quick)
		print_debug("%s: %spayloads", __func__,
		    e ? "decrypted " : "");
	else
		ikev2_pld_payloads(env, msg, offset, length, payload, 1);

	while (payload != 0 && offset < (off_t)length) {
		memcpy(&pld, msgbuf + offset, sizeof(pld));

		if (quick)
			print_debug(" %s",
			    print_map(payload, ikev2_payload_map));
		else
			log_debug("%s: %spayload %s"
			    " nextpayload %s critical 0x%02x length %d",
			    __func__, e ? "decrypted " : "",
			    print_map(payload, ikev2_payload_map),
			    print_map(pld.pld_nextpayload, ikev2_payload_map),
			    pld.pld_reserved & IKEV2_CRITICAL_PAYLOAD,
			    betoh16(pld.pld_length));

		offset += sizeof(pld);
		ret = 0;

		if (quick)
			goto next;

		switch (payload | e) {
		case IKEV2_PAYLOAD_SA:
		case IKEV2_PAYLOAD_SA | IKED_E:
			ret = ikev2_pld_sa(env, &pld, msg, offset);
			break;
		case IKEV2_PAYLOAD_KE:
		case IKEV2_PAYLOAD_KE | IKED_E:
			ret = ikev2_pld_ke(env, &pld, msg, offset);
			break;
		case IKEV2_PAYLOAD_IDi | IKED_E:
		case IKEV2_PAYLOAD_IDr | IKED_E:
			ret = ikev2_pld_id(env, &pld, msg, offset, payload);
			break;
		case IKEV2_PAYLOAD_CERT | IKED_E:
			ret = ikev2_pld_cert(env, &pld, msg, offset);
			break;
		case IKEV2_PAYLOAD_CERTREQ:
		case IKEV2_PAYLOAD_CERTREQ | IKED_E:
			ret = ikev2_pld_certreq(env, &pld, msg, offset);
			break;
		case IKEV2_PAYLOAD_AUTH | IKED_E:
			ret = ikev2_pld_auth(env, &pld, msg, offset);
			break;
		case IKEV2_PAYLOAD_NONCE:
		case IKEV2_PAYLOAD_NONCE | IKED_E:
			ret = ikev2_pld_nonce(env, &pld, msg, offset);
			break;
		case IKEV2_PAYLOAD_NOTIFY:
		case IKEV2_PAYLOAD_NOTIFY | IKED_E:
			ret = ikev2_pld_notify(env, &pld, msg, offset);
			break;
		case IKEV2_PAYLOAD_DELETE | IKED_E:
			ret = ikev2_pld_delete(env, &pld, msg, offset);
			break;
		case IKEV2_PAYLOAD_TSi | IKED_E:
		case IKEV2_PAYLOAD_TSr | IKED_E:
			ret = ikev2_pld_ts(env, &pld, msg, offset, payload);
			break;
		case IKEV2_PAYLOAD_SK:
			ret = ikev2_pld_e(env, &pld, msg, offset);
			break;
		case IKEV2_PAYLOAD_CP | IKED_E:
			ret = ikev2_pld_cp(env, &pld, msg, offset);
			break;
		case IKEV2_PAYLOAD_EAP | IKED_E:
			ret = ikev2_pld_eap(env, &pld, msg, offset);
			break;
		default:
			print_hex(msgbuf, offset,
			    betoh16(pld.pld_length) - sizeof(pld));
			break;
		}

		if (ret != 0 && ikev2_msg_frompeer(msg)) {
			(void)ikev2_send_informational(env, msg);
			return (-1);
		}

		/* Encrypted payload must appear last */
		if (payload == IKEV2_PAYLOAD_SK)
			return (0);

 next:
		payload = pld.pld_nextpayload;
		offset += betoh16(pld.pld_length) - sizeof(pld);
	}

	if (quick)
		print_debug("\n");

	return (0);
}
int
ikev2_pld_payloads(struct iked *env, struct iked_message *msg,
    size_t offset, size_t length, u_int payload)
{
	struct ikev2_payload	 pld;
	u_int			 e;
	int			 ret;
	u_int8_t		*msgbuf = ibuf_data(msg->msg_data);
	size_t			 left;

	/* Check if message was decrypted in an E payload */
	e = msg->msg_e ? IKED_E : 0;

	while (payload != 0 && offset < length) {
		/* Bytes left in datagram. */
		left = length - offset;

		if (ikev2_validate_pld(msg, offset, left, &pld))
			return (-1);

		log_debug("%s: %spayload %s"
		    " nextpayload %s critical 0x%02x length %d",
		    __func__, e ? "decrypted " : "",
		    print_map(payload, ikev2_payload_map),
		    print_map(pld.pld_nextpayload, ikev2_payload_map),
		    pld.pld_reserved & IKEV2_CRITICAL_PAYLOAD,
		    betoh16(pld.pld_length));

		/* Skip over generic payload header. */
		offset += sizeof(pld);
		left -= sizeof(pld);
		ret = 0;

		switch (payload | e) {
		case IKEV2_PAYLOAD_SA:
		case IKEV2_PAYLOAD_SA | IKED_E:
			ret = ikev2_pld_sa(env, &pld, msg, offset, left);
			break;
		case IKEV2_PAYLOAD_KE:
		case IKEV2_PAYLOAD_KE | IKED_E:
			ret = ikev2_pld_ke(env, &pld, msg, offset, left);
			break;
		case IKEV2_PAYLOAD_IDi | IKED_E:
		case IKEV2_PAYLOAD_IDr | IKED_E:
			ret = ikev2_pld_id(env, &pld, msg, offset, left,
			    payload);
			break;
		case IKEV2_PAYLOAD_CERT | IKED_E:
			ret = ikev2_pld_cert(env, &pld, msg, offset, left);
			break;
		case IKEV2_PAYLOAD_CERTREQ:
		case IKEV2_PAYLOAD_CERTREQ | IKED_E:
			ret = ikev2_pld_certreq(env, &pld, msg, offset, left);
			break;
		case IKEV2_PAYLOAD_AUTH | IKED_E:
			ret = ikev2_pld_auth(env, &pld, msg, offset, left);
			break;
		case IKEV2_PAYLOAD_NONCE:
		case IKEV2_PAYLOAD_NONCE | IKED_E:
			ret = ikev2_pld_nonce(env, &pld, msg, offset, left);
			break;
		case IKEV2_PAYLOAD_NOTIFY:
		case IKEV2_PAYLOAD_NOTIFY | IKED_E:
			ret = ikev2_pld_notify(env, &pld, msg, offset, left);
			break;
		case IKEV2_PAYLOAD_DELETE | IKED_E:
			ret = ikev2_pld_delete(env, &pld, msg, offset, left);
			break;
		case IKEV2_PAYLOAD_TSi | IKED_E:
		case IKEV2_PAYLOAD_TSr | IKED_E:
			ret = ikev2_pld_ts(env, &pld, msg, offset, left,
			    payload);
			break;
		case IKEV2_PAYLOAD_SK:
			ret = ikev2_pld_e(env, &pld, msg, offset);
			break;
		case IKEV2_PAYLOAD_CP | IKED_E:
			ret = ikev2_pld_cp(env, &pld, msg, offset, left);
			break;
		case IKEV2_PAYLOAD_EAP | IKED_E:
			ret = ikev2_pld_eap(env, &pld, msg, offset, left);
			break;
		default:
			print_hex(msgbuf, offset,
			    betoh16(pld.pld_length) - sizeof(pld));
			break;
		}

		if (ret != 0 && ikev2_msg_frompeer(msg)) {
			(void)ikev2_send_informational(env, msg);
			return (-1);
		}

		/* Encrypted payload must appear last */
		if (payload == IKEV2_PAYLOAD_SK)
			return (0);

		payload = pld.pld_nextpayload;
		offset += betoh16(pld.pld_length) - sizeof(pld);
	}

	return (0);
}