preparing for release of 3.0-alpha11
[Samba/ekacnet.git] / source / nsswitch / wb_client.c
blob7bfa65176c7f81e008c9d35e7621463c30164a0e
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"
27 #include "nsswitch/nss.h"
29 NSS_STATUS winbindd_request(int req_type,
30 struct winbindd_request *request,
31 struct winbindd_response *response);
33 /* Copy of parse_domain_user from winbindd_util.c. Parse a string of the
34 form DOMAIN/user into a domain and a user */
36 static BOOL parse_domain_user(const char *domuser, fstring domain, fstring user)
38 char *p = strchr(domuser,*lp_winbind_separator());
40 if (!p)
41 return False;
43 fstrcpy(user, p+1);
44 fstrcpy(domain, domuser);
45 domain[PTR_DIFF(p, domuser)] = 0;
46 strupper(domain);
47 return True;
50 /* Call winbindd to convert a name to a sid */
52 BOOL winbind_lookup_name(const char *name, DOM_SID *sid,
53 enum SID_NAME_USE *name_type)
55 struct winbindd_request request;
56 struct winbindd_response response;
57 NSS_STATUS result;
59 if (!sid || !name_type)
60 return False;
63 * Don't do the lookup if the name has no separator.
66 if (!strchr(name, *lp_winbind_separator()))
67 return False;
69 /* Send off request */
71 ZERO_STRUCT(request);
72 ZERO_STRUCT(response);
74 fstrcpy(request.data.name, name);
76 if ((result = winbindd_request(WINBINDD_LOOKUPNAME, &request,
77 &response)) == NSS_STATUS_SUCCESS) {
78 string_to_sid(sid, response.data.sid.sid);
79 *name_type = (enum SID_NAME_USE)response.data.sid.type;
82 return result == NSS_STATUS_SUCCESS;
85 /* Call winbindd to convert sid to name */
87 BOOL winbind_lookup_sid(DOM_SID *sid, fstring dom_name, fstring name,
88 enum SID_NAME_USE *name_type)
90 struct winbindd_request request;
91 struct winbindd_response response;
92 NSS_STATUS result;
93 fstring sid_str;
95 /* Initialise request */
97 ZERO_STRUCT(request);
98 ZERO_STRUCT(response);
100 sid_to_string(sid_str, sid);
101 fstrcpy(request.data.sid, sid_str);
103 /* Make request */
105 result = winbindd_request(WINBINDD_LOOKUPSID, &request, &response);
107 /* Copy out result */
109 if (result == NSS_STATUS_SUCCESS) {
110 parse_domain_user(response.data.name.name, dom_name, name);
111 *name_type = (enum SID_NAME_USE)response.data.name.type;
113 DEBUG(10, ("winbind_lookup_sid: SUCCESS: SID %s -> %s %s\n",
114 sid_str, dom_name, name));
117 return (result == NSS_STATUS_SUCCESS);
120 /* Call winbindd to convert SID to uid */
122 BOOL winbind_sid_to_uid(uid_t *puid, DOM_SID *sid)
124 struct winbindd_request request;
125 struct winbindd_response response;
126 int result;
127 fstring sid_str;
129 if (!puid)
130 return False;
132 /* Initialise request */
134 ZERO_STRUCT(request);
135 ZERO_STRUCT(response);
137 sid_to_string(sid_str, sid);
138 fstrcpy(request.data.sid, sid_str);
140 /* Make request */
142 result = winbindd_request(WINBINDD_SID_TO_UID, &request, &response);
144 /* Copy out result */
146 if (result == NSS_STATUS_SUCCESS) {
147 *puid = response.data.uid;
150 return (result == NSS_STATUS_SUCCESS);
153 /* Call winbindd to convert uid to sid */
155 BOOL winbind_uid_to_sid(DOM_SID *sid, uid_t uid)
157 struct winbindd_request request;
158 struct winbindd_response response;
159 int result;
161 if (!sid)
162 return False;
164 /* Initialise request */
166 ZERO_STRUCT(request);
167 ZERO_STRUCT(response);
169 request.data.uid = uid;
171 /* Make request */
173 result = winbindd_request(WINBINDD_UID_TO_SID, &request, &response);
175 /* Copy out result */
177 if (result == NSS_STATUS_SUCCESS) {
178 string_to_sid(sid, response.data.sid.sid);
179 } else {
180 sid_copy(sid, &global_sid_NULL);
183 return (result == NSS_STATUS_SUCCESS);
186 /* Call winbindd to convert SID to gid */
188 BOOL winbind_sid_to_gid(gid_t *pgid, DOM_SID *sid)
190 struct winbindd_request request;
191 struct winbindd_response response;
192 int result;
193 fstring sid_str;
195 if (!pgid)
196 return False;
198 /* Initialise request */
200 ZERO_STRUCT(request);
201 ZERO_STRUCT(response);
203 sid_to_string(sid_str, sid);
204 fstrcpy(request.data.sid, sid_str);
206 /* Make request */
208 result = winbindd_request(WINBINDD_SID_TO_GID, &request, &response);
210 /* Copy out result */
212 if (result == NSS_STATUS_SUCCESS) {
213 *pgid = response.data.gid;
216 return (result == NSS_STATUS_SUCCESS);
219 /* Call winbindd to convert gid to sid */
221 BOOL winbind_gid_to_sid(DOM_SID *sid, gid_t gid)
223 struct winbindd_request request;
224 struct winbindd_response response;
225 int result;
227 if (!sid)
228 return False;
230 /* Initialise request */
232 ZERO_STRUCT(request);
233 ZERO_STRUCT(response);
235 request.data.gid = gid;
237 /* Make request */
239 result = winbindd_request(WINBINDD_GID_TO_SID, &request, &response);
241 /* Copy out result */
243 if (result == NSS_STATUS_SUCCESS) {
244 string_to_sid(sid, response.data.sid.sid);
245 } else {
246 sid_copy(sid, &global_sid_NULL);
249 return (result == NSS_STATUS_SUCCESS);
252 /* Fetch the list of groups a user is a member of from winbindd. This is
253 used by winbind_initgroups and winbind_getgroups. */
255 static int wb_getgroups(const char *user, gid_t **groups)
257 struct winbindd_request request;
258 struct winbindd_response response;
259 int result;
261 /* Call winbindd */
263 fstrcpy(request.data.username, user);
265 ZERO_STRUCT(response);
267 result = winbindd_request(WINBINDD_GETGROUPS, &request, &response);
269 if (result == NSS_STATUS_SUCCESS) {
271 /* Return group list. Don't forget to free the group list
272 when finished. */
274 *groups = (gid_t *)response.extra_data;
275 return response.data.num_entries;
278 return -1;
281 /* Call winbindd to initialise group membership. This is necessary for
282 some systems (i.e RH5.2) that do not have an initgroups function as part
283 of the nss extension. In RH5.2 this is implemented using getgrent()
284 which can be amazingly inefficient as well as having problems with
285 username case. */
287 int winbind_initgroups(char *user, gid_t gid)
289 gid_t *tgr, *groups = NULL;
290 int result;
292 /* Call normal initgroups if we are a local user */
294 if (!strchr(user, *lp_winbind_separator())) {
295 return initgroups(user, gid);
298 result = wb_getgroups(user, &groups);
300 DEBUG(10,("winbind_getgroups: %s: result = %s\n", user,
301 result == -1 ? "FAIL" : "SUCCESS"));
303 if (result != -1) {
304 int ngroups = result, i;
305 BOOL is_member = False;
307 /* Check to see if the passed gid is already in the list */
309 for (i = 0; i < ngroups; i++) {
310 if (groups[i] == gid) {
311 is_member = True;
315 /* Add group to list if necessary */
317 if (!is_member) {
318 tgr = (gid_t *)Realloc(groups, sizeof(gid_t) * ngroups + 1);
320 if (!tgr) {
321 errno = ENOMEM;
322 result = -1;
323 goto done;
325 else groups = tgr;
327 groups[ngroups] = gid;
328 ngroups++;
331 /* Set the groups */
333 if (sys_setgroups(ngroups, groups) == -1) {
334 errno = EPERM;
335 result = -1;
336 goto done;
339 } else {
341 /* The call failed. Set errno to something so we don't get
342 a bogus value from the last failed system call. */
344 errno = EIO;
347 /* Free response data if necessary */
349 done:
350 SAFE_FREE(groups);
352 return result;
355 /* Return a list of groups the user is a member of. This function is
356 useful for large systems where inverting the group database would be too
357 time consuming. If size is zero, list is not modified and the total
358 number of groups for the user is returned. */
360 int winbind_getgroups(const char *user, int size, gid_t *list)
362 gid_t *groups = NULL;
363 int result, i;
366 * Don't do the lookup if the name has no separator.
369 if (!strchr(user, *lp_winbind_separator()))
370 return -1;
372 /* Fetch list of groups */
374 result = wb_getgroups(user, &groups);
376 if (size == 0)
377 goto done;
379 if (result > size) {
380 result = -1;
381 errno = EINVAL; /* This is what getgroups() does */
382 goto done;
385 /* Copy list of groups across */
387 for (i = 0; i < result; i++) {
388 list[i] = groups[i];
391 done:
392 SAFE_FREE(groups);
393 return result;
396 /* Utility function. Convert a uid_t to a name if possible. */
398 BOOL winbind_uidtoname(fstring name, uid_t uid)
400 DOM_SID sid;
401 fstring dom_name;
402 fstring user_name;
403 enum SID_NAME_USE name_type;
405 if (!winbind_uid_to_sid(&sid, uid))
406 return False;
407 if (!winbind_lookup_sid(&sid, dom_name, user_name, &name_type))
408 return False;
410 if (name_type != SID_NAME_USER)
411 return False;
413 slprintf(name, sizeof(fstring)-1, "%s%s%s", dom_name,
414 lp_winbind_separator(), user_name);
416 return True;
419 /* Utility function. Convert a gid_t to a name if possible. */
421 BOOL winbind_gidtoname(fstring name, gid_t gid)
423 DOM_SID sid;
424 fstring dom_name;
425 fstring group_name;
426 enum SID_NAME_USE name_type;
428 if (!winbind_gid_to_sid(&sid, gid))
429 return False;
430 if (!winbind_lookup_sid(&sid, dom_name, group_name, &name_type))
431 return False;
433 if (name_type != SID_NAME_DOM_GRP)
434 return False;
436 slprintf(name, sizeof(fstring)-1, "%s%s%s", dom_name,
437 lp_winbind_separator(), group_name);
439 return True;
442 /* Utility function. Convert a name to a uid_t if possible. */
444 BOOL winbind_nametouid(uid_t *puid, const char *name)
446 DOM_SID sid;
447 enum SID_NAME_USE name_type;
449 if (!winbind_lookup_name(name, &sid, &name_type))
450 return False;
452 if (name_type != SID_NAME_USER)
453 return False;
455 return winbind_sid_to_uid(puid, &sid);
458 /* Utility function. Convert a name to a gid_t if possible. */
460 BOOL winbind_nametogid(gid_t *pgid, const char *gname)
462 DOM_SID g_sid;
463 enum SID_NAME_USE name_type;
465 if (!winbind_lookup_name(gname, &g_sid, &name_type))
466 return False;
468 if (name_type != SID_NAME_DOM_GRP)
469 return False;
471 return winbind_sid_to_gid(pgid, &g_sid);