r17837: Split out the storing of memory cached credentials
[Samba/nascimento.git] / source3 / nsswitch / winbindd_async.c
blob696f3501efaa94b1d44730b461a2c7694462c4c7
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_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_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(&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),
183 void *private_data)
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)
197 DOM_SID sid;
198 NTSTATUS result;
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
210 * idmap */
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;
226 if (!success) {
227 DEBUG(5, ("Could not trigger sid2uid\n"));
228 cont(private_data, False, 0);
229 return;
232 if (response->result != WINBINDD_OK) {
233 DEBUG(5, ("sid2uid returned an error\n"));
234 cont(private_data, False, 0);
235 return;
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,
247 const char *name),
248 void *private_data)
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)
261 struct passwd *pw;
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);
267 if (pw == NULL) {
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);
274 return WINBINDD_OK;
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;
284 if (!success) {
285 DEBUG(5, ("Could not trigger uid2name\n"));
286 cont(private_data, False, NULL);
287 return;
290 if (response->result != WINBINDD_OK) {
291 DEBUG(5, ("uid2name returned an error\n"));
292 cont(private_data, False, NULL);
293 return;
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,
305 uid_t uid),
306 void *private_data)
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)
319 struct passwd *pw;
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);
329 if (pw == NULL) {
330 return WINBINDD_ERROR;
333 state->response.data.uid = pw->pw_uid;
334 return WINBINDD_OK;
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;
344 if (!success) {
345 DEBUG(5, ("Could not trigger name2uid\n"));
346 cont(private_data, False, 0);
347 return;
350 if (response->result != WINBINDD_OK) {
351 DEBUG(5, ("name2uid returned an error\n"));
352 cont(private_data, False, 0);
353 return;
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),
365 void *private_data)
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)
383 DOM_SID sid;
384 NTSTATUS result;
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
396 * idmap */
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;
421 if (!success) {
422 DEBUG(5, ("Could not trigger sid2gid\n"));
423 cont(private_data, False, 0);
424 return;
427 if (response->result != WINBINDD_OK) {
428 DEBUG(5, ("sid2gid returned an error\n"));
429 cont(private_data, False, 0);
430 return;
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;
443 if (!success) {
444 DEBUG(5, ("Could not trigger gid2name\n"));
445 cont(private_data, False, NULL);
446 return;
449 if (response->result != WINBINDD_OK) {
450 DEBUG(5, ("gid2name returned an error\n"));
451 cont(private_data, False, NULL);
452 return;
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,
460 const char *name),
461 void *private_data)
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)
474 struct group *gr;
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);
480 if (gr == NULL)
481 return WINBINDD_ERROR;
483 fstrcpy(state->response.data.name.name, gr->gr_name);
484 return WINBINDD_OK;
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,
493 gid_t gid),
494 void *private_data)
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)
507 struct group *gr;
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);
517 if (gr == NULL) {
518 return WINBINDD_ERROR;
521 state->response.data.gid = gr->gr_gid;
522 return WINBINDD_OK;
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;
532 if (!success) {
533 DEBUG(5, ("Could not trigger name2gid\n"));
534 cont(private_data, False, 0);
535 return;
538 if (response->result != WINBINDD_OK) {
539 DEBUG(5, ("name2gid returned an error\n"));
540 cont(private_data, False, 0);
541 return;
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;
557 if (!success) {
558 DEBUG(5, ("Could not trigger lookupsid\n"));
559 cont(private_data, False, NULL, NULL, SID_NAME_UNKNOWN);
560 return;
563 if (response->result != WINBINDD_OK) {
564 DEBUG(5, ("lookupsid returned an error\n"));
565 cont(private_data, False, NULL, NULL, SID_NAME_UNKNOWN);
566 return;
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,
577 const char *name,
578 enum SID_NAME_USE type),
579 void *private_data)
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);
589 return;
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;
604 DOM_SID sid;
605 fstring name;
606 fstring dom_name;
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;
621 /* Lookup the sid */
623 if (!winbindd_lookup_name_by_sid(state->mem_ctx, &sid, dom_name, name,
624 &type)) {
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;
632 return WINBINDD_OK;
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;
642 DOM_SID sid;
644 if (!success) {
645 DEBUG(5, ("Could not trigger lookup_name\n"));
646 cont(private_data, False, NULL, SID_NAME_UNKNOWN);
647 return;
650 if (response->result != WINBINDD_OK) {
651 DEBUG(5, ("lookup_name returned an error\n"));
652 cont(private_data, False, NULL, SID_NAME_UNKNOWN);
653 return;
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);
660 return;
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,
668 const char *name,
669 void (*cont)(void *private_data, BOOL success,
670 const DOM_SID *sid,
671 enum SID_NAME_USE type),
672 void *private_data)
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);
682 return;
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;
699 DOM_SID sid;
700 char *p;
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());
710 if (p) {
711 *p = 0;
712 name_domain = state->request.data.name.name;
713 name_user = p+1;
714 } else {
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;
731 return WINBINDD_OK;
734 BOOL print_sidlist(TALLOC_CTX *mem_ctx, const DOM_SID *sids,
735 size_t num_sids, char **result, ssize_t *len)
737 size_t i;
738 size_t buflen = 0;
740 *len = 0;
741 *result = NULL;
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)) {
748 return False;
751 return True;
754 static BOOL parse_sidlist(TALLOC_CTX *mem_ctx, char *sidstr,
755 DOM_SID **sids, size_t *num_sids)
757 char *p, *q;
759 p = sidstr;
760 if (p == NULL)
761 return False;
763 while (p[0] != '\0') {
764 DOM_SID sid;
765 q = strchr(p, '\n');
766 if (q == NULL) {
767 DEBUG(0, ("Got invalid sidstr: %s\n", p));
768 return False;
770 *q = '\0';
771 q += 1;
772 if (!string_to_sid(&sid, p)) {
773 DEBUG(0, ("Could not parse sid %s\n", p));
774 return False;
776 add_sid_to_array(mem_ctx, &sid, sids, num_sids);
777 p = q;
779 return True;
782 static BOOL parse_ridlist(TALLOC_CTX *mem_ctx, char *ridstr,
783 uint32 **rids, size_t *num_rids)
785 char *p;
787 p = ridstr;
788 if (p == NULL)
789 return False;
791 while (p[0] != '\0') {
792 uint32 rid;
793 char *q;
794 rid = strtoul(p, &q, 10);
795 if (*q != '\n') {
796 DEBUG(0, ("Got invalid ridstr: %s\n", p));
797 return False;
799 p = q+1;
800 ADD_TO_ARRAY(mem_ctx, uint32, rid, rids, num_rids);
802 return True;
805 enum winbindd_result winbindd_dual_lookuprids(struct winbindd_domain *domain,
806 struct winbindd_cli_state *state)
808 uint32 *rids = NULL;
809 size_t i, buflen, num_rids = 0;
810 ssize_t len;
811 DOM_SID domain_sid;
812 char *domain_name;
813 char **names;
814 enum SID_NAME_USE *types;
815 NTSTATUS status;
816 char *result;
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,
823 &rids, &num_rids)) {
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,
836 &domain_name,
837 &names, &types);
839 if (!NT_STATUS_IS_OK(status) &&
840 !NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
841 return WINBINDD_ERROR;
844 len = 0;
845 buflen = 0;
846 result = NULL;
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;
860 return WINBINDD_OK;
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;
870 char *aliases_str;
871 DOM_SID *sids = NULL;
872 size_t num_sids = 0;
874 if (!success) {
875 DEBUG(5, ("Could not trigger getsidaliases\n"));
876 cont(private_data, success, NULL, 0);
877 return;
880 if (response->result != WINBINDD_OK) {
881 DEBUG(5, ("getsidaliases returned an error\n"));
882 cont(private_data, False, NULL, 0);
883 return;
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);
891 return;
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);
897 return;
900 SAFE_FREE(response->extra_data.data);
902 cont(private_data, True, sids, num_sids);
905 void winbindd_getsidaliases_async(struct winbindd_domain *domain,
906 TALLOC_CTX *mem_ctx,
907 const DOM_SID *sids, size_t num_sids,
908 void (*cont)(void *private_data,
909 BOOL success,
910 const DOM_SID *aliases,
911 size_t num_aliases),
912 void *private_data)
914 struct winbindd_request request;
915 char *sidstr = NULL;
916 ssize_t len;
918 if (num_sids == 0) {
919 cont(private_data, True, NULL, 0);
920 return;
923 if (!print_sidlist(mem_ctx, sids, num_sids, &sidstr, &len)) {
924 cont(private_data, False, NULL, 0);
925 return;
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;
941 size_t num_sids = 0;
942 char *sidstr;
943 ssize_t len;
944 size_t i;
945 uint32 num_aliases;
946 uint32 *alias_rids;
947 NTSTATUS result;
949 DEBUG(3, ("[%5lu]: getsidaliases\n", (unsigned long)state->pid));
951 sidstr = state->request.extra_data.data;
952 if (sidstr == NULL)
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;
962 num_aliases = 0;
963 alias_rids = NULL;
965 result = domain->methods->lookup_useraliases(domain,
966 state->mem_ctx,
967 num_sids, sids,
968 &num_aliases,
969 &alias_rids);
971 if (!NT_STATUS_IS_OK(result)) {
972 DEBUG(3, ("Could not lookup_useraliases: %s\n",
973 nt_errstr(result)));
974 return WINBINDD_ERROR;
977 num_sids = 0;
978 sids = NULL;
980 DEBUG(10, ("Got %d aliases\n", num_aliases));
982 for (i=0; i<num_aliases; i++) {
983 DOM_SID sid;
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;
1005 return WINBINDD_OK;
1008 struct gettoken_state {
1009 TALLOC_CTX *mem_ctx;
1010 DOM_SID user_sid;
1011 struct winbindd_domain *alias_domain;
1012 struct winbindd_domain *local_alias_domain;
1013 struct winbindd_domain *builtin_domain;
1014 DOM_SID *sids;
1015 size_t num_sids;
1016 void (*cont)(void *private_data, BOOL success, DOM_SID *sids, size_t num_sids);
1017 void *private_data;
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),
1031 void *private_data)
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);
1041 return;
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();
1049 state->cont = cont;
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);
1057 return;
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,
1065 NULL, state);
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);
1074 char *sids_str;
1076 if (!success) {
1077 DEBUG(10, ("Could not get domain groups\n"));
1078 state->cont(state->private_data, False, NULL, 0);
1079 return;
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);
1091 return;
1095 state->sids = NULL;
1096 state->num_sids = 0;
1098 add_sid_to_array(mem_ctx, &state->user_sid, &state->sids,
1099 &state->num_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);
1105 return;
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,
1113 state->num_sids);
1114 return;
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,
1124 size_t num_aliases)
1126 struct gettoken_state *state = (struct gettoken_state *)private_data;
1127 size_t i;
1129 if (!success) {
1130 DEBUG(10, ("Could not receive domain local groups\n"));
1131 state->cont(state->private_data, False, NULL, 0);
1132 return;
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);
1146 return;
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);
1156 return;
1159 state->cont(state->private_data, True, state->sids, state->num_sids);
1162 struct sid2uid_state {
1163 TALLOC_CTX *mem_ctx;
1164 DOM_SID sid;
1165 char *username;
1166 uid_t uid;
1167 void (*cont)(void *private_data, BOOL success, uid_t uid);
1168 void *private_data;
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,
1181 uid_t uid),
1182 void *private_data)
1184 struct sid2uid_state *state;
1185 NTSTATUS result;
1186 uid_t uid;
1188 if (idmap_proxyonly()) {
1189 DEBUG(10, ("idmap proxy only\n"));
1190 cont(private_data, False, 0);
1191 return;
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);
1200 return;
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);
1207 return;
1210 state->mem_ctx = mem_ctx;
1211 state->sid = *sid;
1212 state->cont = cont;
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);
1227 if (!success) {
1228 DEBUG(5, ("Could not trigger lookup_sid\n"));
1229 state->cont(state->private_data, False, 0);
1230 return;
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);
1236 return;
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);
1252 if (success) {
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);
1256 return;
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);
1264 return;
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);
1280 if (!success) {
1281 DEBUG(5, ("Could not allocate uid\n"));
1282 state->cont(state->private_data, False, 0);
1283 return;
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);
1293 unid_t id;
1295 if (!success) {
1296 DEBUG(5, ("Could not find uid for name %s\n",
1297 state->username));
1298 state->cont(state->private_data, False, 0);
1299 return;
1302 state->uid = uid;
1304 id.uid = uid;
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);
1314 if (!success) {
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);
1318 return;
1321 state->cont(state->private_data, True, state->uid);
1324 struct sid2gid_state {
1325 TALLOC_CTX *mem_ctx;
1326 DOM_SID sid;
1327 char *groupname;
1328 gid_t gid;
1329 void (*cont)(void *private_data, BOOL success, gid_t gid);
1330 void *private_data;
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,
1343 gid_t gid),
1344 void *private_data)
1346 struct sid2gid_state *state;
1347 NTSTATUS result;
1348 gid_t gid;
1350 if (idmap_proxyonly()) {
1351 DEBUG(10, ("idmap proxy only\n"));
1352 cont(private_data, False, 0);
1353 return;
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);
1362 return;
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);
1369 return;
1372 state->mem_ctx = mem_ctx;
1373 state->sid = *sid;
1374 state->cont = cont;
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);
1389 if (!success) {
1390 DEBUG(5, ("Could not trigger lookup_sid\n"));
1391 state->cont(state->private_data, False, 0);
1392 return;
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);
1399 return;
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);
1415 if (success) {
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);
1419 return;
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);
1427 return;
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);
1443 if (!success) {
1444 DEBUG(5, ("Could not allocate gid\n"));
1445 state->cont(state->private_data, False, 0);
1446 return;
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);
1456 unid_t id;
1458 if (!success) {
1459 DEBUG(5, ("Could not find gid for name %s\n",
1460 state->groupname));
1461 state->cont(state->private_data, False, 0);
1462 return;
1465 state->gid = gid;
1467 id.gid = gid;
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);
1477 if (!success) {
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);
1481 return;
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;
1497 if (!success) {
1498 DEBUG(5, ("Could not trigger query_user\n"));
1499 cont(private_data, False, NULL, NULL, NULL, NULL, -1);
1500 return;
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,
1511 const DOM_SID *sid,
1512 void (*cont)(void *private_data, BOOL success,
1513 const char *acct_name,
1514 const char *full_name,
1515 const char *homedir,
1516 const char *shell,
1517 uint32 group_rid),
1518 void *private_data)
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);
1528 /* The following uid2sid/gid2sid functions has been contributed by
1529 * Keith Reynolds <Keith.Reynolds@centrify.com> */
1531 static void winbindd_uid2sid_recv(TALLOC_CTX *mem_ctx, BOOL success,
1532 struct winbindd_response *response,
1533 void *c, void *private_data)
1535 void (*cont)(void *priv, BOOL succ, const char *sid) =
1536 (void (*)(void *, BOOL, const char *))c;
1538 if (!success) {
1539 DEBUG(5, ("Could not trigger uid2sid\n"));
1540 cont(private_data, False, NULL);
1541 return;
1544 if (response->result != WINBINDD_OK) {
1545 DEBUG(5, ("uid2sid returned an error\n"));
1546 cont(private_data, False, NULL);
1547 return;
1550 cont(private_data, True, response->data.sid.sid);
1553 void winbindd_uid2sid_async(TALLOC_CTX *mem_ctx, uid_t uid,
1554 void (*cont)(void *private_data, BOOL success, const char *sid),
1555 void *private_data)
1557 struct winbindd_request request;
1559 ZERO_STRUCT(request);
1560 request.cmd = WINBINDD_DUAL_UID2SID;
1561 request.data.uid = uid;
1562 do_async(mem_ctx, idmap_child(), &request, winbindd_uid2sid_recv, cont, private_data);
1565 enum winbindd_result winbindd_dual_uid2sid(struct winbindd_domain *domain,
1566 struct winbindd_cli_state *state)
1568 DOM_SID sid;
1569 NTSTATUS result;
1571 DEBUG(3,("[%5lu]: uid to sid %lu\n",
1572 (unsigned long)state->pid,
1573 (unsigned long) state->request.data.uid));
1575 /* Find sid for this uid and return it, possibly ask the slow remote idmap */
1576 result = idmap_uid_to_sid(&sid, state->request.data.uid, IDMAP_FLAG_NONE);
1578 if (NT_STATUS_IS_OK(result)) {
1579 sid_to_string(state->response.data.sid.sid, &sid);
1580 state->response.data.sid.type = SID_NAME_USER;
1581 return WINBINDD_OK;
1584 return WINBINDD_ERROR;
1587 static void winbindd_gid2sid_recv(TALLOC_CTX *mem_ctx, BOOL success,
1588 struct winbindd_response *response,
1589 void *c, void *private_data)
1591 void (*cont)(void *priv, BOOL succ, const char *sid) =
1592 (void (*)(void *, BOOL, const char *))c;
1594 if (!success) {
1595 DEBUG(5, ("Could not trigger gid2sid\n"));
1596 cont(private_data, False, NULL);
1597 return;
1600 if (response->result != WINBINDD_OK) {
1601 DEBUG(5, ("gid2sid returned an error\n"));
1602 cont(private_data, False, NULL);
1603 return;
1606 cont(private_data, True, response->data.sid.sid);
1609 void winbindd_gid2sid_async(TALLOC_CTX *mem_ctx, gid_t gid,
1610 void (*cont)(void *private_data, BOOL success, const char *sid),
1611 void *private_data)
1613 struct winbindd_request request;
1615 ZERO_STRUCT(request);
1616 request.cmd = WINBINDD_DUAL_GID2SID;
1617 request.data.gid = gid;
1618 do_async(mem_ctx, idmap_child(), &request, winbindd_gid2sid_recv, cont, private_data);
1621 enum winbindd_result winbindd_dual_gid2sid(struct winbindd_domain *domain,
1622 struct winbindd_cli_state *state)
1624 DOM_SID sid;
1625 NTSTATUS result;
1627 DEBUG(3,("[%5lu]: gid %lu to sid\n",
1628 (unsigned long)state->pid,
1629 (unsigned long) state->request.data.gid));
1631 /* Find sid for this gid and return it, possibly ask the slow remote idmap */
1632 result = idmap_gid_to_sid(&sid, state->request.data.gid, IDMAP_FLAG_NONE);
1634 if (NT_STATUS_IS_OK(result)) {
1635 sid_to_string(state->response.data.sid.sid, &sid);
1636 DEBUG(10, ("[%5lu]: retrieved sid: %s\n",
1637 (unsigned long)state->pid,
1638 state->response.data.sid.sid));
1639 state->response.data.sid.type = SID_NAME_DOM_GRP;
1640 return WINBINDD_OK;
1643 return WINBINDD_ERROR;