PageRenderTime 28ms CodeModel.GetById 11ms app.highlight 14ms RepoModel.GetById 1ms app.codeStats 0ms

/contrib/bind9/lib/irs/dnsconf.c

https://bitbucket.org/freebsd/freebsd-head/
C | 269 lines | 195 code | 47 blank | 27 comment | 48 complexity | 5b6cfb290e6cba9fa53abdceb712491b MD5 | raw file
  1/*
  2 * Copyright (C) 2009  Internet Systems Consortium, Inc. ("ISC")
  3 *
  4 * Permission to use, copy, modify, and/or distribute this software for any
  5 * purpose with or without fee is hereby granted, provided that the above
  6 * copyright notice and this permission notice appear in all copies.
  7 *
  8 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
 10 * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
 11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
 13 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 14 * PERFORMANCE OF THIS SOFTWARE.
 15 */
 16
 17/* $Id: dnsconf.c,v 1.3 2009/09/02 23:48:02 tbox Exp $ */
 18
 19/*! \file */
 20
 21#include <config.h>
 22
 23#include <string.h>
 24
 25#include <isc/base64.h>
 26#include <isc/buffer.h>
 27#include <isc/file.h>
 28#include <isc/mem.h>
 29#include <isc/util.h>
 30
 31#include <isccfg/dnsconf.h>
 32
 33#include <dns/fixedname.h>
 34#include <dns/name.h>
 35#include <dns/rdata.h>
 36#include <dns/rdatastruct.h>
 37
 38#include <irs/dnsconf.h>
 39
 40#define IRS_DNSCONF_MAGIC		ISC_MAGIC('D', 'c', 'f', 'g')
 41#define IRS_DNSCONF_VALID(c)		ISC_MAGIC_VALID(c, IRS_DNSCONF_MAGIC)
 42
 43/*!
 44 * configuration data structure
 45 */
 46
 47struct irs_dnsconf {
 48	unsigned int magic;
 49	isc_mem_t *mctx;
 50	irs_dnsconf_dnskeylist_t trusted_keylist;
 51};
 52
 53static isc_result_t
 54configure_dnsseckeys(irs_dnsconf_t *conf, cfg_obj_t *cfgobj,
 55		     dns_rdataclass_t rdclass)
 56{
 57	isc_mem_t *mctx = conf->mctx;
 58	const cfg_obj_t *keys = NULL;
 59	const cfg_obj_t *key, *keylist;
 60	dns_fixedname_t fkeyname;
 61	dns_name_t *keyname_base, *keyname;
 62	const cfg_listelt_t *element, *element2;
 63	isc_result_t result;
 64	isc_uint32_t flags, proto, alg;
 65	const char *keystr, *keynamestr;
 66	unsigned char keydata[4096];
 67	isc_buffer_t keydatabuf_base, *keydatabuf;
 68	dns_rdata_dnskey_t keystruct;
 69	unsigned char rrdata[4096];
 70	isc_buffer_t rrdatabuf;
 71	isc_region_t r;
 72	isc_buffer_t namebuf;
 73	irs_dnsconf_dnskey_t *keyent;
 74
 75	cfg_map_get(cfgobj, "trusted-keys", &keys);
 76	if (keys == NULL)
 77		return (ISC_R_SUCCESS);
 78
 79	for (element = cfg_list_first(keys);
 80	     element != NULL;
 81	     element = cfg_list_next(element)) {
 82		keylist = cfg_listelt_value(element);
 83		for (element2 = cfg_list_first(keylist);
 84		     element2 != NULL;
 85		     element2 = cfg_list_next(element2))
 86		{
 87			keydatabuf = NULL;
 88			keyname = NULL;
 89
 90			key = cfg_listelt_value(element2);
 91
 92			flags = cfg_obj_asuint32(cfg_tuple_get(key, "flags"));
 93			proto = cfg_obj_asuint32(cfg_tuple_get(key,
 94							       "protocol"));
 95			alg = cfg_obj_asuint32(cfg_tuple_get(key,
 96							     "algorithm"));
 97			keynamestr = cfg_obj_asstring(cfg_tuple_get(key,
 98								    "name"));
 99
100			keystruct.common.rdclass = rdclass;
101			keystruct.common.rdtype = dns_rdatatype_dnskey;
102			keystruct.mctx = NULL;
103			ISC_LINK_INIT(&keystruct.common, link);
104
105			if (flags > 0xffff)
106				return (ISC_R_RANGE);
107			if (proto > 0xff)
108				return (ISC_R_RANGE);
109			if (alg > 0xff)
110				return (ISC_R_RANGE);
111			keystruct.flags = (isc_uint16_t)flags;
112			keystruct.protocol = (isc_uint8_t)proto;
113			keystruct.algorithm = (isc_uint8_t)alg;
114
115			isc_buffer_init(&keydatabuf_base, keydata,
116					sizeof(keydata));
117			isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata));
118
119			/* Configure key value */
120			keystr = cfg_obj_asstring(cfg_tuple_get(key, "key"));
121			result = isc_base64_decodestring(keystr,
122							 &keydatabuf_base);
123			if (result != ISC_R_SUCCESS)
124				return (result);
125			isc_buffer_usedregion(&keydatabuf_base, &r);
126			keystruct.datalen = r.length;
127			keystruct.data = r.base;
128
129			result = dns_rdata_fromstruct(NULL,
130						      keystruct.common.rdclass,
131						      keystruct.common.rdtype,
132						      &keystruct, &rrdatabuf);
133			if (result != ISC_R_SUCCESS)
134				return (result);
135			isc_buffer_usedregion(&rrdatabuf, &r);
136			result = isc_buffer_allocate(mctx, &keydatabuf,
137						     r.length);
138			if (result != ISC_R_SUCCESS)
139				return (result);
140			result = isc_buffer_copyregion(keydatabuf, &r);
141			if (result != ISC_R_SUCCESS)
142				goto cleanup;
143
144			/* Configure key name */
145			dns_fixedname_init(&fkeyname);
146			keyname_base = dns_fixedname_name(&fkeyname);
147			isc_buffer_init(&namebuf, keynamestr,
148					strlen(keynamestr));
149			isc_buffer_add(&namebuf, strlen(keynamestr));
150			result = dns_name_fromtext(keyname_base, &namebuf,
151						   dns_rootname, 0, NULL);
152			if (result != ISC_R_SUCCESS)
153				return (result);
154			keyname = isc_mem_get(mctx, sizeof(*keyname));
155			if (keyname == NULL) {
156				result = ISC_R_NOMEMORY;
157				goto cleanup;
158			}
159			dns_name_init(keyname, NULL);
160			result = dns_name_dup(keyname_base, mctx, keyname);
161			if (result != ISC_R_SUCCESS)
162				goto cleanup;
163
164			/* Add the key data to the list */
165			keyent = isc_mem_get(mctx, sizeof(*keyent));
166			if (keyent == NULL) {
167				dns_name_free(keyname, mctx);
168				result = ISC_R_NOMEMORY;
169				goto cleanup;
170			}
171			keyent->keyname = keyname;
172			keyent->keydatabuf = keydatabuf;
173
174			ISC_LIST_APPEND(conf->trusted_keylist, keyent, link);
175		}
176	}
177
178	return (ISC_R_SUCCESS);
179
180 cleanup:
181	if (keydatabuf != NULL)
182		isc_buffer_free(&keydatabuf);
183	if (keyname != NULL)
184		isc_mem_put(mctx, keyname, sizeof(*keyname));
185
186	return (result);
187}
188
189isc_result_t
190irs_dnsconf_load(isc_mem_t *mctx, const char *filename, irs_dnsconf_t **confp)
191{
192	irs_dnsconf_t *conf;
193	cfg_parser_t *parser = NULL;
194	cfg_obj_t *cfgobj = NULL;
195	isc_result_t result = ISC_R_SUCCESS;
196
197	REQUIRE(confp != NULL && *confp == NULL);
198
199	conf = isc_mem_get(mctx, sizeof(*conf));
200	if (conf == NULL)
201		return (ISC_R_NOMEMORY);
202
203	conf->mctx = mctx;
204	ISC_LIST_INIT(conf->trusted_keylist);
205
206	/*
207	 * If the specified file does not exist, we'll simply with an empty
208	 * configuration.
209	 */
210	if (!isc_file_exists(filename))
211		goto cleanup;
212
213	result = cfg_parser_create(mctx, NULL, &parser);
214	if (result != ISC_R_SUCCESS)
215		goto cleanup;
216
217	result = cfg_parse_file(parser, filename, &cfg_type_dnsconf,
218				&cfgobj);
219	if (result != ISC_R_SUCCESS)
220		goto cleanup;
221
222	result = configure_dnsseckeys(conf, cfgobj, dns_rdataclass_in);
223
224 cleanup:
225	if (parser != NULL) {
226		if (cfgobj != NULL)
227			cfg_obj_destroy(parser, &cfgobj);
228		cfg_parser_destroy(&parser);
229	}
230
231	conf->magic = IRS_DNSCONF_MAGIC;
232
233	if (result == ISC_R_SUCCESS)
234		*confp = conf;
235	else
236		irs_dnsconf_destroy(&conf);
237
238	return (result);
239}
240
241void
242irs_dnsconf_destroy(irs_dnsconf_t **confp) {
243	irs_dnsconf_t *conf;
244	irs_dnsconf_dnskey_t *keyent;
245
246	REQUIRE(confp != NULL);
247	conf = *confp;
248	REQUIRE(IRS_DNSCONF_VALID(conf));
249
250	while ((keyent = ISC_LIST_HEAD(conf->trusted_keylist)) != NULL) {
251		ISC_LIST_UNLINK(conf->trusted_keylist, keyent, link);
252
253		isc_buffer_free(&keyent->keydatabuf);
254		dns_name_free(keyent->keyname, conf->mctx);
255		isc_mem_put(conf->mctx, keyent->keyname, sizeof(dns_name_t));
256		isc_mem_put(conf->mctx, keyent, sizeof(*keyent));
257	}
258
259	isc_mem_put(conf->mctx, conf, sizeof(*conf));
260
261	*confp = NULL;
262}
263
264irs_dnsconf_dnskeylist_t *
265irs_dnsconf_gettrustedkeys(irs_dnsconf_t *conf) {
266	REQUIRE(IRS_DNSCONF_VALID(conf));
267
268	return (&conf->trusted_keylist);
269}