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