From 31cd3d13aaa760af27b7c2eba57da19274b51a61 Mon Sep 17 00:00:00 2001 From: Christopher Faulet Date: Wed, 27 May 2026 09:16:37 +0200 Subject: [PATCH] BUG/MINOR: tcpcheck: Check LDAP response to not read more data than available tcpcheck_ldap_expect_bindrsp() parses ASN.1 BER-encoded LDAP responses from the health check target. After reading the outer message size and validating protocol fields, it encounters a long-form BER length for the bindResponse value (high bit set in the length byte). The code reads nbytes = (*ptr & 0x7f) then advances ptr by 1 + nbytes without checking that enough bytes remain in the receive buffer. So, it is possible to read more data than available. Note that it is only possible if the LDAP response was forged because the message length was already checked. LDAP response remains quite short and it is not possible to read outside the buffer area. So at worst, garbage are parsed and a wrong result is reported by the LDAP health-check. Most probably an error will be reported. This patch could be backported to all stable versions. --- src/tcpcheck.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/tcpcheck.c b/src/tcpcheck.c index 2ab1b2bf2..a1ee85f4d 100644 --- a/src/tcpcheck.c +++ b/src/tcpcheck.c @@ -664,7 +664,7 @@ enum tcpcheck_eval_ret tcpcheck_ldap_expect_bindrsp(struct check *check, struct enum healthcheck_status status; struct buffer *msg = NULL; struct ist desc = IST_NULL; - char *ptr; + char *ptr, *end; unsigned short nbytes = 0; size_t msglen = 0; @@ -674,7 +674,12 @@ enum tcpcheck_eval_ret tcpcheck_ldap_expect_bindrsp(struct check *check, struct * http://en.wikipedia.org/wiki/Basic_Encoding_Rules * http://tools.ietf.org/html/rfc4511 */ - ptr = b_head(&check->bi) + 1; + ptr = b_head(&check->bi); + end = ptr + b_data(&check->bi); + ptr++; /* First byte was already matched by the previous expect rule + * and at least 14 bytes are available + * (see do_parse_ldap_check_opt) + */ /* size of LDAPMessage */ if (*ptr & 0x80) { @@ -684,7 +689,7 @@ enum tcpcheck_eval_ret tcpcheck_ldap_expect_bindrsp(struct check *check, struct * encode BindReponse length on 4 bytes. */ nbytes = (*ptr & 0x7f); - if (b_data(&check->bi) < 1 + nbytes) + if (end - ptr < 1 + nbytes) goto too_short; switch (nbytes) { case 4: msglen = read_n32(ptr+1); break; @@ -699,7 +704,7 @@ enum tcpcheck_eval_ret tcpcheck_ldap_expect_bindrsp(struct check *check, struct msglen = *ptr; ptr += 1 + nbytes; - if (b_data(&check->bi) < 2 + nbytes + msglen) + if (end - ptr < msglen) goto too_short; /* http://tools.ietf.org/html/rfc4511#section-4.2.2 @@ -717,6 +722,10 @@ enum tcpcheck_eval_ret tcpcheck_ldap_expect_bindrsp(struct check *check, struct nbytes = 0; if (*ptr & 0x80) nbytes = (*ptr & 0x7f); + + if (end - ptr < 1 + nbytes + 2 + 1) + goto too_short; + ptr += 1 + nbytes; /* http://tools.ietf.org/html/rfc4511#section-4.1.9