root/source3/libsmb/dsgetdcname.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. debug_dsdcinfo_flags
  2. dsgetdcname_cache_key
  3. dsgetdcname_cache_delete
  4. dsgetdcname_cache_store
  5. store_cldap_reply
  6. dsgetdcname_cache_refresh
  7. get_cldap_reply_server_flags
  8. check_cldap_reply_required_flags
  9. dsgetdcname_cache_fetch
  10. dsgetdcname_cached
  11. check_allowed_required_flags
  12. discover_dc_netbios
  13. discover_dc_dns
  14. make_domain_controller_info
  15. map_dc_and_domain_names
  16. make_dc_info_from_cldap_reply
  17. map_ds_flags_to_nt_version
  18. process_dc_dns
  19. ev_context
  20. msg_context
  21. process_dc_netbios
  22. dsgetdcname_rediscover
  23. is_closest_site
  24. dsgetdcname

   1 /*
   2    Unix SMB/CIFS implementation.
   3 
   4    dsgetdcname
   5 
   6    Copyright (C) Gerald Carter 2006
   7    Copyright (C) Guenther Deschner 2007-2008
   8 
   9    This program is free software; you can redistribute it and/or modify
  10    it under the terms of the GNU General Public License as published by
  11    the Free Software Foundation; either version 3 of the License, or
  12    (at your option) any later version.
  13 
  14    This program is distributed in the hope that it will be useful,
  15    but WITHOUT ANY WARRANTY; without even the implied warranty of
  16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17    GNU General Public License for more details.
  18 
  19    You should have received a copy of the GNU General Public License
  20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  21 */
  22 
  23 #include "includes.h"
  24 
  25 #define DSGETDCNAME_FMT "DSGETDCNAME/DOMAIN/%s"
  26 /* 15 minutes */
  27 #define DSGETDCNAME_CACHE_TTL   60*15
  28 
  29 struct ip_service_name {
  30         struct sockaddr_storage ss;
  31         unsigned port;
  32         const char *hostname;
  33 };
  34 
  35 static NTSTATUS make_dc_info_from_cldap_reply(TALLOC_CTX *mem_ctx,
  36                                               uint32_t flags,
  37                                               struct sockaddr_storage *ss,
  38                                               struct NETLOGON_SAM_LOGON_RESPONSE_EX *r,
  39                                               struct netr_DsRGetDCNameInfo **info);
  40 
  41 /****************************************************************
  42 ****************************************************************/
  43 
  44 void debug_dsdcinfo_flags(int lvl, uint32_t flags)
     /* [<][>][^][v][top][bottom][index][help] */
  45 {
  46         DEBUG(lvl,("debug_dsdcinfo_flags: 0x%08x\n\t", flags));
  47 
  48         if (flags & DS_FORCE_REDISCOVERY)
  49                 DEBUGADD(lvl,("DS_FORCE_REDISCOVERY "));
  50         if (flags & 0x000000002)
  51                 DEBUGADD(lvl,("0x00000002 "));
  52         if (flags & 0x000000004)
  53                 DEBUGADD(lvl,("0x00000004 "));
  54         if (flags & 0x000000008)
  55                 DEBUGADD(lvl,("0x00000008 "));
  56         if (flags & DS_DIRECTORY_SERVICE_REQUIRED)
  57                 DEBUGADD(lvl,("DS_DIRECTORY_SERVICE_REQUIRED "));
  58         if (flags & DS_DIRECTORY_SERVICE_PREFERRED)
  59                 DEBUGADD(lvl,("DS_DIRECTORY_SERVICE_PREFERRED "));
  60         if (flags & DS_GC_SERVER_REQUIRED)
  61                 DEBUGADD(lvl,("DS_GC_SERVER_REQUIRED "));
  62         if (flags & DS_PDC_REQUIRED)
  63                 DEBUGADD(lvl,("DS_PDC_REQUIRED "));
  64         if (flags & DS_BACKGROUND_ONLY)
  65                 DEBUGADD(lvl,("DS_BACKGROUND_ONLY "));
  66         if (flags & DS_IP_REQUIRED)
  67                 DEBUGADD(lvl,("DS_IP_REQUIRED "));
  68         if (flags & DS_KDC_REQUIRED)
  69                 DEBUGADD(lvl,("DS_KDC_REQUIRED "));
  70         if (flags & DS_TIMESERV_REQUIRED)
  71                 DEBUGADD(lvl,("DS_TIMESERV_REQUIRED "));
  72         if (flags & DS_WRITABLE_REQUIRED)
  73                 DEBUGADD(lvl,("DS_WRITABLE_REQUIRED "));
  74         if (flags & DS_GOOD_TIMESERV_PREFERRED)
  75                 DEBUGADD(lvl,("DS_GOOD_TIMESERV_PREFERRED "));
  76         if (flags & DS_AVOID_SELF)
  77                 DEBUGADD(lvl,("DS_AVOID_SELF "));
  78         if (flags & DS_ONLY_LDAP_NEEDED)
  79                 DEBUGADD(lvl,("DS_ONLY_LDAP_NEEDED "));
  80         if (flags & DS_IS_FLAT_NAME)
  81                 DEBUGADD(lvl,("DS_IS_FLAT_NAME "));
  82         if (flags & DS_IS_DNS_NAME)
  83                 DEBUGADD(lvl,("DS_IS_DNS_NAME "));
  84         if (flags & 0x00040000)
  85                 DEBUGADD(lvl,("0x00040000 "));
  86         if (flags & 0x00080000)
  87                 DEBUGADD(lvl,("0x00080000 "));
  88         if (flags & 0x00100000)
  89                 DEBUGADD(lvl,("0x00100000 "));
  90         if (flags & 0x00200000)
  91                 DEBUGADD(lvl,("0x00200000 "));
  92         if (flags & 0x00400000)
  93                 DEBUGADD(lvl,("0x00400000 "));
  94         if (flags & 0x00800000)
  95                 DEBUGADD(lvl,("0x00800000 "));
  96         if (flags & 0x01000000)
  97                 DEBUGADD(lvl,("0x01000000 "));
  98         if (flags & 0x02000000)
  99                 DEBUGADD(lvl,("0x02000000 "));
 100         if (flags & 0x04000000)
 101                 DEBUGADD(lvl,("0x04000000 "));
 102         if (flags & 0x08000000)
 103                 DEBUGADD(lvl,("0x08000000 "));
 104         if (flags & 0x10000000)
 105                 DEBUGADD(lvl,("0x10000000 "));
 106         if (flags & 0x20000000)
 107                 DEBUGADD(lvl,("0x20000000 "));
 108         if (flags & DS_RETURN_DNS_NAME)
 109                 DEBUGADD(lvl,("DS_RETURN_DNS_NAME "));
 110         if (flags & DS_RETURN_FLAT_NAME)
 111                 DEBUGADD(lvl,("DS_RETURN_FLAT_NAME "));
 112         if (flags)
 113                 DEBUGADD(lvl,("\n"));
 114 }
 115 
 116 /****************************************************************
 117 ****************************************************************/
 118 
 119 static char *dsgetdcname_cache_key(TALLOC_CTX *mem_ctx, const char *domain)
     /* [<][>][^][v][top][bottom][index][help] */
 120 {
 121         if (!domain) {
 122                 return NULL;
 123         }
 124 
 125         return talloc_asprintf_strupper_m(mem_ctx, DSGETDCNAME_FMT, domain);
 126 }
 127 
 128 /****************************************************************
 129 ****************************************************************/
 130 
 131 static NTSTATUS dsgetdcname_cache_delete(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 132                                         const char *domain_name)
 133 {
 134         char *key;
 135 
 136         if (!gencache_init()) {
 137                 return NT_STATUS_INTERNAL_DB_ERROR;
 138         }
 139 
 140         key = dsgetdcname_cache_key(mem_ctx, domain_name);
 141         if (!key) {
 142                 return NT_STATUS_NO_MEMORY;
 143         }
 144 
 145         if (!gencache_del(key)) {
 146                 return NT_STATUS_UNSUCCESSFUL;
 147         }
 148 
 149         return NT_STATUS_OK;
 150 }
 151 
 152 /****************************************************************
 153 ****************************************************************/
 154 
 155 static NTSTATUS dsgetdcname_cache_store(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 156                                         const char *domain_name,
 157                                         const DATA_BLOB *blob)
 158 {
 159         time_t expire_time;
 160         char *key;
 161         bool ret = false;
 162 
 163         if (!gencache_init()) {
 164                 return NT_STATUS_INTERNAL_DB_ERROR;
 165         }
 166 
 167         key = dsgetdcname_cache_key(mem_ctx, domain_name);
 168         if (!key) {
 169                 return NT_STATUS_NO_MEMORY;
 170         }
 171 
 172         expire_time = time(NULL) + DSGETDCNAME_CACHE_TTL;
 173 
 174         if (gencache_lock_entry(key) != 0) {
 175                 return NT_STATUS_LOCK_NOT_GRANTED;
 176         }
 177 
 178         ret = gencache_set_data_blob(key, blob, expire_time);
 179 
 180         gencache_unlock_entry(key);
 181 
 182         return ret ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
 183 }
 184 
 185 /****************************************************************
 186 ****************************************************************/
 187 
 188 static NTSTATUS store_cldap_reply(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 189                                   uint32_t flags,
 190                                   struct sockaddr_storage *ss,
 191                                   uint32_t nt_version,
 192                                   struct NETLOGON_SAM_LOGON_RESPONSE_EX *r)
 193 {
 194         DATA_BLOB blob;
 195         enum ndr_err_code ndr_err;
 196         NTSTATUS status;
 197         char addr[INET6_ADDRSTRLEN];
 198 
 199        print_sockaddr(addr, sizeof(addr), ss);
 200 
 201         /* FIXME */
 202         r->sockaddr_size = 0x10; /* the w32 winsock addr size */
 203         r->sockaddr.sockaddr_family = 2; /* AF_INET */
 204         r->sockaddr.pdc_ip = talloc_strdup(mem_ctx, addr);
 205 
 206         ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, r,
 207                        (ndr_push_flags_fn_t)ndr_push_NETLOGON_SAM_LOGON_RESPONSE_EX);
 208         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 209                 return ndr_map_error2ntstatus(ndr_err);
 210         }
 211 
 212         if (r->domain) {
 213                 status = dsgetdcname_cache_store(mem_ctx, r->domain, &blob);
 214                 if (!NT_STATUS_IS_OK(status)) {
 215                         goto done;
 216                 }
 217                 if (r->client_site) {
 218                         sitename_store(r->domain, r->client_site);
 219                 }
 220         }
 221         if (r->dns_domain) {
 222                 status = dsgetdcname_cache_store(mem_ctx, r->dns_domain, &blob);
 223                 if (!NT_STATUS_IS_OK(status)) {
 224                         goto done;
 225                 }
 226                 if (r->client_site) {
 227                         sitename_store(r->dns_domain, r->client_site);
 228                 }
 229         }
 230 
 231         status = NT_STATUS_OK;
 232 
 233  done:
 234         data_blob_free(&blob);
 235 
 236         return status;
 237 }
 238 
 239 /****************************************************************
 240 ****************************************************************/
 241 
 242 static NTSTATUS dsgetdcname_cache_refresh(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 243                                           struct messaging_context *msg_ctx,
 244                                           const char *domain_name,
 245                                           struct GUID *domain_guid,
 246                                           uint32_t flags,
 247                                           const char *site_name,
 248                                           struct netr_DsRGetDCNameInfo *info)
 249 {
 250         struct netr_DsRGetDCNameInfo *dc_info;
 251 
 252         return dsgetdcname(mem_ctx,
 253                            msg_ctx,
 254                            domain_name,
 255                            domain_guid,
 256                            site_name,
 257                            flags | DS_FORCE_REDISCOVERY,
 258                            &dc_info);
 259 }
 260 
 261 /****************************************************************
 262 ****************************************************************/
 263 
 264 static uint32_t get_cldap_reply_server_flags(struct netlogon_samlogon_response *r,
     /* [<][>][^][v][top][bottom][index][help] */
 265                                              uint32_t nt_version)
 266 {
 267         switch (nt_version & 0x0000001f) {
 268                 case 0:
 269                 case 1:
 270                 case 16:
 271                 case 17:
 272                         return 0;
 273                 case 2:
 274                 case 3:
 275                 case 18:
 276                 case 19:
 277                         return r->data.nt5.server_type;
 278                 case 4:
 279                 case 5:
 280                 case 6:
 281                 case 7:
 282                         return r->data.nt5_ex.server_type;
 283                 case 8:
 284                 case 9:
 285                 case 10:
 286                 case 11:
 287                 case 12:
 288                 case 13:
 289                 case 14:
 290                 case 15:
 291                         return r->data.nt5_ex.server_type;
 292                 case 20:
 293                 case 21:
 294                 case 22:
 295                 case 23:
 296                 case 24:
 297                 case 25:
 298                 case 26:
 299                 case 27:
 300                 case 28:
 301                         return r->data.nt5_ex.server_type;
 302                 case 29:
 303                 case 30:
 304                 case 31:
 305                         return r->data.nt5_ex.server_type;
 306                 default:
 307                         return 0;
 308         }
 309 }
 310 
 311 /****************************************************************
 312 ****************************************************************/
 313 
 314 #define RETURN_ON_FALSE(x) if (!(x)) return false;
 315 
 316 static bool check_cldap_reply_required_flags(uint32_t ret_flags,
     /* [<][>][^][v][top][bottom][index][help] */
 317                                              uint32_t req_flags)
 318 {
 319         if (ret_flags == 0) {
 320                 return true;
 321         }
 322 
 323         if (req_flags & DS_PDC_REQUIRED)
 324                 RETURN_ON_FALSE(ret_flags & NBT_SERVER_PDC);
 325 
 326         if (req_flags & DS_GC_SERVER_REQUIRED)
 327                 RETURN_ON_FALSE(ret_flags & NBT_SERVER_GC);
 328 
 329         if (req_flags & DS_ONLY_LDAP_NEEDED)
 330                 RETURN_ON_FALSE(ret_flags & NBT_SERVER_LDAP);
 331 
 332         if ((req_flags & DS_DIRECTORY_SERVICE_REQUIRED) ||
 333             (req_flags & DS_DIRECTORY_SERVICE_PREFERRED))
 334                 RETURN_ON_FALSE(ret_flags & NBT_SERVER_DS);
 335 
 336         if (req_flags & DS_KDC_REQUIRED)
 337                 RETURN_ON_FALSE(ret_flags & NBT_SERVER_KDC);
 338 
 339         if (req_flags & DS_TIMESERV_REQUIRED)
 340                 RETURN_ON_FALSE(ret_flags & NBT_SERVER_TIMESERV);
 341 
 342         if (req_flags & DS_WRITABLE_REQUIRED)
 343                 RETURN_ON_FALSE(ret_flags & NBT_SERVER_WRITABLE);
 344 
 345         return true;
 346 }
 347 
 348 /****************************************************************
 349 ****************************************************************/
 350 
 351 static NTSTATUS dsgetdcname_cache_fetch(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 352                                         const char *domain_name,
 353                                         struct GUID *domain_guid,
 354                                         uint32_t flags,
 355                                         const char *site_name,
 356                                         struct netr_DsRGetDCNameInfo **info_p,
 357                                         bool *expired)
 358 {
 359         char *key;
 360         DATA_BLOB blob;
 361         enum ndr_err_code ndr_err;
 362         struct netr_DsRGetDCNameInfo *info;
 363         struct NETLOGON_SAM_LOGON_RESPONSE_EX r;
 364         NTSTATUS status;
 365 
 366         if (!gencache_init()) {
 367                 return NT_STATUS_INTERNAL_DB_ERROR;
 368         }
 369 
 370         key = dsgetdcname_cache_key(mem_ctx, domain_name);
 371         if (!key) {
 372                 return NT_STATUS_NO_MEMORY;
 373         }
 374 
 375         if (!gencache_get_data_blob(key, &blob, expired)) {
 376                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
 377         }
 378 
 379         info = TALLOC_ZERO_P(mem_ctx, struct netr_DsRGetDCNameInfo);
 380         if (!info) {
 381                 return NT_STATUS_NO_MEMORY;
 382         }
 383 
 384         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, NULL, &r,
 385                       (ndr_pull_flags_fn_t)ndr_pull_NETLOGON_SAM_LOGON_RESPONSE_EX);
 386 
 387         data_blob_free(&blob);
 388         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
 389                 dsgetdcname_cache_delete(mem_ctx, domain_name);
 390                 return ndr_map_error2ntstatus(ndr_err);
 391         }
 392 
 393         status = make_dc_info_from_cldap_reply(mem_ctx, flags, NULL,
 394                                                &r, &info);
 395         if (!NT_STATUS_IS_OK(status)) {
 396                 return status;
 397         }
 398 
 399         if (DEBUGLEVEL >= 10) {
 400                 NDR_PRINT_DEBUG(netr_DsRGetDCNameInfo, info);
 401         }
 402 
 403         /* check flags */
 404         if (!check_cldap_reply_required_flags(info->dc_flags, flags)) {
 405                 DEBUG(10,("invalid flags\n"));
 406                 return NT_STATUS_INVALID_PARAMETER;
 407         }
 408 
 409         if ((flags & DS_IP_REQUIRED) &&
 410             (info->dc_address_type != DS_ADDRESS_TYPE_INET)) {
 411                 return NT_STATUS_INVALID_PARAMETER_MIX;
 412         }
 413 
 414         *info_p = info;
 415 
 416         return NT_STATUS_OK;
 417 }
 418 
 419 /****************************************************************
 420 ****************************************************************/
 421 
 422 static NTSTATUS dsgetdcname_cached(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 423                                    struct messaging_context *msg_ctx,
 424                                    const char *domain_name,
 425                                    struct GUID *domain_guid,
 426                                    uint32_t flags,
 427                                    const char *site_name,
 428                                    struct netr_DsRGetDCNameInfo **info)
 429 {
 430         NTSTATUS status;
 431         bool expired = false;
 432 
 433         status = dsgetdcname_cache_fetch(mem_ctx, domain_name, domain_guid,
 434                                          flags, site_name, info, &expired);
 435         if (!NT_STATUS_IS_OK(status)) {
 436                 DEBUG(10,("dsgetdcname_cached: cache fetch failed with: %s\n",
 437                         nt_errstr(status)));
 438                 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
 439         }
 440 
 441         if (flags & DS_BACKGROUND_ONLY) {
 442                 return status;
 443         }
 444 
 445         if (expired) {
 446                 status = dsgetdcname_cache_refresh(mem_ctx, msg_ctx,
 447                                                    domain_name,
 448                                                    domain_guid, flags,
 449                                                    site_name, *info);
 450                 if (!NT_STATUS_IS_OK(status)) {
 451                         return status;
 452                 }
 453         }
 454 
 455         return status;
 456 }
 457 
 458 /****************************************************************
 459 ****************************************************************/
 460 
 461 static bool check_allowed_required_flags(uint32_t flags,
     /* [<][>][^][v][top][bottom][index][help] */
 462                                          const char *site_name)
 463 {
 464         uint32_t return_type = flags & (DS_RETURN_FLAT_NAME|DS_RETURN_DNS_NAME);
 465         uint32_t offered_type = flags & (DS_IS_FLAT_NAME|DS_IS_DNS_NAME);
 466         uint32_t query_type = flags & (DS_BACKGROUND_ONLY|DS_FORCE_REDISCOVERY);
 467 
 468         /* FIXME: check for DSGETDC_VALID_FLAGS and check for excluse bits
 469          * (DS_PDC_REQUIRED, DS_KDC_REQUIRED, DS_GC_SERVER_REQUIRED) */
 470 
 471         debug_dsdcinfo_flags(10, flags);
 472 
 473         if ((flags & DS_TRY_NEXTCLOSEST_SITE) && site_name) {
 474                 return false;
 475         }
 476 
 477         if (return_type == (DS_RETURN_FLAT_NAME|DS_RETURN_DNS_NAME)) {
 478                 return false;
 479         }
 480 
 481         if (offered_type == (DS_IS_DNS_NAME|DS_IS_FLAT_NAME)) {
 482                 return false;
 483         }
 484 
 485         if (query_type == (DS_BACKGROUND_ONLY|DS_FORCE_REDISCOVERY)) {
 486                 return false;
 487         }
 488 
 489 #if 0
 490         if ((flags & DS_RETURN_DNS_NAME) && (!(flags & DS_IP_REQUIRED))) {
 491                 printf("gd: here5 \n");
 492                 return false;
 493         }
 494 #endif
 495         return true;
 496 }
 497 
 498 /****************************************************************
 499 ****************************************************************/
 500 
 501 static NTSTATUS discover_dc_netbios(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 502                                     const char *domain_name,
 503                                     uint32_t flags,
 504                                     struct ip_service_name **returned_dclist,
 505                                     int *returned_count)
 506 {
 507         NTSTATUS status;
 508         enum nbt_name_type name_type = NBT_NAME_LOGON;
 509         struct ip_service *iplist;
 510         int i;
 511         struct ip_service_name *dclist = NULL;
 512         int count;
 513 
 514         *returned_dclist = NULL;
 515         *returned_count = 0;
 516 
 517         if (lp_disable_netbios()) {
 518                 return NT_STATUS_NOT_SUPPORTED;
 519         }
 520 
 521         if (flags & DS_PDC_REQUIRED) {
 522                 name_type = NBT_NAME_PDC;
 523         }
 524 
 525         status = internal_resolve_name(domain_name, name_type, NULL,
 526                                        &iplist, &count,
 527                                        "lmhosts wins bcast");
 528         if (!NT_STATUS_IS_OK(status)) {
 529                 DEBUG(10,("discover_dc_netbios: failed to find DC\n"));
 530                 return status;
 531         }
 532 
 533         dclist = TALLOC_ZERO_ARRAY(mem_ctx, struct ip_service_name, count);
 534         if (!dclist) {
 535                 return NT_STATUS_NO_MEMORY;
 536         }
 537 
 538         for (i=0; i<count; i++) {
 539 
 540                 char addr[INET6_ADDRSTRLEN];
 541                 struct ip_service_name *r = &dclist[i];
 542 
 543                 print_sockaddr(addr, sizeof(addr),
 544                                &iplist[i].ss);
 545 
 546                 r->ss   = iplist[i].ss;
 547                 r->port = iplist[i].port;
 548                 r->hostname = talloc_strdup(mem_ctx, addr);
 549                 if (!r->hostname) {
 550                         return NT_STATUS_NO_MEMORY;
 551                 }
 552 
 553         }
 554 
 555         *returned_dclist = dclist;
 556         *returned_count = count;
 557 
 558         return NT_STATUS_OK;
 559 }
 560 
 561 /****************************************************************
 562 ****************************************************************/
 563 
 564 static NTSTATUS discover_dc_dns(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 565                                 const char *domain_name,
 566                                 struct GUID *domain_guid,
 567                                 uint32_t flags,
 568                                 const char *site_name,
 569                                 struct ip_service_name **returned_dclist,
 570                                 int *return_count)
 571 {
 572         int i, j;
 573         NTSTATUS status;
 574         struct dns_rr_srv *dcs = NULL;
 575         int numdcs = 0;
 576         int numaddrs = 0;
 577         struct ip_service_name *dclist = NULL;
 578         int count = 0;
 579 
 580         if (flags & DS_PDC_REQUIRED) {
 581                 status = ads_dns_query_pdc(mem_ctx, domain_name,
 582                                            &dcs, &numdcs);
 583         } else if (flags & DS_GC_SERVER_REQUIRED) {
 584                 status = ads_dns_query_gcs(mem_ctx, domain_name, site_name,
 585                                            &dcs, &numdcs);
 586         } else if (flags & DS_KDC_REQUIRED) {
 587                 status = ads_dns_query_kdcs(mem_ctx, domain_name, site_name,
 588                                             &dcs, &numdcs);
 589         } else if (flags & DS_DIRECTORY_SERVICE_REQUIRED) {
 590                 status = ads_dns_query_dcs(mem_ctx, domain_name, site_name,
 591                                            &dcs, &numdcs);
 592         } else if (domain_guid) {
 593                 status = ads_dns_query_dcs_guid(mem_ctx, domain_name,
 594                                                 domain_guid, &dcs, &numdcs);
 595         } else {
 596                 status = ads_dns_query_dcs(mem_ctx, domain_name, site_name,
 597                                            &dcs, &numdcs);
 598         }
 599 
 600         if (!NT_STATUS_IS_OK(status)) {
 601                 return status;
 602         }
 603 
 604         if (numdcs == 0) {
 605                 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
 606         }
 607 
 608         for (i=0;i<numdcs;i++) {
 609                 numaddrs += MAX(dcs[i].num_ips,1);
 610         }
 611 
 612         dclist = TALLOC_ZERO_ARRAY(mem_ctx,
 613                                    struct ip_service_name,
 614                                    numaddrs);
 615         if (!dclist) {
 616                 return NT_STATUS_NO_MEMORY;
 617         }
 618 
 619         /* now unroll the list of IP addresses */
 620 
 621         *return_count = 0;
 622         i = 0;
 623         j = 0;
 624 
 625         while ((i < numdcs) && (count < numaddrs)) {
 626 
 627                 struct ip_service_name *r = &dclist[count];
 628 
 629                 r->port = dcs[i].port;
 630                 r->hostname = dcs[i].hostname;
 631 
 632                 /* If we don't have an IP list for a name, lookup it up */
 633 
 634                 if (!dcs[i].ss_s) {
 635                         interpret_string_addr(&r->ss, dcs[i].hostname, 0);
 636                         i++;
 637                         j = 0;
 638                 } else {
 639                         /* use the IP addresses from the SRV sresponse */
 640 
 641                         if (j >= dcs[i].num_ips) {
 642                                 i++;
 643                                 j = 0;
 644                                 continue;
 645                         }
 646 
 647                         r->ss = dcs[i].ss_s[j];
 648                         j++;
 649                 }
 650 
 651                 /* make sure it is a valid IP.  I considered checking the
 652                  * negative connection cache, but this is the wrong place for
 653                  * it.  Maybe only as a hac.  After think about it, if all of
 654                  * the IP addresses retuend from DNS are dead, what hope does a
 655                  * netbios name lookup have?  The standard reason for falling
 656                  * back to netbios lookups is that our DNS server doesn't know
 657                  * anything about the DC's   -- jerry */
 658 
 659                 if (!is_zero_addr((struct sockaddr *)&r->ss)) {
 660                         count++;
 661                         continue;
 662                 }
 663         }
 664 
 665         *returned_dclist = dclist;
 666         *return_count = count;
 667 
 668         if (count > 0) {
 669                 return NT_STATUS_OK;
 670         }
 671 
 672         return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
 673 }
 674 
 675 /****************************************************************
 676 ****************************************************************/
 677 
 678 static NTSTATUS make_domain_controller_info(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 679                                             const char *dc_unc,
 680                                             const char *dc_address,
 681                                             uint32_t dc_address_type,
 682                                             const struct GUID *domain_guid,
 683                                             const char *domain_name,
 684                                             const char *forest_name,
 685                                             uint32_t flags,
 686                                             const char *dc_site_name,
 687                                             const char *client_site_name,
 688                                             struct netr_DsRGetDCNameInfo **info_out)
 689 {
 690         struct netr_DsRGetDCNameInfo *info;
 691 
 692         info = TALLOC_ZERO_P(mem_ctx, struct netr_DsRGetDCNameInfo);
 693         NT_STATUS_HAVE_NO_MEMORY(info);
 694 
 695         if (dc_unc) {
 696                 info->dc_unc = talloc_strdup(mem_ctx, dc_unc);
 697                 NT_STATUS_HAVE_NO_MEMORY(info->dc_unc);
 698         }
 699 
 700         if (dc_address) {
 701                 if (!(dc_address[0] == '\\' && dc_address[1] == '\\')) {
 702                         info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s",
 703                                                            dc_address);
 704                 } else {
 705                         info->dc_address = talloc_strdup(mem_ctx, dc_address);
 706                 }
 707                 NT_STATUS_HAVE_NO_MEMORY(info->dc_address);
 708         }
 709 
 710         info->dc_address_type = dc_address_type;
 711 
 712         if (domain_guid) {
 713                 info->domain_guid = *domain_guid;
 714         }
 715 
 716         if (domain_name) {
 717                 info->domain_name = talloc_strdup(mem_ctx, domain_name);
 718                 NT_STATUS_HAVE_NO_MEMORY(info->domain_name);
 719         }
 720 
 721         if (forest_name && *forest_name) {
 722                 info->forest_name = talloc_strdup(mem_ctx, forest_name);
 723                 NT_STATUS_HAVE_NO_MEMORY(info->forest_name);
 724                 flags |= DS_DNS_FOREST;
 725         }
 726 
 727         info->dc_flags = flags;
 728 
 729         if (dc_site_name) {
 730                 info->dc_site_name = talloc_strdup(mem_ctx, dc_site_name);
 731                 NT_STATUS_HAVE_NO_MEMORY(info->dc_site_name);
 732         }
 733 
 734         if (client_site_name) {
 735                 info->client_site_name = talloc_strdup(mem_ctx,
 736                                                        client_site_name);
 737                 NT_STATUS_HAVE_NO_MEMORY(info->client_site_name);
 738         }
 739 
 740         *info_out = info;
 741 
 742         return NT_STATUS_OK;
 743 }
 744 
 745 /****************************************************************
 746 ****************************************************************/
 747 
 748 static void map_dc_and_domain_names(uint32_t flags,
     /* [<][>][^][v][top][bottom][index][help] */
 749                                     const char *dc_name,
 750                                     const char *domain_name,
 751                                     const char *dns_dc_name,
 752                                     const char *dns_domain_name,
 753                                     uint32_t *dc_flags,
 754                                     const char **hostname_p,
 755                                     const char **domain_p)
 756 {
 757         switch (flags & 0xf0000000) {
 758                 case DS_RETURN_FLAT_NAME:
 759                         if (dc_name && domain_name &&
 760                             *dc_name && *domain_name) {
 761                                 *hostname_p = dc_name;
 762                                 *domain_p = domain_name;
 763                                 break;
 764                         }
 765                 case DS_RETURN_DNS_NAME:
 766                 default:
 767                         if (dns_dc_name && dns_domain_name &&
 768                             *dns_dc_name && *dns_domain_name) {
 769                                 *hostname_p = dns_dc_name;
 770                                 *domain_p = dns_domain_name;
 771                                 *dc_flags |= DS_DNS_DOMAIN | DS_DNS_CONTROLLER;
 772                                 break;
 773                         }
 774                         if (dc_name && domain_name &&
 775                             *dc_name && *domain_name) {
 776                                 *hostname_p = dc_name;
 777                                 *domain_p = domain_name;
 778                                 break;
 779                         }
 780         }
 781 }
 782 
 783 /****************************************************************
 784 ****************************************************************/
 785 
 786 static NTSTATUS make_dc_info_from_cldap_reply(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 787                                               uint32_t flags,
 788                                               struct sockaddr_storage *ss,
 789                                               struct NETLOGON_SAM_LOGON_RESPONSE_EX *r,
 790                                               struct netr_DsRGetDCNameInfo **info)
 791 {
 792         const char *dc_hostname = NULL;
 793         const char *dc_domain_name = NULL;
 794         const char *dc_address = NULL;
 795         const char *dc_forest = NULL;
 796         uint32_t dc_address_type = 0;
 797         uint32_t dc_flags = 0;
 798         struct GUID *dc_domain_guid = NULL;
 799         const char *dc_server_site = NULL;
 800         const char *dc_client_site = NULL;
 801 
 802         char addr[INET6_ADDRSTRLEN];
 803 
 804         if (ss) {
 805                 print_sockaddr(addr, sizeof(addr), ss);
 806                 dc_address = addr;
 807                 dc_address_type = DS_ADDRESS_TYPE_INET;
 808         }
 809 
 810         if (!ss && r->sockaddr.pdc_ip) {
 811                 dc_address      = r->sockaddr.pdc_ip;
 812                 dc_address_type = DS_ADDRESS_TYPE_INET;
 813         } else {
 814                 dc_address      = r->pdc_name;
 815                 dc_address_type = DS_ADDRESS_TYPE_NETBIOS;
 816         }
 817 
 818         map_dc_and_domain_names(flags,
 819                                 r->pdc_name,
 820                                 r->domain,
 821                                 r->pdc_dns_name,
 822                                 r->dns_domain,
 823                                 &dc_flags,
 824                                 &dc_hostname,
 825                                 &dc_domain_name);
 826 
 827         dc_flags        |= r->server_type;
 828         dc_forest       = r->forest;
 829         dc_domain_guid  = &r->domain_uuid;
 830         dc_server_site  = r->server_site;
 831         dc_client_site  = r->client_site;
 832 
 833         return make_domain_controller_info(mem_ctx,
 834                                            dc_hostname,
 835                                            dc_address,
 836                                            dc_address_type,
 837                                            dc_domain_guid,
 838                                            dc_domain_name,
 839                                            dc_forest,
 840                                            dc_flags,
 841                                            dc_server_site,
 842                                            dc_client_site,
 843                                            info);
 844 }
 845 
 846 /****************************************************************
 847 ****************************************************************/
 848 
 849 static uint32_t map_ds_flags_to_nt_version(uint32_t flags)
     /* [<][>][^][v][top][bottom][index][help] */
 850 {
 851         uint32_t nt_version = 0;
 852 
 853         if (flags & DS_PDC_REQUIRED) {
 854                 nt_version |= NETLOGON_NT_VERSION_PDC;
 855         }
 856 
 857         if (flags & DS_GC_SERVER_REQUIRED) {
 858                 nt_version |= NETLOGON_NT_VERSION_GC;
 859         }
 860 
 861         if (flags & DS_TRY_NEXTCLOSEST_SITE) {
 862                 nt_version |= NETLOGON_NT_VERSION_WITH_CLOSEST_SITE;
 863         }
 864 
 865         if (flags & DS_IP_REQUIRED) {
 866                 nt_version |= NETLOGON_NT_VERSION_IP;
 867         }
 868 
 869         return nt_version;
 870 }
 871 
 872 /****************************************************************
 873 ****************************************************************/
 874 
 875 static NTSTATUS process_dc_dns(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 876                                const char *domain_name,
 877                                uint32_t flags,
 878                                struct ip_service_name *dclist,
 879                                int num_dcs,
 880                                struct netr_DsRGetDCNameInfo **info)
 881 {
 882         int i = 0;
 883         bool valid_dc = false;
 884         struct netlogon_samlogon_response *r = NULL;
 885         uint32_t nt_version = NETLOGON_NT_VERSION_5 |
 886                               NETLOGON_NT_VERSION_5EX;
 887         uint32_t ret_flags = 0;
 888         NTSTATUS status;
 889 
 890         nt_version |= map_ds_flags_to_nt_version(flags);
 891 
 892         for (i=0; i<num_dcs; i++) {
 893 
 894                 DEBUG(10,("LDAP ping to %s\n", dclist[i].hostname));
 895 
 896                 if (ads_cldap_netlogon(mem_ctx, dclist[i].hostname,
 897                                         domain_name,
 898                                         nt_version,
 899                                         &r))
 900                 {
 901                         nt_version = r->ntver;
 902                         ret_flags = get_cldap_reply_server_flags(r, nt_version);
 903 
 904                         if (check_cldap_reply_required_flags(ret_flags, flags)) {
 905                                 valid_dc = true;
 906                                 break;
 907                         }
 908                 }
 909 
 910                 continue;
 911         }
 912 
 913         if (!valid_dc) {
 914                 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
 915         }
 916 
 917         status = make_dc_info_from_cldap_reply(mem_ctx, flags, &dclist[i].ss,
 918                                                &r->data.nt5_ex, info);
 919         if (NT_STATUS_IS_OK(status)) {
 920                 return store_cldap_reply(mem_ctx, flags, &dclist[i].ss,
 921                                          nt_version, &r->data.nt5_ex);
 922         }
 923 
 924         return status;
 925 }
 926 
 927 /****************************************************************
 928 ****************************************************************/
 929 
 930 static struct event_context *ev_context(void)
     /* [<][>][^][v][top][bottom][index][help] */
 931 {
 932         static struct event_context *ctx;
 933 
 934         if (!ctx && !(ctx = event_context_init(NULL))) {
 935                 smb_panic("Could not init event context");
 936         }
 937         return ctx;
 938 }
 939 
 940 /****************************************************************
 941 ****************************************************************/
 942 
 943 static struct messaging_context *msg_context(TALLOC_CTX *mem_ctx)
     /* [<][>][^][v][top][bottom][index][help] */
 944 {
 945         static struct messaging_context *ctx;
 946 
 947         if (!ctx && !(ctx = messaging_init(mem_ctx, server_id_self(),
 948                                            ev_context()))) {
 949                 smb_panic("Could not init messaging context");
 950         }
 951         return ctx;
 952 }
 953 
 954 /****************************************************************
 955 ****************************************************************/
 956 
 957 static NTSTATUS process_dc_netbios(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 958                                    struct messaging_context *msg_ctx,
 959                                    const char *domain_name,
 960                                    uint32_t flags,
 961                                    struct ip_service_name *dclist,
 962                                    int num_dcs,
 963                                    struct netr_DsRGetDCNameInfo **info)
 964 {
 965         struct sockaddr_storage ss;
 966         struct ip_service ip_list;
 967         enum nbt_name_type name_type = NBT_NAME_LOGON;
 968         NTSTATUS status;
 969         int i;
 970         const char *dc_name = NULL;
 971         fstring tmp_dc_name;
 972         struct netlogon_samlogon_response *r = NULL;
 973         bool store_cache = false;
 974         uint32_t nt_version = NETLOGON_NT_VERSION_1 |
 975                               NETLOGON_NT_VERSION_5 |
 976                               NETLOGON_NT_VERSION_5EX_WITH_IP;
 977 
 978         if (!msg_ctx) {
 979                 msg_ctx = msg_context(mem_ctx);
 980         }
 981 
 982         if (flags & DS_PDC_REQUIRED) {
 983                 name_type = NBT_NAME_PDC;
 984         }
 985 
 986         nt_version |= map_ds_flags_to_nt_version(flags);
 987 
 988         DEBUG(10,("process_dc_netbios\n"));
 989 
 990         for (i=0; i<num_dcs; i++) {
 991 
 992                 ip_list.ss = dclist[i].ss;
 993                 ip_list.port = 0;
 994 
 995                 if (!interpret_string_addr(&ss, dclist[i].hostname, AI_NUMERICHOST)) {
 996                         return NT_STATUS_UNSUCCESSFUL;
 997                 }
 998 
 999                 if (send_getdc_request(mem_ctx, msg_ctx,
1000                                        &dclist[i].ss, domain_name,
1001                                        NULL, nt_version))
1002                 {
1003                         int k;
1004                         smb_msleep(300);
1005                         for (k=0; k<5; k++) {
1006                                 if (receive_getdc_response(mem_ctx,
1007                                                            &dclist[i].ss,
1008                                                            domain_name,
1009                                                            &nt_version,
1010                                                            &dc_name,
1011                                                            &r)) {
1012                                         store_cache = true;
1013                                         namecache_store(dc_name, NBT_NAME_SERVER, 1, &ip_list);
1014                                         goto make_reply;
1015                                 }
1016                                 smb_msleep(1500);
1017                         }
1018                 }
1019 
1020                 if (name_status_find(domain_name,
1021                                      name_type,
1022                                      NBT_NAME_SERVER,
1023                                      &dclist[i].ss,
1024                                      tmp_dc_name))
1025                 {
1026                         struct NETLOGON_SAM_LOGON_RESPONSE_NT40 logon1;
1027 
1028                         r = TALLOC_ZERO_P(mem_ctx, struct netlogon_samlogon_response);
1029                         NT_STATUS_HAVE_NO_MEMORY(r);
1030 
1031                         ZERO_STRUCT(logon1);
1032 
1033                         nt_version = NETLOGON_NT_VERSION_1;
1034 
1035                         logon1.nt_version = nt_version;
1036                         logon1.server = tmp_dc_name;
1037                         logon1.domain = talloc_strdup_upper(mem_ctx, domain_name);
1038                         NT_STATUS_HAVE_NO_MEMORY(logon1.domain);
1039 
1040                         r->data.nt4 = logon1;
1041                         r->ntver = nt_version;
1042 
1043                         map_netlogon_samlogon_response(r);
1044 
1045                         namecache_store(tmp_dc_name, NBT_NAME_SERVER, 1, &ip_list);
1046 
1047                         goto make_reply;
1048                 }
1049         }
1050 
1051         return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1052 
1053  make_reply:
1054 
1055         status = make_dc_info_from_cldap_reply(mem_ctx, flags, &dclist[i].ss,
1056                                                &r->data.nt5_ex, info);
1057         if (NT_STATUS_IS_OK(status) && store_cache) {
1058                 return store_cldap_reply(mem_ctx, flags, &dclist[i].ss,
1059                                          nt_version, &r->data.nt5_ex);
1060         }
1061 
1062         return status;
1063 }
1064 
1065 /****************************************************************
1066 ****************************************************************/
1067 
1068 static NTSTATUS dsgetdcname_rediscover(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
1069                                        struct messaging_context *msg_ctx,
1070                                        const char *domain_name,
1071                                        struct GUID *domain_guid,
1072                                        uint32_t flags,
1073                                        const char *site_name,
1074                                        struct netr_DsRGetDCNameInfo **info)
1075 {
1076         NTSTATUS status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1077         struct ip_service_name *dclist = NULL;
1078         int num_dcs;
1079 
1080         DEBUG(10,("dsgetdcname_rediscover\n"));
1081 
1082         if (flags & DS_IS_FLAT_NAME) {
1083 
1084                 status = discover_dc_netbios(mem_ctx, domain_name, flags,
1085                                              &dclist, &num_dcs);
1086                 NT_STATUS_NOT_OK_RETURN(status);
1087 
1088                 return process_dc_netbios(mem_ctx, msg_ctx, domain_name, flags,
1089                                           dclist, num_dcs, info);
1090         }
1091 
1092         if (flags & DS_IS_DNS_NAME) {
1093 
1094                 status = discover_dc_dns(mem_ctx, domain_name, domain_guid,
1095                                          flags, site_name, &dclist, &num_dcs);
1096                 NT_STATUS_NOT_OK_RETURN(status);
1097 
1098                 return process_dc_dns(mem_ctx, domain_name, flags,
1099                                       dclist, num_dcs, info);
1100         }
1101 
1102         status = discover_dc_dns(mem_ctx, domain_name, domain_guid, flags,
1103                                  site_name, &dclist, &num_dcs);
1104 
1105         if (NT_STATUS_IS_OK(status) && num_dcs != 0) {
1106 
1107                 status = process_dc_dns(mem_ctx, domain_name, flags, dclist,
1108                                         num_dcs, info);
1109                 if (NT_STATUS_IS_OK(status)) {
1110                         return status;
1111                 }
1112         }
1113 
1114         status = discover_dc_netbios(mem_ctx, domain_name, flags, &dclist,
1115                                      &num_dcs);
1116         NT_STATUS_NOT_OK_RETURN(status);
1117 
1118         return process_dc_netbios(mem_ctx, msg_ctx, domain_name, flags, dclist,
1119                                   num_dcs, info);
1120 }
1121 
1122 static bool is_closest_site(struct netr_DsRGetDCNameInfo *info)
     /* [<][>][^][v][top][bottom][index][help] */
