diff options
Diffstat (limited to 'contrib/bind9/lib/bind9/check.c')
-rw-r--r-- | contrib/bind9/lib/bind9/check.c | 549 |
1 files changed, 458 insertions, 91 deletions
diff --git a/contrib/bind9/lib/bind9/check.c b/contrib/bind9/lib/bind9/check.c index 76ca510..6fa9aa9 100644 --- a/contrib/bind9/lib/bind9/check.c +++ b/contrib/bind9/lib/bind9/check.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2010 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2001-2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: check.c,v 1.95.12.6 2010-03-04 23:47:53 tbox Exp $ */ +/* $Id: check.c,v 1.125 2011-01-07 23:47:07 tbox Exp $ */ /*! \file */ @@ -103,7 +103,7 @@ check_orderent(const cfg_obj_t *ent, isc_log_t *logctx) { isc_buffer_init(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); tresult = dns_name_fromtext(dns_fixedname_name(&fixed), &b, - dns_rootname, ISC_FALSE, NULL); + dns_rootname, 0, NULL); if (tresult != ISC_R_SUCCESS) { cfg_obj_log(obj, logctx, ISC_LOG_ERROR, "rrset-order: invalid name '%s'", str); @@ -202,7 +202,7 @@ check_dual_stack(const cfg_obj_t *options, isc_log_t *logctx) { dns_fixedname_init(&fixed); name = dns_fixedname_name(&fixed); tresult = dns_name_fromtext(name, &buffer, dns_rootname, - ISC_FALSE, NULL); + 0, NULL); if (tresult != ISC_R_SUCCESS) { cfg_obj_log(obj, logctx, ISC_LOG_ERROR, "bad name '%s'", str); @@ -265,7 +265,7 @@ disabled_algorithms(const cfg_obj_t *disabled, isc_log_t *logctx) { str = cfg_obj_asstring(obj); isc_buffer_init(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); - tresult = dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL); + tresult = dns_name_fromtext(name, &b, dns_rootname, 0, NULL); if (tresult != ISC_R_SUCCESS) { cfg_obj_log(obj, logctx, ISC_LOG_ERROR, "bad domain name '%s'", str); @@ -352,7 +352,7 @@ mustbesecure(const cfg_obj_t *secure, isc_symtab_t *symtab, isc_log_t *logctx, str = cfg_obj_asstring(obj); isc_buffer_init(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); - result = dns_name_fromtext(name, &b, dns_rootname, ISC_FALSE, NULL); + result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) { cfg_obj_log(obj, logctx, ISC_LOG_ERROR, "bad domain name '%s'", str); @@ -407,7 +407,7 @@ check_viewacls(cfg_aclconfctx_t *actx, const cfg_obj_t *voptions, static const char *acls[] = { "allow-query", "allow-query-on", "allow-query-cache", "allow-query-cache-on", "blackhole", "match-clients", "match-destinations", - "sortlist", NULL }; + "sortlist", "filter-aaaa", NULL }; while (acls[i] != NULL) { tresult = checkacl(acls[i++], actx, NULL, voptions, config, @@ -418,6 +418,106 @@ check_viewacls(cfg_aclconfctx_t *actx, const cfg_obj_t *voptions, return (result); } +static const unsigned char zeros[16]; + +static isc_result_t +check_dns64(cfg_aclconfctx_t *actx, const cfg_obj_t *voptions, + const cfg_obj_t *config, isc_log_t *logctx, isc_mem_t *mctx) +{ + isc_result_t result = ISC_R_SUCCESS; + const cfg_obj_t *dns64 = NULL; + const cfg_obj_t *options; + const cfg_listelt_t *element; + const cfg_obj_t *map, *obj; + isc_netaddr_t na, sa; + unsigned int prefixlen; + int nbytes; + int i; + + static const char *acls[] = { "client", "exclude", "mapped", NULL}; + + if (voptions != NULL) + cfg_map_get(voptions, "dns64", &dns64); + if (config != NULL && dns64 == NULL) { + options = NULL; + cfg_map_get(config, "options", &options); + if (options != NULL) + cfg_map_get(options, "dns64", &dns64); + } + if (dns64 == NULL) + return (ISC_R_SUCCESS); + + for (element = cfg_list_first(dns64); + element != NULL; + element = cfg_list_next(element)) + { + map = cfg_listelt_value(element); + obj = cfg_map_getname(map); + + cfg_obj_asnetprefix(obj, &na, &prefixlen); + if (na.family != AF_INET6) { + cfg_obj_log(map, logctx, ISC_LOG_ERROR, + "dns64 requires a IPv6 prefix"); + result = ISC_R_FAILURE; + continue; + } + + if (prefixlen != 32 && prefixlen != 40 && prefixlen != 48 && + prefixlen != 56 && prefixlen != 64 && prefixlen != 96) { + cfg_obj_log(map, logctx, ISC_LOG_ERROR, + "bad prefix length %u [32/40/48/56/64/96]", + prefixlen); + result = ISC_R_FAILURE; + continue; + } + + for (i = 0; acls[i] != NULL; i++) { + obj = NULL; + (void)cfg_map_get(map, acls[i], &obj); + if (obj != NULL) { + dns_acl_t *acl = NULL; + isc_result_t tresult; + + tresult = cfg_acl_fromconfig(obj, config, + logctx, actx, + mctx, 0, &acl); + if (acl != NULL) + dns_acl_detach(&acl); + if (tresult != ISC_R_SUCCESS) + result = tresult; + } + } + + obj = NULL; + (void)cfg_map_get(map, "suffix", &obj); + if (obj != NULL) { + isc_netaddr_fromsockaddr(&sa, cfg_obj_assockaddr(obj)); + if (sa.family != AF_INET6) { + cfg_obj_log(map, logctx, ISC_LOG_ERROR, + "dns64 requires a IPv6 suffix"); + result = ISC_R_FAILURE; + continue; + } + nbytes = prefixlen / 8 + 4; + if (prefixlen >= 32 && prefixlen <= 64) + nbytes++; + if (memcmp(sa.type.in6.s6_addr, zeros, nbytes) != 0) { + char netaddrbuf[ISC_NETADDR_FORMATSIZE]; + isc_netaddr_format(&sa, netaddrbuf, + sizeof(netaddrbuf)); + cfg_obj_log(obj, logctx, ISC_LOG_ERROR, + "bad suffix '%s' leading " + "%u octets not zeros", + netaddrbuf, nbytes); + result = ISC_R_FAILURE; + } + } + } + + return (result); +} + + /* * Check allow-recursion and allow-recursion-on acls, and also log a * warning if they're inconsistent with the "recursion" option. @@ -493,6 +593,78 @@ check_recursionacls(cfg_aclconfctx_t *actx, const cfg_obj_t *voptions, return (result); } +static isc_result_t +check_filteraaaa(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; + dns_v4_aaaa_t filter; + const char *forview = " for view "; + + if (voptions != NULL) + cfg_map_get(voptions, "filter-aaaa-on-v4", &obj); + if (obj == NULL && config != NULL) { + options = NULL; + cfg_map_get(config, "options", &options); + if (options != NULL) + cfg_map_get(options, "filter-aaaa-on-v4", &obj); + } + + if (obj == NULL) + filter = dns_v4_aaaa_ok; /* default */ + else if (cfg_obj_isboolean(obj)) + filter = cfg_obj_asboolean(obj) ? dns_v4_aaaa_filter : + dns_v4_aaaa_ok; + else + filter = dns_v4_aaaa_break_dnssec; /* break-dnssec */ + + if (viewname == NULL) { + viewname = ""; + forview = ""; + } + + aclobj = options = NULL; + acl = NULL; + + if (voptions != NULL) + cfg_map_get(voptions, "filter-aaaa", &aclobj); + if (config != NULL && aclobj == NULL) { + options = NULL; + cfg_map_get(config, "options", &options); + if (options != NULL) + cfg_map_get(options, "filter-aaaa", &aclobj); + } + if (aclobj == NULL) + return (result); + + tresult = cfg_acl_fromconfig(aclobj, config, logctx, + actx, mctx, 0, &acl); + + if (tresult != ISC_R_SUCCESS) { + result = tresult; + } else if (filter != dns_v4_aaaa_ok && dns_acl_isnone(acl)) { + cfg_obj_log(aclobj, logctx, ISC_LOG_WARNING, + "both \"filter-aaaa-on-v4 %s;\" and " + "\"filter-aaaa\" is 'none;'%s%s", + filter == dns_v4_aaaa_break_dnssec ? + "break-dnssec" : "yes", forview, viewname); + result = ISC_R_FAILURE; + } else if (filter == dns_v4_aaaa_ok && !dns_acl_isnone(acl)) { + cfg_obj_log(aclobj, logctx, ISC_LOG_WARNING, + "both \"filter-aaaa-on-v4 no;\" and " + "\"filter-aaaa\" is set%s%s", forview, viewname); + result = ISC_R_FAILURE; + } + + if (acl != NULL) + dns_acl_detach(&acl); + + return (result); +} + typedef struct { const char *name; unsigned int scale; @@ -524,6 +696,12 @@ check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx) { { "statistics-interval", 60, 28 * 24 * 60 }, /* 28 days */ }; + static const char *server_contact[] = { + "empty-server", "empty-contact", + "dns64-server", "dns64-contact", + NULL + }; + /* * Check that fields specified in units of time other than seconds * have reasonable values. @@ -620,7 +798,7 @@ check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx) { isc_buffer_add(&b, strlen(str)); tresult = dns_name_fromtext(name, &b, dns_rootname, - ISC_FALSE, NULL); + 0, NULL); if (tresult != ISC_R_SUCCESS) { cfg_obj_log(obj, logctx, ISC_LOG_ERROR, "bad domain name '%s'", @@ -666,14 +844,24 @@ check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx) { element = cfg_list_next(element)) { const char *dlv; + const cfg_obj_t *anchor; obj = cfg_listelt_value(element); dlv = cfg_obj_asstring(cfg_tuple_get(obj, "domain")); + anchor = cfg_tuple_get(obj, "trust-anchor"); + + /* + * If domain is "auto" and trust anchor is missing, + * skip remaining tests + */ + if (!strcmp(dlv, "auto") && cfg_obj_isvoid(anchor)) + continue; + isc_buffer_init(&b, dlv, strlen(dlv)); isc_buffer_add(&b, strlen(dlv)); tresult = dns_name_fromtext(name, &b, dns_rootname, - ISC_TRUE, NULL); + 0, NULL); if (tresult != ISC_R_SUCCESS) { cfg_obj_log(obj, logctx, ISC_LOG_ERROR, "bad domain name '%s'", dlv); @@ -701,19 +889,32 @@ check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx) { if (result == ISC_R_SUCCESS) result = ISC_R_FAILURE; } - dlv = cfg_obj_asstring(cfg_tuple_get(obj, - "trust-anchor")); - isc_buffer_init(&b, dlv, strlen(dlv)); - isc_buffer_add(&b, strlen(dlv)); - tresult = dns_name_fromtext(name, &b, dns_rootname, - ISC_TRUE, NULL); - if (tresult != ISC_R_SUCCESS) { + + if (!cfg_obj_isvoid(anchor)) { + dlv = cfg_obj_asstring(anchor); + isc_buffer_init(&b, dlv, strlen(dlv)); + isc_buffer_add(&b, strlen(dlv)); + tresult = dns_name_fromtext(name, &b, + dns_rootname, + DNS_NAME_DOWNCASE, + NULL); + if (tresult != ISC_R_SUCCESS) { + cfg_obj_log(obj, logctx, ISC_LOG_ERROR, + "bad domain name '%s'", + dlv); + if (result == ISC_R_SUCCESS) + result = tresult; + } + } else { cfg_obj_log(obj, logctx, ISC_LOG_ERROR, - "bad domain name '%s'", dlv); + "dnssec-lookaside requires " + "either 'auto' or a domain and " + "trust anchor"); if (result == ISC_R_SUCCESS) - result = tresult; + result = ISC_R_FAILURE; } } + if (symtab != NULL) isc_symtab_destroy(&symtab); } @@ -743,38 +944,29 @@ check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx) { } /* - * Check empty zone configuration. + * Check server/contacts for syntactic validity. */ - obj = NULL; - (void)cfg_map_get(options, "empty-server", &obj); - if (obj != NULL) { - str = cfg_obj_asstring(obj); - isc_buffer_init(&b, str, strlen(str)); - isc_buffer_add(&b, strlen(str)); - tresult = dns_name_fromtext(dns_fixedname_name(&fixed), &b, - dns_rootname, ISC_FALSE, NULL); - if (tresult != ISC_R_SUCCESS) { - cfg_obj_log(obj, logctx, ISC_LOG_ERROR, - "empty-server: invalid name '%s'", str); - result = ISC_R_FAILURE; - } - } - - obj = NULL; - (void)cfg_map_get(options, "empty-contact", &obj); - if (obj != NULL) { - str = cfg_obj_asstring(obj); - isc_buffer_init(&b, str, strlen(str)); - isc_buffer_add(&b, strlen(str)); - tresult = dns_name_fromtext(dns_fixedname_name(&fixed), &b, - dns_rootname, ISC_FALSE, NULL); - if (tresult != ISC_R_SUCCESS) { - cfg_obj_log(obj, logctx, ISC_LOG_ERROR, - "empty-contact: invalid name '%s'", str); - result = ISC_R_FAILURE; + for (i= 0; server_contact[i] != NULL; i++) { + obj = NULL; + (void)cfg_map_get(options, server_contact[i], &obj); + if (obj != NULL) { + str = cfg_obj_asstring(obj); + isc_buffer_init(&b, str, strlen(str)); + isc_buffer_add(&b, strlen(str)); + tresult = dns_name_fromtext(dns_fixedname_name(&fixed), + &b, dns_rootname, 0, NULL); + if (tresult != ISC_R_SUCCESS) { + cfg_obj_log(obj, logctx, ISC_LOG_ERROR, + "%s: invalid name '%s'", + server_contact[i], str); + result = ISC_R_FAILURE; + } } } + /* + * Check empty zone configuration. + */ obj = NULL; (void)cfg_map_get(options, "disable-empty-zone", &obj); for (element = cfg_list_first(obj); @@ -786,7 +978,7 @@ check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx) { isc_buffer_init(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); tresult = dns_name_fromtext(dns_fixedname_name(&fixed), &b, - dns_rootname, ISC_FALSE, NULL); + dns_rootname, 0, NULL); if (tresult != ISC_R_SUCCESS) { cfg_obj_log(obj, logctx, ISC_LOG_ERROR, "disable-empty-zone: invalid name '%s'", @@ -950,6 +1142,12 @@ check_update_policy(const cfg_obj_t *policy, isc_log_t *logctx) { const char *str; isc_buffer_t b; + /* Check for "update-policy local;" */ + if (cfg_obj_isstring(policy) && + strcmp("local", cfg_obj_asstring(policy)) == 0) + return (ISC_R_SUCCESS); + + /* Now check the grant policy */ for (element = cfg_list_first(policy); element != NULL; element = cfg_list_next(element)) @@ -965,24 +1163,28 @@ check_update_policy(const cfg_obj_t *policy, isc_log_t *logctx) { isc_buffer_init(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); tresult = dns_name_fromtext(dns_fixedname_name(&fixed), &b, - dns_rootname, ISC_FALSE, NULL); + dns_rootname, 0, NULL); if (tresult != ISC_R_SUCCESS) { cfg_obj_log(identity, logctx, ISC_LOG_ERROR, "'%s' is not a valid name", str); result = tresult; } - dns_fixedname_init(&fixed); - str = cfg_obj_asstring(dname); - isc_buffer_init(&b, str, strlen(str)); - isc_buffer_add(&b, strlen(str)); - tresult = dns_name_fromtext(dns_fixedname_name(&fixed), &b, - dns_rootname, ISC_FALSE, NULL); - if (tresult != ISC_R_SUCCESS) { - cfg_obj_log(dname, logctx, ISC_LOG_ERROR, - "'%s' is not a valid name", str); - result = tresult; + if (tresult == ISC_R_SUCCESS && + strcasecmp(cfg_obj_asstring(matchtype), "zonesub") != 0) { + dns_fixedname_init(&fixed); + str = cfg_obj_asstring(dname); + isc_buffer_init(&b, str, strlen(str)); + isc_buffer_add(&b, strlen(str)); + tresult = dns_name_fromtext(dns_fixedname_name(&fixed), + &b, dns_rootname, 0, NULL); + if (tresult != ISC_R_SUCCESS) { + cfg_obj_log(dname, logctx, ISC_LOG_ERROR, + "'%s' is not a valid name", str); + result = tresult; + } } + if (tresult == ISC_R_SUCCESS && strcasecmp(cfg_obj_asstring(matchtype), "wildcard") == 0 && !dns_name_iswildcard(dns_fixedname_name(&fixed))) { @@ -1020,7 +1222,8 @@ check_update_policy(const cfg_obj_t *policy, isc_log_t *logctx) { #define HINTZONE 8 #define FORWARDZONE 16 #define DELEGATIONZONE 32 -#define CHECKACL 64 +#define STATICSTUBZONE 64 +#define CHECKACL 128 typedef struct { const char *name; @@ -1033,7 +1236,7 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, dns_rdataclass_t defclass, cfg_aclconfctx_t *actx, isc_log_t *logctx, isc_mem_t *mctx) { - const char *zname; + const char *znamestr; const char *typestr; unsigned int ztype; const cfg_obj_t *zoptions; @@ -1043,11 +1246,14 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, unsigned int i; dns_rdataclass_t zclass; dns_fixedname_t fixedname; + dns_name_t *zname = NULL; isc_buffer_t b; isc_boolean_t root = ISC_FALSE; + const cfg_listelt_t *element; static optionstable options[] = { - { "allow-query", MASTERZONE | SLAVEZONE | STUBZONE | CHECKACL }, + { "allow-query", MASTERZONE | SLAVEZONE | STUBZONE | CHECKACL | + STATICSTUBZONE }, { "allow-notify", SLAVEZONE | CHECKACL }, { "allow-transfer", MASTERZONE | SLAVEZONE | CHECKACL }, { "notify", MASTERZONE | SLAVEZONE }, @@ -1070,12 +1276,14 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, { "min-retry-time", SLAVEZONE | STUBZONE }, { "max-refresh-time", SLAVEZONE | STUBZONE }, { "min-refresh-time", SLAVEZONE | STUBZONE }, + { "dnssec-secure-to-insecure", MASTERZONE }, { "sig-validity-interval", MASTERZONE }, { "sig-re-signing-interval", MASTERZONE }, { "sig-signing-nodes", MASTERZONE }, { "sig-signing-type", MASTERZONE }, { "sig-signing-signatures", MASTERZONE }, - { "zone-statistics", MASTERZONE | SLAVEZONE | STUBZONE }, + { "zone-statistics", MASTERZONE | SLAVEZONE | STUBZONE | + STATICSTUBZONE}, { "allow-update", MASTERZONE | CHECKACL }, { "allow-update-forwarding", SLAVEZONE | CHECKACL }, { "file", MASTERZONE | SLAVEZONE | STUBZONE | HINTZONE }, @@ -1089,12 +1297,17 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, { "key-directory", MASTERZONE }, { "check-wildcard", MASTERZONE }, { "check-mx", MASTERZONE }, + { "check-dup-records", MASTERZONE }, { "integrity-check", MASTERZONE }, { "check-mx-cname", MASTERZONE }, { "check-srv-cname", MASTERZONE }, { "masterfile-format", MASTERZONE | SLAVEZONE | STUBZONE | HINTZONE }, { "update-check-ksk", MASTERZONE }, + { "dnssec-dnskey-kskonly", MASTERZONE }, + { "auto-dnssec", MASTERZONE }, { "try-tcp-refresh", SLAVEZONE }, + { "server-addresses", STATICSTUBZONE }, + { "server-names", STATICSTUBZONE }, }; static optionstable dialups[] = { @@ -1104,7 +1317,7 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, { "passive", SLAVEZONE | STUBZONE }, }; - zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name")); + znamestr = cfg_obj_asstring(cfg_tuple_get(zconfig, "name")); zoptions = cfg_tuple_get(zconfig, "options"); @@ -1112,7 +1325,7 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, (void)cfg_map_get(zoptions, "type", &obj); if (obj == NULL) { cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR, - "zone '%s': type not present", zname); + "zone '%s': type not present", znamestr); return (ISC_R_FAILURE); } @@ -1123,6 +1336,8 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, ztype = SLAVEZONE; else if (strcasecmp(typestr, "stub") == 0) ztype = STUBZONE; + else if (strcasecmp(typestr, "static-stub") == 0) + ztype = STATICSTUBZONE; else if (strcasecmp(typestr, "forward") == 0) ztype = FORWARDZONE; else if (strcasecmp(typestr, "hint") == 0) @@ -1132,7 +1347,7 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, else { cfg_obj_log(obj, logctx, ISC_LOG_ERROR, "zone '%s': invalid type %s", - zname, typestr); + znamestr, typestr); return (ISC_R_FAILURE); } @@ -1146,14 +1361,14 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, if (result != ISC_R_SUCCESS) { cfg_obj_log(obj, logctx, ISC_LOG_ERROR, "zone '%s': invalid class %s", - zname, r.base); + znamestr, r.base); return (ISC_R_FAILURE); } if (zclass != defclass) { cfg_obj_log(obj, logctx, ISC_LOG_ERROR, "zone '%s': class '%s' does not " "match view/default class", - zname, r.base); + znamestr, r.base); return (ISC_R_FAILURE); } } @@ -1164,26 +1379,25 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, * deals with strings. */ dns_fixedname_init(&fixedname); - isc_buffer_init(&b, zname, strlen(zname)); - isc_buffer_add(&b, strlen(zname)); + isc_buffer_init(&b, znamestr, strlen(znamestr)); + isc_buffer_add(&b, strlen(znamestr)); tresult = dns_name_fromtext(dns_fixedname_name(&fixedname), &b, - dns_rootname, ISC_TRUE, NULL); + dns_rootname, DNS_NAME_DOWNCASE, NULL); if (tresult != ISC_R_SUCCESS) { cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR, - "zone '%s': is not a valid name", zname); + "zone '%s': is not a valid name", znamestr); result = ISC_R_FAILURE; } else { char namebuf[DNS_NAME_FORMATSIZE]; - dns_name_format(dns_fixedname_name(&fixedname), - namebuf, sizeof(namebuf)); + zname = dns_fixedname_name(&fixedname); + dns_name_format(zname, namebuf, sizeof(namebuf)); tresult = nameexist(zconfig, namebuf, ztype == HINTZONE ? 1 : 2, symtab, "zone '%s': already exists " "previous definition: %s:%u", logctx, mctx); if (tresult != ISC_R_SUCCESS) result = tresult; - if (dns_name_equal(dns_fixedname_name(&fixedname), - dns_rootname)) + if (dns_name_equal(zname, dns_rootname)) root = ISC_TRUE; } @@ -1202,13 +1416,15 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, cfg_obj_log(obj, logctx, ISC_LOG_ERROR, "option '%s' is not allowed " "in '%s' zone '%s'", - options[i].name, typestr, zname); + options[i].name, typestr, + znamestr); result = ISC_R_FAILURE; } else cfg_obj_log(obj, logctx, ISC_LOG_WARNING, "option '%s' is not allowed " "in '%s' zone '%s'", - options[i].name, typestr, zname); + options[i].name, typestr, + znamestr); } obj = NULL; if ((options[i].allowed & ztype) != 0 && @@ -1230,7 +1446,7 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, if (cfg_map_get(zoptions, "masters", &obj) != ISC_R_SUCCESS) { cfg_obj_log(zoptions, logctx, ISC_LOG_ERROR, "zone '%s': missing 'masters' entry", - zname); + znamestr); result = ISC_R_FAILURE; } else { isc_uint32_t count; @@ -1241,7 +1457,7 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, if (tresult == ISC_R_SUCCESS && count == 0) { cfg_obj_log(zoptions, logctx, ISC_LOG_ERROR, "zone '%s': empty 'masters' entry", - zname); + znamestr); result = ISC_R_FAILURE; } } @@ -1251,7 +1467,10 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, * Master zones can't have both "allow-update" and "update-policy". */ if (ztype == MASTERZONE) { - isc_result_t res1, res2; + isc_result_t res1, res2, res3; + const char *arg; + isc_boolean_t ddns; + obj = NULL; res1 = cfg_map_get(zoptions, "allow-update", &obj); obj = NULL; @@ -1260,11 +1479,32 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, cfg_obj_log(obj, logctx, ISC_LOG_ERROR, "zone '%s': 'allow-update' is ignored " "when 'update-policy' is present", - zname); + znamestr); result = ISC_R_FAILURE; } else if (res2 == ISC_R_SUCCESS && check_update_policy(obj, logctx) != ISC_R_SUCCESS) result = ISC_R_FAILURE; + ddns = ISC_TF(res1 == ISC_R_SUCCESS || res2 == ISC_R_SUCCESS); + + obj = NULL; + arg = "off"; + res3 = cfg_map_get(zoptions, "auto-dnssec", &obj); + if (res3 == ISC_R_SUCCESS) + arg = cfg_obj_asstring(obj); + if (strcasecmp(arg, "off") != 0 && !ddns) { + cfg_obj_log(obj, logctx, ISC_LOG_ERROR, + "'auto-dnssec %s;' requires " + "dynamic DNS to be configured in the zone", + arg); + result = ISC_R_FAILURE; + } + if (strcasecmp(arg, "create") == 0) { + cfg_obj_log(obj, logctx, ISC_LOG_ERROR, + "'auto-dnssec create;' is not " + "yet implemented"); + result = ISC_R_FAILURE; + } + obj = NULL; res1 = cfg_map_get(zoptions, "sig-signing-type", &obj); if (res1 == ISC_R_SUCCESS) { @@ -1298,7 +1538,7 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, "dialup type '%s' is not " "allowed in '%s' " "zone '%s'", - str, typestr, zname); + str, typestr, znamestr); result = ISC_R_FAILURE; } break; @@ -1306,7 +1546,7 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, if (i == sizeof(dialups) / sizeof(dialups[0])) { cfg_obj_log(obj, logctx, ISC_LOG_ERROR, "invalid dialup type '%s' in zone " - "'%s'", str, zname); + "'%s'", str, znamestr); result = ISC_R_FAILURE; } } @@ -1330,6 +1570,78 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, result = ISC_R_FAILURE; /* + * Check validity of static stub server addresses. + */ + obj = NULL; + (void)cfg_map_get(zoptions, "server-addresses", &obj); + if (ztype == STATICSTUBZONE && obj != NULL) { + for (element = cfg_list_first(obj); + element != NULL; + element = cfg_list_next(element)) + { + isc_sockaddr_t sa; + isc_netaddr_t na; + obj = cfg_listelt_value(element); + sa = *cfg_obj_assockaddr(obj); + + if (isc_sockaddr_getport(&sa) != 0) { + result = ISC_R_FAILURE; + cfg_obj_log(obj, logctx, ISC_LOG_ERROR, + "port is not configurable for " + "static stub server-addresses"); + } + + isc_netaddr_fromsockaddr(&na, &sa); + if (isc_netaddr_getzone(&na) != 0) { + result = ISC_R_FAILURE; + cfg_obj_log(obj, logctx, ISC_LOG_ERROR, + "scoped address is not allowed " + "for static stub " + "server-addresses"); + } + } + } + + /* + * Check validity of static stub server names. + */ + obj = NULL; + (void)cfg_map_get(zoptions, "server-names", &obj); + if (zname != NULL && ztype == STATICSTUBZONE && obj != NULL) { + for (element = cfg_list_first(obj); + element != NULL; + element = cfg_list_next(element)) + { + const char *snamestr; + dns_fixedname_t fixed_sname; + isc_buffer_t b2; + dns_name_t *sname; + + obj = cfg_listelt_value(element); + snamestr = cfg_obj_asstring(obj); + + dns_fixedname_init(&fixed_sname); + isc_buffer_init(&b2, snamestr, strlen(snamestr)); + isc_buffer_add(&b2, strlen(snamestr)); + sname = dns_fixedname_name(&fixed_sname); + tresult = dns_name_fromtext(sname, &b2, dns_rootname, + 0, NULL); + if (tresult != ISC_R_SUCCESS) { + cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR, + "server-name '%s' is not a valid " + "name", snamestr); + result = ISC_R_FAILURE; + } else if (dns_name_issubdomain(sname, zname)) { + cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR, + "server-name '%s' must not be a " + "subdomain of zone name '%s'", + snamestr, znamestr); + result = ISC_R_FAILURE; + } + } + } + + /* * Check various options. */ tresult = check_options(zoptions, logctx, mctx); @@ -1352,7 +1664,7 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, (ztype == MASTERZONE || ztype == HINTZONE)) { cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR, "zone '%s': missing 'file' entry", - zname); + znamestr); result = tresult; } } @@ -1374,6 +1686,9 @@ bind9_check_key(const cfg_obj_t *key, isc_log_t *logctx) { const char *algorithm; int i; size_t len = 0; + isc_result_t result; + isc_buffer_t buf; + unsigned char secretbuf[1024]; static const algorithmtable algorithms[] = { { "hmac-md5", 128 }, { "hmac-md5.sig-alg.reg.int", 0 }, @@ -1396,6 +1711,14 @@ bind9_check_key(const cfg_obj_t *key, isc_log_t *logctx) { return (ISC_R_FAILURE); } + isc_buffer_init(&buf, secretbuf, sizeof(secretbuf)); + result = isc_base64_decodestring(cfg_obj_asstring(secretobj), &buf); + if (result != ISC_R_SUCCESS) { + cfg_obj_log(secretobj, logctx, ISC_LOG_ERROR, + "bad secret '%s'", isc_result_totext(result)); + return (result); + } + algorithm = cfg_obj_asstring(algobj); for (i = 0; algorithms[i].name != NULL; i++) { len = strlen(algorithms[i].name); @@ -1480,7 +1803,7 @@ check_keylist(const cfg_obj_t *keys, isc_symtab_t *symtab, isc_buffer_init(&b, keyid, strlen(keyid)); isc_buffer_add(&b, strlen(keyid)); tresult = dns_name_fromtext(name, &b, dns_rootname, - ISC_FALSE, NULL); + 0, NULL); if (tresult != ISC_R_SUCCESS) { cfg_obj_log(key, logctx, ISC_LOG_ERROR, "key '%s': bad key name", keyid); @@ -1650,7 +1973,7 @@ check_servers(const cfg_obj_t *config, const cfg_obj_t *voptions, isc_buffer_add(&b, strlen(keyval)); keyname = dns_fixedname_name(&fname); tresult = dns_name_fromtext(keyname, &b, dns_rootname, - ISC_FALSE, NULL); + 0, NULL); if (tresult != ISC_R_SUCCESS) { cfg_obj_log(keys, logctx, ISC_LOG_ERROR, "bad key name '%s'", keyval); @@ -1670,7 +1993,8 @@ check_servers(const cfg_obj_t *config, const cfg_obj_t *voptions, } static isc_result_t -check_trusted_key(const cfg_obj_t *key, isc_log_t *logctx) +check_trusted_key(const cfg_obj_t *key, isc_boolean_t managed, + isc_log_t *logctx) { const char *keystr, *keynamestr; dns_fixedname_t fkeyname; @@ -1704,6 +2028,19 @@ check_trusted_key(const cfg_obj_t *key, isc_log_t *logctx) result = ISC_R_FAILURE; } + if (managed) { + const char *initmethod; + initmethod = cfg_obj_asstring(cfg_tuple_get(key, "init")); + + if (strcasecmp(initmethod, "initial-key") != 0) { + cfg_obj_log(key, logctx, ISC_LOG_ERROR, + "managed key '%s': " + "invalid initialization method '%s'", + keynamestr, initmethod); + result = ISC_R_FAILURE; + } + } + isc_buffer_init(&keydatabuf, keydata, sizeof(keydata)); keystr = cfg_obj_asstring(cfg_tuple_get(key, "key")); @@ -1719,7 +2056,8 @@ check_trusted_key(const cfg_obj_t *key, isc_log_t *logctx) if ((alg == DST_ALG_RSASHA1 || alg == DST_ALG_RSAMD5) && r.length > 1 && r.base[0] == 1 && r.base[1] == 3) cfg_obj_log(key, logctx, ISC_LOG_WARNING, - "trusted key '%s' has a weak exponent", + "%s key '%s' has a weak exponent", + managed ? "managed" : "trusted", keynamestr); } @@ -1892,12 +2230,32 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions, element2 != NULL; element2 = cfg_list_next(element2)) { obj = cfg_listelt_value(element2); - tresult = check_trusted_key(obj, logctx); + tresult = check_trusted_key(obj, ISC_FALSE, logctx); if (tresult != ISC_R_SUCCESS) result = tresult; } } + keys = NULL; + if (voptions != NULL) + (void)cfg_map_get(voptions, "managed-keys", &keys); + if (keys == NULL) + (void)cfg_map_get(config, "managed-keys", &keys); + + for (element = cfg_list_first(keys); + element != NULL; + element = cfg_list_next(element)) + { + const cfg_obj_t *keylist = cfg_listelt_value(element); + for (element2 = cfg_list_first(keylist); + element2 != NULL; + element2 = cfg_list_next(element2)) { + obj = cfg_listelt_value(element2); + tresult = check_trusted_key(obj, ISC_TRUE, logctx); + if (tresult != ISC_R_SUCCESS) + result = tresult; + } + } /* * Check options. */ @@ -1917,7 +2275,16 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions, if (tresult != ISC_R_SUCCESS) result = tresult; - cfg_aclconfctx_destroy(&actx); + tresult = check_filteraaaa(&actx, voptions, viewname, config, + logctx, mctx); + if (tresult != ISC_R_SUCCESS) + result = tresult; + + tresult = check_dns64(&actx, voptions, config, logctx, mctx); + if (tresult != ISC_R_SUCCESS) + result = tresult; + + cfg_aclconfctx_clear(&actx); return (result); } @@ -2162,7 +2529,7 @@ bind9_check_controls(const cfg_obj_t *config, isc_log_t *logctx, result = tresult; } } - cfg_aclconfctx_destroy(&actx); + cfg_aclconfctx_clear(&actx); return (result); } |