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