diff --git a/CHANGES b/CHANGES index 76a670b33d..61d4461b30 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,5 @@ +1504. [func] New zone type "delegation-only". + 1503. [port] win32: install libeay32.dll outside of system32. 1502. [bug] nsupdate: adjust timeouts for UPDATE requests over TCP. diff --git a/bin/named/server.c b/bin/named/server.c index 791d8b691a..5568dae366 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: server.c,v 1.400 2003/07/25 02:22:23 marka Exp $ */ +/* $Id: server.c,v 1.401 2003/09/17 05:24:41 marka Exp $ */ #include @@ -1274,6 +1274,7 @@ configure_zone(cfg_obj_t *config, cfg_obj_t *zconfig, cfg_obj_t *vconfig, cfg_obj_t *typeobj = NULL; cfg_obj_t *forwarders = NULL; cfg_obj_t *forwardtype = NULL; + cfg_obj_t *only = NULL; isc_result_t result; isc_buffer_t buffer; dns_fixedname_t fixorigin; @@ -1374,6 +1375,14 @@ configure_zone(cfg_obj_t *config, cfg_obj_t *zconfig, cfg_obj_t *vconfig, goto cleanup; } + /* + * "delegation-only zones" aren't zones either. + */ + if (strcasecmp(ztypestr, "delegation-only") == 0) { + result = dns_view_adddelegationonly(view, origin); + goto cleanup; + } + /* * Check for duplicates in the new zone table. */ @@ -1443,6 +1452,16 @@ configure_zone(cfg_obj_t *config, cfg_obj_t *zconfig, cfg_obj_t *vconfig, forwardtype)); } + /* + * Stub and forward zones may also refer to delegation only points. + */ + only = NULL; + if (cfg_map_get(zoptions, "delegation-only", &only) == ISC_R_SUCCESS) + { + if (cfg_obj_asboolean(only)) + CHECK(dns_view_adddelegationonly(view, origin)); + } + /* * Configure the zone. */ diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml index f43713f8d0..1c9a3f6819 100644 --- a/doc/arm/Bv9ARM-book.xml +++ b/doc/arm/Bv9ARM-book.xml @@ -2,7 +2,7 @@ - + BIND 9 Administrator Reference Manual @@ -2634,6 +2634,14 @@ in remote servers, discovered by BIND 9 when trying to query those servers during resolution. + +delegation-only +Delegation only. Logs queries that have have +been forced to NXDOMAIN as the result of a delegation-only zone or +a delegation-only in a stub or forward +zone declartation. + + @@ -4428,7 +4436,7 @@ view "external" { <command>zone</command> Statement Grammar zone zone_name class { - type ( master | slave | hint | stub | forward ) ; + type ( master | slave | hint | stub | forward /| delegation-only ) ; allow-notify { address_match_list } ; allow-query { address_match_list } ; allow-transfer { address_match_list } ; @@ -4438,6 +4446,7 @@ Statement Grammar also-notify { ip_addr port ip_port ; ip_addr port ip_port ; ... }; check-names (warn|fail|ignore) ; dialup dialup_option ; + delegation-only yes_or_no ; file string ; forward (only|first) ; forwarders { ip_addr port ip_port ; ip_addr port ip_port ; ... }; @@ -4567,6 +4576,14 @@ list of root name servers. If no hint zone is specified for class IN, the server uses a compiled-in default set of root servers hints. Classes other than IN have no built-in defaults hints. + +delegation-only +This is used to enforce the delegation only +status of infrastructure zones (e.g. COM, NET, ORG). Any answer that +is received without a explicit or implict delegation in the authority +section will be treated as NXDOMAIN. This does not apply to the zone +apex. This SHOULD NOT be applied to leaf zones. + @@ -4663,6 +4680,13 @@ with the distribution but none are linked in by default. dialup in . +delegation-only +The flag only applies to forward and stub zones. If set +to yes then the zone will also be treated as if it +is also a delegation-only type zone. + + + forward Only meaningful if the zone has a forwarders list. The only value causes the lookup to fail diff --git a/lib/bind9/check.c b/lib/bind9/check.c index 9e273e5096..a285e1a338 100644 --- a/lib/bind9/check.c +++ b/lib/bind9/check.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: check.c,v 1.37 2003/07/18 06:00:41 marka Exp $ */ +/* $Id: check.c,v 1.38 2003/09/17 05:24:42 marka Exp $ */ #include @@ -407,6 +407,7 @@ validate_masters(cfg_obj_t *obj, cfg_obj_t *config, isc_uint32_t *countp, #define STUBZONE 4 #define HINTZONE 8 #define FORWARDZONE 16 +#define DELEGATIONZONE 32 typedef struct { const char *name; @@ -437,6 +438,7 @@ check_zoneconf(cfg_obj_t *zconfig, cfg_obj_t *config, isc_symtab_t *symtab, { "notify", MASTERZONE | SLAVEZONE }, { "also-notify", MASTERZONE | SLAVEZONE }, { "dialup", MASTERZONE | SLAVEZONE | STUBZONE }, + { "delegation-only", STUBZONE | FORWARDZONE}, { "forward", MASTERZONE | SLAVEZONE | STUBZONE | FORWARDZONE}, { "forwarders", MASTERZONE | SLAVEZONE | STUBZONE | FORWARDZONE}, { "maintain-ixfr-base", MASTERZONE | SLAVEZONE }, @@ -497,6 +499,8 @@ check_zoneconf(cfg_obj_t *zconfig, cfg_obj_t *config, isc_symtab_t *symtab, ztype = FORWARDZONE; else if (strcasecmp(typestr, "hint") == 0) ztype = HINTZONE; + else if (strcasecmp(typestr, "delegation-only") == 0) + ztype = DELEGATIONZONE; else { cfg_obj_log(obj, logctx, ISC_LOG_ERROR, "zone '%s': invalid type %s", diff --git a/lib/dns/include/dns/log.h b/lib/dns/include/dns/log.h index e08ad9b4f9..525a0abdf9 100644 --- a/lib/dns/include/dns/log.h +++ b/lib/dns/include/dns/log.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: log.h,v 1.31 2001/10/11 01:16:18 gson Exp $ */ +/* $Id: log.h,v 1.32 2003/09/17 05:24:43 marka Exp $ */ /* Principal Authors: DCL */ @@ -39,6 +39,7 @@ LIBDNS_EXTERNAL_DATA extern isc_logmodule_t dns_modules[]; #define DNS_LOGCATEGORY_XFER_OUT (&dns_categories[7]) #define DNS_LOGCATEGORY_DISPATCH (&dns_categories[8]) #define DNS_LOGCATEGORY_LAME_SERVERS (&dns_categories[9]) +#define DNS_LOGCATEGORY_DELEGATION_ONLY (&dns_categories[10]) /* Backwards compatibility. */ #define DNS_LOGCATEGORY_GENERAL ISC_LOGCATEGORY_GENERAL diff --git a/lib/dns/include/dns/view.h b/lib/dns/include/dns/view.h index af43f114af..d2a4fa4d5e 100644 --- a/lib/dns/include/dns/view.h +++ b/lib/dns/include/dns/view.h @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: view.h,v 1.82 2003/07/25 02:22:25 marka Exp $ */ +/* $Id: view.h,v 1.83 2003/09/17 05:24:43 marka Exp $ */ #ifndef DNS_VIEW_H #define DNS_VIEW_H 1 @@ -119,6 +119,7 @@ struct dns_view { dns_aclenv_t aclenv; dns_rdatatype_t preferred_glue; isc_boolean_t flush; + dns_namelist_t * delonly; /* * Configurable data for server use only, @@ -715,6 +716,35 @@ dns_view_flushname(dns_view_t *view, dns_name_t *); * other returns are failures. */ +isc_result_t +dns_view_adddelegationonly(dns_view_t *view, dns_name_t *name); +/* + * Add the given name to the delegation only table. + * + * Requires: + * 'view' is valid. + * 'name' is valid. + * + * Returns: + * ISC_R_SUCCESS + * ISC_R_NOMEMORY + */ + +isc_boolean_t +dns_view_isdelegationonly(dns_view_t *view, dns_name_t *name); +/* + * Check if 'name' is in the delegation only table. + * + * Requires: + * 'view' is valid. + * 'name' is valid. + * + * Returns: + * ISC_TRUE if the name is is the table. + * ISC_FALSE othewise. + */ + + ISC_LANG_ENDDECLS #endif /* DNS_VIEW_H */ diff --git a/lib/dns/log.c b/lib/dns/log.c index e738e53216..b64aa89f53 100644 --- a/lib/dns/log.c +++ b/lib/dns/log.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: log.c,v 1.34 2001/10/11 01:16:17 gson Exp $ */ +/* $Id: log.c,v 1.35 2003/09/17 05:24:42 marka Exp $ */ /* Principal Authors: DCL */ @@ -40,6 +40,7 @@ LIBDNS_EXTERNAL_DATA isc_logcategory_t dns_categories[] = { { "xfer-out", 0 }, { "dispatch", 0 }, { "lame-servers", 0 }, + { "delegation-only", 0 }, { NULL, 0 } }; diff --git a/lib/dns/ncache.c b/lib/dns/ncache.c index 67a029fbe6..bba7ab0ecd 100644 --- a/lib/dns/ncache.c +++ b/lib/dns/ncache.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: ncache.c,v 1.32 2003/02/26 23:52:29 marka Exp $ */ +/* $Id: ncache.c,v 1.33 2003/09/17 05:24:42 marka Exp $ */ #include @@ -121,7 +121,10 @@ dns_ncache_add(dns_message_t *message, dns_db_t *cache, dns_dbnode_t *node, ttl = maxttl; trust = 0xffff; isc_buffer_init(&buffer, data, sizeof(data)); - result = dns_message_firstname(message, DNS_SECTION_AUTHORITY); + if (message->counts[DNS_SECTION_AUTHORITY]) + result = dns_message_firstname(message, DNS_SECTION_AUTHORITY); + else + result = ISC_R_NOMORE; while (result == ISC_R_SUCCESS) { name = NULL; dns_message_currentname(message, DNS_SECTION_AUTHORITY, diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index 6d73b8883b..54c42dab5c 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: resolver.c,v 1.264 2003/07/18 04:30:01 marka Exp $ */ +/* $Id: resolver.c,v 1.265 2003/09/17 05:24:42 marka Exp $ */ #include @@ -326,6 +326,53 @@ static isc_result_t ncache_adderesult(dns_message_t *message, dns_rdataset_t *ardataset, isc_result_t *eresultp); +static isc_boolean_t +fix_mustbedelegationornxdomain(dns_message_t *message, dns_name_t *domain) { + + dns_name_t *name; + dns_rdataset_t *rdataset; + dns_rdatatype_t type; + isc_result_t result; + isc_boolean_t keep_auth = ISC_FALSE; + + if (message->rcode == dns_rcode_nxdomain) + return (ISC_FALSE); + + /* Look for referral. */ + if (message->counts[DNS_SECTION_AUTHORITY] == 0) + goto munge; + + result = dns_message_firstname(message, DNS_SECTION_AUTHORITY); + while (result == ISC_R_SUCCESS) { + name = NULL; + dns_message_currentname(message, DNS_SECTION_AUTHORITY, + &name); + for (rdataset = ISC_LIST_HEAD(name->list); + rdataset != NULL; + rdataset = ISC_LIST_NEXT(rdataset, link)) { + type = rdataset->type; + if (type == dns_rdatatype_soa && + dns_name_equal(name, domain)) + keep_auth = ISC_TRUE; + if (type != dns_rdatatype_ns) + continue; + if (dns_name_equal(name, domain)) + goto munge; + if (dns_name_issubdomain(name, domain)) + return (ISC_FALSE); + } + result = dns_message_nextname(message, DNS_SECTION_AUTHORITY); + } + + munge: + message->rcode = dns_rcode_nxdomain; + message->counts[DNS_SECTION_ANSWER] = 0; + if (!keep_auth) + message->counts[DNS_SECTION_AUTHORITY] = 0; + message->counts[DNS_SECTION_ADDITIONAL] = 0; + return (ISC_TRUE); +} + static inline isc_result_t fctx_starttimer(fetchctx_t *fctx) { /* @@ -4917,6 +4964,24 @@ resquery_response(isc_task_t *task, isc_event_t *event) { goto done; } + /* + * Enforce delegations only zones like NET and COM. + */ + if (dns_view_isdelegationonly(fctx->res->view, &fctx->domain) && + !dns_name_equal(&fctx->domain, &fctx->name) && + fix_mustbedelegationornxdomain(message, &fctx->domain)) { + char namebuf[DNS_NAME_FORMATSIZE]; + char domainbuf[DNS_NAME_FORMATSIZE]; + + dns_name_format(&fctx->name, namebuf, sizeof(namebuf)); + dns_name_format(&fctx->domain, domainbuf, sizeof(domainbuf)); + + isc_log_write(dns_lctx, DNS_LOGCATEGORY_DELEGATION_ONLY, + DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE, + "enforced delegation-only for '%s' (%s)", + domainbuf, namebuf); + } + /* * Did we get any answers? */ diff --git a/lib/dns/view.c b/lib/dns/view.c index 322a55ab74..9b4b7d20cc 100644 --- a/lib/dns/view.c +++ b/lib/dns/view.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: view.c,v 1.116 2003/07/25 02:22:24 marka Exp $ */ +/* $Id: view.c,v 1.117 2003/09/17 05:24:43 marka Exp $ */ #include @@ -47,6 +47,8 @@ #define ADBSHUTDOWN(v) (((v)->attributes & DNS_VIEWATTR_ADBSHUTDOWN) != 0) #define REQSHUTDOWN(v) (((v)->attributes & DNS_VIEWATTR_REQSHUTDOWN) != 0) +#define DNS_VIEW_DELONLYHASH 111 + static void resolver_shutdown(isc_task_t *task, isc_event_t *event); static void adb_shutdown(isc_task_t *task, isc_event_t *event); static void req_shutdown(isc_task_t *task, isc_event_t *event); @@ -142,6 +144,7 @@ dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, goto cleanup_fwdtable; view->peers = NULL; view->order = NULL; + view->delonly = NULL; /* * Initialize configuration data with default values. @@ -265,6 +268,23 @@ destroy(dns_view_t *view) { dns_acl_detach(&view->recursionacl); if (view->sortlist != NULL) dns_acl_detach(&view->sortlist); + if (view->delonly != NULL) { + dns_name_t *name; + int i; + + for (i = 0; i < DNS_VIEW_DELONLYHASH; i++) { + name = ISC_LIST_HEAD(view->delonly[i]); + while (name != NULL) { + ISC_LIST_UNLINK(view->delonly[i], name, link); + dns_name_free(name, view->mctx); + isc_mem_put(view->mctx, name, sizeof(*name)); + name = ISC_LIST_HEAD(view->delonly[i]); + } + } + isc_mem_put(view->mctx, view->delonly, sizeof(dns_namelist_t) * + DNS_VIEW_DELONLYHASH); + view->delonly = NULL; + } dns_keytable_detach(&view->trustedkeys); dns_keytable_detach(&view->secroots); dns_fwdtable_destroy(&view->fwdtable); @@ -1168,3 +1188,57 @@ dns_view_flushname(dns_view_t *view, dns_name_t *name) { return (ISC_R_SUCCESS); return (dns_cache_flushname(view->cache, name)); } + +isc_result_t +dns_view_adddelegationonly(dns_view_t *view, dns_name_t *name) { + isc_result_t result; + dns_name_t *new; + isc_uint32_t hash; + + REQUIRE(DNS_VIEW_VALID(view)); + + if (view->delonly == NULL) { + view->delonly = isc_mem_get(view->mctx, + sizeof(dns_namelist_t) * + DNS_VIEW_DELONLYHASH); + if (view->delonly == NULL) + return (ISC_R_NOMEMORY); + for (hash = 0; hash < DNS_VIEW_DELONLYHASH; hash++) + ISC_LIST_INIT(view->delonly[hash]); + } + hash = dns_name_hash(name, ISC_FALSE) % DNS_VIEW_DELONLYHASH; + new = ISC_LIST_HEAD(view->delonly[hash]); + while (new != NULL && !dns_name_equal(new, name)) + new = ISC_LIST_NEXT(new, link); + if (new != NULL) + return (ISC_R_SUCCESS); + new = isc_mem_get(view->mctx, sizeof(*new)); + if (new == NULL) + return (ISC_R_NOMEMORY); + dns_name_init(new, NULL); + result = dns_name_dup(name, view->mctx, new); + if (result == ISC_R_SUCCESS) + ISC_LIST_APPEND(view->delonly[hash], new, link); + else + isc_mem_put(view->mctx, new, sizeof(*new)); + return (result); +} + +isc_result_t +dns_view_isdelegationonly(dns_view_t *view, dns_name_t *name) { + dns_name_t *new; + isc_uint32_t hash; + + REQUIRE(DNS_VIEW_VALID(view)); + + if (view->delonly == NULL) + return (ISC_FALSE); + + hash = dns_name_hash(name, ISC_FALSE) % DNS_VIEW_DELONLYHASH; + new = ISC_LIST_HEAD(view->delonly[hash]); + while (new != NULL && !dns_name_equal(new, name)) + new = ISC_LIST_NEXT(new, link); + if (new == NULL) + return (ISC_FALSE); + return (ISC_TRUE); +} diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c index 874bcf7d27..dfc791b8a8 100644 --- a/lib/isccfg/namedconf.c +++ b/lib/isccfg/namedconf.c @@ -15,7 +15,7 @@ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: namedconf.c,v 1.21 2003/04/17 03:26:58 marka Exp $ */ +/* $Id: namedconf.c,v 1.22 2003/09/17 05:24:43 marka Exp $ */ #include @@ -390,7 +390,7 @@ static cfg_type_t cfg_type_forwardtype = { }; static const char *zonetype_enums[] = { - "master", "slave", "stub", "hint", "forward", NULL }; + "master", "slave", "stub", "hint", "forward", "delegation-only", NULL }; static cfg_type_t cfg_type_zonetype = { "zonetype", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum, &cfg_rep_string, &zonetype_enums @@ -720,6 +720,7 @@ zone_only_clauses[] = { CFG_CLAUSEFLAG_MULTI | CFG_CLAUSEFLAG_OBSOLETE }, { "update-policy", &cfg_type_updatepolicy, 0 }, { "database", &cfg_type_astring, 0 }, + { "delegation-only", &cfg_type_boolean, 0 }, /* * Note that the format of the check-names option is different between * the zone options and the global/view options. Ugh.