Beispiel #1
0
static isc_boolean_t
get_checknames(const cfg_obj_t **maps, 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;
	isc_result_t result;
	int i;

	for (i = 0;; i++) {
		if (maps[i] == NULL)
			return (ISC_FALSE);
		checknames = NULL;
		result = cfg_map_get(maps[i], "check-names", &checknames);
		if (result != ISC_R_SUCCESS)
			continue;
		if (checknames != NULL && !cfg_obj_islist(checknames)) {
			*obj = checknames;
			return (ISC_TRUE);
		}
		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), "master") != 0)
				continue;
			*obj = cfg_tuple_get(value, "mode");
			return (ISC_TRUE);
		}
	}
}
Beispiel #2
0
isc_result_t
ns_log_configure(isc_logconfig_t *logconf, const cfg_obj_t *logstmt) {
	isc_result_t result;
	const cfg_obj_t *channels = NULL;
	const cfg_obj_t *categories = NULL;
	const cfg_listelt_t *element;
	isc_boolean_t default_set = ISC_FALSE;
	isc_boolean_t unmatched_set = ISC_FALSE;
	const cfg_obj_t *catname;

	CHECK(ns_log_setdefaultchannels(logconf));

	(void)cfg_map_get(logstmt, "channel", &channels);
	for (element = cfg_list_first(channels);
	     element != NULL;
	     element = cfg_list_next(element))
	{
		const cfg_obj_t *channel = cfg_listelt_value(element);
		CHECK(channel_fromconf(channel, logconf));
	}

	(void)cfg_map_get(logstmt, "category", &categories);
	for (element = cfg_list_first(categories);
	     element != NULL;
	     element = cfg_list_next(element))
	{
		const cfg_obj_t *category = cfg_listelt_value(element);
		CHECK(category_fromconf(category, logconf));
		if (!default_set) {
			catname = cfg_tuple_get(category, "name");
			if (strcmp(cfg_obj_asstring(catname), "default") == 0)
				default_set = ISC_TRUE;
		}
		if (!unmatched_set) {
			catname = cfg_tuple_get(category, "name");
			if (strcmp(cfg_obj_asstring(catname), "unmatched") == 0)
				unmatched_set = ISC_TRUE;
		}
	}

	if (!default_set)
		CHECK(ns_log_setdefaultcategory(logconf));

	if (!unmatched_set)
		CHECK(ns_log_setunmatchedcategory(logconf));

	return (ISC_R_SUCCESS);

 cleanup:
	if (logconf != NULL)
		isc_logconfig_destroy(&logconf);
	return (result);
}
Beispiel #3
0
static isc_result_t
get_masters_def(const cfg_obj_t *cctx, const char *name,
		const cfg_obj_t **ret)
{
	isc_result_t result;
	const cfg_obj_t *masters = NULL;
	const cfg_listelt_t *elt;

	result = cfg_map_get(cctx, "masters", &masters);
	if (result != ISC_R_SUCCESS)
		return (result);
	for (elt = cfg_list_first(masters);
	     elt != NULL;
	     elt = cfg_list_next(elt)) {
		const cfg_obj_t *list;
		const char *listname;

		list = cfg_listelt_value(elt);
		listname = cfg_obj_asstring(cfg_tuple_get(list, "name"));

		if (strcasecmp(listname, name) == 0) {
			*ret = list;
			return (ISC_R_SUCCESS);
		}
	}
	return (ISC_R_NOTFOUND);
}
Beispiel #4
0
/*% configure a view */
static isc_result_t
configure_view(const char *vclass, const char *view, const cfg_obj_t *config,
	       const cfg_obj_t *vconfig, isc_mem_t *mctx)
{
	const cfg_listelt_t *element;
	const cfg_obj_t *voptions;
	const cfg_obj_t *zonelist;
	isc_result_t result = ISC_R_SUCCESS;
	isc_result_t tresult;

	voptions = NULL;
	if (vconfig != NULL)
		voptions = cfg_tuple_get(vconfig, "options");

	zonelist = NULL;
	if (voptions != NULL)
		(void)cfg_map_get(voptions, "zone", &zonelist);
	else
		(void)cfg_map_get(config, "zone", &zonelist);

	for (element = cfg_list_first(zonelist);
	     element != NULL;
	     element = cfg_list_next(element))
	{
		const cfg_obj_t *zconfig = cfg_listelt_value(element);
		tresult = configure_zone(vclass, view, zconfig, vconfig,
					 config, mctx);
		if (tresult != ISC_R_SUCCESS)
			result = tresult;
	}
	return (result);
}
Beispiel #5
0
/*
 * 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;
        }
    }
}
Beispiel #6
0
isc_boolean_t
ns_zone_reusable(dns_zone_t *zone, const cfg_obj_t *zconfig) {
	const cfg_obj_t *zoptions = NULL;
	const cfg_obj_t *obj = NULL;
	const char *cfilename;
	const char *zfilename;

	zoptions = cfg_tuple_get(zconfig, "options");

	if (zonetype_fromconfig(zoptions) != dns_zone_gettype(zone))
		return (ISC_FALSE);

	/*
	 * We always reconfigure a static-stub zone for simplicity, assuming
	 * the amount of data to be loaded is small.
	 */
	if (zonetype_fromconfig(zoptions) == dns_zone_staticstub)
		return (ISC_FALSE);

	obj = NULL;
	(void)cfg_map_get(zoptions, "file", &obj);
	if (obj != NULL)
		cfilename = cfg_obj_asstring(obj);
	else
		cfilename = NULL;
	zfilename = dns_zone_getfile(zone);
	if (!((cfilename == NULL && zfilename == NULL) ||
	      (cfilename != NULL && zfilename != NULL &&
	       strcmp(cfilename, zfilename) == 0)))
	    return (ISC_FALSE);

	return (ISC_TRUE);
}
Beispiel #7
0
/*%
 * Set up a logging category according to the named.conf data
 * in 'ccat' and add it to 'logconfig'.
 */
