r25152: fix headers used in wbinfo.c
[ira/wip.git] / source3 / nsswitch / winbindd_sid.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    Winbind daemon - sid related functions
5
6    Copyright (C) Tim Potter 2000
7    
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "winbindd.h"
24
25 #undef DBGC_CLASS
26 #define DBGC_CLASS DBGC_WINBIND
27
28 /* Convert a string  */
29
30 static void lookupsid_recv(void *private_data, BOOL success,
31                            const char *dom_name, const char *name,
32                            enum lsa_SidType type);
33
34 void winbindd_lookupsid(struct winbindd_cli_state *state)
35 {
36         DOM_SID sid;
37
38         /* Ensure null termination */
39         state->request.data.sid[sizeof(state->request.data.sid)-1]='\0';
40
41         DEBUG(3, ("[%5lu]: lookupsid %s\n", (unsigned long)state->pid, 
42                   state->request.data.sid));
43
44         if (!string_to_sid(&sid, state->request.data.sid)) {
45                 DEBUG(5, ("%s not a SID\n", state->request.data.sid));
46                 request_error(state);
47                 return;
48         }
49
50         winbindd_lookupsid_async(state->mem_ctx, &sid, lookupsid_recv, state);
51 }
52
53 static void lookupsid_recv(void *private_data, BOOL success,
54                            const char *dom_name, const char *name,
55                            enum lsa_SidType type)
56 {
57         struct winbindd_cli_state *state =
58                 talloc_get_type_abort(private_data, struct winbindd_cli_state);
59
60         if (!success) {
61                 DEBUG(5, ("lookupsid returned an error\n"));
62                 request_error(state);
63                 return;
64         }
65
66         fstrcpy(state->response.data.name.dom_name, dom_name);
67         fstrcpy(state->response.data.name.name, name);
68         state->response.data.name.type = type;
69         request_ok(state);
70 }
71
72 /**
73  * Look up the SID for a qualified name.  
74  **/
75
76 static void lookupname_recv(void *private_data, BOOL success,
77                             const DOM_SID *sid, enum lsa_SidType type);
78
79 void winbindd_lookupname(struct winbindd_cli_state *state)
80 {
81         char *name_domain, *name_user;
82         char *p;
83
84         /* Ensure null termination */
85         state->request.data.name.dom_name[sizeof(state->request.data.name.dom_name)-1]='\0';
86
87         /* Ensure null termination */
88         state->request.data.name.name[sizeof(state->request.data.name.name)-1]='\0';
89
90         /* cope with the name being a fully qualified name */
91         p = strstr(state->request.data.name.name, lp_winbind_separator());
92         if (p) {
93                 *p = 0;
94                 name_domain = state->request.data.name.name;
95                 name_user = p+1;
96         } else {
97                 name_domain = state->request.data.name.dom_name;
98                 name_user = state->request.data.name.name;
99         }
100
101         DEBUG(3, ("[%5lu]: lookupname %s%s%s\n", (unsigned long)state->pid,
102                   name_domain, lp_winbind_separator(), name_user));
103
104         winbindd_lookupname_async(state->mem_ctx, name_domain, name_user,
105                                   lookupname_recv, WINBINDD_LOOKUPNAME, 
106                                   state);
107 }
108
109 static void lookupname_recv(void *private_data, BOOL success,
110                             const DOM_SID *sid, enum lsa_SidType type)
111 {
112         struct winbindd_cli_state *state =
113                 talloc_get_type_abort(private_data, struct winbindd_cli_state);
114
115         if (!success) {
116                 DEBUG(5, ("lookupname returned an error\n"));
117                 request_error(state);
118                 return;
119         }
120
121         sid_to_string(state->response.data.sid.sid, sid);
122         state->response.data.sid.type = type;
123         request_ok(state);
124         return;
125 }
126
127 void winbindd_lookuprids(struct winbindd_cli_state *state)
128 {
129         struct winbindd_domain *domain;
130         DOM_SID domain_sid;
131         
132         /* Ensure null termination */
133         state->request.data.sid[sizeof(state->request.data.sid)-1]='\0';
134
135         DEBUG(10, ("lookup_rids: %s\n", state->request.data.sid));
136
137         if (!string_to_sid(&domain_sid, state->request.data.sid)) {
138                 DEBUG(5, ("Could not convert %s to SID\n",
139                           state->request.data.sid));
140                 request_error(state);
141                 return;
142         }
143
144         domain = find_lookup_domain_from_sid(&domain_sid);
145         if (domain == NULL) {
146                 DEBUG(10, ("Could not find domain for name %s\n",
147                            state->request.domain_name));
148                 request_error(state);
149                 return;
150         }
151
152         sendto_domain(state, domain);
153 }
154
155 static struct winbindd_child static_idmap_child;
156
157 void init_idmap_child(void)
158 {
159         setup_domain_child(NULL, &static_idmap_child, "idmap");
160 }
161
162 struct winbindd_child *idmap_child(void)
163 {
164         return &static_idmap_child;
165 }
166
167 /* Convert a sid to a uid.  We assume we only have one rid attached to the
168    sid. */
169
170 static void sid2uid_recv(void *private_data, BOOL success, uid_t uid)
171 {
172         struct winbindd_cli_state *state =
173                 talloc_get_type_abort(private_data, struct winbindd_cli_state);
174
175         if (!success) {
176                 DEBUG(5, ("Could not convert sid %s\n",
177                           state->request.data.sid));
178                 request_error(state);
179                 return;
180         }
181
182         state->response.data.uid = uid;
183         request_ok(state);
184 }
185
186 static void sid2uid_lookupsid_recv( void *private_data, BOOL success, 
187                                     const char *domain_name, 
188                                     const char *name, 
189                                     enum lsa_SidType type)
190 {
191         struct winbindd_cli_state *state =
192                 talloc_get_type_abort(private_data, struct winbindd_cli_state);
193         DOM_SID sid;
194
195         if (!success) {
196                 DEBUG(5, ("sid2uid_lookupsid_recv Could not convert get sid type for %s\n",
197                           state->request.data.sid));
198                 request_error(state);
199                 return;
200         }
201
202         if ( (type!=SID_NAME_USER) && (type!=SID_NAME_COMPUTER) ) {
203                 DEBUG(5,("sid2uid_lookupsid_recv: Sid %s is not a user or a computer.\n", 
204                          state->request.data.sid));
205                 request_error(state);
206                 return;         
207         }
208
209         if (!string_to_sid(&sid, state->request.data.sid)) {
210                 DEBUG(1, ("sid2uid_lookupsid_recv: Could not get convert sid %s from string\n",
211                           state->request.data.sid));
212                 request_error(state);
213                 return;
214         }
215         
216         /* always use the async interface (may block) */
217         winbindd_sid2uid_async(state->mem_ctx, &sid, sid2uid_recv, state);
218 }
219
220 void winbindd_sid_to_uid(struct winbindd_cli_state *state)
221 {
222         DOM_SID sid;
223
224         /* Ensure null termination */
225         state->request.data.sid[sizeof(state->request.data.sid)-1]='\0';
226
227         DEBUG(3, ("[%5lu]: sid to uid %s\n", (unsigned long)state->pid,
228                   state->request.data.sid));
229
230         if (!string_to_sid(&sid, state->request.data.sid)) {
231                 DEBUG(1, ("Could not get convert sid %s from string\n",
232                           state->request.data.sid));
233                 request_error(state);
234                 return;
235         }
236
237         /* Validate the SID as a user.  Hopefully this will hit cache.
238            Needed to prevent DoS by exhausting the uid allocation
239            range from random SIDs. */
240
241         winbindd_lookupsid_async( state->mem_ctx, &sid, sid2uid_lookupsid_recv, state );
242 }
243
244 /* Convert a sid to a gid.  We assume we only have one rid attached to the
245    sid.*/
246
247 static void sid2gid_recv(void *private_data, BOOL success, gid_t gid)
248 {
249         struct winbindd_cli_state *state =
250                 talloc_get_type_abort(private_data, struct winbindd_cli_state);
251
252         if (!success) {
253                 DEBUG(5, ("Could not convert sid %s\n",
254                           state->request.data.sid));
255                 request_error(state);
256                 return;
257         }
258
259         state->response.data.gid = gid;
260         request_ok(state);
261 }
262
263 static void sid2gid_lookupsid_recv( void *private_data, BOOL success, 
264                                     const char *domain_name, 
265                                     const char *name, 
266                                     enum lsa_SidType type)
267 {
268         struct winbindd_cli_state *state =
269                 talloc_get_type_abort(private_data, struct winbindd_cli_state);
270         DOM_SID sid;
271
272         if (!success) {
273                 DEBUG(5, ("sid2gid_lookupsid_recv: Could not get sid type for %s\n",
274                           state->request.data.sid));
275                 request_error(state);
276                 return;
277         }
278
279         if ( (type!=SID_NAME_DOM_GRP) &&
280              (type!=SID_NAME_ALIAS) && 
281              (type!=SID_NAME_WKN_GRP) ) 
282         {
283                 DEBUG(5,("sid2gid_lookupsid_recv: Sid %s is not a group.\n", 
284                          state->request.data.sid));
285                 request_error(state);
286                 return;         
287         }
288
289         if (!string_to_sid(&sid, state->request.data.sid)) {
290                 DEBUG(1, ("sid2gid_lookupsid_recv: Could not get convert sid %s from string\n",
291                           state->request.data.sid));
292                 request_error(state);
293                 return;
294         }
295         
296         /* always use the async interface (may block) */
297         winbindd_sid2gid_async(state->mem_ctx, &sid, sid2gid_recv, state);
298 }
299
300 void winbindd_sid_to_gid(struct winbindd_cli_state *state)
301 {
302         DOM_SID sid;
303
304         /* Ensure null termination */
305         state->request.data.sid[sizeof(state->request.data.sid)-1]='\0';
306
307         DEBUG(3, ("[%5lu]: sid to gid %s\n", (unsigned long)state->pid,
308                   state->request.data.sid));
309
310         if (!string_to_sid(&sid, state->request.data.sid)) {
311                 DEBUG(1, ("Could not get convert sid %s from string\n",
312                           state->request.data.sid));
313                 request_error(state);
314                 return;
315         }
316
317         /* Validate the SID as a group.  Hopefully this will hit cache.
318            Needed to prevent DoS by exhausting the uid allocation
319            range from random SIDs. */
320
321         winbindd_lookupsid_async( state->mem_ctx, &sid, sid2gid_lookupsid_recv, state );        
322 }
323
324 static void sids2xids_recv(void *private_data, BOOL success, void *data, int len)
325 {
326         struct winbindd_cli_state *state =
327                 talloc_get_type_abort(private_data, struct winbindd_cli_state);
328
329         if (!success) {
330                 DEBUG(5, ("Could not convert sids to xids\n"));
331                 request_error(state);
332                 return;
333         }
334
335         state->response.extra_data.data = data;
336         state->response.length = sizeof(state->response) + len;
337         request_ok(state);
338 }
339
340 void winbindd_sids_to_unixids(struct winbindd_cli_state *state)
341 {
342         DEBUG(3, ("[%5lu]: sids to xids\n", (unsigned long)state->pid));
343
344         winbindd_sids2xids_async(state->mem_ctx,
345                         state->request.extra_data.data,
346                         state->request.extra_len,
347                         sids2xids_recv, state);
348 }
349
350 static void set_mapping_recv(void *private_data, BOOL success)
351 {
352         struct winbindd_cli_state *state =
353                 talloc_get_type_abort(private_data, struct winbindd_cli_state);
354
355         if (!success) {
356                 DEBUG(5, ("Could not set sid mapping\n"));
357                 request_error(state);
358                 return;
359         }
360
361         request_ok(state);
362 }
363
364 void winbindd_set_mapping(struct winbindd_cli_state *state)
365 {
366         struct id_map map;
367         DOM_SID sid;
368
369         DEBUG(3, ("[%5lu]: set id map\n", (unsigned long)state->pid));
370
371         if ( ! state->privileged) {
372                 DEBUG(0, ("Only root is allowed to set mappings!\n"));
373                 request_error(state);
374                 return;
375         }
376
377         if (!string_to_sid(&sid, state->request.data.dual_idmapset.sid)) {
378                 DEBUG(1, ("Could not get convert sid %s from string\n",
379                           state->request.data.sid));
380                 request_error(state);
381                 return;
382         }
383
384         map.sid = &sid;
385         map.xid.id = state->request.data.dual_idmapset.id;
386         map.xid.type = state->request.data.dual_idmapset.type;
387
388         winbindd_set_mapping_async(state->mem_ctx, &map,
389                         set_mapping_recv, state);
390 }
391
392 static void set_hwm_recv(void *private_data, BOOL success)
393 {
394         struct winbindd_cli_state *state =
395                 talloc_get_type_abort(private_data, struct winbindd_cli_state);
396
397         if (!success) {
398                 DEBUG(5, ("Could not set sid mapping\n"));
399                 request_error(state);
400                 return;
401         }
402
403         request_ok(state);
404 }
405
406 void winbindd_set_hwm(struct winbindd_cli_state *state)
407 {
408         struct unixid xid;
409
410         DEBUG(3, ("[%5lu]: set hwm\n", (unsigned long)state->pid));
411
412         if ( ! state->privileged) {
413                 DEBUG(0, ("Only root is allowed to set mappings!\n"));
414                 request_error(state);
415                 return;
416         }
417
418         xid.id = state->request.data.dual_idmapset.id;
419         xid.type = state->request.data.dual_idmapset.type;
420
421         winbindd_set_hwm_async(state->mem_ctx, &xid, set_hwm_recv, state);
422 }
423
424 /* Convert a uid to a sid */
425
426 static void uid2sid_recv(void *private_data, BOOL success, const char *sid)
427 {
428         struct winbindd_cli_state *state =
429                 (struct winbindd_cli_state *)private_data;
430
431         if (success) {
432                 DEBUG(10,("uid2sid: uid %lu has sid %s\n",
433                           (unsigned long)(state->request.data.uid), sid));
434                 fstrcpy(state->response.data.sid.sid, sid);
435                 state->response.data.sid.type = SID_NAME_USER;
436                 request_ok(state);
437                 return;
438         }
439
440         request_error(state);
441         return;
442 }
443
444 void winbindd_uid_to_sid(struct winbindd_cli_state *state)
445 {
446         DEBUG(3, ("[%5lu]: uid to sid %lu\n", (unsigned long)state->pid, 
447                   (unsigned long)state->request.data.uid));
448
449         /* always go via the async interface (may block) */
450         winbindd_uid2sid_async(state->mem_ctx, state->request.data.uid, uid2sid_recv, state);
451 }
452
453 /* Convert a gid to a sid */
454
455 static void gid2sid_recv(void *private_data, BOOL success, const char *sid)
456 {
457         struct winbindd_cli_state *state =
458                 (struct winbindd_cli_state *)private_data;
459
460         if (success) {
461                 DEBUG(10,("gid2sid: gid %lu has sid %s\n",
462                           (unsigned long)(state->request.data.gid), sid));
463                 fstrcpy(state->response.data.sid.sid, sid);
464                 state->response.data.sid.type = SID_NAME_DOM_GRP;
465                 request_ok(state);
466                 return;
467         }
468
469         request_error(state);
470         return;
471 }
472
473
474 void winbindd_gid_to_sid(struct winbindd_cli_state *state)
475 {
476         DEBUG(3, ("[%5lu]: gid to sid %lu\n", (unsigned long)state->pid, 
477                   (unsigned long)state->request.data.gid));
478
479         /* always use async calls (may block) */
480         winbindd_gid2sid_async(state->mem_ctx, state->request.data.gid, gid2sid_recv, state);
481 }
482
483 void winbindd_allocate_uid(struct winbindd_cli_state *state)
484 {
485         if ( !state->privileged ) {
486                 DEBUG(2, ("winbindd_allocate_uid: non-privileged access "
487                           "denied!\n"));
488                 request_error(state);
489                 return;
490         }
491
492         sendto_child(state, idmap_child());
493 }
494
495 enum winbindd_result winbindd_dual_allocate_uid(struct winbindd_domain *domain,
496                                                 struct winbindd_cli_state *state)
497 {
498         struct unixid xid;
499
500         if (!NT_STATUS_IS_OK(idmap_allocate_uid(&xid))) {
501                 return WINBINDD_ERROR;
502         }
503         state->response.data.uid = xid.id;
504         return WINBINDD_OK;
505 }
506
507 void winbindd_allocate_gid(struct winbindd_cli_state *state)
508 {
509         if ( !state->privileged ) {
510                 DEBUG(2, ("winbindd_allocate_gid: non-privileged access "
511                           "denied!\n"));
512                 request_error(state);
513                 return;
514         }
515
516         sendto_child(state, idmap_child());
517 }
518
519 enum winbindd_result winbindd_dual_allocate_gid(struct winbindd_domain *domain,
520                                                 struct winbindd_cli_state *state)
521 {
522         struct unixid xid;
523
524         if (!NT_STATUS_IS_OK(idmap_allocate_gid(&xid))) {
525                 return WINBINDD_ERROR;
526         }
527         state->response.data.gid = xid.id;
528         return WINBINDD_OK;
529 }
530
531 static void dump_maps_recv(void *private_data, BOOL success)
532 {
533         struct winbindd_cli_state *state =
534                 talloc_get_type_abort(private_data, struct winbindd_cli_state);
535
536         if (!success) {
537                 DEBUG(5, ("Could not dump maps\n"));
538                 request_error(state);
539                 return;
540         }
541
542         request_ok(state);
543 }
544
545 void winbindd_dump_maps(struct winbindd_cli_state *state)
546 {
547         if ( ! state->privileged) {
548                 DEBUG(0, ("Only root is allowed to ask for an idmap dump!\n"));
549                 request_error(state);
550                 return;
551         }
552
553         DEBUG(3, ("[%5lu]: dump maps\n", (unsigned long)state->pid));
554
555         winbindd_dump_maps_async(state->mem_ctx,
556                         state->request.extra_data.data,
557                         state->request.extra_len,
558                         dump_maps_recv, state);
559 }
560