diff options
Diffstat (limited to 'sbin/iked/ikev2_pld.c')
-rw-r--r-- | sbin/iked/ikev2_pld.c | 853 |
1 files changed, 705 insertions, 148 deletions
diff --git a/sbin/iked/ikev2_pld.c b/sbin/iked/ikev2_pld.c index 4ec1c5ae6be..a271163f085 100644 --- a/sbin/iked/ikev2_pld.c +++ b/sbin/iked/ikev2_pld.c @@ -1,7 +1,8 @@ -/* $OpenBSD: ikev2_pld.c,v 1.38 2014/02/17 11:00:14 reyk Exp $ */ +/* $OpenBSD: ikev2_pld.c,v 1.39 2014/04/10 16:08:02 reyk Exp $ */ /* * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org> + * Copyright (c) 2014 Hans-Joerg Hoexer * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -45,42 +46,72 @@ #include "eap.h" #include "dh.h" +int ikev2_validate_pld(struct iked_message *, size_t, size_t, + struct ikev2_payload *); int ikev2_pld_payloads(struct iked *, struct iked_message *, - off_t, size_t, u_int, int); + size_t, size_t, u_int); +int ikev2_validate_sa(struct iked_message *, size_t, size_t, + struct ikev2_payload *, struct ikev2_sa_proposal *); int ikev2_pld_sa(struct iked *, struct ikev2_payload *, - struct iked_message *, off_t); + struct iked_message *, size_t, size_t); +int ikev2_validate_xform(struct iked_message *, size_t, size_t, + struct ikev2_transform *); int ikev2_pld_xform(struct iked *, struct ikev2_sa_proposal *, - struct iked_message *, off_t); + struct iked_message *, size_t, size_t); +int ikev2_validate_attr(struct iked_message *, size_t, size_t, + struct ikev2_attribute *); int ikev2_pld_attr(struct iked *, struct ikev2_transform *, - struct iked_message *, off_t, int); + struct iked_message *, size_t, size_t); +int ikev2_validate_ke(struct iked_message *, size_t, size_t, + struct ikev2_payload *, struct ikev2_keyexchange *); int ikev2_pld_ke(struct iked *, struct ikev2_payload *, - struct iked_message *, off_t); + struct iked_message *, size_t, size_t); +int ikev2_validate_id(struct iked_message *, size_t, size_t, + struct ikev2_payload *, struct ikev2_id *); int ikev2_pld_id(struct iked *, struct ikev2_payload *, - struct iked_message *, off_t, u_int); + struct iked_message *, size_t, size_t, u_int); +int ikev2_validate_cert(struct iked_message *, size_t, size_t, + struct ikev2_payload *, struct ikev2_cert *); int ikev2_pld_cert(struct iked *, struct ikev2_payload *, - struct iked_message *, off_t); + struct iked_message *, size_t, size_t); +int ikev2_validate_certreq(struct iked_message *, size_t, size_t, + struct ikev2_payload *, struct ikev2_cert *); int ikev2_pld_certreq(struct iked *, struct ikev2_payload *, - struct iked_message *, off_t); + struct iked_message *, size_t, size_t); +int ikev2_validate_nonce(struct iked_message *, size_t, size_t, + struct ikev2_payload *); int ikev2_pld_nonce(struct iked *, struct ikev2_payload *, - struct iked_message *, off_t); + struct iked_message *, size_t, size_t); +int ikev2_validate_notify(struct iked_message *, size_t, size_t, + struct ikev2_payload *, struct ikev2_notify *); int ikev2_pld_notify(struct iked *, struct ikev2_payload *, - struct iked_message *, off_t); + struct iked_message *, size_t, size_t); +int ikev2_validate_delete(struct iked_message *, size_t, size_t, + struct ikev2_payload *, struct ikev2_delete *); int ikev2_pld_delete(struct iked *, struct ikev2_payload *, - struct iked_message *, off_t); + struct iked_message *, size_t, size_t); +int ikev2_validate_ts(struct iked_message *, size_t, size_t, + struct ikev2_payload *, struct ikev2_tsp *); int ikev2_pld_ts(struct iked *, struct ikev2_payload *, - struct iked_message *, off_t, u_int); + struct iked_message *, size_t, size_t, u_int); +int ikev2_validate_auth(struct iked_message *, size_t, size_t, + struct ikev2_payload *, struct ikev2_auth *); int ikev2_pld_auth(struct iked *, struct ikev2_payload *, - struct iked_message *, off_t); + struct iked_message *, size_t, size_t); int ikev2_pld_e(struct iked *, struct ikev2_payload *, - struct iked_message *, off_t); + struct iked_message *, size_t); +int ikev2_validate_cp(struct iked_message *, size_t, size_t, + struct ikev2_payload *, struct ikev2_cp *); int ikev2_pld_cp(struct iked *, struct ikev2_payload *, - struct iked_message *, off_t); + struct iked_message *, size_t, size_t); +int ikev2_validate_eap(struct iked_message *, size_t, size_t, + struct ikev2_payload *, struct eap_header *); int ikev2_pld_eap(struct iked *, struct ikev2_payload *, - struct iked_message *, off_t); + struct iked_message *, size_t, size_t); int ikev2_pld_parse(struct iked *env, struct ike_header *hdr, - struct iked_message *msg, off_t offset) + struct iked_message *msg, size_t offset) { log_debug("%s: header ispi %s rspi %s" " nextpayload %s version 0x%02x exchange %s flags 0x%02x" @@ -103,94 +134,130 @@ ikev2_pld_parse(struct iked *env, struct ike_header *hdr, offset += sizeof(*hdr); return (ikev2_pld_payloads(env, msg, offset, - betoh32(hdr->ike_length), hdr->ike_nextpayload, 0)); + betoh32(hdr->ike_length), hdr->ike_nextpayload)); +} + +int +ikev2_validate_pld(struct iked_message *msg, size_t offset, size_t left, + struct ikev2_payload *pld) +{ + u_int8_t *msgbuf = ibuf_data(msg->msg_data); + size_t pld_length; + + /* We need at least the generic header. */ + if (left < sizeof(*pld)) { + log_debug("%s: malformed payload: too short for generic " + "header (%zu < %zu)", __func__, left, sizeof(*pld)); + return (-1); + } + memcpy(pld, msgbuf + offset, sizeof(*pld)); + + /* + * We need at least the specified number of bytes. + * pld_length is the full size of the payload including + * the generic payload header. + */ + pld_length = betoh16(pld->pld_length); + if (left < pld_length) { + log_debug("%s: malformed payload: shorter than specified " + "(%zu < %zu)", __func__, left, pld_length); + return (-1); + } + /* + * Sanity check the specified payload size, it must + * be at last the size of the generic payload header. + */ + if (pld_length < sizeof(*pld)) { + log_debug("%s: malformed payload: shorter than minimum " + "header size (%zu < %zu)", __func__, pld_length, + sizeof(*pld)); + return (-1); + } + + return (0); } int ikev2_pld_payloads(struct iked *env, struct iked_message *msg, - off_t offset, size_t length, u_int payload, int quick) + 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; - if (quick) - print_debug("%s: %spayloads", __func__, - e ? "decrypted " : ""); - else - ikev2_pld_payloads(env, msg, offset, length, payload, 1); + while (payload != 0 && offset < length) { + /* Bytes left in datagram. */ + left = length - offset; - while (payload != 0 && offset < (off_t)length) { - memcpy(&pld, msgbuf + offset, sizeof(pld)); + if (ikev2_validate_pld(msg, offset, left, &pld)) + return (-1); - 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)); + 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; - 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); + 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); + 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, payload); + 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); + 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); + ret = ikev2_pld_certreq(env, &pld, msg, offset, left); break; case IKEV2_PAYLOAD_AUTH | IKED_E: - ret = ikev2_pld_auth(env, &pld, msg, offset); + 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); + 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); + ret = ikev2_pld_notify(env, &pld, msg, offset, left); break; case IKEV2_PAYLOAD_DELETE | IKED_E: - ret = ikev2_pld_delete(env, &pld, msg, offset); + 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, payload); + 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); + ret = ikev2_pld_cp(env, &pld, msg, offset, left); break; case IKEV2_PAYLOAD_EAP | IKED_E: - ret = ikev2_pld_eap(env, &pld, msg, offset); + ret = ikev2_pld_eap(env, &pld, msg, offset, left); break; default: print_hex(msgbuf, offset, @@ -207,20 +274,87 @@ ikev2_pld_payloads(struct iked *env, struct iked_message *msg, 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_validate_sa(struct iked_message *msg, size_t offset, size_t left, + struct ikev2_payload *pld, struct ikev2_sa_proposal *sap) +{ + u_int8_t *msgbuf = ibuf_data(msg->msg_data); + size_t pld_length, sap_length; + + pld_length = betoh16(pld->pld_length); + if (pld_length < sizeof(*pld) + sizeof(*sap)) { + log_debug("%s: malformed payload: specified length smaller " + "than minimum size (%zu < %zu)", __func__, pld_length, + sizeof(*pld) + sizeof(*sap)); + return (-1); + } + + /* This will actually be caught by earlier checks. */ + if (left < sizeof(*sap)) { + log_debug("%s: malformed payload: too short for header " + "(%zu < %zu)", __func__, left, sizeof(*sap)); + return (-1); + } + memcpy(sap, msgbuf + offset, sizeof(*sap)); + sap_length = betoh16(sap->sap_length); + if (sap_length < sizeof(*sap)) { + log_debug("%s: malformed payload: shorter than minimum header " + "size (%zu < %zu)", __func__, sap_length, sizeof(*sap)); + return (-1); + } + if (left < sap_length) { + log_debug("%s: malformed payload: too long for actual payload " + "size (%zu < %zu)", __func__, left, sap_length); + return (-1); + } + /* + * NB: There might be more proposals, we parse only the first one. + * This condition must never be true. + */ + if (pld_length - sizeof(*pld) < sap_length) { + log_debug("%s: payload malformed: SA payload length mismatches " + "proposal substructure length (%lu < %zu)", __func__, + pld_length - sizeof(*pld), sap_length); + return (-1); + } + /* + * If there is only one proposal, sap_length must be the + * total payload size. + */ + if (!sap->sap_more && ((pld_length - sizeof(*pld)) != sap_length)) { + log_debug("%s: payload malformed: SA payload length mismatches " + "single proposal substructure length (%lu != %zu)", + __func__, pld_length - sizeof(*pld), sap_length); + return (-1); + } + /* + * If there are more than one proposal, there must be bytes + * left in the payload. + */ + if (sap->sap_more && ((pld_length - sizeof(*pld)) <= sap_length)) { + log_debug("%s: payload malformed: SA payload too small for " + "further proposals (%zu <= %zu)", __func__, + pld_length - sizeof(*pld), sap_length); + return (-1); + } return (0); } +/* + * NB: This function parses both the SA header and the first proposal. + * Additional proposals are ignored. + */ int ikev2_pld_sa(struct iked *env, struct ikev2_payload *pld, - struct iked_message *msg, off_t offset) + struct iked_message *msg, size_t offset, size_t left) { struct ikev2_sa_proposal sap; struct iked_proposal *prop = NULL; @@ -228,13 +362,40 @@ ikev2_pld_sa(struct iked *env, struct ikev2_payload *pld, u_int64_t spi = 0, spi64; u_int8_t *msgbuf = ibuf_data(msg->msg_data); struct iked_proposals *props; + size_t total; + + if (ikev2_validate_sa(msg, offset, left, pld, &sap)) + return (-1); + + if (sap.sap_more) + log_debug("%s: more than one proposal specified", __func__); + + /* Assumed size of the first proposals, including SPI if present. */ + total = (betoh16(sap.sap_length) - sizeof(sap)); props = &msg->msg_parent->msg_proposals; - memcpy(&sap, msgbuf + offset, sizeof(sap)); offset += sizeof(sap); + left -= sizeof(sap); if (sap.sap_spisize) { + if (left < sap.sap_spisize) { + log_debug("%s: malformed payload: SPI larger than " + "actual payload (%zu < %d)", __func__, left, + sap.sap_spisize); + return (-1); + } + if (total < sap.sap_spisize) { + log_debug("%s: malformed payload: SPI larger than " + "proposal (%zu < %d)", __func__, total, + sap.sap_spisize); + return (-1); + } + if (total < sap.sap_spisize) { + log_debug("%s: malformed payload: SPI too large " + "(%zu < %d)", __func__, total, sap.sap_spisize); + return (-1); + } switch (sap.sap_spisize) { case 4: memcpy(&spi32, msgbuf + offset, 4); @@ -251,6 +412,20 @@ ikev2_pld_sa(struct iked *env, struct ikev2_payload *pld, } offset += sap.sap_spisize; + left -= sap.sap_spisize; + + /* Assumed size of the proposal, now without SPI. */ + total -= sap.sap_spisize; + } + + /* + * As we verified sanity of packet headers, this check will + * be always false, but just to be sure we keep it. + */ + if (left < total) { + log_debug("%s: payload malformed: too long for payload " + "(%zu < %zu)", __func__, left, total); + return (-1); } log_debug("%s: more %d reserved %d length %d" @@ -279,7 +454,7 @@ ikev2_pld_sa(struct iked *env, struct ikev2_payload *pld, * Parse the attached transforms */ if (sap.sap_transforms && - ikev2_pld_xform(env, &sap, msg, offset) != 0) { + ikev2_pld_xform(env, &sap, msg, offset, total) != 0) { log_debug("%s: invalid proposal transforms", __func__); return (-1); } @@ -288,14 +463,47 @@ ikev2_pld_sa(struct iked *env, struct ikev2_payload *pld, } int +ikev2_validate_xform(struct iked_message *msg, size_t offset, size_t total, + struct ikev2_transform *xfrm) +{ + u_int8_t *msgbuf = ibuf_data(msg->msg_data); + size_t xfrm_length; + + if (total < sizeof(*xfrm)) { + log_debug("%s: payload malformed: too short for header " + "(%zu < %zu)", __func__, total, sizeof(*xfrm)); + return (-1); + } + memcpy(xfrm, msgbuf + offset, sizeof(*xfrm)); + + xfrm_length = betoh16(xfrm->xfrm_length); + if (xfrm_length < sizeof(*xfrm)) { + log_debug("%s: payload malformed: shorter than minimal header " + "(%zu < %zu)", __func__, xfrm_length, sizeof(*xfrm)); + return (-1); + } + if (total < xfrm_length) { + log_debug("%s: malformed payload: too long for payload size " + "(%zu < %zu)", __func__, total, xfrm_length); + return (-1); + } + + return (0); +} + +int ikev2_pld_xform(struct iked *env, struct ikev2_sa_proposal *sap, - struct iked_message *msg, off_t offset) + struct iked_message *msg, size_t offset, size_t total) { struct ikev2_transform xfrm; char id[BUFSIZ]; - u_int8_t *msgbuf = ibuf_data(msg->msg_data); + int ret = 0; + size_t xfrm_length; + + if (ikev2_validate_xform(msg, offset, total, &xfrm)) + return (-1); - memcpy(&xfrm, msgbuf + offset, sizeof(xfrm)); + xfrm_length = betoh16(xfrm.xfrm_length); switch (xfrm.xfrm_type) { case IKEV2_XFORMTYPE_ENCR: @@ -323,19 +531,21 @@ ikev2_pld_xform(struct iked *env, struct ikev2_sa_proposal *sap, break; } - log_debug("%s: more %d reserved %d length %d" + log_debug("%s: more %d reserved %d length %zu" " type %s id %s", - __func__, xfrm.xfrm_more, xfrm.xfrm_reserved, - betoh16(xfrm.xfrm_length), + __func__, xfrm.xfrm_more, xfrm.xfrm_reserved, xfrm_length, print_map(xfrm.xfrm_type, ikev2_xformtype_map), id); /* * Parse transform attributes, if available */ msg->msg_attrlength = 0; - if ((u_int)betoh16(xfrm.xfrm_length) > sizeof(xfrm)) - ikev2_pld_attr(env, &xfrm, msg, offset + sizeof(xfrm), - betoh16(xfrm.xfrm_length) - sizeof(xfrm)); + if (xfrm_length > sizeof(xfrm)) { + if (ikev2_pld_attr(env, &xfrm, msg, offset + sizeof(xfrm), + xfrm_length - sizeof(xfrm)) != 0) { + return (-1); + } + } if (ikev2_msg_frompeer(msg)) { if (config_add_transform(msg->msg_parent->msg_prop, @@ -347,26 +557,52 @@ ikev2_pld_xform(struct iked *env, struct ikev2_sa_proposal *sap, } /* Next transform */ - offset += betoh16(xfrm.xfrm_length); + offset += xfrm_length; + total -= xfrm_length; if (xfrm.xfrm_more == IKEV2_XFORM_MORE) - ikev2_pld_xform(env, sap, msg, offset); + ret = ikev2_pld_xform(env, sap, msg, offset, total); + else if (total != 0) { + /* No more transforms but still some data left. */ + log_debug("%s: less data than specified, %zu bytes left", + __func__, total); + ret = -1; + } + + return (ret); +} + +int +ikev2_validate_attr(struct iked_message *msg, size_t offset, size_t total, + struct ikev2_attribute *attr) +{ + u_int8_t *msgbuf = ibuf_data(msg->msg_data); + + if (total < sizeof(*attr)) { + log_debug("%s: payload malformed: too short for header " + "(%zu < %zu)", __func__, total, sizeof(*attr)); + return (-1); + } + memcpy(attr, msgbuf + offset, sizeof(*attr)); return (0); } int ikev2_pld_attr(struct iked *env, struct ikev2_transform *xfrm, - struct iked_message *msg, off_t offset, int total) + struct iked_message *msg, size_t offset, size_t total) { struct ikev2_attribute attr; u_int type; u_int8_t *msgbuf = ibuf_data(msg->msg_data); + int ret = 0; + size_t attr_length; - memcpy(&attr, msgbuf + offset, sizeof(attr)); + if (ikev2_validate_attr(msg, offset, total, &attr)) + return (-1); type = betoh16(attr.attr_type) & ~IKEV2_ATTRAF_TV; - log_debug("%s: attribute type %s length %d total %d", + log_debug("%s: attribute type %s length %d total %zu", __func__, print_map(type, ikev2_attrtype_map), betoh16(attr.attr_length), total); @@ -379,30 +615,64 @@ ikev2_pld_attr(struct iked *env, struct ikev2_transform *xfrm, msg->msg_attrlength = betoh16(attr.attr_length); } else { /* Type-Length-Value attribute */ + attr_length = betoh16(attr.attr_length); + if (total < attr_length) { + log_debug("%s: payload malformed: attribute larger " + "than actual payload (%zu < %zu)", __func__, + total, attr_length); + return (-1); + } print_hex(msgbuf, offset + sizeof(attr), - betoh16(attr.attr_length) - sizeof(attr)); - offset += betoh16(attr.attr_length); - total -= betoh16(attr.attr_length); + attr_length - sizeof(attr)); + offset += attr_length; + total -= attr_length; } if (total > 0) { /* Next attribute */ - ikev2_pld_attr(env, xfrm, msg, offset, total); + ret = ikev2_pld_attr(env, xfrm, msg, offset, total); } + return (ret); +} + +int +ikev2_validate_ke(struct iked_message *msg, size_t offset, size_t left, + struct ikev2_payload *pld, struct ikev2_keyexchange *kex) +{ + u_int8_t *msgbuf = ibuf_data(msg->msg_data); + size_t pld_length; + + pld_length = betoh16(pld->pld_length); + if (pld_length < sizeof(*pld) + sizeof(*kex)) { + log_debug("%s: malformed payload: specified length smaller " + "than minimum size (%zu < %zu)", __func__, pld_length, + sizeof(*pld) + sizeof(*kex)); + return (-1); + } + + /* This will actually be caught by earlier checks. */ + if (left < sizeof(*kex)) { + log_debug("%s: malformed payload: too short for header " + "(%zu < %zu)", __func__, left, sizeof(*kex)); + return (-1); + } + memcpy(kex, msgbuf + offset, sizeof(*kex)); + return (0); } int ikev2_pld_ke(struct iked *env, struct ikev2_payload *pld, - struct iked_message *msg, off_t offset) + struct iked_message *msg, size_t offset, size_t left) { struct ikev2_keyexchange kex; u_int8_t *buf; size_t len; u_int8_t *msgbuf = ibuf_data(msg->msg_data); - memcpy(&kex, msgbuf + offset, sizeof(kex)); + if (ikev2_validate_ke(msg, offset, left, pld, &kex)) + return (-1); log_debug("%s: dh group %s reserved %d", __func__, print_map(betoh16(kex.kex_dhgroup), ikev2_xformdh_map), @@ -411,6 +681,17 @@ ikev2_pld_ke(struct iked *env, struct ikev2_payload *pld, buf = msgbuf + offset + sizeof(kex); len = betoh16(pld->pld_length) - sizeof(*pld) - sizeof(kex); + if (len == 0) { + log_debug("%s: malformed payload: no KE data given", __func__); + return (-1); + } + /* This will actually be caught by earlier checks. */ + if (left < len) { + log_debug("%s: malformed payload: smaller than specified " + "(%zu < %zu)", __func__, left, len); + return (-1); + } + print_hex(buf, 0, len); if (ikev2_msg_frompeer(msg)) { @@ -425,8 +706,34 @@ ikev2_pld_ke(struct iked *env, struct ikev2_payload *pld, } int +ikev2_validate_id(struct iked_message *msg, size_t offset, size_t left, + struct ikev2_payload *pld, struct ikev2_id *id) +{ + u_int8_t *msgbuf = ibuf_data(msg->msg_data); + size_t pld_length; + + pld_length = betoh16(pld->pld_length); + if (pld_length < sizeof(*pld) + sizeof(*id)) { + log_debug("%s: malformed payload: specified length smaller " + "than minimum size (%zu < %zu)", __func__, pld_length, + sizeof(*pld) + sizeof(*id)); + return (-1); + } + + /* This will actually be caught by earlier checks. */ + if (left < sizeof(*id)) { + log_debug("%s: malformed payload: too short for header " + "(%zu < %zu)", __func__, left, sizeof(*id)); + return (-1); + } + memcpy(id, msgbuf + offset, sizeof(*id)); + + return (0); +} + +int ikev2_pld_id(struct iked *env, struct ikev2_payload *pld, - struct iked_message *msg, off_t offset, u_int payload) + struct iked_message *msg, size_t offset, size_t left, u_int payload) { u_int8_t *ptr; struct ikev2_id id; @@ -436,7 +743,9 @@ ikev2_pld_id(struct iked *env, struct ikev2_payload *pld, u_int8_t *msgbuf = ibuf_data(msg->msg_data); char idstr[IKED_ID_SIZE]; - memcpy(&id, msgbuf + offset, sizeof(id)); + if (ikev2_validate_id(msg, offset, left, pld, &id)) + return (-1); + bzero(&idb, sizeof(idb)); /* Don't strip the Id payload header */ @@ -480,8 +789,34 @@ ikev2_pld_id(struct iked *env, struct ikev2_payload *pld, } int +ikev2_validate_cert(struct iked_message *msg, size_t offset, size_t left, + struct ikev2_payload *pld, struct ikev2_cert *cert) +{ + u_int8_t *msgbuf = ibuf_data(msg->msg_data); + size_t pld_length; + + pld_length = betoh16(pld->pld_length); + if (pld_length < sizeof(*pld) + sizeof(*cert)) { + log_debug("%s: malformed payload: specified length smaller " + "than minimum size (%zu < %zu)", __func__, pld_length, + sizeof(*pld) + sizeof(*cert)); + return (-1); + } + + /* This will actually be caught by earlier checks. */ + if (left < sizeof(*cert)) { + log_debug("%s: malformed payload: too short for header " + "(%zu < %zu)", __func__, left, sizeof(*cert)); + return (-1); + } + memcpy(cert, msgbuf + offset, sizeof(*cert)); + + return (0); +} + +int ikev2_pld_cert(struct iked *env, struct ikev2_payload *pld, - struct iked_message *msg, off_t offset) + struct iked_message *msg, size_t offset, size_t left) { struct ikev2_cert cert; u_int8_t *buf; @@ -489,7 +824,8 @@ ikev2_pld_cert(struct iked *env, struct ikev2_payload *pld, struct iked_id *certid; u_int8_t *msgbuf = ibuf_data(msg->msg_data); - memcpy(&cert, msgbuf + offset, sizeof(cert)); + if (ikev2_validate_cert(msg, offset, left, pld, &cert)) + return (-1); offset += sizeof(cert); buf = msgbuf + offset; @@ -520,8 +856,34 @@ ikev2_pld_cert(struct iked *env, struct ikev2_payload *pld, } int +ikev2_validate_certreq(struct iked_message *msg, size_t offset, size_t left, + struct ikev2_payload *pld, struct ikev2_cert *cert) +{ + u_int8_t *msgbuf = ibuf_data(msg->msg_data); + size_t pld_length; + + pld_length = betoh16(pld->pld_length); + if (pld_length < sizeof(*pld) + sizeof(*cert)) { + log_debug("%s: malformed payload: specified length smaller " + "than minimum size (%zu < %zu)", __func__, pld_length, + sizeof(*pld) + sizeof(*cert)); + return (-1); + } + + /* This will actually be caught by earlier checks. */ + if (left < sizeof(*cert)) { + log_debug("%s: malformed payload: too short for header " + "(%zu < %zu)", __func__, left, sizeof(*cert)); + return (-1); + } + memcpy(cert, msgbuf + offset, sizeof(*cert)); + + return (0); +} + +int ikev2_pld_certreq(struct iked *env, struct ikev2_payload *pld, - struct iked_message *msg, off_t offset) + struct iked_message *msg, size_t offset, size_t left) { struct iked_sa *sa = msg->msg_sa; struct ikev2_cert cert; @@ -529,7 +891,8 @@ ikev2_pld_certreq(struct iked *env, struct ikev2_payload *pld, ssize_t len; u_int8_t *msgbuf = ibuf_data(msg->msg_data); - memcpy(&cert, msgbuf + offset, sizeof(cert)); + if (ikev2_validate_certreq(msg, offset, left, pld, &cert)) + return (-1); offset += sizeof(cert); buf = msgbuf + offset; @@ -538,6 +901,7 @@ ikev2_pld_certreq(struct iked *env, struct ikev2_payload *pld, log_debug("%s: type %s length %zd", __func__, print_map(cert.cert_type, ikev2_cert_map), len); + /* This will actually be caught by earlier checks. */ if (len < 0) { log_debug("%s: invalid certificate request length", __func__); return (-1); @@ -571,8 +935,34 @@ ikev2_pld_certreq(struct iked *env, struct ikev2_payload *pld, } int +ikev2_validate_auth(struct iked_message *msg, size_t offset, size_t left, + struct ikev2_payload *pld, struct ikev2_auth *auth) +{ + u_int8_t *msgbuf = ibuf_data(msg->msg_data); + size_t pld_length; + + pld_length = betoh16(pld->pld_length); + if (pld_length < sizeof(*pld) + sizeof(*auth)) { + log_debug("%s: malformed payload: specified length smaller " + "than minimum size (%zu < %zu)", __func__, pld_length, + sizeof(*pld) + sizeof(*auth)); + return (-1); + } + + /* This will actually be caught by earlier checks. */ + if (left < sizeof(*auth)) { + log_debug("%s: malformed payload: too short for header " + "(%zu < %zu)", __func__, left, sizeof(*auth)); + return (-1); + } + memcpy(auth, msgbuf + offset, sizeof(*auth)); + + return (0); +} + +int ikev2_pld_auth(struct iked *env, struct ikev2_payload *pld, - struct iked_message *msg, off_t offset) + struct iked_message *msg, size_t offset, size_t left) { struct ikev2_auth auth; struct iked_id *idp; @@ -581,7 +971,8 @@ ikev2_pld_auth(struct iked *env, struct ikev2_payload *pld, struct iked_sa *sa = msg->msg_sa; u_int8_t *msgbuf = ibuf_data(msg->msg_data); - memcpy(&auth, msgbuf + offset, sizeof(auth)); + if (ikev2_validate_auth(msg, offset, left, pld, &auth)) + return (-1); offset += sizeof(auth); buf = msgbuf + offset; @@ -615,15 +1006,48 @@ ikev2_pld_auth(struct iked *env, struct ikev2_payload *pld, } int +ikev2_validate_nonce(struct iked_message *msg, size_t offset, size_t left, + struct ikev2_payload *pld) +{ + size_t pld_length; + + /* This will actually be caught by earlier checks. */ + pld_length = betoh16(pld->pld_length); + if (pld_length < sizeof(*pld)) { + log_debug("%s: malformed payload: specified length smaller " + "than minimum size (%zu < %zu)", __func__, pld_length, + sizeof(*pld)); + return (-1); + } + + return (0); +} + +int ikev2_pld_nonce(struct iked *env, struct ikev2_payload *pld, - struct iked_message *msg, off_t offset) + struct iked_message *msg, size_t offset, size_t left) { size_t len; u_int8_t *buf; u_int8_t *msgbuf = ibuf_data(msg->msg_data); + if (ikev2_validate_nonce(msg, offset, left, pld)) + return (-1); + buf = msgbuf + offset; len = betoh16(pld->pld_length) - sizeof(*pld); + + if (len == 0) { + log_debug("%s: malformed payload: no NONCE given", __func__); + return (-1); + } + /* This will actually be caught by earlier checks. */ + if (left < len) { + log_debug("%s: malformed payload: smaller than specified " + "(%zu < %zu)", __func__, left, len); + return (-1); + } + print_hex(buf, 0, len); if (ikev2_msg_frompeer(msg)) { @@ -639,10 +1063,36 @@ ikev2_pld_nonce(struct iked *env, struct ikev2_payload *pld, } int +ikev2_validate_notify(struct iked_message *msg, size_t offset, size_t left, + struct ikev2_payload *pld, struct ikev2_notify *n) +{ + u_int8_t *msgbuf = ibuf_data(msg->msg_data); + size_t pld_length; + + pld_length = betoh16(pld->pld_length); + if (pld_length < sizeof(*pld) + sizeof(*n)) { + log_debug("%s: malformed payload: specified length smaller " + "than minimum size (%zu < %zu)", __func__, pld_length, + sizeof(*pld) + sizeof(*n)); + return (-1); + } + + /* This will actually be caught by earlier checks. */ + if (left < sizeof(*n)) { + log_debug("%s: malformed payload: too short for header " + "(%zu < %zu)", __func__, left, sizeof(*n)); + return (-1); + } + memcpy(n, msgbuf + offset, sizeof(*n)); + + return (0); +} + +int ikev2_pld_notify(struct iked *env, struct ikev2_payload *pld, - struct iked_message *msg, off_t offset) + struct iked_message *msg, size_t offset, size_t left) { - struct ikev2_notify *n; + struct ikev2_notify n; u_int8_t *buf, md[SHA_DIGEST_LENGTH]; size_t len; u_int32_t spi32; @@ -653,17 +1103,17 @@ ikev2_pld_notify(struct iked *env, struct ikev2_payload *pld, u_int16_t cpi; u_int8_t transform; - if ((n = ibuf_seek(msg->msg_data, offset, sizeof(*n))) == NULL) + if (ikev2_validate_notify(msg, offset, left, pld, &n)) return (-1); - type = betoh16(n->n_type); + type = betoh16(n.n_type); log_debug("%s: protoid %s spisize %d type %s", __func__, - print_map(n->n_protoid, ikev2_saproto_map), n->n_spisize, + print_map(n.n_protoid, ikev2_saproto_map), n.n_spisize, print_map(type, ikev2_n_map)); - len = betoh16(pld->pld_length) - sizeof(*pld) - sizeof(*n); - if ((buf = ibuf_seek(msg->msg_data, offset + sizeof(*n), len)) == NULL) + len = betoh16(pld->pld_length) - sizeof(*pld) - sizeof(n); + if ((buf = ibuf_seek(msg->msg_data, offset + sizeof(n), len)) == NULL) return (-1); print_hex(buf, 0, len); @@ -674,9 +1124,14 @@ ikev2_pld_notify(struct iked *env, struct ikev2_payload *pld, switch (type) { case IKEV2_N_NAT_DETECTION_SOURCE_IP: case IKEV2_N_NAT_DETECTION_DESTINATION_IP: + if (len != sizeof(md)) { + log_debug("%s: malformed payload: hash size mismatch" + " (%zu != %zu)", __func__, len, sizeof(md)); + return (-1); + } if (ikev2_nat_detection(env, msg, md, sizeof(md), type) == -1) return (-1); - if (len != sizeof(md) || memcmp(buf, md, len) != 0) { + if (memcmp(buf, md, len) != 0) { log_debug("%s: %s detected NAT, enabling " "UDP encapsulation", __func__, print_map(type, ikev2_n_map)); @@ -692,7 +1147,8 @@ ikev2_pld_notify(struct iked *env, struct ikev2_payload *pld, break; case IKEV2_N_INVALID_KE_PAYLOAD: if (len != sizeof(group)) { - log_debug("%s: malformed notification", __func__); + log_debug("%s: malformed payload: group size mismatch" + " (%zu != %zu)", __func__, len, sizeof(group)); return (-1); } if (!msg->msg_sa->sa_hdr.sh_initiator) { @@ -724,7 +1180,7 @@ ikev2_pld_notify(struct iked *env, struct ikev2_payload *pld, } break; case IKEV2_N_REKEY_SA: - if (len != n->n_spisize) { + if (len != n.n_spisize) { log_debug("%s: malformed notification", __func__); return (-1); } @@ -734,7 +1190,7 @@ ikev2_pld_notify(struct iked *env, struct ikev2_payload *pld, __func__); return (-1); } - switch (n->n_spisize) { + switch (n.n_spisize) { case 4: memcpy(&spi32, buf, len); rekey->spi = betoh32(spi32); @@ -745,19 +1201,19 @@ ikev2_pld_notify(struct iked *env, struct ikev2_payload *pld, break; default: log_debug("%s: invalid spi size %d", __func__, - n->n_spisize); + n.n_spisize); return (-1); } - rekey->spi_size = n->n_spisize; - rekey->spi_protoid = n->n_protoid; + rekey->spi_size = n.n_spisize; + rekey->spi_protoid = n.n_protoid; log_debug("%s: rekey %s spi %s", __func__, - print_map(n->n_protoid, ikev2_saproto_map), - print_spi(rekey->spi, n->n_spisize)); + print_map(n.n_protoid, ikev2_saproto_map), + print_spi(rekey->spi, n.n_spisize)); break; case IKEV2_N_IPCOMP_SUPPORTED: if (len < sizeof(cpi) + sizeof(transform)) { - log_debug("%s: malformed ipcomp notification", + log_debug("%s: ignoring malformed ipcomp notification", __func__); return (0); } @@ -778,12 +1234,38 @@ ikev2_pld_notify(struct iked *env, struct ikev2_payload *pld, } int +ikev2_validate_delete(struct iked_message *msg, size_t offset, size_t left, + struct ikev2_payload *pld, struct ikev2_delete *del) +{ + u_int8_t *msgbuf = ibuf_data(msg->msg_data); + size_t pld_length; + + pld_length = betoh16(pld->pld_length); + if (pld_length < sizeof(*pld) + sizeof(*del)) { + log_debug("%s: malformed payload: specified length smaller " + "than minimum size (%zu < %zu)", __func__, pld_length, + sizeof(*pld) + sizeof(*del)); + return (-1); + } + + /* This will actually be caught by earlier checks. */ + if (left < sizeof(*del)) { + log_debug("%s: malformed payload: too short for header " + "(%zu < %zu)", __func__, left, sizeof(*del)); + return (-1); + } + memcpy(del, msgbuf + offset, sizeof(*del)); + + return (0); +} + +int ikev2_pld_delete(struct iked *env, struct ikev2_payload *pld, - struct iked_message *msg, off_t offset) + struct iked_message *msg, size_t offset, size_t left) { struct iked_childsa **peersas = NULL; struct iked_sa *sa = msg->msg_sa; - struct ikev2_delete *del, *localdel; + struct ikev2_delete del, *localdel; struct ibuf *resp = NULL; u_int64_t *localspi = NULL; u_int64_t spi64, spi = 0; @@ -792,25 +1274,22 @@ ikev2_pld_delete(struct iked *env, struct ikev2_payload *pld, size_t found = 0, failed = 0; int cnt, i, len, sz, ret = -1; - /* Skip if it's a reply and we don't have to deal with it */ - if (ikev2_msg_frompeer(msg) && sa && - (sa->sa_stateflags & IKED_REQ_INF)) { - sa->sa_stateflags &= ~IKED_REQ_INF; - if ((sa->sa_stateflags & IKED_REQ_DELETE) == 0) - return (0); - } + /* Skip if it's a response, then we don't have to deal with it */ + if (ikev2_msg_frompeer(msg) && + msg->msg_parent->msg_response) + return (0); - if ((del = ibuf_seek(msg->msg_data, offset, sizeof(*del))) == NULL) + if (ikev2_validate_delete(msg, offset, left, pld, &del)) return (-1); - cnt = betoh16(del->del_nspi); - sz = del->del_spisize; + cnt = betoh16(del.del_nspi); + sz = del.del_spisize; log_debug("%s: proto %s spisize %d nspi %d", - __func__, print_map(del->del_protoid, ikev2_saproto_map), + __func__, print_map(del.del_protoid, ikev2_saproto_map), sz, cnt); - buf = msgbuf + offset + sizeof(*del); - len = betoh16(pld->pld_length) - sizeof(*pld) - sizeof(*del); + buf = msgbuf + offset + sizeof(del); + len = betoh16(pld->pld_length) - sizeof(*pld) - sizeof(del); print_hex(buf, 0, len); @@ -819,8 +1298,11 @@ ikev2_pld_delete(struct iked *env, struct ikev2_payload *pld, case 8: break; default: - if (ikev2_msg_frompeer(msg) && - del->del_protoid == IKEV2_SAPROTO_IKE) { + if (del.del_protoid != IKEV2_SAPROTO_IKE) { + log_debug("%s: invalid SPI size", __func__); + return (-1); + } + if (ikev2_msg_frompeer(msg)) { /* Send an empty informational response */ if ((resp = ibuf_static()) == NULL) goto done; @@ -833,7 +1315,7 @@ ikev2_pld_delete(struct iked *env, struct ikev2_payload *pld, return (ret); } log_debug("%s: invalid SPI size", __func__); - return (-1); + return (ret); } if ((len / sz) != cnt) { @@ -867,13 +1349,13 @@ ikev2_pld_delete(struct iked *env, struct ikev2_payload *pld, continue; if ((peersas[i] = childsa_lookup(sa, spi, - del->del_protoid)) == NULL) { + del.del_protoid)) == NULL) { log_warnx("%s: CHILD SA doesn't exist for spi %s", - __func__, print_spi(spi, del->del_spisize)); - goto done; + __func__, print_spi(spi, del.del_spisize)); + continue; } - if (ikev2_childsa_delete(env, sa, del->del_protoid, spi, + if (ikev2_childsa_delete(env, sa, del.del_protoid, spi, &localspi[i], 0) == -1) failed++; else @@ -889,9 +1371,7 @@ ikev2_pld_delete(struct iked *env, struct ikev2_payload *pld, if (!ikev2_msg_frompeer(msg)) goto done; - if (sa && (sa->sa_stateflags & IKED_REQ_DELETE)) { - /* Finish rekeying */ - sa->sa_stateflags &= ~IKED_REQ_DELETE; + if (msg->msg_parent->msg_response) { ret = 0; goto done; } @@ -905,8 +1385,8 @@ ikev2_pld_delete(struct iked *env, struct ikev2_payload *pld, if ((localdel = ibuf_advance(resp, sizeof(*localdel))) == NULL) goto done; - localdel->del_protoid = del->del_protoid; - localdel->del_spisize = del->del_spisize; + localdel->del_protoid = del.del_protoid; + localdel->del_spisize = del.del_spisize; localdel->del_nspi = htobe16(found); for (i = 0; i < cnt; i++) { @@ -946,8 +1426,34 @@ ikev2_pld_delete(struct iked *env, struct ikev2_payload *pld, } int +ikev2_validate_ts(struct iked_message *msg, size_t offset, size_t left, + struct ikev2_payload *pld, struct ikev2_tsp *tsp) +{ + u_int8_t *msgbuf = ibuf_data(msg->msg_data); + size_t pld_length; + + pld_length = betoh16(pld->pld_length); + if (pld_length < sizeof(*pld) + sizeof(*tsp)) { + log_debug("%s: malformed payload: specified length smaller " + "than minimum size (%zu < %zu)", __func__, pld_length, + sizeof(*pld) + sizeof(*tsp)); + return (-1); + } + + /* This will actually be caught by earlier checks. */ + if (left < sizeof(*tsp)) { + log_debug("%s: malformed payload: too short for header " + "(%zu < %zu)", __func__, left, sizeof(*tsp)); + return (-1); + } + memcpy(tsp, msgbuf + offset, sizeof(*tsp)); + + return (0); +} + +int ikev2_pld_ts(struct iked *env, struct ikev2_payload *pld, - struct iked_message *msg, off_t offset, u_int payload) + struct iked_message *msg, size_t offset, size_t left, u_int payload) { struct ikev2_tsp tsp; struct ikev2_ts ts; @@ -957,7 +1463,8 @@ ikev2_pld_ts(struct iked *env, struct ikev2_payload *pld, u_int8_t buf[2][128]; u_int8_t *msgbuf = ibuf_data(msg->msg_data); - memcpy(&tsp, msgbuf + offset, sizeof(tsp)); + if (ikev2_validate_ts(msg, offset, left, pld, &tsp)) + return (-1); offset += sizeof(tsp); len = betoh16(pld->pld_length) - sizeof(*pld) - sizeof(tsp); @@ -1018,7 +1525,7 @@ ikev2_pld_ts(struct iked *env, struct ikev2_payload *pld, int ikev2_pld_e(struct iked *env, struct ikev2_payload *pld, - struct iked_message *msg, off_t offset) + struct iked_message *msg, size_t offset) { struct iked_sa *sa = msg->msg_sa; struct ibuf *e = NULL; @@ -1056,7 +1563,7 @@ ikev2_pld_e(struct iked *env, struct ikev2_payload *pld, TAILQ_INIT(&emsg.msg_proposals); ret = ikev2_pld_payloads(env, &emsg, 0, ibuf_size(e), - pld->pld_nextpayload, 0); + pld->pld_nextpayload); done: ibuf_release(e); @@ -1065,8 +1572,34 @@ ikev2_pld_e(struct iked *env, struct ikev2_payload *pld, } int +ikev2_validate_cp(struct iked_message *msg, size_t offset, size_t left, + struct ikev2_payload *pld, struct ikev2_cp *cp) +{ + u_int8_t *msgbuf = ibuf_data(msg->msg_data); + size_t pld_length; + + pld_length = betoh16(pld->pld_length); + if (pld_length < sizeof(*pld) + sizeof(*cp)) { + log_debug("%s: malformed payload: specified length smaller " + "than minimum size (%zu < %zu)", __func__, pld_length, + sizeof(*pld) + sizeof(*cp)); + return (-1); + } + + /* This will actually be caught by earlier checks. */ + if (left < sizeof(*cp)) { + log_debug("%s: malformed payload: too short for header " + "(%zu < %zu)", __func__, left, sizeof(*cp)); + return (-1); + } + memcpy(cp, msgbuf + offset, sizeof(*cp)); + + return (0); +} + +int ikev2_pld_cp(struct iked *env, struct ikev2_payload *pld, - struct iked_message *msg, off_t offset) + struct iked_message *msg, size_t offset, size_t left) { struct ikev2_cp cp; struct ikev2_cfg *cfg; @@ -1075,7 +1608,8 @@ ikev2_pld_cp(struct iked *env, struct ikev2_payload *pld, u_int8_t *msgbuf = ibuf_data(msg->msg_data); struct iked_sa *sa = msg->msg_sa; - memcpy(&cp, msgbuf + offset, sizeof(cp)); + if (ikev2_validate_cp(msg, offset, left, pld, &cp)) + return (-1); offset += sizeof(cp); buf = msgbuf + offset; @@ -1106,25 +1640,48 @@ ikev2_pld_cp(struct iked *env, struct ikev2_payload *pld, } int +ikev2_validate_eap(struct iked_message *msg, size_t offset, size_t left, + struct ikev2_payload *pld, struct eap_header *hdr) +{ + u_int8_t *msgbuf = ibuf_data(msg->msg_data); + size_t pld_length; + + pld_length = betoh16(pld->pld_length); + if (pld_length < sizeof(*pld) + sizeof(*hdr)) { + log_debug("%s: malformed payload: specified length smaller " + "than minimum size (%zu < %zu)", __func__, pld_length, + sizeof(*pld) + sizeof(*hdr)); + return (-1); + } + + /* This will actually be caught by earlier checks. */ + if (left < sizeof(*hdr)) { + log_debug("%s: malformed payload: too short for header " + "(%zu < %zu)", __func__, left, sizeof(*hdr)); + return (-1); + } + memcpy(hdr, msgbuf + offset, sizeof(*hdr)); + + return (0); +} + +int ikev2_pld_eap(struct iked *env, struct ikev2_payload *pld, - struct iked_message *msg, off_t offset) + struct iked_message *msg, size_t offset, size_t left) { - struct eap_header *hdr; + struct eap_header hdr; struct eap_message *eap = NULL; struct iked_sa *sa = msg->msg_sa; size_t len; - if ((hdr = ibuf_seek(msg->msg_data, offset, sizeof(*hdr))) == NULL) { - log_debug("%s: failed to get EAP header", __func__); + if (ikev2_validate_eap(msg, offset, left, pld, &hdr)) return (-1); - } - - len = betoh16(hdr->eap_length); + len = betoh16(hdr.eap_length); if (len < sizeof(*eap)) { log_info("%s: %s id %d length %d", __func__, - print_map(hdr->eap_code, eap_code_map), - hdr->eap_id, betoh16(hdr->eap_length)); + print_map(hdr.eap_code, eap_code_map), + hdr.eap_id, betoh16(hdr.eap_length)); } else { /* Now try to get the indicated length */ if ((eap = ibuf_seek(msg->msg_data, offset, len)) == NULL) { @@ -1138,7 +1695,7 @@ ikev2_pld_eap(struct iked *env, struct ikev2_payload *pld, print_map(eap->eap_type, eap_type_map)); } - if (eap_parse(env, sa, hdr, msg->msg_response) == -1) + if (eap_parse(env, sa, &hdr, msg->msg_response) == -1) return (-1); return (0); |