/contrib/bind9/lib/dns/private.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 295 lines · 189 code · 32 blank · 74 comment · 92 complexity · 1eb2efb3e45608e069ccaeab41d192ef MD5 · raw file

  1. /*
  2. * Copyright (C) 2009, 2012 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$ */
  17. #include "config.h"
  18. #include <isc/result.h>
  19. #include <isc/string.h>
  20. #include <isc/types.h>
  21. #include <isc/base64.h>
  22. #include <dns/nsec3.h>
  23. #include <dns/private.h>
  24. /*
  25. * We need to build the relevant chain if there exists a NSEC/NSEC3PARAM
  26. * at the apex; normally only one or the other of NSEC/NSEC3PARAM will exist.
  27. *
  28. * If a NSEC3PARAM RRset exists then we will need to build a NSEC chain
  29. * if all the NSEC3PARAM records (and associated chains) are slated for
  30. * destruction and we have not been told to NOT build the NSEC chain.
  31. *
  32. * If the NSEC set exist then check to see if there is a request to create
  33. * a NSEC3 chain.
  34. *
  35. * If neither NSEC/NSEC3PARAM RRsets exist at the origin and the private
  36. * type exists then we need to examine it to determine if NSEC3 chain has
  37. * been requested to be built otherwise a NSEC chain needs to be built.
  38. */
  39. #define REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0)
  40. #define CREATE(x) (((x) & DNS_NSEC3FLAG_CREATE) != 0)
  41. #define NONSEC(x) (((x) & DNS_NSEC3FLAG_NONSEC) != 0)
  42. #define CHECK(x) do { \
  43. result = (x); \
  44. if (result != ISC_R_SUCCESS) \
  45. goto failure; \
  46. } while (0)
  47. /*
  48. * Work out if 'param' should be ignored or not (i.e. it is in the process
  49. * of being removed).
  50. *
  51. * Note: we 'belt-and-braces' here by also checking for a CREATE private
  52. * record and keep the param record in this case.
  53. */
  54. static isc_boolean_t
  55. ignore(dns_rdata_t *param, dns_rdataset_t *privateset) {
  56. isc_result_t result;
  57. for (result = dns_rdataset_first(privateset);
  58. result == ISC_R_SUCCESS;
  59. result = dns_rdataset_next(privateset)) {
  60. unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
  61. dns_rdata_t private = DNS_RDATA_INIT;
  62. dns_rdata_t rdata = DNS_RDATA_INIT;
  63. dns_rdataset_current(privateset, &private);
  64. if (!dns_nsec3param_fromprivate(&private, &rdata,
  65. buf, sizeof(buf)))
  66. continue;
  67. /*
  68. * We are going to create a new NSEC3 chain so it
  69. * doesn't matter if we are removing this one.
  70. */
  71. if (CREATE(rdata.data[1]))
  72. return (ISC_FALSE);
  73. if (rdata.data[0] != param->data[0] ||
  74. rdata.data[2] != param->data[2] ||
  75. rdata.data[3] != param->data[3] ||
  76. rdata.data[4] != param->data[4] ||
  77. memcmp(&rdata.data[5], &param->data[5], param->data[4]))
  78. continue;
  79. /*
  80. * The removal of this NSEC3 chain does NOT cause a
  81. * NSEC chain to be created so we don't need to tell
  82. * the caller that it will be removed.
  83. */
  84. if (NONSEC(rdata.data[1]))
  85. return (ISC_FALSE);
  86. return (ISC_TRUE);
  87. }
  88. return (ISC_FALSE);
  89. }
  90. isc_result_t
  91. dns_private_chains(dns_db_t *db, dns_dbversion_t *ver,
  92. dns_rdatatype_t privatetype,
  93. isc_boolean_t *build_nsec, isc_boolean_t *build_nsec3)
  94. {
  95. dns_dbnode_t *node;
  96. dns_rdataset_t nsecset, nsec3paramset, privateset;
  97. isc_boolean_t nsec3chain;
  98. isc_boolean_t signing;
  99. isc_result_t result;
  100. unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
  101. unsigned int count;
  102. node = NULL;
  103. dns_rdataset_init(&nsecset);
  104. dns_rdataset_init(&nsec3paramset);
  105. dns_rdataset_init(&privateset);
  106. CHECK(dns_db_getoriginnode(db, &node));
  107. result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
  108. 0, (isc_stdtime_t) 0, &nsecset, NULL);
  109. if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
  110. goto failure;
  111. result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
  112. 0, (isc_stdtime_t) 0, &nsec3paramset,
  113. NULL);
  114. if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
  115. goto failure;
  116. if (dns_rdataset_isassociated(&nsecset) &&
  117. dns_rdataset_isassociated(&nsec3paramset)) {
  118. if (build_nsec != NULL)
  119. *build_nsec = ISC_TRUE;
  120. if (build_nsec3 != NULL)
  121. *build_nsec3 = ISC_TRUE;
  122. goto success;
  123. }
  124. if (privatetype != (dns_rdatatype_t)0) {
  125. result = dns_db_findrdataset(db, node, ver, privatetype,
  126. 0, (isc_stdtime_t) 0,
  127. &privateset, NULL);
  128. if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
  129. goto failure;
  130. }
  131. /*
  132. * Look to see if we also need to be creating a NSEC3 chains.
  133. */
  134. if (dns_rdataset_isassociated(&nsecset)) {
  135. if (build_nsec != NULL)
  136. *build_nsec = ISC_TRUE;
  137. if (build_nsec3 != NULL)
  138. *build_nsec3 = ISC_FALSE;
  139. if (!dns_rdataset_isassociated(&privateset))
  140. goto success;
  141. for (result = dns_rdataset_first(&privateset);
  142. result == ISC_R_SUCCESS;
  143. result = dns_rdataset_next(&privateset)) {
  144. unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
  145. dns_rdata_t private = DNS_RDATA_INIT;
  146. dns_rdata_t rdata = DNS_RDATA_INIT;
  147. dns_rdataset_current(&privateset, &private);
  148. if (!dns_nsec3param_fromprivate(&private, &rdata,
  149. buf, sizeof(buf)))
  150. continue;
  151. if (REMOVE(rdata.data[1]))
  152. continue;
  153. if (build_nsec3 != NULL)
  154. *build_nsec3 = ISC_TRUE;
  155. break;
  156. }
  157. goto success;
  158. }
  159. if (dns_rdataset_isassociated(&nsec3paramset)) {
  160. if (build_nsec3 != NULL)
  161. *build_nsec3 = ISC_TRUE;
  162. if (build_nsec != NULL)
  163. *build_nsec = ISC_FALSE;
  164. if (!dns_rdataset_isassociated(&privateset))
  165. goto success;
  166. /*
  167. * If we are in the process of building a new NSEC3 chain
  168. * then we don't need to build a NSEC chain.
  169. */
  170. for (result = dns_rdataset_first(&privateset);
  171. result == ISC_R_SUCCESS;
  172. result = dns_rdataset_next(&privateset)) {
  173. dns_rdata_t private = DNS_RDATA_INIT;
  174. dns_rdata_t rdata = DNS_RDATA_INIT;
  175. dns_rdataset_current(&privateset, &private);
  176. if (!dns_nsec3param_fromprivate(&private, &rdata,
  177. buf, sizeof(buf)))
  178. continue;
  179. if (CREATE(rdata.data[1]))
  180. goto success;
  181. }
  182. /*
  183. * Check to see if there will be a active NSEC3CHAIN once
  184. * the changes queued complete.
  185. */
  186. count = 0;
  187. for (result = dns_rdataset_first(&nsec3paramset);
  188. result == ISC_R_SUCCESS;
  189. result = dns_rdataset_next(&nsec3paramset)) {
  190. dns_rdata_t rdata = DNS_RDATA_INIT;
  191. /*
  192. * If there is more that one NSEC3 chain present then
  193. * we don't need to construct a NSEC chain.
  194. */
  195. if (++count > 1)
  196. goto success;
  197. dns_rdataset_current(&nsec3paramset, &rdata);
  198. if (ignore(&rdata, &privateset))
  199. continue;
  200. /*
  201. * We still have a good NSEC3 chain or we are
  202. * not creating a NSEC chain as NONSEC is set.
  203. */
  204. goto success;
  205. }
  206. /*
  207. * The last NSEC3 chain is being removed and does not have
  208. * have NONSEC set.
  209. */
  210. if (build_nsec != NULL)
  211. *build_nsec = ISC_TRUE;
  212. goto success;
  213. }
  214. if (build_nsec != NULL)
  215. *build_nsec = ISC_FALSE;
  216. if (build_nsec3 != NULL)
  217. *build_nsec3 = ISC_FALSE;
  218. if (!dns_rdataset_isassociated(&privateset))
  219. goto success;
  220. signing = ISC_FALSE;
  221. nsec3chain = ISC_FALSE;
  222. for (result = dns_rdataset_first(&privateset);
  223. result == ISC_R_SUCCESS;
  224. result = dns_rdataset_next(&privateset)) {
  225. dns_rdata_t rdata = DNS_RDATA_INIT;
  226. dns_rdata_t private = DNS_RDATA_INIT;
  227. dns_rdataset_current(&privateset, &private);
  228. if (!dns_nsec3param_fromprivate(&private, &rdata,
  229. buf, sizeof(buf))) {
  230. /*
  231. * Look for record that says we are signing the
  232. * zone with a key.
  233. */
  234. if (private.length == 5 && private.data[0] != 0 &&
  235. private.data[3] == 0 && private.data[4] == 0)
  236. signing = ISC_TRUE;
  237. } else {
  238. if (CREATE(rdata.data[1]))
  239. nsec3chain = ISC_TRUE;
  240. }
  241. }
  242. if (signing) {
  243. if (nsec3chain) {
  244. if (build_nsec3 != NULL)
  245. *build_nsec3 = ISC_TRUE;
  246. } else {
  247. if (build_nsec != NULL)
  248. *build_nsec = ISC_TRUE;
  249. }
  250. }
  251. success:
  252. result = ISC_R_SUCCESS;
  253. failure:
  254. if (dns_rdataset_isassociated(&nsecset))
  255. dns_rdataset_disassociate(&nsecset);
  256. if (dns_rdataset_isassociated(&nsec3paramset))
  257. dns_rdataset_disassociate(&nsec3paramset);
  258. if (dns_rdataset_isassociated(&privateset))
  259. dns_rdataset_disassociate(&privateset);
  260. if (node != NULL)
  261. dns_db_detachnode(db, &node);
  262. return (result);
  263. }