/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. /* $Id: dnsconf.c,v 1.3 2009/09/02 23:48:02 tbox Exp $ */
  17. /*! \file */
  18. #include <config.h>
  19. #include <string.h>
  20. #include <isc/base64.h>
  21. #include <isc/buffer.h>
  22. #include <isc/file.h>
  23. #include <isc/mem.h>
  24. #include <isc/util.h>
  25. #include <isccfg/dnsconf.h>
  26. #include <dns/fixedname.h>
  27. #include <dns/name.h>
  28. #include <dns/rdata.h>
  29. #include <dns/rdatastruct.h>
  30. #include <irs/dnsconf.h>
  31. #define IRS_DNSCONF_MAGIC ISC_MAGIC('D', 'c', 'f', 'g')
  32. #define IRS_DNSCONF_VALID(c) ISC_MAGIC_VALID(c, IRS_DNSCONF_MAGIC)
  33. /*!
  34. * configuration data structure
  35. */
  36. struct irs_dnsconf {
  37. unsigned int magic;
  38. isc_mem_t *mctx;
  39. irs_dnsconf_dnskeylist_t trusted_keylist;
  40. };
  41. static isc_result_t
  42. configure_dnsseckeys(irs_dnsconf_t *conf, cfg_obj_t *cfgobj,
  43. dns_rdataclass_t rdclass)
  44. {
  45. isc_mem_t *mctx = conf->mctx;
  46. const cfg_obj_t *keys = NULL;
  47. const cfg_obj_t *key, *keylist;
  48. dns_fixedname_t fkeyname;
  49. dns_name_t *keyname_base, *keyname;
  50. const cfg_listelt_t *element, *element2;
  51. isc_result_t result;
  52. isc_uint32_t flags, proto, alg;
  53. const char *keystr, *keynamestr;
  54. unsigned char keydata[4096];
  55. isc_buffer_t keydatabuf_base, *keydatabuf;
  56. dns_rdata_dnskey_t keystruct;
  57. unsigned char rrdata[4096];
  58. isc_buffer_t rrdatabuf;
  59. isc_region_t r;
  60. isc_buffer_t namebuf;
  61. irs_dnsconf_dnskey_t *keyent;
  62. cfg_map_get(cfgobj, "trusted-keys", &keys);
  63. if (keys == NULL)
  64. return (ISC_R_SUCCESS);
  65. for (element = cfg_list_first(keys);
  66. element != NULL;
  67. element = cfg_list_next(element)) {
  68. keylist = cfg_listelt_value(element);
  69. for (element2 = cfg_list_first(keylist);
  70. element2 != NULL;
  71. element2 = cfg_list_next(element2))
  72. {
  73. keydatabuf = NULL;
  74. keyname = NULL;
  75. key = cfg_listelt_value(element2);
  76. flags = cfg_obj_asuint32(cfg_tuple_get(key, "flags"));
  77. proto = cfg_obj_asuint32(cfg_tuple_get(key,
  78. "protocol"));
  79. alg = cfg_obj_asuint32(cfg_tuple_get(key,
  80. "algorithm"));
  81. keynamestr = cfg_obj_asstring(cfg_tuple_get(key,
  82. "name"));
  83. keystruct.common.rdclass = rdclass;
  84. keystruct.common.rdtype = dns_rdatatype_dnskey;
  85. keystruct.mctx = NULL;
  86. ISC_LINK_INIT(&keystruct.common, link);
  87. if (flags > 0xffff)
  88. return (ISC_R_RANGE);
  89. if (proto > 0xff)
  90. return (ISC_R_RANGE);
  91. if (alg > 0xff)
  92. return (ISC_R_RANGE);
  93. keystruct.flags = (isc_uint16_t)flags;
  94. keystruct.protocol = (isc_uint8_t)proto;
  95. keystruct.algorithm = (isc_uint8_t)alg;
  96. isc_buffer_init(&keydatabuf_base, keydata,
  97. sizeof(keydata));
  98. isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata));
  99. /* Configure key value */
  100. keystr = cfg_obj_asstring(cfg_tuple_get(key, "key"));
  101. result = isc_base64_decodestring(keystr,
  102. &keydatabuf_base);
  103. if (result != ISC_R_SUCCESS)
  104. return (result);
  105. isc_buffer_usedregion(&keydatabuf_base, &r);
  106. keystruct.datalen = r.length;
  107. keystruct.data = r.base;
  108. result = dns_rdata_fromstruct(NULL,
  109. keystruct.common.rdclass,
  110. keystruct.common.rdtype,
  111. &keystruct, &rrdatabuf);
  112. if (result != ISC_R_SUCCESS)
  113. return (result);
  114. isc_buffer_usedregion(&rrdatabuf, &r);
  115. result = isc_buffer_allocate(mctx, &keydatabuf,
  116. r.length);
  117. if (result != ISC_R_SUCCESS)
  118. return (result);
  119. result = isc_buffer_copyregion(keydatabuf, &r);
  120. if (result != ISC_R_SUCCESS)
  121. goto cleanup;
  122. /* Configure key name */
  123. dns_fixedname_init(&fkeyname);
  124. keyname_base = dns_fixedname_name(&fkeyname);
  125. isc_buffer_init(&namebuf, keynamestr,
  126. strlen(keynamestr));
  127. isc_buffer_add(&namebuf, strlen(keynamestr));
  128. result = dns_name_fromtext(keyname_base, &namebuf,
  129. dns_rootname, 0, NULL);
  130. if (result != ISC_R_SUCCESS)
  131. return (result);
  132. keyname = isc_mem_get(mctx, sizeof(*keyname));
  133. if (keyname == NULL) {
  134. result = ISC_R_NOMEMORY;
  135. goto cleanup;
  136. }
  137. dns_name_init(keyname, NULL);
  138. result = dns_name_dup(keyname_base, mctx, keyname);
  139. if (result != ISC_R_SUCCESS)
  140. goto cleanup;
  141. /* Add the key data to the list */
  142. keyent = isc_mem_get(mctx, sizeof(*keyent));
  143. if (keyent == NULL) {
  144. dns_name_free(keyname, mctx);
  145. result = ISC_R_NOMEMORY;
  146. goto cleanup;
  147. }
  148. keyent->keyname = keyname;
  149. keyent->keydatabuf = keydatabuf;
  150. ISC_LIST_APPEND(conf->trusted_keylist, keyent, link);
  151. }
  152. }
  153. return (ISC_R_SUCCESS);
  154. cleanup:
  155. if (keydatabuf != NULL)
  156. isc_buffer_free(&keydatabuf);
  157. if (keyname != NULL)
  158. isc_mem_put(mctx, keyname, sizeof(*keyname));
  159. return (result);
  160. }
  161. isc_result_t
  162. irs_dnsconf_load(isc_mem_t *mctx, const char *filename, irs_dnsconf_t **confp)
  163. {
  164. irs_dnsconf_t *conf;
  165. cfg_parser_t *parser = NULL;
  166. cfg_obj_t *cfgobj = NULL;
  167. isc_result_t result = ISC_R_SUCCESS;
  168. REQUIRE(confp != NULL && *confp == NULL);
  169. conf = isc_mem_get(mctx, sizeof(*conf));
  170. if (conf == NULL)
  171. return (ISC_R_NOMEMORY);
  172. conf->mctx = mctx;
  173. ISC_LIST_INIT(conf->trusted_keylist);
  174. /*
  175. * If the specified file does not exist, we'll simply with an empty
  176. * configuration.
  177. */
  178. if (!isc_file_exists(filename))
  179. goto cleanup;
  180. result = cfg_parser_create(mctx, NULL, &parser);
  181. if (result != ISC_R_SUCCESS)
  182. goto cleanup;
  183. result = cfg_parse_file(parser, filename, &cfg_type_dnsconf,
  184. &cfgobj);
  185. if (result != ISC_R_SUCCESS)
  186. goto cleanup;
  187. result = configure_dnsseckeys(conf, cfgobj, dns_rdataclass_in);
  188. cleanup:
  189. if (parser != NULL) {
  190. if (cfgobj != NULL)
  191. cfg_obj_destroy(parser, &cfgobj);
  192. cfg_parser_destroy(&parser);
  193. }
  194. conf->magic = IRS_DNSCONF_MAGIC;
  195. if (result == ISC_R_SUCCESS)
  196. *confp = conf;
  197. else
  198. irs_dnsconf_destroy(&conf);
  199. return (result);
  200. }
  201. void
  202. irs_dnsconf_destroy(irs_dnsconf_t **confp) {
  203. irs_dnsconf_t *conf;
  204. irs_dnsconf_dnskey_t *keyent;
  205. REQUIRE(confp != NULL);
  206. conf = *confp;
  207. REQUIRE(IRS_DNSCONF_VALID(conf));
  208. while ((keyent = ISC_LIST_HEAD(conf->trusted_keylist)) != NULL) {
  209. ISC_LIST_UNLINK(conf->trusted_keylist, keyent, link);
  210. isc_buffer_free(&keyent->keydatabuf);
  211. dns_name_free(keyent->keyname, conf->mctx);
  212. isc_mem_put(conf->mctx, keyent->keyname, sizeof(dns_name_t));
  213. isc_mem_put(conf->mctx, keyent, sizeof(*keyent));
  214. }
  215. isc_mem_put(conf->mctx, conf, sizeof(*conf));
  216. *confp = NULL;
  217. }
  218. irs_dnsconf_dnskeylist_t *
  219. irs_dnsconf_gettrustedkeys(irs_dnsconf_t *conf) {
  220. REQUIRE(IRS_DNSCONF_VALID(conf));
  221. return (&conf->trusted_keylist);
  222. }