From: Kirill A. Korinsky Subject: Re: unwind: support wildcard in blacklist To: tech@openbsd.org Date: Tue, 29 Oct 2024 22:51:30 +0100 On Sat, 14 Sep 2024 20:18:14 +0200, Florian Obser wrote: > > I had hopped I'd find the time to review this, but it's been two weeks > and it didn't happen. It's getting too close to release so it won't make > it for 7.6. > I put it on my todo list to look at it mid October at the earliest. Feel > free to prod me if it doesn't happen then. > as asked here the friendly ping which includes the diff. ok? thougths? Index: frontend.c =================================================================== RCS file: /cvs/src/sbin/unwind/frontend.c,v diff -u -p -r1.83 frontend.c --- frontend.c 5 Sep 2024 08:22:46 -0000 1.83 +++ frontend.c 29 Oct 2024 21:50:47 -0000 @@ -118,6 +118,8 @@ TAILQ_HEAD(, pending_query) pending_que struct bl_node { RB_ENTRY(bl_node) entry; char *domain; + int len; + int wildcard; }; __dead void frontend_shutdown(void); @@ -171,6 +173,19 @@ RB_GENERATE(bl_tree, bl_node, entry, bl_ struct dns64_prefix *dns64_prefixes; int dns64_prefix_count; +static void +reverse(char *begin, char *end) +{ + char t; + + while (begin < --end) { + t = *begin; + *begin = *end; + *end = t; + ++begin; + } +} + void frontend_sig_handler(int sig, short event, void *bula) { @@ -734,7 +749,7 @@ handle_query(struct pending_query *pq) { struct query_imsg query_imsg; struct bl_node find; - int rcode; + int rcode, matched; char *str; char dname[LDNS_MAX_DOMAINLEN + 1]; char qclass_buf[16]; @@ -791,8 +806,13 @@ handle_query(struct pending_query *pq) log_debug("%s: %s %s %s ?", ip_port((struct sockaddr *)&pq->from), dname, qclass_buf, qtype_buf); + find.len = strlen(dname); + find.wildcard = 0; + reverse(dname, dname + find.len); find.domain = dname; - if (RB_FIND(bl_tree, &bl_head, &find) != NULL) { + matched = (RB_FIND(bl_tree, &bl_head, &find) != NULL); + reverse(dname, dname + find.len); + if (matched) { if (frontend_conf->blocklist_log) log_info("blocking %s", dname); error_answer(pq, LDNS_RCODE_REFUSED); @@ -1542,14 +1562,20 @@ parse_blocklist(int fd) if (linelen >= 2 && line[linelen - 2] != '.') line[linelen - 1] = '.'; else - line[linelen - 1] = '\0'; + line[linelen-- - 1] = '\0'; } + if (line[0] == '#') + continue; + bl_node = malloc(sizeof *bl_node); if (bl_node == NULL) fatal("%s: malloc", __func__); if ((bl_node->domain = strdup(line)) == NULL) fatal("%s: strdup", __func__); + reverse(bl_node->domain, bl_node->domain + linelen); + bl_node->len = linelen; + bl_node->wildcard = line[0] == '.'; if (RB_INSERT(bl_tree, &bl_head, bl_node) != NULL) { log_warnx("duplicate blocked domain \"%s\"", line); free(bl_node->domain); @@ -1564,7 +1590,12 @@ parse_blocklist(int fd) int bl_cmp(struct bl_node *e1, struct bl_node *e2) { - return (strcasecmp(e1->domain, e2->domain)); + if (e1->wildcard == e2->wildcard) + return (strcasecmp(e1->domain, e2->domain)); + else if (e1->wildcard) + return (strncasecmp(e1->domain, e2->domain, e1->len)); + else /* e2->wildcard */ + return (strncasecmp(e1->domain, e2->domain, e2->len)); } void Index: unwind.conf.5 =================================================================== RCS file: /cvs/src/sbin/unwind/unwind.conf.5,v diff -u -p -r1.34 unwind.conf.5 --- unwind.conf.5 30 Jun 2024 16:10:26 -0000 1.34 +++ unwind.conf.5 29 Oct 2024 21:50:48 -0000 @@ -69,9 +69,10 @@ If a domain from this list is queried, .Nm unwind answers with a return code of .Dv REFUSED . -With .Cm log -blocked queries are logged. +blocked queries are logged. The list supports limited wildcard +syntax: domains starting with . (dot) are treated as any subdomains +on that zone. .It Ic forwarder Brq Ar address Oo Ic port Ar number Oc Oo Oo Ic authentication name Ar name Oc Ic DoT Oc ... A list of addresses of DNS name servers to forward queries to. .Ic port -- wbr, Kirill