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 /* Copy of parse_domain_user from winbindd_util.c. Parse a string of the
29 form DOMAIN/user into a domain and a user */
31 static void parse_domain_user(char *domuser, fstring domain, fstring user)
34 char *sep = lp_winbind_separator();
36 p = strchr(domuser,*sep);
37 if (!p) p = strchr(domuser,'\\');
40 fstrcpy(user, domuser);
45 fstrcpy(domain, domuser);
46 domain[PTR_DIFF(p, domuser)] = 0;
50 /* Call winbindd to convert a name to a sid */
52 BOOL winbind_lookup_name(const char *name, DOM_SID *sid, enum SID_NAME_USE *name_type)
54 struct winbindd_request request;
55 struct winbindd_response response;
56 enum nss_status result;
58 if (!sid || !name_type)
61 /* Send off request */
64 ZERO_STRUCT(response);
66 fstrcpy(request.data.name, name);
67 if ((result = winbindd_request(WINBINDD_LOOKUPNAME, &request,
68 &response)) == NSS_STATUS_SUCCESS) {
69 string_to_sid(sid, response.data.sid.sid);
70 *name_type = (enum SID_NAME_USE)response.data.sid.type;
73 return result == NSS_STATUS_SUCCESS;
76 /* Call winbindd to convert sid to name */
78 BOOL winbind_lookup_sid(DOM_SID *sid, fstring dom_name, fstring name, enum SID_NAME_USE *name_type)
80 struct winbindd_request request;
81 struct winbindd_response response;
82 enum nss_status result;
85 /* Initialise request */
88 ZERO_STRUCT(response);
90 sid_to_string(sid_str, sid);
91 fstrcpy(request.data.sid, sid_str);
95 result = winbindd_request(WINBINDD_LOOKUPSID, &request, &response);
99 if (result == NSS_STATUS_SUCCESS) {
100 parse_domain_user(response.data.name.name, dom_name, name);
101 *name_type = (enum SID_NAME_USE)response.data.name.type;
102 DEBUG(10,("winbind_lookup_sid: SUCCESS: SID %s -> %s %s\n", sid_str, dom_name, name ));
105 return (result == NSS_STATUS_SUCCESS);
108 /* Call winbindd to convert SID to uid */
110 BOOL winbind_sid_to_uid(uid_t *puid, DOM_SID *sid)
112 struct winbindd_request request;
113 struct winbindd_response response;
120 /* Initialise request */
122 ZERO_STRUCT(request);
123 ZERO_STRUCT(response);
125 sid_to_string(sid_str, sid);
126 fstrcpy(request.data.sid, sid_str);
130 result = winbindd_request(WINBINDD_SID_TO_UID, &request, &response);
132 /* Copy out result */
134 if (result == NSS_STATUS_SUCCESS) {
135 *puid = response.data.uid;
138 return (result == NSS_STATUS_SUCCESS);
141 /* Call winbindd to convert uid to sid */
143 BOOL winbind_uid_to_sid(DOM_SID *sid, uid_t uid)
145 struct winbindd_request request;
146 struct winbindd_response response;
152 /* Initialise request */
154 ZERO_STRUCT(request);
155 ZERO_STRUCT(response);
157 request.data.uid = uid;
161 result = winbindd_request(WINBINDD_UID_TO_SID, &request, &response);
163 /* Copy out result */
165 if (result == NSS_STATUS_SUCCESS) {
166 string_to_sid(sid, response.data.sid.sid);
168 sid_copy(sid, &global_sid_NULL);
171 return (result == NSS_STATUS_SUCCESS);
174 /* Call winbindd to convert SID to gid */
176 BOOL winbind_sid_to_gid(gid_t *pgid, DOM_SID *sid)
178 struct winbindd_request request;
179 struct winbindd_response response;
186 /* Initialise request */
188 ZERO_STRUCT(request);
189 ZERO_STRUCT(response);
191 sid_to_string(sid_str, sid);
192 fstrcpy(request.data.sid, sid_str);
196 result = winbindd_request(WINBINDD_SID_TO_UID, &request, &response);
198 /* Copy out result */
200 if (result == NSS_STATUS_SUCCESS) {
201 *pgid = response.data.gid;
204 return (result == NSS_STATUS_SUCCESS);
207 /* Call winbindd to convert gid to sid */
209 BOOL winbind_gid_to_sid(DOM_SID *sid, gid_t gid)
211 struct winbindd_request request;
212 struct winbindd_response response;
218 /* Initialise request */
220 ZERO_STRUCT(request);
221 ZERO_STRUCT(response);
223 request.data.gid = gid;
227 result = winbindd_request(WINBINDD_GID_TO_SID, &request, &response);
229 /* Copy out result */
231 if (result == NSS_STATUS_SUCCESS) {
232 string_to_sid(sid, response.data.sid.sid);
234 sid_copy(sid, &global_sid_NULL);
237 return (result == NSS_STATUS_SUCCESS);
240 /* Fetch the list of groups a user is a member of from winbindd. This is
241 used by winbind_initgroups and winbind_getgroups. */
243 static int wb_getgroups(char *user, gid_t **groups)
245 struct winbindd_request request;
246 struct winbindd_response response;
251 fstrcpy(request.data.username, user);
253 ZERO_STRUCT(response);
255 result = winbindd_request(WINBINDD_GETGROUPS, &request, &response);
257 if (result == NSS_STATUS_SUCCESS) {
259 /* Return group list. Don't forget to free the group list
262 *groups = (gid_t *)response.extra_data;
263 return response.data.num_entries;
269 /* Call winbindd to initialise group membership. This is necessary for
270 some systems (i.e RH5.2) that do not have an initgroups function as part
271 of the nss extension. In RH5.2 this is implemented using getgrent()
272 which can be amazingly inefficient as well as having problems with
275 int winbind_initgroups(char *user, gid_t gid)
277 gid_t *groups = NULL;
281 /* Call normal initgroups if we are a local user */
283 sep = lp_winbind_separator();
285 if (!strchr(user, *sep)) {
286 return initgroups(user, gid);
289 result = wb_getgroups(user, &groups);
291 DEBUG(10,("winbind_getgroups: %s: result = %s\n", user,
292 result == -1 ? "FAIL" : "SUCCESS"));
295 int ngroups = result, i;
296 BOOL is_member = False;
298 /* Check to see if the passed gid is already in the list */
300 for (i = 0; i < ngroups; i++) {
301 if (groups[i] == gid) {
306 /* Add group to list if necessary */
309 groups = Realloc(groups, sizeof(gid_t) * ngroups + 1);
317 groups[ngroups] = gid;
323 if (sys_setgroups(ngroups, groups) == -1) {
331 /* The call failed. Set errno to something so we don't get
332 a bogus value from the last failed system call. */
337 /* Free response data if necessary */
345 /* Return a list of groups the user is a member of. This function is
346 useful for large systems where inverting the group database would be too
347 time consuming. If size is zero, list is not modified and the total
348 number of groups for the user is returned. */
350 int winbind_getgroups(char *user, int size, gid_t *list)
352 gid_t *groups = NULL;
355 /* Fetch list of groups */
357 result = wb_getgroups(user, &groups);
359 if (size == 0) goto done;
363 errno = EINVAL; /* This is what getgroups() does */
367 /* Copy list of groups across */
369 for (i = 0; i < result; i++) {
378 /**********************************************************************************
379 Utility function. Convert a uid_t to a name if possible.
380 **********************************************************************************/
382 BOOL winbind_uidtoname(fstring name, uid_t uid)
387 enum SID_NAME_USE name_type;
389 if (!winbind_uid_to_sid(&sid, uid))
391 if (!winbind_lookup_sid(&sid, dom_name, user_name, &name_type))
394 if (name_type != SID_NAME_USER)
397 slprintf(name, sizeof(fstring)-1, "%s%s%s", dom_name, lp_winbind_separator(), user_name );
401 /**********************************************************************************
402 Utility function. Convert a gid_t to a name if possible.
403 **********************************************************************************/
405 BOOL winbind_gidtoname(fstring name, gid_t gid)
410 enum SID_NAME_USE name_type;
412 if (!winbind_gid_to_sid(&sid, gid))
414 if (!winbind_lookup_sid(&sid, dom_name, group_name, &name_type))
417 if (name_type != SID_NAME_USER)
420 slprintf(name, sizeof(fstring)-1, "%s%s%s", dom_name, lp_winbind_separator(), group_name );
424 /**********************************************************************************
425 Utility function. Convert a name to a uid_t if possible.
426 **********************************************************************************/
428 BOOL winbind_nametouid(uid_t *puid, char *name)
431 enum SID_NAME_USE name_type;
433 if (!winbind_lookup_name(name, &sid, &name_type)) {
437 if (name_type != SID_NAME_USER)
440 return winbind_sid_to_uid(puid, &sid);
443 /**********************************************************************************
444 Utility function. Convert a name to a gid_t if possible.
445 **********************************************************************************/
447 BOOL winbind_nametogid(gid_t *pgid, char *gname)
450 enum SID_NAME_USE name_type;
452 if (!winbind_lookup_name(gname, &g_sid, &name_type)) {
456 if (name_type != SID_NAME_DOM_GRP)
459 return winbind_sid_to_gid(pgid, &g_sid);