1/* 2 Unix SMB/CIFS implementation. 3 DNS utility library 4 Copyright (C) Gerald (Jerry) Carter 2006. 5 Copyright (C) Jeremy Allison 2007. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. 19*/ 20 21#include "includes.h" 22 23/* AIX resolv.h uses 'class' in struct ns_rr */ 24 25#if defined(AIX) 26# if defined(class) 27# undef class 28# endif 29#endif /* AIX */ 30 31/* resolver headers */ 32 33#include <sys/types.h> 34#include <netinet/in.h> 35#include <arpa/nameser.h> 36#include <resolv.h> 37#include <netdb.h> 38 39#define MAX_DNS_PACKET_SIZE 0xffff 40 41#ifdef NS_HFIXEDSZ /* Bind 8/9 interface */ 42#if !defined(C_IN) /* AIX 5.3 already defines C_IN */ 43# define C_IN ns_c_in 44#endif 45#if !defined(T_A) /* AIX 5.3 already defines T_A */ 46# define T_A ns_t_a 47#endif 48 49#if defined(HAVE_IPV6) 50#if !defined(T_AAAA) 51# define T_AAAA ns_t_aaaa 52#endif 53#endif 54 55# define T_SRV ns_t_srv 56#if !defined(T_NS) /* AIX 5.3 already defines T_NS */ 57# define T_NS ns_t_ns 58#endif 59#else 60# ifdef HFIXEDSZ 61# define NS_HFIXEDSZ HFIXEDSZ 62# else 63# define NS_HFIXEDSZ sizeof(HEADER) 64# endif /* HFIXEDSZ */ 65# ifdef PACKETSZ 66# define NS_PACKETSZ PACKETSZ 67# else /* 512 is usually the default */ 68# define NS_PACKETSZ 512 69# endif /* PACKETSZ */ 70# define T_SRV 33 71#endif 72 73/********************************************************************* 74*********************************************************************/ 75 76static bool ads_dns_parse_query( TALLOC_CTX *ctx, uint8 *start, uint8 *end, 77 uint8 **ptr, struct dns_query *q ) 78{ 79 uint8 *p = *ptr; 80 char hostname[MAX_DNS_NAME_LENGTH]; 81 int namelen; 82 83 ZERO_STRUCTP( q ); 84 85 if ( !start || !end || !q || !*ptr) 86 return False; 87 88 /* See RFC 1035 for details. If this fails, then return. */ 89 90 namelen = dn_expand( start, end, p, hostname, sizeof(hostname) ); 91 if ( namelen < 0 ) { 92 return False; 93 } 94 p += namelen; 95 q->hostname = talloc_strdup( ctx, hostname ); 96 97 /* check that we have space remaining */ 98 99 if ( PTR_DIFF(p+4, end) > 0 ) 100 return False; 101 102 q->type = RSVAL( p, 0 ); 103 q->in_class = RSVAL( p, 2 ); 104 p += 4; 105 106 *ptr = p; 107 108 return True; 109} 110 111/********************************************************************* 112*********************************************************************/ 113 114static bool ads_dns_parse_rr( TALLOC_CTX *ctx, uint8 *start, uint8 *end, 115 uint8 **ptr, struct dns_rr *rr ) 116{ 117 uint8 *p = *ptr; 118 char hostname[MAX_DNS_NAME_LENGTH]; 119 int namelen; 120 121 if ( !start || !end || !rr || !*ptr) 122 return -1; 123 124 ZERO_STRUCTP( rr ); 125 /* pull the name from the answer */ 126 127 namelen = dn_expand( start, end, p, hostname, sizeof(hostname) ); 128 if ( namelen < 0 ) { 129 return -1; 130 } 131 p += namelen; 132 rr->hostname = talloc_strdup( ctx, hostname ); 133 134 /* check that we have space remaining */ 135 136 if ( PTR_DIFF(p+10, end) > 0 ) 137 return False; 138 139 /* pull some values and then skip onto the string */ 140 141 rr->type = RSVAL(p, 0); 142 rr->in_class = RSVAL(p, 2); 143 rr->ttl = RIVAL(p, 4); 144 rr->rdatalen = RSVAL(p, 8); 145 146 p += 10; 147 148 /* sanity check the available space */ 149 150 if ( PTR_DIFF(p+rr->rdatalen, end ) > 0 ) { 151 return False; 152 153 } 154 155 /* save a point to the rdata for this section */ 156 157 rr->rdata = p; 158 p += rr->rdatalen; 159 160 *ptr = p; 161 162 return True; 163} 164 165/********************************************************************* 166*********************************************************************/ 167 168static bool ads_dns_parse_rr_srv( TALLOC_CTX *ctx, uint8 *start, uint8 *end, 169 uint8 **ptr, struct dns_rr_srv *srv ) 170{ 171 struct dns_rr rr; 172 uint8 *p; 173 char dcname[MAX_DNS_NAME_LENGTH]; 174 int namelen; 175 176 if ( !start || !end || !srv || !*ptr) 177 return -1; 178 179 /* Parse the RR entry. Coming out of the this, ptr is at the beginning 180 of the next record */ 181 182 if ( !ads_dns_parse_rr( ctx, start, end, ptr, &rr ) ) { 183 DEBUG(1,("ads_dns_parse_rr_srv: Failed to parse RR record\n")); 184 return False; 185 } 186 187 if ( rr.type != T_SRV ) { 188 DEBUG(1,("ads_dns_parse_rr_srv: Bad answer type (%d)\n", 189 rr.type)); 190 return False; 191 } 192 193 p = rr.rdata; 194 195 srv->priority = RSVAL(p, 0); 196 srv->weight = RSVAL(p, 2); 197 srv->port = RSVAL(p, 4); 198 199 p += 6; 200 201 namelen = dn_expand( start, end, p, dcname, sizeof(dcname) ); 202 if ( namelen < 0 ) { 203 DEBUG(1,("ads_dns_parse_rr_srv: Failed to uncompress name!\n")); 204 return False; 205 } 206 207 srv->hostname = talloc_strdup( ctx, dcname ); 208 209 DEBUG(10,("ads_dns_parse_rr_srv: Parsed %s [%u, %u, %u]\n", 210 srv->hostname, 211 srv->priority, 212 srv->weight, 213 srv->port)); 214 215 return True; 216} 217 218/********************************************************************* 219*********************************************************************/ 220 221static bool ads_dns_parse_rr_ns( TALLOC_CTX *ctx, uint8 *start, uint8 *end, 222 uint8 **ptr, struct dns_rr_ns *nsrec ) 223{ 224 struct dns_rr rr; 225 uint8 *p; 226 char nsname[MAX_DNS_NAME_LENGTH]; 227 int namelen; 228 229 if ( !start || !end || !nsrec || !*ptr) 230 return -1; 231 232 /* Parse the RR entry. Coming out of the this, ptr is at the beginning 233 of the next record */ 234 235 if ( !ads_dns_parse_rr( ctx, start, end, ptr, &rr ) ) { 236 DEBUG(1,("ads_dns_parse_rr_ns: Failed to parse RR record\n")); 237 return False; 238 } 239 240 if ( rr.type != T_NS ) { 241 DEBUG(1,("ads_dns_parse_rr_ns: Bad answer type (%d)\n", 242 rr.type)); 243 return False; 244 } 245 246 p = rr.rdata; 247 248 /* ame server hostname */ 249 250 namelen = dn_expand( start, end, p, nsname, sizeof(nsname) ); 251 if ( namelen < 0 ) { 252 DEBUG(1,("ads_dns_parse_rr_ns: Failed to uncompress name!\n")); 253 return False; 254 } 255 nsrec->hostname = talloc_strdup( ctx, nsname ); 256 257 return True; 258} 259 260/********************************************************************* 261 Sort SRV record list based on weight and priority. See RFC 2782. 262*********************************************************************/ 263 264static int dnssrvcmp( struct dns_rr_srv *a, struct dns_rr_srv *b ) 265{ 266 if ( a->priority == b->priority ) { 267 268 /* randomize entries with an equal weight and priority */ 269 if ( a->weight == b->weight ) 270 return 0; 271 272 /* higher weights should be sorted lower */ 273 if ( a->weight > b->weight ) 274 return -1; 275 else 276 return 1; 277 } 278 279 if ( a->priority < b->priority ) 280 return -1; 281 282 return 1; 283} 284 285/********************************************************************* 286 Simple wrapper for a DNS query 287*********************************************************************/ 288 289#define DNS_FAILED_WAITTIME 30 290 291static NTSTATUS dns_send_req( TALLOC_CTX *ctx, const char *name, int q_type, 292 uint8 **buf, int *resp_length ) 293{ 294 uint8 *buffer = NULL; 295 size_t buf_len = 0; 296 int resp_len = NS_PACKETSZ; 297 static time_t last_dns_check = 0; 298 static NTSTATUS last_dns_status = NT_STATUS_OK; 299 time_t now = time(NULL); 300 301 /* Try to prevent bursts of DNS lookups if the server is down */ 302 303 /* Protect against large clock changes */ 304 305 if ( last_dns_check > now ) 306 last_dns_check = 0; 307 308 /* IF we had a DNS timeout or a bad server and we are still 309 in the 30 second cache window, just return the previous 310 status and save the network timeout. */ 311 312 if ( (NT_STATUS_EQUAL(last_dns_status,NT_STATUS_IO_TIMEOUT) || 313 NT_STATUS_EQUAL(last_dns_status,NT_STATUS_CONNECTION_REFUSED)) && 314 (last_dns_check+DNS_FAILED_WAITTIME) > now ) 315 { 316 DEBUG(10,("last_dns_check: Returning cached status (%s)\n", 317 nt_errstr(last_dns_status) )); 318 return last_dns_status; 319 } 320 321 /* Send the Query */ 322 do { 323 if ( buffer ) 324 TALLOC_FREE( buffer ); 325 326 buf_len = resp_len * sizeof(uint8); 327 328 if (buf_len) { 329 if ((buffer = TALLOC_ARRAY(ctx, uint8, buf_len)) 330 == NULL ) { 331 DEBUG(0,("ads_dns_lookup_srv: " 332 "talloc() failed!\n")); 333 last_dns_status = NT_STATUS_NO_MEMORY; 334 last_dns_check = time(NULL); 335 return last_dns_status; 336 } 337 } 338 339 if ((resp_len = res_query(name, C_IN, q_type, buffer, buf_len)) 340 < 0 ) { 341 DEBUG(3,("ads_dns_lookup_srv: " 342 "Failed to resolve %s (%s)\n", 343 name, strerror(errno))); 344 TALLOC_FREE( buffer ); 345 last_dns_status = NT_STATUS_UNSUCCESSFUL; 346 347 if (errno == ETIMEDOUT) { 348 last_dns_status = NT_STATUS_IO_TIMEOUT; 349 } 350 if (errno == ECONNREFUSED) { 351 last_dns_status = NT_STATUS_CONNECTION_REFUSED; 352 } 353 last_dns_check = time(NULL); 354 return last_dns_status; 355 } 356 357 /* On AIX, Solaris, and possibly some older glibc systems (e.g. SLES8) 358 truncated replies never give back a resp_len > buflen 359 which ends up causing DNS resolve failures on large tcp DNS replies */ 360 361 if (buf_len == resp_len) { 362 if (resp_len == MAX_DNS_PACKET_SIZE) { 363 DEBUG(1,("dns_send_req: DNS reply too large when resolving %s\n", 364 name)); 365 TALLOC_FREE( buffer ); 366 last_dns_status = NT_STATUS_BUFFER_TOO_SMALL; 367 last_dns_check = time(NULL); 368 return last_dns_status; 369 } 370 371 resp_len = MIN(resp_len*2, MAX_DNS_PACKET_SIZE); 372 } 373 374 375 } while ( buf_len < resp_len && resp_len <= MAX_DNS_PACKET_SIZE ); 376 377 *buf = buffer; 378 *resp_length = resp_len; 379 380 last_dns_check = time(NULL); 381 last_dns_status = NT_STATUS_OK; 382 return last_dns_status; 383} 384 385/********************************************************************* 386 Simple wrapper for a DNS SRV query 387*********************************************************************/ 388 389static NTSTATUS ads_dns_lookup_srv( TALLOC_CTX *ctx, 390 const char *name, 391 struct dns_rr_srv **dclist, 392 int *numdcs) 393{ 394 uint8 *buffer = NULL; 395 int resp_len = 0; 396 struct dns_rr_srv *dcs = NULL; 397 int query_count, answer_count, auth_count, additional_count; 398 uint8 *p = buffer; 399 int rrnum; 400 int idx = 0; 401 NTSTATUS status; 402 403 if ( !ctx || !name || !dclist ) { 404 return NT_STATUS_INVALID_PARAMETER; 405 } 406 407 /* Send the request. May have to loop several times in case 408 of large replies */ 409 410 status = dns_send_req( ctx, name, T_SRV, &buffer, &resp_len ); 411 if ( !NT_STATUS_IS_OK(status) ) { 412 DEBUG(3,("ads_dns_lookup_srv: Failed to send DNS query (%s)\n", 413 nt_errstr(status))); 414 return status; 415 } 416 p = buffer; 417 418 /* For some insane reason, the ns_initparse() et. al. routines are only 419 available in libresolv.a, and not the shared lib. Who knows why.... 420 So we have to parse the DNS reply ourselves */ 421 422 /* Pull the answer RR's count from the header. 423 * Use the NMB ordering macros */ 424 425 query_count = RSVAL( p, 4 ); 426 answer_count = RSVAL( p, 6 ); 427 auth_count = RSVAL( p, 8 ); 428 additional_count = RSVAL( p, 10 ); 429 430 DEBUG(4,("ads_dns_lookup_srv: " 431 "%d records returned in the answer section.\n", 432 answer_count)); 433 434 if (answer_count) { 435 if ((dcs = TALLOC_ZERO_ARRAY(ctx, struct dns_rr_srv, 436 answer_count)) == NULL ) { 437 DEBUG(0,("ads_dns_lookup_srv: " 438 "talloc() failure for %d char*'s\n", 439 answer_count)); 440 return NT_STATUS_NO_MEMORY; 441 } 442 } else { 443 dcs = NULL; 444 } 445 446 /* now skip the header */ 447 448 p += NS_HFIXEDSZ; 449 450 /* parse the query section */ 451 452 for ( rrnum=0; rrnum<query_count; rrnum++ ) { 453 struct dns_query q; 454 455 if (!ads_dns_parse_query(ctx, buffer, 456 buffer+resp_len, &p, &q)) { 457 DEBUG(1,("ads_dns_lookup_srv: " 458 "Failed to parse query record [%d]!\n", rrnum)); 459 return NT_STATUS_UNSUCCESSFUL; 460 } 461 } 462 463 /* now we are at the answer section */ 464 465 for ( rrnum=0; rrnum<answer_count; rrnum++ ) { 466 if (!ads_dns_parse_rr_srv(ctx, buffer, buffer+resp_len, 467 &p, &dcs[rrnum])) { 468 DEBUG(1,("ads_dns_lookup_srv: " 469 "Failed to parse answer recordi [%d]!\n", rrnum)); 470 return NT_STATUS_UNSUCCESSFUL; 471 } 472 } 473 idx = rrnum; 474 475 /* Parse the authority section */ 476 /* just skip these for now */ 477 478 for ( rrnum=0; rrnum<auth_count; rrnum++ ) { 479 struct dns_rr rr; 480 481 if (!ads_dns_parse_rr( ctx, buffer, 482 buffer+resp_len, &p, &rr)) { 483 DEBUG(1,("ads_dns_lookup_srv: " 484 "Failed to parse authority record! [%d]\n", rrnum)); 485 return NT_STATUS_UNSUCCESSFUL; 486 } 487 } 488 489 /* Parse the additional records section */ 490 491 for ( rrnum=0; rrnum<additional_count; rrnum++ ) { 492 struct dns_rr rr; 493 int i; 494 495 if (!ads_dns_parse_rr(ctx, buffer, buffer+resp_len, 496 &p, &rr)) { 497 DEBUG(1,("ads_dns_lookup_srv: Failed " 498 "to parse additional records section! [%d]\n", rrnum)); 499 return NT_STATUS_UNSUCCESSFUL; 500 } 501 502 /* Only interested in A or AAAA records as a shortcut for having 503 * to come back later and lookup the name. For multi-homed 504 * hosts, the number of additional records and exceed the 505 * number of answer records. */ 506 507 if (rr.type != T_A || rr.rdatalen != 4) { 508#if defined(HAVE_IPV6) 509 /* RFC2874 defines A6 records. This 510 * requires recusive and horribly complex lookups. 511 * Bastards. Ignore this for now.... JRA. 512 * Luckily RFC3363 reprecates A6 records. 513 */ 514 if (rr.type != T_AAAA || rr.rdatalen != 16) 515#endif 516 continue; 517 } 518 519 for ( i=0; i<idx; i++ ) { 520 if ( strcmp( rr.hostname, dcs[i].hostname ) == 0 ) { 521 int num_ips = dcs[i].num_ips; 522 struct sockaddr_storage *tmp_ss_s; 523 524 /* allocate new memory */ 525 526 if (dcs[i].num_ips == 0) { 527 if ((dcs[i].ss_s = TALLOC_ARRAY(dcs, 528 struct sockaddr_storage, 1 )) 529 == NULL ) { 530 return NT_STATUS_NO_MEMORY; 531 } 532 } else { 533 if ((tmp_ss_s = TALLOC_REALLOC_ARRAY(dcs, 534 dcs[i].ss_s, 535 struct sockaddr_storage, 536 dcs[i].num_ips+1)) 537 == NULL ) { 538 return NT_STATUS_NO_MEMORY; 539 } 540 541 dcs[i].ss_s = tmp_ss_s; 542 } 543 dcs[i].num_ips++; 544 545 /* copy the new IP address */ 546 if (rr.type == T_A) { 547 struct in_addr ip; 548 memcpy(&ip, rr.rdata, 4); 549 in_addr_to_sockaddr_storage( 550 &dcs[i].ss_s[num_ips], 551 ip); 552 } 553#if defined(HAVE_IPV6) 554 if (rr.type == T_AAAA) { 555 struct in6_addr ip6; 556 memcpy(&ip6, rr.rdata, rr.rdatalen); 557 in6_addr_to_sockaddr_storage( 558 &dcs[i].ss_s[num_ips], 559 ip6); 560 } 561#endif 562 } 563 } 564 } 565 566 qsort( dcs, idx, sizeof(struct dns_rr_srv), QSORT_CAST dnssrvcmp ); 567 568 *dclist = dcs; 569 *numdcs = idx; 570 571 return NT_STATUS_OK; 572} 573 574/********************************************************************* 575 Simple wrapper for a DNS NS query 576*********************************************************************/ 577 578NTSTATUS ads_dns_lookup_ns(TALLOC_CTX *ctx, 579 const char *dnsdomain, 580 struct dns_rr_ns **nslist, 581 int *numns) 582{ 583 uint8 *buffer = NULL; 584 int resp_len = 0; 585 struct dns_rr_ns *nsarray = NULL; 586 int query_count, answer_count, auth_count, additional_count; 587 uint8 *p; 588 int rrnum; 589 int idx = 0; 590 NTSTATUS status; 591 592 if ( !ctx || !dnsdomain || !nslist ) { 593 return NT_STATUS_INVALID_PARAMETER; 594 } 595 596 /* Send the request. May have to loop several times in case 597 of large replies */ 598 599 status = dns_send_req( ctx, dnsdomain, T_NS, &buffer, &resp_len ); 600 if ( !NT_STATUS_IS_OK(status) ) { 601 DEBUG(3,("ads_dns_lookup_ns: Failed to send DNS query (%s)\n", 602 nt_errstr(status))); 603 return status; 604 } 605 p = buffer; 606 607 /* For some insane reason, the ns_initparse() et. al. routines are only 608 available in libresolv.a, and not the shared lib. Who knows why.... 609 So we have to parse the DNS reply ourselves */ 610 611 /* Pull the answer RR's count from the header. 612 * Use the NMB ordering macros */ 613 614 query_count = RSVAL( p, 4 ); 615 answer_count = RSVAL( p, 6 ); 616 auth_count = RSVAL( p, 8 ); 617 additional_count = RSVAL( p, 10 ); 618 619 DEBUG(4,("ads_dns_lookup_ns: " 620 "%d records returned in the answer section.\n", 621 answer_count)); 622 623 if (answer_count) { 624 if ((nsarray = TALLOC_ARRAY(ctx, struct dns_rr_ns, 625 answer_count)) == NULL ) { 626 DEBUG(0,("ads_dns_lookup_ns: " 627 "talloc() failure for %d char*'s\n", 628 answer_count)); 629 return NT_STATUS_NO_MEMORY; 630 } 631 } else { 632 nsarray = NULL; 633 } 634 635 /* now skip the header */ 636 637 p += NS_HFIXEDSZ; 638 639 /* parse the query section */ 640 641 for ( rrnum=0; rrnum<query_count; rrnum++ ) { 642 struct dns_query q; 643 644 if (!ads_dns_parse_query(ctx, buffer, buffer+resp_len, 645 &p, &q)) { 646 DEBUG(1,("ads_dns_lookup_ns: " 647 " Failed to parse query record!\n")); 648 return NT_STATUS_UNSUCCESSFUL; 649 } 650 } 651 652 /* now we are at the answer section */ 653 654 for ( rrnum=0; rrnum<answer_count; rrnum++ ) { 655 if (!ads_dns_parse_rr_ns(ctx, buffer, buffer+resp_len, 656 &p, &nsarray[rrnum])) { 657 DEBUG(1,("ads_dns_lookup_ns: " 658 "Failed to parse answer record!\n")); 659 return NT_STATUS_UNSUCCESSFUL; 660 } 661 } 662 idx = rrnum; 663 664 /* Parse the authority section */ 665 /* just skip these for now */ 666 667 for ( rrnum=0; rrnum<auth_count; rrnum++ ) { 668 struct dns_rr rr; 669 670 if ( !ads_dns_parse_rr(ctx, buffer, buffer+resp_len, 671 &p, &rr)) { 672 DEBUG(1,("ads_dns_lookup_ns: " 673 "Failed to parse authority record!\n")); 674 return NT_STATUS_UNSUCCESSFUL; 675 } 676 } 677 678 /* Parse the additional records section */ 679 680 for ( rrnum=0; rrnum<additional_count; rrnum++ ) { 681 struct dns_rr rr; 682 int i; 683 684 if (!ads_dns_parse_rr(ctx, buffer, buffer+resp_len, 685 &p, &rr)) { 686 DEBUG(1,("ads_dns_lookup_ns: Failed " 687 "to parse additional records section!\n")); 688 return NT_STATUS_UNSUCCESSFUL; 689 } 690 691 /* only interested in A records as a shortcut for having to come 692 back later and lookup the name */ 693 694 if (rr.type != T_A || rr.rdatalen != 4) { 695#if defined(HAVE_IPV6) 696 if (rr.type != T_AAAA || rr.rdatalen != 16) 697#endif 698 continue; 699 } 700 701 for ( i=0; i<idx; i++ ) { 702 if (strcmp(rr.hostname, nsarray[i].hostname) == 0) { 703 if (rr.type == T_A) { 704 struct in_addr ip; 705 memcpy(&ip, rr.rdata, 4); 706 in_addr_to_sockaddr_storage( 707 &nsarray[i].ss, 708 ip); 709 } 710#if defined(HAVE_IPV6) 711 if (rr.type == T_AAAA) { 712 struct in6_addr ip6; 713 memcpy(&ip6, rr.rdata, rr.rdatalen); 714 in6_addr_to_sockaddr_storage( 715 &nsarray[i].ss, 716 ip6); 717 } 718#endif 719 } 720 } 721 } 722 723 *nslist = nsarray; 724 *numns = idx; 725 726 return NT_STATUS_OK; 727} 728 729/**************************************************************************** 730 Store and fetch the AD client sitename. 731****************************************************************************/ 732 733#define SITENAME_KEY "AD_SITENAME/DOMAIN/%s" 734 735static char *sitename_key(const char *realm) 736{ 737 char *keystr; 738 739 if (asprintf_strupper_m(&keystr, SITENAME_KEY, realm) == -1) { 740 return NULL; 741 } 742 743 return keystr; 744} 745 746 747/**************************************************************************** 748 Store the AD client sitename. 749 We store indefinately as every new CLDAP query will re-write this. 750****************************************************************************/ 751 752bool sitename_store(const char *realm, const char *sitename) 753{ 754 time_t expire; 755 bool ret = False; 756 char *key; 757 758 if (!realm || (strlen(realm) == 0)) { 759 DEBUG(0,("sitename_store: no realm\n")); 760 return False; 761 } 762 763 key = sitename_key(realm); 764 765 if (!sitename || (sitename && !*sitename)) { 766 DEBUG(5,("sitename_store: deleting empty sitename!\n")); 767 ret = gencache_del(key); 768 SAFE_FREE(key); 769 return ret; 770 } 771 772 expire = get_time_t_max(); /* Store indefinately. */ 773 774 DEBUG(10,("sitename_store: realm = [%s], sitename = [%s], expire = [%u]\n", 775 realm, sitename, (unsigned int)expire )); 776 777 ret = gencache_set( key, sitename, expire ); 778 SAFE_FREE(key); 779 return ret; 780} 781 782/**************************************************************************** 783 Fetch the AD client sitename. 784 Caller must free. 785****************************************************************************/ 786 787char *sitename_fetch(const char *realm) 788{ 789 char *sitename = NULL; 790 time_t timeout; 791 bool ret = False; 792 const char *query_realm; 793 char *key; 794 795 if (!realm || (strlen(realm) == 0)) { 796 query_realm = lp_realm(); 797 } else { 798 query_realm = realm; 799 } 800 801 key = sitename_key(query_realm); 802 803 ret = gencache_get( key, &sitename, &timeout ); 804 SAFE_FREE(key); 805 if ( !ret ) { 806 DEBUG(5,("sitename_fetch: No stored sitename for %s\n", 807 query_realm)); 808 } else { 809 DEBUG(5,("sitename_fetch: Returning sitename for %s: \"%s\"\n", 810 query_realm, sitename )); 811 } 812 return sitename; 813} 814 815/**************************************************************************** 816 Did the sitename change ? 817****************************************************************************/ 818 819bool stored_sitename_changed(const char *realm, const char *sitename) 820{ 821 bool ret = False; 822 823 char *new_sitename; 824 825 if (!realm || (strlen(realm) == 0)) { 826 DEBUG(0,("stored_sitename_changed: no realm\n")); 827 return False; 828 } 829 830 new_sitename = sitename_fetch(realm); 831 832 if (sitename && new_sitename && !strequal(sitename, new_sitename)) { 833 ret = True; 834 } else if ((sitename && !new_sitename) || 835 (!sitename && new_sitename)) { 836 ret = True; 837 } 838 SAFE_FREE(new_sitename); 839 return ret; 840} 841 842/******************************************************************** 843 Query with optional sitename. 844********************************************************************/ 845 846static NTSTATUS ads_dns_query_internal(TALLOC_CTX *ctx, 847 const char *servicename, 848 const char *dc_pdc_gc_domains, 849 const char *realm, 850 const char *sitename, 851 struct dns_rr_srv **dclist, 852 int *numdcs ) 853{ 854 char *name; 855 if (sitename) { 856 name = talloc_asprintf(ctx, "%s._tcp.%s._sites.%s._msdcs.%s", 857 servicename, sitename, 858 dc_pdc_gc_domains, realm); 859 } else { 860 name = talloc_asprintf(ctx, "%s._tcp.%s._msdcs.%s", 861 servicename, dc_pdc_gc_domains, realm); 862 } 863 if (!name) { 864 return NT_STATUS_NO_MEMORY; 865 } 866 return ads_dns_lookup_srv( ctx, name, dclist, numdcs ); 867} 868 869/******************************************************************** 870 Query for AD DC's. 871********************************************************************/ 872 873NTSTATUS ads_dns_query_dcs(TALLOC_CTX *ctx, 874 const char *realm, 875 const char *sitename, 876 struct dns_rr_srv **dclist, 877 int *numdcs ) 878{ 879 NTSTATUS status; 880 881 status = ads_dns_query_internal(ctx, "_ldap", "dc", realm, sitename, 882 dclist, numdcs); 883 884 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) || 885 NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_REFUSED)) { 886 return status; 887 } 888 889 if (sitename && 890 ((!NT_STATUS_IS_OK(status)) || 891 (NT_STATUS_IS_OK(status) && (numdcs == 0)))) { 892 /* Sitename DNS query may have failed. Try without. */ 893 status = ads_dns_query_internal(ctx, "_ldap", "dc", realm, 894 NULL, dclist, numdcs); 895 } 896 return status; 897} 898 899/******************************************************************** 900 Query for AD GC's. 901********************************************************************/ 902 903NTSTATUS ads_dns_query_gcs(TALLOC_CTX *ctx, 904 const char *realm, 905 const char *sitename, 906 struct dns_rr_srv **dclist, 907 int *numdcs ) 908{ 909 NTSTATUS status; 910 911 status = ads_dns_query_internal(ctx, "_ldap", "gc", realm, sitename, 912 dclist, numdcs); 913 914 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) || 915 NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_REFUSED)) { 916 return status; 917 } 918 919 if (sitename && 920 ((!NT_STATUS_IS_OK(status)) || 921 (NT_STATUS_IS_OK(status) && (numdcs == 0)))) { 922 /* Sitename DNS query may have failed. Try without. */ 923 status = ads_dns_query_internal(ctx, "_ldap", "gc", realm, 924 NULL, dclist, numdcs); 925 } 926 return status; 927} 928 929/******************************************************************** 930 Query for AD KDC's. 931 Even if our underlying kerberos libraries are UDP only, this 932 is pretty safe as it's unlikely that a KDC supports TCP and not UDP. 933********************************************************************/ 934 935NTSTATUS ads_dns_query_kdcs(TALLOC_CTX *ctx, 936 const char *dns_forest_name, 937 const char *sitename, 938 struct dns_rr_srv **dclist, 939 int *numdcs ) 940{ 941 NTSTATUS status; 942 943 status = ads_dns_query_internal(ctx, "_kerberos", "dc", 944 dns_forest_name, sitename, dclist, 945 numdcs); 946 947 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) || 948 NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_REFUSED)) { 949 return status; 950 } 951 952 if (sitename && 953 ((!NT_STATUS_IS_OK(status)) || 954 (NT_STATUS_IS_OK(status) && (numdcs == 0)))) { 955 /* Sitename DNS query may have failed. Try without. */ 956 status = ads_dns_query_internal(ctx, "_kerberos", "dc", 957 dns_forest_name, NULL, 958 dclist, numdcs); 959 } 960 return status; 961} 962 963/******************************************************************** 964 Query for AD PDC. Sitename is obsolete here. 965********************************************************************/ 966 967NTSTATUS ads_dns_query_pdc(TALLOC_CTX *ctx, 968 const char *dns_domain_name, 969 struct dns_rr_srv **dclist, 970 int *numdcs ) 971{ 972 return ads_dns_query_internal(ctx, "_ldap", "pdc", dns_domain_name, 973 NULL, dclist, numdcs); 974} 975 976/******************************************************************** 977 Query for AD DC by guid. Sitename is obsolete here. 978********************************************************************/ 979 980NTSTATUS ads_dns_query_dcs_guid(TALLOC_CTX *ctx, 981 const char *dns_forest_name, 982 const struct GUID *domain_guid, 983 struct dns_rr_srv **dclist, 984 int *numdcs ) 985{ 986 /*_ldap._tcp.DomainGuid.domains._msdcs.DnsForestName */ 987 988 const char *domains; 989 char *guid_string; 990 991 guid_string = GUID_string(ctx, domain_guid); 992 if (!guid_string) { 993 return NT_STATUS_NO_MEMORY; 994 } 995 996 /* little hack */ 997 domains = talloc_asprintf(ctx, "%s.domains", guid_string); 998 if (!domains) { 999 return NT_STATUS_NO_MEMORY; 1000 } 1001 TALLOC_FREE(guid_string); 1002 1003 return ads_dns_query_internal(ctx, "_ldap", domains, dns_forest_name, 1004 NULL, dclist, numdcs); 1005} 1006