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