From 819b98479eff49ed93f57f4d65eb0ffe72136adc Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Thu, 29 Mar 2007 06:36:31 +0000 Subject: [PATCH] 2165. [func] Allow the destination address of a query to determine if we will answer the query or recurse. allow-query-on, allow-recursion-on and allow-query-cache-on. [RT #16291] --- CHANGES | 5 ++ bin/named/client.c | 71 +++++++++++++---------- bin/named/config.c | 5 +- bin/named/include/named/client.h | 22 ++++--- bin/named/named.conf.docbook | 9 ++- bin/named/query.c | 7 ++- bin/named/server.c | 61 +++++++++++--------- bin/named/update.c | 4 +- bin/named/xfrout.c | 8 +-- doc/arm/Bv9ARM-book.xml | 80 ++++++++++++++++++++++++-- lib/bind9/check.c | 99 +++++++++++++++++++++++++++++--- lib/dns/include/dns/view.h | 4 +- lib/dns/include/dns/zone.h | 34 ++++++++++- lib/dns/view.c | 8 ++- lib/dns/zone.c | 37 +++++++++++- lib/isccfg/namedconf.c | 5 +- 16 files changed, 367 insertions(+), 92 deletions(-) diff --git a/CHANGES b/CHANGES index 64de31d9ae..245420bdde 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,8 @@ +2165. [func] Allow the destination address of a query to determine + if we will answer the query or recurse. + allow-query-on, allow-recursion-on and + allow-query-cache-on. [RT #16291] + 2164. [bug] The code to determine how named-checkzone / named-compilezone was called failed under windows. [RT #16764] diff --git a/bin/named/client.c b/bin/named/client.c index 89cb355669..4a37acab81 100644 --- a/bin/named/client.c +++ b/bin/named/client.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: client.c,v 1.244 2007/03/06 01:14:27 marka Exp $ */ +/* $Id: client.c,v 1.245 2007/03/29 06:36:29 marka Exp $ */ #include @@ -119,9 +119,9 @@ struct ns_clientmgr { isc_mutex_t lock; /* Locked by lock. */ isc_boolean_t exiting; - client_list_t active; /*%< Active clients */ - client_list_t recursing; /*%< Recursing clients */ - client_list_t inactive; /*%< To be recycled */ + client_list_t active; /*%< Active clients */ + client_list_t recursing; /*%< Recursing clients */ + client_list_t inactive; /*%< To be recycled */ #if NMCTXS > 0 /*%< mctx pool for clients. */ unsigned int nextmctx; @@ -640,7 +640,7 @@ ns_client_checkactive(ns_client_t *client) { /* * This client object should normally go inactive * at this point, but if we have fewer active client - * objects than desired due to earlier quota exhaustion, + * objects than desired due to earlier quota exhaustion, * keep it active to make up for the shortage. */ isc_boolean_t need_another_client = ISC_FALSE; @@ -817,7 +817,7 @@ client_sendpkg(ns_client_t *client, isc_buffer_t *buffer) { isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr); if (ns_g_server->blackholeacl != NULL && dns_acl_match(&netaddr, NULL, - ns_g_server->blackholeacl, + ns_g_server->blackholeacl, &ns_g_server->aclenv, &match, NULL) == ISC_R_SUCCESS && match > 0) @@ -1284,7 +1284,7 @@ client_request(isc_task_t *task, isc_event_t *event) { isc_buffer_t tbuffer; dns_view_t *view; dns_rdataset_t *opt; - isc_boolean_t ra; /* Recursion available. */ + isc_boolean_t ra; /* Recursion available. */ isc_netaddr_t netaddr; isc_netaddr_t destaddr; int match; @@ -1724,9 +1724,17 @@ client_request(isc_task_t *task, isc_event_t *event) { ra = ISC_FALSE; if (client->view->resolver != NULL && client->view->recursion == ISC_TRUE && - ns_client_checkaclsilent(client, client->view->recursionacl, + ns_client_checkaclsilent(client, NULL, + client->view->recursionacl, ISC_TRUE) == ISC_R_SUCCESS && - ns_client_checkaclsilent(client, client->view->queryacl, + ns_client_checkaclsilent(client, NULL, + client->view->queryacl, + ISC_TRUE) == ISC_R_SUCCESS && + ns_client_checkaclsilent(client, &client->interface->addr, + client->view->recursiononacl, + ISC_TRUE) == ISC_R_SUCCESS && + ns_client_checkaclsilent(client, &client->interface->addr, + client->view->queryonacl, ISC_TRUE) == ISC_R_SUCCESS) ra = ISC_TRUE; @@ -1735,7 +1743,7 @@ client_request(isc_task_t *task, isc_event_t *event) { ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3), ra ? "recursion available" : - "recursion not available"); + "recursion not available"); /* * Adjust maximum UDP response size for this client. @@ -2078,7 +2086,7 @@ client_newconn(isc_task_t *task, isc_event_t *event) { } else { /* * XXXRTH What should we do? We're trying to accept but - * it didn't work. If we just give up, then TCP + * it didn't work. If we just give up, then TCP * service may eventually stop. * * For now, we just go idle. @@ -2103,7 +2111,7 @@ client_newconn(isc_task_t *task, isc_event_t *event) { if (ns_g_server->blackholeacl != NULL && dns_acl_match(&netaddr, NULL, - ns_g_server->blackholeacl, + ns_g_server->blackholeacl, &ns_g_server->aclenv, &match, NULL) == ISC_R_SUCCESS && match > 0) @@ -2159,7 +2167,7 @@ client_accept(ns_client_t *client) { isc_result_totext(result)); /* * XXXRTH What should we do? We're trying to accept but - * it didn't work. If we just give up, then TCP + * it didn't work. If we just give up, then TCP * service may eventually stop. * * For now, we just go idle. @@ -2452,8 +2460,8 @@ ns_client_getsockaddr(ns_client_t *client) { } isc_result_t -ns_client_checkaclsilent(ns_client_t *client, dns_acl_t *acl, - isc_boolean_t default_allow) +ns_client_checkaclsilent(ns_client_t *client, isc_sockaddr_t *sockaddr, + dns_acl_t *acl, isc_boolean_t default_allow) { isc_result_t result; int match; @@ -2466,11 +2474,16 @@ ns_client_checkaclsilent(ns_client_t *client, dns_acl_t *acl, goto deny; } - isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr); - + + if (sockaddr == NULL) + isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr); + else + isc_netaddr_fromsockaddr(&netaddr, sockaddr); + result = dns_acl_match(&netaddr, client->signer, acl, &ns_g_server->aclenv, &match, NULL); + if (result != ISC_R_SUCCESS) goto deny; /* Internal error, already logged. */ if (match > 0) @@ -2485,12 +2498,12 @@ ns_client_checkaclsilent(ns_client_t *client, dns_acl_t *acl, } isc_result_t -ns_client_checkacl(ns_client_t *client, +ns_client_checkacl(ns_client_t *client, isc_sockaddr_t *sockaddr, const char *opname, dns_acl_t *acl, isc_boolean_t default_allow, int log_level) { isc_result_t result = - ns_client_checkaclsilent(client, acl, default_allow); + ns_client_checkaclsilent(client, sockaddr, acl, default_allow); if (result == ISC_R_SUCCESS) ns_client_log(client, DNS_LOGCATEGORY_SECURITY, @@ -2513,7 +2526,7 @@ ns_client_name(ns_client_t *client, char *peerbuf, size_t len) { void ns_client_logv(ns_client_t *client, isc_logcategory_t *category, - isc_logmodule_t *module, int level, const char *fmt, va_list ap) + isc_logmodule_t *module, int level, const char *fmt, va_list ap) { char msgbuf[2048]; char peerbuf[ISC_SOCKADDR_FORMATSIZE]; @@ -2550,14 +2563,14 @@ void ns_client_aclmsg(const char *msg, dns_name_t *name, dns_rdatatype_t type, dns_rdataclass_t rdclass, char *buf, size_t len) { - char namebuf[DNS_NAME_FORMATSIZE]; - char typebuf[DNS_RDATATYPE_FORMATSIZE]; - char classbuf[DNS_RDATACLASS_FORMATSIZE]; + char namebuf[DNS_NAME_FORMATSIZE]; + char typebuf[DNS_RDATATYPE_FORMATSIZE]; + char classbuf[DNS_RDATACLASS_FORMATSIZE]; - dns_name_format(name, namebuf, sizeof(namebuf)); - dns_rdatatype_format(type, typebuf, sizeof(typebuf)); - dns_rdataclass_format(rdclass, classbuf, sizeof(classbuf)); - (void)snprintf(buf, len, "%s '%s/%s/%s'", msg, namebuf, typebuf, + dns_name_format(name, namebuf, sizeof(namebuf)); + dns_rdatatype_format(type, typebuf, sizeof(typebuf)); + dns_rdataclass_format(rdclass, classbuf, sizeof(classbuf)); + (void)snprintf(buf, len, "%s '%s/%s/%s'", msg, namebuf, typebuf, classbuf); } @@ -2585,7 +2598,7 @@ ns_client_dumpmessage(ns_client_t *client, const char *reason) { isc_mem_put(client->mctx, buf, len); len += 1024; } else if (result == ISC_R_SUCCESS) - ns_client_log(client, NS_LOGCATEGORY_UNMATCHED, + ns_client_log(client, NS_LOGCATEGORY_UNMATCHED, NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1), "%s\n%.*s", reason, (int)isc_buffer_usedlength(&buffer), @@ -2605,7 +2618,7 @@ ns_client_dumprecursing(FILE *f, ns_clientmgr_t *manager) { const char *sep; REQUIRE(VALID_MANAGER(manager)); - + LOCK(&manager->lock); client = ISC_LIST_HEAD(manager->recursing); while (client != NULL) { diff --git a/bin/named/config.c b/bin/named/config.c index 8d3571248f..2beebdb9df 100644 --- a/bin/named/config.c +++ b/bin/named/config.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: config.c,v 1.75 2006/06/04 23:17:06 marka Exp $ */ +/* $Id: config.c,v 1.76 2007/03/29 06:36:29 marka Exp $ */ /*! \file */ @@ -104,7 +104,9 @@ options {\n\ allow-notify {none;};\n\ allow-update-forwarding {none;};\n\ allow-query-cache { localnets; localhost; };\n\ + allow-query-cache-on { any; };\n\ allow-recursion { localnets; localhost; };\n\ + allow-recursion-on { any; };\n\ # allow-v6-synthesis ;\n\ # sortlist \n\ # topology \n\ @@ -145,6 +147,7 @@ options {\n\ " /* zone */\n\ allow-query {any;};\n\ + allow-query-on {any;};\n\ allow-transfer {any;};\n\ notify yes;\n\ # also-notify \n\ diff --git a/bin/named/include/named/client.h b/bin/named/include/named/client.h index 9cf6c58007..f52894570f 100644 --- a/bin/named/include/named/client.h +++ b/bin/named/include/named/client.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: client.h,v 1.79 2006/06/06 00:11:42 marka Exp $ */ +/* $Id: client.h,v 1.80 2007/03/29 06:36:30 marka Exp $ */ #ifndef NAMED_CLIENT_H #define NAMED_CLIENT_H 1 @@ -266,7 +266,9 @@ ns_client_getsockaddr(ns_client_t *client); */ isc_result_t -ns_client_checkaclsilent(ns_client_t *client,dns_acl_t *acl, +ns_client_checkaclsilent(ns_client_t *client, + isc_sockaddr_t *sockaddr, + dns_acl_t *acl, isc_boolean_t default_allow); /*% @@ -274,6 +276,8 @@ ns_client_checkaclsilent(ns_client_t *client,dns_acl_t *acl, * * Check the current client request against 'acl'. If 'acl' * is NULL, allow the request iff 'default_allow' is ISC_TRUE. + * If netaddr is NULL, check the ACL against client->peeraddr; + * otherwise check it against netaddr. * * Notes: *\li This is appropriate for checking allow-update, @@ -284,6 +288,7 @@ ns_client_checkaclsilent(ns_client_t *client,dns_acl_t *acl, * * Requires: *\li 'client' points to a valid client. + *\li 'sockaddr' points to a valid address, or is NULL. *\li 'acl' points to a valid ACL, or is NULL. * * Returns: @@ -294,18 +299,19 @@ ns_client_checkaclsilent(ns_client_t *client,dns_acl_t *acl, isc_result_t ns_client_checkacl(ns_client_t *client, + isc_sockaddr_t *sockaddr, const char *opname, dns_acl_t *acl, isc_boolean_t default_allow, int log_level); /*% - * Like ns_client_checkacl, but also logs the outcome of the - * check at log level 'log_level' if denied, and at debug 3 - * if approved. Log messages will refer to the request as - * an 'opname' request. + * Like ns_client_checkaclsilent, except the outcome of the check is + * logged at log level 'log_level' if denied, and at debug 3 if approved. + * Log messages will refer to the request as an 'opname' request. * * Requires: - *\li Those of ns_client_checkaclsilent(), and: - * + *\li 'client' points to a valid client. + *\li 'sockaddr' points to a valid address, or is NULL. + *\li 'acl' points to a valid ACL, or is NULL. *\li 'opname' points to a null-terminated string. */ diff --git a/bin/named/named.conf.docbook b/bin/named/named.conf.docbook index 02299b5828..6e2731b592 100644 --- a/bin/named/named.conf.docbook +++ b/bin/named/named.conf.docbook @@ -17,7 +17,7 @@ - PERFORMANCE OF THIS SOFTWARE. --> - + Aug 13, 2004 @@ -219,6 +219,7 @@ options { use-ixfr boolean; version ( quoted_string | none ); allow-recursion { address_match_element; ... }; + allow-recursion-on { address_match_element; ... }; sortlist { address_match_element; ... }; topology { address_match_element; ... }; // not implemented auth-nxdomain boolean; // default changed @@ -281,7 +282,9 @@ options { ixfr-from-differences ixfrdiff; allow-query { address_match_element; ... }; + allow-query-on { address_match_element; ... }; allow-query-cache { address_match_element; ... }; + allow-query-cache-on { address_match_element; ... }; allow-transfer { address_match_element; ... }; allow-update { address_match_element; ... }; allow-update-forwarding { address_match_element; ... }; @@ -371,6 +374,7 @@ view string optional_class }; allow-recursion { address_match_element; ... }; + allow-recursion-on { address_match_element; ... }; sortlist { address_match_element; ... }; topology { address_match_element; ... }; // not implemented auth-nxdomain boolean; // default changed @@ -433,7 +437,9 @@ view string optional_class ixfr-from-differences ixfrdiff; allow-query { address_match_element; ... }; + allow-query-on { address_match_element; ... }; allow-query-cache { address_match_element; ... }; + allow-query-cache-on { address_match_element; ... }; allow-transfer { address_match_element; ... }; allow-update { address_match_element; ... }; allow-update-forwarding { address_match_element; ... }; @@ -516,6 +522,7 @@ zone string optional_class zero-no-soa-ttl boolean; allow-query { address_match_element; ... }; + allow-query-on { address_match_element; ... }; allow-transfer { address_match_element; ... }; allow-update { address_match_element; ... }; allow-update-forwarding { address_match_element; ... }; diff --git a/bin/named/query.c b/bin/named/query.c index 6156d555ef..218ac06d52 100644 --- a/bin/named/query.c +++ b/bin/named/query.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: query.c,v 1.293 2007/02/06 04:00:21 marka Exp $ */ +/* $Id: query.c,v 1.294 2007/03/29 06:36:29 marka Exp $ */ /*! \file */ @@ -640,7 +640,8 @@ query_validatezonedb(ns_client_t *client, dns_name_t *name, if (check_acl) { isc_boolean_t log = ISC_TF((options & DNS_GETDB_NOLOG) == 0); - result = ns_client_checkaclsilent(client, queryacl, ISC_TRUE); + result = ns_client_checkaclsilent(client, NULL, queryacl, + ISC_TRUE); if (log) { char msg[NS_CLIENT_ACLMSGSIZE("query")]; if (result == ISC_R_SUCCESS) { @@ -804,7 +805,7 @@ query_getcachedb(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype, isc_boolean_t log = ISC_TF((options & DNS_GETDB_NOLOG) == 0); char msg[NS_CLIENT_ACLMSGSIZE("query (cache)")]; - result = ns_client_checkaclsilent(client, + result = ns_client_checkaclsilent(client, NULL, client->view->queryacl, ISC_TRUE); if (result == ISC_R_SUCCESS) { diff --git a/bin/named/server.c b/bin/named/server.c index e93bd6411b..bb226a2a42 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: server.c,v 1.479 2007/03/13 04:30:17 marka Exp $ */ +/* $Id: server.c,v 1.480 2007/03/29 06:36:29 marka Exp $ */ /*! \file */ @@ -102,12 +102,12 @@ * using it has a 'result' variable and a 'cleanup' label. */ #define CHECK(op) \ - do { result = (op); \ - if (result != ISC_R_SUCCESS) goto cleanup; \ + do { result = (op); \ + if (result != ISC_R_SUCCESS) goto cleanup; \ } while (0) #define CHECKM(op, msg) \ - do { result = (op); \ + do { result = (op); \ if (result != ISC_R_SUCCESS) { \ isc_log_write(ns_g_lctx, \ NS_LOGCATEGORY_GENERAL, \ @@ -120,7 +120,7 @@ } while (0) \ #define CHECKMF(op, msg, file) \ - do { result = (op); \ + do { result = (op); \ if (result != ISC_R_SUCCESS) { \ isc_log_write(ns_g_lctx, \ NS_LOGCATEGORY_GENERAL, \ @@ -133,7 +133,7 @@ } while (0) \ #define CHECKFATAL(op, msg) \ - do { result = (op); \ + do { result = (op); \ if (result != ISC_R_SUCCESS) \ fatal(msg, result); \ } while (0) \ @@ -302,7 +302,7 @@ configure_view_acl(const cfg_obj_t *vconfig, const cfg_obj_t *config, (void)ns_config_get(maps, aclname, &aclobj); if (aclobj == NULL) /* - * No value available. *aclp == NULL. + * No value available. *aclp == NULL. */ return (ISC_R_SUCCESS); @@ -420,7 +420,7 @@ configure_view_dnsseckey(const cfg_obj_t *vconfig, const cfg_obj_t *key, * the security roots. * * The per-view configuration values and the server-global defaults are read - * from 'vconfig' and 'config'. The variable to be configured is '*target'. + * from 'vconfig' and 'config'. The variable to be configured is '*target'. */ static isc_result_t configure_view_dnsseckeys(const cfg_obj_t *vconfig, const cfg_obj_t *config, @@ -1550,29 +1550,36 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, "allow-query-cache", actx, ns_g_mctx, &view->queryacl)); - if (strcmp(view->name, "_bind") != 0) + CHECK(configure_view_acl(vconfig, config, "allow-query-cache-on", + actx, ns_g_mctx, &view->queryonacl)); + if (view->queryonacl == NULL) + CHECK(configure_view_acl(NULL, ns_g_defaults, + "allow-query-cache-on", actx, + ns_g_mctx, &view->queryonacl)); + + if (strcmp(view->name, "_bind") != 0) { CHECK(configure_view_acl(vconfig, config, "allow-recursion", - actx, ns_g_mctx, &view->recursionacl)); + actx, ns_g_mctx, + &view->recursionacl)); + CHECK(configure_view_acl(vconfig, config, "allow-recursion-on", + actx, ns_g_mctx, + &view->recursiononacl)); + } /* - * Warning if both "recursion no;" and allow-recursion are active - * except for "allow-recursion { none; };". - */ - if (!view->recursion && view->recursionacl != NULL && - (view->recursionacl->length != 1 || - view->recursionacl->elements[0].type != dns_aclelementtype_any || - view->recursionacl->elements[0].negative != ISC_TRUE)) - isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, - NS_LOGMODULE_SERVER, ISC_LOG_WARNING, - "both \"recursion no;\" and \"allow-recursion\" " - "active%s%s", forview, viewname); - - /* - * Set default "allow-recursion" acl. + * Set default "allow-recursion" and "allow-recursion-on" acls. */ if (view->recursionacl == NULL && view->recursion) - CHECK(configure_view_acl(NULL, ns_g_defaults, "allow-recursion", - actx, ns_g_mctx, &view->recursionacl)); + CHECK(configure_view_acl(NULL, ns_g_defaults, + "allow-recursion", + actx, ns_g_mctx, + &view->recursionacl)); + + if (view->recursiononacl == NULL && view->recursion) + CHECK(configure_view_acl(NULL, ns_g_defaults, + "allow-recursion-on", + actx, ns_g_mctx, + &view->recursiononacl)); CHECK(configure_view_acl(vconfig, config, "sortlist", actx, ns_g_mctx, &view->sortlist)); @@ -1878,6 +1885,8 @@ configure_view(dns_view_t *view, const cfg_obj_t *config, empty_dbtype)); if (view->queryacl != NULL) dns_zone_setqueryacl(zone, view->queryacl); + if (view->queryonacl != NULL) + dns_zone_setqueryonacl(zone, view->queryonacl); dns_zone_setdialup(zone, dns_dialuptype_no); dns_zone_setnotifytype(zone, dns_notifytype_no); dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, diff --git a/bin/named/update.c b/bin/named/update.c index 74c2149d94..3b103a4d99 100644 --- a/bin/named/update.c +++ b/bin/named/update.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: update.c,v 1.130 2006/12/04 01:52:45 marka Exp $ */ +/* $Id: update.c,v 1.131 2007/03/29 06:36:30 marka Exp $ */ #include @@ -255,7 +255,7 @@ checkupdateacl(ns_client_t *client, dns_acl_t *acl, const char *message, level = ISC_LOG_DEBUG(3); msg = "disabled"; } else - result = ns_client_checkaclsilent(client, acl, ISC_FALSE); + result = ns_client_checkaclsilent(client, NULL, acl, ISC_FALSE); if (result == ISC_R_SUCCESS) { level = ISC_LOG_DEBUG(3); diff --git a/bin/named/xfrout.c b/bin/named/xfrout.c index 02f4f21d89..0eaf0d8219 100644 --- a/bin/named/xfrout.c +++ b/bin/named/xfrout.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: xfrout.c,v 1.123 2006/03/05 23:58:52 marka Exp $ */ +/* $Id: xfrout.c,v 1.124 2007/03/29 06:36:30 marka Exp $ */ #include @@ -1090,9 +1090,9 @@ ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) { #endif ns_client_aclmsg("zone transfer", question_name, reqtype, client->view->rdclass, msg, sizeof(msg)); - CHECK(ns_client_checkacl(client, msg, - dns_zone_getxfracl(zone), ISC_TRUE, - ISC_LOG_ERROR)); + CHECK(ns_client_checkacl(client, NULL, msg, + dns_zone_getxfracl(zone), + ISC_TRUE, ISC_LOG_ERROR)); #ifdef DLZ } #endif diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml index 302222b85f..a53a551c6d 100644 --- a/doc/arm/Bv9ARM-book.xml +++ b/doc/arm/Bv9ARM-book.xml @@ -18,7 +18,7 @@ - PERFORMANCE OF THIS SOFTWARE. --> - + BIND 9 Administrator Reference Manual @@ -3082,8 +3082,12 @@ $ORIGIN 0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa. allows access and a negated match denies access. If there is no match, access is denied. The clauses allow-notify, + allow-recursion, + allow-recursion-on, allow-query, + allow-query-on, allow-query-cache, + allow-query-cache-on, allow-transfer, allow-update, allow-update-forwarding, and @@ -4426,9 +4430,12 @@ category notify { null; }; check-sibling yes_or_no; allow-notify { address_match_list }; allow-query { address_match_list }; + allow-query-on { address_match_list }; allow-query-cache { address_match_list }; + allow-query-cache-on { address_match_list }; allow-transfer { address_match_list }; allow-recursion { address_match_list }; + allow-recursion-on { address_match_list }; allow-update { address_match_list }; allow-update-forwarding { address_match_list }; update-check-ksk yes_or_no; @@ -5865,6 +5872,35 @@ options { + + allow-query-on + + + Specifies which local addresses can accept ordinary + DNS questions. This makes it possible, for instance, + to allow queries on internal-facing interfaces but + disallow them on external-facing ones, without + necessarily knowing the internal network's addresses. + + + allow-query-on may + also be specified in the zone + statement, in which case it overrides the + options allow-query-on statement. + + + If not specified, the default is to allow queries + on all addresses. + + + + allow-query-cache is + used to specify access to the cache. + + + + + allow-query-cache @@ -5874,11 +5910,18 @@ options { localnets and localhost. + + + + + allow-query-cache-on + - The way to set query access to the cache is now - via allow-query-cache. - This differs from earlier versions which used - allow-query. + Specifies which local addresses can give answers + from the cache. If not specified, the default is + to allow cache queries on any address. + localnets and + localhost. @@ -5899,6 +5942,17 @@ options { + + allow-recursion-on + + + Specifies which local addresses can accept recursive + queries. If not specified, the default is to allow + recursive queries on all addresses. + + + + allow-update @@ -8095,6 +8149,7 @@ view "external" { zone zone_name class { type master; allow-query { address_match_list }; + allow-query-on { address_match_list }; allow-transfer { address_match_list }; allow-update { address_match_list }; update-policy { update_policy_rule ... }; @@ -8134,6 +8189,7 @@ zone zone_name class allow-notify { address_match_list }; allow-query { address_match_list }; + allow-query-on { address_match_list }; allow-transfer { address_match_list }; allow-update-forwarding { address_match_list }; update-check-ksk yes_or_no; @@ -8184,6 +8240,7 @@ zone zone_name classzone_name class { type stub; allow-query { address_match_list }; + allow-query-on { address_match_list }; check-names (warn|fail|ignore) ; dialup dialup_option ; delegation-only yes_or_no ; @@ -8483,6 +8540,16 @@ zone zone_name class + + allow-query-on + + + See the description of + allow-query-on in . + + + + allow-transfer @@ -10655,7 +10722,8 @@ $GENERATE 1-127 $ CNAME $.0 Access Control Lists (ACLs), are address match lists that you can set up and nickname for future use in allow-notify, - allow-query, allow-recursion, + allow-query, allow-query-on, + allow-recursion, allow-recursion-on, blackhole, allow-transfer, etc. diff --git a/lib/bind9/check.c b/lib/bind9/check.c index 7ce96f6878..f7bd0d4ef3 100644 --- a/lib/bind9/check.c +++ b/lib/bind9/check.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: check.c,v 1.78 2007/03/14 23:46:54 tbox Exp $ */ +/* $Id: check.c,v 1.79 2007/03/29 06:36:30 marka Exp $ */ /*! \file */ @@ -392,9 +392,10 @@ check_viewacls(cfg_aclconfctx_t *actx, const cfg_obj_t *voptions, isc_result_t result = ISC_R_SUCCESS, tresult; int i = 0; - static const char *acls[] = { "allow-query", "allow-query-cache", - "allow-recursion", "blackhole", "match-clients", - "match-destinations", "sortlist", NULL }; + static const char *acls[] = { "allow-query", "allow-query-on", + "allow-query-cache", "allow-query-cache-on", + "blackhole", "match-clients", "match-destinations", + "sortlist", NULL }; while (acls[i] != NULL) { tresult = checkacl(acls[i++], actx, NULL, voptions, config, @@ -405,6 +406,84 @@ check_viewacls(cfg_aclconfctx_t *actx, const cfg_obj_t *voptions, return (result); } +/* + * Check allow-recursion and allow-recursion-on acls, and also log a + * warning if they're inconsistent with the "recursion" option. + */ +static isc_result_t +check_recursionacls(cfg_aclconfctx_t *actx, const cfg_obj_t *voptions, + const char *viewname, const cfg_obj_t *config, + isc_log_t *logctx, isc_mem_t *mctx) +{ + const cfg_obj_t *options, *aclobj, *obj = NULL; + dns_acl_t *acl = NULL; + isc_result_t result = ISC_R_SUCCESS, tresult; + isc_boolean_t recursion; + const char *forview = " for view "; + int i = 0; + + static const char *acls[] = { "allow-recursion", "allow-recursion-on", + NULL }; + + if (voptions != NULL) + cfg_map_get(voptions, "recursion", &obj); + if (obj == NULL && config != NULL) { + options = NULL; + cfg_map_get(config, "options", &options); + if (options != NULL) + cfg_map_get(options, "recursion", &obj); + } + if (obj == NULL) + recursion = ISC_TRUE; + else + recursion = cfg_obj_asboolean(obj); + + if (viewname == NULL) { + viewname = ""; + forview = ""; + } + + for (i = 0; acls[i] != NULL; i++) { + aclobj = options = NULL; + acl = NULL; + + if (voptions != NULL) + cfg_map_get(voptions, acls[i], &aclobj); + if (config != NULL && aclobj == NULL) { + options = NULL; + cfg_map_get(config, "options", &options); + if (options != NULL) + cfg_map_get(options, acls[i], &aclobj); + } + if (aclobj == NULL) + continue; + + tresult = cfg_acl_fromconfig(aclobj, config, logctx, + actx, mctx, &acl); + + if (tresult != ISC_R_SUCCESS) + result = tresult; + + if (acl == NULL) + continue; + + if (recursion == ISC_FALSE && + (acl->length != 1 || + acl->elements[0].type != dns_aclelementtype_any || + acl->elements[0].negative != ISC_TRUE)) { + cfg_obj_log(aclobj, logctx, ISC_LOG_WARNING, + "both \"recursion no;\" and " + "\"%s\" active%s%s", + acls[i], forview, viewname); + } + + if (acl != NULL) + dns_acl_detach(&acl); + } + + return (result); +} + typedef struct { const char *name; unsigned int scale; @@ -1393,7 +1472,8 @@ check_servers(const cfg_obj_t *servers, isc_log_t *logctx) { static isc_result_t check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions, - dns_rdataclass_t vclass, isc_log_t *logctx, isc_mem_t *mctx) + const char *viewname, dns_rdataclass_t vclass, + isc_log_t *logctx, isc_mem_t *mctx) { const cfg_obj_t *servers = NULL; const cfg_obj_t *zones = NULL; @@ -1548,6 +1628,11 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions, if (tresult != ISC_R_SUCCESS) result = tresult; + tresult = check_recursionacls(&actx, voptions, viewname, + config, logctx, mctx); + if (tresult != ISC_R_SUCCESS) + result = tresult; + cfg_aclconfctx_destroy(&actx); return (result); @@ -1861,7 +1946,7 @@ bind9_check_namedconf(const cfg_obj_t *config, isc_log_t *logctx, result = ISC_R_FAILURE; if (views == NULL) { - if (check_viewconf(config, NULL, dns_rdataclass_in, + if (check_viewconf(config, NULL, NULL, dns_rdataclass_in, logctx, mctx) != ISC_R_SUCCESS) result = ISC_R_FAILURE; } else { @@ -1933,7 +2018,7 @@ bind9_check_namedconf(const cfg_obj_t *config, isc_log_t *logctx, } } if (tresult == ISC_R_SUCCESS) - tresult = check_viewconf(config, voptions, + tresult = check_viewconf(config, voptions, key, vclass, logctx, mctx); if (tresult != ISC_R_SUCCESS) result = ISC_R_FAILURE; diff --git a/lib/dns/include/dns/view.h b/lib/dns/include/dns/view.h index 9af140acfd..1e6b48d9f1 100644 --- a/lib/dns/include/dns/view.h +++ b/lib/dns/include/dns/view.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: view.h,v 1.103 2006/12/22 01:45:00 marka Exp $ */ +/* $Id: view.h,v 1.104 2007/03/29 06:36:31 marka Exp $ */ #ifndef DNS_VIEW_H #define DNS_VIEW_H 1 @@ -118,7 +118,9 @@ struct dns_view { isc_boolean_t acceptexpired; dns_transfer_format_t transfer_format; dns_acl_t * queryacl; + dns_acl_t * queryonacl; dns_acl_t * recursionacl; + dns_acl_t * recursiononacl; dns_acl_t * sortlist; isc_boolean_t requestixfr; isc_boolean_t provideixfr; diff --git a/lib/dns/include/dns/zone.h b/lib/dns/include/dns/zone.h index c674baba0a..3bc1f01b19 100644 --- a/lib/dns/include/dns/zone.h +++ b/lib/dns/include/dns/zone.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zone.h,v 1.149 2006/12/22 01:45:00 marka Exp $ */ +/* $Id: zone.h,v 1.150 2007/03/29 06:36:31 marka Exp $ */ #ifndef DNS_ZONE_H #define DNS_ZONE_H 1 @@ -702,6 +702,16 @@ dns_zone_setqueryacl(dns_zone_t *zone, dns_acl_t *acl); *\li 'acl' to be a valid acl. */ +void +dns_zone_setqueryonacl(dns_zone_t *zone, dns_acl_t *acl); +/*%< + * Sets the query-on acl list for the zone. + * + * Require: + *\li 'zone' to be a valid zone. + *\li 'acl' to be a valid acl. + */ + void dns_zone_setupdateacl(dns_zone_t *zone, dns_acl_t *acl); /*%< @@ -758,6 +768,19 @@ dns_zone_getqueryacl(dns_zone_t *zone); *\li NULL */ +dns_acl_t * +dns_zone_getqueryonacl(dns_zone_t *zone); +/*%< + * Returns the current query-on acl or NULL. + * + * Require: + *\li 'zone' to be a valid zone. + * + * Returns: + *\li acl a pointer to the acl. + *\li NULL + */ + dns_acl_t * dns_zone_getupdateacl(dns_zone_t *zone); /*%< @@ -833,6 +856,15 @@ dns_zone_clearqueryacl(dns_zone_t *zone); *\li 'zone' to be a valid zone. */ +void +dns_zone_clearqueryonacl(dns_zone_t *zone); +/*%< + * Clear the current query-on acl. + * + * Require: + *\li 'zone' to be a valid zone. + */ + void dns_zone_clearxfracl(dns_zone_t *zone); /*%< diff --git a/lib/dns/view.c b/lib/dns/view.c index 30f975569e..e831d0565c 100644 --- a/lib/dns/view.c +++ b/lib/dns/view.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: view.c,v 1.140 2007/03/06 02:12:39 tbox Exp $ */ +/* $Id: view.c,v 1.141 2007/03/29 06:36:30 marka Exp $ */ /*! \file */ @@ -166,7 +166,9 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, view->minimalresponses = ISC_FALSE; view->transfer_format = dns_one_answer; view->queryacl = NULL; + view->queryonacl = NULL; view->recursionacl = NULL; + view->recursiononacl = NULL; view->sortlist = NULL; view->requestixfr = ISC_TRUE; view->provideixfr = ISC_TRUE; @@ -287,8 +289,12 @@ destroy(dns_view_t *view) { dns_acl_detach(&view->matchdestinations); if (view->queryacl != NULL) dns_acl_detach(&view->queryacl); + if (view->queryonacl != NULL) + dns_acl_detach(&view->queryonacl); if (view->recursionacl != NULL) dns_acl_detach(&view->recursionacl); + if (view->recursiononacl != NULL) + dns_acl_detach(&view->recursiononacl); if (view->sortlist != NULL) dns_acl_detach(&view->sortlist); if (view->delonly != NULL) { diff --git a/lib/dns/zone.c b/lib/dns/zone.c index e50ecbb41b..f7a343c098 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: zone.c,v 1.463 2007/02/26 23:46:54 tbox Exp $ */ +/* $Id: zone.c,v 1.464 2007/03/29 06:36:30 marka Exp $ */ /*! \file */ @@ -216,6 +216,7 @@ struct dns_zone { dns_acl_t *forward_acl; dns_acl_t *notify_acl; dns_acl_t *query_acl; + dns_acl_t *queryon_acl; dns_acl_t *xfr_acl; isc_boolean_t update_disabled; isc_boolean_t zero_no_soa_ttl; @@ -623,6 +624,7 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) { zone->forward_acl = NULL; zone->notify_acl = NULL; zone->query_acl = NULL; + zone->queryon_acl = NULL; zone->xfr_acl = NULL; zone->update_disabled = ISC_FALSE; zone->zero_no_soa_ttl = ISC_TRUE; @@ -747,6 +749,8 @@ zone_free(dns_zone_t *zone) { dns_acl_detach(&zone->notify_acl); if (zone->query_acl != NULL) dns_acl_detach(&zone->query_acl); + if (zone->queryon_acl != NULL) + dns_acl_detach(&zone->queryon_acl); if (zone->xfr_acl != NULL) dns_acl_detach(&zone->xfr_acl); if (dns_name_dynamic(&zone->origin)) @@ -5870,6 +5874,18 @@ dns_zone_setqueryacl(dns_zone_t *zone, dns_acl_t *acl) { UNLOCK_ZONE(zone); } +void +dns_zone_setqueryonacl(dns_zone_t *zone, dns_acl_t *acl) { + + REQUIRE(DNS_ZONE_VALID(zone)); + + LOCK_ZONE(zone); + if (zone->queryon_acl != NULL) + dns_acl_detach(&zone->queryon_acl); + dns_acl_attach(acl, &zone->queryon_acl); + UNLOCK_ZONE(zone); +} + void dns_zone_setupdateacl(dns_zone_t *zone, dns_acl_t *acl) { @@ -5922,6 +5938,14 @@ dns_zone_getqueryacl(dns_zone_t *zone) { return (zone->query_acl); } +dns_acl_t * +dns_zone_getqueryonacl(dns_zone_t *zone) { + + REQUIRE(DNS_ZONE_VALID(zone)); + + return (zone->queryon_acl); +} + dns_acl_t * dns_zone_getupdateacl(dns_zone_t *zone) { @@ -5990,6 +6014,17 @@ dns_zone_clearqueryacl(dns_zone_t *zone) { UNLOCK_ZONE(zone); } +void +dns_zone_clearqueryonacl(dns_zone_t *zone) { + + REQUIRE(DNS_ZONE_VALID(zone)); + + LOCK_ZONE(zone); + if (zone->queryon_acl != NULL) + dns_acl_detach(&zone->queryon_acl); + UNLOCK_ZONE(zone); +} + void dns_zone_clearxfracl(dns_zone_t *zone) { diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c index a5379ceffc..ee0a0034c7 100644 --- a/lib/isccfg/namedconf.c +++ b/lib/isccfg/namedconf.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: namedconf.c,v 1.74 2007/02/06 00:01:23 marka Exp $ */ +/* $Id: namedconf.c,v 1.75 2007/03/29 06:36:31 marka Exp $ */ /*! \file */ @@ -735,7 +735,9 @@ static cfg_type_t cfg_type_lookaside = { static cfg_clausedef_t view_clauses[] = { { "allow-query-cache", &cfg_type_bracketed_aml, 0 }, + { "allow-query-cache-on", &cfg_type_bracketed_aml, 0 }, { "allow-recursion", &cfg_type_bracketed_aml, 0 }, + { "allow-recursion-on", &cfg_type_bracketed_aml, 0 }, { "allow-v6-synthesis", &cfg_type_bracketed_aml, CFG_CLAUSEFLAG_OBSOLETE }, { "sortlist", &cfg_type_bracketed_aml, 0 }, @@ -814,6 +816,7 @@ view_only_clauses[] = { static cfg_clausedef_t zone_clauses[] = { { "allow-query", &cfg_type_bracketed_aml, 0 }, + { "allow-query-on", &cfg_type_bracketed_aml, 0 }, { "allow-transfer", &cfg_type_bracketed_aml, 0 }, { "allow-update", &cfg_type_bracketed_aml, 0 }, { "allow-update-forwarding", &cfg_type_bracketed_aml, 0 },