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 "lib/messaging/irpc.h"
28 #include "librpc/gen_ndr/irpc.h"
29 #include "auth/credentials/credentials.h"
30 #include "libcli/security/security.h"
31 #include "libcli/auth/libcli_auth.h"
32 #include "librpc/gen_ndr/ndr_netlogon_c.h"
33 #include "librpc/gen_ndr/ndr_lsa_c.h"
34 #include "librpc/gen_ndr/ndr_samr_c.h"
36 #include "winbind/wb_helper.h"
38 struct lsa_lookupsids_state
{
39 struct composite_context
*ctx
;
41 struct lsa_LookupSids r
;
42 struct lsa_SidArray sids
;
43 struct lsa_TransNameArray names
;
45 struct wb_sid_object
**result
;
48 static void lsa_lookupsids_recv_names(struct rpc_request
*req
);
50 struct composite_context
*wb_lsa_lookupsids_send(TALLOC_CTX
*mem_ctx
,
51 struct dcerpc_pipe
*lsa_pipe
,
52 struct policy_handle
*handle
,
54 const struct dom_sid
**sids
)
56 struct composite_context
*result
;
57 struct rpc_request
*req
;
58 struct lsa_lookupsids_state
*state
;
61 result
= composite_create(mem_ctx
, lsa_pipe
->conn
->event_ctx
);
62 if (result
== NULL
) goto failed
;
64 state
= talloc(result
, struct lsa_lookupsids_state
);
65 if (state
== NULL
) goto failed
;
66 result
->private_data
= state
;
69 state
->sids
.num_sids
= num_sids
;
70 state
->sids
.sids
= talloc_array(state
, struct lsa_SidPtr
, num_sids
);
71 if (state
->sids
.sids
== NULL
) goto failed
;
73 for (i
=0; i
<num_sids
; i
++) {
74 state
->sids
.sids
[i
].sid
= dom_sid_dup(state
->sids
.sids
,
76 if (state
->sids
.sids
[i
].sid
== NULL
) goto failed
;
80 state
->num_sids
= num_sids
;
81 state
->names
.count
= 0;
82 state
->names
.names
= NULL
;
84 state
->r
.in
.handle
= handle
;
85 state
->r
.in
.sids
= &state
->sids
;
86 state
->r
.in
.names
= &state
->names
;
87 state
->r
.in
.level
= 1;
88 state
->r
.in
.count
= &state
->count
;
89 state
->r
.out
.names
= &state
->names
;
90 state
->r
.out
.count
= &state
->count
;
92 req
= dcerpc_lsa_LookupSids_send(lsa_pipe
, state
, &state
->r
);
93 if (req
== NULL
) goto failed
;
95 req
->async
.callback
= lsa_lookupsids_recv_names
;
96 req
->async
.private_data
= state
;
104 static void lsa_lookupsids_recv_names(struct rpc_request
*req
)
106 struct lsa_lookupsids_state
*state
=
107 talloc_get_type(req
->async
.private_data
,
108 struct lsa_lookupsids_state
);
111 state
->ctx
->status
= dcerpc_ndr_request_recv(req
);
112 if (!composite_is_ok(state
->ctx
)) return;
113 state
->ctx
->status
= state
->r
.out
.result
;
114 if (!NT_STATUS_IS_OK(state
->ctx
->status
) &&
115 !NT_STATUS_EQUAL(state
->ctx
->status
, STATUS_SOME_UNMAPPED
)) {
116 composite_error(state
->ctx
, state
->ctx
->status
);
120 state
->result
= talloc_array(state
, struct wb_sid_object
*,
122 if (composite_nomem(state
->result
, state
->ctx
)) return;
124 for (i
=0; i
<state
->num_sids
; i
++) {
125 struct lsa_TranslatedName
*name
=
126 &state
->r
.out
.names
->names
[i
];
127 struct lsa_DomainInfo
*dom
;
129 state
->result
[i
] = talloc_zero(state
->result
,
130 struct wb_sid_object
);
131 if (composite_nomem(state
->result
[i
], state
->ctx
)) return;
133 state
->result
[i
]->type
= name
->sid_type
;
134 if (state
->result
[i
]->type
== SID_NAME_UNKNOWN
) {
138 if (name
->sid_index
>= state
->r
.out
.domains
->count
) {
139 composite_error(state
->ctx
,
140 NT_STATUS_INVALID_PARAMETER
);
144 dom
= &state
->r
.out
.domains
->domains
[name
->sid_index
];
145 state
->result
[i
]->domain
= talloc_reference(state
->result
[i
],
147 if ((name
->sid_type
== SID_NAME_DOMAIN
) ||
148 (name
->name
.string
== NULL
)) {
149 state
->result
[i
]->name
=
150 talloc_strdup(state
->result
[i
], "");
152 state
->result
[i
]->name
=
153 talloc_steal(state
->result
[i
],
157 if (composite_nomem(state
->result
[i
]->name
, state
->ctx
)) {
162 composite_done(state
->ctx
);
165 NTSTATUS
wb_lsa_lookupsids_recv(struct composite_context
*c
,
167 struct wb_sid_object
***names
)
169 NTSTATUS status
= composite_wait(c
);
170 if (NT_STATUS_IS_OK(status
)) {
171 struct lsa_lookupsids_state
*state
=
172 talloc_get_type(c
->private_data
,
173 struct lsa_lookupsids_state
);
174 *names
= talloc_steal(mem_ctx
, state
->result
);
181 struct lsa_lookupnames_state
{
182 struct composite_context
*ctx
;
184 struct lsa_LookupNames r
;
185 struct lsa_TransSidArray sids
;
187 struct wb_sid_object
**result
;
190 static void lsa_lookupnames_recv_sids(struct rpc_request
*req
);
192 struct composite_context
*wb_lsa_lookupnames_send(TALLOC_CTX
*mem_ctx
,
193 struct dcerpc_pipe
*lsa_pipe
,
194 struct policy_handle
*handle
,
198 struct composite_context
*result
;
199 struct rpc_request
*req
;
200 struct lsa_lookupnames_state
*state
;
202 struct lsa_String
*lsa_names
;
205 result
= composite_create(mem_ctx
, lsa_pipe
->conn
->event_ctx
);
206 if (result
== NULL
) goto failed
;
208 state
= talloc(result
, struct lsa_lookupnames_state
);
209 if (state
== NULL
) goto failed
;
210 result
->private_data
= state
;
213 state
->sids
.count
= 0;
214 state
->sids
.sids
= NULL
;
215 state
->num_names
= num_names
;
218 lsa_names
= talloc_array(state
, struct lsa_String
, num_names
);
219 if (lsa_names
== NULL
) goto failed
;
221 for (i
=0; i
<num_names
; i
++) {
222 lsa_names
[i
].string
= names
[i
];
225 state
->r
.in
.handle
= handle
;
226 state
->r
.in
.num_names
= num_names
;
227 state
->r
.in
.names
= lsa_names
;
228 state
->r
.in
.sids
= &state
->sids
;
229 state
->r
.in
.level
= 1;
230 state
->r
.in
.count
= &state
->count
;
231 state
->r
.out
.count
= &state
->count
;
232 state
->r
.out
.sids
= &state
->sids
;
234 req
= dcerpc_lsa_LookupNames_send(lsa_pipe
, state
, &state
->r
);
235 if (req
== NULL
) goto failed
;
237 req
->async
.callback
= lsa_lookupnames_recv_sids
;
238 req
->async
.private_data
= state
;
246 static void lsa_lookupnames_recv_sids(struct rpc_request
*req
)
248 struct lsa_lookupnames_state
*state
=
249 talloc_get_type(req
->async
.private_data
,
250 struct lsa_lookupnames_state
);
253 state
->ctx
->status
= dcerpc_ndr_request_recv(req
);
254 if (!composite_is_ok(state
->ctx
)) return;
255 state
->ctx
->status
= state
->r
.out
.result
;
256 if (!NT_STATUS_IS_OK(state
->ctx
->status
) &&
257 !NT_STATUS_EQUAL(state
->ctx
->status
, STATUS_SOME_UNMAPPED
)) {
258 composite_error(state
->ctx
, state
->ctx
->status
);
262 state
->result
= talloc_array(state
, struct wb_sid_object
*,
264 if (composite_nomem(state
->result
, state
->ctx
)) return;
266 for (i
=0; i
<state
->num_names
; i
++) {
267 struct lsa_TranslatedSid
*sid
= &state
->r
.out
.sids
->sids
[i
];
268 struct lsa_DomainInfo
*dom
;
270 state
->result
[i
] = talloc_zero(state
->result
,
271 struct wb_sid_object
);
272 if (composite_nomem(state
->result
[i
], state
->ctx
)) return;
274 state
->result
[i
]->type
= sid
->sid_type
;
275 if (state
->result
[i
]->type
== SID_NAME_UNKNOWN
) {
279 if (sid
->sid_index
>= state
->r
.out
.domains
->count
) {
280 composite_error(state
->ctx
,
281 NT_STATUS_INVALID_PARAMETER
);
285 dom
= &state
->r
.out
.domains
->domains
[sid
->sid_index
];
287 state
->result
[i
]->sid
= dom_sid_add_rid(state
->result
[i
],
291 composite_done(state
->ctx
);
294 NTSTATUS
wb_lsa_lookupnames_recv(struct composite_context
*c
,
296 struct wb_sid_object
***sids
)
298 NTSTATUS status
= composite_wait(c
);
299 if (NT_STATUS_IS_OK(status
)) {
300 struct lsa_lookupnames_state
*state
=
301 talloc_get_type(c
->private_data
,
302 struct lsa_lookupnames_state
);
303 *sids
= talloc_steal(mem_ctx
, state
->result
);
308 struct samr_getuserdomgroups_state
{
309 struct composite_context
*ctx
;
310 struct dcerpc_pipe
*samr_pipe
;
315 struct policy_handle
*user_handle
;
316 struct samr_OpenUser o
;
317 struct samr_GetGroupsForUser g
;
321 static void samr_usergroups_recv_open(struct rpc_request
*req
);
322 static void samr_usergroups_recv_groups(struct rpc_request
*req
);
323 static void samr_usergroups_recv_close(struct rpc_request
*req
);
325 struct composite_context
*wb_samr_userdomgroups_send(TALLOC_CTX
*mem_ctx
,
326 struct dcerpc_pipe
*samr_pipe
,
327 struct policy_handle
*domain_handle
,
330 struct composite_context
*result
;
331 struct rpc_request
*req
;
332 struct samr_getuserdomgroups_state
*state
;
334 result
= composite_create(mem_ctx
, samr_pipe
->conn
->event_ctx
);
335 if (result
== NULL
) goto failed
;
337 state
= talloc(result
, struct samr_getuserdomgroups_state
);
338 if (state
== NULL
) goto failed
;
339 result
->private_data
= state
;
342 state
->samr_pipe
= samr_pipe
;
344 state
->user_handle
= talloc(state
, struct policy_handle
);
345 if (state
->user_handle
== NULL
) goto failed
;
347 state
->o
.in
.domain_handle
= domain_handle
;
348 state
->o
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
349 state
->o
.in
.rid
= rid
;
350 state
->o
.out
.user_handle
= state
->user_handle
;
352 req
= dcerpc_samr_OpenUser_send(state
->samr_pipe
, state
, &state
->o
);
353 if (req
== NULL
) goto failed
;
355 req
->async
.callback
= samr_usergroups_recv_open
;
356 req
->async
.private_data
= state
;
364 static void samr_usergroups_recv_open(struct rpc_request
*req
)
366 struct samr_getuserdomgroups_state
*state
=
367 talloc_get_type(req
->async
.private_data
,
368 struct samr_getuserdomgroups_state
);
370 state
->ctx
->status
= dcerpc_ndr_request_recv(req
);
371 if (!composite_is_ok(state
->ctx
)) return;
372 state
->ctx
->status
= state
->o
.out
.result
;
373 if (!composite_is_ok(state
->ctx
)) return;
375 state
->g
.in
.user_handle
= state
->user_handle
;
377 req
= dcerpc_samr_GetGroupsForUser_send(state
->samr_pipe
, state
,
379 composite_continue_rpc(state
->ctx
, req
, samr_usergroups_recv_groups
,
383 static void samr_usergroups_recv_groups(struct rpc_request
*req
)
385 struct samr_getuserdomgroups_state
*state
=
386 talloc_get_type(req
->async
.private_data
,
387 struct samr_getuserdomgroups_state
);
389 state
->ctx
->status
= dcerpc_ndr_request_recv(req
);
390 if (!composite_is_ok(state
->ctx
)) return;
391 state
->ctx
->status
= state
->g
.out
.result
;
392 if (!composite_is_ok(state
->ctx
)) return;
394 state
->c
.in
.handle
= state
->user_handle
;
395 state
->c
.out
.handle
= state
->user_handle
;
397 req
= dcerpc_samr_Close_send(state
->samr_pipe
, state
, &state
->c
);
398 composite_continue_rpc(state
->ctx
, req
, samr_usergroups_recv_close
,
402 static void samr_usergroups_recv_close(struct rpc_request
*req
)
404 struct samr_getuserdomgroups_state
*state
=
405 talloc_get_type(req
->async
.private_data
,
406 struct samr_getuserdomgroups_state
);
408 state
->ctx
->status
= dcerpc_ndr_request_recv(req
);
409 if (!composite_is_ok(state
->ctx
)) return;
410 state
->ctx
->status
= state
->c
.out
.result
;
411 if (!composite_is_ok(state
->ctx
)) return;
413 composite_done(state
->ctx
);
416 NTSTATUS
wb_samr_userdomgroups_recv(struct composite_context
*ctx
,
418 int *num_rids
, uint32_t **rids
)
420 struct samr_getuserdomgroups_state
*state
=
421 talloc_get_type(ctx
->private_data
,
422 struct samr_getuserdomgroups_state
);
425 NTSTATUS status
= composite_wait(ctx
);
426 if (!NT_STATUS_IS_OK(status
)) goto done
;
428 *num_rids
= state
->g
.out
.rids
->count
;
429 *rids
= talloc_array(mem_ctx
, uint32_t, *num_rids
);
431 status
= NT_STATUS_NO_MEMORY
;
435 for (i
=0; i
<*num_rids
; i
++) {
436 (*rids
)[i
] = state
->g
.out
.rids
->rids
[i
].rid
;