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 3 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, see <http://www.gnu.org/licenses/>.
38 #define DBGC_CLASS DBGC_WINBIND
40 struct do_async_state {
42 struct winbindd_request request;
43 struct winbindd_response response;
44 void (*cont)(TALLOC_CTX *mem_ctx,
46 struct winbindd_response *response,
47 void *c, void *private_data);
48 void *c, *private_data;
51 static void do_async_recv(void *private_data, bool success)
53 struct do_async_state *state =
54 talloc_get_type_abort(private_data, struct do_async_state);
56 state->cont(state->mem_ctx, success, &state->response,
57 state->c, state->private_data);
60 void do_async(TALLOC_CTX *mem_ctx, struct winbindd_child *child,
61 const struct winbindd_request *request,
62 void (*cont)(TALLOC_CTX *mem_ctx, bool success,
63 struct winbindd_response *response,
64 void *c, void *private_data),
65 void *c, void *private_data)
67 struct do_async_state *state;
69 state = TALLOC_ZERO_P(mem_ctx, struct do_async_state);
71 DEBUG(0, ("talloc failed\n"));
72 cont(mem_ctx, False, NULL, c, private_data);
76 state->mem_ctx = mem_ctx;
77 state->request = *request;
78 state->request.length = sizeof(state->request);
81 state->private_data = private_data;
83 async_request(mem_ctx, child, &state->request,
84 &state->response, do_async_recv, state);
87 void do_async_domain(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
88 const struct winbindd_request *request,
89 void (*cont)(TALLOC_CTX *mem_ctx, bool success,
90 struct winbindd_response *response,
91 void *c, void *private_data),
92 void *c, void *private_data)
94 struct do_async_state *state;
96 state = TALLOC_ZERO_P(mem_ctx, struct do_async_state);
98 DEBUG(0, ("talloc failed\n"));
99 cont(mem_ctx, False, NULL, c, private_data);
103 state->mem_ctx = mem_ctx;
104 state->request = *request;
105 state->request.length = sizeof(state->request);
108 state->private_data = private_data;
110 async_domain_request(mem_ctx, domain, &state->request,
111 &state->response, do_async_recv, state);
114 struct do_async_ndr_state {
116 struct winbindd_ndr_call call;
117 void (*cont)(TALLOC_CTX *mem_ctx, bool success,
118 struct winbindd_ndr_call *call,
121 void *caller_private);
124 void *caller_private;
127 static void do_async_ndr_recv(void *private_data, bool success)
129 struct do_async_ndr_state *state =
130 talloc_get_type_abort(private_data, struct do_async_ndr_state);
132 state->cont(state->mem_ctx, success,
133 &state->call, state->private_data,
134 state->caller_cont, state->caller_private);
137 void do_async_ndr(TALLOC_CTX *mem_ctx, struct winbindd_child *child,
138 uint32 opnum, void *r,
139 void (*cont)(TALLOC_CTX *mem_ctx, bool success,
140 struct winbindd_ndr_call *call,
143 void *caller_private),
146 void *caller_private)
148 struct do_async_ndr_state *state;
150 SMB_ASSERT(opnum < ndr_table_winbind_protocol.num_calls);
152 state = TALLOC_ZERO_P(mem_ctx, struct do_async_ndr_state);
154 DEBUG(0, ("talloc failed\n"));
155 cont(mem_ctx, False, NULL, private_data,
156 caller_cont, caller_private);
160 state->mem_ctx = mem_ctx;
161 state->call.ndr.call = &ndr_table_winbind_protocol.calls[opnum];
162 state->call.ndr.r = r;
164 state->private_data = private_data;
165 state->caller_cont = caller_cont;
166 state->caller_private = caller_private;
168 async_ndr_call(mem_ctx, child, &state->call,
169 do_async_ndr_recv, state);
172 void do_async_ndr_domain(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
173 uint32 opnum, void *r,
174 void (*cont)(TALLOC_CTX *mem_ctx, bool success,
175 struct winbindd_ndr_call *call,
178 void *caller_private),
181 void *caller_private)
183 struct do_async_ndr_state *state;
185 SMB_ASSERT(opnum < ndr_table_winbind_protocol.num_calls);
187 state = TALLOC_ZERO_P(mem_ctx, struct do_async_ndr_state);
189 DEBUG(0, ("talloc failed\n"));
190 cont(mem_ctx, False, NULL, private_data,
191 caller_cont, caller_private);
195 state->mem_ctx = mem_ctx;
196 state->call.ndr.call = &ndr_table_winbind_protocol.calls[opnum];
197 state->call.ndr.r = r;
199 state->private_data = private_data;
200 state->caller_cont = caller_cont;
201 state->caller_private = caller_private;
203 async_ndr_domain_call(mem_ctx, domain, &state->call,
204 do_async_ndr_recv, state);
207 static void winbindd_lookupsid_recv2(TALLOC_CTX *mem_ctx, bool success,
208 struct winbindd_ndr_call *c,
213 void (*cont)(void *priv, bool succ, const char *dom_name,
214 const char *name, enum lsa_SidType type) =
215 (void (*)(void *, bool, const char *, const char *,
216 enum lsa_SidType))_cont;
217 struct winbind_lookup *r =
218 talloc_get_type_abort(_private_data, struct winbind_lookup);
221 DEBUG(5, ("Could not trigger lookup(sid2name)\n"));
223 cont(cont_private, false, NULL, NULL, SID_NAME_UNKNOWN);
227 if (r->out.result != WINBIND_STATUS_OK) {
228 DEBUG(5,("lookup(sid2name) returned an error:0x%08X\n"
229 " (root domain)\n", r->out.result));
231 cont(cont_private, false, NULL, NULL, SID_NAME_UNKNOWN);
235 cont(cont_private, true,
236 r->out.rep->name_info.domain_name,
237 r->out.rep->name_info.account_name,
238 r->out.rep->name_info.type);
241 static void winbindd_lookupsid_recv1(TALLOC_CTX *mem_ctx, bool success,
242 struct winbindd_ndr_call *c,
247 void (*cont)(void *priv, bool succ, const char *dom_name,
248 const char *name, enum lsa_SidType type) =
249 (void (*)(void *, bool, const char *, const char *,
250 enum lsa_SidType))_cont;
251 struct winbind_lookup *r =
252 talloc_get_type_abort(_private_data, struct winbind_lookup);
255 DEBUG(5, ("Could not trigger lookup(sid2name)\n"));
257 cont(cont_private, false, NULL, NULL, SID_NAME_UNKNOWN);
261 if (r->out.result != WINBIND_STATUS_OK) {
262 struct winbindd_domain *root_domain = find_root_domain();
264 if ( !root_domain ) {
265 DEBUG(5,("lookup(sid2name) returned an error:0x%08X\n"
266 " (no root domain as fallback)\n", r->out.result));
269 cont(cont_private, false, NULL, NULL, SID_NAME_UNKNOWN);
272 DEBUG(5,("lookup(sid2name) returned an error:0x%08X"
273 " (fallback to root domain)\n", r->out.result));
275 do_async_ndr_domain(mem_ctx, root_domain,
276 NDR_WINBIND_LOOKUP, r,
277 winbindd_lookupsid_recv2, r,
278 (void *)cont, cont_private);
282 cont(cont_private, true,
283 r->out.rep->name_info.domain_name,
284 r->out.rep->name_info.account_name,
285 r->out.rep->name_info.type);
288 void winbindd_lookupsid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
289 void (*cont)(void *private_data, bool success,
290 const char *dom_name,
292 enum lsa_SidType type),
295 struct winbindd_domain *domain;
296 struct winbind_lookup *r = NULL;
298 domain = find_lookup_domain_from_sid(sid);
299 if (domain == NULL) {
300 DEBUG(5, ("Could not find domain for sid %s\n",
301 sid_string_dbg(sid)));
302 cont(cont_private, false, NULL, NULL, SID_NAME_UNKNOWN);
306 r = TALLOC_P(mem_ctx, struct winbind_lookup);
308 r->in.level = TALLOC_P(r, enum winbind_lookup_level);
309 if (!r->in.level) goto nomem;
311 *r->in.level = WINBIND_LOOKUP_LEVEL_SID2NAME;
312 r->in.req.sid = sid_dup_talloc(r, sid);
313 if (!r->in.req.sid) goto nomem;
315 do_async_ndr_domain(mem_ctx, domain,
316 NDR_WINBIND_LOOKUP, r,
317 winbindd_lookupsid_recv1, r,
318 (void *)cont, cont_private);
322 cont(cont_private, false, NULL, NULL, SID_NAME_UNKNOWN);
326 static void ndr_child_lookup_sid2name(struct winbindd_domain *domain,
327 struct winbindd_cli_state *state,
328 struct winbind_lookup *r)
332 DEBUG(3, ("lookup sid2name %s\n",
333 sid_string_dbg(r->in.req.sid)));
337 ok = winbindd_lookup_name_by_sid(r, domain,
339 (char **)&r->out.rep->name_info.domain_name,
340 (char **)&r->out.rep->name_info.account_name,
341 &r->out.rep->name_info.type);
343 DEBUG(1, ("Can't lookup name by sid\n"));
344 r->out.result = WINBIND_STATUS_FOOBAR;
348 r->out.result = WINBIND_STATUS_OK;
351 static void ndr_child_lookup_name2sid(struct winbindd_domain *domain,
352 struct winbindd_cli_state *state,
353 struct winbind_lookup *r)
360 DEBUG(3, ("lookup name2sid %s\n",
363 name_domain = talloc_strdup(r, r->in.req.name);
365 r->out.result = WINBIND_STATUS_NO_MEMORY;
369 /* the name must be a fully qualified name */
370 p = strstr(name_domain, lp_winbind_separator());
372 r->out.result = WINBIND_STATUS_INVALID_PARAMETER;
379 r->out.rep->sid_info.sid = TALLOC_ZERO_P(r, struct dom_sid);
380 if (!r->out.rep->sid_info.sid) {
381 r->out.result = WINBIND_STATUS_NO_MEMORY;
385 /* Lookup name from DC using lsa_lookup_names() */
386 /* TODO: */ ok = winbindd_lookup_sid_by_name(state->mem_ctx, WINBINDD_LOOKUPNAME,
387 domain, name_domain, name_user,
388 r->out.rep->sid_info.sid,
389 &r->out.rep->sid_info.type);
391 DEBUG(1, ("Can't lookup name by sid\n"));
392 r->out.result = WINBIND_STATUS_FOOBAR;
396 r->out.result = WINBIND_STATUS_OK;
399 void winbindd_ndr_domain_child_lookup(struct winbindd_domain *domain,
400 struct winbindd_cli_state *state)
402 struct winbind_lookup *r;
404 r = talloc_get_type_abort(state->c.ndr.r,
405 struct winbind_lookup);
407 switch (*r->in.level) {
408 case WINBIND_LOOKUP_LEVEL_SID2NAME:
409 ndr_child_lookup_sid2name(domain, state, r);
412 case WINBIND_LOOKUP_LEVEL_NAME2SID:
413 ndr_child_lookup_name2sid(domain, state, r);
417 r->out.result = WINBIND_STATUS_UNKNOWN_LEVEL;
421 /********************************************************************
422 This is the second callback after contacting the forest root
423 ********************************************************************/
425 static void winbindd_lookupname_recv2(TALLOC_CTX *mem_ctx, bool success,
426 struct winbindd_ndr_call *c,
431 void (*cont)(void *priv, bool succ,
432 const DOM_SID *sid, enum lsa_SidType type) =
433 (void (*)(void *, bool, const DOM_SID *,
434 enum lsa_SidType))_cont;
435 struct winbind_lookup *r =
436 talloc_get_type_abort(_private_data, struct winbind_lookup);
439 DEBUG(5, ("Could not trigger lookup(name2sid)\n"));
441 cont(cont_private, false, NULL, SID_NAME_UNKNOWN);
445 if (r->out.result != WINBIND_STATUS_OK) {
446 DEBUG(5,("lookup(name2sid) returned an error:0x%08X\n"
447 " (root domain)\n", r->out.result));
449 cont(cont_private, false, NULL, SID_NAME_UNKNOWN);
453 cont(cont_private, true,
454 r->out.rep->sid_info.sid,
455 r->out.rep->sid_info.type);
458 /********************************************************************
459 This is the first callback after contacting our own domain
460 ********************************************************************/
462 static void winbindd_lookupname_recv1(TALLOC_CTX *mem_ctx, bool success,
463 struct winbindd_ndr_call *c,
468 void (*cont)(void *priv, bool succ,
469 const DOM_SID *sid, enum lsa_SidType type) =
470 (void (*)(void *, bool, const DOM_SID *,
471 enum lsa_SidType))_cont;
472 struct winbind_lookup *r =
473 talloc_get_type_abort(_private_data, struct winbind_lookup);
476 DEBUG(5, ("Could not trigger lookup(name2sid)\n"));
478 cont(cont_private, false, NULL, SID_NAME_UNKNOWN);
482 if (r->out.result != WINBIND_STATUS_OK) {
483 struct winbindd_domain *root_domain = find_root_domain();
485 if ( !root_domain ) {
486 DEBUG(5,("lookup(name2sid) returned an error:0x%08X\n"
487 " (no root domain as fallback)\n", r->out.result));
490 cont(cont_private, false, NULL, SID_NAME_UNKNOWN);
493 DEBUG(5,("lookup(name2sid) returned an error:0x%08X"
494 " (fallback to root domain)\n", r->out.result));
496 do_async_ndr_domain(mem_ctx, root_domain,
497 NDR_WINBIND_LOOKUP, r,
498 winbindd_lookupname_recv2, r,
499 (void *)cont, cont_private);
503 cont(cont_private, true,
504 r->out.rep->sid_info.sid,
505 r->out.rep->sid_info.type);
508 /********************************************************************
509 The lookup name call first contacts a DC in its own domain
510 and fallbacks to contact a DC in the forest in our domain doesn't
512 ********************************************************************/
514 void winbindd_lookupname_async(TALLOC_CTX *mem_ctx,
515 const char *dom_name, const char *name,
516 void (*cont)(void *private_data, bool success,
518 enum lsa_SidType type),
519 enum winbindd_cmd orig_cmd,
522 struct winbindd_domain *domain;
523 struct winbind_lookup *r = NULL;
525 if ( (domain = find_lookup_domain_from_name(dom_name)) == NULL ) {
526 DEBUG(5, ("Could not find domain for name '%s'\n", dom_name));
527 cont(cont_private, false, NULL, SID_NAME_UNKNOWN);
531 r = TALLOC_P(mem_ctx, struct winbind_lookup);
533 r->in.level = TALLOC_P(r, enum winbind_lookup_level);
534 if (!r->in.level) goto nomem;
536 *r->in.level = WINBIND_LOOKUP_LEVEL_NAME2SID;
537 r->in.req.name = talloc_asprintf(r, "%s%s%s",
539 lp_winbind_separator(),
541 if (!r->in.req.name) goto nomem;
542 /*TODO: pass down orig_cmd */
543 do_async_ndr_domain(mem_ctx, domain,
544 NDR_WINBIND_LOOKUP, r,
545 winbindd_lookupname_recv1, r,
546 (void *)cont, cont_private);
550 cont(cont_private, false, NULL, SID_NAME_UNKNOWN);
554 enum winbindd_result winbindd_dual_lookupname(struct winbindd_domain *domain,
555 struct winbindd_cli_state *state)
557 enum lsa_SidType type;
558 char *name_domain, *name_user;
562 /* Ensure null termination */
563 state->request.data.name.dom_name[sizeof(state->request.data.name.dom_name)-1]='\0';
565 /* Ensure null termination */
566 state->request.data.name.name[sizeof(state->request.data.name.name)-1]='\0';
568 /* cope with the name being a fully qualified name */
569 p = strstr(state->request.data.name.name, lp_winbind_separator());
572 name_domain = state->request.data.name.name;
575 name_domain = state->request.data.name.dom_name;
576 name_user = state->request.data.name.name;
579 DEBUG(3, ("[%5lu]: lookupname %s%s%s\n", (unsigned long)state->pid,
580 name_domain, lp_winbind_separator(), name_user));
582 /* Lookup name from DC using lsa_lookup_names() */
583 if (!winbindd_lookup_sid_by_name(state->mem_ctx, state->request.original_cmd, domain, name_domain,
584 name_user, &sid, &type)) {
585 return WINBINDD_ERROR;
588 sid_to_fstring(state->response.data.sid.sid, &sid);
589 state->response.data.sid.type = type;
594 bool print_sidlist(TALLOC_CTX *mem_ctx, const DOM_SID *sids,
595 size_t num_sids, char **result, ssize_t *len)
602 for (i=0; i<num_sids; i++) {
604 sprintf_append(mem_ctx, result, len, &buflen,
605 "%s\n", sid_to_fstring(tmp, &sids[i]));
608 if ((num_sids != 0) && (*result == NULL)) {
615 static bool parse_sidlist(TALLOC_CTX *mem_ctx, char *sidstr,
616 DOM_SID **sids, size_t *num_sids)
624 while (p[0] != '\0') {
628 DEBUG(0, ("Got invalid sidstr: %s\n", p));
633 if (!string_to_sid(&sid, p)) {
634 DEBUG(0, ("Could not parse sid %s\n", p));
637 if (!NT_STATUS_IS_OK(add_sid_to_array(mem_ctx, &sid, sids,
647 static bool parse_ridlist(TALLOC_CTX *mem_ctx, char *ridstr,
648 uint32 **rids, size_t *num_rids)
656 while (p[0] != '\0') {
659 rid = strtoul(p, &q, 10);
661 DEBUG(0, ("Got invalid ridstr: %s\n", p));
665 ADD_TO_ARRAY(mem_ctx, uint32, rid, rids, num_rids);
670 enum winbindd_result winbindd_dual_lookuprids(struct winbindd_domain *domain,
671 struct winbindd_cli_state *state)
674 size_t i, buflen, num_rids = 0;
679 enum lsa_SidType *types;
683 DEBUG(10, ("Looking up RIDs for domain %s (%s)\n",
684 state->request.domain_name,
685 state->request.data.sid));
687 if (!parse_ridlist(state->mem_ctx, state->request.extra_data.data,
689 DEBUG(5, ("Could not parse ridlist\n"));
690 return WINBINDD_ERROR;
693 if (!string_to_sid(&domain_sid, state->request.data.sid)) {
694 DEBUG(5, ("Could not parse domain sid %s\n",
695 state->request.data.sid));
696 return WINBINDD_ERROR;
699 status = domain->methods->rids_to_names(domain, state->mem_ctx,
700 &domain_sid, rids, num_rids,
704 if (!NT_STATUS_IS_OK(status) &&
705 !NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
706 return WINBINDD_ERROR;
713 for (i=0; i<num_rids; i++) {
714 sprintf_append(state->mem_ctx, &result, &len, &buflen,
715 "%d %s\n", types[i], names[i]);
718 fstrcpy(state->response.data.domain_name, domain_name);
720 if (result != NULL) {
721 state->response.extra_data.data = SMB_STRDUP(result);
722 if (!state->response.extra_data.data) {
723 return WINBINDD_ERROR;
725 state->response.length += len+1;
731 static void getsidaliases_recv(TALLOC_CTX *mem_ctx, bool success,
732 struct winbindd_response *response,
733 void *c, void *private_data)
735 void (*cont)(void *priv, bool succ,
736 DOM_SID *aliases, size_t num_aliases) =
737 (void (*)(void *, bool, DOM_SID *, size_t))c;
739 DOM_SID *sids = NULL;
743 DEBUG(5, ("Could not trigger getsidaliases\n"));
744 cont(private_data, success, NULL, 0);
748 if (response->result != WINBINDD_OK) {
749 DEBUG(5, ("getsidaliases returned an error\n"));
750 cont(private_data, False, NULL, 0);
754 aliases_str = (char *)response->extra_data.data;
756 if (aliases_str == NULL) {
757 DEBUG(10, ("getsidaliases return 0 SIDs\n"));
758 cont(private_data, True, NULL, 0);
762 if (!parse_sidlist(mem_ctx, aliases_str, &sids, &num_sids)) {
763 DEBUG(0, ("Could not parse sids\n"));
764 cont(private_data, False, NULL, 0);
768 SAFE_FREE(response->extra_data.data);
770 cont(private_data, True, sids, num_sids);
773 void winbindd_getsidaliases_async(struct winbindd_domain *domain,
775 const DOM_SID *sids, size_t num_sids,
776 void (*cont)(void *private_data,
778 const DOM_SID *aliases,
782 struct winbindd_request request;
787 cont(private_data, True, NULL, 0);
791 if (!print_sidlist(mem_ctx, sids, num_sids, &sidstr, &len)) {
792 cont(private_data, False, NULL, 0);
796 ZERO_STRUCT(request);
797 request.cmd = WINBINDD_DUAL_GETSIDALIASES;
798 request.extra_len = len;
799 request.extra_data.data = sidstr;
801 do_async_domain(mem_ctx, domain, &request, getsidaliases_recv,
802 (void *)cont, private_data);
805 enum winbindd_result winbindd_dual_getsidaliases(struct winbindd_domain *domain,
806 struct winbindd_cli_state *state)
808 DOM_SID *sids = NULL;
817 DEBUG(3, ("[%5lu]: getsidaliases\n", (unsigned long)state->pid));
819 sidstr = state->request.extra_data.data;
820 if (sidstr == NULL) {
821 sidstr = talloc_strdup(state->mem_ctx, "\n"); /* No SID */
823 DEBUG(0, ("Out of memory\n"));
824 return WINBINDD_ERROR;
828 DEBUG(10, ("Sidlist: %s\n", sidstr));
830 if (!parse_sidlist(state->mem_ctx, sidstr, &sids, &num_sids)) {
831 DEBUG(0, ("Could not parse SID list: %s\n", sidstr));
832 return WINBINDD_ERROR;
838 result = domain->methods->lookup_useraliases(domain,
844 if (!NT_STATUS_IS_OK(result)) {
845 DEBUG(3, ("Could not lookup_useraliases: %s\n",
847 return WINBINDD_ERROR;
854 DEBUG(10, ("Got %d aliases\n", num_aliases));
856 for (i=0; i<num_aliases; i++) {
858 DEBUGADD(10, (" rid %d\n", alias_rids[i]));
859 sid_copy(&sid, &domain->sid);
860 sid_append_rid(&sid, alias_rids[i]);
861 result = add_sid_to_array(state->mem_ctx, &sid, &sids,
863 if (!NT_STATUS_IS_OK(result)) {
864 return WINBINDD_ERROR;
869 if (!print_sidlist(state->mem_ctx, sids, num_sids, &sidstr, &len)) {
870 DEBUG(0, ("Could not print_sidlist\n"));
871 state->response.extra_data.data = NULL;
872 return WINBINDD_ERROR;
875 state->response.extra_data.data = NULL;
878 state->response.extra_data.data = SMB_STRDUP(sidstr);
879 if (!state->response.extra_data.data) {
880 DEBUG(0, ("Out of memory\n"));
881 return WINBINDD_ERROR;
883 DEBUG(10, ("aliases_list: %s\n",
884 (char *)state->response.extra_data.data));
885 state->response.length += len+1;
891 struct gettoken_state {
894 struct winbindd_domain *alias_domain;
895 struct winbindd_domain *local_alias_domain;
896 struct winbindd_domain *builtin_domain;
899 void (*cont)(void *private_data, bool success, DOM_SID *sids, size_t num_sids);
903 static void gettoken_recvdomgroups(TALLOC_CTX *mem_ctx, bool success,
904 struct winbindd_response *response,
905 void *c, void *private_data);
906 static void gettoken_recvaliases(void *private_data, bool success,
907 const DOM_SID *aliases,
911 void winbindd_gettoken_async(TALLOC_CTX *mem_ctx, const DOM_SID *user_sid,
912 void (*cont)(void *private_data, bool success,
913 DOM_SID *sids, size_t num_sids),
916 struct winbindd_domain *domain;
917 struct winbindd_request request;
918 struct gettoken_state *state;
920 state = TALLOC_ZERO_P(mem_ctx, struct gettoken_state);
922 DEBUG(0, ("talloc failed\n"));
923 cont(private_data, False, NULL, 0);
927 state->mem_ctx = mem_ctx;
928 sid_copy(&state->user_sid, user_sid);
929 state->alias_domain = find_our_domain();
930 state->local_alias_domain = find_domain_from_name( get_global_sam_name() );
931 state->builtin_domain = find_builtin_domain();
933 state->private_data = private_data;
935 domain = find_domain_from_sid_noinit(user_sid);
936 if (domain == NULL) {
937 DEBUG(5, ("Could not find domain from SID %s\n",
938 sid_string_dbg(user_sid)));
939 cont(private_data, False, NULL, 0);
943 ZERO_STRUCT(request);
944 request.cmd = WINBINDD_GETUSERDOMGROUPS;
945 sid_to_fstring(request.data.sid, user_sid);
947 do_async_domain(mem_ctx, domain, &request, gettoken_recvdomgroups,
951 static void gettoken_recvdomgroups(TALLOC_CTX *mem_ctx, bool success,
952 struct winbindd_response *response,
953 void *c, void *private_data)
955 struct gettoken_state *state =
956 talloc_get_type_abort(private_data, struct gettoken_state);
960 DEBUG(10, ("Could not get domain groups\n"));
961 state->cont(state->private_data, False, NULL, 0);
965 sids_str = (char *)response->extra_data.data;
967 if (sids_str == NULL) {
968 /* This could be normal if we are dealing with a
969 local user and local groups */
971 if ( !sid_check_is_in_our_domain( &state->user_sid ) ) {
972 DEBUG(10, ("Received no domain groups\n"));
973 state->cont(state->private_data, True, NULL, 0);
981 if (!NT_STATUS_IS_OK(add_sid_to_array(mem_ctx, &state->user_sid,
982 &state->sids, &state->num_sids)))
984 DEBUG(0, ("Out of memory\n"));
985 state->cont(state->private_data, False, NULL, 0);
989 if (sids_str && !parse_sidlist(mem_ctx, sids_str, &state->sids,
991 DEBUG(0, ("Could not parse sids\n"));
992 state->cont(state->private_data, False, NULL, 0);
996 SAFE_FREE(response->extra_data.data);
998 if (state->alias_domain == NULL) {
999 DEBUG(10, ("Don't expand domain local groups\n"));
1000 state->cont(state->private_data, True, state->sids,
1005 winbindd_getsidaliases_async(state->alias_domain, mem_ctx,
1006 state->sids, state->num_sids,
1007 gettoken_recvaliases, state);
1010 static void gettoken_recvaliases(void *private_data, bool success,
1011 const DOM_SID *aliases,
1014 struct gettoken_state *state = (struct gettoken_state *)private_data;
1018 DEBUG(10, ("Could not receive domain local groups\n"));
1019 state->cont(state->private_data, False, NULL, 0);
1023 for (i=0; i<num_aliases; i++) {
1024 if (!NT_STATUS_IS_OK(add_sid_to_array(state->mem_ctx,
1029 DEBUG(0, ("Out of memory\n"));
1030 state->cont(state->private_data, False, NULL, 0);
1035 if (state->local_alias_domain != NULL) {
1036 struct winbindd_domain *local_domain = state->local_alias_domain;
1037 DEBUG(10, ("Expanding our own local groups\n"));
1038 state->local_alias_domain = NULL;
1039 winbindd_getsidaliases_async(local_domain, state->mem_ctx,
1040 state->sids, state->num_sids,
1041 gettoken_recvaliases, state);
1045 if (state->builtin_domain != NULL) {
1046 struct winbindd_domain *builtin_domain = state->builtin_domain;
1047 DEBUG(10, ("Expanding our own BUILTIN groups\n"));
1048 state->builtin_domain = NULL;
1049 winbindd_getsidaliases_async(builtin_domain, state->mem_ctx,
1050 state->sids, state->num_sids,
1051 gettoken_recvaliases, state);
1055 state->cont(state->private_data, True, state->sids, state->num_sids);
1058 static void query_user_recv(TALLOC_CTX *mem_ctx, bool success,
1059 struct winbindd_response *response,
1060 void *c, void *private_data)
1062 void (*cont)(void *priv, bool succ, const char *acct_name,
1063 const char *full_name, const char *homedir,
1064 const char *shell, uint32 gid, uint32 group_rid) =
1065 (void (*)(void *, bool, const char *, const char *,
1066 const char *, const char *, uint32, uint32))c;
1069 DEBUG(5, ("Could not trigger query_user\n"));
1070 cont(private_data, False, NULL, NULL, NULL, NULL, -1, -1);
1074 if (response->result != WINBINDD_OK) {
1075 DEBUG(5, ("query_user returned an error\n"));
1076 cont(private_data, False, NULL, NULL, NULL, NULL, -1, -1);
1080 cont(private_data, True, response->data.user_info.acct_name,
1081 response->data.user_info.full_name,
1082 response->data.user_info.homedir,
1083 response->data.user_info.shell,
1084 response->data.user_info.primary_gid,
1085 response->data.user_info.group_rid);
1088 void query_user_async(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1090 void (*cont)(void *private_data, bool success,
1091 const char *acct_name,
1092 const char *full_name,
1093 const char *homedir,
1099 struct winbindd_request request;
1100 ZERO_STRUCT(request);
1101 request.cmd = WINBINDD_DUAL_USERINFO;
1102 sid_to_fstring(request.data.sid, sid);
1103 do_async_domain(mem_ctx, domain, &request, query_user_recv,
1104 (void *)cont, private_data);