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 static void ndr_child_lookup_rids2names(struct winbindd_domain *domain,
400 struct winbindd_cli_state *state,
401 struct winbind_lookup *r)
405 enum lsa_SidType *types;
408 struct winbind_lookup_name_info *n;
410 DEBUG(3, ("lookup rids2name domain:%s num %u\n",
411 sid_string_dbg(r->in.req.rids.domain_sid),
412 r->in.req.rids.num_rids));
415 status = domain->methods->rids_to_names(domain, state->mem_ctx,
416 r->in.req.rids.domain_sid,
418 r->in.req.rids.num_rids,
422 if (!NT_STATUS_IS_OK(status) &&
423 !NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
424 DEBUG(1, ("Can't lookup names by rids: %s\n",
426 r->out.result = WINBIND_STATUS_FOOBAR;
430 r->out.rep->name_array.num_names = r->in.req.rids.num_rids;
432 struct winbind_lookup_name_info,
433 r->out.rep->name_array.num_names);
435 r->out.result = WINBIND_STATUS_NO_MEMORY;
438 r->out.rep->name_array.names = n;
440 for (i=0; i < r->out.rep->name_array.num_names; i++) {
441 n[i].domain_name = domain_name;
442 n[i].account_name = names[i];
443 n[i].type = types[i];
446 r->out.result = WINBIND_STATUS_OK;
449 static void ndr_child_lookup_sid2userinfo(struct winbindd_domain *domain,
450 struct winbindd_cli_state *state,
451 struct winbind_lookup *r)
454 WINBIND_USERINFO user_info;
456 DEBUG(3, ("lookup sid2userinfo user:%s\n",
457 sid_string_dbg(r->in.req.sid)));
460 status = domain->methods->query_user(domain, state->mem_ctx,
461 r->in.req.sid, &user_info);
462 if (!NT_STATUS_IS_OK(status)) {
463 DEBUG(1, ("error getting user info for sid %s: %s\n",
464 sid_string_dbg(r->in.req.sid), nt_errstr(status)));
465 r->out.result = WINBIND_STATUS_FOOBAR;
469 r->out.rep->user_info.account = user_info.acct_name;
470 r->out.rep->user_info.gecos = user_info.full_name;
471 r->out.rep->user_info.homedir = user_info.homedir;
472 r->out.rep->user_info.shell = user_info.shell;
473 r->out.rep->user_info.primary_gid = user_info.primary_gid;
475 if (!sid_peek_check_rid(&domain->sid, &user_info.group_sid,
476 &r->out.rep->user_info.primary_rid)) {
477 DEBUG(1, ("Could not extract group rid out of %s\n",
478 sid_string_dbg(&user_info.group_sid)));
479 r->out.result = WINBIND_STATUS_FOOBAR;
483 r->out.result = WINBIND_STATUS_OK;
486 static void ndr_child_lookup_sid2domgroups(struct winbindd_domain *domain,
487 struct winbindd_cli_state *state,
488 struct winbind_lookup *r)
491 struct winbind_lookup_sid_info *a;
492 struct dom_sid *groups;
493 uint32_t i, num_groups;
495 DEBUG(3, ("lookup sid2domgroups user:%s\n",
496 sid_string_dbg(r->in.req.sid)));
498 status = domain->methods->lookup_usergroups(domain, state->mem_ctx,
499 r->in.req.sid, &num_groups,
501 if (!NT_STATUS_IS_OK(status)) {
502 DEBUG(1, ("error getting user domain groups info for sid %s: %s\n",
503 sid_string_dbg(r->in.req.sid), nt_errstr(status)));
504 r->out.result = WINBIND_STATUS_FOOBAR;
508 a = talloc_array(r, struct winbind_lookup_sid_info, num_groups);
510 r->out.result = WINBIND_STATUS_NO_MEMORY;
514 for (i=0; i < num_groups; i++) {
515 a[i].sid = &groups[i];
516 /* TODO: get this from the backend */
517 a[i].type = SID_NAME_DOM_GRP;
520 r->out.rep->sid_array.num_sids = num_groups;
521 r->out.rep->sid_array.sids = a;
523 r->out.result = WINBIND_STATUS_OK;
526 void winbindd_ndr_domain_child_lookup(struct winbindd_domain *domain,
527 struct winbindd_cli_state *state)
529 struct winbind_lookup *r;
531 r = talloc_get_type_abort(state->c.ndr.r,
532 struct winbind_lookup);
534 switch (*r->in.level) {
535 case WINBIND_LOOKUP_LEVEL_SID2NAME:
536 ndr_child_lookup_sid2name(domain, state, r);
539 case WINBIND_LOOKUP_LEVEL_NAME2SID:
540 ndr_child_lookup_name2sid(domain, state, r);
543 case WINBIND_LOOKUP_LEVEL_RIDS2NAMES:
544 ndr_child_lookup_rids2names(domain, state, r);
547 case WINBIND_LOOKUP_LEVEL_SID2USERINFO:
548 ndr_child_lookup_sid2userinfo(domain, state, r);
551 case WINBIND_LOOKUP_LEVEL_SID2DOMGROUPS:
552 ndr_child_lookup_sid2domgroups(domain, state, r);
556 r->out.result = WINBIND_STATUS_UNKNOWN_LEVEL;
560 /********************************************************************
561 This is the second callback after contacting the forest root
562 ********************************************************************/
564 static void winbindd_lookupname_recv2(TALLOC_CTX *mem_ctx, bool success,
565 struct winbindd_ndr_call *c,
570 void (*cont)(void *priv, bool succ,
571 const DOM_SID *sid, enum lsa_SidType type) =
572 (void (*)(void *, bool, const DOM_SID *,
573 enum lsa_SidType))_cont;
574 struct winbind_lookup *r =
575 talloc_get_type_abort(_private_data, struct winbind_lookup);
578 DEBUG(5, ("Could not trigger lookup(name2sid)\n"));
580 cont(cont_private, false, NULL, SID_NAME_UNKNOWN);
584 if (r->out.result != WINBIND_STATUS_OK) {
585 DEBUG(5,("lookup(name2sid) returned an error:0x%08X\n"
586 " (root domain)\n", r->out.result));
588 cont(cont_private, false, NULL, SID_NAME_UNKNOWN);
592 cont(cont_private, true,
593 r->out.rep->sid_info.sid,
594 r->out.rep->sid_info.type);
597 /********************************************************************
598 This is the first callback after contacting our own domain
599 ********************************************************************/
601 static void winbindd_lookupname_recv1(TALLOC_CTX *mem_ctx, bool success,
602 struct winbindd_ndr_call *c,
607 void (*cont)(void *priv, bool succ,
608 const DOM_SID *sid, enum lsa_SidType type) =
609 (void (*)(void *, bool, const DOM_SID *,
610 enum lsa_SidType))_cont;
611 struct winbind_lookup *r =
612 talloc_get_type_abort(_private_data, struct winbind_lookup);
615 DEBUG(5, ("Could not trigger lookup(name2sid)\n"));
617 cont(cont_private, false, NULL, SID_NAME_UNKNOWN);
621 if (r->out.result != WINBIND_STATUS_OK) {
622 struct winbindd_domain *root_domain = find_root_domain();
624 if ( !root_domain ) {
625 DEBUG(5,("lookup(name2sid) returned an error:0x%08X\n"
626 " (no root domain as fallback)\n", r->out.result));
629 cont(cont_private, false, NULL, SID_NAME_UNKNOWN);
632 DEBUG(5,("lookup(name2sid) returned an error:0x%08X"
633 " (fallback to root domain)\n", r->out.result));
635 do_async_ndr_domain(mem_ctx, root_domain,
636 NDR_WINBIND_LOOKUP, r,
637 winbindd_lookupname_recv2, r,
638 (void *)cont, cont_private);
642 cont(cont_private, true,
643 r->out.rep->sid_info.sid,
644 r->out.rep->sid_info.type);
647 /********************************************************************
648 The lookup name call first contacts a DC in its own domain
649 and fallbacks to contact a DC in the forest in our domain doesn't
651 ********************************************************************/
653 void winbindd_lookupname_async(TALLOC_CTX *mem_ctx,
654 const char *dom_name, const char *name,
655 void (*cont)(void *private_data, bool success,
657 enum lsa_SidType type),
658 enum winbindd_cmd orig_cmd,
661 struct winbindd_domain *domain;
662 struct winbind_lookup *r = NULL;
664 if ( (domain = find_lookup_domain_from_name(dom_name)) == NULL ) {
665 DEBUG(5, ("Could not find domain for name '%s'\n", dom_name));
666 cont(cont_private, false, NULL, SID_NAME_UNKNOWN);
670 r = TALLOC_P(mem_ctx, struct winbind_lookup);
672 r->in.level = TALLOC_P(r, enum winbind_lookup_level);
673 if (!r->in.level) goto nomem;
675 *r->in.level = WINBIND_LOOKUP_LEVEL_NAME2SID;
676 r->in.req.name = talloc_asprintf(r, "%s%s%s",
678 lp_winbind_separator(),
680 if (!r->in.req.name) goto nomem;
681 /*TODO: pass down orig_cmd */
682 do_async_ndr_domain(mem_ctx, domain,
683 NDR_WINBIND_LOOKUP, r,
684 winbindd_lookupname_recv1, r,
685 (void *)cont, cont_private);
689 cont(cont_private, false, NULL, SID_NAME_UNKNOWN);
693 bool print_sidlist(TALLOC_CTX *mem_ctx, const DOM_SID *sids,
694 size_t num_sids, char **result, ssize_t *len)
701 for (i=0; i<num_sids; i++) {
703 sprintf_append(mem_ctx, result, len, &buflen,
704 "%s\n", sid_to_fstring(tmp, &sids[i]));
707 if ((num_sids != 0) && (*result == NULL)) {
714 static bool parse_sidlist(TALLOC_CTX *mem_ctx, char *sidstr,
715 DOM_SID **sids, size_t *num_sids)
723 while (p[0] != '\0') {
727 DEBUG(0, ("Got invalid sidstr: %s\n", p));
732 if (!string_to_sid(&sid, p)) {
733 DEBUG(0, ("Could not parse sid %s\n", p));
736 if (!NT_STATUS_IS_OK(add_sid_to_array(mem_ctx, &sid, sids,
746 bool parse_ridlist(TALLOC_CTX *mem_ctx, char *ridstr,
747 uint32 **rids, size_t *num_rids)
755 while (p[0] != '\0') {
758 rid = strtoul(p, &q, 10);
760 DEBUG(0, ("Got invalid ridstr: %s\n", p));
764 ADD_TO_ARRAY(mem_ctx, uint32, rid, rids, num_rids);
769 static void winbindd_lookup_recv(TALLOC_CTX *mem_ctx, bool success,
770 struct winbindd_ndr_call *c,
775 void (*cont)(void *priv, bool succ, struct winbind_lookup *r) =
776 (void (*)(void *, bool, struct winbind_lookup*))_cont;
777 struct winbind_lookup *r =
778 talloc_get_type_abort(_r, struct winbind_lookup);
781 DEBUG(5, ("Could not lookup\n"));
782 cont(cont_private, false, r);
786 if (r->out.result != WINBIND_STATUS_OK) {
787 DEBUG(5, ("lookup returned an error:0x%08X\n",
789 cont(cont_private, false, r);
793 cont(cont_private, true, r);
796 void winbindd_lookup_async(TALLOC_CTX *mem_ctx,
797 struct winbindd_domain *domain,
798 struct winbind_lookup *r,
799 void (*cont)(void *private_data,
801 struct winbind_lookup *r),
804 do_async_ndr_domain(mem_ctx, domain,
805 NDR_WINBIND_LOOKUP, r,
806 winbindd_lookup_recv, r,
807 (void *)cont, cont_private);
810 static void getsidaliases_recv(TALLOC_CTX *mem_ctx, bool success,
811 struct winbindd_response *response,
812 void *c, void *private_data)
814 void (*cont)(void *priv, bool succ,
815 DOM_SID *aliases, size_t num_aliases) =
816 (void (*)(void *, bool, DOM_SID *, size_t))c;
818 DOM_SID *sids = NULL;
822 DEBUG(5, ("Could not trigger getsidaliases\n"));
823 cont(private_data, success, NULL, 0);
827 if (response->result != WINBINDD_OK) {
828 DEBUG(5, ("getsidaliases returned an error\n"));
829 cont(private_data, False, NULL, 0);
833 aliases_str = (char *)response->extra_data.data;
835 if (aliases_str == NULL) {
836 DEBUG(10, ("getsidaliases return 0 SIDs\n"));
837 cont(private_data, True, NULL, 0);
841 if (!parse_sidlist(mem_ctx, aliases_str, &sids, &num_sids)) {
842 DEBUG(0, ("Could not parse sids\n"));
843 cont(private_data, False, NULL, 0);
847 SAFE_FREE(response->extra_data.data);
849 cont(private_data, True, sids, num_sids);
852 void winbindd_getsidaliases_async(struct winbindd_domain *domain,
854 const DOM_SID *sids, size_t num_sids,
855 void (*cont)(void *private_data,
857 const DOM_SID *aliases,
861 struct winbindd_request request;
866 cont(private_data, True, NULL, 0);
870 if (!print_sidlist(mem_ctx, sids, num_sids, &sidstr, &len)) {
871 cont(private_data, False, NULL, 0);
875 ZERO_STRUCT(request);
876 request.cmd = WINBINDD_DUAL_GETSIDALIASES;
877 request.extra_len = len;
878 request.extra_data.data = sidstr;
880 do_async_domain(mem_ctx, domain, &request, getsidaliases_recv,
881 (void *)cont, private_data);
884 enum winbindd_result winbindd_dual_getsidaliases(struct winbindd_domain *domain,
885 struct winbindd_cli_state *state)
887 DOM_SID *sids = NULL;
896 DEBUG(3, ("[%5lu]: getsidaliases\n", (unsigned long)state->pid));
898 sidstr = state->request.extra_data.data;
899 if (sidstr == NULL) {
900 sidstr = talloc_strdup(state->mem_ctx, "\n"); /* No SID */
902 DEBUG(0, ("Out of memory\n"));
903 return WINBINDD_ERROR;
907 DEBUG(10, ("Sidlist: %s\n", sidstr));
909 if (!parse_sidlist(state->mem_ctx, sidstr, &sids, &num_sids)) {
910 DEBUG(0, ("Could not parse SID list: %s\n", sidstr));
911 return WINBINDD_ERROR;
917 result = domain->methods->lookup_useraliases(domain,
923 if (!NT_STATUS_IS_OK(result)) {
924 DEBUG(3, ("Could not lookup_useraliases: %s\n",
926 return WINBINDD_ERROR;
933 DEBUG(10, ("Got %d aliases\n", num_aliases));
935 for (i=0; i<num_aliases; i++) {
937 DEBUGADD(10, (" rid %d\n", alias_rids[i]));
938 sid_copy(&sid, &domain->sid);
939 sid_append_rid(&sid, alias_rids[i]);
940 result = add_sid_to_array(state->mem_ctx, &sid, &sids,
942 if (!NT_STATUS_IS_OK(result)) {
943 return WINBINDD_ERROR;
948 if (!print_sidlist(state->mem_ctx, sids, num_sids, &sidstr, &len)) {
949 DEBUG(0, ("Could not print_sidlist\n"));
950 state->response.extra_data.data = NULL;
951 return WINBINDD_ERROR;
954 state->response.extra_data.data = NULL;
957 state->response.extra_data.data = SMB_STRDUP(sidstr);
958 if (!state->response.extra_data.data) {
959 DEBUG(0, ("Out of memory\n"));
960 return WINBINDD_ERROR;
962 DEBUG(10, ("aliases_list: %s\n",
963 (char *)state->response.extra_data.data));
964 state->response.length += len+1;
970 struct gettoken_state {
973 struct winbindd_domain *alias_domain;
974 struct winbindd_domain *local_alias_domain;
975 struct winbindd_domain *builtin_domain;
978 void (*cont)(void *private_data, bool success, DOM_SID *sids, size_t num_sids);
982 static void gettoken_recvdomgroups(TALLOC_CTX *mem_ctx, bool success,
983 struct winbindd_response *response,
984 void *c, void *private_data);
985 static void gettoken_recvaliases(void *private_data, bool success,
986 const DOM_SID *aliases,
990 void winbindd_gettoken_async(TALLOC_CTX *mem_ctx, const DOM_SID *user_sid,
991 void (*cont)(void *private_data, bool success,
992 DOM_SID *sids, size_t num_sids),
995 struct winbindd_domain *domain;
996 struct winbindd_request request;
997 struct gettoken_state *state;
999 state = TALLOC_ZERO_P(mem_ctx, struct gettoken_state);
1000 if (state == NULL) {
1001 DEBUG(0, ("talloc failed\n"));
1002 cont(private_data, False, NULL, 0);
1006 state->mem_ctx = mem_ctx;
1007 sid_copy(&state->user_sid, user_sid);
1008 state->alias_domain = find_our_domain();
1009 state->local_alias_domain = find_domain_from_name( get_global_sam_name() );
1010 state->builtin_domain = find_builtin_domain();
1012 state->private_data = private_data;
1014 domain = find_domain_from_sid_noinit(user_sid);
1015 if (domain == NULL) {
1016 DEBUG(5, ("Could not find domain from SID %s\n",
1017 sid_string_dbg(user_sid)));
1018 cont(private_data, False, NULL, 0);
1022 ZERO_STRUCT(request);
1023 request.cmd = WINBINDD_GETUSERDOMGROUPS;
1024 sid_to_fstring(request.data.sid, user_sid);
1026 do_async_domain(mem_ctx, domain, &request, gettoken_recvdomgroups,
1030 static void gettoken_recvdomgroups(TALLOC_CTX *mem_ctx, bool success,
1031 struct winbindd_response *response,
1032 void *c, void *private_data)
1034 struct gettoken_state *state =
1035 talloc_get_type_abort(private_data, struct gettoken_state);
1039 DEBUG(10, ("Could not get domain groups\n"));
1040 state->cont(state->private_data, False, NULL, 0);
1044 sids_str = (char *)response->extra_data.data;
1046 if (sids_str == NULL) {
1047 /* This could be normal if we are dealing with a
1048 local user and local groups */
1050 if ( !sid_check_is_in_our_domain( &state->user_sid ) ) {
1051 DEBUG(10, ("Received no domain groups\n"));
1052 state->cont(state->private_data, True, NULL, 0);
1058 state->num_sids = 0;
1060 if (!NT_STATUS_IS_OK(add_sid_to_array(mem_ctx, &state->user_sid,
1061 &state->sids, &state->num_sids)))
1063 DEBUG(0, ("Out of memory\n"));
1064 state->cont(state->private_data, False, NULL, 0);
1068 if (sids_str && !parse_sidlist(mem_ctx, sids_str, &state->sids,
1069 &state->num_sids)) {
1070 DEBUG(0, ("Could not parse sids\n"));
1071 state->cont(state->private_data, False, NULL, 0);
1075 SAFE_FREE(response->extra_data.data);
1077 if (state->alias_domain == NULL) {
1078 DEBUG(10, ("Don't expand domain local groups\n"));
1079 state->cont(state->private_data, True, state->sids,
1084 winbindd_getsidaliases_async(state->alias_domain, mem_ctx,
1085 state->sids, state->num_sids,
1086 gettoken_recvaliases, state);
1089 static void gettoken_recvaliases(void *private_data, bool success,
1090 const DOM_SID *aliases,
1093 struct gettoken_state *state = (struct gettoken_state *)private_data;
1097 DEBUG(10, ("Could not receive domain local groups\n"));
1098 state->cont(state->private_data, False, NULL, 0);
1102 for (i=0; i<num_aliases; i++) {
1103 if (!NT_STATUS_IS_OK(add_sid_to_array(state->mem_ctx,
1108 DEBUG(0, ("Out of memory\n"));
1109 state->cont(state->private_data, False, NULL, 0);
1114 if (state->local_alias_domain != NULL) {
1115 struct winbindd_domain *local_domain = state->local_alias_domain;
1116 DEBUG(10, ("Expanding our own local groups\n"));
1117 state->local_alias_domain = NULL;
1118 winbindd_getsidaliases_async(local_domain, state->mem_ctx,
1119 state->sids, state->num_sids,
1120 gettoken_recvaliases, state);
1124 if (state->builtin_domain != NULL) {
1125 struct winbindd_domain *builtin_domain = state->builtin_domain;
1126 DEBUG(10, ("Expanding our own BUILTIN groups\n"));
1127 state->builtin_domain = NULL;
1128 winbindd_getsidaliases_async(builtin_domain, state->mem_ctx,
1129 state->sids, state->num_sids,
1130 gettoken_recvaliases, state);
1134 state->cont(state->private_data, True, state->sids, state->num_sids);
1137 static void query_user_recv(TALLOC_CTX *mem_ctx, bool success,
1138 struct winbindd_ndr_call *c,
1139 void *_private_data,
1143 void (*cont)(void *private_data, bool success,
1144 const char *acct_name,
1145 const char *full_name,
1146 const char *homedir,
1150 (void (*)(void *, bool, const char *, const char *,
1151 const char *,const char *, gid_t, uint32_t))_cont;
1152 struct winbind_lookup *r =
1153 talloc_get_type_abort(_private_data, struct winbind_lookup);
1156 DEBUG(5, ("Could not trigger lookup(sid2userinfo)\n"));
1158 cont(cont_private, false, NULL, NULL, NULL, NULL, (gid_t)-1, 0);
1162 if (r->out.result != WINBIND_STATUS_OK) {
1163 DEBUG(5, ("Could not trigger lookup(sid2userinfo): 0x%08X\n",
1166 cont(cont_private, false, NULL, NULL, NULL, NULL, (gid_t)-1, 0);
1170 cont(cont_private, true,
1171 r->out.rep->user_info.account,
1172 r->out.rep->user_info.gecos,
1173 r->out.rep->user_info.homedir,
1174 r->out.rep->user_info.shell,
1175 r->out.rep->user_info.primary_gid,
1176 r->out.rep->user_info.primary_rid);
1179 void query_user_async(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1181 void (*cont)(void *private_data, bool success,
1182 const char *acct_name,
1183 const char *full_name,
1184 const char *homedir,
1190 struct winbind_lookup *r = NULL;
1192 r = TALLOC_P(mem_ctx, struct winbind_lookup);
1194 r->in.level = TALLOC_P(r, enum winbind_lookup_level);
1195 if (!r->in.level) goto nomem;
1197 *r->in.level = WINBIND_LOOKUP_LEVEL_SID2USERINFO;
1198 r->in.req.sid = sid_dup_talloc(r, sid);
1199 if (!r->in.req.sid) goto nomem;
1201 do_async_ndr_domain(mem_ctx, domain,
1202 NDR_WINBIND_LOOKUP, r,
1204 (void *)cont, private_data);
1208 cont(private_data, false, NULL, NULL, NULL, NULL, (gid_t)-1, 0);