41782ff0d151c8c75c94db44f30223a71de99309
[metze/samba/wb-ndr.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_child(&static_idmap_child,
48                     idmap_dispatch_table,
49                     "log.winbindd", "idmap");
50 }
51
52 struct winbindd_child *idmap_child(void)
53 {
54         return &static_idmap_child;
55 }
56
57 static void winbindd_set_mapping_recv(TALLOC_CTX *mem_ctx, bool success,
58                                    struct winbindd_response *response,
59                                    void *c, void *private_data)
60 {
61         void (*cont)(void *priv, bool succ) = (void (*)(void *, bool))c;
62
63         if (!success) {
64                 DEBUG(5, ("Could not trigger idmap_set_mapping\n"));
65                 cont(private_data, False);
66                 return;
67         }
68
69         if (response->result != WINBINDD_OK) {
70                 DEBUG(5, ("idmap_set_mapping returned an error\n"));
71                 cont(private_data, False);
72                 return;
73         }
74
75         cont(private_data, True);
76 }
77
78 void winbindd_set_mapping_async(TALLOC_CTX *mem_ctx, const struct id_map *map,
79                              void (*cont)(void *private_data, bool success),
80                              void *private_data)
81 {
82         struct winbindd_request request;
83         ZERO_STRUCT(request);
84         request.cmd = WINBINDD_DUAL_SET_MAPPING;
85         request.data.dual_idmapset.id = map->xid.id;
86         request.data.dual_idmapset.type = map->xid.type;
87         sid_to_fstring(request.data.dual_idmapset.sid, map->sid);
88
89         do_async(mem_ctx, idmap_child(), &request, winbindd_set_mapping_recv,
90                  (void *)cont, private_data);
91 }
92
93 enum winbindd_result winbindd_dual_set_mapping(struct winbindd_domain *domain,
94                                             struct winbindd_cli_state *state)
95 {
96         struct id_map map;
97         DOM_SID sid;
98         NTSTATUS result;
99
100         DEBUG(3, ("[%5lu]: dual_idmapset\n", (unsigned long)state->pid));
101
102         if (!string_to_sid(&sid, state->request.data.dual_idmapset.sid))
103                 return WINBINDD_ERROR;
104
105         map.sid = &sid;
106         map.xid.id = state->request.data.dual_idmapset.id;
107         map.xid.type = state->request.data.dual_idmapset.type;
108         map.status = ID_MAPPED;
109
110         result = idmap_set_mapping(&map);
111         return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
112 }
113
114 static void winbindd_set_hwm_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) = (void (*)(void *, bool))c;
119
120         if (!success) {
121                 DEBUG(5, ("Could not trigger idmap_set_hwm\n"));
122                 cont(private_data, False);
123                 return;
124         }
125
126         if (response->result != WINBINDD_OK) {
127                 DEBUG(5, ("idmap_set_hwm returned an error\n"));
128                 cont(private_data, False);
129                 return;
130         }
131
132         cont(private_data, True);
133 }
134
135 void winbindd_set_hwm_async(TALLOC_CTX *mem_ctx, const struct unixid *xid,
136                              void (*cont)(void *private_data, bool success),
137                              void *private_data)
138 {
139         struct winbindd_request request;
140         ZERO_STRUCT(request);
141         request.cmd = WINBINDD_DUAL_SET_HWM;
142         request.data.dual_idmapset.id = xid->id;
143         request.data.dual_idmapset.type = xid->type;
144
145         do_async(mem_ctx, idmap_child(), &request, winbindd_set_hwm_recv,
146                  (void *)cont, private_data);
147 }
148
149 enum winbindd_result winbindd_dual_set_hwm(struct winbindd_domain *domain,
150                                             struct winbindd_cli_state *state)
151 {
152         struct unixid xid;
153         NTSTATUS result;
154
155         DEBUG(3, ("[%5lu]: dual_set_hwm\n", (unsigned long)state->pid));
156
157         xid.id = state->request.data.dual_idmapset.id;
158         xid.type = state->request.data.dual_idmapset.type;
159
160         switch (xid.type) {
161         case ID_TYPE_UID:
162                 result = idmap_set_uid_hwm(&xid);
163                 break;
164         case ID_TYPE_GID:
165                 result = idmap_set_gid_hwm(&xid);
166                 break;
167         default:
168                 return WINBINDD_ERROR;
169         }
170         return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
171 }
172
173 static void winbindd_sid2uid_recv(TALLOC_CTX *mem_ctx, bool success,
174                                struct winbindd_response *response,
175                                void *c, void *private_data)
176 {
177         void (*cont)(void *priv, bool succ, uid_t uid) =
178                 (void (*)(void *, bool, uid_t))c;
179
180         if (!success) {
181                 DEBUG(5, ("Could not trigger sid2uid\n"));
182                 cont(private_data, False, 0);
183                 return;
184         }
185
186         if (response->result != WINBINDD_OK) {
187                 DEBUG(5, ("sid2uid returned an error\n"));
188                 cont(private_data, False, 0);
189                 return;
190         }
191
192         cont(private_data, True, response->data.uid);
193 }
194
195 void winbindd_sid2uid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
196                          void (*cont)(void *private_data, bool success, uid_t uid),
197                          void *private_data)
198 {
199         struct winbindd_request request;
200         ZERO_STRUCT(request);
201         request.cmd = WINBINDD_DUAL_SID2UID;
202         sid_to_fstring(request.data.dual_sid2id.sid, sid);
203         do_async(mem_ctx, idmap_child(), &request, winbindd_sid2uid_recv,
204                  (void *)cont, private_data);
205 }
206
207 enum winbindd_result winbindd_dual_sid2uid(struct winbindd_domain *domain,
208                                            struct winbindd_cli_state *state)
209 {
210         DOM_SID sid;
211         NTSTATUS result;
212
213         DEBUG(3, ("[%5lu]: sid to uid %s\n", (unsigned long)state->pid,
214                   state->request.data.dual_sid2id.sid));
215
216         if (!string_to_sid(&sid, state->request.data.dual_sid2id.sid)) {
217                 DEBUG(1, ("Could not get convert sid %s from string\n",
218                           state->request.data.dual_sid2id.sid));
219                 return WINBINDD_ERROR;
220         }
221
222         /* Find uid for this sid and return it, possibly ask the slow remote idmap */
223
224         result = idmap_sid_to_uid(&sid, &(state->response.data.uid));
225
226         return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
227 }
228
229 static void winbindd_sid2gid_recv(TALLOC_CTX *mem_ctx, bool success,
230                                struct winbindd_response *response,
231                                void *c, void *private_data)
232 {
233         void (*cont)(void *priv, bool succ, gid_t gid) =
234                 (void (*)(void *, bool, gid_t))c;
235
236         if (!success) {
237                 DEBUG(5, ("Could not trigger sid2gid\n"));
238                 cont(private_data, False, 0);
239                 return;
240         }
241
242         if (response->result != WINBINDD_OK) {
243                 DEBUG(5, ("sid2gid returned an error\n"));
244                 cont(private_data, False, 0);
245                 return;
246         }
247
248         cont(private_data, True, response->data.gid);
249 }
250
251 void winbindd_sid2gid_async(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
252                          void (*cont)(void *private_data, bool success, gid_t gid),
253                          void *private_data)
254 {
255         struct winbindd_request request;
256         ZERO_STRUCT(request);
257         request.cmd = WINBINDD_DUAL_SID2GID;
258         sid_to_fstring(request.data.dual_sid2id.sid, sid);
259
260         DEBUG(7,("winbindd_sid2gid_async: Resolving %s to a gid\n",
261                 request.data.dual_sid2id.sid));
262
263         do_async(mem_ctx, idmap_child(), &request, winbindd_sid2gid_recv,
264                  (void *)cont, private_data);
265 }
266
267 enum winbindd_result winbindd_dual_sid2gid(struct winbindd_domain *domain,
268                                            struct winbindd_cli_state *state)
269 {
270         DOM_SID sid;
271         NTSTATUS result;
272
273         DEBUG(3, ("[%5lu]: sid to gid %s\n", (unsigned long)state->pid,
274                   state->request.data.dual_sid2id.sid));
275
276         if (!string_to_sid(&sid, state->request.data.dual_sid2id.sid)) {
277                 DEBUG(1, ("Could not get convert sid %s from string\n",
278                           state->request.data.dual_sid2id.sid));
279                 return WINBINDD_ERROR;
280         }
281
282         /* Find gid for this sid and return it, possibly ask the slow remote idmap */
283
284         result = idmap_sid_to_gid(&sid, &state->response.data.gid);
285
286         DEBUG(10, ("winbindd_dual_sid2gid: 0x%08x - %s - %u\n",
287                    NT_STATUS_V(result), sid_string_dbg(&sid),
288                    state->response.data.gid));
289
290         return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
291 }
292
293 /* The following uid2sid/gid2sid functions has been contributed by
294  * Keith Reynolds <Keith.Reynolds@centrify.com> */
295
296 static void winbindd_uid2sid_recv(TALLOC_CTX *mem_ctx, bool success,
297                                   struct winbindd_response *response,
298                                   void *c, void *private_data)
299 {
300         void (*cont)(void *priv, bool succ, const char *sid) =
301                 (void (*)(void *, bool, const char *))c;
302
303         if (!success) {
304                 DEBUG(5, ("Could not trigger uid2sid\n"));
305                 cont(private_data, False, NULL);
306                 return;
307         }
308
309         if (response->result != WINBINDD_OK) {
310                 DEBUG(5, ("uid2sid returned an error\n"));
311                 cont(private_data, False, NULL);
312                 return;
313         }
314
315         cont(private_data, True, response->data.sid.sid);
316 }
317
318 void winbindd_uid2sid_async(TALLOC_CTX *mem_ctx, uid_t uid,
319                             void (*cont)(void *private_data, bool success, const char *sid),
320                             void *private_data)
321 {
322         struct winbindd_request request;
323
324         ZERO_STRUCT(request);
325         request.cmd = WINBINDD_DUAL_UID2SID;
326         request.data.uid = uid;
327         do_async(mem_ctx, idmap_child(), &request, winbindd_uid2sid_recv,
328                  (void *)cont, private_data);
329 }
330
331 enum winbindd_result winbindd_dual_uid2sid(struct winbindd_domain *domain,
332                                            struct winbindd_cli_state *state)
333 {
334         DOM_SID sid;
335         NTSTATUS result;
336
337         DEBUG(3,("[%5lu]: uid to sid %lu\n",
338                  (unsigned long)state->pid,
339                  (unsigned long) state->request.data.uid));
340
341         /* Find sid for this uid and return it, possibly ask the slow remote idmap */
342         result = idmap_uid_to_sid(&sid, state->request.data.uid);
343
344         if (NT_STATUS_IS_OK(result)) {
345                 sid_to_fstring(state->response.data.sid.sid, &sid);
346                 state->response.data.sid.type = SID_NAME_USER;
347                 return WINBINDD_OK;
348         }
349
350         return WINBINDD_ERROR;
351 }
352
353 static void winbindd_gid2sid_recv(TALLOC_CTX *mem_ctx, bool success,
354                                   struct winbindd_response *response,
355                                   void *c, void *private_data)
356 {
357         void (*cont)(void *priv, bool succ, const char *sid) =
358                 (void (*)(void *, bool, const char *))c;
359
360         if (!success) {
361                 DEBUG(5, ("Could not trigger gid2sid\n"));
362                 cont(private_data, False, NULL);
363                 return;
364         }
365
366         if (response->result != WINBINDD_OK) {
367                 DEBUG(5, ("gid2sid returned an error\n"));
368                 cont(private_data, False, NULL);
369                 return;
370         }
371
372         cont(private_data, True, response->data.sid.sid);
373 }
374
375 void winbindd_gid2sid_async(TALLOC_CTX *mem_ctx, gid_t gid,
376                             void (*cont)(void *private_data, bool success, const char *sid),
377                             void *private_data)
378 {
379         struct winbindd_request request;
380
381         ZERO_STRUCT(request);
382         request.cmd = WINBINDD_DUAL_GID2SID;
383         request.data.gid = gid;
384         do_async(mem_ctx, idmap_child(), &request, winbindd_gid2sid_recv,
385                  (void *)cont, private_data);
386 }
387
388 enum winbindd_result winbindd_dual_gid2sid(struct winbindd_domain *domain,
389                                            struct winbindd_cli_state *state)
390 {
391         DOM_SID sid;
392         NTSTATUS result;
393
394         DEBUG(3,("[%5lu]: gid %lu to sid\n",
395                 (unsigned long)state->pid,
396                 (unsigned long) state->request.data.gid));
397
398         /* Find sid for this gid and return it, possibly ask the slow remote idmap */
399         result = idmap_gid_to_sid(&sid, state->request.data.gid);
400
401         if (NT_STATUS_IS_OK(result)) {
402                 sid_to_fstring(state->response.data.sid.sid, &sid);
403                 DEBUG(10, ("[%5lu]: retrieved sid: %s\n",
404                            (unsigned long)state->pid,
405                            state->response.data.sid.sid));
406                 state->response.data.sid.type = SID_NAME_DOM_GRP;
407                 return WINBINDD_OK;
408         }
409
410         return WINBINDD_ERROR;
411 }
412
413 static const struct winbindd_child_dispatch_table idmap_dispatch_table[] = {
414         {
415                 .name           = "DUAL_SID2UID",
416                 .struct_cmd     = WINBINDD_DUAL_SID2UID,
417                 .struct_fn      = winbindd_dual_sid2uid,
418         },{
419                 .name           = "DUAL_SID2GID",
420                 .struct_cmd     = WINBINDD_DUAL_SID2GID,
421                 .struct_fn      = winbindd_dual_sid2gid,
422         },{
423                 .name           = "DUAL_UID2SID",
424                 .struct_cmd     = WINBINDD_DUAL_UID2SID,
425                 .struct_fn      = winbindd_dual_uid2sid,
426         },{
427                 .name           = "DUAL_GID2SID",
428                 .struct_cmd     = WINBINDD_DUAL_GID2SID,
429                 .struct_fn      = winbindd_dual_gid2sid,
430         },{
431                 .name           = "DUAL_SET_MAPPING",
432                 .struct_cmd     = WINBINDD_DUAL_SET_MAPPING,
433                 .struct_fn      = winbindd_dual_set_mapping,
434         },{
435                 .name           = "DUAL_SET_HWMS",
436                 .struct_cmd     = WINBINDD_DUAL_SET_HWM,
437                 .struct_fn      = winbindd_dual_set_hwm,
438         },{
439                 .name           = "ALLOCATE_UID",
440                 .struct_cmd     = WINBINDD_ALLOCATE_UID,
441                 .struct_fn      = winbindd_dual_allocate_uid,
442         },{
443                 .name           = "ALLOCATE_GID",
444                 .struct_cmd     = WINBINDD_ALLOCATE_GID,
445                 .struct_fn      = winbindd_dual_allocate_gid,
446         },{
447                 .name           = NULL,
448         }
449 };