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