From 21e32784001ba993908ef71f5df8598cbf062235 Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Mon, 12 May 2025 14:57:42 +0200 Subject: [PATCH] - Fix #1283: Unsafe usage of atoi() while parsing the configuration file. --- doc/Changelog | 4 ++++ testcode/unitmain.c | 24 ++++++++++++++++++++++++ util/net_help.c | 9 ++++++++- 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/doc/Changelog b/doc/Changelog index e86095860..8d4a93ff6 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -3,6 +3,10 @@ broken auth zones that include unsigned out of zone (above apex) data. Could lead to hang while trying to prove a wildcard answer. +12 May 2025: Wouter + - Fix #1283: Unsafe usage of atoi() while parsing the configuration + file. + 9 May 2025: Wouter - Fix #1281: forward-zone "name: ." conflicts with auth-zone "name: ." in 1.23.0, but worked in 1.22.0. diff --git a/testcode/unitmain.c b/testcode/unitmain.c index 334c1af93..07c016d7b 100644 --- a/testcode/unitmain.c +++ b/testcode/unitmain.c @@ -205,6 +205,8 @@ net_test(void) unit_assert(memcmp(&a6.sin6_addr, "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\000", 16) == 0); addr_mask((struct sockaddr_storage*)&a6, l6, 64); unit_assert(memcmp(&a6.sin6_addr, "\377\377\377\377\377\377\377\377\000\000\000\000\000\000\000\000", 16) == 0); + /* Check that negative value in net is not problematic. */ + addr_mask((struct sockaddr_storage*)&a6, l6, -100); addr_mask((struct sockaddr_storage*)&a6, l6, 0); unit_assert(memcmp(&a6.sin6_addr, "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000", 16) == 0); } @@ -266,6 +268,28 @@ net_test(void) (struct sockaddr_storage*)&b6, i, l6) == i); } } + /* test netblockstrtoaddr */ + unit_show_func("util/net_help.c", "netblockstrtoaddr"); + if(1) { + struct sockaddr_storage a; + socklen_t alen = 0; + int net = 0, res; + char astr[128]; + memset(&a, 0, sizeof(a)); + + res = netblockstrtoaddr("1.2.3.0/24", 53, &a, &alen, &net); + unit_assert(res!=0 && net == 24); + addr_to_str(&a, alen, astr, sizeof(astr)); + unit_assert(strcmp(astr, "1.2.3.0") == 0); + unit_assert(ntohs(((struct sockaddr_in*)&a)->sin_port)==53); + + res = netblockstrtoaddr("2001:DB8:33:44::/64", 53, + &a, &alen, &net); + unit_assert(res!=0 && net == 64); + addr_to_str(&a, alen, astr, sizeof(astr)); + unit_assert(strcmp(astr, "2001:db8:33:44::") == 0); + unit_assert(ntohs(((struct sockaddr_in6*)&a)->sin6_port)==53); + } /* test sockaddr_cmp_addr */ unit_show_func("util/net_help.c", "sockaddr_cmp_addr"); if(1) { diff --git a/util/net_help.c b/util/net_help.c index 8eca6b757..a50737dd8 100644 --- a/util/net_help.c +++ b/util/net_help.c @@ -317,6 +317,11 @@ int netblockstrtoaddr(const char* str, int port, struct sockaddr_storage* addr, log_err("cannot parse netblock: '%s'", str); return 0; } + if(*net < 0) { + log_err("netblock value %d is negative in: '%s'", + *net, str); + return 0; + } strlcpy(buf, str, sizeof(buf)); s = strchr(buf, '/'); if(s) *s = 0; @@ -430,6 +435,8 @@ int netblockdnametoaddr(uint8_t* dname, size_t dnamelen, *net = atoi(buff); if(*net == 0 && strcmp(buff, "0") != 0) return 0; + if(*net < 0) + return 0; dname += nlablen; dname++; if(!ipdnametoaddr(dname, dnamelen-1-nlablen, addr, addrlen, af)) @@ -797,7 +804,7 @@ addr_mask(struct sockaddr_storage* addr, socklen_t len, int net) s = (uint8_t*)&((struct sockaddr_in*)addr)->sin_addr; max = 32; } - if(net >= max) + if(net >= max || net < 0) return; for(i=net/8+1; i