2 Unix SMB/CIFS implementation.
4 Get a struct wb_dom_info for a trusted domain, relying on "our" DC.
6 Copyright (C) Volker Lendecke 2005
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "libcli/composite/composite.h"
24 #include "libcli/resolve/resolve.h"
25 #include "libcli/security/security.h"
26 #include "winbind/wb_server.h"
27 #include "smbd/service_task.h"
28 #include "librpc/gen_ndr/ndr_netlogon_c.h"
29 #include "libcli/libcli.h"
31 struct trusted_dom_info_state
{
32 struct composite_context
*ctx
;
33 struct wbsrv_service
*service
;
34 struct wbsrv_domain
*my_domain
;
36 struct netr_DsRGetDCName d
;
37 struct netr_GetAnyDCName g
;
39 struct wb_dom_info
*info
;
42 static void trusted_dom_info_recv_domain(struct composite_context
*ctx
);
43 static void trusted_dom_info_recv_dsr(struct tevent_req
*subreq
);
44 static void trusted_dom_info_recv_dcname(struct tevent_req
*subreq
);
45 static void trusted_dom_info_recv_dcaddr(struct composite_context
*ctx
);
47 struct composite_context
*wb_trusted_dom_info_send(TALLOC_CTX
*mem_ctx
,
48 struct wbsrv_service
*service
,
49 const char *domain_name
,
50 const struct dom_sid
*sid
)
52 struct composite_context
*result
, *ctx
;
53 struct trusted_dom_info_state
*state
;
55 result
= composite_create(mem_ctx
, service
->task
->event_ctx
);
56 if (result
== NULL
) goto failed
;
58 state
= talloc(result
, struct trusted_dom_info_state
);
59 if (state
== NULL
) goto failed
;
61 result
->private_data
= state
;
63 state
->info
= talloc_zero(state
, struct wb_dom_info
);
64 if (state
->info
== NULL
) goto failed
;
66 state
->service
= service
;
68 state
->info
->sid
= dom_sid_dup(state
->info
, sid
);
69 if (state
->info
->sid
== NULL
) goto failed
;
71 state
->info
->name
= talloc_strdup(state
->info
, domain_name
);
72 if (state
->info
->name
== NULL
) goto failed
;
74 ctx
= wb_sid2domain_send(state
, service
, service
->primary_sid
);
75 if (ctx
== NULL
) goto failed
;
77 ctx
->async
.fn
= trusted_dom_info_recv_domain
;
78 ctx
->async
.private_data
= state
;
86 static void trusted_dom_info_recv_domain(struct composite_context
*ctx
)
88 struct trusted_dom_info_state
*state
=
89 talloc_get_type(ctx
->async
.private_data
,
90 struct trusted_dom_info_state
);
91 struct tevent_req
*subreq
;
93 state
->ctx
->status
= wb_sid2domain_recv(ctx
, &state
->my_domain
);
94 if (!composite_is_ok(state
->ctx
)) return;
96 state
->d
.in
.server_unc
=
97 talloc_asprintf(state
, "\\\\%s",
98 dcerpc_server_name(state
->my_domain
->netlogon_pipe
));
99 if (composite_nomem(state
->d
.in
.server_unc
,
102 state
->d
.in
.domain_name
= state
->info
->name
;
103 state
->d
.in
.domain_guid
= NULL
;
104 state
->d
.in
.site_guid
= NULL
;
105 state
->d
.in
.flags
= DS_RETURN_DNS_NAME
;
106 state
->d
.out
.info
= talloc(state
, struct netr_DsRGetDCNameInfo
*);
107 if (composite_nomem(state
->d
.out
.info
, state
->ctx
)) return;
109 subreq
= dcerpc_netr_DsRGetDCName_r_send(state
,
110 state
->ctx
->event_ctx
,
111 state
->my_domain
->netlogon_pipe
->binding_handle
,
113 if (composite_nomem(subreq
, state
->ctx
)) return;
114 tevent_req_set_callback(subreq
, trusted_dom_info_recv_dsr
, state
);
118 * dcerpc_netr_DsRGetDCName has replied
121 static void trusted_dom_info_recv_dsr(struct tevent_req
*subreq
)
123 struct trusted_dom_info_state
*state
=
124 tevent_req_callback_data(subreq
,
125 struct trusted_dom_info_state
);
127 state
->ctx
->status
= dcerpc_netr_DsRGetDCName_r_recv(subreq
, state
);
129 if (!NT_STATUS_IS_OK(state
->ctx
->status
)) {
130 DEBUG(9, ("dcerpc_netr_DsRGetDCName_recv returned %s\n",
131 nt_errstr(state
->ctx
->status
)));
136 werror_to_ntstatus(state
->d
.out
.result
);
137 if (!NT_STATUS_IS_OK(state
->ctx
->status
)) {
138 DEBUG(9, ("dsrgetdcname returned %s\n",
139 nt_errstr(state
->ctx
->status
)));
143 /* Hey, that was easy! */
144 state
->info
->num_dcs
= 1;
145 state
->info
->dcs
= talloc(state
->info
, struct nbt_dc_name
);
146 state
->info
->dcs
[0].name
= talloc_steal(state
->info
,
147 (*state
->d
.out
.info
)->dc_unc
);
148 if (*state
->info
->dcs
[0].name
== '\\') state
->info
->dcs
[0].name
++;
149 if (*state
->info
->dcs
[0].name
== '\\') state
->info
->dcs
[0].name
++;
151 state
->info
->dcs
[0].address
= talloc_steal(state
->info
,
152 (*state
->d
.out
.info
)->dc_address
);
153 if (*state
->info
->dcs
[0].address
== '\\') state
->info
->dcs
[0].address
++;
154 if (*state
->info
->dcs
[0].address
== '\\') state
->info
->dcs
[0].address
++;
156 state
->info
->dns_name
= talloc_steal(state
->info
,
157 (*state
->d
.out
.info
)->domain_name
);
159 composite_done(state
->ctx
);
164 state
->g
.in
.logon_server
= talloc_asprintf(
166 dcerpc_server_name(state
->my_domain
->netlogon_pipe
));
167 state
->g
.in
.domainname
= state
->info
->name
;
168 state
->g
.out
.dcname
= talloc(state
, const char *);
170 subreq
= dcerpc_netr_GetAnyDCName_r_send(state
,
171 state
->ctx
->event_ctx
,
172 state
->my_domain
->netlogon_pipe
->binding_handle
,
174 if (composite_nomem(subreq
, state
->ctx
)) return;
176 tevent_req_set_callback(subreq
, trusted_dom_info_recv_dcname
, state
);
179 static void trusted_dom_info_recv_dcname(struct tevent_req
*subreq
)
181 struct trusted_dom_info_state
*state
=
182 tevent_req_callback_data(subreq
,
183 struct trusted_dom_info_state
);
184 struct composite_context
*ctx
;
185 struct nbt_name name
;
187 state
->ctx
->status
= dcerpc_netr_GetAnyDCName_r_recv(subreq
, state
);
189 if (!composite_is_ok(state
->ctx
)) return;
190 state
->ctx
->status
= werror_to_ntstatus(state
->g
.out
.result
);
191 if (!composite_is_ok(state
->ctx
)) return;
193 /* Hey, that was easy! */
194 state
->info
->num_dcs
= 1;
195 state
->info
->dcs
= talloc(state
->info
, struct nbt_dc_name
);
196 state
->info
->dcs
[0].name
= talloc_steal(state
->info
,
197 *(state
->g
.out
.dcname
));
198 if (*state
->info
->dcs
[0].name
== '\\') state
->info
->dcs
[0].name
++;
199 if (*state
->info
->dcs
[0].name
== '\\') state
->info
->dcs
[0].name
++;
201 make_nbt_name(&name
, state
->info
->dcs
[0].name
, 0x20);
202 ctx
= resolve_name_send(lp_resolve_context(state
->service
->task
->lp_ctx
), state
,
203 &name
, state
->service
->task
->event_ctx
);
205 composite_continue(state
->ctx
, ctx
, trusted_dom_info_recv_dcaddr
,
209 static void trusted_dom_info_recv_dcaddr(struct composite_context
*ctx
)
211 struct trusted_dom_info_state
*state
=
212 talloc_get_type(ctx
->async
.private_data
,
213 struct trusted_dom_info_state
);
215 state
->ctx
->status
= resolve_name_recv(ctx
, state
->info
,
216 &state
->info
->dcs
[0].address
);
217 if (!composite_is_ok(state
->ctx
)) return;
219 composite_done(state
->ctx
);
222 NTSTATUS
wb_trusted_dom_info_recv(struct composite_context
*ctx
,
224 struct wb_dom_info
**result
)
226 NTSTATUS status
= composite_wait(ctx
);
227 if (NT_STATUS_IS_OK(status
)) {
228 struct trusted_dom_info_state
*state
=
229 talloc_get_type(ctx
->private_data
,
230 struct trusted_dom_info_state
);
231 *result
= talloc_steal(mem_ctx
, state
->info
);
237 NTSTATUS
wb_trusted_dom_info(TALLOC_CTX
*mem_ctx
,
238 struct wbsrv_service
*service
,
239 const char *domain_name
,
240 const struct dom_sid
*sid
,
241 struct wb_dom_info
**result
)
243 struct composite_context
*ctx
=
244 wb_trusted_dom_info_send(mem_ctx
, service
, domain_name
, sid
);
245 return wb_trusted_dom_info_recv(ctx
, mem_ctx
, result
);