unit1658.c (16583B)
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" /* from the lib dir */ 27 28 /* DoH + HTTPSRR are required */ 29 #if !defined(CURL_DISABLE_DOH) && defined(USE_HTTPSRR) 30 31 static CURLcode t1658_setup(void) 32 { 33 /* whatever you want done first */ 34 curl_global_init(CURL_GLOBAL_ALL); 35 return CURLE_OK; 36 } 37 38 extern CURLcode doh_resp_decode_httpsrr(struct Curl_easy *data, 39 const unsigned char *cp, size_t len, 40 struct Curl_https_rrinfo **hrr); 41 extern void doh_print_httpsrr(struct Curl_easy *data, 42 struct Curl_https_rrinfo *hrr); 43 44 /* 45 * The idea here is that we pass one DNS packet at the time to the decoder. we 46 * then generate a string output with the results and compare if it matches 47 * the expected. One by one. 48 */ 49 50 static char rrbuffer[256]; 51 static void rrresults(struct Curl_https_rrinfo *rr, CURLcode result) 52 { 53 char *p = rrbuffer; 54 char *pend = rrbuffer + sizeof(rrbuffer); 55 curl_msnprintf(rrbuffer, sizeof(rrbuffer), "r:%d|", (int)result); 56 p += strlen(rrbuffer); 57 58 if(rr) { 59 unsigned int i; 60 curl_msnprintf(p, pend - p, "p:%d|", rr->priority); 61 p += strlen(p); 62 63 curl_msnprintf(p, pend - p, "%s|", rr->target ? rr->target : "-"); 64 p += strlen(p); 65 66 for(i = 0; i < MAX_HTTPSRR_ALPNS && rr->alpns[i] != ALPN_none; i++) { 67 curl_msnprintf(p, pend - p, "alpn:%x|", rr->alpns[i]); 68 p += strlen(p); 69 } 70 if(rr->no_def_alpn) { 71 curl_msnprintf(p, pend - p, "no-def-alpn|"); 72 p += strlen(p); 73 } 74 if(rr->port >= 0) { 75 curl_msnprintf(p, pend - p, "port:%d|", rr->port); 76 p += strlen(p); 77 } 78 if(rr->ipv4hints) { 79 for(i = 0; i < rr->ipv4hints_len; i += 4) { 80 curl_msnprintf(p, pend - p, "ipv4:%d.%d.%d.%d|", 81 rr->ipv4hints[i], 82 rr->ipv4hints[i + 1], 83 rr->ipv4hints[i + 2], 84 rr->ipv4hints[i + 3]); 85 p += strlen(p); 86 } 87 } 88 if(rr->echconfiglist) { 89 curl_msnprintf(p, pend - p, "ech:"); 90 p += strlen(p); 91 for(i = 0; i < rr->echconfiglist_len; i++) { 92 curl_msnprintf(p, pend - p, "%02x", rr->echconfiglist[i]); 93 p += strlen(p); 94 } 95 curl_msnprintf(p, pend - p, "|"); 96 p += strlen(p); 97 } 98 if(rr->ipv6hints) { 99 for(i = 0; i < rr->ipv6hints_len; i += 16) { 100 int x; 101 curl_msnprintf(p, pend - p, "ipv6:"); 102 p += strlen(p); 103 for(x = 0; x < 16; x += 2) { 104 curl_msnprintf(p, pend - p, "%s%02x%02x", 105 x ? ":" : "", 106 rr->ipv6hints[i + x], 107 rr->ipv6hints[i + x + 1]); 108 p += strlen(p); 109 } 110 curl_msnprintf(p, pend - p, "|"); 111 p += strlen(p); 112 } 113 } 114 } 115 } 116 117 static CURLcode test_unit1658(char *arg) 118 { 119 UNITTEST_BEGIN(t1658_setup()) 120 121 /* The "SvcParamKeys" specified within the HTTPS RR packet *must* be 122 provided in numerical order. */ 123 124 struct test { 125 const char *name; 126 const unsigned char *dns; 127 size_t len; /* size of the dns packet */ 128 const char *expect; 129 }; 130 131 static const struct test t[] = { 132 { 133 "single h2 alpn", 134 (const unsigned char *)"\x00\x00" /* 16-bit prio */ 135 "\x04name\x00" /* RNAME */ 136 "\x00\x01" /* RR (1 == ALPN) */ 137 "\x00\x03" /* data size */ 138 "\x02" /* length byte */ 139 "h2", 140 15, 141 "r:0|p:0|name.|alpn:10|" 142 }, 143 { 144 "single h2 alpn missing last byte", 145 (const unsigned char *)"\x00\x00" /* 16-bit prio */ 146 "\x04name\x00" /* RNAME */ 147 "\x00\x01" /* RR (1 == ALPN) */ 148 "\x00\x03" /* data size */ 149 "\x02" /* length byte */ 150 "h", /* missing byte */ 151 14, 152 "r:8|" 153 }, 154 { 155 "two alpns", 156 (const unsigned char *)"\x00\x00" /* 16-bit prio */ 157 "\x04name\x04some\x00" /* RNAME */ 158 "\x00\x01" /* RR (1 == ALPN) */ 159 "\x00\x06" /* data size */ 160 "\x02" /* ALPN length byte */ 161 "h2" 162 "\x02" /* APLN length byte */ 163 "h3", 164 23, 165 "r:0|p:0|name.some.|alpn:10|alpn:20|" 166 }, 167 { 168 "wrong syntax alpns", 169 (const unsigned char *)"\x00\x00" /* 16-bit prio */ 170 "\x04name\x04some\x00" /* RNAME */ 171 "\x00\x01" /* RR (1 == ALPN) */ 172 "\x00\x06" /* data size */ 173 "\x02" /* ALPN length byte */ 174 "h2" 175 "\x03" /* APLN length byte (WRONG) */ 176 "h3", 177 23, 178 "r:61|" 179 }, 180 { 181 "five alpns (ignore dupes)", /* we only support four */ 182 (const unsigned char *)"\x00\x00" /* 16-bit prio */ 183 "\x04name\x04some\x00" /* RNAME */ 184 "\x00\x01" /* RR (1 == ALPN) */ 185 "\x00\x0f" /* data size */ 186 "\x02" /* ALPN length byte */ 187 "h2" 188 "\x02" /* ALPN length byte */ 189 "h2" 190 "\x02" /* ALPN length byte */ 191 "h2" 192 "\x02" /* ALPN length byte */ 193 "h2" 194 "\x02" /* APLN length byte */ 195 "h3", 196 32, 197 "r:0|p:0|name.some.|alpn:10|alpn:20|" 198 }, 199 { 200 "rname only", 201 (const unsigned char *)"\x00\x00" /* 16-bit prio */ 202 "\x04name\x04some\x00", /* RNAME */ 203 13, 204 "r:0|p:0|name.some.|" 205 }, 206 { 207 "rname with low ascii byte", 208 (const unsigned char *)"\x00\x00" /* 16-bit prio */ 209 "\x04name\x04som\x03\x00", /* RNAME */ 210 13, 211 "r:8|" 212 }, 213 { 214 "rname with null byte", 215 (const unsigned char *)"\x00\x00" /* 16-bit prio */ 216 "\x04sa\x00e\x04some\x00", /* RNAME */ 217 13, 218 "r:27|" 219 }, 220 { 221 "rname only (missing byte)", 222 (const unsigned char *)"\x00\x00" /* 16-bit prio */ 223 "\x04name\x05some\x00", /* RNAME */ 224 /* it lacks a byte */ 225 13, 226 "r:27|" 227 }, 228 { 229 "unrecognized alpn", 230 (const unsigned char *)"\x00\x00" /* 16-bit prio */ 231 "\x04name\x04some\x00" /* RNAME */ 232 "\x00\x01" /* RR (1 == ALPN) */ 233 "\x00\x06" /* data size */ 234 "\x02" /* ALPN length byte */ 235 "h8" /* unrecognized */ 236 "\x02" /* APLN length byte */ 237 "h1", 238 23, 239 "r:0|p:0|name.some.|alpn:8|" 240 }, 241 { 242 "alnt + no-default-alpn", 243 (const unsigned char *)"\x00\x00" /* 16-bit prio */ 244 "\x04name\x04some\x00" /* RNAME */ 245 "\x00\x01" /* RR (1 == ALPN) */ 246 "\x00\x03" /* data size */ 247 "\x02" /* ALPN length byte */ 248 "h2" 249 "\x00\x02" /* RR (2 == NO DEFAULT ALPN) */ 250 "\x00\x00", /* must be zero */ 251 24, 252 "r:0|p:0|name.some.|alpn:10|no-def-alpn|" 253 }, 254 { 255 "alnt + no-default-alpn with size", 256 (const unsigned char *)"\x00\x00" /* 16-bit prio */ 257 "\x04name\x04some\x00" /* RNAME */ 258 "\x00\x01" /* RR (1 == ALPN) */ 259 "\x00\x03" /* data size */ 260 "\x02" /* ALPN length byte */ 261 "h2" 262 "\x00\x02" /* RR (2 == NO DEFAULT ALPN) */ 263 "\x00\x01" /* must be zero */ 264 "\xff", 265 25, 266 "r:43|" 267 }, 268 { 269 "alnt + no-default-alpn with size too short package", 270 (const unsigned char *)"\x00\x00" /* 16-bit prio */ 271 "\x04name\x04some\x00" /* RNAME */ 272 "\x00\x01" /* RR (1 == ALPN) */ 273 "\x00\x03" /* data size */ 274 "\x02" /* ALPN length byte */ 275 "h2" 276 "\x00\x02" /* RR (2 == NO DEFAULT ALPN) */ 277 "\x00\x01", /* must be zero */ 278 /* missing last byte in the packet */ 279 24, 280 "r:8|" 281 }, 282 { 283 "rname + blank alpn field", 284 (const unsigned char *)"\x11\x11" /* 16-bit prio */ 285 "\x04name\x04some\x00" /* RNAME */ 286 "\x00\x01" /* RR (1 == ALPN) */ 287 "\x00\x00", /* data size, strictly speaking this is illegal: 288 "one or more alpn-ids" */ 289 17, 290 "r:0|p:4369|name.some.|" 291 }, 292 { 293 "no rname + blank alpn", 294 (const unsigned char *)"\x00\x11" /* 16-bit prio */ 295 "\x00" /* no RNAME */ 296 "\x00\x01" /* RR (1 == ALPN) */ 297 "\x00\x00", /* data size */ 298 7, 299 "r:0|p:17|.|" 300 }, 301 { 302 "unsupported field", 303 (const unsigned char *)"\xff\xff" /* 16-bit prio */ 304 "\x00" /* no RNAME */ 305 "\x00\x07" /* RR (7 == not a supported data) */ 306 "\x00\x02" /* data size */ 307 "FF", /* unknown to curl */ 308 9, 309 "r:0|p:65535|.|" 310 }, 311 { 312 "unsupported field (wrong size)", 313 (const unsigned char *)"\xff\xff" /* 16-bit prio */ 314 "\x00" /* no RNAME */ 315 "\x00\x07" /* RR (7 == not a supported data) */ 316 "\x00\x02" /* data size */ 317 "F", /* unknown to curl */ 318 8, 319 "r:8|" 320 }, 321 { 322 "port number", 323 (const unsigned char *)"\x00\x10" /* 16-bit prio */ 324 "\x00" /* no RNAME */ 325 "\x00\x01" /* RR (1 == ALPN) */ 326 "\x00\x03" /* data size */ 327 "\x02" /* ALPN length byte */ 328 "h2" 329 "\x00\x03" /* RR (3 == PORT) */ 330 "\x00\x02" /* data size */ 331 "\x12\x34", /* port number */ 332 16, 333 "r:0|p:16|.|alpn:10|port:4660|" 334 }, 335 { 336 "port number with wrong size (3 bytes)", 337 (const unsigned char *)"\x00\x10" /* 16-bit prio */ 338 "\x00" /* no RNAME */ 339 "\x00\x01" /* RR (1 == ALPN) */ 340 "\x00\x03" /* data size */ 341 "\x02" /* ALPN length byte */ 342 "h2" 343 "\x00\x03" /* RR (3 == PORT) */ 344 "\x00\x03" /* data size */ 345 "\x12\x34\x00", /* 24 bit port number! */ 346 17, 347 "r:43|" 348 }, 349 { 350 "port number with wrong size (1 byte)", 351 (const unsigned char *)"\x00\x10" /* 16-bit prio */ 352 "\x00" /* no RNAME */ 353 "\x00\x01" /* RR (1 == ALPN) */ 354 "\x00\x03" /* data size */ 355 "\x02" /* ALPN length byte */ 356 "h2" 357 "\x00\x03" /* RR (3 == PORT) */ 358 "\x00\x01" /* data size */ 359 "\x12", /* 8 bit port number! */ 360 15, 361 "r:43|" 362 }, 363 { 364 "alpn + two ipv4 addresses", 365 (const unsigned char *)"\x00\x10" /* 16-bit prio */ 366 "\x00" /* no RNAME */ 367 "\x00\x01" /* RR (1 == ALPN) */ 368 "\x00\x03" /* data size */ 369 "\x02" /* ALPN length byte */ 370 "h2" 371 "\x00\x04" /* RR (4 == Ipv4hints) */ 372 "\x00\x08" /* data size */ 373 "\xc0\xa8\x00\x01" /* 32 bits */ 374 "\xc0\xa8\x00\x02", /* 32 bits */ 375 22, 376 "r:0|p:16|.|alpn:10|ipv4:192.168.0.1|ipv4:192.168.0.2|" 377 }, 378 { 379 "alpn + two ipv4 addresses in wrong order", 380 (const unsigned char *)"\x00\x10" /* 16-bit prio */ 381 "\x00" /* no RNAME */ 382 "\x00\x04" /* RR (4 == Ipv4hints) */ 383 "\x00\x08" /* data size */ 384 "\xc0\xa8\x00\x01" /* 32 bits */ 385 "\xc0\xa8\x00\x02" /* 32 bits */ 386 "\x00\x01" /* RR (1 == ALPN) */ 387 "\x00\x03" /* data size */ 388 "\x02" /* ALPN length byte */ 389 "h2", 390 22, 391 "r:8|" 392 }, 393 { 394 "alpn + ipv4 address with wrong size", 395 (const unsigned char *)"\x00\x10" /* 16-bit prio */ 396 "\x00" /* no RNAME */ 397 "\x00\x01" /* RR (1 == ALPN) */ 398 "\x00\x03" /* data size */ 399 "\x02" /* ALPN length byte */ 400 "h2" 401 "\x00\x04" /* RR (4 == Ipv4hints) */ 402 "\x00\x05" /* data size */ 403 "\xc0\xa8\x00\x01\xff", /* 32 + 8 bits */ 404 19, 405 "r:43|" 406 }, 407 { 408 "alpn + one ipv6 address", 409 (const unsigned char *)"\x00\x10" /* 16-bit prio */ 410 "\x00" /* no RNAME */ 411 "\x00\x01" /* RR (1 == ALPN) */ 412 "\x00\x03" /* data size */ 413 "\x02" /* ALPN length byte */ 414 "h2" 415 "\x00\x06" /* RR (6 == Ipv6hints) */ 416 "\x00\x10" /* data size */ 417 "\xfe\x80\xda\xbb\xc1\xff\xfe\xa3\x8a\x22\x12\x34\x56\x78\x91\x23", 418 30, 419 "r:0|p:16|.|alpn:10|ipv6:fe80:dabb:c1ff:fea3:8a22:1234:5678:9123|" 420 }, 421 { 422 "alpn + one ipv6 address with wrong size", 423 (const unsigned char *)"\x00\x10" /* 16-bit prio */ 424 "\x00" /* no RNAME */ 425 "\x00\x01" /* RR (1 == ALPN) */ 426 "\x00\x03" /* data size */ 427 "\x02" /* ALPN length byte */ 428 "h2" 429 "\x00\x06" /* RR (6 == Ipv6hints) */ 430 "\x00\x11" /* data size */ 431 "\xfe\x80\xda\xbb\xc1\xff\xfe\xa3\x8a\x22\x12\x34\x56\x78\x91\x23\x45", 432 31, 433 "r:43|" 434 }, 435 { 436 "alpn + two ipv6 addresses", 437 (const unsigned char *)"\x00\x10" /* 16-bit prio */ 438 "\x00" /* no RNAME */ 439 "\x00\x01" /* RR (1 == ALPN) */ 440 "\x00\x03" /* data size */ 441 "\x02" /* ALPN length byte */ 442 "h2" 443 "\x00\x06" /* RR (6 == Ipv6hints) */ 444 "\x00\x20" /* data size */ 445 "\xfe\x80\xda\xbb\xc1\xff\xfe\xa3\x8a\x22\x12\x34\x56\x78\x91\x23" 446 "\xee\x80\xda\xbb\xc1\xff\xfe\xa3\x8a\x22\x12\x34\x56\x78\x91\x25", 447 46, 448 "r:0|p:16|.|alpn:10|ipv6:fe80:dabb:c1ff:fea3:8a22:1234:5678:9123|" 449 "ipv6:ee80:dabb:c1ff:fea3:8a22:1234:5678:9125|" 450 }, 451 { 452 "alpn + ech", 453 (const unsigned char *)"\x00\x10" /* 16-bit prio */ 454 "\x00" /* no RNAME */ 455 "\x00\x01" /* RR (1 == ALPN) */ 456 "\x00\x03" /* data size */ 457 "\x02" /* ALPN length byte */ 458 "h2" 459 "\x00\x05" /* RR (5 == ECH) */ 460 "\x00\x10" /* data size */ 461 "\xfe\x80\xda\xbb\xc1\xff\xfe\xa3\x8a\x22\x12\x34\x56\x78\x91\x23", 462 30, 463 "r:0|p:16|.|alpn:10|ech:fe80dabbc1fffea38a22123456789123|" 464 }, 465 { 466 "fully packed", 467 (const unsigned char *)"\xa0\x0b" /* 16-bit prio */ 468 "\x00" /* no RNAME */ 469 "\x00\x00" /* RR (0 == MANDATORY) */ 470 "\x00\x00" /* data size */ 471 "\x00\x01" /* RR (1 == ALPN) */ 472 "\x00\x06" /* data size */ 473 "\x02" /* ALPN length byte */ 474 "h2" 475 "\x02" /* ALPN length byte */ 476 "h1" 477 "\x00\x02" /* RR (2 == NO DEFAULT ALPN) */ 478 "\x00\x00" /* must be zero */ 479 "\x00\x03" /* RR (3 == PORT) */ 480 "\x00\x02" /* data size */ 481 "\xbc\x71" /* port number */ 482 "\x00\x04" /* RR (4 == Ipv4hints) */ 483 "\x00\x08" /* data size */ 484 "\xc0\xa8\x00\x01" /* 32 bits */ 485 "\xc0\xa8\x00\x02" /* 32 bits */ 486 "\x00\x05" /* RR (5 == ECH) */ 487 "\x00\x10" /* data size */ 488 "\xfe\x80\xda\xbb\xc1\xff\x7e\xb3\x8a\x22\x12\x34\x56\x78\x91\x23" 489 "\x00\x06" /* RR (6 == Ipv6hints) */ 490 "\x00\x20" /* data size */ 491 "\xfe\x80\xda\xbb\xc1\xff\xfe\xa3\x8a\x22\x12\x34\x56\x78\x91\x23" 492 "\xee\x80\xda\xbb\xc1\xff\xfe\xa3\x8a\x22\x12\x34\x56\x78\x91\x25" 493 "\x01\x07" /* RR (263 == not supported) */ 494 "\x00\x04" /* data size */ 495 "FFAA", /* unknown to the world */ 496 103, 497 "r:0|p:40971|.|alpn:10|alpn:8|no-def-alpn|port:48241|" 498 "ipv4:192.168.0.1|ipv4:192.168.0.2|" 499 "ech:fe80dabbc1ff7eb38a22123456789123|" 500 "ipv6:fe80:dabb:c1ff:fea3:8a22:1234:5678:9123|" 501 "ipv6:ee80:dabb:c1ff:fea3:8a22:1234:5678:9125|" 502 } 503 }; 504 505 CURLcode result = CURLE_OUT_OF_MEMORY; 506 CURL *easy; 507 508 easy = curl_easy_init(); 509 /* so that we get the log output: */ 510 curl_easy_setopt(easy, CURLOPT_VERBOSE, 1L); 511 if(easy) { 512 unsigned int i; 513 514 for(i = 0; i < CURL_ARRAYSIZE(t); i++) { 515 struct Curl_https_rrinfo *hrr; 516 517 printf("test %i: %s\n", i, t[i].name); 518 519 result = doh_resp_decode_httpsrr(easy, t[i].dns, t[i].len, &hrr); 520 521 /* create an output */ 522 rrresults(hrr, result); 523 524 /* is the output the expected? */ 525 if(strcmp(rrbuffer, t[i].expect)) { 526 curl_mfprintf(stderr, "Test %s (%i) failed\n" 527 "Expected: %s\n" 528 "Received: %s\n", t[i].name, i, t[i].expect, rrbuffer); 529 unitfail++; 530 } 531 532 /* free the generated struct */ 533 if(hrr) { 534 Curl_httpsrr_cleanup(hrr); 535 curl_free(hrr); 536 } 537 } 538 curl_easy_cleanup(easy); 539 } 540 541 UNITTEST_END(curl_global_cleanup()) 542 } 543 544 #else /* CURL_DISABLE_DOH or not HTTPSRR enabled */ 545 546 static CURLcode test_unit1658(char *arg) 547 { 548 UNITTEST_BEGIN_SIMPLE 549 UNITTEST_END_SIMPLE 550 } 551 552 #endif