Home | History | Annotate | Line # | Download | only in dns
      1 /*	$NetBSD: ssu.c,v 1.1 2024/02/18 20:57:34 christos Exp $	*/
      2 
      3 /*
      4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
      5  *
      6  * SPDX-License-Identifier: MPL-2.0
      7  *
      8  * This Source Code Form is subject to the terms of the Mozilla Public
      9  * License, v. 2.0. If a copy of the MPL was not distributed with this
     10  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
     11  *
     12  * See the COPYRIGHT file distributed with this work for additional
     13  * information regarding copyright ownership.
     14  */
     15 
     16 /*! \file */
     17 
     18 #include <stdbool.h>
     19 
     20 #include <isc/magic.h>
     21 #include <isc/mem.h>
     22 #include <isc/netaddr.h>
     23 #include <isc/print.h>
     24 #include <isc/refcount.h>
     25 #include <isc/result.h>
     26 #include <isc/string.h>
     27 #include <isc/util.h>
     28 
     29 #include <dns/dlz.h>
     30 #include <dns/fixedname.h>
     31 #include <dns/name.h>
     32 #include <dns/ssu.h>
     33 
     34 #include <dst/dst.h>
     35 #include <dst/gssapi.h>
     36 
     37 #define SSUTABLEMAGIC	      ISC_MAGIC('S', 'S', 'U', 'T')
     38 #define VALID_SSUTABLE(table) ISC_MAGIC_VALID(table, SSUTABLEMAGIC)
     39 
     40 #define SSURULEMAGIC	     ISC_MAGIC('S', 'S', 'U', 'R')
     41 #define VALID_SSURULE(table) ISC_MAGIC_VALID(table, SSURULEMAGIC)
     42 
     43 struct dns_ssurule {
     44 	unsigned int magic;
     45 	bool grant;		      /*%< is this a grant or a deny? */
     46 	dns_ssumatchtype_t matchtype; /*%< which type of pattern match?
     47 				       * */
     48 	dns_name_t *identity;	      /*%< the identity to match */
     49 	dns_name_t *name;	      /*%< the name being updated */
     50 	unsigned int ntypes;	      /*%< number of data types covered */
     51 	dns_rdatatype_t *types;	      /*%< the data types.  Can include */
     52 				      /*   ANY. if NULL, defaults to all */
     53 				      /*   types except SIG, SOA, and NS */
     54 	ISC_LINK(dns_ssurule_t) link;
     55 };
     56 
     57 struct dns_ssutable {
     58 	unsigned int magic;
     59 	isc_mem_t *mctx;
     60 	isc_refcount_t references;
     61 	dns_dlzdb_t *dlzdatabase;
     62 	ISC_LIST(dns_ssurule_t) rules;
     63 };
     64 
     65 isc_result_t
     66 dns_ssutable_create(isc_mem_t *mctx, dns_ssutable_t **tablep) {
     67 	dns_ssutable_t *table;
     68 
     69 	REQUIRE(tablep != NULL && *tablep == NULL);
     70 	REQUIRE(mctx != NULL);
     71 
     72 	table = isc_mem_get(mctx, sizeof(dns_ssutable_t));
     73 	isc_refcount_init(&table->references, 1);
     74 	table->mctx = NULL;
     75 	isc_mem_attach(mctx, &table->mctx);
     76 	ISC_LIST_INIT(table->rules);
     77 	table->magic = SSUTABLEMAGIC;
     78 	*tablep = table;
     79 	return (ISC_R_SUCCESS);
     80 }
     81 
     82 static void
     83 destroy(dns_ssutable_t *table) {
     84 	isc_mem_t *mctx;
     85 
     86 	REQUIRE(VALID_SSUTABLE(table));
     87 
     88 	mctx = table->mctx;
     89 	while (!ISC_LIST_EMPTY(table->rules)) {
     90 		dns_ssurule_t *rule = ISC_LIST_HEAD(table->rules);
     91 		if (rule->identity != NULL) {
     92 			dns_name_free(rule->identity, mctx);
     93 			isc_mem_put(mctx, rule->identity, sizeof(dns_name_t));
     94 		}
     95 		if (rule->name != NULL) {
     96 			dns_name_free(rule->name, mctx);
     97 			isc_mem_put(mctx, rule->name, sizeof(dns_name_t));
     98 		}
     99 		if (rule->types != NULL) {
    100 			isc_mem_put(mctx, rule->types,
    101 				    rule->ntypes * sizeof(dns_rdatatype_t));
    102 		}
    103 		ISC_LIST_UNLINK(table->rules, rule, link);
    104 		rule->magic = 0;
    105 		isc_mem_put(mctx, rule, sizeof(dns_ssurule_t));
    106 	}
    107 	isc_refcount_destroy(&table->references);
    108 	table->magic = 0;
    109 	isc_mem_putanddetach(&table->mctx, table, sizeof(dns_ssutable_t));
    110 }
    111 
    112 void
    113 dns_ssutable_attach(dns_ssutable_t *source, dns_ssutable_t **targetp) {
    114 	REQUIRE(VALID_SSUTABLE(source));
    115 	REQUIRE(targetp != NULL && *targetp == NULL);
    116 
    117 	isc_refcount_increment(&source->references);
    118 
    119 	*targetp = source;
    120 }
    121 
    122 void
    123 dns_ssutable_detach(dns_ssutable_t **tablep) {
    124 	dns_ssutable_t *table;
    125 
    126 	REQUIRE(tablep != NULL);
    127 	table = *tablep;
    128 	*tablep = NULL;
    129 	REQUIRE(VALID_SSUTABLE(table));
    130 
    131 	if (isc_refcount_decrement(&table->references) == 1) {
    132 		destroy(table);
    133 	}
    134 }
    135 
    136 isc_result_t
    137 dns_ssutable_addrule(dns_ssutable_t *table, bool grant,
    138 		     const dns_name_t *identity, dns_ssumatchtype_t matchtype,
    139 		     const dns_name_t *name, unsigned int ntypes,
    140 		     dns_rdatatype_t *types) {
    141 	dns_ssurule_t *rule;
    142 	isc_mem_t *mctx;
    143 
    144 	REQUIRE(VALID_SSUTABLE(table));
    145 	REQUIRE(dns_name_isabsolute(identity));
    146 	REQUIRE(dns_name_isabsolute(name));
    147 	REQUIRE(matchtype <= dns_ssumatchtype_max);
    148 	if (matchtype == dns_ssumatchtype_wildcard) {
    149 		REQUIRE(dns_name_iswildcard(name));
    150 	}
    151 	if (ntypes > 0) {
    152 		REQUIRE(types != NULL);
    153 	}
    154 
    155 	mctx = table->mctx;
    156 	rule = isc_mem_get(mctx, sizeof(dns_ssurule_t));
    157 
    158 	rule->identity = NULL;
    159 	rule->name = NULL;
    160 	rule->types = NULL;
    161 
    162 	rule->grant = grant;
    163 
    164 	rule->identity = isc_mem_get(mctx, sizeof(dns_name_t));
    165 	dns_name_init(rule->identity, NULL);
    166 	dns_name_dup(identity, mctx, rule->identity);
    167 
    168 	rule->name = isc_mem_get(mctx, sizeof(dns_name_t));
    169 	dns_name_init(rule->name, NULL);
    170 	dns_name_dup(name, mctx, rule->name);
    171 
    172 	rule->matchtype = matchtype;
    173 
    174 	rule->ntypes = ntypes;
    175 	if (ntypes > 0) {
    176 		rule->types = isc_mem_get(mctx,
    177 					  ntypes * sizeof(dns_rdatatype_t));
    178 		memmove(rule->types, types, ntypes * sizeof(dns_rdatatype_t));
    179 	} else {
    180 		rule->types = NULL;
    181 	}
    182 
    183 	rule->magic = SSURULEMAGIC;
    184 	ISC_LIST_INITANDAPPEND(table->rules, rule, link);
    185 
    186 	return (ISC_R_SUCCESS);
    187 }
    188 
    189 static bool
    190 isusertype(dns_rdatatype_t type) {
    191 	return (type != dns_rdatatype_ns && type != dns_rdatatype_soa &&
    192 		type != dns_rdatatype_rrsig);
    193 }
    194 
    195 static void
    196 reverse_from_address(dns_name_t *tcpself, const isc_netaddr_t *tcpaddr) {
    197 	char buf[16 * 4 + sizeof("IP6.ARPA.")];
    198 	isc_result_t result;
    199 	const unsigned char *ap;
    200 	isc_buffer_t b;
    201 	unsigned long l;
    202 
    203 	switch (tcpaddr->family) {
    204 	case AF_INET:
    205 		l = ntohl(tcpaddr->type.in.s_addr);
    206 		result = snprintf(buf, sizeof(buf),
    207 				  "%lu.%lu.%lu.%lu.IN-ADDR.ARPA.",
    208 				  (l >> 0) & 0xff, (l >> 8) & 0xff,
    209 				  (l >> 16) & 0xff, (l >> 24) & 0xff);
    210 		RUNTIME_CHECK(result < sizeof(buf));
    211 		break;
    212 	case AF_INET6:
    213 		ap = tcpaddr->type.in6.s6_addr;
    214 		result = snprintf(
    215 			buf, sizeof(buf),
    216 			"%x.%x.%x.%x.%x.%x.%x.%x."
    217 			"%x.%x.%x.%x.%x.%x.%x.%x."
    218 			"%x.%x.%x.%x.%x.%x.%x.%x."
    219 			"%x.%x.%x.%x.%x.%x.%x.%x."
    220 			"IP6.ARPA.",
    221 			ap[15] & 0x0f, (ap[15] >> 4) & 0x0f, ap[14] & 0x0f,
    222 			(ap[14] >> 4) & 0x0f, ap[13] & 0x0f,
    223 			(ap[13] >> 4) & 0x0f, ap[12] & 0x0f,
    224 			(ap[12] >> 4) & 0x0f, ap[11] & 0x0f,
    225 			(ap[11] >> 4) & 0x0f, ap[10] & 0x0f,
    226 			(ap[10] >> 4) & 0x0f, ap[9] & 0x0f, (ap[9] >> 4) & 0x0f,
    227 			ap[8] & 0x0f, (ap[8] >> 4) & 0x0f, ap[7] & 0x0f,
    228 			(ap[7] >> 4) & 0x0f, ap[6] & 0x0f, (ap[6] >> 4) & 0x0f,
    229 			ap[5] & 0x0f, (ap[5] >> 4) & 0x0f, ap[4] & 0x0f,
    230 			(ap[4] >> 4) & 0x0f, ap[3] & 0x0f, (ap[3] >> 4) & 0x0f,
    231 			ap[2] & 0x0f, (ap[2] >> 4) & 0x0f, ap[1] & 0x0f,
    232 			(ap[1] >> 4) & 0x0f, ap[0] & 0x0f, (ap[0] >> 4) & 0x0f);
    233 		RUNTIME_CHECK(result < sizeof(buf));
    234 		break;
    235 	default:
    236 		UNREACHABLE();
    237 	}
    238 	isc_buffer_init(&b, buf, strlen(buf));
    239 	isc_buffer_add(&b, strlen(buf));
    240 	result = dns_name_fromtext(tcpself, &b, dns_rootname, 0, NULL);
    241 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
    242 }
    243 
    244 static void
    245 stf_from_address(dns_name_t *stfself, const isc_netaddr_t *tcpaddr) {
    246 	char buf[sizeof("X.X.X.X.Y.Y.Y.Y.2.0.0.2.IP6.ARPA.")];
    247 	isc_result_t result;
    248 	const unsigned char *ap;
    249 	isc_buffer_t b;
    250 	unsigned long l;
    251 
    252 	switch (tcpaddr->family) {
    253 	case AF_INET:
    254 		l = ntohl(tcpaddr->type.in.s_addr);
    255 		result = snprintf(buf, sizeof(buf),
    256 				  "%lx.%lx.%lx.%lx.%lx.%lx.%lx.%lx"
    257 				  "2.0.0.2.IP6.ARPA.",
    258 				  l & 0xf, (l >> 4) & 0xf, (l >> 8) & 0xf,
    259 				  (l >> 12) & 0xf, (l >> 16) & 0xf,
    260 				  (l >> 20) & 0xf, (l >> 24) & 0xf,
    261 				  (l >> 28) & 0xf);
    262 		RUNTIME_CHECK(result < sizeof(buf));
    263 		break;
    264 	case AF_INET6:
    265 		ap = tcpaddr->type.in6.s6_addr;
    266 		result = snprintf(
    267 			buf, sizeof(buf),
    268 			"%x.%x.%x.%x.%x.%x.%x.%x."
    269 			"%x.%x.%x.%x.IP6.ARPA.",
    270 			ap[5] & 0x0f, (ap[5] >> 4) & 0x0f, ap[4] & 0x0f,
    271 			(ap[4] >> 4) & 0x0f, ap[3] & 0x0f, (ap[3] >> 4) & 0x0f,
    272 			ap[2] & 0x0f, (ap[2] >> 4) & 0x0f, ap[1] & 0x0f,
    273 			(ap[1] >> 4) & 0x0f, ap[0] & 0x0f, (ap[0] >> 4) & 0x0f);
    274 		RUNTIME_CHECK(result < sizeof(buf));
    275 		break;
    276 	default:
    277 		UNREACHABLE();
    278 	}
    279 	isc_buffer_init(&b, buf, strlen(buf));
    280 	isc_buffer_add(&b, strlen(buf));
    281 	result = dns_name_fromtext(stfself, &b, dns_rootname, 0, NULL);
    282 	RUNTIME_CHECK(result == ISC_R_SUCCESS);
    283 }
    284 
    285 bool
    286 dns_ssutable_checkrules(dns_ssutable_t *table, const dns_name_t *signer,
    287 			const dns_name_t *name, const isc_netaddr_t *addr,
    288 			bool tcp, const dns_aclenv_t *env, dns_rdatatype_t type,
    289 			const dst_key_t *key) {
    290 	dns_ssurule_t *rule;
    291 	unsigned int i;
    292 	dns_fixedname_t fixed;
    293 	dns_name_t *wildcard;
    294 	dns_name_t *tcpself;
    295 	dns_name_t *stfself;
    296 	isc_result_t result;
    297 	int match;
    298 
    299 	REQUIRE(VALID_SSUTABLE(table));
    300 	REQUIRE(signer == NULL || dns_name_isabsolute(signer));
    301 	REQUIRE(dns_name_isabsolute(name));
    302 	REQUIRE(addr == NULL || env != NULL);
    303 
    304 	if (signer == NULL && addr == NULL) {
    305 		return (false);
    306 	}
    307 
    308 	for (rule = ISC_LIST_HEAD(table->rules); rule != NULL;
    309 	     rule = ISC_LIST_NEXT(rule, link))
    310 	{
    311 		switch (rule->matchtype) {
    312 		case dns_ssumatchtype_name:
    313 		case dns_ssumatchtype_local:
    314 		case dns_ssumatchtype_subdomain:
    315 		case dns_ssumatchtype_wildcard:
    316 		case dns_ssumatchtype_self:
    317 		case dns_ssumatchtype_selfsub:
    318 		case dns_ssumatchtype_selfwild:
    319 			if (signer == NULL) {
    320 				continue;
    321 			}
    322 			if (dns_name_iswildcard(rule->identity)) {
    323 				if (!dns_name_matcheswildcard(signer,
    324 							      rule->identity))
    325 				{
    326 					continue;
    327 				}
    328 			} else {
    329 				if (!dns_name_equal(signer, rule->identity)) {
    330 					continue;
    331 				}
    332 			}
    333 			break;
    334 		case dns_ssumatchtype_selfkrb5:
    335 		case dns_ssumatchtype_selfms:
    336 		case dns_ssumatchtype_selfsubkrb5:
    337 		case dns_ssumatchtype_selfsubms:
    338 		case dns_ssumatchtype_subdomainkrb5:
    339 		case dns_ssumatchtype_subdomainms:
    340 			if (signer == NULL) {
    341 				continue;
    342 			}
    343 			break;
    344 		case dns_ssumatchtype_tcpself:
    345 		case dns_ssumatchtype_6to4self:
    346 			if (!tcp || addr == NULL) {
    347 				continue;
    348 			}
    349 			break;
    350 		case dns_ssumatchtype_external:
    351 		case dns_ssumatchtype_dlz:
    352 			break;
    353 		}
    354 
    355 		switch (rule->matchtype) {
    356 		case dns_ssumatchtype_name:
    357 			if (!dns_name_equal(name, rule->name)) {
    358 				continue;
    359 			}
    360 			break;
    361 		case dns_ssumatchtype_subdomain:
    362 			if (!dns_name_issubdomain(name, rule->name)) {
    363 				continue;
    364 			}
    365 			break;
    366 		case dns_ssumatchtype_local:
    367 			if (addr == NULL) {
    368 				continue;
    369 			}
    370 			if (!dns_name_issubdomain(name, rule->name)) {
    371 				continue;
    372 			}
    373 			dns_acl_match(addr, NULL, env->localhost, NULL, &match,
    374 				      NULL);
    375 			if (match == 0) {
    376 				if (signer != NULL) {
    377 					isc_log_write(dns_lctx,
    378 						      DNS_LOGCATEGORY_GENERAL,
    379 						      DNS_LOGMODULE_SSU,
    380 						      ISC_LOG_WARNING,
    381 						      "update-policy local: "
    382 						      "match on session "
    383 						      "key not from "
    384 						      "localhost");
    385 				}
    386 				continue;
    387 			}
    388 			break;
    389 		case dns_ssumatchtype_wildcard:
    390 			if (!dns_name_matcheswildcard(name, rule->name)) {
    391 				continue;
    392 			}
    393 			break;
    394 		case dns_ssumatchtype_self:
    395 			if (!dns_name_equal(signer, name)) {
    396 				continue;
    397 			}
    398 			break;
    399 		case dns_ssumatchtype_selfsub:
    400 			if (!dns_name_issubdomain(name, signer)) {
    401 				continue;
    402 			}
    403 			break;
    404 		case dns_ssumatchtype_selfwild:
    405 			wildcard = dns_fixedname_initname(&fixed);
    406 			result = dns_name_concatenate(dns_wildcardname, signer,
    407 						      wildcard, NULL);
    408 			if (result != ISC_R_SUCCESS) {
    409 				continue;
    410 			}
    411 			if (!dns_name_matcheswildcard(name, wildcard)) {
    412 				continue;
    413 			}
    414 			break;
    415 		case dns_ssumatchtype_selfkrb5:
    416 			if (dst_gssapi_identitymatchesrealmkrb5(
    417 				    signer, name, rule->identity, false))
    418 			{
    419 				break;
    420 			}
    421 			continue;
    422 		case dns_ssumatchtype_selfms:
    423 			if (dst_gssapi_identitymatchesrealmms(
    424 				    signer, name, rule->identity, false))
    425 			{
    426 				break;
    427 			}
    428 			continue;
    429 		case dns_ssumatchtype_selfsubkrb5:
    430 			if (dst_gssapi_identitymatchesrealmkrb5(
    431 				    signer, name, rule->identity, true))
    432 			{
    433 				break;
    434 			}
    435 			continue;
    436 		case dns_ssumatchtype_selfsubms:
    437 			if (dst_gssapi_identitymatchesrealmms(
    438 				    signer, name, rule->identity, true))
    439 			{
    440 				break;
    441 			}
    442 			continue;
    443 		case dns_ssumatchtype_subdomainkrb5:
    444 			if (!dns_name_issubdomain(name, rule->name)) {
    445 				continue;
    446 			}
    447 			if (dst_gssapi_identitymatchesrealmkrb5(
    448 				    signer, NULL, rule->identity, false))
    449 			{
    450 				break;
    451 			}
    452 			continue;
    453 		case dns_ssumatchtype_subdomainms:
    454 			if (!dns_name_issubdomain(name, rule->name)) {
    455 				continue;
    456 			}
    457 			if (dst_gssapi_identitymatchesrealmms(
    458 				    signer, NULL, rule->identity, false))
    459 			{
    460 				break;
    461 			}
    462 			continue;
    463 		case dns_ssumatchtype_tcpself:
    464 			tcpself = dns_fixedname_initname(&fixed);
    465 			reverse_from_address(tcpself, addr);
    466 			if (dns_name_iswildcard(rule->identity)) {
    467 				if (!dns_name_matcheswildcard(tcpself,
    468 							      rule->identity))
    469 				{
    470 					continue;
    471 				}
    472 			} else {
    473 				if (!dns_name_equal(tcpself, rule->identity)) {
    474 					continue;
    475 				}
    476 			}
    477 			if (!dns_name_equal(tcpself, name)) {
    478 				continue;
    479 			}
    480 			break;
    481 		case dns_ssumatchtype_6to4self:
    482 			stfself = dns_fixedname_initname(&fixed);
    483 			stf_from_address(stfself, addr);
    484 			if (dns_name_iswildcard(rule->identity)) {
    485 				if (!dns_name_matcheswildcard(stfself,
    486 							      rule->identity))
    487 				{
    488 					continue;
    489 				}
    490 			} else {
    491 				if (!dns_name_equal(stfself, rule->identity)) {
    492 					continue;
    493 				}
    494 			}
    495 			if (!dns_name_equal(stfself, name)) {
    496 				continue;
    497 			}
    498 			break;
    499 		case dns_ssumatchtype_external:
    500 			if (!dns_ssu_external_match(rule->identity, signer,
    501 						    name, addr, type, key,
    502 						    table->mctx))
    503 			{
    504 				continue;
    505 			}
    506 			break;
    507 		case dns_ssumatchtype_dlz:
    508 			if (!dns_dlz_ssumatch(table->dlzdatabase, signer, name,
    509 					      addr, type, key))
    510 			{
    511 				continue;
    512 			}
    513 			break;
    514 		}
    515 
    516 		if (rule->ntypes == 0) {
    517 			/*
    518 			 * If this is a DLZ rule, then the DLZ ssu
    519 			 * checks will have already checked
    520 			 * the type.
    521 			 */
    522 			if (rule->matchtype != dns_ssumatchtype_dlz &&
    523 			    !isusertype(type))
    524 			{
    525 				continue;
    526 			}
    527 		} else {
    528 			for (i = 0; i < rule->ntypes; i++) {
    529 				if (rule->types[i] == dns_rdatatype_any ||
    530 				    rule->types[i] == type)
    531 				{
    532 					break;
    533 				}
    534 			}
    535 			if (i == rule->ntypes) {
    536 				continue;
    537 			}
    538 		}
    539 		return (rule->grant);
    540 	}
    541 
    542 	return (false);
    543 }
    544 
    545 bool
    546 dns_ssurule_isgrant(const dns_ssurule_t *rule) {
    547 	REQUIRE(VALID_SSURULE(rule));
    548 	return (rule->grant);
    549 }
    550 
    551 dns_name_t *
    552 dns_ssurule_identity(const dns_ssurule_t *rule) {
    553 	REQUIRE(VALID_SSURULE(rule));
    554 	return (rule->identity);
    555 }
    556 
    557 unsigned int
    558 dns_ssurule_matchtype(const dns_ssurule_t *rule) {
    559 	REQUIRE(VALID_SSURULE(rule));
    560 	return (rule->matchtype);
    561 }
    562 
    563 dns_name_t *
    564 dns_ssurule_name(const dns_ssurule_t *rule) {
    565 	REQUIRE(VALID_SSURULE(rule));
    566 	return (rule->name);
    567 }
    568 
    569 unsigned int
    570 dns_ssurule_types(const dns_ssurule_t *rule, dns_rdatatype_t **types) {
    571 	REQUIRE(VALID_SSURULE(rule));
    572 	REQUIRE(types != NULL && *types != NULL);
    573 	*types = rule->types;
    574 	return (rule->ntypes);
    575 }
    576 
    577 isc_result_t
    578 dns_ssutable_firstrule(const dns_ssutable_t *table, dns_ssurule_t **rule) {
    579 	REQUIRE(VALID_SSUTABLE(table));
    580 	REQUIRE(rule != NULL && *rule == NULL);
    581 	*rule = ISC_LIST_HEAD(table->rules);
    582 	return (*rule != NULL ? ISC_R_SUCCESS : ISC_R_NOMORE);
    583 }
    584 
    585 isc_result_t
    586 dns_ssutable_nextrule(dns_ssurule_t *rule, dns_ssurule_t **nextrule) {
    587 	REQUIRE(VALID_SSURULE(rule));
    588 	REQUIRE(nextrule != NULL && *nextrule == NULL);
    589 	*nextrule = ISC_LIST_NEXT(rule, link);
    590 	return (*nextrule != NULL ? ISC_R_SUCCESS : ISC_R_NOMORE);
    591 }
    592 
    593 /*
    594  * Create a specialised SSU table that points at an external DLZ database
    595  */
    596 isc_result_t
    597 dns_ssutable_createdlz(isc_mem_t *mctx, dns_ssutable_t **tablep,
    598 		       dns_dlzdb_t *dlzdatabase) {
    599 	isc_result_t result;
    600 	dns_ssurule_t *rule;
    601 	dns_ssutable_t *table = NULL;
    602 
    603 	REQUIRE(tablep != NULL && *tablep == NULL);
    604 
    605 	result = dns_ssutable_create(mctx, &table);
    606 	if (result != ISC_R_SUCCESS) {
    607 		return (result);
    608 	}
    609 
    610 	table->dlzdatabase = dlzdatabase;
    611 
    612 	rule = isc_mem_get(table->mctx, sizeof(dns_ssurule_t));
    613 
    614 	rule->identity = NULL;
    615 	rule->name = NULL;
    616 	rule->types = NULL;
    617 	rule->grant = true;
    618 	rule->matchtype = dns_ssumatchtype_dlz;
    619 	rule->ntypes = 0;
    620 	rule->types = NULL;
    621 	rule->magic = SSURULEMAGIC;
    622 
    623 	ISC_LIST_INITANDAPPEND(table->rules, rule, link);
    624 	*tablep = table;
    625 	return (ISC_R_SUCCESS);
    626 }
    627 
    628 isc_result_t
    629 dns_ssu_mtypefromstring(const char *str, dns_ssumatchtype_t *mtype) {
    630 	REQUIRE(str != NULL);
    631 	REQUIRE(mtype != NULL);
    632 
    633 	if (strcasecmp(str, "name") == 0) {
    634 		*mtype = dns_ssumatchtype_name;
    635 	} else if (strcasecmp(str, "subdomain") == 0) {
    636 		*mtype = dns_ssumatchtype_subdomain;
    637 	} else if (strcasecmp(str, "wildcard") == 0) {
    638 		*mtype = dns_ssumatchtype_wildcard;
    639 	} else if (strcasecmp(str, "self") == 0) {
    640 		*mtype = dns_ssumatchtype_self;
    641 	} else if (strcasecmp(str, "selfsub") == 0) {
    642 		*mtype = dns_ssumatchtype_selfsub;
    643 	} else if (strcasecmp(str, "selfwild") == 0) {
    644 		*mtype = dns_ssumatchtype_selfwild;
    645 	} else if (strcasecmp(str, "ms-self") == 0) {
    646 		*mtype = dns_ssumatchtype_selfms;
    647 	} else if (strcasecmp(str, "ms-selfsub") == 0) {
    648 		*mtype = dns_ssumatchtype_selfsubms;
    649 	} else if (strcasecmp(str, "krb5-self") == 0) {
    650 		*mtype = dns_ssumatchtype_selfkrb5;
    651 	} else if (strcasecmp(str, "krb5-selfsub") == 0) {
    652 		*mtype = dns_ssumatchtype_selfsubkrb5;
    653 	} else if (strcasecmp(str, "ms-subdomain") == 0) {
    654 		*mtype = dns_ssumatchtype_subdomainms;
    655 	} else if (strcasecmp(str, "krb5-subdomain") == 0) {
    656 		*mtype = dns_ssumatchtype_subdomainkrb5;
    657 	} else if (strcasecmp(str, "tcp-self") == 0) {
    658 		*mtype = dns_ssumatchtype_tcpself;
    659 	} else if (strcasecmp(str, "6to4-self") == 0) {
    660 		*mtype = dns_ssumatchtype_6to4self;
    661 	} else if (strcasecmp(str, "zonesub") == 0) {
    662 		*mtype = dns_ssumatchtype_subdomain;
    663 	} else if (strcasecmp(str, "external") == 0) {
    664 		*mtype = dns_ssumatchtype_external;
    665 	} else {
    666 		return (ISC_R_NOTFOUND);
    667 	}
    668 	return (ISC_R_SUCCESS);
    669 }
    670