1 /*
2  * Copyright (c) 2011 NLNet Labs. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
17  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
19  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
21  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
22  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
23  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  */
26 
27 /**
28  * Access Control List.
29  *
30  */
31 
32 #include "config.h"
33 #include "log.h"
34 #include "file.h"
35 #include "status.h"
36 #include "wire/acl.h"
37 
38 static const char* acl_str = "acl";
39 
40 
41 /**
42  * Returns range type.
43  * mask is the 2nd part of the range.
44  *
45  */
46 static acl_range_type
acl_parse_range_type(char * ip,char ** mask)47 acl_parse_range_type(char* ip, char** mask)
48 {
49     char *p;
50     if((p=strchr(ip, '&'))!=0) {
51         *p = 0;
52         *mask = p+1;
53         return ACL_RANGE_MASK;
54     }
55     if((p=strchr(ip, '/'))!=0) {
56         *p = 0;
57         *mask = p+1;
58         return ACL_RANGE_SUBNET;
59     }
60     if((p=strchr(ip, '-'))!=0) {
61         *p = 0;
62         *mask = p+1;
63         return ACL_RANGE_MINMAX;
64     }
65     *mask = 0;
66     return ACL_RANGE_SINGLE;
67 }
68 
69 
70 /**
71  * Parses subnet mask, fills 0 mask as well
72  *
73  */
74 static ods_status
acl_parse_range_subnet(char * p,void * addr,int maxbits)75 acl_parse_range_subnet(char* p, void* addr, int maxbits)
76 {
77     int subnet_bits = atoi(p);
78     uint8_t* addr_bytes = (uint8_t*)addr;
79     if (subnet_bits == 0 && strcmp(p, "0")!=0) {
80         return ODS_STATUS_ACL_SUBNET_BAD_RANGE;
81     }
82     if (subnet_bits < 0 || subnet_bits > maxbits) {
83         return ODS_STATUS_ACL_SUBNET_OUT_RANGE;
84     }
85     /* fill addr with n bits of 1s (struct has been zeroed) */
86     while(subnet_bits >= 8) {
87         *addr_bytes++ = 0xff;
88         subnet_bits -= 8;
89     }
90     if(subnet_bits > 0) {
91         uint8_t shifts[] =
92             {0x0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff};
93         *addr_bytes = shifts[subnet_bits];
94     }
95     return ODS_STATUS_OK;
96 }
97 
98 
99 /**
100  * Parse family from address.
101  *
102  */
103 int
acl_parse_family(const char * a)104 acl_parse_family(const char* a)
105 {
106    /* see if addr is ipv6 or ipv4 -- by : and . */
107    while (*a) {
108        if (*a == '.') {
109            return AF_INET;
110        }
111        if (*a == ':') {
112            return AF_INET6;
113        }
114        ++a;
115    }
116    /* default to v4 */
117    return AF_INET;
118 }
119 
120 
121 /**
122  * Create ACL.
123  *
124  */
125 acl_type*
acl_create(char * address,char * port,char * tsig_name,tsig_type * tsig)126 acl_create(char* address, char* port,
127     char* tsig_name, tsig_type* tsig)
128 {
129     ods_status status = ODS_STATUS_OK;
130     acl_type* acl = NULL;
131     char* p = NULL;
132     CHECKALLOC(acl = (acl_type*) malloc(sizeof(acl_type)));
133     acl->address = NULL;
134     acl->next = NULL;
135     acl->tsig = NULL;
136     if (tsig_name) {
137         acl->tsig = tsig_lookup_by_name(tsig, tsig_name);
138         if (!acl->tsig) {
139             ods_log_error("[%s] unable to create acl: tsig %s not found",
140                 acl_str, tsig_name);
141             acl_cleanup(acl);
142             return NULL;
143         }
144     }
145     acl->port = 0;
146     if (port) {
147         acl->port = atoi((const char*) port);
148     }
149     memset(&acl->addr, 0, sizeof(union acl_addr_storage));
150     memset(&acl->range_mask, 0, sizeof(union acl_addr_storage));
151     if (address) {
152         acl->family = acl_parse_family(address);
153         acl->range_type = acl_parse_range_type(address, &p);
154         acl->address = strdup(address);
155         if (!acl->address) {
156             ods_log_error("[%s] unable to create acl: allocator_strdup() "
157                 "failed", acl_str);
158             acl_cleanup(acl);
159             return NULL;
160         }
161         if (acl->family == AF_INET6) {
162             if (inet_pton(AF_INET6, acl->address, &acl->addr.addr6) != 1) {
163                 ods_log_error("[%s] unable to create acl: bad ipv6 address "
164                     "(%s)", acl_str, acl->address);
165                 acl_cleanup(acl);
166                 return NULL;
167             }
168             if (acl->range_type == ACL_RANGE_MASK ||
169                 acl->range_type == ACL_RANGE_MINMAX) {
170                 if (inet_pton(AF_INET6, p, &acl->range_mask.addr6) != 1) {
171                     ods_log_error("[%s] unable to create acl: bad ipv6 address"
172                         " mask (%s)", acl_str, p);
173                     acl_cleanup(acl);
174                     return NULL;
175                 }
176             } else if (acl->range_type == ACL_RANGE_SUBNET) {
177                 status = acl_parse_range_subnet(p, &acl->range_mask.addr6, 128);
178                 if (status != ODS_STATUS_OK) {
179                     ods_log_error("[%s] unable to create acl: %s (%s)",
180                         acl_str, ods_status2str(status), p);
181                     acl_cleanup(acl);
182                     return NULL;
183                 }
184             }
185         } else if (acl->family == AF_INET) {
186             if (inet_pton(AF_INET, acl->address, &acl->addr.addr) != 1) {
187                 ods_log_error("[%s] unable to create acl: bad ipv4 address "
188                     "(%s)", acl_str, acl->address);
189                 acl_cleanup(acl);
190                 return NULL;
191             }
192             if (acl->range_type == ACL_RANGE_MASK ||
193                 acl->range_type == ACL_RANGE_MINMAX) {
194                 if (inet_pton(AF_INET, p, &acl->range_mask.addr) != 1) {
195                     ods_log_error("[%s] unable to create acl: bad ipv4 address"
196                         " mask (%s)", acl_str, p);
197                     acl_cleanup(acl);
198                     return NULL;
199                 }
200             } else if (acl->range_type == ACL_RANGE_SUBNET) {
201                 status = acl_parse_range_subnet(p, &acl->range_mask.addr, 32);
202                 if (status != ODS_STATUS_OK) {
203                     ods_log_error("[%s] unable to create acl: %s (%s)",
204                         acl_str, ods_status2str(status), p);
205                     acl_cleanup(acl);
206                     return NULL;
207                 }
208             }
209         }
210     }
211     acl->ixfr_disabled = 0;
212     return acl;
213 }
214 
215 
216 /**
217  * ACL matches address mask.
218  *
219  */
220 static int
acl_addr_matches_mask(uint32_t * a,uint32_t * b,uint32_t * mask,size_t sz)221 acl_addr_matches_mask(uint32_t* a, uint32_t* b, uint32_t* mask, size_t sz)
222 {
223     size_t i = 0;
224     ods_log_assert(sz % 4 == 0);
225     sz /= 4;
226     for (i=0; i<sz; ++i) {
227         if (((*a++)&*mask) != ((*b++)&*mask)) {
228             return 0;
229         }
230         ++mask;
231     }
232     return 1;
233 }
234 
235 /**
236  * ACL matches address range.
237  *
238  */
239 static int
acl_addr_matches_range(uint32_t * minval,uint32_t * x,uint32_t * maxval,size_t sz)240 acl_addr_matches_range(uint32_t* minval, uint32_t* x, uint32_t* maxval,
241     size_t sz)
242 {
243     size_t i = 0;
244     uint8_t checkmin = 1;
245     uint8_t checkmax = 1;
246     ods_log_assert(sz % 4 == 0);
247     /* check treats x as one huge number */
248     sz /= 4;
249     for (i=0; i<sz; ++i) {
250         /* if outside bounds, we are done */
251         if (checkmin && minval[i] > x[i]) {
252             return 0;
253         }
254         if (checkmax && maxval[i] < x[i]) {
255             return 0;
256         }
257         /* if x is equal to a bound, that bound needs further checks */
258         if (checkmin && minval[i] != x[i]) {
259             checkmin = 0;
260         }
261         if (checkmax && maxval[i]!=x[i]) {
262             checkmax = 0;
263         }
264         if (!checkmin && !checkmax) {
265             return 1; /* will always match */
266         }
267     }
268     return 1;
269 }
270 
271 
272 /**
273  * ACL matches address.
274  *
275  */
276 static int
acl_addr_matches(acl_type * acl,struct sockaddr_storage * addr)277 acl_addr_matches(acl_type* acl, struct sockaddr_storage* addr)
278 {
279     if (!acl) {
280         return 0;
281     }
282     if (!acl->address) {
283         /* all addresses match */
284         return 1;
285     }
286     if (acl->family == AF_INET6) {
287         struct sockaddr_in6* addr6 = (struct sockaddr_in6*) addr;
288         if (addr->ss_family != AF_INET6) {
289             return 0;
290         }
291         if (acl->port != 0 && acl->port != ntohs(addr6->sin6_port)) {
292             return 0;
293         }
294         switch(acl->range_type) {
295             case ACL_RANGE_MASK:
296             case ACL_RANGE_SUBNET:
297                 if (!acl_addr_matches_mask((uint32_t*)&acl->addr.addr6,
298                     (uint32_t*)&addr6->sin6_addr,
299                     (uint32_t*)&acl->range_mask.addr6,
300                     sizeof(struct in6_addr))) {
301                     return 0;
302                 }
303                 break;
304             case ACL_RANGE_MINMAX:
305                 if (!acl_addr_matches_range((uint32_t*)&acl->addr.addr6,
306                     (uint32_t*)&addr6->sin6_addr,
307                     (uint32_t*)&acl->range_mask.addr6,
308                     sizeof(struct in6_addr))) {
309                     return 0;
310                 }
311                 break;
312             case ACL_RANGE_SINGLE:
313             default:
314                 if (memcmp(&addr6->sin6_addr, &acl->addr.addr6,
315                     sizeof(struct in6_addr)) != 0) {
316                     return 0;
317                 }
318                 break;
319         }
320         return 1;
321     } else {
322         struct sockaddr_in* addr4 = (struct sockaddr_in*)addr;
323         if (addr4->sin_family != AF_INET) {
324             return 0;
325         }
326         if (acl->port != 0 && acl->port != ntohs(addr4->sin_port)) {
327             return 0;
328         }
329         switch (acl->range_type) {
330             case ACL_RANGE_MASK:
331             case ACL_RANGE_SUBNET:
332                 if (!acl_addr_matches_mask((uint32_t*)&acl->addr.addr,
333                     (uint32_t*)&addr4->sin_addr,
334                     (uint32_t*)&acl->range_mask.addr,
335                     sizeof(struct in_addr))) {
336                     return 0;
337                 }
338                 break;
339             case ACL_RANGE_MINMAX:
340                 if (!acl_addr_matches_range((uint32_t*)&acl->addr.addr,
341                     (uint32_t*)&addr4->sin_addr,
342                     (uint32_t*)&acl->range_mask.addr,
343                     sizeof(struct in_addr))) {
344                     return 0;
345                 }
346                 break;
347             case ACL_RANGE_SINGLE:
348             default:
349                 if (memcmp(&addr4->sin_addr, &acl->addr.addr,
350                     sizeof(struct in_addr)) != 0) {
351                     return 0;
352                 }
353                 break;
354         }
355         return 1;
356     }
357     /* not reached */
358     return 0;
359 }
360 
361 
362 /**
363  * ACL matches TSIG.
364  *
365  */
366 static int
acl_tsig_matches(acl_type * acl,tsig_rr_type * tsig)367 acl_tsig_matches(acl_type* acl, tsig_rr_type* tsig)
368 {
369     if (!acl || !tsig) {
370         ods_log_debug("[%s] no match: no acl or tsig", acl_str);
371         return 0; /* missing required elements */
372     }
373     if (!acl->tsig) {
374         if (tsig->status == TSIG_NOT_PRESENT) {
375             return 1;
376         }
377         ods_log_debug("[%s] no match: tsig present but no config", acl_str);
378         return 0; /* TSIG present but no config */
379     }
380     if (tsig->status != TSIG_OK) {
381         ods_log_debug("[%s] no match: tsig %s", acl_str,
382             tsig_status2str(tsig->status));
383         return 0; /* query has no TSIG */
384     }
385     if (tsig->error_code != LDNS_RCODE_NOERROR) {
386         ods_log_debug("[%s] no match: tsig error %d", acl_str,
387             tsig->error_code);
388         return 0; /* query has bork TSIG */
389     }
390     if (!tsig->key_name || !tsig->algo) {
391         ods_log_debug("[%s] no match: missing key/algo", acl_str);
392         return 0;
393     }
394     if (!acl->tsig->key) {
395         ods_log_debug("[%s] no match: no config", acl_str);
396         return 0; /* missing TSIG config */
397     }
398     if (ldns_dname_compare(tsig->key_name, acl->tsig->key->dname) != 0) {
399         ods_log_debug("[%s] no match: key names not the same", acl_str);
400         return 0; /* wrong key name */
401     }
402     if (ods_strlowercmp(tsig->algo->txt_name, acl->tsig->algorithm) != 0) {
403         ods_log_debug("[%s] no match: algorithms not the same", acl_str);
404         return 0; /* wrong algorithm name */
405     }
406     /* tsig matches */
407     return 1;
408 }
409 
410 
411 /**
412  * Address storage to IP string.
413  *
414  */
415 int
addr2ip(struct sockaddr_storage addr,char * ip,size_t len)416 addr2ip(struct sockaddr_storage addr, char* ip, size_t len)
417 {
418     if (addr.ss_family == AF_INET6) {
419         if (!inet_ntop(AF_INET6, &((struct sockaddr_in6 *)&addr)->sin6_addr,
420             ip, len)) {
421             return 0;
422         }
423     } else {
424         if (!inet_ntop(AF_INET, &((struct sockaddr_in *)&addr)->sin_addr,
425             ip, len))
426             return 0;
427     }
428     return 1;
429 }
430 
431 
432 /**
433  * Find ACL.
434  *
435  */
436 acl_type*
acl_find(acl_type * acl,struct sockaddr_storage * addr,tsig_rr_type * trr)437 acl_find(acl_type* acl, struct sockaddr_storage* addr, tsig_rr_type* trr)
438 {
439     acl_type* find = acl;
440     while (find) {
441         if (acl_addr_matches(find, addr) && acl_tsig_matches(find, trr)) {
442             ods_log_debug("[%s] match %s", acl_str, find->address);
443             return find;
444         }
445         find = find->next;
446     }
447     return NULL;
448 }
449 
450 
451 /**
452  * Clean up ACL.
453  *
454  */
455 void
acl_cleanup(acl_type * acl)456 acl_cleanup(acl_type* acl)
457 {
458     if (!acl) {
459         return;
460     }
461     acl_cleanup(acl->next);
462     free(acl->address);
463     free(acl);
464 }
465