Initial import
[samba] / source / 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                    size_t num_sids, char **result, ssize_t *len)
711 {
712         size_t 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, size_t *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, size_t num_rids,
758                    char **result, ssize_t *len)
759 {
760         size_t 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, size_t *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, size_t num_aliases) = c;
806         char *aliases_str;
807         DOM_SID *sids = NULL;
808         size_t 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, size_t num_sids,
844                                   void (*cont)(void *private_data,
845                                                BOOL success,
846                                                const DOM_SID *aliases,
847                                                size_t 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         size_t num_sids = 0;
878         char *sidstr;
879         ssize_t len;
880         size_t i;
881         uint32 num_aliases;
882         uint32 *alias_rids;
883         NTSTATUS result;
884
885         DEBUG(3, ("[%5lu]: getsidaliases\n", (unsigned long)state->pid));
886
887         sidstr = state->request.extra_data;
888         if (sidstr == NULL)
889                 sidstr = talloc_strdup(state->mem_ctx, "\n"); /* No SID */
890
891         DEBUG(10, ("Sidlist: %s\n", sidstr));
892
893         if (!parse_sidlist(state->mem_ctx, sidstr, &sids, &num_sids)) {
894                 DEBUG(0, ("Could not parse SID list: %s\n", sidstr));
895                 return WINBINDD_ERROR;
896         }
897
898         num_aliases = 0;
899         alias_rids = NULL;
900
901         result = domain->methods->lookup_useraliases(domain,
902                                                      state->mem_ctx,
903                                                      num_sids, sids,
904                                                      &num_aliases,
905                                                      &alias_rids);
906
907         if (!NT_STATUS_IS_OK(result)) {
908                 DEBUG(3, ("Could not lookup_useraliases: %s\n",
909                           nt_errstr(result)));
910                 return WINBINDD_ERROR;
911         }
912
913         num_sids = 0;
914         sids = NULL;
915
916         DEBUG(10, ("Got %d aliases\n", num_aliases));
917
918         for (i=0; i<num_aliases; i++) {
919                 DOM_SID sid;
920                 DEBUGADD(10, (" rid %d\n", alias_rids[i]));
921                 sid_copy(&sid, &domain->sid);
922                 sid_append_rid(&sid, alias_rids[i]);
923                 add_sid_to_array(state->mem_ctx, &sid, &sids, &num_sids);
924         }
925
926         if (!print_sidlist(NULL, sids, num_sids,
927                            (char **)&state->response.extra_data, &len)) {
928                 DEBUG(0, ("Could not print_sidlist\n"));
929                 return WINBINDD_ERROR;
930         }
931
932         if (state->response.extra_data != NULL) {
933                 DEBUG(10, ("aliases_list: %s\n",
934                            (char *)state->response.extra_data));
935                 state->response.length += len+1;
936         }
937         
938         return WINBINDD_OK;
939 }
940
941 struct gettoken_state {
942         TALLOC_CTX *mem_ctx;
943         DOM_SID user_sid;
944         struct winbindd_domain *alias_domain;
945         struct winbindd_domain *builtin_domain;
946         DOM_SID *sids;
947         size_t num_sids;
948         void (*cont)(void *private_data, BOOL success, DOM_SID *sids, size_t num_sids);
949         void *private_data;
950 };
951
952 static void gettoken_recvdomgroups(TALLOC_CTX *mem_ctx, BOOL success,
953                                    struct winbindd_response *response,
954                                    void *c, void *private_data);
955 static void gettoken_recvaliases(void *private_data, BOOL success,
956                                  const DOM_SID *aliases,
957                                  size_t num_aliases);
958                                  
959
960 void winbindd_gettoken_async(TALLOC_CTX *mem_ctx, const DOM_SID *user_sid,
961                              void (*cont)(void *private_data, BOOL success,
962                                           DOM_SID *sids, size_t num_sids),
963                              void *private_data)
964 {
965         struct winbindd_domain *domain;
966         struct winbindd_request request;
967         struct gettoken_state *state;
968
969         state = TALLOC_P(mem_ctx, struct gettoken_state);
970         if (state == NULL) {
971                 DEBUG(0, ("talloc failed\n"));
972                 cont(private_data, False, NULL, 0);
973                 return;
974         }
975
976         state->mem_ctx = mem_ctx;
977         sid_copy(&state->user_sid, user_sid);
978         state->alias_domain = find_our_domain();
979         state->builtin_domain = find_builtin_domain();
980         state->cont = cont;
981         state->private_data = private_data;
982
983         domain = find_domain_from_sid_noinit(user_sid);
984         if (domain == NULL) {
985                 DEBUG(5, ("Could not find domain from SID %s\n",
986                           sid_string_static(user_sid)));
987                 cont(private_data, False, NULL, 0);
988                 return;
989         }
990
991         ZERO_STRUCT(request);
992         request.cmd = WINBINDD_GETUSERDOMGROUPS;
993         fstrcpy(request.data.sid, sid_string_static(user_sid));
994
995         do_async_domain(mem_ctx, domain, &request, gettoken_recvdomgroups,
996                         NULL, state);
997 }
998
999 static void gettoken_recvdomgroups(TALLOC_CTX *mem_ctx, BOOL success,
1000                                    struct winbindd_response *response,
1001                                    void *c, void *private_data)
1002 {
1003         struct gettoken_state *state =
1004                 talloc_get_type_abort(private_data, struct gettoken_state);
1005         char *sids_str;
1006         
1007         if (!success) {
1008                 DEBUG(10, ("Could not get domain groups\n"));
1009                 state->cont(state->private_data, False, NULL, 0);
1010                 return;
1011         }
1012
1013         sids_str = response->extra_data;
1014
1015         if (sids_str == NULL) {
1016                 DEBUG(10, ("Received no domain groups\n"));
1017                 state->cont(state->private_data, True, NULL, 0);
1018                 return;
1019         }
1020
1021         state->sids = NULL;
1022         state->num_sids = 0;
1023
1024         add_sid_to_array(mem_ctx, &state->user_sid, &state->sids,
1025                          &state->num_sids);
1026
1027         if (!parse_sidlist(mem_ctx, sids_str, &state->sids,
1028                            &state->num_sids)) {
1029                 DEBUG(0, ("Could not parse sids\n"));
1030                 state->cont(state->private_data, False, NULL, 0);
1031                 return;
1032         }
1033
1034         SAFE_FREE(response->extra_data);
1035
1036         if (state->alias_domain == NULL) {
1037                 DEBUG(10, ("Don't expand domain local groups\n"));
1038                 state->cont(state->private_data, True, state->sids,
1039                             state->num_sids);
1040                 return;
1041         }
1042
1043         winbindd_getsidaliases_async(state->alias_domain, mem_ctx,
1044                                      state->sids, state->num_sids,
1045                                      gettoken_recvaliases, state);
1046 }
1047
1048 static void gettoken_recvaliases(void *private_data, BOOL success,
1049                                  const DOM_SID *aliases,
1050                                  size_t num_aliases)
1051 {
1052         struct gettoken_state *state = private_data;
1053         size_t i;
1054
1055         if (!success) {
1056                 DEBUG(10, ("Could not receive domain local groups\n"));
1057                 state->cont(state->private_data, False, NULL, 0);
1058                 return;
1059         }
1060
1061         for (i=0; i<num_aliases; i++)
1062                 add_sid_to_array(state->mem_ctx, &aliases[i],
1063                                  &state->sids, &state->num_sids);
1064
1065         if (state->builtin_domain != NULL) {
1066                 struct winbindd_domain *builtin_domain = state->builtin_domain;
1067                 DEBUG(10, ("Expanding our own local groups\n"));
1068                 state->builtin_domain = NULL;
1069                 winbindd_getsidaliases_async(builtin_domain, state->mem_ctx,
1070                                              state->sids, state->num_sids,
1071                                              gettoken_recvaliases, state);
1072                 return;
1073         }
1074
1075         state->cont(state->private_data, True, state->sids, state->num_sids);
1076 }
1077
1078 struct sid2uid_state {
1079         TALLOC_CTX *mem_ctx;
1080         DOM_SID sid;
1081         char *username;
1082         uid_t uid;
1083         void (*cont)(void *private_data, BOOL success, uid_t uid);
1084         void *private_data;
1085 };
1086
1087 static void sid2uid_lookup_sid_recv(void *private_data, BOOL success,
1088                                     const char *dom_name, const char *name,
1089                                     enum SID_NAME_USE type);
1090 static void sid2uid_noalloc_recv(void *private_data, BOOL success, uid_t uid);
1091 static void sid2uid_alloc_recv(void *private_data, BOOL success, uid_t uid);
1092 static void sid2uid_name2uid_recv(void *private_data, BOOL success, uid_t uid);
1093 static void sid2uid_set_mapping_recv(void *private_data, BOOL success);
1094
1095 void winbindd_sid2uid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
1096                             void (*cont)(void *private_data, BOOL success,
1097                                          uid_t uid),
1098                             void *private_data)
1099 {
1100         struct sid2uid_state *state;
1101         NTSTATUS result;
1102         uid_t uid;
1103
1104         if (idmap_proxyonly()) {
1105                 DEBUG(10, ("idmap proxy only\n"));
1106                 cont(private_data, False, 0);
1107                 return;
1108         }
1109
1110         /* Query only the local tdb, everything else might possibly block */
1111
1112         result = idmap_sid_to_uid(sid, &uid, ID_QUERY_ONLY|ID_CACHE_ONLY);
1113
1114         if (NT_STATUS_IS_OK(result)) {
1115                 cont(private_data, True, uid);
1116                 return;
1117         }
1118
1119         state = TALLOC_P(mem_ctx, struct sid2uid_state);
1120         if (state == NULL) {
1121                 DEBUG(0, ("talloc failed\n"));
1122                 cont(private_data, False, 0);
1123                 return;
1124         }
1125
1126         state->mem_ctx = mem_ctx;
1127         state->sid = *sid;
1128         state->cont = cont;
1129         state->private_data = private_data;
1130
1131         /* Let's see if it's really a user before allocating a uid */
1132
1133         winbindd_lookupsid_async(mem_ctx, sid, sid2uid_lookup_sid_recv, state);
1134 }
1135
1136 static void sid2uid_lookup_sid_recv(void *private_data, BOOL success,
1137                                     const char *dom_name, const char *name,
1138                                     enum SID_NAME_USE type)
1139 {
1140         struct sid2uid_state *state =
1141                 talloc_get_type_abort(private_data, struct sid2uid_state);
1142
1143         if (!success) {
1144                 DEBUG(5, ("Could not trigger lookup_sid\n"));
1145                 state->cont(state->private_data, False, 0);
1146                 return;
1147         }
1148
1149         if ((type != SID_NAME_USER) && (type != SID_NAME_COMPUTER)) {
1150                 DEBUG(5, ("SID is not a user\n"));
1151                 state->cont(state->private_data, False, 0);
1152                 return;
1153         }
1154
1155         state->username = talloc_strdup(state->mem_ctx, name);
1156
1157         /* Ask the possibly blocking remote IDMAP */
1158
1159         idmap_sid2uid_async(state->mem_ctx, &state->sid, False,
1160                             sid2uid_noalloc_recv, state);
1161 }
1162
1163 static void sid2uid_noalloc_recv(void *private_data, BOOL success, uid_t uid)
1164 {
1165         struct sid2uid_state *state =
1166                 talloc_get_type_abort(private_data, struct sid2uid_state);
1167
1168         if (success) {
1169                 DEBUG(10, ("found uid for sid %s in remote backend\n",
1170                            sid_string_static(&state->sid)));
1171                 state->cont(state->private_data, True, uid);
1172                 return;
1173         }
1174
1175         if (lp_winbind_trusted_domains_only() && 
1176             (sid_compare_domain(&state->sid, &find_our_domain()->sid) == 0)) {
1177                 DEBUG(10, ("Trying to go via nss\n"));
1178                 winbindd_name2uid_async(state->mem_ctx, state->username,
1179                                         sid2uid_name2uid_recv, state);
1180                 return;
1181         }
1182
1183         /* To be done: Here we're going to try the unixinfo pipe */
1184
1185         /* Now allocate a uid */
1186
1187         idmap_sid2uid_async(state->mem_ctx, &state->sid, True,
1188                             sid2uid_alloc_recv, state);
1189 }
1190
1191 static void sid2uid_alloc_recv(void *private_data, BOOL success, uid_t uid)
1192 {
1193         struct sid2uid_state *state =
1194                 talloc_get_type_abort(private_data, struct sid2uid_state);
1195
1196         if (!success) {
1197                 DEBUG(5, ("Could not allocate uid\n"));
1198                 state->cont(state->private_data, False, 0);
1199                 return;
1200         }
1201
1202         state->cont(state->private_data, True, uid);
1203 }
1204
1205 static void sid2uid_name2uid_recv(void *private_data, BOOL success, uid_t uid)
1206 {
1207         struct sid2uid_state *state =
1208                 talloc_get_type_abort(private_data, struct sid2uid_state);
1209         unid_t id;
1210
1211         if (!success) {
1212                 DEBUG(5, ("Could not find uid for name %s\n",
1213                           state->username));
1214                 state->cont(state->private_data, False, 0);
1215                 return;
1216         }
1217
1218         state->uid = uid;
1219
1220         id.uid = uid;
1221         idmap_set_mapping_async(state->mem_ctx, &state->sid, id, ID_USERID,
1222                                 sid2uid_set_mapping_recv, state);
1223 }
1224
1225 static void sid2uid_set_mapping_recv(void *private_data, BOOL success)
1226 {
1227         struct sid2uid_state *state =
1228                 talloc_get_type_abort(private_data, struct sid2uid_state);
1229
1230         if (!success) {
1231                 DEBUG(5, ("Could not set ID mapping for sid %s\n",
1232                           sid_string_static(&state->sid)));
1233                 state->cont(state->private_data, False, 0);
1234                 return;
1235         }
1236
1237         state->cont(state->private_data, True, state->uid);
1238 }
1239
1240 struct sid2gid_state {
1241         TALLOC_CTX *mem_ctx;
1242         DOM_SID sid;
1243         char *groupname;
1244         gid_t gid;
1245         void (*cont)(void *private_data, BOOL success, gid_t gid);
1246         void *private_data;
1247 };
1248
1249 static void sid2gid_lookup_sid_recv(void *private_data, BOOL success,
1250                                     const char *dom_name, const char *name,
1251                                     enum SID_NAME_USE type);
1252 static void sid2gid_noalloc_recv(void *private_data, BOOL success, gid_t gid);
1253 static void sid2gid_alloc_recv(void *private_data, BOOL success, gid_t gid);
1254 static void sid2gid_name2gid_recv(void *private_data, BOOL success, gid_t gid);
1255 static void sid2gid_set_mapping_recv(void *private_data, BOOL success);
1256
1257 void winbindd_sid2gid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
1258                             void (*cont)(void *private_data, BOOL success,
1259                                          gid_t gid),
1260                             void *private_data)
1261 {
1262         struct sid2gid_state *state;
1263         NTSTATUS result;
1264         gid_t gid;
1265
1266         if (idmap_proxyonly()) {
1267                 DEBUG(10, ("idmap proxy only\n"));
1268                 cont(private_data, False, 0);
1269                 return;
1270         }
1271
1272         /* Query only the local tdb, everything else might possibly block */
1273
1274         result = idmap_sid_to_gid(sid, &gid, ID_QUERY_ONLY|ID_CACHE_ONLY);
1275
1276         if (NT_STATUS_IS_OK(result)) {
1277                 cont(private_data, True, gid);
1278                 return;
1279         }
1280
1281         state = TALLOC_P(mem_ctx, struct sid2gid_state);
1282         if (state == NULL) {
1283                 DEBUG(0, ("talloc failed\n"));
1284                 cont(private_data, False, 0);
1285                 return;
1286         }
1287
1288         state->mem_ctx = mem_ctx;
1289         state->sid = *sid;
1290         state->cont = cont;
1291         state->private_data = private_data;
1292
1293         /* Let's see if it's really a user before allocating a gid */
1294
1295         winbindd_lookupsid_async(mem_ctx, sid, sid2gid_lookup_sid_recv, state);
1296 }
1297
1298 static void sid2gid_lookup_sid_recv(void *private_data, BOOL success,
1299                                     const char *dom_name, const char *name,
1300                                     enum SID_NAME_USE type)
1301 {
1302         struct sid2gid_state *state =
1303                 talloc_get_type_abort(private_data, struct sid2gid_state);
1304
1305         if (!success) {
1306                 DEBUG(5, ("Could not trigger lookup_sid\n"));
1307                 state->cont(state->private_data, False, 0);
1308                 return;
1309         }
1310
1311         if (((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
1312              (type != SID_NAME_WKN_GRP))) {
1313                 DEBUG(5, ("SID is not a group\n"));
1314                 state->cont(state->private_data, False, 0);
1315                 return;
1316         }
1317
1318         state->groupname = talloc_strdup(state->mem_ctx, name);
1319
1320         /* Ask the possibly blocking remote IDMAP and allocate  */
1321
1322         idmap_sid2gid_async(state->mem_ctx, &state->sid, False,
1323                             sid2gid_noalloc_recv, state);
1324 }
1325
1326 static void sid2gid_noalloc_recv(void *private_data, BOOL success, gid_t gid)
1327 {
1328         struct sid2gid_state *state =
1329                 talloc_get_type_abort(private_data, struct sid2gid_state);
1330
1331         if (success) {
1332                 DEBUG(10, ("found gid for sid %s in remote backend\n",
1333                            sid_string_static(&state->sid)));
1334                 state->cont(state->private_data, True, gid);
1335                 return;
1336         }
1337
1338         if (lp_winbind_trusted_domains_only() && 
1339             (sid_compare_domain(&state->sid, &find_our_domain()->sid) == 0)) {
1340                 DEBUG(10, ("Trying to go via nss\n"));
1341                 winbindd_name2gid_async(state->mem_ctx, state->groupname,
1342                                         sid2gid_name2gid_recv, state);
1343                 return;
1344         }
1345
1346         /* To be done: Here we're going to try the unixinfo pipe */
1347
1348         /* Now allocate a gid */
1349
1350         idmap_sid2gid_async(state->mem_ctx, &state->sid, True,
1351                             sid2gid_alloc_recv, state);
1352 }
1353
1354 static void sid2gid_alloc_recv(void *private_data, BOOL success, gid_t gid)
1355 {
1356         struct sid2gid_state *state =
1357                 talloc_get_type_abort(private_data, struct sid2gid_state);
1358
1359         if (!success) {
1360                 DEBUG(5, ("Could not allocate gid\n"));
1361                 state->cont(state->private_data, False, 0);
1362                 return;
1363         }
1364
1365         state->cont(state->private_data, True, gid);
1366 }
1367
1368 static void sid2gid_name2gid_recv(void *private_data, BOOL success, gid_t gid)
1369 {
1370         struct sid2gid_state *state =
1371                 talloc_get_type_abort(private_data, struct sid2gid_state);
1372         unid_t id;
1373
1374         if (!success) {
1375                 DEBUG(5, ("Could not find gid for name %s\n",
1376                           state->groupname));
1377                 state->cont(state->private_data, False, 0);
1378                 return;
1379         }
1380
1381         state->gid = gid;
1382
1383         id.gid = gid;
1384         idmap_set_mapping_async(state->mem_ctx, &state->sid, id, ID_GROUPID,
1385                                 sid2gid_set_mapping_recv, state);
1386 }
1387
1388 static void sid2gid_set_mapping_recv(void *private_data, BOOL success)
1389 {
1390         struct sid2gid_state *state =
1391                 talloc_get_type_abort(private_data, struct sid2gid_state);
1392
1393         if (!success) {
1394                 DEBUG(5, ("Could not set ID mapping for sid %s\n",
1395                           sid_string_static(&state->sid)));
1396                 state->cont(state->private_data, False, 0);
1397                 return;
1398         }
1399
1400         state->cont(state->private_data, True, state->gid);
1401 }
1402
1403 static void query_user_recv(TALLOC_CTX *mem_ctx, BOOL success,
1404                             struct winbindd_response *response,
1405                             void *c, void *private_data)
1406 {
1407         void (*cont)(void *priv, BOOL succ, const char *acct_name,
1408                      const char *full_name, const char *homedir, 
1409                      const char *shell, uint32 group_rid) = c;
1410
1411         if (!success) {
1412                 DEBUG(5, ("Could not trigger query_user\n"));
1413                 cont(private_data, False, NULL, NULL, NULL, NULL, -1);
1414                 return;
1415         }
1416
1417         cont(private_data, True, response->data.user_info.acct_name,
1418              response->data.user_info.full_name,
1419              response->data.user_info.homedir,
1420              response->data.user_info.shell,
1421              response->data.user_info.group_rid);
1422 }
1423
1424 void query_user_async(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
1425                       const DOM_SID *sid,
1426                       void (*cont)(void *private_data, BOOL success,
1427                                    const char *acct_name,
1428                                    const char *full_name,
1429                                    const char *homedir,
1430                                    const char *shell,
1431                                    uint32 group_rid),
1432                       void *private_data)
1433 {
1434         struct winbindd_request request;
1435         ZERO_STRUCT(request);
1436         request.cmd = WINBINDD_DUAL_USERINFO;
1437         sid_to_string(request.data.sid, sid);
1438         do_async_domain(mem_ctx, domain, &request, query_user_recv,
1439                         cont, private_data);
1440 }