2 Unix SMB/CIFS implementation.
4 Copyright (C) Volker Lendecke 2005
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/>.
20 a composite API for finding a DC and its name
25 #include "libcli/composite/composite.h"
26 #include "winbind/wb_async_helpers.h"
28 #include "libcli/security/security.h"
29 #include "librpc/gen_ndr/ndr_lsa_c.h"
30 #include "librpc/gen_ndr/ndr_samr_c.h"
33 struct lsa_lookupsids_state
{
34 struct composite_context
*ctx
;
36 struct lsa_LookupSids r
;
37 struct lsa_SidArray sids
;
38 struct lsa_TransNameArray names
;
39 struct lsa_RefDomainList
*domains
;
41 struct wb_sid_object
**result
;
44 static void lsa_lookupsids_recv_names(struct tevent_req
*subreq
);
46 struct composite_context
*wb_lsa_lookupsids_send(TALLOC_CTX
*mem_ctx
,
47 struct dcerpc_pipe
*lsa_pipe
,
48 struct policy_handle
*handle
,
50 const struct dom_sid
**sids
)
52 struct composite_context
*result
;
53 struct lsa_lookupsids_state
*state
;
55 struct tevent_req
*subreq
;
57 result
= composite_create(mem_ctx
, lsa_pipe
->conn
->event_ctx
);
58 if (result
== NULL
) goto failed
;
60 state
= talloc(result
, struct lsa_lookupsids_state
);
61 if (state
== NULL
) goto failed
;
62 result
->private_data
= state
;
65 state
->sids
.num_sids
= num_sids
;
66 state
->sids
.sids
= talloc_array(state
, struct lsa_SidPtr
, num_sids
);
67 if (state
->sids
.sids
== NULL
) goto failed
;
69 for (i
=0; i
<num_sids
; i
++) {
70 state
->sids
.sids
[i
].sid
= dom_sid_dup(state
->sids
.sids
,
72 if (state
->sids
.sids
[i
].sid
== NULL
) goto failed
;
75 state
->domains
= talloc(state
, struct lsa_RefDomainList
);
76 if (state
->domains
== NULL
) goto failed
;
79 state
->num_sids
= num_sids
;
80 state
->names
.count
= 0;
81 state
->names
.names
= NULL
;
83 state
->r
.in
.handle
= handle
;
84 state
->r
.in
.sids
= &state
->sids
;
85 state
->r
.in
.names
= &state
->names
;
86 state
->r
.in
.level
= 1;
87 state
->r
.in
.count
= &state
->count
;
88 state
->r
.out
.names
= &state
->names
;
89 state
->r
.out
.count
= &state
->count
;
90 state
->r
.out
.domains
= &state
->domains
;
92 subreq
= dcerpc_lsa_LookupSids_r_send(state
,
94 lsa_pipe
->binding_handle
,
96 if (subreq
== NULL
) goto failed
;
97 tevent_req_set_callback(subreq
, lsa_lookupsids_recv_names
, state
);
106 static void lsa_lookupsids_recv_names(struct tevent_req
*subreq
)
108 struct lsa_lookupsids_state
*state
=
109 tevent_req_callback_data(subreq
,
110 struct lsa_lookupsids_state
);
113 state
->ctx
->status
= dcerpc_lsa_LookupSids_r_recv(subreq
, state
);
115 if (!composite_is_ok(state
->ctx
)) return;
116 state
->ctx
->status
= state
->r
.out
.result
;
117 if (!NT_STATUS_IS_OK(state
->ctx
->status
) &&
118 !NT_STATUS_EQUAL(state
->ctx
->status
, STATUS_SOME_UNMAPPED
)) {
119 composite_error(state
->ctx
, state
->ctx
->status
);
123 state
->result
= talloc_array(state
, struct wb_sid_object
*,
125 if (composite_nomem(state
->result
, state
->ctx
)) return;
127 for (i
=0; i
<state
->num_sids
; i
++) {
128 struct lsa_TranslatedName
*name
=
129 &state
->r
.out
.names
->names
[i
];
130 struct lsa_DomainInfo
*dom
;
131 struct lsa_RefDomainList
*domains
=
134 state
->result
[i
] = talloc_zero(state
->result
,
135 struct wb_sid_object
);
136 if (composite_nomem(state
->result
[i
], state
->ctx
)) return;
138 state
->result
[i
]->type
= name
->sid_type
;
139 if (state
->result
[i
]->type
== SID_NAME_UNKNOWN
) {
143 if (name
->sid_index
>= domains
->count
) {
144 composite_error(state
->ctx
,
145 NT_STATUS_INVALID_PARAMETER
);
149 dom
= &domains
->domains
[name
->sid_index
];
150 state
->result
[i
]->domain
= talloc_reference(state
->result
[i
],
152 if ((name
->sid_type
== SID_NAME_DOMAIN
) ||
153 (name
->name
.string
== NULL
)) {
154 state
->result
[i
]->name
=
155 talloc_strdup(state
->result
[i
], "");
157 state
->result
[i
]->name
=
158 talloc_steal(state
->result
[i
],
162 if (composite_nomem(state
->result
[i
]->name
, state
->ctx
)) {
167 composite_done(state
->ctx
);
170 NTSTATUS
wb_lsa_lookupsids_recv(struct composite_context
*c
,
172 struct wb_sid_object
***names
)
174 NTSTATUS status
= composite_wait(c
);
175 if (NT_STATUS_IS_OK(status
)) {
176 struct lsa_lookupsids_state
*state
=
177 talloc_get_type(c
->private_data
,
178 struct lsa_lookupsids_state
);
179 *names
= talloc_steal(mem_ctx
, state
->result
);
186 struct lsa_lookupnames_state
{
187 struct composite_context
*ctx
;
189 struct lsa_LookupNames r
;
190 struct lsa_TransSidArray sids
;
191 struct lsa_RefDomainList
*domains
;
193 struct wb_sid_object
**result
;
196 static void lsa_lookupnames_recv_sids(struct tevent_req
*subreq
);
198 struct composite_context
*wb_lsa_lookupnames_send(TALLOC_CTX
*mem_ctx
,
199 struct dcerpc_pipe
*lsa_pipe
,
200 struct policy_handle
*handle
,
204 struct composite_context
*result
;
205 struct lsa_lookupnames_state
*state
;
206 struct tevent_req
*subreq
;
208 struct lsa_String
*lsa_names
;
211 result
= composite_create(mem_ctx
, lsa_pipe
->conn
->event_ctx
);
212 if (result
== NULL
) goto failed
;
214 state
= talloc(result
, struct lsa_lookupnames_state
);
215 if (state
== NULL
) goto failed
;
216 result
->private_data
= state
;
219 state
->sids
.count
= 0;
220 state
->sids
.sids
= NULL
;
221 state
->num_names
= num_names
;
224 lsa_names
= talloc_array(state
, struct lsa_String
, num_names
);
225 if (lsa_names
== NULL
) goto failed
;
227 for (i
=0; i
<num_names
; i
++) {
228 lsa_names
[i
].string
= names
[i
];
231 state
->domains
= talloc(state
, struct lsa_RefDomainList
);
232 if (state
->domains
== NULL
) goto failed
;
234 state
->r
.in
.handle
= handle
;
235 state
->r
.in
.num_names
= num_names
;
236 state
->r
.in
.names
= lsa_names
;
237 state
->r
.in
.sids
= &state
->sids
;
238 state
->r
.in
.level
= 1;
239 state
->r
.in
.count
= &state
->count
;
240 state
->r
.out
.count
= &state
->count
;
241 state
->r
.out
.sids
= &state
->sids
;
242 state
->r
.out
.domains
= &state
->domains
;
244 subreq
= dcerpc_lsa_LookupNames_r_send(state
,
246 lsa_pipe
->binding_handle
,
248 if (subreq
== NULL
) goto failed
;
249 tevent_req_set_callback(subreq
, lsa_lookupnames_recv_sids
, state
);
258 static void lsa_lookupnames_recv_sids(struct tevent_req
*subreq
)
260 struct lsa_lookupnames_state
*state
=
261 tevent_req_callback_data(subreq
,
262 struct lsa_lookupnames_state
);
265 state
->ctx
->status
= dcerpc_lsa_LookupNames_r_recv(subreq
, state
);
267 if (!composite_is_ok(state
->ctx
)) return;
268 state
->ctx
->status
= state
->r
.out
.result
;
269 if (!NT_STATUS_IS_OK(state
->ctx
->status
) &&
270 !NT_STATUS_EQUAL(state
->ctx
->status
, STATUS_SOME_UNMAPPED
)) {
271 composite_error(state
->ctx
, state
->ctx
->status
);
275 state
->result
= talloc_array(state
, struct wb_sid_object
*,
277 if (composite_nomem(state
->result
, state
->ctx
)) return;
279 for (i
=0; i
<state
->num_names
; i
++) {
280 struct lsa_TranslatedSid
*sid
= &state
->r
.out
.sids
->sids
[i
];
281 struct lsa_RefDomainList
*domains
= state
->domains
;
282 struct lsa_DomainInfo
*dom
;
284 state
->result
[i
] = talloc_zero(state
->result
,
285 struct wb_sid_object
);
286 if (composite_nomem(state
->result
[i
], state
->ctx
)) return;
288 state
->result
[i
]->type
= sid
->sid_type
;
289 if (state
->result
[i
]->type
== SID_NAME_UNKNOWN
) {
293 if (sid
->sid_index
>= domains
->count
) {
294 composite_error(state
->ctx
,
295 NT_STATUS_INVALID_PARAMETER
);
299 dom
= &domains
->domains
[sid
->sid_index
];
301 state
->result
[i
]->sid
= dom_sid_add_rid(state
->result
[i
],
305 composite_done(state
->ctx
);
308 NTSTATUS
wb_lsa_lookupnames_recv(struct composite_context
*c
,
310 struct wb_sid_object
***sids
)
312 NTSTATUS status
= composite_wait(c
);
313 if (NT_STATUS_IS_OK(status
)) {
314 struct lsa_lookupnames_state
*state
=
315 talloc_get_type(c
->private_data
,
316 struct lsa_lookupnames_state
);
317 *sids
= talloc_steal(mem_ctx
, state
->result
);
322 struct samr_getuserdomgroups_state
{
323 struct composite_context
*ctx
;
324 struct dcerpc_pipe
*samr_pipe
;
329 struct samr_RidWithAttributeArray
*rid_array
;
331 struct policy_handle
*user_handle
;
332 struct samr_OpenUser o
;
333 struct samr_GetGroupsForUser g
;
337 static void samr_usergroups_recv_open(struct tevent_req
*subreq
);
338 static void samr_usergroups_recv_groups(struct tevent_req
*subreq
);
339 static void samr_usergroups_recv_close(struct tevent_req
*subreq
);
341 struct composite_context
*wb_samr_userdomgroups_send(TALLOC_CTX
*mem_ctx
,
342 struct dcerpc_pipe
*samr_pipe
,
343 struct policy_handle
*domain_handle
,
346 struct composite_context
*result
;
347 struct samr_getuserdomgroups_state
*state
;
348 struct tevent_req
*subreq
;
350 result
= composite_create(mem_ctx
, samr_pipe
->conn
->event_ctx
);
351 if (result
== NULL
) goto failed
;
353 state
= talloc(result
, struct samr_getuserdomgroups_state
);
354 if (state
== NULL
) goto failed
;
355 result
->private_data
= state
;
358 state
->samr_pipe
= samr_pipe
;
360 state
->user_handle
= talloc(state
, struct policy_handle
);
361 if (state
->user_handle
== NULL
) goto failed
;
363 state
->o
.in
.domain_handle
= domain_handle
;
364 state
->o
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
365 state
->o
.in
.rid
= rid
;
366 state
->o
.out
.user_handle
= state
->user_handle
;
368 subreq
= dcerpc_samr_OpenUser_r_send(state
,
370 state
->samr_pipe
->binding_handle
,
372 if (subreq
== NULL
) goto failed
;
373 tevent_req_set_callback(subreq
, samr_usergroups_recv_open
, state
);
382 static void samr_usergroups_recv_open(struct tevent_req
*subreq
)
384 struct samr_getuserdomgroups_state
*state
=
385 tevent_req_callback_data(subreq
,
386 struct samr_getuserdomgroups_state
);
388 state
->ctx
->status
= dcerpc_samr_OpenUser_r_recv(subreq
, state
);
390 if (!composite_is_ok(state
->ctx
)) return;
391 state
->ctx
->status
= state
->o
.out
.result
;
392 if (!composite_is_ok(state
->ctx
)) return;
394 state
->g
.in
.user_handle
= state
->user_handle
;
395 state
->g
.out
.rids
= &state
->rid_array
;
397 subreq
= dcerpc_samr_GetGroupsForUser_r_send(state
,
398 state
->ctx
->event_ctx
,
399 state
->samr_pipe
->binding_handle
,
401 if (composite_nomem(subreq
, state
->ctx
)) return;
402 tevent_req_set_callback(subreq
, samr_usergroups_recv_groups
, state
);
405 static void samr_usergroups_recv_groups(struct tevent_req
*subreq
)
407 struct samr_getuserdomgroups_state
*state
=
408 tevent_req_callback_data(subreq
,
409 struct samr_getuserdomgroups_state
);
411 state
->ctx
->status
= dcerpc_samr_GetGroupsForUser_r_recv(subreq
, state
);
413 if (!composite_is_ok(state
->ctx
)) return;
414 state
->ctx
->status
= state
->g
.out
.result
;
415 if (!composite_is_ok(state
->ctx
)) return;
417 state
->c
.in
.handle
= state
->user_handle
;
418 state
->c
.out
.handle
= state
->user_handle
;
420 subreq
= dcerpc_samr_Close_r_send(state
,
421 state
->ctx
->event_ctx
,
422 state
->samr_pipe
->binding_handle
,
424 if (composite_nomem(subreq
, state
->ctx
)) return;
425 tevent_req_set_callback(subreq
, samr_usergroups_recv_close
, state
);
428 static void samr_usergroups_recv_close(struct tevent_req
*subreq
)
430 struct samr_getuserdomgroups_state
*state
=
431 tevent_req_callback_data(subreq
,
432 struct samr_getuserdomgroups_state
);
434 state
->ctx
->status
= dcerpc_samr_Close_r_recv(subreq
, state
);
436 if (!composite_is_ok(state
->ctx
)) return;
437 state
->ctx
->status
= state
->c
.out
.result
;
438 if (!composite_is_ok(state
->ctx
)) return;
440 composite_done(state
->ctx
);
443 NTSTATUS
wb_samr_userdomgroups_recv(struct composite_context
*ctx
,
445 uint32_t *num_rids
, uint32_t **rids
)
447 struct samr_getuserdomgroups_state
*state
=
448 talloc_get_type(ctx
->private_data
,
449 struct samr_getuserdomgroups_state
);
452 NTSTATUS status
= composite_wait(ctx
);
453 if (!NT_STATUS_IS_OK(status
)) goto done
;
455 *num_rids
= state
->rid_array
->count
;
456 *rids
= talloc_array(mem_ctx
, uint32_t, *num_rids
);
458 status
= NT_STATUS_NO_MEMORY
;
462 for (i
=0; i
<*num_rids
; i
++) {
463 (*rids
)[i
] = state
->rid_array
->rids
[i
].rid
;