Blame


1 f1509490 2022-03-20 martijn /* $OpenBSD: unpack_dns.c,v 1.1 2018/01/06 07:57:53 sunil Exp $ */
2 f1509490 2022-03-20 martijn
3 f1509490 2022-03-20 martijn /*
4 f1509490 2022-03-20 martijn * Copyright (c) 2011-2014 Eric Faurot <eric@faurot.net>
5 f1509490 2022-03-20 martijn *
6 f1509490 2022-03-20 martijn * Permission to use, copy, modify, and distribute this software for any
7 f1509490 2022-03-20 martijn * purpose with or without fee is hereby granted, provided that the above
8 f1509490 2022-03-20 martijn * copyright notice and this permission notice appear in all copies.
9 f1509490 2022-03-20 martijn *
10 f1509490 2022-03-20 martijn * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 f1509490 2022-03-20 martijn * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 f1509490 2022-03-20 martijn * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 f1509490 2022-03-20 martijn * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 f1509490 2022-03-20 martijn * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 f1509490 2022-03-20 martijn * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 f1509490 2022-03-20 martijn * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 f1509490 2022-03-20 martijn */
18 f1509490 2022-03-20 martijn
19 f1509490 2022-03-20 martijn #include <arpa/inet.h>
20 f1509490 2022-03-20 martijn
21 f1509490 2022-03-20 martijn #include <string.h>
22 f1509490 2022-03-20 martijn
23 f1509490 2022-03-20 martijn #include "unpack_dns.h"
24 f1509490 2022-03-20 martijn
25 f1509490 2022-03-20 martijn static int unpack_data(struct unpack *, void *, size_t);
26 f1509490 2022-03-20 martijn static int unpack_u16(struct unpack *, uint16_t *);
27 f1509490 2022-03-20 martijn static int unpack_u32(struct unpack *, uint32_t *);
28 f1509490 2022-03-20 martijn static int unpack_inaddr(struct unpack *, struct in_addr *);
29 f1509490 2022-03-20 martijn static int unpack_in6addr(struct unpack *, struct in6_addr *);
30 f1509490 2022-03-20 martijn static int unpack_dname(struct unpack *, char *, size_t);
31 f1509490 2022-03-20 martijn
32 f1509490 2022-03-20 martijn void
33 f1509490 2022-03-20 martijn unpack_init(struct unpack *unpack, const char *buf, size_t len)
34 f1509490 2022-03-20 martijn {
35 f1509490 2022-03-20 martijn unpack->buf = buf;
36 f1509490 2022-03-20 martijn unpack->len = len;
37 f1509490 2022-03-20 martijn unpack->offset = 0;
38 f1509490 2022-03-20 martijn unpack->err = NULL;
39 f1509490 2022-03-20 martijn }
40 f1509490 2022-03-20 martijn
41 f1509490 2022-03-20 martijn int
42 f1509490 2022-03-20 martijn unpack_header(struct unpack *p, struct dns_header *h)
43 f1509490 2022-03-20 martijn {
44 f1509490 2022-03-20 martijn if (unpack_data(p, h, HFIXEDSZ) == -1)
45 f1509490 2022-03-20 martijn return (-1);
46 f1509490 2022-03-20 martijn
47 f1509490 2022-03-20 martijn h->flags = ntohs(h->flags);
48 f1509490 2022-03-20 martijn h->qdcount = ntohs(h->qdcount);
49 f1509490 2022-03-20 martijn h->ancount = ntohs(h->ancount);
50 f1509490 2022-03-20 martijn h->nscount = ntohs(h->nscount);
51 f1509490 2022-03-20 martijn h->arcount = ntohs(h->arcount);
52 f1509490 2022-03-20 martijn
53 f1509490 2022-03-20 martijn return (0);
54 f1509490 2022-03-20 martijn }
55 f1509490 2022-03-20 martijn
56 f1509490 2022-03-20 martijn int
57 f1509490 2022-03-20 martijn unpack_query(struct unpack *p, struct dns_query *q)
58 f1509490 2022-03-20 martijn {
59 f1509490 2022-03-20 martijn unpack_dname(p, q->q_dname, sizeof(q->q_dname));
60 f1509490 2022-03-20 martijn unpack_u16(p, &q->q_type);
61 f1509490 2022-03-20 martijn unpack_u16(p, &q->q_class);
62 f1509490 2022-03-20 martijn
63 f1509490 2022-03-20 martijn return (p->err) ? (-1) : (0);
64 f1509490 2022-03-20 martijn }
65 f1509490 2022-03-20 martijn
66 f1509490 2022-03-20 martijn int
67 f1509490 2022-03-20 martijn unpack_rr(struct unpack *p, struct dns_rr *rr)
68 f1509490 2022-03-20 martijn {
69 f1509490 2022-03-20 martijn uint16_t rdlen;
70 f1509490 2022-03-20 martijn size_t save_offset;
71 f1509490 2022-03-20 martijn
72 f1509490 2022-03-20 martijn unpack_dname(p, rr->rr_dname, sizeof(rr->rr_dname));
73 f1509490 2022-03-20 martijn unpack_u16(p, &rr->rr_type);
74 f1509490 2022-03-20 martijn unpack_u16(p, &rr->rr_class);
75 f1509490 2022-03-20 martijn unpack_u32(p, &rr->rr_ttl);
76 f1509490 2022-03-20 martijn unpack_u16(p, &rdlen);
77 f1509490 2022-03-20 martijn
78 f1509490 2022-03-20 martijn if (p->err)
79 f1509490 2022-03-20 martijn return (-1);
80 f1509490 2022-03-20 martijn
81 f1509490 2022-03-20 martijn if (p->len - p->offset < rdlen) {
82 f1509490 2022-03-20 martijn p->err = "too short";
83 f1509490 2022-03-20 martijn return (-1);
84 f1509490 2022-03-20 martijn }
85 f1509490 2022-03-20 martijn
86 f1509490 2022-03-20 martijn save_offset = p->offset;
87 f1509490 2022-03-20 martijn
88 f1509490 2022-03-20 martijn switch (rr->rr_type) {
89 f1509490 2022-03-20 martijn
90 f1509490 2022-03-20 martijn case T_CNAME:
91 f1509490 2022-03-20 martijn unpack_dname(p, rr->rr.cname.cname, sizeof(rr->rr.cname.cname));
92 f1509490 2022-03-20 martijn break;
93 f1509490 2022-03-20 martijn
94 f1509490 2022-03-20 martijn case T_MX:
95 f1509490 2022-03-20 martijn unpack_u16(p, &rr->rr.mx.preference);
96 f1509490 2022-03-20 martijn unpack_dname(p, rr->rr.mx.exchange, sizeof(rr->rr.mx.exchange));
97 f1509490 2022-03-20 martijn break;
98 f1509490 2022-03-20 martijn
99 f1509490 2022-03-20 martijn case T_NS:
100 f1509490 2022-03-20 martijn unpack_dname(p, rr->rr.ns.nsname, sizeof(rr->rr.ns.nsname));
101 f1509490 2022-03-20 martijn break;
102 f1509490 2022-03-20 martijn
103 f1509490 2022-03-20 martijn case T_PTR:
104 f1509490 2022-03-20 martijn unpack_dname(p, rr->rr.ptr.ptrname, sizeof(rr->rr.ptr.ptrname));
105 f1509490 2022-03-20 martijn break;
106 f1509490 2022-03-20 martijn
107 f1509490 2022-03-20 martijn case T_SOA:
108 f1509490 2022-03-20 martijn unpack_dname(p, rr->rr.soa.mname, sizeof(rr->rr.soa.mname));
109 f1509490 2022-03-20 martijn unpack_dname(p, rr->rr.soa.rname, sizeof(rr->rr.soa.rname));
110 f1509490 2022-03-20 martijn unpack_u32(p, &rr->rr.soa.serial);
111 f1509490 2022-03-20 martijn unpack_u32(p, &rr->rr.soa.refresh);
112 f1509490 2022-03-20 martijn unpack_u32(p, &rr->rr.soa.retry);
113 f1509490 2022-03-20 martijn unpack_u32(p, &rr->rr.soa.expire);
114 f1509490 2022-03-20 martijn unpack_u32(p, &rr->rr.soa.minimum);
115 f1509490 2022-03-20 martijn break;
116 f1509490 2022-03-20 martijn
117 f1509490 2022-03-20 martijn case T_A:
118 f1509490 2022-03-20 martijn if (rr->rr_class != C_IN)
119 f1509490 2022-03-20 martijn goto other;
120 f1509490 2022-03-20 martijn unpack_inaddr(p, &rr->rr.in_a.addr);
121 f1509490 2022-03-20 martijn break;
122 f1509490 2022-03-20 martijn
123 f1509490 2022-03-20 martijn case T_AAAA:
124 f1509490 2022-03-20 martijn if (rr->rr_class != C_IN)
125 f1509490 2022-03-20 martijn goto other;
126 f1509490 2022-03-20 martijn unpack_in6addr(p, &rr->rr.in_aaaa.addr6);
127 f1509490 2022-03-20 martijn break;
128 f1509490 2022-03-20 martijn default:
129 f1509490 2022-03-20 martijn other:
130 f1509490 2022-03-20 martijn rr->rr.other.rdata = p->buf + p->offset;
131 f1509490 2022-03-20 martijn rr->rr.other.rdlen = rdlen;
132 f1509490 2022-03-20 martijn p->offset += rdlen;
133 f1509490 2022-03-20 martijn }
134 f1509490 2022-03-20 martijn
135 f1509490 2022-03-20 martijn if (p->err)
136 f1509490 2022-03-20 martijn return (-1);
137 f1509490 2022-03-20 martijn
138 f1509490 2022-03-20 martijn /* make sure that the advertised rdlen is really ok */
139 f1509490 2022-03-20 martijn if (p->offset - save_offset != rdlen)
140 f1509490 2022-03-20 martijn p->err = "bad dlen";
141 f1509490 2022-03-20 martijn
142 f1509490 2022-03-20 martijn return (p->err) ? (-1) : (0);
143 f1509490 2022-03-20 martijn }
144 f1509490 2022-03-20 martijn
145 f1509490 2022-03-20 martijn ssize_t
146 f1509490 2022-03-20 martijn dname_expand(const unsigned char *data, size_t len, size_t offset,
147 f1509490 2022-03-20 martijn size_t *newoffset, char *dst, size_t max)
148 f1509490 2022-03-20 martijn {
149 f1509490 2022-03-20 martijn size_t n, count, end, ptr, start;
150 f1509490 2022-03-20 martijn ssize_t res;
151 f1509490 2022-03-20 martijn
152 f1509490 2022-03-20 martijn if (offset >= len)
153 f1509490 2022-03-20 martijn return (-1);
154 f1509490 2022-03-20 martijn
155 f1509490 2022-03-20 martijn res = 0;
156 f1509490 2022-03-20 martijn end = start = offset;
157 f1509490 2022-03-20 martijn
158 f1509490 2022-03-20 martijn for (; (n = data[offset]); ) {
159 f1509490 2022-03-20 martijn if ((n & 0xc0) == 0xc0) {
160 f1509490 2022-03-20 martijn if (offset + 2 > len)
161 f1509490 2022-03-20 martijn return (-1);
162 f1509490 2022-03-20 martijn ptr = 256 * (n & ~0xc0) + data[offset + 1];
163 f1509490 2022-03-20 martijn if (ptr >= start)
164 f1509490 2022-03-20 martijn return (-1);
165 f1509490 2022-03-20 martijn if (end < offset + 2)
166 f1509490 2022-03-20 martijn end = offset + 2;
167 f1509490 2022-03-20 martijn offset = start = ptr;
168 f1509490 2022-03-20 martijn continue;
169 f1509490 2022-03-20 martijn }
170 f1509490 2022-03-20 martijn if (offset + n + 1 > len)
171 f1509490 2022-03-20 martijn return (-1);
172 f1509490 2022-03-20 martijn
173 f1509490 2022-03-20 martijn /* copy n + at offset+1 */
174 f1509490 2022-03-20 martijn if (dst != NULL && max != 0) {
175 f1509490 2022-03-20 martijn count = (max < n + 1) ? (max) : (n + 1);
176 f1509490 2022-03-20 martijn memmove(dst, data + offset, count);
177 f1509490 2022-03-20 martijn dst += count;
178 f1509490 2022-03-20 martijn max -= count;
179 f1509490 2022-03-20 martijn }
180 f1509490 2022-03-20 martijn res += n + 1;
181 f1509490 2022-03-20 martijn offset += n + 1;
182 f1509490 2022-03-20 martijn if (end < offset)
183 f1509490 2022-03-20 martijn end = offset;
184 f1509490 2022-03-20 martijn }
185 f1509490 2022-03-20 martijn if (end < offset + 1)
186 f1509490 2022-03-20 martijn end = offset + 1;
187 f1509490 2022-03-20 martijn
188 f1509490 2022-03-20 martijn if (dst != NULL && max != 0)
189 f1509490 2022-03-20 martijn dst[0] = 0;
190 f1509490 2022-03-20 martijn if (newoffset)
191 f1509490 2022-03-20 martijn *newoffset = end;
192 f1509490 2022-03-20 martijn return (res + 1);
193 f1509490 2022-03-20 martijn }
194 f1509490 2022-03-20 martijn
195 f1509490 2022-03-20 martijn char *
196 f1509490 2022-03-20 martijn print_dname(const char *_dname, char *buf, size_t max)
197 f1509490 2022-03-20 martijn {
198 f1509490 2022-03-20 martijn const unsigned char *dname = _dname;
199 f1509490 2022-03-20 martijn char *res;
200 f1509490 2022-03-20 martijn size_t left, count;
201 f1509490 2022-03-20 martijn
202 f1509490 2022-03-20 martijn if (_dname[0] == 0) {
203 f1509490 2022-03-20 martijn (void)strlcpy(buf, ".", max);
204 f1509490 2022-03-20 martijn return buf;
205 f1509490 2022-03-20 martijn }
206 f1509490 2022-03-20 martijn
207 f1509490 2022-03-20 martijn res = buf;
208 f1509490 2022-03-20 martijn left = max - 1;
209 f1509490 2022-03-20 martijn for (; dname[0] && left;) {
210 f1509490 2022-03-20 martijn count = (dname[0] < (left - 1)) ? dname[0] : (left - 1);
211 f1509490 2022-03-20 martijn memmove(buf, dname + 1, count);
212 f1509490 2022-03-20 martijn dname += dname[0] + 1;
213 f1509490 2022-03-20 martijn left -= count;
214 f1509490 2022-03-20 martijn buf += count;
215 f1509490 2022-03-20 martijn if (left) {
216 f1509490 2022-03-20 martijn left -= 1;
217 f1509490 2022-03-20 martijn *buf++ = '.';
218 f1509490 2022-03-20 martijn }
219 f1509490 2022-03-20 martijn }
220 f1509490 2022-03-20 martijn buf[0] = 0;
221 f1509490 2022-03-20 martijn
222 f1509490 2022-03-20 martijn return (res);
223 f1509490 2022-03-20 martijn }
224 f1509490 2022-03-20 martijn
225 f1509490 2022-03-20 martijn static int
226 f1509490 2022-03-20 martijn unpack_data(struct unpack *p, void *data, size_t len)
227 f1509490 2022-03-20 martijn {
228 f1509490 2022-03-20 martijn if (p->err)
229 f1509490 2022-03-20 martijn return (-1);
230 f1509490 2022-03-20 martijn
231 f1509490 2022-03-20 martijn if (p->len - p->offset < len) {
232 f1509490 2022-03-20 martijn p->err = "too short";
233 f1509490 2022-03-20 martijn return (-1);
234 f1509490 2022-03-20 martijn }
235 f1509490 2022-03-20 martijn
236 f1509490 2022-03-20 martijn memmove(data, p->buf + p->offset, len);
237 f1509490 2022-03-20 martijn p->offset += len;
238 f1509490 2022-03-20 martijn
239 f1509490 2022-03-20 martijn return (0);
240 f1509490 2022-03-20 martijn }
241 f1509490 2022-03-20 martijn
242 f1509490 2022-03-20 martijn static int
243 f1509490 2022-03-20 martijn unpack_u16(struct unpack *p, uint16_t *u16)
244 f1509490 2022-03-20 martijn {
245 f1509490 2022-03-20 martijn if (unpack_data(p, u16, 2) == -1)
246 f1509490 2022-03-20 martijn return (-1);
247 f1509490 2022-03-20 martijn
248 f1509490 2022-03-20 martijn *u16 = ntohs(*u16);
249 f1509490 2022-03-20 martijn
250 f1509490 2022-03-20 martijn return (0);
251 f1509490 2022-03-20 martijn }
252 f1509490 2022-03-20 martijn
253 f1509490 2022-03-20 martijn static int
254 f1509490 2022-03-20 martijn unpack_u32(struct unpack *p, uint32_t *u32)
255 f1509490 2022-03-20 martijn {
256 f1509490 2022-03-20 martijn if (unpack_data(p, u32, 4) == -1)
257 f1509490 2022-03-20 martijn return (-1);
258 f1509490 2022-03-20 martijn
259 f1509490 2022-03-20 martijn *u32 = ntohl(*u32);
260 f1509490 2022-03-20 martijn
261 f1509490 2022-03-20 martijn return (0);
262 f1509490 2022-03-20 martijn }
263 f1509490 2022-03-20 martijn
264 f1509490 2022-03-20 martijn static int
265 f1509490 2022-03-20 martijn unpack_inaddr(struct unpack *p, struct in_addr *a)
266 f1509490 2022-03-20 martijn {
267 f1509490 2022-03-20 martijn return (unpack_data(p, a, 4));
268 f1509490 2022-03-20 martijn }
269 f1509490 2022-03-20 martijn
270 f1509490 2022-03-20 martijn static int
271 f1509490 2022-03-20 martijn unpack_in6addr(struct unpack *p, struct in6_addr *a6)
272 f1509490 2022-03-20 martijn {
273 f1509490 2022-03-20 martijn return (unpack_data(p, a6, 16));
274 f1509490 2022-03-20 martijn }
275 f1509490 2022-03-20 martijn
276 f1509490 2022-03-20 martijn static int
277 f1509490 2022-03-20 martijn unpack_dname(struct unpack *p, char *dst, size_t max)
278 f1509490 2022-03-20 martijn {
279 f1509490 2022-03-20 martijn ssize_t e;
280 f1509490 2022-03-20 martijn
281 f1509490 2022-03-20 martijn if (p->err)
282 f1509490 2022-03-20 martijn return (-1);
283 f1509490 2022-03-20 martijn
284 f1509490 2022-03-20 martijn e = dname_expand(p->buf, p->len, p->offset, &p->offset, dst, max);
285 f1509490 2022-03-20 martijn if (e == -1) {
286 f1509490 2022-03-20 martijn p->err = "bad domain name";
287 f1509490 2022-03-20 martijn return (-1);
288 f1509490 2022-03-20 martijn }
289 f1509490 2022-03-20 martijn if (e < 0 || e > MAXDNAME) {
290 f1509490 2022-03-20 martijn p->err = "domain name too long";
291 f1509490 2022-03-20 martijn return (-1);
292 f1509490 2022-03-20 martijn }
293 f1509490 2022-03-20 martijn
294 f1509490 2022-03-20 martijn return (0);
295 f1509490 2022-03-20 martijn }