]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/bind9/lib/irs/dnsconf.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / contrib / bind9 / lib / irs / dnsconf.c
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
47 struct irs_dnsconf {
48         unsigned int magic;
49         isc_mem_t *mctx;
50         irs_dnsconf_dnskeylist_t trusted_keylist;
51 };
52
53 static isc_result_t
54 configure_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
189 isc_result_t
190 irs_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
241 void
242 irs_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
264 irs_dnsconf_dnskeylist_t *
265 irs_dnsconf_gettrustedkeys(irs_dnsconf_t *conf) {
266         REQUIRE(IRS_DNSCONF_VALID(conf));
267
268         return (&conf->trusted_keylist);
269 }