let winbindd_set_mapping() use WINBIND_SET_IDMAP_LEVEL_SET_MAPPING...
[metze/samba/wb-ndr.git] / source / winbindd / 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_fstring(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 /* Convert a sid to a uid.  We assume we only have one rid attached to the
156    sid. */
157
158 static void sid2uid_recv(void *private_data, bool success, uid_t uid)
159 {
160         struct winbindd_cli_state *state =
161                 talloc_get_type_abort(private_data, struct winbindd_cli_state);
162
163         if (!success) {
164                 DEBUG(5, ("Could not convert sid %s\n",
165                           state->request.data.sid));
166                 request_error(state);
167                 return;
168         }
169
170         state->response.data.uid = uid;
171         request_ok(state);
172 }
173
174 static void sid2uid_lookupsid_recv( void *private_data, bool success, 
175                                     const char *domain_name, 
176                                     const char *name, 
177                                     enum lsa_SidType type)
178 {
179         struct winbindd_cli_state *state =
180                 talloc_get_type_abort(private_data, struct winbindd_cli_state);
181         DOM_SID sid;
182
183         if (!success) {
184                 DEBUG(5, ("sid2uid_lookupsid_recv Could not convert get sid type for %s\n",
185                           state->request.data.sid));
186                 request_error(state);
187                 return;
188         }
189
190         if ( (type!=SID_NAME_USER) && (type!=SID_NAME_COMPUTER) ) {
191                 DEBUG(5,("sid2uid_lookupsid_recv: Sid %s is not a user or a computer.\n", 
192                          state->request.data.sid));
193                 request_error(state);
194                 return;         
195         }
196
197         if (!string_to_sid(&sid, state->request.data.sid)) {
198                 DEBUG(1, ("sid2uid_lookupsid_recv: Could not get convert sid %s from string\n",
199                           state->request.data.sid));
200                 request_error(state);
201                 return;
202         }
203         
204         /* always use the async interface (may block) */
205         winbindd_sid2uid_async(state->mem_ctx, &sid, sid2uid_recv, state);
206 }
207
208 void winbindd_sid_to_uid(struct winbindd_cli_state *state)
209 {
210         DOM_SID sid;
211
212         /* Ensure null termination */
213         state->request.data.sid[sizeof(state->request.data.sid)-1]='\0';
214
215         DEBUG(3, ("[%5lu]: sid to uid %s\n", (unsigned long)state->pid,
216                   state->request.data.sid));
217
218         if (!string_to_sid(&sid, state->request.data.sid)) {
219                 DEBUG(1, ("Could not get convert sid %s from string\n",
220                           state->request.data.sid));
221                 request_error(state);
222                 return;
223         }
224
225         /* Validate the SID as a user.  Hopefully this will hit cache.
226            Needed to prevent DoS by exhausting the uid allocation
227            range from random SIDs. */
228
229         winbindd_lookupsid_async( state->mem_ctx, &sid, sid2uid_lookupsid_recv, state );
230 }
231
232 /* Convert a sid to a gid.  We assume we only have one rid attached to the
233    sid.*/
234
235 static void sid2gid_recv(void *private_data, bool success, gid_t gid)
236 {
237         struct winbindd_cli_state *state =
238                 talloc_get_type_abort(private_data, struct winbindd_cli_state);
239
240         if (!success) {
241                 DEBUG(5, ("Could not convert sid %s\n",
242                           state->request.data.sid));
243                 request_error(state);
244                 return;
245         }
246
247         state->response.data.gid = gid;
248         request_ok(state);
249 }
250
251 static void sid2gid_lookupsid_recv( void *private_data, bool success, 
252                                     const char *domain_name, 
253                                     const char *name, 
254                                     enum lsa_SidType type)
255 {
256         struct winbindd_cli_state *state =
257                 talloc_get_type_abort(private_data, struct winbindd_cli_state);
258         DOM_SID sid;
259
260         if (!success) {
261                 DEBUG(5, ("sid2gid_lookupsid_recv: Could not get sid type for %s\n",
262                           state->request.data.sid));
263                 request_error(state);
264                 return;
265         }
266
267         if ( (type!=SID_NAME_DOM_GRP) &&
268              (type!=SID_NAME_ALIAS) && 
269              (type!=SID_NAME_WKN_GRP) ) 
270         {
271                 DEBUG(5,("sid2gid_lookupsid_recv: Sid %s is not a group.\n", 
272                          state->request.data.sid));
273                 request_error(state);
274                 return;         
275         }
276
277         if (!string_to_sid(&sid, state->request.data.sid)) {
278                 DEBUG(1, ("sid2gid_lookupsid_recv: Could not get convert sid %s from string\n",
279                           state->request.data.sid));
280                 request_error(state);
281                 return;
282         }
283         
284         /* always use the async interface (may block) */
285         winbindd_sid2gid_async(state->mem_ctx, &sid, sid2gid_recv, state);
286 }
287
288 void winbindd_sid_to_gid(struct winbindd_cli_state *state)
289 {
290         DOM_SID sid;
291
292         /* Ensure null termination */
293         state->request.data.sid[sizeof(state->request.data.sid)-1]='\0';
294
295         DEBUG(3, ("[%5lu]: sid to gid %s\n", (unsigned long)state->pid,
296                   state->request.data.sid));
297
298         if (!string_to_sid(&sid, state->request.data.sid)) {
299                 DEBUG(1, ("Could not get convert sid %s from string\n",
300                           state->request.data.sid));
301                 request_error(state);
302                 return;
303         }
304
305         /* Validate the SID as a group.  Hopefully this will hit cache.
306            Needed to prevent DoS by exhausting the uid allocation
307            range from random SIDs. */
308
309         winbindd_lookupsid_async( state->mem_ctx, &sid, sid2gid_lookupsid_recv, state );        
310 }
311
312 static void winbindd_set_mapping_recv(TALLOC_CTX *mem_ctx, bool success,
313                                       struct winbindd_ndr_call *c,
314                                       void *private_data,
315                                       void *_cont,
316                                       void *_cont_private)
317 {
318         struct winbindd_cli_state *state =
319                 talloc_get_type_abort(private_data, struct winbindd_cli_state);
320         struct winbind_set_idmap *r =
321                 talloc_get_type_abort(c->ndr.r, struct winbind_set_idmap);
322
323         if (!success) {
324                 DEBUG(5, ("Could not set_idmap(set_mapping)\n"));
325                 request_error(state);
326                 return;
327         }
328
329         if (r->out.result != WINBIND_STATUS_OK) {
330                 DEBUG(5, ("set_idmap(set_mapping) returned an error:0x%08X\n",
331                         r->out.result));
332                 request_error(state);
333                 return;
334         }
335
336         request_ok(state);
337 }
338
339 void winbindd_set_mapping(struct winbindd_cli_state *state)
340 {
341         struct winbind_set_idmap *r = NULL;
342
343         DEBUG(3, ("[%5lu]: set id map\n", (unsigned long)state->pid));
344
345         if ( ! state->privileged) {
346                 DEBUG(0, ("Only root is allowed to set mappings!\n"));
347                 request_error(state);
348                 return;
349         }
350
351         r = TALLOC_P(state->mem_ctx, struct winbind_set_idmap);
352         if (!r) goto nomem;
353         r->in.level = TALLOC_P(r, enum winbind_set_idmap_level);
354         if (!r->in.level) goto nomem;
355
356         *r->in.level = WINBIND_SET_IDMAP_LEVEL_SET_MAPPING;
357         r->in.req.mapping.sid = string_sid_talloc(r,
358                                         state->request.data.dual_idmapset.sid);
359         if (!r->in.req.mapping.sid) {
360                 DEBUG(1, ("Could not get convert sid %s from string\n",
361                           state->request.data.dual_idmapset.sid));
362                 goto nomem;
363         }
364         r->in.req.mapping.xid.id = state->request.data.dual_idmapset.id;
365         r->in.req.mapping.xid.type = state->request.data.dual_idmapset.type;
366         r->in.req.mapping.status = ID_MAPPED;
367
368         do_async_ndr(state->mem_ctx, idmap_child(),
369                      NDR_WINBIND_SET_IDMAP, r,
370                      winbindd_set_mapping_recv, state,
371                      NULL, NULL);
372         return;
373 nomem:
374         request_error(state);
375         return;
376 }
377
378 static void set_hwm_recv(void *private_data, bool success)
379 {
380         struct winbindd_cli_state *state =
381                 talloc_get_type_abort(private_data, struct winbindd_cli_state);
382
383         if (!success) {
384                 DEBUG(5, ("Could not set sid mapping\n"));
385                 request_error(state);
386                 return;
387         }
388
389         request_ok(state);
390 }
391
392 void winbindd_set_hwm(struct winbindd_cli_state *state)
393 {
394         struct unixid xid;
395
396         DEBUG(3, ("[%5lu]: set hwm\n", (unsigned long)state->pid));
397
398         if ( ! state->privileged) {
399                 DEBUG(0, ("Only root is allowed to set mappings!\n"));
400                 request_error(state);
401                 return;
402         }
403
404         xid.id = state->request.data.dual_idmapset.id;
405         xid.type = state->request.data.dual_idmapset.type;
406
407         winbindd_set_hwm_async(state->mem_ctx, &xid, set_hwm_recv, state);
408 }
409
410 /* Convert a uid to a sid */
411
412 static void uid2sid_recv(void *private_data, bool success, const char *sid)
413 {
414         struct winbindd_cli_state *state =
415                 (struct winbindd_cli_state *)private_data;
416
417         if (success) {
418                 DEBUG(10,("uid2sid: uid %lu has sid %s\n",
419                           (unsigned long)(state->request.data.uid), sid));
420                 fstrcpy(state->response.data.sid.sid, sid);
421                 state->response.data.sid.type = SID_NAME_USER;
422                 request_ok(state);
423                 return;
424         }
425
426         request_error(state);
427         return;
428 }
429
430 void winbindd_uid_to_sid(struct winbindd_cli_state *state)
431 {
432         DEBUG(3, ("[%5lu]: uid to sid %lu\n", (unsigned long)state->pid, 
433                   (unsigned long)state->request.data.uid));
434
435         /* always go via the async interface (may block) */
436         winbindd_uid2sid_async(state->mem_ctx, state->request.data.uid, uid2sid_recv, state);
437 }
438
439 /* Convert a gid to a sid */
440
441 static void gid2sid_recv(void *private_data, bool success, const char *sid)
442 {
443         struct winbindd_cli_state *state =
444                 (struct winbindd_cli_state *)private_data;
445
446         if (success) {
447                 DEBUG(10,("gid2sid: gid %lu has sid %s\n",
448                           (unsigned long)(state->request.data.gid), sid));
449                 fstrcpy(state->response.data.sid.sid, sid);
450                 state->response.data.sid.type = SID_NAME_DOM_GRP;
451                 request_ok(state);
452                 return;
453         }
454
455         request_error(state);
456         return;
457 }
458
459
460 void winbindd_gid_to_sid(struct winbindd_cli_state *state)
461 {
462         DEBUG(3, ("[%5lu]: gid to sid %lu\n", (unsigned long)state->pid, 
463                   (unsigned long)state->request.data.gid));
464
465         /* always use async calls (may block) */
466         winbindd_gid2sid_async(state->mem_ctx, state->request.data.gid, gid2sid_recv, state);
467 }
468
469 static void winbindd_allocate_uid_recv(TALLOC_CTX *mem_ctx, bool success,
470                                        struct winbindd_ndr_call *c,
471                                        void *private_data,
472                                        void *_cont,
473                                        void *_cont_private)
474 {
475         struct winbindd_cli_state *state =
476                 talloc_get_type_abort(private_data, struct winbindd_cli_state);
477         struct winbind_set_idmap *r =
478                 talloc_get_type_abort(c->ndr.r, struct winbind_set_idmap);
479
480         if (!success) {
481                 DEBUG(5, ("Could not set_idmap(allocate_uid)\n"));
482                 request_error(state);
483                 return;
484         }
485
486         if (r->out.result != WINBIND_STATUS_OK) {
487                 DEBUG(5, ("set_idmap(allocate_uid) returned an error:0x%08X\n",
488                         r->out.result));
489                 request_error(state);
490                 return;
491         }
492
493         if (r->out.rep->uid > UINT32_MAX) {
494                 DEBUG(1, ("set_idmap(allocate_uid) returned a 64bit uid %llu\n",
495                         (unsigned long long)r->out.rep->uid));
496                 request_error(state);
497                 return;
498         }
499
500         state->response.data.uid = r->out.rep->uid;
501         request_ok(state);
502 }
503
504 void winbindd_allocate_uid(struct winbindd_cli_state *state)
505 {
506         struct winbind_set_idmap *r = NULL;
507
508         if ( !state->privileged ) {
509                 DEBUG(2, ("winbindd_allocate_uid: non-privileged access "
510                           "denied!\n"));
511                 request_error(state);
512                 return;
513         }
514
515         r = TALLOC_P(state->mem_ctx, struct winbind_set_idmap);
516         if (!r) goto nomem;
517         r->in.level = TALLOC_P(r, enum winbind_set_idmap_level);
518         if (!r->in.level) goto nomem;
519
520         *r->in.level = WINBIND_SET_IDMAP_LEVEL_ALLOCATE_UID;
521
522         do_async_ndr(state->mem_ctx, idmap_child(),
523                      NDR_WINBIND_SET_IDMAP, r,
524                      winbindd_allocate_uid_recv, state,
525                      NULL, NULL);
526         return;
527 nomem:
528         request_error(state);
529         return;
530 }
531
532 static void winbindd_allocate_gid_recv(TALLOC_CTX *mem_ctx, bool success,
533                                        struct winbindd_ndr_call *c,
534                                        void *private_data,
535                                        void *_cont,
536                                        void *_cont_private)
537 {
538         struct winbindd_cli_state *state =
539                 talloc_get_type_abort(private_data, struct winbindd_cli_state);
540         struct winbind_set_idmap *r =
541                 talloc_get_type_abort(c->ndr.r, struct winbind_set_idmap);
542
543         if (!success) {
544                 DEBUG(5, ("Could not set_idmap(allocate_gid)\n"));
545                 request_error(state);
546                 return;
547         }
548
549         if (r->out.result != WINBIND_STATUS_OK) {
550                 DEBUG(5, ("set_idmap(allocate_gid) returned an error:0x%08X\n",
551                         r->out.result));
552                 request_error(state);
553                 return;
554         }
555
556         if (r->out.rep->gid > UINT32_MAX) {
557                 DEBUG(1, ("set_idmap(allocate_gid) returned a 64bit gid %llu\n",
558                         (unsigned long long)r->out.rep->gid));
559                 request_error(state);
560                 return;
561         }
562
563         state->response.data.gid = r->out.rep->gid;
564         request_ok(state);
565 }
566
567 void winbindd_allocate_gid(struct winbindd_cli_state *state)
568 {
569         struct winbind_set_idmap *r = NULL;
570
571         if ( !state->privileged ) {
572                 DEBUG(2, ("winbindd_allocate_gid: non-privileged access "
573                           "denied!\n"));
574                 request_error(state);
575                 return;
576         }
577
578         r = TALLOC_P(state->mem_ctx, struct winbind_set_idmap);
579         if (!r) goto nomem;
580         r->in.level = TALLOC_P(r, enum winbind_set_idmap_level);
581         if (!r->in.level) goto nomem;
582
583         *r->in.level = WINBIND_SET_IDMAP_LEVEL_ALLOCATE_GID;
584
585         do_async_ndr(state->mem_ctx, idmap_child(),
586                      NDR_WINBIND_SET_IDMAP, r,
587                      winbindd_allocate_gid_recv, state,
588                      NULL, NULL);
589         return;
590 nomem:
591         request_error(state);
592         return;
593 }