1123 {
1124         if (info->dc_flags & DS_SERVER_CLOSEST) {
1125                 return true;
1126         }
1127 
1128         if (!info->client_site_name) {
1129                 return true;
1130         }
1131 
1132         if (!info->dc_site_name) {
1133                 return false;
1134         }
1135 
1136         if (strcmp(info->client_site_name, info->dc_site_name) == 0) {
1137                 return true;
1138         }
1139 
1140         return false;
1141 }
1142 
1143 /********************************************************************
1144  dsgetdcname.
1145 
1146  This will be the only public function here.
1147 ********************************************************************/
1148 
1149 NTSTATUS dsgetdcname(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
1150                      struct messaging_context *msg_ctx,
1151                      const char *domain_name,
1152                      struct GUID *domain_guid,
1153                      const char *site_name,
1154                      uint32_t flags,
1155                      struct netr_DsRGetDCNameInfo **info)
1156 {
1157         NTSTATUS status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1158         struct netr_DsRGetDCNameInfo *myinfo = NULL;
1159         char *query_site = NULL;
1160         bool first = true;
1161         struct netr_DsRGetDCNameInfo *first_info = NULL;
1162 
1163         DEBUG(10,("dsgetdcname: domain_name: %s, "
1164                   "domain_guid: %s, site_name: %s, flags: 0x%08x\n",
1165                   domain_name,
1166                   domain_guid ? GUID_string(mem_ctx, domain_guid) : "(null)",
1167                   site_name, flags));
1168 
1169         *info = NULL;
1170 
1171         if (!check_allowed_required_flags(flags, site_name)) {
1172                 DEBUG(0,("invalid flags specified\n"));
1173                 return NT_STATUS_INVALID_PARAMETER;
1174         }
1175 
1176         if (!site_name) {
1177                 query_site = sitename_fetch(domain_name);
1178         } else {
1179                 query_site = SMB_STRDUP(site_name);
1180         }
1181 
1182         if (flags & DS_FORCE_REDISCOVERY) {
1183                 goto rediscover;
1184         }
1185 
1186         status = dsgetdcname_cached(mem_ctx, msg_ctx, domain_name, domain_guid,
1187                                     flags, query_site, &myinfo);
1188         if (NT_STATUS_IS_OK(status)) {
1189                 goto done;
1190         }
1191 
1192         if (flags & DS_BACKGROUND_ONLY) {
1193                 goto done;
1194         }
1195 
1196  rediscover:
1197         status = dsgetdcname_rediscover(mem_ctx, msg_ctx, domain_name,
1198                                         domain_guid, flags, query_site,
1199                                         &myinfo);
1200 
1201  done:
1202         SAFE_FREE(query_site);
1203 
1204         if (!NT_STATUS_IS_OK(status)) {
1205                 if (!first) {
1206                         *info = first_info;
1207                         return NT_STATUS_OK;
1208                 }
1209                 return status;
1210         }
1211 
1212         if (!first) {
1213                 TALLOC_FREE(first_info);
1214         } else if (!is_closest_site(myinfo)) {
1215                 first = false;
1216                 first_info = myinfo;
1217                 /* TODO: may use the next_closest_site here */
1218                 query_site = SMB_STRDUP(myinfo->client_site_name);
1219                 goto rediscover;
1220         }
1221 
1222         *info = myinfo;
1223         return NT_STATUS_OK;
1224 }

/* [<][>][^][v][top][bottom][index][help] */