From cf741e9cb955246f2028070b19c4e226c8f4e2e5 Mon Sep 17 00:00:00 2001 From: hshoexer Date: Thu, 11 Jun 2026 09:44:07 +0000 Subject: [PATCH] isakmpd(8): Validate DELETE payload SPI array size [1/2] The number of SPIs provided in a DELETE message is not properly validated. This might cause a read beyond the message end. However, the outside read is limited to 4 bytes for IPsec SAs and 16 bytes for ISAKMP SAs. A crash is possible, but seems unlikely to me. test & ok sthen --- sbin/isakmpd/message.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/sbin/isakmpd/message.c b/sbin/isakmpd/message.c index e69e126b20d..3e2099949c0 100644 --- a/sbin/isakmpd/message.c +++ b/sbin/isakmpd/message.c @@ -1,4 +1,4 @@ -/* $OpenBSD: message.c,v 1.130 2026/06/11 09:40:20 hshoexer Exp $ */ +/* $OpenBSD: message.c,v 1.131 2026/06/11 09:44:07 hshoexer Exp $ */ /* $EOM: message.c,v 1.156 2000/10/10 12:36:39 provos Exp $ */ /* @@ -620,6 +620,7 @@ message_validate_delete(struct message *msg, struct payload *p) struct doi *doi; struct sa *sa, *isakmp_sa; struct sockaddr *dst, *dst_isa; + size_t spisz, len; u_int32_t nspis = GET_ISAKMP_DELETE_NSPIS(p->p); u_int8_t *spis = (u_int8_t *)p->p + ISAKMP_DELETE_SPI_OFF; u_int32_t i; @@ -666,6 +667,24 @@ message_validate_delete(struct message *msg, struct payload *p) message_free(msg); return -1; } + /* Enforce that SPI size matches the protocol. */ + spisz = (proto == ISAKMP_PROTO_ISAKMP) ? + ISAKMP_HDR_COOKIES_LEN : sizeof(u_int32_t); + if (GET_ISAKMP_DELETE_SPI_SZ(p->p) != spisz) { + log_print("message_validate_delete: invalid SPI size %u " + "for protocol %u", GET_ISAKMP_DELETE_SPI_SZ(p->p), proto); + message_free(msg); + return -1; + } + /* All SPIs must fit into the DELETE payload. */ + len = GET_ISAKMP_GEN_LENGTH(p->p); + if (len < ISAKMP_DELETE_SPI_OFF || + (len - ISAKMP_DELETE_SPI_OFF) / spisz < nspis) { + log_print("message_validate_delete: SPI count %u exceeds " + "payload length %zu", nspis, len); + message_free(msg); + return -1; + } /* Validate the SPIs. */ for (i = 0; i < nspis; i++) { /* Get ISAKMP SA protecting this message. */