diff options
author | Thomas Haller <thaller@redhat.com> | 2023-08-18 11:40:37 +0200 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2023-08-24 09:01:45 +0200 |
commit | 3684a1b69c255d5268dd2b1590c1dc039e48052d (patch) | |
tree | 6dab3f3dc8e948338b47ac08248f23923699ea21 /src | |
parent | 4496b390ed2a086c4abbaa864798f36d891fa933 (diff) |
src: add input flag NFT_CTX_INPUT_NO_DNS to avoid blocking
getaddrinfo() blocks while trying to resolve the name. Blocking the
caller of the library is in many cases undesirable. Also, while
reconfiguring the firewall, it's not clear that resolving names via
the network will work or makes sense.
Add a new input flag NFT_CTX_INPUT_NO_DNS to opt-out from getaddrinfo()
and only accept plain IP addresses.
We could also use AI_NUMERICHOST with getaddrinfo() instead of
inet_pton(). By parsing via inet_pton(), we are better aware of
what we expect and can generate a better error message in case of
failure.
Signed-off-by: Thomas Haller <thaller@redhat.com>
Reviewed-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src')
-rw-r--r-- | src/datatype.c | 68 | ||||
-rw-r--r-- | src/evaluate.c | 10 |
2 files changed, 48 insertions, 30 deletions
diff --git a/src/datatype.c b/src/datatype.c index 381320ea..64396db8 100644 --- a/src/datatype.c +++ b/src/datatype.c @@ -600,27 +600,33 @@ static struct error_record *ipaddr_type_parse(struct parse_ctx *ctx, const struct expr *sym, struct expr **res) { - struct addrinfo *ai, hints = { .ai_family = AF_INET, - .ai_socktype = SOCK_DGRAM}; - struct in_addr *addr; - int err; + struct in_addr addr; - err = getaddrinfo(sym->identifier, NULL, &hints, &ai); - if (err != 0) - return error(&sym->location, "Could not resolve hostname: %s", - gai_strerror(err)); + if (nft_input_no_dns(ctx->input)) { + if (inet_pton(AF_INET, sym->identifier, &addr) != 1) + return error(&sym->location, "Invalid IPv4 address"); + } else { + struct addrinfo *ai, hints = { .ai_family = AF_INET, + .ai_socktype = SOCK_DGRAM}; + int err; - if (ai->ai_next != NULL) { + err = getaddrinfo(sym->identifier, NULL, &hints, &ai); + if (err != 0) + return error(&sym->location, "Could not resolve hostname: %s", + gai_strerror(err)); + + if (ai->ai_next != NULL) { + freeaddrinfo(ai); + return error(&sym->location, + "Hostname resolves to multiple addresses"); + } + addr = ((struct sockaddr_in *)ai->ai_addr)->sin_addr; freeaddrinfo(ai); - return error(&sym->location, - "Hostname resolves to multiple addresses"); } - addr = &((struct sockaddr_in *)ai->ai_addr)->sin_addr; *res = constant_expr_alloc(&sym->location, &ipaddr_type, BYTEORDER_BIG_ENDIAN, - sizeof(*addr) * BITS_PER_BYTE, addr); - freeaddrinfo(ai); + sizeof(addr) * BITS_PER_BYTE, &addr); return NULL; } @@ -659,27 +665,33 @@ static struct error_record *ip6addr_type_parse(struct parse_ctx *ctx, const struct expr *sym, struct expr **res) { - struct addrinfo *ai, hints = { .ai_family = AF_INET6, - .ai_socktype = SOCK_DGRAM}; - struct in6_addr *addr; - int err; + struct in6_addr addr; - err = getaddrinfo(sym->identifier, NULL, &hints, &ai); - if (err != 0) - return error(&sym->location, "Could not resolve hostname: %s", - gai_strerror(err)); + if (nft_input_no_dns(ctx->input)) { + if (inet_pton(AF_INET6, sym->identifier, &addr) != 1) + return error(&sym->location, "Invalid IPv6 address"); + } else { + struct addrinfo *ai, hints = { .ai_family = AF_INET6, + .ai_socktype = SOCK_DGRAM}; + int err; - if (ai->ai_next != NULL) { + err = getaddrinfo(sym->identifier, NULL, &hints, &ai); + if (err != 0) + return error(&sym->location, "Could not resolve hostname: %s", + gai_strerror(err)); + + if (ai->ai_next != NULL) { + freeaddrinfo(ai); + return error(&sym->location, + "Hostname resolves to multiple addresses"); + } + addr = ((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr; freeaddrinfo(ai); - return error(&sym->location, - "Hostname resolves to multiple addresses"); } - addr = &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr; *res = constant_expr_alloc(&sym->location, &ip6addr_type, BYTEORDER_BIG_ENDIAN, - sizeof(*addr) * BITS_PER_BYTE, addr); - freeaddrinfo(ai); + sizeof(addr) * BITS_PER_BYTE, &addr); return NULL; } diff --git a/src/evaluate.c b/src/evaluate.c index bdd3c651..2b158aee 100644 --- a/src/evaluate.c +++ b/src/evaluate.c @@ -277,7 +277,10 @@ static int flowtable_not_found(struct eval_ctx *ctx, const struct location *loc, */ static int expr_evaluate_symbol(struct eval_ctx *ctx, struct expr **expr) { - struct parse_ctx parse_ctx = { .tbl = &ctx->nft->output.tbl, }; + struct parse_ctx parse_ctx = { + .tbl = &ctx->nft->output.tbl, + .input = &ctx->nft->input, + }; struct error_record *erec; struct table *table; struct set *set; @@ -3450,7 +3453,10 @@ static int stmt_evaluate_reject_default(struct eval_ctx *ctx, static int stmt_evaluate_reject_icmp(struct eval_ctx *ctx, struct stmt *stmt) { - struct parse_ctx parse_ctx = { .tbl = &ctx->nft->output.tbl, }; + struct parse_ctx parse_ctx = { + .tbl = &ctx->nft->output.tbl, + .input = &ctx->nft->input, + }; struct error_record *erec; struct expr *code; |