diff options
author | Tobias Heider <tobhe@cvs.openbsd.org> | 2024-03-02 16:16:08 +0000 |
---|---|---|
committer | Tobias Heider <tobhe@cvs.openbsd.org> | 2024-03-02 16:16:08 +0000 |
commit | 5d25cd599e7dba10080f358c9d2101e6fa79eb4a (patch) | |
tree | 392bbe1b8e1a80184428c4c3352dc7d4dde29a64 /sbin/iked/ikev2_pld.c | |
parent | 903fc5927a38d6f0d7fd4d5684b66ce3dd3efeac (diff) |
Trigger retransmission only for fragment 1/x, otherwise each received
fragment can trigger retransmission of the full fragment queue.
From RFC7383, 2.6.1:
"[...] that even MUST only trigger a retransmission of the response message
(fragmented or no) if the Fragment Number field in the received
fragments is set to 1; otherwise, it MUST be ignored."
from markus
Diffstat (limited to 'sbin/iked/ikev2_pld.c')
-rw-r--r-- | sbin/iked/ikev2_pld.c | 78 |
1 files changed, 77 insertions, 1 deletions
diff --git a/sbin/iked/ikev2_pld.c b/sbin/iked/ikev2_pld.c index f207fbfc348..1fb5f305499 100644 --- a/sbin/iked/ikev2_pld.c +++ b/sbin/iked/ikev2_pld.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ikev2_pld.c,v 1.133 2023/09/02 18:36:30 tobhe Exp $ */ +/* $OpenBSD: ikev2_pld.c,v 1.134 2024/03/02 16:16:07 tobhe Exp $ */ /* * Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de> @@ -2103,3 +2103,79 @@ ikev2_pld_eap(struct iked *env, struct ikev2_payload *pld, return (0); } + +/* parser for the initial IKE_AUTH payload, does not require msg_sa */ +int +ikev2_pld_parse_quick(struct iked *env, struct ike_header *hdr, + struct iked_message *msg, size_t offset) +{ + struct ikev2_payload pld; + struct ikev2_frag_payload frag; + uint8_t *msgbuf = ibuf_data(msg->msg_data); + uint8_t *buf; + size_t len, total, left; + size_t length; + unsigned int payload; + + log_debug("%s: header ispi %s rspi %s" + " nextpayload %s version 0x%02x exchange %s flags 0x%02x" + " msgid %d length %u response %d", __func__, + print_spi(betoh64(hdr->ike_ispi), 8), + print_spi(betoh64(hdr->ike_rspi), 8), + print_map(hdr->ike_nextpayload, ikev2_payload_map), + hdr->ike_version, + print_map(hdr->ike_exchange, ikev2_exchange_map), + hdr->ike_flags, + betoh32(hdr->ike_msgid), + betoh32(hdr->ike_length), + msg->msg_response); + + length = betoh32(hdr->ike_length); + + if (ibuf_size(msg->msg_data) < length) { + log_debug("%s: short message", __func__); + return (-1); + } + + offset += sizeof(*hdr); + + /* Bytes left in datagram. */ + total = length - offset; + + payload = hdr->ike_nextpayload; + + while (payload != 0 && offset < length) { + if (ikev2_validate_pld(msg, offset, total, &pld)) + return (-1); + + log_debug("%s: %spayload %s" + " nextpayload %s critical 0x%02x length %d", + __func__, msg->msg_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); + total -= sizeof(pld); + left = betoh16(pld.pld_length) - sizeof(pld); + + switch (payload) { + case IKEV2_PAYLOAD_SKF: + len = left; + buf = msgbuf + offset; + if (len < sizeof(frag)) + return (-1); + memcpy(&frag, buf, sizeof(frag)); + msg->msg_frag_num = betoh16(frag.frag_num); + break; + } + + payload = pld.pld_nextpayload; + offset += left; + total -= left; + } + + return (0); +} |