/contrib/bind9/lib/dns/rdata/generic/hip_55.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 506 lines · 350 code · 99 blank · 57 comment · 91 complexity · 5e2a4653a02e53b1a8240f6d0ae2e06d MD5 · raw file

  1. /*
  2. * Copyright (C) 2009, 2011 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: hip_55.c,v 1.8 2011/01/13 04:59:26 tbox Exp $ */
  17. /* reviewed: TBC */
  18. /* RFC 5205 */
  19. #ifndef RDATA_GENERIC_HIP_5_C
  20. #define RDATA_GENERIC_HIP_5_C
  21. #define RRTYPE_HIP_ATTRIBUTES (0)
  22. static inline isc_result_t
  23. fromtext_hip(ARGS_FROMTEXT) {
  24. isc_token_t token;
  25. dns_name_t name;
  26. isc_buffer_t buffer;
  27. isc_buffer_t hit_len;
  28. isc_buffer_t key_len;
  29. unsigned char *start;
  30. size_t len;
  31. REQUIRE(type == 55);
  32. UNUSED(type);
  33. UNUSED(rdclass);
  34. UNUSED(callbacks);
  35. /*
  36. * Dummy HIT len.
  37. */
  38. hit_len = *target;
  39. RETERR(uint8_tobuffer(0, target));
  40. /*
  41. * Algorithm.
  42. */
  43. RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number,
  44. ISC_FALSE));
  45. if (token.value.as_ulong > 0xffU)
  46. RETTOK(ISC_R_RANGE);
  47. RETERR(uint8_tobuffer(token.value.as_ulong, target));
  48. /*
  49. * Dummy KEY len.
  50. */
  51. key_len = *target;
  52. RETERR(uint16_tobuffer(0, target));
  53. /*
  54. * HIT (base16).
  55. */
  56. start = isc_buffer_used(target);
  57. RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
  58. ISC_FALSE));
  59. RETTOK(isc_hex_decodestring(DNS_AS_STR(token), target));
  60. /*
  61. * Fill in HIT len.
  62. */
  63. len = (unsigned char *)isc_buffer_used(target) - start;
  64. if (len > 0xffU)
  65. RETTOK(ISC_R_RANGE);
  66. RETERR(uint8_tobuffer(len, &hit_len));
  67. /*
  68. * Public key (base64).
  69. */
  70. start = isc_buffer_used(target);
  71. RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string,
  72. ISC_FALSE));
  73. RETTOK(isc_base64_decodestring(DNS_AS_STR(token), target));
  74. /*
  75. * Fill in KEY len.
  76. */
  77. len = (unsigned char *)isc_buffer_used(target) - start;
  78. if (len > 0xffffU)
  79. RETTOK(ISC_R_RANGE);
  80. RETERR(uint16_tobuffer(len, &key_len));
  81. /*
  82. * Rendezvous Servers.
  83. */
  84. dns_name_init(&name, NULL);
  85. do {
  86. RETERR(isc_lex_getmastertoken(lexer, &token,
  87. isc_tokentype_string,
  88. ISC_TRUE));
  89. if (token.type != isc_tokentype_string)
  90. break;
  91. buffer_fromregion(&buffer, &token.value.as_region);
  92. origin = (origin != NULL) ? origin : dns_rootname;
  93. RETTOK(dns_name_fromtext(&name, &buffer, origin, options,
  94. target));
  95. } while (1);
  96. /*
  97. * Let upper layer handle eol/eof.
  98. */
  99. isc_lex_ungettoken(lexer, &token);
  100. return (ISC_R_SUCCESS);
  101. }
  102. static inline isc_result_t
  103. totext_hip(ARGS_TOTEXT) {
  104. isc_region_t region;
  105. dns_name_t name;
  106. size_t length, key_len, hit_len;
  107. unsigned char algorithm;
  108. char buf[sizeof("225 ")];
  109. REQUIRE(rdata->type == 55);
  110. REQUIRE(rdata->length != 0);
  111. dns_rdata_toregion(rdata, &region);
  112. hit_len = uint8_fromregion(&region);
  113. isc_region_consume(&region, 1);
  114. algorithm = uint8_fromregion(&region);
  115. isc_region_consume(&region, 1);
  116. key_len = uint16_fromregion(&region);
  117. isc_region_consume(&region, 2);
  118. if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
  119. RETERR(str_totext("( ", target));
  120. /*
  121. * Algorithm
  122. */
  123. sprintf(buf, "%u ", algorithm);
  124. RETERR(str_totext(buf, target));
  125. /*
  126. * HIT.
  127. */
  128. INSIST(hit_len < region.length);
  129. length = region.length;
  130. region.length = hit_len;
  131. RETERR(isc_hex_totext(&region, 1, "", target));
  132. region.length = length - hit_len;
  133. RETERR(str_totext(tctx->linebreak, target));
  134. /*
  135. * Public KEY.
  136. */
  137. INSIST(key_len <= region.length);
  138. length = region.length;
  139. region.length = key_len;
  140. RETERR(isc_base64_totext(&region, 1, "", target));
  141. region.length = length - key_len;
  142. RETERR(str_totext(tctx->linebreak, target));
  143. /*
  144. * Rendezvous Servers.
  145. */
  146. dns_name_init(&name, NULL);
  147. while (region.length > 0) {
  148. dns_name_fromregion(&name, &region);
  149. RETERR(dns_name_totext(&name, ISC_FALSE, target));
  150. isc_region_consume(&region, name.length);
  151. if (region.length > 0)
  152. RETERR(str_totext(tctx->linebreak, target));
  153. }
  154. if ((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0)
  155. RETERR(str_totext(" )", target));
  156. return (ISC_R_SUCCESS);
  157. }
  158. static inline isc_result_t
  159. fromwire_hip(ARGS_FROMWIRE) {
  160. isc_region_t region, rr;
  161. dns_name_t name;
  162. isc_uint8_t hit_len;
  163. isc_uint16_t key_len;
  164. REQUIRE(type == 55);
  165. UNUSED(type);
  166. UNUSED(rdclass);
  167. isc_buffer_activeregion(source, &region);
  168. if (region.length < 4U)
  169. RETERR(DNS_R_FORMERR);
  170. rr = region;
  171. hit_len = uint8_fromregion(&region);
  172. if (hit_len == 0)
  173. RETERR(DNS_R_FORMERR);
  174. isc_region_consume(&region, 2); /* hit length + algorithm */
  175. key_len = uint16_fromregion(&region);
  176. if (key_len == 0)
  177. RETERR(DNS_R_FORMERR);
  178. isc_region_consume(&region, 2);
  179. if (region.length < (unsigned) (hit_len + key_len))
  180. RETERR(DNS_R_FORMERR);
  181. RETERR(mem_tobuffer(target, rr.base, 4 + hit_len + key_len));
  182. isc_buffer_forward(source, 4 + hit_len + key_len);
  183. dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE);
  184. while (isc_buffer_activelength(source) > 0) {
  185. dns_name_init(&name, NULL);
  186. RETERR(dns_name_fromwire(&name, source, dctx, options, target));
  187. }
  188. return (ISC_R_SUCCESS);
  189. }
  190. static inline isc_result_t
  191. towire_hip(ARGS_TOWIRE) {
  192. isc_region_t region;
  193. REQUIRE(rdata->type == 55);
  194. REQUIRE(rdata->length != 0);
  195. UNUSED(cctx);
  196. dns_rdata_toregion(rdata, &region);
  197. return (mem_tobuffer(target, region.base, region.length));
  198. }
  199. static inline int
  200. compare_hip(ARGS_COMPARE) {
  201. isc_region_t region1;
  202. isc_region_t region2;
  203. REQUIRE(rdata1->type == rdata2->type);
  204. REQUIRE(rdata1->rdclass == rdata2->rdclass);
  205. REQUIRE(rdata1->type == 55);
  206. REQUIRE(rdata1->length != 0);
  207. REQUIRE(rdata2->length != 0);
  208. dns_rdata_toregion(rdata1, &region1);
  209. dns_rdata_toregion(rdata2, &region2);
  210. return (isc_region_compare(&region1, &region2));
  211. }
  212. static inline isc_result_t
  213. fromstruct_hip(ARGS_FROMSTRUCT) {
  214. dns_rdata_hip_t *hip = source;
  215. dns_rdata_hip_t myhip;
  216. isc_result_t result;
  217. REQUIRE(type == 55);
  218. REQUIRE(source != NULL);
  219. REQUIRE(hip->common.rdtype == type);
  220. REQUIRE(hip->common.rdclass == rdclass);
  221. REQUIRE(hip->hit_len > 0 && hip->hit != NULL);
  222. REQUIRE(hip->key_len > 0 && hip->key != NULL);
  223. REQUIRE((hip->servers == NULL && hip->servers_len == 0) ||
  224. (hip->servers != NULL && hip->servers_len != 0));
  225. UNUSED(type);
  226. UNUSED(rdclass);
  227. RETERR(uint8_tobuffer(hip->hit_len, target));
  228. RETERR(uint8_tobuffer(hip->algorithm, target));
  229. RETERR(uint16_tobuffer(hip->key_len, target));
  230. RETERR(mem_tobuffer(target, hip->hit, hip->hit_len));
  231. RETERR(mem_tobuffer(target, hip->key, hip->key_len));
  232. myhip = *hip;
  233. for (result = dns_rdata_hip_first(&myhip);
  234. result == ISC_R_SUCCESS;
  235. result = dns_rdata_hip_next(&myhip))
  236. /* empty */;
  237. return(mem_tobuffer(target, hip->servers, hip->servers_len));
  238. }
  239. static inline isc_result_t
  240. tostruct_hip(ARGS_TOSTRUCT) {
  241. isc_region_t region;
  242. dns_rdata_hip_t *hip = target;
  243. REQUIRE(rdata->type == 55);
  244. REQUIRE(target != NULL);
  245. REQUIRE(rdata->length != 0);
  246. hip->common.rdclass = rdata->rdclass;
  247. hip->common.rdtype = rdata->type;
  248. ISC_LINK_INIT(&hip->common, link);
  249. dns_rdata_toregion(rdata, &region);
  250. hip->hit_len = uint8_fromregion(&region);
  251. isc_region_consume(&region, 1);
  252. hip->algorithm = uint8_fromregion(&region);
  253. isc_region_consume(&region, 1);
  254. hip->key_len = uint16_fromregion(&region);
  255. isc_region_consume(&region, 2);
  256. hip->hit = hip->key = hip->servers = NULL;
  257. hip->hit = mem_maybedup(mctx, region.base, hip->hit_len);
  258. if (hip->hit == NULL)
  259. goto cleanup;
  260. isc_region_consume(&region, hip->hit_len);
  261. hip->key = mem_maybedup(mctx, region.base, hip->key_len);
  262. if (hip->key == NULL)
  263. goto cleanup;
  264. isc_region_consume(&region, hip->key_len);
  265. hip->servers_len = region.length;
  266. if (hip->servers_len != 0) {
  267. hip->servers = mem_maybedup(mctx, region.base, region.length);
  268. if (hip->servers == NULL)
  269. goto cleanup;
  270. }
  271. hip->offset = hip->servers_len;
  272. hip->mctx = mctx;
  273. return (ISC_R_SUCCESS);
  274. cleanup:
  275. if (hip->hit != NULL)
  276. isc_mem_free(mctx, hip->hit);
  277. if (hip->key != NULL)
  278. isc_mem_free(mctx, hip->key);
  279. if (hip->servers != NULL)
  280. isc_mem_free(mctx, hip->servers);
  281. return (ISC_R_NOMEMORY);
  282. }
  283. static inline void
  284. freestruct_hip(ARGS_FREESTRUCT) {
  285. dns_rdata_hip_t *hip = source;
  286. REQUIRE(source != NULL);
  287. if (hip->mctx == NULL)
  288. return;
  289. isc_mem_free(hip->mctx, hip->hit);
  290. isc_mem_free(hip->mctx, hip->key);
  291. if (hip->servers != NULL)
  292. isc_mem_free(hip->mctx, hip->servers);
  293. hip->mctx = NULL;
  294. }
  295. static inline isc_result_t
  296. additionaldata_hip(ARGS_ADDLDATA) {
  297. UNUSED(rdata);
  298. UNUSED(add);
  299. UNUSED(arg);
  300. REQUIRE(rdata->type == 55);
  301. return (ISC_R_SUCCESS);
  302. }
  303. static inline isc_result_t
  304. digest_hip(ARGS_DIGEST) {
  305. isc_region_t r;
  306. REQUIRE(rdata->type == 55);
  307. dns_rdata_toregion(rdata, &r);
  308. return ((digest)(arg, &r));
  309. }
  310. static inline isc_boolean_t
  311. checkowner_hip(ARGS_CHECKOWNER) {
  312. REQUIRE(type == 55);
  313. UNUSED(name);
  314. UNUSED(type);
  315. UNUSED(rdclass);
  316. UNUSED(wildcard);
  317. return (ISC_TRUE);
  318. }
  319. static inline isc_boolean_t
  320. checknames_hip(ARGS_CHECKNAMES) {
  321. REQUIRE(rdata->type == 55);
  322. UNUSED(rdata);
  323. UNUSED(owner);
  324. UNUSED(bad);
  325. return (ISC_TRUE);
  326. }
  327. isc_result_t
  328. dns_rdata_hip_first(dns_rdata_hip_t *hip) {
  329. if (hip->servers_len == 0)
  330. return (ISC_R_NOMORE);
  331. hip->offset = 0;
  332. return (ISC_R_SUCCESS);
  333. }
  334. isc_result_t
  335. dns_rdata_hip_next(dns_rdata_hip_t *hip) {
  336. isc_region_t region;
  337. dns_name_t name;
  338. if (hip->offset >= hip->servers_len)
  339. return (ISC_R_NOMORE);
  340. region.base = hip->servers + hip->offset;
  341. region.length = hip->servers_len - hip->offset;
  342. dns_name_init(&name, NULL);
  343. dns_name_fromregion(&name, &region);
  344. hip->offset += name.length;
  345. INSIST(hip->offset <= hip->servers_len);
  346. return (ISC_R_SUCCESS);
  347. }
  348. void
  349. dns_rdata_hip_current(dns_rdata_hip_t *hip, dns_name_t *name) {
  350. isc_region_t region;
  351. REQUIRE(hip->offset < hip->servers_len);
  352. region.base = hip->servers + hip->offset;
  353. region.length = hip->servers_len - hip->offset;
  354. dns_name_fromregion(name, &region);
  355. INSIST(name->length + hip->offset <= hip->servers_len);
  356. }
  357. static inline int
  358. casecompare_hip(ARGS_COMPARE) {
  359. isc_region_t r1;
  360. isc_region_t r2;
  361. dns_name_t name1;
  362. dns_name_t name2;
  363. int order;
  364. isc_uint8_t hit_len;
  365. isc_uint16_t key_len;
  366. REQUIRE(rdata1->type == rdata2->type);
  367. REQUIRE(rdata1->rdclass == rdata2->rdclass);
  368. REQUIRE(rdata1->type == 55);
  369. REQUIRE(rdata1->length != 0);
  370. REQUIRE(rdata2->length != 0);
  371. dns_rdata_toregion(rdata1, &r1);
  372. dns_rdata_toregion(rdata2, &r2);
  373. INSIST(r1.length > 4);
  374. INSIST(r2.length > 4);
  375. r1.length = 4;
  376. r2.length = 4;
  377. order = isc_region_compare(&r1, &r2);
  378. if (order != 0)
  379. return (order);
  380. hit_len = uint8_fromregion(&r1);
  381. isc_region_consume(&r1, 2); /* hit length + algorithm */
  382. key_len = uint16_fromregion(&r1);
  383. dns_rdata_toregion(rdata1, &r1);
  384. dns_rdata_toregion(rdata2, &r2);
  385. isc_region_consume(&r1, 4);
  386. isc_region_consume(&r2, 4);
  387. INSIST(r1.length >= (unsigned) (hit_len + key_len));
  388. INSIST(r2.length >= (unsigned) (hit_len + key_len));
  389. order = isc_region_compare(&r1, &r2);
  390. if (order != 0)
  391. return (order);
  392. isc_region_consume(&r1, hit_len + key_len);
  393. isc_region_consume(&r2, hit_len + key_len);
  394. dns_name_init(&name1, NULL);
  395. dns_name_init(&name2, NULL);
  396. while (r1.length != 0 && r2.length != 0) {
  397. dns_name_fromregion(&name1, &r1);
  398. dns_name_fromregion(&name2, &r2);
  399. order = dns_name_rdatacompare(&name1, &name2);
  400. if (order != 0)
  401. return (order);
  402. isc_region_consume(&r1, name_length(&name1));
  403. isc_region_consume(&r2, name_length(&name2));
  404. }
  405. return (isc_region_compare(&r1, &r2));
  406. }
  407. #endif /* RDATA_GENERIC_HIP_5_C */