/*% load zones from the configuration */ static isc_result_t load_zones_fromconfig(const cfg_obj_t *config, isc_mem_t *mctx) { const cfg_listelt_t *element; const cfg_obj_t *classobj; const cfg_obj_t *views; const cfg_obj_t *vconfig; const char *vclass; isc_result_t result = ISC_R_SUCCESS; isc_result_t tresult; views = NULL; (void)cfg_map_get(config, "view", &views); for (element = cfg_list_first(views); element != NULL; element = cfg_list_next(element)) { const char *vname; vclass = "IN"; vconfig = cfg_listelt_value(element); if (vconfig != NULL) { classobj = cfg_tuple_get(vconfig, "class"); if (cfg_obj_isstring(classobj)) vclass = cfg_obj_asstring(classobj); } vname = cfg_obj_asstring(cfg_tuple_get(vconfig, "name")); tresult = configure_view(vclass, vname, config, vconfig, mctx); if (tresult != ISC_R_SUCCESS) result = tresult; } if (views == NULL) { tresult = configure_view("IN", "_default", config, NULL, mctx); if (tresult != ISC_R_SUCCESS) result = tresult; } return (result); }
isc_result_t ns_checknames_get(const cfg_obj_t **maps, const char *which, const cfg_obj_t **obj) { const cfg_listelt_t *element; const cfg_obj_t *checknames; const cfg_obj_t *type; const cfg_obj_t *value; int i; for (i = 0;; i++) { if (maps[i] == NULL) return (ISC_R_NOTFOUND); checknames = NULL; if (cfg_map_get(maps[i], "check-names", &checknames) == ISC_R_SUCCESS) { /* * Zone map entry is not a list. */ if (checknames != NULL && !cfg_obj_islist(checknames)) { *obj = checknames; return (ISC_R_SUCCESS); } for (element = cfg_list_first(checknames); element != NULL; element = cfg_list_next(element)) { value = cfg_listelt_value(element); type = cfg_tuple_get(value, "type"); if (strcasecmp(cfg_obj_asstring(type), which) == 0) { *obj = cfg_tuple_get(value, "mode"); return (ISC_R_SUCCESS); } } } } }
/* * Find the definition of the named acl whose name is "name". */ static isc_result_t get_acl_def(const cfg_obj_t *cctx, const char *name, const cfg_obj_t **ret) { isc_result_t result; const cfg_obj_t *acls = NULL; const cfg_listelt_t *elt; result = cfg_map_get(cctx, "acl", &acls); if (result != ISC_R_SUCCESS) return (result); for (elt = cfg_list_first(acls); elt != NULL; elt = cfg_list_next(elt)) { const cfg_obj_t *acl = cfg_listelt_value(elt); const char *aclname = cfg_obj_asstring(cfg_tuple_get(acl, "name")); if (strcasecmp(aclname, name) == 0) { if (ret != NULL) { *ret = cfg_tuple_get(acl, "value"); } return (ISC_R_SUCCESS); } } return (ISC_R_NOTFOUND); }
/* * Ensures that both '*global_keylistp' and '*control_keylistp' are * valid or both are NULL. */ static void get_key_info(const cfg_obj_t *config, const cfg_obj_t *control, const cfg_obj_t **global_keylistp, const cfg_obj_t **control_keylistp) { isc_result_t result; const cfg_obj_t *control_keylist = NULL; const cfg_obj_t *global_keylist = NULL; REQUIRE(global_keylistp != NULL && *global_keylistp == NULL); REQUIRE(control_keylistp != NULL && *control_keylistp == NULL); control_keylist = cfg_tuple_get(control, "keys"); if (!cfg_obj_isvoid(control_keylist) && cfg_list_first(control_keylist) != NULL) { result = cfg_map_get(config, "key", &global_keylist); if (result == ISC_R_SUCCESS) { *global_keylistp = global_keylist; *control_keylistp = control_keylist; } } }
/*% configure the zone */ static isc_result_t configure_zone(const char *vclass, const char *view, const cfg_obj_t *zconfig, const cfg_obj_t *vconfig, const cfg_obj_t *config, isc_mem_t *mctx) { int i = 0; isc_result_t result; const char *zclass; const char *zname; const char *zfile; const cfg_obj_t *maps[4]; const cfg_obj_t *zoptions = NULL; const cfg_obj_t *classobj = NULL; const cfg_obj_t *typeobj = NULL; const cfg_obj_t *fileobj = NULL; const cfg_obj_t *dbobj = NULL; const cfg_obj_t *obj = NULL; const cfg_obj_t *fmtobj = NULL; dns_masterformat_t masterformat; zone_options = DNS_ZONEOPT_CHECKNS | DNS_ZONEOPT_MANYERRORS; zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name")); classobj = cfg_tuple_get(zconfig, "class"); if (!cfg_obj_isstring(classobj)) zclass = vclass; else zclass = cfg_obj_asstring(classobj); zoptions = cfg_tuple_get(zconfig, "options"); maps[i++] = zoptions; if (vconfig != NULL) maps[i++] = cfg_tuple_get(vconfig, "options"); if (config != NULL) { cfg_map_get(config, "options", &obj); if (obj != NULL) maps[i++] = obj; } maps[i++] = NULL; cfg_map_get(zoptions, "type", &typeobj); if (typeobj == NULL) return (ISC_R_FAILURE); if (strcasecmp(cfg_obj_asstring(typeobj), "master") != 0) return (ISC_R_SUCCESS); cfg_map_get(zoptions, "database", &dbobj); if (dbobj != NULL) return (ISC_R_SUCCESS); cfg_map_get(zoptions, "file", &fileobj); if (fileobj == NULL) return (ISC_R_FAILURE); zfile = cfg_obj_asstring(fileobj); obj = NULL; if (get_maps(maps, "check-dup-records", &obj)) { if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { zone_options |= DNS_ZONEOPT_CHECKDUPRR; zone_options &= ~DNS_ZONEOPT_CHECKDUPRRFAIL; } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { zone_options |= DNS_ZONEOPT_CHECKDUPRR; zone_options |= DNS_ZONEOPT_CHECKDUPRRFAIL; } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { zone_options &= ~DNS_ZONEOPT_CHECKDUPRR; zone_options &= ~DNS_ZONEOPT_CHECKDUPRRFAIL; } else INSIST(0); } else { zone_options |= DNS_ZONEOPT_CHECKDUPRR; zone_options &= ~DNS_ZONEOPT_CHECKDUPRRFAIL; } obj = NULL; if (get_maps(maps, "check-mx", &obj)) { if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { zone_options |= DNS_ZONEOPT_CHECKMX; zone_options &= ~DNS_ZONEOPT_CHECKMXFAIL; } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { zone_options |= DNS_ZONEOPT_CHECKMX; zone_options |= DNS_ZONEOPT_CHECKMXFAIL; } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { zone_options &= ~DNS_ZONEOPT_CHECKMX; zone_options &= ~DNS_ZONEOPT_CHECKMXFAIL; } else INSIST(0); } else { zone_options |= DNS_ZONEOPT_CHECKMX; zone_options &= ~DNS_ZONEOPT_CHECKMXFAIL; } obj = NULL; if (get_maps(maps, "check-integrity", &obj)) { if (cfg_obj_asboolean(obj)) zone_options |= DNS_ZONEOPT_CHECKINTEGRITY; else zone_options &= ~DNS_ZONEOPT_CHECKINTEGRITY; } else zone_options |= DNS_ZONEOPT_CHECKINTEGRITY; obj = NULL; if (get_maps(maps, "check-mx-cname", &obj)) { if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { zone_options |= DNS_ZONEOPT_WARNMXCNAME; zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME; } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { zone_options &= ~DNS_ZONEOPT_WARNMXCNAME; zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME; } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { zone_options |= DNS_ZONEOPT_WARNMXCNAME; zone_options |= DNS_ZONEOPT_IGNOREMXCNAME; } else INSIST(0); } else { zone_options |= DNS_ZONEOPT_WARNMXCNAME; zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME; } obj = NULL; if (get_maps(maps, "check-srv-cname", &obj)) { if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { zone_options |= DNS_ZONEOPT_WARNSRVCNAME; zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME; } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { zone_options &= ~DNS_ZONEOPT_WARNSRVCNAME; zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME; } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { zone_options |= DNS_ZONEOPT_WARNSRVCNAME; zone_options |= DNS_ZONEOPT_IGNORESRVCNAME; } else INSIST(0); } else { zone_options |= DNS_ZONEOPT_WARNSRVCNAME; zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME; } obj = NULL; if (get_maps(maps, "check-sibling", &obj)) { if (cfg_obj_asboolean(obj)) zone_options |= DNS_ZONEOPT_CHECKSIBLING; else zone_options &= ~DNS_ZONEOPT_CHECKSIBLING; } obj = NULL; if (get_checknames(maps, &obj)) { if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { zone_options |= DNS_ZONEOPT_CHECKNAMES; zone_options &= ~DNS_ZONEOPT_CHECKNAMESFAIL; } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { zone_options |= DNS_ZONEOPT_CHECKNAMES; zone_options |= DNS_ZONEOPT_CHECKNAMESFAIL; } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { zone_options &= ~DNS_ZONEOPT_CHECKNAMES; zone_options &= ~DNS_ZONEOPT_CHECKNAMESFAIL; } else INSIST(0); } else { zone_options |= DNS_ZONEOPT_CHECKNAMES; zone_options |= DNS_ZONEOPT_CHECKNAMESFAIL; } masterformat = dns_masterformat_text; fmtobj = NULL; result = config_get(maps, "masterfile-format", &fmtobj); if (result == ISC_R_SUCCESS) { const char *masterformatstr = cfg_obj_asstring(fmtobj); if (strcasecmp(masterformatstr, "text") == 0) masterformat = dns_masterformat_text; else if (strcasecmp(masterformatstr, "raw") == 0) masterformat = dns_masterformat_raw; else INSIST(0); } result = load_zone(mctx, zname, zfile, masterformat, zclass, NULL); if (result != ISC_R_SUCCESS) fprintf(stderr, "%s/%s/%s: %s\n", view, zname, zclass, dns_result_totext(result)); return(result); }
isc_result_t ns_tkeyctx_fromconfig(const cfg_obj_t *options, isc_mem_t *mctx, isc_entropy_t *ectx, dns_tkeyctx_t **tctxp) { isc_result_t result; dns_tkeyctx_t *tctx = NULL; const char *s; isc_uint32_t n; dns_fixedname_t fname; dns_name_t *name; isc_buffer_t b; const cfg_obj_t *obj; int type; result = dns_tkeyctx_create(mctx, ectx, &tctx); if (result != ISC_R_SUCCESS) return (result); obj = NULL; result = cfg_map_get(options, "tkey-dhkey", &obj); if (result == ISC_R_SUCCESS) { s = cfg_obj_asstring(cfg_tuple_get(obj, "name")); n = cfg_obj_asuint32(cfg_tuple_get(obj, "keyid")); isc_buffer_constinit(&b, s, strlen(s)); isc_buffer_add(&b, strlen(s)); dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); RETERR(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); type = DST_TYPE_PUBLIC|DST_TYPE_PRIVATE|DST_TYPE_KEY; RETERR(dst_key_fromfile(name, (dns_keytag_t) n, DNS_KEYALG_DH, type, NULL, mctx, &tctx->dhkey)); } obj = NULL; result = cfg_map_get(options, "tkey-domain", &obj); if (result == ISC_R_SUCCESS) { s = cfg_obj_asstring(obj); isc_buffer_constinit(&b, s, strlen(s)); isc_buffer_add(&b, strlen(s)); dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); RETERR(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); tctx->domain = isc_mem_get(mctx, sizeof(dns_name_t)); if (tctx->domain == NULL) { result = ISC_R_NOMEMORY; goto failure; } dns_name_init(tctx->domain, NULL); RETERR(dns_name_dup(name, mctx, tctx->domain)); } obj = NULL; result = cfg_map_get(options, "tkey-gssapi-credential", &obj); if (result == ISC_R_SUCCESS) { s = cfg_obj_asstring(obj); isc_buffer_constinit(&b, s, strlen(s)); isc_buffer_add(&b, strlen(s)); dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); RETERR(dns_name_fromtext(name, &b, dns_rootname, 0, NULL)); RETERR(dst_gssapi_acquirecred(name, ISC_FALSE, &tctx->gsscred)); } obj = NULL; result = cfg_map_get(options, "tkey-gssapi-keytab", &obj); if (result == ISC_R_SUCCESS) { s = cfg_obj_asstring(obj); tctx->gssapi_keytab = isc_mem_strdup(mctx, s); if (tctx->gssapi_keytab == NULL) { result = ISC_R_NOMEMORY; goto failure; } } *tctxp = tctx; return (ISC_R_SUCCESS); failure: dns_tkeyctx_destroy(&tctx); return (result); }
/* * Handle lwresd manager objects */ isc_result_t ns_lwdmanager_create(isc_mem_t *mctx, const cfg_obj_t *lwres, ns_lwresd_t **lwresdp) { ns_lwresd_t *lwresd; const char *vname; dns_rdataclass_t vclass; const cfg_obj_t *obj, *viewobj, *searchobj; const cfg_listelt_t *element; isc_result_t result; INSIST(lwresdp != NULL && *lwresdp == NULL); lwresd = isc_mem_get(mctx, sizeof(ns_lwresd_t)); if (lwresd == NULL) return (ISC_R_NOMEMORY); lwresd->mctx = NULL; isc_mem_attach(mctx, &lwresd->mctx); lwresd->view = NULL; lwresd->search = NULL; lwresd->refs = 1; obj = NULL; (void)cfg_map_get(lwres, "ndots", &obj); if (obj != NULL) lwresd->ndots = cfg_obj_asuint32(obj); else lwresd->ndots = 1; RUNTIME_CHECK(isc_mutex_init(&lwresd->lock) == ISC_R_SUCCESS); lwresd->shutting_down = ISC_FALSE; viewobj = NULL; (void)cfg_map_get(lwres, "view", &viewobj); if (viewobj != NULL) { vname = cfg_obj_asstring(cfg_tuple_get(viewobj, "name")); obj = cfg_tuple_get(viewobj, "class"); result = ns_config_getclass(obj, dns_rdataclass_in, &vclass); if (result != ISC_R_SUCCESS) goto fail; } else { vname = "_default"; vclass = dns_rdataclass_in; } result = dns_viewlist_find(&ns_g_server->viewlist, vname, vclass, &lwresd->view); if (result != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_LWRESD, ISC_LOG_WARNING, "couldn't find view %s", vname); goto fail; } searchobj = NULL; (void)cfg_map_get(lwres, "search", &searchobj); if (searchobj != NULL) { lwresd->search = NULL; result = ns_lwsearchlist_create(lwresd->mctx, &lwresd->search); if (result != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_LWRESD, ISC_LOG_WARNING, "couldn't create searchlist"); goto fail; } for (element = cfg_list_first(searchobj); element != NULL; element = cfg_list_next(element)) { const cfg_obj_t *search; const char *searchstr; isc_buffer_t namebuf; dns_fixedname_t fname; dns_name_t *name; search = cfg_listelt_value(element); searchstr = cfg_obj_asstring(search); dns_fixedname_init(&fname); name = dns_fixedname_name(&fname); isc_buffer_init(&namebuf, searchstr, strlen(searchstr)); isc_buffer_add(&namebuf, strlen(searchstr)); result = dns_name_fromtext(name, &namebuf, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_LWRESD, ISC_LOG_WARNING, "invalid name %s in searchlist", searchstr); continue; } result = ns_lwsearchlist_append(lwresd->search, name); if (result != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_LWRESD, ISC_LOG_WARNING, "couldn't update searchlist"); goto fail; } } } lwresd->magic = LWRESD_MAGIC; *lwresdp = lwresd; return (ISC_R_SUCCESS); fail: if (lwresd->view != NULL) dns_view_detach(&lwresd->view); if (lwresd->search != NULL) ns_lwsearchlist_detach(&lwresd->search); if (lwresd->mctx != NULL) isc_mem_detach(&lwresd->mctx); isc_mem_put(mctx, lwresd, sizeof(ns_lwresd_t)); return (result); }
static isc_result_t get_rndckey(isc_mem_t *mctx, controlkeylist_t *keyids) { isc_result_t result; cfg_parser_t *pctx = NULL; cfg_obj_t *config = NULL; const cfg_obj_t *key = NULL; const cfg_obj_t *algobj = NULL; const cfg_obj_t *secretobj = NULL; const char *algstr = NULL; const char *secretstr = NULL; controlkey_t *keyid = NULL; char secret[1024]; unsigned int algtype; isc_buffer_t b; isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_CONTROL, ISC_LOG_INFO, "configuring command channel from '%s'", ns_g_keyfile); if (! isc_file_exists(ns_g_keyfile)) return (ISC_R_FILENOTFOUND); CHECK(cfg_parser_create(mctx, ns_g_lctx, &pctx)); CHECK(cfg_parse_file(pctx, ns_g_keyfile, &cfg_type_rndckey, &config)); CHECK(cfg_map_get(config, "key", &key)); keyid = isc_mem_get(mctx, sizeof(*keyid)); if (keyid == NULL) CHECK(ISC_R_NOMEMORY); keyid->keyname = isc_mem_strdup(mctx, cfg_obj_asstring(cfg_map_getname(key))); keyid->secret.base = NULL; keyid->secret.length = 0; keyid->algorithm = DST_ALG_UNKNOWN; ISC_LINK_INIT(keyid, link); if (keyid->keyname == NULL) CHECK(ISC_R_NOMEMORY); CHECK(bind9_check_key(key, ns_g_lctx)); (void)cfg_map_get(key, "algorithm", &algobj); (void)cfg_map_get(key, "secret", &secretobj); INSIST(algobj != NULL && secretobj != NULL); algstr = cfg_obj_asstring(algobj); secretstr = cfg_obj_asstring(secretobj); if (ns_config_getkeyalgorithm2(algstr, NULL, &algtype, NULL) != ISC_R_SUCCESS) { cfg_obj_log(key, ns_g_lctx, ISC_LOG_WARNING, "unsupported algorithm '%s' in " "key '%s' for use with command " "channel", algstr, keyid->keyname); goto cleanup; } keyid->algorithm = algtype; isc_buffer_init(&b, secret, sizeof(secret)); result = isc_base64_decodestring(secretstr, &b); if (result != ISC_R_SUCCESS) { cfg_obj_log(key, ns_g_lctx, ISC_LOG_WARNING, "secret for key '%s' on command channel: %s", keyid->keyname, isc_result_totext(result)); goto cleanup; } keyid->secret.length = isc_buffer_usedlength(&b); keyid->secret.base = isc_mem_get(mctx, keyid->secret.length); if (keyid->secret.base == NULL) { cfg_obj_log(key, ns_g_lctx, ISC_LOG_WARNING, "couldn't register key '%s': " "out of memory", keyid->keyname); CHECK(ISC_R_NOMEMORY); } memmove(keyid->secret.base, isc_buffer_base(&b), keyid->secret.length); ISC_LIST_APPEND(*keyids, keyid, link); keyid = NULL; result = ISC_R_SUCCESS; cleanup: if (keyid != NULL) free_controlkey(keyid, mctx); if (config != NULL) cfg_obj_destroy(pctx, &config); if (pctx != NULL) cfg_parser_destroy(&pctx); return (result); }
isc_result_t ns_controls_configure(ns_controls_t *cp, const cfg_obj_t *config, cfg_aclconfctx_t *aclconfctx) { controllistener_t *listener; controllistenerlist_t new_listeners; const cfg_obj_t *controlslist = NULL; const cfg_listelt_t *element, *element2; char socktext[ISC_SOCKADDR_FORMATSIZE]; ISC_LIST_INIT(new_listeners); /* * Get the list of named.conf 'controls' statements. */ (void)cfg_map_get(config, "controls", &controlslist); /* * Run through the new control channel list, noting sockets that * are already being listened on and moving them to the new list. * * Identifying duplicate addr/port combinations is left to either * the underlying config code, or to the bind attempt getting an * address-in-use error. */ if (controlslist != NULL) { for (element = cfg_list_first(controlslist); element != NULL; element = cfg_list_next(element)) { const cfg_obj_t *controls; const cfg_obj_t *inetcontrols = NULL; controls = cfg_listelt_value(element); (void)cfg_map_get(controls, "inet", &inetcontrols); if (inetcontrols == NULL) continue; for (element2 = cfg_list_first(inetcontrols); element2 != NULL; element2 = cfg_list_next(element2)) { const cfg_obj_t *control; const cfg_obj_t *obj; isc_sockaddr_t addr; /* * The parser handles BIND 8 configuration file * syntax, so it allows unix phrases as well * inet phrases with no keys{} clause. */ control = cfg_listelt_value(element2); obj = cfg_tuple_get(control, "address"); addr = *cfg_obj_assockaddr(obj); if (isc_sockaddr_getport(&addr) == 0) isc_sockaddr_setport(&addr, NS_CONTROL_PORT); isc_sockaddr_format(&addr, socktext, sizeof(socktext)); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_CONTROL, ISC_LOG_DEBUG(9), "processing control channel %s", socktext); update_listener(cp, &listener, control, config, &addr, aclconfctx, socktext, isc_sockettype_tcp); if (listener != NULL) /* * Remove the listener from the old * list, so it won't be shut down. */ ISC_LIST_UNLINK(cp->listeners, listener, link); else /* * This is a new listener. */ add_listener(cp, &listener, control, config, &addr, aclconfctx, socktext, isc_sockettype_tcp); if (listener != NULL) ISC_LIST_APPEND(new_listeners, listener, link); } } for (element = cfg_list_first(controlslist); element != NULL; element = cfg_list_next(element)) { const cfg_obj_t *controls; const cfg_obj_t *unixcontrols = NULL; controls = cfg_listelt_value(element); (void)cfg_map_get(controls, "unix", &unixcontrols); if (unixcontrols == NULL) continue; for (element2 = cfg_list_first(unixcontrols); element2 != NULL; element2 = cfg_list_next(element2)) { const cfg_obj_t *control; const cfg_obj_t *path; isc_sockaddr_t addr; isc_result_t result; /* * The parser handles BIND 8 configuration file * syntax, so it allows unix phrases as well * inet phrases with no keys{} clause. */ control = cfg_listelt_value(element2); path = cfg_tuple_get(control, "path"); result = isc_sockaddr_frompath(&addr, cfg_obj_asstring(path)); if (result != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_CONTROL, ISC_LOG_DEBUG(9), "control channel '%s': %s", cfg_obj_asstring(path), isc_result_totext(result)); continue; } isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_CONTROL, ISC_LOG_DEBUG(9), "processing control channel '%s'", cfg_obj_asstring(path)); update_listener(cp, &listener, control, config, &addr, aclconfctx, cfg_obj_asstring(path), isc_sockettype_unix); if (listener != NULL) /* * Remove the listener from the old * list, so it won't be shut down. */ ISC_LIST_UNLINK(cp->listeners, listener, link); else /* * This is a new listener. */ add_listener(cp, &listener, control, config, &addr, aclconfctx, cfg_obj_asstring(path), isc_sockettype_unix); if (listener != NULL) ISC_LIST_APPEND(new_listeners, listener, link); } } } else { int i; for (i = 0; i < 2; i++) { isc_sockaddr_t addr; if (i == 0) { struct in_addr localhost; if (isc_net_probeipv4() != ISC_R_SUCCESS) continue; localhost.s_addr = htonl(INADDR_LOOPBACK); isc_sockaddr_fromin(&addr, &localhost, 0); } else { if (isc_net_probeipv6() != ISC_R_SUCCESS) continue; isc_sockaddr_fromin6(&addr, &in6addr_loopback, 0); } isc_sockaddr_setport(&addr, NS_CONTROL_PORT); isc_sockaddr_format(&addr, socktext, sizeof(socktext)); update_listener(cp, &listener, NULL, NULL, &addr, NULL, socktext, isc_sockettype_tcp); if (listener != NULL) /* * Remove the listener from the old * list, so it won't be shut down. */ ISC_LIST_UNLINK(cp->listeners, listener, link); else /* * This is a new listener. */ add_listener(cp, &listener, NULL, NULL, &addr, NULL, socktext, isc_sockettype_tcp); if (listener != NULL) ISC_LIST_APPEND(new_listeners, listener, link); } } /* * ns_control_shutdown() will stop whatever is on the global * listeners list, which currently only has whatever sockaddrs * were in the previous configuration (if any) that do not * remain in the current configuration. */ controls_shutdown(cp); /* * Put all of the valid listeners on the listeners list. * Anything already on listeners in the process of shutting * down will be taken care of by listen_done(). */ ISC_LIST_APPENDLIST(cp->listeners, new_listeners, link); return (ISC_R_SUCCESS); }
/*% * Configure static-stub zone. */ static isc_result_t configure_staticstub(const cfg_obj_t *zconfig, dns_zone_t *zone, const char *zname, const char *dbtype) { int i = 0; const cfg_obj_t *obj; isc_mem_t *mctx = dns_zone_getmctx(zone); dns_db_t *db = NULL; dns_dbversion_t *dbversion = NULL; dns_dbnode_t *apexnode = NULL; dns_name_t apexname; isc_result_t result; dns_rdataset_t rdataset; dns_rdatalist_t rdatalist_ns, rdatalist_a, rdatalist_aaaa; dns_rdatalist_t* rdatalists[] = { &rdatalist_ns, &rdatalist_a, &rdatalist_aaaa, NULL }; dns_rdata_t *rdata; isc_region_t region; /* Create the DB beforehand */ RETERR(dns_db_create(mctx, dbtype, dns_zone_getorigin(zone), dns_dbtype_stub, dns_zone_getclass(zone), 0, NULL, &db)); dns_zone_setdb(zone, db); dns_rdatalist_init(&rdatalist_ns); rdatalist_ns.rdclass = dns_zone_getclass(zone); rdatalist_ns.type = dns_rdatatype_ns; rdatalist_ns.ttl = STATICSTUB_SERVER_TTL; dns_rdatalist_init(&rdatalist_a); rdatalist_a.rdclass = dns_zone_getclass(zone); rdatalist_a.type = dns_rdatatype_a; rdatalist_a.ttl = STATICSTUB_SERVER_TTL; dns_rdatalist_init(&rdatalist_aaaa); rdatalist_aaaa.rdclass = dns_zone_getclass(zone); rdatalist_aaaa.type = dns_rdatatype_aaaa; rdatalist_aaaa.ttl = STATICSTUB_SERVER_TTL; /* Prepare zone RRs from the configuration */ obj = NULL; result = cfg_map_get(zconfig, "server-addresses", &obj); if (result == ISC_R_SUCCESS) { INSIST(obj != NULL); result = configure_staticstub_serveraddrs(obj, zone, &rdatalist_ns, &rdatalist_a, &rdatalist_aaaa); if (result != ISC_R_SUCCESS) goto cleanup; } obj = NULL; result = cfg_map_get(zconfig, "server-names", &obj); if (result == ISC_R_SUCCESS) { INSIST(obj != NULL); result = configure_staticstub_servernames(obj, zone, &rdatalist_ns, zname); if (result != ISC_R_SUCCESS) goto cleanup; } /* * Sanity check: there should be at least one NS RR at the zone apex * to trigger delegation. */ if (ISC_LIST_EMPTY(rdatalist_ns.rdata)) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "No NS record is configured for a " "static-stub zone '%s'", zname); result = ISC_R_FAILURE; goto cleanup; } /* * Now add NS and glue A/AAAA RRsets to the zone DB. * First open a new version for the add operation and get a pointer * to the apex node (all RRs are of the apex name). */ result = dns_db_newversion(db, &dbversion); if (result != ISC_R_SUCCESS) goto cleanup; dns_name_init(&apexname, NULL); dns_name_clone(dns_zone_getorigin(zone), &apexname); result = dns_db_findnode(db, &apexname, ISC_FALSE, &apexnode); if (result != ISC_R_SUCCESS) goto cleanup; /* Add NS RRset */ dns_rdataset_init(&rdataset); RUNTIME_CHECK(dns_rdatalist_tordataset(&rdatalist_ns, &rdataset) == ISC_R_SUCCESS); result = dns_db_addrdataset(db, apexnode, dbversion, 0, &rdataset, 0, NULL); dns_rdataset_disassociate(&rdataset); if (result != ISC_R_SUCCESS) goto cleanup; /* Add glue A RRset, if any */ if (!ISC_LIST_EMPTY(rdatalist_a.rdata)) { RUNTIME_CHECK(dns_rdatalist_tordataset(&rdatalist_a, &rdataset) == ISC_R_SUCCESS); result = dns_db_addrdataset(db, apexnode, dbversion, 0, &rdataset, 0, NULL); dns_rdataset_disassociate(&rdataset); if (result != ISC_R_SUCCESS) goto cleanup; } /* Add glue AAAA RRset, if any */ if (!ISC_LIST_EMPTY(rdatalist_aaaa.rdata)) { RUNTIME_CHECK(dns_rdatalist_tordataset(&rdatalist_aaaa, &rdataset) == ISC_R_SUCCESS); result = dns_db_addrdataset(db, apexnode, dbversion, 0, &rdataset, 0, NULL); dns_rdataset_disassociate(&rdataset); if (result != ISC_R_SUCCESS) goto cleanup; } result = ISC_R_SUCCESS; cleanup: if (apexnode != NULL) dns_db_detachnode(db, &apexnode); if (dbversion != NULL) dns_db_closeversion(db, &dbversion, ISC_TRUE); if (db != NULL) dns_db_detach(&db); for (i = 0; rdatalists[i] != NULL; i++) { while ((rdata = ISC_LIST_HEAD(rdatalists[i]->rdata)) != NULL) { ISC_LIST_UNLINK(rdatalists[i]->rdata, rdata, link); dns_rdata_toregion(rdata, ®ion); isc_mem_put(mctx, rdata, sizeof(*rdata) + region.length); } } return (result); }
/*% * Parse the zone update-policy statement. */ static isc_result_t configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone, const char *zname) { const cfg_obj_t *updatepolicy = NULL; const cfg_listelt_t *element, *element2; dns_ssutable_t *table = NULL; isc_mem_t *mctx = dns_zone_getmctx(zone); isc_boolean_t autoddns = ISC_FALSE; isc_result_t result; (void)cfg_map_get(zconfig, "update-policy", &updatepolicy); if (updatepolicy == NULL) { dns_zone_setssutable(zone, NULL); return (ISC_R_SUCCESS); } if (cfg_obj_isstring(updatepolicy) && strcmp("local", cfg_obj_asstring(updatepolicy)) == 0) { autoddns = ISC_TRUE; updatepolicy = NULL; } result = dns_ssutable_create(mctx, &table); if (result != ISC_R_SUCCESS) return (result); for (element = cfg_list_first(updatepolicy); element != NULL; element = cfg_list_next(element)) { const cfg_obj_t *stmt = cfg_listelt_value(element); const cfg_obj_t *mode = cfg_tuple_get(stmt, "mode"); const cfg_obj_t *identity = cfg_tuple_get(stmt, "identity"); const cfg_obj_t *matchtype = cfg_tuple_get(stmt, "matchtype"); const cfg_obj_t *dname = cfg_tuple_get(stmt, "name"); const cfg_obj_t *typelist = cfg_tuple_get(stmt, "types"); const char *str; isc_boolean_t grant = ISC_FALSE; isc_boolean_t usezone = ISC_FALSE; unsigned int mtype = DNS_SSUMATCHTYPE_NAME; dns_fixedname_t fname, fident; isc_buffer_t b; dns_rdatatype_t *types; unsigned int i, n; str = cfg_obj_asstring(mode); if (strcasecmp(str, "grant") == 0) grant = ISC_TRUE; else if (strcasecmp(str, "deny") == 0) grant = ISC_FALSE; else INSIST(0); str = cfg_obj_asstring(matchtype); if (strcasecmp(str, "name") == 0) mtype = DNS_SSUMATCHTYPE_NAME; else if (strcasecmp(str, "subdomain") == 0) mtype = DNS_SSUMATCHTYPE_SUBDOMAIN; else if (strcasecmp(str, "wildcard") == 0) mtype = DNS_SSUMATCHTYPE_WILDCARD; else if (strcasecmp(str, "self") == 0) mtype = DNS_SSUMATCHTYPE_SELF; else if (strcasecmp(str, "selfsub") == 0) mtype = DNS_SSUMATCHTYPE_SELFSUB; else if (strcasecmp(str, "selfwild") == 0) mtype = DNS_SSUMATCHTYPE_SELFWILD; else if (strcasecmp(str, "ms-self") == 0) mtype = DNS_SSUMATCHTYPE_SELFMS; else if (strcasecmp(str, "krb5-self") == 0) mtype = DNS_SSUMATCHTYPE_SELFKRB5; else if (strcasecmp(str, "ms-subdomain") == 0) mtype = DNS_SSUMATCHTYPE_SUBDOMAINMS; else if (strcasecmp(str, "krb5-subdomain") == 0) mtype = DNS_SSUMATCHTYPE_SUBDOMAINKRB5; else if (strcasecmp(str, "tcp-self") == 0) mtype = DNS_SSUMATCHTYPE_TCPSELF; else if (strcasecmp(str, "6to4-self") == 0) mtype = DNS_SSUMATCHTYPE_6TO4SELF; else if (strcasecmp(str, "zonesub") == 0) { mtype = DNS_SSUMATCHTYPE_SUBDOMAIN; usezone = ISC_TRUE; } else if (strcasecmp(str, "external") == 0) mtype = DNS_SSUMATCHTYPE_EXTERNAL; else INSIST(0); dns_fixedname_init(&fident); str = cfg_obj_asstring(identity); isc_buffer_init(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); result = dns_name_fromtext(dns_fixedname_name(&fident), &b, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) { cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR, "'%s' is not a valid name", str); goto cleanup; } dns_fixedname_init(&fname); if (usezone) { result = dns_name_copy(dns_zone_getorigin(zone), dns_fixedname_name(&fname), NULL); if (result != ISC_R_SUCCESS) { cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR, "error copying origin: %s", isc_result_totext(result)); goto cleanup; } } else { str = cfg_obj_asstring(dname); isc_buffer_init(&b, str, strlen(str)); isc_buffer_add(&b, strlen(str)); result = dns_name_fromtext(dns_fixedname_name(&fname), &b, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) { cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR, "'%s' is not a valid name", str); goto cleanup; } } n = ns_config_listcount(typelist); if (n == 0) types = NULL; else { types = isc_mem_get(mctx, n * sizeof(dns_rdatatype_t)); if (types == NULL) { result = ISC_R_NOMEMORY; goto cleanup; } } i = 0; for (element2 = cfg_list_first(typelist); element2 != NULL; element2 = cfg_list_next(element2)) { const cfg_obj_t *typeobj; isc_textregion_t r; INSIST(i < n); typeobj = cfg_listelt_value(element2); str = cfg_obj_asstring(typeobj); DE_CONST(str, r.base); r.length = strlen(str); result = dns_rdatatype_fromtext(&types[i++], &r); if (result != ISC_R_SUCCESS) { cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR, "'%s' is not a valid type", str); isc_mem_put(mctx, types, n * sizeof(dns_rdatatype_t)); goto cleanup; } } INSIST(i == n); result = dns_ssutable_addrule(table, grant, dns_fixedname_name(&fident), mtype, dns_fixedname_name(&fname), n, types); if (types != NULL) isc_mem_put(mctx, types, n * sizeof(dns_rdatatype_t)); if (result != ISC_R_SUCCESS) { goto cleanup; } } /* * If "update-policy local;" and a session key exists, * then use the default policy, which is equivalent to: * update-policy { grant <session-keyname> zonesub any; }; */ if (autoddns) { dns_rdatatype_t any = dns_rdatatype_any; if (ns_g_server->session_keyname == NULL) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "failed to enable auto DDNS policy " "for zone %s: session key not found", zname); result = ISC_R_NOTFOUND; goto cleanup; } result = dns_ssutable_addrule(table, ISC_TRUE, ns_g_server->session_keyname, DNS_SSUMATCHTYPE_SUBDOMAIN, dns_zone_getorigin(zone), 1, &any); if (result != ISC_R_SUCCESS) goto cleanup; } result = ISC_R_SUCCESS; dns_zone_setssutable(zone, table); cleanup: dns_ssutable_detach(&table); return (result); }
static isc_result_t add_initial_keys(const cfg_obj_t *list, dns_tsig_keyring_t *ring, isc_mem_t *mctx) { dns_tsigkey_t *tsigkey = NULL; const cfg_listelt_t *element; const cfg_obj_t *key = NULL; const char *keyid = NULL; unsigned char *secret = NULL; int secretalloc = 0; int secretlen = 0; isc_result_t ret; isc_stdtime_t now; isc_uint16_t bits; for (element = cfg_list_first(list); element != NULL; element = cfg_list_next(element)) { const cfg_obj_t *algobj = NULL; const cfg_obj_t *secretobj = NULL; dns_name_t keyname; dns_name_t *alg; const char *algstr; char keynamedata[1024]; isc_buffer_t keynamesrc, keynamebuf; const char *secretstr; isc_buffer_t secretbuf; key = cfg_listelt_value(element); keyid = cfg_obj_asstring(cfg_map_getname(key)); algobj = NULL; secretobj = NULL; (void)cfg_map_get(key, "algorithm", &algobj); (void)cfg_map_get(key, "secret", &secretobj); INSIST(algobj != NULL && secretobj != NULL); /* * Create the key name. */ dns_name_init(&keyname, NULL); isc_buffer_init(&keynamesrc, keyid, strlen(keyid)); isc_buffer_add(&keynamesrc, strlen(keyid)); isc_buffer_init(&keynamebuf, keynamedata, sizeof(keynamedata)); ret = dns_name_fromtext(&keyname, &keynamesrc, dns_rootname, ISC_TRUE, &keynamebuf); if (ret != ISC_R_SUCCESS) goto failure; /* * Create the algorithm. */ algstr = cfg_obj_asstring(algobj); if (ns_config_getkeyalgorithm(algstr, &alg, &bits) != ISC_R_SUCCESS) { cfg_obj_log(algobj, ns_g_lctx, ISC_LOG_ERROR, "key '%s': has a unsupported algorithm '%s'", keyid, algstr); ret = DNS_R_BADALG; goto failure; } secretstr = cfg_obj_asstring(secretobj); secretalloc = secretlen = strlen(secretstr) * 3 / 4; secret = isc_mem_get(mctx, secretlen); if (secret == NULL) { ret = ISC_R_NOMEMORY; goto failure; } isc_buffer_init(&secretbuf, secret, secretlen); ret = isc_base64_decodestring(secretstr, &secretbuf); if (ret != ISC_R_SUCCESS) goto failure; secretlen = isc_buffer_usedlength(&secretbuf); isc_stdtime_get(&now); ret = dns_tsigkey_create(&keyname, alg, secret, secretlen, ISC_FALSE, NULL, now, now, mctx, ring, &tsigkey); isc_mem_put(mctx, secret, secretalloc); secret = NULL; if (ret != ISC_R_SUCCESS) goto failure; /* * Set digest bits. */ dst_key_setbits(tsigkey->key, bits); dns_tsigkey_detach(&tsigkey); } return (ISC_R_SUCCESS); failure: cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR, "configuring key '%s': %s", keyid, isc_result_totext(ret)); if (secret != NULL) isc_mem_put(mctx, secret, secretalloc); return (ret); }
static isc_result_t configure_dnsseckeys(irs_dnsconf_t *conf, cfg_obj_t *cfgobj, 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; isc_uint32_t flags, proto, alg; const char *keystr, *keynamestr; unsigned char keydata[4096]; isc_buffer_t keydatabuf_base, *keydatabuf; 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; cfg_map_get(cfgobj, "trusted-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)) { 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 = (isc_uint16_t)flags; keystruct.protocol = (isc_uint8_t)proto; keystruct.algorithm = (isc_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 */ dns_fixedname_init(&fkeyname); keyname_base = dns_fixedname_name(&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); } } 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 ns_statschannels_configure(ns_server_t *server, const cfg_obj_t *config, cfg_aclconfctx_t *aclconfctx) { ns_statschannel_t *listener, *listener_next; ns_statschannellist_t new_listeners; const cfg_obj_t *statschannellist = NULL; const cfg_listelt_t *element, *element2; char socktext[ISC_SOCKADDR_FORMATSIZE]; RUNTIME_CHECK(isc_once_do(&once, init_desc) == ISC_R_SUCCESS); ISC_LIST_INIT(new_listeners); /* * Get the list of named.conf 'statistics-channels' statements. */ (void)cfg_map_get(config, "statistics-channels", &statschannellist); /* * Run through the new address/port list, noting sockets that are * already being listened on and moving them to the new list. * * Identifying duplicate addr/port combinations is left to either * the underlying config code, or to the bind attempt getting an * address-in-use error. */ if (statschannellist != NULL) { #ifndef HAVE_LIBXML2 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_WARNING, "statistics-channels specified but not effective " "due to missing XML library"); #endif for (element = cfg_list_first(statschannellist); element != NULL; element = cfg_list_next(element)) { const cfg_obj_t *statschannel; const cfg_obj_t *listenercfg = NULL; statschannel = cfg_listelt_value(element); (void)cfg_map_get(statschannel, "inet", &listenercfg); if (listenercfg == NULL) continue; for (element2 = cfg_list_first(listenercfg); element2 != NULL; element2 = cfg_list_next(element2)) { const cfg_obj_t *listen_params; const cfg_obj_t *obj; isc_sockaddr_t addr; listen_params = cfg_listelt_value(element2); obj = cfg_tuple_get(listen_params, "address"); addr = *cfg_obj_assockaddr(obj); if (isc_sockaddr_getport(&addr) == 0) isc_sockaddr_setport(&addr, NS_STATSCHANNEL_HTTPPORT); isc_sockaddr_format(&addr, socktext, sizeof(socktext)); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_DEBUG(9), "processing statistics " "channel %s", socktext); update_listener(server, &listener, listen_params, config, &addr, aclconfctx, socktext); if (listener != NULL) { /* * Remove the listener from the old * list, so it won't be shut down. */ ISC_LIST_UNLINK(server->statschannels, listener, link); } else { /* * This is a new listener. */ isc_result_t r; r = add_listener(server, &listener, listen_params, config, &addr, aclconfctx, socktext); if (r != ISC_R_SUCCESS) { cfg_obj_log(listen_params, ns_g_lctx, ISC_LOG_WARNING, "couldn't allocate " "statistics channel" " %s: %s", socktext, isc_result_totext(r)); } } if (listener != NULL) ISC_LIST_APPEND(new_listeners, listener, link); } } } for (listener = ISC_LIST_HEAD(server->statschannels); listener != NULL; listener = listener_next) { listener_next = ISC_LIST_NEXT(listener, link); ISC_LIST_UNLINK(server->statschannels, listener, link); shutdown_listener(listener); } ISC_LIST_APPENDLIST(server->statschannels, new_listeners, link); return (ISC_R_SUCCESS); }
/*% configure the zone */ static isc_result_t configure_zone(const char *vclass, const char *view, const cfg_obj_t *zconfig, const cfg_obj_t *vconfig, const cfg_obj_t *config, isc_mem_t *mctx) { int i = 0; isc_result_t result; const char *zclass; const char *zname; const char *zfile = NULL; const cfg_obj_t *maps[4]; const cfg_obj_t *mastersobj = NULL; const cfg_obj_t *inviewobj = NULL; const cfg_obj_t *zoptions = NULL; const cfg_obj_t *classobj = NULL; const cfg_obj_t *typeobj = NULL; const cfg_obj_t *fileobj = NULL; const cfg_obj_t *dlzobj = NULL; const cfg_obj_t *dbobj = NULL; const cfg_obj_t *obj = NULL; const cfg_obj_t *fmtobj = NULL; dns_masterformat_t masterformat; dns_ttl_t maxttl = 0; zone_options = DNS_ZONEOPT_CHECKNS | DNS_ZONEOPT_MANYERRORS; zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name")); classobj = cfg_tuple_get(zconfig, "class"); if (!cfg_obj_isstring(classobj)) zclass = vclass; else zclass = cfg_obj_asstring(classobj); zoptions = cfg_tuple_get(zconfig, "options"); maps[i++] = zoptions; if (vconfig != NULL) maps[i++] = cfg_tuple_get(vconfig, "options"); if (config != NULL) { cfg_map_get(config, "options", &obj); if (obj != NULL) maps[i++] = obj; } maps[i] = NULL; cfg_map_get(zoptions, "in-view", &inviewobj); if (inviewobj != NULL) return (ISC_R_SUCCESS); cfg_map_get(zoptions, "type", &typeobj); if (typeobj == NULL) return (ISC_R_FAILURE); /* * Skip checks when using an alternate data source. */ cfg_map_get(zoptions, "database", &dbobj); if (dbobj != NULL && strcmp("rbt", cfg_obj_asstring(dbobj)) != 0 && strcmp("rbt64", cfg_obj_asstring(dbobj)) != 0) return (ISC_R_SUCCESS); cfg_map_get(zoptions, "dlz", &dlzobj); if (dlzobj != NULL) return (ISC_R_SUCCESS); cfg_map_get(zoptions, "file", &fileobj); if (fileobj != NULL) zfile = cfg_obj_asstring(fileobj); /* * Check hints files for hint zones. * Skip loading checks for any type other than * master and redirect */ if (strcasecmp(cfg_obj_asstring(typeobj), "hint") == 0) return (configure_hint(zfile, zclass, mctx)); else if ((strcasecmp(cfg_obj_asstring(typeobj), "master") != 0) && (strcasecmp(cfg_obj_asstring(typeobj), "redirect") != 0)) return (ISC_R_SUCCESS); /* * Is the redirect zone configured as a slave? */ if (strcasecmp(cfg_obj_asstring(typeobj), "redirect") == 0) { cfg_map_get(zoptions, "masters", &mastersobj); if (mastersobj != NULL) return (ISC_R_SUCCESS); } if (zfile == NULL) return (ISC_R_FAILURE); obj = NULL; if (get_maps(maps, "check-dup-records", &obj)) { if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { zone_options |= DNS_ZONEOPT_CHECKDUPRR; zone_options &= ~DNS_ZONEOPT_CHECKDUPRRFAIL; } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { zone_options |= DNS_ZONEOPT_CHECKDUPRR; zone_options |= DNS_ZONEOPT_CHECKDUPRRFAIL; } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { zone_options &= ~DNS_ZONEOPT_CHECKDUPRR; zone_options &= ~DNS_ZONEOPT_CHECKDUPRRFAIL; } else INSIST(0); } else { zone_options |= DNS_ZONEOPT_CHECKDUPRR; zone_options &= ~DNS_ZONEOPT_CHECKDUPRRFAIL; } obj = NULL; if (get_maps(maps, "check-mx", &obj)) { if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { zone_options |= DNS_ZONEOPT_CHECKMX; zone_options &= ~DNS_ZONEOPT_CHECKMXFAIL; } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { zone_options |= DNS_ZONEOPT_CHECKMX; zone_options |= DNS_ZONEOPT_CHECKMXFAIL; } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { zone_options &= ~DNS_ZONEOPT_CHECKMX; zone_options &= ~DNS_ZONEOPT_CHECKMXFAIL; } else INSIST(0); } else { zone_options |= DNS_ZONEOPT_CHECKMX; zone_options &= ~DNS_ZONEOPT_CHECKMXFAIL; } obj = NULL; if (get_maps(maps, "check-integrity", &obj)) { if (cfg_obj_asboolean(obj)) zone_options |= DNS_ZONEOPT_CHECKINTEGRITY; else zone_options &= ~DNS_ZONEOPT_CHECKINTEGRITY; } else zone_options |= DNS_ZONEOPT_CHECKINTEGRITY; obj = NULL; if (get_maps(maps, "check-mx-cname", &obj)) { if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { zone_options |= DNS_ZONEOPT_WARNMXCNAME; zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME; } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { zone_options &= ~DNS_ZONEOPT_WARNMXCNAME; zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME; } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { zone_options |= DNS_ZONEOPT_WARNMXCNAME; zone_options |= DNS_ZONEOPT_IGNOREMXCNAME; } else INSIST(0); } else { zone_options |= DNS_ZONEOPT_WARNMXCNAME; zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME; } obj = NULL; if (get_maps(maps, "check-srv-cname", &obj)) { if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { zone_options |= DNS_ZONEOPT_WARNSRVCNAME; zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME; } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { zone_options &= ~DNS_ZONEOPT_WARNSRVCNAME; zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME; } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { zone_options |= DNS_ZONEOPT_WARNSRVCNAME; zone_options |= DNS_ZONEOPT_IGNORESRVCNAME; } else INSIST(0); } else { zone_options |= DNS_ZONEOPT_WARNSRVCNAME; zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME; } obj = NULL; if (get_maps(maps, "check-sibling", &obj)) { if (cfg_obj_asboolean(obj)) zone_options |= DNS_ZONEOPT_CHECKSIBLING; else zone_options &= ~DNS_ZONEOPT_CHECKSIBLING; } obj = NULL; if (get_maps(maps, "check-spf", &obj)) { if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { zone_options |= DNS_ZONEOPT_CHECKSPF; } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { zone_options &= ~DNS_ZONEOPT_CHECKSPF; } else INSIST(0); } else { zone_options |= DNS_ZONEOPT_CHECKSPF; } obj = NULL; if (get_checknames(maps, &obj)) { if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { zone_options |= DNS_ZONEOPT_CHECKNAMES; zone_options &= ~DNS_ZONEOPT_CHECKNAMESFAIL; } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { zone_options |= DNS_ZONEOPT_CHECKNAMES; zone_options |= DNS_ZONEOPT_CHECKNAMESFAIL; } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { zone_options &= ~DNS_ZONEOPT_CHECKNAMES; zone_options &= ~DNS_ZONEOPT_CHECKNAMESFAIL; } else INSIST(0); } else { zone_options |= DNS_ZONEOPT_CHECKNAMES; zone_options |= DNS_ZONEOPT_CHECKNAMESFAIL; } masterformat = dns_masterformat_text; fmtobj = NULL; if (get_maps(maps, "masterfile-format", &fmtobj)) { const char *masterformatstr = cfg_obj_asstring(fmtobj); if (strcasecmp(masterformatstr, "text") == 0) masterformat = dns_masterformat_text; else if (strcasecmp(masterformatstr, "raw") == 0) masterformat = dns_masterformat_raw; else if (strcasecmp(masterformatstr, "map") == 0) masterformat = dns_masterformat_map; else INSIST(0); } obj = NULL; if (get_maps(maps, "max-zone-ttl", &obj)) { maxttl = cfg_obj_asuint32(obj); zone_options2 |= DNS_ZONEOPT2_CHECKTTL; } result = load_zone(mctx, zname, zfile, masterformat, zclass, maxttl, NULL); if (result != ISC_R_SUCCESS) fprintf(stderr, "%s/%s/%s: %s\n", view, zname, zclass, dns_result_totext(result)); return (result); }
/*% * Set up a logging channel according to the named.conf data * in 'cchan' and add it to 'logconfig'. */ static isc_result_t channel_fromconf(const cfg_obj_t *channel, isc_logconfig_t *logconfig) { isc_result_t result; isc_logdestination_t dest; unsigned int type; unsigned int flags = 0; int level; const char *channelname; const cfg_obj_t *fileobj = NULL; const cfg_obj_t *syslogobj = NULL; const cfg_obj_t *nullobj = NULL; const cfg_obj_t *stderrobj = NULL; const cfg_obj_t *severity = NULL; int i; channelname = cfg_obj_asstring(cfg_map_getname(channel)); (void)cfg_map_get(channel, "file", &fileobj); (void)cfg_map_get(channel, "syslog", &syslogobj); (void)cfg_map_get(channel, "null", &nullobj); (void)cfg_map_get(channel, "stderr", &stderrobj); i = 0; if (fileobj != NULL) i++; if (syslogobj != NULL) i++; if (nullobj != NULL) i++; if (stderrobj != NULL) i++; if (i != 1) { cfg_obj_log(channel, ns_g_lctx, ISC_LOG_ERROR, "channel '%s': exactly one of file, syslog, " "null, and stderr must be present", channelname); return (ISC_R_FAILURE); } type = ISC_LOG_TONULL; if (fileobj != NULL) { const cfg_obj_t *pathobj = cfg_tuple_get(fileobj, "file"); const cfg_obj_t *sizeobj = cfg_tuple_get(fileobj, "size"); const cfg_obj_t *versionsobj = cfg_tuple_get(fileobj, "versions"); isc_int32_t versions = ISC_LOG_ROLLNEVER; isc_offset_t size = 0; type = ISC_LOG_TOFILE; if (versionsobj != NULL && cfg_obj_isuint32(versionsobj)) versions = cfg_obj_asuint32(versionsobj); if (versionsobj != NULL && cfg_obj_isstring(versionsobj) && strcasecmp(cfg_obj_asstring(versionsobj), "unlimited") == 0) versions = ISC_LOG_ROLLINFINITE; if (sizeobj != NULL && cfg_obj_isuint64(sizeobj) && cfg_obj_asuint64(sizeobj) < ISC_OFFSET_MAXIMUM) size = (isc_offset_t)cfg_obj_asuint64(sizeobj); dest.file.stream = NULL; dest.file.name = cfg_obj_asstring(pathobj); dest.file.versions = versions; dest.file.maximum_size = size; } else if (syslogobj != NULL) { int facility = LOG_DAEMON; type = ISC_LOG_TOSYSLOG; if (cfg_obj_isstring(syslogobj)) { const char *facilitystr = cfg_obj_asstring(syslogobj); (void)isc_syslog_facilityfromstring(facilitystr, &facility); } dest.facility = facility; } else if (stderrobj != NULL) { type = ISC_LOG_TOFILEDESC; dest.file.stream = stderr; dest.file.name = NULL; dest.file.versions = ISC_LOG_ROLLNEVER; dest.file.maximum_size = 0; } /* * Munge flags. */ { const cfg_obj_t *printcat = NULL; const cfg_obj_t *printsev = NULL; const cfg_obj_t *printtime = NULL; const cfg_obj_t *buffered = NULL; (void)cfg_map_get(channel, "print-category", &printcat); (void)cfg_map_get(channel, "print-severity", &printsev); (void)cfg_map_get(channel, "print-time", &printtime); (void)cfg_map_get(channel, "buffered", &buffered); if (printcat != NULL && cfg_obj_asboolean(printcat)) flags |= ISC_LOG_PRINTCATEGORY; if (printtime != NULL && cfg_obj_asboolean(printtime)) flags |= ISC_LOG_PRINTTIME; if (printsev != NULL && cfg_obj_asboolean(printsev)) flags |= ISC_LOG_PRINTLEVEL; if (buffered != NULL && cfg_obj_asboolean(buffered)) flags |= ISC_LOG_BUFFERED; } level = ISC_LOG_INFO; if (cfg_map_get(channel, "severity", &severity) == ISC_R_SUCCESS) { if (cfg_obj_isstring(severity)) { const char *str = cfg_obj_asstring(severity); if (strcasecmp(str, "critical") == 0) level = ISC_LOG_CRITICAL; else if (strcasecmp(str, "error") == 0) level = ISC_LOG_ERROR; else if (strcasecmp(str, "warning") == 0) level = ISC_LOG_WARNING; else if (strcasecmp(str, "notice") == 0) level = ISC_LOG_NOTICE; else if (strcasecmp(str, "info") == 0) level = ISC_LOG_INFO; else if (strcasecmp(str, "dynamic") == 0) level = ISC_LOG_DYNAMIC; } else /* debug */ level = cfg_obj_asuint32(severity); } if (logconfig == NULL) result = ISC_R_SUCCESS; else result = isc_log_createchannel(logconfig, channelname, type, level, &dest, flags); if (result == ISC_R_SUCCESS && type == ISC_LOG_TOFILE) { FILE *fp; /* * Test to make sure that file is a plain file. * Fix defect #22771 */ result = isc_file_isplainfile(dest.file.name); if (result == ISC_R_SUCCESS || result == ISC_R_FILENOTFOUND) { /* * Test that the file can be opened, since * isc_log_open() can't effectively report * failures when called in isc_log_doit(). */ result = isc_stdio_open(dest.file.name, "a", &fp); if (result != ISC_R_SUCCESS) { if (logconfig != NULL && !ns_g_nosyslog) syslog(LOG_ERR, "isc_stdio_open '%s' failed: " "%s", dest.file.name, isc_result_totext(result)); fprintf(stderr, "isc_stdio_open '%s' failed: %s\n", dest.file.name, isc_result_totext(result)); } else (void)isc_stdio_close(fp); goto done; } if (logconfig != NULL && !ns_g_nosyslog) syslog(LOG_ERR, "isc_file_isplainfile '%s' failed: %s", dest.file.name, isc_result_totext(result)); fprintf(stderr, "isc_file_isplainfile '%s' failed: %s\n", dest.file.name, isc_result_totext(result)); } done: return (result); }
/*% * Convenience function for configuring a single zone ACL. */ static isc_result_t configure_zone_acl(const cfg_obj_t *zconfig, const cfg_obj_t *vconfig, const cfg_obj_t *config, acl_type_t acltype, cfg_aclconfctx_t *actx, dns_zone_t *zone, void (*setzacl)(dns_zone_t *, dns_acl_t *), void (*clearzacl)(dns_zone_t *)) { isc_result_t result; const cfg_obj_t *maps[5] = {NULL, NULL, NULL, NULL, NULL}; const cfg_obj_t *aclobj = NULL; int i = 0; dns_acl_t **aclp = NULL, *acl = NULL; const char *aclname; dns_view_t *view; view = dns_zone_getview(zone); switch (acltype) { case allow_notify: if (view != NULL) aclp = &view->notifyacl; aclname = "allow-notify"; break; case allow_query: if (view != NULL) aclp = &view->queryacl; aclname = "allow-query"; break; case allow_transfer: if (view != NULL) aclp = &view->transferacl; aclname = "allow-transfer"; break; case allow_update: if (view != NULL) aclp = &view->updateacl; aclname = "allow-update"; break; case allow_update_forwarding: if (view != NULL) aclp = &view->upfwdacl; aclname = "allow-update-forwarding"; break; default: INSIST(0); return (ISC_R_FAILURE); } /* First check to see if ACL is defined within the zone */ if (zconfig != NULL) { maps[0] = cfg_tuple_get(zconfig, "options"); (void)ns_config_get(maps, aclname, &aclobj); if (aclobj != NULL) { aclp = NULL; goto parse_acl; } } /* Failing that, see if there's a default ACL already in the view */ if (aclp != NULL && *aclp != NULL) { (*setzacl)(zone, *aclp); return (ISC_R_SUCCESS); } /* Check for default ACLs that haven't been parsed yet */ if (vconfig != NULL) { const cfg_obj_t *options = cfg_tuple_get(vconfig, "options"); if (options != NULL) maps[i++] = options; } if (config != NULL) { const cfg_obj_t *options = NULL; (void)cfg_map_get(config, "options", &options); if (options != NULL) maps[i++] = options; } maps[i++] = ns_g_defaults; maps[i] = NULL; (void)ns_config_get(maps, aclname, &aclobj); if (aclobj == NULL) { (*clearzacl)(zone); return (ISC_R_SUCCESS); } parse_acl: result = cfg_acl_fromconfig(aclobj, config, ns_g_lctx, actx, dns_zone_getmctx(zone), 0, &acl); if (result != ISC_R_SUCCESS) return (result); (*setzacl)(zone, acl); /* Set the view default now */ if (aclp != NULL) dns_acl_attach(acl, aclp); dns_acl_detach(&acl); return (ISC_R_SUCCESS); }
static void register_keys(const cfg_obj_t *control, const cfg_obj_t *keylist, controlkeylist_t *keyids, isc_mem_t *mctx, const char *socktext) { controlkey_t *keyid, *next; const cfg_obj_t *keydef; char secret[1024]; isc_buffer_t b; isc_result_t result; /* * Find the keys corresponding to the keyids used by this listener. */ for (keyid = ISC_LIST_HEAD(*keyids); keyid != NULL; keyid = next) { next = ISC_LIST_NEXT(keyid, link); result = cfgkeylist_find(keylist, keyid->keyname, &keydef); if (result != ISC_R_SUCCESS) { cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING, "couldn't find key '%s' for use with " "command channel %s", keyid->keyname, socktext); ISC_LIST_UNLINK(*keyids, keyid, link); free_controlkey(keyid, mctx); } else { const cfg_obj_t *algobj = NULL; const cfg_obj_t *secretobj = NULL; const char *algstr = NULL; const char *secretstr = NULL; unsigned int algtype; (void)cfg_map_get(keydef, "algorithm", &algobj); (void)cfg_map_get(keydef, "secret", &secretobj); INSIST(algobj != NULL && secretobj != NULL); algstr = cfg_obj_asstring(algobj); secretstr = cfg_obj_asstring(secretobj); if (ns_config_getkeyalgorithm2(algstr, NULL, &algtype, NULL) != ISC_R_SUCCESS) { cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING, "unsupported algorithm '%s' in " "key '%s' for use with command " "channel %s", algstr, keyid->keyname, socktext); ISC_LIST_UNLINK(*keyids, keyid, link); free_controlkey(keyid, mctx); continue; } keyid->algorithm = algtype; isc_buffer_init(&b, secret, sizeof(secret)); result = isc_base64_decodestring(secretstr, &b); if (result != ISC_R_SUCCESS) { cfg_obj_log(keydef, ns_g_lctx, ISC_LOG_WARNING, "secret for key '%s' on " "command channel %s: %s", keyid->keyname, socktext, isc_result_totext(result)); ISC_LIST_UNLINK(*keyids, keyid, link); free_controlkey(keyid, mctx); continue; } keyid->secret.length = isc_buffer_usedlength(&b); keyid->secret.base = isc_mem_get(mctx, keyid->secret.length); if (keyid->secret.base == NULL) { cfg_obj_log(keydef, ns_g_lctx, ISC_LOG_WARNING, "couldn't register key '%s': " "out of memory", keyid->keyname); ISC_LIST_UNLINK(*keyids, keyid, link); free_controlkey(keyid, mctx); break; } memmove(keyid->secret.base, isc_buffer_base(&b), keyid->secret.length); } } }
isc_result_t ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig, const cfg_obj_t *zconfig, cfg_aclconfctx_t *ac, dns_zone_t *zone) { isc_result_t result; const char *zname; dns_rdataclass_t zclass; dns_rdataclass_t vclass; const cfg_obj_t *maps[5]; const cfg_obj_t *zoptions = NULL; const cfg_obj_t *options = NULL; const cfg_obj_t *obj; const char *filename = NULL; dns_notifytype_t notifytype = dns_notifytype_yes; isc_sockaddr_t *addrs; dns_name_t **keynames; isc_uint32_t count; char *cpval; unsigned int dbargc; char **dbargv; static char default_dbtype[] = "rbt"; isc_mem_t *mctx = dns_zone_getmctx(zone); dns_dialuptype_t dialup = dns_dialuptype_no; dns_zonetype_t ztype; int i; isc_int32_t journal_size; isc_boolean_t multi; isc_boolean_t alt; dns_view_t *view; isc_boolean_t check = ISC_FALSE, fail = ISC_FALSE; isc_boolean_t warn = ISC_FALSE, ignore = ISC_FALSE; isc_boolean_t ixfrdiff; dns_masterformat_t masterformat; isc_stats_t *zoneqrystats; isc_boolean_t zonestats_on; int seconds; i = 0; if (zconfig != NULL) { zoptions = cfg_tuple_get(zconfig, "options"); maps[i++] = zoptions; } if (vconfig != NULL) maps[i++] = cfg_tuple_get(vconfig, "options"); if (config != NULL) { (void)cfg_map_get(config, "options", &options); if (options != NULL) maps[i++] = options; } maps[i++] = ns_g_defaults; maps[i] = NULL; if (vconfig != NULL) RETERR(ns_config_getclass(cfg_tuple_get(vconfig, "class"), dns_rdataclass_in, &vclass)); else vclass = dns_rdataclass_in; /* * Configure values common to all zone types. */ zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name")); RETERR(ns_config_getclass(cfg_tuple_get(zconfig, "class"), vclass, &zclass)); dns_zone_setclass(zone, zclass); ztype = zonetype_fromconfig(zoptions); dns_zone_settype(zone, ztype); obj = NULL; result = cfg_map_get(zoptions, "database", &obj); if (result == ISC_R_SUCCESS) cpval = isc_mem_strdup(mctx, cfg_obj_asstring(obj)); else cpval = default_dbtype; if (cpval == NULL) return(ISC_R_NOMEMORY); result = strtoargv(mctx, cpval, &dbargc, &dbargv); if (result != ISC_R_SUCCESS && cpval != default_dbtype) { isc_mem_free(mctx, cpval); return (result); } /* * ANSI C is strange here. There is no logical reason why (char **) * cannot be promoted automatically to (const char * const *) by the * compiler w/o generating a warning. */ result = dns_zone_setdbtype(zone, dbargc, (const char * const *)dbargv); isc_mem_put(mctx, dbargv, dbargc * sizeof(*dbargv)); if (cpval != default_dbtype) isc_mem_free(mctx, cpval); if (result != ISC_R_SUCCESS) return (result); obj = NULL; result = cfg_map_get(zoptions, "file", &obj); if (result == ISC_R_SUCCESS) filename = cfg_obj_asstring(obj); /* * Unless we're using some alternative database, a master zone * will be needing a master file. */ if (ztype == dns_zone_master && cpval == default_dbtype && filename == NULL) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, "zone '%s': 'file' not specified", zname); return (ISC_R_FAILURE); } masterformat = dns_masterformat_text; obj = NULL; result= ns_config_get(maps, "masterfile-format", &obj); if (result == ISC_R_SUCCESS) { const char *masterformatstr = cfg_obj_asstring(obj); if (strcasecmp(masterformatstr, "text") == 0) masterformat = dns_masterformat_text; else if (strcasecmp(masterformatstr, "raw") == 0) masterformat = dns_masterformat_raw; else INSIST(0); } RETERR(dns_zone_setfile2(zone, filename, masterformat)); obj = NULL; result = cfg_map_get(zoptions, "journal", &obj); if (result == ISC_R_SUCCESS) RETERR(dns_zone_setjournal(zone, cfg_obj_asstring(obj))); if (ztype == dns_zone_slave) RETERR(configure_zone_acl(zconfig, vconfig, config, allow_notify, ac, zone, dns_zone_setnotifyacl, dns_zone_clearnotifyacl)); /* * XXXAG This probably does not make sense for stubs. */ RETERR(configure_zone_acl(zconfig, vconfig, config, allow_query, ac, zone, dns_zone_setqueryacl, dns_zone_clearqueryacl)); obj = NULL; result = ns_config_get(maps, "dialup", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); if (cfg_obj_isboolean(obj)) { if (cfg_obj_asboolean(obj)) dialup = dns_dialuptype_yes; else dialup = dns_dialuptype_no; } else { const char *dialupstr = cfg_obj_asstring(obj); if (strcasecmp(dialupstr, "notify") == 0) dialup = dns_dialuptype_notify; else if (strcasecmp(dialupstr, "notify-passive") == 0) dialup = dns_dialuptype_notifypassive; else if (strcasecmp(dialupstr, "refresh") == 0) dialup = dns_dialuptype_refresh; else if (strcasecmp(dialupstr, "passive") == 0) dialup = dns_dialuptype_passive; else INSIST(0); } dns_zone_setdialup(zone, dialup); obj = NULL; result = ns_config_get(maps, "zone-statistics", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); zonestats_on = cfg_obj_asboolean(obj); zoneqrystats = NULL; if (zonestats_on) { RETERR(isc_stats_create(mctx, &zoneqrystats, dns_nsstatscounter_max)); } dns_zone_setrequeststats(zone, zoneqrystats); if (zoneqrystats != NULL) isc_stats_detach(&zoneqrystats); /* * Configure master functionality. This applies * to primary masters (type "master") and slaves * acting as masters (type "slave"), but not to stubs. */ if (ztype != dns_zone_stub && ztype != dns_zone_staticstub) { obj = NULL; result = ns_config_get(maps, "notify", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); if (cfg_obj_isboolean(obj)) { if (cfg_obj_asboolean(obj)) notifytype = dns_notifytype_yes; else notifytype = dns_notifytype_no; } else { const char *notifystr = cfg_obj_asstring(obj); if (strcasecmp(notifystr, "explicit") == 0) notifytype = dns_notifytype_explicit; else if (strcasecmp(notifystr, "master-only") == 0) notifytype = dns_notifytype_masteronly; else INSIST(0); } dns_zone_setnotifytype(zone, notifytype); obj = NULL; result = ns_config_get(maps, "also-notify", &obj); if (result == ISC_R_SUCCESS) { isc_sockaddr_t *addrs = NULL; isc_uint32_t addrcount; result = ns_config_getiplist(config, obj, 0, mctx, &addrs, &addrcount); if (result != ISC_R_SUCCESS) return (result); result = dns_zone_setalsonotify(zone, addrs, addrcount); ns_config_putiplist(mctx, &addrs, addrcount); if (result != ISC_R_SUCCESS) return (result); } else RETERR(dns_zone_setalsonotify(zone, NULL, 0)); obj = NULL; result = ns_config_get(maps, "notify-source", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); RETERR(dns_zone_setnotifysrc4(zone, cfg_obj_assockaddr(obj))); ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj)); obj = NULL; result = ns_config_get(maps, "notify-source-v6", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); RETERR(dns_zone_setnotifysrc6(zone, cfg_obj_assockaddr(obj))); ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj)); obj = NULL; result = ns_config_get(maps, "notify-to-soa", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); dns_zone_setoption(zone, DNS_ZONEOPT_NOTIFYTOSOA, cfg_obj_asboolean(obj)); dns_zone_setisself(zone, ns_client_isself, NULL); RETERR(configure_zone_acl(zconfig, vconfig, config, allow_transfer, ac, zone, dns_zone_setxfracl, dns_zone_clearxfracl)); obj = NULL; result = ns_config_get(maps, "max-transfer-time-out", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); dns_zone_setmaxxfrout(zone, cfg_obj_asuint32(obj) * 60); obj = NULL; result = ns_config_get(maps, "max-transfer-idle-out", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); dns_zone_setidleout(zone, cfg_obj_asuint32(obj) * 60); obj = NULL; result = ns_config_get(maps, "max-journal-size", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); dns_zone_setjournalsize(zone, -1); if (cfg_obj_isstring(obj)) { const char *str = cfg_obj_asstring(obj); INSIST(strcasecmp(str, "unlimited") == 0); journal_size = ISC_UINT32_MAX / 2; } else { isc_resourcevalue_t value; value = cfg_obj_asuint64(obj); if (value > ISC_UINT32_MAX / 2) { cfg_obj_log(obj, ns_g_lctx, ISC_LOG_ERROR, "'max-journal-size " "%" ISC_PRINT_QUADFORMAT "d' " "is too large", value); RETERR(ISC_R_RANGE); } journal_size = (isc_uint32_t)value; } dns_zone_setjournalsize(zone, journal_size); obj = NULL; result = ns_config_get(maps, "ixfr-from-differences", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); if (cfg_obj_isboolean(obj)) ixfrdiff = cfg_obj_asboolean(obj); else if (!strcasecmp(cfg_obj_asstring(obj), "master") && ztype == dns_zone_master) ixfrdiff = ISC_TRUE; else if (!strcasecmp(cfg_obj_asstring(obj), "slave") && ztype == dns_zone_slave) ixfrdiff = ISC_TRUE; else ixfrdiff = ISC_FALSE; dns_zone_setoption(zone, DNS_ZONEOPT_IXFRFROMDIFFS, ixfrdiff); checknames(ztype, maps, &obj); INSIST(obj != NULL); if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { fail = ISC_FALSE; check = ISC_TRUE; } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { fail = check = ISC_TRUE; } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { fail = check = ISC_FALSE; } else INSIST(0); dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMES, check); dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMESFAIL, fail); obj = NULL; result = ns_config_get(maps, "notify-delay", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); dns_zone_setnotifydelay(zone, cfg_obj_asuint32(obj)); obj = NULL; result = ns_config_get(maps, "check-sibling", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); dns_zone_setoption(zone, DNS_ZONEOPT_CHECKSIBLING, cfg_obj_asboolean(obj)); obj = NULL; result = ns_config_get(maps, "zero-no-soa-ttl", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); dns_zone_setzeronosoattl(zone, cfg_obj_asboolean(obj)); obj = NULL; result = ns_config_get(maps, "nsec3-test-zone", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); dns_zone_setoption(zone, DNS_ZONEOPT_NSEC3TESTZONE, cfg_obj_asboolean(obj)); } /* * Configure update-related options. These apply to * primary masters only. */ if (ztype == dns_zone_master) { dns_acl_t *updateacl; RETERR(configure_zone_acl(zconfig, vconfig, config, allow_update, ac, zone, dns_zone_setupdateacl, dns_zone_clearupdateacl)); updateacl = dns_zone_getupdateacl(zone); if (updateacl != NULL && dns_acl_isinsecure(updateacl)) isc_log_write(ns_g_lctx, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_SERVER, ISC_LOG_WARNING, "zone '%s' allows updates by IP " "address, which is insecure", zname); RETERR(configure_zone_ssutable(zoptions, zone, zname)); obj = NULL; result = ns_config_get(maps, "sig-validity-interval", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); { const cfg_obj_t *validity, *resign; validity = cfg_tuple_get(obj, "validity"); seconds = cfg_obj_asuint32(validity) * 86400; dns_zone_setsigvalidityinterval(zone, seconds); resign = cfg_tuple_get(obj, "re-sign"); if (cfg_obj_isvoid(resign)) { seconds /= 4; } else { if (seconds > 7 * 86400) seconds = cfg_obj_asuint32(resign) * 86400; else seconds = cfg_obj_asuint32(resign) * 3600; } dns_zone_setsigresigninginterval(zone, seconds); } obj = NULL; result = ns_config_get(maps, "key-directory", &obj); if (result == ISC_R_SUCCESS) { filename = cfg_obj_asstring(obj); RETERR(dns_zone_setkeydirectory(zone, filename)); } obj = NULL; result = ns_config_get(maps, "sig-signing-signatures", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); dns_zone_setsignatures(zone, cfg_obj_asuint32(obj)); obj = NULL; result = ns_config_get(maps, "sig-signing-nodes", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); dns_zone_setnodes(zone, cfg_obj_asuint32(obj)); obj = NULL; result = ns_config_get(maps, "sig-signing-type", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); dns_zone_setprivatetype(zone, cfg_obj_asuint32(obj)); obj = NULL; result = ns_config_get(maps, "update-check-ksk", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); dns_zone_setoption(zone, DNS_ZONEOPT_UPDATECHECKKSK, cfg_obj_asboolean(obj)); obj = NULL; result = ns_config_get(maps, "dnssec-dnskey-kskonly", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); dns_zone_setoption(zone, DNS_ZONEOPT_DNSKEYKSKONLY, cfg_obj_asboolean(obj)); } else if (ztype == dns_zone_slave) { RETERR(configure_zone_acl(zconfig, vconfig, config, allow_update_forwarding, ac, zone, dns_zone_setforwardacl, dns_zone_clearforwardacl)); } /*% * Primary master functionality. */ if (ztype == dns_zone_master) { isc_boolean_t allow = ISC_FALSE, maint = ISC_FALSE; obj = NULL; result = ns_config_get(maps, "check-wildcard", &obj); if (result == ISC_R_SUCCESS) check = cfg_obj_asboolean(obj); else check = ISC_FALSE; dns_zone_setoption(zone, DNS_ZONEOPT_CHECKWILDCARD, check); obj = NULL; result = ns_config_get(maps, "check-dup-records", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { fail = ISC_FALSE; check = ISC_TRUE; } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { fail = check = ISC_TRUE; } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { fail = check = ISC_FALSE; } else INSIST(0); dns_zone_setoption(zone, DNS_ZONEOPT_CHECKDUPRR, check); dns_zone_setoption(zone, DNS_ZONEOPT_CHECKDUPRRFAIL, fail); obj = NULL; result = ns_config_get(maps, "check-mx", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { fail = ISC_FALSE; check = ISC_TRUE; } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { fail = check = ISC_TRUE; } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { fail = check = ISC_FALSE; } else INSIST(0); dns_zone_setoption(zone, DNS_ZONEOPT_CHECKMX, check); dns_zone_setoption(zone, DNS_ZONEOPT_CHECKMXFAIL, fail); obj = NULL; result = ns_config_get(maps, "check-integrity", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); dns_zone_setoption(zone, DNS_ZONEOPT_CHECKINTEGRITY, cfg_obj_asboolean(obj)); obj = NULL; result = ns_config_get(maps, "check-mx-cname", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { warn = ISC_TRUE; ignore = ISC_FALSE; } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { warn = ignore = ISC_FALSE; } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { warn = ignore = ISC_TRUE; } else INSIST(0); dns_zone_setoption(zone, DNS_ZONEOPT_WARNMXCNAME, warn); dns_zone_setoption(zone, DNS_ZONEOPT_IGNOREMXCNAME, ignore); obj = NULL; result = ns_config_get(maps, "check-srv-cname", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) { warn = ISC_TRUE; ignore = ISC_FALSE; } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) { warn = ignore = ISC_FALSE; } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) { warn = ignore = ISC_TRUE; } else INSIST(0); dns_zone_setoption(zone, DNS_ZONEOPT_WARNSRVCNAME, warn); dns_zone_setoption(zone, DNS_ZONEOPT_IGNORESRVCNAME, ignore); obj = NULL; result = ns_config_get(maps, "dnssec-secure-to-insecure", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); dns_zone_setoption(zone, DNS_ZONEOPT_SECURETOINSECURE, cfg_obj_asboolean(obj)); obj = NULL; result = cfg_map_get(zoptions, "auto-dnssec", &obj); if (result == ISC_R_SUCCESS) { const char *arg = cfg_obj_asstring(obj); if (strcasecmp(arg, "allow") == 0) allow = ISC_TRUE; else if (strcasecmp(arg, "maintain") == 0) allow = maint = ISC_TRUE; else if (strcasecmp(arg, "off") == 0) ; else INSIST(0); dns_zone_setkeyopt(zone, DNS_ZONEKEY_ALLOW, allow); dns_zone_setkeyopt(zone, DNS_ZONEKEY_MAINTAIN, maint); } } /* * Configure slave functionality. */ switch (ztype) { case dns_zone_slave: case dns_zone_stub: count = 0; obj = NULL; (void)cfg_map_get(zoptions, "masters", &obj); if (obj != NULL) { addrs = NULL; keynames = NULL; RETERR(ns_config_getipandkeylist(config, obj, mctx, &addrs, &keynames, &count)); result = dns_zone_setmasterswithkeys(zone, addrs, keynames, count); ns_config_putipandkeylist(mctx, &addrs, &keynames, count); } else result = dns_zone_setmasters(zone, NULL, 0); RETERR(result); multi = ISC_FALSE; if (count > 1) { obj = NULL; result = ns_config_get(maps, "multi-master", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); multi = cfg_obj_asboolean(obj); } dns_zone_setoption(zone, DNS_ZONEOPT_MULTIMASTER, multi); obj = NULL; result = ns_config_get(maps, "max-transfer-time-in", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); dns_zone_setmaxxfrin(zone, cfg_obj_asuint32(obj) * 60); obj = NULL; result = ns_config_get(maps, "max-transfer-idle-in", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); dns_zone_setidlein(zone, cfg_obj_asuint32(obj) * 60); obj = NULL; result = ns_config_get(maps, "max-refresh-time", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); dns_zone_setmaxrefreshtime(zone, cfg_obj_asuint32(obj)); obj = NULL; result = ns_config_get(maps, "min-refresh-time", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); dns_zone_setminrefreshtime(zone, cfg_obj_asuint32(obj)); obj = NULL; result = ns_config_get(maps, "max-retry-time", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); dns_zone_setmaxretrytime(zone, cfg_obj_asuint32(obj)); obj = NULL; result = ns_config_get(maps, "min-retry-time", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); dns_zone_setminretrytime(zone, cfg_obj_asuint32(obj)); obj = NULL; result = ns_config_get(maps, "transfer-source", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); RETERR(dns_zone_setxfrsource4(zone, cfg_obj_assockaddr(obj))); ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj)); obj = NULL; result = ns_config_get(maps, "transfer-source-v6", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); RETERR(dns_zone_setxfrsource6(zone, cfg_obj_assockaddr(obj))); ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj)); obj = NULL; result = ns_config_get(maps, "alt-transfer-source", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); RETERR(dns_zone_setaltxfrsource4(zone, cfg_obj_assockaddr(obj))); obj = NULL; result = ns_config_get(maps, "alt-transfer-source-v6", &obj); INSIST(result == ISC_R_SUCCESS && obj != NULL); RETERR(dns_zone_setaltxfrsource6(zone, cfg_obj_assockaddr(obj))); obj = NULL; (void)ns_config_get(maps, "use-alt-transfer-source", &obj); if (obj == NULL) { /* * Default off when views are in use otherwise * on for BIND 8 compatibility. */ view = dns_zone_getview(zone); if (view != NULL && strcmp(view->name, "_default") == 0) alt = ISC_TRUE; else alt = ISC_FALSE; } else alt = cfg_obj_asboolean(obj); dns_zone_setoption(zone, DNS_ZONEOPT_USEALTXFRSRC, alt); obj = NULL; (void)ns_config_get(maps, "try-tcp-refresh", &obj); dns_zone_setoption(zone, DNS_ZONEOPT_TRYTCPREFRESH, cfg_obj_asboolean(obj)); break; case dns_zone_staticstub: RETERR(configure_staticstub(zoptions, zone, zname, default_dbtype)); break; default: break; } return (ISC_R_SUCCESS); }
static void parse_config(isc_mem_t *mctx, isc_log_t *log, const char *keyname, cfg_parser_t **pctxp, cfg_obj_t **configp) { isc_result_t result; const char *conffile = admin_conffile; const cfg_obj_t *addresses = NULL; const cfg_obj_t *defkey = NULL; const cfg_obj_t *options = NULL; const cfg_obj_t *servers = NULL; const cfg_obj_t *server = NULL; const cfg_obj_t *keys = NULL; const cfg_obj_t *key = NULL; const cfg_obj_t *defport = NULL; const cfg_obj_t *secretobj = NULL; const cfg_obj_t *algorithmobj = NULL; cfg_obj_t *config = NULL; const cfg_obj_t *address = NULL; const cfg_listelt_t *elt; const char *secretstr; const char *algorithm; static char secretarray[1024]; const cfg_type_t *conftype = &cfg_type_rndcconf; isc_boolean_t key_only = ISC_FALSE; const cfg_listelt_t *element; if (! isc_file_exists(conffile)) { conffile = admin_keyfile; conftype = &cfg_type_rndckey; if (! isc_file_exists(conffile)) fatal("neither %s nor %s was found", admin_conffile, admin_keyfile); key_only = ISC_TRUE; } DO("create parser", cfg_parser_create(mctx, log, pctxp)); /* * The parser will output its own errors, so DO() is not used. */ result = cfg_parse_file(*pctxp, conffile, conftype, &config); if (result != ISC_R_SUCCESS) fatal("could not load rndc configuration"); if (!key_only) (void)cfg_map_get(config, "options", &options); if (key_only && servername == NULL) servername = "127.0.0.1"; else if (servername == NULL && options != NULL) { const cfg_obj_t *defserverobj = NULL; (void)cfg_map_get(options, "default-server", &defserverobj); if (defserverobj != NULL) servername = cfg_obj_asstring(defserverobj); } if (servername == NULL) fatal("no server specified and no default"); if (!key_only) { (void)cfg_map_get(config, "server", &servers); if (servers != NULL) { for (elt = cfg_list_first(servers); elt != NULL; elt = cfg_list_next(elt)) { const char *name; server = cfg_listelt_value(elt); name = cfg_obj_asstring(cfg_map_getname(server)); if (strcasecmp(name, servername) == 0) break; server = NULL; } } } /* * Look for the name of the key to use. */ if (keyname != NULL) ; /* Was set on command line, do nothing. */ else if (server != NULL) { DO("get key for server", cfg_map_get(server, "key", &defkey)); keyname = cfg_obj_asstring(defkey); } else if (options != NULL) { DO("get default key", cfg_map_get(options, "default-key", &defkey)); keyname = cfg_obj_asstring(defkey); } else if (!key_only) fatal("no key for server and no default"); /* * Get the key's definition. */ if (key_only) DO("get key", cfg_map_get(config, "key", &key)); else { DO("get config key list", cfg_map_get(config, "key", &keys)); for (elt = cfg_list_first(keys); elt != NULL; elt = cfg_list_next(elt)) { key = cfg_listelt_value(elt); if (strcasecmp(cfg_obj_asstring(cfg_map_getname(key)), keyname) == 0) break; } if (elt == NULL) fatal("no key definition for name %s", keyname); } (void)cfg_map_get(key, "secret", &secretobj); (void)cfg_map_get(key, "algorithm", &algorithmobj); if (secretobj == NULL || algorithmobj == NULL) fatal("key must have algorithm and secret"); secretstr = cfg_obj_asstring(secretobj); algorithm = cfg_obj_asstring(algorithmobj); if (strcasecmp(algorithm, "hmac-md5") != 0) fatal("unsupported algorithm: %s", algorithm); secret.rstart = (unsigned char *)secretarray; secret.rend = (unsigned char *)secretarray + sizeof(secretarray); DO("decode base64 secret", isccc_base64_decode(secretstr, &secret)); secret.rend = secret.rstart; secret.rstart = (unsigned char *)secretarray; /* * Find the port to connect to. */ if (remoteport != 0) ; /* Was set on command line, do nothing. */ else { if (server != NULL) (void)cfg_map_get(server, "port", &defport); if (defport == NULL && options != NULL) (void)cfg_map_get(options, "default-port", &defport); } if (defport != NULL) { remoteport = cfg_obj_asuint32(defport); if (remoteport > 65535 || remoteport == 0) fatal("port %u out of range", remoteport); } else if (remoteport == 0) remoteport = NS_CONTROL_PORT; if (server != NULL) result = cfg_map_get(server, "addresses", &addresses); else result = ISC_R_NOTFOUND; if (result == ISC_R_SUCCESS) { for (element = cfg_list_first(addresses); element != NULL; element = cfg_list_next(element)) { isc_sockaddr_t sa; address = cfg_listelt_value(element); if (!cfg_obj_issockaddr(address)) { unsigned int myport; const char *name; const cfg_obj_t *obj; obj = cfg_tuple_get(address, "name"); name = cfg_obj_asstring(obj); obj = cfg_tuple_get(address, "port"); if (cfg_obj_isuint32(obj)) { myport = cfg_obj_asuint32(obj); if (myport > ISC_UINT16_MAX || myport == 0) fatal("port %u out of range", myport); } else myport = remoteport; if (nserveraddrs < SERVERADDRS) get_addresses(name, (in_port_t) myport); else fprintf(stderr, "too many address: " "%s: dropped\n", name); continue; } sa = *cfg_obj_assockaddr(address); if (isc_sockaddr_getport(&sa) == 0) isc_sockaddr_setport(&sa, remoteport); if (nserveraddrs < SERVERADDRS) serveraddrs[nserveraddrs++] = sa; else { char socktext[ISC_SOCKADDR_FORMATSIZE]; isc_sockaddr_format(&sa, socktext, sizeof(socktext)); fprintf(stderr, "too many address: %s: dropped\n", socktext); } } } if (!local4set && server != NULL) { address = NULL; cfg_map_get(server, "source-address", &address); if (address != NULL) { local4 = *cfg_obj_assockaddr(address); local4set = ISC_TRUE; } } if (!local4set && options != NULL) { address = NULL; cfg_map_get(options, "default-source-address", &address); if (address != NULL) { local4 = *cfg_obj_assockaddr(address); local4set = ISC_TRUE; } } if (!local6set && server != NULL) { address = NULL; cfg_map_get(server, "source-address-v6", &address); if (address != NULL) { local6 = *cfg_obj_assockaddr(address); local6set = ISC_TRUE; } } if (!local6set && options != NULL) { address = NULL; cfg_map_get(options, "default-source-address-v6", &address); if (address != NULL) { local6 = *cfg_obj_assockaddr(address); local6set = ISC_TRUE; } } *configp = config; }
static void parse_config(isc_mem_t *mctx, isc_log_t *log, const char *keyname, cfg_parser_t **pctxp, cfg_obj_t **configp) { isc_result_t result; const char *conffile = admin_conffile; cfg_obj_t *defkey = NULL; cfg_obj_t *options = NULL; cfg_obj_t *servers = NULL; cfg_obj_t *server = NULL; cfg_obj_t *keys = NULL; cfg_obj_t *key = NULL; cfg_obj_t *defport = NULL; cfg_obj_t *secretobj = NULL; cfg_obj_t *algorithmobj = NULL; cfg_obj_t *config = NULL; cfg_listelt_t *elt; const char *secretstr; const char *algorithm; static char secretarray[1024]; const cfg_type_t *conftype = &cfg_type_rndcconf; isc_boolean_t key_only = ISC_FALSE; if (! isc_file_exists(conffile)) { conffile = admin_keyfile; conftype = &cfg_type_rndckey; if (! isc_file_exists(conffile)) fatal("neither %s nor %s was found", admin_conffile, admin_keyfile); key_only = ISC_TRUE; } DO("create parser", cfg_parser_create(mctx, log, pctxp)); /* * The parser will output its own errors, so DO() is not used. */ result = cfg_parse_file(*pctxp, conffile, conftype, &config); if (result != ISC_R_SUCCESS) fatal("could not load rndc configuration"); if (!key_only) (void)cfg_map_get(config, "options", &options); if (key_only && servername == NULL) servername = "127.0.0.1"; else if (servername == NULL && options != NULL) { cfg_obj_t *defserverobj = NULL; (void)cfg_map_get(options, "default-server", &defserverobj); if (defserverobj != NULL) servername = cfg_obj_asstring(defserverobj); } if (servername == NULL) fatal("no server specified and no default"); if (!key_only) { (void)cfg_map_get(config, "server", &servers); if (servers != NULL) { for (elt = cfg_list_first(servers); elt != NULL; elt = cfg_list_next(elt)) { const char *name; server = cfg_listelt_value(elt); name = cfg_obj_asstring(cfg_map_getname(server)); if (strcasecmp(name, servername) == 0) break; server = NULL; } } } /* * Look for the name of the key to use. */ if (keyname != NULL) ; /* Was set on command line, do nothing. */ else if (server != NULL) { DO("get key for server", cfg_map_get(server, "key", &defkey)); keyname = cfg_obj_asstring(defkey); } else if (options != NULL) { DO("get default key", cfg_map_get(options, "default-key", &defkey)); keyname = cfg_obj_asstring(defkey); } else if (!key_only) fatal("no key for server and no default"); /* * Get the key's definition. */ if (key_only) DO("get key", cfg_map_get(config, "key", &key)); else { DO("get config key list", cfg_map_get(config, "key", &keys)); for (elt = cfg_list_first(keys); elt != NULL; elt = cfg_list_next(elt)) { key = cfg_listelt_value(elt); if (strcasecmp(cfg_obj_asstring(cfg_map_getname(key)), keyname) == 0) break; } if (elt == NULL) fatal("no key definition for name %s", keyname); } (void)cfg_map_get(key, "secret", &secretobj); (void)cfg_map_get(key, "algorithm", &algorithmobj); if (secretobj == NULL || algorithmobj == NULL) fatal("key must have algorithm and secret"); secretstr = cfg_obj_asstring(secretobj); algorithm = cfg_obj_asstring(algorithmobj); if (strcasecmp(algorithm, "hmac-md5") != 0) fatal("unsupported algorithm: %s", algorithm); secret.rstart = (unsigned char *)secretarray; secret.rend = (unsigned char *)secretarray + sizeof(secretarray); DO("decode base64 secret", isccc_base64_decode(secretstr, &secret)); secret.rend = secret.rstart; secret.rstart = (unsigned char *)secretarray; /* * Find the port to connect to. */ if (remoteport != 0) ; /* Was set on command line, do nothing. */ else { if (server != NULL) (void)cfg_map_get(server, "port", &defport); if (defport == NULL && options != NULL) (void)cfg_map_get(options, "default-port", &defport); } if (defport != NULL) { remoteport = cfg_obj_asuint32(defport); if (remoteport > 65535 || remoteport == 0) fatal("port %d out of range", remoteport); } else if (remoteport == 0) remoteport = NS_CONTROL_PORT; *configp = config; }
isc_result_t ns_lwresd_configure(isc_mem_t *mctx, const cfg_obj_t *config) { const cfg_obj_t *lwreslist = NULL; const cfg_obj_t *lwres = NULL; const cfg_obj_t *listenerslist = NULL; const cfg_listelt_t *element = NULL; ns_lwreslistener_t *listener; ns_lwreslistenerlist_t newlisteners; isc_result_t result; char socktext[ISC_SOCKADDR_FORMATSIZE]; isc_sockaddr_t *addrs = NULL; ns_lwresd_t *lwresd = NULL; isc_uint32_t count = 0; REQUIRE(mctx != NULL); REQUIRE(config != NULL); RUNTIME_CHECK(isc_once_do(&once, initialize_mutex) == ISC_R_SUCCESS); ISC_LIST_INIT(newlisteners); result = cfg_map_get(config, "lwres", &lwreslist); if (result != ISC_R_SUCCESS) return (ISC_R_SUCCESS); LOCK(&listeners_lock); /* * Run through the new lwres address list, noting sockets that * are already being listened on and moving them to the new list. * * Identifying duplicates addr/port combinations is left to either * the underlying config code, or to the bind attempt getting an * address-in-use error. */ for (element = cfg_list_first(lwreslist); element != NULL; element = cfg_list_next(element)) { in_port_t port; lwres = cfg_listelt_value(element); CHECK(ns_lwdmanager_create(mctx, lwres, &lwresd)); port = lwresd_g_listenport; if (port == 0) port = LWRES_UDP_PORT; listenerslist = NULL; (void)cfg_map_get(lwres, "listen-on", &listenerslist); if (listenerslist == NULL) { struct in_addr localhost; isc_sockaddr_t address; localhost.s_addr = htonl(INADDR_LOOPBACK); isc_sockaddr_fromin(&address, &localhost, port); CHECK(configure_listener(&address, lwresd, mctx, &newlisteners)); } else { isc_uint32_t i; CHECK(ns_config_getiplist(config, listenerslist, port, mctx, &addrs, &count)); for (i = 0; i < count; i++) CHECK(configure_listener(&addrs[i], lwresd, mctx, &newlisteners)); ns_config_putiplist(mctx, &addrs, count); } ns_lwdmanager_detach(&lwresd); } /* * Shutdown everything on the listeners list, and remove them from * the list. Then put all of the new listeners on it. */ while (!ISC_LIST_EMPTY(listeners)) { listener = ISC_LIST_HEAD(listeners); ISC_LIST_UNLINK(listeners, listener, link); isc_sockaddr_format(&listener->address, socktext, sizeof(socktext)); listener_shutdown(listener); ns_lwreslistener_detach(&listener); isc_log_write(ns_g_lctx, ISC_LOGCATEGORY_GENERAL, NS_LOGMODULE_LWRESD, ISC_LOG_NOTICE, "lwres no longer listening on %s", socktext); } cleanup: ISC_LIST_APPENDLIST(listeners, newlisteners, link); if (addrs != NULL) ns_config_putiplist(mctx, &addrs, count); if (lwresd != NULL) ns_lwdmanager_detach(&lwresd); UNLOCK(&listeners_lock); return (result); }
static isc_result_t setup_dnsseckeys(dns_client_t *client) { isc_result_t result; cfg_parser_t *parser = NULL; const cfg_obj_t *keys = NULL; const cfg_obj_t *managed_keys = NULL; cfg_obj_t *bindkeys = NULL; const char *filename = anchorfile; if (!root_validation && !dlv_validation) return (ISC_R_SUCCESS); if (filename == NULL) { #ifndef WIN32 filename = NS_SYSCONFDIR "/bind.keys"; #else static char buf[MAX_PATH]; strlcpy(buf, isc_ntpaths_get(SYS_CONF_DIR), sizeof(buf)); strlcat(buf, "\\bind.keys", sizeof(buf)); filename = buf; #endif } if (trust_anchor == NULL) { trust_anchor = isc_mem_strdup(mctx, "."); if (trust_anchor == NULL) fatal("out of memory"); } if (trust_anchor != NULL) CHECK(convert_name(&afn, &anchor_name, trust_anchor)); if (dlv_anchor != NULL) CHECK(convert_name(&dfn, &dlv_name, dlv_anchor)); CHECK(cfg_parser_create(mctx, dns_lctx, &parser)); if (access(filename, R_OK) != 0) { if (anchorfile != NULL) fatal("Unable to read key file '%s'", anchorfile); } else { result = cfg_parse_file(parser, filename, &cfg_type_bindkeys, &bindkeys); if (result != ISC_R_SUCCESS) if (anchorfile != NULL) fatal("Unable to load keys from '%s'", anchorfile); } if (bindkeys == NULL) { isc_buffer_t b; isc_buffer_init(&b, anchortext, sizeof(anchortext) - 1); isc_buffer_add(&b, sizeof(anchortext) - 1); result = cfg_parse_buffer(parser, &b, &cfg_type_bindkeys, &bindkeys); if (result != ISC_R_SUCCESS) fatal("Unable to parse built-in keys"); } INSIST(bindkeys != NULL); cfg_map_get(bindkeys, "trusted-keys", &keys); cfg_map_get(bindkeys, "managed-keys", &managed_keys); if (keys != NULL) CHECK(load_keys(keys, client)); if (managed_keys != NULL) CHECK(load_keys(managed_keys, client)); result = ISC_R_SUCCESS; if (trusted_keys == 0) fatal("No trusted keys were loaded"); if (dlv_validation) dns_client_setdlv(client, dns_rdataclass_in, dlv_anchor); cleanup: if (result != ISC_R_SUCCESS) delv_log(ISC_LOG_ERROR, "setup_dnsseckeys: %s", isc_result_totext(result)); return (result); }