From: Kirill A. Korinsky Subject: Re: unwind: support wildcard in blacklist To: Florian Obser Cc: OpenBSD tech Date: Fri, 22 Nov 2024 00:55:24 +0100 On Tue, 29 Oct 2024 22:51:30 +0100, Kirill A. Korinsky wrote: > > 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. > I'd like to remind about this diff. Ok? Index: sbin/unwind/frontend.c =================================================================== RCS file: /home/cvs/src/sbin/unwind/frontend.c,v diff -u -p -r1.89 frontend.c --- sbin/unwind/frontend.c 21 Nov 2024 13:35:20 -0000 1.89 +++ sbin/unwind/frontend.c 21 Nov 2024 22:05:20 -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) { @@ -741,7 +756,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]; @@ -798,8 +813,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); @@ -1549,14 +1569,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); @@ -1571,7 +1597,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: sbin/unwind/unwind.conf.5 =================================================================== RCS file: /home/cvs/src/sbin/unwind/unwind.conf.5,v diff -u -p -r1.34 unwind.conf.5 --- sbin/unwind/unwind.conf.5 30 Jun 2024 16:10:26 -0000 1.34 +++ sbin/unwind/unwind.conf.5 6 Sep 2024 20:40:53 -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