From 53ef2b7119f57f4140e6bd9c5cd2d3c6af228179 Mon Sep 17 00:00:00 2001
From: Armands Arseniuss Skolmeisters <armands.skolmeisters@zabbix.com>
Date: Thu, 11 Jan 2024 12:00:24 +0000
Subject: [PATCH] ...G...... [DEV-2702] fixed buffer overread in DNS response

* commit '893902999ab7f0b15cce91e8555cb251b32b6df4':
 ...G...... [DEV-2702] fixed DNS record data length check
 ...G...... [DEV-2702] improved DNS error messages
 ...G...... [DEV-2702] fixed DNS error messages
 ...G...... [DEV-2702] improved DNS error messages
 ...G...... [DEV-2702] fixed buffer overread in DNS response

CVE: CVE-2023-32726
Upstream-Status: Backport [https://github.com/zabbix/zabbix/commit/53ef2b7119f57f4140e6bd9c5cd2d3c6af228179]

Signed-off-by: Yogita Urade <yogita.urade@windriver.com>
---
 src/libs/zbxsysinfo/common/dns.c | 65 +++++++++++++++++++++++++++-----
 1 file changed, 56 insertions(+), 9 deletions(-)

diff --git a/src/libs/zbxsysinfo/common/dns.c b/src/libs/zbxsysinfo/common/dns.c
index e8938d8..bf456f2 100644
--- a/src/libs/zbxsysinfo/common/dns.c
+++ b/src/libs/zbxsysinfo/common/dns.c
@@ -638,7 +638,8 @@ static int	dns_query(AGENT_REQUEST *request, AGENT_RESULT *result, int short_ans
	{
		if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr)))
		{
-			SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response."));
+			SET_MSG_RESULT(result, zbx_strdup(NULL,
+					"Cannot decode DNS response: cannot expand domain name."));
			ret = SYSINFO_RET_FAIL;
			goto clean;
		}
@@ -651,6 +652,13 @@ static int	dns_query(AGENT_REQUEST *request, AGENT_RESULT *result, int short_ans
		GETSHORT(q_len, msg_ptr);
		offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %-8s", decode_type(q_type));

+		if (msg_ptr + q_len > msg_end)
+		{
+			SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response: record overflow."));
+			ret = SYSINFO_RET_FAIL;
+			goto clean;
+		}
+
		switch (q_type)
		{
			case T_A:
@@ -695,8 +703,40 @@ static int	dns_query(AGENT_REQUEST *request, AGENT_RESULT *result, int short_ans
			case T_PTR:
				if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr)))
				{
-					SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response."));
+#define ERR_MSG_PREFIX	"Cannot decode DNS response: cannot expand "
+					const char	*err_msg = NULL;
+
+					switch (q_type)
+					{
+						case T_NS:
+							err_msg = ERR_MSG_PREFIX "name server name.";
+							break;
+						case T_CNAME:
+							err_msg = ERR_MSG_PREFIX "canonical name.";
+							break;
+						case T_MB:
+							err_msg = ERR_MSG_PREFIX "mailbox name.";
+							break;
+						case T_MD:
+							err_msg = ERR_MSG_PREFIX "mail destination name.";
+							break;
+						case T_MF:
+							err_msg = ERR_MSG_PREFIX "mail forwarder name.";
+							break;
+						case T_MG:
+							err_msg = ERR_MSG_PREFIX "mail group name.";
+							break;
+						case T_MR:
+							err_msg = ERR_MSG_PREFIX "renamed mailbox name.";
+							break;
+						case T_PTR:
+							err_msg = ERR_MSG_PREFIX "PTR name.";
+							break;
+					}
+
+					SET_MSG_RESULT(result, zbx_strdup(NULL, err_msg));
					return SYSINFO_RET_FAIL;
+#undef ERR_MSG_PREFIX
				}
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name);
				break;
@@ -706,7 +746,8 @@ static int	dns_query(AGENT_REQUEST *request, AGENT_RESULT *result, int short_ans

				if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr)))	/* exchange */
				{
-					SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response."));
+					SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response:"
+							" cannot expand mail exchange name."));
					return SYSINFO_RET_FAIL;
				}
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name);
@@ -715,14 +756,16 @@ static int	dns_query(AGENT_REQUEST *request, AGENT_RESULT *result, int short_ans
			case T_SOA:
				if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr)))	/* source host */
				{
-					SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response."));
+					SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response:"
+							" cannot expand source nameserver name."));
					return SYSINFO_RET_FAIL;
				}
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name);

				if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr)))	/* administrator */
				{
-					SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response."));
+					SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response:"
+							" cannot expand administrator mailbox name."));
					return SYSINFO_RET_FAIL;
				}
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name);
@@ -750,7 +793,8 @@ static int	dns_query(AGENT_REQUEST *request, AGENT_RESULT *result, int short_ans
			case T_WKS:
				if (INT32SZ + 1 > q_len)
				{
-					SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response."));
+					SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response:"
+							" malformed WKS resource record."));
					return SYSINFO_RET_FAIL;
				}

@@ -816,14 +860,16 @@ static int	dns_query(AGENT_REQUEST *request, AGENT_RESULT *result, int short_ans
			case T_MINFO:
				if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr)))	/* mailbox responsible for mailing lists */
				{
-					SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response."));
+					SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response:"
+							" cannot expand mailbox responsible for mailing lists."));
					return SYSINFO_RET_FAIL;
				}
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name);

				if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr)))	/* mailbox for error messages */
				{
-					SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response."));
+					SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response:"
+							" cannot expand mailbox for error messages."));
					return SYSINFO_RET_FAIL;
				}
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name);
@@ -854,7 +900,8 @@ static int	dns_query(AGENT_REQUEST *request, AGENT_RESULT *result, int short_ans

				if (NULL == (name = get_name(answer.buffer, msg_end, &msg_ptr)))	/* target */
				{
-					SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response."));
+					SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot decode DNS response:"
+							" cannot expand service target hostname."));
					return SYSINFO_RET_FAIL;
				}
				offset += zbx_snprintf(buffer + offset, sizeof(buffer) - offset, " %s", name);
--
2.40.0
