From: Otto Moerbeek Subject: Re: unwind: support wildcard in blacklist To: "Kirill A. Korinsky" Cc: OpenBSD tech , florian@openbsd.org Date: Tue, 25 Jun 2024 07:20:26 +0200 On Mon, Jun 24, 2024 at 10:55:23PM +0100, Kirill A. Korinsky wrote: > Florian, tech@, > > Here a diff which introduced support of wildcard inside unwind's domain > blacklist. Wildcard supported only at begining and as '*' which should be > followed by '.'. > > So, after that this two lines: > > google.com > *.google.com > > blocks any requests to google.com and all its subdomains. Please be aware that in DNS wildcards are already used and have a somehat different than expected interpretation. https://en.wikipedia.org/wiki/Wildcard_DNS_record This means that this should be docuemnted extra carefully, or a different syntax should be used that does not confuse DNS people. -Otto > > The diff: > > diff --git sbin/unwind/frontend.c sbin/unwind/frontend.c > index ccbc977eb73..32a83b56468 100644 > --- sbin/unwind/frontend.c > +++ sbin/unwind/frontend.c > @@ -118,6 +118,8 @@ TAILQ_HEAD(, pending_query) pending_queries; > struct bl_node { > RB_ENTRY(bl_node) entry; > char *domain; > + int len; > + int wildcard; > }; > > __dead void frontend_shutdown(void); > @@ -171,6 +173,18 @@ RB_GENERATE(bl_tree, bl_node, entry, bl_cmp) > 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) > { > @@ -790,6 +804,9 @@ 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) { > if (frontend_conf->blocklist_log) > @@ -797,6 +814,7 @@ handle_query(struct pending_query *pq) > error_answer(pq, LDNS_RCODE_REFUSED); > goto send_answer; > } > + reverse(dname, dname + find.len); > > if (pq->qinfo.qtype == LDNS_RR_TYPE_AXFR || pq->qinfo.qtype == > LDNS_RR_TYPE_IXFR) { > @@ -1541,7 +1559,7 @@ parse_blocklist(int fd) > if (linelen >= 2 && line[linelen - 2] != '.') > line[linelen - 1] = '.'; > else > - line[linelen - 1] = '\0'; > + line[linelen-- - 1] = '\0'; > } > > bl_node = malloc(sizeof *bl_node); > @@ -1549,6 +1567,15 @@ parse_blocklist(int fd) > fatal("%s: malloc", __func__); > if ((bl_node->domain = strdup(line)) == NULL) > fatal("%s: strdup", __func__); > + reverse(bl_node->domain, bl_node->domain + linelen); > + if (linelen > 2 && line[0] == '*' && line[1] == '.') { > + bl_node->wildcard = 1; > + bl_node->domain[linelen - 1] = '\0'; > + bl_node->len = linelen - 1; > + } else { > + bl_node->wildcard = 0; > + bl_node->len = linelen; > + } > if (RB_INSERT(bl_tree, &bl_head, bl_node) != NULL) { > log_warnx("duplicate blocked domain \"%s\"", line); > free(bl_node->domain); > @@ -1563,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 > > > -- > wbr, Kirill >