r25598: Add missing become_root/unbecome_root around calls of add_aliases.
[tprouty/samba.git] / source / winbindd / winbindd_idmap.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    Async helpers for blocking functions
5
6    Copyright (C) Volker Lendecke 2005
7    Copyright (C) Gerald Carter 2006
8    Copyright (C) Simo Sorce 2007
9
10    The helpers always consist of three functions:
11
12    * A request setup function that takes the necessary parameters together
13      with a continuation function that is to be called upon completion
14
15    * A private continuation function that is internal only. This is to be
16      called by the lower-level functions in do_async(). Its only task is to
17      properly call the continuation function named above.
18
19    * A worker function that is called inside the appropriate child process.
20
21    This program is free software; you can redistribute it and/or modify
22    it under the terms of the GNU General Public License as published by
23    the Free Software Foundation; either version 3 of the License, or
24    (at your option) any later version.
25
26    This program is distributed in the hope that it will be useful,
27    but WITHOUT ANY WARRANTY; without even the implied warranty of
28    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
29    GNU General Public License for more details.
30
31    You should have received a copy of the GNU General Public License
32    along with this program.  If not, see <http://www.gnu.org/licenses/>.
33 */
34
35 #include "includes.h"
36 #include "winbindd.h"
37
38 #undef DBGC_CLASS
39 #define DBGC_CLASS DBGC_WINBIND
40
41 static const struct winbindd_child_dispatch_table idmap_dispatch_table[];
42
43 static struct winbindd_child static_idmap_child;
44
45 void init_idmap_child(void)
46 {
47         setup_domain_child(NULL,
48                            &static_idmap_child,
49                            idmap_dispatch_table,
50                            "idmap");
51 }
52
53 struct winbindd_child *idmap_child(void)
54 {
55         return &static_idmap_child;
56 }
57
58 static void winbindd_set_mapping_recv(TALLOC_CTX *mem_ctx, BOOL success,
59                                    struct winbindd_response *response,
60                                    void *c, void *private_data)
61 {
62         void (*cont)(void *priv, BOOL succ) = (void (*)(void *, BOOL))c;
63
64         if (!success) {
65                 DEBUG(5, ("Could not trigger idmap_set_mapping\n"));
66                 cont(private_data, False);
67                 return;
68         }
69
70         if (response->result != WINBINDD_OK) {
71                 DEBUG(5, ("idmap_set_mapping returned an error\n"));
72                 cont(private_data, False);
73                 return;
74         }
75
76         cont(private_data, True);
77 }
78
79 void winbindd_set_mapping_async(TALLOC_CTX *mem_ctx, const struct id_map *map,
80                              void (*cont)(void *private_data, BOOL success),
81                              void *private_data)
82 {
83         struct winbindd_request request;
84         ZERO_STRUCT(request);
85         request.cmd = WINBINDD_DUAL_SET_MAPPING;
86         request.data.dual_idmapset.id = map->xid.id;
87         request.data.dual_idmapset.type = map->xid.type;
88         sid_to_string(request.data.dual_idmapset.sid, map->sid);
89
90         do_async(mem_ctx, idmap_child(), &request, winbindd_set_mapping_recv,
91                  (void *)cont, private_data);
92 }
93
94 enum winbindd_result winbindd_dual_set_mapping(struct winbindd_domain *domain,
95                                             struct winbindd_cli_state *state)
96 {
97         struct id_map map;
98         DOM_SID sid;
99         NTSTATUS result;
100
101         DEBUG(3, ("[%5lu]: dual_idmapset\n", (unsigned long)state->pid));
102
103         if (!string_to_sid(&sid, state->request.data.dual_idmapset.sid))
104                 return WINBINDD_ERROR;
105
106         map.sid = &sid;
107         map.xid.id = state->request.data.dual_idmapset.id;
108         map.xid.type = state->request.data.dual_idmapset.type;
109         map.status = ID_MAPPED;
110
111         result = idmap_set_mapping(&map);
112         return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
113 }
114
115 static void winbindd_set_hwm_recv(TALLOC_CTX *mem_ctx, BOOL success,
116                                    struct winbindd_response *response,
117                                    void *c, void *private_data)
118 {
119         void (*cont)(void *priv, BOOL succ) = (void (*)(void *, BOOL))c;
120
121         if (!success) {
122                 DEBUG(5, ("Could not trigger idmap_set_hwm\n"));
123                 cont(private_data, False);
124                 return;
125         }
126
127         if (response->result != WINBINDD_OK) {
128                 DEBUG(5, ("idmap_set_hwm returned an error\n"));
129                 cont(private_data, False);
130                 return;
131         }
132
133         cont(private_data, True);
134 }
135
136 void winbindd_set_hwm_async(TALLOC_CTX *mem_ctx, const struct unixid *xid,
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_SET_HWM;
143         request.data.dual_idmapset.id = xid->id;
144         request.data.dual_idmapset.type = xid->type;
145
146         do_async(mem_ctx, idmap_child(), &request, winbindd_set_hwm_recv,
147                  (void *)cont, private_data);
148 }
149
150 enum winbindd_result winbindd_dual_set_hwm(struct winbindd_domain *domain,
151                                             struct winbindd_cli_state *state)
152 {
153         struct unixid xid;
154         NTSTATUS result;
155
156         DEBUG(3, ("[%5lu]: dual_set_hwm\n", (unsigned long)state->pid));
157
158         xid.id = state->request.data.dual_idmapset.id;
159         xid.type = state->request.data.dual_idmapset.type;
160
161         switch (xid.type) {
162         case ID_TYPE_UID:
163                 result = idmap_set_uid_hwm(&xid);
164                 break;
165         case ID_TYPE_GID:
166                 result = idmap_set_gid_hwm(&xid);
167                 break;
168         default:
169                 return WINBINDD_ERROR;
170         }
171         return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
172 }
173
174 static void winbindd_sids2xids_recv(TALLOC_CTX *mem_ctx, BOOL success,
175                                struct winbindd_response *response,
176                                void *c, void *private_data)
177 {
178         void (*cont)(void *priv, BOOL succ, void *, int) =
179                 (void (*)(void *, BOOL, void *, int))c;
180
181         if (!success) {
182                 DEBUG(5, ("Could not trigger sids2xids\n"));
183                 cont(private_data, False, NULL, 0);
184                 return;
185         }
186
187         if (response->result != WINBINDD_OK) {
188                 DEBUG(5, ("sids2xids returned an error\n"));
189                 cont(private_data, False, NULL, 0);
190                 return;
191         }
192
193         cont(private_data, True, response->extra_data.data, response->length - sizeof(response));
194 }
195
196 void winbindd_sids2xids_async(TALLOC_CTX *mem_ctx, void *sids, int size,
197                          void (*cont)(void *private_data, BOOL success, void *data, int len),
198                          void *private_data)
199 {
200         struct winbindd_request request;
201         ZERO_STRUCT(request);
202         request.cmd = WINBINDD_DUAL_SIDS2XIDS;
203         request.extra_data.data = (char *)sids;
204         request.extra_len = size;
205         do_async(mem_ctx, idmap_child(), &request, winbindd_sids2xids_recv,
206                  (void *)cont, private_data);
207 }
208
209 enum winbindd_result winbindd_dual_sids2xids(struct winbindd_domain *domain,
210                                            struct winbindd_cli_state *state)
211 {
212         DOM_SID *sids;
213         struct unixid *xids;
214         struct id_map **ids;
215         NTSTATUS result;
216         int num, i;
217
218         DEBUG(3, ("[%5lu]: sids to unix ids\n", (unsigned long)state->pid));
219
220         if (state->request.extra_len == 0) {
221                 DEBUG(0, ("Invalid buffer size!\n"));
222                 return WINBINDD_ERROR;
223         }
224
225         sids = (DOM_SID *)state->request.extra_data.data;
226         num = state->request.extra_len / sizeof(DOM_SID);
227
228         ids = TALLOC_ZERO_ARRAY(state->mem_ctx, struct id_map *, num + 1);
229         if ( ! ids) {
230                 DEBUG(0, ("Out of memory!\n"));
231                 return WINBINDD_ERROR;
232         }
233         for (i = 0; i < num; i++) {
234                 ids[i] = TALLOC_P(ids, struct id_map);
235                 if ( ! ids[i]) {
236                         DEBUG(0, ("Out of memory!\n"));
237                         talloc_free(ids);
238                         return WINBINDD_ERROR;
239                 }
240                 ids[i]->sid = &sids[i];
241         }
242
243         result = idmap_sids_to_unixids(ids);
244
245         if (NT_STATUS_IS_OK(result)) {
246
247                 xids = SMB_MALLOC_ARRAY(struct unixid, num);
248                 if ( ! xids) {
249                         DEBUG(0, ("Out of memory!\n"));
250                         talloc_free(ids);
251                         return WINBINDD_ERROR;
252                 }
253
254                 for (i = 0; i < num; i++) {
255                         if (ids[i]->status == ID_MAPPED) {
256                                 xids[i].type = ids[i]->xid.type;
257                                 xids[i].id = ids[i]->xid.id;
258                         } else {
259                                 xids[i].type = -1;
260                         }
261                 }
262
263                 state->response.length = sizeof(state->response) + (sizeof(struct unixid) * num);
264                 state->response.extra_data.data = xids;
265
266         } else {
267                 DEBUG (2, ("idmap_sids_to_unixids returned an error: 0x%08x\n", NT_STATUS_V(result)));
268                 talloc_free(ids);
269                 return WINBINDD_ERROR;
270         }
271
272         talloc_free(ids);
273         return WINBINDD_OK;
274 }
275
276 static void winbindd_sid2uid_recv(TALLOC_CTX *mem_ctx, BOOL success,
277                                struct winbindd_response *response,
278                                void *c, void *private_data)
279 {
280         void (*cont)(void *priv, BOOL succ, uid_t uid) =
281                 (void (*)(void *, BOOL, uid_t))c;
282
283         if (!success) {
284                 DEBUG(5, ("Could not trigger sid2uid\n"));
285                 cont(private_data, False, 0);
286                 return;
287         }
288
289         if (response->result != WINBINDD_OK) {
290                 DEBUG(5, ("sid2uid returned an error\n"));
291                 cont(private_data, False, 0);
292                 return;
293         }
294
295         cont(private_data, True, response->data.uid);
296 }
297
298 void winbindd_sid2uid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
299                          void (*cont)(void *private_data, BOOL success, uid_t uid),
300                          void *private_data)
301 {
302         struct winbindd_request request;
303         ZERO_STRUCT(request);
304         request.cmd = WINBINDD_DUAL_SID2UID;
305         sid_to_string(request.data.dual_sid2id.sid, sid);
306         do_async(mem_ctx, idmap_child(), &request, winbindd_sid2uid_recv,
307                  (void *)cont, private_data);
308 }
309
310 enum winbindd_result winbindd_dual_sid2uid(struct winbindd_domain *domain,
311                                            struct winbindd_cli_state *state)
312 {
313         DOM_SID sid;
314         NTSTATUS result;
315
316         DEBUG(3, ("[%5lu]: sid to uid %s\n", (unsigned long)state->pid,
317                   state->request.data.dual_sid2id.sid));
318
319         if (!string_to_sid(&sid, state->request.data.dual_sid2id.sid)) {
320                 DEBUG(1, ("Could not get convert sid %s from string\n",
321                           state->request.data.dual_sid2id.sid));
322                 return WINBINDD_ERROR;
323         }
324
325         /* Find uid for this sid and return it, possibly ask the slow remote idmap */
326
327         result = idmap_sid_to_uid(&sid, &(state->response.data.uid));
328
329         return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
330 }
331
332 #if 0   /* not used */
333 static void uid2name_recv(TALLOC_CTX *mem_ctx, BOOL success,
334                           struct winbindd_response *response,
335                           void *c, void *private_data);
336
337 void winbindd_uid2name_async(TALLOC_CTX *mem_ctx, uid_t uid,
338                              void (*cont)(void *private_data, BOOL success,
339                                           const char *name),
340                              void *private_data)
341 {
342         struct winbindd_request request;
343         ZERO_STRUCT(request);
344         request.cmd = WINBINDD_DUAL_UID2NAME;
345         request.data.uid = uid;
346         do_async(mem_ctx, idmap_child(), &request, uid2name_recv,
347                  (void *)cont, private_data);
348 }
349 #endif  /* not used */
350
351 enum winbindd_result winbindd_dual_uid2name(struct winbindd_domain *domain,
352                                             struct winbindd_cli_state *state)
353 {
354         struct passwd *pw;
355
356         DEBUG(3, ("[%5lu]: uid2name %lu\n", (unsigned long)state->pid,
357                   (unsigned long)state->request.data.uid));
358
359         pw = getpwuid(state->request.data.uid);
360         if (pw == NULL) {
361                 DEBUG(5, ("User %lu not found\n",
362                           (unsigned long)state->request.data.uid));
363                 return WINBINDD_ERROR;
364         }
365
366         fstrcpy(state->response.data.name.name, pw->pw_name);
367         return WINBINDD_OK;
368 }
369
370 #if 0   /* not used */
371 static void uid2name_recv(TALLOC_CTX *mem_ctx, BOOL success,
372                           struct winbindd_response *response,
373                           void *c, void *private_data)
374 {
375         void (*cont)(void *priv, BOOL succ, const char *name) =
376                 (void (*)(void *, BOOL, const char *))c;
377
378         if (!success) {
379                 DEBUG(5, ("Could not trigger uid2name\n"));
380                 cont(private_data, False, NULL);
381                 return;
382         }
383
384         if (response->result != WINBINDD_OK) {
385                 DEBUG(5, ("uid2name returned an error\n"));
386                 cont(private_data, False, NULL);
387                 return;
388         }
389
390         cont(private_data, True, response->data.name.name);
391 }
392
393 static void name2uid_recv(TALLOC_CTX *mem_ctx, BOOL success,
394                           struct winbindd_response *response,
395                           void *c, void *private_data);
396
397 static void winbindd_name2uid_async(TALLOC_CTX *mem_ctx, const char *name,
398                                     void (*cont)(void *private_data, BOOL success,
399                                                  uid_t uid),
400                                     void *private_data)
401 {
402         struct winbindd_request request;
403         ZERO_STRUCT(request);
404         request.cmd = WINBINDD_DUAL_NAME2UID;
405         fstrcpy(request.data.username, name);
406         do_async(mem_ctx, idmap_child(), &request, name2uid_recv,
407                  (void *)cont, private_data);
408 }
409 #endif  /* not used */
410
411 enum winbindd_result winbindd_dual_name2uid(struct winbindd_domain *domain,
412                                             struct winbindd_cli_state *state)
413 {
414         struct passwd *pw;
415
416         /* Ensure null termination */
417         state->request.data.username
418                 [sizeof(state->request.data.username)-1] = '\0';
419
420         DEBUG(3, ("[%5lu]: name2uid %s\n", (unsigned long)state->pid,
421                   state->request.data.username));
422
423         pw = getpwnam(state->request.data.username);
424         if (pw == NULL) {
425                 return WINBINDD_ERROR;
426         }
427
428         state->response.data.uid = pw->pw_uid;
429         return WINBINDD_OK;
430 }
431
432 #if 0   /* not used */
433 static void name2uid_recv(TALLOC_CTX *mem_ctx, BOOL success,
434                           struct winbindd_response *response,
435                           void *c, void *private_data)
436 {
437         void (*cont)(void *priv, BOOL succ, uid_t uid) =
438                 (void (*)(void *, BOOL, uid_t))c;
439
440         if (!success) {
441                 DEBUG(5, ("Could not trigger name2uid\n"));
442                 cont(private_data, False, 0);
443                 return;
444         }
445
446         if (response->result != WINBINDD_OK) {
447                 DEBUG(5, ("name2uid returned an error\n"));
448                 cont(private_data, False, 0);
449                 return;
450         }
451
452         cont(private_data, True, response->data.uid);
453 }
454 #endif  /* not used */
455
456 static void winbindd_sid2gid_recv(TALLOC_CTX *mem_ctx, BOOL success,
457                                struct winbindd_response *response,
458                                void *c, void *private_data)
459 {
460         void (*cont)(void *priv, BOOL succ, gid_t gid) =
461                 (void (*)(void *, BOOL, gid_t))c;
462
463         if (!success) {
464                 DEBUG(5, ("Could not trigger sid2gid\n"));
465                 cont(private_data, False, 0);
466                 return;
467         }
468
469         if (response->result != WINBINDD_OK) {
470                 DEBUG(5, ("sid2gid returned an error\n"));
471                 cont(private_data, False, 0);
472                 return;
473         }
474
475         cont(private_data, True, response->data.gid);
476 }
477
478 void winbindd_sid2gid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
479                          void (*cont)(void *private_data, BOOL success, gid_t gid),
480                          void *private_data)
481 {
482         struct winbindd_request request;
483         ZERO_STRUCT(request);
484         request.cmd = WINBINDD_DUAL_SID2GID;
485         sid_to_string(request.data.dual_sid2id.sid, sid);
486
487         DEBUG(7,("winbindd_sid2gid_async: Resolving %s to a gid\n",
488                 request.data.dual_sid2id.sid));
489
490         do_async(mem_ctx, idmap_child(), &request, winbindd_sid2gid_recv,
491                  (void *)cont, private_data);
492 }
493
494 enum winbindd_result winbindd_dual_sid2gid(struct winbindd_domain *domain,
495                                            struct winbindd_cli_state *state)
496 {
497         DOM_SID sid;
498         NTSTATUS result;
499
500         DEBUG(3, ("[%5lu]: sid to gid %s\n", (unsigned long)state->pid,
501                   state->request.data.dual_sid2id.sid));
502
503         if (!string_to_sid(&sid, state->request.data.dual_sid2id.sid)) {
504                 DEBUG(1, ("Could not get convert sid %s from string\n",
505                           state->request.data.dual_sid2id.sid));
506                 return WINBINDD_ERROR;
507         }
508
509         /* Find gid for this sid and return it, possibly ask the slow remote idmap */
510
511         result = idmap_sid_to_gid(&sid, &state->response.data.gid);
512
513         DEBUG(10, ("winbindd_dual_sid2gid: 0x%08x - %s - %u\n", NT_STATUS_V(result), sid_string_static(&sid), state->response.data.gid));
514
515         return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
516 }
517
518 static void gid2name_recv(TALLOC_CTX *mem_ctx, BOOL success,
519                           struct winbindd_response *response,
520                           void *c, void *private_data)
521 {
522         void (*cont)(void *priv, BOOL succ, const char *name) =
523                 (void (*)(void *, BOOL, const char *))c;
524
525         if (!success) {
526                 DEBUG(5, ("Could not trigger gid2name\n"));
527                 cont(private_data, False, NULL);
528                 return;
529         }
530
531         if (response->result != WINBINDD_OK) {
532                 DEBUG(5, ("gid2name returned an error\n"));
533                 cont(private_data, False, NULL);
534                 return;
535         }
536
537         cont(private_data, True, response->data.name.name);
538 }
539
540 void winbindd_gid2name_async(TALLOC_CTX *mem_ctx, gid_t gid,
541                              void (*cont)(void *private_data, BOOL success,
542                                           const char *name),
543                              void *private_data)
544 {
545         struct winbindd_request request;
546         ZERO_STRUCT(request);
547         request.cmd = WINBINDD_DUAL_GID2NAME;
548         request.data.gid = gid;
549         do_async(mem_ctx, idmap_child(), &request, gid2name_recv,
550                  (void *)cont, private_data);
551 }
552
553 enum winbindd_result winbindd_dual_gid2name(struct winbindd_domain *domain,
554                                             struct winbindd_cli_state *state)
555 {
556         struct group *gr;
557
558         DEBUG(3, ("[%5lu]: gid2name %lu\n", (unsigned long)state->pid,
559                   (unsigned long)state->request.data.gid));
560
561         gr = getgrgid(state->request.data.gid);
562         if (gr == NULL)
563                 return WINBINDD_ERROR;
564
565         fstrcpy(state->response.data.name.name, gr->gr_name);
566         return WINBINDD_OK;
567 }
568
569 #if 0   /* not used */
570 static void name2gid_recv(TALLOC_CTX *mem_ctx, BOOL success,
571                           struct winbindd_response *response,
572                           void *c, void *private_data);
573
574 static void winbindd_name2gid_async(TALLOC_CTX *mem_ctx, const char *name,
575                                     void (*cont)(void *private_data, BOOL success,
576                                                  gid_t gid),
577                                     void *private_data)
578 {
579         struct winbindd_request request;
580         ZERO_STRUCT(request);
581         request.cmd = WINBINDD_DUAL_NAME2GID;
582         fstrcpy(request.data.groupname, name);
583         do_async(mem_ctx, idmap_child(), &request, name2gid_recv,
584                  (void *)cont, private_data);
585 }
586 #endif  /* not used */
587
588 enum winbindd_result winbindd_dual_name2gid(struct winbindd_domain *domain,
589                                             struct winbindd_cli_state *state)
590 {
591         struct group *gr;
592
593         /* Ensure null termination */
594         state->request.data.groupname
595                 [sizeof(state->request.data.groupname)-1] = '\0';
596
597         DEBUG(3, ("[%5lu]: name2gid %s\n", (unsigned long)state->pid,
598                   state->request.data.groupname));
599
600         gr = getgrnam(state->request.data.groupname);
601         if (gr == NULL) {
602                 return WINBINDD_ERROR;
603         }
604
605         state->response.data.gid = gr->gr_gid;
606         return WINBINDD_OK;
607 }
608
609 #if 0   /* not used */
610 static void name2gid_recv(TALLOC_CTX *mem_ctx, BOOL success,
611                           struct winbindd_response *response,
612                           void *c, void *private_data)
613 {
614         void (*cont)(void *priv, BOOL succ, gid_t gid) =
615                 (void (*)(void *, BOOL, gid_t))c;
616
617         if (!success) {
618                 DEBUG(5, ("Could not trigger name2gid\n"));
619                 cont(private_data, False, 0);
620                 return;
621         }
622
623         if (response->result != WINBINDD_OK) {
624                 DEBUG(5, ("name2gid returned an error\n"));
625                 cont(private_data, False, 0);
626                 return;
627         }
628
629         cont(private_data, True, response->data.gid);
630 }
631 #endif  /* not used */
632
633 /* The following uid2sid/gid2sid functions has been contributed by
634  * Keith Reynolds <Keith.Reynolds@centrify.com> */
635
636 static void winbindd_uid2sid_recv(TALLOC_CTX *mem_ctx, BOOL success,
637                                   struct winbindd_response *response,
638                                   void *c, void *private_data)
639 {
640         void (*cont)(void *priv, BOOL succ, const char *sid) =
641                 (void (*)(void *, BOOL, const char *))c;
642
643         if (!success) {
644                 DEBUG(5, ("Could not trigger uid2sid\n"));
645                 cont(private_data, False, NULL);
646                 return;
647         }
648
649         if (response->result != WINBINDD_OK) {
650                 DEBUG(5, ("uid2sid returned an error\n"));
651                 cont(private_data, False, NULL);
652                 return;
653         }
654
655         cont(private_data, True, response->data.sid.sid);
656 }
657
658 void winbindd_uid2sid_async(TALLOC_CTX *mem_ctx, uid_t uid,
659                             void (*cont)(void *private_data, BOOL success, const char *sid),
660                             void *private_data)
661 {
662         struct winbindd_request request;
663
664         ZERO_STRUCT(request);
665         request.cmd = WINBINDD_DUAL_UID2SID;
666         request.data.uid = uid;
667         do_async(mem_ctx, idmap_child(), &request, winbindd_uid2sid_recv,
668                  (void *)cont, private_data);
669 }
670
671 enum winbindd_result winbindd_dual_uid2sid(struct winbindd_domain *domain,
672                                            struct winbindd_cli_state *state)
673 {
674         DOM_SID sid;
675         NTSTATUS result;
676
677         DEBUG(3,("[%5lu]: uid to sid %lu\n",
678                  (unsigned long)state->pid,
679                  (unsigned long) state->request.data.uid));
680
681         /* Find sid for this uid and return it, possibly ask the slow remote idmap */
682         result = idmap_uid_to_sid(&sid, state->request.data.uid);
683
684         if (NT_STATUS_IS_OK(result)) {
685                 sid_to_string(state->response.data.sid.sid, &sid);
686                 state->response.data.sid.type = SID_NAME_USER;
687                 return WINBINDD_OK;
688         }
689
690         return WINBINDD_ERROR;
691 }
692
693 static void winbindd_gid2sid_recv(TALLOC_CTX *mem_ctx, BOOL success,
694                                   struct winbindd_response *response,
695                                   void *c, void *private_data)
696 {
697         void (*cont)(void *priv, BOOL succ, const char *sid) =
698                 (void (*)(void *, BOOL, const char *))c;
699
700         if (!success) {
701                 DEBUG(5, ("Could not trigger gid2sid\n"));
702                 cont(private_data, False, NULL);
703                 return;
704         }
705
706         if (response->result != WINBINDD_OK) {
707                 DEBUG(5, ("gid2sid returned an error\n"));
708                 cont(private_data, False, NULL);
709                 return;
710         }
711
712         cont(private_data, True, response->data.sid.sid);
713 }
714
715 void winbindd_gid2sid_async(TALLOC_CTX *mem_ctx, gid_t gid,
716                             void (*cont)(void *private_data, BOOL success, const char *sid),
717                             void *private_data)
718 {
719         struct winbindd_request request;
720
721         ZERO_STRUCT(request);
722         request.cmd = WINBINDD_DUAL_GID2SID;
723         request.data.gid = gid;
724         do_async(mem_ctx, idmap_child(), &request, winbindd_gid2sid_recv,
725                  (void *)cont, private_data);
726 }
727
728 enum winbindd_result winbindd_dual_gid2sid(struct winbindd_domain *domain,
729                                            struct winbindd_cli_state *state)
730 {
731         DOM_SID sid;
732         NTSTATUS result;
733
734         DEBUG(3,("[%5lu]: gid %lu to sid\n",
735                 (unsigned long)state->pid,
736                 (unsigned long) state->request.data.gid));
737
738         /* Find sid for this gid and return it, possibly ask the slow remote idmap */
739         result = idmap_gid_to_sid(&sid, state->request.data.gid);
740
741         if (NT_STATUS_IS_OK(result)) {
742                 sid_to_string(state->response.data.sid.sid, &sid);
743                 DEBUG(10, ("[%5lu]: retrieved sid: %s\n",
744                            (unsigned long)state->pid,
745                            state->response.data.sid.sid));
746                 state->response.data.sid.type = SID_NAME_DOM_GRP;
747                 return WINBINDD_OK;
748         }
749
750         return WINBINDD_ERROR;
751 }
752
753 static void winbindd_dump_id_maps_recv(TALLOC_CTX *mem_ctx, BOOL success,
754                                struct winbindd_response *response,
755                                void *c, void *private_data)
756 {
757         void (*cont)(void *priv, BOOL succ) =
758                 (void (*)(void *, BOOL))c;
759
760         if (!success) {
761                 DEBUG(5, ("Could not trigger a map dump\n"));
762                 cont(private_data, False);
763                 return;
764         }
765
766         if (response->result != WINBINDD_OK) {
767                 DEBUG(5, ("idmap dump maps returned an error\n"));
768                 cont(private_data, False);
769                 return;
770         }
771
772         cont(private_data, True);
773 }
774
775 void winbindd_dump_maps_async(TALLOC_CTX *mem_ctx, void *data, int size,
776                          void (*cont)(void *private_data, BOOL success),
777                          void *private_data)
778 {
779         struct winbindd_request request;
780         ZERO_STRUCT(request);
781         request.cmd = WINBINDD_DUAL_DUMP_MAPS;
782         request.extra_data.data = (char *)data;
783         request.extra_len = size;
784         do_async(mem_ctx, idmap_child(), &request, winbindd_dump_id_maps_recv,
785                  (void *)cont, private_data);
786 }
787
788 enum winbindd_result winbindd_dual_dump_maps(struct winbindd_domain *domain,
789                                            struct winbindd_cli_state *state)
790 {
791         DEBUG(3, ("[%5lu]: dual dump maps\n", (unsigned long)state->pid));
792
793         idmap_dump_maps((char *)state->request.extra_data.data);
794
795         return WINBINDD_OK;
796 }
797
798 static const struct winbindd_child_dispatch_table idmap_dispatch_table[] = {
799
800         { WINBINDD_DUAL_SID2UID,         winbindd_dual_sid2uid,               "DUAL_SID2UID" },
801         { WINBINDD_DUAL_SID2GID,         winbindd_dual_sid2gid,               "DUAL_SID2GID" },
802 #if 0   /* DISABLED until we fix the interface in Samba 3.0.26 --jerry */
803         { WINBINDD_DUAL_SIDS2XIDS,       winbindd_dual_sids2xids,             "DUAL_SIDS2XIDS" },
804 #endif  /* end DISABLED */
805         { WINBINDD_DUAL_UID2SID,         winbindd_dual_uid2sid,               "DUAL_UID2SID" },
806         { WINBINDD_DUAL_GID2SID,         winbindd_dual_gid2sid,               "DUAL_GID2SID" },
807         { WINBINDD_DUAL_UID2NAME,        winbindd_dual_uid2name,              "DUAL_UID2NAME" },
808         { WINBINDD_DUAL_NAME2UID,        winbindd_dual_name2uid,              "DUAL_NAME2UID" },
809         { WINBINDD_DUAL_GID2NAME,        winbindd_dual_gid2name,              "DUAL_GID2NAME" },
810         { WINBINDD_DUAL_NAME2GID,        winbindd_dual_name2gid,              "DUAL_NAME2GID" },
811         { WINBINDD_DUAL_SET_MAPPING,     winbindd_dual_set_mapping,           "DUAL_SET_MAPPING" },
812         { WINBINDD_DUAL_SET_HWM,         winbindd_dual_set_hwm,               "DUAL_SET_HWMS" },
813         { WINBINDD_DUAL_DUMP_MAPS,       winbindd_dual_dump_maps,             "DUAL_DUMP_MAPS" },
814         { WINBINDD_ALLOCATE_UID,         winbindd_dual_allocate_uid,          "ALLOCATE_UID" },
815         { WINBINDD_ALLOCATE_GID,         winbindd_dual_allocate_gid,          "ALLOCATE_GID" },
816         /* End of list */
817
818         { WINBINDD_NUM_CMDS, NULL, "NONE" }
819 };