acl.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2004-2009, 2011, 2013, 2014  Internet Systems Consortium, Inc. ("ISC")
00003  * Copyright (C) 1999-2002  Internet Software Consortium.
00004  *
00005  * Permission to use, copy, modify, and/or distribute this software for any
00006  * purpose with or without fee is hereby granted, provided that the above
00007  * copyright notice and this permission notice appear in all copies.
00008  *
00009  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00010  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00011  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00012  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00013  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00014  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00015  * PERFORMANCE OF THIS SOFTWARE.
00016  */
00017 
00018 /*! \file */
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  * Create a new ACL, including an IP table and an array with room
00033  * for 'n' ACL elements.  The elements are uninitialized and the
00034  * length is 0.
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          * Work around silly limitation of isc_mem_get().
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          * Must set magic early because we use dns_acl_detach() to clean up.
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  * Create a new ACL and initialize it with the value "any" or "none",
00096  * depending on the value of the "neg" parameter.
00097  * "any" is a positive iptable entry with bit length 0.
00098  * "none" is the same as "!any".
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  * Create a new ACL that matches everything.
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  * Create a new ACL that matches nothing.
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  * If pos is ISC_TRUE, test whether acl is set to "{ any; }"
00137  * If pos is ISC_FALSE, test whether acl is set to "{ none; }"
00138  */
00139 static isc_boolean_t
00140 dns_acl_isanyornone(dns_acl_t *acl, isc_boolean_t pos)
00141 {
00142         /* Should never happen but let's be safe */
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); /* All others */
00161 }
00162 
00163 /*
00164  * Test whether acl is set to "{ any; }"
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  * Test whether acl is set to "{ none; }"
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  * Determine whether a given address or signer matches a given ACL.
00183  * For a match with a positive ACL element or iptable radix entry,
00184  * return with a positive value in match; for a match with a negated ACL
00185  * element or radix entry, return with a negative value in match.
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         /* Always match with host addresses. */
00232         bitlen = (addr->family == AF_INET6) ? 128 : 32;
00233         NETADDR_TO_PREFIX_T(addr, pfx, bitlen, ISC_FALSE);
00234 
00235         /* Assume no match. */
00236         *match = 0;
00237 
00238         /* Search radix. */
00239         result = isc_radix_search(acl->iptable->radix, &node, &pfx);
00240 
00241         /* Found a match. */
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          * If ecs is not NULL, we search the radix tree again to
00255          * see if we find a better match on an ECS node
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         /* Now search non-radix elements for a match with a lower node_num. */
00291         for (i = 0; i < acl->length; i++) {
00292                 dns_aclelement_t *e = &acl->elements[i];
00293 
00294                 /* Already found a better match? */
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  * Merge the contents of one ACL into another.  Call dns_iptable_merge()
00317  * for the IP tables, then concatenate the element arrays.
00318  *
00319  * If pos is set to false, then the nested ACL is to be negated.  This
00320  * means reverse the sense of each *positive* element or IP table node,
00321  * but leave negatives alone, so as to prevent a double-negative causing
00322  * an unexpected positive match in the parent ACL.
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         /* Resize the element array if needed. */
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                 /* Zero. */
00345                 memset(newmem, 0, newalloc * sizeof(dns_aclelement_t));
00346 
00347                 /* Copy in the original elements */
00348                 memmove(newmem, dest->elements,
00349                         dest->length * sizeof(dns_aclelement_t));
00350 
00351                 /* Release the memory for the old elements array */
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          * Now copy in the new elements, increasing their node_num
00360          * values so as to keep the new ACL consistent.  If we're
00361          * negating, then negate positive elements, but keep negative
00362          * elements the same for security reasons.
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                 /* Copy type. */
00371                 dest->elements[nelem + i].type = source->elements[i].type;
00372 
00373                 /* Adjust node numbering. */
00374                 dest->elements[nelem + i].node_num =
00375                         source->elements[i].node_num + dest->node_count;
00376 
00377                 /* Duplicate nested acl. */
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                 /* Duplicate key name. */
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                 /* Duplicate GeoIP data */
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                 /* reverse sense of positives if this is a negative acl */
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          * Merge the iptables.  Make sure the destination ACL's
00412          * node_count value is set correctly afterward.
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  * Like dns_acl_match, but matches against the single ACL element 'e'
00426  * rather than a complete ACL, and returns ISC_TRUE iff it matched.
00427  *
00428  * To determine whether the match was positive or negative, the
00429  * caller should examine e->negative.  Since the element 'e' may be
00430  * a reference to a named ACL or a nested ACL, a matching element
00431  * returned through 'matchelt' is not necessarily 'e' itself.
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                 /* Should be impossible. */
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          * Treat negative matches in indirect ACLs as "no match".
00508          * That way, a negated indirect ACL will never become a
00509          * surprise positive match through double negation.
00510          * XXXDCL this should be documented.
00511          */
00512         if (indirectmatch > 0) {
00513                 if (matchelt != NULL)
00514                         *matchelt = e;
00515                 return (ISC_TRUE);
00516         }
00517 
00518         /*
00519          * A negative indirect match may have set *matchelt, but we don't
00520          * want it set when we return.
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  * Called via isc_radix_walk() to find IP table nodes that are
00587  * insecure.
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         /* Negated entries are always secure. */
00597         off = ISC_RADIX_OFF(prefix);
00598         if (data[off] != NULL && * (isc_boolean_t *) data[off])
00599                 return;
00600 
00601         /* If loopback prefix found, return */
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         /* Non-negated, non-loopback */
00617         insecure_prefix_found = ISC_TRUE;       /* LOCKED */
00618         return;
00619 }
00620 
00621 /*
00622  * Return ISC_TRUE iff the acl 'a' is considered insecure, that is,
00623  * if it contains IP addresses other than those of the local host.
00624  * This is intended for applications such as printing warning
00625  * messages for suspect ACLs; it is not intended for making access
00626  * control decisions.  We make no guarantee that an ACL for which
00627  * this function returns ISC_FALSE is safe.
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          * Walk radix tree to find out if there are any non-negated,
00639          * non-loopback prefixes.
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         /* Now check non-radix elements */
00650         for (i = 0; i < a->length; i++) {
00651                 dns_aclelement_t *e = &a->elements[i];
00652 
00653                 /* A negated match can never be insecure. */
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         /* No insecure elements were found. */
00677         return (ISC_FALSE);
00678 }
00679 
00680 /*
00681  * Initialize ACL environment, setting up localhost and localnets ACLs
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 }

Generated on Tue Apr 28 17:40:55 2015 by Doxygen 1.5.4 for BIND9 Internals 9.11.0pre-alpha