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