2 Unix SMB/CIFS implementation.
4 Async helpers for blocking functions
6 Copyright (C) Volker Lendecke 2005
7 Copyright (C) Volker Lendecke 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_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_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 idmap_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) = 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 idmap_set_mapping_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
137 unid_t id, int id_type,
138 void (*cont)(void *private_data, BOOL success),
141 struct winbindd_request request;
142 ZERO_STRUCT(request);
143 request.cmd = WINBINDD_DUAL_IDMAPSET;
144 if (id_type == ID_USERID)
145 request.data.dual_idmapset.uid = id.uid;
147 request.data.dual_idmapset.gid = id.gid;
148 request.data.dual_idmapset.type = id_type;
149 sid_to_string(request.data.dual_idmapset.sid, sid);
151 do_async(mem_ctx, idmap_child(), &request, idmap_set_mapping_recv,
155 enum winbindd_result winbindd_dual_idmapset(struct winbindd_domain *domain,
156 struct winbindd_cli_state *state)
162 DEBUG(3, ("[%5lu]: dual_idmapset\n", (unsigned long)state->pid));
164 if (!string_to_sid(&sid, state->request.data.dual_idmapset.sid))
165 return WINBINDD_ERROR;
167 if (state->request.data.dual_idmapset.type == ID_USERID)
168 id.uid = state->request.data.dual_idmapset.uid;
170 id.gid = state->request.data.dual_idmapset.gid;
172 result = idmap_set_mapping(&sid, id,
173 state->request.data.dual_idmapset.type);
174 return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
177 static void idmap_sid2uid_recv(TALLOC_CTX *mem_ctx, BOOL success,
178 struct winbindd_response *response,
179 void *c, void *private_data);
181 void idmap_sid2uid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid, BOOL alloc,
182 void (*cont)(void *private_data, BOOL success, uid_t uid),
185 struct winbindd_request request;
186 ZERO_STRUCT(request);
187 request.cmd = WINBINDD_DUAL_SID2UID;
188 sid_to_string(request.data.dual_sid2id.sid, sid);
189 request.data.dual_sid2id.alloc = alloc;
190 do_async(mem_ctx, idmap_child(), &request, idmap_sid2uid_recv,
194 enum winbindd_result winbindd_dual_sid2uid(struct winbindd_domain *domain,
195 struct winbindd_cli_state *state)
200 DEBUG(3, ("[%5lu]: sid to uid %s\n", (unsigned long)state->pid,
201 state->request.data.dual_sid2id.sid));
203 if (!string_to_sid(&sid, state->request.data.dual_sid2id.sid)) {
204 DEBUG(1, ("Could not get convert sid %s from string\n",
205 state->request.data.dual_sid2id.sid));
206 return WINBINDD_ERROR;
209 /* Find uid for this sid and return it, possibly ask the slow remote
212 result = idmap_sid_to_uid(&sid, &(state->response.data.uid),
213 state->request.data.dual_sid2id.alloc ?
216 return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
219 static void idmap_sid2uid_recv(TALLOC_CTX *mem_ctx, BOOL success,
220 struct winbindd_response *response,
221 void *c, void *private_data)
223 void (*cont)(void *priv, BOOL succ, uid_t uid) = c;
226 DEBUG(5, ("Could not trigger sid2uid\n"));
227 cont(private_data, False, 0);
231 if (response->result != WINBINDD_OK) {
232 DEBUG(5, ("sid2uid returned an error\n"));
233 cont(private_data, False, 0);
237 cont(private_data, True, response->data.uid);
240 static void uid2name_recv(TALLOC_CTX *mem_ctx, BOOL success,
241 struct winbindd_response *response,
242 void *c, void *private_data);
244 void winbindd_uid2name_async(TALLOC_CTX *mem_ctx, uid_t uid,
245 void (*cont)(void *private_data, BOOL success,
249 struct winbindd_request request;
250 ZERO_STRUCT(request);
251 request.cmd = WINBINDD_DUAL_UID2NAME;
252 request.data.uid = uid;
253 do_async(mem_ctx, idmap_child(), &request, uid2name_recv,
257 enum winbindd_result winbindd_dual_uid2name(struct winbindd_domain *domain,
258 struct winbindd_cli_state *state)
262 DEBUG(3, ("[%5lu]: uid2name %lu\n", (unsigned long)state->pid,
263 (unsigned long)state->request.data.uid));
265 pw = getpwuid(state->request.data.uid);
267 DEBUG(5, ("User %lu not found\n",
268 (unsigned long)state->request.data.uid));
269 return WINBINDD_ERROR;
272 fstrcpy(state->response.data.name.name, pw->pw_name);
276 static void uid2name_recv(TALLOC_CTX *mem_ctx, BOOL success,
277 struct winbindd_response *response,
278 void *c, void *private_data)
280 void (*cont)(void *priv, BOOL succ, const char *name) = c;
283 DEBUG(5, ("Could not trigger uid2name\n"));
284 cont(private_data, False, NULL);
288 if (response->result != WINBINDD_OK) {
289 DEBUG(5, ("uid2name returned an error\n"));
290 cont(private_data, False, NULL);
294 cont(private_data, True, response->data.name.name);
297 static void name2uid_recv(TALLOC_CTX *mem_ctx, BOOL success,
298 struct winbindd_response *response,
299 void *c, void *private_data);
301 static void winbindd_name2uid_async(TALLOC_CTX *mem_ctx, const char *name,
302 void (*cont)(void *private_data, BOOL success,
306 struct winbindd_request request;
307 ZERO_STRUCT(request);
308 request.cmd = WINBINDD_DUAL_NAME2UID;
309 fstrcpy(request.data.username, name);
310 do_async(mem_ctx, idmap_child(), &request, name2uid_recv,
314 enum winbindd_result winbindd_dual_name2uid(struct winbindd_domain *domain,
315 struct winbindd_cli_state *state)
319 /* Ensure null termination */
320 state->request.data.username
321 [sizeof(state->request.data.username)-1] = '\0';
323 DEBUG(3, ("[%5lu]: name2uid %s\n", (unsigned long)state->pid,
324 state->request.data.username));
326 pw = getpwnam(state->request.data.username);
328 return WINBINDD_ERROR;
331 state->response.data.uid = pw->pw_uid;
335 static void name2uid_recv(TALLOC_CTX *mem_ctx, BOOL success,
336 struct winbindd_response *response,
337 void *c, void *private_data)
339 void (*cont)(void *priv, BOOL succ, uid_t uid) = c;
342 DEBUG(5, ("Could not trigger name2uid\n"));
343 cont(private_data, False, 0);
347 if (response->result != WINBINDD_OK) {
348 DEBUG(5, ("name2uid returned an error\n"));
349 cont(private_data, False, 0);
353 cont(private_data, True, response->data.uid);
356 static void idmap_sid2gid_recv(TALLOC_CTX *mem_ctx, BOOL success,
357 struct winbindd_response *response,
358 void *c, void *private_data);
360 void idmap_sid2gid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid, BOOL alloc,
361 void (*cont)(void *private_data, BOOL success, gid_t gid),
364 struct winbindd_request request;
365 ZERO_STRUCT(request);
366 request.cmd = WINBINDD_DUAL_SID2GID;
367 sid_to_string(request.data.dual_sid2id.sid, sid);
369 DEBUG(7,("idmap_sid2gid_async: Resolving %s to a gid\n",
370 request.data.dual_sid2id.sid));
372 request.data.dual_sid2id.alloc = alloc;
373 do_async(mem_ctx, idmap_child(), &request, idmap_sid2gid_recv,
377 enum winbindd_result winbindd_dual_sid2gid(struct winbindd_domain *domain,
378 struct winbindd_cli_state *state)
383 DEBUG(3, ("[%5lu]: sid to gid %s\n", (unsigned long)state->pid,
384 state->request.data.dual_sid2id.sid));
386 if (!string_to_sid(&sid, state->request.data.dual_sid2id.sid)) {
387 DEBUG(1, ("Could not get convert sid %s from string\n",
388 state->request.data.dual_sid2id.sid));
389 return WINBINDD_ERROR;
392 /* Find gid for this sid and return it, possibly ask the slow remote
395 result = idmap_sid_to_gid(&sid, &(state->response.data.gid),
396 state->request.data.dual_sid2id.alloc ?
399 /* If the lookup failed, the perhaps we need to look
400 at the passdb for local groups */
402 if ( !NT_STATUS_IS_OK(result) ) {
403 if ( sid_to_gid( &sid, &(state->response.data.gid) ) ) {
404 result = NT_STATUS_OK;
408 return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
411 static void idmap_sid2gid_recv(TALLOC_CTX *mem_ctx, BOOL success,
412 struct winbindd_response *response,
413 void *c, void *private_data)
415 void (*cont)(void *priv, BOOL succ, gid_t gid) = c;
418 DEBUG(5, ("Could not trigger sid2gid\n"));
419 cont(private_data, False, 0);
423 if (response->result != WINBINDD_OK) {
424 DEBUG(5, ("sid2gid returned an error\n"));
425 cont(private_data, False, 0);
429 cont(private_data, True, response->data.gid);
432 static void gid2name_recv(TALLOC_CTX *mem_ctx, BOOL success,
433 struct winbindd_response *response,
434 void *c, void *private_data)
436 void (*cont)(void *priv, BOOL succ, const char *name) = c;
439 DEBUG(5, ("Could not trigger gid2name\n"));
440 cont(private_data, False, NULL);
444 if (response->result != WINBINDD_OK) {
445 DEBUG(5, ("gid2name returned an error\n"));
446 cont(private_data, False, NULL);
450 cont(private_data, True, response->data.name.name);
453 void winbindd_gid2name_async(TALLOC_CTX *mem_ctx, gid_t gid,
454 void (*cont)(void *private_data, BOOL success,
458 struct winbindd_request request;
459 ZERO_STRUCT(request);
460 request.cmd = WINBINDD_DUAL_GID2NAME;
461 request.data.gid = gid;
462 do_async(mem_ctx, idmap_child(), &request, gid2name_recv,
466 enum winbindd_result winbindd_dual_gid2name(struct winbindd_domain *domain,
467 struct winbindd_cli_state *state)
471 DEBUG(3, ("[%5lu]: gid2name %lu\n", (unsigned long)state->pid,
472 (unsigned long)state->request.data.gid));
474 gr = getgrgid(state->request.data.gid);
476 return WINBINDD_ERROR;
478 fstrcpy(state->response.data.name.name, gr->gr_name);
482 static void name2gid_recv(TALLOC_CTX *mem_ctx, BOOL success,
483 struct winbindd_response *response,
484 void *c, void *private_data);
486 static void winbindd_name2gid_async(TALLOC_CTX *mem_ctx, const char *name,
487 void (*cont)(void *private_data, BOOL success,
491 struct winbindd_request request;
492 ZERO_STRUCT(request);
493 request.cmd = WINBINDD_DUAL_NAME2GID;
494 fstrcpy(request.data.groupname, name);
495 do_async(mem_ctx, idmap_child(), &request, name2gid_recv,
499 enum winbindd_result winbindd_dual_name2gid(struct winbindd_domain *domain,
500 struct winbindd_cli_state *state)
504 /* Ensure null termination */
505 state->request.data.groupname
506 [sizeof(state->request.data.groupname)-1] = '\0';
508 DEBUG(3, ("[%5lu]: name2gid %s\n", (unsigned long)state->pid,
509 state->request.data.groupname));
511 gr = getgrnam(state->request.data.groupname);
513 return WINBINDD_ERROR;
516 state->response.data.gid = gr->gr_gid;
520 static void name2gid_recv(TALLOC_CTX *mem_ctx, BOOL success,
521 struct winbindd_response *response,
522 void *c, void *private_data)
524 void (*cont)(void *priv, BOOL succ, gid_t gid) = c;
527 DEBUG(5, ("Could not trigger name2gid\n"));
528 cont(private_data, False, 0);
532 if (response->result != WINBINDD_OK) {
533 DEBUG(5, ("name2gid returned an error\n"));
534 cont(private_data, False, 0);
538 cont(private_data, True, response->data.gid);
542 static void lookupsid_recv(TALLOC_CTX *mem_ctx, BOOL success,
543 struct winbindd_response *response,
544 void *c, void *private_data)
546 void (*cont)(void *priv, BOOL succ, const char *dom_name,
547 const char *name, enum SID_NAME_USE type) = c;
550 DEBUG(5, ("Could not trigger lookupsid\n"));
551 cont(private_data, False, NULL, NULL, SID_NAME_UNKNOWN);
555 if (response->result != WINBINDD_OK) {
556 DEBUG(5, ("lookupsid returned an error\n"));
557 cont(private_data, False, NULL, NULL, SID_NAME_UNKNOWN);
561 cont(private_data, True, response->data.name.dom_name,
562 response->data.name.name, response->data.name.type);
565 void winbindd_lookupsid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
566 void (*cont)(void *private_data, BOOL success,
567 const char *dom_name,
569 enum SID_NAME_USE type),
572 struct winbindd_domain *domain;
573 struct winbindd_request request;
575 domain = find_lookup_domain_from_sid(sid);
576 if (domain == NULL) {
577 DEBUG(5, ("Could not find domain for sid %s\n",
578 sid_string_static(sid)));
579 cont(private_data, False, NULL, NULL, SID_NAME_UNKNOWN);
583 ZERO_STRUCT(request);
584 request.cmd = WINBINDD_LOOKUPSID;
585 fstrcpy(request.data.sid, sid_string_static(sid));
587 do_async_domain(mem_ctx, domain, &request, lookupsid_recv,
591 enum winbindd_result winbindd_dual_lookupsid(struct winbindd_domain *domain,
592 struct winbindd_cli_state *state)
594 enum SID_NAME_USE type;
599 /* Ensure null termination */
600 state->request.data.sid[sizeof(state->request.data.sid)-1]='\0';
602 DEBUG(3, ("[%5lu]: lookupsid %s\n", (unsigned long)state->pid,
603 state->request.data.sid));
605 /* Lookup sid from PDC using lsa_lookup_sids() */
607 if (!string_to_sid(&sid, state->request.data.sid)) {
608 DEBUG(5, ("%s not a SID\n", state->request.data.sid));
609 return WINBINDD_ERROR;
614 if (!winbindd_lookup_name_by_sid(state->mem_ctx, &sid, dom_name, name,
616 return WINBINDD_ERROR;
619 fstrcpy(state->response.data.name.dom_name, dom_name);
620 fstrcpy(state->response.data.name.name, name);
621 state->response.data.name.type = type;
626 static void lookupname_recv(TALLOC_CTX *mem_ctx, BOOL success,
627 struct winbindd_response *response,
628 void *c, void *private_data)
630 void (*cont)(void *priv, BOOL succ, const DOM_SID *sid,
631 enum SID_NAME_USE type) = c;
635 DEBUG(5, ("Could not trigger lookup_name\n"));
636 cont(private_data, False, NULL, SID_NAME_UNKNOWN);
640 if (response->result != WINBINDD_OK) {
641 DEBUG(5, ("lookup_name returned an error\n"));
642 cont(private_data, False, NULL, SID_NAME_UNKNOWN);
646 if (!string_to_sid(&sid, response->data.sid.sid)) {
647 DEBUG(0, ("Could not convert string %s to sid\n",
648 response->data.sid.sid));
649 cont(private_data, False, NULL, SID_NAME_UNKNOWN);
653 cont(private_data, True, &sid, response->data.sid.type);
656 void winbindd_lookupname_async(TALLOC_CTX *mem_ctx, const char *dom_name,
658 void (*cont)(void *private_data, BOOL success,
660 enum SID_NAME_USE type),
663 struct winbindd_request request;
664 struct winbindd_domain *domain;
666 domain = find_lookup_domain_from_name(dom_name);
668 if (domain == NULL) {
669 DEBUG(5, ("Could not find domain for name %s\n", dom_name));
670 cont(private_data, False, NULL, SID_NAME_UNKNOWN);
674 ZERO_STRUCT(request);
675 request.cmd = WINBINDD_LOOKUPNAME;
676 fstrcpy(request.data.name.dom_name, dom_name);
677 fstrcpy(request.data.name.name, name);
679 do_async_domain(mem_ctx, domain, &request, lookupname_recv,
683 enum winbindd_result winbindd_dual_lookupname(struct winbindd_domain *domain,
684 struct winbindd_cli_state *state)
686 enum SID_NAME_USE type;
687 char *name_domain, *name_user;
691 /* Ensure null termination */
692 state->request.data.sid[sizeof(state->request.data.name.dom_name)-1]='\0';
694 /* Ensure null termination */
695 state->request.data.sid[sizeof(state->request.data.name.name)-1]='\0';
697 /* cope with the name being a fully qualified name */
698 p = strstr(state->request.data.name.name, lp_winbind_separator());
701 name_domain = state->request.data.name.name;
704 name_domain = state->request.data.name.dom_name;
705 name_user = state->request.data.name.name;
708 DEBUG(3, ("[%5lu]: lookupname %s%s%s\n", (unsigned long)state->pid,
709 name_domain, lp_winbind_separator(), name_user));
711 /* Lookup name from PDC using lsa_lookup_names() */
712 if (!winbindd_lookup_sid_by_name(state->mem_ctx, domain, name_domain,
713 name_user, &sid, &type)) {
714 return WINBINDD_ERROR;
717 sid_to_string(state->response.data.sid.sid, &sid);
718 state->response.data.sid.type = type;
723 BOOL print_sidlist(TALLOC_CTX *mem_ctx, const DOM_SID *sids,
724 size_t num_sids, char **result, ssize_t *len)
731 for (i=0; i<num_sids; i++) {
732 sprintf_append(mem_ctx, result, len, &buflen,
733 "%s\n", sid_string_static(&sids[i]));
736 if ((num_sids != 0) && (*result == NULL)) {
743 BOOL parse_sidlist(TALLOC_CTX *mem_ctx, char *sidstr,
744 DOM_SID **sids, size_t *num_sids)
752 while (p[0] != '\0') {
756 DEBUG(0, ("Got invalid sidstr: %s\n", p));
761 if (!string_to_sid(&sid, p)) {
762 DEBUG(0, ("Could not parse sid %s\n", p));
765 add_sid_to_array(mem_ctx, &sid, sids, num_sids);
771 BOOL print_ridlist(TALLOC_CTX *mem_ctx, uint32 *rids, size_t num_rids,
772 char **result, ssize_t *len)
779 for (i=0; i<num_rids; i++) {
780 sprintf_append(mem_ctx, result, len, &buflen,
784 if ((num_rids != 0) && (*result == NULL)) {
791 BOOL parse_ridlist(TALLOC_CTX *mem_ctx, char *ridstr,
792 uint32 **sids, size_t *num_rids)
800 while (p[0] != '\0') {
803 rid = strtoul(p, &q, 10);
805 DEBUG(0, ("Got invalid ridstr: %s\n", p));
809 ADD_TO_ARRAY(mem_ctx, uint32, rid, sids, num_rids);
814 static void getsidaliases_recv(TALLOC_CTX *mem_ctx, BOOL success,
815 struct winbindd_response *response,
816 void *c, void *private_data)
818 void (*cont)(void *priv, BOOL succ,
819 DOM_SID *aliases, size_t num_aliases) = c;
821 DOM_SID *sids = NULL;
825 DEBUG(5, ("Could not trigger getsidaliases\n"));
826 cont(private_data, success, NULL, 0);
830 if (response->result != WINBINDD_OK) {
831 DEBUG(5, ("getsidaliases returned an error\n"));
832 cont(private_data, False, NULL, 0);
836 aliases_str = response->extra_data.data;
838 if (aliases_str == NULL) {
839 DEBUG(10, ("getsidaliases return 0 SIDs\n"));
840 cont(private_data, True, NULL, 0);
844 if (!parse_sidlist(mem_ctx, aliases_str, &sids, &num_sids)) {
845 DEBUG(0, ("Could not parse sids\n"));
846 cont(private_data, False, NULL, 0);
850 SAFE_FREE(response->extra_data.data);
852 cont(private_data, True, sids, num_sids);
855 void winbindd_getsidaliases_async(struct winbindd_domain *domain,
857 const DOM_SID *sids, size_t num_sids,
858 void (*cont)(void *private_data,
860 const DOM_SID *aliases,
864 struct winbindd_request request;
869 cont(private_data, True, NULL, 0);
873 if (!print_sidlist(mem_ctx, sids, num_sids, &sidstr, &len)) {
874 cont(private_data, False, NULL, 0);
878 ZERO_STRUCT(request);
879 request.cmd = WINBINDD_DUAL_GETSIDALIASES;
880 request.extra_len = len;
881 request.extra_data.data = sidstr;
883 do_async_domain(mem_ctx, domain, &request, getsidaliases_recv,
887 enum winbindd_result winbindd_dual_getsidaliases(struct winbindd_domain *domain,
888 struct winbindd_cli_state *state)
890 DOM_SID *sids = NULL;
899 DEBUG(3, ("[%5lu]: getsidaliases\n", (unsigned long)state->pid));
901 sidstr = state->request.extra_data.data;
903 sidstr = talloc_strdup(state->mem_ctx, "\n"); /* No SID */
905 DEBUG(10, ("Sidlist: %s\n", sidstr));
907 if (!parse_sidlist(state->mem_ctx, sidstr, &sids, &num_sids)) {
908 DEBUG(0, ("Could not parse SID list: %s\n", sidstr));
909 return WINBINDD_ERROR;
915 result = domain->methods->lookup_useraliases(domain,
921 if (!NT_STATUS_IS_OK(result)) {
922 DEBUG(3, ("Could not lookup_useraliases: %s\n",
924 return WINBINDD_ERROR;
930 DEBUG(10, ("Got %d aliases\n", num_aliases));
932 for (i=0; i<num_aliases; i++) {
934 DEBUGADD(10, (" rid %d\n", alias_rids[i]));
935 sid_copy(&sid, &domain->sid);
936 sid_append_rid(&sid, alias_rids[i]);
937 add_sid_to_array(state->mem_ctx, &sid, &sids, &num_sids);
940 if (!print_sidlist(NULL, sids, num_sids,
941 (char **)&state->response.extra_data.data, &len)) {
942 DEBUG(0, ("Could not print_sidlist\n"));
943 return WINBINDD_ERROR;
946 if (state->response.extra_data.data != NULL) {
947 DEBUG(10, ("aliases_list: %s\n",
948 (char *)state->response.extra_data.data));
949 state->response.length += len+1;
955 struct gettoken_state {
958 struct winbindd_domain *alias_domain;
959 struct winbindd_domain *local_alias_domain;
960 struct winbindd_domain *builtin_domain;
963 void (*cont)(void *private_data, BOOL success, DOM_SID *sids, size_t num_sids);
967 static void gettoken_recvdomgroups(TALLOC_CTX *mem_ctx, BOOL success,
968 struct winbindd_response *response,
969 void *c, void *private_data);
970 static void gettoken_recvaliases(void *private_data, BOOL success,
971 const DOM_SID *aliases,
975 void winbindd_gettoken_async(TALLOC_CTX *mem_ctx, const DOM_SID *user_sid,
976 void (*cont)(void *private_data, BOOL success,
977 DOM_SID *sids, size_t num_sids),
980 struct winbindd_domain *domain;
981 struct winbindd_request request;
982 struct gettoken_state *state;
984 state = TALLOC_P(mem_ctx, struct gettoken_state);
986 DEBUG(0, ("talloc failed\n"));
987 cont(private_data, False, NULL, 0);
991 state->mem_ctx = mem_ctx;
992 sid_copy(&state->user_sid, user_sid);
993 state->alias_domain = find_our_domain();
994 state->local_alias_domain = find_domain_from_name( get_global_sam_name() );
995 state->builtin_domain = find_builtin_domain();
997 state->private_data = private_data;
999 domain = find_domain_from_sid_noinit(user_sid);
1000 if (domain == NULL) {
1001 DEBUG(5, ("Could not find domain from SID %s\n",
1002 sid_string_static(user_sid)));
1003 cont(private_data, False, NULL, 0);
1007 ZERO_STRUCT(request);
1008 request.cmd = WINBINDD_GETUSERDOMGROUPS;
1009 fstrcpy(request.data.sid, sid_string_static(user_sid));
1011 do_async_domain(mem_ctx, domain, &request, gettoken_recvdomgroups,
1015 static void gettoken_recvdomgroups(TALLOC_CTX *mem_ctx, BOOL success,
1016 struct winbindd_response *response,
1017 void *c, void *private_data)
1019 struct gettoken_state *state =
1020 talloc_get_type_abort(private_data, struct gettoken_state);
1024 DEBUG(10, ("Could not get domain groups\n"));
1025 state->cont(state->private_data, False, NULL, 0);
1029 sids_str = response->extra_data.data;
1031 if (sids_str == NULL) {
1032 /* This could be normal if we are dealing with a
1033 local user and local groups */
1035 if ( !sid_check_is_in_our_domain( &state->user_sid ) ) {
1036 DEBUG(10, ("Received no domain groups\n"));
1037 state->cont(state->private_data, True, NULL, 0);
1043 state->num_sids = 0;
1045 add_sid_to_array(mem_ctx, &state->user_sid, &state->sids,
1048 if (sids_str && !parse_sidlist(mem_ctx, sids_str, &state->sids,
1049 &state->num_sids)) {
1050 DEBUG(0, ("Could not parse sids\n"));
1051 state->cont(state->private_data, False, NULL, 0);
1055 SAFE_FREE(response->extra_data.data);
1057 if (state->alias_domain == NULL) {
1058 DEBUG(10, ("Don't expand domain local groups\n"));
1059 state->cont(state->private_data, True, state->sids,
1064 winbindd_getsidaliases_async(state->alias_domain, mem_ctx,
1065 state->sids, state->num_sids,
1066 gettoken_recvaliases, state);
1069 static void gettoken_recvaliases(void *private_data, BOOL success,
1070 const DOM_SID *aliases,
1073 struct gettoken_state *state = private_data;
1077 DEBUG(10, ("Could not receive domain local groups\n"));
1078 state->cont(state->private_data, False, NULL, 0);
1082 for (i=0; i<num_aliases; i++)
1083 add_sid_to_array(state->mem_ctx, &aliases[i],
1084 &state->sids, &state->num_sids);
1086 if (state->local_alias_domain != NULL) {
1087 struct winbindd_domain *local_domain = state->local_alias_domain;
1088 DEBUG(10, ("Expanding our own local groups\n"));
1089 state->local_alias_domain = NULL;
1090 winbindd_getsidaliases_async(local_domain, state->mem_ctx,
1091 state->sids, state->num_sids,
1092 gettoken_recvaliases, state);
1096 if (state->builtin_domain != NULL) {
1097 struct winbindd_domain *builtin_domain = state->builtin_domain;
1098 DEBUG(10, ("Expanding our own BUILTIN groups\n"));
1099 state->builtin_domain = NULL;
1100 winbindd_getsidaliases_async(builtin_domain, state->mem_ctx,
1101 state->sids, state->num_sids,
1102 gettoken_recvaliases, state);
1106 state->cont(state->private_data, True, state->sids, state->num_sids);
1109 struct sid2uid_state {
1110 TALLOC_CTX *mem_ctx;
1114 void (*cont)(void *private_data, BOOL success, uid_t uid);
1118 static void sid2uid_lookup_sid_recv(void *private_data, BOOL success,
1119 const char *dom_name, const char *name,
1120 enum SID_NAME_USE type);
1121 static void sid2uid_noalloc_recv(void *private_data, BOOL success, uid_t uid);
1122 static void sid2uid_alloc_recv(void *private_data, BOOL success, uid_t uid);
1123 static void sid2uid_name2uid_recv(void *private_data, BOOL success, uid_t uid);
1124 static void sid2uid_set_mapping_recv(void *private_data, BOOL success);
1126 void winbindd_sid2uid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
1127 void (*cont)(void *private_data, BOOL success,
1131 struct sid2uid_state *state;
1135 if (idmap_proxyonly()) {
1136 DEBUG(10, ("idmap proxy only\n"));
1137 cont(private_data, False, 0);
1141 /* Query only the local tdb, everything else might possibly block */
1143 result = idmap_sid_to_uid(sid, &uid, ID_QUERY_ONLY|ID_CACHE_ONLY);
1145 if (NT_STATUS_IS_OK(result)) {
1146 cont(private_data, True, uid);
1150 state = TALLOC_P(mem_ctx, struct sid2uid_state);
1151 if (state == NULL) {
1152 DEBUG(0, ("talloc failed\n"));
1153 cont(private_data, False, 0);
1157 state->mem_ctx = mem_ctx;
1160 state->private_data = private_data;
1162 /* Let's see if it's really a user before allocating a uid */
1164 winbindd_lookupsid_async(mem_ctx, sid, sid2uid_lookup_sid_recv, state);
1167 static void sid2uid_lookup_sid_recv(void *private_data, BOOL success,
1168 const char *dom_name, const char *name,
1169 enum SID_NAME_USE type)
1171 struct sid2uid_state *state =
1172 talloc_get_type_abort(private_data, struct sid2uid_state);
1175 DEBUG(5, ("Could not trigger lookup_sid\n"));
1176 state->cont(state->private_data, False, 0);
1180 if ((type != SID_NAME_USER) && (type != SID_NAME_COMPUTER)) {
1181 DEBUG(5, ("SID is not a user\n"));
1182 state->cont(state->private_data, False, 0);
1186 state->username = talloc_strdup(state->mem_ctx, name);
1188 /* Ask the possibly blocking remote IDMAP */
1190 idmap_sid2uid_async(state->mem_ctx, &state->sid, False,
1191 sid2uid_noalloc_recv, state);
1194 static void sid2uid_noalloc_recv(void *private_data, BOOL success, uid_t uid)
1196 struct sid2uid_state *state =
1197 talloc_get_type_abort(private_data, struct sid2uid_state);
1200 DEBUG(10, ("found uid for sid %s in remote backend\n",
1201 sid_string_static(&state->sid)));
1202 state->cont(state->private_data, True, uid);
1206 if (lp_winbind_trusted_domains_only() &&
1207 (sid_compare_domain(&state->sid, &find_our_domain()->sid) == 0)) {
1208 DEBUG(10, ("Trying to go via nss\n"));
1209 winbindd_name2uid_async(state->mem_ctx, state->username,
1210 sid2uid_name2uid_recv, state);
1214 /* To be done: Here we're going to try the unixinfo pipe */
1216 /* Now allocate a uid */
1218 idmap_sid2uid_async(state->mem_ctx, &state->sid, True,
1219 sid2uid_alloc_recv, state);
1222 static void sid2uid_alloc_recv(void *private_data, BOOL success, uid_t uid)
1224 struct sid2uid_state *state =
1225 talloc_get_type_abort(private_data, struct sid2uid_state);
1228 DEBUG(5, ("Could not allocate uid\n"));
1229 state->cont(state->private_data, False, 0);
1233 state->cont(state->private_data, True, uid);
1236 static void sid2uid_name2uid_recv(void *private_data, BOOL success, uid_t uid)
1238 struct sid2uid_state *state =
1239 talloc_get_type_abort(private_data, struct sid2uid_state);
1243 DEBUG(5, ("Could not find uid for name %s\n",
1245 state->cont(state->private_data, False, 0);
1252 idmap_set_mapping_async(state->mem_ctx, &state->sid, id, ID_USERID,
1253 sid2uid_set_mapping_recv, state);
1256 static void sid2uid_set_mapping_recv(void *private_data, BOOL success)
1258 struct sid2uid_state *state =
1259 talloc_get_type_abort(private_data, struct sid2uid_state);
1262 DEBUG(5, ("Could not set ID mapping for sid %s\n",
1263 sid_string_static(&state->sid)));
1264 state->cont(state->private_data, False, 0);
1268 state->cont(state->private_data, True, state->uid);
1271 struct sid2gid_state {
1272 TALLOC_CTX *mem_ctx;
1276 void (*cont)(void *private_data, BOOL success, gid_t gid);
1280 static void sid2gid_lookup_sid_recv(void *private_data, BOOL success,
1281 const char *dom_name, const char *name,
1282 enum SID_NAME_USE type);
1283 static void sid2gid_noalloc_recv(void *private_data, BOOL success, gid_t gid);
1284 static void sid2gid_alloc_recv(void *private_data, BOOL success, gid_t gid);
1285 static void sid2gid_name2gid_recv(void *private_data, BOOL success, gid_t gid);
1286 static void sid2gid_set_mapping_recv(void *private_data, BOOL success);
1288 void winbindd_sid2gid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
1289 void (*cont)(void *private_data, BOOL success,
1293 struct sid2gid_state *state;
1297 if (idmap_proxyonly()) {
1298 DEBUG(10, ("idmap proxy only\n"));
1299 cont(private_data, False, 0);
1303 /* Query only the local tdb, everything else might possibly block */
1305 result = idmap_sid_to_gid(sid, &gid, ID_QUERY_ONLY|ID_CACHE_ONLY);
1307 if (NT_STATUS_IS_OK(result)) {
1308 cont(private_data, True, gid);
1312 state = TALLOC_P(mem_ctx, struct sid2gid_state);
1313 if (state == NULL) {
1314 DEBUG(0, ("talloc failed\n"));
1315 cont(private_data, False, 0);
1319 state->mem_ctx = mem_ctx;
1322 state->private_data = private_data;
1324 /* Let's see if it's really a user before allocating a gid */
1326 winbindd_lookupsid_async(mem_ctx, sid, sid2gid_lookup_sid_recv, state);
1329 static void sid2gid_lookup_sid_recv(void *private_data, BOOL success,
1330 const char *dom_name, const char *name,
1331 enum SID_NAME_USE type)
1333 struct sid2gid_state *state =
1334 talloc_get_type_abort(private_data, struct sid2gid_state);
1337 DEBUG(5, ("Could not trigger lookup_sid\n"));
1338 state->cont(state->private_data, False, 0);
1342 if (((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
1343 (type != SID_NAME_WKN_GRP))) {
1344 DEBUG(5, ("SID is not a group\n"));
1345 state->cont(state->private_data, False, 0);
1349 state->groupname = talloc_strdup(state->mem_ctx, name);
1351 /* Ask the possibly blocking remote IDMAP and allocate */
1353 idmap_sid2gid_async(state->mem_ctx, &state->sid, False,
1354 sid2gid_noalloc_recv, state);
1357 static void sid2gid_noalloc_recv(void *private_data, BOOL success, gid_t gid)
1359 struct sid2gid_state *state =
1360 talloc_get_type_abort(private_data, struct sid2gid_state);
1363 DEBUG(10, ("found gid for sid %s in remote backend\n",
1364 sid_string_static(&state->sid)));
1365 state->cont(state->private_data, True, gid);
1369 if (lp_winbind_trusted_domains_only() &&
1370 (sid_compare_domain(&state->sid, &find_our_domain()->sid) == 0)) {
1371 DEBUG(10, ("Trying to go via nss\n"));
1372 winbindd_name2gid_async(state->mem_ctx, state->groupname,
1373 sid2gid_name2gid_recv, state);
1377 /* To be done: Here we're going to try the unixinfo pipe */
1379 /* Now allocate a gid */
1381 idmap_sid2gid_async(state->mem_ctx, &state->sid, True,
1382 sid2gid_alloc_recv, state);
1385 static void sid2gid_alloc_recv(void *private_data, BOOL success, gid_t gid)
1387 struct sid2gid_state *state =
1388 talloc_get_type_abort(private_data, struct sid2gid_state);
1391 DEBUG(5, ("Could not allocate gid\n"));
1392 state->cont(state->private_data, False, 0);
1396 state->cont(state->private_data, True, gid);
1399 static void sid2gid_name2gid_recv(void *private_data, BOOL success, gid_t gid)
1401 struct sid2gid_state *state =
1402 talloc_get_type_abort(private_data, struct sid2gid_state);
1406 DEBUG(5, ("Could not find gid for name %s\n",
1408 state->cont(state->private_data, False, 0);
1415 idmap_set_mapping_async(state->mem_ctx, &state->sid, id, ID_GROUPID,
1416 sid2gid_set_mapping_recv, state);
1419 static void sid2gid_set_mapping_recv(void *private_data, BOOL success)
1421 struct sid2gid_state *state =
1422 talloc_get_type_abort(private_data, struct sid2gid_state);
1425 DEBUG(5, ("Could not set ID mapping for sid %s\n",
1426 sid_string_static(&state->sid)));
1427 state->cont(state->private_data, False, 0);
1431 state->cont(state->private_data, True, state->gid);
1434 static void query_user_recv(TALLOC_CTX *mem_ctx, BOOL success,
1435 struct winbindd_response *response,
1436 void *c, void *private_data)
1438 void (*cont)(void *priv, BOOL succ, const char *acct_name,
1439 const char *full_name, const char *homedir,
1440 const char *shell, uint32 group_rid) = c;
1443 DEBUG(5, ("Could not trigger query_user\n"));
1444 cont(private_data, False, NULL, NULL, NULL, NULL, -1);
1448 cont(private_data, True, response->data.user_info.acct_name,
1449 response->data.user_info.full_name,
1450 response->data.user_info.homedir,
1451 response->data.user_info.shell,
1452 response->data.user_info.group_rid);
1455 void query_user_async(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1457 void (*cont)(void *private_data, BOOL success,
1458 const char *acct_name,
1459 const char *full_name,
1460 const char *homedir,
1465 struct winbindd_request request;
1466 ZERO_STRUCT(request);
1467 request.cmd = WINBINDD_DUAL_USERINFO;
1468 sid_to_string(request.data.sid, sid);
1469 do_async_domain(mem_ctx, domain, &request, query_user_recv,
1470 cont, private_data);