2 * Copyright (C) 2004-2008, 2010, 2011, 2013, 2014 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 2000, 2001, 2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
20 * $Id: ssu.c,v 1.38 2011/01/06 23:47:00 tbox Exp $
21 * Principal Author: Brian Wellington
26 #include <isc/magic.h>
28 #include <isc/netaddr.h>
29 #include <isc/result.h>
30 #include <isc/string.h>
34 #include <dns/fixedname.h>
38 #include <dst/gssapi.h>
41 #define SSUTABLEMAGIC ISC_MAGIC('S', 'S', 'U', 'T')
42 #define VALID_SSUTABLE(table) ISC_MAGIC_VALID(table, SSUTABLEMAGIC)
44 #define SSURULEMAGIC ISC_MAGIC('S', 'S', 'U', 'R')
45 #define VALID_SSURULE(table) ISC_MAGIC_VALID(table, SSURULEMAGIC)
49 isc_boolean_t grant; /*%< is this a grant or a deny? */
50 unsigned int matchtype; /*%< which type of pattern match? */
51 dns_name_t *identity; /*%< the identity to match */
52 dns_name_t *name; /*%< the name being updated */
53 unsigned int ntypes; /*%< number of data types covered */
54 dns_rdatatype_t *types; /*%< the data types. Can include ANY, */
55 /*%< defaults to all but SIG,SOA,NS if NULL */
56 ISC_LINK(dns_ssurule_t) link;
62 unsigned int references;
64 dns_dlzdb_t *dlzdatabase;
65 ISC_LIST(dns_ssurule_t) rules;
69 dns_ssutable_create(isc_mem_t *mctx, dns_ssutable_t **tablep) {
71 dns_ssutable_t *table;
73 REQUIRE(tablep != NULL && *tablep == NULL);
74 REQUIRE(mctx != NULL);
76 table = isc_mem_get(mctx, sizeof(dns_ssutable_t));
78 return (ISC_R_NOMEMORY);
79 result = isc_mutex_init(&table->lock);
80 if (result != ISC_R_SUCCESS) {
81 isc_mem_put(mctx, table, sizeof(dns_ssutable_t));
84 table->references = 1;
86 isc_mem_attach(mctx, &table->mctx);
87 ISC_LIST_INIT(table->rules);
88 table->magic = SSUTABLEMAGIC;
90 return (ISC_R_SUCCESS);
94 destroy(dns_ssutable_t *table) {
97 REQUIRE(VALID_SSUTABLE(table));
100 while (!ISC_LIST_EMPTY(table->rules)) {
101 dns_ssurule_t *rule = ISC_LIST_HEAD(table->rules);
102 if (rule->identity != NULL) {
103 dns_name_free(rule->identity, mctx);
104 isc_mem_put(mctx, rule->identity, sizeof(dns_name_t));
106 if (rule->name != NULL) {
107 dns_name_free(rule->name, mctx);
108 isc_mem_put(mctx, rule->name, sizeof(dns_name_t));
110 if (rule->types != NULL)
111 isc_mem_put(mctx, rule->types,
112 rule->ntypes * sizeof(dns_rdatatype_t));
113 ISC_LIST_UNLINK(table->rules, rule, link);
115 isc_mem_put(mctx, rule, sizeof(dns_ssurule_t));
117 DESTROYLOCK(&table->lock);
119 isc_mem_putanddetach(&table->mctx, table, sizeof(dns_ssutable_t));
123 dns_ssutable_attach(dns_ssutable_t *source, dns_ssutable_t **targetp) {
124 REQUIRE(VALID_SSUTABLE(source));
125 REQUIRE(targetp != NULL && *targetp == NULL);
129 INSIST(source->references > 0);
130 source->references++;
131 INSIST(source->references != 0);
133 UNLOCK(&source->lock);
139 dns_ssutable_detach(dns_ssutable_t **tablep) {
140 dns_ssutable_t *table;
141 isc_boolean_t done = ISC_FALSE;
143 REQUIRE(tablep != NULL);
145 REQUIRE(VALID_SSUTABLE(table));
149 INSIST(table->references > 0);
150 if (--table->references == 0)
152 UNLOCK(&table->lock);
161 dns_ssutable_addrule(dns_ssutable_t *table, isc_boolean_t grant,
162 dns_name_t *identity, unsigned int matchtype,
163 dns_name_t *name, unsigned int ntypes,
164 dns_rdatatype_t *types)
170 REQUIRE(VALID_SSUTABLE(table));
171 REQUIRE(dns_name_isabsolute(identity));
172 REQUIRE(dns_name_isabsolute(name));
173 REQUIRE(matchtype <= DNS_SSUMATCHTYPE_MAX);
174 if (matchtype == DNS_SSUMATCHTYPE_WILDCARD)
175 REQUIRE(dns_name_iswildcard(name));
177 REQUIRE(types != NULL);
180 rule = isc_mem_get(mctx, sizeof(dns_ssurule_t));
182 return (ISC_R_NOMEMORY);
184 rule->identity = NULL;
190 rule->identity = isc_mem_get(mctx, sizeof(dns_name_t));
191 if (rule->identity == NULL) {
192 result = ISC_R_NOMEMORY;
195 dns_name_init(rule->identity, NULL);
196 result = dns_name_dup(identity, mctx, rule->identity);
197 if (result != ISC_R_SUCCESS)
200 rule->name = isc_mem_get(mctx, sizeof(dns_name_t));
201 if (rule->name == NULL) {
202 result = ISC_R_NOMEMORY;
205 dns_name_init(rule->name, NULL);
206 result = dns_name_dup(name, mctx, rule->name);
207 if (result != ISC_R_SUCCESS)
210 rule->matchtype = matchtype;
212 rule->ntypes = ntypes;
214 rule->types = isc_mem_get(mctx,
215 ntypes * sizeof(dns_rdatatype_t));
216 if (rule->types == NULL) {
217 result = ISC_R_NOMEMORY;
220 memmove(rule->types, types, ntypes * sizeof(dns_rdatatype_t));
224 rule->magic = SSURULEMAGIC;
225 ISC_LIST_INITANDAPPEND(table->rules, rule, link);
227 return (ISC_R_SUCCESS);
230 if (rule->identity != NULL) {
231 if (dns_name_dynamic(rule->identity))
232 dns_name_free(rule->identity, mctx);
233 isc_mem_put(mctx, rule->identity, sizeof(dns_name_t));
235 if (rule->name != NULL) {
236 if (dns_name_dynamic(rule->name))
237 dns_name_free(rule->name, mctx);
238 isc_mem_put(mctx, rule->name, sizeof(dns_name_t));
240 if (rule->types != NULL)
241 isc_mem_put(mctx, rule->types,
242 ntypes * sizeof(dns_rdatatype_t));
243 isc_mem_put(mctx, rule, sizeof(dns_ssurule_t));
248 static inline isc_boolean_t
249 isusertype(dns_rdatatype_t type) {
250 return (ISC_TF(type != dns_rdatatype_ns &&
251 type != dns_rdatatype_soa &&
252 type != dns_rdatatype_rrsig));
256 reverse_from_address(dns_name_t *tcpself, isc_netaddr_t *tcpaddr) {
257 char buf[16 * 4 + sizeof("IP6.ARPA.")];
263 switch (tcpaddr->family) {
265 l = ntohl(tcpaddr->type.in.s_addr);
266 result = isc_string_printf(buf, sizeof(buf),
267 "%lu.%lu.%lu.%lu.IN-ADDR.ARPA.",
268 (l >> 0) & 0xff, (l >> 8) & 0xff,
269 (l >> 16) & 0xff, (l >> 24) & 0xff);
270 RUNTIME_CHECK(result == ISC_R_SUCCESS);
273 ap = tcpaddr->type.in6.s6_addr;
274 result = isc_string_printf(buf, sizeof(buf),
275 "%x.%x.%x.%x.%x.%x.%x.%x."
276 "%x.%x.%x.%x.%x.%x.%x.%x."
277 "%x.%x.%x.%x.%x.%x.%x.%x."
278 "%x.%x.%x.%x.%x.%x.%x.%x."
280 ap[15] & 0x0f, (ap[15] >> 4) & 0x0f,
281 ap[14] & 0x0f, (ap[14] >> 4) & 0x0f,
282 ap[13] & 0x0f, (ap[13] >> 4) & 0x0f,
283 ap[12] & 0x0f, (ap[12] >> 4) & 0x0f,
284 ap[11] & 0x0f, (ap[11] >> 4) & 0x0f,
285 ap[10] & 0x0f, (ap[10] >> 4) & 0x0f,
286 ap[9] & 0x0f, (ap[9] >> 4) & 0x0f,
287 ap[8] & 0x0f, (ap[8] >> 4) & 0x0f,
288 ap[7] & 0x0f, (ap[7] >> 4) & 0x0f,
289 ap[6] & 0x0f, (ap[6] >> 4) & 0x0f,
290 ap[5] & 0x0f, (ap[5] >> 4) & 0x0f,
291 ap[4] & 0x0f, (ap[4] >> 4) & 0x0f,
292 ap[3] & 0x0f, (ap[3] >> 4) & 0x0f,
293 ap[2] & 0x0f, (ap[2] >> 4) & 0x0f,
294 ap[1] & 0x0f, (ap[1] >> 4) & 0x0f,
295 ap[0] & 0x0f, (ap[0] >> 4) & 0x0f);
296 RUNTIME_CHECK(result == ISC_R_SUCCESS);
301 isc_buffer_init(&b, buf, strlen(buf));
302 isc_buffer_add(&b, strlen(buf));
303 result = dns_name_fromtext(tcpself, &b, dns_rootname, 0, NULL);
304 RUNTIME_CHECK(result == ISC_R_SUCCESS);
308 stf_from_address(dns_name_t *stfself, isc_netaddr_t *tcpaddr) {
309 char buf[sizeof("X.X.X.X.Y.Y.Y.Y.2.0.0.2.IP6.ARPA.")];
315 switch(tcpaddr->family) {
317 l = ntohl(tcpaddr->type.in.s_addr);
318 result = isc_string_printf(buf, sizeof(buf),
319 "%lx.%lx.%lx.%lx.%lx.%lx.%lx.%lx"
321 l & 0xf, (l >> 4) & 0xf,
322 (l >> 8) & 0xf, (l >> 12) & 0xf,
323 (l >> 16) & 0xf, (l >> 20) & 0xf,
324 (l >> 24) & 0xf, (l >> 28) & 0xf);
325 RUNTIME_CHECK(result == ISC_R_SUCCESS);
328 ap = tcpaddr->type.in6.s6_addr;
329 result = isc_string_printf(buf, sizeof(buf),
330 "%x.%x.%x.%x.%x.%x.%x.%x."
331 "%x.%x.%x.%x.IP6.ARPA.",
332 ap[5] & 0x0f, (ap[5] >> 4) & 0x0f,
333 ap[4] & 0x0f, (ap[4] >> 4) & 0x0f,
334 ap[3] & 0x0f, (ap[3] >> 4) & 0x0f,
335 ap[2] & 0x0f, (ap[2] >> 4) & 0x0f,
336 ap[1] & 0x0f, (ap[1] >> 4) & 0x0f,
337 ap[0] & 0x0f, (ap[0] >> 4) & 0x0f);
338 RUNTIME_CHECK(result == ISC_R_SUCCESS);
343 isc_buffer_init(&b, buf, strlen(buf));
344 isc_buffer_add(&b, strlen(buf));
345 result = dns_name_fromtext(stfself, &b, dns_rootname, 0, NULL);
346 RUNTIME_CHECK(result == ISC_R_SUCCESS);
350 dns_ssutable_checkrules(dns_ssutable_t *table, dns_name_t *signer,
351 dns_name_t *name, isc_netaddr_t *tcpaddr,
352 dns_rdatatype_t type,
353 const dst_key_t *key)
357 dns_fixedname_t fixed;
358 dns_name_t *wildcard;
363 REQUIRE(VALID_SSUTABLE(table));
364 REQUIRE(signer == NULL || dns_name_isabsolute(signer));
365 REQUIRE(dns_name_isabsolute(name));
367 if (signer == NULL && tcpaddr == NULL)
370 for (rule = ISC_LIST_HEAD(table->rules);
372 rule = ISC_LIST_NEXT(rule, link))
374 switch (rule->matchtype) {
375 case DNS_SSUMATCHTYPE_NAME:
376 case DNS_SSUMATCHTYPE_SUBDOMAIN:
377 case DNS_SSUMATCHTYPE_WILDCARD:
378 case DNS_SSUMATCHTYPE_SELF:
379 case DNS_SSUMATCHTYPE_SELFSUB:
380 case DNS_SSUMATCHTYPE_SELFWILD:
383 if (dns_name_iswildcard(rule->identity)) {
384 if (!dns_name_matcheswildcard(signer,
388 if (!dns_name_equal(signer, rule->identity))
392 case DNS_SSUMATCHTYPE_SELFKRB5:
393 case DNS_SSUMATCHTYPE_SELFMS:
394 case DNS_SSUMATCHTYPE_SUBDOMAINKRB5:
395 case DNS_SSUMATCHTYPE_SUBDOMAINMS:
399 case DNS_SSUMATCHTYPE_TCPSELF:
400 case DNS_SSUMATCHTYPE_6TO4SELF:
406 switch (rule->matchtype) {
407 case DNS_SSUMATCHTYPE_NAME:
408 if (!dns_name_equal(name, rule->name))
411 case DNS_SSUMATCHTYPE_SUBDOMAIN:
412 if (!dns_name_issubdomain(name, rule->name))
415 case DNS_SSUMATCHTYPE_WILDCARD:
416 if (!dns_name_matcheswildcard(name, rule->name))
419 case DNS_SSUMATCHTYPE_SELF:
420 if (!dns_name_equal(signer, name))
423 case DNS_SSUMATCHTYPE_SELFSUB:
424 if (!dns_name_issubdomain(name, signer))
427 case DNS_SSUMATCHTYPE_SELFWILD:
428 dns_fixedname_init(&fixed);
429 wildcard = dns_fixedname_name(&fixed);
430 result = dns_name_concatenate(dns_wildcardname, signer,
432 if (result != ISC_R_SUCCESS)
434 if (!dns_name_matcheswildcard(name, wildcard))
437 case DNS_SSUMATCHTYPE_SELFKRB5:
438 if (!dst_gssapi_identitymatchesrealmkrb5(signer, name,
442 case DNS_SSUMATCHTYPE_SELFMS:
443 if (!dst_gssapi_identitymatchesrealmms(signer, name,
447 case DNS_SSUMATCHTYPE_SUBDOMAINKRB5:
448 if (!dns_name_issubdomain(name, rule->name))
450 if (!dst_gssapi_identitymatchesrealmkrb5(signer, NULL,
454 case DNS_SSUMATCHTYPE_SUBDOMAINMS:
455 if (!dns_name_issubdomain(name, rule->name))
457 if (!dst_gssapi_identitymatchesrealmms(signer, NULL,
461 case DNS_SSUMATCHTYPE_TCPSELF:
462 dns_fixedname_init(&fixed);
463 tcpself = dns_fixedname_name(&fixed);
464 reverse_from_address(tcpself, tcpaddr);
465 if (dns_name_iswildcard(rule->identity)) {
466 if (!dns_name_matcheswildcard(tcpself,
470 if (!dns_name_equal(tcpself, rule->identity))
473 if (!dns_name_equal(tcpself, name))
476 case DNS_SSUMATCHTYPE_6TO4SELF:
477 dns_fixedname_init(&fixed);
478 stfself = dns_fixedname_name(&fixed);
479 stf_from_address(stfself, tcpaddr);
480 if (dns_name_iswildcard(rule->identity)) {
481 if (!dns_name_matcheswildcard(stfself,
485 if (!dns_name_equal(stfself, rule->identity))
488 if (!dns_name_equal(stfself, name))
491 case DNS_SSUMATCHTYPE_EXTERNAL:
492 if (!dns_ssu_external_match(rule->identity, signer,
493 name, tcpaddr, type, key,
497 case DNS_SSUMATCHTYPE_DLZ:
498 if (!dns_dlz_ssumatch(table->dlzdatabase, signer,
499 name, tcpaddr, type, key))
504 if (rule->ntypes == 0) {
506 * If this is a DLZ rule, then the DLZ ssu
507 * checks will have already checked
510 if (rule->matchtype != DNS_SSUMATCHTYPE_DLZ &&
514 for (i = 0; i < rule->ntypes; i++) {
515 if (rule->types[i] == dns_rdatatype_any ||
516 rule->types[i] == type)
519 if (i == rule->ntypes)
522 return (rule->grant);
529 dns_ssurule_isgrant(const dns_ssurule_t *rule) {
530 REQUIRE(VALID_SSURULE(rule));
531 return (rule->grant);
535 dns_ssurule_identity(const dns_ssurule_t *rule) {
536 REQUIRE(VALID_SSURULE(rule));
537 return (rule->identity);
541 dns_ssurule_matchtype(const dns_ssurule_t *rule) {
542 REQUIRE(VALID_SSURULE(rule));
543 return (rule->matchtype);
547 dns_ssurule_name(const dns_ssurule_t *rule) {
548 REQUIRE(VALID_SSURULE(rule));
553 dns_ssurule_types(const dns_ssurule_t *rule, dns_rdatatype_t **types) {
554 REQUIRE(VALID_SSURULE(rule));
555 REQUIRE(types != NULL && *types != NULL);
556 *types = rule->types;
557 return (rule->ntypes);
561 dns_ssutable_firstrule(const dns_ssutable_t *table, dns_ssurule_t **rule) {
562 REQUIRE(VALID_SSUTABLE(table));
563 REQUIRE(rule != NULL && *rule == NULL);
564 *rule = ISC_LIST_HEAD(table->rules);
565 return (*rule != NULL ? ISC_R_SUCCESS : ISC_R_NOMORE);
569 dns_ssutable_nextrule(dns_ssurule_t *rule, dns_ssurule_t **nextrule) {
570 REQUIRE(VALID_SSURULE(rule));
571 REQUIRE(nextrule != NULL && *nextrule == NULL);
572 *nextrule = ISC_LIST_NEXT(rule, link);
573 return (*nextrule != NULL ? ISC_R_SUCCESS : ISC_R_NOMORE);
577 * Create a specialised SSU table that points at an external DLZ database
580 dns_ssutable_createdlz(isc_mem_t *mctx, dns_ssutable_t **tablep,
581 dns_dlzdb_t *dlzdatabase)
585 dns_ssutable_t *table = NULL;
587 REQUIRE(tablep != NULL && *tablep == NULL);
589 result = dns_ssutable_create(mctx, &table);
590 if (result != ISC_R_SUCCESS)
593 table->dlzdatabase = dlzdatabase;
595 rule = isc_mem_get(table->mctx, sizeof(dns_ssurule_t));
597 dns_ssutable_detach(&table);
598 return (ISC_R_NOMEMORY);
601 rule->identity = NULL;
604 rule->grant = ISC_TRUE;
605 rule->matchtype = DNS_SSUMATCHTYPE_DLZ;
608 rule->magic = SSURULEMAGIC;
610 ISC_LIST_INITANDAPPEND(table->rules, rule, link);
612 return (ISC_R_SUCCESS);