xref: /freebsd/contrib/unbound/ipsecmod/ipsecmod-whitelist.c (revision c7f4d7ad9b7dbb008bffe724ae877e10fea2f821)
1*c7f4d7adSDag-Erling Smørgrav /*
2*c7f4d7adSDag-Erling Smørgrav  * ipsecmod/ipsecmod-whitelist.h - White listed domains for the ipsecmod to
3*c7f4d7adSDag-Erling Smørgrav  * operate on.
4*c7f4d7adSDag-Erling Smørgrav  *
5*c7f4d7adSDag-Erling Smørgrav  * Copyright (c) 2017, NLnet Labs. All rights reserved.
6*c7f4d7adSDag-Erling Smørgrav  *
7*c7f4d7adSDag-Erling Smørgrav  * This software is open source.
8*c7f4d7adSDag-Erling Smørgrav  *
9*c7f4d7adSDag-Erling Smørgrav  * Redistribution and use in source and binary forms, with or without
10*c7f4d7adSDag-Erling Smørgrav  * modification, are permitted provided that the following conditions
11*c7f4d7adSDag-Erling Smørgrav  * are met:
12*c7f4d7adSDag-Erling Smørgrav  *
13*c7f4d7adSDag-Erling Smørgrav  * Redistributions of source code must retain the above copyright notice,
14*c7f4d7adSDag-Erling Smørgrav  * this list of conditions and the following disclaimer.
15*c7f4d7adSDag-Erling Smørgrav  *
16*c7f4d7adSDag-Erling Smørgrav  * Redistributions in binary form must reproduce the above copyright notice,
17*c7f4d7adSDag-Erling Smørgrav  * this list of conditions and the following disclaimer in the documentation
18*c7f4d7adSDag-Erling Smørgrav  * and/or other materials provided with the distribution.
19*c7f4d7adSDag-Erling Smørgrav  *
20*c7f4d7adSDag-Erling Smørgrav  * Neither the name of the NLNET LABS nor the names of its contributors may
21*c7f4d7adSDag-Erling Smørgrav  * be used to endorse or promote products derived from this software without
22*c7f4d7adSDag-Erling Smørgrav  * specific prior written permission.
23*c7f4d7adSDag-Erling Smørgrav  *
24*c7f4d7adSDag-Erling Smørgrav  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25*c7f4d7adSDag-Erling Smørgrav  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26*c7f4d7adSDag-Erling Smørgrav  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27*c7f4d7adSDag-Erling Smørgrav  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28*c7f4d7adSDag-Erling Smørgrav  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29*c7f4d7adSDag-Erling Smørgrav  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
30*c7f4d7adSDag-Erling Smørgrav  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31*c7f4d7adSDag-Erling Smørgrav  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32*c7f4d7adSDag-Erling Smørgrav  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33*c7f4d7adSDag-Erling Smørgrav  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34*c7f4d7adSDag-Erling Smørgrav  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35*c7f4d7adSDag-Erling Smørgrav  */
36*c7f4d7adSDag-Erling Smørgrav /**
37*c7f4d7adSDag-Erling Smørgrav  * \file
38*c7f4d7adSDag-Erling Smørgrav  *
39*c7f4d7adSDag-Erling Smørgrav  * Keep track of the white listed domains for ipsecmod.
40*c7f4d7adSDag-Erling Smørgrav  */
41*c7f4d7adSDag-Erling Smørgrav 
42*c7f4d7adSDag-Erling Smørgrav #include "config.h"
43*c7f4d7adSDag-Erling Smørgrav 
44*c7f4d7adSDag-Erling Smørgrav #ifdef USE_IPSECMOD
45*c7f4d7adSDag-Erling Smørgrav #include "ipsecmod/ipsecmod.h"
46*c7f4d7adSDag-Erling Smørgrav #include "ipsecmod/ipsecmod-whitelist.h"
47*c7f4d7adSDag-Erling Smørgrav #include "util/regional.h"
48*c7f4d7adSDag-Erling Smørgrav #include "util/log.h"
49*c7f4d7adSDag-Erling Smørgrav #include "util/config_file.h"
50*c7f4d7adSDag-Erling Smørgrav #include "util/rbtree.h"
51*c7f4d7adSDag-Erling Smørgrav #include "util/data/dname.h"
52*c7f4d7adSDag-Erling Smørgrav #include "util/storage/dnstree.h"
53*c7f4d7adSDag-Erling Smørgrav #include "sldns/str2wire.h"
54*c7f4d7adSDag-Erling Smørgrav 
55*c7f4d7adSDag-Erling Smørgrav /** Apply ipsecmod-whitelist string. */
56*c7f4d7adSDag-Erling Smørgrav static int
whitelist_str_cfg(rbtree_type * whitelist,const char * name)57*c7f4d7adSDag-Erling Smørgrav whitelist_str_cfg(rbtree_type* whitelist, const char* name)
58*c7f4d7adSDag-Erling Smørgrav {
59*c7f4d7adSDag-Erling Smørgrav     struct name_tree_node* n;
60*c7f4d7adSDag-Erling Smørgrav     size_t len;
61*c7f4d7adSDag-Erling Smørgrav     uint8_t* nm = sldns_str2wire_dname(name, &len);
62*c7f4d7adSDag-Erling Smørgrav     if(!nm) {
63*c7f4d7adSDag-Erling Smørgrav         log_err("ipsecmod: could not parse %s for whitelist.", name);
64*c7f4d7adSDag-Erling Smørgrav         return 0;
65*c7f4d7adSDag-Erling Smørgrav     }
66*c7f4d7adSDag-Erling Smørgrav     n = (struct name_tree_node*)calloc(1, sizeof(*n));
67*c7f4d7adSDag-Erling Smørgrav     if(!n) {
68*c7f4d7adSDag-Erling Smørgrav         log_err("ipsecmod: out of memory while creating whitelist.");
69*c7f4d7adSDag-Erling Smørgrav         free(nm);
70*c7f4d7adSDag-Erling Smørgrav         return 0;
71*c7f4d7adSDag-Erling Smørgrav     }
72*c7f4d7adSDag-Erling Smørgrav     n->node.key = n;
73*c7f4d7adSDag-Erling Smørgrav     n->name = nm;
74*c7f4d7adSDag-Erling Smørgrav     n->len = len;
75*c7f4d7adSDag-Erling Smørgrav     n->labs = dname_count_labels(nm);
76*c7f4d7adSDag-Erling Smørgrav     n->dclass = LDNS_RR_CLASS_IN;
77*c7f4d7adSDag-Erling Smørgrav     if(!name_tree_insert(whitelist, n, nm, len, n->labs, n->dclass)) {
78*c7f4d7adSDag-Erling Smørgrav         /* duplicate element ignored, idempotent */
79*c7f4d7adSDag-Erling Smørgrav         free(n->name);
80*c7f4d7adSDag-Erling Smørgrav         free(n);
81*c7f4d7adSDag-Erling Smørgrav     }
82*c7f4d7adSDag-Erling Smørgrav     return 1;
83*c7f4d7adSDag-Erling Smørgrav }
84*c7f4d7adSDag-Erling Smørgrav 
85*c7f4d7adSDag-Erling Smørgrav /** Read ipsecmod-whitelist config. */
86*c7f4d7adSDag-Erling Smørgrav static int
read_whitelist(rbtree_type * whitelist,struct config_file * cfg)87*c7f4d7adSDag-Erling Smørgrav read_whitelist(rbtree_type* whitelist, struct config_file* cfg)
88*c7f4d7adSDag-Erling Smørgrav {
89*c7f4d7adSDag-Erling Smørgrav 	struct config_strlist* p;
90*c7f4d7adSDag-Erling Smørgrav 	for(p = cfg->ipsecmod_whitelist; p; p = p->next) {
91*c7f4d7adSDag-Erling Smørgrav 		log_assert(p->str);
92*c7f4d7adSDag-Erling Smørgrav 		if(!whitelist_str_cfg(whitelist, p->str))
93*c7f4d7adSDag-Erling Smørgrav 			return 0;
94*c7f4d7adSDag-Erling Smørgrav 	}
95*c7f4d7adSDag-Erling Smørgrav 	return 1;
96*c7f4d7adSDag-Erling Smørgrav }
97*c7f4d7adSDag-Erling Smørgrav 
98*c7f4d7adSDag-Erling Smørgrav int
ipsecmod_whitelist_apply_cfg(struct ipsecmod_env * ie,struct config_file * cfg)99*c7f4d7adSDag-Erling Smørgrav ipsecmod_whitelist_apply_cfg(struct ipsecmod_env* ie,
100*c7f4d7adSDag-Erling Smørgrav 	struct config_file* cfg)
101*c7f4d7adSDag-Erling Smørgrav {
102*c7f4d7adSDag-Erling Smørgrav 	ie->whitelist = rbtree_create(name_tree_compare);
103*c7f4d7adSDag-Erling Smørgrav 	if(!read_whitelist(ie->whitelist, cfg))
104*c7f4d7adSDag-Erling Smørgrav 		return 0;
105*c7f4d7adSDag-Erling Smørgrav 	name_tree_init_parents(ie->whitelist);
106*c7f4d7adSDag-Erling Smørgrav 	return 1;
107*c7f4d7adSDag-Erling Smørgrav }
108*c7f4d7adSDag-Erling Smørgrav 
109*c7f4d7adSDag-Erling Smørgrav /** Delete ipsecmod_env->whitelist element. */
110*c7f4d7adSDag-Erling Smørgrav static void
whitelist_free(struct rbnode_type * n,void * ATTR_UNUSED (d))111*c7f4d7adSDag-Erling Smørgrav whitelist_free(struct rbnode_type* n, void* ATTR_UNUSED(d))
112*c7f4d7adSDag-Erling Smørgrav {
113*c7f4d7adSDag-Erling Smørgrav 	if(n) {
114*c7f4d7adSDag-Erling Smørgrav 		free(((struct name_tree_node*)n)->name);
115*c7f4d7adSDag-Erling Smørgrav 		free(n);
116*c7f4d7adSDag-Erling Smørgrav 	}
117*c7f4d7adSDag-Erling Smørgrav }
118*c7f4d7adSDag-Erling Smørgrav 
119*c7f4d7adSDag-Erling Smørgrav /** Get memory usage of ipsecmod_env->whitelist element. */
120*c7f4d7adSDag-Erling Smørgrav static void
whitelist_get_mem(struct rbnode_type * n,void * arg)121*c7f4d7adSDag-Erling Smørgrav whitelist_get_mem(struct rbnode_type* n, void* arg)
122*c7f4d7adSDag-Erling Smørgrav {
123*c7f4d7adSDag-Erling Smørgrav 	struct name_tree_node* node = (struct name_tree_node*)n;
124*c7f4d7adSDag-Erling Smørgrav 	size_t* size = (size_t*) arg;
125*c7f4d7adSDag-Erling Smørgrav 	if(node) {
126*c7f4d7adSDag-Erling Smørgrav 		*size += sizeof(node) + node->len;
127*c7f4d7adSDag-Erling Smørgrav 	}
128*c7f4d7adSDag-Erling Smørgrav }
129*c7f4d7adSDag-Erling Smørgrav 
130*c7f4d7adSDag-Erling Smørgrav void
ipsecmod_whitelist_delete(rbtree_type * whitelist)131*c7f4d7adSDag-Erling Smørgrav ipsecmod_whitelist_delete(rbtree_type* whitelist)
132*c7f4d7adSDag-Erling Smørgrav {
133*c7f4d7adSDag-Erling Smørgrav 	if(whitelist) {
134*c7f4d7adSDag-Erling Smørgrav 		traverse_postorder(whitelist, whitelist_free, NULL);
135*c7f4d7adSDag-Erling Smørgrav 		free(whitelist);
136*c7f4d7adSDag-Erling Smørgrav 	}
137*c7f4d7adSDag-Erling Smørgrav }
138*c7f4d7adSDag-Erling Smørgrav 
139*c7f4d7adSDag-Erling Smørgrav int
ipsecmod_domain_is_whitelisted(struct ipsecmod_env * ie,uint8_t * dname,size_t dname_len,uint16_t qclass)140*c7f4d7adSDag-Erling Smørgrav ipsecmod_domain_is_whitelisted(struct ipsecmod_env* ie, uint8_t* dname,
141*c7f4d7adSDag-Erling Smørgrav 	size_t dname_len, uint16_t qclass)
142*c7f4d7adSDag-Erling Smørgrav {
143*c7f4d7adSDag-Erling Smørgrav 	if(!ie->whitelist) return 1; /* No whitelist, treat as whitelisted. */
144*c7f4d7adSDag-Erling Smørgrav 	return name_tree_lookup(ie->whitelist, dname, dname_len,
145*c7f4d7adSDag-Erling Smørgrav 		dname_count_labels(dname), qclass) != NULL;
146*c7f4d7adSDag-Erling Smørgrav }
147*c7f4d7adSDag-Erling Smørgrav 
148*c7f4d7adSDag-Erling Smørgrav size_t
ipsecmod_whitelist_get_mem(rbtree_type * whitelist)149*c7f4d7adSDag-Erling Smørgrav ipsecmod_whitelist_get_mem(rbtree_type* whitelist)
150*c7f4d7adSDag-Erling Smørgrav {
151*c7f4d7adSDag-Erling Smørgrav 	size_t size = 0;
152*c7f4d7adSDag-Erling Smørgrav 	if(whitelist) {
153*c7f4d7adSDag-Erling Smørgrav 		traverse_postorder(whitelist, whitelist_get_mem, &size);
154*c7f4d7adSDag-Erling Smørgrav 	}
155*c7f4d7adSDag-Erling Smørgrav 	return size;
156*c7f4d7adSDag-Erling Smørgrav }
157*c7f4d7adSDag-Erling Smørgrav 
158*c7f4d7adSDag-Erling Smørgrav #endif /* USE_IPSECMOD */
159