xref: /curl/tests/unit/unit1650.c (revision 25cbc2f7)
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
9  *
10  * This software is licensed as described in the file COPYING, which
11  * you should have received as part of this distribution. The terms
12  * are also available at https://curl.se/docs/copyright.html.
13  *
14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15  * copies of the Software, and permit persons to whom the Software is
16  * furnished to do so, under the terms of the COPYING file.
17  *
18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19  * KIND, either express or implied.
20  *
21  * SPDX-License-Identifier: curl
22  *
23  ***************************************************************************/
24 #include "curlcheck.h"
25 
26 #include "doh.h"
27 #include "dynbuf.h"
28 
unit_setup(void)29 static CURLcode unit_setup(void)
30 {
31   return CURLE_OK;
32 }
33 
unit_stop(void)34 static void unit_stop(void)
35 {
36 
37 }
38 
39 #ifndef CURL_DISABLE_DOH
40 #define DNS_PREAMBLE "\x00\x00\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00"
41 #define LABEL_TEST "\x04\x74\x65\x73\x74"
42 #define LABEL_HOST "\x04\x68\x6f\x73\x74"
43 #define LABEL_NAME "\x04\x6e\x61\x6d\x65"
44 #define DNSA_TYPE "\x01"
45 #define DNSAAAA_TYPE "\x1c"
46 #define DNSA_EPILOGUE "\x00\x00" DNSA_TYPE "\x00\x01"
47 #define DNSAAAA_EPILOGUE "\x00\x00" DNSAAAA_TYPE "\x00\x01"
48 
49 #define DNS_Q1 DNS_PREAMBLE LABEL_TEST LABEL_HOST LABEL_NAME DNSA_EPILOGUE
50 #define DNS_Q2 DNS_PREAMBLE LABEL_TEST LABEL_HOST LABEL_NAME DNSAAAA_EPILOGUE
51 
52 struct dohrequest {
53   /* input */
54   const char *name;
55   DNStype type;
56 
57   /* output */
58   const char *packet;
59   size_t size;
60   DOHcode rc;
61 };
62 
63 
64 static const struct dohrequest req[] = {
65   {"test.host.name", DNS_TYPE_A, DNS_Q1, sizeof(DNS_Q1)-1, DOH_OK },
66   {"test.host.name", DNS_TYPE_AAAA, DNS_Q2, sizeof(DNS_Q2)-1, DOH_OK },
67   {"zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"
68    ".host.name",
69    DNS_TYPE_AAAA, NULL, 0, DOH_DNS_BAD_LABEL }
70 };
71 
72 struct dohresp {
73   /* input */
74   const char *packet;
75   size_t size;
76   DNStype type;
77 
78   /* output */
79   DOHcode rc;
80   const char *out;
81 };
82 
83 #define DNS_FOO_EXAMPLE_COM                                          \
84   "\x00\x00\x01\x00\x00\x01\x00\x01\x00\x00\x00\x00\x03\x66\x6f\x6f" \
85   "\x07\x65\x78\x61\x6d\x70\x6c\x65\x03\x63\x6f\x6d\x00\x00\x01\x00" \
86   "\x01\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x37\x00\x04\x7f\x00\x00" \
87   "\x01"
88 
89 static const char full49[] = DNS_FOO_EXAMPLE_COM;
90 
91 static const struct dohresp resp[] = {
92   {"\x00\x00", 2, DNS_TYPE_A, DOH_TOO_SMALL_BUFFER, NULL },
93   {"\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01", 12,
94    DNS_TYPE_A, DOH_DNS_BAD_ID, NULL },
95   {"\x00\x00\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01", 12,
96    DNS_TYPE_A, DOH_DNS_BAD_RCODE, NULL },
97   {"\x00\x00\x01\x00\x00\x01\x00\x01\x00\x00\x00\x00\x03\x66\x6f\x6f", 16,
98    DNS_TYPE_A, DOH_DNS_OUT_OF_RANGE, NULL },
99   {"\x00\x00\x01\x00\x00\x01\x00\x01\x00\x00\x00\x00\x03\x66\x6f\x6f\x00", 17,
100    DNS_TYPE_A, DOH_DNS_OUT_OF_RANGE, NULL },
101   {"\x00\x00\x01\x00\x00\x01\x00\x01\x00\x00\x00\x00\x03\x66\x6f\x6f\x00"
102    "\x00\x01\x00\x01", 21,
103    DNS_TYPE_A, DOH_DNS_OUT_OF_RANGE, NULL },
104   {"\x00\x00\x01\x00\x00\x01\x00\x01\x00\x00\x00\x00\x03\x66\x6f\x6f\x00"
105    "\x00\x01\x00\x01"
106    "\x04", 18,
107    DNS_TYPE_A, DOH_DNS_OUT_OF_RANGE, NULL },
108 
109   {"\x00\x00\x01\x00\x00\x01\x00\x01\x00\x00\x00\x00\x04\x63\x75\x72"
110    "\x6c\x04\x63\x75\x72\x6c\x00\x00\x05\x00\x01\xc0\x0c\x00\x05\x00"
111    "\x01\x00\x00\x00\x37\x00\x11\x08\x61\x6e\x79\x77\x68\x65\x72\x65"
112    "\x06\x72\x65\x61\x6c\x6c\x79\x00", 56,
113    DNS_TYPE_A, DOH_OK, "anywhere.really "},
114 
115   {DNS_FOO_EXAMPLE_COM, 49, DNS_TYPE_A, DOH_OK, "127.0.0.1 "},
116 
117   {"\x00\x00\x01\x00\x00\x01\x00\x01\x00\x00\x00\x00\x04\x61\x61\x61"
118    "\x61\x07\x65\x78\x61\x6d\x70\x6c\x65\x03\x63\x6f\x6d\x00\x00\x1c"
119    "\x00\x01\xc0\x0c\x00\x1c\x00\x01\x00\x00\x00\x37\x00\x10\x20\x20"
120    "\x20\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\x20", 62,
121    DNS_TYPE_AAAA, DOH_OK,
122    "2020:2020:0000:0000:0000:0000:0000:2020 " },
123 
124   {"\x00\x00\x01\x00\x00\x01\x00\x01\x00\x00\x00\x00\x04\x63\x75\x72"
125    "\x6c\x04\x63\x75\x72\x6c\x00\x00\x05\x00\x01\xc0\x0c\x00\x05\x00"
126    "\x01\x00\x00\x00\x37\x00"
127    "\x07\x03\x61\x6e\x79\xc0\x27\x00", 46,
128    DNS_TYPE_A, DOH_DNS_LABEL_LOOP, NULL},
129 
130   /* packet with NSCOUNT == 1 */
131   {"\x00\x00\x01\x00\x00\x01\x00\x01\x00\x01\x00\x00\x04\x61\x61\x61"
132    "\x61\x07\x65\x78\x61\x6d\x70\x6c\x65\x03\x63\x6f\x6d\x00\x00\x1c"
133    "\x00\x01\xc0\x0c\x00\x1c\x00\x01\x00\x00\x00\x37\x00\x10\x20\x20"
134    "\x20\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\x20"
135    LABEL_TEST LABEL_HOST LABEL_NAME DNSAAAA_EPILOGUE "\x00\x00\x00\x01"
136    "\00\x04\x01\x01\x01\x01", /* RDDATA */
137 
138    62 + 30,
139    DNS_TYPE_AAAA, DOH_OK,
140    "2020:2020:0000:0000:0000:0000:0000:2020 " },
141 
142   /* packet with ARCOUNT == 1 */
143   {"\x00\x00\x01\x00\x00\x01\x00\x01\x00\x00\x00\x01\x04\x61\x61\x61"
144    "\x61\x07\x65\x78\x61\x6d\x70\x6c\x65\x03\x63\x6f\x6d\x00\x00\x1c"
145    "\x00\x01\xc0\x0c\x00\x1c\x00\x01\x00\x00\x00\x37\x00\x10\x20\x20"
146    "\x20\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\x20"
147    LABEL_TEST LABEL_HOST LABEL_NAME DNSAAAA_EPILOGUE "\x00\x00\x00\x01"
148    "\00\x04\x01\x01\x01\x01", /* RDDATA */
149 
150    62 + 30,
151    DNS_TYPE_AAAA, DOH_OK,
152    "2020:2020:0000:0000:0000:0000:0000:2020 " },
153 
154 };
155 
156 UNITTEST_START
157 {
158   size_t size = 0;
159   unsigned char buffer[256];
160   size_t i;
161   unsigned char *p;
162 
163   for(i = 0; i < sizeof(req) / sizeof(req[0]); i++) {
164     DOHcode rc = doh_encode(req[i].name, req[i].type,
165                             buffer, sizeof(buffer), &size);
166     if(rc != req[i].rc) {
167       fprintf(stderr, "req %zu: Expected return code %d got %d\n", i,
168               req[i].rc, rc);
169       abort_if(rc != req[i].rc, "return code");
170     }
171     if(size != req[i].size) {
172       fprintf(stderr, "req %zu: Expected size %zu got %zu\n", i,
173               req[i].size, size);
174       fprintf(stderr, "DNS encode made: %s\n", hexdump(buffer, size));
175       abort_if(size != req[i].size, "size");
176     }
177     if(req[i].packet && memcmp(req[i].packet, buffer, size)) {
178       fprintf(stderr, "DNS encode made: %s\n", hexdump(buffer, size));
179       fprintf(stderr, "... instead of: %s\n",
180              hexdump((unsigned char *)req[i].packet, size));
181       abort_if(req[i].packet && memcmp(req[i].packet, buffer, size),
182                "contents");
183     }
184   }
185 
186   for(i = 0; i < sizeof(resp) / sizeof(resp[0]); i++) {
187     struct dohentry d;
188     DOHcode rc;
189     char *ptr;
190     size_t len;
191     int u;
192     de_init(&d);
193     rc = doh_decode((const unsigned char *)resp[i].packet, resp[i].size,
194                     resp[i].type, &d);
195     if(rc != resp[i].rc) {
196       fprintf(stderr, "resp %zu: Expected return code %d got %d\n", i,
197               resp[i].rc, rc);
198       abort_if(rc != resp[i].rc, "return code");
199     }
200     len = sizeof(buffer);
201     ptr = (char *)buffer;
202     for(u = 0; u < d.numaddr; u++) {
203       size_t o;
204       struct dohaddr *a;
205       a = &d.addr[u];
206       if(resp[i].type == DNS_TYPE_A) {
207         p = &a->ip.v4[0];
208         msnprintf(ptr, len, "%u.%u.%u.%u ", p[0], p[1], p[2], p[3]);
209         o = strlen(ptr);
210         len -= o;
211         ptr += o;
212       }
213       else {
214         int j;
215         for(j = 0; j < 16; j += 2) {
216           size_t l;
217           msnprintf(ptr, len, "%s%02x%02x", j?":":"", a->ip.v6[j],
218                    a->ip.v6[j + 1]);
219           l = strlen(ptr);
220           len -= l;
221           ptr += l;
222         }
223         msnprintf(ptr, len, " ");
224         len--;
225         ptr++;
226       }
227     }
228     for(u = 0; u < d.numcname; u++) {
229       size_t o;
230       msnprintf(ptr, len, "%s ", Curl_dyn_ptr(&d.cname[u]));
231       o = strlen(ptr);
232       len -= o;
233       ptr += o;
234     }
235     de_cleanup(&d);
236     if(resp[i].out && strcmp((char *)buffer, resp[i].out)) {
237       fprintf(stderr, "resp %zu: Expected %s got %s\n", i,
238               resp[i].out, buffer);
239       abort_if(resp[i].out && strcmp((char *)buffer, resp[i].out), "content");
240     }
241   }
242 
243   /* pass all sizes into the decoder until full */
244   for(i = 0; i < sizeof(full49)-1; i++) {
245     struct dohentry d;
246     DOHcode rc;
247     memset(&d, 0, sizeof(d));
248     rc = doh_decode((const unsigned char *)full49, i, DNS_TYPE_A, &d);
249     if(!rc) {
250       /* none of them should work */
251       fprintf(stderr, "%zu: %d\n", i, rc);
252       abort_if(!rc, "error rc");
253     }
254   }
255 
256   /* and try all pieces from the other end of the packet */
257   for(i = 1; i < sizeof(full49); i++) {
258     struct dohentry d;
259     DOHcode rc;
260     memset(&d, 0, sizeof(d));
261     rc = doh_decode((const unsigned char *)&full49[i], sizeof(full49)-i-1,
262                     DNS_TYPE_A, &d);
263     if(!rc) {
264       /* none of them should work */
265       fprintf(stderr, "2 %zu: %d\n", i, rc);
266       abort_if(!rc, "error rc");
267     }
268   }
269 
270   {
271     DOHcode rc;
272     struct dohentry d;
273     struct dohaddr *a;
274     memset(&d, 0, sizeof(d));
275     rc = doh_decode((const unsigned char *)full49, sizeof(full49)-1,
276                     DNS_TYPE_A, &d);
277     fail_if(d.numaddr != 1, "missing address");
278     a = &d.addr[0];
279     p = &a->ip.v4[0];
280     msnprintf((char *)buffer, sizeof(buffer),
281               "%u.%u.%u.%u", p[0], p[1], p[2], p[3]);
282     if(rc || strcmp((char *)buffer, "127.0.0.1")) {
283       fprintf(stderr, "bad address decoded: %s, rc == %d\n", buffer, rc);
284       abort_if(rc || strcmp((char *)buffer, "127.0.0.1"), "bad address");
285     }
286     fail_if(d.numcname, "bad cname counter");
287   }
288 }
289 UNITTEST_STOP
290 
291 #else /* CURL_DISABLE_DOH */
292 UNITTEST_START
293 /* nothing to do, just succeed */
294 UNITTEST_STOP
295 
296 
297 #endif
298