On Mon, Dec 04, 2017 at 09:23:17PM +0100, Patrick Wildt wrote:
> Hi,
>
> this diff changes our SA payload parser to parse more than the first
> proposal. This allows us to select one of the peer's proposals (and not
> only the first). The xforms parser calls itself recursively without
> limits, which I'm not sure is a good idea. This diff uses a do {} while
> for the proposal parser instead. I'm not sure this is great, but I
> think it's better than the recursive way. I'd like to change the xforms
> parser to do the same later on.
>
> ok?
>
> Patrick
Updated diff, because I had committed something in the meantime. Should
apply cleanly to -current.
diff --git a/sbin/iked/ikev2_pld.c b/sbin/iked/ikev2_pld.c
index f3e21c3a41c..fb599d1c080 100644
--- a/sbin/iked/ikev2_pld.c
+++ b/sbin/iked/ikev2_pld.c
@@ -326,10 +326,6 @@ ikev2_validate_sa(struct iked_message *msg, size_t offset,
size_t left,
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, size_t offset, size_t left)
@@ -342,95 +338,97 @@ ikev2_pld_sa(struct iked *env, struct ikev2_payload *pld,
struct iked_proposals *props;
size_t total;
- if (ikev2_validate_sa(msg, offset, left, &sap))
- return (-1);
+ do {
+ if (ikev2_validate_sa(msg, offset, left, &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));
- /* Assumed size of the first proposals, including SPI if present. */
- total = (betoh16(sap.sap_length) - sizeof(sap));
+ props = &msg->msg_parent->msg_proposals;
- props = &msg->msg_parent->msg_proposals;
+ 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);
+ }
+ switch (sap.sap_spisize) {
+ case 4:
+ memcpy(&spi32, msgbuf + offset, 4);
+ spi = betoh32(spi32);
+ break;
+ case 8:
+ memcpy(&spi64, msgbuf + offset, 8);
+ spi = betoh64(spi64);
+ break;
+ default:
+ log_debug("%s: unsupported SPI size %d",
+ __func__, sap.sap_spisize);
+ return (-1);
+ }
- offset += sizeof(sap);
- left -= sizeof(sap);
+ offset += sap.sap_spisize;
+ left -= sap.sap_spisize;
- 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);
+ /* Assumed size of the proposal, now without SPI. */
+ total -= sap.sap_spisize;
}
- switch (sap.sap_spisize) {
- case 4:
- memcpy(&spi32, msgbuf + offset, 4);
- spi = betoh32(spi32);
- break;
- case 8:
- memcpy(&spi64, msgbuf + offset, 8);
- spi = betoh64(spi64);
- break;
- default:
- log_debug("%s: unsupported SPI size %d",
- __func__, 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: malformed payload: too long for payload "
+ "(%zu < %zu)", __func__, left, total);
return (-1);
}
- offset += sap.sap_spisize;
- left -= sap.sap_spisize;
+ log_debug("%s: more %d reserved %d length %d"
+ " proposal #%d protoid %s spisize %d xforms %d spi %s",
+ __func__, sap.sap_more, sap.sap_reserved,
+ betoh16(sap.sap_length), sap.sap_proposalnr,
+ print_map(sap.sap_protoid, ikev2_saproto_map),
sap.sap_spisize,
+ sap.sap_transforms, print_spi(spi, 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: malformed payload: too long for payload "
- "(%zu < %zu)", __func__, left, total);
- return (-1);
- }
+ if (ikev2_msg_frompeer(msg)) {
+ if ((msg->msg_parent->msg_prop =
config_add_proposal(props,
+ sap.sap_proposalnr, sap.sap_protoid)) == NULL) {
+ log_debug("%s: invalid proposal", __func__);
+ return (-1);
+ }
+ prop = msg->msg_parent->msg_prop;
+ prop->prop_peerspi.spi = spi;
+ prop->prop_peerspi.spi_protoid = sap.sap_protoid;
+ prop->prop_peerspi.spi_size = sap.sap_spisize;
- log_debug("%s: more %d reserved %d length %d"
- " proposal #%d protoid %s spisize %d xforms %d spi %s",
- __func__, sap.sap_more, sap.sap_reserved,
- betoh16(sap.sap_length), sap.sap_proposalnr,
- print_map(sap.sap_protoid, ikev2_saproto_map), sap.sap_spisize,
- sap.sap_transforms, print_spi(spi, sap.sap_spisize));
+ prop->prop_localspi.spi_protoid = sap.sap_protoid;
+ prop->prop_localspi.spi_size = sap.sap_spisize;
+ }
- if (ikev2_msg_frompeer(msg)) {
- if ((msg->msg_parent->msg_prop = config_add_proposal(props,
- sap.sap_proposalnr, sap.sap_protoid)) == NULL) {
- log_debug("%s: invalid proposal", __func__);
+ /*
+ * Parse the attached transforms
+ */
+ if (sap.sap_transforms &&
+ ikev2_pld_xform(env, &sap, msg, offset, total) != 0) {
+ log_debug("%s: invalid proposal transforms", __func__);
return (-1);
}
- prop = msg->msg_parent->msg_prop;
- prop->prop_peerspi.spi = spi;
- prop->prop_peerspi.spi_protoid = sap.sap_protoid;
- prop->prop_peerspi.spi_size = sap.sap_spisize;
- prop->prop_localspi.spi_protoid = sap.sap_protoid;
- prop->prop_localspi.spi_size = sap.sap_spisize;
- }
-
- /*
- * Parse the attached transforms
- */
- if (sap.sap_transforms &&
- ikev2_pld_xform(env, &sap, msg, offset, total) != 0) {
- log_debug("%s: invalid proposal transforms", __func__);
- return (-1);
- }
+ offset += total;
+ left -= total;
+ } while (sap.sap_more);
return (0);
}