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