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) = (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 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,
152 (void *)cont, private_data);
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,
191 (void *)cont, private_data);
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 ?
214 0 : IDMAP_FLAG_QUERY_ONLY);
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) =
224 (void (*)(void *, BOOL, uid_t))c;
227 DEBUG(5, ("Could not trigger sid2uid\n"));
228 cont(private_data, False, 0);
232 if (response->result != WINBINDD_OK) {
233 DEBUG(5, ("sid2uid returned an error\n"));
234 cont(private_data, False, 0);
238 cont(private_data, True, response->data.uid);
241 static void uid2name_recv(TALLOC_CTX *mem_ctx, BOOL success,
242 struct winbindd_response *response,
243 void *c, void *private_data);
245 void winbindd_uid2name_async(TALLOC_CTX *mem_ctx, uid_t uid,
246 void (*cont)(void *private_data, BOOL success,
250 struct winbindd_request request;
251 ZERO_STRUCT(request);
252 request.cmd = WINBINDD_DUAL_UID2NAME;
253 request.data.uid = uid;
254 do_async(mem_ctx, idmap_child(), &request, uid2name_recv,
255 (void *)cont, private_data);
258 enum winbindd_result winbindd_dual_uid2name(struct winbindd_domain *domain,
259 struct winbindd_cli_state *state)
263 DEBUG(3, ("[%5lu]: uid2name %lu\n", (unsigned long)state->pid,
264 (unsigned long)state->request.data.uid));
266 pw = getpwuid(state->request.data.uid);
268 DEBUG(5, ("User %lu not found\n",
269 (unsigned long)state->request.data.uid));
270 return WINBINDD_ERROR;
273 fstrcpy(state->response.data.name.name, pw->pw_name);
277 static void uid2name_recv(TALLOC_CTX *mem_ctx, BOOL success,
278 struct winbindd_response *response,
279 void *c, void *private_data)
281 void (*cont)(void *priv, BOOL succ, const char *name) =
282 (void (*)(void *, BOOL, const char *))c;
285 DEBUG(5, ("Could not trigger uid2name\n"));
286 cont(private_data, False, NULL);
290 if (response->result != WINBINDD_OK) {
291 DEBUG(5, ("uid2name returned an error\n"));
292 cont(private_data, False, NULL);
296 cont(private_data, True, response->data.name.name);
299 static void name2uid_recv(TALLOC_CTX *mem_ctx, BOOL success,
300 struct winbindd_response *response,
301 void *c, void *private_data);
303 static void winbindd_name2uid_async(TALLOC_CTX *mem_ctx, const char *name,
304 void (*cont)(void *private_data, BOOL success,
308 struct winbindd_request request;
309 ZERO_STRUCT(request);
310 request.cmd = WINBINDD_DUAL_NAME2UID;
311 fstrcpy(request.data.username, name);
312 do_async(mem_ctx, idmap_child(), &request, name2uid_recv,
313 (void *)cont, private_data);
316 enum winbindd_result winbindd_dual_name2uid(struct winbindd_domain *domain,
317 struct winbindd_cli_state *state)
321 /* Ensure null termination */
322 state->request.data.username
323 [sizeof(state->request.data.username)-1] = '\0';
325 DEBUG(3, ("[%5lu]: name2uid %s\n", (unsigned long)state->pid,
326 state->request.data.username));
328 pw = getpwnam(state->request.data.username);
330 return WINBINDD_ERROR;
333 state->response.data.uid = pw->pw_uid;
337 static void name2uid_recv(TALLOC_CTX *mem_ctx, BOOL success,
338 struct winbindd_response *response,
339 void *c, void *private_data)
341 void (*cont)(void *priv, BOOL succ, uid_t uid) =
342 (void (*)(void *, BOOL, uid_t))c;
345 DEBUG(5, ("Could not trigger name2uid\n"));
346 cont(private_data, False, 0);
350 if (response->result != WINBINDD_OK) {
351 DEBUG(5, ("name2uid returned an error\n"));
352 cont(private_data, False, 0);
356 cont(private_data, True, response->data.uid);
359 static void idmap_sid2gid_recv(TALLOC_CTX *mem_ctx, BOOL success,
360 struct winbindd_response *response,
361 void *c, void *private_data);
363 void idmap_sid2gid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid, BOOL alloc,
364 void (*cont)(void *private_data, BOOL success, gid_t gid),
367 struct winbindd_request request;
368 ZERO_STRUCT(request);
369 request.cmd = WINBINDD_DUAL_SID2GID;
370 sid_to_string(request.data.dual_sid2id.sid, sid);
372 DEBUG(7,("idmap_sid2gid_async: Resolving %s to a gid\n",
373 request.data.dual_sid2id.sid));
375 request.data.dual_sid2id.alloc = alloc;
376 do_async(mem_ctx, idmap_child(), &request, idmap_sid2gid_recv,
377 (void *)cont, private_data);
380 enum winbindd_result winbindd_dual_sid2gid(struct winbindd_domain *domain,
381 struct winbindd_cli_state *state)
386 DEBUG(3, ("[%5lu]: sid to gid %s\n", (unsigned long)state->pid,
387 state->request.data.dual_sid2id.sid));
389 if (!string_to_sid(&sid, state->request.data.dual_sid2id.sid)) {
390 DEBUG(1, ("Could not get convert sid %s from string\n",
391 state->request.data.dual_sid2id.sid));
392 return WINBINDD_ERROR;
395 /* Find gid for this sid and return it, possibly ask the slow remote
398 result = idmap_sid_to_gid(&sid, &state->response.data.gid,
399 state->request.data.dual_sid2id.alloc ?
400 0 : IDMAP_FLAG_QUERY_ONLY);
402 /* If the lookup failed, the perhaps we need to look
403 at the passdb for local groups */
405 if ( !NT_STATUS_IS_OK(result) ) {
406 if ( sid_to_gid( &sid, &(state->response.data.gid) ) ) {
407 result = NT_STATUS_OK;
411 return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
414 static void idmap_sid2gid_recv(TALLOC_CTX *mem_ctx, BOOL success,
415 struct winbindd_response *response,
416 void *c, void *private_data)
418 void (*cont)(void *priv, BOOL succ, gid_t gid) =
419 (void (*)(void *, BOOL, gid_t))c;
422 DEBUG(5, ("Could not trigger sid2gid\n"));
423 cont(private_data, False, 0);
427 if (response->result != WINBINDD_OK) {
428 DEBUG(5, ("sid2gid returned an error\n"));
429 cont(private_data, False, 0);
433 cont(private_data, True, response->data.gid);
436 static void gid2name_recv(TALLOC_CTX *mem_ctx, BOOL success,
437 struct winbindd_response *response,
438 void *c, void *private_data)
440 void (*cont)(void *priv, BOOL succ, const char *name) =
441 (void (*)(void *, BOOL, const char *))c;
444 DEBUG(5, ("Could not trigger gid2name\n"));
445 cont(private_data, False, NULL);
449 if (response->result != WINBINDD_OK) {
450 DEBUG(5, ("gid2name returned an error\n"));
451 cont(private_data, False, NULL);
455 cont(private_data, True, response->data.name.name);
458 void winbindd_gid2name_async(TALLOC_CTX *mem_ctx, gid_t gid,
459 void (*cont)(void *private_data, BOOL success,
463 struct winbindd_request request;
464 ZERO_STRUCT(request);
465 request.cmd = WINBINDD_DUAL_GID2NAME;
466 request.data.gid = gid;
467 do_async(mem_ctx, idmap_child(), &request, gid2name_recv,
468 (void *)cont, private_data);
471 enum winbindd_result winbindd_dual_gid2name(struct winbindd_domain *domain,
472 struct winbindd_cli_state *state)
476 DEBUG(3, ("[%5lu]: gid2name %lu\n", (unsigned long)state->pid,
477 (unsigned long)state->request.data.gid));
479 gr = getgrgid(state->request.data.gid);
481 return WINBINDD_ERROR;
483 fstrcpy(state->response.data.name.name, gr->gr_name);
487 static void name2gid_recv(TALLOC_CTX *mem_ctx, BOOL success,
488 struct winbindd_response *response,
489 void *c, void *private_data);
491 static void winbindd_name2gid_async(TALLOC_CTX *mem_ctx, const char *name,
492 void (*cont)(void *private_data, BOOL success,
496 struct winbindd_request request;
497 ZERO_STRUCT(request);
498 request.cmd = WINBINDD_DUAL_NAME2GID;
499 fstrcpy(request.data.groupname, name);
500 do_async(mem_ctx, idmap_child(), &request, name2gid_recv,
501 (void *)cont, private_data);
504 enum winbindd_result winbindd_dual_name2gid(struct winbindd_domain *domain,
505 struct winbindd_cli_state *state)
509 /* Ensure null termination */
510 state->request.data.groupname
511 [sizeof(state->request.data.groupname)-1] = '\0';
513 DEBUG(3, ("[%5lu]: name2gid %s\n", (unsigned long)state->pid,
514 state->request.data.groupname));
516 gr = getgrnam(state->request.data.groupname);
518 return WINBINDD_ERROR;
521 state->response.data.gid = gr->gr_gid;
525 static void name2gid_recv(TALLOC_CTX *mem_ctx, BOOL success,
526 struct winbindd_response *response,
527 void *c, void *private_data)
529 void (*cont)(void *priv, BOOL succ, gid_t gid) =
530 (void (*)(void *, BOOL, gid_t))c;
533 DEBUG(5, ("Could not trigger name2gid\n"));
534 cont(private_data, False, 0);
538 if (response->result != WINBINDD_OK) {
539 DEBUG(5, ("name2gid returned an error\n"));
540 cont(private_data, False, 0);
544 cont(private_data, True, response->data.gid);
548 static void lookupsid_recv(TALLOC_CTX *mem_ctx, BOOL success,
549 struct winbindd_response *response,
550 void *c, void *private_data)
552 void (*cont)(void *priv, BOOL succ, const char *dom_name,
553 const char *name, enum SID_NAME_USE type) =
554 (void (*)(void *, BOOL, const char *, const char *,
555 enum SID_NAME_USE))c;
558 DEBUG(5, ("Could not trigger lookupsid\n"));
559 cont(private_data, False, NULL, NULL, SID_NAME_UNKNOWN);
563 if (response->result != WINBINDD_OK) {
564 DEBUG(5, ("lookupsid returned an error\n"));
565 cont(private_data, False, NULL, NULL, SID_NAME_UNKNOWN);
569 cont(private_data, True, response->data.name.dom_name,
570 response->data.name.name,
571 (enum SID_NAME_USE)response->data.name.type);
574 void winbindd_lookupsid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
575 void (*cont)(void *private_data, BOOL success,
576 const char *dom_name,
578 enum SID_NAME_USE type),
581 struct winbindd_domain *domain;
582 struct winbindd_request request;
584 domain = find_lookup_domain_from_sid(sid);
585 if (domain == NULL) {
586 DEBUG(5, ("Could not find domain for sid %s\n",
587 sid_string_static(sid)));
588 cont(private_data, False, NULL, NULL, SID_NAME_UNKNOWN);
592 ZERO_STRUCT(request);
593 request.cmd = WINBINDD_LOOKUPSID;
594 fstrcpy(request.data.sid, sid_string_static(sid));
596 do_async_domain(mem_ctx, domain, &request, lookupsid_recv,
597 (void *)cont, private_data);
600 enum winbindd_result winbindd_dual_lookupsid(struct winbindd_domain *domain,
601 struct winbindd_cli_state *state)
603 enum SID_NAME_USE type;
608 /* Ensure null termination */
609 state->request.data.sid[sizeof(state->request.data.sid)-1]='\0';
611 DEBUG(3, ("[%5lu]: lookupsid %s\n", (unsigned long)state->pid,
612 state->request.data.sid));
614 /* Lookup sid from PDC using lsa_lookup_sids() */
616 if (!string_to_sid(&sid, state->request.data.sid)) {
617 DEBUG(5, ("%s not a SID\n", state->request.data.sid));
618 return WINBINDD_ERROR;
623 if (!winbindd_lookup_name_by_sid(state->mem_ctx, &sid, dom_name, name,
625 return WINBINDD_ERROR;
628 fstrcpy(state->response.data.name.dom_name, dom_name);
629 fstrcpy(state->response.data.name.name, name);
630 state->response.data.name.type = type;
635 static void lookupname_recv(TALLOC_CTX *mem_ctx, BOOL success,
636 struct winbindd_response *response,
637 void *c, void *private_data)
639 void (*cont)(void *priv, BOOL succ, const DOM_SID *sid,
640 enum SID_NAME_USE type) =
641 (void (*)(void *, BOOL, const DOM_SID *, enum SID_NAME_USE))c;
645 DEBUG(5, ("Could not trigger lookup_name\n"));
646 cont(private_data, False, NULL, SID_NAME_UNKNOWN);
650 if (response->result != WINBINDD_OK) {
651 DEBUG(5, ("lookup_name returned an error\n"));
652 cont(private_data, False, NULL, SID_NAME_UNKNOWN);
656 if (!string_to_sid(&sid, response->data.sid.sid)) {
657 DEBUG(0, ("Could not convert string %s to sid\n",
658 response->data.sid.sid));
659 cont(private_data, False, NULL, SID_NAME_UNKNOWN);
663 cont(private_data, True, &sid,
664 (enum SID_NAME_USE)response->data.sid.type);
667 void winbindd_lookupname_async(TALLOC_CTX *mem_ctx, const char *dom_name,
669 void (*cont)(void *private_data, BOOL success,
671 enum SID_NAME_USE type),
674 struct winbindd_request request;
675 struct winbindd_domain *domain;
677 domain = find_lookup_domain_from_name(dom_name);
679 if (domain == NULL) {
680 DEBUG(5, ("Could not find domain for name %s\n", dom_name));
681 cont(private_data, False, NULL, SID_NAME_UNKNOWN);
685 ZERO_STRUCT(request);
686 request.cmd = WINBINDD_LOOKUPNAME;
687 fstrcpy(request.data.name.dom_name, dom_name);
688 fstrcpy(request.data.name.name, name);
690 do_async_domain(mem_ctx, domain, &request, lookupname_recv,
691 (void *)cont, private_data);
694 enum winbindd_result winbindd_dual_lookupname(struct winbindd_domain *domain,
695 struct winbindd_cli_state *state)
697 enum SID_NAME_USE type;
698 char *name_domain, *name_user;
702 /* Ensure null termination */
703 state->request.data.sid[sizeof(state->request.data.name.dom_name)-1]='\0';
705 /* Ensure null termination */
706 state->request.data.sid[sizeof(state->request.data.name.name)-1]='\0';
708 /* cope with the name being a fully qualified name */
709 p = strstr(state->request.data.name.name, lp_winbind_separator());
712 name_domain = state->request.data.name.name;
715 name_domain = state->request.data.name.dom_name;
716 name_user = state->request.data.name.name;
719 DEBUG(3, ("[%5lu]: lookupname %s%s%s\n", (unsigned long)state->pid,
720 name_domain, lp_winbind_separator(), name_user));
722 /* Lookup name from PDC using lsa_lookup_names() */
723 if (!winbindd_lookup_sid_by_name(state->mem_ctx, domain, name_domain,
724 name_user, &sid, &type)) {
725 return WINBINDD_ERROR;
728 sid_to_string(state->response.data.sid.sid, &sid);
729 state->response.data.sid.type = type;
734 BOOL print_sidlist(TALLOC_CTX *mem_ctx, const DOM_SID *sids,
735 size_t num_sids, char **result, ssize_t *len)
742 for (i=0; i<num_sids; i++) {
743 sprintf_append(mem_ctx, result, len, &buflen,
744 "%s\n", sid_string_static(&sids[i]));
747 if ((num_sids != 0) && (*result == NULL)) {
754 static BOOL parse_sidlist(TALLOC_CTX *mem_ctx, char *sidstr,
755 DOM_SID **sids, size_t *num_sids)
763 while (p[0] != '\0') {
767 DEBUG(0, ("Got invalid sidstr: %s\n", p));
772 if (!string_to_sid(&sid, p)) {
773 DEBUG(0, ("Could not parse sid %s\n", p));
776 add_sid_to_array(mem_ctx, &sid, sids, num_sids);
782 static BOOL parse_ridlist(TALLOC_CTX *mem_ctx, char *ridstr,
783 uint32 **rids, size_t *num_rids)
791 while (p[0] != '\0') {
794 rid = strtoul(p, &q, 10);
796 DEBUG(0, ("Got invalid ridstr: %s\n", p));
800 ADD_TO_ARRAY(mem_ctx, uint32, rid, rids, num_rids);
805 enum winbindd_result winbindd_dual_lookuprids(struct winbindd_domain *domain,
806 struct winbindd_cli_state *state)
809 size_t i, buflen, num_rids = 0;
814 enum SID_NAME_USE *types;
818 DEBUG(10, ("Looking up RIDs for domain %s (%s)\n",
819 state->request.domain_name,
820 state->request.data.sid));
822 if (!parse_ridlist(state->mem_ctx, state->request.extra_data.data,
824 DEBUG(5, ("Could not parse ridlist\n"));
825 return WINBINDD_ERROR;
828 if (!string_to_sid(&domain_sid, state->request.data.sid)) {
829 DEBUG(5, ("Could not parse domain sid %s\n",
830 state->request.data.sid));
831 return WINBINDD_ERROR;
834 status = domain->methods->rids_to_names(domain, state->mem_ctx,
835 &domain_sid, rids, num_rids,
839 if (!NT_STATUS_IS_OK(status) &&
840 !NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
841 return WINBINDD_ERROR;
848 for (i=0; i<num_rids; i++) {
849 sprintf_append(state->mem_ctx, &result, &len, &buflen,
850 "%d %s\n", types[i], names[i]);
853 fstrcpy(state->response.data.domain_name, domain_name);
855 if (result != NULL) {
856 state->response.extra_data.data = SMB_STRDUP(result);
857 state->response.length += len+1;
863 static void getsidaliases_recv(TALLOC_CTX *mem_ctx, BOOL success,
864 struct winbindd_response *response,
865 void *c, void *private_data)
867 void (*cont)(void *priv, BOOL succ,
868 DOM_SID *aliases, size_t num_aliases) =
869 (void (*)(void *, BOOL, DOM_SID *, size_t))c;
871 DOM_SID *sids = NULL;
875 DEBUG(5, ("Could not trigger getsidaliases\n"));
876 cont(private_data, success, NULL, 0);
880 if (response->result != WINBINDD_OK) {
881 DEBUG(5, ("getsidaliases returned an error\n"));
882 cont(private_data, False, NULL, 0);
886 aliases_str = (char *)response->extra_data.data;
888 if (aliases_str == NULL) {
889 DEBUG(10, ("getsidaliases return 0 SIDs\n"));
890 cont(private_data, True, NULL, 0);
894 if (!parse_sidlist(mem_ctx, aliases_str, &sids, &num_sids)) {
895 DEBUG(0, ("Could not parse sids\n"));
896 cont(private_data, False, NULL, 0);
900 SAFE_FREE(response->extra_data.data);
902 cont(private_data, True, sids, num_sids);
905 void winbindd_getsidaliases_async(struct winbindd_domain *domain,
907 const DOM_SID *sids, size_t num_sids,
908 void (*cont)(void *private_data,
910 const DOM_SID *aliases,
914 struct winbindd_request request;
919 cont(private_data, True, NULL, 0);
923 if (!print_sidlist(mem_ctx, sids, num_sids, &sidstr, &len)) {
924 cont(private_data, False, NULL, 0);
928 ZERO_STRUCT(request);
929 request.cmd = WINBINDD_DUAL_GETSIDALIASES;
930 request.extra_len = len;
931 request.extra_data.data = sidstr;
933 do_async_domain(mem_ctx, domain, &request, getsidaliases_recv,
934 (void *)cont, private_data);
937 enum winbindd_result winbindd_dual_getsidaliases(struct winbindd_domain *domain,
938 struct winbindd_cli_state *state)
940 DOM_SID *sids = NULL;
949 DEBUG(3, ("[%5lu]: getsidaliases\n", (unsigned long)state->pid));
951 sidstr = state->request.extra_data.data;
953 sidstr = talloc_strdup(state->mem_ctx, "\n"); /* No SID */
955 DEBUG(10, ("Sidlist: %s\n", sidstr));
957 if (!parse_sidlist(state->mem_ctx, sidstr, &sids, &num_sids)) {
958 DEBUG(0, ("Could not parse SID list: %s\n", sidstr));
959 return WINBINDD_ERROR;
965 result = domain->methods->lookup_useraliases(domain,
971 if (!NT_STATUS_IS_OK(result)) {
972 DEBUG(3, ("Could not lookup_useraliases: %s\n",
974 return WINBINDD_ERROR;
980 DEBUG(10, ("Got %d aliases\n", num_aliases));
982 for (i=0; i<num_aliases; i++) {
984 DEBUGADD(10, (" rid %d\n", alias_rids[i]));
985 sid_copy(&sid, &domain->sid);
986 sid_append_rid(&sid, alias_rids[i]);
987 add_sid_to_array(state->mem_ctx, &sid, &sids, &num_sids);
991 if (!print_sidlist(NULL, sids, num_sids, &sidstr, &len)) {
992 DEBUG(0, ("Could not print_sidlist\n"));
993 state->response.extra_data.data = NULL;
994 return WINBINDD_ERROR;
997 state->response.extra_data.data = sidstr;
999 if (state->response.extra_data.data != NULL) {
1000 DEBUG(10, ("aliases_list: %s\n",
1001 (char *)state->response.extra_data.data));
1002 state->response.length += len+1;
1008 struct gettoken_state {
1009 TALLOC_CTX *mem_ctx;
1011 struct winbindd_domain *alias_domain;
1012 struct winbindd_domain *local_alias_domain;
1013 struct winbindd_domain *builtin_domain;
1016 void (*cont)(void *private_data, BOOL success, DOM_SID *sids, size_t num_sids);
1020 static void gettoken_recvdomgroups(TALLOC_CTX *mem_ctx, BOOL success,
1021 struct winbindd_response *response,
1022 void *c, void *private_data);
1023 static void gettoken_recvaliases(void *private_data, BOOL success,
1024 const DOM_SID *aliases,
1025 size_t num_aliases);
1028 void winbindd_gettoken_async(TALLOC_CTX *mem_ctx, const DOM_SID *user_sid,
1029 void (*cont)(void *private_data, BOOL success,
1030 DOM_SID *sids, size_t num_sids),
1033 struct winbindd_domain *domain;
1034 struct winbindd_request request;
1035 struct gettoken_state *state;
1037 state = TALLOC_P(mem_ctx, struct gettoken_state);
1038 if (state == NULL) {
1039 DEBUG(0, ("talloc failed\n"));
1040 cont(private_data, False, NULL, 0);
1044 state->mem_ctx = mem_ctx;
1045 sid_copy(&state->user_sid, user_sid);
1046 state->alias_domain = find_our_domain();
1047 state->local_alias_domain = find_domain_from_name( get_global_sam_name() );
1048 state->builtin_domain = find_builtin_domain();
1050 state->private_data = private_data;
1052 domain = find_domain_from_sid_noinit(user_sid);
1053 if (domain == NULL) {
1054 DEBUG(5, ("Could not find domain from SID %s\n",
1055 sid_string_static(user_sid)));
1056 cont(private_data, False, NULL, 0);
1060 ZERO_STRUCT(request);
1061 request.cmd = WINBINDD_GETUSERDOMGROUPS;
1062 fstrcpy(request.data.sid, sid_string_static(user_sid));
1064 do_async_domain(mem_ctx, domain, &request, gettoken_recvdomgroups,
1068 static void gettoken_recvdomgroups(TALLOC_CTX *mem_ctx, BOOL success,
1069 struct winbindd_response *response,
1070 void *c, void *private_data)
1072 struct gettoken_state *state =
1073 talloc_get_type_abort(private_data, struct gettoken_state);
1077 DEBUG(10, ("Could not get domain groups\n"));
1078 state->cont(state->private_data, False, NULL, 0);
1082 sids_str = (char *)response->extra_data.data;
1084 if (sids_str == NULL) {
1085 /* This could be normal if we are dealing with a
1086 local user and local groups */
1088 if ( !sid_check_is_in_our_domain( &state->user_sid ) ) {
1089 DEBUG(10, ("Received no domain groups\n"));
1090 state->cont(state->private_data, True, NULL, 0);
1096 state->num_sids = 0;
1098 add_sid_to_array(mem_ctx, &state->user_sid, &state->sids,
1101 if (sids_str && !parse_sidlist(mem_ctx, sids_str, &state->sids,
1102 &state->num_sids)) {
1103 DEBUG(0, ("Could not parse sids\n"));
1104 state->cont(state->private_data, False, NULL, 0);
1108 SAFE_FREE(response->extra_data.data);
1110 if (state->alias_domain == NULL) {
1111 DEBUG(10, ("Don't expand domain local groups\n"));
1112 state->cont(state->private_data, True, state->sids,
1117 winbindd_getsidaliases_async(state->alias_domain, mem_ctx,
1118 state->sids, state->num_sids,
1119 gettoken_recvaliases, state);
1122 static void gettoken_recvaliases(void *private_data, BOOL success,
1123 const DOM_SID *aliases,
1126 struct gettoken_state *state = (struct gettoken_state *)private_data;
1130 DEBUG(10, ("Could not receive domain local groups\n"));
1131 state->cont(state->private_data, False, NULL, 0);
1135 for (i=0; i<num_aliases; i++)
1136 add_sid_to_array(state->mem_ctx, &aliases[i],
1137 &state->sids, &state->num_sids);
1139 if (state->local_alias_domain != NULL) {
1140 struct winbindd_domain *local_domain = state->local_alias_domain;
1141 DEBUG(10, ("Expanding our own local groups\n"));
1142 state->local_alias_domain = NULL;
1143 winbindd_getsidaliases_async(local_domain, state->mem_ctx,
1144 state->sids, state->num_sids,
1145 gettoken_recvaliases, state);
1149 if (state->builtin_domain != NULL) {
1150 struct winbindd_domain *builtin_domain = state->builtin_domain;
1151 DEBUG(10, ("Expanding our own BUILTIN groups\n"));
1152 state->builtin_domain = NULL;
1153 winbindd_getsidaliases_async(builtin_domain, state->mem_ctx,
1154 state->sids, state->num_sids,
1155 gettoken_recvaliases, state);
1159 state->cont(state->private_data, True, state->sids, state->num_sids);
1162 struct sid2uid_state {
1163 TALLOC_CTX *mem_ctx;
1167 void (*cont)(void *private_data, BOOL success, uid_t uid);
1171 static void sid2uid_lookup_sid_recv(void *private_data, BOOL success,
1172 const char *dom_name, const char *name,
1173 enum SID_NAME_USE type);
1174 static void sid2uid_noalloc_recv(void *private_data, BOOL success, uid_t uid);
1175 static void sid2uid_alloc_recv(void *private_data, BOOL success, uid_t uid);
1176 static void sid2uid_name2uid_recv(void *private_data, BOOL success, uid_t uid);
1177 static void sid2uid_set_mapping_recv(void *private_data, BOOL success);
1179 void winbindd_sid2uid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
1180 void (*cont)(void *private_data, BOOL success,
1184 struct sid2uid_state *state;
1188 if (idmap_proxyonly()) {
1189 DEBUG(10, ("idmap proxy only\n"));
1190 cont(private_data, False, 0);
1194 /* Query only the local tdb, everything else might possibly block */
1196 result = idmap_sid_to_uid(sid, &uid, IDMAP_FLAG_QUERY_ONLY|IDMAP_FLAG_CACHE_ONLY);
1198 if (NT_STATUS_IS_OK(result)) {
1199 cont(private_data, True, uid);
1203 state = TALLOC_P(mem_ctx, struct sid2uid_state);
1204 if (state == NULL) {
1205 DEBUG(0, ("talloc failed\n"));
1206 cont(private_data, False, 0);
1210 state->mem_ctx = mem_ctx;
1213 state->private_data = private_data;
1215 /* Let's see if it's really a user before allocating a uid */
1217 winbindd_lookupsid_async(mem_ctx, sid, sid2uid_lookup_sid_recv, state);
1220 static void sid2uid_lookup_sid_recv(void *private_data, BOOL success,
1221 const char *dom_name, const char *name,
1222 enum SID_NAME_USE type)
1224 struct sid2uid_state *state =
1225 talloc_get_type_abort(private_data, struct sid2uid_state);
1228 DEBUG(5, ("Could not trigger lookup_sid\n"));
1229 state->cont(state->private_data, False, 0);
1233 if ((type != SID_NAME_USER) && (type != SID_NAME_COMPUTER)) {
1234 DEBUG(5, ("SID is not a user\n"));
1235 state->cont(state->private_data, False, 0);
1239 state->username = talloc_strdup(state->mem_ctx, name);
1241 /* Ask the possibly blocking remote IDMAP */
1243 idmap_sid2uid_async(state->mem_ctx, &state->sid, False,
1244 sid2uid_noalloc_recv, state);
1247 static void sid2uid_noalloc_recv(void *private_data, BOOL success, uid_t uid)
1249 struct sid2uid_state *state =
1250 talloc_get_type_abort(private_data, struct sid2uid_state);
1253 DEBUG(10, ("found uid for sid %s in remote backend\n",
1254 sid_string_static(&state->sid)));
1255 state->cont(state->private_data, True, uid);
1259 if (lp_winbind_trusted_domains_only() &&
1260 (sid_compare_domain(&state->sid, &find_our_domain()->sid) == 0)) {
1261 DEBUG(10, ("Trying to go via nss\n"));
1262 winbindd_name2uid_async(state->mem_ctx, state->username,
1263 sid2uid_name2uid_recv, state);
1267 /* To be done: Here we're going to try the unixinfo pipe */
1269 /* Now allocate a uid */
1271 idmap_sid2uid_async(state->mem_ctx, &state->sid, True,
1272 sid2uid_alloc_recv, state);
1275 static void sid2uid_alloc_recv(void *private_data, BOOL success, uid_t uid)
1277 struct sid2uid_state *state =
1278 talloc_get_type_abort(private_data, struct sid2uid_state);
1281 DEBUG(5, ("Could not allocate uid\n"));
1282 state->cont(state->private_data, False, 0);
1286 state->cont(state->private_data, True, uid);
1289 static void sid2uid_name2uid_recv(void *private_data, BOOL success, uid_t uid)
1291 struct sid2uid_state *state =
1292 talloc_get_type_abort(private_data, struct sid2uid_state);
1296 DEBUG(5, ("Could not find uid for name %s\n",
1298 state->cont(state->private_data, False, 0);
1305 idmap_set_mapping_async(state->mem_ctx, &state->sid, id, ID_USERID,
1306 sid2uid_set_mapping_recv, state);
1309 static void sid2uid_set_mapping_recv(void *private_data, BOOL success)
1311 struct sid2uid_state *state =
1312 talloc_get_type_abort(private_data, struct sid2uid_state);
1315 DEBUG(5, ("Could not set ID mapping for sid %s\n",
1316 sid_string_static(&state->sid)));
1317 state->cont(state->private_data, False, 0);
1321 state->cont(state->private_data, True, state->uid);
1324 struct sid2gid_state {
1325 TALLOC_CTX *mem_ctx;
1329 void (*cont)(void *private_data, BOOL success, gid_t gid);
1333 static void sid2gid_lookup_sid_recv(void *private_data, BOOL success,
1334 const char *dom_name, const char *name,
1335 enum SID_NAME_USE type);
1336 static void sid2gid_noalloc_recv(void *private_data, BOOL success, gid_t gid);
1337 static void sid2gid_alloc_recv(void *private_data, BOOL success, gid_t gid);
1338 static void sid2gid_name2gid_recv(void *private_data, BOOL success, gid_t gid);
1339 static void sid2gid_set_mapping_recv(void *private_data, BOOL success);
1341 void winbindd_sid2gid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
1342 void (*cont)(void *private_data, BOOL success,
1346 struct sid2gid_state *state;
1350 if (idmap_proxyonly()) {
1351 DEBUG(10, ("idmap proxy only\n"));
1352 cont(private_data, False, 0);
1356 /* Query only the local tdb, everything else might possibly block */
1358 result = idmap_sid_to_gid(sid, &gid, IDMAP_FLAG_QUERY_ONLY|IDMAP_FLAG_CACHE_ONLY);
1360 if (NT_STATUS_IS_OK(result)) {
1361 cont(private_data, True, gid);
1365 state = TALLOC_P(mem_ctx, struct sid2gid_state);
1366 if (state == NULL) {
1367 DEBUG(0, ("talloc failed\n"));
1368 cont(private_data, False, 0);
1372 state->mem_ctx = mem_ctx;
1375 state->private_data = private_data;
1377 /* Let's see if it's really a user before allocating a gid */
1379 winbindd_lookupsid_async(mem_ctx, sid, sid2gid_lookup_sid_recv, state);
1382 static void sid2gid_lookup_sid_recv(void *private_data, BOOL success,
1383 const char *dom_name, const char *name,
1384 enum SID_NAME_USE type)
1386 struct sid2gid_state *state =
1387 talloc_get_type_abort(private_data, struct sid2gid_state);
1390 DEBUG(5, ("Could not trigger lookup_sid\n"));
1391 state->cont(state->private_data, False, 0);
1395 if (((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
1396 (type != SID_NAME_WKN_GRP))) {
1397 DEBUG(5, ("SID is not a group\n"));
1398 state->cont(state->private_data, False, 0);
1402 state->groupname = talloc_strdup(state->mem_ctx, name);
1404 /* Ask the possibly blocking remote IDMAP and allocate */
1406 idmap_sid2gid_async(state->mem_ctx, &state->sid, False,
1407 sid2gid_noalloc_recv, state);
1410 static void sid2gid_noalloc_recv(void *private_data, BOOL success, gid_t gid)
1412 struct sid2gid_state *state =
1413 talloc_get_type_abort(private_data, struct sid2gid_state);
1416 DEBUG(10, ("found gid for sid %s in remote backend\n",
1417 sid_string_static(&state->sid)));
1418 state->cont(state->private_data, True, gid);
1422 if (lp_winbind_trusted_domains_only() &&
1423 (sid_compare_domain(&state->sid, &find_our_domain()->sid) == 0)) {
1424 DEBUG(10, ("Trying to go via nss\n"));
1425 winbindd_name2gid_async(state->mem_ctx, state->groupname,
1426 sid2gid_name2gid_recv, state);
1430 /* To be done: Here we're going to try the unixinfo pipe */
1432 /* Now allocate a gid */
1434 idmap_sid2gid_async(state->mem_ctx, &state->sid, True,
1435 sid2gid_alloc_recv, state);
1438 static void sid2gid_alloc_recv(void *private_data, BOOL success, gid_t gid)
1440 struct sid2gid_state *state =
1441 talloc_get_type_abort(private_data, struct sid2gid_state);
1444 DEBUG(5, ("Could not allocate gid\n"));
1445 state->cont(state->private_data, False, 0);
1449 state->cont(state->private_data, True, gid);
1452 static void sid2gid_name2gid_recv(void *private_data, BOOL success, gid_t gid)
1454 struct sid2gid_state *state =
1455 talloc_get_type_abort(private_data, struct sid2gid_state);
1459 DEBUG(5, ("Could not find gid for name %s\n",
1461 state->cont(state->private_data, False, 0);
1468 idmap_set_mapping_async(state->mem_ctx, &state->sid, id, ID_GROUPID,
1469 sid2gid_set_mapping_recv, state);
1472 static void sid2gid_set_mapping_recv(void *private_data, BOOL success)
1474 struct sid2gid_state *state =
1475 talloc_get_type_abort(private_data, struct sid2gid_state);
1478 DEBUG(5, ("Could not set ID mapping for sid %s\n",
1479 sid_string_static(&state->sid)));
1480 state->cont(state->private_data, False, 0);
1484 state->cont(state->private_data, True, state->gid);
1487 static void query_user_recv(TALLOC_CTX *mem_ctx, BOOL success,
1488 struct winbindd_response *response,
1489 void *c, void *private_data)
1491 void (*cont)(void *priv, BOOL succ, const char *acct_name,
1492 const char *full_name, const char *homedir,
1493 const char *shell, uint32 group_rid) =
1494 (void (*)(void *, BOOL, const char *, const char *,
1495 const char *, const char *, uint32))c;
1498 DEBUG(5, ("Could not trigger query_user\n"));
1499 cont(private_data, False, NULL, NULL, NULL, NULL, -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.group_rid);
1510 void query_user_async(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1512 void (*cont)(void *private_data, BOOL success,
1513 const char *acct_name,
1514 const char *full_name,
1515 const char *homedir,
1520 struct winbindd_request request;
1521 ZERO_STRUCT(request);
1522 request.cmd = WINBINDD_DUAL_USERINFO;
1523 sid_to_string(request.data.sid, sid);
1524 do_async_domain(mem_ctx, domain, &request, query_user_recv,
1525 (void *)cont, private_data);