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