r20090: Fix a class of bugs found by James Peach. Ensure
[Samba/nascimento.git] / source3 / nsswitch / winbindd_async.c
blob607a9947ea22fb5b5ac0d97b42328b8dc24932aa
1 /*
2 Unix SMB/CIFS implementation.
4 Async helpers for blocking functions
6 Copyright (C) Volker Lendecke 2005
7 Copyright (C) Gerald Carter 2006
9 The helpers always consist of three functions:
11 * A request setup function that takes the necessary parameters together
12 with a continuation function that is to be called upon completion
14 * A private continuation function that is internal only. This is to be
15 called by the lower-level functions in do_async(). Its only task is to
16 properly call the continuation function named above.
18 * A worker function that is called inside the appropriate child process.
20 This program is free software; you can redistribute it and/or modify
21 it under the terms of the GNU General Public License as published by
22 the Free Software Foundation; either version 2 of the License, or
23 (at your option) any later version.
25 This program is distributed in the hope that it will be useful,
26 but WITHOUT ANY WARRANTY; without even the implied warranty of
27 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 GNU General Public License for more details.
30 You should have received a copy of the GNU General Public License
31 along with this program; if not, write to the Free Software
32 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
35 #include "includes.h"
36 #include "winbindd.h"
38 #undef DBGC_CLASS
39 #define DBGC_CLASS DBGC_WINBIND
41 struct do_async_state {
42 TALLOC_CTX *mem_ctx;
43 struct winbindd_request request;
44 struct winbindd_response response;
45 void (*cont)(TALLOC_CTX *mem_ctx,
46 BOOL success,
47 struct winbindd_response *response,
48 void *c, void *private_data);
49 void *c, *private_data;
52 static void do_async_recv(void *private_data, BOOL success)
54 struct do_async_state *state =
55 talloc_get_type_abort(private_data, struct do_async_state);
57 state->cont(state->mem_ctx, success, &state->response,
58 state->c, state->private_data);
61 static void do_async(TALLOC_CTX *mem_ctx, struct winbindd_child *child,
62 const struct winbindd_request *request,
63 void (*cont)(TALLOC_CTX *mem_ctx, BOOL success,
64 struct winbindd_response *response,
65 void *c, void *private_data),
66 void *c, void *private_data)
68 struct do_async_state *state;
70 state = TALLOC_ZERO_P(mem_ctx, struct do_async_state);
71 if (state == NULL) {
72 DEBUG(0, ("talloc failed\n"));
73 cont(mem_ctx, False, NULL, c, private_data);
74 return;
77 state->mem_ctx = mem_ctx;
78 state->request = *request;
79 state->request.length = sizeof(state->request);
80 state->cont = cont;
81 state->c = c;
82 state->private_data = private_data;
84 async_request(mem_ctx, child, &state->request,
85 &state->response, do_async_recv, state);
88 void do_async_domain(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
89 const struct winbindd_request *request,
90 void (*cont)(TALLOC_CTX *mem_ctx, BOOL success,
91 struct winbindd_response *response,
92 void *c, void *private_data),
93 void *c, void *private_data)
95 struct do_async_state *state;
97 state = TALLOC_ZERO_P(mem_ctx, struct do_async_state);
98 if (state == NULL) {
99 DEBUG(0, ("talloc failed\n"));
100 cont(mem_ctx, False, NULL, c, private_data);
101 return;
104 state->mem_ctx = mem_ctx;
105 state->request = *request;
106 state->request.length = sizeof(state->request);
107 state->cont = cont;
108 state->c = c;
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;
121 if (!success) {
122 DEBUG(5, ("Could not trigger idmap_set_mapping\n"));
123 cont(private_data, False);
124 return;
127 if (response->result != WINBINDD_OK) {
128 DEBUG(5, ("idmap_set_mapping returned an error\n"));
129 cont(private_data, False);
130 return;
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),
139 void *private_data)
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;
146 else
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)
158 DOM_SID sid;
159 unid_t id;
160 NTSTATUS result;
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;
169 else
170 id.gid = state->request.data.dual_idmapset.gid;
172 result = idmap_set_mapping(
173 &sid, id,
174 (enum idmap_type)state->request.data.dual_idmapset.type);
175 return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
178 static void idmap_sid2uid_recv(TALLOC_CTX *mem_ctx, BOOL success,
179 struct winbindd_response *response,
180 void *c, void *private_data);
182 void idmap_sid2uid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid, BOOL alloc,
183 void (*cont)(void *private_data, BOOL success, uid_t uid),
184 void *private_data)
186 struct winbindd_request request;
187 ZERO_STRUCT(request);
188 request.cmd = WINBINDD_DUAL_SID2UID;
189 sid_to_string(request.data.dual_sid2id.sid, sid);
190 request.data.dual_sid2id.alloc = alloc;
191 do_async(mem_ctx, idmap_child(), &request, idmap_sid2uid_recv,
192 (void *)cont, private_data);
195 enum winbindd_result winbindd_dual_sid2uid(struct winbindd_domain *domain,
196 struct winbindd_cli_state *state)
198 DOM_SID sid;
199 NTSTATUS result;
201 DEBUG(3, ("[%5lu]: sid to uid %s\n", (unsigned long)state->pid,
202 state->request.data.dual_sid2id.sid));
204 if (!string_to_sid(&sid, state->request.data.dual_sid2id.sid)) {
205 DEBUG(1, ("Could not get convert sid %s from string\n",
206 state->request.data.dual_sid2id.sid));
207 return WINBINDD_ERROR;
210 /* Find uid for this sid and return it, possibly ask the slow remote
211 * idmap */
213 result = idmap_sid_to_uid(&sid, &(state->response.data.uid),
214 state->request.data.dual_sid2id.alloc ?
215 0 : IDMAP_FLAG_QUERY_ONLY);
217 return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
220 static void idmap_sid2uid_recv(TALLOC_CTX *mem_ctx, BOOL success,
221 struct winbindd_response *response,
222 void *c, void *private_data)
224 void (*cont)(void *priv, BOOL succ, uid_t uid) =
225 (void (*)(void *, BOOL, uid_t))c;
227 if (!success) {
228 DEBUG(5, ("Could not trigger sid2uid\n"));
229 cont(private_data, False, 0);
230 return;
233 if (response->result != WINBINDD_OK) {
234 DEBUG(5, ("sid2uid returned an error\n"));
235 cont(private_data, False, 0);
236 return;
239 cont(private_data, True, response->data.uid);
242 static void uid2name_recv(TALLOC_CTX *mem_ctx, BOOL success,
243 struct winbindd_response *response,
244 void *c, void *private_data);
246 void winbindd_uid2name_async(TALLOC_CTX *mem_ctx, uid_t uid,
247 void (*cont)(void *private_data, BOOL success,
248 const char *name),
249 void *private_data)
251 struct winbindd_request request;
252 ZERO_STRUCT(request);
253 request.cmd = WINBINDD_DUAL_UID2NAME;
254 request.data.uid = uid;
255 do_async(mem_ctx, idmap_child(), &request, uid2name_recv,
256 (void *)cont, private_data);
259 enum winbindd_result winbindd_dual_uid2name(struct winbindd_domain *domain,
260 struct winbindd_cli_state *state)
262 struct passwd *pw;
264 DEBUG(3, ("[%5lu]: uid2name %lu\n", (unsigned long)state->pid,
265 (unsigned long)state->request.data.uid));
267 pw = getpwuid(state->request.data.uid);
268 if (pw == NULL) {
269 DEBUG(5, ("User %lu not found\n",
270 (unsigned long)state->request.data.uid));
271 return WINBINDD_ERROR;
274 fstrcpy(state->response.data.name.name, pw->pw_name);
275 return WINBINDD_OK;
278 static void uid2name_recv(TALLOC_CTX *mem_ctx, BOOL success,
279 struct winbindd_response *response,
280 void *c, void *private_data)
282 void (*cont)(void *priv, BOOL succ, const char *name) =
283 (void (*)(void *, BOOL, const char *))c;
285 if (!success) {
286 DEBUG(5, ("Could not trigger uid2name\n"));
287 cont(private_data, False, NULL);
288 return;
291 if (response->result != WINBINDD_OK) {
292 DEBUG(5, ("uid2name returned an error\n"));
293 cont(private_data, False, NULL);
294 return;
297 cont(private_data, True, response->data.name.name);
300 static void name2uid_recv(TALLOC_CTX *mem_ctx, BOOL success,
301 struct winbindd_response *response,
302 void *c, void *private_data);
304 static void winbindd_name2uid_async(TALLOC_CTX *mem_ctx, const char *name,
305 void (*cont)(void *private_data, BOOL success,
306 uid_t uid),
307 void *private_data)
309 struct winbindd_request request;
310 ZERO_STRUCT(request);
311 request.cmd = WINBINDD_DUAL_NAME2UID;
312 fstrcpy(request.data.username, name);
313 do_async(mem_ctx, idmap_child(), &request, name2uid_recv,
314 (void *)cont, private_data);
317 enum winbindd_result winbindd_dual_name2uid(struct winbindd_domain *domain,
318 struct winbindd_cli_state *state)
320 struct passwd *pw;
322 /* Ensure null termination */
323 state->request.data.username
324 [sizeof(state->request.data.username)-1] = '\0';
326 DEBUG(3, ("[%5lu]: name2uid %s\n", (unsigned long)state->pid,
327 state->request.data.username));
329 pw = getpwnam(state->request.data.username);
330 if (pw == NULL) {
331 return WINBINDD_ERROR;
334 state->response.data.uid = pw->pw_uid;
335 return WINBINDD_OK;
338 static void name2uid_recv(TALLOC_CTX *mem_ctx, BOOL success,
339 struct winbindd_response *response,
340 void *c, void *private_data)
342 void (*cont)(void *priv, BOOL succ, uid_t uid) =
343 (void (*)(void *, BOOL, uid_t))c;
345 if (!success) {
346 DEBUG(5, ("Could not trigger name2uid\n"));
347 cont(private_data, False, 0);
348 return;
351 if (response->result != WINBINDD_OK) {
352 DEBUG(5, ("name2uid returned an error\n"));
353 cont(private_data, False, 0);
354 return;
357 cont(private_data, True, response->data.uid);
360 static void idmap_sid2gid_recv(TALLOC_CTX *mem_ctx, BOOL success,
361 struct winbindd_response *response,
362 void *c, void *private_data);
364 void idmap_sid2gid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid, BOOL alloc,
365 void (*cont)(void *private_data, BOOL success, gid_t gid),
366 void *private_data)
368 struct winbindd_request request;
369 ZERO_STRUCT(request);
370 request.cmd = WINBINDD_DUAL_SID2GID;
371 sid_to_string(request.data.dual_sid2id.sid, sid);
373 DEBUG(7,("idmap_sid2gid_async: Resolving %s to a gid\n",
374 request.data.dual_sid2id.sid));
376 request.data.dual_sid2id.alloc = alloc;
377 do_async(mem_ctx, idmap_child(), &request, idmap_sid2gid_recv,
378 (void *)cont, private_data);
381 enum winbindd_result winbindd_dual_sid2gid(struct winbindd_domain *domain,
382 struct winbindd_cli_state *state)
384 DOM_SID sid;
385 NTSTATUS result;
387 DEBUG(3, ("[%5lu]: sid to gid %s\n", (unsigned long)state->pid,
388 state->request.data.dual_sid2id.sid));
390 if (!string_to_sid(&sid, state->request.data.dual_sid2id.sid)) {
391 DEBUG(1, ("Could not get convert sid %s from string\n",
392 state->request.data.dual_sid2id.sid));
393 return WINBINDD_ERROR;
396 /* Find gid for this sid and return it, possibly ask the slow remote
397 * idmap */
399 result = idmap_sid_to_gid(&sid, &state->response.data.gid,
400 state->request.data.dual_sid2id.alloc ?
401 0 : IDMAP_FLAG_QUERY_ONLY);
403 /* If the lookup failed, the perhaps we need to look
404 at the passdb for local groups */
406 if ( !NT_STATUS_IS_OK(result) ) {
407 if ( sid_to_gid( &sid, &(state->response.data.gid) ) ) {
408 result = NT_STATUS_OK;
412 return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
415 static void idmap_sid2gid_recv(TALLOC_CTX *mem_ctx, BOOL success,
416 struct winbindd_response *response,
417 void *c, void *private_data)
419 void (*cont)(void *priv, BOOL succ, gid_t gid) =
420 (void (*)(void *, BOOL, gid_t))c;
422 if (!success) {
423 DEBUG(5, ("Could not trigger sid2gid\n"));
424 cont(private_data, False, 0);
425 return;
428 if (response->result != WINBINDD_OK) {
429 DEBUG(5, ("sid2gid returned an error\n"));
430 cont(private_data, False, 0);
431 return;
434 cont(private_data, True, response->data.gid);
437 static void gid2name_recv(TALLOC_CTX *mem_ctx, BOOL success,
438 struct winbindd_response *response,
439 void *c, void *private_data)
441 void (*cont)(void *priv, BOOL succ, const char *name) =
442 (void (*)(void *, BOOL, const char *))c;
444 if (!success) {
445 DEBUG(5, ("Could not trigger gid2name\n"));
446 cont(private_data, False, NULL);
447 return;
450 if (response->result != WINBINDD_OK) {
451 DEBUG(5, ("gid2name returned an error\n"));
452 cont(private_data, False, NULL);
453 return;
456 cont(private_data, True, response->data.name.name);
459 void winbindd_gid2name_async(TALLOC_CTX *mem_ctx, gid_t gid,
460 void (*cont)(void *private_data, BOOL success,
461 const char *name),
462 void *private_data)
464 struct winbindd_request request;
465 ZERO_STRUCT(request);
466 request.cmd = WINBINDD_DUAL_GID2NAME;
467 request.data.gid = gid;
468 do_async(mem_ctx, idmap_child(), &request, gid2name_recv,
469 (void *)cont, private_data);
472 enum winbindd_result winbindd_dual_gid2name(struct winbindd_domain *domain,
473 struct winbindd_cli_state *state)
475 struct group *gr;
477 DEBUG(3, ("[%5lu]: gid2name %lu\n", (unsigned long)state->pid,
478 (unsigned long)state->request.data.gid));
480 gr = getgrgid(state->request.data.gid);
481 if (gr == NULL)
482 return WINBINDD_ERROR;
484 fstrcpy(state->response.data.name.name, gr->gr_name);
485 return WINBINDD_OK;
488 static void name2gid_recv(TALLOC_CTX *mem_ctx, BOOL success,
489 struct winbindd_response *response,
490 void *c, void *private_data);
492 static void winbindd_name2gid_async(TALLOC_CTX *mem_ctx, const char *name,
493 void (*cont)(void *private_data, BOOL success,
494 gid_t gid),
495 void *private_data)
497 struct winbindd_request request;
498 ZERO_STRUCT(request);
499 request.cmd = WINBINDD_DUAL_NAME2GID;
500 fstrcpy(request.data.groupname, name);
501 do_async(mem_ctx, idmap_child(), &request, name2gid_recv,
502 (void *)cont, private_data);
505 enum winbindd_result winbindd_dual_name2gid(struct winbindd_domain *domain,
506 struct winbindd_cli_state *state)
508 struct group *gr;
510 /* Ensure null termination */
511 state->request.data.groupname
512 [sizeof(state->request.data.groupname)-1] = '\0';
514 DEBUG(3, ("[%5lu]: name2gid %s\n", (unsigned long)state->pid,
515 state->request.data.groupname));
517 gr = getgrnam(state->request.data.groupname);
518 if (gr == NULL) {
519 return WINBINDD_ERROR;
522 state->response.data.gid = gr->gr_gid;
523 return WINBINDD_OK;
526 static void name2gid_recv(TALLOC_CTX *mem_ctx, BOOL success,
527 struct winbindd_response *response,
528 void *c, void *private_data)
530 void (*cont)(void *priv, BOOL succ, gid_t gid) =
531 (void (*)(void *, BOOL, gid_t))c;
533 if (!success) {
534 DEBUG(5, ("Could not trigger name2gid\n"));
535 cont(private_data, False, 0);
536 return;
539 if (response->result != WINBINDD_OK) {
540 DEBUG(5, ("name2gid returned an error\n"));
541 cont(private_data, False, 0);
542 return;
545 cont(private_data, True, response->data.gid);
549 static void lookupsid_recv(TALLOC_CTX *mem_ctx, BOOL success,
550 struct winbindd_response *response,
551 void *c, void *private_data)
553 void (*cont)(void *priv, BOOL succ, const char *dom_name,
554 const char *name, enum lsa_SidType type) =
555 (void (*)(void *, BOOL, const char *, const char *,
556 enum lsa_SidType))c;
558 if (!success) {
559 DEBUG(5, ("Could not trigger lookupsid\n"));
560 cont(private_data, False, NULL, NULL, SID_NAME_UNKNOWN);
561 return;
564 if (response->result != WINBINDD_OK) {
565 DEBUG(5, ("lookupsid returned an error\n"));
566 cont(private_data, False, NULL, NULL, SID_NAME_UNKNOWN);
567 return;
570 cont(private_data, True, response->data.name.dom_name,
571 response->data.name.name,
572 (enum lsa_SidType)response->data.name.type);
575 void winbindd_lookupsid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
576 void (*cont)(void *private_data, BOOL success,
577 const char *dom_name,
578 const char *name,
579 enum lsa_SidType type),
580 void *private_data)
582 struct winbindd_domain *domain;
583 struct winbindd_request request;
585 domain = find_lookup_domain_from_sid(sid);
586 if (domain == NULL) {
587 DEBUG(5, ("Could not find domain for sid %s\n",
588 sid_string_static(sid)));
589 cont(private_data, False, NULL, NULL, SID_NAME_UNKNOWN);
590 return;
593 ZERO_STRUCT(request);
594 request.cmd = WINBINDD_LOOKUPSID;
595 fstrcpy(request.data.sid, sid_string_static(sid));
597 do_async_domain(mem_ctx, domain, &request, lookupsid_recv,
598 (void *)cont, private_data);
601 enum winbindd_result winbindd_dual_lookupsid(struct winbindd_domain *domain,
602 struct winbindd_cli_state *state)
604 enum lsa_SidType type;
605 DOM_SID sid;
606 fstring name;
607 fstring dom_name;
609 /* Ensure null termination */
610 state->request.data.sid[sizeof(state->request.data.sid)-1]='\0';
612 DEBUG(3, ("[%5lu]: lookupsid %s\n", (unsigned long)state->pid,
613 state->request.data.sid));
615 /* Lookup sid from PDC using lsa_lookup_sids() */
617 if (!string_to_sid(&sid, state->request.data.sid)) {
618 DEBUG(5, ("%s not a SID\n", state->request.data.sid));
619 return WINBINDD_ERROR;
622 /* Lookup the sid */
624 if (!winbindd_lookup_name_by_sid(state->mem_ctx, &sid, dom_name, name,
625 &type)) {
626 return WINBINDD_ERROR;
629 fstrcpy(state->response.data.name.dom_name, dom_name);
630 fstrcpy(state->response.data.name.name, name);
631 state->response.data.name.type = type;
633 return WINBINDD_OK;
636 static void lookupname_recv(TALLOC_CTX *mem_ctx, BOOL success,
637 struct winbindd_response *response,
638 void *c, void *private_data)
640 void (*cont)(void *priv, BOOL succ, const DOM_SID *sid,
641 enum lsa_SidType type) =
642 (void (*)(void *, BOOL, const DOM_SID *, enum lsa_SidType))c;
643 DOM_SID sid;
645 if (!success) {
646 DEBUG(5, ("Could not trigger lookup_name\n"));
647 cont(private_data, False, NULL, SID_NAME_UNKNOWN);
648 return;
651 if (response->result != WINBINDD_OK) {
652 DEBUG(5, ("lookup_name returned an error\n"));
653 cont(private_data, False, NULL, SID_NAME_UNKNOWN);
654 return;
657 if (!string_to_sid(&sid, response->data.sid.sid)) {
658 DEBUG(0, ("Could not convert string %s to sid\n",
659 response->data.sid.sid));
660 cont(private_data, False, NULL, SID_NAME_UNKNOWN);
661 return;
664 cont(private_data, True, &sid,
665 (enum lsa_SidType)response->data.sid.type);
668 void winbindd_lookupname_async(TALLOC_CTX *mem_ctx, const char *dom_name,
669 const char *name,
670 void (*cont)(void *private_data, BOOL success,
671 const DOM_SID *sid,
672 enum lsa_SidType type),
673 void *private_data)
675 struct winbindd_request request;
676 struct winbindd_domain *domain;
678 domain = find_lookup_domain_from_name(dom_name);
680 if (domain == NULL) {
681 DEBUG(5, ("Could not find domain for name %s\n", dom_name));
682 cont(private_data, False, NULL, SID_NAME_UNKNOWN);
683 return;
686 ZERO_STRUCT(request);
687 request.cmd = WINBINDD_LOOKUPNAME;
688 fstrcpy(request.data.name.dom_name, dom_name);
689 fstrcpy(request.data.name.name, name);
691 do_async_domain(mem_ctx, domain, &request, lookupname_recv,
692 (void *)cont, private_data);
695 enum winbindd_result winbindd_dual_lookupname(struct winbindd_domain *domain,
696 struct winbindd_cli_state *state)
698 enum lsa_SidType type;
699 char *name_domain, *name_user;
700 DOM_SID sid;
701 char *p;
703 /* Ensure null termination */
704 state->request.data.sid[sizeof(state->request.data.name.dom_name)-1]='\0';
706 /* Ensure null termination */
707 state->request.data.sid[sizeof(state->request.data.name.name)-1]='\0';
709 /* cope with the name being a fully qualified name */
710 p = strstr(state->request.data.name.name, lp_winbind_separator());
711 if (p) {
712 *p = 0;
713 name_domain = state->request.data.name.name;
714 name_user = p+1;
715 } else {
716 name_domain = state->request.data.name.dom_name;
717 name_user = state->request.data.name.name;
720 DEBUG(3, ("[%5lu]: lookupname %s%s%s\n", (unsigned long)state->pid,
721 name_domain, lp_winbind_separator(), name_user));
723 /* Lookup name from PDC using lsa_lookup_names() */
724 if (!winbindd_lookup_sid_by_name(state->mem_ctx, domain, name_domain,
725 name_user, &sid, &type)) {
726 return WINBINDD_ERROR;
729 sid_to_string(state->response.data.sid.sid, &sid);
730 state->response.data.sid.type = type;
732 return WINBINDD_OK;
735 BOOL print_sidlist(TALLOC_CTX *mem_ctx, const DOM_SID *sids,
736 size_t num_sids, char **result, ssize_t *len)
738 size_t i;
739 size_t buflen = 0;
741 *len = 0;
742 *result = NULL;
743 for (i=0; i<num_sids; i++) {
744 sprintf_append(mem_ctx, result, len, &buflen,
745 "%s\n", sid_string_static(&sids[i]));
748 if ((num_sids != 0) && (*result == NULL)) {
749 return False;
752 return True;
755 static BOOL parse_sidlist(TALLOC_CTX *mem_ctx, char *sidstr,
756 DOM_SID **sids, size_t *num_sids)
758 char *p, *q;
760 p = sidstr;
761 if (p == NULL)
762 return False;
764 while (p[0] != '\0') {
765 DOM_SID sid;
766 q = strchr(p, '\n');
767 if (q == NULL) {
768 DEBUG(0, ("Got invalid sidstr: %s\n", p));
769 return False;
771 *q = '\0';
772 q += 1;
773 if (!string_to_sid(&sid, p)) {
774 DEBUG(0, ("Could not parse sid %s\n", p));
775 return False;
777 if (!add_sid_to_array(mem_ctx, &sid, sids, num_sids)) {
778 return False;
780 p = q;
782 return True;
785 static BOOL parse_ridlist(TALLOC_CTX *mem_ctx, char *ridstr,
786 uint32 **rids, size_t *num_rids)
788 char *p;
790 p = ridstr;
791 if (p == NULL)
792 return False;
794 while (p[0] != '\0') {
795 uint32 rid;
796 char *q;
797 rid = strtoul(p, &q, 10);
798 if (*q != '\n') {
799 DEBUG(0, ("Got invalid ridstr: %s\n", p));
800 return False;
802 p = q+1;
803 ADD_TO_ARRAY(mem_ctx, uint32, rid, rids, num_rids);
805 return True;
808 enum winbindd_result winbindd_dual_lookuprids(struct winbindd_domain *domain,
809 struct winbindd_cli_state *state)
811 uint32 *rids = NULL;
812 size_t i, buflen, num_rids = 0;
813 ssize_t len;
814 DOM_SID domain_sid;
815 char *domain_name;
816 char **names;
817 enum lsa_SidType *types;
818 NTSTATUS status;
819 char *result;
821 DEBUG(10, ("Looking up RIDs for domain %s (%s)\n",
822 state->request.domain_name,
823 state->request.data.sid));
825 if (!parse_ridlist(state->mem_ctx, state->request.extra_data.data,
826 &rids, &num_rids)) {
827 DEBUG(5, ("Could not parse ridlist\n"));
828 return WINBINDD_ERROR;
831 if (!string_to_sid(&domain_sid, state->request.data.sid)) {
832 DEBUG(5, ("Could not parse domain sid %s\n",
833 state->request.data.sid));
834 return WINBINDD_ERROR;
837 status = domain->methods->rids_to_names(domain, state->mem_ctx,
838 &domain_sid, rids, num_rids,
839 &domain_name,
840 &names, &types);
842 if (!NT_STATUS_IS_OK(status) &&
843 !NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
844 return WINBINDD_ERROR;
847 len = 0;
848 buflen = 0;
849 result = NULL;
851 for (i=0; i<num_rids; i++) {
852 sprintf_append(state->mem_ctx, &result, &len, &buflen,
853 "%d %s\n", types[i], names[i]);
856 fstrcpy(state->response.data.domain_name, domain_name);
858 if (result != NULL) {
859 state->response.extra_data.data = SMB_STRDUP(result);
860 state->response.length += len+1;
863 return WINBINDD_OK;
866 static void getsidaliases_recv(TALLOC_CTX *mem_ctx, BOOL success,
867 struct winbindd_response *response,
868 void *c, void *private_data)
870 void (*cont)(void *priv, BOOL succ,
871 DOM_SID *aliases, size_t num_aliases) =
872 (void (*)(void *, BOOL, DOM_SID *, size_t))c;
873 char *aliases_str;
874 DOM_SID *sids = NULL;
875 size_t num_sids = 0;
877 if (!success) {
878 DEBUG(5, ("Could not trigger getsidaliases\n"));
879 cont(private_data, success, NULL, 0);
880 return;
883 if (response->result != WINBINDD_OK) {
884 DEBUG(5, ("getsidaliases returned an error\n"));
885 cont(private_data, False, NULL, 0);
886 return;
889 aliases_str = (char *)response->extra_data.data;
891 if (aliases_str == NULL) {
892 DEBUG(10, ("getsidaliases return 0 SIDs\n"));
893 cont(private_data, True, NULL, 0);
894 return;
897 if (!parse_sidlist(mem_ctx, aliases_str, &sids, &num_sids)) {
898 DEBUG(0, ("Could not parse sids\n"));
899 cont(private_data, False, NULL, 0);
900 return;
903 SAFE_FREE(response->extra_data.data);
905 cont(private_data, True, sids, num_sids);
908 void winbindd_getsidaliases_async(struct winbindd_domain *domain,
909 TALLOC_CTX *mem_ctx,
910 const DOM_SID *sids, size_t num_sids,
911 void (*cont)(void *private_data,
912 BOOL success,
913 const DOM_SID *aliases,
914 size_t num_aliases),
915 void *private_data)
917 struct winbindd_request request;
918 char *sidstr = NULL;
919 ssize_t len;
921 if (num_sids == 0) {
922 cont(private_data, True, NULL, 0);
923 return;
926 if (!print_sidlist(mem_ctx, sids, num_sids, &sidstr, &len)) {
927 cont(private_data, False, NULL, 0);
928 return;
931 ZERO_STRUCT(request);
932 request.cmd = WINBINDD_DUAL_GETSIDALIASES;
933 request.extra_len = len;
934 request.extra_data.data = sidstr;
936 do_async_domain(mem_ctx, domain, &request, getsidaliases_recv,
937 (void *)cont, private_data);
940 enum winbindd_result winbindd_dual_getsidaliases(struct winbindd_domain *domain,
941 struct winbindd_cli_state *state)
943 DOM_SID *sids = NULL;
944 size_t num_sids = 0;
945 char *sidstr;
946 ssize_t len;
947 size_t i;
948 uint32 num_aliases;
949 uint32 *alias_rids;
950 NTSTATUS result;
952 DEBUG(3, ("[%5lu]: getsidaliases\n", (unsigned long)state->pid));
954 sidstr = state->request.extra_data.data;
955 if (sidstr == NULL)
956 sidstr = talloc_strdup(state->mem_ctx, "\n"); /* No SID */
958 DEBUG(10, ("Sidlist: %s\n", sidstr));
960 if (!parse_sidlist(state->mem_ctx, sidstr, &sids, &num_sids)) {
961 DEBUG(0, ("Could not parse SID list: %s\n", sidstr));
962 return WINBINDD_ERROR;
965 num_aliases = 0;
966 alias_rids = NULL;
968 result = domain->methods->lookup_useraliases(domain,
969 state->mem_ctx,
970 num_sids, sids,
971 &num_aliases,
972 &alias_rids);
974 if (!NT_STATUS_IS_OK(result)) {
975 DEBUG(3, ("Could not lookup_useraliases: %s\n",
976 nt_errstr(result)));
977 return WINBINDD_ERROR;
980 num_sids = 0;
981 sids = NULL;
983 DEBUG(10, ("Got %d aliases\n", num_aliases));
985 for (i=0; i<num_aliases; i++) {
986 DOM_SID sid;
987 DEBUGADD(10, (" rid %d\n", alias_rids[i]));
988 sid_copy(&sid, &domain->sid);
989 sid_append_rid(&sid, alias_rids[i]);
990 if (!add_sid_to_array(state->mem_ctx, &sid, &sids, &num_sids)) {
991 return WINBINDD_ERROR;
996 if (!print_sidlist(NULL, sids, num_sids, &sidstr, &len)) {
997 DEBUG(0, ("Could not print_sidlist\n"));
998 state->response.extra_data.data = NULL;
999 return WINBINDD_ERROR;
1002 state->response.extra_data.data = sidstr;
1004 if (state->response.extra_data.data != NULL) {
1005 DEBUG(10, ("aliases_list: %s\n",
1006 (char *)state->response.extra_data.data));
1007 state->response.length += len+1;
1010 return WINBINDD_OK;
1013 struct gettoken_state {
1014 TALLOC_CTX *mem_ctx;
1015 DOM_SID user_sid;
1016 struct winbindd_domain *alias_domain;
1017 struct winbindd_domain *local_alias_domain;
1018 struct winbindd_domain *builtin_domain;
1019 DOM_SID *sids;
1020 size_t num_sids;
1021 void (*cont)(void *private_data, BOOL success, DOM_SID *sids, size_t num_sids);
1022 void *private_data;
1025 static void gettoken_recvdomgroups(TALLOC_CTX *mem_ctx, BOOL success,
1026 struct winbindd_response *response,
1027 void *c, void *private_data);
1028 static void gettoken_recvaliases(void *private_data, BOOL success,
1029 const DOM_SID *aliases,
1030 size_t num_aliases);
1033 void winbindd_gettoken_async(TALLOC_CTX *mem_ctx, const DOM_SID *user_sid,
1034 void (*cont)(void *private_data, BOOL success,
1035 DOM_SID *sids, size_t num_sids),
1036 void *private_data)
1038 struct winbindd_domain *domain;
1039 struct winbindd_request request;
1040 struct gettoken_state *state;
1042 state = TALLOC_ZERO_P(mem_ctx, struct gettoken_state);
1043 if (state == NULL) {
1044 DEBUG(0, ("talloc failed\n"));
1045 cont(private_data, False, NULL, 0);
1046 return;
1049 state->mem_ctx = mem_ctx;
1050 sid_copy(&state->user_sid, user_sid);
1051 state->alias_domain = find_our_domain();
1052 state->local_alias_domain = find_domain_from_name( get_global_sam_name() );
1053 state->builtin_domain = find_builtin_domain();
1054 state->cont = cont;
1055 state->private_data = private_data;
1057 domain = find_domain_from_sid_noinit(user_sid);
1058 if (domain == NULL) {
1059 DEBUG(5, ("Could not find domain from SID %s\n",
1060 sid_string_static(user_sid)));
1061 cont(private_data, False, NULL, 0);
1062 return;
1065 ZERO_STRUCT(request);
1066 request.cmd = WINBINDD_GETUSERDOMGROUPS;
1067 fstrcpy(request.data.sid, sid_string_static(user_sid));
1069 do_async_domain(mem_ctx, domain, &request, gettoken_recvdomgroups,
1070 NULL, state);
1073 static void gettoken_recvdomgroups(TALLOC_CTX *mem_ctx, BOOL success,
1074 struct winbindd_response *response,
1075 void *c, void *private_data)
1077 struct gettoken_state *state =
1078 talloc_get_type_abort(private_data, struct gettoken_state);
1079 char *sids_str;
1081 if (!success) {
1082 DEBUG(10, ("Could not get domain groups\n"));
1083 state->cont(state->private_data, False, NULL, 0);
1084 return;
1087 sids_str = (char *)response->extra_data.data;
1089 if (sids_str == NULL) {
1090 /* This could be normal if we are dealing with a
1091 local user and local groups */
1093 if ( !sid_check_is_in_our_domain( &state->user_sid ) ) {
1094 DEBUG(10, ("Received no domain groups\n"));
1095 state->cont(state->private_data, True, NULL, 0);
1096 return;
1100 state->sids = NULL;
1101 state->num_sids = 0;
1103 if (!add_sid_to_array(mem_ctx, &state->user_sid, &state->sids,
1104 &state->num_sids)) {
1105 DEBUG(0, ("Out of memory\n"));
1106 state->cont(state->private_data, False, NULL, 0);
1107 return;
1110 if (sids_str && !parse_sidlist(mem_ctx, sids_str, &state->sids,
1111 &state->num_sids)) {
1112 DEBUG(0, ("Could not parse sids\n"));
1113 state->cont(state->private_data, False, NULL, 0);
1114 return;
1117 SAFE_FREE(response->extra_data.data);
1119 if (state->alias_domain == NULL) {
1120 DEBUG(10, ("Don't expand domain local groups\n"));
1121 state->cont(state->private_data, True, state->sids,
1122 state->num_sids);
1123 return;
1126 winbindd_getsidaliases_async(state->alias_domain, mem_ctx,
1127 state->sids, state->num_sids,
1128 gettoken_recvaliases, state);
1131 static void gettoken_recvaliases(void *private_data, BOOL success,
1132 const DOM_SID *aliases,
1133 size_t num_aliases)
1135 struct gettoken_state *state = (struct gettoken_state *)private_data;
1136 size_t i;
1138 if (!success) {
1139 DEBUG(10, ("Could not receive domain local groups\n"));
1140 state->cont(state->private_data, False, NULL, 0);
1141 return;
1144 for (i=0; i<num_aliases; i++) {
1145 if (!add_sid_to_array(state->mem_ctx, &aliases[i],
1146 &state->sids, &state->num_sids)) {
1147 DEBUG(0, ("Out of memory\n"));
1148 state->cont(state->private_data, False, NULL, 0);
1149 return;
1153 if (state->local_alias_domain != NULL) {
1154 struct winbindd_domain *local_domain = state->local_alias_domain;
1155 DEBUG(10, ("Expanding our own local groups\n"));
1156 state->local_alias_domain = NULL;
1157 winbindd_getsidaliases_async(local_domain, state->mem_ctx,
1158 state->sids, state->num_sids,
1159 gettoken_recvaliases, state);
1160 return;
1163 if (state->builtin_domain != NULL) {
1164 struct winbindd_domain *builtin_domain = state->builtin_domain;
1165 DEBUG(10, ("Expanding our own BUILTIN groups\n"));
1166 state->builtin_domain = NULL;
1167 winbindd_getsidaliases_async(builtin_domain, state->mem_ctx,
1168 state->sids, state->num_sids,
1169 gettoken_recvaliases, state);
1170 return;
1173 state->cont(state->private_data, True, state->sids, state->num_sids);
1176 struct sid2uid_state {
1177 TALLOC_CTX *mem_ctx;
1178 DOM_SID sid;
1179 char *username;
1180 uid_t uid;
1181 void (*cont)(void *private_data, BOOL success, uid_t uid);
1182 void *private_data;
1185 static void sid2uid_lookup_sid_recv(void *private_data, BOOL success,
1186 const char *dom_name, const char *name,
1187 enum lsa_SidType type);
1188 static void sid2uid_noalloc_recv(void *private_data, BOOL success, uid_t uid);
1189 static void sid2uid_alloc_recv(void *private_data, BOOL success, uid_t uid);
1190 static void sid2uid_name2uid_recv(void *private_data, BOOL success, uid_t uid);
1191 static void sid2uid_set_mapping_recv(void *private_data, BOOL success);
1193 void winbindd_sid2uid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
1194 void (*cont)(void *private_data, BOOL success,
1195 uid_t uid),
1196 void *private_data)
1198 struct sid2uid_state *state;
1199 NTSTATUS result;
1200 uid_t uid;
1202 if (idmap_proxyonly()) {
1203 DEBUG(10, ("idmap proxy only\n"));
1204 cont(private_data, False, 0);
1205 return;
1208 /* Query only the local tdb, everything else might possibly block */
1210 result = idmap_sid_to_uid(sid, &uid, IDMAP_FLAG_QUERY_ONLY|IDMAP_FLAG_CACHE_ONLY);
1212 if (NT_STATUS_IS_OK(result)) {
1213 cont(private_data, True, uid);
1214 return;
1217 state = TALLOC_ZERO_P(mem_ctx, struct sid2uid_state);
1218 if (state == NULL) {
1219 DEBUG(0, ("talloc failed\n"));
1220 cont(private_data, False, 0);
1221 return;
1224 state->mem_ctx = mem_ctx;
1225 state->sid = *sid;
1226 state->cont = cont;
1227 state->private_data = private_data;
1229 /* Let's see if it's really a user before allocating a uid */
1231 winbindd_lookupsid_async(mem_ctx, sid, sid2uid_lookup_sid_recv, state);
1234 static void sid2uid_lookup_sid_recv(void *private_data, BOOL success,
1235 const char *dom_name, const char *name,
1236 enum lsa_SidType type)
1238 struct sid2uid_state *state =
1239 talloc_get_type_abort(private_data, struct sid2uid_state);
1241 if (!success) {
1242 DEBUG(5, ("Could not trigger lookup_sid\n"));
1243 state->cont(state->private_data, False, 0);
1244 return;
1247 if ((type != SID_NAME_USER) && (type != SID_NAME_COMPUTER)) {
1248 DEBUG(5, ("SID is not a user\n"));
1249 state->cont(state->private_data, False, 0);
1250 return;
1253 state->username = talloc_strdup(state->mem_ctx, name);
1255 /* Ask the possibly blocking remote IDMAP */
1257 idmap_sid2uid_async(state->mem_ctx, &state->sid, False,
1258 sid2uid_noalloc_recv, state);
1261 static void sid2uid_noalloc_recv(void *private_data, BOOL success, uid_t uid)
1263 struct sid2uid_state *state =
1264 talloc_get_type_abort(private_data, struct sid2uid_state);
1266 if (success) {
1267 DEBUG(10, ("found uid for sid %s in remote backend\n",
1268 sid_string_static(&state->sid)));
1269 state->cont(state->private_data, True, uid);
1270 return;
1273 if (lp_winbind_trusted_domains_only() &&
1274 (sid_compare_domain(&state->sid, &find_our_domain()->sid) == 0)) {
1275 DEBUG(10, ("Trying to go via nss\n"));
1276 winbindd_name2uid_async(state->mem_ctx, state->username,
1277 sid2uid_name2uid_recv, state);
1278 return;
1281 /* To be done: Here we're going to try the unixinfo pipe */
1283 /* Now allocate a uid */
1285 idmap_sid2uid_async(state->mem_ctx, &state->sid, True,
1286 sid2uid_alloc_recv, state);
1289 static void sid2uid_alloc_recv(void *private_data, BOOL success, uid_t uid)
1291 struct sid2uid_state *state =
1292 talloc_get_type_abort(private_data, struct sid2uid_state);
1294 if (!success) {
1295 DEBUG(5, ("Could not allocate uid\n"));
1296 state->cont(state->private_data, False, 0);
1297 return;
1300 state->cont(state->private_data, True, uid);
1303 static void sid2uid_name2uid_recv(void *private_data, BOOL success, uid_t uid)
1305 struct sid2uid_state *state =
1306 talloc_get_type_abort(private_data, struct sid2uid_state);
1307 unid_t id;
1309 if (!success) {
1310 DEBUG(5, ("Could not find uid for name %s\n",
1311 state->username));
1312 state->cont(state->private_data, False, 0);
1313 return;
1316 state->uid = uid;
1318 id.uid = uid;
1319 idmap_set_mapping_async(state->mem_ctx, &state->sid, id, ID_USERID,
1320 sid2uid_set_mapping_recv, state);
1323 static void sid2uid_set_mapping_recv(void *private_data, BOOL success)
1325 struct sid2uid_state *state =
1326 talloc_get_type_abort(private_data, struct sid2uid_state);
1328 if (!success) {
1329 DEBUG(5, ("Could not set ID mapping for sid %s\n",
1330 sid_string_static(&state->sid)));
1331 state->cont(state->private_data, False, 0);
1332 return;
1335 state->cont(state->private_data, True, state->uid);
1338 struct sid2gid_state {
1339 TALLOC_CTX *mem_ctx;
1340 DOM_SID sid;
1341 char *groupname;
1342 gid_t gid;
1343 void (*cont)(void *private_data, BOOL success, gid_t gid);
1344 void *private_data;
1347 static void sid2gid_lookup_sid_recv(void *private_data, BOOL success,
1348 const char *dom_name, const char *name,
1349 enum lsa_SidType type);
1350 static void sid2gid_noalloc_recv(void *private_data, BOOL success, gid_t gid);
1351 static void sid2gid_alloc_recv(void *private_data, BOOL success, gid_t gid);
1352 static void sid2gid_name2gid_recv(void *private_data, BOOL success, gid_t gid);
1353 static void sid2gid_set_mapping_recv(void *private_data, BOOL success);
1355 void winbindd_sid2gid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
1356 void (*cont)(void *private_data, BOOL success,
1357 gid_t gid),
1358 void *private_data)
1360 struct sid2gid_state *state;
1361 NTSTATUS result;
1362 gid_t gid;
1364 if (idmap_proxyonly()) {
1365 DEBUG(10, ("idmap proxy only\n"));
1366 cont(private_data, False, 0);
1367 return;
1370 /* Query only the local tdb, everything else might possibly block */
1372 result = idmap_sid_to_gid(sid, &gid, IDMAP_FLAG_QUERY_ONLY|IDMAP_FLAG_CACHE_ONLY);
1374 if (NT_STATUS_IS_OK(result)) {
1375 cont(private_data, True, gid);
1376 return;
1379 state = TALLOC_ZERO_P(mem_ctx, struct sid2gid_state);
1380 if (state == NULL) {
1381 DEBUG(0, ("talloc failed\n"));
1382 cont(private_data, False, 0);
1383 return;
1386 state->mem_ctx = mem_ctx;
1387 state->sid = *sid;
1388 state->cont = cont;
1389 state->private_data = private_data;
1391 /* Let's see if it's really a user before allocating a gid */
1393 winbindd_lookupsid_async(mem_ctx, sid, sid2gid_lookup_sid_recv, state);
1396 static void sid2gid_lookup_sid_recv(void *private_data, BOOL success,
1397 const char *dom_name, const char *name,
1398 enum lsa_SidType type)
1400 struct sid2gid_state *state =
1401 talloc_get_type_abort(private_data, struct sid2gid_state);
1403 if (!success) {
1404 DEBUG(5, ("Could not trigger lookup_sid\n"));
1405 state->cont(state->private_data, False, 0);
1406 return;
1409 if (((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
1410 (type != SID_NAME_WKN_GRP))) {
1411 DEBUG(5, ("SID is not a group\n"));
1412 state->cont(state->private_data, False, 0);
1413 return;
1416 state->groupname = talloc_strdup(state->mem_ctx, name);
1418 /* Ask the possibly blocking remote IDMAP and allocate */
1420 idmap_sid2gid_async(state->mem_ctx, &state->sid, False,
1421 sid2gid_noalloc_recv, state);
1424 static void sid2gid_noalloc_recv(void *private_data, BOOL success, gid_t gid)
1426 struct sid2gid_state *state =
1427 talloc_get_type_abort(private_data, struct sid2gid_state);
1429 if (success) {
1430 DEBUG(10, ("found gid for sid %s in remote backend\n",
1431 sid_string_static(&state->sid)));
1432 state->cont(state->private_data, True, gid);
1433 return;
1436 if (lp_winbind_trusted_domains_only() &&
1437 (sid_compare_domain(&state->sid, &find_our_domain()->sid) == 0)) {
1438 DEBUG(10, ("Trying to go via nss\n"));
1439 winbindd_name2gid_async(state->mem_ctx, state->groupname,
1440 sid2gid_name2gid_recv, state);
1441 return;
1444 /* To be done: Here we're going to try the unixinfo pipe */
1446 /* Now allocate a gid */
1448 idmap_sid2gid_async(state->mem_ctx, &state->sid, True,
1449 sid2gid_alloc_recv, state);
1452 static void sid2gid_alloc_recv(void *private_data, BOOL success, gid_t gid)
1454 struct sid2gid_state *state =
1455 talloc_get_type_abort(private_data, struct sid2gid_state);
1457 if (!success) {
1458 DEBUG(5, ("Could not allocate gid\n"));
1459 state->cont(state->private_data, False, 0);
1460 return;
1463 state->cont(state->private_data, True, gid);
1466 static void sid2gid_name2gid_recv(void *private_data, BOOL success, gid_t gid)
1468 struct sid2gid_state *state =
1469 talloc_get_type_abort(private_data, struct sid2gid_state);
1470 unid_t id;
1472 if (!success) {
1473 DEBUG(5, ("Could not find gid for name %s\n",
1474 state->groupname));
1475 state->cont(state->private_data, False, 0);
1476 return;
1479 state->gid = gid;
1481 id.gid = gid;
1482 idmap_set_mapping_async(state->mem_ctx, &state->sid, id, ID_GROUPID,
1483 sid2gid_set_mapping_recv, state);
1486 static void sid2gid_set_mapping_recv(void *private_data, BOOL success)
1488 struct sid2gid_state *state =
1489 talloc_get_type_abort(private_data, struct sid2gid_state);
1491 if (!success) {
1492 DEBUG(5, ("Could not set ID mapping for sid %s\n",
1493 sid_string_static(&state->sid)));
1494 state->cont(state->private_data, False, 0);
1495 return;
1498 state->cont(state->private_data, True, state->gid);
1501 static void query_user_recv(TALLOC_CTX *mem_ctx, BOOL success,
1502 struct winbindd_response *response,
1503 void *c, void *private_data)
1505 void (*cont)(void *priv, BOOL succ, const char *acct_name,
1506 const char *full_name, const char *homedir,
1507 const char *shell, uint32 group_rid) =
1508 (void (*)(void *, BOOL, const char *, const char *,
1509 const char *, const char *, uint32))c;
1511 if (!success) {
1512 DEBUG(5, ("Could not trigger query_user\n"));
1513 cont(private_data, False, NULL, NULL, NULL, NULL, -1);
1514 return;
1517 cont(private_data, True, response->data.user_info.acct_name,
1518 response->data.user_info.full_name,
1519 response->data.user_info.homedir,
1520 response->data.user_info.shell,
1521 response->data.user_info.group_rid);
1524 void query_user_async(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1525 const DOM_SID *sid,
1526 void (*cont)(void *private_data, BOOL success,
1527 const char *acct_name,
1528 const char *full_name,
1529 const char *homedir,
1530 const char *shell,
1531 uint32 group_rid),
1532 void *private_data)
1534 struct winbindd_request request;
1535 ZERO_STRUCT(request);
1536 request.cmd = WINBINDD_DUAL_USERINFO;
1537 sid_to_string(request.data.sid, sid);
1538 do_async_domain(mem_ctx, domain, &request, query_user_recv,
1539 (void *)cont, private_data);
1542 /* The following uid2sid/gid2sid functions has been contributed by
1543 * Keith Reynolds <Keith.Reynolds@centrify.com> */
1545 static void winbindd_uid2sid_recv(TALLOC_CTX *mem_ctx, BOOL success,
1546 struct winbindd_response *response,
1547 void *c, void *private_data)
1549 void (*cont)(void *priv, BOOL succ, const char *sid) =
1550 (void (*)(void *, BOOL, const char *))c;
1552 if (!success) {
1553 DEBUG(5, ("Could not trigger uid2sid\n"));
1554 cont(private_data, False, NULL);
1555 return;
1558 if (response->result != WINBINDD_OK) {
1559 DEBUG(5, ("uid2sid returned an error\n"));
1560 cont(private_data, False, NULL);
1561 return;
1564 cont(private_data, True, response->data.sid.sid);
1567 void winbindd_uid2sid_async(TALLOC_CTX *mem_ctx, uid_t uid,
1568 void (*cont)(void *private_data, BOOL success, const char *sid),
1569 void *private_data)
1571 struct winbindd_request request;
1573 ZERO_STRUCT(request);
1574 request.cmd = WINBINDD_DUAL_UID2SID;
1575 request.data.uid = uid;
1576 do_async(mem_ctx, idmap_child(), &request, winbindd_uid2sid_recv,
1577 (void *)cont, private_data);
1580 enum winbindd_result winbindd_dual_uid2sid(struct winbindd_domain *domain,
1581 struct winbindd_cli_state *state)
1583 DOM_SID sid;
1584 NTSTATUS result;
1586 DEBUG(3,("[%5lu]: uid to sid %lu\n",
1587 (unsigned long)state->pid,
1588 (unsigned long) state->request.data.uid));
1590 /* Find sid for this uid and return it, possibly ask the slow remote idmap */
1591 result = idmap_uid_to_sid(&sid, state->request.data.uid, IDMAP_FLAG_NONE);
1593 if (NT_STATUS_IS_OK(result)) {
1594 sid_to_string(state->response.data.sid.sid, &sid);
1595 state->response.data.sid.type = SID_NAME_USER;
1596 return WINBINDD_OK;
1599 return WINBINDD_ERROR;
1602 static void winbindd_gid2sid_recv(TALLOC_CTX *mem_ctx, BOOL success,
1603 struct winbindd_response *response,
1604 void *c, void *private_data)
1606 void (*cont)(void *priv, BOOL succ, const char *sid) =
1607 (void (*)(void *, BOOL, const char *))c;
1609 if (!success) {
1610 DEBUG(5, ("Could not trigger gid2sid\n"));
1611 cont(private_data, False, NULL);
1612 return;
1615 if (response->result != WINBINDD_OK) {
1616 DEBUG(5, ("gid2sid returned an error\n"));
1617 cont(private_data, False, NULL);
1618 return;
1621 cont(private_data, True, response->data.sid.sid);
1624 void winbindd_gid2sid_async(TALLOC_CTX *mem_ctx, gid_t gid,
1625 void (*cont)(void *private_data, BOOL success, const char *sid),
1626 void *private_data)
1628 struct winbindd_request request;
1630 ZERO_STRUCT(request);
1631 request.cmd = WINBINDD_DUAL_GID2SID;
1632 request.data.gid = gid;
1633 do_async(mem_ctx, idmap_child(), &request, winbindd_gid2sid_recv,
1634 (void *)cont, private_data);
1637 enum winbindd_result winbindd_dual_gid2sid(struct winbindd_domain *domain,
1638 struct winbindd_cli_state *state)
1640 DOM_SID sid;
1641 NTSTATUS result;
1643 DEBUG(3,("[%5lu]: gid %lu to sid\n",
1644 (unsigned long)state->pid,
1645 (unsigned long) state->request.data.gid));
1647 /* Find sid for this gid and return it, possibly ask the slow remote idmap */
1648 result = idmap_gid_to_sid(&sid, state->request.data.gid, IDMAP_FLAG_NONE);
1650 if (NT_STATUS_IS_OK(result)) {
1651 sid_to_string(state->response.data.sid.sid, &sid);
1652 DEBUG(10, ("[%5lu]: retrieved sid: %s\n",
1653 (unsigned long)state->pid,
1654 state->response.data.sid.sid));
1655 state->response.data.sid.type = SID_NAME_DOM_GRP;
1656 return WINBINDD_OK;
1659 return WINBINDD_ERROR;