Renamed WINBINDD_INITGROUPS constant to WINBINDD_GETGROUPS.
[Samba/gebeck_regimport.git] / source3 / nsswitch / wb_client.c
blob1725ab34483de92c86c0ac9b8d2284b9d3a6ddac
1 /*
2 Unix SMB/Netbios implementation.
3 Version 2.0
5 winbind client code
7 Copyright (C) Tim Potter 2000
8 Copyright (C) Andrew Tridgell 2000
10 This library is free software; you can redistribute it and/or
11 modify it under the terms of the GNU Library General Public
12 License as published by the Free Software Foundation; either
13 version 2 of the License, or (at your option) any later version.
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Library General Public License for more details.
20 You should have received a copy of the GNU Library General Public
21 License along with this library; if not, write to the
22 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 Boston, MA 02111-1307, USA.
26 #include "includes.h"
28 /* Call winbindd to convert a name to a sid */
30 BOOL winbind_lookup_name(char *name, DOM_SID *sid, enum SID_NAME_USE *name_type)
32 struct winbindd_request request;
33 struct winbindd_response response;
34 enum nss_status result;
36 if (!sid || !name_type)
37 return False;
39 /* Send off request */
41 ZERO_STRUCT(request);
42 ZERO_STRUCT(response);
44 fstrcpy(request.data.name, name);
45 if ((result = winbindd_request(WINBINDD_LOOKUPNAME, &request,
46 &response)) == NSS_STATUS_SUCCESS) {
47 string_to_sid(sid, response.data.sid.sid);
48 *name_type = (enum SID_NAME_USE)response.data.sid.type;
51 return result == NSS_STATUS_SUCCESS;
54 /* Call winbindd to convert sid to name */
56 BOOL winbind_lookup_sid(DOM_SID *sid, fstring dom_name, fstring name, enum SID_NAME_USE *name_type)
58 struct winbindd_request request;
59 struct winbindd_response response;
60 enum nss_status result;
61 DOM_SID tmp_sid;
62 uint32 rid;
63 fstring sid_str;
65 if (!name_type)
66 return False;
68 /* Check if this is our own sid. This should perhaps be done by
69 winbind? For the moment handle it here. */
71 if (sid->num_auths == 5) {
72 sid_copy(&tmp_sid, sid);
73 sid_split_rid(&tmp_sid, &rid);
75 if (sid_equal(&global_sam_sid, &tmp_sid)) {
77 return map_domain_sid_to_name(&tmp_sid, dom_name) &&
78 local_lookup_rid(rid, name, name_type);
82 /* Initialise request */
84 ZERO_STRUCT(request);
85 ZERO_STRUCT(response);
87 sid_to_string(sid_str, sid);
88 fstrcpy(request.data.sid, sid_str);
90 /* Make request */
92 result = winbindd_request(WINBINDD_LOOKUPSID, &request, &response);
94 /* Copy out result */
96 if (result == NSS_STATUS_SUCCESS) {
97 parse_domain_user(response.data.name.name, dom_name, name);
98 *name_type = (enum SID_NAME_USE)response.data.name.type;
101 return (result == NSS_STATUS_SUCCESS);
104 /* Call winbindd to convert SID to uid */
106 static BOOL winbind_sid_to_uid(uid_t *puid, DOM_SID *sid)
108 struct winbindd_request request;
109 struct winbindd_response response;
110 int result;
111 fstring sid_str;
113 if (!puid)
114 return False;
116 /* Initialise request */
118 ZERO_STRUCT(request);
119 ZERO_STRUCT(response);
121 sid_to_string(sid_str, sid);
122 fstrcpy(request.data.sid, sid_str);
124 /* Make request */
126 result = winbindd_request(WINBINDD_SID_TO_UID, &request, &response);
128 /* Copy out result */
130 if (result == NSS_STATUS_SUCCESS) {
131 *puid = response.data.uid;
134 return (result == NSS_STATUS_SUCCESS);
137 /* Call winbindd to convert uid to sid */
139 static BOOL winbind_uid_to_sid(DOM_SID *sid, uid_t uid)
141 struct winbindd_request request;
142 struct winbindd_response response;
143 int result;
145 if (!sid)
146 return False;
148 /* Initialise request */
150 ZERO_STRUCT(request);
151 ZERO_STRUCT(response);
153 request.data.uid = uid;
155 /* Make request */
157 result = winbindd_request(WINBINDD_UID_TO_SID, &request, &response);
159 /* Copy out result */
161 if (result == NSS_STATUS_SUCCESS) {
162 string_to_sid(sid, response.data.sid.sid);
163 } else {
164 sid_copy(sid, &global_sid_NULL);
167 return (result == NSS_STATUS_SUCCESS);
170 /* Call winbindd to convert SID to gid */
172 static BOOL winbind_sid_to_gid(gid_t *pgid, DOM_SID *sid)
174 struct winbindd_request request;
175 struct winbindd_response response;
176 int result;
177 fstring sid_str;
179 if (!pgid)
180 return False;
182 /* Initialise request */
184 ZERO_STRUCT(request);
185 ZERO_STRUCT(response);
187 sid_to_string(sid_str, sid);
188 fstrcpy(request.data.sid, sid_str);
190 /* Make request */
192 result = winbindd_request(WINBINDD_SID_TO_UID, &request, &response);
194 /* Copy out result */
196 if (result == NSS_STATUS_SUCCESS) {
197 *pgid = response.data.gid;
200 return (result == NSS_STATUS_SUCCESS);
203 /* Call winbindd to convert gid to sid */
205 static BOOL winbind_gid_to_sid(DOM_SID *sid, gid_t gid)
207 struct winbindd_request request;
208 struct winbindd_response response;
209 int result;
211 if (!sid)
212 return False;
214 /* Initialise request */
216 ZERO_STRUCT(request);
217 ZERO_STRUCT(response);
219 request.data.gid = gid;
221 /* Make request */
223 result = winbindd_request(WINBINDD_GID_TO_SID, &request, &response);
225 /* Copy out result */
227 if (result == NSS_STATUS_SUCCESS) {
228 string_to_sid(sid, response.data.sid.sid);
229 } else {
230 sid_copy(sid, &global_sid_NULL);
233 return (result == NSS_STATUS_SUCCESS);
236 /* Fetch the list of groups a user is a member of from winbindd. This is
237 used by winbind_initgroups and winbind_getgroups. */
239 static int wb_getgroups(char *user, gid_t **groups)
241 struct winbindd_request request;
242 struct winbindd_response response;
243 int result;
245 /* Call winbindd */
247 fstrcpy(request.data.username, user);
249 ZERO_STRUCT(response);
251 result = winbindd_request(WINBINDD_GETGROUPS, &request, &response);
253 if (result == NSS_STATUS_SUCCESS) {
255 /* Return group list. Don't forget to free the group list
256 when finished. */
258 *groups = (gid_t *)response.extra_data;
259 return response.data.num_entries;
262 return -1;
265 /* Call winbindd to initialise group membership. This is necessary for
266 some systems (i.e RH5.2) that do not have an initgroups function as part
267 of the nss extension. In RH5.2 this is implemented using getgrent()
268 which can be amazingly inefficient as well as having problems with
269 username case. */
271 int winbind_initgroups(char *user, gid_t gid)
273 gid_t *groups = NULL;
274 int result;
275 char *sep;
277 /* Call normal initgroups if we are a local user */
279 sep = lp_winbind_separator();
281 if (!strchr(user, *sep)) {
282 return initgroups(user, gid);
285 result = wb_getgroups(user, &groups);
287 if (result != -1) {
288 int ngroups = result, i;
289 BOOL is_member = False;
291 /* Check to see if the passed gid is already in the list */
293 for (i = 0; i < ngroups; i++) {
294 if (groups[i] == gid) {
295 is_member = True;
299 /* Add group to list if necessary */
301 if (!is_member) {
302 groups = Realloc(groups, sizeof(gid_t) * ngroups + 1);
304 if (!groups) {
305 errno = ENOMEM;
306 result = -1;
307 goto done;
310 groups[ngroups] = gid;
311 ngroups++;
314 /* Set the groups */
316 if (setgroups(ngroups, groups) == -1) {
317 errno = EPERM;
318 result = -1;
319 goto done;
323 /* Free response data if necessary */
325 done:
326 safe_free(groups);
328 return result;
331 /* Return a list of groups the user is a member of. This function is
332 useful for large systems where inverting the group database would be too
333 time consuming. If size is zero, list is not modified and the total
334 number of groups for the user is returned. */
336 int winbind_getgroups(char *user, int size, gid_t *list)
338 gid_t *groups = NULL;
339 int result, i;
341 /* Fetch list of groups */
343 result = wb_getgroups(user, &groups);
345 if (size == 0) goto done;
347 if (result > size) {
348 result = -1;
349 errno = EINVAL; /* This is what getgroups() does */
350 goto done;
353 /* Copy list of groups across */
355 for (i = 0; i < result; i++) {
356 list[i] = groups[i];
359 done:
360 safe_free(groups);
361 return result;
364 /*****************************************************************
365 *THE CANONICAL* convert name to SID function.
366 Tries winbind first - then uses local lookup.
367 *****************************************************************/
369 BOOL lookup_name(char *name, DOM_SID *psid, enum SID_NAME_USE *name_type)
371 extern pstring global_myname;
372 fstring sid;
374 if (!winbind_lookup_name(name, psid, name_type)) {
375 BOOL ret;
377 DEBUG(10,("lookup_name: winbind lookup for %s failed - trying local\n", name ));
379 ret = local_lookup_name(global_myname, name, psid, name_type);
380 if (ret)
381 DEBUG(10,("lookup_name : (local) %s -> SID %s (type %u)\n",
382 name, sid_to_string(sid,psid),
383 (unsigned int)*name_type ));
384 else
385 DEBUG(10,("lookup name : (local) %s failed.\n",
386 name ));
387 return ret;
390 DEBUG(10,("lookup_name (winbindd): %s -> SID %s (type %u)\n",
391 name, sid_to_string(sid,psid), (unsigned int)*name_type ));
392 return True;
395 /*****************************************************************
396 *THE CANONICAL* convert SID to name function.
397 Tries winbind first - then uses local lookup.
398 *****************************************************************/
400 BOOL lookup_sid(DOM_SID *sid, fstring dom_name, fstring name, enum SID_NAME_USE *name_type)
402 if (!winbind_lookup_sid(sid, dom_name, name, name_type)) {
403 fstring sid_str;
404 DOM_SID tmp_sid;
405 uint32 rid;
407 DEBUG(10,("lookup_sid: winbind lookup for SID %s failed - trying local.\n", sid_to_string(sid_str, sid) ));
409 sid_copy(&tmp_sid, sid);
410 sid_split_rid(&tmp_sid, &rid);
411 return map_domain_sid_to_name(&tmp_sid, dom_name) &&
412 lookup_known_rid(&tmp_sid, rid, name, name_type);
414 return True;
417 /*****************************************************************
418 *THE CANONICAL* convert uid_t to SID function.
419 Tries winbind first - then uses local lookup.
420 Returns SID pointer.
421 *****************************************************************/
423 DOM_SID *uid_to_sid(DOM_SID *psid, uid_t uid)
425 fstring sid;
427 if (!winbind_uid_to_sid(psid, uid)) {
428 DEBUG(10,("uid_to_sid: winbind lookup for uid %u failed - trying local.\n", (unsigned int)uid ));
430 return local_uid_to_sid(psid, uid);
433 DEBUG(10,("uid_to_sid: winbindd %u -> %s\n",
434 (unsigned int)uid, sid_to_string(sid, psid) ));
436 return psid;
439 /*****************************************************************
440 *THE CANONICAL* convert gid_t to SID function.
441 Tries winbind first - then uses local lookup.
442 Returns SID pointer.
443 *****************************************************************/
445 DOM_SID *gid_to_sid(DOM_SID *psid, gid_t gid)
447 fstring sid;
449 if (!winbind_gid_to_sid(psid, gid)) {
450 DEBUG(10,("gid_to_sid: winbind lookup for gid %u failed - trying local.\n", (unsigned int)gid ));
452 return local_gid_to_sid(psid, gid);
455 DEBUG(10,("gid_to_sid: winbindd %u -> %s\n",
456 (unsigned int)gid, sid_to_string(sid,psid) ));
458 return psid;
461 /*****************************************************************
462 *THE CANONICAL* convert SID to uid function.
463 Tries winbind first - then uses local lookup.
464 Returns True if this name is a user sid and the conversion
465 was done correctly, False if not.
466 *****************************************************************/
468 BOOL sid_to_uid(DOM_SID *psid, uid_t *puid, enum SID_NAME_USE *sidtype)
470 fstring dom_name, name, sid_str;
471 enum SID_NAME_USE name_type;
473 *sidtype = SID_NAME_UNKNOWN;
476 * First we must look up the name and decide if this is a user sid.
479 if (!winbind_lookup_sid(psid, dom_name, name, &name_type)) {
480 DEBUG(10,("sid_to_uid: winbind lookup for sid %s failed - trying local.\n",
481 sid_to_string(sid_str, psid) ));
483 return local_sid_to_uid(puid, psid, sidtype);
487 * Ensure this is a user sid.
490 if (name_type != SID_NAME_USER) {
491 DEBUG(10,("sid_to_uid: winbind lookup succeeded but SID is not a uid (%u)\n",
492 (unsigned int)name_type ));
493 return False;
496 *sidtype = SID_NAME_USER;
499 * Get the uid for this SID.
502 if (!winbind_sid_to_uid(puid, psid)) {
503 DEBUG(10,("sid_to_uid: winbind lookup for sid %s failed.\n",
504 sid_to_string(sid_str, psid) ));
505 return False;
508 DEBUG(10,("sid_to_uid: winbindd %s -> %u\n",
509 sid_to_string(sid_str, psid),
510 (unsigned int)*puid ));
512 return True;
515 /*****************************************************************
516 *THE CANONICAL* convert SID to gid function.
517 Tries winbind first - then uses local lookup.
518 Returns True if this name is a user sid and the conversion
519 was done correctly, False if not.
520 *****************************************************************/
522 BOOL sid_to_gid(DOM_SID *psid, gid_t *pgid, enum SID_NAME_USE *sidtype)
524 fstring dom_name, name, sid_str;
525 enum SID_NAME_USE name_type;
527 *sidtype = SID_NAME_UNKNOWN;
530 * First we must look up the name and decide if this is a group sid.
533 if (!winbind_lookup_sid(psid, dom_name, name, &name_type)) {
534 DEBUG(10,("sid_to_gid: winbind lookup for sid %s failed - trying local.\n",
535 sid_to_string(sid_str, psid) ));
537 return local_sid_to_gid(pgid, psid, sidtype);
541 * Ensure this is a group sid.
544 if ((name_type != SID_NAME_DOM_GRP) && (name_type != SID_NAME_ALIAS) && (name_type != SID_NAME_WKN_GRP)) {
545 DEBUG(10,("sid_to_gid: winbind lookup succeeded but SID is not a know group (%u)\n",
546 (unsigned int)name_type ));
548 return local_sid_to_gid(pgid, psid, sidtype);
551 *sidtype = name_type;
554 * Get the gid for this SID.
557 if (!winbind_sid_to_gid(pgid, psid)) {
558 DEBUG(10,("sid_to_gid: winbind lookup for sid %s failed.\n",
559 sid_to_string(sid_str, psid) ));
560 return False;
563 DEBUG(10,("gid_to_uid: winbindd %s -> %u\n",
564 sid_to_string(sid_str, psid),
565 (unsigned int)*pgid ));
567 return True;