PageRenderTime 66ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 1ms

/bind-9.9.1-P1/lib/bind9/check.c

#
C | 2830 lines | 2411 code | 270 blank | 149 comment | 837 complexity | 8c8384140e49c312ad035ebbd0e957f7 MD5 | raw file
Possible License(s): BSD-3-Clause, ISC

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * Copyright (C) 2004-2012 Internet Systems Consortium, Inc. ("ISC")
  3. * Copyright (C) 2001-2003 Internet Software Consortium.
  4. *
  5. * Permission to use, copy, modify, and/or distribute this software for any
  6. * purpose with or without fee is hereby granted, provided that the above
  7. * copyright notice and this permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  10. * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  11. * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  12. * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  13. * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  14. * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  15. * PERFORMANCE OF THIS SOFTWARE.
  16. */
  17. /* $Id$ */
  18. /*! \file */
  19. #include <config.h>
  20. #include <stdlib.h>
  21. #include <isc/base64.h>
  22. #include <isc/buffer.h>
  23. #include <isc/log.h>
  24. #include <isc/mem.h>
  25. #include <isc/netaddr.h>
  26. #include <isc/parseint.h>
  27. #include <isc/region.h>
  28. #include <isc/result.h>
  29. #include <isc/sockaddr.h>
  30. #include <isc/string.h>
  31. #include <isc/symtab.h>
  32. #include <isc/util.h>
  33. #include <dns/acl.h>
  34. #include <dns/fixedname.h>
  35. #include <dns/rdataclass.h>
  36. #include <dns/rdatatype.h>
  37. #include <dns/secalg.h>
  38. #include <dst/dst.h>
  39. #include <isccfg/aclconf.h>
  40. #include <isccfg/cfg.h>
  41. #include <bind9/check.h>
  42. static void
  43. freekey(char *key, unsigned int type, isc_symvalue_t value, void *userarg) {
  44. UNUSED(type);
  45. UNUSED(value);
  46. isc_mem_free(userarg, key);
  47. }
  48. static isc_result_t
  49. check_orderent(const cfg_obj_t *ent, isc_log_t *logctx) {
  50. isc_result_t result = ISC_R_SUCCESS;
  51. isc_result_t tresult;
  52. isc_textregion_t r;
  53. dns_fixedname_t fixed;
  54. const cfg_obj_t *obj;
  55. dns_rdataclass_t rdclass;
  56. dns_rdatatype_t rdtype;
  57. isc_buffer_t b;
  58. const char *str;
  59. dns_fixedname_init(&fixed);
  60. obj = cfg_tuple_get(ent, "class");
  61. if (cfg_obj_isstring(obj)) {
  62. DE_CONST(cfg_obj_asstring(obj), r.base);
  63. r.length = strlen(r.base);
  64. tresult = dns_rdataclass_fromtext(&rdclass, &r);
  65. if (tresult != ISC_R_SUCCESS) {
  66. cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
  67. "rrset-order: invalid class '%s'",
  68. r.base);
  69. result = ISC_R_FAILURE;
  70. }
  71. }
  72. obj = cfg_tuple_get(ent, "type");
  73. if (cfg_obj_isstring(obj)) {
  74. DE_CONST(cfg_obj_asstring(obj), r.base);
  75. r.length = strlen(r.base);
  76. tresult = dns_rdatatype_fromtext(&rdtype, &r);
  77. if (tresult != ISC_R_SUCCESS) {
  78. cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
  79. "rrset-order: invalid type '%s'",
  80. r.base);
  81. result = ISC_R_FAILURE;
  82. }
  83. }
  84. obj = cfg_tuple_get(ent, "name");
  85. if (cfg_obj_isstring(obj)) {
  86. str = cfg_obj_asstring(obj);
  87. isc_buffer_init(&b, str, strlen(str));
  88. isc_buffer_add(&b, strlen(str));
  89. tresult = dns_name_fromtext(dns_fixedname_name(&fixed), &b,
  90. dns_rootname, 0, NULL);
  91. if (tresult != ISC_R_SUCCESS) {
  92. cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
  93. "rrset-order: invalid name '%s'", str);
  94. result = ISC_R_FAILURE;
  95. }
  96. }
  97. obj = cfg_tuple_get(ent, "order");
  98. if (!cfg_obj_isstring(obj) ||
  99. strcasecmp("order", cfg_obj_asstring(obj)) != 0) {
  100. cfg_obj_log(ent, logctx, ISC_LOG_ERROR,
  101. "rrset-order: keyword 'order' missing");
  102. result = ISC_R_FAILURE;
  103. }
  104. obj = cfg_tuple_get(ent, "ordering");
  105. if (!cfg_obj_isstring(obj)) {
  106. cfg_obj_log(ent, logctx, ISC_LOG_ERROR,
  107. "rrset-order: missing ordering");
  108. result = ISC_R_FAILURE;
  109. } else if (strcasecmp(cfg_obj_asstring(obj), "fixed") == 0) {
  110. #if !DNS_RDATASET_FIXED
  111. cfg_obj_log(obj, logctx, ISC_LOG_WARNING,
  112. "rrset-order: order 'fixed' was disabled at "
  113. "compilation time");
  114. #endif
  115. } else if (strcasecmp(cfg_obj_asstring(obj), "random") != 0 &&
  116. strcasecmp(cfg_obj_asstring(obj), "cyclic") != 0) {
  117. cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
  118. "rrset-order: invalid order '%s'",
  119. cfg_obj_asstring(obj));
  120. result = ISC_R_FAILURE;
  121. }
  122. return (result);
  123. }
  124. static isc_result_t
  125. check_order(const cfg_obj_t *options, isc_log_t *logctx) {
  126. isc_result_t result = ISC_R_SUCCESS;
  127. isc_result_t tresult;
  128. const cfg_listelt_t *element;
  129. const cfg_obj_t *obj = NULL;
  130. if (cfg_map_get(options, "rrset-order", &obj) != ISC_R_SUCCESS)
  131. return (result);
  132. for (element = cfg_list_first(obj);
  133. element != NULL;
  134. element = cfg_list_next(element))
  135. {
  136. tresult = check_orderent(cfg_listelt_value(element), logctx);
  137. if (tresult != ISC_R_SUCCESS)
  138. result = tresult;
  139. }
  140. return (result);
  141. }
  142. static isc_result_t
  143. check_dual_stack(const cfg_obj_t *options, isc_log_t *logctx) {
  144. const cfg_listelt_t *element;
  145. const cfg_obj_t *alternates = NULL;
  146. const cfg_obj_t *value;
  147. const cfg_obj_t *obj;
  148. const char *str;
  149. dns_fixedname_t fixed;
  150. dns_name_t *name;
  151. isc_buffer_t buffer;
  152. isc_result_t result = ISC_R_SUCCESS;
  153. isc_result_t tresult;
  154. (void)cfg_map_get(options, "dual-stack-servers", &alternates);
  155. if (alternates == NULL)
  156. return (ISC_R_SUCCESS);
  157. obj = cfg_tuple_get(alternates, "port");
  158. if (cfg_obj_isuint32(obj)) {
  159. isc_uint32_t val = cfg_obj_asuint32(obj);
  160. if (val > ISC_UINT16_MAX) {
  161. cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
  162. "port '%u' out of range", val);
  163. result = ISC_R_FAILURE;
  164. }
  165. }
  166. obj = cfg_tuple_get(alternates, "addresses");
  167. for (element = cfg_list_first(obj);
  168. element != NULL;
  169. element = cfg_list_next(element)) {
  170. value = cfg_listelt_value(element);
  171. if (cfg_obj_issockaddr(value))
  172. continue;
  173. obj = cfg_tuple_get(value, "name");
  174. str = cfg_obj_asstring(obj);
  175. isc_buffer_init(&buffer, str, strlen(str));
  176. isc_buffer_add(&buffer, strlen(str));
  177. dns_fixedname_init(&fixed);
  178. name = dns_fixedname_name(&fixed);
  179. tresult = dns_name_fromtext(name, &buffer, dns_rootname,
  180. 0, NULL);
  181. if (tresult != ISC_R_SUCCESS) {
  182. cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
  183. "bad name '%s'", str);
  184. result = ISC_R_FAILURE;
  185. }
  186. obj = cfg_tuple_get(value, "port");
  187. if (cfg_obj_isuint32(obj)) {
  188. isc_uint32_t val = cfg_obj_asuint32(obj);
  189. if (val > ISC_UINT16_MAX) {
  190. cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
  191. "port '%u' out of range", val);
  192. result = ISC_R_FAILURE;
  193. }
  194. }
  195. }
  196. return (result);
  197. }
  198. static isc_result_t
  199. check_forward(const cfg_obj_t *options, const cfg_obj_t *global,
  200. isc_log_t *logctx)
  201. {
  202. const cfg_obj_t *forward = NULL;
  203. const cfg_obj_t *forwarders = NULL;
  204. (void)cfg_map_get(options, "forward", &forward);
  205. (void)cfg_map_get(options, "forwarders", &forwarders);
  206. if (forwarders != NULL && global != NULL) {
  207. const char *file = cfg_obj_file(global);
  208. unsigned int line = cfg_obj_line(global);
  209. cfg_obj_log(forwarders, logctx, ISC_LOG_ERROR,
  210. "forwarders declared in root zone and "
  211. "in general configuration: %s:%u",
  212. file, line);
  213. return (ISC_R_FAILURE);
  214. }
  215. if (forward != NULL && forwarders == NULL) {
  216. cfg_obj_log(forward, logctx, ISC_LOG_ERROR,
  217. "no matching 'forwarders' statement");
  218. return (ISC_R_FAILURE);
  219. }
  220. return (ISC_R_SUCCESS);
  221. }
  222. static isc_result_t
  223. disabled_algorithms(const cfg_obj_t *disabled, isc_log_t *logctx) {
  224. isc_result_t result = ISC_R_SUCCESS;
  225. isc_result_t tresult;
  226. const cfg_listelt_t *element;
  227. const char *str;
  228. isc_buffer_t b;
  229. dns_fixedname_t fixed;
  230. dns_name_t *name;
  231. const cfg_obj_t *obj;
  232. dns_fixedname_init(&fixed);
  233. name = dns_fixedname_name(&fixed);
  234. obj = cfg_tuple_get(disabled, "name");
  235. str = cfg_obj_asstring(obj);
  236. isc_buffer_init(&b, str, strlen(str));
  237. isc_buffer_add(&b, strlen(str));
  238. tresult = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
  239. if (tresult != ISC_R_SUCCESS) {
  240. cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
  241. "bad domain name '%s'", str);
  242. result = tresult;
  243. }
  244. obj = cfg_tuple_get(disabled, "algorithms");
  245. for (element = cfg_list_first(obj);
  246. element != NULL;
  247. element = cfg_list_next(element))
  248. {
  249. isc_textregion_t r;
  250. dns_secalg_t alg;
  251. isc_result_t tresult;
  252. DE_CONST(cfg_obj_asstring(cfg_listelt_value(element)), r.base);
  253. r.length = strlen(r.base);
  254. tresult = dns_secalg_fromtext(&alg, &r);
  255. if (tresult != ISC_R_SUCCESS) {
  256. isc_uint8_t ui;
  257. result = isc_parse_uint8(&ui, r.base, 10);
  258. }
  259. if (tresult != ISC_R_SUCCESS) {
  260. cfg_obj_log(cfg_listelt_value(element), logctx,
  261. ISC_LOG_ERROR, "invalid algorithm '%s'",
  262. r.base);
  263. result = tresult;
  264. }
  265. }
  266. return (result);
  267. }
  268. static isc_result_t
  269. nameexist(const cfg_obj_t *obj, const char *name, int value,
  270. isc_symtab_t *symtab, const char *fmt, isc_log_t *logctx,
  271. isc_mem_t *mctx)
  272. {
  273. char *key;
  274. const char *file;
  275. unsigned int line;
  276. isc_result_t result;
  277. isc_symvalue_t symvalue;
  278. key = isc_mem_strdup(mctx, name);
  279. if (key == NULL)
  280. return (ISC_R_NOMEMORY);
  281. symvalue.as_cpointer = obj;
  282. result = isc_symtab_define(symtab, key, value, symvalue,
  283. isc_symexists_reject);
  284. if (result == ISC_R_EXISTS) {
  285. RUNTIME_CHECK(isc_symtab_lookup(symtab, key, value,
  286. &symvalue) == ISC_R_SUCCESS);
  287. file = cfg_obj_file(symvalue.as_cpointer);
  288. line = cfg_obj_line(symvalue.as_cpointer);
  289. if (file == NULL)
  290. file = "<unknown file>";
  291. cfg_obj_log(obj, logctx, ISC_LOG_ERROR, fmt, key, file, line);
  292. isc_mem_free(mctx, key);
  293. result = ISC_R_EXISTS;
  294. } else if (result != ISC_R_SUCCESS) {
  295. isc_mem_free(mctx, key);
  296. }
  297. return (result);
  298. }
  299. static isc_result_t
  300. mustbesecure(const cfg_obj_t *secure, isc_symtab_t *symtab, isc_log_t *logctx,
  301. isc_mem_t *mctx)
  302. {
  303. const cfg_obj_t *obj;
  304. char namebuf[DNS_NAME_FORMATSIZE];
  305. const char *str;
  306. dns_fixedname_t fixed;
  307. dns_name_t *name;
  308. isc_buffer_t b;
  309. isc_result_t result = ISC_R_SUCCESS;
  310. dns_fixedname_init(&fixed);
  311. name = dns_fixedname_name(&fixed);
  312. obj = cfg_tuple_get(secure, "name");
  313. str = cfg_obj_asstring(obj);
  314. isc_buffer_init(&b, str, strlen(str));
  315. isc_buffer_add(&b, strlen(str));
  316. result = dns_name_fromtext(name, &b, dns_rootname, 0, NULL);
  317. if (result != ISC_R_SUCCESS) {
  318. cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
  319. "bad domain name '%s'", str);
  320. } else {
  321. dns_name_format(name, namebuf, sizeof(namebuf));
  322. result = nameexist(secure, namebuf, 1, symtab,
  323. "dnssec-must-be-secure '%s': already "
  324. "exists previous definition: %s:%u",
  325. logctx, mctx);
  326. }
  327. return (result);
  328. }
  329. static isc_result_t
  330. checkacl(const char *aclname, cfg_aclconfctx_t *actx, const cfg_obj_t *zconfig,
  331. const cfg_obj_t *voptions, const cfg_obj_t *config,
  332. isc_log_t *logctx, isc_mem_t *mctx)
  333. {
  334. isc_result_t result;
  335. const cfg_obj_t *aclobj = NULL;
  336. const cfg_obj_t *options;
  337. dns_acl_t *acl = NULL;
  338. if (zconfig != NULL) {
  339. options = cfg_tuple_get(zconfig, "options");
  340. cfg_map_get(options, aclname, &aclobj);
  341. }
  342. if (voptions != NULL && aclobj == NULL)
  343. cfg_map_get(voptions, aclname, &aclobj);
  344. if (config != NULL && aclobj == NULL) {
  345. options = NULL;
  346. cfg_map_get(config, "options", &options);
  347. if (options != NULL)
  348. cfg_map_get(options, aclname, &aclobj);
  349. }
  350. if (aclobj == NULL)
  351. return (ISC_R_SUCCESS);
  352. result = cfg_acl_fromconfig(aclobj, config, logctx,
  353. actx, mctx, 0, &acl);
  354. if (acl != NULL)
  355. dns_acl_detach(&acl);
  356. return (result);
  357. }
  358. static isc_result_t
  359. check_viewacls(cfg_aclconfctx_t *actx, const cfg_obj_t *voptions,
  360. const cfg_obj_t *config, isc_log_t *logctx, isc_mem_t *mctx)
  361. {
  362. isc_result_t result = ISC_R_SUCCESS, tresult;
  363. int i = 0;
  364. static const char *acls[] = { "allow-query", "allow-query-on",
  365. "allow-query-cache", "allow-query-cache-on",
  366. "blackhole", "match-clients", "match-destinations",
  367. "sortlist", "filter-aaaa", NULL };
  368. while (acls[i] != NULL) {
  369. tresult = checkacl(acls[i++], actx, NULL, voptions, config,
  370. logctx, mctx);
  371. if (tresult != ISC_R_SUCCESS)
  372. result = tresult;
  373. }
  374. return (result);
  375. }
  376. static const unsigned char zeros[16];
  377. static isc_result_t
  378. check_dns64(cfg_aclconfctx_t *actx, const cfg_obj_t *voptions,
  379. const cfg_obj_t *config, isc_log_t *logctx, isc_mem_t *mctx)
  380. {
  381. isc_result_t result = ISC_R_SUCCESS;
  382. const cfg_obj_t *dns64 = NULL;
  383. const cfg_obj_t *options;
  384. const cfg_listelt_t *element;
  385. const cfg_obj_t *map, *obj;
  386. isc_netaddr_t na, sa;
  387. unsigned int prefixlen;
  388. int nbytes;
  389. int i;
  390. static const char *acls[] = { "clients", "exclude", "mapped", NULL};
  391. if (voptions != NULL)
  392. cfg_map_get(voptions, "dns64", &dns64);
  393. if (config != NULL && dns64 == NULL) {
  394. options = NULL;
  395. cfg_map_get(config, "options", &options);
  396. if (options != NULL)
  397. cfg_map_get(options, "dns64", &dns64);
  398. }
  399. if (dns64 == NULL)
  400. return (ISC_R_SUCCESS);
  401. for (element = cfg_list_first(dns64);
  402. element != NULL;
  403. element = cfg_list_next(element))
  404. {
  405. map = cfg_listelt_value(element);
  406. obj = cfg_map_getname(map);
  407. cfg_obj_asnetprefix(obj, &na, &prefixlen);
  408. if (na.family != AF_INET6) {
  409. cfg_obj_log(map, logctx, ISC_LOG_ERROR,
  410. "dns64 requires a IPv6 prefix");
  411. result = ISC_R_FAILURE;
  412. continue;
  413. }
  414. if (prefixlen != 32 && prefixlen != 40 && prefixlen != 48 &&
  415. prefixlen != 56 && prefixlen != 64 && prefixlen != 96) {
  416. cfg_obj_log(map, logctx, ISC_LOG_ERROR,
  417. "bad prefix length %u [32/40/48/56/64/96]",
  418. prefixlen);
  419. result = ISC_R_FAILURE;
  420. continue;
  421. }
  422. for (i = 0; acls[i] != NULL; i++) {
  423. obj = NULL;
  424. (void)cfg_map_get(map, acls[i], &obj);
  425. if (obj != NULL) {
  426. dns_acl_t *acl = NULL;
  427. isc_result_t tresult;
  428. tresult = cfg_acl_fromconfig(obj, config,
  429. logctx, actx,
  430. mctx, 0, &acl);
  431. if (acl != NULL)
  432. dns_acl_detach(&acl);
  433. if (tresult != ISC_R_SUCCESS)
  434. result = tresult;
  435. }
  436. }
  437. obj = NULL;
  438. (void)cfg_map_get(map, "suffix", &obj);
  439. if (obj != NULL) {
  440. isc_netaddr_fromsockaddr(&sa, cfg_obj_assockaddr(obj));
  441. if (sa.family != AF_INET6) {
  442. cfg_obj_log(map, logctx, ISC_LOG_ERROR,
  443. "dns64 requires a IPv6 suffix");
  444. result = ISC_R_FAILURE;
  445. continue;
  446. }
  447. nbytes = prefixlen / 8 + 4;
  448. if (prefixlen >= 32 && prefixlen <= 64)
  449. nbytes++;
  450. if (memcmp(sa.type.in6.s6_addr, zeros, nbytes) != 0) {
  451. char netaddrbuf[ISC_NETADDR_FORMATSIZE];
  452. isc_netaddr_format(&sa, netaddrbuf,
  453. sizeof(netaddrbuf));
  454. cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
  455. "bad suffix '%s' leading "
  456. "%u octets not zeros",
  457. netaddrbuf, nbytes);
  458. result = ISC_R_FAILURE;
  459. }
  460. }
  461. }
  462. return (result);
  463. }
  464. /*
  465. * Check allow-recursion and allow-recursion-on acls, and also log a
  466. * warning if they're inconsistent with the "recursion" option.
  467. */
  468. static isc_result_t
  469. check_recursionacls(cfg_aclconfctx_t *actx, const cfg_obj_t *voptions,
  470. const char *viewname, const cfg_obj_t *config,
  471. isc_log_t *logctx, isc_mem_t *mctx)
  472. {
  473. const cfg_obj_t *options, *aclobj, *obj = NULL;
  474. dns_acl_t *acl = NULL;
  475. isc_result_t result = ISC_R_SUCCESS, tresult;
  476. isc_boolean_t recursion;
  477. const char *forview = " for view ";
  478. int i = 0;
  479. static const char *acls[] = { "allow-recursion", "allow-recursion-on",
  480. NULL };
  481. if (voptions != NULL)
  482. cfg_map_get(voptions, "recursion", &obj);
  483. if (obj == NULL && config != NULL) {
  484. options = NULL;
  485. cfg_map_get(config, "options", &options);
  486. if (options != NULL)
  487. cfg_map_get(options, "recursion", &obj);
  488. }
  489. if (obj == NULL)
  490. recursion = ISC_TRUE;
  491. else
  492. recursion = cfg_obj_asboolean(obj);
  493. if (viewname == NULL) {
  494. viewname = "";
  495. forview = "";
  496. }
  497. for (i = 0; acls[i] != NULL; i++) {
  498. aclobj = options = NULL;
  499. acl = NULL;
  500. if (voptions != NULL)
  501. cfg_map_get(voptions, acls[i], &aclobj);
  502. if (config != NULL && aclobj == NULL) {
  503. options = NULL;
  504. cfg_map_get(config, "options", &options);
  505. if (options != NULL)
  506. cfg_map_get(options, acls[i], &aclobj);
  507. }
  508. if (aclobj == NULL)
  509. continue;
  510. tresult = cfg_acl_fromconfig(aclobj, config, logctx,
  511. actx, mctx, 0, &acl);
  512. if (tresult != ISC_R_SUCCESS)
  513. result = tresult;
  514. if (acl == NULL)
  515. continue;
  516. if (recursion == ISC_FALSE && !dns_acl_isnone(acl)) {
  517. cfg_obj_log(aclobj, logctx, ISC_LOG_WARNING,
  518. "both \"recursion no;\" and "
  519. "\"%s\" active%s%s",
  520. acls[i], forview, viewname);
  521. }
  522. if (acl != NULL)
  523. dns_acl_detach(&acl);
  524. }
  525. return (result);
  526. }
  527. static isc_result_t
  528. check_filteraaaa(cfg_aclconfctx_t *actx, const cfg_obj_t *voptions,
  529. const char *viewname, const cfg_obj_t *config,
  530. isc_log_t *logctx, isc_mem_t *mctx)
  531. {
  532. const cfg_obj_t *options, *aclobj, *obj = NULL;
  533. dns_acl_t *acl = NULL;
  534. isc_result_t result = ISC_R_SUCCESS, tresult;
  535. dns_v4_aaaa_t filter;
  536. const char *forview = " for view ";
  537. if (voptions != NULL)
  538. cfg_map_get(voptions, "filter-aaaa-on-v4", &obj);
  539. if (obj == NULL && config != NULL) {
  540. options = NULL;
  541. cfg_map_get(config, "options", &options);
  542. if (options != NULL)
  543. cfg_map_get(options, "filter-aaaa-on-v4", &obj);
  544. }
  545. if (obj == NULL)
  546. filter = dns_v4_aaaa_ok; /* default */
  547. else if (cfg_obj_isboolean(obj))
  548. filter = cfg_obj_asboolean(obj) ? dns_v4_aaaa_filter :
  549. dns_v4_aaaa_ok;
  550. else
  551. filter = dns_v4_aaaa_break_dnssec; /* break-dnssec */
  552. if (viewname == NULL) {
  553. viewname = "";
  554. forview = "";
  555. }
  556. aclobj = options = NULL;
  557. acl = NULL;
  558. if (voptions != NULL)
  559. cfg_map_get(voptions, "filter-aaaa", &aclobj);
  560. if (config != NULL && aclobj == NULL) {
  561. options = NULL;
  562. cfg_map_get(config, "options", &options);
  563. if (options != NULL)
  564. cfg_map_get(options, "filter-aaaa", &aclobj);
  565. }
  566. if (aclobj == NULL)
  567. return (result);
  568. tresult = cfg_acl_fromconfig(aclobj, config, logctx,
  569. actx, mctx, 0, &acl);
  570. if (tresult != ISC_R_SUCCESS) {
  571. result = tresult;
  572. } else if (filter != dns_v4_aaaa_ok && dns_acl_isnone(acl)) {
  573. cfg_obj_log(aclobj, logctx, ISC_LOG_WARNING,
  574. "both \"filter-aaaa-on-v4 %s;\" and "
  575. "\"filter-aaaa\" is 'none;'%s%s",
  576. filter == dns_v4_aaaa_break_dnssec ?
  577. "break-dnssec" : "yes", forview, viewname);
  578. result = ISC_R_FAILURE;
  579. } else if (filter == dns_v4_aaaa_ok && !dns_acl_isnone(acl)) {
  580. cfg_obj_log(aclobj, logctx, ISC_LOG_WARNING,
  581. "both \"filter-aaaa-on-v4 no;\" and "
  582. "\"filter-aaaa\" is set%s%s", forview, viewname);
  583. result = ISC_R_FAILURE;
  584. }
  585. if (acl != NULL)
  586. dns_acl_detach(&acl);
  587. return (result);
  588. }
  589. typedef struct {
  590. const char *name;
  591. unsigned int scale;
  592. unsigned int max;
  593. } intervaltable;
  594. typedef enum {
  595. optlevel_config,
  596. optlevel_options,
  597. optlevel_view,
  598. optlevel_zone
  599. } optlevel_t;
  600. static isc_result_t
  601. check_options(const cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx,
  602. optlevel_t optlevel)
  603. {
  604. isc_result_t result = ISC_R_SUCCESS;
  605. isc_result_t tresult;
  606. unsigned int i;
  607. const cfg_obj_t *obj = NULL;
  608. const cfg_obj_t *resignobj = NULL;
  609. const cfg_listelt_t *element;
  610. isc_symtab_t *symtab = NULL;
  611. dns_fixedname_t fixed;
  612. const char *str;
  613. dns_name_t *name;
  614. isc_buffer_t b;
  615. static intervaltable intervals[] = {
  616. { "cleaning-interval", 60, 28 * 24 * 60 }, /* 28 days */
  617. { "heartbeat-interval", 60, 28 * 24 * 60 }, /* 28 days */
  618. { "interface-interval", 60, 28 * 24 * 60 }, /* 28 days */
  619. { "max-transfer-idle-in", 60, 28 * 24 * 60 }, /* 28 days */
  620. { "max-transfer-idle-out", 60, 28 * 24 * 60 }, /* 28 days */
  621. { "max-transfer-time-in", 60, 28 * 24 * 60 }, /* 28 days */
  622. { "max-transfer-time-out", 60, 28 * 24 * 60 }, /* 28 days */
  623. { "statistics-interval", 60, 28 * 24 * 60 }, /* 28 days */
  624. };
  625. static const char *server_contact[] = {
  626. "empty-server", "empty-contact",
  627. "dns64-server", "dns64-contact",
  628. NULL
  629. };
  630. /*
  631. * Check that fields specified in units of time other than seconds
  632. * have reasonable values.
  633. */
  634. for (i = 0; i < sizeof(intervals) / sizeof(intervals[0]); i++) {
  635. isc_uint32_t val;
  636. obj = NULL;
  637. (void)cfg_map_get(options, intervals[i].name, &obj);
  638. if (obj == NULL)
  639. continue;
  640. val = cfg_obj_asuint32(obj);
  641. if (val > intervals[i].max) {
  642. cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
  643. "%s '%u' is out of range (0..%u)",
  644. intervals[i].name, val,
  645. intervals[i].max);
  646. result = ISC_R_RANGE;
  647. } else if (val > (ISC_UINT32_MAX / intervals[i].scale)) {
  648. cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
  649. "%s '%d' is out of range",
  650. intervals[i].name, val);
  651. result = ISC_R_RANGE;
  652. }
  653. }
  654. obj = NULL;
  655. cfg_map_get(options, "sig-validity-interval", &obj);
  656. if (obj != NULL) {
  657. isc_uint32_t validity, resign = 0;
  658. validity = cfg_obj_asuint32(cfg_tuple_get(obj, "validity"));
  659. resignobj = cfg_tuple_get(obj, "re-sign");
  660. if (!cfg_obj_isvoid(resignobj))
  661. resign = cfg_obj_asuint32(resignobj);
  662. if (validity > 3660 || validity == 0) { /* 10 years */
  663. cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
  664. "%s '%u' is out of range (1..3660)",
  665. "sig-validity-interval", validity);
  666. result = ISC_R_RANGE;
  667. }
  668. if (!cfg_obj_isvoid(resignobj)) {
  669. if (resign > 3660 || resign == 0) { /* 10 years */
  670. cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
  671. "%s '%u' is out of range (1..3660)",
  672. "sig-validity-interval (re-sign)",
  673. validity);
  674. result = ISC_R_RANGE;
  675. } else if ((validity > 7 && validity < resign) ||
  676. (validity <= 7 && validity * 24 < resign)) {
  677. cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
  678. "validity interval (%u days) "
  679. "less than re-signing interval "
  680. "(%u %s)", validity, resign,
  681. (validity > 7) ? "days" : "hours");
  682. result = ISC_R_RANGE;
  683. }
  684. }
  685. }
  686. obj = NULL;
  687. (void)cfg_map_get(options, "preferred-glue", &obj);
  688. if (obj != NULL) {
  689. const char *str;
  690. str = cfg_obj_asstring(obj);
  691. if (strcasecmp(str, "a") != 0 &&
  692. strcasecmp(str, "aaaa") != 0 &&
  693. strcasecmp(str, "none") != 0)
  694. cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
  695. "preferred-glue unexpected value '%s'",
  696. str);
  697. }
  698. obj = NULL;
  699. (void)cfg_map_get(options, "root-delegation-only", &obj);
  700. if (obj != NULL) {
  701. if (!cfg_obj_isvoid(obj)) {
  702. const cfg_listelt_t *element;
  703. const cfg_obj_t *exclude;
  704. const char *str;
  705. dns_fixedname_t fixed;
  706. dns_name_t *name;
  707. isc_buffer_t b;
  708. dns_fixedname_init(&fixed);
  709. name = dns_fixedname_name(&fixed);
  710. for (element = cfg_list_first(obj);
  711. element != NULL;
  712. element = cfg_list_next(element)) {
  713. exclude = cfg_listelt_value(element);
  714. str = cfg_obj_asstring(exclude);
  715. isc_buffer_init(&b, str, strlen(str));
  716. isc_buffer_add(&b, strlen(str));
  717. tresult = dns_name_fromtext(name, &b,
  718. dns_rootname,
  719. 0, NULL);
  720. if (tresult != ISC_R_SUCCESS) {
  721. cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
  722. "bad domain name '%s'",
  723. str);
  724. result = tresult;
  725. }
  726. }
  727. }
  728. }
  729. /*
  730. * Set supported DNSSEC algorithms.
  731. */
  732. obj = NULL;
  733. (void)cfg_map_get(options, "disable-algorithms", &obj);
  734. if (obj != NULL) {
  735. for (element = cfg_list_first(obj);
  736. element != NULL;
  737. element = cfg_list_next(element))
  738. {
  739. obj = cfg_listelt_value(element);
  740. tresult = disabled_algorithms(obj, logctx);
  741. if (tresult != ISC_R_SUCCESS)
  742. result = tresult;
  743. }
  744. }
  745. dns_fixedname_init(&fixed);
  746. name = dns_fixedname_name(&fixed);
  747. /*
  748. * Check the DLV zone name.
  749. */
  750. obj = NULL;
  751. (void)cfg_map_get(options, "dnssec-lookaside", &obj);
  752. if (obj != NULL) {
  753. tresult = isc_symtab_create(mctx, 100, freekey, mctx,
  754. ISC_FALSE, &symtab);
  755. if (tresult != ISC_R_SUCCESS)
  756. result = tresult;
  757. for (element = cfg_list_first(obj);
  758. element != NULL;
  759. element = cfg_list_next(element))
  760. {
  761. const char *dlv;
  762. const cfg_obj_t *dlvobj, *anchor;
  763. obj = cfg_listelt_value(element);
  764. anchor = cfg_tuple_get(obj, "trust-anchor");
  765. dlvobj = cfg_tuple_get(obj, "domain");
  766. dlv = cfg_obj_asstring(dlvobj);
  767. /*
  768. * If domain is "auto" or "no" and trust anchor
  769. * is missing, skip remaining tests
  770. */
  771. if (cfg_obj_isvoid(anchor)) {
  772. if (!strcasecmp(dlv, "no") ||
  773. !strcasecmp(dlv, "auto"))
  774. continue;
  775. }
  776. isc_buffer_init(&b, dlv, strlen(dlv));
  777. isc_buffer_add(&b, strlen(dlv));
  778. tresult = dns_name_fromtext(name, &b, dns_rootname,
  779. 0, NULL);
  780. if (tresult != ISC_R_SUCCESS) {
  781. cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
  782. "bad domain name '%s'", dlv);
  783. result = tresult;
  784. continue;
  785. }
  786. if (symtab != NULL) {
  787. tresult = nameexist(obj, dlv, 1, symtab,
  788. "dnssec-lookaside '%s': "
  789. "already exists previous "
  790. "definition: %s:%u",
  791. logctx, mctx);
  792. if (tresult != ISC_R_SUCCESS &&
  793. result == ISC_R_SUCCESS)
  794. result = tresult;
  795. }
  796. /*
  797. * XXXMPA to be removed when multiple lookaside
  798. * namespaces are supported.
  799. */
  800. if (!dns_name_equal(dns_rootname, name)) {
  801. cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
  802. "dnssec-lookaside '%s': "
  803. "non-root not yet supported", dlv);
  804. if (result == ISC_R_SUCCESS)
  805. result = ISC_R_FAILURE;
  806. }
  807. if (!cfg_obj_isvoid(anchor)) {
  808. dlv = cfg_obj_asstring(anchor);
  809. isc_buffer_init(&b, dlv, strlen(dlv));
  810. isc_buffer_add(&b, strlen(dlv));
  811. tresult = dns_name_fromtext(name, &b,
  812. dns_rootname,
  813. DNS_NAME_DOWNCASE,
  814. NULL);
  815. if (tresult != ISC_R_SUCCESS) {
  816. cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
  817. "bad domain name '%s'",
  818. dlv);
  819. if (result == ISC_R_SUCCESS)
  820. result = tresult;
  821. }
  822. } else {
  823. cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
  824. "dnssec-lookaside requires "
  825. "either 'auto' or 'no', or a "
  826. "domain and trust anchor");
  827. if (result == ISC_R_SUCCESS)
  828. result = ISC_R_FAILURE;
  829. }
  830. }
  831. if (symtab != NULL)
  832. isc_symtab_destroy(&symtab);
  833. }
  834. /*
  835. * Check auto-dnssec at the view/options level
  836. */
  837. obj = NULL;
  838. (void)cfg_map_get(options, "auto-dnssec", &obj);
  839. if (obj != NULL) {
  840. const char *arg = cfg_obj_asstring(obj);
  841. if (optlevel != optlevel_zone && strcasecmp(arg, "off") != 0) {
  842. cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
  843. "auto-dnssec may only be activated at the "
  844. "zone level");
  845. result = ISC_R_FAILURE;
  846. }
  847. }
  848. /*
  849. * Check dnssec-must-be-secure.
  850. */
  851. obj = NULL;
  852. (void)cfg_map_get(options, "dnssec-must-be-secure", &obj);
  853. if (obj != NULL) {
  854. isc_symtab_t *symtab = NULL;
  855. tresult = isc_symtab_create(mctx, 100, freekey, mctx,
  856. ISC_FALSE, &symtab);
  857. if (tresult != ISC_R_SUCCESS)
  858. result = tresult;
  859. for (element = cfg_list_first(obj);
  860. element != NULL;
  861. element = cfg_list_next(element))
  862. {
  863. obj = cfg_listelt_value(element);
  864. tresult = mustbesecure(obj, symtab, logctx, mctx);
  865. if (tresult != ISC_R_SUCCESS)
  866. result = tresult;
  867. }
  868. if (symtab != NULL)
  869. isc_symtab_destroy(&symtab);
  870. }
  871. /*
  872. * Check server/contacts for syntactic validity.
  873. */
  874. for (i= 0; server_contact[i] != NULL; i++) {
  875. obj = NULL;
  876. (void)cfg_map_get(options, server_contact[i], &obj);
  877. if (obj != NULL) {
  878. str = cfg_obj_asstring(obj);
  879. isc_buffer_init(&b, str, strlen(str));
  880. isc_buffer_add(&b, strlen(str));
  881. tresult = dns_name_fromtext(dns_fixedname_name(&fixed),
  882. &b, dns_rootname, 0, NULL);
  883. if (tresult != ISC_R_SUCCESS) {
  884. cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
  885. "%s: invalid name '%s'",
  886. server_contact[i], str);
  887. result = ISC_R_FAILURE;
  888. }
  889. }
  890. }
  891. /*
  892. * Check empty zone configuration.
  893. */
  894. obj = NULL;
  895. (void)cfg_map_get(options, "disable-empty-zone", &obj);
  896. for (element = cfg_list_first(obj);
  897. element != NULL;
  898. element = cfg_list_next(element))
  899. {
  900. obj = cfg_listelt_value(element);
  901. str = cfg_obj_asstring(obj);
  902. isc_buffer_init(&b, str, strlen(str));
  903. isc_buffer_add(&b, strlen(str));
  904. tresult = dns_name_fromtext(dns_fixedname_name(&fixed), &b,
  905. dns_rootname, 0, NULL);
  906. if (tresult != ISC_R_SUCCESS) {
  907. cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
  908. "disable-empty-zone: invalid name '%s'",
  909. str);
  910. result = ISC_R_FAILURE;
  911. }
  912. }
  913. /*
  914. * Check that server-id is not too long.
  915. * 1024 bytes should be big enough.
  916. */
  917. obj = NULL;
  918. (void)cfg_map_get(options, "server-id", &obj);
  919. if (obj != NULL && cfg_obj_isstring(obj) &&
  920. strlen(cfg_obj_asstring(obj)) > 1024U) {
  921. cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
  922. "'server-id' too big (>1024 bytes)");
  923. result = ISC_R_FAILURE;
  924. }
  925. return (result);
  926. }
  927. static isc_result_t
  928. get_masters_def(const cfg_obj_t *cctx, const char *name, const cfg_obj_t **ret) {
  929. isc_result_t result;
  930. const cfg_obj_t *masters = NULL;
  931. const cfg_listelt_t *elt;
  932. result = cfg_map_get(cctx, "masters", &masters);
  933. if (result != ISC_R_SUCCESS)
  934. return (result);
  935. for (elt = cfg_list_first(masters);
  936. elt != NULL;
  937. elt = cfg_list_next(elt)) {
  938. const cfg_obj_t *list;
  939. const char *listname;
  940. list = cfg_listelt_value(elt);
  941. listname = cfg_obj_asstring(cfg_tuple_get(list, "name"));
  942. if (strcasecmp(listname, name) == 0) {
  943. *ret = list;
  944. return (ISC_R_SUCCESS);
  945. }
  946. }
  947. return (ISC_R_NOTFOUND);
  948. }
  949. static isc_result_t
  950. validate_masters(const cfg_obj_t *obj, const cfg_obj_t *config,
  951. isc_uint32_t *countp, isc_log_t *logctx, isc_mem_t *mctx)
  952. {
  953. isc_result_t result = ISC_R_SUCCESS;
  954. isc_result_t tresult;
  955. isc_uint32_t count = 0;
  956. isc_symtab_t *symtab = NULL;
  957. isc_symvalue_t symvalue;
  958. const cfg_listelt_t *element;
  959. const cfg_listelt_t **stack = NULL;
  960. isc_uint32_t stackcount = 0, pushed = 0;
  961. const cfg_obj_t *list;
  962. REQUIRE(countp != NULL);
  963. result = isc_symtab_create(mctx, 100, NULL, NULL, ISC_FALSE, &symtab);
  964. if (result != ISC_R_SUCCESS) {
  965. *countp = count;
  966. return (result);
  967. }
  968. newlist:
  969. list = cfg_tuple_get(obj, "addresses");
  970. element = cfg_list_first(list);
  971. resume:
  972. for ( ;
  973. element != NULL;
  974. element = cfg_list_next(element))
  975. {
  976. const char *listname;
  977. const cfg_obj_t *addr;
  978. const cfg_obj_t *key;
  979. addr = cfg_tuple_get(cfg_listelt_value(element),
  980. "masterselement");
  981. key = cfg_tuple_get(cfg_listelt_value(element), "key");
  982. if (cfg_obj_issockaddr(addr)) {
  983. count++;
  984. continue;
  985. }
  986. if (!cfg_obj_isvoid(key)) {
  987. cfg_obj_log(key, logctx, ISC_LOG_ERROR,
  988. "unexpected token '%s'",
  989. cfg_obj_asstring(key));
  990. if (result == ISC_R_SUCCESS)
  991. result = ISC_R_FAILURE;
  992. }
  993. listname = cfg_obj_asstring(addr);
  994. symvalue.as_cpointer = addr;
  995. tresult = isc_symtab_define(symtab, listname, 1, symvalue,
  996. isc_symexists_reject);
  997. if (tresult == ISC_R_EXISTS)
  998. continue;
  999. tresult = get_masters_def(config, listname, &obj);
  1000. if (tresult != ISC_R_SUCCESS) {
  1001. if (result == ISC_R_SUCCESS)
  1002. result = tresult;
  1003. cfg_obj_log(addr, logctx, ISC_LOG_ERROR,
  1004. "unable to find masters list '%s'",
  1005. listname);
  1006. continue;
  1007. }
  1008. /* Grow stack? */
  1009. if (stackcount == pushed) {
  1010. void * new;
  1011. isc_uint32_t newlen = stackcount + 16;
  1012. size_t newsize, oldsize;
  1013. newsize = newlen * sizeof(*stack);
  1014. oldsize = stackcount * sizeof(*stack);
  1015. new = isc_mem_get(mctx, newsize);
  1016. if (new == NULL)
  1017. goto cleanup;
  1018. if (stackcount != 0) {
  1019. void *ptr;
  1020. DE_CONST(stack, ptr);
  1021. memcpy(new, stack, oldsize);
  1022. isc_mem_put(mctx, ptr, oldsize);
  1023. }
  1024. stack = new;
  1025. stackcount = newlen;
  1026. }
  1027. stack[pushed++] = cfg_list_next(element);
  1028. goto newlist;
  1029. }
  1030. if (pushed != 0) {
  1031. element = stack[--pushed];
  1032. goto resume;
  1033. }
  1034. cleanup:
  1035. if (stack != NULL) {
  1036. void *ptr;
  1037. DE_CONST(stack, ptr);
  1038. isc_mem_put(mctx, ptr, stackcount * sizeof(*stack));
  1039. }
  1040. isc_symtab_destroy(&symtab);
  1041. *countp = count;
  1042. return (result);
  1043. }
  1044. static isc_result_t
  1045. check_update_policy(const cfg_obj_t *policy, isc_log_t *logctx) {
  1046. isc_result_t result = ISC_R_SUCCESS;
  1047. isc_result_t tresult;
  1048. const cfg_listelt_t *element;
  1049. const cfg_listelt_t *element2;
  1050. dns_fixedname_t fixed;
  1051. const char *str;
  1052. isc_buffer_t b;
  1053. /* Check for "update-policy local;" */
  1054. if (cfg_obj_isstring(policy) &&
  1055. strcmp("local", cfg_obj_asstring(policy)) == 0)
  1056. return (ISC_R_SUCCESS);
  1057. /* Now check the grant policy */
  1058. for (element = cfg_list_first(policy);
  1059. element != NULL;
  1060. element = cfg_list_next(element))
  1061. {
  1062. const cfg_obj_t *stmt = cfg_listelt_value(element);
  1063. const cfg_obj_t *identity = cfg_tuple_get(stmt, "identity");
  1064. const cfg_obj_t *matchtype = cfg_tuple_get(stmt, "matchtype");
  1065. const cfg_obj_t *dname = cfg_tuple_get(stmt, "name");
  1066. const cfg_obj_t *typelist = cfg_tuple_get(stmt, "types");
  1067. dns_fixedname_init(&fixed);
  1068. str = cfg_obj_asstring(identity);
  1069. isc_buffer_init(&b, str, strlen(str));
  1070. isc_buffer_add(&b, strlen(str));
  1071. tresult = dns_name_fromtext(dns_fixedname_name(&fixed), &b,
  1072. dns_rootname, 0, NULL);
  1073. if (tresult != ISC_R_SUCCESS) {
  1074. cfg_obj_log(identity, logctx, ISC_LOG_ERROR,
  1075. "'%s' is not a valid name", str);
  1076. result = tresult;
  1077. }
  1078. if (tresult == ISC_R_SUCCESS &&
  1079. strcasecmp(cfg_obj_asstring(matchtype), "zonesub") != 0) {
  1080. dns_fixedname_init(&fixed);
  1081. str = cfg_obj_asstring(dname);
  1082. isc_buffer_init(&b, str, strlen(str));
  1083. isc_buffer_add(&b, strlen(str));
  1084. tresult = dns_name_fromtext(dns_fixedname_name(&fixed),
  1085. &b, dns_rootname, 0, NULL);
  1086. if (tresult != ISC_R_SUCCESS) {
  1087. cfg_obj_log(dname, logctx, ISC_LOG_ERROR,
  1088. "'%s' is not a valid name", str);
  1089. result = tresult;
  1090. }
  1091. }
  1092. if (tresult == ISC_R_SUCCESS &&
  1093. strcasecmp(cfg_obj_asstring(matchtype), "wildcard") == 0 &&
  1094. !dns_name_iswildcard(dns_fixedname_name(&fixed))) {
  1095. cfg_obj_log(identity, logctx, ISC_LOG_ERROR,
  1096. "'%s' is not a wildcard", str);
  1097. result = ISC_R_FAILURE;
  1098. }
  1099. for (element2 = cfg_list_first(typelist);
  1100. element2 != NULL;
  1101. element2 = cfg_list_next(element2))
  1102. {
  1103. const cfg_obj_t *typeobj;
  1104. isc_textregion_t r;
  1105. dns_rdatatype_t type;
  1106. typeobj = cfg_listelt_value(element2);
  1107. DE_CONST(cfg_obj_asstring(typeobj), r.base);
  1108. r.length = strlen(r.base);
  1109. tresult = dns_rdatatype_fromtext(&type, &r);
  1110. if (tresult != ISC_R_SUCCESS) {
  1111. cfg_obj_log(typeobj, logctx, ISC_LOG_ERROR,
  1112. "'%s' is not a valid type", r.base);
  1113. result = tresult;
  1114. }
  1115. }
  1116. }
  1117. return (result);
  1118. }
  1119. #define MASTERZONE 1
  1120. #define SLAVEZONE 2
  1121. #define STUBZONE 4
  1122. #define HINTZONE 8
  1123. #define FORWARDZONE 16
  1124. #define DELEGATIONZONE 32
  1125. #define STATICSTUBZONE 64
  1126. #define REDIRECTZONE 128
  1127. #define STREDIRECTZONE 0 /* Set to REDIRECTZONE to allow xfr-in. */
  1128. #define CHECKACL 512
  1129. typedef struct {
  1130. const char *name;
  1131. int allowed;
  1132. } optionstable;
  1133. static isc_result_t
  1134. check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
  1135. const cfg_obj_t *config, isc_symtab_t *symtab,
  1136. dns_rdataclass_t defclass, cfg_aclconfctx_t *actx,
  1137. isc_log_t *logctx, isc_mem_t *mctx)
  1138. {
  1139. const char *znamestr;
  1140. const char *typestr;
  1141. unsigned int ztype;
  1142. const cfg_obj_t *zoptions;
  1143. const cfg_obj_t *obj = NULL;
  1144. isc_result_t result = ISC_R_SUCCESS;
  1145. isc_result_t tresult;
  1146. unsigned int i;
  1147. dns_rdataclass_t zclass;
  1148. dns_fixedname_t fixedname;
  1149. dns_name_t *zname = NULL;
  1150. isc_buffer_t b;
  1151. isc_boolean_t root = ISC_FALSE;
  1152. const cfg_listelt_t *element;
  1153. static optionstable options[] = {
  1154. { "allow-query", MASTERZONE | SLAVEZONE | STUBZONE | REDIRECTZONE |
  1155. CHECKACL | STATICSTUBZONE },
  1156. { "allow-notify", SLAVEZONE | CHECKACL },
  1157. { "allow-transfer", MASTERZONE | SLAVEZONE | CHECKACL },
  1158. { "notify", MASTERZONE | SLAVEZONE },
  1159. { "also-notify", MASTERZONE | SLAVEZONE },
  1160. { "dialup", MASTERZONE | SLAVEZONE | STUBZONE | STREDIRECTZONE },
  1161. { "delegation-only", HINTZONE | STUBZONE | DELEGATIONZONE },
  1162. { "forward", MASTERZONE | SLAVEZONE | STUBZONE | FORWARDZONE },
  1163. { "forwarders", MASTERZONE | SLAVEZONE | STUBZONE | FORWARDZONE },
  1164. { "maintain-ixfr-base", MASTERZONE | SLAVEZONE | STREDIRECTZONE },
  1165. { "max-ixfr-log-size", MASTERZONE | SLAVEZONE | STREDIRECTZONE },
  1166. { "notify-source", MASTERZONE | SLAVEZONE },
  1167. { "notify-source-v6", MASTERZONE | SLAVEZONE },
  1168. { "transfer-source", SLAVEZONE | STUBZONE | STREDIRECTZONE },
  1169. { "transfer-source-v6", SLAVEZONE | STUBZONE | STREDIRECTZONE },
  1170. { "max-transfer-time-in", SLAVEZONE | STUBZONE | STREDIRECTZONE },
  1171. { "max-transfer-time-out", MASTERZONE | SLAVEZONE },
  1172. { "max-transfer-idle-in", SLAVEZONE | STUBZONE | STREDIRECTZONE },
  1173. { "max-transfer-idle-out", MASTERZONE | SLAVEZONE },
  1174. { "max-retry-time", SLAVEZONE | STUBZONE | STREDIRECTZONE },
  1175. { "min-retry-time", SLAVEZONE | STUBZONE | STREDIRECTZONE },
  1176. { "max-refresh-time", SLAVEZONE | STUBZONE | STREDIRECTZONE },
  1177. { "min-refresh-time", SLAVEZONE | STUBZONE | STREDIRECTZONE },
  1178. { "dnssec-secure-to-insecure", MASTERZONE },
  1179. { "sig-re-signing-interval", MASTERZONE | SLAVEZONE },
  1180. { "sig-signing-nodes", MASTERZONE | SLAVEZONE },
  1181. { "sig-signing-signatures", MASTERZONE | SLAVEZONE },
  1182. { "sig-signing-type", MASTERZONE | SLAVEZONE },
  1183. { "sig-validity-interval", MASTERZONE | SLAVEZONE },
  1184. { "signing", MASTERZONE | SLAVEZONE },
  1185. { "zone-statistics", MASTERZONE | SLAVEZONE | STUBZONE |
  1186. STATICSTUBZONE | REDIRECTZONE },
  1187. { "allow-update", MASTERZONE | CHECKACL },
  1188. { "allow-update-forwarding", SLAVEZONE | CHECKACL },
  1189. { "file", MASTERZONE | SLAVEZONE | STUBZONE | HINTZONE | REDIRECTZONE },
  1190. { "journal", MASTERZONE | SLAVEZONE | STREDIRECTZONE },
  1191. { "ixfr-base", MASTERZONE | SLAVEZONE },
  1192. { "ixfr-tmp-file", MASTERZONE | SLAVEZONE },
  1193. { "masters", SLAVEZONE | STUBZONE | REDIRECTZONE },
  1194. { "pubkey", MASTERZONE | SLAVEZONE | STUBZONE },
  1195. { "update-policy", MASTERZONE },
  1196. { "database", MASTERZONE | SLAVEZONE | STUBZONE | REDIRECTZONE },
  1197. { "key-directory", MASTERZONE | SLAVEZONE },
  1198. { "check-wildcard", MASTERZONE },
  1199. { "check-mx", MASTERZONE },
  1200. { "check-dup-records", MASTERZONE },
  1201. { "integrity-check", MASTERZONE },
  1202. { "check-mx-cname", MASTERZONE },
  1203. { "check-srv-cname", MASTERZONE },
  1204. { "masterfile-format", MASTERZONE | SLAVEZONE | STUBZONE | HINTZONE |
  1205. REDIRECTZONE },
  1206. { "update-check-ksk", MASTERZONE },
  1207. { "dnssec-dnskey-kskonly", MASTERZONE },
  1208. { "dnssec-loadkeys-interval", MASTERZONE },
  1209. { "auto-dnssec", MASTERZONE | SLAVEZONE },
  1210. { "try-tcp-refresh", SLAVEZONE | STREDIRECTZONE },
  1211. { "server-addresses", STATICSTUBZONE },
  1212. { "server-names", STATICSTUBZONE },
  1213. };
  1214. static optionstable dialups[] = {
  1215. { "notify", MASTERZONE | SLAVEZONE | STREDIRECTZONE },
  1216. { "notify-passive", SLAVEZONE | STREDIRECTZONE },
  1217. { "refresh", SLAVEZONE | STUBZONE | STREDIRECTZONE },
  1218. { "passive", SLAVEZONE | STUBZONE | STREDIRECTZONE },
  1219. };
  1220. znamestr = cfg_obj_asstring(cfg_tuple_get(zconfig, "name"));
  1221. zoptions = cfg_tuple_get(zconfig, "options");
  1222. obj = NULL;
  1223. (void)cfg_map_get(zoptions, "type", &obj);
  1224. if (obj == NULL) {
  1225. cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR,
  1226. "zone '%s': type not present", znamestr);
  1227. return (ISC_R_FAILURE);
  1228. }
  1229. typestr = cfg_obj_asstring(obj);
  1230. if (strcasecmp(typestr, "master") == 0)
  1231. ztype = MASTERZONE;
  1232. else if (strcasecmp(typestr, "slave") == 0)
  1233. ztype = SLAVEZONE;
  1234. else if (strcasecmp(typestr, "stub") == 0)
  1235. ztype = STUBZONE;
  1236. else if (strcasecmp(typestr, "static-stub") == 0)
  1237. ztype = STATICSTUBZONE;
  1238. else if (strcasecmp(typestr, "forward") == 0)
  1239. ztype = FORWARDZONE;
  1240. else if (strcasecmp(typestr, "hint") == 0)
  1241. ztype = HINTZONE;
  1242. else if (strcasecmp(typestr, "delegation-only") == 0)
  1243. ztype = DELEGATIONZONE;
  1244. else if (strcasecmp(typestr, "redirect") == 0)
  1245. ztype = REDIRECTZONE;
  1246. else {
  1247. cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
  1248. "zone '%s': invalid type %s",
  1249. znamestr, typestr);
  1250. return (ISC_R_FAILURE);
  1251. }
  1252. if (ztype == REDIRECTZONE && strcmp(znamestr, ".") != 0) {
  1253. cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR,
  1254. "redirect zones must be called \".\"");
  1255. return (ISC_R_FAILURE);
  1256. }
  1257. obj = cfg_tuple_get(zconfig, "class");
  1258. if (cfg_obj_isstring(obj)) {
  1259. isc_textregion_t r;
  1260. DE_CONST(cfg_obj_asstring(obj), r.base);
  1261. r.length = strlen(r.base);
  1262. result = dns_rdataclass_fromtext(&zclass, &r);
  1263. if (result != ISC_R_SUCCESS) {
  1264. cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
  1265. "zone '%s': invalid class %s",
  1266. znamestr, r.base);
  1267. return (ISC_R_FAILURE);
  1268. }
  1269. if (zclass != defclass) {
  1270. cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
  1271. "zone '%s': class '%s' does not "
  1272. "match view/default class",
  1273. znamestr, r.base);
  1274. return (ISC_R_FAILURE);
  1275. }
  1276. }
  1277. /*
  1278. * Look for an already existing zone.
  1279. * We need to make this canonical as isc_symtab_define()
  1280. * deals with strings.
  1281. */
  1282. dns_fixedname_init(&fixedname);
  1283. isc_buffer_init(&b, znamestr, strlen(znamestr));
  1284. isc_buffer_add(&b, strlen(znamestr));
  1285. tresult = dns_name_fromtext(dns_fixedname_name(&fixedname), &b,
  1286. dns_rootname, DNS_NAME_DOWNCASE, NULL);
  1287. if (tresult != ISC_R_SUCCESS) {
  1288. cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR,
  1289. "zone '%s': is not a valid name", znamestr);
  1290. result = ISC_R_FAILURE;
  1291. } else {
  1292. char namebuf[DNS_NAME_FORMATSIZE];
  1293. zname = dns_fixedname_name(&fixedname);
  1294. dns_name_format(zname, namebuf, sizeof(namebuf));
  1295. tresult = nameexist(zconfig, namebuf, ztype == HINTZONE ? 1 :
  1296. ztype == REDIRECTZONE ? 2 : 3,
  1297. symtab, "zone '%s': already exists "
  1298. "previous definition: %s:%u", logctx, mctx);
  1299. if (tresult != ISC_R_SUCCESS)
  1300. result = tresult;
  1301. if (dns_name_equal(zname, dns_rootname))
  1302. root = ISC_TRUE;
  1303. }
  1304. /*
  1305. * Look for inappropriate options for the given zone type.
  1306. * Check that ACLs expand correctly.
  1307. */
  1308. for (i = 0; i < sizeof(options) / sizeof(options[0]); i++) {
  1309. obj = NULL;
  1310. if ((options[i].allowed & ztype) == 0 &&
  1311. cfg_map_get(zoptions, options[i].name, &obj) ==
  1312. ISC_R_SUCCESS)
  1313. {
  1314. if (strcmp(options[i].name, "allow-update") != 0 ||
  1315. ztype != SLAVEZONE) {
  1316. cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
  1317. "option '%s' is not allowed "
  1318. "in '%s' zone '%s'",
  1319. options[i].name, typestr,
  1320. znamestr);
  1321. result = ISC_R_FAILURE;
  1322. } else
  1323. cfg_obj_log(obj, logctx, ISC_LOG_WARNING,
  1324. "option '%s' is not allowed "
  1325. "in '%s' zone '%s'",
  1326. options[i].name, typestr,
  1327. znamestr);
  1328. }
  1329. obj = NULL;
  1330. if ((options[i].allowed & ztype) != 0 &&
  1331. (options[i].allowed & CHECKACL) != 0) {
  1332. tresult = checkacl(options[i].name, actx, zconfig,
  1333. voptions, config, logctx, mctx);
  1334. if (tresult != ISC_R_SUCCESS)
  1335. result = tresult;
  1336. }
  1337. }
  1338. /*
  1339. * Slave & stub zones must have a "masters" field.
  1340. */
  1341. if (ztype == SLAVEZONE || ztype == STUBZONE) {
  1342. obj = NULL;
  1343. if (cfg_map_get(zoptions, "masters", &obj) != ISC_R_SUCCESS) {
  1344. cfg_obj_log(zoptions, logctx, ISC_LOG_ERROR,
  1345. "zone '%s': missing 'masters' entry",
  1346. znamestr);
  1347. result = ISC_R_FAILURE;
  1348. } else {
  1349. isc_uint32_t count;
  1350. tresult = validate_masters(obj, config, &count,
  1351. logctx, mctx);
  1352. if (tresult != ISC_R_SUCCESS && result == ISC_R_SUCCESS)
  1353. result = tresult;
  1354. if (tresult == ISC_R_SUCCESS && count == 0) {
  1355. cfg_obj_log(zoptions, logctx, ISC_LOG_ERROR,
  1356. "zone '%s': empty 'masters' entry",
  1357. znamestr);
  1358. result = ISC_R_FAILURE;
  1359. }
  1360. }
  1361. }
  1362. /*
  1363. * Master zones can't have both "allow-update" and "update-policy".
  1364. */
  1365. if (ztype == MASTERZONE || ztype == SLAVEZONE) {
  1366. isc_result_t res1, res2, res3;
  1367. const char *arg;
  1368. isc_boolean_t ddns = ISC_FALSE, signing = ISC_FALSE;
  1369. obj = NULL;
  1370. res1 = cfg_map_get(zoptions, "allow-update", &obj);
  1371. obj = NULL;
  1372. res2 = cfg_map_get(zoptions, "update-policy", &obj);
  1373. if (res1 == ISC_R_SUCCESS && res2 == ISC_R_SUCCESS) {
  1374. cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
  1375. "zone '%s': 'allow-update' is ignored "
  1376. "when 'update-policy' is present",
  1377. znamestr);
  1378. result = ISC_R_FAILURE;
  1379. } else if (res2 == ISC_R_SUCCESS &&
  1380. check_update_policy(obj, logctx) != ISC_R_SUCCESS)
  1381. result = ISC_R_FAILURE;
  1382. ddns = ISC_TF(res1 == ISC_R_SUCCESS || res2 == ISC_R_SUCCESS);
  1383. obj = NULL;
  1384. res1 = cfg_map_get(zoptions, "inline-signing", &obj);
  1385. if (res1 == ISC_R_SUCCESS)
  1386. signing = cfg_obj_asboolean(obj);
  1387. obj = NULL;
  1388. arg = "off";
  1389. res3 = cfg_map_get(zoptions, "auto-dnssec", &obj);
  1390. if (res3 == ISC_R_SUCCESS)
  1391. arg = cfg_obj_asstring(obj);
  1392. if (strcasecmp(arg, "off") != 0 && !ddns && !signing) {
  1393. cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
  1394. "'auto-dnssec %s;' requires%s "
  1395. "inline-signing to be configured for "
  1396. "the zone", arg,
  1397. (ztype == MASTERZONE) ?
  1398. " dynamic DNS or" : "");
  1399. result = ISC_R_FAILURE;
  1400. }
  1401. if (strcasecmp(arg, "create") == 0) {
  1402. cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
  1403. "'auto-dnssec create;' is not "
  1404. "yet implemented");
  1405. result = ISC_R_FAILURE;
  1406. }
  1407. obj = NULL;
  1408. res1 = cfg_map_get(zoptions, "sig-signing-type", &obj);
  1409. if (res1 == ISC_R_SUCCESS) {
  1410. isc_uint32_t type = cfg_obj_asuint32(obj);
  1411. if (type < 0xff00U || type > 0xffffU)
  1412. cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
  1413. "sig-signing-type: %u out of "
  1414. "range [%u..%u]", type,
  1415. 0xff00U, 0xffffU);
  1416. result = ISC_R_FAILURE;
  1417. }
  1418. }
  1419. /*
  1420. * Check the excessively complicated "dialup" option.
  1421. */
  1422. if (ztype == MASTERZONE || ztype == SLAVEZONE || ztype == STUBZONE) {
  1423. const cfg_obj_t *dialup = NULL;
  1424. (void)cfg_map_get(zoptions, "dialup", &dialup);
  1425. if (dialup != NULL && cfg_obj_isstring(dialup)) {
  1426. const char *str = cfg_obj_asstring(dialup);
  1427. for (i = 0;
  1428. i < sizeof(dialups) / sizeof(dialups[0]);
  1429. i++)
  1430. {
  1431. if (strcasecmp(dialups[i].name, str) != 0)
  1432. continue;
  1433. if ((dialups[i].allowed & ztype) == 0) {
  1434. cfg_obj_log(obj, logctx,
  1435. ISC_LOG_ERROR,
  1436. "dialup type '%s' is not "
  1437. "allowed in '%s' "
  1438. "zone '%s'",
  1439. str, typestr, znamestr);
  1440. result = ISC_R_FAILURE;
  1441. }
  1442. break;
  1443. }
  1444. if (i == sizeof(dialups) / sizeof(dialups[0])) {
  1445. cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
  1446. "invalid dialup type '%s' in zone "
  1447. "'%s'", str, znamestr);
  1448. result = ISC_R_FAILURE;
  1449. }
  1450. }
  1451. }
  1452. /*
  1453. * Check that forwarding is reasonable.
  1454. */
  1455. obj = NULL;
  1456. if (root) {
  1457. if (voptions != NULL)
  1458. (void)cfg_map_get(voptions, "forwarders", &obj);
  1459. if (obj == NULL) {
  1460. const cfg_obj_t *options = NULL;
  1461. (void)cfg_map_get(config, "options", &options);
  1462. if (options != NULL)
  1463. (void)cfg_map_get(options, "forwarders", &obj);
  1464. }
  1465. }
  1466. if (check_forward(zoptions, obj, logctx) != ISC_R_SUCCESS)
  1467. result = ISC_R_FAILURE;
  1468. /*
  1469. * Check validity of static stub server addresses.
  1470. */
  1471. obj = NULL;
  1472. (void)cfg_map_get(zoptions, "server-addresses", &obj);
  1473. if (ztype == STATICSTUBZONE && obj != NULL) {
  1474. for (element = cfg_list_first(obj);
  1475. element != NULL;
  1476. element = cfg_list_next(element))
  1477. {
  1478. isc_sockaddr_t sa;
  1479. isc_netaddr_t na;
  1480. obj = cfg_listelt_value(element);
  1481. sa = *cfg_obj_assockaddr(obj);
  1482. if (isc_sockaddr_getport(&sa) != 0) {
  1483. result = ISC_R_FAILURE;
  1484. cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
  1485. "port is not configurable for "
  1486. "static stub server-addresses");
  1487. }
  1488. isc_netaddr_fromsockaddr(&na, &sa);
  1489. if (isc_netaddr_getzone(&na) != 0) {
  1490. result = ISC_R_FAILURE;
  1491. cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
  1492. "scoped address is not allowed "
  1493. "for static stub "
  1494. "server-addresses");
  1495. }
  1496. }
  1497. }
  1498. /*
  1499. * Check validity of static stub server names.
  1500. */
  1501. obj = NULL;
  1502. (void)cfg_map_get(zoptions, "server-names", &obj);
  1503. if (zname != NULL && ztype == STATICSTUBZONE && obj != NULL) {
  1504. for (element = cfg_list_first(obj);
  1505. element != NULL;
  1506. element = cfg_list_next(element))
  1507. {
  1508. const char *snamestr;
  1509. dns_fixedname_t fixed_sname;
  1510. isc_buffer_t b2;
  1511. dns_name_t *sname;
  1512. obj = cfg_listelt_value(element);
  1513. snamestr = cfg_obj_asstring(obj);
  1514. dns_fixedname_init(&fixed_sname);
  1515. isc_buffer_init(&b2, snamestr, strlen(snamestr));
  1516. isc_buffer_add(&b2, strlen(snamestr));
  1517. sname = dns_fixedname_name(&fixed_sname);
  1518. tresult = dns_name_fromtext(sname, &b2, dns_rootname,
  1519. 0, NULL);
  1520. if (tresult != ISC_R_SUCCESS) {
  1521. cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR,
  1522. "server-name '%s' is not a valid "
  1523. "name", snamestr);
  1524. result = ISC_R_FAILURE;
  1525. } else if (dns_name_issubdomain(sname, zname)) {
  1526. cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR,
  1527. "server-name '%s' must not be a "
  1528. "subdomain of zone name '%s'",
  1529. snamestr, znamestr);
  1530. result = ISC_R_FAILURE;
  1531. }
  1532. }
  1533. }
  1534. /*
  1535. * Check various options.
  1536. */
  1537. tresult = check_options(zoptions, logctx, mctx, optlevel_zone);
  1538. if (tresult != ISC_R_SUCCESS)
  1539. result = tresult;
  1540. /*
  1541. * If the zone type is rbt/rbt64 then master/hint zones
  1542. * require file clauses.
  1543. */
  1544. obj = NULL;
  1545. tresult = cfg_map_get(zoptions, "database", &obj);
  1546. if (tresult == ISC_R_NOTFOUND ||
  1547. (tresult == ISC_R_SUCCESS &&
  1548. (strcmp("rbt", cfg_obj_asstring(obj)) == 0 ||
  1549. strcmp("rbt64", cfg_obj_asstring(obj)) == 0))) {
  1550. obj = NULL;
  1551. tresult = cfg_map_get(zoptions, "file", &obj);
  1552. if (tresult != ISC_R_SUCCESS &&
  1553. (ztype == MASTERZONE || ztype == HINTZONE)) {
  1554. cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR,
  1555. "zone '%s': missing 'file' entry",
  1556. znamestr);
  1557. result = tresult;
  1558. }
  1559. }
  1560. return (result);
  1561. }
  1562. typedef struct keyalgorithms {
  1563. const char *name;
  1564. isc_uint16_t size;
  1565. } algorithmtable;
  1566. isc_result_t
  1567. bind9_check_key(const cfg_obj_t *key, isc_log_t *logctx) {
  1568. const cfg_obj_t *algobj = NULL;
  1569. const cfg_obj_t *secretobj = NULL;
  1570. const char *keyname = cfg_obj_asstring(cfg_map_getname(key));
  1571. const char *algorithm;
  1572. int i;
  1573. size_t len = 0;
  1574. isc_result_t result;
  1575. isc_buffer_t buf;
  1576. unsigned char secretbuf[1024];
  1577. static const algorithmtable algorithms[] = {
  1578. { "hmac-md5", 128 },
  1579. { "hmac-md5.sig-alg.reg.int", 0 },
  1580. { "hmac-md5.sig-alg.reg.int.", 0 },
  1581. { "hmac-sha1", 160 },
  1582. { "hmac-sha224", 224 },
  1583. { "hmac-sha256", 256 },
  1584. { "hmac-sha384", 384 },
  1585. { "hmac-sha512", 512 },
  1586. { NULL, 0 }
  1587. };
  1588. (void)cfg_map_get(key, "algorithm", &algobj);
  1589. (void)cfg_map_get(key, "secret", &secretobj);
  1590. if (secretobj == NULL || algobj == NULL) {
  1591. cfg_obj_log(key, logctx, ISC_LOG_ERROR,
  1592. "key '%s' must have both 'secret' and "
  1593. "'algorithm' defined",
  1594. keyname);
  1595. return (ISC_R_FAILURE);
  1596. }
  1597. isc_buffer_init(&buf, secretbuf, sizeof(secretbuf));
  1598. result = isc_base64_decodestring(cfg_obj_asstring(secretobj), &buf);
  1599. if (result != ISC_R_SUCCESS) {
  1600. cfg_obj_log(secretobj, logctx, ISC_LOG_ERROR,
  1601. "bad secret '%s'", isc_result_totext(result));
  1602. r

Large files files are truncated, but you can click here to view the full file