2 Unix SMB/CIFS implementation.
4 Winbind daemon - sid related functions
6 Copyright (C) Tim Potter 2000
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.
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.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 #define DBGC_CLASS DBGC_WINBIND
29 /* Convert a string */
31 static void lookupsid_recv(void *private_data, BOOL success,
32 const char *dom_name, const char *name,
33 enum lsa_SidType type);
35 void winbindd_lookupsid(struct winbindd_cli_state *state)
39 /* Ensure null termination */
40 state->request.data.sid[sizeof(state->request.data.sid)-1]='\0';
42 DEBUG(3, ("[%5lu]: lookupsid %s\n", (unsigned long)state->pid,
43 state->request.data.sid));
45 if (!string_to_sid(&sid, state->request.data.sid)) {
46 DEBUG(5, ("%s not a SID\n", state->request.data.sid));
51 winbindd_lookupsid_async(state->mem_ctx, &sid, lookupsid_recv, state);
54 static void lookupsid_recv(void *private_data, BOOL success,
55 const char *dom_name, const char *name,
56 enum lsa_SidType type)
58 struct winbindd_cli_state *state =
59 talloc_get_type_abort(private_data, struct winbindd_cli_state);
62 DEBUG(5, ("lookupsid returned an error\n"));
67 fstrcpy(state->response.data.name.dom_name, dom_name);
68 fstrcpy(state->response.data.name.name, name);
69 state->response.data.name.type = type;
74 * Look up the SID for a qualified name.
77 static void lookupname_recv(void *private_data, BOOL success,
78 const DOM_SID *sid, enum lsa_SidType type);
80 void winbindd_lookupname(struct winbindd_cli_state *state)
82 char *name_domain, *name_user;
85 /* Ensure null termination */
86 state->request.data.name.dom_name[sizeof(state->request.data.name.dom_name)-1]='\0';
88 /* Ensure null termination */
89 state->request.data.name.name[sizeof(state->request.data.name.name)-1]='\0';
91 /* cope with the name being a fully qualified name */
92 p = strstr(state->request.data.name.name, lp_winbind_separator());
95 name_domain = state->request.data.name.name;
98 name_domain = state->request.data.name.dom_name;
99 name_user = state->request.data.name.name;
102 DEBUG(3, ("[%5lu]: lookupname %s%s%s\n", (unsigned long)state->pid,
103 name_domain, lp_winbind_separator(), name_user));
105 winbindd_lookupname_async(state->mem_ctx, name_domain, name_user,
106 lookupname_recv, WINBINDD_LOOKUPNAME,
110 static void lookupname_recv(void *private_data, BOOL success,
111 const DOM_SID *sid, enum lsa_SidType type)
113 struct winbindd_cli_state *state =
114 talloc_get_type_abort(private_data, struct winbindd_cli_state);
117 DEBUG(5, ("lookupname returned an error\n"));
118 request_error(state);
122 sid_to_string(state->response.data.sid.sid, sid);
123 state->response.data.sid.type = type;
128 void winbindd_lookuprids(struct winbindd_cli_state *state)
130 struct winbindd_domain *domain;
133 /* Ensure null termination */
134 state->request.data.sid[sizeof(state->request.data.sid)-1]='\0';
136 DEBUG(10, ("lookup_rids: %s\n", state->request.data.sid));
138 if (!string_to_sid(&domain_sid, state->request.data.sid)) {
139 DEBUG(5, ("Could not convert %s to SID\n",
140 state->request.data.sid));
141 request_error(state);
145 domain = find_lookup_domain_from_sid(&domain_sid);
146 if (domain == NULL) {
147 DEBUG(10, ("Could not find domain for name %s\n",
148 state->request.domain_name));
149 request_error(state);
153 sendto_domain(state, domain);
156 static struct winbindd_child static_idmap_child;
158 void init_idmap_child(void)
160 setup_domain_child(NULL, &static_idmap_child, "idmap");
163 struct winbindd_child *idmap_child(void)
165 return &static_idmap_child;
168 /* Convert a sid to a uid. We assume we only have one rid attached to the
171 static void sid2uid_recv(void *private_data, BOOL success, uid_t uid)
173 struct winbindd_cli_state *state =
174 talloc_get_type_abort(private_data, struct winbindd_cli_state);
177 DEBUG(5, ("Could not convert sid %s\n",
178 state->request.data.sid));
179 request_error(state);
183 state->response.data.uid = uid;
187 static void sid2uid_lookupsid_recv( void *private_data, BOOL success,
188 const char *domain_name,
190 enum lsa_SidType type)
192 struct winbindd_cli_state *state =
193 talloc_get_type_abort(private_data, struct winbindd_cli_state);
197 DEBUG(5, ("sid2uid_lookupsid_recv Could not convert get sid type for %s\n",
198 state->request.data.sid));
199 request_error(state);
203 if ( (type!=SID_NAME_USER) && (type!=SID_NAME_COMPUTER) ) {
204 DEBUG(5,("sid2uid_lookupsid_recv: Sid %s is not a user or a computer.\n",
205 state->request.data.sid));
206 request_error(state);
210 if (!string_to_sid(&sid, state->request.data.sid)) {
211 DEBUG(1, ("sid2uid_lookupsid_recv: Could not get convert sid %s from string\n",
212 state->request.data.sid));
213 request_error(state);
217 /* always use the async interface (may block) */
218 winbindd_sid2uid_async(state->mem_ctx, &sid, sid2uid_recv, state);
221 void winbindd_sid_to_uid(struct winbindd_cli_state *state)
225 /* Ensure null termination */
226 state->request.data.sid[sizeof(state->request.data.sid)-1]='\0';
228 DEBUG(3, ("[%5lu]: sid to uid %s\n", (unsigned long)state->pid,
229 state->request.data.sid));
231 if (!string_to_sid(&sid, state->request.data.sid)) {
232 DEBUG(1, ("Could not get convert sid %s from string\n",
233 state->request.data.sid));
234 request_error(state);
238 /* Validate the SID as a user. Hopefully this will hit cache.
239 Needed to prevent DoS by exhausting the uid allocation
240 range from random SIDs. */
242 winbindd_lookupsid_async( state->mem_ctx, &sid, sid2uid_lookupsid_recv, state );
245 /* Convert a sid to a gid. We assume we only have one rid attached to the
248 static void sid2gid_recv(void *private_data, BOOL success, gid_t gid)
250 struct winbindd_cli_state *state =
251 talloc_get_type_abort(private_data, struct winbindd_cli_state);
254 DEBUG(5, ("Could not convert sid %s\n",
255 state->request.data.sid));
256 request_error(state);
260 state->response.data.gid = gid;
264 static void sid2gid_lookupsid_recv( void *private_data, BOOL success,
265 const char *domain_name,
267 enum lsa_SidType type)
269 struct winbindd_cli_state *state =
270 talloc_get_type_abort(private_data, struct winbindd_cli_state);
274 DEBUG(5, ("sid2gid_lookupsid_recv: Could not get sid type for %s\n",
275 state->request.data.sid));
276 request_error(state);
280 if ( (type!=SID_NAME_DOM_GRP) &&
281 (type!=SID_NAME_ALIAS) &&
282 (type!=SID_NAME_WKN_GRP) )
284 DEBUG(5,("sid2gid_lookupsid_recv: Sid %s is not a group.\n",
285 state->request.data.sid));
286 request_error(state);
290 if (!string_to_sid(&sid, state->request.data.sid)) {
291 DEBUG(1, ("sid2gid_lookupsid_recv: Could not get convert sid %s from string\n",
292 state->request.data.sid));
293 request_error(state);
297 /* always use the async interface (may block) */
298 winbindd_sid2gid_async(state->mem_ctx, &sid, sid2gid_recv, state);
301 void winbindd_sid_to_gid(struct winbindd_cli_state *state)
305 /* Ensure null termination */
306 state->request.data.sid[sizeof(state->request.data.sid)-1]='\0';
308 DEBUG(3, ("[%5lu]: sid to gid %s\n", (unsigned long)state->pid,
309 state->request.data.sid));
311 if (!string_to_sid(&sid, state->request.data.sid)) {
312 DEBUG(1, ("Could not get convert sid %s from string\n",
313 state->request.data.sid));
314 request_error(state);
318 /* Validate the SID as a group. Hopefully this will hit cache.
319 Needed to prevent DoS by exhausting the uid allocation
320 range from random SIDs. */
322 winbindd_lookupsid_async( state->mem_ctx, &sid, sid2gid_lookupsid_recv, state );
325 static void sids2xids_recv(void *private_data, BOOL success, void *data, int len)
327 struct winbindd_cli_state *state =
328 talloc_get_type_abort(private_data, struct winbindd_cli_state);
331 DEBUG(5, ("Could not convert sids to xids\n"));
332 request_error(state);
336 state->response.extra_data.data = data;
337 state->response.length = sizeof(state->response) + len;
341 void winbindd_sids_to_unixids(struct winbindd_cli_state *state)
343 DEBUG(3, ("[%5lu]: sids to xids\n", (unsigned long)state->pid));
345 winbindd_sids2xids_async(state->mem_ctx,
346 state->request.extra_data.data,
347 state->request.extra_len,
348 sids2xids_recv, state);
351 static void set_mapping_recv(void *private_data, BOOL success)
353 struct winbindd_cli_state *state =
354 talloc_get_type_abort(private_data, struct winbindd_cli_state);
357 DEBUG(5, ("Could not set sid mapping\n"));
358 request_error(state);
365 void winbindd_set_mapping(struct winbindd_cli_state *state)
370 DEBUG(3, ("[%5lu]: set id map\n", (unsigned long)state->pid));
372 if ( ! state->privileged) {
373 DEBUG(0, ("Only root is allowed to set mappings!\n"));
374 request_error(state);
378 if (!string_to_sid(&sid, state->request.data.dual_idmapset.sid)) {
379 DEBUG(1, ("Could not get convert sid %s from string\n",
380 state->request.data.sid));
381 request_error(state);
386 map.xid.id = state->request.data.dual_idmapset.id;
387 map.xid.type = state->request.data.dual_idmapset.type;
389 winbindd_set_mapping_async(state->mem_ctx, &map,
390 set_mapping_recv, state);
393 static void set_hwm_recv(void *private_data, BOOL success)
395 struct winbindd_cli_state *state =
396 talloc_get_type_abort(private_data, struct winbindd_cli_state);
399 DEBUG(5, ("Could not set sid mapping\n"));
400 request_error(state);
407 void winbindd_set_hwm(struct winbindd_cli_state *state)
411 DEBUG(3, ("[%5lu]: set hwm\n", (unsigned long)state->pid));
413 if ( ! state->privileged) {
414 DEBUG(0, ("Only root is allowed to set mappings!\n"));
415 request_error(state);
419 xid.id = state->request.data.dual_idmapset.id;
420 xid.type = state->request.data.dual_idmapset.type;
422 winbindd_set_hwm_async(state->mem_ctx, &xid, set_hwm_recv, state);
425 /* Convert a uid to a sid */
427 static void uid2sid_recv(void *private_data, BOOL success, const char *sid)
429 struct winbindd_cli_state *state =
430 (struct winbindd_cli_state *)private_data;
433 DEBUG(10,("uid2sid: uid %lu has sid %s\n",
434 (unsigned long)(state->request.data.uid), sid));
435 fstrcpy(state->response.data.sid.sid, sid);
436 state->response.data.sid.type = SID_NAME_USER;
441 request_error(state);
445 void winbindd_uid_to_sid(struct winbindd_cli_state *state)
447 DEBUG(3, ("[%5lu]: uid to sid %lu\n", (unsigned long)state->pid,
448 (unsigned long)state->request.data.uid));
450 /* always go via the async interface (may block) */
451 winbindd_uid2sid_async(state->mem_ctx, state->request.data.uid, uid2sid_recv, state);
454 /* Convert a gid to a sid */
456 static void gid2sid_recv(void *private_data, BOOL success, const char *sid)
458 struct winbindd_cli_state *state =
459 (struct winbindd_cli_state *)private_data;
462 DEBUG(10,("gid2sid: gid %lu has sid %s\n",
463 (unsigned long)(state->request.data.gid), sid));
464 fstrcpy(state->response.data.sid.sid, sid);
465 state->response.data.sid.type = SID_NAME_DOM_GRP;
470 request_error(state);
475 void winbindd_gid_to_sid(struct winbindd_cli_state *state)
477 DEBUG(3, ("[%5lu]: gid to sid %lu\n", (unsigned long)state->pid,
478 (unsigned long)state->request.data.gid));
480 /* always use async calls (may block) */
481 winbindd_gid2sid_async(state->mem_ctx, state->request.data.gid, gid2sid_recv, state);
484 void winbindd_allocate_uid(struct winbindd_cli_state *state)
486 if ( !state->privileged ) {
487 DEBUG(2, ("winbindd_allocate_uid: non-privileged access "
489 request_error(state);
493 sendto_child(state, idmap_child());
496 enum winbindd_result winbindd_dual_allocate_uid(struct winbindd_domain *domain,
497 struct winbindd_cli_state *state)
501 if (!NT_STATUS_IS_OK(idmap_allocate_uid(&xid))) {
502 return WINBINDD_ERROR;
504 state->response.data.uid = xid.id;
508 void winbindd_allocate_gid(struct winbindd_cli_state *state)
510 if ( !state->privileged ) {
511 DEBUG(2, ("winbindd_allocate_gid: non-privileged access "
513 request_error(state);
517 sendto_child(state, idmap_child());
520 enum winbindd_result winbindd_dual_allocate_gid(struct winbindd_domain *domain,
521 struct winbindd_cli_state *state)
525 if (!NT_STATUS_IS_OK(idmap_allocate_gid(&xid))) {
526 return WINBINDD_ERROR;
528 state->response.data.gid = xid.id;
532 static void dump_maps_recv(void *private_data, BOOL success)
534 struct winbindd_cli_state *state =
535 talloc_get_type_abort(private_data, struct winbindd_cli_state);
538 DEBUG(5, ("Could not dump maps\n"));
539 request_error(state);
546 void winbindd_dump_maps(struct winbindd_cli_state *state)
548 if ( ! state->privileged) {
549 DEBUG(0, ("Only root is allowed to ask for an idmap dump!\n"));
550 request_error(state);
554 DEBUG(3, ("[%5lu]: dump maps\n", (unsigned long)state->pid));
556 winbindd_dump_maps_async(state->mem_ctx,
557 state->request.extra_data.data,
558 state->request.extra_len,
559 dump_maps_recv, state);