1135446Strhodes/* 2262706Serwin * Copyright (C) 2004-2008, 2010, 2011, 2013, 2014 Internet Systems Consortium, Inc. ("ISC") 3135446Strhodes * Copyright (C) 2000, 2001, 2003 Internet Software Consortium. 4135446Strhodes * 5193149Sdougb * Permission to use, copy, modify, and/or distribute this software for any 6135446Strhodes * purpose with or without fee is hereby granted, provided that the above 7135446Strhodes * copyright notice and this permission notice appear in all copies. 8135446Strhodes * 9135446Strhodes * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10135446Strhodes * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11135446Strhodes * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12135446Strhodes * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13135446Strhodes * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14135446Strhodes * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15135446Strhodes * PERFORMANCE OF THIS SOFTWARE. 16135446Strhodes */ 17135446Strhodes 18170222Sdougb/*! \file */ 19135446Strhodes/* 20234010Sdougb * $Id: ssu.c,v 1.38 2011/01/06 23:47:00 tbox Exp $ 21135446Strhodes * Principal Author: Brian Wellington 22135446Strhodes */ 23135446Strhodes 24135446Strhodes#include <config.h> 25135446Strhodes 26135446Strhodes#include <isc/magic.h> 27135446Strhodes#include <isc/mem.h> 28193149Sdougb#include <isc/netaddr.h> 29170222Sdougb#include <isc/result.h> 30193149Sdougb#include <isc/string.h> 31135446Strhodes#include <isc/util.h> 32135446Strhodes 33224092Sdougb#include <dns/dlz.h> 34170222Sdougb#include <dns/fixedname.h> 35135446Strhodes#include <dns/name.h> 36135446Strhodes#include <dns/ssu.h> 37135446Strhodes 38193149Sdougb#include <dst/gssapi.h> 39224092Sdougb#include <dst/dst.h> 40193149Sdougb 41135446Strhodes#define SSUTABLEMAGIC ISC_MAGIC('S', 'S', 'U', 'T') 42135446Strhodes#define VALID_SSUTABLE(table) ISC_MAGIC_VALID(table, SSUTABLEMAGIC) 43135446Strhodes 44135446Strhodes#define SSURULEMAGIC ISC_MAGIC('S', 'S', 'U', 'R') 45135446Strhodes#define VALID_SSURULE(table) ISC_MAGIC_VALID(table, SSURULEMAGIC) 46135446Strhodes 47135446Strhodesstruct dns_ssurule { 48135446Strhodes unsigned int magic; 49170222Sdougb isc_boolean_t grant; /*%< is this a grant or a deny? */ 50170222Sdougb unsigned int matchtype; /*%< which type of pattern match? */ 51170222Sdougb dns_name_t *identity; /*%< the identity to match */ 52170222Sdougb dns_name_t *name; /*%< the name being updated */ 53170222Sdougb unsigned int ntypes; /*%< number of data types covered */ 54170222Sdougb dns_rdatatype_t *types; /*%< the data types. Can include ANY, */ 55170222Sdougb /*%< defaults to all but SIG,SOA,NS if NULL */ 56135446Strhodes ISC_LINK(dns_ssurule_t) link; 57135446Strhodes}; 58135446Strhodes 59135446Strhodesstruct dns_ssutable { 60135446Strhodes unsigned int magic; 61135446Strhodes isc_mem_t *mctx; 62135446Strhodes unsigned int references; 63135446Strhodes isc_mutex_t lock; 64224092Sdougb dns_dlzdb_t *dlzdatabase; 65135446Strhodes ISC_LIST(dns_ssurule_t) rules; 66135446Strhodes}; 67135446Strhodes 68135446Strhodesisc_result_t 69135446Strhodesdns_ssutable_create(isc_mem_t *mctx, dns_ssutable_t **tablep) { 70135446Strhodes isc_result_t result; 71135446Strhodes dns_ssutable_t *table; 72135446Strhodes 73135446Strhodes REQUIRE(tablep != NULL && *tablep == NULL); 74135446Strhodes REQUIRE(mctx != NULL); 75135446Strhodes 76135446Strhodes table = isc_mem_get(mctx, sizeof(dns_ssutable_t)); 77135446Strhodes if (table == NULL) 78135446Strhodes return (ISC_R_NOMEMORY); 79135446Strhodes result = isc_mutex_init(&table->lock); 80135446Strhodes if (result != ISC_R_SUCCESS) { 81135446Strhodes isc_mem_put(mctx, table, sizeof(dns_ssutable_t)); 82135446Strhodes return (result); 83135446Strhodes } 84135446Strhodes table->references = 1; 85254402Serwin table->mctx = NULL; 86254402Serwin isc_mem_attach(mctx, &table->mctx); 87135446Strhodes ISC_LIST_INIT(table->rules); 88135446Strhodes table->magic = SSUTABLEMAGIC; 89135446Strhodes *tablep = table; 90135446Strhodes return (ISC_R_SUCCESS); 91135446Strhodes} 92135446Strhodes 93135446Strhodesstatic inline void 94135446Strhodesdestroy(dns_ssutable_t *table) { 95135446Strhodes isc_mem_t *mctx; 96135446Strhodes 97135446Strhodes REQUIRE(VALID_SSUTABLE(table)); 98135446Strhodes 99135446Strhodes mctx = table->mctx; 100135446Strhodes while (!ISC_LIST_EMPTY(table->rules)) { 101135446Strhodes dns_ssurule_t *rule = ISC_LIST_HEAD(table->rules); 102135446Strhodes if (rule->identity != NULL) { 103135446Strhodes dns_name_free(rule->identity, mctx); 104135446Strhodes isc_mem_put(mctx, rule->identity, sizeof(dns_name_t)); 105135446Strhodes } 106135446Strhodes if (rule->name != NULL) { 107135446Strhodes dns_name_free(rule->name, mctx); 108135446Strhodes isc_mem_put(mctx, rule->name, sizeof(dns_name_t)); 109135446Strhodes } 110135446Strhodes if (rule->types != NULL) 111135446Strhodes isc_mem_put(mctx, rule->types, 112135446Strhodes rule->ntypes * sizeof(dns_rdatatype_t)); 113135446Strhodes ISC_LIST_UNLINK(table->rules, rule, link); 114135446Strhodes rule->magic = 0; 115135446Strhodes isc_mem_put(mctx, rule, sizeof(dns_ssurule_t)); 116135446Strhodes } 117135446Strhodes DESTROYLOCK(&table->lock); 118135446Strhodes table->magic = 0; 119254402Serwin isc_mem_putanddetach(&table->mctx, table, sizeof(dns_ssutable_t)); 120135446Strhodes} 121135446Strhodes 122135446Strhodesvoid 123135446Strhodesdns_ssutable_attach(dns_ssutable_t *source, dns_ssutable_t **targetp) { 124135446Strhodes REQUIRE(VALID_SSUTABLE(source)); 125135446Strhodes REQUIRE(targetp != NULL && *targetp == NULL); 126135446Strhodes 127135446Strhodes LOCK(&source->lock); 128135446Strhodes 129135446Strhodes INSIST(source->references > 0); 130135446Strhodes source->references++; 131135446Strhodes INSIST(source->references != 0); 132135446Strhodes 133135446Strhodes UNLOCK(&source->lock); 134135446Strhodes 135135446Strhodes *targetp = source; 136135446Strhodes} 137135446Strhodes 138135446Strhodesvoid 139135446Strhodesdns_ssutable_detach(dns_ssutable_t **tablep) { 140135446Strhodes dns_ssutable_t *table; 141135446Strhodes isc_boolean_t done = ISC_FALSE; 142135446Strhodes 143135446Strhodes REQUIRE(tablep != NULL); 144135446Strhodes table = *tablep; 145135446Strhodes REQUIRE(VALID_SSUTABLE(table)); 146135446Strhodes 147135446Strhodes LOCK(&table->lock); 148135446Strhodes 149135446Strhodes INSIST(table->references > 0); 150135446Strhodes if (--table->references == 0) 151135446Strhodes done = ISC_TRUE; 152135446Strhodes UNLOCK(&table->lock); 153135446Strhodes 154135446Strhodes *tablep = NULL; 155135446Strhodes 156135446Strhodes if (done) 157135446Strhodes destroy(table); 158135446Strhodes} 159135446Strhodes 160135446Strhodesisc_result_t 161135446Strhodesdns_ssutable_addrule(dns_ssutable_t *table, isc_boolean_t grant, 162135446Strhodes dns_name_t *identity, unsigned int matchtype, 163135446Strhodes dns_name_t *name, unsigned int ntypes, 164135446Strhodes dns_rdatatype_t *types) 165135446Strhodes{ 166135446Strhodes dns_ssurule_t *rule; 167135446Strhodes isc_mem_t *mctx; 168135446Strhodes isc_result_t result; 169135446Strhodes 170135446Strhodes REQUIRE(VALID_SSUTABLE(table)); 171135446Strhodes REQUIRE(dns_name_isabsolute(identity)); 172135446Strhodes REQUIRE(dns_name_isabsolute(name)); 173170222Sdougb REQUIRE(matchtype <= DNS_SSUMATCHTYPE_MAX); 174135446Strhodes if (matchtype == DNS_SSUMATCHTYPE_WILDCARD) 175135446Strhodes REQUIRE(dns_name_iswildcard(name)); 176135446Strhodes if (ntypes > 0) 177135446Strhodes REQUIRE(types != NULL); 178135446Strhodes 179135446Strhodes mctx = table->mctx; 180135446Strhodes rule = isc_mem_get(mctx, sizeof(dns_ssurule_t)); 181135446Strhodes if (rule == NULL) 182135446Strhodes return (ISC_R_NOMEMORY); 183135446Strhodes 184135446Strhodes rule->identity = NULL; 185135446Strhodes rule->name = NULL; 186135446Strhodes rule->types = NULL; 187135446Strhodes 188135446Strhodes rule->grant = grant; 189135446Strhodes 190135446Strhodes rule->identity = isc_mem_get(mctx, sizeof(dns_name_t)); 191135446Strhodes if (rule->identity == NULL) { 192135446Strhodes result = ISC_R_NOMEMORY; 193135446Strhodes goto failure; 194135446Strhodes } 195135446Strhodes dns_name_init(rule->identity, NULL); 196135446Strhodes result = dns_name_dup(identity, mctx, rule->identity); 197135446Strhodes if (result != ISC_R_SUCCESS) 198135446Strhodes goto failure; 199135446Strhodes 200135446Strhodes rule->name = isc_mem_get(mctx, sizeof(dns_name_t)); 201135446Strhodes if (rule->name == NULL) { 202135446Strhodes result = ISC_R_NOMEMORY; 203135446Strhodes goto failure; 204135446Strhodes } 205135446Strhodes dns_name_init(rule->name, NULL); 206135446Strhodes result = dns_name_dup(name, mctx, rule->name); 207135446Strhodes if (result != ISC_R_SUCCESS) 208135446Strhodes goto failure; 209135446Strhodes 210135446Strhodes rule->matchtype = matchtype; 211135446Strhodes 212135446Strhodes rule->ntypes = ntypes; 213135446Strhodes if (ntypes > 0) { 214135446Strhodes rule->types = isc_mem_get(mctx, 215135446Strhodes ntypes * sizeof(dns_rdatatype_t)); 216135446Strhodes if (rule->types == NULL) { 217135446Strhodes result = ISC_R_NOMEMORY; 218135446Strhodes goto failure; 219135446Strhodes } 220262706Serwin memmove(rule->types, types, ntypes * sizeof(dns_rdatatype_t)); 221170222Sdougb } else 222135446Strhodes rule->types = NULL; 223135446Strhodes 224135446Strhodes rule->magic = SSURULEMAGIC; 225135446Strhodes ISC_LIST_INITANDAPPEND(table->rules, rule, link); 226135446Strhodes 227135446Strhodes return (ISC_R_SUCCESS); 228135446Strhodes 229135446Strhodes failure: 230135446Strhodes if (rule->identity != NULL) { 231135446Strhodes if (dns_name_dynamic(rule->identity)) 232135446Strhodes dns_name_free(rule->identity, mctx); 233135446Strhodes isc_mem_put(mctx, rule->identity, sizeof(dns_name_t)); 234135446Strhodes } 235135446Strhodes if (rule->name != NULL) { 236135446Strhodes if (dns_name_dynamic(rule->name)) 237135446Strhodes dns_name_free(rule->name, mctx); 238135446Strhodes isc_mem_put(mctx, rule->name, sizeof(dns_name_t)); 239135446Strhodes } 240135446Strhodes if (rule->types != NULL) 241135446Strhodes isc_mem_put(mctx, rule->types, 242135446Strhodes ntypes * sizeof(dns_rdatatype_t)); 243135446Strhodes isc_mem_put(mctx, rule, sizeof(dns_ssurule_t)); 244135446Strhodes 245135446Strhodes return (result); 246135446Strhodes} 247135446Strhodes 248135446Strhodesstatic inline isc_boolean_t 249135446Strhodesisusertype(dns_rdatatype_t type) { 250135446Strhodes return (ISC_TF(type != dns_rdatatype_ns && 251135446Strhodes type != dns_rdatatype_soa && 252135446Strhodes type != dns_rdatatype_rrsig)); 253135446Strhodes} 254135446Strhodes 255193149Sdougbstatic void 256193149Sdougbreverse_from_address(dns_name_t *tcpself, isc_netaddr_t *tcpaddr) { 257193149Sdougb char buf[16 * 4 + sizeof("IP6.ARPA.")]; 258193149Sdougb isc_result_t result; 259193149Sdougb unsigned char *ap; 260193149Sdougb isc_buffer_t b; 261193149Sdougb unsigned long l; 262193149Sdougb 263193149Sdougb switch (tcpaddr->family) { 264193149Sdougb case AF_INET: 265193149Sdougb l = ntohl(tcpaddr->type.in.s_addr); 266193149Sdougb result = isc_string_printf(buf, sizeof(buf), 267193149Sdougb "%lu.%lu.%lu.%lu.IN-ADDR.ARPA.", 268193149Sdougb (l >> 0) & 0xff, (l >> 8) & 0xff, 269193149Sdougb (l >> 16) & 0xff, (l >> 24) & 0xff); 270193149Sdougb RUNTIME_CHECK(result == ISC_R_SUCCESS); 271193149Sdougb break; 272193149Sdougb case AF_INET6: 273193149Sdougb ap = tcpaddr->type.in6.s6_addr; 274193149Sdougb result = isc_string_printf(buf, sizeof(buf), 275193149Sdougb "%x.%x.%x.%x.%x.%x.%x.%x." 276193149Sdougb "%x.%x.%x.%x.%x.%x.%x.%x." 277193149Sdougb "%x.%x.%x.%x.%x.%x.%x.%x." 278193149Sdougb "%x.%x.%x.%x.%x.%x.%x.%x." 279193149Sdougb "IP6.ARPA.", 280193149Sdougb ap[15] & 0x0f, (ap[15] >> 4) & 0x0f, 281193149Sdougb ap[14] & 0x0f, (ap[14] >> 4) & 0x0f, 282193149Sdougb ap[13] & 0x0f, (ap[13] >> 4) & 0x0f, 283193149Sdougb ap[12] & 0x0f, (ap[12] >> 4) & 0x0f, 284193149Sdougb ap[11] & 0x0f, (ap[11] >> 4) & 0x0f, 285193149Sdougb ap[10] & 0x0f, (ap[10] >> 4) & 0x0f, 286193149Sdougb ap[9] & 0x0f, (ap[9] >> 4) & 0x0f, 287193149Sdougb ap[8] & 0x0f, (ap[8] >> 4) & 0x0f, 288193149Sdougb ap[7] & 0x0f, (ap[7] >> 4) & 0x0f, 289193149Sdougb ap[6] & 0x0f, (ap[6] >> 4) & 0x0f, 290193149Sdougb ap[5] & 0x0f, (ap[5] >> 4) & 0x0f, 291193149Sdougb ap[4] & 0x0f, (ap[4] >> 4) & 0x0f, 292193149Sdougb ap[3] & 0x0f, (ap[3] >> 4) & 0x0f, 293193149Sdougb ap[2] & 0x0f, (ap[2] >> 4) & 0x0f, 294193149Sdougb ap[1] & 0x0f, (ap[1] >> 4) & 0x0f, 295193149Sdougb ap[0] & 0x0f, (ap[0] >> 4) & 0x0f); 296193149Sdougb RUNTIME_CHECK(result == ISC_R_SUCCESS); 297193149Sdougb break; 298193149Sdougb default: 299193149Sdougb INSIST(0); 300193149Sdougb } 301193149Sdougb isc_buffer_init(&b, buf, strlen(buf)); 302193149Sdougb isc_buffer_add(&b, strlen(buf)); 303193149Sdougb result = dns_name_fromtext(tcpself, &b, dns_rootname, 0, NULL); 304193149Sdougb RUNTIME_CHECK(result == ISC_R_SUCCESS); 305193149Sdougb} 306193149Sdougb 307193149Sdougbstatic void 308193149Sdougbstf_from_address(dns_name_t *stfself, isc_netaddr_t *tcpaddr) { 309193149Sdougb char buf[sizeof("X.X.X.X.Y.Y.Y.Y.2.0.0.2.IP6.ARPA.")]; 310193149Sdougb isc_result_t result; 311193149Sdougb unsigned char *ap; 312193149Sdougb isc_buffer_t b; 313193149Sdougb unsigned long l; 314193149Sdougb 315193149Sdougb switch(tcpaddr->family) { 316193149Sdougb case AF_INET: 317193149Sdougb l = ntohl(tcpaddr->type.in.s_addr); 318193149Sdougb result = isc_string_printf(buf, sizeof(buf), 319193149Sdougb "%lx.%lx.%lx.%lx.%lx.%lx.%lx.%lx" 320193149Sdougb "2.0.0.2.IP6.ARPA.", 321193149Sdougb l & 0xf, (l >> 4) & 0xf, 322193149Sdougb (l >> 8) & 0xf, (l >> 12) & 0xf, 323193149Sdougb (l >> 16) & 0xf, (l >> 20) & 0xf, 324193149Sdougb (l >> 24) & 0xf, (l >> 28) & 0xf); 325193149Sdougb RUNTIME_CHECK(result == ISC_R_SUCCESS); 326193149Sdougb break; 327193149Sdougb case AF_INET6: 328193149Sdougb ap = tcpaddr->type.in6.s6_addr; 329193149Sdougb result = isc_string_printf(buf, sizeof(buf), 330193149Sdougb "%x.%x.%x.%x.%x.%x.%x.%x." 331193149Sdougb "%x.%x.%x.%x.IP6.ARPA.", 332193149Sdougb ap[5] & 0x0f, (ap[5] >> 4) & 0x0f, 333193149Sdougb ap[4] & 0x0f, (ap[4] >> 4) & 0x0f, 334193149Sdougb ap[3] & 0x0f, (ap[3] >> 4) & 0x0f, 335193149Sdougb ap[2] & 0x0f, (ap[2] >> 4) & 0x0f, 336193149Sdougb ap[1] & 0x0f, (ap[1] >> 4) & 0x0f, 337193149Sdougb ap[0] & 0x0f, (ap[0] >> 4) & 0x0f); 338193149Sdougb RUNTIME_CHECK(result == ISC_R_SUCCESS); 339193149Sdougb break; 340193149Sdougb default: 341193149Sdougb INSIST(0); 342193149Sdougb } 343193149Sdougb isc_buffer_init(&b, buf, strlen(buf)); 344193149Sdougb isc_buffer_add(&b, strlen(buf)); 345193149Sdougb result = dns_name_fromtext(stfself, &b, dns_rootname, 0, NULL); 346193149Sdougb RUNTIME_CHECK(result == ISC_R_SUCCESS); 347193149Sdougb} 348193149Sdougb 349135446Strhodesisc_boolean_t 350135446Strhodesdns_ssutable_checkrules(dns_ssutable_t *table, dns_name_t *signer, 351193149Sdougb dns_name_t *name, isc_netaddr_t *tcpaddr, 352224092Sdougb dns_rdatatype_t type, 353224092Sdougb const dst_key_t *key) 354135446Strhodes{ 355135446Strhodes dns_ssurule_t *rule; 356135446Strhodes unsigned int i; 357170222Sdougb dns_fixedname_t fixed; 358170222Sdougb dns_name_t *wildcard; 359193149Sdougb dns_name_t *tcpself; 360193149Sdougb dns_name_t *stfself; 361170222Sdougb isc_result_t result; 362135446Strhodes 363135446Strhodes REQUIRE(VALID_SSUTABLE(table)); 364135446Strhodes REQUIRE(signer == NULL || dns_name_isabsolute(signer)); 365135446Strhodes REQUIRE(dns_name_isabsolute(name)); 366135446Strhodes 367193149Sdougb if (signer == NULL && tcpaddr == NULL) 368135446Strhodes return (ISC_FALSE); 369193149Sdougb 370135446Strhodes for (rule = ISC_LIST_HEAD(table->rules); 371135446Strhodes rule != NULL; 372135446Strhodes rule = ISC_LIST_NEXT(rule, link)) 373135446Strhodes { 374193149Sdougb switch (rule->matchtype) { 375193149Sdougb case DNS_SSUMATCHTYPE_NAME: 376193149Sdougb case DNS_SSUMATCHTYPE_SUBDOMAIN: 377193149Sdougb case DNS_SSUMATCHTYPE_WILDCARD: 378193149Sdougb case DNS_SSUMATCHTYPE_SELF: 379193149Sdougb case DNS_SSUMATCHTYPE_SELFSUB: 380193149Sdougb case DNS_SSUMATCHTYPE_SELFWILD: 381193149Sdougb if (signer == NULL) 382135446Strhodes continue; 383193149Sdougb if (dns_name_iswildcard(rule->identity)) { 384193149Sdougb if (!dns_name_matcheswildcard(signer, 385193149Sdougb rule->identity)) 386193149Sdougb continue; 387193149Sdougb } else { 388193149Sdougb if (!dns_name_equal(signer, rule->identity)) 389193149Sdougb continue; 390193149Sdougb } 391193149Sdougb break; 392193149Sdougb case DNS_SSUMATCHTYPE_SELFKRB5: 393193149Sdougb case DNS_SSUMATCHTYPE_SELFMS: 394193149Sdougb case DNS_SSUMATCHTYPE_SUBDOMAINKRB5: 395193149Sdougb case DNS_SSUMATCHTYPE_SUBDOMAINMS: 396193149Sdougb if (signer == NULL) 397135446Strhodes continue; 398193149Sdougb break; 399193149Sdougb case DNS_SSUMATCHTYPE_TCPSELF: 400193149Sdougb case DNS_SSUMATCHTYPE_6TO4SELF: 401193149Sdougb if (tcpaddr == NULL) 402193149Sdougb continue; 403193149Sdougb break; 404193149Sdougb } 405135446Strhodes 406193149Sdougb switch (rule->matchtype) { 407193149Sdougb case DNS_SSUMATCHTYPE_NAME: 408135446Strhodes if (!dns_name_equal(name, rule->name)) 409135446Strhodes continue; 410193149Sdougb break; 411193149Sdougb case DNS_SSUMATCHTYPE_SUBDOMAIN: 412135446Strhodes if (!dns_name_issubdomain(name, rule->name)) 413135446Strhodes continue; 414193149Sdougb break; 415193149Sdougb case DNS_SSUMATCHTYPE_WILDCARD: 416135446Strhodes if (!dns_name_matcheswildcard(name, rule->name)) 417135446Strhodes continue; 418193149Sdougb break; 419193149Sdougb case DNS_SSUMATCHTYPE_SELF: 420135446Strhodes if (!dns_name_equal(signer, name)) 421135446Strhodes continue; 422193149Sdougb break; 423193149Sdougb case DNS_SSUMATCHTYPE_SELFSUB: 424170222Sdougb if (!dns_name_issubdomain(name, signer)) 425170222Sdougb continue; 426193149Sdougb break; 427193149Sdougb case DNS_SSUMATCHTYPE_SELFWILD: 428170222Sdougb dns_fixedname_init(&fixed); 429170222Sdougb wildcard = dns_fixedname_name(&fixed); 430170222Sdougb result = dns_name_concatenate(dns_wildcardname, signer, 431170222Sdougb wildcard, NULL); 432170222Sdougb if (result != ISC_R_SUCCESS) 433170222Sdougb continue; 434170222Sdougb if (!dns_name_matcheswildcard(name, wildcard)) 435170222Sdougb continue; 436193149Sdougb break; 437193149Sdougb case DNS_SSUMATCHTYPE_SELFKRB5: 438193149Sdougb if (!dst_gssapi_identitymatchesrealmkrb5(signer, name, 439193149Sdougb rule->identity)) 440193149Sdougb continue; 441193149Sdougb break; 442193149Sdougb case DNS_SSUMATCHTYPE_SELFMS: 443193149Sdougb if (!dst_gssapi_identitymatchesrealmms(signer, name, 444193149Sdougb rule->identity)) 445193149Sdougb continue; 446193149Sdougb break; 447193149Sdougb case DNS_SSUMATCHTYPE_SUBDOMAINKRB5: 448193149Sdougb if (!dns_name_issubdomain(name, rule->name)) 449193149Sdougb continue; 450193149Sdougb if (!dst_gssapi_identitymatchesrealmkrb5(signer, NULL, 451193149Sdougb rule->identity)) 452193149Sdougb continue; 453193149Sdougb break; 454193149Sdougb case DNS_SSUMATCHTYPE_SUBDOMAINMS: 455193149Sdougb if (!dns_name_issubdomain(name, rule->name)) 456193149Sdougb continue; 457193149Sdougb if (!dst_gssapi_identitymatchesrealmms(signer, NULL, 458193149Sdougb rule->identity)) 459193149Sdougb continue; 460193149Sdougb break; 461193149Sdougb case DNS_SSUMATCHTYPE_TCPSELF: 462193149Sdougb dns_fixedname_init(&fixed); 463193149Sdougb tcpself = dns_fixedname_name(&fixed); 464193149Sdougb reverse_from_address(tcpself, tcpaddr); 465193149Sdougb if (dns_name_iswildcard(rule->identity)) { 466193149Sdougb if (!dns_name_matcheswildcard(tcpself, 467193149Sdougb rule->identity)) 468193149Sdougb continue; 469193149Sdougb } else { 470193149Sdougb if (!dns_name_equal(tcpself, rule->identity)) 471193149Sdougb continue; 472193149Sdougb } 473193149Sdougb if (!dns_name_equal(tcpself, name)) 474193149Sdougb continue; 475193149Sdougb break; 476193149Sdougb case DNS_SSUMATCHTYPE_6TO4SELF: 477193149Sdougb dns_fixedname_init(&fixed); 478193149Sdougb stfself = dns_fixedname_name(&fixed); 479193149Sdougb stf_from_address(stfself, tcpaddr); 480193149Sdougb if (dns_name_iswildcard(rule->identity)) { 481193149Sdougb if (!dns_name_matcheswildcard(stfself, 482193149Sdougb rule->identity)) 483193149Sdougb continue; 484193149Sdougb } else { 485193149Sdougb if (!dns_name_equal(stfself, rule->identity)) 486193149Sdougb continue; 487193149Sdougb } 488193149Sdougb if (!dns_name_equal(stfself, name)) 489193149Sdougb continue; 490193149Sdougb break; 491224092Sdougb case DNS_SSUMATCHTYPE_EXTERNAL: 492224092Sdougb if (!dns_ssu_external_match(rule->identity, signer, 493224092Sdougb name, tcpaddr, type, key, 494224092Sdougb table->mctx)) 495224092Sdougb continue; 496224092Sdougb break; 497224092Sdougb case DNS_SSUMATCHTYPE_DLZ: 498224092Sdougb if (!dns_dlz_ssumatch(table->dlzdatabase, signer, 499224092Sdougb name, tcpaddr, type, key)) 500224092Sdougb continue; 501224092Sdougb break; 502135446Strhodes } 503135446Strhodes 504135446Strhodes if (rule->ntypes == 0) { 505224092Sdougb /* 506224092Sdougb * If this is a DLZ rule, then the DLZ ssu 507224092Sdougb * checks will have already checked 508224092Sdougb * the type. 509224092Sdougb */ 510224092Sdougb if (rule->matchtype != DNS_SSUMATCHTYPE_DLZ && 511224092Sdougb !isusertype(type)) 512135446Strhodes continue; 513170222Sdougb } else { 514135446Strhodes for (i = 0; i < rule->ntypes; i++) { 515135446Strhodes if (rule->types[i] == dns_rdatatype_any || 516135446Strhodes rule->types[i] == type) 517135446Strhodes break; 518135446Strhodes } 519135446Strhodes if (i == rule->ntypes) 520135446Strhodes continue; 521135446Strhodes } 522135446Strhodes return (rule->grant); 523135446Strhodes } 524135446Strhodes 525135446Strhodes return (ISC_FALSE); 526135446Strhodes} 527135446Strhodes 528135446Strhodesisc_boolean_t 529135446Strhodesdns_ssurule_isgrant(const dns_ssurule_t *rule) { 530135446Strhodes REQUIRE(VALID_SSURULE(rule)); 531135446Strhodes return (rule->grant); 532135446Strhodes} 533135446Strhodes 534135446Strhodesdns_name_t * 535135446Strhodesdns_ssurule_identity(const dns_ssurule_t *rule) { 536135446Strhodes REQUIRE(VALID_SSURULE(rule)); 537135446Strhodes return (rule->identity); 538135446Strhodes} 539135446Strhodes 540135446Strhodesunsigned int 541135446Strhodesdns_ssurule_matchtype(const dns_ssurule_t *rule) { 542135446Strhodes REQUIRE(VALID_SSURULE(rule)); 543135446Strhodes return (rule->matchtype); 544135446Strhodes} 545135446Strhodes 546135446Strhodesdns_name_t * 547135446Strhodesdns_ssurule_name(const dns_ssurule_t *rule) { 548135446Strhodes REQUIRE(VALID_SSURULE(rule)); 549135446Strhodes return (rule->name); 550135446Strhodes} 551135446Strhodes 552135446Strhodesunsigned int 553135446Strhodesdns_ssurule_types(const dns_ssurule_t *rule, dns_rdatatype_t **types) { 554135446Strhodes REQUIRE(VALID_SSURULE(rule)); 555135446Strhodes REQUIRE(types != NULL && *types != NULL); 556135446Strhodes *types = rule->types; 557135446Strhodes return (rule->ntypes); 558135446Strhodes} 559135446Strhodes 560135446Strhodesisc_result_t 561135446Strhodesdns_ssutable_firstrule(const dns_ssutable_t *table, dns_ssurule_t **rule) { 562135446Strhodes REQUIRE(VALID_SSUTABLE(table)); 563135446Strhodes REQUIRE(rule != NULL && *rule == NULL); 564135446Strhodes *rule = ISC_LIST_HEAD(table->rules); 565135446Strhodes return (*rule != NULL ? ISC_R_SUCCESS : ISC_R_NOMORE); 566135446Strhodes} 567135446Strhodes 568135446Strhodesisc_result_t 569135446Strhodesdns_ssutable_nextrule(dns_ssurule_t *rule, dns_ssurule_t **nextrule) { 570135446Strhodes REQUIRE(VALID_SSURULE(rule)); 571135446Strhodes REQUIRE(nextrule != NULL && *nextrule == NULL); 572135446Strhodes *nextrule = ISC_LIST_NEXT(rule, link); 573135446Strhodes return (*nextrule != NULL ? ISC_R_SUCCESS : ISC_R_NOMORE); 574135446Strhodes} 575224092Sdougb 576224092Sdougb/* 577224092Sdougb * Create a specialised SSU table that points at an external DLZ database 578224092Sdougb */ 579224092Sdougbisc_result_t 580224092Sdougbdns_ssutable_createdlz(isc_mem_t *mctx, dns_ssutable_t **tablep, 581224092Sdougb dns_dlzdb_t *dlzdatabase) 582224092Sdougb{ 583224092Sdougb isc_result_t result; 584224092Sdougb dns_ssurule_t *rule; 585224092Sdougb dns_ssutable_t *table = NULL; 586224092Sdougb 587224092Sdougb REQUIRE(tablep != NULL && *tablep == NULL); 588224092Sdougb 589224092Sdougb result = dns_ssutable_create(mctx, &table); 590224092Sdougb if (result != ISC_R_SUCCESS) 591224092Sdougb return (result); 592224092Sdougb 593224092Sdougb table->dlzdatabase = dlzdatabase; 594224092Sdougb 595224092Sdougb rule = isc_mem_get(table->mctx, sizeof(dns_ssurule_t)); 596224092Sdougb if (rule == NULL) { 597224092Sdougb dns_ssutable_detach(&table); 598224092Sdougb return (ISC_R_NOMEMORY); 599224092Sdougb } 600224092Sdougb 601224092Sdougb rule->identity = NULL; 602224092Sdougb rule->name = NULL; 603224092Sdougb rule->types = NULL; 604224092Sdougb rule->grant = ISC_TRUE; 605224092Sdougb rule->matchtype = DNS_SSUMATCHTYPE_DLZ; 606224092Sdougb rule->ntypes = 0; 607224092Sdougb rule->types = NULL; 608224092Sdougb rule->magic = SSURULEMAGIC; 609224092Sdougb 610224092Sdougb ISC_LIST_INITANDAPPEND(table->rules, rule, link); 611224092Sdougb *tablep = table; 612224092Sdougb return (ISC_R_SUCCESS); 613224092Sdougb} 614