s3-dsgetdcname: fix reply generation (forgot to map nt1 to nt5ex).
[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
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)
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)
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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[count].port;
630                 r->hostname = dcs[count].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,
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,
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,
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)
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,
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)
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)
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,
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,
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 /********************************************************************
1123  dsgetdcname.
1124
1125  This will be the only public function here.
1126 ********************************************************************/
1127
1128 NTSTATUS dsgetdcname(TALLOC_CTX *mem_ctx,
1129                      struct messaging_context *msg_ctx,
1130                      const char *domain_name,
1131                      struct GUID *domain_guid,
1132                      const char *site_name,
1133                      uint32_t flags,
1134                      struct netr_DsRGetDCNameInfo **info)
1135 {
1136         NTSTATUS status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1137         struct netr_DsRGetDCNameInfo *myinfo = NULL;
1138         char *query_site = NULL;
1139
1140         DEBUG(10,("dsgetdcname: domain_name: %s, "
1141                   "domain_guid: %s, site_name: %s, flags: 0x%08x\n",
1142                   domain_name,
1143                   domain_guid ? GUID_string(mem_ctx, domain_guid) : "(null)",
1144                   site_name, flags));
1145
1146         *info = NULL;
1147
1148         if (!check_allowed_required_flags(flags, site_name)) {
1149                 DEBUG(0,("invalid flags specified\n"));
1150                 return NT_STATUS_INVALID_PARAMETER;
1151         }
1152
1153         if (!site_name) {
1154                 query_site = sitename_fetch(domain_name);
1155         } else {
1156                 query_site = SMB_STRDUP(site_name);
1157         }
1158
1159         if (flags & DS_FORCE_REDISCOVERY) {
1160                 goto rediscover;
1161         }
1162
1163         status = dsgetdcname_cached(mem_ctx, msg_ctx, domain_name, domain_guid,
1164                                     flags, query_site, &myinfo);
1165         if (NT_STATUS_IS_OK(status)) {
1166                 *info = myinfo;
1167                 goto done;
1168         }
1169
1170         if (flags & DS_BACKGROUND_ONLY) {
1171                 goto done;
1172         }
1173
1174  rediscover:
1175         status = dsgetdcname_rediscover(mem_ctx, msg_ctx, domain_name,
1176                                         domain_guid, flags, query_site,
1177                                         &myinfo);
1178
1179         if (NT_STATUS_IS_OK(status)) {
1180                 *info = myinfo;
1181         }
1182
1183  done:
1184         SAFE_FREE(query_site);
1185
1186         return status;
1187 }