2
Unix SMB/CIFS implementation.
6
Copyright (C) Gerald Carter 2006
7
Copyright (C) Guenther Deschner 2007-2008
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.
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.
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/>.
25
#define DSGETDCNAME_FMT "DSGETDCNAME/DOMAIN/%s"
27
#define DSGETDCNAME_CACHE_TTL 60*15
29
struct ip_service_name {
30
struct sockaddr_storage ss;
35
static NTSTATUS make_dc_info_from_cldap_reply(TALLOC_CTX *mem_ctx,
37
struct sockaddr_storage *ss,
38
struct NETLOGON_SAM_LOGON_RESPONSE_EX *r,
39
struct netr_DsRGetDCNameInfo **info);
41
/****************************************************************
42
****************************************************************/
44
void debug_dsdcinfo_flags(int lvl, uint32_t flags)
46
DEBUG(lvl,("debug_dsdcinfo_flags: 0x%08x\n\t", flags));
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 "));
113
DEBUGADD(lvl,("\n"));
116
/****************************************************************
117
****************************************************************/
119
static char *dsgetdcname_cache_key(TALLOC_CTX *mem_ctx, const char *domain)
125
return talloc_asprintf_strupper_m(mem_ctx, DSGETDCNAME_FMT, domain);
128
/****************************************************************
129
****************************************************************/
131
static NTSTATUS dsgetdcname_cache_delete(TALLOC_CTX *mem_ctx,
132
const char *domain_name)
136
if (!gencache_init()) {
137
return NT_STATUS_INTERNAL_DB_ERROR;
140
key = dsgetdcname_cache_key(mem_ctx, domain_name);
142
return NT_STATUS_NO_MEMORY;
145
if (!gencache_del(key)) {
146
return NT_STATUS_UNSUCCESSFUL;
152
/****************************************************************
153
****************************************************************/
155
static NTSTATUS dsgetdcname_cache_store(TALLOC_CTX *mem_ctx,
156
const char *domain_name,
157
const DATA_BLOB *blob)
163
if (!gencache_init()) {
164
return NT_STATUS_INTERNAL_DB_ERROR;
167
key = dsgetdcname_cache_key(mem_ctx, domain_name);
169
return NT_STATUS_NO_MEMORY;
172
expire_time = time(NULL) + DSGETDCNAME_CACHE_TTL;
174
if (gencache_lock_entry(key) != 0) {
175
return NT_STATUS_LOCK_NOT_GRANTED;
178
ret = gencache_set_data_blob(key, blob, expire_time);
180
gencache_unlock_entry(key);
182
return ret ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
185
/****************************************************************
186
****************************************************************/
188
static NTSTATUS store_cldap_reply(TALLOC_CTX *mem_ctx,
190
struct sockaddr_storage *ss,
192
struct NETLOGON_SAM_LOGON_RESPONSE_EX *r)
195
enum ndr_err_code ndr_err;
197
char addr[INET6_ADDRSTRLEN];
199
print_sockaddr(addr, sizeof(addr), ss);
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);
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);
213
status = dsgetdcname_cache_store(mem_ctx, r->domain, &blob);
214
if (!NT_STATUS_IS_OK(status)) {
217
if (r->client_site) {
218
sitename_store(r->domain, r->client_site);
222
status = dsgetdcname_cache_store(mem_ctx, r->dns_domain, &blob);
223
if (!NT_STATUS_IS_OK(status)) {
226
if (r->client_site) {
227
sitename_store(r->dns_domain, r->client_site);
231
status = NT_STATUS_OK;
234
data_blob_free(&blob);
239
/****************************************************************
240
****************************************************************/
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,
247
const char *site_name,
248
struct netr_DsRGetDCNameInfo *info)
250
struct netr_DsRGetDCNameInfo *dc_info;
252
return dsgetdcname(mem_ctx,
257
flags | DS_FORCE_REDISCOVERY,
261
/****************************************************************
262
****************************************************************/
264
static uint32_t get_cldap_reply_server_flags(struct netlogon_samlogon_response *r,
267
switch (nt_version & 0x0000001f) {
277
return r->data.nt5.server_type;
282
return r->data.nt5_ex.server_type;
291
return r->data.nt5_ex.server_type;
301
return r->data.nt5_ex.server_type;
305
return r->data.nt5_ex.server_type;
311
/****************************************************************
312
****************************************************************/
314
#define RETURN_ON_FALSE(x) if (!(x)) return false;
316
static bool check_cldap_reply_required_flags(uint32_t ret_flags,
319
if (ret_flags == 0) {
323
if (req_flags & DS_PDC_REQUIRED)
324
RETURN_ON_FALSE(ret_flags & NBT_SERVER_PDC);
326
if (req_flags & DS_GC_SERVER_REQUIRED)
327
RETURN_ON_FALSE(ret_flags & NBT_SERVER_GC);
329
if (req_flags & DS_ONLY_LDAP_NEEDED)
330
RETURN_ON_FALSE(ret_flags & NBT_SERVER_LDAP);
332
if ((req_flags & DS_DIRECTORY_SERVICE_REQUIRED) ||
333
(req_flags & DS_DIRECTORY_SERVICE_PREFERRED))
334
RETURN_ON_FALSE(ret_flags & NBT_SERVER_DS);
336
if (req_flags & DS_KDC_REQUIRED)
337
RETURN_ON_FALSE(ret_flags & NBT_SERVER_KDC);
339
if (req_flags & DS_TIMESERV_REQUIRED)
340
RETURN_ON_FALSE(ret_flags & NBT_SERVER_TIMESERV);
342
if (req_flags & DS_WRITABLE_REQUIRED)
343
RETURN_ON_FALSE(ret_flags & NBT_SERVER_WRITABLE);
348
/****************************************************************
349
****************************************************************/
351
static NTSTATUS dsgetdcname_cache_fetch(TALLOC_CTX *mem_ctx,
352
const char *domain_name,
353
struct GUID *domain_guid,
355
const char *site_name,
356
struct netr_DsRGetDCNameInfo **info_p,
361
enum ndr_err_code ndr_err;
362
struct netr_DsRGetDCNameInfo *info;
363
struct NETLOGON_SAM_LOGON_RESPONSE_EX r;
366
if (!gencache_init()) {
367
return NT_STATUS_INTERNAL_DB_ERROR;
370
key = dsgetdcname_cache_key(mem_ctx, domain_name);
372
return NT_STATUS_NO_MEMORY;
375
if (!gencache_get_data_blob(key, &blob, expired)) {
376
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
379
info = TALLOC_ZERO_P(mem_ctx, struct netr_DsRGetDCNameInfo);
381
return NT_STATUS_NO_MEMORY;
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);
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);
393
status = make_dc_info_from_cldap_reply(mem_ctx, flags, NULL,
395
if (!NT_STATUS_IS_OK(status)) {
399
if (DEBUGLEVEL >= 10) {
400
NDR_PRINT_DEBUG(netr_DsRGetDCNameInfo, info);
404
if (!check_cldap_reply_required_flags(info->dc_flags, flags)) {
405
DEBUG(10,("invalid flags\n"));
406
return NT_STATUS_INVALID_PARAMETER;
409
if ((flags & DS_IP_REQUIRED) &&
410
(info->dc_address_type != DS_ADDRESS_TYPE_INET)) {
411
return NT_STATUS_INVALID_PARAMETER_MIX;
419
/****************************************************************
420
****************************************************************/
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,
427
const char *site_name,
428
struct netr_DsRGetDCNameInfo **info)
431
bool expired = false;
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",
438
return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
441
if (flags & DS_BACKGROUND_ONLY) {
446
status = dsgetdcname_cache_refresh(mem_ctx, msg_ctx,
450
if (!NT_STATUS_IS_OK(status)) {
458
/****************************************************************
459
****************************************************************/
461
static bool check_allowed_required_flags(uint32_t flags,
462
const char *site_name)
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);
468
/* FIXME: check for DSGETDC_VALID_FLAGS and check for excluse bits
469
* (DS_PDC_REQUIRED, DS_KDC_REQUIRED, DS_GC_SERVER_REQUIRED) */
471
debug_dsdcinfo_flags(10, flags);
473
if ((flags & DS_TRY_NEXTCLOSEST_SITE) && site_name) {
477
if (return_type == (DS_RETURN_FLAT_NAME|DS_RETURN_DNS_NAME)) {
481
if (offered_type == (DS_IS_DNS_NAME|DS_IS_FLAT_NAME)) {
485
if (query_type == (DS_BACKGROUND_ONLY|DS_FORCE_REDISCOVERY)) {
490
if ((flags & DS_RETURN_DNS_NAME) && (!(flags & DS_IP_REQUIRED))) {
491
printf("gd: here5 \n");
498
/****************************************************************
499
****************************************************************/
501
static NTSTATUS discover_dc_netbios(TALLOC_CTX *mem_ctx,
502
const char *domain_name,
504
struct ip_service_name **returned_dclist,
508
enum nbt_name_type name_type = NBT_NAME_LOGON;
509
struct ip_service *iplist;
511
struct ip_service_name *dclist = NULL;
514
*returned_dclist = NULL;
517
if (lp_disable_netbios()) {
518
return NT_STATUS_NOT_SUPPORTED;
521
if (flags & DS_PDC_REQUIRED) {
522
name_type = NBT_NAME_PDC;
525
status = internal_resolve_name(domain_name, name_type, NULL,
527
"lmhosts wins bcast");
528
if (!NT_STATUS_IS_OK(status)) {
529
DEBUG(10,("discover_dc_netbios: failed to find DC\n"));
533
dclist = TALLOC_ZERO_ARRAY(mem_ctx, struct ip_service_name, count);
535
return NT_STATUS_NO_MEMORY;
538
for (i=0; i<count; i++) {
540
char addr[INET6_ADDRSTRLEN];
541
struct ip_service_name *r = &dclist[i];
543
print_sockaddr(addr, sizeof(addr),
546
r->ss = iplist[i].ss;
547
r->port = iplist[i].port;
548
r->hostname = talloc_strdup(mem_ctx, addr);
550
return NT_STATUS_NO_MEMORY;
555
*returned_dclist = dclist;
556
*returned_count = count;
561
/****************************************************************
562
****************************************************************/
564
static NTSTATUS discover_dc_dns(TALLOC_CTX *mem_ctx,
565
const char *domain_name,
566
struct GUID *domain_guid,
568
const char *site_name,
569
struct ip_service_name **returned_dclist,
574
struct dns_rr_srv *dcs = NULL;
577
struct ip_service_name *dclist = NULL;
580
if (flags & DS_PDC_REQUIRED) {
581
status = ads_dns_query_pdc(mem_ctx, domain_name,
583
} else if (flags & DS_GC_SERVER_REQUIRED) {
584
status = ads_dns_query_gcs(mem_ctx, domain_name, site_name,
586
} else if (flags & DS_KDC_REQUIRED) {
587
status = ads_dns_query_kdcs(mem_ctx, domain_name, site_name,
589
} else if (flags & DS_DIRECTORY_SERVICE_REQUIRED) {
590
status = ads_dns_query_dcs(mem_ctx, domain_name, site_name,
592
} else if (domain_guid) {
593
status = ads_dns_query_dcs_guid(mem_ctx, domain_name,
594
domain_guid, &dcs, &numdcs);
596
status = ads_dns_query_dcs(mem_ctx, domain_name, site_name,
600
if (!NT_STATUS_IS_OK(status)) {
605
return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
608
for (i=0;i<numdcs;i++) {
609
numaddrs += MAX(dcs[i].num_ips,1);
612
dclist = TALLOC_ZERO_ARRAY(mem_ctx,
613
struct ip_service_name,
616
return NT_STATUS_NO_MEMORY;
619
/* now unroll the list of IP addresses */
625
while ((i < numdcs) && (count < numaddrs)) {
627
struct ip_service_name *r = &dclist[count];
629
r->port = dcs[i].port;
630
r->hostname = dcs[i].hostname;
632
/* If we don't have an IP list for a name, lookup it up */
635
interpret_string_addr(&r->ss, dcs[i].hostname, 0);
639
/* use the IP addresses from the SRV sresponse */
641
if (j >= dcs[i].num_ips) {
647
r->ss = dcs[i].ss_s[j];
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 */
659
if (!is_zero_addr((struct sockaddr *)&r->ss)) {
665
*returned_dclist = dclist;
666
*return_count = count;
672
return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
675
/****************************************************************
676
****************************************************************/
678
static NTSTATUS make_domain_controller_info(TALLOC_CTX *mem_ctx,
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,
686
const char *dc_site_name,
687
const char *client_site_name,
688
struct netr_DsRGetDCNameInfo **info_out)
690
struct netr_DsRGetDCNameInfo *info;
692
info = TALLOC_ZERO_P(mem_ctx, struct netr_DsRGetDCNameInfo);
693
NT_STATUS_HAVE_NO_MEMORY(info);
696
info->dc_unc = talloc_strdup(mem_ctx, dc_unc);
697
NT_STATUS_HAVE_NO_MEMORY(info->dc_unc);
701
if (!(dc_address[0] == '\\' && dc_address[1] == '\\')) {
702
info->dc_address = talloc_asprintf(mem_ctx, "\\\\%s",
705
info->dc_address = talloc_strdup(mem_ctx, dc_address);
707
NT_STATUS_HAVE_NO_MEMORY(info->dc_address);
710
info->dc_address_type = dc_address_type;
713
info->domain_guid = *domain_guid;
717
info->domain_name = talloc_strdup(mem_ctx, domain_name);
718
NT_STATUS_HAVE_NO_MEMORY(info->domain_name);
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;
727
info->dc_flags = flags;
730
info->dc_site_name = talloc_strdup(mem_ctx, dc_site_name);
731
NT_STATUS_HAVE_NO_MEMORY(info->dc_site_name);
734
if (client_site_name) {
735
info->client_site_name = talloc_strdup(mem_ctx,
737
NT_STATUS_HAVE_NO_MEMORY(info->client_site_name);
745
/****************************************************************
746
****************************************************************/
748
static void map_dc_and_domain_names(uint32_t flags,
750
const char *domain_name,
751
const char *dns_dc_name,
752
const char *dns_domain_name,
754
const char **hostname_p,
755
const char **domain_p)
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;
765
case DS_RETURN_DNS_NAME:
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;
774
if (dc_name && domain_name &&
775
*dc_name && *domain_name) {
776
*hostname_p = dc_name;
777
*domain_p = domain_name;
783
/****************************************************************
784
****************************************************************/
786
static NTSTATUS make_dc_info_from_cldap_reply(TALLOC_CTX *mem_ctx,
788
struct sockaddr_storage *ss,
789
struct NETLOGON_SAM_LOGON_RESPONSE_EX *r,
790
struct netr_DsRGetDCNameInfo **info)
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;
802
char addr[INET6_ADDRSTRLEN];
805
print_sockaddr(addr, sizeof(addr), ss);
807
dc_address_type = DS_ADDRESS_TYPE_INET;
810
if (!ss && r->sockaddr.pdc_ip) {
811
dc_address = r->sockaddr.pdc_ip;
812
dc_address_type = DS_ADDRESS_TYPE_INET;
814
dc_address = r->pdc_name;
815
dc_address_type = DS_ADDRESS_TYPE_NETBIOS;
818
map_dc_and_domain_names(flags,
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;
833
return make_domain_controller_info(mem_ctx,
846
/****************************************************************
847
****************************************************************/
849
static uint32_t map_ds_flags_to_nt_version(uint32_t flags)
851
uint32_t nt_version = 0;
853
if (flags & DS_PDC_REQUIRED) {
854
nt_version |= NETLOGON_NT_VERSION_PDC;
857
if (flags & DS_GC_SERVER_REQUIRED) {
858
nt_version |= NETLOGON_NT_VERSION_GC;
861
if (flags & DS_TRY_NEXTCLOSEST_SITE) {
862
nt_version |= NETLOGON_NT_VERSION_WITH_CLOSEST_SITE;
865
if (flags & DS_IP_REQUIRED) {
866
nt_version |= NETLOGON_NT_VERSION_IP;
872
/****************************************************************
873
****************************************************************/
875
static NTSTATUS process_dc_dns(TALLOC_CTX *mem_ctx,
876
const char *domain_name,
878
struct ip_service_name *dclist,
880
struct netr_DsRGetDCNameInfo **info)
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;
890
nt_version |= map_ds_flags_to_nt_version(flags);
892
for (i=0; i<num_dcs; i++) {
894
DEBUG(10,("LDAP ping to %s\n", dclist[i].hostname));
896
if (ads_cldap_netlogon(mem_ctx, dclist[i].hostname,
901
nt_version = r->ntver;
902
ret_flags = get_cldap_reply_server_flags(r, nt_version);
904
if (check_cldap_reply_required_flags(ret_flags, flags)) {
914
return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
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);
927
/****************************************************************
928
****************************************************************/
930
static struct event_context *ev_context(void)
932
static struct event_context *ctx;
934
if (!ctx && !(ctx = event_context_init(NULL))) {
935
smb_panic("Could not init event context");
940
/****************************************************************
941
****************************************************************/
943
static struct messaging_context *msg_context(TALLOC_CTX *mem_ctx)
945
static struct messaging_context *ctx;
947
if (!ctx && !(ctx = messaging_init(mem_ctx, server_id_self(),
949
smb_panic("Could not init messaging context");
954
/****************************************************************
955
****************************************************************/
957
static NTSTATUS process_dc_netbios(TALLOC_CTX *mem_ctx,
958
struct messaging_context *msg_ctx,
959
const char *domain_name,
961
struct ip_service_name *dclist,
963
struct netr_DsRGetDCNameInfo **info)
965
struct sockaddr_storage ss;
966
struct ip_service ip_list;
967
enum nbt_name_type name_type = NBT_NAME_LOGON;
970
const char *dc_name = NULL;
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;
979
msg_ctx = msg_context(mem_ctx);
982
if (flags & DS_PDC_REQUIRED) {
983
name_type = NBT_NAME_PDC;
986
nt_version |= map_ds_flags_to_nt_version(flags);
988
DEBUG(10,("process_dc_netbios\n"));
990
for (i=0; i<num_dcs; i++) {
992
ip_list.ss = dclist[i].ss;
995
if (!interpret_string_addr(&ss, dclist[i].hostname, AI_NUMERICHOST)) {
996
return NT_STATUS_UNSUCCESSFUL;
999
if (send_getdc_request(mem_ctx, msg_ctx,
1000
&dclist[i].ss, domain_name,
1005
for (k=0; k<5; k++) {
1006
if (receive_getdc_response(mem_ctx,
1013
namecache_store(dc_name, NBT_NAME_SERVER, 1, &ip_list);
1020
if (name_status_find(domain_name,
1026
struct NETLOGON_SAM_LOGON_RESPONSE_NT40 logon1;
1028
r = TALLOC_ZERO_P(mem_ctx, struct netlogon_samlogon_response);
1029
NT_STATUS_HAVE_NO_MEMORY(r);
1031
ZERO_STRUCT(logon1);
1033
nt_version = NETLOGON_NT_VERSION_1;
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);
1040
r->data.nt4 = logon1;
1041
r->ntver = nt_version;
1043
map_netlogon_samlogon_response(r);
1045
namecache_store(tmp_dc_name, NBT_NAME_SERVER, 1, &ip_list);
1051
return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
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);
1065
/****************************************************************
1066
****************************************************************/
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,
1073
const char *site_name,
1074
struct netr_DsRGetDCNameInfo **info)
1076
NTSTATUS status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1077
struct ip_service_name *dclist = NULL;
1080
DEBUG(10,("dsgetdcname_rediscover\n"));
1082
if (flags & DS_IS_FLAT_NAME) {
1084
status = discover_dc_netbios(mem_ctx, domain_name, flags,
1086
NT_STATUS_NOT_OK_RETURN(status);
1088
return process_dc_netbios(mem_ctx, msg_ctx, domain_name, flags,
1089
dclist, num_dcs, info);
1092
if (flags & DS_IS_DNS_NAME) {
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);
1098
return process_dc_dns(mem_ctx, domain_name, flags,
1099
dclist, num_dcs, info);
1102
status = discover_dc_dns(mem_ctx, domain_name, domain_guid, flags,
1103
site_name, &dclist, &num_dcs);
1105
if (NT_STATUS_IS_OK(status) && num_dcs != 0) {
1107
status = process_dc_dns(mem_ctx, domain_name, flags, dclist,
1109
if (NT_STATUS_IS_OK(status)) {
1114
status = discover_dc_netbios(mem_ctx, domain_name, flags, &dclist,
1116
NT_STATUS_NOT_OK_RETURN(status);
1118
return process_dc_netbios(mem_ctx, msg_ctx, domain_name, flags, dclist,
1122
static bool is_closest_site(struct netr_DsRGetDCNameInfo *info)
1124
if (info->dc_flags & DS_SERVER_CLOSEST) {
1128
if (!info->client_site_name) {
1132
if (!info->dc_site_name) {
1136
if (strcmp(info->client_site_name, info->dc_site_name) == 0) {
1143
/********************************************************************
1146
This will be the only public function here.
1147
********************************************************************/
1149
NTSTATUS dsgetdcname(TALLOC_CTX *mem_ctx,
1150
struct messaging_context *msg_ctx,
1151
const char *domain_name,
1152
struct GUID *domain_guid,
1153
const char *site_name,
1155
struct netr_DsRGetDCNameInfo **info)
1157
NTSTATUS status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
1158
struct netr_DsRGetDCNameInfo *myinfo = NULL;
1159
char *query_site = NULL;
1161
struct netr_DsRGetDCNameInfo *first_info = NULL;
1163
DEBUG(10,("dsgetdcname: domain_name: %s, "
1164
"domain_guid: %s, site_name: %s, flags: 0x%08x\n",
1166
domain_guid ? GUID_string(mem_ctx, domain_guid) : "(null)",
1171
if (!check_allowed_required_flags(flags, site_name)) {
1172
DEBUG(0,("invalid flags specified\n"));
1173
return NT_STATUS_INVALID_PARAMETER;
1177
query_site = sitename_fetch(domain_name);
1179
query_site = SMB_STRDUP(site_name);
1182
if (flags & DS_FORCE_REDISCOVERY) {
1186
status = dsgetdcname_cached(mem_ctx, msg_ctx, domain_name, domain_guid,
1187
flags, query_site, &myinfo);
1188
if (NT_STATUS_IS_OK(status)) {
1192
if (flags & DS_BACKGROUND_ONLY) {
1197
status = dsgetdcname_rediscover(mem_ctx, msg_ctx, domain_name,
1198
domain_guid, flags, query_site,
1202
SAFE_FREE(query_site);
1204
if (!NT_STATUS_IS_OK(status)) {
1207
return NT_STATUS_OK;
1213
TALLOC_FREE(first_info);
1214
} else if (!is_closest_site(myinfo)) {
1216
first_info = myinfo;
1217
/* TODO: may use the next_closest_site here */
1218
query_site = SMB_STRDUP(myinfo->client_site_name);
1223
return NT_STATUS_OK;