r10656: BIG merge from trunk. Features not copied over
[ab/samba.git/.git] / source3 / nsswitch / winbindd_async.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    Async helpers for blocking functions
5
6    Copyright (C) Volker Lendecke 2005
7    
8    The helpers always consist of three functions: 
9
10    * A request setup function that takes the necessary parameters together
11      with a continuation function that is to be called upon completion
12
13    * A private continuation function that is internal only. This is to be
14      called by the lower-level functions in do_async(). Its only task is to
15      properly call the continuation function named above.
16
17    * A worker function that is called inside the appropriate child process.
18
19    This program is free software; you can redistribute it and/or modify
20    it under the terms of the GNU General Public License as published by
21    the Free Software Foundation; either version 2 of the License, or
22    (at your option) any later version.
23    
24    This program is distributed in the hope that it will be useful,
25    but WITHOUT ANY WARRANTY; without even the implied warranty of
26    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27    GNU General Public License for more details.
28    
29    You should have received a copy of the GNU General Public License
30    along with this program; if not, write to the Free Software
31    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
32 */
33
34 #include "includes.h"
35 #include "winbindd.h"
36
37 #undef DBGC_CLASS
38 #define DBGC_CLASS DBGC_WINBIND
39
40 struct do_async_state {
41         TALLOC_CTX *mem_ctx;
42         struct winbindd_request request;
43         struct winbindd_response response;
44         void (*cont)(TALLOC_CTX *mem_ctx,
45                      BOOL success,
46                      struct winbindd_response *response,
47                      void *c, void *private_data);
48         void *c, *private_data;
49 };
50
51 static void do_async_recv(void *private_data, BOOL success)
52 {
53         struct do_async_state *state =
54                 talloc_get_type_abort(private_data, struct do_async_state);
55
56         state->cont(state->mem_ctx, success, &state->response,
57                     state->c, state->private_data);
58 }
59
60 static void do_async(TALLOC_CTX *mem_ctx, struct winbindd_child *child,
61                      const struct winbindd_request *request,
62                      void (*cont)(TALLOC_CTX *mem_ctx, BOOL success,
63                                   struct winbindd_response *response,
64                                   void *c, void *private_data),
65                      void *c, void *private_data)
66 {
67         struct do_async_state *state;
68
69         state = TALLOC_P(mem_ctx, struct do_async_state);
70         if (state == NULL) {
71                 DEBUG(0, ("talloc failed\n"));
72                 cont(mem_ctx, False, NULL, c, private_data);
73                 return;
74         }
75
76         state->mem_ctx = mem_ctx;
77         state->request = *request;
78         state->request.length = sizeof(state->request);
79         state->cont = cont;
80         state->c = c;
81         state->private_data = private_data;
82
83         async_request(mem_ctx, child, &state->request,
84                       &state->response, do_async_recv, state);
85 }
86
87 void do_async_domain(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
88                      const struct winbindd_request *request,
89                      void (*cont)(TALLOC_CTX *mem_ctx, BOOL success,
90                                   struct winbindd_response *response,
91                                   void *c, void *private_data),
92                      void *c, void *private_data)
93 {
94         struct do_async_state *state;
95
96         state = TALLOC_P(mem_ctx, struct do_async_state);
97         if (state == NULL) {
98                 DEBUG(0, ("talloc failed\n"));
99                 cont(mem_ctx, False, NULL, c, private_data);
100                 return;
101         }
102
103         state->mem_ctx = mem_ctx;
104         state->request = *request;
105         state->request.length = sizeof(state->request);
106         state->cont = cont;
107         state->c = c;
108         state->private_data = private_data;
109
110         async_domain_request(mem_ctx, domain, &state->request,
111                              &state->response, do_async_recv, state);
112 }
113
114 static void idmap_set_mapping_recv(TALLOC_CTX *mem_ctx, BOOL success,
115                                    struct winbindd_response *response,
116                                    void *c, void *private_data)
117 {
118         void (*cont)(void *priv, BOOL succ) = c;
119
120         if (!success) {
121                 DEBUG(5, ("Could not trigger idmap_set_mapping\n"));
122                 cont(private_data, False);
123                 return;
124         }
125
126         if (response->result != WINBINDD_OK) {
127                 DEBUG(5, ("idmap_set_mapping returned an error\n"));
128                 cont(private_data, False);
129                 return;
130         }
131
132         cont(private_data, True);
133 }
134
135 void idmap_set_mapping_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
136                              unid_t id, int id_type,
137                              void (*cont)(void *private_data, BOOL success),
138                              void *private_data)
139 {
140         struct winbindd_request request;
141         ZERO_STRUCT(request);
142         request.cmd = WINBINDD_DUAL_IDMAPSET;
143         if (id_type == ID_USERID)
144                 request.data.dual_idmapset.uid = id.uid;
145         else
146                 request.data.dual_idmapset.gid = id.gid;
147         request.data.dual_idmapset.type = id_type;
148         sid_to_string(request.data.dual_idmapset.sid, sid);
149
150         do_async(mem_ctx, idmap_child(), &request, idmap_set_mapping_recv,
151                  cont, private_data);
152 }
153
154 enum winbindd_result winbindd_dual_idmapset(struct winbindd_domain *domain,
155                                             struct winbindd_cli_state *state)
156 {
157         DOM_SID sid;
158         unid_t id;
159         NTSTATUS result;
160
161         DEBUG(3, ("[%5lu]: dual_idmapset\n", (unsigned long)state->pid));
162
163         if (!string_to_sid(&sid, state->request.data.dual_idmapset.sid))
164                 return WINBINDD_ERROR;
165
166         if (state->request.data.dual_idmapset.type == ID_USERID)
167                 id.uid = state->request.data.dual_idmapset.uid;
168         else
169                 id.gid = state->request.data.dual_idmapset.gid;
170
171         result = idmap_set_mapping(&sid, id,
172                                    state->request.data.dual_idmapset.type);
173         return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
174 }
175
176 static void idmap_sid2uid_recv(TALLOC_CTX *mem_ctx, BOOL success,
177                                struct winbindd_response *response,
178                                void *c, void *private_data);
179
180 void idmap_sid2uid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid, BOOL alloc,
181                          void (*cont)(void *private_data, BOOL success, uid_t uid),
182                          void *private_data)
183 {
184         struct winbindd_request request;
185         ZERO_STRUCT(request);
186         request.cmd = WINBINDD_DUAL_SID2UID;
187         sid_to_string(request.data.dual_sid2id.sid, sid);
188         request.data.dual_sid2id.alloc = alloc;
189         do_async(mem_ctx, idmap_child(), &request, idmap_sid2uid_recv,
190                  cont, private_data);
191 }
192
193 enum winbindd_result winbindd_dual_sid2uid(struct winbindd_domain *domain,
194                                            struct winbindd_cli_state *state)
195 {
196         DOM_SID sid;
197         NTSTATUS result;
198
199         DEBUG(3, ("[%5lu]: sid to uid %s\n", (unsigned long)state->pid,
200                   state->request.data.dual_sid2id.sid));
201
202         if (!string_to_sid(&sid, state->request.data.dual_sid2id.sid)) {
203                 DEBUG(1, ("Could not get convert sid %s from string\n",
204                           state->request.data.dual_sid2id.sid));
205                 return WINBINDD_ERROR;
206         }
207
208         /* Find uid for this sid and return it, possibly ask the slow remote
209          * idmap */
210
211         result = idmap_sid_to_uid(&sid, &(state->response.data.uid),
212                                   state->request.data.dual_sid2id.alloc ?
213                                   0 : ID_QUERY_ONLY);
214
215         return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
216 }
217
218 static void idmap_sid2uid_recv(TALLOC_CTX *mem_ctx, BOOL success,
219                                struct winbindd_response *response,
220                                void *c, void *private_data)
221 {
222         void (*cont)(void *priv, BOOL succ, uid_t uid) = c;
223
224         if (!success) {
225                 DEBUG(5, ("Could not trigger sid2uid\n"));
226                 cont(private_data, False, 0);
227                 return;
228         }
229
230         if (response->result != WINBINDD_OK) {
231                 DEBUG(5, ("sid2uid returned an error\n"));
232                 cont(private_data, False, 0);
233                 return;
234         }
235
236         cont(private_data, True, response->data.uid);
237 }
238                          
239 static void uid2name_recv(TALLOC_CTX *mem_ctx, BOOL success,
240                           struct winbindd_response *response,
241                           void *c, void *private_data);
242
243 void winbindd_uid2name_async(TALLOC_CTX *mem_ctx, uid_t uid,
244                              void (*cont)(void *private_data, BOOL success,
245                                           const char *name),
246                              void *private_data)
247 {
248         struct winbindd_request request;
249         ZERO_STRUCT(request);
250         request.cmd = WINBINDD_DUAL_UID2NAME;
251         request.data.uid = uid;
252         do_async(mem_ctx, idmap_child(), &request, uid2name_recv,
253                  cont, private_data);
254 }
255
256 enum winbindd_result winbindd_dual_uid2name(struct winbindd_domain *domain,
257                                             struct winbindd_cli_state *state)
258 {
259         struct passwd *pw;
260
261         DEBUG(3, ("[%5lu]: uid2name %lu\n", (unsigned long)state->pid, 
262                   (unsigned long)state->request.data.uid));
263
264         pw = getpwuid(state->request.data.uid);
265         if (pw == NULL) {
266                 DEBUG(5, ("User %lu not found\n",
267                           (unsigned long)state->request.data.uid));
268                 return WINBINDD_ERROR;
269         }
270
271         fstrcpy(state->response.data.name.name, pw->pw_name);
272         return WINBINDD_OK;
273 }
274
275 static void uid2name_recv(TALLOC_CTX *mem_ctx, BOOL success,
276                           struct winbindd_response *response,
277                           void *c, void *private_data)
278 {
279         void (*cont)(void *priv, BOOL succ, const char *name) = c;
280
281         if (!success) {
282                 DEBUG(5, ("Could not trigger uid2name\n"));
283                 cont(private_data, False, NULL);
284                 return;
285         }
286
287         if (response->result != WINBINDD_OK) {
288                 DEBUG(5, ("uid2name returned an error\n"));
289                 cont(private_data, False, NULL);
290                 return;
291         }
292
293         cont(private_data, True, response->data.name.name);
294 }
295
296 static void name2uid_recv(TALLOC_CTX *mem_ctx, BOOL success,
297                           struct winbindd_response *response,
298                           void *c, void *private_data);
299
300 static void winbindd_name2uid_async(TALLOC_CTX *mem_ctx, const char *name,
301                                     void (*cont)(void *private_data, BOOL success,
302                                                  uid_t uid),
303                                     void *private_data)
304 {
305         struct winbindd_request request;
306         ZERO_STRUCT(request);
307         request.cmd = WINBINDD_DUAL_NAME2UID;
308         fstrcpy(request.data.username, name);
309         do_async(mem_ctx, idmap_child(), &request, name2uid_recv,
310                  cont, private_data);
311 }
312
313 enum winbindd_result winbindd_dual_name2uid(struct winbindd_domain *domain,
314                                             struct winbindd_cli_state *state)
315 {
316         struct passwd *pw;
317
318         /* Ensure null termination */
319         state->request.data.username
320                 [sizeof(state->request.data.username)-1] = '\0';
321
322         DEBUG(3, ("[%5lu]: name2uid %s\n", (unsigned long)state->pid, 
323                   state->request.data.username));
324
325         pw = getpwnam(state->request.data.username);
326         if (pw == NULL) {
327                 return WINBINDD_ERROR;
328         }
329
330         state->response.data.uid = pw->pw_uid;
331         return WINBINDD_OK;
332 }
333
334 static void name2uid_recv(TALLOC_CTX *mem_ctx, BOOL success,
335                           struct winbindd_response *response,
336                           void *c, void *private_data)
337 {
338         void (*cont)(void *priv, BOOL succ, uid_t uid) = c;
339
340         if (!success) {
341                 DEBUG(5, ("Could not trigger name2uid\n"));
342                 cont(private_data, False, 0);
343                 return;
344         }
345
346         if (response->result != WINBINDD_OK) {
347                 DEBUG(5, ("name2uid returned an error\n"));
348                 cont(private_data, False, 0);
349                 return;
350         }
351
352         cont(private_data, True, response->data.uid);
353 }
354
355 static void idmap_sid2gid_recv(TALLOC_CTX *mem_ctx, BOOL success,
356                                struct winbindd_response *response,
357                                void *c, void *private_data);
358
359 void idmap_sid2gid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid, BOOL alloc,
360                          void (*cont)(void *private_data, BOOL success, gid_t gid),
361                          void *private_data)
362 {
363         struct winbindd_request request;
364         ZERO_STRUCT(request);
365         request.cmd = WINBINDD_DUAL_SID2GID;
366         sid_to_string(request.data.dual_sid2id.sid, sid);
367         request.data.dual_sid2id.alloc = alloc;
368         do_async(mem_ctx, idmap_child(), &request, idmap_sid2gid_recv,
369                  cont, private_data);
370 }
371
372 enum winbindd_result winbindd_dual_sid2gid(struct winbindd_domain *domain,
373                                            struct winbindd_cli_state *state)
374 {
375         DOM_SID sid;
376         NTSTATUS result;
377
378         DEBUG(3, ("[%5lu]: sid to gid %s\n", (unsigned long)state->pid,
379                   state->request.data.dual_sid2id.sid));
380
381         if (!string_to_sid(&sid, state->request.data.dual_sid2id.sid)) {
382                 DEBUG(1, ("Could not get convert sid %s from string\n",
383                           state->request.data.dual_sid2id.sid));
384                 return WINBINDD_ERROR;
385         }
386
387         /* Find gid for this sid and return it, possibly ask the slow remote
388          * idmap */
389
390         result = idmap_sid_to_gid(&sid, &(state->response.data.gid),
391                                   state->request.data.dual_sid2id.alloc ?
392                                   0 : ID_QUERY_ONLY);
393
394         return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
395 }
396
397 static void idmap_sid2gid_recv(TALLOC_CTX *mem_ctx, BOOL success,
398                                struct winbindd_response *response,
399                                void *c, void *private_data)
400 {
401         void (*cont)(void *priv, BOOL succ, gid_t gid) = c;
402
403         if (!success) {
404                 DEBUG(5, ("Could not trigger sid2gid\n"));
405                 cont(private_data, False, 0);
406                 return;
407         }
408
409         if (response->result != WINBINDD_OK) {
410                 DEBUG(5, ("sid2gid returned an error\n"));
411                 cont(private_data, False, 0);
412                 return;
413         }
414
415         cont(private_data, True, response->data.gid);
416 }
417                          
418 static void gid2name_recv(TALLOC_CTX *mem_ctx, BOOL success,
419                           struct winbindd_response *response,
420                           void *c, void *private_data)
421 {
422         void (*cont)(void *priv, BOOL succ, const char *name) = c;
423
424         if (!success) {
425                 DEBUG(5, ("Could not trigger gid2name\n"));
426                 cont(private_data, False, NULL);
427                 return;
428         }
429
430         if (response->result != WINBINDD_OK) {
431                 DEBUG(5, ("gid2name returned an error\n"));
432                 cont(private_data, False, NULL);
433                 return;
434         }
435
436         cont(private_data, True, response->data.name.name);
437 }
438
439 void winbindd_gid2name_async(TALLOC_CTX *mem_ctx, gid_t gid,
440                              void (*cont)(void *private_data, BOOL success,
441                                           const char *name),
442                              void *private_data)
443 {
444         struct winbindd_request request;
445         ZERO_STRUCT(request);
446         request.cmd = WINBINDD_DUAL_GID2NAME;
447         request.data.gid = gid;
448         do_async(mem_ctx, idmap_child(), &request, gid2name_recv,
449                  cont, private_data);
450 }
451
452 enum winbindd_result winbindd_dual_gid2name(struct winbindd_domain *domain,
453                                             struct winbindd_cli_state *state)
454 {
455         struct group *gr;
456
457         DEBUG(3, ("[%5lu]: gid2name %lu\n", (unsigned long)state->pid, 
458                   (unsigned long)state->request.data.gid));
459
460         gr = getgrgid(state->request.data.gid);
461         if (gr == NULL)
462                 return WINBINDD_ERROR;
463
464         fstrcpy(state->response.data.name.name, gr->gr_name);
465         return WINBINDD_OK;
466 }
467
468 static void name2gid_recv(TALLOC_CTX *mem_ctx, BOOL success,
469                           struct winbindd_response *response,
470                           void *c, void *private_data);
471
472 static void winbindd_name2gid_async(TALLOC_CTX *mem_ctx, const char *name,
473                                     void (*cont)(void *private_data, BOOL success,
474                                                  gid_t gid),
475                                     void *private_data)
476 {
477         struct winbindd_request request;
478         ZERO_STRUCT(request);
479         request.cmd = WINBINDD_DUAL_NAME2GID;
480         fstrcpy(request.data.groupname, name);
481         do_async(mem_ctx, idmap_child(), &request, name2gid_recv,
482                  cont, private_data);
483 }
484
485 enum winbindd_result winbindd_dual_name2gid(struct winbindd_domain *domain,
486                                             struct winbindd_cli_state *state)
487 {
488         struct group *gr;
489
490         /* Ensure null termination */
491         state->request.data.groupname
492                 [sizeof(state->request.data.groupname)-1] = '\0';
493
494         DEBUG(3, ("[%5lu]: name2gid %s\n", (unsigned long)state->pid, 
495                   state->request.data.groupname));
496
497         gr = getgrnam(state->request.data.groupname);
498         if (gr == NULL) {
499                 return WINBINDD_ERROR;
500         }
501
502         state->response.data.gid = gr->gr_gid;
503         return WINBINDD_OK;
504 }
505
506 static void name2gid_recv(TALLOC_CTX *mem_ctx, BOOL success,
507                           struct winbindd_response *response,
508                           void *c, void *private_data)
509 {
510         void (*cont)(void *priv, BOOL succ, gid_t gid) = c;
511
512         if (!success) {
513                 DEBUG(5, ("Could not trigger name2gid\n"));
514                 cont(private_data, False, 0);
515                 return;
516         }
517
518         if (response->result != WINBINDD_OK) {
519                 DEBUG(5, ("name2gid returned an error\n"));
520                 cont(private_data, False, 0);
521                 return;
522         }
523
524         cont(private_data, True, response->data.gid);
525 }
526
527
528 static void lookupsid_recv(TALLOC_CTX *mem_ctx, BOOL success,
529                            struct winbindd_response *response,
530                            void *c, void *private_data)
531 {
532         void (*cont)(void *priv, BOOL succ, const char *dom_name,
533                      const char *name, enum SID_NAME_USE type) = c;
534
535         if (!success) {
536                 DEBUG(5, ("Could not trigger lookupsid\n"));
537                 cont(private_data, False, NULL, NULL, SID_NAME_UNKNOWN);
538                 return;
539         }
540
541         if (response->result != WINBINDD_OK) {
542                 DEBUG(5, ("lookupsid returned an error\n"));
543                 cont(private_data, False, NULL, NULL, SID_NAME_UNKNOWN);
544                 return;
545         }
546
547         cont(private_data, True, response->data.name.dom_name,
548              response->data.name.name, response->data.name.type);
549 }
550
551 void winbindd_lookupsid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
552                               void (*cont)(void *private_data, BOOL success,
553                                            const char *dom_name,
554                                            const char *name,
555                                            enum SID_NAME_USE type),
556                               void *private_data)
557 {
558         struct winbindd_domain *domain;
559         struct winbindd_request request;
560
561         domain = find_lookup_domain_from_sid(sid);
562         if (domain == NULL) {
563                 DEBUG(5, ("Could not find domain for sid %s\n",
564                           sid_string_static(sid)));
565                 cont(private_data, False, NULL, NULL, SID_NAME_UNKNOWN);
566                 return;
567         }
568
569         ZERO_STRUCT(request);
570         request.cmd = WINBINDD_LOOKUPSID;
571         fstrcpy(request.data.sid, sid_string_static(sid));
572
573         do_async_domain(mem_ctx, domain, &request, lookupsid_recv,
574                         cont, private_data);
575 }
576
577 enum winbindd_result winbindd_dual_lookupsid(struct winbindd_domain *domain,
578                                              struct winbindd_cli_state *state)
579 {
580         enum SID_NAME_USE type;
581         DOM_SID sid;
582         fstring name;
583         fstring dom_name;
584
585         /* Ensure null termination */
586         state->request.data.sid[sizeof(state->request.data.sid)-1]='\0';
587
588         DEBUG(3, ("[%5lu]: lookupsid %s\n", (unsigned long)state->pid, 
589                   state->request.data.sid));
590
591         /* Lookup sid from PDC using lsa_lookup_sids() */
592
593         if (!string_to_sid(&sid, state->request.data.sid)) {
594                 DEBUG(5, ("%s not a SID\n", state->request.data.sid));
595                 return WINBINDD_ERROR;
596         }
597
598         /* Lookup the sid */
599
600         if (!winbindd_lookup_name_by_sid(state->mem_ctx, &sid, dom_name, name,
601                                          &type)) {
602                 return WINBINDD_ERROR;
603         }
604
605         fstrcpy(state->response.data.name.dom_name, dom_name);
606         fstrcpy(state->response.data.name.name, name);
607         state->response.data.name.type = type;
608
609         return WINBINDD_OK;
610 }
611
612 static void lookupname_recv(TALLOC_CTX *mem_ctx, BOOL success,
613                             struct winbindd_response *response,
614                             void *c, void *private_data)
615 {
616         void (*cont)(void *priv, BOOL succ, const DOM_SID *sid,
617                      enum SID_NAME_USE type) = c;
618         DOM_SID sid;
619
620         if (!success) {
621                 DEBUG(5, ("Could not trigger lookup_name\n"));
622                 cont(private_data, False, NULL, SID_NAME_UNKNOWN);
623                 return;
624         }
625
626         if (response->result != WINBINDD_OK) {
627                 DEBUG(5, ("lookup_name returned an error\n"));
628                 cont(private_data, False, NULL, SID_NAME_UNKNOWN);
629                 return;
630         }
631
632         if (!string_to_sid(&sid, response->data.sid.sid)) {
633                 DEBUG(0, ("Could not convert string %s to sid\n",
634                           response->data.sid.sid));
635                 cont(private_data, False, NULL, SID_NAME_UNKNOWN);
636                 return;
637         }
638
639         cont(private_data, True, &sid, response->data.sid.type);
640 }
641
642 void winbindd_lookupname_async(TALLOC_CTX *mem_ctx, const char *dom_name,
643                                const char *name,
644                                void (*cont)(void *private_data, BOOL success,
645                                             const DOM_SID *sid,
646                                             enum SID_NAME_USE type),
647                                void *private_data)
648 {
649         struct winbindd_request request;
650         struct winbindd_domain *domain;
651
652         domain = find_lookup_domain_from_name(dom_name);
653
654         if (domain == NULL) {
655                 DEBUG(5, ("Could not find domain for name %s\n", dom_name));
656                 cont(private_data, False, NULL, SID_NAME_UNKNOWN);
657                 return;
658         }
659
660         ZERO_STRUCT(request);
661         request.cmd = WINBINDD_LOOKUPNAME;
662         fstrcpy(request.data.name.dom_name, dom_name);
663         fstrcpy(request.data.name.name, name);
664
665         do_async_domain(mem_ctx, domain, &request, lookupname_recv,
666                         cont, private_data);
667 }
668
669 enum winbindd_result winbindd_dual_lookupname(struct winbindd_domain *domain,
670                                               struct winbindd_cli_state *state)
671 {
672         enum SID_NAME_USE type;
673         char *name_domain, *name_user;
674         DOM_SID sid;
675         char *p;
676
677         /* Ensure null termination */
678         state->request.data.sid[sizeof(state->request.data.name.dom_name)-1]='\0';
679
680         /* Ensure null termination */
681         state->request.data.sid[sizeof(state->request.data.name.name)-1]='\0';
682
683         /* cope with the name being a fully qualified name */
684         p = strstr(state->request.data.name.name, lp_winbind_separator());
685         if (p) {
686                 *p = 0;
687                 name_domain = state->request.data.name.name;
688                 name_user = p+1;
689         } else {
690                 name_domain = state->request.data.name.dom_name;
691                 name_user = state->request.data.name.name;
692         }
693
694         DEBUG(3, ("[%5lu]: lookupname %s%s%s\n", (unsigned long)state->pid,
695                   name_domain, lp_winbind_separator(), name_user));
696
697         /* Lookup name from PDC using lsa_lookup_names() */
698         if (!winbindd_lookup_sid_by_name(state->mem_ctx, domain, name_domain,
699                                          name_user, &sid, &type)) {
700                 return WINBINDD_ERROR;
701         }
702
703         sid_to_string(state->response.data.sid.sid, &sid);
704         state->response.data.sid.type = type;
705
706         return WINBINDD_OK;
707 }
708
709 BOOL print_sidlist(TALLOC_CTX *mem_ctx, const DOM_SID *sids,
710                    int num_sids, char **result, ssize_t *len)
711 {
712         int i;
713         size_t buflen = 0;
714
715         *len = 0;
716         *result = NULL;
717         for (i=0; i<num_sids; i++) {
718                 sprintf_append(mem_ctx, result, len, &buflen,
719                                "%s\n", sid_string_static(&sids[i]));
720         }
721
722         if ((num_sids != 0) && (*result == NULL)) {
723                 return False;
724         }
725
726         return True;
727 }
728
729 BOOL parse_sidlist(TALLOC_CTX *mem_ctx, char *sidstr,
730                    DOM_SID **sids, int *num_sids)
731 {
732         char *p, *q;
733
734         p = sidstr;
735         if (p == NULL)
736                 return False;
737
738         while (p[0] != '\0') {
739                 DOM_SID sid;
740                 q = strchr(p, '\n');
741                 if (q == NULL) {
742                         DEBUG(0, ("Got invalid sidstr: %s\n", p));
743                         return False;
744                 }
745                 *q = '\0';
746                 q += 1;
747                 if (!string_to_sid(&sid, p)) {
748                         DEBUG(0, ("Could not parse sid %s\n", p));
749                         return False;
750                 }
751                 add_sid_to_array(mem_ctx, &sid, sids, num_sids);
752                 p = q;
753         }
754         return True;
755 }
756
757 BOOL print_ridlist(TALLOC_CTX *mem_ctx, uint32 *rids, int num_rids,
758                    char **result, ssize_t *len)
759 {
760         int i;
761         size_t buflen = 0;
762
763         *len = 0;
764         *result = NULL;
765         for (i=0; i<num_rids; i++) {
766                 sprintf_append(mem_ctx, result, len, &buflen,
767                                "%ld\n", rids[i]);
768         }
769
770         if ((num_rids != 0) && (*result == NULL)) {
771                 return False;
772         }
773
774         return True;
775 }
776
777 BOOL parse_ridlist(TALLOC_CTX *mem_ctx, char *ridstr,
778                    uint32 **sids, int *num_rids)
779 {
780         char *p;
781
782         p = ridstr;
783         if (p == NULL)
784                 return False;
785
786         while (p[0] != '\0') {
787                 uint32 rid;
788                 char *q;
789                 rid = strtoul(p, &q, 10);
790                 if (*q != '\n') {
791                         DEBUG(0, ("Got invalid ridstr: %s\n", p));
792                         return False;
793                 }
794                 p = q+1;
795                 ADD_TO_ARRAY(mem_ctx, uint32, rid, sids, num_rids);
796         }
797         return True;
798 }
799
800 static void getsidaliases_recv(TALLOC_CTX *mem_ctx, BOOL success,
801                                struct winbindd_response *response,
802                                void *c, void *private_data)
803 {
804         void (*cont)(void *priv, BOOL succ,
805                      DOM_SID *aliases, int num_aliases) = c;
806         char *aliases_str;
807         DOM_SID *sids = NULL;
808         int num_sids = 0;
809
810         if (!success) {
811                 DEBUG(5, ("Could not trigger getsidaliases\n"));
812                 cont(private_data, success, NULL, 0);
813                 return;
814         }
815
816         if (response->result != WINBINDD_OK) {
817                 DEBUG(5, ("getsidaliases returned an error\n"));
818                 cont(private_data, False, NULL, 0);
819                 return;
820         }
821
822         aliases_str = response->extra_data;
823
824         if (aliases_str == NULL) {
825                 DEBUG(10, ("getsidaliases return 0 SIDs\n"));
826                 cont(private_data, True, NULL, 0);
827                 return;
828         }
829
830         if (!parse_sidlist(mem_ctx, aliases_str, &sids, &num_sids)) {
831                 DEBUG(0, ("Could not parse sids\n"));
832                 cont(private_data, False, NULL, 0);
833                 return;
834         }
835
836         SAFE_FREE(response->extra_data);
837
838         cont(private_data, True, sids, num_sids);
839 }
840
841 void winbindd_getsidaliases_async(struct winbindd_domain *domain,
842                                   TALLOC_CTX *mem_ctx,
843                                   const DOM_SID *sids, int num_sids,
844                                   void (*cont)(void *private_data,
845                                                BOOL success,
846                                                const DOM_SID *aliases,
847                                                int num_aliases),
848                                   void *private_data)
849 {
850         struct winbindd_request request;
851         char *sidstr = NULL;
852         ssize_t len;
853
854         if (num_sids == 0) {
855                 cont(private_data, True, NULL, 0);
856                 return;
857         }
858
859         if (!print_sidlist(mem_ctx, sids, num_sids, &sidstr, &len)) {
860                 cont(private_data, False, NULL, 0);
861                 return;
862         }
863
864         ZERO_STRUCT(request);
865         request.cmd = WINBINDD_DUAL_GETSIDALIASES;
866         request.extra_len = len;
867         request.extra_data = sidstr;
868
869         do_async_domain(mem_ctx, domain, &request, getsidaliases_recv,
870                         cont, private_data);
871 }
872
873 enum winbindd_result winbindd_dual_getsidaliases(struct winbindd_domain *domain,
874                                                  struct winbindd_cli_state *state)
875 {
876         DOM_SID *sids = NULL;
877         int num_sids = 0;
878         char *sidstr;
879         size_t len;
880         int i, num_aliases;
881         uint32 *alias_rids;
882         NTSTATUS result;
883
884         DEBUG(3, ("[%5lu]: getsidaliases\n", (unsigned long)state->pid));
885
886         sidstr = state->request.extra_data;
887         if (sidstr == NULL)
888                 sidstr = talloc_strdup(state->mem_ctx, "\n"); /* No SID */
889
890         DEBUG(10, ("Sidlist: %s\n", sidstr));
891
892         if (!parse_sidlist(state->mem_ctx, sidstr, &sids, &num_sids)) {
893                 DEBUG(0, ("Could not parse SID list: %s\n", sidstr));
894                 return WINBINDD_ERROR;
895         }
896
897         num_aliases = 0;
898         alias_rids = NULL;
899
900         result = domain->methods->lookup_useraliases(domain,
901                                                      state->mem_ctx,
902                                                      num_sids, sids,
903                                                      &num_aliases,
904                                                      &alias_rids);
905
906         if (!NT_STATUS_IS_OK(result)) {
907                 DEBUG(3, ("Could not lookup_useraliases: %s\n",
908                           nt_errstr(result)));
909                 return WINBINDD_ERROR;
910         }
911
912         num_sids = 0;
913         sids = NULL;
914
915         DEBUG(10, ("Got %d aliases\n", num_aliases));
916
917         for (i=0; i<num_aliases; i++) {
918                 DOM_SID sid;
919                 DEBUGADD(10, (" rid %d\n", alias_rids[i]));
920                 sid_copy(&sid, &domain->sid);
921                 sid_append_rid(&sid, alias_rids[i]);
922                 add_sid_to_array(state->mem_ctx, &sid, &sids, &num_sids);
923         }
924
925         if (!print_sidlist(NULL, sids, num_sids,
926                            (char **)&state->response.extra_data, &len)) {
927                 DEBUG(0, ("Could not print_sidlist\n"));
928                 return WINBINDD_ERROR;
929         }
930
931         if (state->response.extra_data != NULL) {
932                 DEBUG(10, ("aliases_list: %s\n",
933                            (char *)state->response.extra_data));
934                 state->response.length += len+1;
935         }
936         
937         return WINBINDD_OK;
938 }
939
940 struct gettoken_state {
941         TALLOC_CTX *mem_ctx;
942         DOM_SID user_sid;
943         struct winbindd_domain *alias_domain;
944         struct winbindd_domain *builtin_domain;
945         DOM_SID *sids;
946         int num_sids;
947         void (*cont)(void *private_data, BOOL success, DOM_SID *sids, int num_sids);
948         void *private_data;
949 };
950
951 static void gettoken_recvdomgroups(TALLOC_CTX *mem_ctx, BOOL success,
952                                    struct winbindd_response *response,
953                                    void *c, void *private_data);
954 static void gettoken_recvaliases(void *private_data, BOOL success,
955                                  const DOM_SID *aliases,
956                                  int num_aliases);
957                                  
958
959 void winbindd_gettoken_async(TALLOC_CTX *mem_ctx, const DOM_SID *user_sid,
960                              void (*cont)(void *private_data, BOOL success,
961                                           DOM_SID *sids, int num_sids),
962                              void *private_data)
963 {
964         struct winbindd_domain *domain;
965         struct winbindd_request request;
966         struct gettoken_state *state;
967
968         state = TALLOC_P(mem_ctx, struct gettoken_state);
969         if (state == NULL) {
970                 DEBUG(0, ("talloc failed\n"));
971                 cont(private_data, False, NULL, 0);
972                 return;
973         }
974
975         state->mem_ctx = mem_ctx;
976         sid_copy(&state->user_sid, user_sid);
977         state->alias_domain = find_our_domain();
978         state->builtin_domain = find_builtin_domain();
979         state->cont = cont;
980         state->private_data = private_data;
981
982         domain = find_domain_from_sid_noinit(user_sid);
983         if (domain == NULL) {
984                 DEBUG(5, ("Could not find domain from SID %s\n",
985                           sid_string_static(user_sid)));
986                 cont(private_data, False, NULL, 0);
987                 return;
988         }
989
990         ZERO_STRUCT(request);
991         request.cmd = WINBINDD_GETUSERDOMGROUPS;
992         fstrcpy(request.data.sid, sid_string_static(user_sid));
993
994         do_async_domain(mem_ctx, domain, &request, gettoken_recvdomgroups,
995                         NULL, state);
996 }
997
998 static void gettoken_recvdomgroups(TALLOC_CTX *mem_ctx, BOOL success,
999                                    struct winbindd_response *response,
1000                                    void *c, void *private_data)
1001 {
1002         struct gettoken_state *state =
1003                 talloc_get_type_abort(private_data, struct gettoken_state);
1004         char *sids_str;
1005         
1006         if (!success) {
1007                 DEBUG(10, ("Could not get domain groups\n"));
1008                 state->cont(state->private_data, False, NULL, 0);
1009                 return;
1010         }
1011
1012         sids_str = response->extra_data;
1013
1014         if (sids_str == NULL) {
1015                 DEBUG(10, ("Received no domain groups\n"));
1016                 state->cont(state->private_data, True, NULL, 0);
1017                 return;
1018         }
1019
1020         state->sids = NULL;
1021         state->num_sids = 0;
1022
1023         add_sid_to_array(mem_ctx, &state->user_sid, &state->sids,
1024                          &state->num_sids);
1025
1026         if (!parse_sidlist(mem_ctx, sids_str, &state->sids,
1027                            &state->num_sids)) {
1028                 DEBUG(0, ("Could not parse sids\n"));
1029                 state->cont(state->private_data, False, NULL, 0);
1030                 return;
1031         }
1032
1033         SAFE_FREE(response->extra_data);
1034
1035         if (state->alias_domain == NULL) {
1036                 DEBUG(10, ("Don't expand domain local groups\n"));
1037                 state->cont(state->private_data, True, state->sids,
1038                             state->num_sids);
1039                 return;
1040         }
1041
1042         winbindd_getsidaliases_async(state->alias_domain, mem_ctx,
1043                                      state->sids, state->num_sids,
1044                                      gettoken_recvaliases, state);
1045 }
1046
1047 static void gettoken_recvaliases(void *private_data, BOOL success,
1048                                  const DOM_SID *aliases,
1049                                  int num_aliases)
1050 {
1051         struct gettoken_state *state = private_data;
1052         int i;
1053
1054         if (!success) {
1055                 DEBUG(10, ("Could not receive domain local groups\n"));
1056                 state->cont(state->private_data, False, NULL, 0);
1057                 return;
1058         }
1059
1060         for (i=0; i<num_aliases; i++)
1061                 add_sid_to_array(state->mem_ctx, &aliases[i],
1062                                  &state->sids, &state->num_sids);
1063
1064         if (state->builtin_domain != NULL) {
1065                 struct winbindd_domain *builtin_domain = state->builtin_domain;
1066                 DEBUG(10, ("Expanding our own local groups\n"));
1067                 state->builtin_domain = NULL;
1068                 winbindd_getsidaliases_async(builtin_domain, state->mem_ctx,
1069                                              state->sids, state->num_sids,
1070                                              gettoken_recvaliases, state);
1071                 return;
1072         }
1073
1074         state->cont(state->private_data, True, state->sids, state->num_sids);
1075 }
1076
1077 struct sid2uid_state {
1078         TALLOC_CTX *mem_ctx;
1079         DOM_SID sid;
1080         char *username;
1081         uid_t uid;
1082         void (*cont)(void *private_data, BOOL success, uid_t uid);
1083         void *private_data;
1084 };
1085
1086 static void sid2uid_lookup_sid_recv(void *private_data, BOOL success,
1087                                     const char *dom_name, const char *name,
1088                                     enum SID_NAME_USE type);
1089 static void sid2uid_noalloc_recv(void *private_data, BOOL success, uid_t uid);
1090 static void sid2uid_alloc_recv(void *private_data, BOOL success, uid_t uid);
1091 static void sid2uid_name2uid_recv(void *private_data, BOOL success, uid_t uid);
1092 static void sid2uid_set_mapping_recv(void *private_data, BOOL success);
1093
1094 void winbindd_sid2uid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
1095                             void (*cont)(void *private_data, BOOL success,
1096                                          uid_t uid),
1097                             void *private_data)
1098 {
1099         struct sid2uid_state *state;
1100         NTSTATUS result;
1101         uid_t uid;
1102
1103         if (idmap_proxyonly()) {
1104                 DEBUG(10, ("idmap proxy only\n"));
1105                 cont(private_data, False, 0);
1106                 return;
1107         }
1108
1109         /* Query only the local tdb, everything else might possibly block */
1110
1111         result = idmap_sid_to_uid(sid, &uid, ID_QUERY_ONLY|ID_CACHE_ONLY);
1112
1113         if (NT_STATUS_IS_OK(result)) {
1114                 cont(private_data, True, uid);
1115                 return;
1116         }
1117
1118         state = TALLOC_P(mem_ctx, struct sid2uid_state);
1119         if (state == NULL) {
1120                 DEBUG(0, ("talloc failed\n"));
1121                 cont(private_data, False, 0);
1122                 return;
1123         }
1124
1125         state->mem_ctx = mem_ctx;
1126         state->sid = *sid;
1127         state->cont = cont;
1128         state->private_data = private_data;
1129
1130         /* Let's see if it's really a user before allocating a uid */
1131
1132         winbindd_lookupsid_async(mem_ctx, sid, sid2uid_lookup_sid_recv, state);
1133 }
1134
1135 static void sid2uid_lookup_sid_recv(void *private_data, BOOL success,
1136                                     const char *dom_name, const char *name,
1137                                     enum SID_NAME_USE type)
1138 {
1139         struct sid2uid_state *state =
1140                 talloc_get_type_abort(private_data, struct sid2uid_state);
1141
1142         if (!success) {
1143                 DEBUG(5, ("Could not trigger lookup_sid\n"));
1144                 state->cont(state->private_data, False, 0);
1145                 return;
1146         }
1147
1148         if ((type != SID_NAME_USER) && (type != SID_NAME_COMPUTER)) {
1149                 DEBUG(5, ("SID is not a user\n"));
1150                 state->cont(state->private_data, False, 0);
1151                 return;
1152         }
1153
1154         state->username = talloc_strdup(state->mem_ctx, name);
1155
1156         /* Ask the possibly blocking remote IDMAP */
1157
1158         idmap_sid2uid_async(state->mem_ctx, &state->sid, False,
1159                             sid2uid_noalloc_recv, state);
1160 }
1161
1162 static void sid2uid_noalloc_recv(void *private_data, BOOL success, uid_t uid)
1163 {
1164         struct sid2uid_state *state =
1165                 talloc_get_type_abort(private_data, struct sid2uid_state);
1166
1167         if (success) {
1168                 DEBUG(10, ("found uid for sid %s in remote backend\n",
1169                            sid_string_static(&state->sid)));
1170                 state->cont(state->private_data, True, uid);
1171                 return;
1172         }
1173
1174         if (lp_winbind_trusted_domains_only() && 
1175             (sid_compare_domain(&state->sid, &find_our_domain()->sid) == 0)) {
1176                 DEBUG(10, ("Trying to go via nss\n"));
1177                 winbindd_name2uid_async(state->mem_ctx, state->username,
1178                                         sid2uid_name2uid_recv, state);
1179                 return;
1180         }
1181
1182         /* To be done: Here we're going to try the unixinfo pipe */
1183
1184         /* Now allocate a uid */
1185
1186         idmap_sid2uid_async(state->mem_ctx, &state->sid, True,
1187                             sid2uid_alloc_recv, state);
1188 }
1189
1190 static void sid2uid_alloc_recv(void *private_data, BOOL success, uid_t uid)
1191 {
1192         struct sid2uid_state *state =
1193                 talloc_get_type_abort(private_data, struct sid2uid_state);
1194
1195         if (!success) {
1196                 DEBUG(5, ("Could not allocate uid\n"));
1197                 state->cont(state->private_data, False, 0);
1198                 return;
1199         }
1200
1201         state->cont(state->private_data, True, uid);
1202 }
1203
1204 static void sid2uid_name2uid_recv(void *private_data, BOOL success, uid_t uid)
1205 {
1206         struct sid2uid_state *state =
1207                 talloc_get_type_abort(private_data, struct sid2uid_state);
1208         unid_t id;
1209
1210         if (!success) {
1211                 DEBUG(5, ("Could not find uid for name %s\n",
1212                           state->username));
1213                 state->cont(state->private_data, False, 0);
1214                 return;
1215         }
1216
1217         state->uid = uid;
1218
1219         id.uid = uid;
1220         idmap_set_mapping_async(state->mem_ctx, &state->sid, id, ID_USERID,
1221                                 sid2uid_set_mapping_recv, state);
1222 }
1223
1224 static void sid2uid_set_mapping_recv(void *private_data, BOOL success)
1225 {
1226         struct sid2uid_state *state =
1227                 talloc_get_type_abort(private_data, struct sid2uid_state);
1228
1229         if (!success) {
1230                 DEBUG(5, ("Could not set ID mapping for sid %s\n",
1231                           sid_string_static(&state->sid)));
1232                 state->cont(state->private_data, False, 0);
1233                 return;
1234         }
1235
1236         state->cont(state->private_data, True, state->uid);
1237 }
1238
1239 struct sid2gid_state {
1240         TALLOC_CTX *mem_ctx;
1241         DOM_SID sid;
1242         char *groupname;
1243         gid_t gid;
1244         void (*cont)(void *private_data, BOOL success, gid_t gid);
1245         void *private_data;
1246 };
1247
1248 static void sid2gid_lookup_sid_recv(void *private_data, BOOL success,
1249                                     const char *dom_name, const char *name,
1250                                     enum SID_NAME_USE type);
1251 static void sid2gid_noalloc_recv(void *private_data, BOOL success, gid_t gid);
1252 static void sid2gid_alloc_recv(void *private_data, BOOL success, gid_t gid);
1253 static void sid2gid_name2gid_recv(void *private_data, BOOL success, gid_t gid);
1254 static void sid2gid_set_mapping_recv(void *private_data, BOOL success);
1255
1256 void winbindd_sid2gid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
1257                             void (*cont)(void *private_data, BOOL success,
1258                                          gid_t gid),
1259                             void *private_data)
1260 {
1261         struct sid2gid_state *state;
1262         NTSTATUS result;
1263         gid_t gid;
1264
1265         if (idmap_proxyonly()) {
1266                 DEBUG(10, ("idmap proxy only\n"));
1267                 cont(private_data, False, 0);
1268                 return;
1269         }
1270
1271         /* Query only the local tdb, everything else might possibly block */
1272
1273         result = idmap_sid_to_gid(sid, &gid, ID_QUERY_ONLY|ID_CACHE_ONLY);
1274
1275         if (NT_STATUS_IS_OK(result)) {
1276                 cont(private_data, True, gid);
1277                 return;
1278         }
1279
1280         state = TALLOC_P(mem_ctx, struct sid2gid_state);
1281         if (state == NULL) {
1282                 DEBUG(0, ("talloc failed\n"));
1283                 cont(private_data, False, 0);
1284                 return;
1285         }
1286
1287         state->mem_ctx = mem_ctx;
1288         state->sid = *sid;
1289         state->cont = cont;
1290         state->private_data = private_data;
1291
1292         /* Let's see if it's really a user before allocating a gid */
1293
1294         winbindd_lookupsid_async(mem_ctx, sid, sid2gid_lookup_sid_recv, state);
1295 }
1296
1297 static void sid2gid_lookup_sid_recv(void *private_data, BOOL success,
1298                                     const char *dom_name, const char *name,
1299                                     enum SID_NAME_USE type)
1300 {
1301         struct sid2gid_state *state =
1302                 talloc_get_type_abort(private_data, struct sid2gid_state);
1303
1304         if (!success) {
1305                 DEBUG(5, ("Could not trigger lookup_sid\n"));
1306                 state->cont(state->private_data, False, 0);
1307                 return;
1308         }
1309
1310         if (((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
1311              (type != SID_NAME_WKN_GRP))) {
1312                 DEBUG(5, ("SID is not a group\n"));
1313                 state->cont(state->private_data, False, 0);
1314                 return;
1315         }
1316
1317         state->groupname = talloc_strdup(state->mem_ctx, name);
1318
1319         /* Ask the possibly blocking remote IDMAP and allocate  */
1320
1321         idmap_sid2gid_async(state->mem_ctx, &state->sid, False,
1322                             sid2gid_noalloc_recv, state);
1323 }
1324
1325 static void sid2gid_noalloc_recv(void *private_data, BOOL success, gid_t gid)
1326 {
1327         struct sid2gid_state *state =
1328                 talloc_get_type_abort(private_data, struct sid2gid_state);
1329
1330         if (success) {
1331                 DEBUG(10, ("found gid for sid %s in remote backend\n",
1332                            sid_string_static(&state->sid)));
1333                 state->cont(state->private_data, True, gid);
1334                 return;
1335         }
1336
1337         if (lp_winbind_trusted_domains_only() && 
1338             (sid_compare_domain(&state->sid, &find_our_domain()->sid) == 0)) {
1339                 DEBUG(10, ("Trying to go via nss\n"));
1340                 winbindd_name2gid_async(state->mem_ctx, state->groupname,
1341                                         sid2gid_name2gid_recv, state);
1342                 return;
1343         }
1344
1345         /* To be done: Here we're going to try the unixinfo pipe */
1346
1347         /* Now allocate a gid */
1348
1349         idmap_sid2gid_async(state->mem_ctx, &state->sid, True,
1350                             sid2gid_alloc_recv, state);
1351 }
1352
1353 static void sid2gid_alloc_recv(void *private_data, BOOL success, gid_t gid)
1354 {
1355         struct sid2gid_state *state =
1356                 talloc_get_type_abort(private_data, struct sid2gid_state);
1357
1358         if (!success) {
1359                 DEBUG(5, ("Could not allocate gid\n"));
1360                 state->cont(state->private_data, False, 0);
1361                 return;
1362         }
1363
1364         state->cont(state->private_data, True, gid);
1365 }
1366
1367 static void sid2gid_name2gid_recv(void *private_data, BOOL success, gid_t gid)
1368 {
1369         struct sid2gid_state *state =
1370                 talloc_get_type_abort(private_data, struct sid2gid_state);
1371         unid_t id;
1372
1373         if (!success) {
1374                 DEBUG(5, ("Could not find gid for name %s\n",
1375                           state->groupname));
1376                 state->cont(state->private_data, False, 0);
1377                 return;
1378         }
1379
1380         state->gid = gid;
1381
1382         id.gid = gid;
1383         idmap_set_mapping_async(state->mem_ctx, &state->sid, id, ID_GROUPID,
1384                                 sid2gid_set_mapping_recv, state);
1385 }
1386
1387 static void sid2gid_set_mapping_recv(void *private_data, BOOL success)
1388 {
1389         struct sid2gid_state *state =
1390                 talloc_get_type_abort(private_data, struct sid2gid_state);
1391
1392         if (!success) {
1393                 DEBUG(5, ("Could not set ID mapping for sid %s\n",
1394                           sid_string_static(&state->sid)));
1395                 state->cont(state->private_data, False, 0);
1396                 return;
1397         }
1398
1399         state->cont(state->private_data, True, state->gid);
1400 }
1401
1402 static void query_user_recv(TALLOC_CTX *mem_ctx, BOOL success,
1403                             struct winbindd_response *response,
1404                             void *c, void *private_data)
1405 {
1406         void (*cont)(void *priv, BOOL succ, const char *acct_name,
1407                      const char *full_name, const char *homedir, 
1408                      const char *shell, uint32 group_rid) = c;
1409
1410         if (!success) {
1411                 DEBUG(5, ("Could not trigger query_user\n"));
1412                 cont(private_data, False, NULL, NULL, NULL, NULL, -1);
1413                 return;
1414         }
1415
1416         cont(private_data, True, response->data.user_info.acct_name,
1417              response->data.user_info.full_name,
1418              response->data.user_info.homedir,
1419              response->data.user_info.shell,
1420              response->data.user_info.group_rid);
1421 }
1422
1423 void query_user_async(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1424                       const DOM_SID *sid,
1425                       void (*cont)(void *private_data, BOOL success,
1426                                    const char *acct_name,
1427                                    const char *full_name,
1428                                    const char *homedir,
1429                                    const char *shell,
1430                                    uint32 group_rid),
1431                       void *private_data)
1432 {
1433         struct winbindd_request request;
1434         ZERO_STRUCT(request);
1435         request.cmd = WINBINDD_DUAL_USERINFO;
1436         sid_to_string(request.data.sid, sid);
1437         do_async_domain(mem_ctx, domain, &request, query_user_recv,
1438                         cont, private_data);
1439 }
1440