2 Unix SMB/Netbios implementation.
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.
28 NSS_STATUS winbindd_request(int req_type,
29 struct winbindd_request *request,
30 struct winbindd_response *response);
32 /* Copy of parse_domain_user from winbindd_util.c. Parse a string of the
33 form DOMAIN/user into a domain and a user */
35 static void parse_domain_user(char *domuser, fstring domain, fstring user)
37 char *p = strchr(domuser,*lp_winbind_separator());
41 fstrcpy(user, domuser);
46 fstrcpy(domain, domuser);
47 domain[PTR_DIFF(p, domuser)] = 0;
51 /* Call winbindd to convert a name to a sid */
53 BOOL winbind_lookup_name(const char *name, DOM_SID *sid,
54 enum SID_NAME_USE *name_type)
56 struct winbindd_request request;
57 struct winbindd_response response;
60 if (!sid || !name_type)
64 * Don't do the lookup if the name has no separator.
67 if (!strchr(name, *lp_winbind_separator()))
70 /* Send off request */
73 ZERO_STRUCT(response);
75 fstrcpy(request.data.name, name);
77 if ((result = winbindd_request(WINBINDD_LOOKUPNAME, &request,
78 &response)) == NSS_STATUS_SUCCESS) {
79 string_to_sid(sid, response.data.sid.sid);
80 *name_type = (enum SID_NAME_USE)response.data.sid.type;
83 return result == NSS_STATUS_SUCCESS;
86 /* Call winbindd to convert sid to name */
88 BOOL winbind_lookup_sid(DOM_SID *sid, fstring dom_name, fstring name,
89 enum SID_NAME_USE *name_type)
91 struct winbindd_request request;
92 struct winbindd_response response;
96 /* Initialise request */
99 ZERO_STRUCT(response);
101 sid_to_string(sid_str, sid);
102 fstrcpy(request.data.sid, sid_str);
106 result = winbindd_request(WINBINDD_LOOKUPSID, &request, &response);
108 /* Copy out result */
110 if (result == NSS_STATUS_SUCCESS) {
111 parse_domain_user(response.data.name.name, dom_name, name);
112 *name_type = (enum SID_NAME_USE)response.data.name.type;
114 DEBUG(10, ("winbind_lookup_sid: SUCCESS: SID %s -> %s %s\n",
115 sid_str, dom_name, name));
118 return (result == NSS_STATUS_SUCCESS);
121 /* Call winbindd to convert SID to uid */
123 BOOL winbind_sid_to_uid(uid_t *puid, DOM_SID *sid)
125 struct winbindd_request request;
126 struct winbindd_response response;
133 /* Initialise request */
135 ZERO_STRUCT(request);
136 ZERO_STRUCT(response);
138 sid_to_string(sid_str, sid);
139 fstrcpy(request.data.sid, sid_str);
143 result = winbindd_request(WINBINDD_SID_TO_UID, &request, &response);
145 /* Copy out result */
147 if (result == NSS_STATUS_SUCCESS) {
148 *puid = response.data.uid;
151 return (result == NSS_STATUS_SUCCESS);
154 /* Call winbindd to convert uid to sid */
156 BOOL winbind_uid_to_sid(DOM_SID *sid, uid_t uid)
158 struct winbindd_request request;
159 struct winbindd_response response;
165 /* Initialise request */
167 ZERO_STRUCT(request);
168 ZERO_STRUCT(response);
170 request.data.uid = uid;
174 result = winbindd_request(WINBINDD_UID_TO_SID, &request, &response);
176 /* Copy out result */
178 if (result == NSS_STATUS_SUCCESS) {
179 string_to_sid(sid, response.data.sid.sid);
181 sid_copy(sid, &global_sid_NULL);
184 return (result == NSS_STATUS_SUCCESS);
187 /* Call winbindd to convert SID to gid */
189 BOOL winbind_sid_to_gid(gid_t *pgid, DOM_SID *sid)
191 struct winbindd_request request;
192 struct winbindd_response response;
199 /* Initialise request */
201 ZERO_STRUCT(request);
202 ZERO_STRUCT(response);
204 sid_to_string(sid_str, sid);
205 fstrcpy(request.data.sid, sid_str);
209 result = winbindd_request(WINBINDD_SID_TO_GID, &request, &response);
211 /* Copy out result */
213 if (result == NSS_STATUS_SUCCESS) {
214 *pgid = response.data.gid;
217 return (result == NSS_STATUS_SUCCESS);
220 /* Call winbindd to convert gid to sid */
222 BOOL winbind_gid_to_sid(DOM_SID *sid, gid_t gid)
224 struct winbindd_request request;
225 struct winbindd_response response;
231 /* Initialise request */
233 ZERO_STRUCT(request);
234 ZERO_STRUCT(response);
236 request.data.gid = gid;
240 result = winbindd_request(WINBINDD_GID_TO_SID, &request, &response);
242 /* Copy out result */
244 if (result == NSS_STATUS_SUCCESS) {
245 string_to_sid(sid, response.data.sid.sid);
247 sid_copy(sid, &global_sid_NULL);
250 return (result == NSS_STATUS_SUCCESS);
253 /* Fetch the list of groups a user is a member of from winbindd. This is
254 used by winbind_initgroups and winbind_getgroups. */
256 static int wb_getgroups(const char *user, gid_t **groups)
258 struct winbindd_request request;
259 struct winbindd_response response;
264 fstrcpy(request.data.username, user);
266 ZERO_STRUCT(response);
268 result = winbindd_request(WINBINDD_GETGROUPS, &request, &response);
270 if (result == NSS_STATUS_SUCCESS) {
272 /* Return group list. Don't forget to free the group list
275 *groups = (gid_t *)response.extra_data;
276 return response.data.num_entries;
282 /* Call winbindd to initialise group membership. This is necessary for
283 some systems (i.e RH5.2) that do not have an initgroups function as part
284 of the nss extension. In RH5.2 this is implemented using getgrent()
285 which can be amazingly inefficient as well as having problems with
288 int winbind_initgroups(char *user, gid_t gid)
290 gid_t *tgr, *groups = NULL;
293 /* Call normal initgroups if we are a local user */
295 if (!strchr(user, *lp_winbind_separator())) {
296 return initgroups(user, gid);
299 result = wb_getgroups(user, &groups);
301 DEBUG(10,("winbind_getgroups: %s: result = %s\n", user,
302 result == -1 ? "FAIL" : "SUCCESS"));
305 int ngroups = result, i;
306 BOOL is_member = False;
308 /* Check to see if the passed gid is already in the list */
310 for (i = 0; i < ngroups; i++) {
311 if (groups[i] == gid) {
316 /* Add group to list if necessary */
319 tgr = (gid_t *)Realloc(groups, sizeof(gid_t) * ngroups + 1);
328 groups[ngroups] = gid;
334 if (sys_setgroups(ngroups, groups) == -1) {
342 /* The call failed. Set errno to something so we don't get
343 a bogus value from the last failed system call. */
348 /* Free response data if necessary */
356 /* Return a list of groups the user is a member of. This function is
357 useful for large systems where inverting the group database would be too
358 time consuming. If size is zero, list is not modified and the total
359 number of groups for the user is returned. */
361 int winbind_getgroups(const char *user, int size, gid_t *list)
363 gid_t *groups = NULL;
367 * Don't do the lookup if the name has no separator.
370 if (!strchr(user, *lp_winbind_separator()))
373 /* Fetch list of groups */
375 result = wb_getgroups(user, &groups);
382 errno = EINVAL; /* This is what getgroups() does */
386 /* Copy list of groups across */
388 for (i = 0; i < result; i++) {
397 /* Utility function. Convert a uid_t to a name if possible. */
399 BOOL winbind_uidtoname(fstring name, uid_t uid)
404 enum SID_NAME_USE name_type;
406 if (!winbind_uid_to_sid(&sid, uid))
408 if (!winbind_lookup_sid(&sid, dom_name, user_name, &name_type))
411 if (name_type != SID_NAME_USER)
414 slprintf(name, sizeof(fstring)-1, "%s%s%s", dom_name,
415 lp_winbind_separator(), user_name);
420 /* Utility function. Convert a gid_t to a name if possible. */
422 BOOL winbind_gidtoname(fstring name, gid_t gid)
427 enum SID_NAME_USE name_type;
429 if (!winbind_gid_to_sid(&sid, gid))
431 if (!winbind_lookup_sid(&sid, dom_name, group_name, &name_type))
434 if (name_type != SID_NAME_DOM_GRP)
437 slprintf(name, sizeof(fstring)-1, "%s%s%s", dom_name,
438 lp_winbind_separator(), group_name);
443 /* Utility function. Convert a name to a uid_t if possible. */
445 BOOL winbind_nametouid(uid_t *puid, const char *name)
448 enum SID_NAME_USE name_type;
450 if (!winbind_lookup_name(name, &sid, &name_type))
453 if (name_type != SID_NAME_USER)
456 return winbind_sid_to_uid(puid, &sid);
459 /* Utility function. Convert a name to a gid_t if possible. */
461 BOOL winbind_nametogid(gid_t *pgid, const char *gname)
464 enum SID_NAME_USE name_type;
466 if (!winbind_lookup_name(gname, &g_sid, &name_type))
469 if (name_type != SID_NAME_DOM_GRP)
472 return winbind_sid_to_gid(pgid, &g_sid);