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