OpenDNSSEC-signer  2.1.6
acl.c
Go to the documentation of this file.
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 
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 
46 static acl_range_type
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 
74 static ods_status
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 
103 int
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 
125 acl_type*
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 
220 static int
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 
239 static int
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 
276 static int
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 
366 static int
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 
415 int
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 
436 acl_type*
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 
455 void
457 {
458  if (!acl) {
459  return;
460  }
461  acl_cleanup(acl->next);
462  free(acl->address);
463  free(acl);
464 }
tsig_rr_struct::error_code
uint16_t error_code
Definition: tsig.h:142
acl_parse_family
int acl_parse_family(const char *a)
Definition: acl.c:104
tsig_algo_struct::txt_name
const char * txt_name
Definition: tsig.h:90
acl_range_type
enum acl_range_enum acl_range_type
Definition: acl.h:51
acl_struct::port
unsigned int port
Definition: acl.h:62
acl_addr_storage
Definition: listener.h:59
tsig_struct
Definition: tsig.h:110
acl_cleanup
void acl_cleanup(acl_type *acl)
Definition: acl.c:456
ACL_RANGE_SUBNET
@ ACL_RANGE_SUBNET
Definition: acl.h:48
acl_struct::ixfr_disabled
time_t ixfr_disabled
Definition: acl.h:71
tsig_lookup_by_name
tsig_type * tsig_lookup_by_name(tsig_type *tsig, const char *name)
Definition: tsig.c:235
tsig_struct::key
tsig_key_type * key
Definition: tsig.h:115
tsig_status2str
const char * tsig_status2str(tsig_status status)
Definition: tsig.c:759
tsig_rr_struct
Definition: tsig.h:123
acl_struct::range_mask
union acl_addr_storage range_mask
Definition: acl.h:65
tsig_struct::algorithm
const char * algorithm
Definition: tsig.h:113
acl.h
ACL_RANGE_MINMAX
@ ACL_RANGE_MINMAX
Definition: acl.h:49
acl_find
acl_type * acl_find(acl_type *acl, struct sockaddr_storage *addr, tsig_rr_type *trr)
Definition: acl.c:437
acl_struct
Definition: acl.h:58
acl_addr_storage::addr6
struct in6_addr addr6
Definition: listener.h:61
tsig_rr_struct::key_name
ldns_rdf * key_name
Definition: tsig.h:134
acl_addr_storage::addr
struct in_addr addr
Definition: listener.h:60
acl_create
acl_type * acl_create(char *address, char *port, char *tsig_name, tsig_type *tsig)
Definition: acl.c:126
acl_struct::address
char * address
Definition: acl.h:61
acl_struct::range_type
acl_range_type range_type
Definition: acl.h:66
TSIG_NOT_PRESENT
@ TSIG_NOT_PRESENT
Definition: tsig.h:56
addr2ip
int addr2ip(struct sockaddr_storage addr, char *ip, size_t len)
Definition: acl.c:416
ACL_RANGE_SINGLE
@ ACL_RANGE_SINGLE
Definition: acl.h:46
acl_struct::addr
union acl_addr_storage addr
Definition: acl.h:64
ACL_RANGE_MASK
@ ACL_RANGE_MASK
Definition: acl.h:47
TSIG_OK
@ TSIG_OK
Definition: tsig.h:57
acl_struct::next
acl_type * next
Definition: acl.h:59
tsig_key_struct::dname
ldns_rdf * dname
Definition: tsig.h:79
acl_struct::family
int family
Definition: acl.h:63
acl_struct::tsig
tsig_type * tsig
Definition: acl.h:69
tsig_rr_struct::status
tsig_status status
Definition: tsig.h:124
tsig_rr_struct::algo
tsig_algo_type * algo
Definition: tsig.h:129