From: Evan Hunt Date: Wed, 15 Aug 2018 23:59:45 +0000 (-0700) Subject: deprecate "trusted-keys" X-Git-Tag: v9.15.1~9^2~8 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=5ab252183bda933b399c442ac5b48ed18e0b465b;p=thirdparty%2Fbind9.git deprecate "trusted-keys" - trusted-keys is now flagged as deprecated, but still works - managed-keys can be used to configure permanent trust anchors by using the "static-key" keyword in place of "initial-key" - parser now uses an enum for static-key and initial-key keywords --- diff --git a/bin/named/server.c b/bin/named/server.c index a0357dcffde..6a4fd535d58 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -700,11 +700,9 @@ configure_view_nametable(const cfg_obj_t *vconfig, const cfg_obj_t *config, } static isc_result_t -dstkey_fromconfig(const cfg_obj_t *vconfig, const cfg_obj_t *key, - bool managed, dst_key_t **target, const char **keynamestrp, - isc_mem_t *mctx) +dstkey_fromconfig(const cfg_obj_t *key, bool *initialp, dst_key_t **target, + const char **keynamestrp, isc_mem_t *mctx) { - dns_rdataclass_t viewclass; dns_rdata_dnskey_t keystruct; uint32_t flags, proto, alg; const char *keystr, *keynamestr; @@ -729,13 +727,15 @@ dstkey_fromconfig(const cfg_obj_t *vconfig, const cfg_obj_t *key, keynamestr = cfg_obj_asstring(cfg_tuple_get(key, "name")); *keynamestrp = keynamestr; - if (managed) { + if (*initialp) { const char *initmethod; initmethod = cfg_obj_asstring(cfg_tuple_get(key, "init")); - if (strcasecmp(initmethod, "initial-key") != 0) { + if (strcasecmp(initmethod, "static-key") == 0) { + *initialp = false; + } else if (strcasecmp(initmethod, "initial-key") != 0) { cfg_obj_log(key, named_g_lctx, ISC_LOG_ERROR, - "managed key '%s': " + "key '%s': " "invalid initialization method '%s'", keynamestr, initmethod); result = ISC_R_FAILURE; @@ -743,15 +743,12 @@ dstkey_fromconfig(const cfg_obj_t *vconfig, const cfg_obj_t *key, } } - if (vconfig == NULL) - viewclass = dns_rdataclass_in; - else { - const cfg_obj_t *classobj = cfg_tuple_get(vconfig, "class"); - CHECK(named_config_getclass(classobj, dns_rdataclass_in, - &viewclass)); - } - keystruct.common.rdclass = viewclass; + /* + * This function should never be reached for non-IN classes. + */ + keystruct.common.rdclass = dns_rdataclass_in; keystruct.common.rdtype = dns_rdatatype_dnskey; + /* * The key data in keystruct is not dynamically allocated. */ @@ -782,10 +779,12 @@ dstkey_fromconfig(const cfg_obj_t *vconfig, const cfg_obj_t *key, if ((keystruct.algorithm == DST_ALG_RSASHA1) && r.length > 1 && r.base[0] == 1 && r.base[1] == 3) + { cfg_obj_log(key, named_g_lctx, ISC_LOG_WARNING, - "%s key '%s' has a weak exponent", - managed ? "managed" : "trusted", + "%s '%s' has a weak exponent", + *initialp ? "initial-key" : "static-key", keynamestr); + } CHECK(dns_rdata_fromstruct(NULL, keystruct.common.rdclass, @@ -795,7 +794,7 @@ dstkey_fromconfig(const cfg_obj_t *vconfig, const cfg_obj_t *key, isc_buffer_constinit(&namebuf, keynamestr, strlen(keynamestr)); isc_buffer_add(&namebuf, strlen(keynamestr)); CHECK(dns_name_fromtext(keyname, &namebuf, dns_rootname, 0, NULL)); - CHECK(dst_key_fromdns(keyname, viewclass, &rrdatabuf, + CHECK(dst_key_fromdns(keyname, dns_rdataclass_in, &rrdatabuf, mctx, &dstkey)); *target = dstkey; @@ -821,18 +820,19 @@ dstkey_fromconfig(const cfg_obj_t *vconfig, const cfg_obj_t *key, * the memory context to use for allocating memory. */ static isc_result_t -process_key(const cfg_obj_t *key, const cfg_obj_t *vconfig, - dns_keytable_t *secroots, const dns_name_t *keyname_match, - dns_resolver_t *resolver, bool managed, isc_mem_t *mctx) +process_key(const cfg_obj_t *key, dns_keytable_t *secroots, + const dns_name_t *keyname_match, dns_resolver_t *resolver, + bool managed, isc_mem_t *mctx) { const dns_name_t *keyname = NULL; const char *keynamestr = NULL; dst_key_t *dstkey = NULL; unsigned int keyalg; isc_result_t result; + bool initializing = managed; - result = dstkey_fromconfig(vconfig, key, managed, &dstkey, &keynamestr, - mctx); + result = dstkey_fromconfig(key, &initializing, + &dstkey, &keynamestr, mctx); switch (result) { case ISC_R_SUCCESS: @@ -851,8 +851,8 @@ process_key(const cfg_obj_t *key, const cfg_obj_t *vconfig, * but do not prevent any further ones from being processed. */ cfg_obj_log(key, named_g_lctx, ISC_LOG_WARNING, - "ignoring %s key for '%s': %s", - managed ? "managed" : "trusted", + "ignoring %s for '%s': %s", + initializing ? "initial-key" : "static-key", keynamestr, isc_result_totext(result)); return (ISC_R_SUCCESS); case DST_R_NOCRYPTO: @@ -860,8 +860,8 @@ process_key(const cfg_obj_t *key, const cfg_obj_t *vconfig, * Crypto support is not available. */ cfg_obj_log(key, named_g_lctx, ISC_LOG_ERROR, - "ignoring %s key for '%s': no crypto support", - managed ? "managed" : "trusted", + "ignoring %s for '%s': no crypto support", + initializing ? "initial-key" : "static-key", keynamestr); return (result); default: @@ -871,8 +871,8 @@ process_key(const cfg_obj_t *key, const cfg_obj_t *vconfig, * is interrupted. */ cfg_obj_log(key, named_g_lctx, ISC_LOG_ERROR, - "configuring %s key for '%s': %s", - managed ? "managed" : "trusted", + "configuring %s for '%s': %s", + initializing ? "initial-key" : "static-key", keynamestr, isc_result_totext(result)); return (ISC_R_FAILURE); } @@ -893,17 +893,21 @@ process_key(const cfg_obj_t *key, const cfg_obj_t *vconfig, */ if (!dns_resolver_algorithm_supported(resolver, keyname, keyalg)) { cfg_obj_log(key, named_g_lctx, ISC_LOG_WARNING, - "ignoring %s key for '%s': algorithm is disabled", - managed ? "managed" : "trusted", keynamestr); + "ignoring %s for '%s': algorithm is disabled", + initializing ? "initial-key" : "static-key", + keynamestr); goto done; } /* - * Add the key to 'secroots'. This key is taken from the - * configuration, so if it's a managed key then it's an initializing - * key; that's why 'managed' is duplicated below. + * Add the key to 'secroots'. Keys from a "dnssec-keys" or + * "managed-keys" * statement may be either static or initializing + * keys. If it's not initializing, we don't want to treat it as + * managed, so we use 'initializing' twice here, for both the + * 'managed' and 'initializing' arguments to dns_keytable_add(). */ - result = dns_keytable_add(secroots, managed, managed, &dstkey); + result = dns_keytable_add(secroots, initializing, + initializing, &dstkey); done: /* @@ -924,8 +928,7 @@ process_key(const cfg_obj_t *key, const cfg_obj_t *vconfig, * an initializing key. */ static isc_result_t -load_view_keys(const cfg_obj_t *keys, const cfg_obj_t *vconfig, - dns_view_t *view, bool managed, +load_view_keys(const cfg_obj_t *keys, dns_view_t *view, bool managed, const dns_name_t *keyname, isc_mem_t *mctx) { const cfg_listelt_t *elt, *elt2; @@ -945,7 +948,7 @@ load_view_keys(const cfg_obj_t *keys, const cfg_obj_t *vconfig, elt2 != NULL; elt2 = cfg_list_next(elt2)) { - CHECK(process_key(cfg_listelt_value(elt2), vconfig, + CHECK(process_key(cfg_listelt_value(elt2), secroots, keyname, view->resolver, managed, mctx)); } @@ -1055,7 +1058,6 @@ configure_view_dnsseckeys(dns_view_t *view, const cfg_obj_t *vconfig, if (auto_root && view->rdclass == dns_rdataclass_in) { const cfg_obj_t *builtin_keys = NULL; - const cfg_obj_t *builtin_managed_keys = NULL; /* * If bind.keys exists and is populated, it overrides @@ -1068,13 +1070,10 @@ configure_view_dnsseckeys(dns_view_t *view, const cfg_obj_t *vconfig, "from '%s'", view->name, named_g_server->bindkeysfile); - (void)cfg_map_get(bindkeys, "trusted-keys", - &builtin_keys); (void)cfg_map_get(bindkeys, "managed-keys", - &builtin_managed_keys); + &builtin_keys); - if ((builtin_keys == NULL) && - (builtin_managed_keys == NULL)) + if (builtin_keys == NULL) { isc_log_write(named_g_lctx, DNS_LOGCATEGORY_SECURITY, NAMED_LOGMODULE_SERVER, @@ -1082,29 +1081,23 @@ configure_view_dnsseckeys(dns_view_t *view, const cfg_obj_t *vconfig, "dnssec-validation auto: " "WARNING: root zone key " "not found"); + } } - if ((builtin_keys == NULL) && - (builtin_managed_keys == NULL)) - { + if (builtin_keys == NULL) { isc_log_write(named_g_lctx, DNS_LOGCATEGORY_SECURITY, NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, "using built-in root key for view %s", view->name); - (void)cfg_map_get(named_g_config, "trusted-keys", - &builtin_keys); (void)cfg_map_get(named_g_config, "managed-keys", - &builtin_managed_keys); + &builtin_keys); } - if (builtin_keys != NULL) - CHECK(load_view_keys(builtin_keys, vconfig, view, - false, dns_rootname, mctx)); - if (builtin_managed_keys != NULL) - CHECK(load_view_keys(builtin_managed_keys, vconfig, - view, true, dns_rootname, - mctx)); + if (builtin_keys != NULL) { + CHECK(load_view_keys(builtin_keys, view, true, + dns_rootname, mctx)); + } if (!keyloaded(view, dns_rootname)) { isc_log_write(named_g_lctx, DNS_LOGCATEGORY_SECURITY, @@ -1115,16 +1108,13 @@ configure_view_dnsseckeys(dns_view_t *view, const cfg_obj_t *vconfig, } } - CHECK(load_view_keys(view_keys, vconfig, view, false, - NULL, mctx)); - CHECK(load_view_keys(view_managed_keys, vconfig, view, true, - NULL, mctx)); + CHECK(load_view_keys(view_keys, view, false, NULL, mctx)); + CHECK(load_view_keys(view_managed_keys, view, true, NULL, mctx)); if (view->rdclass == dns_rdataclass_in) { - CHECK(load_view_keys(global_keys, vconfig, view, false, + CHECK(load_view_keys(global_keys, view, false, NULL, mctx)); + CHECK(load_view_keys(global_managed_keys, view, true, NULL, mctx)); - CHECK(load_view_keys(global_managed_keys, vconfig, view, - true, NULL, mctx)); } /* diff --git a/bin/tests/system/checkconf/check-root-ksk-2017.conf b/bin/tests/system/checkconf/check-root-ksk-2017.conf index ebefd9c9778..cbadc895672 100644 --- a/bin/tests/system/checkconf/check-root-ksk-2017.conf +++ b/bin/tests/system/checkconf/check-root-ksk-2017.conf @@ -9,7 +9,7 @@ * information regarding copyright ownership. */ -trusted-keys { +managed-keys { # This key (20326) was published in the root zone in 2017. # Servers which were already using the old key (19036) should # roll seamlessly to this new one via RFC 5011 rollover. Servers @@ -17,7 +17,7 @@ trusted-keys { # file as initializing keys; thereafter, the keys in the # managed key database will be trusted and maintained # automatically. - . 257 3 8 "AwEAAaz/tAm8yTn4Mfeh5eyI96WSVexTBAvkMgJzkKTOiW1vkIbzxeF3 + . static-key 257 3 8 "AwEAAaz/tAm8yTn4Mfeh5eyI96WSVexTBAvkMgJzkKTOiW1vkIbzxeF3 +/4RgWOq7HrxRixHlFlExOLAJr5emLvN7SWXgnLh4+B5xQlNVz8Og8kv ArMtNROxVQuCaSnIDdD5LKyWbRd2n9WGe2R8PzgCmr3EgVLrjyBxWezF 0jLHwVN8efS3rCj/EWgvIWgb9tarpVUDK/b58Da+sqqls3eNbuv7pr+e diff --git a/bin/tests/system/checkconf/check-root-ksk-both.conf b/bin/tests/system/checkconf/check-root-ksk-both.conf index aebf7f5b870..6572e9e7aa0 100644 --- a/bin/tests/system/checkconf/check-root-ksk-both.conf +++ b/bin/tests/system/checkconf/check-root-ksk-both.conf @@ -9,12 +9,12 @@ * information regarding copyright ownership. */ -trusted-keys { +managed-keys { # This key (19036) is to be phased out starting in 2017. It will # remain in the root zone for some time after its successor key # has been added. It will remain this file until it is removed from # the root zone. - . 257 3 8 "AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjF + . static-key 257 3 8 "AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjF FVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8g0NfnfL2MTJRkxoX bfDaUeVPQuYEhg37NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaD X6RS6CXpoY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3LQpz @@ -29,7 +29,7 @@ trusted-keys { # file as initializing keys; thereafter, the keys in the # managed key database will be trusted and maintained # automatically. - . 257 3 8 "AwEAAaz/tAm8yTn4Mfeh5eyI96WSVexTBAvkMgJzkKTOiW1vkIbzxeF3 + . static-key 257 3 8 "AwEAAaz/tAm8yTn4Mfeh5eyI96WSVexTBAvkMgJzkKTOiW1vkIbzxeF3 +/4RgWOq7HrxRixHlFlExOLAJr5emLvN7SWXgnLh4+B5xQlNVz8Og8kv ArMtNROxVQuCaSnIDdD5LKyWbRd2n9WGe2R8PzgCmr3EgVLrjyBxWezF 0jLHwVN8efS3rCj/EWgvIWgb9tarpVUDK/b58Da+sqqls3eNbuv7pr+e diff --git a/bin/tests/system/checkconf/tests.sh b/bin/tests/system/checkconf/tests.sh index 9bb9c05f85d..285746ae682 100644 --- a/bin/tests/system/checkconf/tests.sh +++ b/bin/tests/system/checkconf/tests.sh @@ -371,7 +371,7 @@ if [ $ret != 0 ]; then echo_i "failed"; ret=1; fi status=`expr $status + $ret` n=`expr $n + 1` -echo_i "check that 'dnssec-lookaside . trust-anchor dlv.example.com;' doesn't generates a warning ($n)" +echo_i "check that 'dnssec-lookaside . trust-anchor dlv.example.com;' does not generate a warning ($n)" ret=0 $CHECKCONF good-dlv-dlv.example.com.conf > checkconf.out$n 2>/dev/null || ret=1 [ -s checkconf.out$n ] && ret=1 @@ -395,7 +395,7 @@ $CHECKCONF check-root-ksk-both.conf > checkconf.out$n 2>/dev/null || ret=1 if [ $ret != 0 ]; then echo_i "failed"; ret=1; fi status=`expr $status + $ret` -echo_i "check that the 2017 ICANN ROOT KSK alone does not warning ($n)" +echo_i "check that the 2017 ICANN ROOT KSK alone does not generate a warning ($n)" ret=0 $CHECKCONF check-root-ksk-2017.conf > checkconf.out$n 2>/dev/null || ret=1 [ -s checkconf.out$n ] && ret=1 diff --git a/bin/tests/system/dnssec/tests.sh b/bin/tests/system/dnssec/tests.sh index a914f5f501d..c1a0c40c700 100644 --- a/bin/tests/system/dnssec/tests.sh +++ b/bin/tests/system/dnssec/tests.sh @@ -1774,7 +1774,7 @@ ret=0 rndccmd 10.53.0.4 secroots 2>&1 | sed 's/^/ns4 /' | cat_i keyid=$(cat ns1/managed.key.id) cp ns4/named.secroots named.secroots.test$n -linecount=$(grep -c "./${DEFAULT_ALGORITHM}/$keyid ; trusted" named.secroots.test$n || true) +linecount=$(grep -c "./${DEFAULT_ALGORITHM}/$keyid ; static" named.secroots.test$n || true) [ "$linecount" -eq 1 ] || ret=1 linecount=$(< named.secroots.test$n wc -l) [ "$linecount" -eq 10 ] || ret=1 @@ -3759,12 +3759,12 @@ status=$((status+ret)) # lines in the logfile. echo_i "checking that keys with unsupported algorithms and disabled algorithms are ignored ($n)" ret=0 -grep -q "ignoring trusted key for 'disabled\.trusted\.': algorithm is disabled" ns8/named.run || ret=1 -grep -q "ignoring trusted key for 'unsupported\.trusted\.': algorithm is unsupported" ns8/named.run || ret=1 -grep -q "ignoring trusted key for 'revoked\.trusted\.': bad key type" ns8/named.run || ret=1 -grep -q "ignoring managed key for 'disabled\.managed\.': algorithm is disabled" ns8/named.run || ret=1 -grep -q "ignoring managed key for 'unsupported\.managed\.': algorithm is unsupported" ns8/named.run || ret=1 -grep -q "ignoring trusted key for 'revoked\.trusted\.': bad key type" ns8/named.run || ret=1 +grep -q "ignoring static-key for 'disabled\.trusted\.': algorithm is disabled" ns8/named.run || ret=1 +grep -q "ignoring static-key for 'unsupported\.trusted\.': algorithm is unsupported" ns8/named.run || ret=1 +grep -q "ignoring static-key for 'revoked\.trusted\.': bad key type" ns8/named.run || ret=1 +grep -q "ignoring initial-key for 'disabled\.managed\.': algorithm is disabled" ns8/named.run || ret=1 +grep -q "ignoring initial-key for 'unsupported\.managed\.': algorithm is unsupported" ns8/named.run || ret=1 +grep -q "ignoring initial-key for 'revoked\.managed\.': bad key type" ns8/named.run || ret=1 n=$((n+1)) test "$ret" -eq 0 || echo_i "failed" status=$((status+ret)) diff --git a/bin/tests/system/mkeys/tests.sh b/bin/tests/system/mkeys/tests.sh index cfee9c89ff1..22409c2d1d7 100644 --- a/bin/tests/system/mkeys/tests.sh +++ b/bin/tests/system/mkeys/tests.sh @@ -763,7 +763,7 @@ rm -f ns6/managed-keys.bind* nextpart ns6/named.run > /dev/null $PERL $SYSTEMTESTTOP/start.pl --noclean --restart --port ${PORT} mkeys ns6 # log when an unsupported algorithm is encountered during startup -wait_for_log "ignoring managed key for 'unsupported\.': algorithm is unsupported" ns6/named.run +wait_for_log "ignoring initial-key for 'unsupported\.': algorithm is unsupported" ns6/named.run if [ $ret != 0 ]; then echo_i "failed"; fi status=`expr $status + $ret` diff --git a/lib/bind9/check.c b/lib/bind9/check.c index 45d179bbc1e..4f40b493109 100644 --- a/lib/bind9/check.c +++ b/lib/bind9/check.c @@ -3109,7 +3109,9 @@ check_trusted_key(const cfg_obj_t *key, bool managed, const char *initmethod; initmethod = cfg_obj_asstring(cfg_tuple_get(key, "init")); - if (strcasecmp(initmethod, "initial-key") != 0) { + if (strcasecmp(initmethod, "static-key") == 0) { + managed = false; + } else if (strcasecmp(initmethod, "initial-key") != 0) { cfg_obj_log(key, logctx, ISC_LOG_ERROR, "managed key '%s': " "invalid initialization method '%s'", @@ -3134,7 +3136,7 @@ check_trusted_key(const cfg_obj_t *key, bool managed, r.length > 1 && r.base[0] == 1 && r.base[1] == 3) cfg_obj_log(key, logctx, ISC_LOG_WARNING, "%s key '%s' has a weak exponent", - managed ? "managed" : "trusted", + managed ? "initializing" : "static", keynamestr); } diff --git a/lib/dns/keytable.c b/lib/dns/keytable.c index f877659819c..9a72d8f94ec 100644 --- a/lib/dns/keytable.c +++ b/lib/dns/keytable.c @@ -685,7 +685,7 @@ dns_keytable_totext(dns_keytable_t *keytable, isc_buffer_t **text) { dst_key_format(knode->key, pbuf, sizeof(pbuf)); snprintf(obuf, sizeof(obuf), "%s ; %s%s\n", pbuf, knode->initial ? "initializing " : "", - knode->managed ? "managed" : "trusted"); + knode->managed ? "managed" : "static"); result = putstr(text, obuf); if (result != ISC_R_SUCCESS) break; diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c index 1d2aa9afd75..0c728141f0f 100644 --- a/lib/isccfg/namedconf.c +++ b/lib/isccfg/namedconf.c @@ -449,9 +449,15 @@ static cfg_type_t cfg_type_dnsseckey = { * A managed key initialization specifier, as used in the * "managed-keys" statement. */ +static const char *init_enums[] = { "static-key", "initial-key", NULL }; +static cfg_type_t cfg_type_keyinit = { + "keyinit", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum, + &cfg_rep_string, &init_enums +}; + static cfg_tuplefielddef_t managedkey_fields[] = { { "name", &cfg_type_astring, 0 }, - { "init", &cfg_type_ustring, 0 }, /* must be literal "initial-key" */ + { "init", &cfg_type_keyinit, 0 }, { "flags", &cfg_type_uint32, 0 }, { "protocol", &cfg_type_uint32, 0 }, { "algorithm", &cfg_type_uint32, 0 }, @@ -618,20 +624,18 @@ static cfg_type_t cfg_type_keylist = { cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_astring }; -/*% A list of dnssec keys, as in "trusted-keys" */ +/*% A list of dnssec keys, as in "trusted-keys". Deprecated. */ static cfg_type_t cfg_type_dnsseckeys = { "dnsseckeys", cfg_parse_bracketed_list, cfg_print_bracketed_list, cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_dnsseckey }; /*% - * A list of managed key entries, as in "trusted-keys". Currently - * (9.7.0) this has a format similar to dnssec keys, except the keyname - * is followed by the keyword "initial-key". In future releases, this - * keyword may take other values indicating different methods for the - * key to be initialized. + * A list of key entries, as in "trusted-keys". This has a format similar + * to dnssec keys, except the keyname is followed by keyword, either + * "initial-key" or "static-key". If "initial-key", then the key is + * RFC 5011 managed; if "static-key", then the key never changes. */ - static cfg_type_t cfg_type_managedkeys = { "managedkeys", cfg_parse_bracketed_list, cfg_print_bracketed_list, cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_managedkey @@ -985,7 +989,8 @@ namedconf_or_view_clauses[] = { { "managed-keys", &cfg_type_managedkeys, CFG_CLAUSEFLAG_MULTI }, { "plugin", &cfg_type_plugin, CFG_CLAUSEFLAG_MULTI }, { "server", &cfg_type_server, CFG_CLAUSEFLAG_MULTI }, - { "trusted-keys", &cfg_type_dnsseckeys, CFG_CLAUSEFLAG_MULTI }, + { "trusted-keys", &cfg_type_dnsseckeys, + CFG_CLAUSEFLAG_MULTI|CFG_CLAUSEFLAG_DEPRECATED }, { "zone", &cfg_type_zone, CFG_CLAUSEFLAG_MULTI }, { NULL, NULL, 0 } };