/contrib/bind9/bin/named/config.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 855 lines · 746 code · 79 blank · 30 comment · 182 complexity · 73bbe39786e9360eee01c72188599234 MD5 · raw file

  1. /*
  2. * Copyright (C) 2004-2011 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: config.c,v 1.113.16.2 2011/02/28 01:19:58 tbox Exp $ */
  18. /*! \file */
  19. #include <config.h>
  20. #include <stdlib.h>
  21. #include <isc/buffer.h>
  22. #include <isc/log.h>
  23. #include <isc/mem.h>
  24. #include <isc/parseint.h>
  25. #include <isc/region.h>
  26. #include <isc/result.h>
  27. #include <isc/sockaddr.h>
  28. #include <isc/string.h>
  29. #include <isc/util.h>
  30. #include <isccfg/namedconf.h>
  31. #include <dns/fixedname.h>
  32. #include <dns/name.h>
  33. #include <dns/rdataclass.h>
  34. #include <dns/rdatatype.h>
  35. #include <dns/tsig.h>
  36. #include <dns/zone.h>
  37. #include <dst/dst.h>
  38. #include <named/config.h>
  39. #include <named/globals.h>
  40. #include "bind.keys.h"
  41. /*% default configuration */
  42. static char defaultconf[] = "\
  43. options {\n\
  44. # blackhole {none;};\n"
  45. #ifndef WIN32
  46. " coresize default;\n\
  47. datasize default;\n\
  48. files unlimited;\n\
  49. stacksize default;\n"
  50. #endif
  51. "# session-keyfile \"" NS_LOCALSTATEDIR "/run/named/session.key\";\n\
  52. session-keyname local-ddns;\n\
  53. session-keyalg hmac-sha256;\n\
  54. deallocate-on-exit true;\n\
  55. # directory <none>\n\
  56. dump-file \"named_dump.db\";\n\
  57. fake-iquery no;\n\
  58. has-old-clients false;\n\
  59. heartbeat-interval 60;\n\
  60. host-statistics no;\n\
  61. interface-interval 60;\n\
  62. listen-on {any;};\n\
  63. listen-on-v6 {none;};\n\
  64. match-mapped-addresses no;\n\
  65. memstatistics-file \"named.memstats\";\n\
  66. multiple-cnames no;\n\
  67. # named-xfer <obsolete>;\n\
  68. # pid-file \"" NS_LOCALSTATEDIR "/run/named/named.pid\"; /* or /lwresd.pid */\n\
  69. bindkeys-file \"" NS_SYSCONFDIR "/bind.keys\";\n\
  70. port 53;\n\
  71. recursing-file \"named.recursing\";\n\
  72. secroots-file \"named.secroots\";\n\
  73. "
  74. #ifdef PATH_RANDOMDEV
  75. "\
  76. random-device \"" PATH_RANDOMDEV "\";\n\
  77. "
  78. #endif
  79. "\
  80. recursive-clients 1000;\n\
  81. resolver-query-timeout 30;\n\
  82. rrset-order {type NS order random; order cyclic; };\n\
  83. serial-queries 20;\n\
  84. serial-query-rate 20;\n\
  85. server-id none;\n\
  86. statistics-file \"named.stats\";\n\
  87. statistics-interval 60;\n\
  88. tcp-clients 100;\n\
  89. tcp-listen-queue 3;\n\
  90. # tkey-dhkey <none>\n\
  91. # tkey-gssapi-credential <none>\n\
  92. # tkey-domain <none>\n\
  93. transfers-per-ns 2;\n\
  94. transfers-in 10;\n\
  95. transfers-out 10;\n\
  96. treat-cr-as-space true;\n\
  97. use-id-pool true;\n\
  98. use-ixfr true;\n\
  99. edns-udp-size 4096;\n\
  100. max-udp-size 4096;\n\
  101. request-nsid false;\n\
  102. reserved-sockets 512;\n\
  103. \n\
  104. /* DLV */\n\
  105. dnssec-lookaside . trust-anchor dlv.isc.org;\n\
  106. \n\
  107. /* view */\n\
  108. allow-notify {none;};\n\
  109. allow-update-forwarding {none;};\n\
  110. allow-query-cache { localnets; localhost; };\n\
  111. allow-query-cache-on { any; };\n\
  112. allow-recursion { localnets; localhost; };\n\
  113. allow-recursion-on { any; };\n\
  114. # allow-v6-synthesis <obsolete>;\n\
  115. # sortlist <none>\n\
  116. # topology <none>\n\
  117. auth-nxdomain false;\n\
  118. minimal-responses false;\n\
  119. recursion true;\n\
  120. provide-ixfr true;\n\
  121. request-ixfr true;\n\
  122. fetch-glue no;\n\
  123. rfc2308-type1 no;\n\
  124. additional-from-auth true;\n\
  125. additional-from-cache true;\n\
  126. query-source address *;\n\
  127. query-source-v6 address *;\n\
  128. notify-source *;\n\
  129. notify-source-v6 *;\n\
  130. cleaning-interval 0; /* now meaningless */\n\
  131. min-roots 2;\n\
  132. lame-ttl 600;\n\
  133. max-ncache-ttl 10800; /* 3 hours */\n\
  134. max-cache-ttl 604800; /* 1 week */\n\
  135. transfer-format many-answers;\n\
  136. max-cache-size 0;\n\
  137. check-names master fail;\n\
  138. check-names slave warn;\n\
  139. check-names response ignore;\n\
  140. check-dup-records warn;\n\
  141. check-mx warn;\n\
  142. acache-enable no;\n\
  143. acache-cleaning-interval 60;\n\
  144. max-acache-size 16M;\n\
  145. dnssec-enable yes;\n\
  146. dnssec-validation yes; \n\
  147. dnssec-accept-expired no;\n\
  148. clients-per-query 10;\n\
  149. max-clients-per-query 100;\n\
  150. zero-no-soa-ttl-cache no;\n\
  151. nsec3-test-zone no;\n\
  152. allow-new-zones no;\n\
  153. "
  154. #ifdef ALLOW_FILTER_AAAA_ON_V4
  155. " filter-aaaa-on-v4 no;\n\
  156. filter-aaaa { any; };\n\
  157. "
  158. #endif
  159. " /* zone */\n\
  160. allow-query {any;};\n\
  161. allow-query-on {any;};\n\
  162. allow-transfer {any;};\n\
  163. notify yes;\n\
  164. # also-notify <none>\n\
  165. notify-delay 5;\n\
  166. notify-to-soa no;\n\
  167. dialup no;\n\
  168. # forward <none>\n\
  169. # forwarders <none>\n\
  170. maintain-ixfr-base no;\n\
  171. # max-ixfr-log-size <obsolete>\n\
  172. transfer-source *;\n\
  173. transfer-source-v6 *;\n\
  174. alt-transfer-source *;\n\
  175. alt-transfer-source-v6 *;\n\
  176. max-transfer-time-in 120;\n\
  177. max-transfer-time-out 120;\n\
  178. max-transfer-idle-in 60;\n\
  179. max-transfer-idle-out 60;\n\
  180. max-retry-time 1209600; /* 2 weeks */\n\
  181. min-retry-time 500;\n\
  182. max-refresh-time 2419200; /* 4 weeks */\n\
  183. min-refresh-time 300;\n\
  184. multi-master no;\n\
  185. dnssec-secure-to-insecure no;\n\
  186. sig-validity-interval 30; /* days */\n\
  187. sig-signing-nodes 100;\n\
  188. sig-signing-signatures 10;\n\
  189. sig-signing-type 65534;\n\
  190. zone-statistics false;\n\
  191. max-journal-size unlimited;\n\
  192. ixfr-from-differences false;\n\
  193. check-wildcard yes;\n\
  194. check-sibling yes;\n\
  195. check-integrity yes;\n\
  196. check-mx-cname warn;\n\
  197. check-srv-cname warn;\n\
  198. zero-no-soa-ttl yes;\n\
  199. update-check-ksk yes;\n\
  200. dnssec-dnskey-kskonly no;\n\
  201. try-tcp-refresh yes; /* BIND 8 compat */\n\
  202. };\n\
  203. "
  204. "#\n\
  205. # Zones in the \"_bind\" view are NOT counted in the count of zones.\n\
  206. #\n\
  207. view \"_bind\" chaos {\n\
  208. recursion no;\n\
  209. notify no;\n\
  210. allow-new-zones no;\n\
  211. \n\
  212. zone \"version.bind\" chaos {\n\
  213. type master;\n\
  214. database \"_builtin version\";\n\
  215. };\n\
  216. \n\
  217. zone \"hostname.bind\" chaos {\n\
  218. type master;\n\
  219. database \"_builtin hostname\";\n\
  220. };\n\
  221. \n\
  222. zone \"authors.bind\" chaos {\n\
  223. type master;\n\
  224. database \"_builtin authors\";\n\
  225. };\n\
  226. \n\
  227. zone \"id.server\" chaos {\n\
  228. type master;\n\
  229. database \"_builtin id\";\n\
  230. };\n\
  231. };\n\
  232. "
  233. "#\n\
  234. # Default trusted key(s) for builtin DLV support\n\
  235. # (used if \"dnssec-lookaside auto;\" is set and\n\
  236. # sysconfdir/bind.keys doesn't exist).\n\
  237. #\n\
  238. # BEGIN MANAGED KEYS\n"
  239. /* Imported from bind.keys.h: */
  240. MANAGED_KEYS
  241. "# END MANAGED KEYS\n\
  242. ";
  243. isc_result_t
  244. ns_config_parsedefaults(cfg_parser_t *parser, cfg_obj_t **conf) {
  245. isc_buffer_t b;
  246. isc_buffer_init(&b, defaultconf, sizeof(defaultconf) - 1);
  247. isc_buffer_add(&b, sizeof(defaultconf) - 1);
  248. return (cfg_parse_buffer(parser, &b, &cfg_type_namedconf, conf));
  249. }
  250. isc_result_t
  251. ns_config_get(const cfg_obj_t **maps, const char *name, const cfg_obj_t **obj) {
  252. int i;
  253. for (i = 0;; i++) {
  254. if (maps[i] == NULL)
  255. return (ISC_R_NOTFOUND);
  256. if (cfg_map_get(maps[i], name, obj) == ISC_R_SUCCESS)
  257. return (ISC_R_SUCCESS);
  258. }
  259. }
  260. isc_result_t
  261. ns_checknames_get(const cfg_obj_t **maps, const char *which,
  262. const cfg_obj_t **obj)
  263. {
  264. const cfg_listelt_t *element;
  265. const cfg_obj_t *checknames;
  266. const cfg_obj_t *type;
  267. const cfg_obj_t *value;
  268. int i;
  269. for (i = 0;; i++) {
  270. if (maps[i] == NULL)
  271. return (ISC_R_NOTFOUND);
  272. checknames = NULL;
  273. if (cfg_map_get(maps[i], "check-names", &checknames) == ISC_R_SUCCESS) {
  274. /*
  275. * Zone map entry is not a list.
  276. */
  277. if (checknames != NULL && !cfg_obj_islist(checknames)) {
  278. *obj = checknames;
  279. return (ISC_R_SUCCESS);
  280. }
  281. for (element = cfg_list_first(checknames);
  282. element != NULL;
  283. element = cfg_list_next(element)) {
  284. value = cfg_listelt_value(element);
  285. type = cfg_tuple_get(value, "type");
  286. if (strcasecmp(cfg_obj_asstring(type), which) == 0) {
  287. *obj = cfg_tuple_get(value, "mode");
  288. return (ISC_R_SUCCESS);
  289. }
  290. }
  291. }
  292. }
  293. }
  294. int
  295. ns_config_listcount(const cfg_obj_t *list) {
  296. const cfg_listelt_t *e;
  297. int i = 0;
  298. for (e = cfg_list_first(list); e != NULL; e = cfg_list_next(e))
  299. i++;
  300. return (i);
  301. }
  302. isc_result_t
  303. ns_config_getclass(const cfg_obj_t *classobj, dns_rdataclass_t defclass,
  304. dns_rdataclass_t *classp) {
  305. isc_textregion_t r;
  306. isc_result_t result;
  307. if (!cfg_obj_isstring(classobj)) {
  308. *classp = defclass;
  309. return (ISC_R_SUCCESS);
  310. }
  311. DE_CONST(cfg_obj_asstring(classobj), r.base);
  312. r.length = strlen(r.base);
  313. result = dns_rdataclass_fromtext(classp, &r);
  314. if (result != ISC_R_SUCCESS)
  315. cfg_obj_log(classobj, ns_g_lctx, ISC_LOG_ERROR,
  316. "unknown class '%s'", r.base);
  317. return (result);
  318. }
  319. isc_result_t
  320. ns_config_gettype(const cfg_obj_t *typeobj, dns_rdatatype_t deftype,
  321. dns_rdatatype_t *typep) {
  322. isc_textregion_t r;
  323. isc_result_t result;
  324. if (!cfg_obj_isstring(typeobj)) {
  325. *typep = deftype;
  326. return (ISC_R_SUCCESS);
  327. }
  328. DE_CONST(cfg_obj_asstring(typeobj), r.base);
  329. r.length = strlen(r.base);
  330. result = dns_rdatatype_fromtext(typep, &r);
  331. if (result != ISC_R_SUCCESS)
  332. cfg_obj_log(typeobj, ns_g_lctx, ISC_LOG_ERROR,
  333. "unknown type '%s'", r.base);
  334. return (result);
  335. }
  336. dns_zonetype_t
  337. ns_config_getzonetype(const cfg_obj_t *zonetypeobj) {
  338. dns_zonetype_t ztype = dns_zone_none;
  339. const char *str;
  340. str = cfg_obj_asstring(zonetypeobj);
  341. if (strcasecmp(str, "master") == 0)
  342. ztype = dns_zone_master;
  343. else if (strcasecmp(str, "slave") == 0)
  344. ztype = dns_zone_slave;
  345. else if (strcasecmp(str, "stub") == 0)
  346. ztype = dns_zone_stub;
  347. else if (strcasecmp(str, "static-stub") == 0)
  348. ztype = dns_zone_staticstub;
  349. else
  350. INSIST(0);
  351. return (ztype);
  352. }
  353. isc_result_t
  354. ns_config_getiplist(const cfg_obj_t *config, const cfg_obj_t *list,
  355. in_port_t defport, isc_mem_t *mctx,
  356. isc_sockaddr_t **addrsp, isc_uint32_t *countp)
  357. {
  358. int count, i = 0;
  359. const cfg_obj_t *addrlist;
  360. const cfg_obj_t *portobj;
  361. const cfg_listelt_t *element;
  362. isc_sockaddr_t *addrs;
  363. in_port_t port;
  364. isc_result_t result;
  365. INSIST(addrsp != NULL && *addrsp == NULL);
  366. INSIST(countp != NULL);
  367. addrlist = cfg_tuple_get(list, "addresses");
  368. count = ns_config_listcount(addrlist);
  369. portobj = cfg_tuple_get(list, "port");
  370. if (cfg_obj_isuint32(portobj)) {
  371. isc_uint32_t val = cfg_obj_asuint32(portobj);
  372. if (val > ISC_UINT16_MAX) {
  373. cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR,
  374. "port '%u' out of range", val);
  375. return (ISC_R_RANGE);
  376. }
  377. port = (in_port_t) val;
  378. } else if (defport != 0)
  379. port = defport;
  380. else {
  381. result = ns_config_getport(config, &port);
  382. if (result != ISC_R_SUCCESS)
  383. return (result);
  384. }
  385. addrs = isc_mem_get(mctx, count * sizeof(isc_sockaddr_t));
  386. if (addrs == NULL)
  387. return (ISC_R_NOMEMORY);
  388. for (element = cfg_list_first(addrlist);
  389. element != NULL;
  390. element = cfg_list_next(element), i++)
  391. {
  392. INSIST(i < count);
  393. addrs[i] = *cfg_obj_assockaddr(cfg_listelt_value(element));
  394. if (isc_sockaddr_getport(&addrs[i]) == 0)
  395. isc_sockaddr_setport(&addrs[i], port);
  396. }
  397. INSIST(i == count);
  398. *addrsp = addrs;
  399. *countp = count;
  400. return (ISC_R_SUCCESS);
  401. }
  402. void
  403. ns_config_putiplist(isc_mem_t *mctx, isc_sockaddr_t **addrsp,
  404. isc_uint32_t count)
  405. {
  406. INSIST(addrsp != NULL && *addrsp != NULL);
  407. isc_mem_put(mctx, *addrsp, count * sizeof(isc_sockaddr_t));
  408. *addrsp = NULL;
  409. }
  410. static isc_result_t
  411. get_masters_def(const cfg_obj_t *cctx, const char *name,
  412. const cfg_obj_t **ret)
  413. {
  414. isc_result_t result;
  415. const cfg_obj_t *masters = NULL;
  416. const cfg_listelt_t *elt;
  417. result = cfg_map_get(cctx, "masters", &masters);
  418. if (result != ISC_R_SUCCESS)
  419. return (result);
  420. for (elt = cfg_list_first(masters);
  421. elt != NULL;
  422. elt = cfg_list_next(elt)) {
  423. const cfg_obj_t *list;
  424. const char *listname;
  425. list = cfg_listelt_value(elt);
  426. listname = cfg_obj_asstring(cfg_tuple_get(list, "name"));
  427. if (strcasecmp(listname, name) == 0) {
  428. *ret = list;
  429. return (ISC_R_SUCCESS);
  430. }
  431. }
  432. return (ISC_R_NOTFOUND);
  433. }
  434. isc_result_t
  435. ns_config_getipandkeylist(const cfg_obj_t *config, const cfg_obj_t *list,
  436. isc_mem_t *mctx, isc_sockaddr_t **addrsp,
  437. dns_name_t ***keysp, isc_uint32_t *countp)
  438. {
  439. isc_uint32_t addrcount = 0, keycount = 0, i = 0;
  440. isc_uint32_t listcount = 0, l = 0, j;
  441. isc_uint32_t stackcount = 0, pushed = 0;
  442. isc_result_t result;
  443. const cfg_listelt_t *element;
  444. const cfg_obj_t *addrlist;
  445. const cfg_obj_t *portobj;
  446. in_port_t port;
  447. dns_fixedname_t fname;
  448. isc_sockaddr_t *addrs = NULL;
  449. dns_name_t **keys = NULL;
  450. struct { const char *name; } *lists = NULL;
  451. struct {
  452. const cfg_listelt_t *element;
  453. in_port_t port;
  454. } *stack = NULL;
  455. REQUIRE(addrsp != NULL && *addrsp == NULL);
  456. REQUIRE(keysp != NULL && *keysp == NULL);
  457. REQUIRE(countp != NULL);
  458. newlist:
  459. addrlist = cfg_tuple_get(list, "addresses");
  460. portobj = cfg_tuple_get(list, "port");
  461. if (cfg_obj_isuint32(portobj)) {
  462. isc_uint32_t val = cfg_obj_asuint32(portobj);
  463. if (val > ISC_UINT16_MAX) {
  464. cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR,
  465. "port '%u' out of range", val);
  466. result = ISC_R_RANGE;
  467. goto cleanup;
  468. }
  469. port = (in_port_t) val;
  470. } else {
  471. result = ns_config_getport(config, &port);
  472. if (result != ISC_R_SUCCESS)
  473. goto cleanup;
  474. }
  475. result = ISC_R_NOMEMORY;
  476. element = cfg_list_first(addrlist);
  477. resume:
  478. for ( ;
  479. element != NULL;
  480. element = cfg_list_next(element))
  481. {
  482. const cfg_obj_t *addr;
  483. const cfg_obj_t *key;
  484. const char *keystr;
  485. isc_buffer_t b;
  486. addr = cfg_tuple_get(cfg_listelt_value(element),
  487. "masterselement");
  488. key = cfg_tuple_get(cfg_listelt_value(element), "key");
  489. if (!cfg_obj_issockaddr(addr)) {
  490. const char *listname = cfg_obj_asstring(addr);
  491. isc_result_t tresult;
  492. /* Grow lists? */
  493. if (listcount == l) {
  494. void * new;
  495. isc_uint32_t newlen = listcount + 16;
  496. size_t newsize, oldsize;
  497. newsize = newlen * sizeof(*lists);
  498. oldsize = listcount * sizeof(*lists);
  499. new = isc_mem_get(mctx, newsize);
  500. if (new == NULL)
  501. goto cleanup;
  502. if (listcount != 0) {
  503. memcpy(new, lists, oldsize);
  504. isc_mem_put(mctx, lists, oldsize);
  505. }
  506. lists = new;
  507. listcount = newlen;
  508. }
  509. /* Seen? */
  510. for (j = 0; j < l; j++)
  511. if (strcasecmp(lists[j].name, listname) == 0)
  512. break;
  513. if (j < l)
  514. continue;
  515. tresult = get_masters_def(config, listname, &list);
  516. if (tresult == ISC_R_NOTFOUND) {
  517. cfg_obj_log(addr, ns_g_lctx, ISC_LOG_ERROR,
  518. "masters \"%s\" not found", listname);
  519. result = tresult;
  520. goto cleanup;
  521. }
  522. if (tresult != ISC_R_SUCCESS)
  523. goto cleanup;
  524. lists[l++].name = listname;
  525. /* Grow stack? */
  526. if (stackcount == pushed) {
  527. void * new;
  528. isc_uint32_t newlen = stackcount + 16;
  529. size_t newsize, oldsize;
  530. newsize = newlen * sizeof(*stack);
  531. oldsize = stackcount * sizeof(*stack);
  532. new = isc_mem_get(mctx, newsize);
  533. if (new == NULL)
  534. goto cleanup;
  535. if (stackcount != 0) {
  536. memcpy(new, stack, oldsize);
  537. isc_mem_put(mctx, stack, oldsize);
  538. }
  539. stack = new;
  540. stackcount = newlen;
  541. }
  542. /*
  543. * We want to resume processing this list on the
  544. * next element.
  545. */
  546. stack[pushed].element = cfg_list_next(element);
  547. stack[pushed].port = port;
  548. pushed++;
  549. goto newlist;
  550. }
  551. if (i == addrcount) {
  552. void * new;
  553. isc_uint32_t newlen = addrcount + 16;
  554. size_t newsize, oldsize;
  555. newsize = newlen * sizeof(isc_sockaddr_t);
  556. oldsize = addrcount * sizeof(isc_sockaddr_t);
  557. new = isc_mem_get(mctx, newsize);
  558. if (new == NULL)
  559. goto cleanup;
  560. if (addrcount != 0) {
  561. memcpy(new, addrs, oldsize);
  562. isc_mem_put(mctx, addrs, oldsize);
  563. }
  564. addrs = new;
  565. addrcount = newlen;
  566. newsize = newlen * sizeof(dns_name_t *);
  567. oldsize = keycount * sizeof(dns_name_t *);
  568. new = isc_mem_get(mctx, newsize);
  569. if (new == NULL)
  570. goto cleanup;
  571. if (keycount != 0) {
  572. memcpy(new, keys, oldsize);
  573. isc_mem_put(mctx, keys, oldsize);
  574. }
  575. keys = new;
  576. keycount = newlen;
  577. }
  578. addrs[i] = *cfg_obj_assockaddr(addr);
  579. if (isc_sockaddr_getport(&addrs[i]) == 0)
  580. isc_sockaddr_setport(&addrs[i], port);
  581. keys[i] = NULL;
  582. if (!cfg_obj_isstring(key)) {
  583. i++;
  584. continue;
  585. }
  586. keys[i] = isc_mem_get(mctx, sizeof(dns_name_t));
  587. if (keys[i] == NULL)
  588. goto cleanup;
  589. dns_name_init(keys[i], NULL);
  590. keystr = cfg_obj_asstring(key);
  591. isc_buffer_init(&b, keystr, strlen(keystr));
  592. isc_buffer_add(&b, strlen(keystr));
  593. dns_fixedname_init(&fname);
  594. result = dns_name_fromtext(dns_fixedname_name(&fname), &b,
  595. dns_rootname, 0, NULL);
  596. if (result != ISC_R_SUCCESS)
  597. goto cleanup;
  598. result = dns_name_dup(dns_fixedname_name(&fname), mctx,
  599. keys[i]);
  600. if (result != ISC_R_SUCCESS)
  601. goto cleanup;
  602. i++;
  603. }
  604. if (pushed != 0) {
  605. pushed--;
  606. element = stack[pushed].element;
  607. port = stack[pushed].port;
  608. goto resume;
  609. }
  610. if (i < addrcount) {
  611. void * new;
  612. size_t newsize, oldsize;
  613. newsize = i * sizeof(isc_sockaddr_t);
  614. oldsize = addrcount * sizeof(isc_sockaddr_t);
  615. if (i != 0) {
  616. new = isc_mem_get(mctx, newsize);
  617. if (new == NULL)
  618. goto cleanup;
  619. memcpy(new, addrs, newsize);
  620. } else
  621. new = NULL;
  622. isc_mem_put(mctx, addrs, oldsize);
  623. addrs = new;
  624. addrcount = i;
  625. newsize = i * sizeof(dns_name_t *);
  626. oldsize = keycount * sizeof(dns_name_t *);
  627. if (i != 0) {
  628. new = isc_mem_get(mctx, newsize);
  629. if (new == NULL)
  630. goto cleanup;
  631. memcpy(new, keys, newsize);
  632. } else
  633. new = NULL;
  634. isc_mem_put(mctx, keys, oldsize);
  635. keys = new;
  636. keycount = i;
  637. }
  638. if (lists != NULL)
  639. isc_mem_put(mctx, lists, listcount * sizeof(*lists));
  640. if (stack != NULL)
  641. isc_mem_put(mctx, stack, stackcount * sizeof(*stack));
  642. INSIST(keycount == addrcount);
  643. *addrsp = addrs;
  644. *keysp = keys;
  645. *countp = addrcount;
  646. return (ISC_R_SUCCESS);
  647. cleanup:
  648. if (addrs != NULL)
  649. isc_mem_put(mctx, addrs, addrcount * sizeof(isc_sockaddr_t));
  650. if (keys != NULL) {
  651. for (j = 0; j <= i; j++) {
  652. if (keys[j] == NULL)
  653. continue;
  654. if (dns_name_dynamic(keys[j]))
  655. dns_name_free(keys[j], mctx);
  656. isc_mem_put(mctx, keys[j], sizeof(dns_name_t));
  657. }
  658. isc_mem_put(mctx, keys, keycount * sizeof(dns_name_t *));
  659. }
  660. if (lists != NULL)
  661. isc_mem_put(mctx, lists, listcount * sizeof(*lists));
  662. if (stack != NULL)
  663. isc_mem_put(mctx, stack, stackcount * sizeof(*stack));
  664. return (result);
  665. }
  666. void
  667. ns_config_putipandkeylist(isc_mem_t *mctx, isc_sockaddr_t **addrsp,
  668. dns_name_t ***keysp, isc_uint32_t count)
  669. {
  670. unsigned int i;
  671. dns_name_t **keys = *keysp;
  672. INSIST(addrsp != NULL && *addrsp != NULL);
  673. isc_mem_put(mctx, *addrsp, count * sizeof(isc_sockaddr_t));
  674. for (i = 0; i < count; i++) {
  675. if (keys[i] == NULL)
  676. continue;
  677. if (dns_name_dynamic(keys[i]))
  678. dns_name_free(keys[i], mctx);
  679. isc_mem_put(mctx, keys[i], sizeof(dns_name_t));
  680. }
  681. isc_mem_put(mctx, *keysp, count * sizeof(dns_name_t *));
  682. *addrsp = NULL;
  683. *keysp = NULL;
  684. }
  685. isc_result_t
  686. ns_config_getport(const cfg_obj_t *config, in_port_t *portp) {
  687. const cfg_obj_t *maps[3];
  688. const cfg_obj_t *options = NULL;
  689. const cfg_obj_t *portobj = NULL;
  690. isc_result_t result;
  691. int i;
  692. (void)cfg_map_get(config, "options", &options);
  693. i = 0;
  694. if (options != NULL)
  695. maps[i++] = options;
  696. maps[i++] = ns_g_defaults;
  697. maps[i] = NULL;
  698. result = ns_config_get(maps, "port", &portobj);
  699. INSIST(result == ISC_R_SUCCESS);
  700. if (cfg_obj_asuint32(portobj) >= ISC_UINT16_MAX) {
  701. cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR,
  702. "port '%u' out of range",
  703. cfg_obj_asuint32(portobj));
  704. return (ISC_R_RANGE);
  705. }
  706. *portp = (in_port_t)cfg_obj_asuint32(portobj);
  707. return (ISC_R_SUCCESS);
  708. }
  709. struct keyalgorithms {
  710. const char *str;
  711. enum { hmacnone, hmacmd5, hmacsha1, hmacsha224,
  712. hmacsha256, hmacsha384, hmacsha512 } hmac;
  713. unsigned int type;
  714. isc_uint16_t size;
  715. } algorithms[] = {
  716. { "hmac-md5", hmacmd5, DST_ALG_HMACMD5, 128 },
  717. { "hmac-md5.sig-alg.reg.int", hmacmd5, DST_ALG_HMACMD5, 0 },
  718. { "hmac-md5.sig-alg.reg.int.", hmacmd5, DST_ALG_HMACMD5, 0 },
  719. { "hmac-sha1", hmacsha1, DST_ALG_HMACSHA1, 160 },
  720. { "hmac-sha224", hmacsha224, DST_ALG_HMACSHA224, 224 },
  721. { "hmac-sha256", hmacsha256, DST_ALG_HMACSHA256, 256 },
  722. { "hmac-sha384", hmacsha384, DST_ALG_HMACSHA384, 384 },
  723. { "hmac-sha512", hmacsha512, DST_ALG_HMACSHA512, 512 },
  724. { NULL, hmacnone, DST_ALG_UNKNOWN, 0 }
  725. };
  726. isc_result_t
  727. ns_config_getkeyalgorithm(const char *str, dns_name_t **name,
  728. isc_uint16_t *digestbits)
  729. {
  730. return (ns_config_getkeyalgorithm2(str, name, NULL, digestbits));
  731. }
  732. isc_result_t
  733. ns_config_getkeyalgorithm2(const char *str, dns_name_t **name,
  734. unsigned int *typep, isc_uint16_t *digestbits)
  735. {
  736. int i;
  737. size_t len = 0;
  738. isc_uint16_t bits;
  739. isc_result_t result;
  740. for (i = 0; algorithms[i].str != NULL; i++) {
  741. len = strlen(algorithms[i].str);
  742. if (strncasecmp(algorithms[i].str, str, len) == 0 &&
  743. (str[len] == '\0' ||
  744. (algorithms[i].size != 0 && str[len] == '-')))
  745. break;
  746. }
  747. if (algorithms[i].str == NULL)
  748. return (ISC_R_NOTFOUND);
  749. if (str[len] == '-') {
  750. result = isc_parse_uint16(&bits, str + len + 1, 10);
  751. if (result != ISC_R_SUCCESS)
  752. return (result);
  753. if (bits > algorithms[i].size)
  754. return (ISC_R_RANGE);
  755. } else if (algorithms[i].size == 0)
  756. bits = 128;
  757. else
  758. bits = algorithms[i].size;
  759. if (name != NULL) {
  760. switch (algorithms[i].hmac) {
  761. case hmacmd5: *name = dns_tsig_hmacmd5_name; break;
  762. case hmacsha1: *name = dns_tsig_hmacsha1_name; break;
  763. case hmacsha224: *name = dns_tsig_hmacsha224_name; break;
  764. case hmacsha256: *name = dns_tsig_hmacsha256_name; break;
  765. case hmacsha384: *name = dns_tsig_hmacsha384_name; break;
  766. case hmacsha512: *name = dns_tsig_hmacsha512_name; break;
  767. default:
  768. INSIST(0);
  769. }
  770. }
  771. if (typep != NULL)
  772. *typep = algorithms[i].type;
  773. if (digestbits != NULL)
  774. *digestbits = bits;
  775. return (ISC_R_SUCCESS);
  776. }