Example #1
0
static isc_result_t
load_keys(const cfg_obj_t *keys, dns_client_t *client) {
	const cfg_listelt_t *elt, *elt2;
	const cfg_obj_t *key, *keylist;
	isc_result_t result = ISC_R_SUCCESS;

	for (elt = cfg_list_first(keys);
	     elt != NULL;
	     elt = cfg_list_next(elt))
	{
		keylist = cfg_listelt_value(elt);

		for (elt2 = cfg_list_first(keylist);
		     elt2 != NULL;
		     elt2 = cfg_list_next(elt2))
		{
			key = cfg_listelt_value(elt2);
			CHECK(key_fromconfig(key, client));
		}
	}

 cleanup:
	if (result == DST_R_NOCRYPTO)
		result = ISC_R_SUCCESS;
	return (result);
}
Example #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);
}
Example #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);
}
Example #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);
}
Example #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;
        }
    }
}
Example #6
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);
		}
	}
}
Example #7
0
/*%
 * Configure an apex NS with an out-of-zone NS names for a static-stub zone.
 * For example, for the zone named "example.com", something like the following
 * RRs will be added to the zone DB:
 * example.com. NS ns.example.net.
 */
static isc_result_t
configure_staticstub_servernames(const cfg_obj_t *zconfig, dns_zone_t *zone,
				 dns_rdatalist_t *rdatalist, const char *zname)
{
	const cfg_listelt_t *element;
	isc_mem_t *mctx = dns_zone_getmctx(zone);
	dns_rdata_t *rdata;
	isc_region_t sregion, region;
	isc_result_t result = ISC_R_SUCCESS;

	for (element = cfg_list_first(zconfig);
	     element != NULL;
	     element = cfg_list_next(element))
	{
		const cfg_obj_t *obj;
		const char *str;
		dns_fixedname_t fixed_name;
		dns_name_t *nsname;
		isc_buffer_t b;

		obj = cfg_listelt_value(element);
		str = cfg_obj_asstring(obj);

		dns_fixedname_init(&fixed_name);
		nsname = dns_fixedname_name(&fixed_name);

		isc_buffer_init(&b, str, strlen(str));
		isc_buffer_add(&b, strlen(str));
		result = dns_name_fromtext(nsname, &b, dns_rootname, 0, NULL);
		if (result != ISC_R_SUCCESS) {
			cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR,
					    "server-name '%s' is not a valid "
					    "name", str);
			return (result);
		}
		if (dns_name_issubdomain(nsname, dns_zone_getorigin(zone))) {
			cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR,
				    "server-name '%s' must not be a "
				    "subdomain of zone name '%s'",
				    str, zname);
			return (ISC_R_FAILURE);
		}

		dns_name_toregion(nsname, &sregion);
		rdata = isc_mem_get(mctx, sizeof(*rdata) + sregion.length);
		if (rdata == NULL)
			return (ISC_R_NOMEMORY);
		region.length = sregion.length;
		region.base = (unsigned char *)(rdata + 1);
		memcpy(region.base, sregion.base, region.length);
		dns_rdata_init(rdata);
		dns_rdata_fromregion(rdata, dns_zone_getclass(zone),
				     dns_rdatatype_ns, &region);
		ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
	}

	return (result);
}
Example #8
0
int
ns_config_listcount(const cfg_obj_t *list) {
	const cfg_listelt_t *e;
	int i = 0;

	for (e = cfg_list_first(list); e != NULL; e = cfg_list_next(e))
		i++;

	return (i);
}
Example #9
0
static unsigned int ATTR_NONNULLS ATTR_CHECKRESULT
count_list_elements(const cfg_obj_t *list)
{
	const cfg_listelt_t *el;
	unsigned int ret = 0;

	for (el = cfg_list_first(list); el != NULL; el = cfg_list_next(el))
		ret++;

	return ret;
}
Example #10
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;
}
Example #11
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;
}
Example #12
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);
}
Example #13
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);
}
Example #14
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);
}
Example #15
0
static isc_result_t cfgkeylist_find (const cfg_obj_t * keylist, const char *keyname, const cfg_obj_t ** objp)
{
    const cfg_listelt_t *element;

    const char *str;

    const cfg_obj_t *obj;

    for (element = cfg_list_first (keylist); element != NULL; element = cfg_list_next (element))
    {
        obj = cfg_listelt_value (element);
        str = cfg_obj_asstring (cfg_map_getname (obj));
        if (strcasecmp (str, keyname) == 0)
            break;
    }
    if (element == NULL)
        return (ISC_R_NOTFOUND);
    obj = cfg_listelt_value (element);
    *objp = obj;
    return (ISC_R_SUCCESS);
}
Example #16
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);
}
Example #17
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);
				}
			}

		}
	}
}
Example #18
0
static isc_result_t
controlkeylist_fromcfg(const cfg_obj_t *keylist, isc_mem_t *mctx,
		       controlkeylist_t *keyids)
{
	const cfg_listelt_t *element;
	char *newstr = NULL;
	const char *str;
	const cfg_obj_t *obj;
	controlkey_t *key;

	for (element = cfg_list_first(keylist);
	     element != NULL;
	     element = cfg_list_next(element))
	{
		obj = cfg_listelt_value(element);
		str = cfg_obj_asstring(obj);
		newstr = isc_mem_strdup(mctx, str);
		if (newstr == NULL)
			goto cleanup;
		key = isc_mem_get(mctx, sizeof(*key));
		if (key == NULL)
			goto cleanup;
		key->keyname = newstr;
		key->algorithm = DST_ALG_UNKNOWN;
		key->secret.base = NULL;
		key->secret.length = 0;
		ISC_LINK_INIT(key, link);
		ISC_LIST_APPEND(*keyids, key, link);
		newstr = NULL;
	}
	return (ISC_R_SUCCESS);

 cleanup:
	if (newstr != NULL)
		isc_mem_free(mctx, newstr);
	free_controlkeylist(keyids, mctx);
	return (ISC_R_NOMEMORY);
}
Example #19
0
static isc_result_t
add_initial_keys(const cfg_obj_t *list, dns_tsig_keyring_t *ring,
		 isc_mem_t *mctx)
{
	dns_tsigkey_t *tsigkey = NULL;
	const cfg_listelt_t *element;
	const cfg_obj_t *key = NULL;
	const char *keyid = NULL;
	unsigned char *secret = NULL;
	int secretalloc = 0;
	int secretlen = 0;
	isc_result_t ret;
	isc_stdtime_t now;
	isc_uint16_t bits;

	for (element = cfg_list_first(list);
	     element != NULL;
	     element = cfg_list_next(element))
	{
		const cfg_obj_t *algobj = NULL;
		const cfg_obj_t *secretobj = NULL;
		dns_name_t keyname;
		dns_name_t *alg;
		const char *algstr;
		char keynamedata[1024];
		isc_buffer_t keynamesrc, keynamebuf;
		const char *secretstr;
		isc_buffer_t secretbuf;

		key = cfg_listelt_value(element);
		keyid = cfg_obj_asstring(cfg_map_getname(key));

		algobj = NULL;
		secretobj = NULL;
		(void)cfg_map_get(key, "algorithm", &algobj);
		(void)cfg_map_get(key, "secret", &secretobj);
		INSIST(algobj != NULL && secretobj != NULL);

		/*
		 * Create the key name.
		 */
		dns_name_init(&keyname, NULL);
		isc_buffer_init(&keynamesrc, keyid, strlen(keyid));
		isc_buffer_add(&keynamesrc, strlen(keyid));
		isc_buffer_init(&keynamebuf, keynamedata, sizeof(keynamedata));
		ret = dns_name_fromtext(&keyname, &keynamesrc, dns_rootname,
					ISC_TRUE, &keynamebuf);
		if (ret != ISC_R_SUCCESS)
			goto failure;

		/*
		 * Create the algorithm.
		 */
		algstr = cfg_obj_asstring(algobj);
		if (ns_config_getkeyalgorithm(algstr, &alg, &bits)
		    != ISC_R_SUCCESS) {
			cfg_obj_log(algobj, ns_g_lctx, ISC_LOG_ERROR,
				    "key '%s': has a unsupported algorithm '%s'",
				    keyid, algstr);
			ret = DNS_R_BADALG;
			goto failure;
		}

		secretstr = cfg_obj_asstring(secretobj);
		secretalloc = secretlen = strlen(secretstr) * 3 / 4;
		secret = isc_mem_get(mctx, secretlen);
		if (secret == NULL) {
			ret = ISC_R_NOMEMORY;
			goto failure;
		}
		isc_buffer_init(&secretbuf, secret, secretlen);
		ret = isc_base64_decodestring(secretstr, &secretbuf);
		if (ret != ISC_R_SUCCESS)
			goto failure;
		secretlen = isc_buffer_usedlength(&secretbuf);

		isc_stdtime_get(&now);
		ret = dns_tsigkey_create(&keyname, alg, secret, secretlen,
					 ISC_FALSE, NULL, now, now,
					 mctx, ring, &tsigkey);
		isc_mem_put(mctx, secret, secretalloc);
		secret = NULL;
		if (ret != ISC_R_SUCCESS)
			goto failure;
		/*
		 * Set digest bits.
		 */
		dst_key_setbits(tsigkey->key, bits);
		dns_tsigkey_detach(&tsigkey);
	}

	return (ISC_R_SUCCESS);

 failure:
	cfg_obj_log(key, ns_g_lctx, ISC_LOG_ERROR,
		    "configuring key '%s': %s", keyid,
		    isc_result_totext(ret));

	if (secret != NULL)
		isc_mem_put(mctx, secret, secretalloc);
	return (ret);
}
Example #20
0
isc_result_t
ns_config_getiplist(const cfg_obj_t *config, const cfg_obj_t *list,
		    in_port_t defport, isc_mem_t *mctx,
		    isc_sockaddr_t **addrsp, isc_dscp_t **dscpsp,
		    isc_uint32_t *countp)
{
	int count, i = 0;
	const cfg_obj_t *addrlist;
	const cfg_obj_t *portobj, *dscpobj;
	const cfg_listelt_t *element;
	isc_sockaddr_t *addrs;
	in_port_t port;
	isc_dscp_t dscp = -1, *dscps = NULL;
	isc_result_t result;

	INSIST(addrsp != NULL && *addrsp == NULL);
	INSIST(dscpsp == NULL || *dscpsp == NULL);
	INSIST(countp != NULL);

	addrlist = cfg_tuple_get(list, "addresses");
	count = ns_config_listcount(addrlist);

	portobj = cfg_tuple_get(list, "port");
	if (cfg_obj_isuint32(portobj)) {
		isc_uint32_t val = cfg_obj_asuint32(portobj);
		if (val > ISC_UINT16_MAX) {
			cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR,
				    "port '%u' out of range", val);
			return (ISC_R_RANGE);
		}
		port = (in_port_t) val;
	} else if (defport != 0)
		port = defport;
	else {
		result = ns_config_getport(config, &port);
		if (result != ISC_R_SUCCESS)
			return (result);
	}

	if (dscpsp != NULL) {
		dscpobj = cfg_tuple_get(list, "dscp");
		if (dscpobj != NULL && cfg_obj_isuint32(dscpobj)) {
			if (cfg_obj_asuint32(dscpobj) > 63) {
				cfg_obj_log(dscpobj, ns_g_lctx, ISC_LOG_ERROR,
					    "dscp value '%u' is out of range",
					    cfg_obj_asuint32(dscpobj));
				return (ISC_R_RANGE);
			}
			dscp = (isc_dscp_t)cfg_obj_asuint32(dscpobj);
		}

		dscps = isc_mem_get(mctx, count * sizeof(isc_dscp_t));
		if (dscps == NULL)
			return (ISC_R_NOMEMORY);
	}

	addrs = isc_mem_get(mctx, count * sizeof(isc_sockaddr_t));
	if (addrs == NULL) {
		if (dscps != NULL)
			isc_mem_put(mctx, dscps, count * sizeof(isc_dscp_t));
		return (ISC_R_NOMEMORY);
	}

	for (element = cfg_list_first(addrlist);
	     element != NULL;
	     element = cfg_list_next(element), i++)
	{
		const cfg_obj_t *addr;
		INSIST(i < count);
		addr = cfg_listelt_value(element);
		addrs[i] = *cfg_obj_assockaddr(addr);
		if (dscpsp != NULL) {
			isc_dscp_t innerdscp;
			innerdscp = cfg_obj_getdscp(addr);
			if (innerdscp == -1)
				innerdscp = dscp;
			dscps[i] = innerdscp;
		}
		if (isc_sockaddr_getport(&addrs[i]) == 0)
			isc_sockaddr_setport(&addrs[i], port);
	}
	INSIST(i == count);

	*addrsp = addrs;
	*countp = count;

	if (dscpsp != NULL)
		*dscpsp = dscps;

	return (ISC_R_SUCCESS);
}
Example #21
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);
}
Example #22
0
isc_result_t
ns_statschannels_configure(ns_server_t *server, const cfg_obj_t *config,
			 cfg_aclconfctx_t *aclconfctx)
{
	ns_statschannel_t *listener, *listener_next;
	ns_statschannellist_t new_listeners;
	const cfg_obj_t *statschannellist = NULL;
	const cfg_listelt_t *element, *element2;
	char socktext[ISC_SOCKADDR_FORMATSIZE];

	RUNTIME_CHECK(isc_once_do(&once, init_desc) == ISC_R_SUCCESS);

	ISC_LIST_INIT(new_listeners);

	/*
	 * Get the list of named.conf 'statistics-channels' statements.
	 */
	(void)cfg_map_get(config, "statistics-channels", &statschannellist);

	/*
	 * Run through the new address/port list, noting sockets that are
	 * already being listened on and moving them to the new list.
	 *
	 * Identifying duplicate addr/port combinations is left to either
	 * the underlying config code, or to the bind attempt getting an
	 * address-in-use error.
	 */
	if (statschannellist != NULL) {
#ifndef HAVE_LIBXML2
		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
			      NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
			      "statistics-channels specified but not effective "
			      "due to missing XML library");
#endif

		for (element = cfg_list_first(statschannellist);
		     element != NULL;
		     element = cfg_list_next(element)) {
			const cfg_obj_t *statschannel;
			const cfg_obj_t *listenercfg = NULL;

			statschannel = cfg_listelt_value(element);
			(void)cfg_map_get(statschannel, "inet",
					  &listenercfg);
			if (listenercfg == NULL)
				continue;

			for (element2 = cfg_list_first(listenercfg);
			     element2 != NULL;
			     element2 = cfg_list_next(element2)) {
				const cfg_obj_t *listen_params;
				const cfg_obj_t *obj;
				isc_sockaddr_t addr;

				listen_params = cfg_listelt_value(element2);

				obj = cfg_tuple_get(listen_params, "address");
				addr = *cfg_obj_assockaddr(obj);
				if (isc_sockaddr_getport(&addr) == 0)
					isc_sockaddr_setport(&addr, NS_STATSCHANNEL_HTTPPORT);

				isc_sockaddr_format(&addr, socktext,
						    sizeof(socktext));

				isc_log_write(ns_g_lctx,
					      NS_LOGCATEGORY_GENERAL,
					      NS_LOGMODULE_SERVER,
					      ISC_LOG_DEBUG(9),
					      "processing statistics "
					      "channel %s",
					      socktext);

				update_listener(server, &listener,
						listen_params, config, &addr,
						aclconfctx, socktext);

				if (listener != NULL) {
					/*
					 * Remove the listener from the old
					 * list, so it won't be shut down.
					 */
					ISC_LIST_UNLINK(server->statschannels,
							listener, link);
				} else {
					/*
					 * This is a new listener.
					 */
					isc_result_t r;

					r = add_listener(server, &listener,
							 listen_params, config,
							 &addr, aclconfctx,
							 socktext);
					if (r != ISC_R_SUCCESS) {
						cfg_obj_log(listen_params,
							    ns_g_lctx,
							    ISC_LOG_WARNING,
							    "couldn't allocate "
							    "statistics channel"
							    " %s: %s",
							    socktext,
							    isc_result_totext(r));
					}
				}

				if (listener != NULL)
					ISC_LIST_APPEND(new_listeners, listener,
							link);
			}
		}
	}

	for (listener = ISC_LIST_HEAD(server->statschannels);
	     listener != NULL;
	     listener = listener_next) {
		listener_next = ISC_LIST_NEXT(listener, link);
		ISC_LIST_UNLINK(server->statschannels, listener, link);
		shutdown_listener(listener);
	}

	ISC_LIST_APPENDLIST(server->statschannels, new_listeners, link);
	return (ISC_R_SUCCESS);
}
Example #23
0
isc_result_t
ns_config_getipandkeylist(const cfg_obj_t *config, const cfg_obj_t *list,
			  isc_mem_t *mctx, isc_sockaddr_t **addrsp,
			  isc_dscp_t **dscpsp, dns_name_t ***keysp,
			  isc_uint32_t *countp)
{
	isc_uint32_t addrcount = 0, dscpcount = 0, keycount = 0, i = 0;
	isc_uint32_t listcount = 0, l = 0, j;
	isc_uint32_t stackcount = 0, pushed = 0;
	isc_result_t result;
	const cfg_listelt_t *element;
	const cfg_obj_t *addrlist;
	const cfg_obj_t *portobj;
	const cfg_obj_t *dscpobj;
	in_port_t port;
	isc_dscp_t dscp = -1;
	dns_fixedname_t fname;
	isc_sockaddr_t *addrs = NULL;
	isc_dscp_t *dscps = NULL;
	dns_name_t **keys = NULL;
	struct { const char *name; } *lists = NULL;
	struct {
		const cfg_listelt_t *element;
		in_port_t port;
		isc_dscp_t dscp;
	} *stack = NULL;

	REQUIRE(addrsp != NULL && *addrsp == NULL);
	REQUIRE(dscpsp != NULL && *dscpsp == NULL);
	REQUIRE(keysp != NULL && *keysp == NULL);
	REQUIRE(countp != NULL);

	/*
	 * Get system defaults.
	 */
	result = ns_config_getport(config, &port);
	if (result != ISC_R_SUCCESS)
		goto cleanup;

	result = ns_config_getdscp(config, &dscp);
	if (result != ISC_R_SUCCESS)
		goto cleanup;

 newlist:
	addrlist = cfg_tuple_get(list, "addresses");
	portobj = cfg_tuple_get(list, "port");
	dscpobj = cfg_tuple_get(list, "dscp");

	if (cfg_obj_isuint32(portobj)) {
		isc_uint32_t val = cfg_obj_asuint32(portobj);
		if (val > ISC_UINT16_MAX) {
			cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR,
				    "port '%u' out of range", val);
			result = ISC_R_RANGE;
			goto cleanup;
		}
		port = (in_port_t) val;
	}

	if (dscpobj != NULL && cfg_obj_isuint32(dscpobj)) {
		if (cfg_obj_asuint32(dscpobj) > 63) {
			cfg_obj_log(dscpobj, ns_g_lctx, ISC_LOG_ERROR,
				    "dscp value '%u' is out of range",
				    cfg_obj_asuint32(dscpobj));
			result = ISC_R_RANGE;
			goto cleanup;
		}
		dscp = (isc_dscp_t)cfg_obj_asuint32(dscpobj);
	}

	result = ISC_R_NOMEMORY;

	element = cfg_list_first(addrlist);
 resume:
	for ( ;
	     element != NULL;
	     element = cfg_list_next(element))
	{
		const cfg_obj_t *addr;
		const cfg_obj_t *key;
		const char *keystr;
		isc_buffer_t b;

		addr = cfg_tuple_get(cfg_listelt_value(element),
				     "masterselement");
		key = cfg_tuple_get(cfg_listelt_value(element), "key");

		if (!cfg_obj_issockaddr(addr)) {
			const char *listname = cfg_obj_asstring(addr);
			isc_result_t tresult;

			/* Grow lists? */
			if (listcount == l) {
				void * tmp;
				isc_uint32_t newlen = listcount + 16;
				size_t newsize, oldsize;

				newsize = newlen * sizeof(*lists);
				oldsize = listcount * sizeof(*lists);
				tmp = isc_mem_get(mctx, newsize);
				if (tmp == NULL)
					goto cleanup;
				if (listcount != 0) {
					memmove(tmp, lists, oldsize);
					isc_mem_put(mctx, lists, oldsize);
				}
				lists = tmp;
				listcount = newlen;
			}
			/* Seen? */
			for (j = 0; j < l; j++)
				if (strcasecmp(lists[j].name, listname) == 0)
					break;
			if (j < l)
				continue;
			tresult = get_masters_def(config, listname, &list);
			if (tresult == ISC_R_NOTFOUND) {
				cfg_obj_log(addr, ns_g_lctx, ISC_LOG_ERROR,
				    "masters \"%s\" not found", listname);

				result = tresult;
				goto cleanup;
			}
			if (tresult != ISC_R_SUCCESS)
				goto cleanup;
			lists[l++].name = listname;
			/* Grow stack? */
			if (stackcount == pushed) {
				void * tmp;
				isc_uint32_t newlen = stackcount + 16;
				size_t newsize, oldsize;

				newsize = newlen * sizeof(*stack);
				oldsize = stackcount * sizeof(*stack);
				tmp = isc_mem_get(mctx, newsize);
				if (tmp == NULL)
					goto cleanup;
				if (stackcount != 0) {
					memmove(tmp, stack, oldsize);
					isc_mem_put(mctx, stack, oldsize);
				}
				stack = tmp;
				stackcount = newlen;
			}
			/*
			 * We want to resume processing this list on the
			 * next element.
			 */
			stack[pushed].element = cfg_list_next(element);
			stack[pushed].port = port;
			stack[pushed].dscp = dscp;
			pushed++;
			goto newlist;
		}

		if (i == addrcount) {
			void * tmp;
			isc_uint32_t newlen = addrcount + 16;
			size_t newsize, oldsize;

			newsize = newlen * sizeof(isc_sockaddr_t);
			oldsize = addrcount * sizeof(isc_sockaddr_t);
			tmp = isc_mem_get(mctx, newsize);
			if (tmp == NULL)
				goto cleanup;
			if (addrcount != 0) {
				memmove(tmp, addrs, oldsize);
				isc_mem_put(mctx, addrs, oldsize);
			}
			addrs = tmp;
			addrcount = newlen;

			newsize = newlen * sizeof(isc_dscp_t);
			oldsize = dscpcount * sizeof(isc_dscp_t);
			tmp = isc_mem_get(mctx, newsize);
			if (tmp == NULL)
				goto cleanup;
			if (dscpcount != 0) {
				memmove(tmp, dscps, oldsize);
				isc_mem_put(mctx, dscps, oldsize);
			}
			dscps = tmp;
			dscpcount = newlen;

			newsize = newlen * sizeof(dns_name_t *);
			oldsize = keycount * sizeof(dns_name_t *);
			tmp = isc_mem_get(mctx, newsize);
			if (tmp == NULL)
				goto cleanup;
			if (keycount != 0) {
				memmove(tmp, keys, oldsize);
				isc_mem_put(mctx, keys, oldsize);
			}
			keys = tmp;
			keycount = newlen;
		}

		addrs[i] = *cfg_obj_assockaddr(addr);
		if (isc_sockaddr_getport(&addrs[i]) == 0)
			isc_sockaddr_setport(&addrs[i], port);
		dscps[i] = cfg_obj_getdscp(addr);
		if (dscps[i] == -1)
			dscps[i] = dscp;
		keys[i] = NULL;
		i++;	/* Increment here so that cleanup on error works. */
		if (!cfg_obj_isstring(key))
			continue;
		keys[i - 1] = isc_mem_get(mctx, sizeof(dns_name_t));
		if (keys[i - 1] == NULL)
			goto cleanup;
		dns_name_init(keys[i - 1], NULL);

		keystr = cfg_obj_asstring(key);
		isc_buffer_constinit(&b, keystr, strlen(keystr));
		isc_buffer_add(&b, strlen(keystr));
		dns_fixedname_init(&fname);
		result = dns_name_fromtext(dns_fixedname_name(&fname), &b,
					   dns_rootname, 0, NULL);
		if (result != ISC_R_SUCCESS)
			goto cleanup;
		result = dns_name_dup(dns_fixedname_name(&fname), mctx,
				      keys[i - 1]);
		if (result != ISC_R_SUCCESS)
			goto cleanup;
	}
	if (pushed != 0) {
		pushed--;
		element = stack[pushed].element;
		port = stack[pushed].port;
		dscp = stack[pushed].dscp;
		goto resume;
	}
	if (i < addrcount) {
		void * tmp;
		size_t newsize, oldsize;

		newsize = i * sizeof(isc_sockaddr_t);
		oldsize = addrcount * sizeof(isc_sockaddr_t);
		if (i != 0) {
			tmp = isc_mem_get(mctx, newsize);
			if (tmp == NULL)
				goto cleanup;
			memmove(tmp, addrs, newsize);
		} else
			tmp = NULL;
		isc_mem_put(mctx, addrs, oldsize);
		addrs = tmp;
		addrcount = i;

		newsize = i * sizeof(isc_dscp_t);
		oldsize = dscpcount * sizeof(isc_dscp_t);
		if (i != 0) {
			tmp = isc_mem_get(mctx, newsize);
			if (tmp == NULL)
				goto cleanup;
			memmove(tmp, dscps, newsize);
		} else
			tmp = NULL;
		isc_mem_put(mctx, dscps, oldsize);
		dscps = tmp;
		dscpcount = i;

		newsize = i * sizeof(dns_name_t *);
		oldsize = keycount * sizeof(dns_name_t *);
		if (i != 0) {
			tmp = isc_mem_get(mctx, newsize);
			if (tmp == NULL)
				goto cleanup;
			memmove(tmp, keys,  newsize);
		} else
			tmp = NULL;
		isc_mem_put(mctx, keys, oldsize);
		keys = tmp;
		keycount = i;
	}

	if (lists != NULL)
		isc_mem_put(mctx, lists, listcount * sizeof(*lists));
	if (stack != NULL)
		isc_mem_put(mctx, stack, stackcount * sizeof(*stack));

	INSIST(keycount == addrcount);

	*addrsp = addrs;
	*dscpsp = dscps;
	*keysp = keys;
	*countp = addrcount;

	return (ISC_R_SUCCESS);

 cleanup:
	if (addrs != NULL)
		isc_mem_put(mctx, addrs, addrcount * sizeof(isc_sockaddr_t));
	if (dscps != NULL)
		isc_mem_put(mctx, dscps, dscpcount * sizeof(isc_dscp_t));
	if (keys != NULL) {
		for (j = 0; j < i; j++) {
			if (keys[j] == NULL)
				continue;
			if (dns_name_dynamic(keys[j]))
				dns_name_free(keys[j], mctx);
			isc_mem_put(mctx, keys[j], sizeof(dns_name_t));
		}
		isc_mem_put(mctx, keys, keycount * sizeof(dns_name_t *));
	}
	if (lists != NULL)
		isc_mem_put(mctx, lists, listcount * sizeof(*lists));
	if (stack != NULL)
		isc_mem_put(mctx, stack, stackcount * sizeof(*stack));
	return (result);
}
Example #24
0
static isc_result_t
configure_dnsseckeys(irs_dnsconf_t *conf, cfg_obj_t *cfgobj,
		     dns_rdataclass_t rdclass)
{
	isc_mem_t *mctx = conf->mctx;
	const cfg_obj_t *keys = NULL;
	const cfg_obj_t *key, *keylist;
	dns_fixedname_t fkeyname;
	dns_name_t *keyname_base, *keyname;
	const cfg_listelt_t *element, *element2;
	isc_result_t result;
	isc_uint32_t flags, proto, alg;
	const char *keystr, *keynamestr;
	unsigned char keydata[4096];
	isc_buffer_t keydatabuf_base, *keydatabuf;
	dns_rdata_dnskey_t keystruct;
	unsigned char rrdata[4096];
	isc_buffer_t rrdatabuf;
	isc_region_t r;
	isc_buffer_t namebuf;
	irs_dnsconf_dnskey_t *keyent;

	cfg_map_get(cfgobj, "trusted-keys", &keys);
	if (keys == NULL)
		return (ISC_R_SUCCESS);

	for (element = cfg_list_first(keys);
	     element != NULL;
	     element = cfg_list_next(element)) {
		keylist = cfg_listelt_value(element);
		for (element2 = cfg_list_first(keylist);
		     element2 != NULL;
		     element2 = cfg_list_next(element2))
		{
			keydatabuf = NULL;
			keyname = NULL;

			key = cfg_listelt_value(element2);

			flags = cfg_obj_asuint32(cfg_tuple_get(key, "flags"));
			proto = cfg_obj_asuint32(cfg_tuple_get(key,
							       "protocol"));
			alg = cfg_obj_asuint32(cfg_tuple_get(key,
							     "algorithm"));
			keynamestr = cfg_obj_asstring(cfg_tuple_get(key,
								    "name"));

			keystruct.common.rdclass = rdclass;
			keystruct.common.rdtype = dns_rdatatype_dnskey;
			keystruct.mctx = NULL;
			ISC_LINK_INIT(&keystruct.common, link);

			if (flags > 0xffff)
				return (ISC_R_RANGE);
			if (proto > 0xff)
				return (ISC_R_RANGE);
			if (alg > 0xff)
				return (ISC_R_RANGE);
			keystruct.flags = (isc_uint16_t)flags;
			keystruct.protocol = (isc_uint8_t)proto;
			keystruct.algorithm = (isc_uint8_t)alg;

			isc_buffer_init(&keydatabuf_base, keydata,
					sizeof(keydata));
			isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata));

			/* Configure key value */
			keystr = cfg_obj_asstring(cfg_tuple_get(key, "key"));
			result = isc_base64_decodestring(keystr,
							 &keydatabuf_base);
			if (result != ISC_R_SUCCESS)
				return (result);
			isc_buffer_usedregion(&keydatabuf_base, &r);
			keystruct.datalen = r.length;
			keystruct.data = r.base;

			result = dns_rdata_fromstruct(NULL,
						      keystruct.common.rdclass,
						      keystruct.common.rdtype,
						      &keystruct, &rrdatabuf);
			if (result != ISC_R_SUCCESS)
				return (result);
			isc_buffer_usedregion(&rrdatabuf, &r);
			result = isc_buffer_allocate(mctx, &keydatabuf,
						     r.length);
			if (result != ISC_R_SUCCESS)
				return (result);
			result = isc_buffer_copyregion(keydatabuf, &r);
			if (result != ISC_R_SUCCESS)
				goto cleanup;

			/* Configure key name */
			dns_fixedname_init(&fkeyname);
			keyname_base = dns_fixedname_name(&fkeyname);
			isc_buffer_constinit(&namebuf, keynamestr,
					     strlen(keynamestr));
			isc_buffer_add(&namebuf, strlen(keynamestr));
			result = dns_name_fromtext(keyname_base, &namebuf,
						   dns_rootname, 0, NULL);
			if (result != ISC_R_SUCCESS)
				return (result);
			keyname = isc_mem_get(mctx, sizeof(*keyname));
			if (keyname == NULL) {
				result = ISC_R_NOMEMORY;
				goto cleanup;
			}
			dns_name_init(keyname, NULL);
			result = dns_name_dup(keyname_base, mctx, keyname);
			if (result != ISC_R_SUCCESS)
				goto cleanup;

			/* Add the key data to the list */
			keyent = isc_mem_get(mctx, sizeof(*keyent));
			if (keyent == NULL) {
				dns_name_free(keyname, mctx);
				result = ISC_R_NOMEMORY;
				goto cleanup;
			}
			keyent->keyname = keyname;
			keyent->keydatabuf = keydatabuf;

			ISC_LIST_APPEND(conf->trusted_keylist, keyent, link);
		}
	}

	return (ISC_R_SUCCESS);

 cleanup:
	if (keydatabuf != NULL)
		isc_buffer_free(&keydatabuf);
	if (keyname != NULL)
		isc_mem_put(mctx, keyname, sizeof(*keyname));

	return (result);
}
Example #25
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);
}
Example #26
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;
	cfg_obj_t *defkey = NULL;
	cfg_obj_t *options = NULL;
	cfg_obj_t *servers = NULL;
	cfg_obj_t *server = NULL;
	cfg_obj_t *keys = NULL;
	cfg_obj_t *key = NULL;
	cfg_obj_t *defport = NULL;
	cfg_obj_t *secretobj = NULL;
	cfg_obj_t *algorithmobj = NULL;
	cfg_obj_t *config = NULL;
	cfg_listelt_t *elt;
	const char *secretstr;
	const char *algorithm;
	static char secretarray[1024];
	const cfg_type_t *conftype = &cfg_type_rndcconf;
	isc_boolean_t key_only = ISC_FALSE;

	if (! isc_file_exists(conffile)) {
		conffile = admin_keyfile;
		conftype = &cfg_type_rndckey;

		if (! isc_file_exists(conffile))
			fatal("neither %s nor %s was found",
			      admin_conffile, admin_keyfile);
		key_only = ISC_TRUE;
	}

	DO("create parser", cfg_parser_create(mctx, log, pctxp));

	/*
	 * The parser will output its own errors, so DO() is not used.
	 */
	result = cfg_parse_file(*pctxp, conffile, conftype, &config);
	if (result != ISC_R_SUCCESS)
		fatal("could not load rndc configuration");

	if (!key_only)
		(void)cfg_map_get(config, "options", &options);

	if (key_only && servername == NULL)
		servername = "127.0.0.1";
	else if (servername == NULL && options != NULL) {
		cfg_obj_t *defserverobj = NULL;
		(void)cfg_map_get(options, "default-server", &defserverobj);
		if (defserverobj != NULL)
			servername = cfg_obj_asstring(defserverobj);
	}

	if (servername == NULL)
		fatal("no server specified and no default");

	if (!key_only) {
		(void)cfg_map_get(config, "server", &servers);
		if (servers != NULL) {
			for (elt = cfg_list_first(servers);
			     elt != NULL; 
			     elt = cfg_list_next(elt))
			{
				const char *name;
				server = cfg_listelt_value(elt);
				name = cfg_obj_asstring(cfg_map_getname(server));
				if (strcasecmp(name, servername) == 0)
					break;
				server = NULL;
			}
		}
	}

	/*
	 * Look for the name of the key to use.
	 */
	if (keyname != NULL)
		;		/* Was set on command line, do nothing. */
	else if (server != NULL) {
		DO("get key for server", cfg_map_get(server, "key", &defkey));
		keyname = cfg_obj_asstring(defkey);
	} else if (options != NULL) {
		DO("get default key", cfg_map_get(options, "default-key",
						  &defkey));
		keyname = cfg_obj_asstring(defkey);
	} else if (!key_only)
		fatal("no key for server and no default");

	/*
	 * Get the key's definition.
	 */
	if (key_only)
		DO("get key", cfg_map_get(config, "key", &key));
	else {
		DO("get config key list", cfg_map_get(config, "key", &keys));
		for (elt = cfg_list_first(keys);
		     elt != NULL; 
		     elt = cfg_list_next(elt))
		{
			key = cfg_listelt_value(elt);
			if (strcasecmp(cfg_obj_asstring(cfg_map_getname(key)),
				       keyname) == 0)
				break;
		}
		if (elt == NULL)
			fatal("no key definition for name %s", keyname);
	}
	(void)cfg_map_get(key, "secret", &secretobj);
	(void)cfg_map_get(key, "algorithm", &algorithmobj);
	if (secretobj == NULL || algorithmobj == NULL)
		fatal("key must have algorithm and secret");

	secretstr = cfg_obj_asstring(secretobj);
	algorithm = cfg_obj_asstring(algorithmobj);

	if (strcasecmp(algorithm, "hmac-md5") != 0)
		fatal("unsupported algorithm: %s", algorithm);

	secret.rstart = (unsigned char *)secretarray;
	secret.rend = (unsigned char *)secretarray + sizeof(secretarray);
	DO("decode base64 secret", isccc_base64_decode(secretstr, &secret));
	secret.rend = secret.rstart;
	secret.rstart = (unsigned char *)secretarray;

	/*
	 * Find the port to connect to.
	 */
	if (remoteport != 0)
		;		/* Was set on command line, do nothing. */
	else {
		if (server != NULL)
			(void)cfg_map_get(server, "port", &defport);
		if (defport == NULL && options != NULL)
			(void)cfg_map_get(options, "default-port", &defport);
	}
	if (defport != NULL) {
		remoteport = cfg_obj_asuint32(defport);
		if (remoteport > 65535 || remoteport == 0)
			fatal("port %d out of range", remoteport);
	} else if (remoteport == 0)
		remoteport = NS_CONTROL_PORT;

	*configp = config;
}
Example #27
0
/*%
 * Configure an apex NS with glues for a static-stub zone.
 * For example, for the zone named "example.com", the following RRs will be
 * added to the zone DB:
 * example.com. NS example.com.
 * example.com. A 192.0.2.1
 * example.com. AAAA 2001:db8::1
 */
