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 2 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, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 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 "lib/messaging/irpc.h"
29 #include "librpc/gen_ndr/irpc.h"
30 #include "libcli/auth/credentials.h"
31 #include "libcli/security/proto.h"
32 #include "libcli/auth/libcli_auth.h"
33 #include "librpc/gen_ndr/ndr_netlogon_c.h"
34 #include "librpc/gen_ndr/ndr_lsa_c.h"
35 #include "librpc/gen_ndr/ndr_samr_c.h"
37 #include "winbind/wb_helper.h"
39 struct get_schannel_creds_state
{
40 struct cli_credentials
*wks_creds
;
41 struct dcerpc_pipe
*p
;
42 struct netr_ServerReqChallenge r
;
44 struct creds_CredentialState
*creds_state
;
45 struct netr_Credential netr_cred
;
46 uint32_t negotiate_flags
;
47 struct netr_ServerAuthenticate2 a
;
50 static void get_schannel_creds_recv_anonbind(struct composite_context
*creq
);
51 static void get_schannel_creds_recv_auth(struct rpc_request
*req
);
52 static void get_schannel_creds_recv_chal(struct rpc_request
*req
);
53 static void get_schannel_creds_recv_pipe(struct composite_context
*ctx
);
55 struct composite_context
*wb_get_schannel_creds_send(TALLOC_CTX
*mem_ctx
,
56 struct cli_credentials
*wks_creds
,
57 struct smbcli_tree
*tree
,
58 struct event_context
*ev
)
60 struct composite_context
*c
, *creq
;
61 struct get_schannel_creds_state
*state
;
63 c
= talloc_zero(mem_ctx
, struct composite_context
);
64 if (c
== NULL
) return NULL
;
66 state
= talloc(c
, struct get_schannel_creds_state
);
68 c
->status
= NT_STATUS_NO_MEMORY
;
72 c
->state
= COMPOSITE_STATE_IN_PROGRESS
;
73 c
->private_data
= state
;
76 state
->wks_creds
= wks_creds
;
78 state
->p
= dcerpc_pipe_init(state
, ev
);
79 if (state
->p
== NULL
) {
80 c
->status
= NT_STATUS_NO_MEMORY
;
84 creq
= dcerpc_pipe_open_smb_send(state
->p
->conn
, tree
, "\\netlogon");
86 c
->status
= NT_STATUS_NO_MEMORY
;
90 creq
->async
.fn
= get_schannel_creds_recv_pipe
;
91 creq
->async
.private_data
= c
;
96 composite_error(c
, c
->status
);
100 static void get_schannel_creds_recv_pipe(struct composite_context
*creq
)
102 struct composite_context
*c
=
103 talloc_get_type(creq
->async
.private_data
,
104 struct composite_context
);
105 struct get_schannel_creds_state
*state
=
106 talloc_get_type(c
->private_data
,
107 struct get_schannel_creds_state
);
109 c
->status
= dcerpc_pipe_open_smb_recv(creq
);
110 if (!composite_is_ok(c
)) return;
112 creq
= dcerpc_bind_auth_none_send(state
, state
->p
,
113 &dcerpc_table_netlogon
);
114 composite_continue(c
, creq
, get_schannel_creds_recv_anonbind
, c
);
117 static void get_schannel_creds_recv_anonbind(struct composite_context
*creq
)
119 struct composite_context
*c
=
120 talloc_get_type(creq
->async
.private_data
,
121 struct composite_context
);
122 struct get_schannel_creds_state
*state
=
123 talloc_get_type(c
->private_data
,
124 struct get_schannel_creds_state
);
125 struct rpc_request
*req
;
127 c
->status
= dcerpc_bind_auth_none_recv(creq
);
128 if (!composite_is_ok(c
)) return;
130 state
->r
.in
.computer_name
=
131 cli_credentials_get_workstation(state
->wks_creds
);
132 state
->r
.in
.server_name
=
133 talloc_asprintf(state
, "\\\\%s",
134 dcerpc_server_name(state
->p
));
135 if (composite_nomem(state
->r
.in
.server_name
, c
)) return;
137 state
->r
.in
.credentials
= talloc(state
, struct netr_Credential
);
138 if (composite_nomem(state
->r
.in
.credentials
, c
)) return;
140 state
->r
.out
.credentials
= talloc(state
, struct netr_Credential
);
141 if (composite_nomem(state
->r
.out
.credentials
, c
)) return;
143 generate_random_buffer(state
->r
.in
.credentials
->data
,
144 sizeof(state
->r
.in
.credentials
->data
));
146 req
= dcerpc_netr_ServerReqChallenge_send(state
->p
, state
, &state
->r
);
147 composite_continue_rpc(c
, req
, get_schannel_creds_recv_chal
, c
);
150 static void get_schannel_creds_recv_chal(struct rpc_request
*req
)
152 struct composite_context
*c
=
153 talloc_get_type(req
->async
.private,
154 struct composite_context
);
155 struct get_schannel_creds_state
*state
=
156 talloc_get_type(c
->private_data
,
157 struct get_schannel_creds_state
);
158 const struct samr_Password
*mach_pwd
;
160 c
->status
= dcerpc_ndr_request_recv(req
);
161 if (!composite_is_ok(c
)) return;
162 c
->status
= state
->r
.out
.result
;
163 if (!composite_is_ok(c
)) return;
165 state
->creds_state
= talloc(state
, struct creds_CredentialState
);
166 if (composite_nomem(state
->creds_state
, c
)) return;
168 mach_pwd
= cli_credentials_get_nt_hash(state
->wks_creds
, state
);
169 if (composite_nomem(mach_pwd
, c
)) return;
171 state
->negotiate_flags
= NETLOGON_NEG_AUTH2_FLAGS
;
173 creds_client_init(state
->creds_state
, state
->r
.in
.credentials
,
174 state
->r
.out
.credentials
, mach_pwd
,
175 &state
->netr_cred
, state
->negotiate_flags
);
177 state
->a
.in
.server_name
=
178 talloc_reference(state
, state
->r
.in
.server_name
);
179 state
->a
.in
.account_name
=
180 cli_credentials_get_username(state
->wks_creds
);
181 state
->a
.in
.secure_channel_type
=
182 cli_credentials_get_secure_channel_type(state
->wks_creds
);
183 state
->a
.in
.computer_name
=
184 cli_credentials_get_workstation(state
->wks_creds
);
185 state
->a
.in
.negotiate_flags
= &state
->negotiate_flags
;
186 state
->a
.out
.negotiate_flags
= &state
->negotiate_flags
;
187 state
->a
.in
.credentials
= &state
->netr_cred
;
188 state
->a
.out
.credentials
= &state
->netr_cred
;
190 req
= dcerpc_netr_ServerAuthenticate2_send(state
->p
, state
, &state
->a
);
191 composite_continue_rpc(c
, req
, get_schannel_creds_recv_auth
, c
);
194 static void get_schannel_creds_recv_auth(struct rpc_request
*req
)
196 struct composite_context
*c
=
197 talloc_get_type(req
->async
.private,
198 struct composite_context
);
199 struct get_schannel_creds_state
*state
=
200 talloc_get_type(c
->private_data
,
201 struct get_schannel_creds_state
);
203 c
->status
= dcerpc_ndr_request_recv(req
);
204 if (!composite_is_ok(c
)) return;
205 c
->status
= state
->a
.out
.result
;
206 if (!composite_is_ok(c
)) return;
208 if (!creds_client_check(state
->creds_state
,
209 state
->a
.out
.credentials
)) {
210 DEBUG(5, ("Server got us invalid creds\n"));
211 composite_error(c
, NT_STATUS_UNSUCCESSFUL
);
215 cli_credentials_set_netlogon_creds(state
->wks_creds
,
221 NTSTATUS
wb_get_schannel_creds_recv(struct composite_context
*c
,
223 struct dcerpc_pipe
**netlogon_pipe
)
225 NTSTATUS status
= composite_wait(c
);
226 if (NT_STATUS_IS_OK(status
)) {
227 struct get_schannel_creds_state
*state
=
228 talloc_get_type(c
->private_data
,
229 struct get_schannel_creds_state
);
230 *netlogon_pipe
= talloc_steal(mem_ctx
, state
->p
);
236 NTSTATUS
wb_get_schannel_creds(TALLOC_CTX
*mem_ctx
,
237 struct cli_credentials
*wks_creds
,
238 struct smbcli_tree
*tree
,
239 struct event_context
*event_ctx
,
240 struct dcerpc_pipe
**netlogon_pipe
)
242 struct composite_context
*c
=
243 wb_get_schannel_creds_send(mem_ctx
, wks_creds
, tree
,
245 return wb_get_schannel_creds_recv(c
, mem_ctx
, netlogon_pipe
);
248 struct lsa_lookupsids_state
{
249 struct composite_context
*ctx
;
251 struct lsa_LookupSids r
;
252 struct lsa_SidArray sids
;
253 struct lsa_TransNameArray names
;
255 struct wb_sid_object
**result
;
258 static void lsa_lookupsids_recv_names(struct rpc_request
*req
);
260 struct composite_context
*wb_lsa_lookupsids_send(TALLOC_CTX
*mem_ctx
,
261 struct dcerpc_pipe
*lsa_pipe
,
262 struct policy_handle
*handle
,
264 const struct dom_sid
**sids
)
266 struct composite_context
*result
;
267 struct rpc_request
*req
;
268 struct lsa_lookupsids_state
*state
;
271 result
= talloc(mem_ctx
, struct composite_context
);
272 if (result
== NULL
) goto failed
;
273 result
->state
= COMPOSITE_STATE_IN_PROGRESS
;
274 result
->async
.fn
= NULL
;
275 result
->event_ctx
= lsa_pipe
->conn
->event_ctx
;
277 state
= talloc(result
, struct lsa_lookupsids_state
);
278 if (state
== NULL
) goto failed
;
279 result
->private_data
= state
;
282 state
->sids
.num_sids
= num_sids
;
283 state
->sids
.sids
= talloc_array(state
, struct lsa_SidPtr
, num_sids
);
284 if (state
->sids
.sids
== NULL
) goto failed
;
286 for (i
=0; i
<num_sids
; i
++) {
287 state
->sids
.sids
[i
].sid
= dom_sid_dup(state
->sids
.sids
,
289 if (state
->sids
.sids
[i
].sid
== NULL
) goto failed
;
293 state
->num_sids
= num_sids
;
294 state
->names
.count
= 0;
295 state
->names
.names
= NULL
;
297 state
->r
.in
.handle
= handle
;
298 state
->r
.in
.sids
= &state
->sids
;
299 state
->r
.in
.names
= &state
->names
;
300 state
->r
.in
.level
= 1;
301 state
->r
.in
.count
= &state
->count
;
302 state
->r
.out
.names
= &state
->names
;
303 state
->r
.out
.count
= &state
->count
;
305 req
= dcerpc_lsa_LookupSids_send(lsa_pipe
, state
, &state
->r
);
306 if (req
== NULL
) goto failed
;
308 req
->async
.callback
= lsa_lookupsids_recv_names
;
309 req
->async
.private = state
;
317 static void lsa_lookupsids_recv_names(struct rpc_request
*req
)
319 struct lsa_lookupsids_state
*state
=
320 talloc_get_type(req
->async
.private,
321 struct lsa_lookupsids_state
);
324 state
->ctx
->status
= dcerpc_ndr_request_recv(req
);
325 if (!composite_is_ok(state
->ctx
)) return;
326 state
->ctx
->status
= state
->r
.out
.result
;
327 if (!NT_STATUS_IS_OK(state
->ctx
->status
) &&
328 !NT_STATUS_EQUAL(state
->ctx
->status
, STATUS_SOME_UNMAPPED
)) {
329 composite_error(state
->ctx
, state
->ctx
->status
);
333 state
->result
= talloc_array(state
, struct wb_sid_object
*,
335 if (composite_nomem(state
->result
, state
->ctx
)) return;
337 for (i
=0; i
<state
->num_sids
; i
++) {
338 struct lsa_TranslatedName
*name
=
339 &state
->r
.out
.names
->names
[i
];
340 struct lsa_TrustInformation
*dom
;
342 state
->result
[i
] = talloc_zero(state
->result
,
343 struct wb_sid_object
);
344 if (composite_nomem(state
->result
[i
], state
->ctx
)) return;
346 state
->result
[i
]->type
= name
->sid_type
;
347 if (state
->result
[i
]->type
== SID_NAME_UNKNOWN
) {
351 if (name
->sid_index
>= state
->r
.out
.domains
->count
) {
352 composite_error(state
->ctx
,
353 NT_STATUS_INVALID_PARAMETER
);
357 dom
= &state
->r
.out
.domains
->domains
[name
->sid_index
];
358 state
->result
[i
]->domain
= talloc_reference(state
->result
[i
],
360 if ((name
->sid_type
== SID_NAME_DOMAIN
) ||
361 (name
->name
.string
== NULL
)) {
362 state
->result
[i
]->name
=
363 talloc_strdup(state
->result
[i
], "");
365 state
->result
[i
]->name
=
366 talloc_steal(state
->result
[i
],
370 if (composite_nomem(state
->result
[i
]->name
, state
->ctx
)) {
375 composite_done(state
->ctx
);
378 NTSTATUS
wb_lsa_lookupsids_recv(struct composite_context
*c
,
380 struct wb_sid_object
***names
)
382 NTSTATUS status
= composite_wait(c
);
383 if (NT_STATUS_IS_OK(status
)) {
384 struct lsa_lookupsids_state
*state
=
385 talloc_get_type(c
->private_data
,
386 struct lsa_lookupsids_state
);
387 *names
= talloc_steal(mem_ctx
, state
->result
);
393 NTSTATUS
wb_lsa_lookupsids(TALLOC_CTX
*mem_ctx
,
394 struct dcerpc_pipe
*lsa_pipe
,
395 struct policy_handle
*handle
,
396 int num_sids
, const struct dom_sid
**sids
,
397 struct wb_sid_object
***names
)
399 struct composite_context
*c
=
400 wb_lsa_lookupsids_send(mem_ctx
, lsa_pipe
, handle
,
402 return wb_lsa_lookupnames_recv(c
, mem_ctx
, names
);
407 struct lsa_lookupnames_state
{
408 struct composite_context
*ctx
;
410 struct lsa_LookupNames r
;
411 struct lsa_TransSidArray sids
;
413 struct wb_sid_object
**result
;
416 static void lsa_lookupnames_recv_sids(struct rpc_request
*req
);
418 struct composite_context
*wb_lsa_lookupnames_send(TALLOC_CTX
*mem_ctx
,
419 struct dcerpc_pipe
*lsa_pipe
,
420 struct policy_handle
*handle
,
424 struct composite_context
*result
;
425 struct rpc_request
*req
;
426 struct lsa_lookupnames_state
*state
;
428 struct lsa_String
*lsa_names
;
431 result
= talloc(mem_ctx
, struct composite_context
);
432 if (result
== NULL
) goto failed
;
433 result
->state
= COMPOSITE_STATE_IN_PROGRESS
;
434 result
->async
.fn
= NULL
;
435 result
->event_ctx
= lsa_pipe
->conn
->event_ctx
;
437 state
= talloc(result
, struct lsa_lookupnames_state
);
438 if (state
== NULL
) goto failed
;
439 result
->private_data
= state
;
442 state
->sids
.count
= 0;
443 state
->sids
.sids
= NULL
;
444 state
->num_names
= num_names
;
447 lsa_names
= talloc_array(state
, struct lsa_String
, num_names
);
448 if (lsa_names
== NULL
) goto failed
;
450 for (i
=0; i
<num_names
; i
++) {
451 lsa_names
[i
].string
= names
[i
];
454 state
->r
.in
.handle
= handle
;
455 state
->r
.in
.num_names
= num_names
;
456 state
->r
.in
.names
= lsa_names
;
457 state
->r
.in
.sids
= &state
->sids
;
458 state
->r
.in
.level
= 1;
459 state
->r
.in
.count
= &state
->count
;
460 state
->r
.out
.count
= &state
->count
;
461 state
->r
.out
.sids
= &state
->sids
;
463 req
= dcerpc_lsa_LookupNames_send(lsa_pipe
, state
, &state
->r
);
464 if (req
== NULL
) goto failed
;
466 req
->async
.callback
= lsa_lookupnames_recv_sids
;
467 req
->async
.private = state
;
475 static void lsa_lookupnames_recv_sids(struct rpc_request
*req
)
477 struct lsa_lookupnames_state
*state
=
478 talloc_get_type(req
->async
.private,
479 struct lsa_lookupnames_state
);
482 state
->ctx
->status
= dcerpc_ndr_request_recv(req
);
483 if (!composite_is_ok(state
->ctx
)) return;
484 state
->ctx
->status
= state
->r
.out
.result
;
485 if (!NT_STATUS_IS_OK(state
->ctx
->status
) &&
486 !NT_STATUS_EQUAL(state
->ctx
->status
, STATUS_SOME_UNMAPPED
)) {
487 composite_error(state
->ctx
, state
->ctx
->status
);
491 state
->result
= talloc_array(state
, struct wb_sid_object
*,
493 if (composite_nomem(state
->result
, state
->ctx
)) return;
495 for (i
=0; i
<state
->num_names
; i
++) {
496 struct lsa_TranslatedSid
*sid
= &state
->r
.out
.sids
->sids
[i
];
497 struct lsa_TrustInformation
*dom
;
499 state
->result
[i
] = talloc_zero(state
->result
,
500 struct wb_sid_object
);
501 if (composite_nomem(state
->result
[i
], state
->ctx
)) return;
503 state
->result
[i
]->type
= sid
->sid_type
;
504 if (state
->result
[i
]->type
== SID_NAME_UNKNOWN
) {
508 if (sid
->sid_index
>= state
->r
.out
.domains
->count
) {
509 composite_error(state
->ctx
,
510 NT_STATUS_INVALID_PARAMETER
);
514 dom
= &state
->r
.out
.domains
->domains
[sid
->sid_index
];
516 state
->result
[i
]->sid
= dom_sid_add_rid(state
->result
[i
],
520 composite_done(state
->ctx
);
523 NTSTATUS
wb_lsa_lookupnames_recv(struct composite_context
*c
,
525 struct wb_sid_object
***sids
)
527 NTSTATUS status
= composite_wait(c
);
528 if (NT_STATUS_IS_OK(status
)) {
529 struct lsa_lookupnames_state
*state
=
530 talloc_get_type(c
->private_data
,
531 struct lsa_lookupnames_state
);
532 *sids
= talloc_steal(mem_ctx
, state
->result
);
538 NTSTATUS
wb_lsa_lookupnames(TALLOC_CTX
*mem_ctx
,
539 struct dcerpc_pipe
*lsa_pipe
,
540 struct policy_handle
*handle
,
541 int num_names
, const char **names
,
542 struct wb_sid_object
***sids
)
544 struct composite_context
*c
=
545 wb_lsa_lookupnames_send(mem_ctx
, lsa_pipe
, handle
,
547 return wb_lsa_lookupnames_recv(c
, mem_ctx
, sids
);
552 struct cmd_checkmachacc_state
{
553 struct composite_context
*ctx
;
554 struct wbsrv_call
*call
;
555 struct wbsrv_domain
*domain
;
558 static void cmd_checkmachacc_recv_init(struct composite_context
*ctx
);
560 struct composite_context
*wb_cmd_checkmachacc_send(struct wbsrv_call
*call
)
562 struct composite_context
*result
, *ctx
;
563 struct cmd_checkmachacc_state
*state
;
564 struct wbsrv_service
*service
= call
->wbconn
->listen_socket
->service
;
566 result
= talloc(call
, struct composite_context
);
567 if (result
== NULL
) goto failed
;
568 result
->state
= COMPOSITE_STATE_IN_PROGRESS
;
569 result
->async
.fn
= NULL
;
570 result
->event_ctx
= call
->event_ctx
;
572 state
= talloc(result
, struct cmd_checkmachacc_state
);
573 if (state
== NULL
) goto failed
;
575 result
->private_data
= state
;
578 state
->domain
= service
->domains
;
580 ctx
= wb_init_domain_send(service
, state
->domain
);
581 if (ctx
== NULL
) goto failed
;
582 ctx
->async
.fn
= cmd_checkmachacc_recv_init
;
583 ctx
->async
.private_data
= state
;
592 static void cmd_checkmachacc_recv_init(struct composite_context
*ctx
)
594 struct cmd_checkmachacc_state
*state
=
595 talloc_get_type(ctx
->async
.private_data
,
596 struct cmd_checkmachacc_state
);
598 state
->ctx
->status
= wb_init_domain_recv(ctx
);
599 if (!composite_is_ok(state
->ctx
)) return;
601 composite_done(state
->ctx
);
604 NTSTATUS
wb_cmd_checkmachacc_recv(struct composite_context
*c
)
606 NTSTATUS status
= composite_wait(c
);
611 NTSTATUS
wb_cmd_checkmachacc(struct wbsrv_call
*call
)
613 struct composite_context
*c
= wb_cmd_checkmachacc_send(call
);
614 return wb_cmd_checkmachacc_recv(c
);
618 struct samr_getuserdomgroups_state
{
619 struct composite_context
*ctx
;
620 struct dcerpc_pipe
*samr_pipe
;
625 struct policy_handle
*user_handle
;
626 struct samr_OpenUser o
;
627 struct samr_GetGroupsForUser g
;
631 static void samr_usergroups_recv_open(struct rpc_request
*req
);
632 static void samr_usergroups_recv_groups(struct rpc_request
*req
);
633 static void samr_usergroups_recv_close(struct rpc_request
*req
);
635 struct composite_context
*wb_samr_userdomgroups_send(TALLOC_CTX
*mem_ctx
,
636 struct dcerpc_pipe
*samr_pipe
,
637 struct policy_handle
*domain_handle
,
640 struct composite_context
*result
;
641 struct rpc_request
*req
;
642 struct samr_getuserdomgroups_state
*state
;
644 result
= talloc(mem_ctx
, struct composite_context
);
645 if (result
== NULL
) goto failed
;
646 result
->state
= COMPOSITE_STATE_IN_PROGRESS
;
647 result
->async
.fn
= NULL
;
648 result
->event_ctx
= samr_pipe
->conn
->event_ctx
;
650 state
= talloc(result
, struct samr_getuserdomgroups_state
);
651 if (state
== NULL
) goto failed
;
652 result
->private_data
= state
;
655 state
->samr_pipe
= samr_pipe
;
657 state
->user_handle
= talloc(state
, struct policy_handle
);
658 if (state
->user_handle
== NULL
) goto failed
;
660 state
->o
.in
.domain_handle
= domain_handle
;
661 state
->o
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
662 state
->o
.in
.rid
= rid
;
663 state
->o
.out
.user_handle
= state
->user_handle
;
665 req
= dcerpc_samr_OpenUser_send(state
->samr_pipe
, state
, &state
->o
);
666 if (req
== NULL
) goto failed
;
668 req
->async
.callback
= samr_usergroups_recv_open
;
669 req
->async
.private = state
;
677 static void samr_usergroups_recv_open(struct rpc_request
*req
)
679 struct samr_getuserdomgroups_state
*state
=
680 talloc_get_type(req
->async
.private,
681 struct samr_getuserdomgroups_state
);
683 state
->ctx
->status
= dcerpc_ndr_request_recv(req
);
684 if (!composite_is_ok(state
->ctx
)) return;
685 state
->ctx
->status
= state
->o
.out
.result
;
686 if (!composite_is_ok(state
->ctx
)) return;
688 state
->g
.in
.user_handle
= state
->user_handle
;
690 req
= dcerpc_samr_GetGroupsForUser_send(state
->samr_pipe
, state
,
692 composite_continue_rpc(state
->ctx
, req
, samr_usergroups_recv_groups
,
696 static void samr_usergroups_recv_groups(struct rpc_request
*req
)
698 struct samr_getuserdomgroups_state
*state
=
699 talloc_get_type(req
->async
.private,
700 struct samr_getuserdomgroups_state
);
702 state
->ctx
->status
= dcerpc_ndr_request_recv(req
);
703 if (!composite_is_ok(state
->ctx
)) return;
704 state
->ctx
->status
= state
->g
.out
.result
;
705 if (!composite_is_ok(state
->ctx
)) return;
707 state
->c
.in
.handle
= state
->user_handle
;
708 state
->c
.out
.handle
= state
->user_handle
;
710 req
= dcerpc_samr_Close_send(state
->samr_pipe
, state
, &state
->c
);
711 composite_continue_rpc(state
->ctx
, req
, samr_usergroups_recv_close
,
715 static void samr_usergroups_recv_close(struct rpc_request
*req
)
717 struct samr_getuserdomgroups_state
*state
=
718 talloc_get_type(req
->async
.private,
719 struct samr_getuserdomgroups_state
);
721 state
->ctx
->status
= dcerpc_ndr_request_recv(req
);
722 if (!composite_is_ok(state
->ctx
)) return;
723 state
->ctx
->status
= state
->c
.out
.result
;
724 if (!composite_is_ok(state
->ctx
)) return;
726 composite_done(state
->ctx
);
729 NTSTATUS
wb_samr_userdomgroups_recv(struct composite_context
*ctx
,
731 int *num_rids
, uint32_t **rids
)
733 struct samr_getuserdomgroups_state
*state
=
734 talloc_get_type(ctx
->private_data
,
735 struct samr_getuserdomgroups_state
);
738 NTSTATUS status
= composite_wait(ctx
);
739 if (!NT_STATUS_IS_OK(status
)) goto done
;
741 *num_rids
= state
->g
.out
.rids
->count
;
742 *rids
= talloc_array(mem_ctx
, uint32_t, *num_rids
);
744 status
= NT_STATUS_NO_MEMORY
;
748 for (i
=0; i
<*num_rids
; i
++) {
749 (*rids
)[i
] = state
->g
.out
.rids
->rids
[i
].rid
;