2 Unix SMB/CIFS implementation.
4 Async helpers for blocking functions
6 Copyright (C) Volker Lendecke 2005
7 Copyright (C) Gerald Carter 2006
9 The helpers always consist of three functions:
11 * A request setup function that takes the necessary parameters together
12 with a continuation function that is to be called upon completion
14 * A private continuation function that is internal only. This is to be
15 called by the lower-level functions in do_async(). Its only task is to
16 properly call the continuation function named above.
18 * A worker function that is called inside the appropriate child process.
20 This program is free software; you can redistribute it and/or modify
21 it under the terms of the GNU General Public License as published by
22 the Free Software Foundation; either version 2 of the License, or
23 (at your option) any later version.
25 This program is distributed in the hope that it will be useful,
26 but WITHOUT ANY WARRANTY; without even the implied warranty of
27 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 GNU General Public License for more details.
30 You should have received a copy of the GNU General Public License
31 along with this program; if not, write to the Free Software
32 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
39 #define DBGC_CLASS DBGC_WINBIND
41 struct do_async_state
{
43 struct winbindd_request request
;
44 struct winbindd_response response
;
45 void (*cont
)(TALLOC_CTX
*mem_ctx
,
47 struct winbindd_response
*response
,
48 void *c
, void *private_data
);
49 void *c
, *private_data
;
52 static void do_async_recv(void *private_data
, BOOL success
)
54 struct do_async_state
*state
=
55 talloc_get_type_abort(private_data
, struct do_async_state
);
57 state
->cont(state
->mem_ctx
, success
, &state
->response
,
58 state
->c
, state
->private_data
);
61 static void do_async(TALLOC_CTX
*mem_ctx
, struct winbindd_child
*child
,
62 const struct winbindd_request
*request
,
63 void (*cont
)(TALLOC_CTX
*mem_ctx
, BOOL success
,
64 struct winbindd_response
*response
,
65 void *c
, void *private_data
),
66 void *c
, void *private_data
)
68 struct do_async_state
*state
;
70 state
= TALLOC_ZERO_P(mem_ctx
, struct do_async_state
);
72 DEBUG(0, ("talloc failed\n"));
73 cont(mem_ctx
, False
, NULL
, c
, private_data
);
77 state
->mem_ctx
= mem_ctx
;
78 state
->request
= *request
;
79 state
->request
.length
= sizeof(state
->request
);
82 state
->private_data
= private_data
;
84 async_request(mem_ctx
, child
, &state
->request
,
85 &state
->response
, do_async_recv
, state
);
88 void do_async_domain(TALLOC_CTX
*mem_ctx
, struct winbindd_domain
*domain
,
89 const struct winbindd_request
*request
,
90 void (*cont
)(TALLOC_CTX
*mem_ctx
, BOOL success
,
91 struct winbindd_response
*response
,
92 void *c
, void *private_data
),
93 void *c
, void *private_data
)
95 struct do_async_state
*state
;
97 state
= TALLOC_ZERO_P(mem_ctx
, struct do_async_state
);
99 DEBUG(0, ("talloc failed\n"));
100 cont(mem_ctx
, False
, NULL
, c
, private_data
);
104 state
->mem_ctx
= mem_ctx
;
105 state
->request
= *request
;
106 state
->request
.length
= sizeof(state
->request
);
109 state
->private_data
= private_data
;
111 async_domain_request(mem_ctx
, domain
, &state
->request
,
112 &state
->response
, do_async_recv
, state
);
115 static void winbindd_set_mapping_recv(TALLOC_CTX
*mem_ctx
, BOOL success
,
116 struct winbindd_response
*response
,
117 void *c
, void *private_data
)
119 void (*cont
)(void *priv
, BOOL succ
) = (void (*)(void *, BOOL
))c
;
122 DEBUG(5, ("Could not trigger idmap_set_mapping\n"));
123 cont(private_data
, False
);
127 if (response
->result
!= WINBINDD_OK
) {
128 DEBUG(5, ("idmap_set_mapping returned an error\n"));
129 cont(private_data
, False
);
133 cont(private_data
, True
);
136 void winbindd_set_mapping_async(TALLOC_CTX
*mem_ctx
, const struct id_map
*map
,
137 void (*cont
)(void *private_data
, BOOL success
),
140 struct winbindd_request request
;
141 ZERO_STRUCT(request
);
142 request
.cmd
= WINBINDD_DUAL_SET_MAPPING
;
143 request
.data
.dual_idmapset
.id
= map
->xid
.id
;
144 request
.data
.dual_idmapset
.type
= map
->xid
.type
;
145 sid_to_string(request
.data
.dual_idmapset
.sid
, map
->sid
);
147 do_async(mem_ctx
, idmap_child(), &request
, winbindd_set_mapping_recv
,
148 (void *)cont
, private_data
);
151 enum winbindd_result
winbindd_dual_set_mapping(struct winbindd_domain
*domain
,
152 struct winbindd_cli_state
*state
)
158 DEBUG(3, ("[%5lu]: dual_idmapset\n", (unsigned long)state
->pid
));
160 if (!string_to_sid(&sid
, state
->request
.data
.dual_idmapset
.sid
))
161 return WINBINDD_ERROR
;
164 map
.xid
.id
= state
->request
.data
.dual_idmapset
.id
;
165 map
.xid
.type
= state
->request
.data
.dual_idmapset
.type
;
166 map
.status
= ID_MAPPED
;
168 result
= idmap_set_mapping(&map
);
169 return NT_STATUS_IS_OK(result
) ? WINBINDD_OK
: WINBINDD_ERROR
;
172 static void winbindd_set_hwm_recv(TALLOC_CTX
*mem_ctx
, BOOL success
,
173 struct winbindd_response
*response
,
174 void *c
, void *private_data
)
176 void (*cont
)(void *priv
, BOOL succ
) = (void (*)(void *, BOOL
))c
;
179 DEBUG(5, ("Could not trigger idmap_set_hwm\n"));
180 cont(private_data
, False
);
184 if (response
->result
!= WINBINDD_OK
) {
185 DEBUG(5, ("idmap_set_hwm returned an error\n"));
186 cont(private_data
, False
);
190 cont(private_data
, True
);
193 void winbindd_set_hwm_async(TALLOC_CTX
*mem_ctx
, const struct unixid
*xid
,
194 void (*cont
)(void *private_data
, BOOL success
),
197 struct winbindd_request request
;
198 ZERO_STRUCT(request
);
199 request
.cmd
= WINBINDD_DUAL_SET_HWM
;
200 request
.data
.dual_idmapset
.id
= xid
->id
;
201 request
.data
.dual_idmapset
.type
= xid
->type
;
203 do_async(mem_ctx
, idmap_child(), &request
, winbindd_set_hwm_recv
,
204 (void *)cont
, private_data
);
207 enum winbindd_result
winbindd_dual_set_hwm(struct winbindd_domain
*domain
,
208 struct winbindd_cli_state
*state
)
213 DEBUG(3, ("[%5lu]: dual_set_hwm\n", (unsigned long)state
->pid
));
215 xid
.id
= state
->request
.data
.dual_idmapset
.id
;
216 xid
.type
= state
->request
.data
.dual_idmapset
.type
;
220 result
= idmap_set_uid_hwm(&xid
);
223 result
= idmap_set_gid_hwm(&xid
);
226 return WINBINDD_ERROR
;
228 return NT_STATUS_IS_OK(result
) ? WINBINDD_OK
: WINBINDD_ERROR
;
231 static void winbindd_sids2xids_recv(TALLOC_CTX
*mem_ctx
, BOOL success
,
232 struct winbindd_response
*response
,
233 void *c
, void *private_data
)
235 void (*cont
)(void *priv
, BOOL succ
, void *, int) =
236 (void (*)(void *, BOOL
, void *, int))c
;
239 DEBUG(5, ("Could not trigger sids2xids\n"));
240 cont(private_data
, False
, NULL
, 0);
244 if (response
->result
!= WINBINDD_OK
) {
245 DEBUG(5, ("sids2xids returned an error\n"));
246 cont(private_data
, False
, NULL
, 0);
250 cont(private_data
, True
, response
->extra_data
.data
, response
->length
- sizeof(response
));
253 void winbindd_sids2xids_async(TALLOC_CTX
*mem_ctx
, void *sids
, int size
,
254 void (*cont
)(void *private_data
, BOOL success
, void *data
, int len
),
257 struct winbindd_request request
;
258 ZERO_STRUCT(request
);
259 request
.cmd
= WINBINDD_DUAL_SIDS2XIDS
;
260 request
.extra_data
.data
= (char *)sids
;
261 request
.extra_len
= size
;
262 do_async(mem_ctx
, idmap_child(), &request
, winbindd_sids2xids_recv
,
263 (void *)cont
, private_data
);
266 enum winbindd_result
winbindd_dual_sids2xids(struct winbindd_domain
*domain
,
267 struct winbindd_cli_state
*state
)
275 DEBUG(3, ("[%5lu]: sids to unix ids\n", (unsigned long)state
->pid
));
277 if (state
->request
.extra_len
== 0) {
278 DEBUG(0, ("Invalid buffer size!\n"));
279 return WINBINDD_ERROR
;
282 sids
= (DOM_SID
*)state
->request
.extra_data
.data
;
283 num
= state
->request
.extra_len
/ sizeof(DOM_SID
);
285 ids
= TALLOC_ZERO_ARRAY(state
->mem_ctx
, struct id_map
*, num
+ 1);
287 DEBUG(0, ("Out of memory!\n"));
288 return WINBINDD_ERROR
;
290 for (i
= 0; i
< num
; i
++) {
291 ids
[i
] = TALLOC_P(ids
, struct id_map
);
293 DEBUG(0, ("Out of memory!\n"));
295 return WINBINDD_ERROR
;
297 ids
[i
]->sid
= &sids
[i
];
300 result
= idmap_sids_to_unixids(ids
);
302 if (NT_STATUS_IS_OK(result
)) {
304 xids
= SMB_MALLOC_ARRAY(struct unixid
, num
);
306 DEBUG(0, ("Out of memory!\n"));
308 return WINBINDD_ERROR
;
311 for (i
= 0; i
< num
; i
++) {
312 if (ids
[i
]->status
== ID_MAPPED
) {
313 xids
[i
].type
= ids
[i
]->xid
.type
;
314 xids
[i
].id
= ids
[i
]->xid
.id
;
320 state
->response
.length
= sizeof(state
->response
) + (sizeof(struct unixid
) * num
);
321 state
->response
.extra_data
.data
= xids
;
324 DEBUG (2, ("idmap_sids_to_unixids returned an error: 0x%08x\n", NT_STATUS_V(result
)));
326 return WINBINDD_ERROR
;
333 static void winbindd_sid2uid_recv(TALLOC_CTX
*mem_ctx
, BOOL success
,
334 struct winbindd_response
*response
,
335 void *c
, void *private_data
)
337 void (*cont
)(void *priv
, BOOL succ
, uid_t uid
) =
338 (void (*)(void *, BOOL
, uid_t
))c
;
341 DEBUG(5, ("Could not trigger sid2uid\n"));
342 cont(private_data
, False
, 0);
346 if (response
->result
!= WINBINDD_OK
) {
347 DEBUG(5, ("sid2uid returned an error\n"));
348 cont(private_data
, False
, 0);
352 cont(private_data
, True
, response
->data
.uid
);
355 void winbindd_sid2uid_async(TALLOC_CTX
*mem_ctx
, const DOM_SID
*sid
,
356 void (*cont
)(void *private_data
, BOOL success
, uid_t uid
),
359 struct winbindd_request request
;
360 ZERO_STRUCT(request
);
361 request
.cmd
= WINBINDD_DUAL_SID2UID
;
362 sid_to_string(request
.data
.dual_sid2id
.sid
, sid
);
363 do_async(mem_ctx
, idmap_child(), &request
, winbindd_sid2uid_recv
,
364 (void *)cont
, private_data
);
367 enum winbindd_result
winbindd_dual_sid2uid(struct winbindd_domain
*domain
,
368 struct winbindd_cli_state
*state
)
373 DEBUG(3, ("[%5lu]: sid to uid %s\n", (unsigned long)state
->pid
,
374 state
->request
.data
.dual_sid2id
.sid
));
376 if (!string_to_sid(&sid
, state
->request
.data
.dual_sid2id
.sid
)) {
377 DEBUG(1, ("Could not get convert sid %s from string\n",
378 state
->request
.data
.dual_sid2id
.sid
));
379 return WINBINDD_ERROR
;
382 /* Find uid for this sid and return it, possibly ask the slow remote idmap */
384 result
= idmap_sid_to_uid(&sid
, &(state
->response
.data
.uid
));
386 return NT_STATUS_IS_OK(result
) ? WINBINDD_OK
: WINBINDD_ERROR
;
390 static void uid2name_recv(TALLOC_CTX
*mem_ctx
, BOOL success
,
391 struct winbindd_response
*response
,
392 void *c
, void *private_data
);
394 void winbindd_uid2name_async(TALLOC_CTX
*mem_ctx
, uid_t uid
,
395 void (*cont
)(void *private_data
, BOOL success
,
399 struct winbindd_request request
;
400 ZERO_STRUCT(request
);
401 request
.cmd
= WINBINDD_DUAL_UID2NAME
;
402 request
.data
.uid
= uid
;
403 do_async(mem_ctx
, idmap_child(), &request
, uid2name_recv
,
404 (void *)cont
, private_data
);
406 #endif /* not used */
408 enum winbindd_result
winbindd_dual_uid2name(struct winbindd_domain
*domain
,
409 struct winbindd_cli_state
*state
)
413 DEBUG(3, ("[%5lu]: uid2name %lu\n", (unsigned long)state
->pid
,
414 (unsigned long)state
->request
.data
.uid
));
416 pw
= getpwuid(state
->request
.data
.uid
);
418 DEBUG(5, ("User %lu not found\n",
419 (unsigned long)state
->request
.data
.uid
));
420 return WINBINDD_ERROR
;
423 fstrcpy(state
->response
.data
.name
.name
, pw
->pw_name
);
428 static void uid2name_recv(TALLOC_CTX
*mem_ctx
, BOOL success
,
429 struct winbindd_response
*response
,
430 void *c
, void *private_data
)
432 void (*cont
)(void *priv
, BOOL succ
, const char *name
) =
433 (void (*)(void *, BOOL
, const char *))c
;
436 DEBUG(5, ("Could not trigger uid2name\n"));
437 cont(private_data
, False
, NULL
);
441 if (response
->result
!= WINBINDD_OK
) {
442 DEBUG(5, ("uid2name returned an error\n"));
443 cont(private_data
, False
, NULL
);
447 cont(private_data
, True
, response
->data
.name
.name
);
450 static void name2uid_recv(TALLOC_CTX
*mem_ctx
, BOOL success
,
451 struct winbindd_response
*response
,
452 void *c
, void *private_data
);
454 static void winbindd_name2uid_async(TALLOC_CTX
*mem_ctx
, const char *name
,
455 void (*cont
)(void *private_data
, BOOL success
,
459 struct winbindd_request request
;
460 ZERO_STRUCT(request
);
461 request
.cmd
= WINBINDD_DUAL_NAME2UID
;
462 fstrcpy(request
.data
.username
, name
);
463 do_async(mem_ctx
, idmap_child(), &request
, name2uid_recv
,
464 (void *)cont
, private_data
);
466 #endif /* not used */
468 enum winbindd_result
winbindd_dual_name2uid(struct winbindd_domain
*domain
,
469 struct winbindd_cli_state
*state
)
473 /* Ensure null termination */
474 state
->request
.data
.username
475 [sizeof(state
->request
.data
.username
)-1] = '\0';
477 DEBUG(3, ("[%5lu]: name2uid %s\n", (unsigned long)state
->pid
,
478 state
->request
.data
.username
));
480 pw
= getpwnam(state
->request
.data
.username
);
482 return WINBINDD_ERROR
;
485 state
->response
.data
.uid
= pw
->pw_uid
;
490 static void name2uid_recv(TALLOC_CTX
*mem_ctx
, BOOL success
,
491 struct winbindd_response
*response
,
492 void *c
, void *private_data
)
494 void (*cont
)(void *priv
, BOOL succ
, uid_t uid
) =
495 (void (*)(void *, BOOL
, uid_t
))c
;
498 DEBUG(5, ("Could not trigger name2uid\n"));
499 cont(private_data
, False
, 0);
503 if (response
->result
!= WINBINDD_OK
) {
504 DEBUG(5, ("name2uid returned an error\n"));
505 cont(private_data
, False
, 0);
509 cont(private_data
, True
, response
->data
.uid
);
511 #endif /* not used */
513 static void winbindd_sid2gid_recv(TALLOC_CTX
*mem_ctx
, BOOL success
,
514 struct winbindd_response
*response
,
515 void *c
, void *private_data
)
517 void (*cont
)(void *priv
, BOOL succ
, gid_t gid
) =
518 (void (*)(void *, BOOL
, gid_t
))c
;
521 DEBUG(5, ("Could not trigger sid2gid\n"));
522 cont(private_data
, False
, 0);
526 if (response
->result
!= WINBINDD_OK
) {
527 DEBUG(5, ("sid2gid returned an error\n"));
528 cont(private_data
, False
, 0);
532 cont(private_data
, True
, response
->data
.gid
);
535 void winbindd_sid2gid_async(TALLOC_CTX
*mem_ctx
, const DOM_SID
*sid
,
536 void (*cont
)(void *private_data
, BOOL success
, gid_t gid
),
539 struct winbindd_request request
;
540 ZERO_STRUCT(request
);
541 request
.cmd
= WINBINDD_DUAL_SID2GID
;
542 sid_to_string(request
.data
.dual_sid2id
.sid
, sid
);
544 DEBUG(7,("winbindd_sid2gid_async: Resolving %s to a gid\n",
545 request
.data
.dual_sid2id
.sid
));
547 do_async(mem_ctx
, idmap_child(), &request
, winbindd_sid2gid_recv
,
548 (void *)cont
, private_data
);
551 enum winbindd_result
winbindd_dual_sid2gid(struct winbindd_domain
*domain
,
552 struct winbindd_cli_state
*state
)
557 DEBUG(3, ("[%5lu]: sid to gid %s\n", (unsigned long)state
->pid
,
558 state
->request
.data
.dual_sid2id
.sid
));
560 if (!string_to_sid(&sid
, state
->request
.data
.dual_sid2id
.sid
)) {
561 DEBUG(1, ("Could not get convert sid %s from string\n",
562 state
->request
.data
.dual_sid2id
.sid
));
563 return WINBINDD_ERROR
;
566 /* Find gid for this sid and return it, possibly ask the slow remote idmap */
568 result
= idmap_sid_to_gid(&sid
, &state
->response
.data
.gid
);
570 DEBUG(10, ("winbindd_dual_sid2gid: 0x%08x - %s - %u\n", NT_STATUS_V(result
), sid_string_static(&sid
), state
->response
.data
.gid
));
572 return NT_STATUS_IS_OK(result
) ? WINBINDD_OK
: WINBINDD_ERROR
;
575 static void gid2name_recv(TALLOC_CTX
*mem_ctx
, BOOL success
,
576 struct winbindd_response
*response
,
577 void *c
, void *private_data
)
579 void (*cont
)(void *priv
, BOOL succ
, const char *name
) =
580 (void (*)(void *, BOOL
, const char *))c
;
583 DEBUG(5, ("Could not trigger gid2name\n"));
584 cont(private_data
, False
, NULL
);
588 if (response
->result
!= WINBINDD_OK
) {
589 DEBUG(5, ("gid2name returned an error\n"));
590 cont(private_data
, False
, NULL
);
594 cont(private_data
, True
, response
->data
.name
.name
);
597 void winbindd_gid2name_async(TALLOC_CTX
*mem_ctx
, gid_t gid
,
598 void (*cont
)(void *private_data
, BOOL success
,
602 struct winbindd_request request
;
603 ZERO_STRUCT(request
);
604 request
.cmd
= WINBINDD_DUAL_GID2NAME
;
605 request
.data
.gid
= gid
;
606 do_async(mem_ctx
, idmap_child(), &request
, gid2name_recv
,
607 (void *)cont
, private_data
);
610 enum winbindd_result
winbindd_dual_gid2name(struct winbindd_domain
*domain
,
611 struct winbindd_cli_state
*state
)
615 DEBUG(3, ("[%5lu]: gid2name %lu\n", (unsigned long)state
->pid
,
616 (unsigned long)state
->request
.data
.gid
));
618 gr
= getgrgid(state
->request
.data
.gid
);
620 return WINBINDD_ERROR
;
622 fstrcpy(state
->response
.data
.name
.name
, gr
->gr_name
);
627 static void name2gid_recv(TALLOC_CTX
*mem_ctx
, BOOL success
,
628 struct winbindd_response
*response
,
629 void *c
, void *private_data
);
631 static void winbindd_name2gid_async(TALLOC_CTX
*mem_ctx
, const char *name
,
632 void (*cont
)(void *private_data
, BOOL success
,
636 struct winbindd_request request
;
637 ZERO_STRUCT(request
);
638 request
.cmd
= WINBINDD_DUAL_NAME2GID
;
639 fstrcpy(request
.data
.groupname
, name
);
640 do_async(mem_ctx
, idmap_child(), &request
, name2gid_recv
,
641 (void *)cont
, private_data
);
643 #endif /* not used */
645 enum winbindd_result
winbindd_dual_name2gid(struct winbindd_domain
*domain
,
646 struct winbindd_cli_state
*state
)
650 /* Ensure null termination */
651 state
->request
.data
.groupname
652 [sizeof(state
->request
.data
.groupname
)-1] = '\0';
654 DEBUG(3, ("[%5lu]: name2gid %s\n", (unsigned long)state
->pid
,
655 state
->request
.data
.groupname
));
657 gr
= getgrnam(state
->request
.data
.groupname
);
659 return WINBINDD_ERROR
;
662 state
->response
.data
.gid
= gr
->gr_gid
;
667 static void name2gid_recv(TALLOC_CTX
*mem_ctx
, BOOL success
,
668 struct winbindd_response
*response
,
669 void *c
, void *private_data
)
671 void (*cont
)(void *priv
, BOOL succ
, gid_t gid
) =
672 (void (*)(void *, BOOL
, gid_t
))c
;
675 DEBUG(5, ("Could not trigger name2gid\n"));
676 cont(private_data
, False
, 0);
680 if (response
->result
!= WINBINDD_OK
) {
681 DEBUG(5, ("name2gid returned an error\n"));
682 cont(private_data
, False
, 0);
686 cont(private_data
, True
, response
->data
.gid
);
688 #endif /* not used */
690 struct lookupsid_state
{
692 void *caller_private_data
;
696 static void lookupsid_recv2(TALLOC_CTX
*mem_ctx
, BOOL success
,
697 struct winbindd_response
*response
,
698 void *c
, void *private_data
)
700 void (*cont
)(void *priv
, BOOL succ
, const char *dom_name
,
701 const char *name
, enum lsa_SidType type
) =
702 (void (*)(void *, BOOL
, const char *, const char *,
704 struct lookupsid_state
*s
= talloc_get_type_abort(private_data
,
705 struct lookupsid_state
);
708 DEBUG(5, ("Could not trigger lookupsid\n"));
709 cont(s
->caller_private_data
, False
, NULL
, NULL
, SID_NAME_UNKNOWN
);
713 if (response
->result
!= WINBINDD_OK
) {
714 DEBUG(5, ("lookupsid (forest root) returned an error\n"));
715 cont(s
->caller_private_data
, False
, NULL
, NULL
, SID_NAME_UNKNOWN
);
719 cont(s
->caller_private_data
, True
, response
->data
.name
.dom_name
,
720 response
->data
.name
.name
,
721 (enum lsa_SidType
)response
->data
.name
.type
);
724 static void lookupsid_recv(TALLOC_CTX
*mem_ctx
, BOOL success
,
725 struct winbindd_response
*response
,
726 void *c
, void *private_data
)
728 void (*cont
)(void *priv
, BOOL succ
, const char *dom_name
,
729 const char *name
, enum lsa_SidType type
) =
730 (void (*)(void *, BOOL
, const char *, const char *,
732 struct lookupsid_state
*s
= talloc_get_type_abort(private_data
,
733 struct lookupsid_state
);
736 DEBUG(5, ("Could not trigger lookupsid\n"));
737 cont(s
->caller_private_data
, False
, NULL
, NULL
, SID_NAME_UNKNOWN
);
741 if (response
->result
!= WINBINDD_OK
) {
742 /* Try again using the forest root */
743 struct winbindd_domain
*root_domain
= find_root_domain();
744 struct winbindd_request request
;
746 if ( !root_domain
) {
747 DEBUG(5,("lookupsid_recv: unable to determine forest root\n"));
748 cont(s
->caller_private_data
, False
, NULL
, NULL
, SID_NAME_UNKNOWN
);
752 ZERO_STRUCT(request
);
753 request
.cmd
= WINBINDD_LOOKUPSID
;
754 fstrcpy(request
.data
.sid
, sid_string_static(&s
->sid
));
756 do_async_domain(mem_ctx
, root_domain
, &request
, lookupsid_recv2
,
762 cont(s
->caller_private_data
, True
, response
->data
.name
.dom_name
,
763 response
->data
.name
.name
,
764 (enum lsa_SidType
)response
->data
.name
.type
);
767 void winbindd_lookupsid_async(TALLOC_CTX
*mem_ctx
, const DOM_SID
*sid
,
768 void (*cont
)(void *private_data
, BOOL success
,
769 const char *dom_name
,
771 enum lsa_SidType type
),
774 struct winbindd_domain
*domain
;
775 struct winbindd_request request
;
776 struct lookupsid_state
*s
;
778 domain
= find_lookup_domain_from_sid(sid
);
779 if (domain
== NULL
) {
780 DEBUG(5, ("Could not find domain for sid %s\n",
781 sid_string_static(sid
)));
782 cont(private_data
, False
, NULL
, NULL
, SID_NAME_UNKNOWN
);
786 ZERO_STRUCT(request
);
787 request
.cmd
= WINBINDD_LOOKUPSID
;
788 fstrcpy(request
.data
.sid
, sid_string_static(sid
));
790 if ( (s
= TALLOC_ZERO_P(mem_ctx
, struct lookupsid_state
)) == NULL
) {
791 DEBUG(0, ("winbindd_lookupsid_async: talloc failed\n"));
792 cont(private_data
, False
, NULL
, NULL
, SID_NAME_UNKNOWN
);
796 sid_copy( &s
->sid
, sid
);
797 s
->caller_private_data
= private_data
;
799 do_async_domain(mem_ctx
, domain
, &request
, lookupsid_recv
,
803 enum winbindd_result
winbindd_dual_lookupsid(struct winbindd_domain
*domain
,
804 struct winbindd_cli_state
*state
)
806 enum lsa_SidType type
;
811 /* Ensure null termination */
812 state
->request
.data
.sid
[sizeof(state
->request
.data
.sid
)-1]='\0';
814 DEBUG(3, ("[%5lu]: lookupsid %s\n", (unsigned long)state
->pid
,
815 state
->request
.data
.sid
));
817 /* Lookup sid from PDC using lsa_lookup_sids() */
819 if (!string_to_sid(&sid
, state
->request
.data
.sid
)) {
820 DEBUG(5, ("%s not a SID\n", state
->request
.data
.sid
));
821 return WINBINDD_ERROR
;
826 if (!winbindd_lookup_name_by_sid(state
->mem_ctx
, domain
, &sid
,
827 &dom_name
, &name
, &type
))
829 TALLOC_FREE(dom_name
);
831 return WINBINDD_ERROR
;
834 fstrcpy(state
->response
.data
.name
.dom_name
, dom_name
);
835 fstrcpy(state
->response
.data
.name
.name
, name
);
836 state
->response
.data
.name
.type
= type
;
838 TALLOC_FREE(dom_name
);
843 /********************************************************************
844 This is the second callback after contacting the forest root
845 ********************************************************************/
847 struct lookupname_state
{
850 void *caller_private_data
;
854 static void lookupname_recv2(TALLOC_CTX
*mem_ctx
, BOOL success
,
855 struct winbindd_response
*response
,
856 void *c
, void *private_data
)
858 void (*cont
)(void *priv
, BOOL succ
, const DOM_SID
*sid
,
859 enum lsa_SidType type
) =
860 (void (*)(void *, BOOL
, const DOM_SID
*, enum lsa_SidType
))c
;
862 struct lookupname_state
*s
= talloc_get_type_abort( private_data
,
863 struct lookupname_state
);
867 DEBUG(5, ("Could not trigger lookup_name\n"));
868 cont(s
->caller_private_data
, False
, NULL
, SID_NAME_UNKNOWN
);
872 if (response
->result
!= WINBINDD_OK
) {
873 DEBUG(5, ("lookup_name returned an error\n"));
874 cont(s
->caller_private_data
, False
, NULL
, SID_NAME_UNKNOWN
);
878 if (!string_to_sid(&sid
, response
->data
.sid
.sid
)) {
879 DEBUG(0, ("Could not convert string %s to sid\n",
880 response
->data
.sid
.sid
));
881 cont(s
->caller_private_data
, False
, NULL
, SID_NAME_UNKNOWN
);
885 cont(s
->caller_private_data
, True
, &sid
,
886 (enum lsa_SidType
)response
->data
.sid
.type
);
889 /********************************************************************
890 This is the first callback after contacting our own domain
891 ********************************************************************/
893 static void lookupname_recv(TALLOC_CTX
*mem_ctx
, BOOL success
,
894 struct winbindd_response
*response
,
895 void *c
, void *private_data
)
897 void (*cont
)(void *priv
, BOOL succ
, const DOM_SID
*sid
,
898 enum lsa_SidType type
) =
899 (void (*)(void *, BOOL
, const DOM_SID
*, enum lsa_SidType
))c
;
901 struct lookupname_state
*s
= talloc_get_type_abort( private_data
,
902 struct lookupname_state
);
905 DEBUG(5, ("lookupname_recv: lookup_name() failed!\n"));
906 cont(s
->caller_private_data
, False
, NULL
, SID_NAME_UNKNOWN
);
910 if (response
->result
!= WINBINDD_OK
) {
911 /* Try again using the forest root */
912 struct winbindd_domain
*root_domain
= find_root_domain();
913 struct winbindd_request request
;
915 if ( !root_domain
) {
916 DEBUG(5,("lookupname_recv: unable to determine forest root\n"));
917 cont(s
->caller_private_data
, False
, NULL
, SID_NAME_UNKNOWN
);
921 ZERO_STRUCT(request
);
922 request
.cmd
= WINBINDD_LOOKUPNAME
;
924 fstrcpy( request
.data
.name
.dom_name
, s
->dom_name
);
925 fstrcpy( request
.data
.name
.name
, s
->name
);
927 do_async_domain(mem_ctx
, root_domain
, &request
, lookupname_recv2
,
933 if (!string_to_sid(&sid
, response
->data
.sid
.sid
)) {
934 DEBUG(0, ("Could not convert string %s to sid\n",
935 response
->data
.sid
.sid
));
936 cont(s
->caller_private_data
, False
, NULL
, SID_NAME_UNKNOWN
);
940 cont(s
->caller_private_data
, True
, &sid
,
941 (enum lsa_SidType
)response
->data
.sid
.type
);
944 /********************************************************************
945 The lookup name call first contacts a DC in its own domain
946 and fallbacks to contact a DC in the forest in our domain doesn't
948 ********************************************************************/
950 void winbindd_lookupname_async(TALLOC_CTX
*mem_ctx
,
951 const char *dom_name
, const char *name
,
952 void (*cont
)(void *private_data
, BOOL success
,
954 enum lsa_SidType type
),
957 struct winbindd_request request
;
958 struct winbindd_domain
*domain
;
959 struct lookupname_state
*s
;
961 if ( (domain
= find_lookup_domain_from_name(dom_name
)) == NULL
) {
962 DEBUG(5, ("Could not find domain for name %s\n", dom_name
));
963 cont(private_data
, False
, NULL
, SID_NAME_UNKNOWN
);
967 ZERO_STRUCT(request
);
968 request
.cmd
= WINBINDD_LOOKUPNAME
;
969 fstrcpy(request
.data
.name
.dom_name
, dom_name
);
970 fstrcpy(request
.data
.name
.name
, name
);
972 if ( (s
= TALLOC_ZERO_P(mem_ctx
, struct lookupname_state
)) == NULL
) {
973 DEBUG(0, ("winbindd_lookupname_async: talloc failed\n"));
974 cont(private_data
, False
, NULL
, SID_NAME_UNKNOWN
);
978 s
->dom_name
= talloc_strdup( s
, dom_name
);
979 s
->name
= talloc_strdup( s
, name
);
980 s
->caller_private_data
= private_data
;
982 do_async_domain(mem_ctx
, domain
, &request
, lookupname_recv
,
986 enum winbindd_result
winbindd_dual_lookupname(struct winbindd_domain
*domain
,
987 struct winbindd_cli_state
*state
)
989 enum lsa_SidType type
;
990 char *name_domain
, *name_user
;
994 /* Ensure null termination */
995 state
->request
.data
.name
.dom_name
[sizeof(state
->request
.data
.name
.dom_name
)-1]='\0';
997 /* Ensure null termination */
998 state
->request
.data
.name
.name
[sizeof(state
->request
.data
.name
.name
)-1]='\0';
1000 /* cope with the name being a fully qualified name */
1001 p
= strstr(state
->request
.data
.name
.name
, lp_winbind_separator());
1004 name_domain
= state
->request
.data
.name
.name
;
1007 name_domain
= state
->request
.data
.name
.dom_name
;
1008 name_user
= state
->request
.data
.name
.name
;
1011 DEBUG(3, ("[%5lu]: lookupname %s%s%s\n", (unsigned long)state
->pid
,
1012 name_domain
, lp_winbind_separator(), name_user
));
1014 /* Lookup name from DC using lsa_lookup_names() */
1015 if (!winbindd_lookup_sid_by_name(state
->mem_ctx
, domain
, name_domain
,
1016 name_user
, &sid
, &type
)) {
1017 return WINBINDD_ERROR
;
1020 sid_to_string(state
->response
.data
.sid
.sid
, &sid
);
1021 state
->response
.data
.sid
.type
= type
;
1026 BOOL
print_sidlist(TALLOC_CTX
*mem_ctx
, const DOM_SID
*sids
,
1027 size_t num_sids
, char **result
, ssize_t
*len
)
1034 for (i
=0; i
<num_sids
; i
++) {
1035 sprintf_append(mem_ctx
, result
, len
, &buflen
,
1036 "%s\n", sid_string_static(&sids
[i
]));
1039 if ((num_sids
!= 0) && (*result
== NULL
)) {
1046 static BOOL
parse_sidlist(TALLOC_CTX
*mem_ctx
, char *sidstr
,
1047 DOM_SID
**sids
, size_t *num_sids
)
1055 while (p
[0] != '\0') {
1057 q
= strchr(p
, '\n');
1059 DEBUG(0, ("Got invalid sidstr: %s\n", p
));
1064 if (!string_to_sid(&sid
, p
)) {
1065 DEBUG(0, ("Could not parse sid %s\n", p
));
1068 if (!add_sid_to_array(mem_ctx
, &sid
, sids
, num_sids
)) {
1076 static BOOL
parse_ridlist(TALLOC_CTX
*mem_ctx
, char *ridstr
,
1077 uint32
**rids
, size_t *num_rids
)
1085 while (p
[0] != '\0') {
1088 rid
= strtoul(p
, &q
, 10);
1090 DEBUG(0, ("Got invalid ridstr: %s\n", p
));
1094 ADD_TO_ARRAY(mem_ctx
, uint32
, rid
, rids
, num_rids
);
1099 enum winbindd_result
winbindd_dual_lookuprids(struct winbindd_domain
*domain
,
1100 struct winbindd_cli_state
*state
)
1102 uint32
*rids
= NULL
;
1103 size_t i
, buflen
, num_rids
= 0;
1108 enum lsa_SidType
*types
;
1112 DEBUG(10, ("Looking up RIDs for domain %s (%s)\n",
1113 state
->request
.domain_name
,
1114 state
->request
.data
.sid
));
1116 if (!parse_ridlist(state
->mem_ctx
, state
->request
.extra_data
.data
,
1117 &rids
, &num_rids
)) {
1118 DEBUG(5, ("Could not parse ridlist\n"));
1119 return WINBINDD_ERROR
;
1122 if (!string_to_sid(&domain_sid
, state
->request
.data
.sid
)) {
1123 DEBUG(5, ("Could not parse domain sid %s\n",
1124 state
->request
.data
.sid
));
1125 return WINBINDD_ERROR
;
1128 status
= domain
->methods
->rids_to_names(domain
, state
->mem_ctx
,
1129 &domain_sid
, rids
, num_rids
,
1133 if (!NT_STATUS_IS_OK(status
) &&
1134 !NT_STATUS_EQUAL(status
, STATUS_SOME_UNMAPPED
)) {
1135 return WINBINDD_ERROR
;
1142 for (i
=0; i
<num_rids
; i
++) {
1143 sprintf_append(state
->mem_ctx
, &result
, &len
, &buflen
,
1144 "%d %s\n", types
[i
], names
[i
]);
1147 fstrcpy(state
->response
.data
.domain_name
, domain_name
);
1149 if (result
!= NULL
) {
1150 state
->response
.extra_data
.data
= SMB_STRDUP(result
);
1151 if (!state
->response
.extra_data
.data
) {
1152 return WINBINDD_ERROR
;
1154 state
->response
.length
+= len
+1;
1160 static void getsidaliases_recv(TALLOC_CTX
*mem_ctx
, BOOL success
,
1161 struct winbindd_response
*response
,
1162 void *c
, void *private_data
)
1164 void (*cont
)(void *priv
, BOOL succ
,
1165 DOM_SID
*aliases
, size_t num_aliases
) =
1166 (void (*)(void *, BOOL
, DOM_SID
*, size_t))c
;
1168 DOM_SID
*sids
= NULL
;
1169 size_t num_sids
= 0;
1172 DEBUG(5, ("Could not trigger getsidaliases\n"));
1173 cont(private_data
, success
, NULL
, 0);
1177 if (response
->result
!= WINBINDD_OK
) {
1178 DEBUG(5, ("getsidaliases returned an error\n"));
1179 cont(private_data
, False
, NULL
, 0);
1183 aliases_str
= (char *)response
->extra_data
.data
;
1185 if (aliases_str
== NULL
) {
1186 DEBUG(10, ("getsidaliases return 0 SIDs\n"));
1187 cont(private_data
, True
, NULL
, 0);
1191 if (!parse_sidlist(mem_ctx
, aliases_str
, &sids
, &num_sids
)) {
1192 DEBUG(0, ("Could not parse sids\n"));
1193 cont(private_data
, False
, NULL
, 0);
1197 SAFE_FREE(response
->extra_data
.data
);
1199 cont(private_data
, True
, sids
, num_sids
);
1202 void winbindd_getsidaliases_async(struct winbindd_domain
*domain
,
1203 TALLOC_CTX
*mem_ctx
,
1204 const DOM_SID
*sids
, size_t num_sids
,
1205 void (*cont
)(void *private_data
,
1207 const DOM_SID
*aliases
,
1208 size_t num_aliases
),
1211 struct winbindd_request request
;
1212 char *sidstr
= NULL
;
1215 if (num_sids
== 0) {
1216 cont(private_data
, True
, NULL
, 0);
1220 if (!print_sidlist(mem_ctx
, sids
, num_sids
, &sidstr
, &len
)) {
1221 cont(private_data
, False
, NULL
, 0);
1225 ZERO_STRUCT(request
);
1226 request
.cmd
= WINBINDD_DUAL_GETSIDALIASES
;
1227 request
.extra_len
= len
;
1228 request
.extra_data
.data
= sidstr
;
1230 do_async_domain(mem_ctx
, domain
, &request
, getsidaliases_recv
,
1231 (void *)cont
, private_data
);
1234 enum winbindd_result
winbindd_dual_getsidaliases(struct winbindd_domain
*domain
,
1235 struct winbindd_cli_state
*state
)
1237 DOM_SID
*sids
= NULL
;
1238 size_t num_sids
= 0;
1239 char *sidstr
= NULL
;
1246 DEBUG(3, ("[%5lu]: getsidaliases\n", (unsigned long)state
->pid
));
1248 sidstr
= state
->request
.extra_data
.data
;
1249 if (sidstr
== NULL
) {
1250 sidstr
= talloc_strdup(state
->mem_ctx
, "\n"); /* No SID */
1252 DEBUG(0, ("Out of memory\n"));
1253 return WINBINDD_ERROR
;
1257 DEBUG(10, ("Sidlist: %s\n", sidstr
));
1259 if (!parse_sidlist(state
->mem_ctx
, sidstr
, &sids
, &num_sids
)) {
1260 DEBUG(0, ("Could not parse SID list: %s\n", sidstr
));
1261 return WINBINDD_ERROR
;
1267 result
= domain
->methods
->lookup_useraliases(domain
,
1273 if (!NT_STATUS_IS_OK(result
)) {
1274 DEBUG(3, ("Could not lookup_useraliases: %s\n",
1275 nt_errstr(result
)));
1276 return WINBINDD_ERROR
;
1283 DEBUG(10, ("Got %d aliases\n", num_aliases
));
1285 for (i
=0; i
<num_aliases
; i
++) {
1287 DEBUGADD(10, (" rid %d\n", alias_rids
[i
]));
1288 sid_copy(&sid
, &domain
->sid
);
1289 sid_append_rid(&sid
, alias_rids
[i
]);
1290 if (!add_sid_to_array(state
->mem_ctx
, &sid
, &sids
, &num_sids
)) {
1291 return WINBINDD_ERROR
;
1296 if (!print_sidlist(state
->mem_ctx
, sids
, num_sids
, &sidstr
, &len
)) {
1297 DEBUG(0, ("Could not print_sidlist\n"));
1298 state
->response
.extra_data
.data
= NULL
;
1299 return WINBINDD_ERROR
;
1302 state
->response
.extra_data
.data
= NULL
;
1305 state
->response
.extra_data
.data
= SMB_STRDUP(sidstr
);
1306 if (!state
->response
.extra_data
.data
) {
1307 DEBUG(0, ("Out of memory\n"));
1308 return WINBINDD_ERROR
;
1310 DEBUG(10, ("aliases_list: %s\n",
1311 (char *)state
->response
.extra_data
.data
));
1312 state
->response
.length
+= len
+1;
1318 struct gettoken_state
{
1319 TALLOC_CTX
*mem_ctx
;
1321 struct winbindd_domain
*alias_domain
;
1322 struct winbindd_domain
*local_alias_domain
;
1323 struct winbindd_domain
*builtin_domain
;
1326 void (*cont
)(void *private_data
, BOOL success
, DOM_SID
*sids
, size_t num_sids
);
1330 static void gettoken_recvdomgroups(TALLOC_CTX
*mem_ctx
, BOOL success
,
1331 struct winbindd_response
*response
,
1332 void *c
, void *private_data
);
1333 static void gettoken_recvaliases(void *private_data
, BOOL success
,
1334 const DOM_SID
*aliases
,
1335 size_t num_aliases
);
1338 void winbindd_gettoken_async(TALLOC_CTX
*mem_ctx
, const DOM_SID
*user_sid
,
1339 void (*cont
)(void *private_data
, BOOL success
,
1340 DOM_SID
*sids
, size_t num_sids
),
1343 struct winbindd_domain
*domain
;
1344 struct winbindd_request request
;
1345 struct gettoken_state
*state
;
1347 state
= TALLOC_ZERO_P(mem_ctx
, struct gettoken_state
);
1348 if (state
== NULL
) {
1349 DEBUG(0, ("talloc failed\n"));
1350 cont(private_data
, False
, NULL
, 0);
1354 state
->mem_ctx
= mem_ctx
;
1355 sid_copy(&state
->user_sid
, user_sid
);
1356 state
->alias_domain
= find_our_domain();
1357 state
->local_alias_domain
= find_domain_from_name( get_global_sam_name() );
1358 state
->builtin_domain
= find_builtin_domain();
1360 state
->private_data
= private_data
;
1362 domain
= find_domain_from_sid_noinit(user_sid
);
1363 if (domain
== NULL
) {
1364 DEBUG(5, ("Could not find domain from SID %s\n",
1365 sid_string_static(user_sid
)));
1366 cont(private_data
, False
, NULL
, 0);
1370 ZERO_STRUCT(request
);
1371 request
.cmd
= WINBINDD_GETUSERDOMGROUPS
;
1372 fstrcpy(request
.data
.sid
, sid_string_static(user_sid
));
1374 do_async_domain(mem_ctx
, domain
, &request
, gettoken_recvdomgroups
,
1378 static void gettoken_recvdomgroups(TALLOC_CTX
*mem_ctx
, BOOL success
,
1379 struct winbindd_response
*response
,
1380 void *c
, void *private_data
)
1382 struct gettoken_state
*state
=
1383 talloc_get_type_abort(private_data
, struct gettoken_state
);
1387 DEBUG(10, ("Could not get domain groups\n"));
1388 state
->cont(state
->private_data
, False
, NULL
, 0);
1392 sids_str
= (char *)response
->extra_data
.data
;
1394 if (sids_str
== NULL
) {
1395 /* This could be normal if we are dealing with a
1396 local user and local groups */
1398 if ( !sid_check_is_in_our_domain( &state
->user_sid
) ) {
1399 DEBUG(10, ("Received no domain groups\n"));
1400 state
->cont(state
->private_data
, True
, NULL
, 0);
1406 state
->num_sids
= 0;
1408 if (!add_sid_to_array(mem_ctx
, &state
->user_sid
, &state
->sids
,
1409 &state
->num_sids
)) {
1410 DEBUG(0, ("Out of memory\n"));
1411 state
->cont(state
->private_data
, False
, NULL
, 0);
1415 if (sids_str
&& !parse_sidlist(mem_ctx
, sids_str
, &state
->sids
,
1416 &state
->num_sids
)) {
1417 DEBUG(0, ("Could not parse sids\n"));
1418 state
->cont(state
->private_data
, False
, NULL
, 0);
1422 SAFE_FREE(response
->extra_data
.data
);
1424 if (state
->alias_domain
== NULL
) {
1425 DEBUG(10, ("Don't expand domain local groups\n"));
1426 state
->cont(state
->private_data
, True
, state
->sids
,
1431 winbindd_getsidaliases_async(state
->alias_domain
, mem_ctx
,
1432 state
->sids
, state
->num_sids
,
1433 gettoken_recvaliases
, state
);
1436 static void gettoken_recvaliases(void *private_data
, BOOL success
,
1437 const DOM_SID
*aliases
,
1440 struct gettoken_state
*state
= (struct gettoken_state
*)private_data
;
1444 DEBUG(10, ("Could not receive domain local groups\n"));
1445 state
->cont(state
->private_data
, False
, NULL
, 0);
1449 for (i
=0; i
<num_aliases
; i
++) {
1450 if (!add_sid_to_array(state
->mem_ctx
, &aliases
[i
],
1451 &state
->sids
, &state
->num_sids
)) {
1452 DEBUG(0, ("Out of memory\n"));
1453 state
->cont(state
->private_data
, False
, NULL
, 0);
1458 if (state
->local_alias_domain
!= NULL
) {
1459 struct winbindd_domain
*local_domain
= state
->local_alias_domain
;
1460 DEBUG(10, ("Expanding our own local groups\n"));
1461 state
->local_alias_domain
= NULL
;
1462 winbindd_getsidaliases_async(local_domain
, state
->mem_ctx
,
1463 state
->sids
, state
->num_sids
,
1464 gettoken_recvaliases
, state
);
1468 if (state
->builtin_domain
!= NULL
) {
1469 struct winbindd_domain
*builtin_domain
= state
->builtin_domain
;
1470 DEBUG(10, ("Expanding our own BUILTIN groups\n"));
1471 state
->builtin_domain
= NULL
;
1472 winbindd_getsidaliases_async(builtin_domain
, state
->mem_ctx
,
1473 state
->sids
, state
->num_sids
,
1474 gettoken_recvaliases
, state
);
1478 state
->cont(state
->private_data
, True
, state
->sids
, state
->num_sids
);
1481 static void query_user_recv(TALLOC_CTX
*mem_ctx
, BOOL success
,
1482 struct winbindd_response
*response
,
1483 void *c
, void *private_data
)
1485 void (*cont
)(void *priv
, BOOL succ
, const char *acct_name
,
1486 const char *full_name
, const char *homedir
,
1487 const char *shell
, uint32 gid
, uint32 group_rid
) =
1488 (void (*)(void *, BOOL
, const char *, const char *,
1489 const char *, const char *, uint32
, uint32
))c
;
1492 DEBUG(5, ("Could not trigger query_user\n"));
1493 cont(private_data
, False
, NULL
, NULL
, NULL
, NULL
, -1, -1);
1497 if (response
->result
!= WINBINDD_OK
) {
1498 DEBUG(5, ("query_user returned an error\n"));
1499 cont(private_data
, False
, NULL
, NULL
, NULL
, NULL
, -1, -1);
1503 cont(private_data
, True
, response
->data
.user_info
.acct_name
,
1504 response
->data
.user_info
.full_name
,
1505 response
->data
.user_info
.homedir
,
1506 response
->data
.user_info
.shell
,
1507 response
->data
.user_info
.primary_gid
,
1508 response
->data
.user_info
.group_rid
);
1511 void query_user_async(TALLOC_CTX
*mem_ctx
, struct winbindd_domain
*domain
,
1513 void (*cont
)(void *private_data
, BOOL success
,
1514 const char *acct_name
,
1515 const char *full_name
,
1516 const char *homedir
,
1522 struct winbindd_request request
;
1523 ZERO_STRUCT(request
);
1524 request
.cmd
= WINBINDD_DUAL_USERINFO
;
1525 sid_to_string(request
.data
.sid
, sid
);
1526 do_async_domain(mem_ctx
, domain
, &request
, query_user_recv
,
1527 (void *)cont
, private_data
);
1530 /* The following uid2sid/gid2sid functions has been contributed by
1531 * Keith Reynolds <Keith.Reynolds@centrify.com> */
1533 static void winbindd_uid2sid_recv(TALLOC_CTX
*mem_ctx
, BOOL success
,
1534 struct winbindd_response
*response
,
1535 void *c
, void *private_data
)
1537 void (*cont
)(void *priv
, BOOL succ
, const char *sid
) =
1538 (void (*)(void *, BOOL
, const char *))c
;
1541 DEBUG(5, ("Could not trigger uid2sid\n"));
1542 cont(private_data
, False
, NULL
);
1546 if (response
->result
!= WINBINDD_OK
) {
1547 DEBUG(5, ("uid2sid returned an error\n"));
1548 cont(private_data
, False
, NULL
);
1552 cont(private_data
, True
, response
->data
.sid
.sid
);
1555 void winbindd_uid2sid_async(TALLOC_CTX
*mem_ctx
, uid_t uid
,
1556 void (*cont
)(void *private_data
, BOOL success
, const char *sid
),
1559 struct winbindd_request request
;
1561 ZERO_STRUCT(request
);
1562 request
.cmd
= WINBINDD_DUAL_UID2SID
;
1563 request
.data
.uid
= uid
;
1564 do_async(mem_ctx
, idmap_child(), &request
, winbindd_uid2sid_recv
,
1565 (void *)cont
, private_data
);
1568 enum winbindd_result
winbindd_dual_uid2sid(struct winbindd_domain
*domain
,
1569 struct winbindd_cli_state
*state
)
1574 DEBUG(3,("[%5lu]: uid to sid %lu\n",
1575 (unsigned long)state
->pid
,
1576 (unsigned long) state
->request
.data
.uid
));
1578 /* Find sid for this uid and return it, possibly ask the slow remote idmap */
1579 result
= idmap_uid_to_sid(&sid
, state
->request
.data
.uid
);
1581 if (NT_STATUS_IS_OK(result
)) {
1582 sid_to_string(state
->response
.data
.sid
.sid
, &sid
);
1583 state
->response
.data
.sid
.type
= SID_NAME_USER
;
1587 return WINBINDD_ERROR
;
1590 static void winbindd_gid2sid_recv(TALLOC_CTX
*mem_ctx
, BOOL success
,
1591 struct winbindd_response
*response
,
1592 void *c
, void *private_data
)
1594 void (*cont
)(void *priv
, BOOL succ
, const char *sid
) =
1595 (void (*)(void *, BOOL
, const char *))c
;
1598 DEBUG(5, ("Could not trigger gid2sid\n"));
1599 cont(private_data
, False
, NULL
);
1603 if (response
->result
!= WINBINDD_OK
) {
1604 DEBUG(5, ("gid2sid returned an error\n"));
1605 cont(private_data
, False
, NULL
);
1609 cont(private_data
, True
, response
->data
.sid
.sid
);
1612 void winbindd_gid2sid_async(TALLOC_CTX
*mem_ctx
, gid_t gid
,
1613 void (*cont
)(void *private_data
, BOOL success
, const char *sid
),
1616 struct winbindd_request request
;
1618 ZERO_STRUCT(request
);
1619 request
.cmd
= WINBINDD_DUAL_GID2SID
;
1620 request
.data
.gid
= gid
;
1621 do_async(mem_ctx
, idmap_child(), &request
, winbindd_gid2sid_recv
,
1622 (void *)cont
, private_data
);
1625 enum winbindd_result
winbindd_dual_gid2sid(struct winbindd_domain
*domain
,
1626 struct winbindd_cli_state
*state
)
1631 DEBUG(3,("[%5lu]: gid %lu to sid\n",
1632 (unsigned long)state
->pid
,
1633 (unsigned long) state
->request
.data
.gid
));
1635 /* Find sid for this gid and return it, possibly ask the slow remote idmap */
1636 result
= idmap_gid_to_sid(&sid
, state
->request
.data
.gid
);
1638 if (NT_STATUS_IS_OK(result
)) {
1639 sid_to_string(state
->response
.data
.sid
.sid
, &sid
);
1640 DEBUG(10, ("[%5lu]: retrieved sid: %s\n",
1641 (unsigned long)state
->pid
,
1642 state
->response
.data
.sid
.sid
));
1643 state
->response
.data
.sid
.type
= SID_NAME_DOM_GRP
;
1647 return WINBINDD_ERROR
;
1650 static void winbindd_dump_id_maps_recv(TALLOC_CTX
*mem_ctx
, BOOL success
,
1651 struct winbindd_response
*response
,
1652 void *c
, void *private_data
)
1654 void (*cont
)(void *priv
, BOOL succ
) =
1655 (void (*)(void *, BOOL
))c
;
1658 DEBUG(5, ("Could not trigger a map dump\n"));
1659 cont(private_data
, False
);
1663 if (response
->result
!= WINBINDD_OK
) {
1664 DEBUG(5, ("idmap dump maps returned an error\n"));
1665 cont(private_data
, False
);
1669 cont(private_data
, True
);
1672 void winbindd_dump_maps_async(TALLOC_CTX
*mem_ctx
, void *data
, int size
,
1673 void (*cont
)(void *private_data
, BOOL success
),
1676 struct winbindd_request request
;
1677 ZERO_STRUCT(request
);
1678 request
.cmd
= WINBINDD_DUAL_DUMP_MAPS
;
1679 request
.extra_data
.data
= (char *)data
;
1680 request
.extra_len
= size
;
1681 do_async(mem_ctx
, idmap_child(), &request
, winbindd_dump_id_maps_recv
,
1682 (void *)cont
, private_data
);
1685 enum winbindd_result
winbindd_dual_dump_maps(struct winbindd_domain
*domain
,
1686 struct winbindd_cli_state
*state
)
1688 DEBUG(3, ("[%5lu]: dual dump maps\n", (unsigned long)state
->pid
));
1690 idmap_dump_maps((char *)state
->request
.extra_data
.data
);