2 Unix SMB/CIFS implementation.
3 async implementation of WINBINDD_DSGETDCNAME
4 Copyright (C) Volker Lendecke 2009
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "util/debug.h"
23 #include "librpc/gen_ndr/ndr_winbind_c.h"
24 #include "lib/util/string_wrappers.h"
26 struct winbindd_dsgetdcname_state
{
28 struct netr_DsRGetDCNameInfo
*dc_info
;
31 static uint32_t get_dsgetdc_flags(uint32_t wbc_flags
);
32 static void winbindd_dsgetdcname_done(struct tevent_req
*subreq
);
34 struct tevent_req
*winbindd_dsgetdcname_send(TALLOC_CTX
*mem_ctx
,
35 struct tevent_context
*ev
,
36 struct winbindd_cli_state
*cli
,
37 struct winbindd_request
*request
)
39 struct tevent_req
*req
, *subreq
;
40 struct dcerpc_binding_handle
*child_binding_handle
= NULL
;
41 struct winbindd_dsgetdcname_state
*state
;
42 struct GUID
*guid_ptr
= NULL
;
43 uint32_t ds_flags
= 0;
46 req
= tevent_req_create(mem_ctx
, &state
,
47 struct winbindd_dsgetdcname_state
);
52 D_NOTICE("[%s (%u)] Winbind external command DSGETDCNAME start.\n",
54 (unsigned int)cli
->pid
);
56 request
->data
.dsgetdcname
.domain_name
57 [sizeof(request
->data
.dsgetdcname
.domain_name
)-1] = '\0';
58 request
->data
.dsgetdcname
.site_name
59 [sizeof(request
->data
.dsgetdcname
.site_name
)-1] = '\0';
60 request
->data
.dsgetdcname
.domain_guid
61 [sizeof(request
->data
.dsgetdcname
.domain_guid
)-1] = '\0';
63 D_NOTICE("Calling DsGetDcName for domain '%s'.\n",
64 request
->data
.dsgetdcname
.domain_name
);
66 ds_flags
= get_dsgetdc_flags(request
->data
.dsgetdcname
.flags
);
68 status
= GUID_from_string(request
->data
.dsgetdcname
.domain_guid
,
70 if (NT_STATUS_IS_OK(status
) && !GUID_all_zero(&state
->guid
)) {
71 guid_ptr
= &state
->guid
;
74 child_binding_handle
= locator_child_handle();
76 subreq
= dcerpc_wbint_DsGetDcName_send(
77 state
, ev
, child_binding_handle
,
78 request
->data
.dsgetdcname
.domain_name
, guid_ptr
,
79 request
->data
.dsgetdcname
.site_name
,
80 ds_flags
, &state
->dc_info
);
81 if (tevent_req_nomem(subreq
, req
)) {
82 return tevent_req_post(req
, ev
);
84 tevent_req_set_callback(subreq
, winbindd_dsgetdcname_done
, req
);
88 static void winbindd_dsgetdcname_done(struct tevent_req
*subreq
)
90 struct tevent_req
*req
= tevent_req_callback_data(
91 subreq
, struct tevent_req
);
92 struct winbindd_dsgetdcname_state
*state
= tevent_req_data(
93 req
, struct winbindd_dsgetdcname_state
);
94 NTSTATUS status
, result
;
96 status
= dcerpc_wbint_DsGetDcName_recv(subreq
, state
, &result
);
98 if (any_nt_status_not_ok(status
, result
, &status
)) {
99 tevent_req_nterror(req
, status
);
102 tevent_req_done(req
);
105 NTSTATUS
winbindd_dsgetdcname_recv(struct tevent_req
*req
,
106 struct winbindd_response
*response
)
108 struct winbindd_dsgetdcname_state
*state
= tevent_req_data(
109 req
, struct winbindd_dsgetdcname_state
);
110 struct GUID_txt_buf guid_str_buf
;
114 D_NOTICE("Winbind external command DSGETDCNAME end.\n");
115 if (tevent_req_is_nterror(req
, &status
)) {
116 D_WARNING("Failed with: %s\n", nt_errstr(status
));
120 fstrcpy(response
->data
.dsgetdcname
.dc_unc
,
121 state
->dc_info
->dc_unc
);
122 fstrcpy(response
->data
.dsgetdcname
.dc_address
,
123 state
->dc_info
->dc_address
);
124 response
->data
.dsgetdcname
.dc_address_type
=
125 state
->dc_info
->dc_address_type
;
127 guid_str
= GUID_buf_string(&state
->dc_info
->domain_guid
,
129 fstrcpy(response
->data
.dsgetdcname
.domain_guid
, guid_str
);
131 fstrcpy(response
->data
.dsgetdcname
.domain_name
,
132 state
->dc_info
->domain_name
);
133 fstrcpy(response
->data
.dsgetdcname
.forest_name
,
134 state
->dc_info
->forest_name
);
135 response
->data
.dsgetdcname
.dc_flags
= state
->dc_info
->dc_flags
;
136 fstrcpy(response
->data
.dsgetdcname
.dc_site_name
,
137 state
->dc_info
->dc_site_name
);
138 fstrcpy(response
->data
.dsgetdcname
.client_site_name
,
139 state
->dc_info
->client_site_name
);
144 static uint32_t get_dsgetdc_flags(uint32_t wbc_flags
)
146 struct wbc_flag_map
{
147 uint32_t wbc_dc_flag
;
148 uint32_t ds_dc_flags
;
149 } lookup_dc_flags
[] = {
150 { WBC_LOOKUP_DC_FORCE_REDISCOVERY
,
151 DS_FORCE_REDISCOVERY
},
152 { WBC_LOOKUP_DC_DS_REQUIRED
,
153 DS_DIRECTORY_SERVICE_REQUIRED
},
154 { WBC_LOOKUP_DC_DS_PREFERRED
,
155 DS_DIRECTORY_SERVICE_PREFERRED
},
156 { WBC_LOOKUP_DC_GC_SERVER_REQUIRED
,
157 DS_GC_SERVER_REQUIRED
},
158 { WBC_LOOKUP_DC_PDC_REQUIRED
,
160 { WBC_LOOKUP_DC_BACKGROUND_ONLY
,
161 DS_BACKGROUND_ONLY
},
162 { WBC_LOOKUP_DC_IP_REQUIRED
,
164 { WBC_LOOKUP_DC_KDC_REQUIRED
,
166 { WBC_LOOKUP_DC_TIMESERV_REQUIRED
,
167 DS_TIMESERV_REQUIRED
},
168 { WBC_LOOKUP_DC_WRITABLE_REQUIRED
,
169 DS_WRITABLE_REQUIRED
},
170 { WBC_LOOKUP_DC_GOOD_TIMESERV_PREFERRED
,
171 DS_GOOD_TIMESERV_PREFERRED
},
172 { WBC_LOOKUP_DC_AVOID_SELF
,
174 { WBC_LOOKUP_DC_ONLY_LDAP_NEEDED
,
175 DS_ONLY_LDAP_NEEDED
},
176 { WBC_LOOKUP_DC_IS_FLAT_NAME
,
178 { WBC_LOOKUP_DC_IS_DNS_NAME
,
180 { WBC_LOOKUP_DC_TRY_NEXTCLOSEST_SITE
,
181 DS_TRY_NEXTCLOSEST_SITE
},
182 { WBC_LOOKUP_DC_DS_6_REQUIRED
,
183 DS_DIRECTORY_SERVICE_6_REQUIRED
},
184 { WBC_LOOKUP_DC_RETURN_DNS_NAME
,
185 DS_RETURN_DNS_NAME
},
186 { WBC_LOOKUP_DC_RETURN_FLAT_NAME
,
187 DS_RETURN_FLAT_NAME
}
190 uint32_t ds_flags
= 0;
193 for (i
=0; i
<ARRAY_SIZE(lookup_dc_flags
); i
++) {
194 if (wbc_flags
& lookup_dc_flags
[i
].wbc_dc_flag
) {
195 ds_flags
|= lookup_dc_flags
[i
].ds_dc_flags
;