1 /* 2 * dname.c -- Domain name handling. 3 * 4 * Copyright (c) 2001-2006, NLnet Labs. All rights reserved. 5 * 6 * See LICENSE for the license. 7 * 8 */ 9 10 11 #include "config.h" 12 13 #include <sys/types.h> 14 15 #include <assert.h> 16 #include <ctype.h> 17 #include <limits.h> 18 #include <stdio.h> 19 #include <string.h> 20 21 #include "dns.h" 22 #include "dname.h" 23 #include "query.h" 24 25 const dname_type * 26 dname_make(region_type *region, const uint8_t *name, int normalize) 27 { 28 size_t name_size = 0; 29 uint8_t label_offsets[MAXDOMAINLEN/2+1]; 30 uint8_t label_count = 0; 31 const uint8_t *label = name; 32 dname_type *result; 33 ssize_t i; 34 35 assert(name); 36 37 while (1) { 38 if (!label_is_normal(label)) 39 return NULL; 40 41 label_offsets[label_count] = (uint8_t) (label - name); 42 ++label_count; 43 name_size += label_length(label) + 1; 44 45 if (name_size > MAXDOMAINLEN) 46 return NULL; 47 if (label_is_root(label)) 48 break; 49 50 label = label_next(label); 51 } 52 53 assert(label_count <= MAXDOMAINLEN / 2 + 1); 54 55 /* Reverse label offsets. */ 56 for (i = 0; i < label_count / 2; ++i) { 57 uint8_t tmp = label_offsets[i]; 58 label_offsets[i] = label_offsets[label_count - i - 1]; 59 label_offsets[label_count - i - 1] = tmp; 60 } 61 62 result = (dname_type *) region_alloc( 63 region, 64 (sizeof(dname_type) 65 + (((size_t)label_count) + ((size_t)name_size)) * sizeof(uint8_t))); 66 result->name_size = name_size; 67 result->label_count = label_count; 68 memcpy((uint8_t *) dname_label_offsets(result), 69 label_offsets, 70 label_count * sizeof(uint8_t)); 71 if (normalize) { 72 uint8_t *dst = (uint8_t *) dname_name(result); 73 const uint8_t *src = name; 74 while (!label_is_root(src)) { 75 ssize_t len = label_length(src); 76 *dst++ = *src++; 77 for (i = 0; i < len; ++i) { 78 *dst++ = DNAME_NORMALIZE((unsigned char)*src++); 79 } 80 } 81 *dst = *src; 82 } else { 83 memcpy((uint8_t *) dname_name(result), 84 name, 85 name_size * sizeof(uint8_t)); 86 } 87 return result; 88 } 89 90 91 const dname_type * 92 dname_make_from_packet(region_type *region, buffer_type *packet, 93 int allow_pointers, int normalize) 94 { 95 uint8_t buf[MAXDOMAINLEN + 1]; 96 if(!dname_make_wire_from_packet(buf, packet, allow_pointers)) 97 return 0; 98 return dname_make(region, buf, normalize); 99 } 100 101 int 102 dname_make_wire_from_packet(uint8_t *buf, buffer_type *packet, 103 int allow_pointers) 104 { 105 int done = 0; 106 uint8_t visited[(MAX_PACKET_SIZE+7)/8]; 107 size_t dname_length = 0; 108 const uint8_t *label; 109 ssize_t mark = -1; 110 111 if(sizeof(visited)<(buffer_limit(packet)+7)/8) 112 memset(visited, 0, sizeof(visited)); 113 else memset(visited, 0, (buffer_limit(packet)+7)/8); 114 115 while (!done) { 116 if (!buffer_available(packet, 1)) { 117 /* error("dname out of bounds"); */ 118 return 0; 119 } 120 121 if (get_bit(visited, buffer_position(packet))) { 122 /* error("dname loops"); */ 123 return 0; 124 } 125 set_bit(visited, buffer_position(packet)); 126 127 label = buffer_current(packet); 128 if (label_is_pointer(label)) { 129 size_t pointer; 130 if (!allow_pointers) { 131 return 0; 132 } 133 if (!buffer_available(packet, 2)) { 134 /* error("dname pointer out of bounds"); */ 135 return 0; 136 } 137 pointer = label_pointer_location(label); 138 if (pointer >= buffer_limit(packet)) { 139 /* error("dname pointer points outside packet"); */ 140 return 0; 141 } 142 buffer_skip(packet, 2); 143 if (mark == -1) { 144 mark = buffer_position(packet); 145 } 146 buffer_set_position(packet, pointer); 147 } else if (label_is_normal(label)) { 148 size_t length = label_length(label) + 1; 149 done = label_is_root(label); 150 if (!buffer_available(packet, length)) { 151 /* error("dname label out of bounds"); */ 152 return 0; 153 } 154 if (dname_length + length >= MAXDOMAINLEN+1) { 155 /* error("dname too large"); */ 156 return 0; 157 } 158 buffer_read(packet, buf + dname_length, length); 159 dname_length += length; 160 } else { 161 /* error("bad label type"); */ 162 return 0; 163 } 164 } 165 166 if (mark != -1) { 167 buffer_set_position(packet, mark); 168 } 169 170 return dname_length; 171 } 172 173 const dname_type * 174 dname_parse(region_type *region, const char *name) 175 { 176 uint8_t dname[MAXDOMAINLEN]; 177 if(!dname_parse_wire(dname, name)) 178 return 0; 179 return dname_make(region, dname, 1); 180 } 181 182 int dname_parse_wire(uint8_t* dname, const char* name) 183 { 184 const uint8_t *s = (const uint8_t *) name; 185 uint8_t *h; 186 uint8_t *p; 187 uint8_t *d = dname; 188 size_t label_length; 189 190 if (strcmp(name, ".") == 0) { 191 /* Root domain. */ 192 dname[0] = 0; 193 return 1; 194 } 195 196 for (h = d, p = h + 1; *s; ++s, ++p) { 197 if (p - dname >= MAXDOMAINLEN) { 198 return 0; 199 } 200 201 switch (*s) { 202 case '.': 203 if (p == h + 1) { 204 /* Empty label. */ 205 return 0; 206 } else { 207 label_length = p - h - 1; 208 if (label_length > MAXLABELLEN) { 209 return 0; 210 } 211 *h = label_length; 212 h = p; 213 } 214 break; 215 case '\\': 216 /* Handle escaped characters (RFC1035 5.1) */ 217 if (isdigit((unsigned char)s[1]) && isdigit((unsigned char)s[2]) && isdigit((unsigned char)s[3])) { 218 int val = (hexdigit_to_int(s[1]) * 100 + 219 hexdigit_to_int(s[2]) * 10 + 220 hexdigit_to_int(s[3])); 221 if (0 <= val && val <= 255) { 222 s += 3; 223 *p = val; 224 } else { 225 *p = *++s; 226 } 227 } else if (s[1] != '\0') { 228 *p = *++s; 229 } 230 break; 231 default: 232 *p = *s; 233 break; 234 } 235 } 236 237 if (p != h + 1) { 238 /* Terminate last label. */ 239 label_length = p - h - 1; 240 if (label_length > MAXLABELLEN) { 241 return 0; 242 } 243 *h = label_length; 244 h = p; 245 p++; 246 } 247 248 /* Add root label. */ 249 if (h - dname >= MAXDOMAINLEN) { 250 return 0; 251 } 252 *h = 0; 253 254 return p-dname; 255 } 256 257 258 const dname_type * 259 dname_copy(region_type *region, const dname_type *dname) 260 { 261 return (dname_type *) region_alloc_init( 262 region, dname, dname_total_size(dname)); 263 } 264 265 266 const dname_type * 267 dname_partial_copy(region_type *region, const dname_type *dname, uint8_t label_count) 268 { 269 if (!dname) 270 return NULL; 271 272 if (label_count == 0) { 273 /* Always copy the root label. */ 274 label_count = 1; 275 } 276 277 assert(label_count <= dname->label_count); 278 279 return dname_make(region, dname_label(dname, label_count - 1), 0); 280 } 281 282 283 const dname_type * 284 dname_origin(region_type *region, const dname_type *dname) 285 { 286 return dname_partial_copy(region, dname, dname->label_count - 1); 287 } 288 289 290 int 291 dname_is_subdomain(const dname_type *left, const dname_type *right) 292 { 293 uint8_t i; 294 295 if (left->label_count < right->label_count) 296 return 0; 297 298 for (i = 1; i < right->label_count; ++i) { 299 if (label_compare(dname_label(left, i), 300 dname_label(right, i)) != 0) 301 return 0; 302 } 303 304 return 1; 305 } 306 307 308 int 309 dname_compare(const void *a, const void *b) 310 { 311 int result; 312 uint8_t label_count; 313 uint8_t i; 314 const dname_type *left, *right; 315 316 left = a; 317 right = b; 318 319 assert(left); 320 assert(right); 321 322 if (left == right) { 323 return 0; 324 } 325 326 label_count = (left->label_count <= right->label_count 327 ? left->label_count 328 : right->label_count); 329 330 /* Skip the root label by starting at label 1. */ 331 for (i = 1; i < label_count; ++i) { 332 result = label_compare(dname_label(left, i), 333 dname_label(right, i)); 334 if (result) { 335 return result; 336 } 337 } 338 339 /* Dname with the fewest labels is "first". */ 340 /* the subtraction works because the size of int is much larger than 341 * the label count and the values won't wrap around */ 342 return (int) left->label_count - (int) right->label_count; 343 } 344 345 346 int 347 label_compare(const uint8_t *left, const uint8_t *right) 348 { 349 int left_length; 350 int right_length; 351 size_t size; 352 int result; 353 354 assert(left); 355 assert(right); 356 357 assert(label_is_normal(left)); 358 assert(label_is_normal(right)); 359 360 left_length = label_length(left); 361 right_length = label_length(right); 362 size = left_length < right_length ? left_length : right_length; 363 364 result = memcmp(label_data(left), label_data(right), size); 365 if (result) { 366 return result; 367 } else { 368 /* the subtraction works because the size of int is much 369 * larger than the lengths and the values won't wrap around */ 370 return (int) left_length - (int) right_length; 371 } 372 } 373 374 375 uint8_t 376 dname_label_match_count(const dname_type *left, const dname_type *right) 377 { 378 uint8_t i; 379 380 assert(left); 381 assert(right); 382 383 for (i = 1; i < left->label_count && i < right->label_count; ++i) { 384 if (label_compare(dname_label(left, i), 385 dname_label(right, i)) != 0) 386 { 387 return i; 388 } 389 } 390 391 return i; 392 } 393 394 const char * 395 dname_to_string(const dname_type *dname, const dname_type *origin) 396 { 397 static char buf[MAXDOMAINLEN * 5]; 398 return dname_to_string_buf(dname, origin, buf); 399 } 400 401 const char * 402 dname_to_string_buf(const dname_type *dname, const dname_type *origin, char buf[MAXDOMAINLEN * 5]) 403 { 404 size_t i; 405 size_t labels_to_convert = dname->label_count - 1; 406 int absolute = 1; 407 char *dst; 408 const uint8_t *src; 409 410 if (dname->label_count == 1) { 411 strlcpy(buf, ".", MAXDOMAINLEN * 5); 412 return buf; 413 } 414 415 if (origin && dname_is_subdomain(dname, origin)) { 416 int common_labels = dname_label_match_count(dname, origin); 417 labels_to_convert = dname->label_count - common_labels; 418 absolute = 0; 419 } 420 421 dst = buf; 422 src = dname_name(dname); 423 for (i = 0; i < labels_to_convert; ++i) { 424 size_t len = label_length(src); 425 size_t j; 426 ++src; 427 for (j = 0; j < len; ++j) { 428 uint8_t ch = *src++; 429 if (isalnum((unsigned char)ch) || ch == '-' || ch == '_' || ch == '*') { 430 *dst++ = ch; 431 } else if (ch == '.' || ch == '\\') { 432 *dst++ = '\\'; 433 *dst++ = ch; 434 } else { 435 snprintf(dst, 5, "\\%03u", (unsigned int)ch); 436 dst += 4; 437 } 438 } 439 *dst++ = '.'; 440 } 441 if (absolute) { 442 *dst = '\0'; 443 } else { 444 *--dst = '\0'; 445 } 446 return buf; 447 } 448 449 450 const dname_type * 451 dname_make_from_label(region_type *region, 452 const uint8_t *label, const size_t length) 453 { 454 uint8_t temp[MAXLABELLEN + 2]; 455 456 assert(length > 0 && length <= MAXLABELLEN); 457 458 temp[0] = length; 459 memcpy(temp + 1, label, length * sizeof(uint8_t)); 460 temp[length + 1] = '\000'; 461 462 return dname_make(region, temp, 1); 463 } 464 465 466 const dname_type * 467 dname_concatenate(region_type *region, 468 const dname_type *left, 469 const dname_type *right) 470 { 471 uint8_t temp[MAXDOMAINLEN]; 472 473 assert(left->name_size + right->name_size - 1 <= MAXDOMAINLEN); 474 475 memcpy(temp, dname_name(left), left->name_size - 1); 476 memcpy(temp + left->name_size - 1, dname_name(right), right->name_size); 477 478 return dname_make(region, temp, 0); 479 } 480 481 482 const dname_type * 483 dname_replace(region_type* region, 484 const dname_type* name, 485 const dname_type* src, 486 const dname_type* dest) 487 { 488 /* nomenclature: name is said to be <x>.<src>. x can be null. */ 489 dname_type* res; 490 int x_labels = name->label_count - src->label_count; 491 int x_len = name->name_size - src->name_size; 492 int i; 493 assert(dname_is_subdomain(name, src)); 494 495 /* check if final size is acceptable */ 496 if(x_len+dest->name_size > MAXDOMAINLEN) 497 return NULL; 498 499 res = (dname_type*)region_alloc(region, sizeof(dname_type) + 500 (x_labels+((int)dest->label_count) + x_len+((int)dest->name_size)) 501 *sizeof(uint8_t)); 502 res->name_size = x_len+dest->name_size; 503 res->label_count = x_labels+dest->label_count; 504 for(i=0; i<dest->label_count; i++) 505 ((uint8_t*)dname_label_offsets(res))[i] = 506 dname_label_offsets(dest)[i] + x_len; 507 for(i=dest->label_count; i<res->label_count; i++) 508 ((uint8_t*)dname_label_offsets(res))[i] = 509 dname_label_offsets(name)[i - dest->label_count + 510 src->label_count]; 511 memcpy((uint8_t*)dname_name(res), dname_name(name), x_len); 512 memcpy((uint8_t*)dname_name(res)+x_len, dname_name(dest), dest->name_size); 513 assert(dname_is_subdomain(res, dest)); 514 return res; 515 } 516 517 char* wirelabel2str(const uint8_t* label) 518 { 519 static char buf[MAXDOMAINLEN*5+3]; 520 char* p = buf; 521 uint8_t lablen; 522 lablen = *label++; 523 while(lablen--) { 524 uint8_t ch = *label++; 525 if (isalnum((unsigned char)ch) || ch == '-' || ch == '_' || ch == '*') { 526 *p++ = ch; 527 } else if (ch == '.' || ch == '\\') { 528 *p++ = '\\'; 529 *p++ = ch; 530 } else { 531 snprintf(p, 5, "\\%03u", (unsigned int)ch); 532 p += 4; 533 } 534 } 535 *p++ = 0; 536 return buf; 537 } 538 539 char* wiredname2str(const uint8_t* dname) 540 { 541 static char buf[MAXDOMAINLEN*5+3]; 542 char* p = buf; 543 uint8_t lablen; 544 if(*dname == 0) { 545 strlcpy(buf, ".", sizeof(buf)); 546 return buf; 547 } 548 lablen = *dname++; 549 while(lablen) { 550 while(lablen--) { 551 uint8_t ch = *dname++; 552 if (isalnum((unsigned char)ch) || ch == '-' || ch == '_' || ch == '*') { 553 *p++ = ch; 554 } else if (ch == '.' || ch == '\\') { 555 *p++ = '\\'; 556 *p++ = ch; 557 } else { 558 snprintf(p, 5, "\\%03u", (unsigned int)ch); 559 p += 4; 560 } 561 } 562 lablen = *dname++; 563 *p++ = '.'; 564 } 565 *p++ = 0; 566 return buf; 567 } 568 569 int dname_equal_nocase(uint8_t* a, uint8_t* b, uint16_t len) 570 { 571 uint8_t i, lablen; 572 while(len > 0) { 573 /* check labellen */ 574 if(*a != *b) 575 return 0; 576 lablen = *a++; 577 b++; 578 len--; 579 /* malformed or compression ptr; we stop scanning */ 580 if((lablen & 0xc0) || len < lablen) 581 return (memcmp(a, b, len) == 0); 582 /* check the label, lowercased */ 583 for(i=0; i<lablen; i++) { 584 if(DNAME_NORMALIZE((unsigned char)*a++) != DNAME_NORMALIZE((unsigned char)*b++)) 585 return 0; 586 } 587 len -= lablen; 588 } 589 return 1; 590 } 591 592 int 593 is_dname_subdomain_of_case(const uint8_t* d, unsigned int len, 594 const uint8_t* d2, unsigned int len2) 595 { 596 unsigned int i; 597 if(len < len2) 598 return 0; 599 if(len == len2) { 600 if(memcmp(d, d2, len) == 0) 601 return 1; 602 return 0; 603 } 604 /* so len > len2, for d=a.example.com. and d2=example.com. */ 605 /* trailing portion must be exactly name d2. */ 606 if(memcmp(d+len-len2, d2, len2) != 0) 607 return 0; 608 /* that must also be a label point */ 609 i=0; 610 while(i < len) { 611 if(i == len-len2) 612 return 1; 613 i += d[i]; 614 i += 1; 615 } 616 617 /* The trailing portion is not at a label point. */ 618 return 0; 619 } 620 621 size_t 622 buf_dname_length(const uint8_t* buf, size_t len) 623 { 624 size_t l = 0; 625 if(!buf || len == 0) 626 return l; 627 while(len > 0 && buf[0] != 0) { 628 size_t lablen = (size_t)(buf[0]); 629 if( (lablen&0xc0) ) 630 return 0; /* the name should be uncompressed */ 631 if(lablen+1 > len) 632 return 0; /* should fit in the buffer */ 633 l += lablen+1; 634 len -= lablen+1; 635 buf += lablen+1; 636 if(l > MAXDOMAINLEN) 637 return 0; 638 } 639 if(len == 0) 640 return 0; /* end label should fit in buffer */ 641 if(buf[0] != 0) 642 return 0; /* must end in root label */ 643 l += 1; /* for the end root label */ 644 if(l > MAXDOMAINLEN) 645 return 0; 646 return l; 647 } 648 649 int 650 dname_make_buffered(struct dname_buffer* dname, uint8_t *name, int normalize) 651 { 652 size_t name_size = 0; 653 uint8_t label_offsets[MAXDOMAINLEN/2+1]; 654 uint8_t label_count = 0; 655 const uint8_t *label = name; 656 ssize_t i; 657 658 assert(name); 659 660 while (1) { 661 if(!label_is_normal(label)) 662 return 0; 663 664 label_offsets[label_count] = (uint8_t) (label - name); 665 ++label_count; 666 name_size += label_length(label) + 1; 667 668 if (name_size > MAXDOMAINLEN) 669 return 0; 670 if (label_is_root(label)) 671 break; 672 673 label = label_next(label); 674 } 675 676 assert(label_count <= MAXDOMAINLEN / 2 + 1); 677 678 /* Reverse label offsets. */ 679 for (i = 0; i < label_count / 2; ++i) { 680 uint8_t tmp = label_offsets[i]; 681 label_offsets[i] = label_offsets[label_count - i - 1]; 682 label_offsets[label_count - i - 1] = tmp; 683 } 684 685 /* Move the name to the correct part of the result */ 686 memmove( ((char*)dname)+sizeof(struct dname)+ 687 label_count*sizeof(uint8_t), name, name_size); 688 dname->dname.name_size = name_size; 689 dname->dname.label_count = label_count; 690 memcpy((uint8_t *) dname_label_offsets((void*)dname), 691 label_offsets, label_count * sizeof(uint8_t)); 692 if (normalize) { 693 uint8_t *src = (uint8_t *) dname_name((void*)dname); 694 while (!label_is_root(src)) { 695 ssize_t len = label_length(src); 696 src++; 697 for (i = 0; i < len; ++i) { 698 *src = DNAME_NORMALIZE((unsigned char)*src); 699 src++; 700 } 701 } 702 } 703 return 1; 704 } 705 706 int 707 dname_make_from_packet_buffered(struct dname_buffer* dname, 708 buffer_type *packet, int allow_pointers, int normalize) 709 { 710 int wirelen = dname_make_wire_from_packet(dname->storage, 711 packet, allow_pointers); 712 if(wirelen == 0) 713 return 0; 714 if(!dname_make_buffered(dname, dname->storage, normalize)) 715 return 0; 716 assert(wirelen == dname->dname.name_size); 717 return wirelen; 718 } 719