Index | Thread | Search

From:
Kirill A. Korinsky <kirill@korins.ky>
Subject:
Re: unwind: support wildcard in blacklist
To:
tech@openbsd.org
Date:
Sat, 23 Nov 2024 18:29:52 +0100

Download raw body.

Thread
  • Raf Czlonka:

    unwind: support wildcard in blacklist

  • On Sat, 23 Nov 2024 17:30:44 +0100,
    Florian Obser <florian@openbsd.org> wrote:
    > 
    > 
    > no objections from me with all the things fixed.
    > 
    
    Addressed all your remarks. 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	23 Nov 2024 17:27:17 -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);
    @@ -153,6 +155,7 @@ int			 bl_cmp(struct bl_node *, struct b
     void			 free_bl(void);
     int			 pending_query_cnt(void);
     void			 check_available_af(void);
    +void			 reverse(char *, char *);
     
     struct uw_conf		*frontend_conf;
     static struct imsgev	*iev_main;
    @@ -741,7 +744,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,12 +801,19 @@ handle_query(struct pending_query *pq)
     	log_debug("%s: %s %s %s ?", ip_port((struct sockaddr *)&pq->from),
     	    dname, qclass_buf, qtype_buf);
     
    -	find.domain = dname;
    -	if (RB_FIND(bl_tree, &bl_head, &find) != NULL) {
    -		if (frontend_conf->blocklist_log)
    -			log_info("blocking %s", dname);
    -		error_answer(pq, LDNS_RCODE_REFUSED);
    -		goto send_answer;
    +	if (!RB_EMPTY(&bl_head)) {
    +		find.len = strlen(dname);
    +		find.wildcard = 0;
    +		reverse(dname, dname + find.len);
    +		find.domain = dname;
    +		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);
    +			goto send_answer;
    +		}
     	}
     
     	if (pq->qinfo.qtype == LDNS_RR_TYPE_AXFR || pq->qinfo.qtype ==
    @@ -1549,14 +1559,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 +1587,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
    @@ -1828,5 +1849,18 @@ check_available_af(void)
     		available_af = new_available_af;
     		frontend_imsg_compose_resolver(IMSG_CHANGE_AFS, 0,
     		    &available_af, sizeof(available_af));
    +	}
    +}
    +
    +void
    +reverse(char *begin, char *end)
    +{
    +	char	t;
    +
    +	while (begin < --end) {
    +		t = *begin;
    +		*begin = *end;
    +		*end = t;
    +		++begin;
     	}
     }
    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	23 Nov 2024 17:22:15 -0000
    @@ -72,6 +72,8 @@ answers with a return code of
     With
     .Cm log
     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
    
    
    
  • Raf Czlonka:

    unwind: support wildcard in blacklist