00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <config.h>
00021
00022 #include <isc/mem.h>
00023 #include <isc/once.h>
00024 #include <isc/string.h>
00025 #include <isc/util.h>
00026
00027 #include <dns/acl.h>
00028 #include <dns/iptable.h>
00029
00030
00031
00032
00033
00034
00035
00036 isc_result_t
00037 dns_acl_create(isc_mem_t *mctx, int n, dns_acl_t **target) {
00038 isc_result_t result;
00039 dns_acl_t *acl;
00040
00041
00042
00043
00044 if (n == 0)
00045 n = 1;
00046
00047 acl = isc_mem_get(mctx, sizeof(*acl));
00048 if (acl == NULL)
00049 return (ISC_R_NOMEMORY);
00050
00051 acl->mctx = NULL;
00052 isc_mem_attach(mctx, &acl->mctx);
00053
00054 acl->name = NULL;
00055
00056 result = isc_refcount_init(&acl->refcount, 1);
00057 if (result != ISC_R_SUCCESS) {
00058 isc_mem_put(mctx, acl, sizeof(*acl));
00059 return (result);
00060 }
00061
00062 result = dns_iptable_create(mctx, &acl->iptable);
00063 if (result != ISC_R_SUCCESS) {
00064 isc_mem_put(mctx, acl, sizeof(*acl));
00065 return (result);
00066 }
00067
00068 acl->elements = NULL;
00069 acl->alloc = 0;
00070 acl->length = 0;
00071 acl->has_negatives = ISC_FALSE;
00072
00073 ISC_LINK_INIT(acl, nextincache);
00074
00075
00076
00077 acl->magic = DNS_ACL_MAGIC;
00078
00079 acl->elements = isc_mem_get(mctx, n * sizeof(dns_aclelement_t));
00080 if (acl->elements == NULL) {
00081 result = ISC_R_NOMEMORY;
00082 goto cleanup;
00083 }
00084 acl->alloc = n;
00085 memset(acl->elements, 0, n * sizeof(dns_aclelement_t));
00086 *target = acl;
00087 return (ISC_R_SUCCESS);
00088
00089 cleanup:
00090 dns_acl_detach(&acl);
00091 return (result);
00092 }
00093
00094
00095
00096
00097
00098
00099
00100 static isc_result_t
00101 dns_acl_anyornone(isc_mem_t *mctx, isc_boolean_t neg, dns_acl_t **target) {
00102 isc_result_t result;
00103 dns_acl_t *acl = NULL;
00104
00105 result = dns_acl_create(mctx, 0, &acl);
00106 if (result != ISC_R_SUCCESS)
00107 return (result);
00108
00109 result = dns_iptable_addprefix(acl->iptable, NULL, 0, ISC_TF(!neg));
00110 if (result != ISC_R_SUCCESS) {
00111 dns_acl_detach(&acl);
00112 return (result);
00113 }
00114
00115 *target = acl;
00116 return (result);
00117 }
00118
00119
00120
00121
00122 isc_result_t
00123 dns_acl_any(isc_mem_t *mctx, dns_acl_t **target) {
00124 return (dns_acl_anyornone(mctx, ISC_FALSE, target));
00125 }
00126
00127
00128
00129
00130 isc_result_t
00131 dns_acl_none(isc_mem_t *mctx, dns_acl_t **target) {
00132 return (dns_acl_anyornone(mctx, ISC_TRUE, target));
00133 }
00134
00135
00136
00137
00138
00139 static isc_boolean_t
00140 dns_acl_isanyornone(dns_acl_t *acl, isc_boolean_t pos)
00141 {
00142
00143 if (acl == NULL ||
00144 acl->iptable == NULL ||
00145 acl->iptable->radix == NULL ||
00146 acl->iptable->radix->head == NULL ||
00147 acl->iptable->radix->head->prefix == NULL)
00148 return (ISC_FALSE);
00149
00150 if (acl->length != 0 || acl->node_count != 1)
00151 return (ISC_FALSE);
00152
00153 if (acl->iptable->radix->head->prefix->bitlen == 0 &&
00154 acl->iptable->radix->head->data[0] != NULL &&
00155 acl->iptable->radix->head->data[0] ==
00156 acl->iptable->radix->head->data[1] &&
00157 *(isc_boolean_t *) (acl->iptable->radix->head->data[0]) == pos)
00158 return (ISC_TRUE);
00159
00160 return (ISC_FALSE);
00161 }
00162
00163
00164
00165
00166 isc_boolean_t
00167 dns_acl_isany(dns_acl_t *acl)
00168 {
00169 return (dns_acl_isanyornone(acl, ISC_TRUE));
00170 }
00171
00172
00173
00174
00175 isc_boolean_t
00176 dns_acl_isnone(dns_acl_t *acl)
00177 {
00178 return (dns_acl_isanyornone(acl, ISC_FALSE));
00179 }
00180
00181
00182
00183
00184
00185
00186
00187 isc_result_t
00188 dns_acl_match(const isc_netaddr_t *reqaddr,
00189 const dns_name_t *reqsigner,
00190 const dns_acl_t *acl,
00191 const dns_aclenv_t *env,
00192 int *match,
00193 const dns_aclelement_t **matchelt)
00194 {
00195 return (dns_acl_match2(reqaddr, reqsigner, NULL, 0, NULL, acl, env,
00196 match, matchelt));
00197 }
00198
00199 isc_result_t
00200 dns_acl_match2(const isc_netaddr_t *reqaddr,
00201 const dns_name_t *reqsigner,
00202 const isc_netaddr_t *ecs,
00203 isc_uint8_t ecslen,
00204 isc_uint8_t *scope,
00205 const dns_acl_t *acl,
00206 const dns_aclenv_t *env,
00207 int *match,
00208 const dns_aclelement_t **matchelt)
00209 {
00210 isc_uint16_t bitlen;
00211 isc_prefix_t pfx;
00212 isc_radix_node_t *node = NULL;
00213 const isc_netaddr_t *addr = reqaddr;
00214 isc_netaddr_t v4addr;
00215 isc_result_t result;
00216 int match_num = -1;
00217 unsigned int i;
00218
00219 REQUIRE(reqaddr != NULL);
00220 REQUIRE(matchelt == NULL || *matchelt == NULL);
00221 REQUIRE(ecs != NULL || scope == NULL);
00222
00223 if (env != NULL && env->match_mapped &&
00224 addr->family == AF_INET6 &&
00225 IN6_IS_ADDR_V4MAPPED(&addr->type.in6))
00226 {
00227 isc_netaddr_fromv4mapped(&v4addr, addr);
00228 addr = &v4addr;
00229 }
00230
00231
00232 bitlen = (addr->family == AF_INET6) ? 128 : 32;
00233 NETADDR_TO_PREFIX_T(addr, pfx, bitlen, ISC_FALSE);
00234
00235
00236 *match = 0;
00237
00238
00239 result = isc_radix_search(acl->iptable->radix, &node, &pfx);
00240
00241
00242 if (result == ISC_R_SUCCESS && node != NULL) {
00243 int off = ISC_RADIX_OFF(&pfx);
00244 match_num = node->node_num[off];
00245 if (*(isc_boolean_t *) node->data[off])
00246 *match = match_num;
00247 else
00248 *match = -match_num;
00249 }
00250
00251 isc_refcount_destroy(&pfx.refcount);
00252
00253
00254
00255
00256
00257 if (ecs != NULL) {
00258 node = NULL;
00259 addr = ecs;
00260
00261 if (env != NULL && env->match_mapped &&
00262 addr->family == AF_INET6 &&
00263 IN6_IS_ADDR_V4MAPPED(&addr->type.in6))
00264 {
00265 isc_netaddr_fromv4mapped(&v4addr, addr);
00266 addr = &v4addr;
00267 }
00268
00269 NETADDR_TO_PREFIX_T(addr, pfx, ecslen, ISC_TRUE);
00270
00271 result = isc_radix_search(acl->iptable->radix, &node, &pfx);
00272 if (result == ISC_R_SUCCESS && node != NULL) {
00273 int off = ISC_RADIX_OFF(&pfx);
00274 if (match_num == -1 ||
00275 node->node_num[off] < match_num)
00276 {
00277 match_num = node->node_num[off];
00278 if (scope != NULL)
00279 *scope = node->bit;
00280 if (*(isc_boolean_t *) node->data[off])
00281 *match = match_num;
00282 else
00283 *match = -match_num;
00284 }
00285 }
00286
00287 isc_refcount_destroy(&pfx.refcount);
00288 }
00289
00290
00291 for (i = 0; i < acl->length; i++) {
00292 dns_aclelement_t *e = &acl->elements[i];
00293
00294
00295 if (match_num != -1 && match_num < e->node_num) {
00296 break;
00297 }
00298
00299 if (dns_aclelement_match2(reqaddr, reqsigner, ecs, ecslen,
00300 scope, e, env, matchelt))
00301 {
00302 if (match_num == -1 || e->node_num < match_num) {
00303 if (e->negative)
00304 *match = -e->node_num;
00305 else
00306 *match = e->node_num;
00307 }
00308 break;
00309 }
00310 }
00311
00312 return (ISC_R_SUCCESS);
00313 }
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324 isc_result_t
00325 dns_acl_merge(dns_acl_t *dest, dns_acl_t *source, isc_boolean_t pos)
00326 {
00327 isc_result_t result;
00328 unsigned int newalloc, nelem, i;
00329 int max_node = 0, nodes;
00330
00331
00332 if (dest->length + source->length > dest->alloc) {
00333 void *newmem;
00334
00335 newalloc = dest->alloc + source->alloc;
00336 if (newalloc < 4)
00337 newalloc = 4;
00338
00339 newmem = isc_mem_get(dest->mctx,
00340 newalloc * sizeof(dns_aclelement_t));
00341 if (newmem == NULL)
00342 return (ISC_R_NOMEMORY);
00343
00344
00345 memset(newmem, 0, newalloc * sizeof(dns_aclelement_t));
00346
00347
00348 memmove(newmem, dest->elements,
00349 dest->length * sizeof(dns_aclelement_t));
00350
00351
00352 isc_mem_put(dest->mctx, dest->elements,
00353 dest->alloc * sizeof(dns_aclelement_t));
00354 dest->elements = newmem;
00355 dest->alloc = newalloc;
00356 }
00357
00358
00359
00360
00361
00362
00363
00364 nelem = dest->length;
00365 dest->length += source->length;
00366 for (i = 0; i < source->length; i++) {
00367 if (source->elements[i].node_num > max_node)
00368 max_node = source->elements[i].node_num;
00369
00370
00371 dest->elements[nelem + i].type = source->elements[i].type;
00372
00373
00374 dest->elements[nelem + i].node_num =
00375 source->elements[i].node_num + dest->node_count;
00376
00377
00378 if (source->elements[i].type == dns_aclelementtype_nestedacl &&
00379 source->elements[i].nestedacl != NULL)
00380 dns_acl_attach(source->elements[i].nestedacl,
00381 &dest->elements[nelem + i].nestedacl);
00382
00383
00384 if (source->elements[i].type == dns_aclelementtype_keyname) {
00385 dns_name_init(&dest->elements[nelem+i].keyname, NULL);
00386 result = dns_name_dup(&source->elements[i].keyname,
00387 dest->mctx,
00388 &dest->elements[nelem+i].keyname);
00389 if (result != ISC_R_SUCCESS)
00390 return result;
00391 }
00392
00393 #ifdef HAVE_GEOIP
00394
00395 if (source->elements[i].type == dns_aclelementtype_geoip) {
00396 dest->elements[nelem + i].geoip_elem =
00397 source->elements[i].geoip_elem;
00398 }
00399 #endif
00400
00401
00402 if (!pos && !source->elements[i].negative) {
00403 dest->elements[nelem + i].negative = ISC_TRUE;
00404 } else {
00405 dest->elements[nelem + i].negative =
00406 source->elements[i].negative;
00407 }
00408 }
00409
00410
00411
00412
00413
00414 nodes = max_node + dest->node_count;
00415 result = dns_iptable_merge(dest->iptable, source->iptable, pos);
00416 if (result != ISC_R_SUCCESS)
00417 return (result);
00418 if (nodes > dest->node_count)
00419 dest->node_count = nodes;
00420
00421 return (ISC_R_SUCCESS);
00422 }
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433 isc_boolean_t
00434 dns_aclelement_match(const isc_netaddr_t *reqaddr,
00435 const dns_name_t *reqsigner,
00436 const dns_aclelement_t *e,
00437 const dns_aclenv_t *env,
00438 const dns_aclelement_t **matchelt)
00439 {
00440 return (dns_aclelement_match2(reqaddr, reqsigner, NULL, 0, NULL,
00441 e, env, matchelt));
00442 }
00443
00444 isc_boolean_t
00445 dns_aclelement_match2(const isc_netaddr_t *reqaddr,
00446 const dns_name_t *reqsigner,
00447 const isc_netaddr_t *ecs,
00448 isc_uint8_t ecslen,
00449 isc_uint8_t *scope,
00450 const dns_aclelement_t *e,
00451 const dns_aclenv_t *env,
00452 const dns_aclelement_t **matchelt)
00453 {
00454 dns_acl_t *inner = NULL;
00455 int indirectmatch;
00456 isc_result_t result;
00457 #ifdef HAVE_GEOIP
00458 const isc_netaddr_t *addr = NULL;
00459 #endif
00460
00461 REQUIRE(ecs != NULL || scope == NULL);
00462
00463 switch (e->type) {
00464 case dns_aclelementtype_keyname:
00465 if (reqsigner != NULL &&
00466 dns_name_equal(reqsigner, &e->keyname)) {
00467 if (matchelt != NULL)
00468 *matchelt = e;
00469 return (ISC_TRUE);
00470 } else
00471 return (ISC_FALSE);
00472
00473 case dns_aclelementtype_nestedacl:
00474 inner = e->nestedacl;
00475 break;
00476
00477 case dns_aclelementtype_localhost:
00478 if (env == NULL || env->localhost == NULL)
00479 return (ISC_FALSE);
00480 inner = env->localhost;
00481 break;
00482
00483 case dns_aclelementtype_localnets:
00484 if (env == NULL || env->localnets == NULL)
00485 return (ISC_FALSE);
00486 inner = env->localnets;
00487 break;
00488
00489 #ifdef HAVE_GEOIP
00490 case dns_aclelementtype_geoip:
00491 if (env == NULL || env->geoip == NULL)
00492 return (ISC_FALSE);
00493 addr = (env->geoip_use_ecs && ecs != NULL) ? ecs : reqaddr;
00494 return (dns_geoip_match(addr, scope, env->geoip,
00495 &e->geoip_elem));
00496 #endif
00497 default:
00498
00499 INSIST(0);
00500 }
00501
00502 result = dns_acl_match2(reqaddr, reqsigner, ecs, ecslen, scope,
00503 inner, env, &indirectmatch, matchelt);
00504 INSIST(result == ISC_R_SUCCESS);
00505
00506
00507
00508
00509
00510
00511
00512 if (indirectmatch > 0) {
00513 if (matchelt != NULL)
00514 *matchelt = e;
00515 return (ISC_TRUE);
00516 }
00517
00518
00519
00520
00521
00522 if (matchelt != NULL)
00523 *matchelt = NULL;
00524
00525 return (ISC_FALSE);
00526 }
00527
00528 void
00529 dns_acl_attach(dns_acl_t *source, dns_acl_t **target) {
00530 REQUIRE(DNS_ACL_VALID(source));
00531
00532 isc_refcount_increment(&source->refcount, NULL);
00533 *target = source;
00534 }
00535
00536 static void
00537 destroy(dns_acl_t *dacl) {
00538 unsigned int i;
00539
00540 INSIST(!ISC_LINK_LINKED(dacl, nextincache));
00541
00542 for (i = 0; i < dacl->length; i++) {
00543 dns_aclelement_t *de = &dacl->elements[i];
00544 if (de->type == dns_aclelementtype_keyname) {
00545 dns_name_free(&de->keyname, dacl->mctx);
00546 } else if (de->type == dns_aclelementtype_nestedacl) {
00547 dns_acl_detach(&de->nestedacl);
00548 }
00549 }
00550 if (dacl->elements != NULL)
00551 isc_mem_put(dacl->mctx, dacl->elements,
00552 dacl->alloc * sizeof(dns_aclelement_t));
00553 if (dacl->name != NULL)
00554 isc_mem_free(dacl->mctx, dacl->name);
00555 if (dacl->iptable != NULL)
00556 dns_iptable_detach(&dacl->iptable);
00557 isc_refcount_destroy(&dacl->refcount);
00558 dacl->magic = 0;
00559 isc_mem_putanddetach(&dacl->mctx, dacl, sizeof(*dacl));
00560 }
00561
00562 void
00563 dns_acl_detach(dns_acl_t **aclp) {
00564 dns_acl_t *acl = *aclp;
00565 unsigned int refs;
00566
00567 REQUIRE(DNS_ACL_VALID(acl));
00568
00569 isc_refcount_decrement(&acl->refcount, &refs);
00570 if (refs == 0)
00571 destroy(acl);
00572 *aclp = NULL;
00573 }
00574
00575
00576 static isc_once_t insecure_prefix_once = ISC_ONCE_INIT;
00577 static isc_mutex_t insecure_prefix_lock;
00578 static isc_boolean_t insecure_prefix_found;
00579
00580 static void
00581 initialize_action(void) {
00582 RUNTIME_CHECK(isc_mutex_init(&insecure_prefix_lock) == ISC_R_SUCCESS);
00583 }
00584
00585
00586
00587
00588
00589 static void
00590 is_insecure(isc_prefix_t *prefix, void **data) {
00591 int bitlen, family, off;
00592
00593 bitlen = prefix->bitlen;
00594 family = prefix->family;
00595
00596
00597 off = ISC_RADIX_OFF(prefix);
00598 if (data[off] != NULL && * (isc_boolean_t *) data[off])
00599 return;
00600
00601
00602 switch (family) {
00603 case AF_INET:
00604 if (bitlen == 32 &&
00605 htonl(prefix->add.sin.s_addr) == INADDR_LOOPBACK)
00606 return;
00607 break;
00608 case AF_INET6:
00609 if (bitlen == 128 && IN6_IS_ADDR_LOOPBACK(&prefix->add.sin6))
00610 return;
00611 break;
00612 default:
00613 break;
00614 }
00615
00616
00617 insecure_prefix_found = ISC_TRUE;
00618 return;
00619 }
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629 isc_boolean_t
00630 dns_acl_isinsecure(const dns_acl_t *a) {
00631 unsigned int i;
00632 isc_boolean_t insecure;
00633
00634 RUNTIME_CHECK(isc_once_do(&insecure_prefix_once,
00635 initialize_action) == ISC_R_SUCCESS);
00636
00637
00638
00639
00640
00641 LOCK(&insecure_prefix_lock);
00642 insecure_prefix_found = ISC_FALSE;
00643 isc_radix_process(a->iptable->radix, is_insecure);
00644 insecure = insecure_prefix_found;
00645 UNLOCK(&insecure_prefix_lock);
00646 if (insecure)
00647 return (ISC_TRUE);
00648
00649
00650 for (i = 0; i < a->length; i++) {
00651 dns_aclelement_t *e = &a->elements[i];
00652
00653
00654 if (e->negative)
00655 continue;
00656
00657 switch (e->type) {
00658 case dns_aclelementtype_keyname:
00659 case dns_aclelementtype_localhost:
00660 continue;
00661
00662 case dns_aclelementtype_nestedacl:
00663 if (dns_acl_isinsecure(e->nestedacl))
00664 return (ISC_TRUE);
00665 continue;
00666
00667 case dns_aclelementtype_localnets:
00668 return (ISC_TRUE);
00669
00670 default:
00671 INSIST(0);
00672 return (ISC_TRUE);
00673 }
00674 }
00675
00676
00677 return (ISC_FALSE);
00678 }
00679
00680
00681
00682
00683 isc_result_t
00684 dns_aclenv_init(isc_mem_t *mctx, dns_aclenv_t *env) {
00685 isc_result_t result;
00686
00687 env->localhost = NULL;
00688 env->localnets = NULL;
00689 result = dns_acl_create(mctx, 0, &env->localhost);
00690 if (result != ISC_R_SUCCESS)
00691 goto cleanup_nothing;
00692 result = dns_acl_create(mctx, 0, &env->localnets);
00693 if (result != ISC_R_SUCCESS)
00694 goto cleanup_localhost;
00695 env->match_mapped = ISC_FALSE;
00696 #ifdef HAVE_GEOIP
00697 env->geoip = NULL;
00698 env->geoip_use_ecs = ISC_FALSE;
00699 #endif
00700 return (ISC_R_SUCCESS);
00701
00702 cleanup_localhost:
00703 dns_acl_detach(&env->localhost);
00704 cleanup_nothing:
00705 return (result);
00706 }
00707
00708 void
00709 dns_aclenv_copy(dns_aclenv_t *t, dns_aclenv_t *s) {
00710 dns_acl_detach(&t->localhost);
00711 dns_acl_attach(s->localhost, &t->localhost);
00712 dns_acl_detach(&t->localnets);
00713 dns_acl_attach(s->localnets, &t->localnets);
00714 t->match_mapped = s->match_mapped;
00715 #ifdef HAVE_GEOIP
00716 t->geoip_use_ecs = s->geoip_use_ecs;
00717 #endif
00718 }
00719
00720 void
00721 dns_aclenv_destroy(dns_aclenv_t *env) {
00722 dns_acl_detach(&env->localhost);
00723 dns_acl_detach(&env->localnets);
00724 }