isc_result_t ns_config_getport(const cfg_obj_t *config, in_port_t *portp) { const cfg_obj_t *maps[3]; const cfg_obj_t *options = NULL; const cfg_obj_t *portobj = NULL; isc_result_t result; int i; (void)cfg_map_get(config, "options", &options); i = 0; if (options != NULL) maps[i++] = options; maps[i++] = ns_g_defaults; maps[i] = NULL; result = ns_config_get(maps, "port", &portobj); INSIST(result == ISC_R_SUCCESS); if (cfg_obj_asuint32(portobj) >= ISC_UINT16_MAX) { cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR, "port '%u' out of range", cfg_obj_asuint32(portobj)); return (ISC_R_RANGE); } *portp = (in_port_t)cfg_obj_asuint32(portobj); return (ISC_R_SUCCESS); }
isc_result_t ns_config_getdscp(const cfg_obj_t *config, isc_dscp_t *dscpp) { const cfg_obj_t *options = NULL; const cfg_obj_t *dscpobj = NULL; isc_result_t result; (void)cfg_map_get(config, "options", &options); if (options == NULL) return (ISC_R_SUCCESS); result = cfg_map_get(options, "dscp", &dscpobj); if (result != ISC_R_SUCCESS || dscpobj == NULL) { *dscpp = -1; return (ISC_R_SUCCESS); } if (cfg_obj_asuint32(dscpobj) >= 64) { cfg_obj_log(dscpobj, ns_g_lctx, ISC_LOG_ERROR, "dscp '%u' out of range", cfg_obj_asuint32(dscpobj)); return (ISC_R_RANGE); } *dscpp = (isc_dscp_t)cfg_obj_asuint32(dscpobj); return (ISC_R_SUCCESS); }
/* * 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 void update_listener(ns_controls_t *cp, controllistener_t **listenerp, const cfg_obj_t *control, const cfg_obj_t *config, isc_sockaddr_t *addr, cfg_aclconfctx_t *aclconfctx, const char *socktext, isc_sockettype_t type) { controllistener_t *listener; const cfg_obj_t *allow; const cfg_obj_t *global_keylist = NULL; const cfg_obj_t *control_keylist = NULL; dns_acl_t *new_acl = NULL; controlkeylist_t keys; isc_result_t result = ISC_R_SUCCESS; for (listener = ISC_LIST_HEAD(cp->listeners); listener != NULL; listener = ISC_LIST_NEXT(listener, link)) if (isc_sockaddr_equal(addr, &listener->address)) break; if (listener == NULL) { *listenerp = NULL; return; } /* * There is already a listener for this sockaddr. * Update the access list and key information. * * First try to deal with the key situation. There are a few * possibilities: * (a) It had an explicit keylist and still has an explicit keylist. * (b) It had an automagic key and now has an explicit keylist. * (c) It had an explicit keylist and now needs an automagic key. * (d) It has an automagic key and still needs the automagic key. * * (c) and (d) are the annoying ones. The caller needs to know * that it should use the automagic configuration for key information * in place of the named.conf configuration. * * XXXDCL There is one other hazard that has not been dealt with, * the problem that if a key change is being caused by a control * channel reload, then the response will be with the new key * and not able to be decrypted by the client. */ if (control != NULL) get_key_info(config, control, &global_keylist, &control_keylist); if (control_keylist != NULL) { INSIST(global_keylist != NULL); ISC_LIST_INIT(keys); result = controlkeylist_fromcfg(control_keylist, listener->mctx, &keys); if (result == ISC_R_SUCCESS) { free_controlkeylist(&listener->keys, listener->mctx); listener->keys = keys; register_keys(control, global_keylist, &listener->keys, listener->mctx, socktext); } } else { free_controlkeylist(&listener->keys, listener->mctx); result = get_rndckey(listener->mctx, &listener->keys); } if (result != ISC_R_SUCCESS && global_keylist != NULL) { /* * This message might be a little misleading since the * "new keys" might in fact be identical to the old ones, * but tracking whether they are identical just for the * sake of avoiding this message would be too much trouble. */ if (control != NULL) cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING, "couldn't install new keys for " "command channel %s: %s", socktext, isc_result_totext(result)); else isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_CONTROL, ISC_LOG_WARNING, "couldn't install new keys for " "command channel %s: %s", socktext, isc_result_totext(result)); } /* * Now, keep the old access list unless a new one can be made. */ if (control != NULL && type == isc_sockettype_tcp) { allow = cfg_tuple_get(control, "allow"); result = cfg_acl_fromconfig(allow, config, ns_g_lctx, aclconfctx, listener->mctx, 0, &new_acl); } else { result = dns_acl_any(listener->mctx, &new_acl); } if (result == ISC_R_SUCCESS) { dns_acl_detach(&listener->acl); dns_acl_attach(new_acl, &listener->acl); dns_acl_detach(&new_acl); /* XXXDCL say the old acl is still used? */ } else if (control != NULL) cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING, "couldn't install new acl for " "command channel %s: %s", socktext, isc_result_totext(result)); else isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_CONTROL, ISC_LOG_WARNING, "couldn't install new acl for " "command channel %s: %s", socktext, isc_result_totext(result)); if (result == ISC_R_SUCCESS && type == isc_sockettype_unix) { isc_uint32_t perm, owner, group; perm = cfg_obj_asuint32(cfg_tuple_get(control, "perm")); owner = cfg_obj_asuint32(cfg_tuple_get(control, "owner")); group = cfg_obj_asuint32(cfg_tuple_get(control, "group")); result = ISC_R_SUCCESS; if (listener->perm != perm || listener->owner != owner || listener->group != group) result = isc_socket_permunix(&listener->address, perm, owner, group); if (result == ISC_R_SUCCESS) { listener->perm = perm; listener->owner = owner; listener->group = group; } else if (control != NULL) cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING, "couldn't update ownership/permission for " "command channel %s", socktext); } *listenerp = listener; }
static void add_listener(ns_controls_t *cp, controllistener_t **listenerp, const cfg_obj_t *control, const cfg_obj_t *config, isc_sockaddr_t *addr, cfg_aclconfctx_t *aclconfctx, const char *socktext, isc_sockettype_t type) { isc_mem_t *mctx = cp->server->mctx; controllistener_t *listener; const cfg_obj_t *allow; const cfg_obj_t *global_keylist = NULL; const cfg_obj_t *control_keylist = NULL; dns_acl_t *new_acl = NULL; isc_result_t result = ISC_R_SUCCESS; listener = isc_mem_get(mctx, sizeof(*listener)); if (listener == NULL) result = ISC_R_NOMEMORY; if (result == ISC_R_SUCCESS) { listener->mctx = NULL; isc_mem_attach(mctx, &listener->mctx); listener->controls = cp; listener->task = cp->server->task; listener->address = *addr; listener->sock = NULL; listener->listening = ISC_FALSE; listener->exiting = ISC_FALSE; listener->acl = NULL; listener->type = type; listener->perm = 0; listener->owner = 0; listener->group = 0; ISC_LINK_INIT(listener, link); ISC_LIST_INIT(listener->keys); ISC_LIST_INIT(listener->connections); /* * Make the acl. */ if (control != NULL && type == isc_sockettype_tcp) { allow = cfg_tuple_get(control, "allow"); result = cfg_acl_fromconfig(allow, config, ns_g_lctx, aclconfctx, mctx, 0, &new_acl); } else { result = dns_acl_any(mctx, &new_acl); } } if (result == ISC_R_SUCCESS) { dns_acl_attach(new_acl, &listener->acl); dns_acl_detach(&new_acl); if (config != NULL) get_key_info(config, control, &global_keylist, &control_keylist); if (control_keylist != NULL) { result = controlkeylist_fromcfg(control_keylist, listener->mctx, &listener->keys); if (result == ISC_R_SUCCESS) register_keys(control, global_keylist, &listener->keys, listener->mctx, socktext); } else result = get_rndckey(mctx, &listener->keys); if (result != ISC_R_SUCCESS && control != NULL) cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING, "couldn't install keys for " "command channel %s: %s", socktext, isc_result_totext(result)); } if (result == ISC_R_SUCCESS) { int pf = isc_sockaddr_pf(&listener->address); if ((pf == AF_INET && isc_net_probeipv4() != ISC_R_SUCCESS) || #ifdef ISC_PLATFORM_HAVESYSUNH (pf == AF_UNIX && isc_net_probeunix() != ISC_R_SUCCESS) || #endif (pf == AF_INET6 && isc_net_probeipv6() != ISC_R_SUCCESS)) result = ISC_R_FAMILYNOSUPPORT; } if (result == ISC_R_SUCCESS && type == isc_sockettype_unix) isc_socket_cleanunix(&listener->address, ISC_FALSE); if (result == ISC_R_SUCCESS) result = isc_socket_create(ns_g_socketmgr, isc_sockaddr_pf(&listener->address), type, &listener->sock); if (result == ISC_R_SUCCESS) isc_socket_setname(listener->sock, "control", NULL); #ifndef ISC_ALLOW_MAPPED if (result == ISC_R_SUCCESS) isc_socket_ipv6only(listener->sock, ISC_TRUE); #endif if (result == ISC_R_SUCCESS) result = isc_socket_bind(listener->sock, &listener->address, ISC_SOCKET_REUSEADDRESS); if (result == ISC_R_SUCCESS && type == isc_sockettype_unix) { listener->perm = cfg_obj_asuint32(cfg_tuple_get(control, "perm")); listener->owner = cfg_obj_asuint32(cfg_tuple_get(control, "owner")); listener->group = cfg_obj_asuint32(cfg_tuple_get(control, "group")); result = isc_socket_permunix(&listener->address, listener->perm, listener->owner, listener->group); } if (result == ISC_R_SUCCESS) result = control_listen(listener); if (result == ISC_R_SUCCESS) result = control_accept(listener); if (result == ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_CONTROL, ISC_LOG_NOTICE, "command channel listening on %s", socktext); *listenerp = listener; } else { if (listener != NULL) { listener->exiting = ISC_TRUE; free_listener(listener); } if (control != NULL) cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING, "couldn't add command channel %s: %s", socktext, isc_result_totext(result)); else isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_CONTROL, ISC_LOG_NOTICE, "couldn't add command channel %s: %s", socktext, isc_result_totext(result)); *listenerp = NULL; } /* XXXDCL return error results? fail hard? */ }
/*% * 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); }
/*% 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); }
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); }
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; }
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; }
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 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_config_getipandkeylist(const cfg_obj_t *config, const cfg_obj_t *list, isc_mem_t *mctx, isc_sockaddr_t **addrsp, isc_dscp_t **dscpsp, dns_name_t ***keysp, isc_uint32_t *countp) { isc_uint32_t addrcount = 0, dscpcount = 0, keycount = 0, i = 0; isc_uint32_t listcount = 0, l = 0, j; isc_uint32_t stackcount = 0, pushed = 0; isc_result_t result; const cfg_listelt_t *element; const cfg_obj_t *addrlist; const cfg_obj_t *portobj; const cfg_obj_t *dscpobj; in_port_t port; isc_dscp_t dscp = -1; dns_fixedname_t fname; isc_sockaddr_t *addrs = NULL; isc_dscp_t *dscps = NULL; dns_name_t **keys = NULL; struct { const char *name; } *lists = NULL; struct { const cfg_listelt_t *element; in_port_t port; isc_dscp_t dscp; } *stack = NULL; REQUIRE(addrsp != NULL && *addrsp == NULL); REQUIRE(dscpsp != NULL && *dscpsp == NULL); REQUIRE(keysp != NULL && *keysp == NULL); REQUIRE(countp != NULL); /* * Get system defaults. */ result = ns_config_getport(config, &port); if (result != ISC_R_SUCCESS) goto cleanup; result = ns_config_getdscp(config, &dscp); if (result != ISC_R_SUCCESS) goto cleanup; newlist: addrlist = cfg_tuple_get(list, "addresses"); portobj = cfg_tuple_get(list, "port"); dscpobj = cfg_tuple_get(list, "dscp"); if (cfg_obj_isuint32(portobj)) { isc_uint32_t val = cfg_obj_asuint32(portobj); if (val > ISC_UINT16_MAX) { cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR, "port '%u' out of range", val); result = ISC_R_RANGE; goto cleanup; } port = (in_port_t) val; } if (dscpobj != NULL && cfg_obj_isuint32(dscpobj)) { if (cfg_obj_asuint32(dscpobj) > 63) { cfg_obj_log(dscpobj, ns_g_lctx, ISC_LOG_ERROR, "dscp value '%u' is out of range", cfg_obj_asuint32(dscpobj)); result = ISC_R_RANGE; goto cleanup; } dscp = (isc_dscp_t)cfg_obj_asuint32(dscpobj); } result = ISC_R_NOMEMORY; element = cfg_list_first(addrlist); resume: for ( ; element != NULL; element = cfg_list_next(element)) { const cfg_obj_t *addr; const cfg_obj_t *key; const char *keystr; isc_buffer_t b; addr = cfg_tuple_get(cfg_listelt_value(element), "masterselement"); key = cfg_tuple_get(cfg_listelt_value(element), "key"); if (!cfg_obj_issockaddr(addr)) { const char *listname = cfg_obj_asstring(addr); isc_result_t tresult; /* Grow lists? */ if (listcount == l) { void * tmp; isc_uint32_t newlen = listcount + 16; size_t newsize, oldsize; newsize = newlen * sizeof(*lists); oldsize = listcount * sizeof(*lists); tmp = isc_mem_get(mctx, newsize); if (tmp == NULL) goto cleanup; if (listcount != 0) { memmove(tmp, lists, oldsize); isc_mem_put(mctx, lists, oldsize); } lists = tmp; listcount = newlen; } /* Seen? */ for (j = 0; j < l; j++) if (strcasecmp(lists[j].name, listname) == 0) break; if (j < l) continue; tresult = get_masters_def(config, listname, &list); if (tresult == ISC_R_NOTFOUND) { cfg_obj_log(addr, ns_g_lctx, ISC_LOG_ERROR, "masters \"%s\" not found", listname); result = tresult; goto cleanup; } if (tresult != ISC_R_SUCCESS) goto cleanup; lists[l++].name = listname; /* Grow stack? */ if (stackcount == pushed) { void * tmp; isc_uint32_t newlen = stackcount + 16; size_t newsize, oldsize; newsize = newlen * sizeof(*stack); oldsize = stackcount * sizeof(*stack); tmp = isc_mem_get(mctx, newsize); if (tmp == NULL) goto cleanup; if (stackcount != 0) { memmove(tmp, stack, oldsize); isc_mem_put(mctx, stack, oldsize); } stack = tmp; stackcount = newlen; } /* * We want to resume processing this list on the * next element. */ stack[pushed].element = cfg_list_next(element); stack[pushed].port = port; stack[pushed].dscp = dscp; pushed++; goto newlist; } if (i == addrcount) { void * tmp; isc_uint32_t newlen = addrcount + 16; size_t newsize, oldsize; newsize = newlen * sizeof(isc_sockaddr_t); oldsize = addrcount * sizeof(isc_sockaddr_t); tmp = isc_mem_get(mctx, newsize); if (tmp == NULL) goto cleanup; if (addrcount != 0) { memmove(tmp, addrs, oldsize); isc_mem_put(mctx, addrs, oldsize); } addrs = tmp; addrcount = newlen; newsize = newlen * sizeof(isc_dscp_t); oldsize = dscpcount * sizeof(isc_dscp_t); tmp = isc_mem_get(mctx, newsize); if (tmp == NULL) goto cleanup; if (dscpcount != 0) { memmove(tmp, dscps, oldsize); isc_mem_put(mctx, dscps, oldsize); } dscps = tmp; dscpcount = newlen; newsize = newlen * sizeof(dns_name_t *); oldsize = keycount * sizeof(dns_name_t *); tmp = isc_mem_get(mctx, newsize); if (tmp == NULL) goto cleanup; if (keycount != 0) { memmove(tmp, keys, oldsize); isc_mem_put(mctx, keys, oldsize); } keys = tmp; keycount = newlen; } addrs[i] = *cfg_obj_assockaddr(addr); if (isc_sockaddr_getport(&addrs[i]) == 0) isc_sockaddr_setport(&addrs[i], port); dscps[i] = cfg_obj_getdscp(addr); if (dscps[i] == -1) dscps[i] = dscp; keys[i] = NULL; i++; /* Increment here so that cleanup on error works. */ if (!cfg_obj_isstring(key)) continue; keys[i - 1] = isc_mem_get(mctx, sizeof(dns_name_t)); if (keys[i - 1] == NULL) goto cleanup; dns_name_init(keys[i - 1], NULL); keystr = cfg_obj_asstring(key); isc_buffer_constinit(&b, keystr, strlen(keystr)); isc_buffer_add(&b, strlen(keystr)); dns_fixedname_init(&fname); result = dns_name_fromtext(dns_fixedname_name(&fname), &b, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) goto cleanup; result = dns_name_dup(dns_fixedname_name(&fname), mctx, keys[i - 1]); if (result != ISC_R_SUCCESS) goto cleanup; } if (pushed != 0) { pushed--; element = stack[pushed].element; port = stack[pushed].port; dscp = stack[pushed].dscp; goto resume; } if (i < addrcount) { void * tmp; size_t newsize, oldsize; newsize = i * sizeof(isc_sockaddr_t); oldsize = addrcount * sizeof(isc_sockaddr_t); if (i != 0) { tmp = isc_mem_get(mctx, newsize); if (tmp == NULL) goto cleanup; memmove(tmp, addrs, newsize); } else tmp = NULL; isc_mem_put(mctx, addrs, oldsize); addrs = tmp; addrcount = i; newsize = i * sizeof(isc_dscp_t); oldsize = dscpcount * sizeof(isc_dscp_t); if (i != 0) { tmp = isc_mem_get(mctx, newsize); if (tmp == NULL) goto cleanup; memmove(tmp, dscps, newsize); } else tmp = NULL; isc_mem_put(mctx, dscps, oldsize); dscps = tmp; dscpcount = i; newsize = i * sizeof(dns_name_t *); oldsize = keycount * sizeof(dns_name_t *); if (i != 0) { tmp = isc_mem_get(mctx, newsize); if (tmp == NULL) goto cleanup; memmove(tmp, keys, newsize); } else tmp = NULL; isc_mem_put(mctx, keys, oldsize); keys = tmp; keycount = i; } if (lists != NULL) isc_mem_put(mctx, lists, listcount * sizeof(*lists)); if (stack != NULL) isc_mem_put(mctx, stack, stackcount * sizeof(*stack)); INSIST(keycount == addrcount); *addrsp = addrs; *dscpsp = dscps; *keysp = keys; *countp = addrcount; return (ISC_R_SUCCESS); cleanup: if (addrs != NULL) isc_mem_put(mctx, addrs, addrcount * sizeof(isc_sockaddr_t)); if (dscps != NULL) isc_mem_put(mctx, dscps, dscpcount * sizeof(isc_dscp_t)); if (keys != NULL) { for (j = 0; j < i; j++) { if (keys[j] == NULL) continue; if (dns_name_dynamic(keys[j])) dns_name_free(keys[j], mctx); isc_mem_put(mctx, keys[j], sizeof(dns_name_t)); } isc_mem_put(mctx, keys, keycount * sizeof(dns_name_t *)); } if (lists != NULL) isc_mem_put(mctx, lists, listcount * sizeof(*lists)); if (stack != NULL) isc_mem_put(mctx, stack, stackcount * sizeof(*stack)); return (result); }
isc_result_t ns_config_getiplist(const cfg_obj_t *config, const cfg_obj_t *list, in_port_t defport, isc_mem_t *mctx, isc_sockaddr_t **addrsp, isc_dscp_t **dscpsp, isc_uint32_t *countp) { int count, i = 0; const cfg_obj_t *addrlist; const cfg_obj_t *portobj, *dscpobj; const cfg_listelt_t *element; isc_sockaddr_t *addrs; in_port_t port; isc_dscp_t dscp = -1, *dscps = NULL; isc_result_t result; INSIST(addrsp != NULL && *addrsp == NULL); INSIST(dscpsp == NULL || *dscpsp == NULL); INSIST(countp != NULL); addrlist = cfg_tuple_get(list, "addresses"); count = ns_config_listcount(addrlist); portobj = cfg_tuple_get(list, "port"); if (cfg_obj_isuint32(portobj)) { isc_uint32_t val = cfg_obj_asuint32(portobj); if (val > ISC_UINT16_MAX) { cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR, "port '%u' out of range", val); return (ISC_R_RANGE); } port = (in_port_t) val; } else if (defport != 0) port = defport; else { result = ns_config_getport(config, &port); if (result != ISC_R_SUCCESS) return (result); } if (dscpsp != NULL) { dscpobj = cfg_tuple_get(list, "dscp"); if (dscpobj != NULL && cfg_obj_isuint32(dscpobj)) { if (cfg_obj_asuint32(dscpobj) > 63) { cfg_obj_log(dscpobj, ns_g_lctx, ISC_LOG_ERROR, "dscp value '%u' is out of range", cfg_obj_asuint32(dscpobj)); return (ISC_R_RANGE); } dscp = (isc_dscp_t)cfg_obj_asuint32(dscpobj); } dscps = isc_mem_get(mctx, count * sizeof(isc_dscp_t)); if (dscps == NULL) return (ISC_R_NOMEMORY); } addrs = isc_mem_get(mctx, count * sizeof(isc_sockaddr_t)); if (addrs == NULL) { if (dscps != NULL) isc_mem_put(mctx, dscps, count * sizeof(isc_dscp_t)); return (ISC_R_NOMEMORY); } for (element = cfg_list_first(addrlist); element != NULL; element = cfg_list_next(element), i++) { const cfg_obj_t *addr; INSIST(i < count); addr = cfg_listelt_value(element); addrs[i] = *cfg_obj_assockaddr(addr); if (dscpsp != NULL) { isc_dscp_t innerdscp; innerdscp = cfg_obj_getdscp(addr); if (innerdscp == -1) innerdscp = dscp; dscps[i] = innerdscp; } if (isc_sockaddr_getport(&addrs[i]) == 0) isc_sockaddr_setport(&addrs[i], port); } INSIST(i == count); *addrsp = addrs; *countp = count; if (dscpsp != NULL) *dscpsp = dscps; return (ISC_R_SUCCESS); }
static isc_result_t key_fromconfig(const cfg_obj_t *key, dns_client_t *client) { dns_rdata_dnskey_t keystruct; isc_uint32_t flags, proto, alg; const char *keystr, *keynamestr; unsigned char keydata[4096]; isc_buffer_t keydatabuf; unsigned char rrdata[4096]; isc_buffer_t rrdatabuf; isc_region_t r; dns_fixedname_t fkeyname; dns_name_t *keyname; isc_result_t result; isc_boolean_t match_root = ISC_FALSE, match_dlv = ISC_FALSE; keynamestr = cfg_obj_asstring(cfg_tuple_get(key, "name")); CHECK(convert_name(&fkeyname, &keyname, keynamestr)); if (!root_validation && !dlv_validation) return (ISC_R_SUCCESS); if (anchor_name) match_root = dns_name_equal(keyname, anchor_name); if (dlv_name) match_dlv = dns_name_equal(keyname, dlv_name); if (!match_root && !match_dlv) return (ISC_R_SUCCESS); if ((!root_validation && match_root) || (!dlv_validation && match_dlv)) return (ISC_R_SUCCESS); if (match_root) delv_log(ISC_LOG_DEBUG(3), "adding trust anchor %s", trust_anchor); if (match_dlv) delv_log(ISC_LOG_DEBUG(3), "adding DLV trust anchor %s", dlv_anchor); 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")); keystruct.common.rdclass = dns_rdataclass_in; keystruct.common.rdtype = dns_rdatatype_dnskey; /* * The key data in keystruct is not dynamically allocated. */ keystruct.mctx = NULL; ISC_LINK_INIT(&keystruct.common, link); if (flags > 0xffff) CHECK(ISC_R_RANGE); if (proto > 0xff) CHECK(ISC_R_RANGE); if (alg > 0xff) CHECK(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, keydata, sizeof(keydata)); isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata)); keystr = cfg_obj_asstring(cfg_tuple_get(key, "key")); CHECK(isc_base64_decodestring(keystr, &keydatabuf)); isc_buffer_usedregion(&keydatabuf, &r); keystruct.datalen = r.length; keystruct.data = r.base; CHECK(dns_rdata_fromstruct(NULL, keystruct.common.rdclass, keystruct.common.rdtype, &keystruct, &rrdatabuf)); CHECK(dns_client_addtrustedkey(client, dns_rdataclass_in, keyname, &rrdatabuf)); trusted_keys++; cleanup: if (result == DST_R_NOCRYPTO) cfg_obj_log(key, lctx, ISC_LOG_ERROR, "no crypto support"); else if (result == DST_R_UNSUPPORTEDALG) { cfg_obj_log(key, lctx, ISC_LOG_WARNING, "skipping trusted key '%s': %s", keynamestr, isc_result_totext(result)); result = ISC_R_SUCCESS; } else if (result != ISC_R_SUCCESS) { cfg_obj_log(key, lctx, ISC_LOG_ERROR, "failed to add trusted key '%s': %s", keynamestr, isc_result_totext(result)); result = ISC_R_FAILURE; } return (result); }