source: branches/samba-3.2.x/source/winbindd/winbindd_sid.c

Last change on this file was 335, checked in by Herwig Bauernfeind, 16 years ago

Update 3.2 to 3.2.14 (final)

File size: 13.9 KB
Line 
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
30static void lookupsid_recv(void *private_data, bool success,
31 const char *dom_name, const char *name,
32 enum lsa_SidType type);
33
34void 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
53static 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
76static void lookupname_recv(void *private_data, bool success,
77 const DOM_SID *sid, enum lsa_SidType type);
78
79void 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 if ((p = strchr(state->request.data.name.name, '@')) != NULL) {
97 name_domain = p + 1;
98 *p = 0;
99 name_user = state->request.data.name.name;
100 } else {
101 name_domain = state->request.data.name.dom_name;
102 name_user = state->request.data.name.name;
103 }
104
105 DEBUG(3, ("[%5lu]: lookupname %s%s%s\n", (unsigned long)state->pid,
106 name_domain, lp_winbind_separator(), name_user));
107
108 winbindd_lookupname_async(state->mem_ctx, name_domain, name_user,
109 lookupname_recv, WINBINDD_LOOKUPNAME,
110 state);
111}
112
113static void lookupname_recv(void *private_data, bool success,
114 const DOM_SID *sid, enum lsa_SidType type)
115{
116 struct winbindd_cli_state *state =
117 talloc_get_type_abort(private_data, struct winbindd_cli_state);
118
119 if (!success) {
120 DEBUG(5, ("lookupname returned an error\n"));
121 request_error(state);
122 return;
123 }
124
125 sid_to_fstring(state->response.data.sid.sid, sid);
126 state->response.data.sid.type = type;
127 request_ok(state);
128 return;
129}
130
131void winbindd_lookuprids(struct winbindd_cli_state *state)
132{
133 struct winbindd_domain *domain;
134 DOM_SID domain_sid;
135
136 /* Ensure null termination */
137 state->request.data.sid[sizeof(state->request.data.sid)-1]='\0';
138
139 DEBUG(10, ("lookup_rids: %s\n", state->request.data.sid));
140
141 if (!string_to_sid(&domain_sid, state->request.data.sid)) {
142 DEBUG(5, ("Could not convert %s to SID\n",
143 state->request.data.sid));
144 request_error(state);
145 return;
146 }
147
148 domain = find_lookup_domain_from_sid(&domain_sid);
149 if (domain == NULL) {
150 DEBUG(10, ("Could not find domain for name %s\n",
151 state->request.domain_name));
152 request_error(state);
153 return;
154 }
155
156 sendto_domain(state, domain);
157}
158
159/* Convert a sid to a uid. We assume we only have one rid attached to the
160 sid. */
161
162static void sid2uid_recv(void *private_data, bool success, uid_t uid)
163{
164 struct winbindd_cli_state *state =
165 talloc_get_type_abort(private_data, struct winbindd_cli_state);
166
167 if (!success) {
168 DEBUG(5, ("Could not convert sid %s\n",
169 state->request.data.sid));
170 request_error(state);
171 return;
172 }
173
174 state->response.data.uid = uid;
175 request_ok(state);
176}
177
178static void sid2uid_lookupsid_recv( void *private_data, bool success,
179 const char *domain_name,
180 const char *name,
181 enum lsa_SidType type)
182{
183 struct winbindd_cli_state *state =
184 talloc_get_type_abort(private_data, struct winbindd_cli_state);
185 DOM_SID sid;
186
187 if (!success) {
188 DEBUG(5, ("sid2uid_lookupsid_recv Could not convert get sid type for %s\n",
189 state->request.data.sid));
190 request_error(state);
191 return;
192 }
193
194 if ( (type!=SID_NAME_USER) && (type!=SID_NAME_COMPUTER) ) {
195 DEBUG(5,("sid2uid_lookupsid_recv: Sid %s is not a user or a computer.\n",
196 state->request.data.sid));
197 request_error(state);
198 return;
199 }
200
201 if (!string_to_sid(&sid, state->request.data.sid)) {
202 DEBUG(1, ("sid2uid_lookupsid_recv: Could not get convert sid %s from string\n",
203 state->request.data.sid));
204 request_error(state);
205 return;
206 }
207
208 /* always use the async interface (may block) */
209 winbindd_sid2uid_async(state->mem_ctx, &sid, sid2uid_recv, state);
210}
211
212void winbindd_sid_to_uid(struct winbindd_cli_state *state)
213{
214 DOM_SID sid;
215
216 /* Ensure null termination */
217 state->request.data.sid[sizeof(state->request.data.sid)-1]='\0';
218
219 DEBUG(3, ("[%5lu]: sid to uid %s\n", (unsigned long)state->pid,
220 state->request.data.sid));
221
222 if (!string_to_sid(&sid, state->request.data.sid)) {
223 DEBUG(1, ("Could not get convert sid %s from string\n",
224 state->request.data.sid));
225 request_error(state);
226 return;
227 }
228
229 /* Validate the SID as a user. Hopefully this will hit cache.
230 Needed to prevent DoS by exhausting the uid allocation
231 range from random SIDs. */
232
233 winbindd_lookupsid_async( state->mem_ctx, &sid, sid2uid_lookupsid_recv, state );
234}
235
236/* Convert a sid to a gid. We assume we only have one rid attached to the
237 sid.*/
238
239static void sid2gid_recv(void *private_data, bool success, gid_t gid)
240{
241 struct winbindd_cli_state *state =
242 talloc_get_type_abort(private_data, struct winbindd_cli_state);
243
244 if (!success) {
245 DEBUG(5, ("Could not convert sid %s\n",
246 state->request.data.sid));
247 request_error(state);
248 return;
249 }
250
251 state->response.data.gid = gid;
252 request_ok(state);
253}
254
255static void sid2gid_lookupsid_recv( void *private_data, bool success,
256 const char *domain_name,
257 const char *name,
258 enum lsa_SidType type)
259{
260 struct winbindd_cli_state *state =
261 talloc_get_type_abort(private_data, struct winbindd_cli_state);
262 DOM_SID sid;
263
264 if (!success) {
265 DEBUG(5, ("sid2gid_lookupsid_recv: Could not get sid type for %s\n",
266 state->request.data.sid));
267 request_error(state);
268 return;
269 }
270
271 if ( (type!=SID_NAME_DOM_GRP) &&
272 (type!=SID_NAME_ALIAS) &&
273 (type!=SID_NAME_WKN_GRP) )
274 {
275 DEBUG(5,("sid2gid_lookupsid_recv: Sid %s is not a group.\n",
276 state->request.data.sid));
277 request_error(state);
278 return;
279 }
280
281 if (!string_to_sid(&sid, state->request.data.sid)) {
282 DEBUG(1, ("sid2gid_lookupsid_recv: Could not get convert sid %s from string\n",
283 state->request.data.sid));
284 request_error(state);
285 return;
286 }
287
288 /* always use the async interface (may block) */
289 winbindd_sid2gid_async(state->mem_ctx, &sid, sid2gid_recv, state);
290}
291
292void winbindd_sid_to_gid(struct winbindd_cli_state *state)
293{
294 DOM_SID sid;
295
296 /* Ensure null termination */
297 state->request.data.sid[sizeof(state->request.data.sid)-1]='\0';
298
299 DEBUG(3, ("[%5lu]: sid to gid %s\n", (unsigned long)state->pid,
300 state->request.data.sid));
301
302 if (!string_to_sid(&sid, state->request.data.sid)) {
303 DEBUG(1, ("Could not get convert sid %s from string\n",
304 state->request.data.sid));
305 request_error(state);
306 return;
307 }
308
309 /* Validate the SID as a group. Hopefully this will hit cache.
310 Needed to prevent DoS by exhausting the uid allocation
311 range from random SIDs. */
312
313 winbindd_lookupsid_async( state->mem_ctx, &sid, sid2gid_lookupsid_recv, state );
314}
315
316static void sids2xids_recv(void *private_data, bool success, void *data, int len)
317{
318 struct winbindd_cli_state *state =
319 talloc_get_type_abort(private_data, struct winbindd_cli_state);
320
321 if (!success) {
322 DEBUG(5, ("Could not convert sids to xids\n"));
323 request_error(state);
324 return;
325 }
326
327 state->response.extra_data.data = data;
328 state->response.length = sizeof(state->response) + len;
329 request_ok(state);
330}
331
332void winbindd_sids_to_unixids(struct winbindd_cli_state *state)
333{
334 DEBUG(3, ("[%5lu]: sids to xids\n", (unsigned long)state->pid));
335
336 winbindd_sids2xids_async(state->mem_ctx,
337 state->request.extra_data.data,
338 state->request.extra_len,
339 sids2xids_recv, state);
340}
341
342static void set_mapping_recv(void *private_data, bool success)
343{
344 struct winbindd_cli_state *state =
345 talloc_get_type_abort(private_data, struct winbindd_cli_state);
346
347 if (!success) {
348 DEBUG(5, ("Could not set sid mapping\n"));
349 request_error(state);
350 return;
351 }
352
353 request_ok(state);
354}
355
356void winbindd_set_mapping(struct winbindd_cli_state *state)
357{
358 struct id_map map;
359 DOM_SID sid;
360
361 DEBUG(3, ("[%5lu]: set id map\n", (unsigned long)state->pid));
362
363 if ( ! state->privileged) {
364 DEBUG(0, ("Only root is allowed to set mappings!\n"));
365 request_error(state);
366 return;
367 }
368
369 if (!string_to_sid(&sid, state->request.data.dual_idmapset.sid)) {
370 DEBUG(1, ("Could not get convert sid %s from string\n",
371 state->request.data.sid));
372 request_error(state);
373 return;
374 }
375
376 map.sid = &sid;
377 map.xid.id = state->request.data.dual_idmapset.id;
378 map.xid.type = state->request.data.dual_idmapset.type;
379
380 winbindd_set_mapping_async(state->mem_ctx, &map,
381 set_mapping_recv, state);
382}
383
384static void set_hwm_recv(void *private_data, bool success)
385{
386 struct winbindd_cli_state *state =
387 talloc_get_type_abort(private_data, struct winbindd_cli_state);
388
389 if (!success) {
390 DEBUG(5, ("Could not set sid mapping\n"));
391 request_error(state);
392 return;
393 }
394
395 request_ok(state);
396}
397
398void winbindd_set_hwm(struct winbindd_cli_state *state)
399{
400 struct unixid xid;
401
402 DEBUG(3, ("[%5lu]: set hwm\n", (unsigned long)state->pid));
403
404 if ( ! state->privileged) {
405 DEBUG(0, ("Only root is allowed to set mappings!\n"));
406 request_error(state);
407 return;
408 }
409
410 xid.id = state->request.data.dual_idmapset.id;
411 xid.type = state->request.data.dual_idmapset.type;
412
413 winbindd_set_hwm_async(state->mem_ctx, &xid, set_hwm_recv, state);
414}
415
416/* Convert a uid to a sid */
417
418static void uid2sid_recv(void *private_data, bool success, const char *sid)
419{
420 struct winbindd_cli_state *state =
421 (struct winbindd_cli_state *)private_data;
422
423 if (success) {
424 DEBUG(10,("uid2sid: uid %lu has sid %s\n",
425 (unsigned long)(state->request.data.uid), sid));
426 fstrcpy(state->response.data.sid.sid, sid);
427 state->response.data.sid.type = SID_NAME_USER;
428 request_ok(state);
429 return;
430 }
431
432 request_error(state);
433 return;
434}
435
436void winbindd_uid_to_sid(struct winbindd_cli_state *state)
437{
438 DEBUG(3, ("[%5lu]: uid to sid %lu\n", (unsigned long)state->pid,
439 (unsigned long)state->request.data.uid));
440
441 /* always go via the async interface (may block) */
442 winbindd_uid2sid_async(state->mem_ctx, state->request.data.uid, uid2sid_recv, state);
443}
444
445/* Convert a gid to a sid */
446
447static void gid2sid_recv(void *private_data, bool success, const char *sid)
448{
449 struct winbindd_cli_state *state =
450 (struct winbindd_cli_state *)private_data;
451
452 if (success) {
453 DEBUG(10,("gid2sid: gid %lu has sid %s\n",
454 (unsigned long)(state->request.data.gid), sid));
455 fstrcpy(state->response.data.sid.sid, sid);
456 state->response.data.sid.type = SID_NAME_DOM_GRP;
457 request_ok(state);
458 return;
459 }
460
461 request_error(state);
462 return;
463}
464
465
466void winbindd_gid_to_sid(struct winbindd_cli_state *state)
467{
468 DEBUG(3, ("[%5lu]: gid to sid %lu\n", (unsigned long)state->pid,
469 (unsigned long)state->request.data.gid));
470
471 /* always use async calls (may block) */
472 winbindd_gid2sid_async(state->mem_ctx, state->request.data.gid, gid2sid_recv, state);
473}
474
475void winbindd_allocate_uid(struct winbindd_cli_state *state)
476{
477 if ( !state->privileged ) {
478 DEBUG(2, ("winbindd_allocate_uid: non-privileged access "
479 "denied!\n"));
480 request_error(state);
481 return;
482 }
483
484 sendto_child(state, idmap_child());
485}
486
487enum winbindd_result winbindd_dual_allocate_uid(struct winbindd_domain *domain,
488 struct winbindd_cli_state *state)
489{
490 struct unixid xid;
491
492 if (!NT_STATUS_IS_OK(idmap_allocate_uid(&xid))) {
493 return WINBINDD_ERROR;
494 }
495 state->response.data.uid = xid.id;
496 return WINBINDD_OK;
497}
498
499void winbindd_allocate_gid(struct winbindd_cli_state *state)
500{
501 if ( !state->privileged ) {
502 DEBUG(2, ("winbindd_allocate_gid: non-privileged access "
503 "denied!\n"));
504 request_error(state);
505 return;
506 }
507
508 sendto_child(state, idmap_child());
509}
510
511enum winbindd_result winbindd_dual_allocate_gid(struct winbindd_domain *domain,
512 struct winbindd_cli_state *state)
513{
514 struct unixid xid;
515
516 if (!NT_STATUS_IS_OK(idmap_allocate_gid(&xid))) {
517 return WINBINDD_ERROR;
518 }
519 state->response.data.gid = xid.id;
520 return WINBINDD_OK;
521}
Note: See TracBrowser for help on using the repository browser.