static isc_result_t
category_fromconf(const cfg_obj_t *ccat, isc_logconfig_t *logconfig) {
	isc_result_t result;
	const char *catname;
	isc_logcategory_t *category;
	isc_logmodule_t *module;
	const cfg_obj_t *destinations = NULL;
	const cfg_listelt_t *element = NULL;

	catname = cfg_obj_asstring(cfg_tuple_get(ccat, "name"));
	category = isc_log_categorybyname(ns_g_lctx, catname);
	if (category == NULL) {
		cfg_obj_log(ccat, ns_g_lctx, ISC_LOG_ERROR,
			    "unknown logging category '%s' ignored",
			    catname);
		/*
		 * Allow further processing by returning success.
		 */
		return (ISC_R_SUCCESS);
	}

	if (logconfig == NULL)
		return (ISC_R_SUCCESS);

	module = NULL;

	destinations = cfg_tuple_get(ccat, "destinations");
	for (element = cfg_list_first(destinations);
	     element != NULL;
	     element = cfg_list_next(element))
	{
		const cfg_obj_t *channel = cfg_listelt_value(element);
		const char *channelname = cfg_obj_asstring(channel);

		result = isc_log_usechannel(logconfig, channelname, category,
					    module);
		if (result != ISC_R_SUCCESS) {
			isc_log_write(ns_g_lctx, CFG_LOGCATEGORY_CONFIG,
				      NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
				      "logging channel '%s': %s", channelname,
				      isc_result_totext(result));
			return (result);
		}
	}
	return (ISC_R_SUCCESS);
}
Beispiel #8
0
/*% 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 *views;
	const cfg_obj_t *vconfig;
	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 cfg_obj_t *classobj;
		dns_rdataclass_t viewclass;
		const char *vname;
		char buf[sizeof("CLASS65535")];

		vconfig = cfg_listelt_value(element);
		if (vconfig == NULL)
			continue;

		classobj = cfg_tuple_get(vconfig, "class");
		CHECK(config_getclass(classobj, dns_rdataclass_in,
					 &viewclass));
		if (dns_rdataclass_ismeta(viewclass))
			CHECK(ISC_R_FAILURE);

		dns_rdataclass_format(viewclass, buf, sizeof(buf));
		vname = cfg_obj_asstring(cfg_tuple_get(vconfig, "name"));
		tresult = configure_view(buf, 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;
	}

cleanup:
	return (result);
}
Beispiel #9
0
/*
 * Find the definition of the named acl whose name is "name".
 */
