diff --git a/lib/irs/dnsconf.c b/lib/irs/dnsconf.c index 6c2e3c402b..5e77e4775f 100644 --- a/lib/irs/dnsconf.c +++ b/lib/irs/dnsconf.c @@ -44,138 +44,181 @@ struct irs_dnsconf { }; static isc_result_t -configure_dnsseckeys(irs_dnsconf_t *conf, cfg_obj_t *cfgobj, - dns_rdataclass_t rdclass) +configure_key(isc_mem_t *mctx, const cfg_obj_t *key, irs_dnsconf_t *conf, + dns_rdataclass_t rdclass) { - isc_mem_t *mctx = conf->mctx; - const cfg_obj_t *keys = NULL; - const cfg_obj_t *key, *keylist; - dns_fixedname_t fkeyname; - dns_name_t *keyname_base, *keyname; - const cfg_listelt_t *element, *element2; isc_result_t result; uint32_t flags, proto, alg; - const char *keystr, *keynamestr; + dns_fixedname_t fkeyname; + dns_name_t *keyname_base = NULL, *keyname = NULL; + const char *keystr = NULL, *keynamestr = NULL; unsigned char keydata[4096]; - isc_buffer_t keydatabuf_base, *keydatabuf; + isc_buffer_t keydatabuf_base, *keydatabuf = NULL; dns_rdata_dnskey_t keystruct; unsigned char rrdata[4096]; isc_buffer_t rrdatabuf; isc_region_t r; isc_buffer_t namebuf; - irs_dnsconf_dnskey_t *keyent; + irs_dnsconf_dnskey_t *keyent = NULL; + + flags = cfg_obj_asuint32(cfg_tuple_get(key, "flags")); + proto = cfg_obj_asuint32(cfg_tuple_get(key, + "protocol")); + alg = cfg_obj_asuint32(cfg_tuple_get(key, + "algorithm")); + keynamestr = cfg_obj_asstring(cfg_tuple_get(key, + "name")); + + keystruct.common.rdclass = rdclass; + keystruct.common.rdtype = dns_rdatatype_dnskey; + keystruct.mctx = NULL; + ISC_LINK_INIT(&keystruct.common, link); + + if (flags > 0xffff) { + return (ISC_R_RANGE); + } + if (proto > 0xff) { + return (ISC_R_RANGE); + } + if (alg > 0xff) { + return (ISC_R_RANGE); + } + keystruct.flags = (uint16_t)flags; + keystruct.protocol = (uint8_t)proto; + keystruct.algorithm = (uint8_t)alg; + + isc_buffer_init(&keydatabuf_base, keydata, + sizeof(keydata)); + isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata)); + + /* Configure key value */ + keystr = cfg_obj_asstring(cfg_tuple_get(key, "key")); + result = isc_base64_decodestring(keystr, + &keydatabuf_base); + if (result != ISC_R_SUCCESS) { + return (result); + } + isc_buffer_usedregion(&keydatabuf_base, &r); + keystruct.datalen = r.length; + keystruct.data = r.base; + + result = dns_rdata_fromstruct(NULL, keystruct.common.rdclass, + keystruct.common.rdtype, + &keystruct, &rrdatabuf); + if (result != ISC_R_SUCCESS) { + return (result); + } + isc_buffer_usedregion(&rrdatabuf, &r); + result = isc_buffer_allocate(mctx, &keydatabuf, + r.length); + if (result != ISC_R_SUCCESS) { + return (result); + } + result = isc_buffer_copyregion(keydatabuf, &r); + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + + /* Configure key name */ + keyname_base = dns_fixedname_initname(&fkeyname); + isc_buffer_constinit(&namebuf, keynamestr, + strlen(keynamestr)); + isc_buffer_add(&namebuf, strlen(keynamestr)); + result = dns_name_fromtext(keyname_base, &namebuf, + dns_rootname, 0, NULL); + if (result != ISC_R_SUCCESS) { + return (result); + } + keyname = isc_mem_get(mctx, sizeof(*keyname)); + if (keyname == NULL) { + result = ISC_R_NOMEMORY; + goto cleanup; + } + dns_name_init(keyname, NULL); + result = dns_name_dup(keyname_base, mctx, keyname); + if (result != ISC_R_SUCCESS) { + goto cleanup; + } + + /* Add the key data to the list */ + keyent = isc_mem_get(mctx, sizeof(*keyent)); + if (keyent == NULL) { + dns_name_free(keyname, mctx); + result = ISC_R_NOMEMORY; + goto cleanup; + } + keyent->keyname = keyname; + keyent->keydatabuf = keydatabuf; + + ISC_LIST_APPEND(conf->trusted_keylist, keyent, link); + + cleanup: + if (keydatabuf != NULL) { + isc_buffer_free(&keydatabuf); + } + if (keyname != NULL) { + isc_mem_put(mctx, keyname, sizeof(*keyname)); + } + + return (result); +} + +static isc_result_t +configure_dnsseckeys(irs_dnsconf_t *conf, cfg_obj_t *cfgobj, + dns_rdataclass_t rdclass) +{ + isc_result_t result; + isc_mem_t *mctx = conf->mctx; + const cfg_obj_t *keys = NULL; + const cfg_obj_t *key, *keylist; + const cfg_listelt_t *element, *element2; cfg_map_get(cfgobj, "trusted-keys", &keys); - if (keys == NULL) + if (keys == NULL) { return (ISC_R_SUCCESS); + } for (element = cfg_list_first(keys); element != NULL; - element = cfg_list_next(element)) { + element = cfg_list_next(element)) + { keylist = cfg_listelt_value(element); for (element2 = cfg_list_first(keylist); element2 != NULL; element2 = cfg_list_next(element2)) { - keydatabuf = NULL; - keyname = NULL; - key = cfg_listelt_value(element2); - - flags = cfg_obj_asuint32(cfg_tuple_get(key, "flags")); - proto = cfg_obj_asuint32(cfg_tuple_get(key, - "protocol")); - alg = cfg_obj_asuint32(cfg_tuple_get(key, - "algorithm")); - keynamestr = cfg_obj_asstring(cfg_tuple_get(key, - "name")); - - keystruct.common.rdclass = rdclass; - keystruct.common.rdtype = dns_rdatatype_dnskey; - keystruct.mctx = NULL; - ISC_LINK_INIT(&keystruct.common, link); - - if (flags > 0xffff) - return (ISC_R_RANGE); - if (proto > 0xff) - return (ISC_R_RANGE); - if (alg > 0xff) - return (ISC_R_RANGE); - keystruct.flags = (uint16_t)flags; - keystruct.protocol = (uint8_t)proto; - keystruct.algorithm = (uint8_t)alg; - - isc_buffer_init(&keydatabuf_base, keydata, - sizeof(keydata)); - isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata)); - - /* Configure key value */ - keystr = cfg_obj_asstring(cfg_tuple_get(key, "key")); - result = isc_base64_decodestring(keystr, - &keydatabuf_base); - if (result != ISC_R_SUCCESS) + result = configure_key(mctx, key, conf, rdclass); + if (result != ISC_R_SUCCESS) { return (result); - isc_buffer_usedregion(&keydatabuf_base, &r); - keystruct.datalen = r.length; - keystruct.data = r.base; - - result = dns_rdata_fromstruct(NULL, - keystruct.common.rdclass, - keystruct.common.rdtype, - &keystruct, &rrdatabuf); - if (result != ISC_R_SUCCESS) - return (result); - isc_buffer_usedregion(&rrdatabuf, &r); - result = isc_buffer_allocate(mctx, &keydatabuf, - r.length); - if (result != ISC_R_SUCCESS) - return (result); - result = isc_buffer_copyregion(keydatabuf, &r); - if (result != ISC_R_SUCCESS) - goto cleanup; - - /* Configure key name */ - keyname_base = dns_fixedname_initname(&fkeyname); - isc_buffer_constinit(&namebuf, keynamestr, - strlen(keynamestr)); - isc_buffer_add(&namebuf, strlen(keynamestr)); - result = dns_name_fromtext(keyname_base, &namebuf, - dns_rootname, 0, NULL); - if (result != ISC_R_SUCCESS) - return (result); - keyname = isc_mem_get(mctx, sizeof(*keyname)); - if (keyname == NULL) { - result = ISC_R_NOMEMORY; - goto cleanup; } - dns_name_init(keyname, NULL); - result = dns_name_dup(keyname_base, mctx, keyname); - if (result != ISC_R_SUCCESS) - goto cleanup; + } + } - /* Add the key data to the list */ - keyent = isc_mem_get(mctx, sizeof(*keyent)); - if (keyent == NULL) { - dns_name_free(keyname, mctx); - result = ISC_R_NOMEMORY; - goto cleanup; + keys = NULL; + cfg_map_get(cfgobj, "managed-keys", &keys); + if (keys == NULL) { + return (ISC_R_SUCCESS); + } + + for (element = cfg_list_first(keys); + element != NULL; + element = cfg_list_next(element)) + { + keylist = cfg_listelt_value(element); + for (element2 = cfg_list_first(keylist); + element2 != NULL; + element2 = cfg_list_next(element2)) + { + key = cfg_listelt_value(element2); + result = configure_key(mctx, key, conf, rdclass); + if (result != ISC_R_SUCCESS) { + return (result); } - keyent->keyname = keyname; - keyent->keydatabuf = keydatabuf; - - ISC_LIST_APPEND(conf->trusted_keylist, keyent, link); } } return (ISC_R_SUCCESS); - - cleanup: - if (keydatabuf != NULL) - isc_buffer_free(&keydatabuf); - if (keyname != NULL) - isc_mem_put(mctx, keyname, sizeof(*keyname)); - - return (result); } isc_result_t diff --git a/lib/irs/include/irs/dnsconf.h b/lib/irs/include/irs/dnsconf.h index 89898bafbc..ecebc454e0 100644 --- a/lib/irs/include/irs/dnsconf.h +++ b/lib/irs/include/irs/dnsconf.h @@ -22,9 +22,12 @@ * * Notes: * This module is very experimental and the configuration syntax or library - * interfaces may change in future versions. Currently, only the - * 'trusted-keys' statement is supported, whose syntax is the same as the - * same name of statement for named.conf. + * interfaces may change in future versions. Currently, only static + * key configuration is supported; "trusted-keys" and "managed-keys" + * statements will be parsed exactly as they are in named.conf, except + * that all "managed-keys" entries will be treated as if they were + * configured with "static-key", even if they were actually configured + * with "initial-key". */ #include