static isc_result_t
configure_staticstub_serveraddrs(const cfg_obj_t *zconfig, dns_zone_t *zone,
				 dns_rdatalist_t *rdatalist_ns,
				 dns_rdatalist_t *rdatalist_a,
				 dns_rdatalist_t *rdatalist_aaaa)
{
	const cfg_listelt_t *element;
	isc_mem_t *mctx = dns_zone_getmctx(zone);
	isc_region_t region, sregion;
	dns_rdata_t *rdata;
	isc_result_t result = ISC_R_SUCCESS;

	for (element = cfg_list_first(zconfig);
	     element != NULL;
	     element = cfg_list_next(element))
	{
		const isc_sockaddr_t* sa;
		isc_netaddr_t na;
		const cfg_obj_t *address = cfg_listelt_value(element);
		dns_rdatalist_t *rdatalist;

		sa = cfg_obj_assockaddr(address);
		if (isc_sockaddr_getport(sa) != 0) {
			cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR,
				    "port is not configurable for "
				    "static stub server-addresses");
			return (ISC_R_FAILURE);
		}
		isc_netaddr_fromsockaddr(&na, sa);
		if (isc_netaddr_getzone(&na) != 0) {
			cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR,
					    "scoped address is not allowed "
					    "for static stub "
					    "server-addresses");
			return (ISC_R_FAILURE);
		}

		switch (na.family) {
		case AF_INET:
			region.length = sizeof(na.type.in);
			rdatalist = rdatalist_a;
			break;
		default:
			INSIST(na.family == AF_INET6);
			region.length = sizeof(na.type.in6);
			rdatalist = rdatalist_aaaa;
			break;
		}

		rdata = isc_mem_get(mctx, sizeof(*rdata) + region.length);
		if (rdata == NULL)
			return (ISC_R_NOMEMORY);
		region.base = (unsigned char *)(rdata + 1);
		memcpy(region.base, &na.type, region.length);
		dns_rdata_init(rdata);
		dns_rdata_fromregion(rdata, dns_zone_getclass(zone),
				     rdatalist->type, &region);
		ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
	}

	/*
	 * If no address is specified (unlikely in this context, but possible),
	 * there's nothing to do anymore.
	 */
	if (ISC_LIST_EMPTY(rdatalist_a->rdata) &&
	    ISC_LIST_EMPTY(rdatalist_aaaa->rdata)) {
		return (ISC_R_SUCCESS);
	}

	/* Add to the list an apex NS with the ns name being the origin name */
	dns_name_toregion(dns_zone_getorigin(zone), &sregion);
	rdata = isc_mem_get(mctx, sizeof(*rdata) + sregion.length);
	if (rdata == NULL) {
		/*
		 * Already allocated data will be freed in the caller, so
		 * we can simply return here.
		 */
		return (ISC_R_NOMEMORY);
	}
	region.length = sregion.length;
	region.base = (unsigned char *)(rdata + 1);
	memcpy(region.base, sregion.base, region.length);
	dns_rdata_init(rdata);
	dns_rdata_fromregion(rdata, dns_zone_getclass(zone),
			     dns_rdatatype_ns, &region);
	ISC_LIST_APPEND(rdatalist_ns->rdata, rdata, link);

	return (result);
}
Example #28
0
File: rndc.c Project: OPSF/uClinux
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;
}
Example #29
0
isc_result_t
ns_lwresd_configure(isc_mem_t *mctx, const cfg_obj_t *config) {
	const cfg_obj_t *lwreslist = NULL;
	const cfg_obj_t *lwres = NULL;
	const cfg_obj_t *listenerslist = NULL;
	const cfg_listelt_t *element = NULL;
	ns_lwreslistener_t *listener;
	ns_lwreslistenerlist_t newlisteners;
	isc_result_t result;
	char socktext[ISC_SOCKADDR_FORMATSIZE];
	isc_sockaddr_t *addrs = NULL;
	ns_lwresd_t *lwresd = NULL;
	isc_uint32_t count = 0;

	REQUIRE(mctx != NULL);
	REQUIRE(config != NULL);

	RUNTIME_CHECK(isc_once_do(&once, initialize_mutex) == ISC_R_SUCCESS);

	ISC_LIST_INIT(newlisteners);

	result = cfg_map_get(config, "lwres", &lwreslist);
	if (result != ISC_R_SUCCESS)
		return (ISC_R_SUCCESS);

	LOCK(&listeners_lock);
	/*
	 * Run through the new lwres address list, noting sockets that
	 * are already being listened on and moving them to the new list.
	 *
	 * Identifying duplicates addr/port combinations is left to either
	 * the underlying config code, or to the bind attempt getting an
	 * address-in-use error.
	 */
	for (element = cfg_list_first(lwreslist);
	     element != NULL;
	     element = cfg_list_next(element))
	{
		in_port_t port;

		lwres = cfg_listelt_value(element);
		CHECK(ns_lwdmanager_create(mctx, lwres, &lwresd));

		port = lwresd_g_listenport;
		if (port == 0)
			port = LWRES_UDP_PORT;

		listenerslist = NULL;
		(void)cfg_map_get(lwres, "listen-on", &listenerslist);
		if (listenerslist == NULL) {
			struct in_addr localhost;
			isc_sockaddr_t address;

			localhost.s_addr = htonl(INADDR_LOOPBACK);
			isc_sockaddr_fromin(&address, &localhost, port);
			CHECK(configure_listener(&address, lwresd, mctx,
						 &newlisteners));
		} else {
			isc_uint32_t i;

			CHECK(ns_config_getiplist(config, listenerslist,
						  port, mctx, &addrs, &count));
			for (i = 0; i < count; i++)
				CHECK(configure_listener(&addrs[i], lwresd,
							 mctx, &newlisteners));
			ns_config_putiplist(mctx, &addrs, count);
		}
		ns_lwdmanager_detach(&lwresd);
	}

	/*
	 * Shutdown everything on the listeners list, and remove them from
	 * the list.  Then put all of the new listeners on it.
	 */

	while (!ISC_LIST_EMPTY(listeners)) {
		listener = ISC_LIST_HEAD(listeners);
		ISC_LIST_UNLINK(listeners, listener, link);

		isc_sockaddr_format(&listener->address,
				    socktext, sizeof(socktext));

		listener_shutdown(listener);
		ns_lwreslistener_detach(&listener);

		isc_log_write(ns_g_lctx, ISC_LOGCATEGORY_GENERAL,
			      NS_LOGMODULE_LWRESD, ISC_LOG_NOTICE,
			      "lwres no longer listening on %s", socktext);
	}

 cleanup:
	ISC_LIST_APPENDLIST(listeners, newlisteners, link);

	if (addrs != NULL)
		ns_config_putiplist(mctx, &addrs, count);

	if (lwresd != NULL)
		ns_lwdmanager_detach(&lwresd);

	UNLOCK(&listeners_lock);

	return (result);
}
Example #30
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);
}