static isc_result_t
get_acl_def(cfg_obj_t *cctx, char *name, cfg_obj_t **ret) {
	isc_result_t result;
	cfg_obj_t *acls = NULL;
	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)) {
		cfg_obj_t *acl = cfg_listelt_value(elt);
		const char *aclname = cfg_obj_asstring(cfg_tuple_get(acl, "name"));
		if (strcasecmp(aclname, name) == 0) {
			*ret = cfg_tuple_get(acl, "value");
			return (ISC_R_SUCCESS);
		}
	}
	return (ISC_R_NOTFOUND);
}
Beispiel #10
0
/*% 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);
}
Beispiel #11
0
/*
 * Recursively pre-parse an ACL definition to find the total number
 * of non-IP-prefix elements (localhost, localnets, key) in all nested
 * ACLs, so that the parent will have enough space allocated for the
 * elements table after all the nested ACLs have been merged in to the
 * parent.
 */
static int
count_acl_elements(const cfg_obj_t *caml, const cfg_obj_t *cctx,
		   isc_boolean_t *has_negative)
{
	const cfg_listelt_t *elt;
	const cfg_obj_t *cacl = NULL;
	isc_result_t result;
	int n = 0;

	if (has_negative != NULL)
		*has_negative = ISC_FALSE;

	for (elt = cfg_list_first(caml);
	     elt != NULL;
	     elt = cfg_list_next(elt)) {
		const cfg_obj_t *ce = cfg_listelt_value(elt);

		/* negated element; just get the value. */
		if (cfg_obj_istuple(ce)) {
			ce = cfg_tuple_get(ce, "value");
			if (has_negative != NULL)
				*has_negative = ISC_TRUE;
		}

		if (cfg_obj_istype(ce, &cfg_type_keyref)) {
			n++;
		} else if (cfg_obj_islist(ce)) {
			isc_boolean_t negative;
			n += count_acl_elements(ce, cctx, &negative);
			if (negative)
				n++;
		} else if (cfg_obj_isstring(ce)) {
			const char *name = cfg_obj_asstring(ce);
			if (strcasecmp(name, "localhost") == 0 ||
#ifdef SUPPORT_GEOIP
			    strncasecmp(name, "country_", 8) == 0 ||
#endif
			    strcasecmp(name, "localnets") == 0) {
				n++;
			} else if (strcasecmp(name, "any") != 0 &&
				   strcasecmp(name, "none") != 0) {
				result = get_acl_def(cctx, name, &cacl);
				if (result == ISC_R_SUCCESS)
					n += count_acl_elements(cacl, cctx,
								NULL) + 1;
			}
		}
	}

	return n;
}
Beispiel #12
0
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);
				}
			}

		}
	}
}
Beispiel #13
0
static isc_result_t ATTR_NONNULLS ATTR_CHECKRESULT
get_types(isc_mem_t *mctx, const cfg_obj_t *obj, dns_rdatatype_t **typesp,
	  unsigned int *np)
{
	isc_result_t result = ISC_R_SUCCESS;
	unsigned int i;
	unsigned int n = 0;
	const cfg_listelt_t *el;
	dns_rdatatype_t *types = NULL;

	REQUIRE(obj != NULL);
	REQUIRE(typesp != NULL && *typesp == NULL);
	REQUIRE(np != NULL);

	obj = cfg_tuple_get(obj, "types");

	n = count_list_elements(obj);
	if (n > 0)
		CHECKED_MEM_GET(mctx, types, n * sizeof(dns_rdatatype_t));

	i = 0;
	for (el = cfg_list_first(obj); el != NULL; el = cfg_list_next(el)) {
		const cfg_obj_t *typeobj;
		const char *str;
		isc_textregion_t r;

		INSIST(i < n);

		typeobj = cfg_listelt_value(el);
		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) {
			log_error("'%s' is not a valid type", str);
			goto cleanup;
		}
	}
	INSIST(i == n);

	*typesp = types;
	*np = n;
	return result;

