Allow named-checkconf to selectively check dnssec-policy algorithms

There are times where you want named-checkconf to check whether the
dnssec-policies should be constrained by the cryptographic algorithms
supported by the operation system or to just accept all possible
algorithms.  This provides a mechanism to make that selection.
This commit is contained in:
Mark Andrews 2022-08-25 16:47:34 +10:00
parent 1eaff9a670
commit a830adff1c
8 changed files with 80 additions and 49 deletions

View file

@ -44,8 +44,6 @@
static const char *program = "named-checkconf";
static bool loadplugins = true;
isc_log_t *logc = NULL;
#define CHECK(r) \
@ -62,7 +60,7 @@ usage(void);
static void
usage(void) {
fprintf(stderr,
"usage: %s [-chijlvz] [-p [-x]] [-t directory] "
"usage: %s [-achijlvz] [-p [-x]] [-t directory] "
"[named.conf]\n",
program);
exit(1);
@ -599,13 +597,14 @@ main(int argc, char **argv) {
bool print = false;
bool nodeprecate = false;
unsigned int flags = 0;
unsigned int checkflags = BIND_CHECK_PLUGINS | BIND_CHECK_ALGORITHMS;
isc_commandline_errprint = false;
/*
* Process memory debugging argument first.
*/
#define CMDLINE_FLAGS "cdhijlm:t:pvxz"
#define CMDLINE_FLAGS "acdhijlm:t:pvxz"
while ((c = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
switch (c) {
case 'm':
@ -632,8 +631,12 @@ main(int argc, char **argv) {
while ((c = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != EOF) {
switch (c) {
case 'a':
checkflags &= ~BIND_CHECK_ALGORITHMS;
break;
case 'c':
loadplugins = false;
checkflags &= ~BIND_CHECK_PLUGINS;
break;
case 'd':
@ -735,7 +738,7 @@ main(int argc, char **argv) {
exit(1);
}
result = isccfg_check_namedconf(config, loadplugins, logc, mctx);
result = isccfg_check_namedconf(config, checkflags, logc, mctx);
if (result != ISC_R_SUCCESS) {
exit_status = 1;
}

View file

@ -21,7 +21,7 @@ named-checkconf - named configuration file syntax checking tool
Synopsis
~~~~~~~~
:program:`named-checkconf` [**-chjlvz**] [**-p** [**-x** ]] [**-t** directory] {filename}
:program:`named-checkconf` [**-achjlvz**] [**-p** [**-x** ]] [**-t** directory] {filename}
Description
~~~~~~~~~~~
@ -41,6 +41,13 @@ explicitly.
Options
~~~~~~~
.. option:: -a
Don't check the `dnssec-policy`'s DNSSEC key algorithms against
those supported by the crypto provider. This is useful when checking
a `named.conf` intended to be run on another machine with possibly a
different set of supported DNSSEC key algorithms.
.. option:: -h
This option prints the usage summary and exits.

View file

@ -275,7 +275,7 @@ kasp_from_conf(cfg_obj_t *config, isc_mem_t *mctx, const char *name,
continue;
}
result = cfg_kasp_fromconfig(kconfig, NULL, mctx, lctx,
result = cfg_kasp_fromconfig(kconfig, NULL, true, mctx, lctx,
&kasplist, &kasp);
if (result != ISC_R_SUCCESS) {
fatal("failed to configure dnssec-policy '%s': %s",

View file

@ -8366,8 +8366,8 @@ load_configuration(const char *filename, named_server_t *server,
* checked later when the modules are actually loaded and
* registered.)
*/
result = isccfg_check_namedconf(config, false, named_g_lctx,
named_g_mctx);
result = isccfg_check_namedconf(config, BIND_CHECK_ALGORITHMS,
named_g_lctx, named_g_mctx);
if (result != ISC_R_SUCCESS) {
goto cleanup_config;
}
@ -9034,7 +9034,7 @@ load_configuration(const char *filename, named_server_t *server,
cfg_obj_t *kconfig = cfg_listelt_value(element);
kasp = NULL;
result = cfg_kasp_fromconfig(kconfig, default_kasp,
result = cfg_kasp_fromconfig(kconfig, default_kasp, true,
named_g_mctx, named_g_lctx,
&kasplist, &kasp);
if (result != ISC_R_SUCCESS) {
@ -9063,7 +9063,7 @@ load_configuration(const char *filename, named_server_t *server,
{
cfg_obj_t *kconfig = cfg_listelt_value(element);
kasp = NULL;
result = cfg_kasp_fromconfig(kconfig, default_kasp,
result = cfg_kasp_fromconfig(kconfig, default_kasp, true,
named_g_mctx, named_g_lctx,
&kasplist, &kasp);
if (result != ISC_R_SUCCESS) {

View file

@ -1152,7 +1152,8 @@ check_port(const cfg_obj_t *options, isc_log_t *logctx, const char *type,
static isc_result_t
check_options(const cfg_obj_t *options, const cfg_obj_t *config,
isc_log_t *logctx, isc_mem_t *mctx, optlevel_t optlevel) {
bool check_algorithms, isc_log_t *logctx, isc_mem_t *mctx,
optlevel_t optlevel) {
isc_result_t result = ISC_R_SUCCESS;
isc_result_t tresult;
unsigned int i;
@ -1328,9 +1329,9 @@ check_options(const cfg_obj_t *options, const cfg_obj_t *config,
continue;
}
ret = cfg_kasp_fromconfig(kconfig, NULL,
mctx, logctx,
&list, &kasp);
ret = cfg_kasp_fromconfig(
kconfig, NULL, check_algorithms,
mctx, logctx, &list, &kasp);
if (ret != ISC_R_SUCCESS) {
if (result == ISC_R_SUCCESS) {
result = ret;
@ -3789,7 +3790,8 @@ check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
/*
* Check various options.
*/
tresult = check_options(zoptions, config, logctx, mctx, optlevel_zone);
tresult = check_options(zoptions, config, false, logctx, mctx,
optlevel_zone);
if (tresult != ISC_R_SUCCESS) {
result = tresult;
}
@ -5205,7 +5207,7 @@ check_dnstap(const cfg_obj_t *voptions, const cfg_obj_t *config,
static isc_result_t
check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
const char *viewname, dns_rdataclass_t vclass,
isc_symtab_t *files, isc_symtab_t *keydirs, bool check_plugins,
isc_symtab_t *files, isc_symtab_t *keydirs, unsigned int flags,
isc_symtab_t *inview, isc_log_t *logctx, isc_mem_t *mctx) {
const cfg_obj_t *zones = NULL;
const cfg_obj_t *view_tkeys = NULL, *global_tkeys = NULL;
@ -5225,6 +5227,8 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
bool autovalidation = false;
unsigned int tflags = 0, dflags = 0;
int i;
bool check_plugins = (flags & BIND_CHECK_PLUGINS) != 0;
bool check_algorithms = (flags & BIND_CHECK_ALGORITHMS) != 0;
/*
* Get global options block
@ -5420,7 +5424,7 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
check_keys[1] = global_tkeys;
for (i = 0; i < 2; i++) {
if (check_keys[i] != NULL) {
unsigned int flags = 0;
unsigned int taflags = 0;
for (element = cfg_list_first(check_keys[i]);
element != NULL; element = cfg_list_next(element))
@ -5433,14 +5437,14 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
{
obj = cfg_listelt_value(element2);
tresult = check_trust_anchor(
obj, false, &flags, logctx);
obj, false, &taflags, logctx);
if (tresult != ISC_R_SUCCESS) {
result = tresult;
}
}
}
if ((flags & ROOT_KSK_STATIC) != 0) {
if ((taflags & ROOT_KSK_STATIC) != 0) {
cfg_obj_log(check_keys[i], logctx,
ISC_LOG_WARNING,
"trusted-keys entry for the root "
@ -5450,7 +5454,7 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
"or initial-ds instead.");
}
tflags |= flags;
tflags |= taflags;
}
}
@ -5477,7 +5481,7 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
check_keys[1] = global_ta;
for (i = 0; i < 2; i++) {
if (check_keys[i] != NULL) {
unsigned int flags = 0;
unsigned int taflags = 0;
for (element = cfg_list_first(check_keys[i]);
element != NULL; element = cfg_list_next(element))
@ -5490,14 +5494,14 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
{
obj = cfg_listelt_value(element2);
tresult = check_trust_anchor(
obj, true, &flags, logctx);
obj, true, &taflags, logctx);
if (tresult != ISC_R_SUCCESS) {
result = tresult;
}
}
}
if ((flags & ROOT_KSK_STATIC) != 0) {
if ((taflags & ROOT_KSK_STATIC) != 0) {
cfg_obj_log(check_keys[i], logctx,
ISC_LOG_WARNING,
"static entry for the root "
@ -5507,8 +5511,8 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
"or initial-ds instead.");
}
if ((flags & ROOT_KSK_2010) != 0 &&
(flags & ROOT_KSK_2017) == 0)
if ((taflags & ROOT_KSK_2010) != 0 &&
(taflags & ROOT_KSK_2017) == 0)
{
cfg_obj_log(check_keys[i], logctx,
ISC_LOG_WARNING,
@ -5517,7 +5521,7 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
"the updated 2017 key");
}
dflags |= flags;
dflags |= taflags;
}
}
@ -5556,11 +5560,11 @@ check_viewconf(const cfg_obj_t *config, const cfg_obj_t *voptions,
* Check options.
*/
if (voptions != NULL) {
tresult = check_options(voptions, NULL, logctx, mctx,
optlevel_view);
tresult = check_options(voptions, NULL, check_algorithms,
logctx, mctx, optlevel_view);
} else {
tresult = check_options(config, config, logctx, mctx,
optlevel_config);
tresult = check_options(config, config, check_algorithms,
logctx, mctx, optlevel_config);
}
if (tresult != ISC_R_SUCCESS) {
result = tresult;
@ -5876,7 +5880,7 @@ check_controls(const cfg_obj_t *config, isc_log_t *logctx, isc_mem_t *mctx) {
}
isc_result_t
isccfg_check_namedconf(const cfg_obj_t *config, bool check_plugins,
isccfg_check_namedconf(const cfg_obj_t *config, unsigned int flags,
isc_log_t *logctx, isc_mem_t *mctx) {
const cfg_obj_t *options = NULL;
const cfg_obj_t *views = NULL;
@ -5888,14 +5892,16 @@ isccfg_check_namedconf(const cfg_obj_t *config, bool check_plugins,
isc_symtab_t *files = NULL;
isc_symtab_t *keydirs = NULL;
isc_symtab_t *inview = NULL;
bool check_algorithms = (flags & BIND_CHECK_ALGORITHMS) != 0;
static const char *builtin[] = { "localhost", "localnets", "any",
"none" };
(void)cfg_map_get(config, "options", &options);
if (options != NULL && check_options(options, config, logctx, mctx,
optlevel_options) != ISC_R_SUCCESS)
if (options != NULL &&
check_options(options, config, check_algorithms, logctx, mctx,
optlevel_options) != ISC_R_SUCCESS)
{
result = ISC_R_FAILURE;
}
@ -5966,8 +5972,8 @@ isccfg_check_namedconf(const cfg_obj_t *config, bool check_plugins,
if (views == NULL) {
tresult = check_viewconf(config, NULL, NULL, dns_rdataclass_in,
files, keydirs, check_plugins, inview,
logctx, mctx);
files, keydirs, flags, inview, logctx,
mctx);
if (result == ISC_R_SUCCESS && tresult != ISC_R_SUCCESS) {
result = ISC_R_FAILURE;
}
@ -6058,8 +6064,8 @@ isccfg_check_namedconf(const cfg_obj_t *config, bool check_plugins,
}
if (tresult == ISC_R_SUCCESS) {
tresult = check_viewconf(config, voptions, key, vclass,
files, keydirs, check_plugins,
inview, logctx, mctx);
files, keydirs, flags, inview,
logctx, mctx);
}
if (tresult != ISC_R_SUCCESS) {
result = ISC_R_FAILURE;

View file

@ -32,10 +32,20 @@
#define MAX_MAX_NCACHE_TTL 7 * 24 * 3600
#endif /* MAX_MAX_NCACHE_TTL */
#define BIND_CHECK_PLUGINS 0x00000001
/*%<
* Check the plugin configuration.
*/
#define BIND_CHECK_ALGORITHMS 0x00000002
/*%<
* Check the dnssec-policy DNSSEC algorithms against those
* supported by the crypto provider.
*/
ISC_LANG_BEGINDECLS
isc_result_t
isccfg_check_namedconf(const cfg_obj_t *config, bool check_plugins,
isccfg_check_namedconf(const cfg_obj_t *config, unsigned int flags,
isc_log_t *logctx, isc_mem_t *mctx);
/*%<
* Check the syntactic validity of a configuration parse tree generated from

View file

@ -25,7 +25,7 @@ ISC_LANG_BEGINDECLS
isc_result_t
cfg_kasp_fromconfig(const cfg_obj_t *config, dns_kasp_t *default_kasp,
isc_mem_t *mctx, isc_log_t *logctx,
bool check_algorithms, isc_mem_t *mctx, isc_log_t *logctx,
dns_kasplist_t *kasplist, dns_kasp_t **kaspp);
/*%<
* Create and configure a KASP. If 'default_kasp' is not NULL, the built-in
@ -34,6 +34,9 @@ cfg_kasp_fromconfig(const cfg_obj_t *config, dns_kasp_t *default_kasp,
* already exists with the same name, no new KASP is created, and no attach to
* 'kaspp' happens.
*
* If 'check_algorithms' is true then the dnssec-policy DNSSEC key
* algorithms are checked against those supported by the crypto provider.
*
* Requires:
*
*\li 'name' is either NULL, or a valid C string.

View file

@ -94,8 +94,8 @@ get_duration(const cfg_obj_t **maps, const char *option, const char *dfl) {
*/
static isc_result_t
cfg_kaspkey_fromconfig(const cfg_obj_t *config, dns_kasp_t *kasp,
isc_log_t *logctx, uint32_t ksk_min_lifetime,
uint32_t zsk_min_lifetime) {
bool check_algorithms, isc_log_t *logctx,
uint32_t ksk_min_lifetime, uint32_t zsk_min_lifetime) {
isc_result_t result;
dns_kasp_key_t *key = NULL;
@ -171,7 +171,7 @@ cfg_kaspkey_fromconfig(const cfg_obj_t *config, dns_kasp_t *kasp,
goto cleanup;
}
if (isc_fips_mode() &&
if (check_algorithms && isc_fips_mode() &&
(key->algorithm == DNS_KEYALG_RSASHA1 ||
key->algorithm == DNS_KEYALG_NSEC3RSASHA1))
{
@ -183,7 +183,9 @@ cfg_kaspkey_fromconfig(const cfg_obj_t *config, dns_kasp_t *kasp,
goto cleanup;
}
if (!dst_algorithm_supported(key->algorithm)) {
if (check_algorithms &&
!dst_algorithm_supported(key->algorithm))
{
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
"dnssec-policy: algorithm %s not supported",
alg.base);
@ -351,7 +353,7 @@ add_digest(dns_kasp_t *kasp, const cfg_obj_t *digest, isc_log_t *logctx) {
isc_result_t
cfg_kasp_fromconfig(const cfg_obj_t *config, dns_kasp_t *default_kasp,
isc_mem_t *mctx, isc_log_t *logctx,
bool check_algorithms, isc_mem_t *mctx, isc_log_t *logctx,
dns_kasplist_t *kasplist, dns_kasp_t **kaspp) {
isc_result_t result;
const cfg_obj_t *maps[2];
@ -507,9 +509,9 @@ cfg_kasp_fromconfig(const cfg_obj_t *config, dns_kasp_t *default_kasp,
element = cfg_list_next(element))
{
cfg_obj_t *kobj = cfg_listelt_value(element);
result = cfg_kaspkey_fromconfig(kobj, kasp, logctx,
ksk_min_lifetime,
zsk_min_lifetime);
result = cfg_kaspkey_fromconfig(
kobj, kasp, check_algorithms, logctx,
ksk_min_lifetime, zsk_min_lifetime);
if (result != ISC_R_SUCCESS) {
goto cleanup;
}