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
24 #include "libcli/composite/composite.h"
25 #include "winbind/wb_async_helpers.h"
27 #include "libcli/security/security.h"
28 #include "librpc/gen_ndr/ndr_lsa_c.h"
29 #include "librpc/gen_ndr/ndr_samr_c.h"
32 struct lsa_lookupsids_state
{
33 struct composite_context
*ctx
;
35 struct lsa_LookupSids r
;
36 struct lsa_SidArray sids
;
37 struct lsa_TransNameArray names
;
38 struct lsa_RefDomainList
*domains
;
40 struct wb_sid_object
**result
;
43 static void lsa_lookupsids_recv_names(struct rpc_request
*req
);
45 struct composite_context
*wb_lsa_lookupsids_send(TALLOC_CTX
*mem_ctx
,
46 struct dcerpc_pipe
*lsa_pipe
,
47 struct policy_handle
*handle
,
49 const struct dom_sid
**sids
)
51 struct composite_context
*result
;
52 struct rpc_request
*req
;
53 struct lsa_lookupsids_state
*state
;
56 result
= composite_create(mem_ctx
, lsa_pipe
->conn
->event_ctx
);
57 if (result
== NULL
) goto failed
;
59 state
= talloc(result
, struct lsa_lookupsids_state
);
60 if (state
== NULL
) goto failed
;
61 result
->private_data
= state
;
64 state
->sids
.num_sids
= num_sids
;
65 state
->sids
.sids
= talloc_array(state
, struct lsa_SidPtr
, num_sids
);
66 if (state
->sids
.sids
== NULL
) goto failed
;
68 for (i
=0; i
<num_sids
; i
++) {
69 state
->sids
.sids
[i
].sid
= dom_sid_dup(state
->sids
.sids
,
71 if (state
->sids
.sids
[i
].sid
== NULL
) goto failed
;
74 state
->domains
= talloc(state
, struct lsa_RefDomainList
);
75 if (state
->domains
== NULL
) goto failed
;
78 state
->num_sids
= num_sids
;
79 state
->names
.count
= 0;
80 state
->names
.names
= NULL
;
82 state
->r
.in
.handle
= handle
;
83 state
->r
.in
.sids
= &state
->sids
;
84 state
->r
.in
.names
= &state
->names
;
85 state
->r
.in
.level
= 1;
86 state
->r
.in
.count
= &state
->count
;
87 state
->r
.out
.names
= &state
->names
;
88 state
->r
.out
.count
= &state
->count
;
89 state
->r
.out
.domains
= &state
->domains
;
91 req
= dcerpc_lsa_LookupSids_send(lsa_pipe
, state
, &state
->r
);
92 if (req
== NULL
) goto failed
;
94 req
->async
.callback
= lsa_lookupsids_recv_names
;
95 req
->async
.private_data
= state
;
103 static void lsa_lookupsids_recv_names(struct rpc_request
*req
)
105 struct lsa_lookupsids_state
*state
=
106 talloc_get_type(req
->async
.private_data
,
107 struct lsa_lookupsids_state
);
110 state
->ctx
->status
= dcerpc_lsa_LookupSids_recv(req
);
111 if (!composite_is_ok(state
->ctx
)) return;
112 state
->ctx
->status
= state
->r
.out
.result
;
113 if (!NT_STATUS_IS_OK(state
->ctx
->status
) &&
114 !NT_STATUS_EQUAL(state
->ctx
->status
, STATUS_SOME_UNMAPPED
)) {
115 composite_error(state
->ctx
, state
->ctx
->status
);
119 state
->result
= talloc_array(state
, struct wb_sid_object
*,
121 if (composite_nomem(state
->result
, state
->ctx
)) return;
123 for (i
=0; i
<state
->num_sids
; i
++) {
124 struct lsa_TranslatedName
*name
=
125 &state
->r
.out
.names
->names
[i
];
126 struct lsa_DomainInfo
*dom
;
127 struct lsa_RefDomainList
*domains
=
130 state
->result
[i
] = talloc_zero(state
->result
,
131 struct wb_sid_object
);
132 if (composite_nomem(state
->result
[i
], state
->ctx
)) return;
134 state
->result
[i
]->type
= name
->sid_type
;
135 if (state
->result
[i
]->type
== SID_NAME_UNKNOWN
) {
139 if (name
->sid_index
>= domains
->count
) {
140 composite_error(state
->ctx
,
141 NT_STATUS_INVALID_PARAMETER
);
145 dom
= &domains
->domains
[name
->sid_index
];
146 state
->result
[i
]->domain
= talloc_reference(state
->result
[i
],
148 if ((name
->sid_type
== SID_NAME_DOMAIN
) ||
149 (name
->name
.string
== NULL
)) {
150 state
->result
[i
]->name
=
151 talloc_strdup(state
->result
[i
], "");
153 state
->result
[i
]->name
=
154 talloc_steal(state
->result
[i
],
158 if (composite_nomem(state
->result
[i
]->name
, state
->ctx
)) {
163 composite_done(state
->ctx
);
166 NTSTATUS
wb_lsa_lookupsids_recv(struct composite_context
*c
,
168 struct wb_sid_object
***names
)
170 NTSTATUS status
= composite_wait(c
);
171 if (NT_STATUS_IS_OK(status
)) {
172 struct lsa_lookupsids_state
*state
=
173 talloc_get_type(c
->private_data
,
174 struct lsa_lookupsids_state
);
175 *names
= talloc_steal(mem_ctx
, state
->result
);
182 struct lsa_lookupnames_state
{
183 struct composite_context
*ctx
;
185 struct lsa_LookupNames r
;
186 struct lsa_TransSidArray sids
;
187 struct lsa_RefDomainList
*domains
;
189 struct wb_sid_object
**result
;
192 static void lsa_lookupnames_recv_sids(struct rpc_request
*req
);
194 struct composite_context
*wb_lsa_lookupnames_send(TALLOC_CTX
*mem_ctx
,
195 struct dcerpc_pipe
*lsa_pipe
,
196 struct policy_handle
*handle
,
200 struct composite_context
*result
;
201 struct rpc_request
*req
;
202 struct lsa_lookupnames_state
*state
;
204 struct lsa_String
*lsa_names
;
207 result
= composite_create(mem_ctx
, lsa_pipe
->conn
->event_ctx
);
208 if (result
== NULL
) goto failed
;
210 state
= talloc(result
, struct lsa_lookupnames_state
);
211 if (state
== NULL
) goto failed
;
212 result
->private_data
= state
;
215 state
->sids
.count
= 0;
216 state
->sids
.sids
= NULL
;
217 state
->num_names
= num_names
;
220 lsa_names
= talloc_array(state
, struct lsa_String
, num_names
);
221 if (lsa_names
== NULL
) goto failed
;
223 for (i
=0; i
<num_names
; i
++) {
224 lsa_names
[i
].string
= names
[i
];
227 state
->domains
= talloc(state
, struct lsa_RefDomainList
);
228 if (state
->domains
== NULL
) goto failed
;
230 state
->r
.in
.handle
= handle
;
231 state
->r
.in
.num_names
= num_names
;
232 state
->r
.in
.names
= lsa_names
;
233 state
->r
.in
.sids
= &state
->sids
;
234 state
->r
.in
.level
= 1;
235 state
->r
.in
.count
= &state
->count
;
236 state
->r
.out
.count
= &state
->count
;
237 state
->r
.out
.sids
= &state
->sids
;
238 state
->r
.out
.domains
= &state
->domains
;
240 req
= dcerpc_lsa_LookupNames_send(lsa_pipe
, state
, &state
->r
);
241 if (req
== NULL
) goto failed
;
243 req
->async
.callback
= lsa_lookupnames_recv_sids
;
244 req
->async
.private_data
= state
;
252 static void lsa_lookupnames_recv_sids(struct rpc_request
*req
)
254 struct lsa_lookupnames_state
*state
=
255 talloc_get_type(req
->async
.private_data
,
256 struct lsa_lookupnames_state
);
259 state
->ctx
->status
= dcerpc_lsa_LookupNames_recv(req
);
260 if (!composite_is_ok(state
->ctx
)) return;
261 state
->ctx
->status
= state
->r
.out
.result
;
262 if (!NT_STATUS_IS_OK(state
->ctx
->status
) &&
263 !NT_STATUS_EQUAL(state
->ctx
->status
, STATUS_SOME_UNMAPPED
)) {
264 composite_error(state
->ctx
, state
->ctx
->status
);
268 state
->result
= talloc_array(state
, struct wb_sid_object
*,
270 if (composite_nomem(state
->result
, state
->ctx
)) return;
272 for (i
=0; i
<state
->num_names
; i
++) {
273 struct lsa_TranslatedSid
*sid
= &state
->r
.out
.sids
->sids
[i
];
274 struct lsa_RefDomainList
*domains
= state
->domains
;
275 struct lsa_DomainInfo
*dom
;
277 state
->result
[i
] = talloc_zero(state
->result
,
278 struct wb_sid_object
);
279 if (composite_nomem(state
->result
[i
], state
->ctx
)) return;
281 state
->result
[i
]->type
= sid
->sid_type
;
282 if (state
->result
[i
]->type
== SID_NAME_UNKNOWN
) {
286 if (sid
->sid_index
>= domains
->count
) {
287 composite_error(state
->ctx
,
288 NT_STATUS_INVALID_PARAMETER
);
292 dom
= &domains
->domains
[sid
->sid_index
];
294 state
->result
[i
]->sid
= dom_sid_add_rid(state
->result
[i
],
298 composite_done(state
->ctx
);
301 NTSTATUS
wb_lsa_lookupnames_recv(struct composite_context
*c
,
303 struct wb_sid_object
***sids
)
305 NTSTATUS status
= composite_wait(c
);
306 if (NT_STATUS_IS_OK(status
)) {
307 struct lsa_lookupnames_state
*state
=
308 talloc_get_type(c
->private_data
,
309 struct lsa_lookupnames_state
);
310 *sids
= talloc_steal(mem_ctx
, state
->result
);
315 struct samr_getuserdomgroups_state
{
316 struct composite_context
*ctx
;
317 struct dcerpc_pipe
*samr_pipe
;
322 struct samr_RidWithAttributeArray
*rid_array
;
324 struct policy_handle
*user_handle
;
325 struct samr_OpenUser o
;
326 struct samr_GetGroupsForUser g
;
330 static void samr_usergroups_recv_open(struct rpc_request
*req
);
331 static void samr_usergroups_recv_groups(struct rpc_request
*req
);
332 static void samr_usergroups_recv_close(struct rpc_request
*req
);
334 struct composite_context
*wb_samr_userdomgroups_send(TALLOC_CTX
*mem_ctx
,
335 struct dcerpc_pipe
*samr_pipe
,
336 struct policy_handle
*domain_handle
,
339 struct composite_context
*result
;
340 struct rpc_request
*req
;
341 struct samr_getuserdomgroups_state
*state
;
343 result
= composite_create(mem_ctx
, samr_pipe
->conn
->event_ctx
);
344 if (result
== NULL
) goto failed
;
346 state
= talloc(result
, struct samr_getuserdomgroups_state
);
347 if (state
== NULL
) goto failed
;
348 result
->private_data
= state
;
351 state
->samr_pipe
= samr_pipe
;
353 state
->user_handle
= talloc(state
, struct policy_handle
);
354 if (state
->user_handle
== NULL
) goto failed
;
356 state
->o
.in
.domain_handle
= domain_handle
;
357 state
->o
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
358 state
->o
.in
.rid
= rid
;
359 state
->o
.out
.user_handle
= state
->user_handle
;
361 req
= dcerpc_samr_OpenUser_send(state
->samr_pipe
, state
, &state
->o
);
362 if (req
== NULL
) goto failed
;
364 req
->async
.callback
= samr_usergroups_recv_open
;
365 req
->async
.private_data
= state
;
373 static void samr_usergroups_recv_open(struct rpc_request
*req
)
375 struct samr_getuserdomgroups_state
*state
=
376 talloc_get_type(req
->async
.private_data
,
377 struct samr_getuserdomgroups_state
);
379 state
->ctx
->status
= dcerpc_samr_OpenUser_recv(req
);
380 if (!composite_is_ok(state
->ctx
)) return;
381 state
->ctx
->status
= state
->o
.out
.result
;
382 if (!composite_is_ok(state
->ctx
)) return;
384 state
->g
.in
.user_handle
= state
->user_handle
;
385 state
->g
.out
.rids
= &state
->rid_array
;
387 req
= dcerpc_samr_GetGroupsForUser_send(state
->samr_pipe
, state
,
389 composite_continue_rpc(state
->ctx
, req
, samr_usergroups_recv_groups
,
393 static void samr_usergroups_recv_groups(struct rpc_request
*req
)
395 struct samr_getuserdomgroups_state
*state
=
396 talloc_get_type(req
->async
.private_data
,
397 struct samr_getuserdomgroups_state
);
399 state
->ctx
->status
= dcerpc_samr_GetGroupsForUser_recv(req
);
400 if (!composite_is_ok(state
->ctx
)) return;
401 state
->ctx
->status
= state
->g
.out
.result
;
402 if (!composite_is_ok(state
->ctx
)) return;
404 state
->c
.in
.handle
= state
->user_handle
;
405 state
->c
.out
.handle
= state
->user_handle
;
407 req
= dcerpc_samr_Close_send(state
->samr_pipe
, state
, &state
->c
);
408 composite_continue_rpc(state
->ctx
, req
, samr_usergroups_recv_close
,
412 static void samr_usergroups_recv_close(struct rpc_request
*req
)
414 struct samr_getuserdomgroups_state
*state
=
415 talloc_get_type(req
->async
.private_data
,
416 struct samr_getuserdomgroups_state
);
418 state
->ctx
->status
= dcerpc_samr_Close_recv(req
);
419 if (!composite_is_ok(state
->ctx
)) return;
420 state
->ctx
->status
= state
->c
.out
.result
;
421 if (!composite_is_ok(state
->ctx
)) return;
423 composite_done(state
->ctx
);
426 NTSTATUS
wb_samr_userdomgroups_recv(struct composite_context
*ctx
,
428 int *num_rids
, uint32_t **rids
)
430 struct samr_getuserdomgroups_state
*state
=
431 talloc_get_type(ctx
->private_data
,
432 struct samr_getuserdomgroups_state
);
435 NTSTATUS status
= composite_wait(ctx
);
436 if (!NT_STATUS_IS_OK(status
)) goto done
;
438 *num_rids
= state
->rid_array
->count
;
439 *rids
= talloc_array(mem_ctx
, uint32_t, *num_rids
);
441 status
= NT_STATUS_NO_MEMORY
;
445 for (i
=0; i
<*num_rids
; i
++) {
446 (*rids
)[i
] = state
->rid_array
->rids
[i
].rid
;