cleanup:
	SAFE_MEM_PUT(mctx, types, n * sizeof(dns_rdatatype_t));

	return result;
}
Beispiel #14
0
static void
update_listener(ns_server_t *server, ns_statschannel_t **listenerp,
		const cfg_obj_t *listen_params, const cfg_obj_t *config,
		isc_sockaddr_t *addr, cfg_aclconfctx_t *aclconfctx,
		const char *socktext)
{
	ns_statschannel_t *listener;
	const cfg_obj_t *allow = NULL;
	dns_acl_t *new_acl = NULL;
	isc_result_t result = ISC_R_SUCCESS;

	for (listener = ISC_LIST_HEAD(server->statschannels);
	     listener != NULL;
	     listener = ISC_LIST_NEXT(listener, link))
		if (isc_sockaddr_equal(addr, &listener->address))
			break;

	if (listener == NULL) {
		*listenerp = NULL;
		return;
	}

	/*
	 * Now, keep the old access list unless a new one can be made.
	 */
	allow = cfg_tuple_get(listen_params, "allow");
	if (allow != NULL && cfg_obj_islist(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) {
		LOCK(&listener->lock);

		dns_acl_detach(&listener->acl);
		dns_acl_attach(new_acl, &listener->acl);
		dns_acl_detach(&new_acl);

		UNLOCK(&listener->lock);
	} else {
		cfg_obj_log(listen_params, ns_g_lctx, ISC_LOG_WARNING,
			    "couldn't install new acl for "
			    "statistics channel %s: %s",
			    socktext, isc_result_totext(result));
	}

	*listenerp = listener;
}
Beispiel #15
0
static isc_result_t ATTR_NONNULLS ATTR_CHECKRESULT
get_match_type(const cfg_obj_t *obj, unsigned int *value)
{
	const char *str;

	if (!cfg_obj_istuple(obj)) {
		log_bug("tuple is expected");
		return ISC_R_UNEXPECTED;
	}
	obj = cfg_tuple_get(obj, "matchtype");
	if (!cfg_obj_isstring(obj)) {
		log_bug("matchtype is not defined");
		return ISC_R_UNEXPECTED;
	}
	str = cfg_obj_asstring(obj);

	MATCH("name", DNS_SSUMATCHTYPE_NAME);
	MATCH("subdomain", DNS_SSUMATCHTYPE_SUBDOMAIN);
	MATCH("zonesub", DNS_SSUMATCHTYPE_SUBDOMAIN);
	MATCH("wildcard", DNS_SSUMATCHTYPE_WILDCARD);
	MATCH("self", DNS_SSUMATCHTYPE_SELF);
#if defined(DNS_SSUMATCHTYPE_SELFSUB) && defined(DNS_SSUMATCHTYPE_SELFWILD)
	MATCH("selfsub", DNS_SSUMATCHTYPE_SELFSUB);
	MATCH("selfwild", DNS_SSUMATCHTYPE_SELFWILD);
#endif
#ifdef DNS_SSUMATCHTYPE_SELFMS
	MATCH("ms-self", DNS_SSUMATCHTYPE_SELFMS);
#endif
#ifdef DNS_SSUMATCHTYPE_SELFKRB5
	MATCH("krb5-self", DNS_SSUMATCHTYPE_SELFKRB5);
#endif
#ifdef DNS_SSUMATCHTYPE_SUBDOMAINMS
	MATCH("ms-subdomain", DNS_SSUMATCHTYPE_SUBDOMAINMS);
#endif
#ifdef DNS_SSUMATCHTYPE_SUBDOMAINKRB5
	MATCH("krb5-subdomain", DNS_SSUMATCHTYPE_SUBDOMAINKRB5);
#endif
#if defined(DNS_SSUMATCHTYPE_TCPSELF) && defined(DNS_SSUMATCHTYPE_6TO4SELF)
	MATCH("tcp-self", DNS_SSUMATCHTYPE_TCPSELF);
	MATCH("6to4-self", DNS_SSUMATCHTYPE_6TO4SELF);
#endif
#if defined(DNS_SSUMATCHTYPE_EXTERNAL)
	MATCH("external", DNS_SSUMATCHTYPE_EXTERNAL);
#endif

	log_bug("unsupported match type '%s'", str);
	return ISC_R_NOTIMPLEMENTED;
}
Beispiel #16
0
isc_result_t
ns_tsigkeyring_fromconfig (const cfg_obj_t * config, const cfg_obj_t * vconfig,
                           isc_mem_t * mctx, dns_tsig_keyring_t ** ringp)
{
    const cfg_obj_t *maps[3];

    const cfg_obj_t *keylist;

    dns_tsig_keyring_t *ring = NULL;

    isc_result_t result;

    int i;

    REQUIRE (ringp != NULL && *ringp == NULL);

    i = 0;
    if (config != NULL)
        maps[i++] = config;
    if (vconfig != NULL)
        maps[i++] = cfg_tuple_get (vconfig, "options");
    maps[i] = NULL;

    result = dns_tsigkeyring_create (mctx, &ring);
    if (result != ISC_R_SUCCESS)
        return (result);

    for (i = 0;; i++)
    {
        if (maps[i] == NULL)
            break;
        keylist = NULL;
        result = cfg_map_get (maps[i], "key", &keylist);
        if (result != ISC_R_SUCCESS)
            continue;
        result = add_initial_keys (keylist, ring, mctx);
        if (result != ISC_R_SUCCESS)
            goto failure;
    }

    *ringp = ring;
    return (ISC_R_SUCCESS);

  failure:
    dns_tsigkeyring_detach (&ring);
    return (result);
}
Beispiel #17
0
static isc_result_t ATTR_NONNULLS ATTR_CHECKRESULT
get_fixed_name(const cfg_obj_t *obj, const char *name, dns_fixedname_t *fname)
{
	isc_result_t result;
	isc_buffer_t buf;
	const char *str;
	size_t len;

	REQUIRE(fname != NULL);

	if (!cfg_obj_istuple(obj)) {
		log_bug("configuration object is not a tuple");
		return ISC_R_UNEXPECTED;
	}
	obj = cfg_tuple_get(obj, name);

	if (!cfg_obj_isstring(obj))
		return ISC_R_NOTFOUND;
	str = cfg_obj_asstring(obj);

	len = strlen(str);
	isc_buffer_init(&buf, (char *)str, len);

	/*
	 * Workaround for https://bugzilla.redhat.com/show_bug.cgi?id=728925
	 *
	 * ipa-server-install script could create SSU rules with
	 * double-dot-ending FQDNs. Silently "adjust" such wrong FQDNs.
	 */
	if (str[len - 1] == '.' && str[len - 2] == '.')
		isc_buffer_add(&buf, len - 1);
	else
		isc_buffer_add(&buf, len);

	dns_fixedname_init(fname);

	result = dns_name_fromtext(dns_fixedname_name(fname), &buf,
				   dns_rootname, ISC_FALSE, NULL);
	if (result != ISC_R_SUCCESS)
		log_error("'%s' is not a valid name", str);

	return result;
}
Beispiel #18
0
static isc_result_t ATTR_NONNULLS ATTR_CHECKRESULT
get_mode(const cfg_obj_t *obj, isc_boolean_t *value)
{
	const char *str;

	if (!cfg_obj_istuple(obj)) {
		log_bug("tuple is expected");
		return ISC_R_UNEXPECTED;
	}
	obj = cfg_tuple_get(obj, "mode");
	if (!cfg_obj_isstring(obj)) {
		log_bug("mode is not defined");
		return ISC_R_UNEXPECTED;
	}
	str = cfg_obj_asstring(obj);

	MATCH("grant", ISC_TRUE);
	MATCH("deny", ISC_FALSE);

	log_bug("unsupported ACL mode '%s'", str);
	return ISC_R_NOTIMPLEMENTED;
}
Beispiel #19
0
/*%
 * 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);
}
Beispiel #20
0
/*% 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);
}
Beispiel #21
0
/*% 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);
}
Beispiel #22
0
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);
}
Beispiel #23
0
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;
}
Beispiel #24
0
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? */
}
Beispiel #25
0
/*%
 * 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);
}
Beispiel #26
0
/*%
 * 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);
}
Beispiel #27
0
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);
}
Beispiel #28
0
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);
}
Beispiel #29
0
/*
 * 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);
}
Beispiel #30
0
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;
}