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