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