Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

parse.c 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. /* Copyright (c) 2014, Vsevolod Stakhov
  2. * All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions are met:
  6. * * Redistributions of source code must retain the above copyright
  7. * notice, this list of conditions and the following disclaimer.
  8. * * Redistributions in binary form must reproduce the above copyright
  9. * notice, this list of conditions and the following disclaimer in the
  10. * documentation and/or other materials provided with the distribution.
  11. *
  12. * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
  13. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  14. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  15. * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
  16. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  17. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  18. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  19. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  20. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  21. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  22. */
  23. #include "rdns.h"
  24. #include "dns_private.h"
  25. #include "parse.h"
  26. #include "logger.h"
  27. static uint8_t *
  28. rdns_decompress_label (uint8_t *begin, uint16_t *len, uint16_t max)
  29. {
  30. uint16_t offset = (*len);
  31. if (offset > max) {
  32. return NULL;
  33. }
  34. *len = *(begin + offset);
  35. return begin + offset;
  36. }
  37. #define UNCOMPRESS_DNS_OFFSET(p) (((*(p)) ^ DNS_COMPRESSION_BITS) << 8) + *((p) + 1)
  38. uint8_t *
  39. rdns_request_reply_cmp (struct rdns_request *req, uint8_t *in, int len)
  40. {
  41. uint8_t *p, *c, *l1, *l2;
  42. uint16_t len1, len2;
  43. int decompressed = 0;
  44. struct rdns_resolver *resolver = req->resolver;
  45. /* QR format:
  46. * labels - len:octets
  47. * null label - 0
  48. * class - 2 octets
  49. * type - 2 octets
  50. */
  51. /* In p we would store current position in reply and in c - position in request */
  52. p = in;
  53. c = req->packet + req->pos;
  54. for (;;) {
  55. /* Get current label */
  56. len1 = *p;
  57. len2 = *c;
  58. if (p - in > len) {
  59. rdns_info ("invalid dns reply");
  60. return NULL;
  61. }
  62. /* This may be compressed, so we need to decompress it */
  63. if (len1 & DNS_COMPRESSION_BITS) {
  64. len1 = UNCOMPRESS_DNS_OFFSET(p);
  65. l1 = rdns_decompress_label (in, &len1, len);
  66. if (l1 == NULL) {
  67. return NULL;
  68. }
  69. decompressed ++;
  70. l1 ++;
  71. p += 2;
  72. }
  73. else {
  74. l1 = ++p;
  75. p += len1;
  76. }
  77. if (len2 & DNS_COMPRESSION_BITS) {
  78. len2 = UNCOMPRESS_DNS_OFFSET(c);
  79. l2 = rdns_decompress_label (c, &len2, len);
  80. if (l2 == NULL) {
  81. rdns_info ("invalid DNS pointer, cannot decompress");
  82. return NULL;
  83. }
  84. decompressed ++;
  85. l2 ++;
  86. c += 2;
  87. }
  88. else {
  89. l2 = ++c;
  90. c += len2;
  91. }
  92. if (len1 != len2) {
  93. return NULL;
  94. }
  95. if (len1 == 0) {
  96. break;
  97. }
  98. if (memcmp (l1, l2, len1) != 0) {
  99. return NULL;
  100. }
  101. if (decompressed == 2) {
  102. break;
  103. }
  104. }
  105. /* p now points to the end of QR section */
  106. /* Compare class and type */
  107. if (memcmp (p, c, sizeof (uint16_t) * 2) == 0) {
  108. req->pos = c - req->packet + sizeof (uint16_t) * 2;
  109. return p + sizeof (uint16_t) * 2;
  110. }
  111. return NULL;
  112. }
  113. #define MAX_RECURSION_LEVEL 10
  114. bool
  115. rdns_parse_labels (struct rdns_resolver *resolver,
  116. uint8_t *in, char **target, uint8_t **pos, struct rdns_reply *rep,
  117. int *remain, bool make_name)
  118. {
  119. uint16_t namelen = 0;
  120. uint8_t *p = *pos, *begin = *pos, *l, *t, *end = *pos + *remain, *new_pos = *pos;
  121. uint16_t llen;
  122. int length = *remain, new_remain = *remain;
  123. int ptrs = 0, labels = 0;
  124. bool got_compression = false;
  125. /* First go through labels and calculate name length */
  126. while (p - begin < length) {
  127. if (ptrs > MAX_RECURSION_LEVEL) {
  128. rdns_info ("dns pointers are nested too much");
  129. return false;
  130. }
  131. llen = *p;
  132. if (llen == 0) {
  133. if (!got_compression) {
  134. /* In case of compression we have already decremented the processing position */
  135. new_remain -= sizeof (uint8_t);
  136. new_pos += sizeof (uint8_t);
  137. }
  138. break;
  139. }
  140. else if ((llen & DNS_COMPRESSION_BITS)) {
  141. if (end - p > 1) {
  142. ptrs ++;
  143. llen = UNCOMPRESS_DNS_OFFSET(p);
  144. l = rdns_decompress_label (in, &llen, end - in);
  145. if (l == NULL) {
  146. rdns_info ("invalid DNS pointer");
  147. return false;
  148. }
  149. if (!got_compression) {
  150. /* Our label processing is finished actually */
  151. new_remain -= sizeof (uint16_t);
  152. new_pos += sizeof (uint16_t);
  153. got_compression = true;
  154. }
  155. if (l < in || l > begin + length) {
  156. rdns_info ("invalid pointer in DNS packet");
  157. return false;
  158. }
  159. begin = l;
  160. length = end - begin;
  161. p = l + *l + 1;
  162. namelen += *l;
  163. labels ++;
  164. }
  165. else {
  166. rdns_info ("DNS packet has incomplete compressed label, input length: %d bytes, remain: %d",
  167. *remain, new_remain);
  168. return false;
  169. }
  170. }
  171. else {
  172. namelen += llen;
  173. p += llen + 1;
  174. labels ++;
  175. if (!got_compression) {
  176. new_remain -= llen + 1;
  177. new_pos += llen + 1;
  178. }
  179. }
  180. }
  181. if (!make_name) {
  182. goto end;
  183. }
  184. *target = malloc (namelen + labels + 3);
  185. t = (uint8_t *)*target;
  186. p = *pos;
  187. begin = *pos;
  188. length = *remain;
  189. /* Now copy labels to name */
  190. while (p - begin < length) {
  191. llen = *p;
  192. if (llen == 0) {
  193. break;
  194. }
  195. else if (llen & DNS_COMPRESSION_BITS) {
  196. llen = UNCOMPRESS_DNS_OFFSET(p);
  197. l = rdns_decompress_label (in, &llen, end - in);
  198. begin = l;
  199. length = end - begin;
  200. p = l + *l + 1;
  201. memcpy (t, l + 1, *l);
  202. t += *l;
  203. *t ++ = '.';
  204. }
  205. else {
  206. memcpy (t, p + 1, *p);
  207. t += *p;
  208. *t ++ = '.';
  209. p += *p + 1;
  210. }
  211. }
  212. if (t > (uint8_t *)*target) {
  213. *(t - 1) = '\0';
  214. }
  215. else {
  216. /* Handle empty labels */
  217. **target = '\0';
  218. }
  219. end:
  220. *remain = new_remain;
  221. *pos = new_pos;
  222. return true;
  223. }
  224. #define GET8(x) do {(x) = ((*p)); p += sizeof (uint8_t); *remain -= sizeof (uint8_t); } while(0)
  225. #define GET16(x) do {(x) = ((*p) << 8) + *(p + 1); p += sizeof (uint16_t); *remain -= sizeof (uint16_t); } while(0)
  226. #define GET32(x) do {(x) = ((*p) << 24) + ((*(p + 1)) << 16) + ((*(p + 2)) << 8) + *(p + 3); p += sizeof (uint32_t); *remain -= sizeof (uint32_t); } while(0)
  227. #define SKIP(type) do { p += sizeof(type); *remain -= sizeof(type); } while (0)
  228. int
  229. rdns_parse_rr (struct rdns_resolver *resolver,
  230. uint8_t *in, struct rdns_reply_entry *elt, uint8_t **pos,
  231. struct rdns_reply *rep, int *remain)
  232. {
  233. uint8_t *p = *pos, parts;
  234. uint16_t type, datalen, txtlen, copied;
  235. int32_t ttl;
  236. bool parsed = false;
  237. /* Skip the whole name */
  238. if (! rdns_parse_labels (resolver, in, NULL, &p, rep, remain, false)) {
  239. rdns_info ("bad RR name");
  240. return -1;
  241. }
  242. if (*remain < (int)sizeof (uint16_t) * 6) {
  243. rdns_info ("stripped dns reply: %d bytes remain", *remain);
  244. return -1;
  245. }
  246. GET16 (type);
  247. /* Skip class */
  248. SKIP (uint16_t);
  249. GET32 (ttl);
  250. GET16 (datalen);
  251. elt->type = type;
  252. /* Now p points to RR data */
  253. switch (type) {
  254. case DNS_T_A:
  255. if (!(datalen & 0x3) && datalen <= *remain) {
  256. memcpy (&elt->content.a.addr, p, sizeof (struct in_addr));
  257. p += datalen;
  258. *remain -= datalen;
  259. parsed = true;
  260. }
  261. else {
  262. rdns_info ("corrupted A record");
  263. return -1;
  264. }
  265. break;
  266. case DNS_T_AAAA:
  267. if (datalen == sizeof (struct in6_addr) && datalen <= *remain) {
  268. memcpy (&elt->content.aaa.addr, p, sizeof (struct in6_addr));
  269. p += datalen;
  270. *remain -= datalen;
  271. parsed = true;
  272. }
  273. else {
  274. rdns_info ("corrupted AAAA record");
  275. return -1;
  276. }
  277. break;
  278. case DNS_T_PTR:
  279. if (! rdns_parse_labels (resolver, in, &elt->content.ptr.name, &p,
  280. rep, remain, true)) {
  281. rdns_info ("invalid labels in PTR record");
  282. return -1;
  283. }
  284. parsed = true;
  285. break;
  286. case DNS_T_NS:
  287. if (! rdns_parse_labels (resolver, in, &elt->content.ns.name, &p,
  288. rep, remain, true)) {
  289. rdns_info ("invalid labels in NS record");
  290. return -1;
  291. }
  292. parsed = true;
  293. break;
  294. case DNS_T_SOA:
  295. if (! rdns_parse_labels (resolver, in, &elt->content.soa.mname, &p,
  296. rep, remain, true)) {
  297. rdns_info ("invalid labels in NS record");
  298. return -1;
  299. }
  300. if (! rdns_parse_labels (resolver, in, &elt->content.soa.admin, &p,
  301. rep, remain, true)) {
  302. rdns_info ("invalid labels in NS record");
  303. return -1;
  304. }
  305. GET32 (elt->content.soa.serial);
  306. GET32 (elt->content.soa.refresh);
  307. GET32 (elt->content.soa.retry);
  308. GET32 (elt->content.soa.expire);
  309. GET32 (elt->content.soa.minimum);
  310. parsed = true;
  311. break;
  312. case DNS_T_MX:
  313. GET16 (elt->content.mx.priority);
  314. if (! rdns_parse_labels (resolver, in, &elt->content.mx.name, &p,
  315. rep, remain, true)) {
  316. rdns_info ("invalid labels in MX record");
  317. return -1;
  318. }
  319. parsed = true;
  320. break;
  321. case DNS_T_TXT:
  322. case DNS_T_SPF:
  323. elt->content.txt.data = malloc (datalen + 1);
  324. if (elt->content.txt.data == NULL) {
  325. rdns_err ("failed to allocate %d bytes for TXT record", (int)datalen + 1);
  326. return -1;
  327. }
  328. /* Now we should compose data from parts */
  329. copied = 0;
  330. parts = 0;
  331. while (copied + parts < datalen) {
  332. txtlen = *p;
  333. if (txtlen + copied + parts <= datalen) {
  334. parts ++;
  335. memcpy (elt->content.txt.data + copied, p + 1, txtlen);
  336. copied += txtlen;
  337. p += txtlen + 1;
  338. *remain -= txtlen + 1;
  339. }
  340. else {
  341. break;
  342. }
  343. }
  344. *(elt->content.txt.data + copied) = '\0';
  345. parsed = true;
  346. elt->type = RDNS_REQUEST_TXT;
  347. break;
  348. case DNS_T_SRV:
  349. if (p - *pos > (int)(*remain - sizeof (uint16_t) * 3)) {
  350. rdns_info ("stripped dns reply while reading SRV record");
  351. return -1;
  352. }
  353. GET16 (elt->content.srv.priority);
  354. GET16 (elt->content.srv.weight);
  355. GET16 (elt->content.srv.port);
  356. if (! rdns_parse_labels (resolver, in, &elt->content.srv.target,
  357. &p, rep, remain, true)) {
  358. rdns_info ("invalid labels in SRV record");
  359. return -1;
  360. }
  361. parsed = true;
  362. break;
  363. case DNS_T_TLSA:
  364. if (p - *pos > (int)(*remain - sizeof (uint8_t) * 3) || datalen <= 3) {
  365. rdns_info ("stripped dns reply while reading TLSA record");
  366. return -1;
  367. }
  368. GET8 (elt->content.tlsa.usage);
  369. GET8 (elt->content.tlsa.selector);
  370. GET8 (elt->content.tlsa.match_type);
  371. datalen -= 3;
  372. elt->content.tlsa.data = malloc (datalen);
  373. if (elt->content.tlsa.data == NULL) {
  374. rdns_err ("failed to allocate %d bytes for TLSA record", (int)datalen + 1);
  375. return -1;
  376. }
  377. elt->content.tlsa.datalen = datalen;
  378. memcpy (elt->content.tlsa.data, p, datalen);
  379. p += datalen;
  380. *remain -= datalen;
  381. parsed = true;
  382. break;
  383. case DNS_T_CNAME:
  384. /* Skip cname records */
  385. p += datalen;
  386. *remain -= datalen;
  387. break;
  388. default:
  389. rdns_debug ("unexpected RR type: %d", type);
  390. p += datalen;
  391. *remain -= datalen;
  392. break;
  393. }
  394. *pos = p;
  395. if (parsed) {
  396. elt->ttl = ttl;
  397. return 1;
  398. }
  399. return 0;
  400. }