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 /* 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)
39 /* Send off 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;
63 /* Initialise request */
66 ZERO_STRUCT(response);
68 sid_to_string(sid_str, sid);
69 fstrcpy(request.data.sid, sid_str);
73 result = winbindd_request(WINBINDD_LOOKUPSID, &request, &response);
77 if (result == NSS_STATUS_SUCCESS) {
78 parse_domain_user(response.data.name.name, dom_name, name);
79 *name_type = (enum SID_NAME_USE)response.data.name.type;
80 DEBUG(10,("winbind_lookup_sid: SUCCESS: SID %s -> %s %s\n", sid_str, dom_name, name ));
83 return (result == NSS_STATUS_SUCCESS);
86 /* Call winbindd to convert SID to uid */
88 BOOL winbind_sid_to_uid(uid_t *puid, DOM_SID *sid)
90 struct winbindd_request request;
91 struct winbindd_response response;
98 /* Initialise request */
100 ZERO_STRUCT(request);
101 ZERO_STRUCT(response);
103 sid_to_string(sid_str, sid);
104 fstrcpy(request.data.sid, sid_str);
108 result = winbindd_request(WINBINDD_SID_TO_UID, &request, &response);
110 /* Copy out result */
112 if (result == NSS_STATUS_SUCCESS) {
113 *puid = response.data.uid;
116 return (result == NSS_STATUS_SUCCESS);
119 /* Call winbindd to convert uid to sid */
121 BOOL winbind_uid_to_sid(DOM_SID *sid, uid_t uid)
123 struct winbindd_request request;
124 struct winbindd_response response;
130 /* Initialise request */
132 ZERO_STRUCT(request);
133 ZERO_STRUCT(response);
135 request.data.uid = uid;
139 result = winbindd_request(WINBINDD_UID_TO_SID, &request, &response);
141 /* Copy out result */
143 if (result == NSS_STATUS_SUCCESS) {
144 string_to_sid(sid, response.data.sid.sid);
146 sid_copy(sid, &global_sid_NULL);
149 return (result == NSS_STATUS_SUCCESS);
152 /* Call winbindd to convert SID to gid */
154 BOOL winbind_sid_to_gid(gid_t *pgid, DOM_SID *sid)
156 struct winbindd_request request;
157 struct winbindd_response response;
164 /* Initialise request */
166 ZERO_STRUCT(request);
167 ZERO_STRUCT(response);
169 sid_to_string(sid_str, sid);
170 fstrcpy(request.data.sid, sid_str);
174 result = winbindd_request(WINBINDD_SID_TO_UID, &request, &response);
176 /* Copy out result */
178 if (result == NSS_STATUS_SUCCESS) {
179 *pgid = response.data.gid;
182 return (result == NSS_STATUS_SUCCESS);
185 /* Call winbindd to convert gid to sid */
187 BOOL winbind_gid_to_sid(DOM_SID *sid, gid_t gid)
189 struct winbindd_request request;
190 struct winbindd_response response;
196 /* Initialise request */
198 ZERO_STRUCT(request);
199 ZERO_STRUCT(response);
201 request.data.gid = gid;
205 result = winbindd_request(WINBINDD_GID_TO_SID, &request, &response);
207 /* Copy out result */
209 if (result == NSS_STATUS_SUCCESS) {
210 string_to_sid(sid, response.data.sid.sid);
212 sid_copy(sid, &global_sid_NULL);
215 return (result == NSS_STATUS_SUCCESS);
218 /* Fetch the list of groups a user is a member of from winbindd. This is
219 used by winbind_initgroups and winbind_getgroups. */
221 static int wb_getgroups(char *user, gid_t **groups)
223 struct winbindd_request request;
224 struct winbindd_response response;
229 fstrcpy(request.data.username, user);
231 ZERO_STRUCT(response);
233 result = winbindd_request(WINBINDD_GETGROUPS, &request, &response);
235 if (result == NSS_STATUS_SUCCESS) {
237 /* Return group list. Don't forget to free the group list
240 *groups = (gid_t *)response.extra_data;
241 return response.data.num_entries;
247 /* Call winbindd to initialise group membership. This is necessary for
248 some systems (i.e RH5.2) that do not have an initgroups function as part
249 of the nss extension. In RH5.2 this is implemented using getgrent()
250 which can be amazingly inefficient as well as having problems with
253 int winbind_initgroups(char *user, gid_t gid)
255 gid_t *groups = NULL;
259 /* Call normal initgroups if we are a local user */
261 sep = lp_winbind_separator();
263 if (!strchr(user, *sep)) {
264 return initgroups(user, gid);
267 result = wb_getgroups(user, &groups);
269 DEBUG(10,("winbind_getgroups: %s: result = %s\n", user,
270 result == -1 ? "FAIL" : "SUCCESS"));
273 int ngroups = result, i;
274 BOOL is_member = False;
276 /* Check to see if the passed gid is already in the list */
278 for (i = 0; i < ngroups; i++) {
279 if (groups[i] == gid) {
284 /* Add group to list if necessary */
287 groups = Realloc(groups, sizeof(gid_t) * ngroups + 1);
295 groups[ngroups] = gid;
301 if (sys_setgroups(ngroups, groups) == -1) {
309 /* The call failed. Set errno to something so we don't get
310 a bogus value from the last failed system call. */
315 /* Free response data if necessary */
323 /* Return a list of groups the user is a member of. This function is
324 useful for large systems where inverting the group database would be too
325 time consuming. If size is zero, list is not modified and the total
326 number of groups for the user is returned. */
328 int winbind_getgroups(char *user, int size, gid_t *list)
330 gid_t *groups = NULL;
333 /* Fetch list of groups */
335 result = wb_getgroups(user, &groups);
337 if (size == 0) goto done;
341 errno = EINVAL; /* This is what getgroups() does */
345 /* Copy list of groups across */
347 for (i = 0; i < result; i++) {
356 /**********************************************************************************
357 Utility function. Convert a uid_t to a name if possible.
358 **********************************************************************************/
360 BOOL winbind_uidtoname(fstring name, uid_t uid)
365 enum SID_NAME_USE name_type;
367 if (!winbind_uid_to_sid(&sid, uid))
369 if (!winbind_lookup_sid(&sid, dom_name, user_name, &name_type))
372 if (name_type != SID_NAME_USER)
375 slprintf(name, sizeof(fstring)-1, "%s%s%s", dom_name, lp_winbind_separator(), user_name );
379 /**********************************************************************************
380 Utility function. Convert a gid_t to a name if possible.
381 **********************************************************************************/
383 BOOL winbind_gidtoname(fstring name, gid_t gid)
388 enum SID_NAME_USE name_type;
390 if (!winbind_gid_to_sid(&sid, gid))
392 if (!winbind_lookup_sid(&sid, dom_name, group_name, &name_type))
395 if (name_type != SID_NAME_USER)
398 slprintf(name, sizeof(fstring)-1, "%s%s%s", dom_name, lp_winbind_separator(), group_name );
402 /**********************************************************************************
403 Utility function. Convert a name to a uid_t if possible.
404 **********************************************************************************/
406 BOOL winbind_nametouid(uid_t *puid, char *name)
409 enum SID_NAME_USE name_type;
411 if (!winbind_lookup_name(name, &sid, &name_type)) {
415 if (name_type != SID_NAME_USER)
418 return winbind_sid_to_uid(puid, &sid);
421 /**********************************************************************************
422 Utility function. Convert a name to a gid_t if possible.
423 **********************************************************************************/
425 BOOL winbind_nametogid(gid_t *pgid, char *gname)
428 enum SID_NAME_USE name_type;
430 if (!winbind_lookup_name(gname, &g_sid, &name_type)) {
434 if (name_type != SID_NAME_DOM_GRP)
437 return winbind_sid_to_gid(pgid, &g_sid);