libads/dns.c

説明を見る。
00001 /* 
00002    Unix SMB/CIFS implementation.
00003    DNS utility library
00004    Copyright (C) Gerald (Jerry) Carter           2006.
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010    
00011    This program is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014    GNU General Public License for more details.
00015    
00016    You should have received a copy of the GNU General Public License
00017    along with this program; if not, write to the Free Software
00018    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019 */
00020 
00021 #include "includes.h"
00022 
00023 /* AIX resolv.h uses 'class' in struct ns_rr */
00024 
00025 #if defined(AIX)
00026 #  if defined(class)
00027 #    undef class
00028 #  endif
00029 #endif  /* AIX */
00030 
00031 /* resolver headers */
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      /* Bind 8/9 interface */
00042 #if !defined(C_IN)      /* AIX 5.3 already defines C_IN */
00043 #  define C_IN          ns_c_in
00044 #endif
00045 #if !defined(T_A)       /* AIX 5.3 already defines T_A */
00046 #  define T_A           ns_t_a
00047 #endif
00048 #  define T_SRV         ns_t_srv
00049 #if !defined(T_NS)      /* AIX 5.3 already defines 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        /* HFIXEDSZ */
00058 #  ifdef PACKETSZ
00059 #    define NS_PACKETSZ PACKETSZ
00060 #  else /* 512 is usually the default */
00061 #    define NS_PACKETSZ 512
00062 #  endif        /* PACKETSZ */
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         /* See RFC 1035 for details. If this fails, then return. */
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         /* check that we have space remaining */
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         /* pull the name from the answer */
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         /* check that we have space remaining */
00128 
00129         if ( PTR_DIFF(p+10, end) > 0 )
00130                 return False;
00131 
00132         /* pull some values and then skip onto the string */
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         /* sanity check the available space */
00142 
00143         if ( PTR_DIFF(p+rr->rdatalen, end ) > 0 ) {
00144                 return False;
00145 
00146         }
00147 
00148         /* save a point to the rdata for this section */
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         /* Parse the RR entry.  Coming out of the this, ptr is at the beginning 
00173            of the next record */
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         /* Parse the RR entry.  Coming out of the this, ptr is at the beginning 
00225            of the next record */
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         /* ame server hostname */
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  Sort SRV record list based on weight and priority.  See RFC 2782.
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                 /* randomize entries with an equal weight and priority */
00260                 if ( a->weight == b->weight ) 
00261                         return 0;
00262 
00263                 /* higher weights should be sorted lower */ 
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  Simple wrapper for a DNS query
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                 /* On AIX, Solaris, and possibly some older glibc systems (e.g. SLES8)
00315                    truncated replies never give back a resp_len > buflen
00316                    which ends up causing DNS resolve failures on large tcp DNS replies */
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  Simple wrapper for a DNS SRV query
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         /* Send the request.  May have to loop several times in case 
00358            of large replies */
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         /* For some insane reason, the ns_initparse() et. al. routines are only
00369            available in libresolv.a, and not the shared lib.  Who knows why....
00370            So we have to parse the DNS reply ourselves */
00371 
00372         /* Pull the answer RR's count from the header.  Use the NMB ordering macros */
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         /* now skip the header */
00393 
00394         p += NS_HFIXEDSZ;
00395 
00396         /* parse the query section */
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         /* now we are at the answer section */
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         /* Parse the authority section */
00422         /* just skip these for now */
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         /* Parse the additional records section */
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                 /* only interested in A records as a shortcut for having to come 
00449                    back later and lookup the name.  For multi-homed hosts, the 
00450                    number of additional records and exceed the number of answer 
00451                    records. */
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                                 /* allocate new memory */
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                                 /* copy the new IP address */
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  Simple wrapper for a DNS NS query
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         /* Send the request.  May have to loop several times in case 
00518            of large replies */
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         /* For some insane reason, the ns_initparse() et. al. routines are only
00529            available in libresolv.a, and not the shared lib.  Who knows why....
00530            So we have to parse the DNS reply ourselves */
00531 
00532         /* Pull the answer RR's count from the header.  Use the NMB ordering macros */
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         /* now skip the header */
00553 
00554         p += NS_HFIXEDSZ;
00555 
00556         /* parse the query section */
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         /* now we are at the answer section */
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         /* Parse the authority section */
00578         /* just skip these for now */
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         /* Parse the additional records section */
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                 /* only interested in A records as a shortcut for having to come 
00601                    back later and lookup the name */
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  Store and fetch the AD client sitename.
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  Store the AD client sitename.
00640  We store indefinately as every new CLDAP query will re-write this.
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(); /* Store indefinately. */
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  Fetch the AD client sitename.
00679  Caller must free.
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  Did the sitename change ?
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  Query with optional sitename.
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  Query for AD DC's.
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                 /* Sitename DNS query may have failed. Try without. */
00788                 status = ads_dns_query_internal(ctx, "_ldap", realm, NULL,
00789                                                 dclist, numdcs);
00790         }
00791         return status;
00792 }
00793 
00794 /********************************************************************
00795  Query for AD KDC's.
00796  Even if our underlying kerberos libraries are UDP only, this
00797  is pretty safe as it's unlikely that a KDC supports TCP and not UDP.
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                 /* Sitename DNS query may have failed. Try without. */
00818                 status = ads_dns_query_internal(ctx, "_kerberos", realm, NULL,
00819                                                 dclist, numdcs);
00820         }
00821         return status;
00822 }

Sambaに対してSat Aug 29 21:23:00 2009に生成されました。  doxygen 1.4.7