1 /* 2 * str2host.c 3 * 4 * conversion routines from the presentation format 5 * to the host format 6 * 7 * a Net::DNS like library for C 8 * 9 * (c) NLnet Labs, 2004-2006 10 * 11 * See the file LICENSE for the license 12 */ 13 #include <ldns/config.h> 14 15 #include <ldns/ldns.h> 16 17 #ifdef HAVE_SYS_SOCKET_H 18 #include <sys/socket.h> 19 #endif 20 #ifdef HAVE_ARPA_INET_H 21 #include <arpa/inet.h> 22 #endif 23 #include <time.h> 24 25 #include <errno.h> 26 #ifdef HAVE_NETDB_H 27 #include <netdb.h> 28 #endif 29 30 #include <limits.h> 31 #ifdef HAVE_SYS_PARAM_H 32 #include <sys/param.h> 33 #endif 34 35 ldns_status 36 ldns_str2rdf_int16(ldns_rdf **rd, const char *shortstr) 37 { 38 char *end = NULL; 39 uint16_t *r; 40 r = LDNS_MALLOC(uint16_t); 41 if(!r) return LDNS_STATUS_MEM_ERR; 42 43 *r = htons((uint16_t)strtol((char *)shortstr, &end, 10)); 44 45 if(*end != 0) { 46 LDNS_FREE(r); 47 return LDNS_STATUS_INVALID_INT; 48 } else { 49 *rd = ldns_rdf_new_frm_data( 50 LDNS_RDF_TYPE_INT16, sizeof(uint16_t), r); 51 LDNS_FREE(r); 52 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 53 } 54 } 55 56 ldns_status 57 ldns_str2rdf_time(ldns_rdf **rd, const char *time) 58 { 59 /* convert a time YYYYDDMMHHMMSS to wireformat */ 60 uint32_t *r = NULL; 61 struct tm tm; 62 uint32_t l; 63 char *end; 64 65 /* Try to scan the time... */ 66 r = (uint32_t *)LDNS_MALLOC(uint32_t); 67 if(!r) return LDNS_STATUS_MEM_ERR; 68 69 memset(&tm, 0, sizeof(tm)); 70 71 if (strlen(time) == 14 && 72 sscanf(time, "%4d%2d%2d%2d%2d%2d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec) == 6 73 ) { 74 tm.tm_year -= 1900; 75 tm.tm_mon--; 76 /* Check values */ 77 if (tm.tm_year < 70) { 78 goto bad_format; 79 } 80 if (tm.tm_mon < 0 || tm.tm_mon > 11) { 81 goto bad_format; 82 } 83 if (tm.tm_mday < 1 || tm.tm_mday > 31) { 84 goto bad_format; 85 } 86 87 if (tm.tm_hour < 0 || tm.tm_hour > 23) { 88 goto bad_format; 89 } 90 91 if (tm.tm_min < 0 || tm.tm_min > 59) { 92 goto bad_format; 93 } 94 95 if (tm.tm_sec < 0 || tm.tm_sec > 59) { 96 goto bad_format; 97 } 98 99 l = htonl(ldns_mktime_from_utc(&tm)); 100 memcpy(r, &l, sizeof(uint32_t)); 101 *rd = ldns_rdf_new_frm_data( 102 LDNS_RDF_TYPE_TIME, sizeof(uint32_t), r); 103 LDNS_FREE(r); 104 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 105 } else { 106 /* handle it as 32 bits timestamp */ 107 l = htonl((uint32_t)strtol((char*)time, &end, 10)); 108 if(*end != 0) { 109 LDNS_FREE(r); 110 return LDNS_STATUS_ERR; 111 } else { 112 memcpy(r, &l, sizeof(uint32_t)); 113 *rd = ldns_rdf_new_frm_data( 114 LDNS_RDF_TYPE_INT32, sizeof(uint32_t), r); 115 LDNS_FREE(r); 116 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 117 } 118 } 119 120 bad_format: 121 LDNS_FREE(r); 122 return LDNS_STATUS_INVALID_TIME; 123 } 124 125 ldns_status 126 ldns_str2rdf_nsec3_salt(ldns_rdf **rd, const char *salt_str) 127 { 128 uint8_t salt_length; 129 int c; 130 int salt_length_str; 131 132 uint8_t *salt; 133 uint8_t *data; 134 if(rd == NULL) { 135 return LDNS_STATUS_NULL; 136 } 137 138 salt_length_str = (int)strlen(salt_str); 139 if (salt_length_str == 1 && salt_str[0] == '-') { 140 salt_length_str = 0; 141 } else if (salt_length_str % 2 != 0) { 142 return LDNS_STATUS_INVALID_HEX; 143 } 144 if (salt_length_str > 512) { 145 return LDNS_STATUS_INVALID_HEX; 146 } 147 148 salt = LDNS_XMALLOC(uint8_t, salt_length_str / 2); 149 if(!salt) { 150 return LDNS_STATUS_MEM_ERR; 151 } 152 for (c = 0; c < salt_length_str; c += 2) { 153 if (isxdigit((int) salt_str[c]) && isxdigit((int) salt_str[c+1])) { 154 salt[c/2] = (uint8_t) ldns_hexdigit_to_int(salt_str[c]) * 16 + 155 ldns_hexdigit_to_int(salt_str[c+1]); 156 } else { 157 LDNS_FREE(salt); 158 return LDNS_STATUS_INVALID_HEX; 159 } 160 } 161 salt_length = (uint8_t) (salt_length_str / 2); 162 163 data = LDNS_XMALLOC(uint8_t, 1 + salt_length); 164 if(!data) { 165 LDNS_FREE(salt); 166 return LDNS_STATUS_MEM_ERR; 167 } 168 data[0] = salt_length; 169 memcpy(&data[1], salt, salt_length); 170 *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_NSEC3_SALT, 1 + salt_length, data); 171 LDNS_FREE(data); 172 LDNS_FREE(salt); 173 174 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 175 } 176 177 ldns_status 178 ldns_str2rdf_period(ldns_rdf **rd,const char *period) 179 { 180 uint32_t p; 181 const char *end; 182 183 /* Allocate required space... */ 184 p = ldns_str2period(period, &end); 185 186 if (*end != 0) { 187 return LDNS_STATUS_ERR; 188 } else { 189 p = (uint32_t) htonl(p); 190 *rd = ldns_rdf_new_frm_data( 191 LDNS_RDF_TYPE_PERIOD, sizeof(uint32_t), &p); 192 } 193 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 194 } 195 196 ldns_status 197 ldns_str2rdf_int32(ldns_rdf **rd, const char *longstr) 198 { 199 char *end; 200 uint32_t *r = NULL; 201 uint32_t l; 202 203 r = (uint32_t*)LDNS_MALLOC(uint32_t); 204 if(!r) return LDNS_STATUS_MEM_ERR; 205 errno = 0; /* must set to zero before call, 206 note race condition on errno */ 207 if(*longstr == '-') 208 l = htonl((uint32_t)strtol((char*)longstr, &end, 10)); 209 else l = htonl((uint32_t)strtoul((char*)longstr, &end, 10)); 210 211 if(*end != 0) { 212 LDNS_FREE(r); 213 return LDNS_STATUS_ERR; 214 } else { 215 if (errno == ERANGE) { 216 LDNS_FREE(r); 217 return LDNS_STATUS_SYNTAX_INTEGER_OVERFLOW; 218 } 219 memcpy(r, &l, sizeof(uint32_t)); 220 *rd = ldns_rdf_new_frm_data( 221 LDNS_RDF_TYPE_INT32, sizeof(uint32_t), r); 222 LDNS_FREE(r); 223 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 224 } 225 } 226 227 ldns_status 228 ldns_str2rdf_int8(ldns_rdf **rd, const char *bytestr) 229 { 230 char *end; 231 uint8_t *r = NULL; 232 233 r = LDNS_MALLOC(uint8_t); 234 if(!r) return LDNS_STATUS_MEM_ERR; 235 236 *r = (uint8_t)strtol((char*)bytestr, &end, 10); 237 238 if(*end != 0) { 239 LDNS_FREE(r); 240 return LDNS_STATUS_ERR; 241 } else { 242 *rd = ldns_rdf_new_frm_data( 243 LDNS_RDF_TYPE_INT8, sizeof(uint8_t), r); 244 LDNS_FREE(r); 245 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 246 } 247 } 248 249 250 /* 251 * Checks whether the escaped value at **s is an decimal value or 252 * a 'normally' escaped character (and not eos) 253 * 254 * The string pointer at *s is increased by either 0 (on error), 1 (on 255 * normal escapes), or 3 (on decimals) 256 * 257 * Returns the number of bytes read from the escaped string, or 258 * 0 on error 259 */ 260 INLINE bool 261 parse_escape(uint8_t *ch_p, const char** str_p) 262 { 263 uint16_t val; 264 265 if ((*str_p)[0] && isdigit((unsigned char)(*str_p)[0]) && 266 (*str_p)[1] && isdigit((unsigned char)(*str_p)[1]) && 267 (*str_p)[2] && isdigit((unsigned char)(*str_p)[2])) { 268 269 val = (uint16_t)(((*str_p)[0] - '0') * 100 + 270 ((*str_p)[1] - '0') * 10 + 271 ((*str_p)[2] - '0')); 272 273 if (val > 255) { 274 goto error; 275 } 276 *ch_p = (uint8_t)val; 277 *str_p += 3; 278 return true; 279 280 } else if ((*str_p)[0] && !isdigit((unsigned char)(*str_p)[0])) { 281 282 *ch_p = (uint8_t)*(*str_p)++; 283 return true; 284 } 285 error: 286 *str_p = NULL; 287 return false; /* LDNS_STATUS_SYNTAX_BAD_ESCAPE */ 288 } 289 290 INLINE bool 291 parse_char(uint8_t *ch_p, const char** str_p) 292 { 293 switch (**str_p) { 294 295 case '\0': return false; 296 297 case '\\': *str_p += 1; 298 return parse_escape(ch_p, str_p); 299 300 default: *ch_p = (uint8_t)*(*str_p)++; 301 return true; 302 } 303 } 304 305 /* 306 * No special care is taken, all dots are translated into 307 * label separators. 308 * Could be made more efficient....we do 3 memcpy's in total... 309 */ 310 ldns_status 311 ldns_str2rdf_dname(ldns_rdf **d, const char *str) 312 { 313 size_t len; 314 315 const char *s; 316 uint8_t *q, *pq, label_len; 317 uint8_t buf[LDNS_MAX_DOMAINLEN + 1]; 318 *d = NULL; 319 320 len = strlen((char*)str); 321 /* octet representation can make strings a lot longer than actual length */ 322 if (len > LDNS_MAX_DOMAINLEN * 4) { 323 return LDNS_STATUS_DOMAINNAME_OVERFLOW; 324 } 325 if (0 == len) { 326 return LDNS_STATUS_DOMAINNAME_UNDERFLOW; 327 } 328 329 /* root label */ 330 if (1 == len && *str == '.') { 331 *d = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME, 1, "\0"); 332 return LDNS_STATUS_OK; 333 } 334 335 /* get on with the rest */ 336 337 /* s is on the current character in the string 338 * pq points to where the labellength is going to go 339 * label_len keeps track of the current label's length 340 * q builds the dname inside the buf array 341 */ 342 len = 0; 343 q = buf+1; 344 pq = buf; 345 label_len = 0; 346 for (s = str; *s; s++, q++) { 347 if (q >= buf + LDNS_MAX_DOMAINLEN) { 348 return LDNS_STATUS_DOMAINNAME_OVERFLOW; 349 } 350 *q = 0; 351 switch (*s) { 352 case '.': 353 if (label_len > LDNS_MAX_LABELLEN) { 354 return LDNS_STATUS_LABEL_OVERFLOW; 355 } 356 if (label_len == 0) { 357 return LDNS_STATUS_EMPTY_LABEL; 358 } 359 len += label_len + 1; 360 *pq = label_len; 361 label_len = 0; 362 pq = q; 363 break; 364 case '\\': 365 /* octet value or literal char */ 366 s += 1; 367 if (! parse_escape(q, &s)) { 368 return LDNS_STATUS_SYNTAX_BAD_ESCAPE; 369 } 370 s -= 1; 371 label_len++; 372 break; 373 default: 374 *q = (uint8_t)*s; 375 label_len++; 376 } 377 } 378 379 /* add root label if last char was not '.' */ 380 if (!ldns_dname_str_absolute(str)) { 381 if (q >= buf + LDNS_MAX_DOMAINLEN) { 382 return LDNS_STATUS_DOMAINNAME_OVERFLOW; 383 } 384 if (label_len > LDNS_MAX_LABELLEN) { 385 return LDNS_STATUS_LABEL_OVERFLOW; 386 } 387 if (label_len == 0) { /* label_len 0 but not . at end? */ 388 return LDNS_STATUS_EMPTY_LABEL; 389 } 390 len += label_len + 1; 391 *pq = label_len; 392 *q = 0; 393 } 394 len++; 395 396 *d = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_DNAME, len, buf); 397 return LDNS_STATUS_OK; 398 } 399 400 ldns_status 401 ldns_str2rdf_a(ldns_rdf **rd, const char *str) 402 { 403 in_addr_t address; 404 if (inet_pton(AF_INET, (char*)str, &address) != 1) { 405 return LDNS_STATUS_INVALID_IP4; 406 } else { 407 *rd = ldns_rdf_new_frm_data( 408 LDNS_RDF_TYPE_A, sizeof(address), &address); 409 } 410 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 411 } 412 413 ldns_status 414 ldns_str2rdf_aaaa(ldns_rdf **rd, const char *str) 415 { 416 uint8_t address[LDNS_IP6ADDRLEN + 1]; 417 418 if (inet_pton(AF_INET6, (char*)str, address) != 1) { 419 return LDNS_STATUS_INVALID_IP6; 420 } else { 421 *rd = ldns_rdf_new_frm_data( 422 LDNS_RDF_TYPE_AAAA, sizeof(address) - 1, &address); 423 } 424 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 425 } 426 427 ldns_status 428 ldns_str2rdf_str(ldns_rdf **rd, const char *str) 429 { 430 uint8_t *data, *dp, ch = 0; 431 size_t length; 432 433 /* Worst case space requirement. We'll realloc to actual size later. */ 434 dp = data = LDNS_XMALLOC(uint8_t, strlen(str) > 255 ? 256 : (strlen(str) + 1)); 435 if (! data) { 436 return LDNS_STATUS_MEM_ERR; 437 } 438 439 /* Fill data (up to 255 characters) */ 440 while (parse_char(&ch, &str)) { 441 if (dp - data >= 255) { 442 LDNS_FREE(data); 443 return LDNS_STATUS_INVALID_STR; 444 } 445 *++dp = ch; 446 } 447 if (! str) { 448 LDNS_FREE(data); 449 return LDNS_STATUS_SYNTAX_BAD_ESCAPE; 450 } 451 length = (size_t)(dp - data); 452 /* Fix last length byte */ 453 data[0] = (uint8_t)length; 454 455 /* Lose the overmeasure */ 456 data = LDNS_XREALLOC(dp = data, uint8_t, length + 1); 457 if (! data) { 458 LDNS_FREE(dp); 459 return LDNS_STATUS_MEM_ERR; 460 } 461 462 /* Create rdf */ 463 *rd = ldns_rdf_new(LDNS_RDF_TYPE_STR, length + 1, data); 464 if (! *rd) { 465 LDNS_FREE(data); 466 return LDNS_STATUS_MEM_ERR; 467 } 468 return LDNS_STATUS_OK; 469 } 470 471 ldns_status 472 ldns_str2rdf_apl(ldns_rdf **rd, const char *str) 473 { 474 const char *my_str = str; 475 476 char *my_ip_str; 477 size_t ip_str_len; 478 479 uint16_t family; 480 bool negation; 481 uint8_t afdlength = 0; 482 uint8_t *afdpart; 483 uint8_t prefix; 484 485 uint8_t *data; 486 487 size_t i = 0; 488 489 /* [!]afi:address/prefix */ 490 if (strlen(my_str) < 2 491 || strchr(my_str, ':') == NULL 492 || strchr(my_str, '/') == NULL 493 || strchr(my_str, ':') > strchr(my_str, '/')) { 494 return LDNS_STATUS_INVALID_STR; 495 } 496 497 if (my_str[0] == '!') { 498 negation = true; 499 my_str += 1; 500 } else { 501 negation = false; 502 } 503 504 family = (uint16_t) atoi(my_str); 505 506 my_str = strchr(my_str, ':') + 1; 507 508 /* need ip addr and only ip addr for inet_pton */ 509 ip_str_len = (size_t) (strchr(my_str, '/') - my_str); 510 my_ip_str = LDNS_XMALLOC(char, ip_str_len + 1); 511 if(!my_ip_str) return LDNS_STATUS_MEM_ERR; 512 strncpy(my_ip_str, my_str, ip_str_len + 1); 513 my_ip_str[ip_str_len] = '\0'; 514 515 if (family == 1) { 516 /* ipv4 */ 517 afdpart = LDNS_XMALLOC(uint8_t, 4); 518 if(!afdpart) { 519 LDNS_FREE(my_ip_str); 520 return LDNS_STATUS_MEM_ERR; 521 } 522 if (inet_pton(AF_INET, my_ip_str, afdpart) == 0) { 523 LDNS_FREE(my_ip_str); 524 LDNS_FREE(afdpart); 525 return LDNS_STATUS_INVALID_STR; 526 } 527 for (i = 0; i < 4; i++) { 528 if (afdpart[i] != 0) { 529 afdlength = i + 1; 530 } 531 } 532 } else if (family == 2) { 533 /* ipv6 */ 534 afdpart = LDNS_XMALLOC(uint8_t, 16); 535 if(!afdpart) { 536 LDNS_FREE(my_ip_str); 537 return LDNS_STATUS_MEM_ERR; 538 } 539 if (inet_pton(AF_INET6, my_ip_str, afdpart) == 0) { 540 LDNS_FREE(my_ip_str); 541 LDNS_FREE(afdpart); 542 return LDNS_STATUS_INVALID_STR; 543 } 544 for (i = 0; i < 16; i++) { 545 if (afdpart[i] != 0) { 546 afdlength = i + 1; 547 } 548 } 549 } else { 550 /* unknown family */ 551 LDNS_FREE(my_ip_str); 552 return LDNS_STATUS_INVALID_STR; 553 } 554 555 my_str = strchr(my_str, '/') + 1; 556 prefix = (uint8_t) atoi(my_str); 557 558 data = LDNS_XMALLOC(uint8_t, 4 + afdlength); 559 if(!data) { 560 LDNS_FREE(afdpart); 561 LDNS_FREE(my_ip_str); 562 return LDNS_STATUS_INVALID_STR; 563 } 564 ldns_write_uint16(data, family); 565 data[2] = prefix; 566 data[3] = afdlength; 567 if (negation) { 568 /* set bit 1 of byte 3 */ 569 data[3] = data[3] | 0x80; 570 } 571 572 memcpy(data + 4, afdpart, afdlength); 573 574 *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_APL, afdlength + 4, data); 575 LDNS_FREE(afdpart); 576 LDNS_FREE(data); 577 LDNS_FREE(my_ip_str); 578 579 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 580 } 581 582 ldns_status 583 ldns_str2rdf_b64(ldns_rdf **rd, const char *str) 584 { 585 uint8_t *buffer; 586 int16_t i; 587 588 if ((*str == '-' || *str == '0') && str[1] == '\0') { 589 *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_B64, 0, NULL); 590 return *rd ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR; 591 } 592 593 buffer = LDNS_XMALLOC(uint8_t, ldns_b64_ntop_calculate_size(strlen(str))); 594 if(!buffer) { 595 return LDNS_STATUS_MEM_ERR; 596 } 597 598 i = (uint16_t)ldns_b64_pton((const char*)str, buffer, 599 ldns_b64_ntop_calculate_size(strlen(str))); 600 if (-1 == i) { 601 LDNS_FREE(buffer); 602 return LDNS_STATUS_INVALID_B64; 603 } else { 604 *rd = ldns_rdf_new_frm_data( 605 LDNS_RDF_TYPE_B64, (uint16_t) i, buffer); 606 } 607 LDNS_FREE(buffer); 608 609 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 610 } 611 612 ldns_status 613 ldns_str2rdf_b32_ext(ldns_rdf **rd, const char *str) 614 { 615 uint8_t *buffer; 616 int i; 617 /* first byte contains length of actual b32 data */ 618 size_t slen = strlen(str); 619 size_t len = ldns_b32_pton_calculate_size(slen); 620 if (len > 255) { 621 return LDNS_STATUS_INVALID_B32_EXT; 622 } 623 buffer = LDNS_XMALLOC(uint8_t, len + 1); 624 if(!buffer) { 625 return LDNS_STATUS_MEM_ERR; 626 } 627 buffer[0] = len; 628 629 i = ldns_b32_pton_extended_hex((const char*)str, slen, buffer + 1, 630 ldns_b32_ntop_calculate_size(slen)); 631 if (i < 0) { 632 LDNS_FREE(buffer); 633 return LDNS_STATUS_INVALID_B32_EXT; 634 } else { 635 *rd = ldns_rdf_new_frm_data( 636 LDNS_RDF_TYPE_B32_EXT, (uint16_t) i + 1, buffer); 637 } 638 LDNS_FREE(buffer); 639 640 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 641 } 642 643 ldns_status 644 ldns_str2rdf_hex(ldns_rdf **rd, const char *str) 645 { 646 uint8_t *t, *t_orig; 647 int i; 648 size_t len; 649 650 len = strlen(str); 651 652 if (len > LDNS_MAX_RDFLEN * 2) { 653 return LDNS_STATUS_LABEL_OVERFLOW; 654 } else { 655 t = LDNS_XMALLOC(uint8_t, (len / 2) + 1); 656 if(!t) { 657 return LDNS_STATUS_MEM_ERR; 658 } 659 t_orig = t; 660 /* Now process octet by octet... */ 661 while (*str) { 662 *t = 0; 663 if (isspace((int) *str)) { 664 str++; 665 } else { 666 for (i = 16; i >= 1; i -= 15) { 667 while (*str && isspace((int) *str)) { str++; } 668 if (*str) { 669 if (isxdigit((int) *str)) { 670 *t += ldns_hexdigit_to_int(*str) * i; 671 } else { 672 LDNS_FREE(t_orig); 673 return LDNS_STATUS_ERR; 674 } 675 ++str; 676 } 677 } 678 ++t; 679 } 680 } 681 *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_HEX, 682 (size_t) (t - t_orig), 683 t_orig); 684 LDNS_FREE(t_orig); 685 } 686 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 687 } 688 689 ldns_status 690 ldns_str2rdf_nsec(ldns_rdf **rd, const char *str) 691 { 692 const char *delimiters = "\n\t "; 693 char *token = LDNS_XMALLOC(char, LDNS_MAX_RDFLEN); 694 ldns_buffer *str_buf; 695 ssize_t c; 696 uint16_t cur_type; 697 size_t type_count = 0; 698 ldns_rr_type type_list[65536]; 699 if(!token) return LDNS_STATUS_MEM_ERR; 700 if(rd == NULL) { 701 LDNS_FREE(token); 702 return LDNS_STATUS_NULL; 703 } 704 705 str_buf = LDNS_MALLOC(ldns_buffer); 706 if(!str_buf) { 707 LDNS_FREE(token); 708 return LDNS_STATUS_MEM_ERR; 709 } 710 ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str)); 711 if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) { 712 LDNS_FREE(str_buf); 713 LDNS_FREE(token); 714 return LDNS_STATUS_MEM_ERR; 715 } 716 717 while ((c = ldns_bget_token(str_buf, token, delimiters, LDNS_MAX_RDFLEN)) != -1 && c != 0) { 718 if(type_count >= sizeof(type_list)) { 719 LDNS_FREE(str_buf); 720 LDNS_FREE(token); 721 return LDNS_STATUS_ERR; 722 } 723 cur_type = ldns_get_rr_type_by_name(token); 724 type_list[type_count] = cur_type; 725 type_count++; 726 } 727 728 *rd = ldns_dnssec_create_nsec_bitmap(type_list, 729 type_count, 730 LDNS_RR_TYPE_NSEC); 731 732 LDNS_FREE(token); 733 ldns_buffer_free(str_buf); 734 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 735 } 736 737 ldns_status 738 ldns_str2rdf_type(ldns_rdf **rd, const char *str) 739 { 740 uint16_t type; 741 type = htons(ldns_get_rr_type_by_name(str)); 742 /* ldns_rr_type is a 16 bit value */ 743 *rd = ldns_rdf_new_frm_data( 744 LDNS_RDF_TYPE_TYPE, sizeof(uint16_t), &type); 745 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 746 } 747 748 ldns_status 749 ldns_str2rdf_class(ldns_rdf **rd, const char *str) 750 { 751 uint16_t klass; 752 klass = htons(ldns_get_rr_class_by_name(str)); 753 /* class is 16 bit */ 754 *rd = ldns_rdf_new_frm_data( 755 LDNS_RDF_TYPE_CLASS, sizeof(uint16_t), &klass); 756 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 757 } 758 759 /* An certificate alg field can either be specified as a 8 bits number 760 * or by its symbolic name. Handle both 761 */ 762 ldns_status 763 ldns_str2rdf_cert_alg(ldns_rdf **rd, const char *str) 764 { 765 ldns_lookup_table *lt; 766 ldns_status st; 767 uint8_t idd[2]; 768 lt = ldns_lookup_by_name(ldns_cert_algorithms, str); 769 st = LDNS_STATUS_OK; 770 771 if (lt) { 772 ldns_write_uint16(idd, (uint16_t) lt->id); 773 *rd = ldns_rdf_new_frm_data( 774 LDNS_RDF_TYPE_INT16, sizeof(uint16_t), idd); 775 if (!*rd) { 776 st = LDNS_STATUS_ERR; 777 } 778 } else { 779 /* try as-is (a number) */ 780 st = ldns_str2rdf_int16(rd, str); 781 if (st == LDNS_STATUS_OK && 782 ldns_rdf2native_int16(*rd) == 0) { 783 st = LDNS_STATUS_CERT_BAD_ALGORITHM; 784 } 785 } 786 787 return st; 788 } 789 790 static ldns_lookup_table ldns_tlsa_certificate_usages[] = { 791 { LDNS_TLSA_USAGE_PKIX_TA , "PKIX-TA" }, 792 { LDNS_TLSA_USAGE_PKIX_EE , "PKIX-EE" }, 793 { LDNS_TLSA_USAGE_DANE_TA , "DANE-TA" }, 794 { LDNS_TLSA_USAGE_DANE_EE , "DANE-EE" }, 795 { LDNS_TLSA_USAGE_PRIVCERT , "PrivCert" }, 796 { 0, NULL } 797 }; 798 799 static ldns_lookup_table ldns_tlsa_selectors[] = { 800 { LDNS_TLSA_SELECTOR_CERT , "Cert" }, 801 { LDNS_TLSA_SELECTOR_SPKI , "SPKI" }, 802 { LDNS_TLSA_SELECTOR_PRIVSEL , "PrivSel" }, 803 { 0, NULL } 804 }; 805 806 static ldns_lookup_table ldns_tlsa_matching_types[] = { 807 { LDNS_TLSA_MATCHING_TYPE_FULL , "Full" }, 808 { LDNS_TLSA_MATCHING_TYPE_SHA2_256 , "SHA2-256" }, 809 { LDNS_TLSA_MATCHING_TYPE_SHA2_512 , "SHA2-512" }, 810 { LDNS_TLSA_MATCHING_TYPE_PRIVMATCH , "PrivMatch" }, 811 { 0, NULL } 812 }; 813 814 static ldns_status 815 ldns_str2rdf_mnemonic4int8(ldns_lookup_table *lt, 816 ldns_rdf **rd, const char *str) 817 { 818 if ((lt = ldns_lookup_by_name(lt, str))) { 819 /* it was given as a integer */ 820 *rd = ldns_native2rdf_int8(LDNS_RDF_TYPE_INT8, (uint8_t) lt->id); 821 if (!*rd) 822 return LDNS_STATUS_ERR; 823 else 824 return LDNS_STATUS_OK; 825 } 826 return ldns_str2rdf_int8(rd, str); 827 } 828 829 /* An alg field can either be specified as a 8 bits number 830 * or by its symbolic name. Handle both 831 */ 832 ldns_status 833 ldns_str2rdf_alg(ldns_rdf **rd, const char *str) 834 { 835 return ldns_str2rdf_mnemonic4int8(ldns_algorithms, rd, str); 836 } 837 838 ldns_status 839 ldns_str2rdf_certificate_usage(ldns_rdf **rd, const char *str) 840 { 841 return ldns_str2rdf_mnemonic4int8( 842 ldns_tlsa_certificate_usages, rd, str); 843 } 844 845 ldns_status 846 ldns_str2rdf_selector(ldns_rdf **rd, const char *str) 847 { 848 return ldns_str2rdf_mnemonic4int8(ldns_tlsa_selectors, rd, str); 849 } 850 851 ldns_status 852 ldns_str2rdf_matching_type(ldns_rdf **rd, const char *str) 853 { 854 return ldns_str2rdf_mnemonic4int8(ldns_tlsa_matching_types, rd, str); 855 } 856 857 ldns_status 858 ldns_str2rdf_unknown( ATTR_UNUSED(ldns_rdf **rd) 859 , ATTR_UNUSED(const char *str) 860 ) 861 { 862 /* this should be caught in an earlier time (general str2host for 863 rr's */ 864 return LDNS_STATUS_NOT_IMPL; 865 } 866 867 ldns_status 868 ldns_str2rdf_service( ATTR_UNUSED(ldns_rdf **rd) 869 , ATTR_UNUSED(const char *str) 870 ) 871 { 872 /* is this used? is this actually WKS? or SRV? */ 873 return LDNS_STATUS_NOT_IMPL; 874 } 875 876 static int 877 loc_parse_cm(char* my_str, char** endstr, uint8_t* m, uint8_t* e) 878 { 879 /* read <digits>[.<digits>][mM] */ 880 /* into mantissa exponent format for LOC type */ 881 uint32_t meters = 0, cm = 0, val; 882 char* cm_endstr; 883 while (isblank((unsigned char)*my_str)) { 884 my_str++; 885 } 886 meters = (uint32_t)strtol(my_str, &my_str, 10); 887 if (*my_str == '.') { 888 my_str++; 889 cm = (uint32_t)strtol(my_str, &cm_endstr, 10); 890 if (cm_endstr - my_str == 1) cm *= 10; 891 my_str = cm_endstr; 892 } 893 if (meters >= 1) { 894 *e = 2; 895 val = meters; 896 } else { 897 *e = 0; 898 val = cm; 899 } 900 while(val >= 10) { 901 (*e)++; 902 val /= 10; 903 } 904 *m = (uint8_t)val; 905 906 if (*e > 9) 907 return 0; 908 if (*my_str == 'm' || *my_str == 'M') { 909 my_str++; 910 } 911 *endstr = my_str; 912 return 1; 913 } 914 915 ldns_status 916 ldns_str2rdf_loc(ldns_rdf **rd, const char *str) 917 { 918 uint32_t latitude = 0; 919 uint32_t longitude = 0; 920 uint32_t altitude = 0; 921 922 uint8_t *data; 923 uint32_t equator = (uint32_t) ldns_power(2, 31); 924 925 uint32_t h = 0; 926 uint32_t m = 0; 927 uint8_t size_b = 1, size_e = 2; 928 uint8_t horiz_pre_b = 1, horiz_pre_e = 6; 929 uint8_t vert_pre_b = 1, vert_pre_e = 3; 930 931 double s = 0.0; 932 bool northern_hemisphere; 933 bool eastern_hemisphere; 934 935 char *my_str = (char *) str; 936 937 /* only support version 0 */ 938 if (isdigit((int) *my_str)) { 939 h = (uint32_t) strtol(my_str, &my_str, 10); 940 } else { 941 return LDNS_STATUS_INVALID_STR; 942 } 943 944 while (isblank((int) *my_str)) { 945 my_str++; 946 } 947 948 if (isdigit((int) *my_str)) { 949 m = (uint32_t) strtol(my_str, &my_str, 10); 950 } else if (*my_str == 'N' || *my_str == 'S') { 951 goto north; 952 } else { 953 return LDNS_STATUS_INVALID_STR; 954 } 955 956 while (isblank((int) *my_str)) { 957 my_str++; 958 } 959 960 if (isdigit((int) *my_str)) { 961 s = strtod(my_str, &my_str); 962 } 963 north: 964 while (isblank((int) *my_str)) { 965 my_str++; 966 } 967 968 if (*my_str == 'N') { 969 northern_hemisphere = true; 970 } else if (*my_str == 'S') { 971 northern_hemisphere = false; 972 } else { 973 return LDNS_STATUS_INVALID_STR; 974 } 975 976 my_str++; 977 978 /* store number */ 979 s = 1000.0 * s; 980 /* add a little to make floor in conversion a round */ 981 s += 0.0005; 982 latitude = (uint32_t) s; 983 latitude += 1000 * 60 * m; 984 latitude += 1000 * 60 * 60 * h; 985 if (northern_hemisphere) { 986 latitude = equator + latitude; 987 } else { 988 latitude = equator - latitude; 989 } 990 while (isblank((unsigned char)*my_str)) { 991 my_str++; 992 } 993 994 if (isdigit((int) *my_str)) { 995 h = (uint32_t) strtol(my_str, &my_str, 10); 996 } else { 997 return LDNS_STATUS_INVALID_STR; 998 } 999 1000 while (isblank((int) *my_str)) { 1001 my_str++; 1002 } 1003 1004 if (isdigit((int) *my_str)) { 1005 m = (uint32_t) strtol(my_str, &my_str, 10); 1006 } else if (*my_str == 'E' || *my_str == 'W') { 1007 goto east; 1008 } else { 1009 return LDNS_STATUS_INVALID_STR; 1010 } 1011 1012 while (isblank((unsigned char)*my_str)) { 1013 my_str++; 1014 } 1015 1016 if (isdigit((int) *my_str)) { 1017 s = strtod(my_str, &my_str); 1018 } 1019 1020 east: 1021 while (isblank((unsigned char)*my_str)) { 1022 my_str++; 1023 } 1024 1025 if (*my_str == 'E') { 1026 eastern_hemisphere = true; 1027 } else if (*my_str == 'W') { 1028 eastern_hemisphere = false; 1029 } else { 1030 return LDNS_STATUS_INVALID_STR; 1031 } 1032 1033 my_str++; 1034 1035 /* store number */ 1036 s *= 1000.0; 1037 /* add a little to make floor in conversion a round */ 1038 s += 0.0005; 1039 longitude = (uint32_t) s; 1040 longitude += 1000 * 60 * m; 1041 longitude += 1000 * 60 * 60 * h; 1042 1043 if (eastern_hemisphere) { 1044 longitude += equator; 1045 } else { 1046 longitude = equator - longitude; 1047 } 1048 1049 altitude = (uint32_t)(strtod(my_str, &my_str)*100.0 + 1050 10000000.0 + 0.5); 1051 if (*my_str == 'm' || *my_str == 'M') { 1052 my_str++; 1053 } 1054 1055 if (strlen(my_str) > 0) { 1056 if(!loc_parse_cm(my_str, &my_str, &size_b, &size_e)) 1057 return LDNS_STATUS_INVALID_STR; 1058 } 1059 1060 if (strlen(my_str) > 0) { 1061 if(!loc_parse_cm(my_str, &my_str, &horiz_pre_b, &horiz_pre_e)) 1062 return LDNS_STATUS_INVALID_STR; 1063 } 1064 1065 if (strlen(my_str) > 0) { 1066 if(!loc_parse_cm(my_str, &my_str, &vert_pre_b, &vert_pre_e)) 1067 return LDNS_STATUS_INVALID_STR; 1068 } 1069 1070 data = LDNS_XMALLOC(uint8_t, 16); 1071 if(!data) { 1072 return LDNS_STATUS_MEM_ERR; 1073 } 1074 data[0] = 0; 1075 data[1] = 0; 1076 data[1] = ((size_b << 4) & 0xf0) | (size_e & 0x0f); 1077 data[2] = ((horiz_pre_b << 4) & 0xf0) | (horiz_pre_e & 0x0f); 1078 data[3] = ((vert_pre_b << 4) & 0xf0) | (vert_pre_e & 0x0f); 1079 ldns_write_uint32(data + 4, latitude); 1080 ldns_write_uint32(data + 8, longitude); 1081 ldns_write_uint32(data + 12, altitude); 1082 1083 *rd = ldns_rdf_new_frm_data( 1084 LDNS_RDF_TYPE_LOC, 16, data); 1085 1086 LDNS_FREE(data); 1087 return *rd?LDNS_STATUS_OK:LDNS_STATUS_MEM_ERR; 1088 } 1089 1090 ldns_status 1091 ldns_str2rdf_wks(ldns_rdf **rd, const char *str) 1092 { 1093 uint8_t *bitmap = NULL; 1094 uint8_t *data; 1095 int bm_len = 0; 1096 1097 struct protoent *proto = NULL; 1098 struct servent *serv = NULL; 1099 int serv_port; 1100 1101 ldns_buffer *str_buf; 1102 1103 char *proto_str = NULL; 1104 char *lc_proto_str = NULL; 1105 char *token; 1106 char *lc_token; 1107 char *c; 1108 if(strlen(str) == 0) 1109 token = LDNS_XMALLOC(char, 50); 1110 else token = LDNS_XMALLOC(char, strlen(str)+2); 1111 if(!token) return LDNS_STATUS_MEM_ERR; 1112 1113 str_buf = LDNS_MALLOC(ldns_buffer); 1114 if(!str_buf) {LDNS_FREE(token); return LDNS_STATUS_MEM_ERR;} 1115 ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str)); 1116 if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) { 1117 LDNS_FREE(str_buf); 1118 LDNS_FREE(token); 1119 return LDNS_STATUS_MEM_ERR; 1120 } 1121 1122 while(ldns_bget_token(str_buf, token, "\t\n ", strlen(str)) > 0) { 1123 if (!proto_str) { 1124 proto_str = strdup(token); 1125 lc_proto_str = strdup(token); 1126 for (c = lc_proto_str; *c; c++) { 1127 *c = tolower((unsigned char)*c); 1128 } 1129 if (!proto_str || !lc_proto_str) { 1130 free(proto_str); 1131 free(lc_proto_str); 1132 LDNS_FREE(bitmap); 1133 LDNS_FREE(token); 1134 ldns_buffer_free(str_buf); 1135 return LDNS_STATUS_INVALID_STR; 1136 } 1137 } else { 1138 serv = getservbyname(token, proto_str); 1139 if (!serv) { 1140 serv = getservbyname(token, lc_proto_str); 1141 } 1142 if (!serv && (lc_token = strdup(token))) { 1143 for (c = lc_token; *c; c++) { 1144 *c = tolower((unsigned char)*c); 1145 } 1146 serv = getservbyname(lc_token, proto_str); 1147 if (!serv) { 1148 serv = getservbyname(lc_token, lc_proto_str); 1149 } 1150 free(lc_token); 1151 } 1152 if (serv) { 1153 serv_port = (int) ntohs((uint16_t) serv->s_port); 1154 } else { 1155 serv_port = atoi(token); 1156 } 1157 if (serv_port < 0 || serv_port > 65535) { 1158 LDNS_FREE(bitmap); 1159 LDNS_FREE(token); 1160 ldns_buffer_free(str_buf); 1161 free(proto_str); 1162 free(lc_proto_str); 1163 return LDNS_STATUS_INVALID_STR; 1164 } 1165 if (serv_port / 8 >= bm_len) { 1166 uint8_t *b2 = LDNS_XREALLOC(bitmap, uint8_t, (serv_port / 8) + 1); 1167 if(!b2) { 1168 LDNS_FREE(bitmap); 1169 LDNS_FREE(token); 1170 ldns_buffer_free(str_buf); 1171 free(proto_str); 1172 free(lc_proto_str); 1173 return LDNS_STATUS_INVALID_STR; 1174 } 1175 bitmap = b2; 1176 /* set to zero to be sure */ 1177 for (; bm_len <= serv_port / 8; bm_len++) { 1178 bitmap[bm_len] = 0; 1179 } 1180 } 1181 ldns_set_bit(bitmap + (serv_port / 8), 7 - (serv_port % 8), true); 1182 } 1183 } 1184 1185 if (!proto_str || !bitmap) { 1186 LDNS_FREE(bitmap); 1187 LDNS_FREE(token); 1188 ldns_buffer_free(str_buf); 1189 free(proto_str); 1190 free(lc_proto_str); 1191 return LDNS_STATUS_INVALID_STR; 1192 } 1193 1194 data = LDNS_XMALLOC(uint8_t, bm_len + 1); 1195 if(!data) { 1196 LDNS_FREE(token); 1197 ldns_buffer_free(str_buf); 1198 LDNS_FREE(bitmap); 1199 free(proto_str); 1200 free(lc_proto_str); 1201 return LDNS_STATUS_INVALID_STR; 1202 } 1203 if (proto_str) 1204 proto = getprotobyname(proto_str); 1205 if (!proto) { 1206 proto = getprotobyname(lc_proto_str); 1207 } 1208 if (proto) { 1209 data[0] = (uint8_t) proto->p_proto; 1210 } else if (proto_str) { 1211 data[0] = (uint8_t) atoi(proto_str); 1212 } 1213 memcpy(data + 1, bitmap, (size_t) bm_len); 1214 1215 *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_WKS, (uint16_t) (bm_len + 1), data); 1216 1217 LDNS_FREE(data); 1218 LDNS_FREE(token); 1219 ldns_buffer_free(str_buf); 1220 LDNS_FREE(bitmap); 1221 free(proto_str); 1222 free(lc_proto_str); 1223 #ifdef HAVE_ENDSERVENT 1224 endservent(); 1225 #endif 1226 #ifdef HAVE_ENDPROTOENT 1227 endprotoent(); 1228 #endif 1229 1230 if(!*rd) return LDNS_STATUS_MEM_ERR; 1231 1232 return LDNS_STATUS_OK; 1233 } 1234 1235 ldns_status 1236 ldns_str2rdf_nsap(ldns_rdf **rd, const char *str) 1237 { 1238 size_t len, i; 1239 char* nsap_str = (char*) str; 1240 1241 /* just a hex string with optional dots? */ 1242 if (str[0] != '0' || str[1] != 'x') { 1243 return LDNS_STATUS_INVALID_STR; 1244 } else { 1245 len = strlen(str); 1246 for (i=0; i < len; i++) { 1247 if (nsap_str[i] == '.') 1248 nsap_str[i] = ' '; 1249 } 1250 return ldns_str2rdf_hex(rd, str+2); 1251 } 1252 } 1253 1254 ldns_status 1255 ldns_str2rdf_atma(ldns_rdf **rd, const char *str) 1256 { 1257 size_t len, i; 1258 char* atma_str = (char*) str; 1259 ldns_status status; 1260 1261 /* just a hex string with optional dots? */ 1262 len = strlen(str); 1263 for (i=0; i < len; i++) { 1264 if (atma_str[i] == '.') 1265 atma_str[i] = ' '; 1266 } 1267 status = ldns_str2rdf_hex(rd, str); 1268 if (status != LDNS_STATUS_OK) { 1269 ; /* probably in e.164 format than */ 1270 } 1271 return status; 1272 } 1273 1274 ldns_status 1275 ldns_str2rdf_ipseckey(ldns_rdf **rd, const char *str) 1276 { 1277 uint8_t precedence = 0; 1278 uint8_t gateway_type = 0; 1279 uint8_t algorithm = 0; 1280 char* gateway = NULL; 1281 char* publickey = NULL; 1282 uint8_t *data; 1283 ldns_buffer *str_buf; 1284 char *token; 1285 int token_count = 0; 1286 int ipseckey_len = 0; 1287 ldns_rdf* gateway_rdf = NULL; 1288 ldns_rdf* publickey_rdf = NULL; 1289 ldns_status status = LDNS_STATUS_OK; 1290 1291 if(strlen(str) == 0) 1292 token = LDNS_XMALLOC(char, 256); 1293 else token = LDNS_XMALLOC(char, strlen(str)+2); 1294 if(!token) return LDNS_STATUS_MEM_ERR; 1295 1296 str_buf = LDNS_MALLOC(ldns_buffer); 1297 if(!str_buf) {LDNS_FREE(token); return LDNS_STATUS_MEM_ERR;} 1298 ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str)); 1299 if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) { 1300 LDNS_FREE(str_buf); 1301 LDNS_FREE(token); 1302 return LDNS_STATUS_MEM_ERR; 1303 } 1304 while(ldns_bget_token(str_buf, token, "\t\n ", strlen(str)) > 0) { 1305 switch (token_count) { 1306 case 0: 1307 precedence = (uint8_t)atoi(token); 1308 break; 1309 case 1: 1310 gateway_type = (uint8_t)atoi(token); 1311 break; 1312 case 2: 1313 algorithm = (uint8_t)atoi(token); 1314 break; 1315 case 3: 1316 gateway = strdup(token); 1317 if (!gateway || (gateway_type == 0 && 1318 (token[0] != '.' || token[1] != '\0'))) { 1319 LDNS_FREE(gateway); 1320 LDNS_FREE(token); 1321 ldns_buffer_free(str_buf); 1322 return LDNS_STATUS_INVALID_STR; 1323 } 1324 break; 1325 case 4: 1326 publickey = strdup(token); 1327 break; 1328 default: 1329 LDNS_FREE(token); 1330 ldns_buffer_free(str_buf); 1331 return LDNS_STATUS_INVALID_STR; 1332 break; 1333 } 1334 token_count++; 1335 } 1336 1337 if (!gateway || !publickey) { 1338 if (gateway) 1339 LDNS_FREE(gateway); 1340 if (publickey) 1341 LDNS_FREE(publickey); 1342 LDNS_FREE(token); 1343 ldns_buffer_free(str_buf); 1344 return LDNS_STATUS_INVALID_STR; 1345 } 1346 1347 if (gateway_type == 1) { 1348 status = ldns_str2rdf_a(&gateway_rdf, gateway); 1349 } else if (gateway_type == 2) { 1350 status = ldns_str2rdf_aaaa(&gateway_rdf, gateway); 1351 } else if (gateway_type == 3) { 1352 status = ldns_str2rdf_dname(&gateway_rdf, gateway); 1353 } else if (gateway_type > 3) { 1354 status = LDNS_STATUS_INVALID_STR; 1355 } 1356 1357 if (status != LDNS_STATUS_OK) { 1358 if (gateway) 1359 LDNS_FREE(gateway); 1360 if (publickey) 1361 LDNS_FREE(publickey); 1362 LDNS_FREE(token); 1363 ldns_buffer_free(str_buf); 1364 return LDNS_STATUS_INVALID_STR; 1365 } 1366 1367 status = ldns_str2rdf_b64(&publickey_rdf, publickey); 1368 1369 if (status != LDNS_STATUS_OK) { 1370 if (gateway) 1371 LDNS_FREE(gateway); 1372 if (publickey) 1373 LDNS_FREE(publickey); 1374 LDNS_FREE(token); 1375 ldns_buffer_free(str_buf); 1376 if (gateway_rdf) ldns_rdf_free(gateway_rdf); 1377 return LDNS_STATUS_INVALID_STR; 1378 } 1379 1380 /* now copy all into one ipseckey rdf */ 1381 if (gateway_type) 1382 ipseckey_len = 3 + (int)ldns_rdf_size(gateway_rdf) + (int)ldns_rdf_size(publickey_rdf); 1383 else 1384 ipseckey_len = 3 + (int)ldns_rdf_size(publickey_rdf); 1385 1386 data = LDNS_XMALLOC(uint8_t, ipseckey_len); 1387 if(!data) { 1388 if (gateway) 1389 LDNS_FREE(gateway); 1390 if (publickey) 1391 LDNS_FREE(publickey); 1392 LDNS_FREE(token); 1393 ldns_buffer_free(str_buf); 1394 if (gateway_rdf) ldns_rdf_free(gateway_rdf); 1395 if (publickey_rdf) ldns_rdf_free(publickey_rdf); 1396 return LDNS_STATUS_MEM_ERR; 1397 } 1398 1399 data[0] = precedence; 1400 data[1] = gateway_type; 1401 data[2] = algorithm; 1402 1403 if (gateway_type) { 1404 memcpy(data + 3, 1405 ldns_rdf_data(gateway_rdf), ldns_rdf_size(gateway_rdf)); 1406 memcpy(data + 3 + ldns_rdf_size(gateway_rdf), 1407 ldns_rdf_data(publickey_rdf), ldns_rdf_size(publickey_rdf)); 1408 } else { 1409 memcpy(data + 3, 1410 ldns_rdf_data(publickey_rdf), ldns_rdf_size(publickey_rdf)); 1411 } 1412 1413 *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_IPSECKEY, (uint16_t) ipseckey_len, data); 1414 1415 if (gateway) 1416 LDNS_FREE(gateway); 1417 if (publickey) 1418 LDNS_FREE(publickey); 1419 LDNS_FREE(token); 1420 ldns_buffer_free(str_buf); 1421 ldns_rdf_deep_free(gateway_rdf); 1422 ldns_rdf_deep_free(publickey_rdf); 1423 LDNS_FREE(data); 1424 if(!*rd) return LDNS_STATUS_MEM_ERR; 1425 return LDNS_STATUS_OK; 1426 } 1427 1428 ldns_status 1429 ldns_str2rdf_ilnp64(ldns_rdf **rd, const char *str) 1430 { 1431 unsigned int a, b, c, d; 1432 uint16_t shorts[4]; 1433 int l; 1434 1435 if (sscanf(str, "%4x:%4x:%4x:%4x%n", &a, &b, &c, &d, &l) != 4 || 1436 l != (int)strlen(str) || /* more data to read */ 1437 strpbrk(str, "+-") /* signed hexes */ 1438 ) { 1439 return LDNS_STATUS_INVALID_ILNP64; 1440 } else { 1441 shorts[0] = htons(a); 1442 shorts[1] = htons(b); 1443 shorts[2] = htons(c); 1444 shorts[3] = htons(d); 1445 *rd = ldns_rdf_new_frm_data( 1446 LDNS_RDF_TYPE_ILNP64, 4 * sizeof(uint16_t), &shorts); 1447 } 1448 return *rd ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR; 1449 } 1450 1451 ldns_status 1452 ldns_str2rdf_eui48(ldns_rdf **rd, const char *str) 1453 { 1454 unsigned int a, b, c, d, e, f; 1455 uint8_t bytes[6]; 1456 int l; 1457 1458 if (sscanf(str, "%2x-%2x-%2x-%2x-%2x-%2x%n", 1459 &a, &b, &c, &d, &e, &f, &l) != 6 || 1460 l != (int)strlen(str)) { 1461 return LDNS_STATUS_INVALID_EUI48; 1462 } else { 1463 bytes[0] = a; 1464 bytes[1] = b; 1465 bytes[2] = c; 1466 bytes[3] = d; 1467 bytes[4] = e; 1468 bytes[5] = f; 1469 *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_EUI48, 6, &bytes); 1470 } 1471 return *rd ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR; 1472 } 1473 1474 ldns_status 1475 ldns_str2rdf_eui64(ldns_rdf **rd, const char *str) 1476 { 1477 unsigned int a, b, c, d, e, f, g, h; 1478 uint8_t bytes[8]; 1479 int l; 1480 1481 if (sscanf(str, "%2x-%2x-%2x-%2x-%2x-%2x-%2x-%2x%n", 1482 &a, &b, &c, &d, &e, &f, &g, &h, &l) != 8 || 1483 l != (int)strlen(str)) { 1484 return LDNS_STATUS_INVALID_EUI64; 1485 } else { 1486 bytes[0] = a; 1487 bytes[1] = b; 1488 bytes[2] = c; 1489 bytes[3] = d; 1490 bytes[4] = e; 1491 bytes[5] = f; 1492 bytes[6] = g; 1493 bytes[7] = h; 1494 *rd = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_EUI64, 8, &bytes); 1495 } 1496 return *rd ? LDNS_STATUS_OK : LDNS_STATUS_MEM_ERR; 1497 } 1498 1499 ldns_status 1500 ldns_str2rdf_tag(ldns_rdf **rd, const char *str) 1501 { 1502 uint8_t *data; 1503 const char* ptr; 1504 1505 if (strlen(str) > 255) { 1506 return LDNS_STATUS_INVALID_TAG; 1507 } 1508 for (ptr = str; *ptr; ptr++) { 1509 if (! isalnum((unsigned char)*ptr)) { 1510 return LDNS_STATUS_INVALID_TAG; 1511 } 1512 } 1513 data = LDNS_XMALLOC(uint8_t, strlen(str) + 1); 1514 if (!data) { 1515 return LDNS_STATUS_MEM_ERR; 1516 } 1517 data[0] = strlen(str); 1518 memcpy(data + 1, str, strlen(str)); 1519 1520 *rd = ldns_rdf_new(LDNS_RDF_TYPE_TAG, strlen(str) + 1, data); 1521 if (!*rd) { 1522 LDNS_FREE(data); 1523 return LDNS_STATUS_MEM_ERR; 1524 } 1525 return LDNS_STATUS_OK; 1526 } 1527 1528 ldns_status 1529 ldns_str2rdf_long_str(ldns_rdf **rd, const char *str) 1530 { 1531 uint8_t *data, *dp, ch = 0; 1532 size_t length; 1533 1534 /* Worst case space requirement. We'll realloc to actual size later. */ 1535 dp = data = LDNS_XMALLOC(uint8_t, strlen(str)); 1536 if (! data) { 1537 return LDNS_STATUS_MEM_ERR; 1538 } 1539 1540 /* Fill data with parsed bytes */ 1541 while (parse_char(&ch, &str)) { 1542 *dp++ = ch; 1543 if (dp - data > LDNS_MAX_RDFLEN) { 1544 LDNS_FREE(data); 1545 return LDNS_STATUS_INVALID_STR; 1546 } 1547 } 1548 if (! str) { 1549 LDNS_FREE(data); 1550 return LDNS_STATUS_SYNTAX_BAD_ESCAPE; 1551 } 1552 if (!(length = (size_t)(dp - data))) { 1553 /* An empty string is a data buffer of 0 bytes. The rdf for 1554 * this long string has to have length 0 and point to NULL. 1555 */ 1556 LDNS_FREE(data); 1557 data = NULL; 1558 } else { 1559 /* Lose the overmeasure */ 1560 data = LDNS_XREALLOC(dp = data, uint8_t, length); 1561 if (! data) { 1562 LDNS_FREE(dp); 1563 return LDNS_STATUS_MEM_ERR; 1564 } 1565 } 1566 /* Create rdf */ 1567 *rd = ldns_rdf_new(LDNS_RDF_TYPE_LONG_STR, length, data); 1568 if (! *rd) { 1569 LDNS_FREE(data); 1570 return LDNS_STATUS_MEM_ERR; 1571 } 1572 return LDNS_STATUS_OK; 1573 } 1574 1575 ldns_status 1576 ldns_str2rdf_hip(ldns_rdf **rd, const char *str) 1577 { 1578 const char *hit = str == NULL ? NULL : strchr(str, ' '); 1579 const char *pk = hit == NULL ? NULL : strchr(hit + 1, ' '); 1580 size_t hit_size = hit == NULL ? 0 1581 : pk == NULL ? strlen(hit + 1) : (size_t) (pk - hit) - 1; 1582 size_t pk_size = pk == NULL ? 0 : strlen(pk + 1); 1583 size_t hit_wire_size = (hit_size + 1) / 2; 1584 size_t pk_wire_size = ldns_b64_pton_calculate_size(pk_size); 1585 size_t rdf_size = 4 + hit_wire_size + pk_wire_size; 1586 1587 char *endptr; /* utility var for strtol usage */ 1588 int algorithm = str == NULL ? 0 : strtol(str, &endptr, 10); 1589 1590 uint8_t *data, *dp; 1591 int hi, lo, written; 1592 1593 if (hit_size == 0 || pk_size == 0 || (hit_size + 1) / 2 > 255 1594 || rdf_size > LDNS_MAX_RDFLEN 1595 || algorithm < 0 || algorithm > 255 1596 || (errno != 0 && algorithm == 0) /* out of range */ 1597 || endptr == str /* no digits */) { 1598 1599 return LDNS_STATUS_SYNTAX_ERR; 1600 } 1601 hit += 1; 1602 pk += 1; 1603 if ((data = LDNS_XMALLOC(uint8_t, rdf_size)) == NULL) { 1604 1605 return LDNS_STATUS_MEM_ERR; 1606 } 1607 /* From RFC 5205 section 5. HIP RR Storage Format: 1608 ************************************************* 1609 1610 0 1 2 3 1611 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 1612 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1613 | HIT length | PK algorithm | PK length | 1614 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1615 | | 1616 ~ HIT ~ 1617 | | 1618 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1619 | | | 1620 +-+-+-+-+-+-+-+-+-+-+-+ + 1621 | Public Key | 1622 ~ ~ 1623 | | 1624 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1625 | | | 1626 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + 1627 | | 1628 ~ Rendezvous Servers ~ 1629 | | 1630 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1631 | | 1632 +-+-+-+-+-+-+-+ */ 1633 1634 data[0] = (uint8_t) hit_wire_size; 1635 data[1] = (uint8_t) algorithm; 1636 1637 for (dp = data + 4; *hit && *hit != ' '; dp++) { 1638 1639 if ((hi = ldns_hexdigit_to_int(*hit++)) == -1 || 1640 (lo = ldns_hexdigit_to_int(*hit++)) == -1) { 1641 1642 LDNS_FREE(data); 1643 return LDNS_STATUS_INVALID_HEX; 1644 } 1645 *dp = (uint8_t) hi << 4 | lo; 1646 } 1647 if ((written = ldns_b64_pton(pk, dp, pk_wire_size)) <= 0) { 1648 1649 LDNS_FREE(data); 1650 return LDNS_STATUS_INVALID_B64; 1651 } 1652 1653 /* Because ldns_b64_pton_calculate_size isn't always correct: 1654 * (we have to fix it at some point) 1655 */ 1656 pk_wire_size = (uint16_t) written; 1657 ldns_write_uint16(data + 2, pk_wire_size); 1658 rdf_size = 4 + hit_wire_size + pk_wire_size; 1659 1660 /* Create rdf */ 1661 if (! (*rd = ldns_rdf_new(LDNS_RDF_TYPE_HIP, rdf_size, data))) { 1662 1663 LDNS_FREE(data); 1664 return LDNS_STATUS_MEM_ERR; 1665 } 1666 return LDNS_STATUS_OK; 1667 } 1668 1669 1670 /* Implementation mimics ldns_str2rdf_ipseckey */ 1671 ldns_status 1672 ldns_str2rdf_amtrelay(ldns_rdf **rd, const char *str) 1673 { 1674 /* From draft-ietf-mboned-driad-amt-discovery 1675 * Section 4.2. AMTRELAY RData Format 1676 ************************************************* 1677 1678 0 1 2 3 1679 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 1680 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 1681 | precedence |D| type | | 1682 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + 1683 ~ relay ~ 1684 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ 1685 1686 uint8_t precedence = 0; 1687 uint8_t relay_type = 0; 1688 uint8_t discovery_optional = 0; 1689 char* relay = NULL; 1690 uint8_t *data; 1691 ldns_buffer *str_buf; 1692 char *token; 1693 int token_count = 0; 1694 int amtrelay_len = 0; 1695 ldns_rdf* relay_rdf = NULL; 1696 ldns_status status = LDNS_STATUS_OK; 1697 1698 if(strlen(str) == 0) 1699 token = LDNS_XMALLOC(char, 256); 1700 else token = LDNS_XMALLOC(char, strlen(str)+2); 1701 if(!token) return LDNS_STATUS_MEM_ERR; 1702 1703 str_buf = LDNS_MALLOC(ldns_buffer); 1704 if(!str_buf) {LDNS_FREE(token); return LDNS_STATUS_MEM_ERR;} 1705 ldns_buffer_new_frm_data(str_buf, (char *)str, strlen(str)); 1706 if(ldns_buffer_status(str_buf) != LDNS_STATUS_OK) { 1707 LDNS_FREE(str_buf); 1708 LDNS_FREE(token); 1709 return LDNS_STATUS_MEM_ERR; 1710 } 1711 while(ldns_bget_token(str_buf, token, "\t\n ", strlen(str)) > 0) { 1712 switch (token_count) { 1713 case 0: 1714 precedence = (uint8_t)atoi(token); 1715 break; 1716 case 1: 1717 discovery_optional = (uint8_t)atoi(token); 1718 if (discovery_optional != 0 && 1719 discovery_optional != 1) { 1720 LDNS_FREE(relay); 1721 LDNS_FREE(token); 1722 ldns_buffer_free(str_buf); 1723 return LDNS_STATUS_INVALID_STR; 1724 } 1725 break; 1726 case 2: 1727 relay_type = (uint8_t)atoi(token); 1728 break; 1729 case 3: 1730 relay = strdup(token); 1731 if (!relay || (relay_type == 0 && 1732 (token[0] != '.' || token[1] != '\0'))) { 1733 LDNS_FREE(relay); 1734 LDNS_FREE(token); 1735 ldns_buffer_free(str_buf); 1736 return LDNS_STATUS_INVALID_STR; 1737 } 1738 break; 1739 default: 1740 LDNS_FREE(token); 1741 ldns_buffer_free(str_buf); 1742 return LDNS_STATUS_INVALID_STR; 1743 break; 1744 } 1745 token_count++; 1746 } 1747 if (!relay && relay_type > 0) { 1748 if (relay) 1749 LDNS_FREE(relay); 1750 LDNS_FREE(token); 1751 ldns_buffer_free(str_buf); 1752 return LDNS_STATUS_INVALID_STR; 1753 } 1754 1755 if (relay_type == 1) { 1756 status = ldns_str2rdf_a(&relay_rdf, relay); 1757 } else if (relay_type == 2) { 1758 status = ldns_str2rdf_aaaa(&relay_rdf, relay); 1759 } else if (relay_type == 3) { 1760 status = ldns_str2rdf_dname(&relay_rdf, relay); 1761 } else if (relay_type > 3) { 1762 status = LDNS_STATUS_INVALID_STR; 1763 } 1764 1765 if (status != LDNS_STATUS_OK) { 1766 if (relay) 1767 LDNS_FREE(relay); 1768 LDNS_FREE(token); 1769 ldns_buffer_free(str_buf); 1770 return LDNS_STATUS_INVALID_STR; 1771 } 1772 1773 /* now copy all into one amtrelay rdf */ 1774 if (relay_type) 1775 amtrelay_len = 2 + (int)ldns_rdf_size(relay_rdf); 1776 else 1777 amtrelay_len = 2; 1778 1779 data = LDNS_XMALLOC(uint8_t, amtrelay_len); 1780 if(!data) { 1781 if (relay) 1782 LDNS_FREE(relay); 1783 LDNS_FREE(token); 1784 ldns_buffer_free(str_buf); 1785 if (relay_rdf) ldns_rdf_free(relay_rdf); 1786 return LDNS_STATUS_MEM_ERR; 1787 } 1788 1789 data[0] = precedence; 1790 data[1] = relay_type; 1791 data[1] |= (discovery_optional << 7); 1792 1793 if (relay_type) { 1794 memcpy(data + 2, 1795 ldns_rdf_data(relay_rdf), ldns_rdf_size(relay_rdf)); 1796 } 1797 *rd = ldns_rdf_new_frm_data( LDNS_RDF_TYPE_AMTRELAY 1798 , (uint16_t) amtrelay_len, data); 1799 1800 if (relay) 1801 LDNS_FREE(relay); 1802 LDNS_FREE(token); 1803 ldns_buffer_free(str_buf); 1804 ldns_rdf_free(relay_rdf); 1805 LDNS_FREE(data); 1806 if(!*rd) return LDNS_STATUS_MEM_ERR; 1807 return LDNS_STATUS_OK; 1808 } 1809 1810 #ifdef RRTYPE_SVCB_HTTPS 1811 static int 1812 network_uint16_cmp(const void *a, const void *b) 1813 { 1814 return ((int)ldns_read_uint16(a)) - ((int)ldns_read_uint16(b)); 1815 } 1816 1817 static ldns_status parse_svcparam_key(const char **s, ldns_svcparam_key *key); 1818 static ldns_status 1819 parse_svcparam_mandatory(const char **s, uint8_t **dp, uint8_t *eod) 1820 { 1821 bool quoted = false; 1822 uint8_t *keys = *dp; 1823 int prev_key; 1824 1825 if (**s == '"') { 1826 *s += 1; 1827 quoted = true; 1828 } 1829 for (;;) { 1830 ldns_status st; 1831 ldns_svcparam_key key; 1832 1833 if ((st = parse_svcparam_key(s, &key))) 1834 return st; 1835 1836 if (*dp + 2 > eod) 1837 return LDNS_STATUS_RDATA_OVERFLOW; 1838 1839 ldns_write_uint16(*dp, key); 1840 *dp += 2; 1841 1842 if (**s == ',') 1843 *s += 1; 1844 else 1845 break; 1846 } 1847 if (quoted) { 1848 if (**s != '"') 1849 return LDNS_STATUS_INVALID_STR; 1850 *s += 1; 1851 } 1852 if (*dp - keys == 0) 1853 return LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR; 1854 1855 if (**s && !isspace((unsigned char)**s)) 1856 return LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR; 1857 1858 /* In draft-ietf-dnsop-svcb-https-02 Section 7: 1859 * 1860 * In wire format, the keys are represented by their numeric 1861 * values in network byte order, concatenated in ascending order. 1862 */ 1863 qsort(keys, (*dp - keys) / 2, 2, network_uint16_cmp); 1864 1865 /* In draft-ietf-dnsop-svcb-https-02 Section 7: 1866 * 1867 * Keys ...<snip>... MUST NOT appear more than once. 1868 */ 1869 prev_key = -1; 1870 while (keys < *dp) { 1871 uint16_t key = ldns_read_uint16(keys); 1872 1873 if (key == prev_key) { 1874 /* "Be conservative in what you send, 1875 * be liberal in what you accept" 1876 * 1877 * Instead of 1878 * `return LDNS_STATUS_SVCPARAM_KEY_MORE_THAN_ONCE;`, 1879 * 1880 * we eliminate the double occurrence. 1881 */ 1882 memmove(keys - 2, keys, *dp - keys); 1883 *dp -= 2; 1884 } else { 1885 prev_key = key; 1886 keys += 2; 1887 } 1888 } 1889 return LDNS_STATUS_OK; 1890 } 1891 1892 INLINE bool parse_escape2(uint8_t *ch_p, const char** str_p) 1893 { *str_p += 1; return parse_escape(ch_p, str_p); } 1894 1895 static ldns_status 1896 parse_svcparam_alpn(const char **s, uint8_t **dp, uint8_t *eod) 1897 { 1898 uint8_t *val; 1899 size_t len; 1900 1901 if (*dp + 1 > eod) 1902 return LDNS_STATUS_RDATA_OVERFLOW; 1903 *dp += 1; 1904 val = *dp; 1905 if (**s == '"') { 1906 *s += 1; 1907 while (**s != '"') { 1908 if (**s == 0) 1909 return LDNS_STATUS_INVALID_STR; 1910 1911 else if (**s == ',') { 1912 len = *dp - val; 1913 if (len == 0 || len > 255) 1914 return LDNS_STATUS_INVALID_STR; 1915 val[-1] = len; 1916 if (*dp + 1 > eod) 1917 return LDNS_STATUS_RDATA_OVERFLOW; 1918 *dp += 1; 1919 val = *dp; 1920 *s += 1; 1921 1922 } else if (*dp + 1 > eod) 1923 return LDNS_STATUS_RDATA_OVERFLOW; 1924 1925 else if (**s != '\\') 1926 *(*dp)++ = (uint8_t)*(*s)++; 1927 1928 else if (!parse_escape2(*dp, s)) 1929 return LDNS_STATUS_SYNTAX_BAD_ESCAPE; 1930 else 1931 *dp += 1; 1932 } 1933 *s += 1; 1934 1935 } else while (**s && !isspace((unsigned char)**s)) { 1936 if (**s == ',') { 1937 len = *dp - val; 1938 if (len == 0 || len > 255) 1939 return LDNS_STATUS_INVALID_STR; 1940 val[-1] = len; 1941 if (*dp + 1 > eod) 1942 return LDNS_STATUS_RDATA_OVERFLOW; 1943 *dp += 1; 1944 val = *dp; 1945 *s += 1; 1946 1947 } else if (*dp + 1 > eod) 1948 return LDNS_STATUS_RDATA_OVERFLOW; 1949 1950 else if (**s != '\\') 1951 *(*dp)++ = (uint8_t)*(*s)++; 1952 1953 else if (!parse_escape2(*dp, s)) 1954 return LDNS_STATUS_SYNTAX_BAD_ESCAPE; 1955 else 1956 *dp += 1; 1957 } 1958 len = *dp - val; 1959 if (len == 0 || len > 255) 1960 return LDNS_STATUS_INVALID_STR; 1961 val[-1] = len; 1962 return **s && !isspace((unsigned char)**s) 1963 ? LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR 1964 : LDNS_STATUS_OK; 1965 } 1966 1967 static ldns_status 1968 parse_svcparam_value(const char **s, uint8_t **dp, uint8_t *eod) 1969 { 1970 if (**s == '"') { 1971 *s += 1; 1972 while (**s != '"') { 1973 if (**s == 0) 1974 return LDNS_STATUS_INVALID_STR; 1975 1976 else if (*dp + 1 > eod) 1977 return LDNS_STATUS_RDATA_OVERFLOW; 1978 1979 else if (**s != '\\') 1980 *(*dp)++ = (uint8_t)*(*s)++; 1981 1982 else if (!parse_escape2(*dp, s)) 1983 return LDNS_STATUS_SYNTAX_BAD_ESCAPE; 1984 else 1985 *dp += 1; 1986 } 1987 *s += 1; 1988 1989 } else while (**s && !isspace((unsigned char)**s)) { 1990 if (*dp + 1 > eod) 1991 return LDNS_STATUS_RDATA_OVERFLOW; 1992 1993 else if (**s != '\\') 1994 *(*dp)++ = (uint8_t)*(*s)++; 1995 1996 else if (!parse_escape2(*dp, s)) 1997 return LDNS_STATUS_SYNTAX_BAD_ESCAPE; 1998 else 1999 *dp += 1; 2000 } 2001 return **s && !isspace((unsigned char)**s) 2002 ? LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR 2003 : LDNS_STATUS_OK; 2004 } 2005 2006 static ldns_status 2007 parse_svcparam_port(const char **s, uint8_t **dp, uint8_t *eod) 2008 { 2009 uint8_t *val = *dp; 2010 ldns_status st; 2011 size_t len; 2012 char num_str[6]; 2013 char *endptr; 2014 unsigned long int num; 2015 2016 if ((st = parse_svcparam_value(s, dp, eod))) 2017 return st; 2018 len = *dp - val; 2019 if (len == 0 || len > 5) 2020 return LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR; 2021 2022 memcpy(num_str, val, len); 2023 num_str[len] = 0; 2024 num = strtoul(num_str, &endptr, 10); 2025 if (*endptr) 2026 return LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR; 2027 2028 ldns_write_uint16(val, num); 2029 *dp = val + 2; 2030 return LDNS_STATUS_OK; 2031 } 2032 2033 static ldns_status 2034 parse_svcparam_ipv4hint(const char **s, uint8_t **dp, uint8_t *eod) 2035 { 2036 bool quoted = false; 2037 2038 if (**s == '"') { 2039 *s += 1; 2040 quoted = true; 2041 } 2042 for (;;) { 2043 const char *ipv4_start = *s; 2044 char ipv4_str[16]; 2045 size_t len; 2046 2047 while (isdigit((unsigned char)**s) || **s == '.') 2048 *s += 1; 2049 2050 len = *s - ipv4_start; 2051 if (len == 0 || len > 15) 2052 return LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR; 2053 2054 if (*dp + 4 > eod) 2055 return LDNS_STATUS_RDATA_OVERFLOW; 2056 2057 memcpy(ipv4_str, ipv4_start, len); 2058 ipv4_str[len] = 0; 2059 if (inet_pton(AF_INET, ipv4_str, *dp) != 1) 2060 return LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR; 2061 2062 *dp += 4; 2063 if (**s == ',') 2064 *s += 1; 2065 else 2066 break; 2067 } 2068 if (quoted) { 2069 if (**s != '"') 2070 return LDNS_STATUS_INVALID_STR; 2071 *s += 1; 2072 } 2073 return **s && !isspace((unsigned char)**s) 2074 ? LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR 2075 : LDNS_STATUS_OK; 2076 } 2077 2078 static ldns_status 2079 parse_svcparam_ech(const char **s, uint8_t **dp, uint8_t *eod) 2080 { 2081 bool quoted = false; 2082 const char *b64_str; 2083 size_t len, pad, out_len; 2084 char in_buf[4096]; 2085 char *in = in_buf; 2086 int out; 2087 2088 if (**s == '"') { 2089 *s += 1; 2090 quoted = true; 2091 } 2092 b64_str = *s; 2093 while (isalnum((unsigned char)**s) || **s == '+' 2094 || **s == '/' 2095 || **s == '=') 2096 *s += 1; 2097 2098 len = *s - b64_str; 2099 pad = len % 4; 2100 pad = pad ? 4 - pad : 0; 2101 if (len == 0 || pad == 3) 2102 return LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR; 2103 2104 if (quoted) { 2105 if (**s != '"') 2106 return LDNS_STATUS_INVALID_STR; 2107 *s += 1; 2108 } 2109 if (**s && !isspace((unsigned char)**s)) 2110 return LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR; 2111 2112 out_len = ldns_b64_pton_calculate_size(len); 2113 if (*dp + out_len > eod) 2114 return LDNS_STATUS_RDATA_OVERFLOW; 2115 2116 if (len + pad > sizeof(in_buf) - 1 2117 && !(in = LDNS_XMALLOC(char, len + pad + 1))) 2118 return LDNS_STATUS_MEM_ERR; 2119 2120 memcpy(in, b64_str, len); 2121 while (pad--) 2122 in[len++] = '='; 2123 in[len] = 0; 2124 out = ldns_b64_pton(in, *dp, out_len); 2125 if (in != in_buf) 2126 LDNS_FREE(in); 2127 2128 if (out <= 0) 2129 return LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR; 2130 2131 *dp += out; 2132 return LDNS_STATUS_OK; 2133 } 2134 2135 static ldns_status 2136 parse_svcparam_ipv6hint(const char **s, uint8_t **dp, uint8_t *eod) 2137 { 2138 bool quoted = false; 2139 2140 if (**s == '"') { 2141 *s += 1; 2142 quoted = true; 2143 } 2144 for (;;) { 2145 const char *ipv6_start = *s; 2146 char ipv6_str[INET6_ADDRSTRLEN]; 2147 size_t len; 2148 2149 while (isxdigit((unsigned char)**s) || **s == ':' || **s == '.') 2150 *s += 1; 2151 2152 len = *s - ipv6_start; 2153 if (len == 0 || len > INET6_ADDRSTRLEN) 2154 return LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR; 2155 2156 if (*dp + 16 > eod) 2157 return LDNS_STATUS_RDATA_OVERFLOW; 2158 2159 memcpy(ipv6_str, ipv6_start, len); 2160 ipv6_str[len] = 0; 2161 if (inet_pton(AF_INET6, ipv6_str, *dp) != 1) 2162 return LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR; 2163 2164 *dp += 16; 2165 if (**s == ',') 2166 *s += 1; 2167 else 2168 break; 2169 } 2170 if (quoted) { 2171 if (**s != '"') 2172 return LDNS_STATUS_INVALID_STR; 2173 *s += 1; 2174 } 2175 return **s && !isspace((unsigned char)**s) 2176 ? LDNS_STATUS_SYNTAX_SVCPARAM_VALUE_ERR 2177 : LDNS_STATUS_OK; 2178 } 2179 2180 struct struct_svcparam_key_def { 2181 const char *str; 2182 size_t len; 2183 }; 2184 typedef struct struct_svcparam_key_def svcparam_key_def; 2185 2186 static svcparam_key_def svcparam_key_defs[] = { { "mandatory" , 9 } 2187 , { "alpn" , 4 } 2188 , { "no-default-alpn", 15 } 2189 , { "port" , 4 } 2190 , { "ipv4hint" , 8 } 2191 , { "ech" , 3 } 2192 , { "ipv6hint" , 8 } 2193 , { "dohpath" , 7 } }; 2194 2195 static const size_t svcparam_key_defs_len = sizeof(svcparam_key_defs) 2196 / sizeof(svcparam_key_def); 2197 2198 /* svcparam_key2buffer_str() should actually be in host2str.c, but we need the 2199 * svcparam_key_defs for it and it is not an exposed symbol anyway. 2200 */ 2201 ldns_status svcparam_key2buffer_str(ldns_buffer *output, uint16_t key) 2202 { 2203 if (key <= LDNS_SVCPARAM_KEY_LAST_KEY) 2204 ldns_buffer_write_string(output, svcparam_key_defs[key].str); 2205 else 2206 ldns_buffer_printf(output, "key%d", (int)key); 2207 return ldns_buffer_status(output); 2208 } 2209 2210 static ldns_status 2211 parse_svcparam_key(const char **s, ldns_svcparam_key *key) 2212 { 2213 size_t i, len; 2214 const char *key_str = *s; 2215 char num_str[6]; 2216 char *endptr; 2217 unsigned long int num; 2218 2219 /* parse key */ 2220 while (islower((unsigned char)**s) || isdigit((unsigned char)**s) 2221 || **s == '-') 2222 *s += 1; 2223 2224 len = *s - key_str; 2225 for (i = 0; i < svcparam_key_defs_len; i++) { 2226 if (len == svcparam_key_defs[i].len 2227 && !strncmp(key_str, svcparam_key_defs[i].str, len)) { 2228 *key = i; 2229 return LDNS_STATUS_OK; 2230 } 2231 } 2232 /* Also allow "echconfig" from earlier draft versions. */ 2233 if (len == 9 && !strncmp(key_str, "echconfig", 9)) { 2234 *key = LDNS_SVCPARAM_KEY_ECH; 2235 return LDNS_STATUS_OK; 2236 } 2237 if (len < 4 || len > 8 || strncmp(key_str, "key", 3)) 2238 return LDNS_STATUS_SYNTAX_SVCPARAM_KEY_ERR; 2239 2240 memcpy(num_str, key_str + 3, len - 3); 2241 num_str[len - 3] = 0; 2242 num = strtoul(num_str, &endptr, 10); 2243 if (*endptr || num > 65535) 2244 return LDNS_STATUS_SYNTAX_SVCPARAM_KEY_ERR; 2245 2246 /* key65535 is Reserved to be an ("Invalid key"), though there is no 2247 * physiological reason to deny usage. We restrict ourselves to the 2248 * anatomical limitations only to maximize serviceability. 2249 * ``` 2250 * if (num == 65535) 2251 * return LDNS_STATUS_RESERVED_SVCPARAM_KEY; 2252 * ``` 2253 */ 2254 *key = num; 2255 return LDNS_STATUS_OK; 2256 } 2257 2258 static ldns_status 2259 parse_svcparam(const char **s, uint8_t **dp, uint8_t *eod) 2260 { 2261 ldns_svcparam_key key; 2262 ldns_status st; 2263 uint8_t *val; 2264 2265 if (*dp + 4 > eod) 2266 return LDNS_STATUS_RDATA_OVERFLOW; 2267 2268 if ((st = parse_svcparam_key(s, &key))) 2269 return st; 2270 2271 ldns_write_uint16(*dp, key); 2272 ldns_write_uint16(*dp + 2, 0); 2273 *dp += 4; 2274 if (isspace((unsigned char)**s) || !**s) 2275 return LDNS_STATUS_OK; 2276 2277 else if (**s != '=') 2278 return LDNS_STATUS_SYNTAX_ERR; 2279 *s += 1; 2280 val = *dp; 2281 switch(key) { 2282 case LDNS_SVCPARAM_KEY_MANDATORY: 2283 st = parse_svcparam_mandatory(s, dp, eod); 2284 break; 2285 case LDNS_SVCPARAM_KEY_ALPN: 2286 st = parse_svcparam_alpn(s, dp, eod); 2287 break; 2288 case LDNS_SVCPARAM_KEY_NO_DEFAULT_ALPN: 2289 return LDNS_STATUS_NO_SVCPARAM_VALUE_EXPECTED; 2290 case LDNS_SVCPARAM_KEY_PORT: 2291 st = parse_svcparam_port(s, dp, eod); 2292 break; 2293 case LDNS_SVCPARAM_KEY_IPV4HINT: 2294 st = parse_svcparam_ipv4hint(s, dp, eod); 2295 break; 2296 case LDNS_SVCPARAM_KEY_ECH: 2297 st = parse_svcparam_ech(s, dp, eod); 2298 break; 2299 case LDNS_SVCPARAM_KEY_IPV6HINT: 2300 st = parse_svcparam_ipv6hint(s, dp, eod); 2301 break; 2302 default: 2303 st = parse_svcparam_value(s, dp, eod); 2304 break; 2305 } 2306 if (st) 2307 return st; 2308 ldns_write_uint16(val - 2, *dp - val); 2309 return LDNS_STATUS_OK; 2310 } 2311 2312 static int 2313 svcparam_ptr_cmp(const void *a, const void *b) 2314 { 2315 uint8_t *x = *(uint8_t **)a , *y = *(uint8_t **)b; 2316 uint16_t x_type = ldns_read_uint16(x), y_type = ldns_read_uint16(y); 2317 uint16_t x_len , y_len; 2318 2319 if (x_type != y_type) 2320 return x_type > y_type ? 1 : -1; 2321 2322 x_len = ldns_read_uint16(x + 2); 2323 y_len = ldns_read_uint16(y + 2); 2324 2325 return x_len != y_len 2326 ? (x_len > y_len ? 1 : -1) 2327 : (x_len == 0 ? 0 : memcmp(x + 4, y + 4, x_len)); 2328 } 2329 2330 ldns_status 2331 ldns_str2rdf_svcparams(ldns_rdf **rd, const char *str) 2332 { 2333 uint8_t *data, *dp, *eod, *p, *new_data; 2334 ldns_status st = LDNS_STATUS_OK; 2335 size_t length, i; 2336 size_t nparams = 0; 2337 uint8_t **svcparams; 2338 int prev_key; 2339 2340 if (!rd || !str) 2341 return LDNS_STATUS_NULL; 2342 2343 length = strlen(str); 2344 /* Worst case space requirement. We'll realloc to actual size later. */ 2345 if (!(dp = data = LDNS_XMALLOC(uint8_t, length * 4))) 2346 return LDNS_STATUS_MEM_ERR; 2347 eod = data + length * 4; 2348 2349 /* Fill data with parsed bytes */ 2350 for (;;) { 2351 while (isspace((unsigned char)*str)) 2352 str += 1; 2353 if(!*str) 2354 break; 2355 if ((st = parse_svcparam(&str, &dp, eod))) { 2356 LDNS_FREE(data); 2357 return st; 2358 } 2359 nparams += 1; 2360 } 2361 2362 /* draft-ietf-dnsop-svcb-https-02 in Section 2.2: 2363 * 2364 * SvcParamKeys SHALL appear in increasing numeric order 2365 * 2366 * A svcparams array (with pointers to the individual key, value pairs) 2367 * is created to qsort the pairs in increasing numeric order. 2368 */ 2369 if (!(svcparams = LDNS_XMALLOC(uint8_t *, nparams))) { 2370 LDNS_FREE(data); 2371 return LDNS_STATUS_MEM_ERR; 2372 } 2373 for ( p = data, i = 0 2374 ; p < dp && i < nparams 2375 ; p += 4 + ldns_read_uint16(p + 2)) 2376 svcparams[i++] = p; 2377 2378 qsort(svcparams, i, sizeof(uint8_t *), svcparam_ptr_cmp); 2379 2380 /* Write out the (key, value) pairs to a newly allocated data in 2381 * sorted order. 2382 */ 2383 length = dp - data; 2384 if (!(new_data = LDNS_XMALLOC(uint8_t, length))) { 2385 LDNS_FREE(data); 2386 LDNS_FREE(svcparams); 2387 return LDNS_STATUS_MEM_ERR; 2388 } 2389 prev_key = -1; 2390 for ( p = new_data, i = 0 2391 ; p < new_data + length && i < nparams 2392 ; p += 4 + ldns_read_uint16(p + 2), i += 1) { 2393 uint16_t key = ldns_read_uint16(svcparams[i]); 2394 2395 /* In draft-ietf-dnsop-svcb-https-02 Section 2.1: 2396 * 2397 * SvcParams ...<snip>... keys MUST NOT be repeated. 2398 * 2399 * ldns will not impose this limitation on the library user, 2400 * but we can merge completely equal repetitions into one. 2401 * So, not doing 2402 * ``` 2403 * if (key == prev_key) 2404 * return LDNS_STATUS_SVCPARAM_KEY_MORE_THAN_ONCE; 2405 * ``` 2406 * but instead: 2407 */ 2408 if (key == prev_key && ldns_read_uint16(svcparams[i] + 2) 2409 == ldns_read_uint16(svcparams[i - 1] + 2) 2410 && 0 == memcmp( svcparams[i ] + 4 2411 , svcparams[i - 1] + 4 2412 , ldns_read_uint16(svcparams[i] + 2))) { 2413 p -= 4 + ldns_read_uint16(svcparams[i] + 2); 2414 continue; 2415 } 2416 memcpy(p, svcparams[i], 4 + ldns_read_uint16(svcparams[i] + 2)); 2417 prev_key = key; 2418 } 2419 LDNS_FREE(data); 2420 LDNS_FREE(svcparams); 2421 2422 /* Create rdf */ 2423 *rd = ldns_rdf_new(LDNS_RDF_TYPE_SVCPARAMS, p - new_data, new_data); 2424 if (! *rd) { 2425 LDNS_FREE(new_data); 2426 return LDNS_STATUS_MEM_ERR; 2427 } 2428 return LDNS_STATUS_OK; 2429 } 2430 #else /* #ifdef RRTYPE_SVCB_HTTPS */ 2431 ldns_status 2432 ldns_str2rdf_svcparams(ldns_rdf **rd, const char *str) 2433 { 2434 (void)rd; (void)str; 2435 return LDNS_STATUS_NOT_IMPL; 2436 } 2437 #endif /* #ifdef RRTYPE_SVCB_HTTPS */ 2438