00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "includes.h"
00022
00023
00024
00025 #if defined(AIX)
00026 # if defined(class)
00027 # undef class
00028 # endif
00029 #endif
00030
00031
00032
00033 #include <sys/types.h>
00034 #include <netinet/in.h>
00035 #include <arpa/nameser.h>
00036 #include <resolv.h>
00037 #include <netdb.h>
00038
00039 #define MAX_DNS_PACKET_SIZE 0xffff
00040
00041 #ifdef NS_HFIXEDSZ
00042 #if !defined(C_IN)
00043 # define C_IN ns_c_in
00044 #endif
00045 #if !defined(T_A)
00046 # define T_A ns_t_a
00047 #endif
00048 # define T_SRV ns_t_srv
00049 #if !defined(T_NS)
00050 # define T_NS ns_t_ns
00051 #endif
00052 #else
00053 # ifdef HFIXEDSZ
00054 # define NS_HFIXEDSZ HFIXEDSZ
00055 # else
00056 # define NS_HFIXEDSZ sizeof(HEADER)
00057 # endif
00058 # ifdef PACKETSZ
00059 # define NS_PACKETSZ PACKETSZ
00060 # else
00061 # define NS_PACKETSZ 512
00062 # endif
00063 # define T_SRV 33
00064 #endif
00065
00066
00067
00068
00069 static BOOL ads_dns_parse_query( TALLOC_CTX *ctx, uint8 *start, uint8 *end,
00070 uint8 **ptr, struct dns_query *q )
00071 {
00072 uint8 *p = *ptr;
00073 pstring hostname;
00074 int namelen;
00075
00076 ZERO_STRUCTP( q );
00077
00078 if ( !start || !end || !q || !*ptr)
00079 return False;
00080
00081
00082
00083 namelen = dn_expand( start, end, p, hostname, sizeof(hostname) );
00084 if ( namelen < 0 ) {
00085 return False;
00086 }
00087 p += namelen;
00088 q->hostname = talloc_strdup( ctx, hostname );
00089
00090
00091
00092 if ( PTR_DIFF(p+4, end) > 0 )
00093 return False;
00094
00095 q->type = RSVAL( p, 0 );
00096 q->in_class = RSVAL( p, 2 );
00097 p += 4;
00098
00099 *ptr = p;
00100
00101 return True;
00102 }
00103
00104
00105
00106
00107 static BOOL ads_dns_parse_rr( TALLOC_CTX *ctx, uint8 *start, uint8 *end,
00108 uint8 **ptr, struct dns_rr *rr )
00109 {
00110 uint8 *p = *ptr;
00111 pstring hostname;
00112 int namelen;
00113
00114 if ( !start || !end || !rr || !*ptr)
00115 return -1;
00116
00117 ZERO_STRUCTP( rr );
00118
00119
00120 namelen = dn_expand( start, end, p, hostname, sizeof(hostname) );
00121 if ( namelen < 0 ) {
00122 return -1;
00123 }
00124 p += namelen;
00125 rr->hostname = talloc_strdup( ctx, hostname );
00126
00127
00128
00129 if ( PTR_DIFF(p+10, end) > 0 )
00130 return False;
00131
00132
00133
00134 rr->type = RSVAL(p, 0);
00135 rr->in_class = RSVAL(p, 2);
00136 rr->ttl = RIVAL(p, 4);
00137 rr->rdatalen = RSVAL(p, 8);
00138
00139 p += 10;
00140
00141
00142
00143 if ( PTR_DIFF(p+rr->rdatalen, end ) > 0 ) {
00144 return False;
00145
00146 }
00147
00148
00149
00150 rr->rdata = p;
00151 p += rr->rdatalen;
00152
00153 *ptr = p;
00154
00155 return True;
00156 }
00157
00158
00159
00160
00161 static BOOL ads_dns_parse_rr_srv( TALLOC_CTX *ctx, uint8 *start, uint8 *end,
00162 uint8 **ptr, struct dns_rr_srv *srv )
00163 {
00164 struct dns_rr rr;
00165 uint8 *p;
00166 pstring dcname;
00167 int namelen;
00168
00169 if ( !start || !end || !srv || !*ptr)
00170 return -1;
00171
00172
00173
00174
00175 if ( !ads_dns_parse_rr( ctx, start, end, ptr, &rr ) ) {
00176 DEBUG(1,("ads_dns_parse_rr_srv: Failed to parse RR record\n"));
00177 return False;
00178 }
00179
00180 if ( rr.type != T_SRV ) {
00181 DEBUG(1,("ads_dns_parse_rr_srv: Bad answer type (%d)\n", rr.type));
00182 return False;
00183 }
00184
00185 p = rr.rdata;
00186
00187 srv->priority = RSVAL(p, 0);
00188 srv->weight = RSVAL(p, 2);
00189 srv->port = RSVAL(p, 4);
00190
00191 p += 6;
00192
00193 namelen = dn_expand( start, end, p, dcname, sizeof(dcname) );
00194 if ( namelen < 0 ) {
00195 DEBUG(1,("ads_dns_parse_rr_srv: Failed to uncompress name!\n"));
00196 return False;
00197 }
00198
00199 srv->hostname = talloc_strdup( ctx, dcname );
00200
00201 DEBUG(10,("ads_dns_parse_rr_srv: Parsed %s [%u, %u, %u]\n",
00202 srv->hostname,
00203 srv->priority,
00204 srv->weight,
00205 srv->port));
00206
00207 return True;
00208 }
00209
00210
00211
00212
00213 static BOOL ads_dns_parse_rr_ns( TALLOC_CTX *ctx, uint8 *start, uint8 *end,
00214 uint8 **ptr, struct dns_rr_ns *nsrec )
00215 {
00216 struct dns_rr rr;
00217 uint8 *p;
00218 pstring nsname;
00219 int namelen;
00220
00221 if ( !start || !end || !nsrec || !*ptr)
00222 return -1;
00223
00224
00225
00226
00227 if ( !ads_dns_parse_rr( ctx, start, end, ptr, &rr ) ) {
00228 DEBUG(1,("ads_dns_parse_rr_ns: Failed to parse RR record\n"));
00229 return False;
00230 }
00231
00232 if ( rr.type != T_NS ) {
00233 DEBUG(1,("ads_dns_parse_rr_ns: Bad answer type (%d)\n", rr.type));
00234 return False;
00235 }
00236
00237 p = rr.rdata;
00238
00239
00240
00241 namelen = dn_expand( start, end, p, nsname, sizeof(nsname) );
00242 if ( namelen < 0 ) {
00243 DEBUG(1,("ads_dns_parse_rr_ns: Failed to uncompress name!\n"));
00244 return False;
00245 }
00246 nsrec->hostname = talloc_strdup( ctx, nsname );
00247
00248 return True;
00249 }
00250
00251
00252
00253
00254
00255 static int dnssrvcmp( struct dns_rr_srv *a, struct dns_rr_srv *b )
00256 {
00257 if ( a->priority == b->priority ) {
00258
00259
00260 if ( a->weight == b->weight )
00261 return 0;
00262
00263
00264 if ( a->weight > b->weight )
00265 return -1;
00266 else
00267 return 1;
00268 }
00269
00270 if ( a->priority < b->priority )
00271 return -1;
00272
00273 return 1;
00274 }
00275
00276
00277
00278
00279
00280 static NTSTATUS dns_send_req( TALLOC_CTX *ctx, const char *name, int q_type,
00281 uint8 **buf, int *resp_length )
00282 {
00283 uint8 *buffer = NULL;
00284 size_t buf_len = 0;
00285 int resp_len = NS_PACKETSZ;
00286
00287 do {
00288 if ( buffer )
00289 TALLOC_FREE( buffer );
00290
00291 buf_len = resp_len * sizeof(uint8);
00292
00293 if (buf_len) {
00294 if ( (buffer = TALLOC_ARRAY(ctx, uint8, buf_len)) == NULL ) {
00295 DEBUG(0,("ads_dns_lookup_srv: talloc() failed!\n"));
00296 return NT_STATUS_NO_MEMORY;
00297 }
00298 } else {
00299 buffer = NULL;
00300 }
00301
00302 if ( (resp_len = res_query(name, C_IN, q_type, buffer, buf_len)) < 0 ) {
00303 DEBUG(3,("ads_dns_lookup_srv: Failed to resolve %s (%s)\n", name, strerror(errno)));
00304 TALLOC_FREE( buffer );
00305 if (errno == ETIMEDOUT) {
00306 return NT_STATUS_IO_TIMEOUT;
00307 }
00308 if (errno == ECONNREFUSED) {
00309 return NT_STATUS_CONNECTION_REFUSED;
00310 }
00311 return NT_STATUS_UNSUCCESSFUL;
00312 }
00313
00314
00315
00316
00317
00318 if (buf_len == resp_len) {
00319 if (resp_len == MAX_DNS_PACKET_SIZE) {
00320 DEBUG(1,("dns_send_req: DNS reply too large when resolving %s\n",
00321 name));
00322 TALLOC_FREE( buffer );
00323 return NT_STATUS_BUFFER_TOO_SMALL;
00324 }
00325
00326 resp_len = MIN(resp_len*2, MAX_DNS_PACKET_SIZE);
00327 }
00328
00329
00330 } while ( buf_len < resp_len && resp_len <= MAX_DNS_PACKET_SIZE );
00331
00332 *buf = buffer;
00333 *resp_length = resp_len;
00334
00335 return NT_STATUS_OK;
00336 }
00337
00338
00339
00340
00341
00342 static NTSTATUS ads_dns_lookup_srv( TALLOC_CTX *ctx, const char *name, struct dns_rr_srv **dclist, int *numdcs )
00343 {
00344 uint8 *buffer = NULL;
00345 int resp_len = 0;
00346 struct dns_rr_srv *dcs = NULL;
00347 int query_count, answer_count, auth_count, additional_count;
00348 uint8 *p = buffer;
00349 int rrnum;
00350 int idx = 0;
00351 NTSTATUS status;
00352
00353 if ( !ctx || !name || !dclist ) {
00354 return NT_STATUS_INVALID_PARAMETER;
00355 }
00356
00357
00358
00359
00360 status = dns_send_req( ctx, name, T_SRV, &buffer, &resp_len );
00361 if ( !NT_STATUS_IS_OK(status) ) {
00362 DEBUG(3,("ads_dns_lookup_srv: Failed to send DNS query (%s)\n",
00363 nt_errstr(status)));
00364 return status;
00365 }
00366 p = buffer;
00367
00368
00369
00370
00371
00372
00373
00374 query_count = RSVAL( p, 4 );
00375 answer_count = RSVAL( p, 6 );
00376 auth_count = RSVAL( p, 8 );
00377 additional_count = RSVAL( p, 10 );
00378
00379 DEBUG(4,("ads_dns_lookup_srv: %d records returned in the answer section.\n",
00380 answer_count));
00381
00382 if (answer_count) {
00383 if ( (dcs = TALLOC_ZERO_ARRAY(ctx, struct dns_rr_srv, answer_count)) == NULL ) {
00384 DEBUG(0,("ads_dns_lookup_srv: talloc() failure for %d char*'s\n",
00385 answer_count));
00386 return NT_STATUS_NO_MEMORY;
00387 }
00388 } else {
00389 dcs = NULL;
00390 }
00391
00392
00393
00394 p += NS_HFIXEDSZ;
00395
00396
00397
00398 for ( rrnum=0; rrnum<query_count; rrnum++ ) {
00399 struct dns_query q;
00400
00401 if (!ads_dns_parse_query(ctx, buffer,
00402 buffer+resp_len, &p, &q)) {
00403 DEBUG(1,("ads_dns_lookup_srv: "
00404 "Failed to parse query record [%d]!\n", rrnum));
00405 return NT_STATUS_UNSUCCESSFUL;
00406 }
00407 }
00408
00409
00410
00411 for ( rrnum=0; rrnum<answer_count; rrnum++ ) {
00412 if (!ads_dns_parse_rr_srv(ctx, buffer, buffer+resp_len,
00413 &p, &dcs[rrnum])) {
00414 DEBUG(1,("ads_dns_lookup_srv: "
00415 "Failed to parse answer recordi [%d]!\n", rrnum));
00416 return NT_STATUS_UNSUCCESSFUL;
00417 }
00418 }
00419 idx = rrnum;
00420
00421
00422
00423
00424 for ( rrnum=0; rrnum<auth_count; rrnum++ ) {
00425 struct dns_rr rr;
00426
00427 if (!ads_dns_parse_rr( ctx, buffer,
00428 buffer+resp_len, &p, &rr)) {
00429 DEBUG(1,("ads_dns_lookup_srv: "
00430 "Failed to parse authority record! [%d]\n", rrnum));
00431 return NT_STATUS_UNSUCCESSFUL;
00432 }
00433 }
00434
00435
00436
00437 for ( rrnum=0; rrnum<additional_count; rrnum++ ) {
00438 struct dns_rr rr;
00439 int i;
00440
00441 if (!ads_dns_parse_rr(ctx, buffer, buffer+resp_len,
00442 &p, &rr)) {
00443 DEBUG(1,("ads_dns_lookup_srv: Failed "
00444 "to parse additional records section! [%d]\n", rrnum));
00445 return NT_STATUS_UNSUCCESSFUL;
00446 }
00447
00448
00449
00450
00451
00452
00453
00454 if ( (rr.type != T_A) || (rr.rdatalen != 4) )
00455 continue;
00456
00457 for ( i=0; i<idx; i++ ) {
00458 if ( strcmp( rr.hostname, dcs[i].hostname ) == 0 ) {
00459 int num_ips = dcs[i].num_ips;
00460 uint8 *buf;
00461 struct in_addr *tmp_ips;
00462
00463
00464
00465 if ( dcs[i].num_ips == 0 ) {
00466 if ( (dcs[i].ips = TALLOC_ARRAY( dcs,
00467 struct in_addr, 1 )) == NULL )
00468 {
00469 return NT_STATUS_NO_MEMORY;
00470 }
00471 } else {
00472 if ( (tmp_ips = TALLOC_REALLOC_ARRAY( dcs, dcs[i].ips,
00473 struct in_addr, dcs[i].num_ips+1)) == NULL )
00474 {
00475 return NT_STATUS_NO_MEMORY;
00476 }
00477
00478 dcs[i].ips = tmp_ips;
00479 }
00480 dcs[i].num_ips++;
00481
00482
00483
00484 buf = (uint8*)&dcs[i].ips[num_ips].s_addr;
00485 memcpy( buf, rr.rdata, 4 );
00486 }
00487 }
00488 }
00489
00490 qsort( dcs, idx, sizeof(struct dns_rr_srv), QSORT_CAST dnssrvcmp );
00491
00492 *dclist = dcs;
00493 *numdcs = idx;
00494
00495 return NT_STATUS_OK;
00496 }
00497
00498
00499
00500
00501
00502 NTSTATUS ads_dns_lookup_ns( TALLOC_CTX *ctx, const char *dnsdomain, struct dns_rr_ns **nslist, int *numns )
00503 {
00504 uint8 *buffer = NULL;
00505 int resp_len = 0;
00506 struct dns_rr_ns *nsarray = NULL;
00507 int query_count, answer_count, auth_count, additional_count;
00508 uint8 *p;
00509 int rrnum;
00510 int idx = 0;
00511 NTSTATUS status;
00512
00513 if ( !ctx || !dnsdomain || !nslist ) {
00514 return NT_STATUS_INVALID_PARAMETER;
00515 }
00516
00517
00518
00519
00520 status = dns_send_req( ctx, dnsdomain, T_NS, &buffer, &resp_len );
00521 if ( !NT_STATUS_IS_OK(status) ) {
00522 DEBUG(3,("ads_dns_lookup_ns: Failed to send DNS query (%s)\n",
00523 nt_errstr(status)));
00524 return status;
00525 }
00526 p = buffer;
00527
00528
00529
00530
00531
00532
00533
00534 query_count = RSVAL( p, 4 );
00535 answer_count = RSVAL( p, 6 );
00536 auth_count = RSVAL( p, 8 );
00537 additional_count = RSVAL( p, 10 );
00538
00539 DEBUG(4,("ads_dns_lookup_ns: %d records returned in the answer section.\n",
00540 answer_count));
00541
00542 if (answer_count) {
00543 if ( (nsarray = TALLOC_ARRAY(ctx, struct dns_rr_ns, answer_count)) == NULL ) {
00544 DEBUG(0,("ads_dns_lookup_ns: talloc() failure for %d char*'s\n",
00545 answer_count));
00546 return NT_STATUS_NO_MEMORY;
00547 }
00548 } else {
00549 nsarray = NULL;
00550 }
00551
00552
00553
00554 p += NS_HFIXEDSZ;
00555
00556
00557
00558 for ( rrnum=0; rrnum<query_count; rrnum++ ) {
00559 struct dns_query q;
00560
00561 if ( !ads_dns_parse_query( ctx, buffer, buffer+resp_len, &p, &q ) ) {
00562 DEBUG(1,("ads_dns_lookup_ns: Failed to parse query record!\n"));
00563 return NT_STATUS_UNSUCCESSFUL;
00564 }
00565 }
00566
00567
00568
00569 for ( rrnum=0; rrnum<answer_count; rrnum++ ) {
00570 if ( !ads_dns_parse_rr_ns( ctx, buffer, buffer+resp_len, &p, &nsarray[rrnum] ) ) {
00571 DEBUG(1,("ads_dns_lookup_ns: Failed to parse answer record!\n"));
00572 return NT_STATUS_UNSUCCESSFUL;
00573 }
00574 }
00575 idx = rrnum;
00576
00577
00578
00579
00580 for ( rrnum=0; rrnum<auth_count; rrnum++ ) {
00581 struct dns_rr rr;
00582
00583 if ( !ads_dns_parse_rr( ctx, buffer, buffer+resp_len, &p, &rr ) ) {
00584 DEBUG(1,("ads_dns_lookup_ns: Failed to parse authority record!\n"));
00585 return NT_STATUS_UNSUCCESSFUL;
00586 }
00587 }
00588
00589
00590
00591 for ( rrnum=0; rrnum<additional_count; rrnum++ ) {
00592 struct dns_rr rr;
00593 int i;
00594
00595 if ( !ads_dns_parse_rr( ctx, buffer, buffer+resp_len, &p, &rr ) ) {
00596 DEBUG(1,("ads_dns_lookup_ns: Failed to parse additional records section!\n"));
00597 return NT_STATUS_UNSUCCESSFUL;
00598 }
00599
00600
00601
00602
00603 if ( (rr.type != T_A) || (rr.rdatalen != 4) )
00604 continue;
00605
00606 for ( i=0; i<idx; i++ ) {
00607 if ( strcmp( rr.hostname, nsarray[i].hostname ) == 0 ) {
00608 uint8 *buf = (uint8*)&nsarray[i].ip.s_addr;
00609 memcpy( buf, rr.rdata, 4 );
00610 }
00611 }
00612 }
00613
00614 *nslist = nsarray;
00615 *numns = idx;
00616
00617 return NT_STATUS_OK;
00618 }
00619
00620
00621
00622
00623
00624 #define SITENAME_KEY "AD_SITENAME/DOMAIN/%s"
00625
00626 static char *sitename_key(const char *realm)
00627 {
00628 char *keystr;
00629
00630 if (asprintf(&keystr, SITENAME_KEY, strupper_static(realm)) == -1) {
00631 return NULL;
00632 }
00633
00634 return keystr;
00635 }
00636
00637
00638
00639
00640
00641
00642
00643 BOOL sitename_store(const char *realm, const char *sitename)
00644 {
00645 time_t expire;
00646 BOOL ret = False;
00647 char *key;
00648
00649 if (!gencache_init()) {
00650 return False;
00651 }
00652
00653 if (!realm || (strlen(realm) == 0)) {
00654 DEBUG(0,("sitename_store: no realm\n"));
00655 return False;
00656 }
00657
00658 key = sitename_key(realm);
00659
00660 if (!sitename || (sitename && !*sitename)) {
00661 DEBUG(5,("sitename_store: deleting empty sitename!\n"));
00662 ret = gencache_del(key);
00663 SAFE_FREE(key);
00664 return ret;
00665 }
00666
00667 expire = get_time_t_max();
00668
00669 DEBUG(10,("sitename_store: realm = [%s], sitename = [%s], expire = [%u]\n",
00670 realm, sitename, (unsigned int)expire ));
00671
00672 ret = gencache_set( key, sitename, expire );
00673 SAFE_FREE(key);
00674 return ret;
00675 }
00676
00677
00678
00679
00680
00681
00682 char *sitename_fetch(const char *realm)
00683 {
00684 char *sitename = NULL;
00685 time_t timeout;
00686 BOOL ret = False;
00687 const char *query_realm;
00688 char *key;
00689
00690 if (!gencache_init()) {
00691 return NULL;
00692 }
00693
00694 if (!realm || (strlen(realm) == 0)) {
00695 query_realm = lp_realm();
00696 } else {
00697 query_realm = realm;
00698 }
00699
00700 key = sitename_key(query_realm);
00701
00702 ret = gencache_get( key, &sitename, &timeout );
00703 SAFE_FREE(key);
00704 if ( !ret ) {
00705 DEBUG(5,("sitename_fetch: No stored sitename for %s\n",
00706 query_realm));
00707 } else {
00708 DEBUG(5,("sitename_fetch: Returning sitename for %s: \"%s\"\n",
00709 query_realm, sitename ));
00710 }
00711 return sitename;
00712 }
00713
00714
00715
00716
00717
00718 BOOL stored_sitename_changed(const char *realm, const char *sitename)
00719 {
00720 BOOL ret = False;
00721
00722 char *new_sitename;
00723
00724 if (!realm || (strlen(realm) == 0)) {
00725 DEBUG(0,("stored_sitename_changed: no realm\n"));
00726 return False;
00727 }
00728
00729 new_sitename = sitename_fetch(realm);
00730
00731 if (sitename && new_sitename && !strequal(sitename, new_sitename)) {
00732 ret = True;
00733 } else if ((sitename && !new_sitename) ||
00734 (!sitename && new_sitename)) {
00735 ret = True;
00736 }
00737 SAFE_FREE(new_sitename);
00738 return ret;
00739 }
00740
00741
00742
00743
00744
00745 NTSTATUS ads_dns_query_internal(TALLOC_CTX *ctx,
00746 const char *servicename,
00747 const char *realm,
00748 const char *sitename,
00749 struct dns_rr_srv **dclist,
00750 int *numdcs )
00751 {
00752 char *name;
00753 if (sitename) {
00754 name = talloc_asprintf(ctx, "%s._tcp.%s._sites.dc._msdcs.%s",
00755 servicename, sitename, realm );
00756 } else {
00757 name = talloc_asprintf(ctx, "%s._tcp.dc._msdcs.%s",
00758 servicename, realm );
00759 }
00760 if (!name) {
00761 return NT_STATUS_NO_MEMORY;
00762 }
00763 return ads_dns_lookup_srv( ctx, name, dclist, numdcs );
00764 }
00765
00766
00767
00768
00769
00770 NTSTATUS ads_dns_query_dcs(TALLOC_CTX *ctx,
00771 const char *realm,
00772 const char *sitename,
00773 struct dns_rr_srv **dclist,
00774 int *numdcs )
00775 {
00776 NTSTATUS status;
00777
00778 status = ads_dns_query_internal(ctx, "_ldap", realm, sitename,
00779 dclist, numdcs);
00780
00781 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
00782 NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_REFUSED)) {
00783 return status;
00784 }
00785
00786 if (sitename && !NT_STATUS_IS_OK(status)) {
00787
00788 status = ads_dns_query_internal(ctx, "_ldap", realm, NULL,
00789 dclist, numdcs);
00790 }
00791 return status;
00792 }
00793
00794
00795
00796
00797
00798
00799
00800 NTSTATUS ads_dns_query_kdcs(TALLOC_CTX *ctx,
00801 const char *realm,
00802 const char *sitename,
00803 struct dns_rr_srv **dclist,
00804 int *numdcs )
00805 {
00806 NTSTATUS status;
00807
00808 status = ads_dns_query_internal(ctx, "_kerberos", realm, sitename,
00809 dclist, numdcs);
00810
00811 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
00812 NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_REFUSED)) {
00813 return status;
00814 }
00815
00816 if (sitename && !NT_STATUS_IS_OK(status)) {
00817
00818 status = ads_dns_query_internal(ctx, "_kerberos", realm, NULL,
00819 dclist, numdcs);
00820 }
00821 return status;
00822 }