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