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 int winbindd_request(int req_type, struct winbindd_request *request,
29 struct winbindd_response *response);
31 /* Copy of parse_domain_user from winbindd_util.c. Parse a string of the
32 form DOMAIN/user into a domain and a user */
34 static void parse_domain_user(char *domuser, fstring domain, fstring user)
37 char *sep = lp_winbind_separator();
39 p = strchr(domuser,*sep);
40 if (!p) p = strchr(domuser,'\\');
43 fstrcpy(user, domuser);
48 fstrcpy(domain, domuser);
49 domain[PTR_DIFF(p, domuser)] = 0;
53 /* Call winbindd to convert a name to a sid */
55 BOOL winbind_lookup_name(const char *name, DOM_SID *sid, enum SID_NAME_USE *name_type)
57 struct winbindd_request request;
58 struct winbindd_response response;
61 if (!sid || !name_type)
64 /* Send off request */
67 ZERO_STRUCT(response);
69 fstrcpy(request.data.name, name);
71 if ((result = winbindd_request(WINBINDD_LOOKUPNAME, &request,
72 &response)) == NSS_STATUS_SUCCESS) {
73 string_to_sid(sid, response.data.sid.sid);
74 *name_type = (enum SID_NAME_USE)response.data.sid.type;
77 return result == NSS_STATUS_SUCCESS;
80 /* Call winbindd to convert sid to name */
82 BOOL winbind_lookup_sid(DOM_SID *sid, fstring dom_name, fstring name, enum SID_NAME_USE *name_type)
84 struct winbindd_request request;
85 struct winbindd_response response;
89 /* Initialise request */
92 ZERO_STRUCT(response);
94 sid_to_string(sid_str, sid);
95 fstrcpy(request.data.sid, sid_str);
99 result = winbindd_request(WINBINDD_LOOKUPSID, &request, &response);
101 /* Copy out result */
103 if (result == NSS_STATUS_SUCCESS) {
104 parse_domain_user(response.data.name.name, dom_name, name);
105 *name_type = (enum SID_NAME_USE)response.data.name.type;
106 DEBUG(10,("winbind_lookup_sid: SUCCESS: SID %s -> %s %s\n", sid_str, dom_name, name ));
109 return (result == NSS_STATUS_SUCCESS);
112 /* Call winbindd to convert SID to uid */
114 BOOL winbind_sid_to_uid(uid_t *puid, DOM_SID *sid)
116 struct winbindd_request request;
117 struct winbindd_response response;
124 /* Initialise request */
126 ZERO_STRUCT(request);
127 ZERO_STRUCT(response);
129 sid_to_string(sid_str, sid);
130 fstrcpy(request.data.sid, sid_str);
134 result = winbindd_request(WINBINDD_SID_TO_UID, &request, &response);
136 /* Copy out result */
138 if (result == NSS_STATUS_SUCCESS) {
139 *puid = response.data.uid;
142 return (result == NSS_STATUS_SUCCESS);
145 /* Call winbindd to convert uid to sid */
147 BOOL winbind_uid_to_sid(DOM_SID *sid, uid_t uid)
149 struct winbindd_request request;
150 struct winbindd_response response;
156 /* Initialise request */
158 ZERO_STRUCT(request);
159 ZERO_STRUCT(response);
161 request.data.uid = uid;
165 result = winbindd_request(WINBINDD_UID_TO_SID, &request, &response);
167 /* Copy out result */
169 if (result == NSS_STATUS_SUCCESS) {
170 string_to_sid(sid, response.data.sid.sid);
172 sid_copy(sid, &global_sid_NULL);
175 return (result == NSS_STATUS_SUCCESS);
178 /* Call winbindd to convert SID to gid */
180 BOOL winbind_sid_to_gid(gid_t *pgid, DOM_SID *sid)
182 struct winbindd_request request;
183 struct winbindd_response response;
190 /* Initialise request */
192 ZERO_STRUCT(request);
193 ZERO_STRUCT(response);
195 sid_to_string(sid_str, sid);
196 fstrcpy(request.data.sid, sid_str);
200 result = winbindd_request(WINBINDD_SID_TO_GID, &request, &response);
202 /* Copy out result */
204 if (result == NSS_STATUS_SUCCESS) {
205 *pgid = response.data.gid;
208 return (result == NSS_STATUS_SUCCESS);
211 /* Call winbindd to convert gid to sid */
213 BOOL winbind_gid_to_sid(DOM_SID *sid, gid_t gid)
215 struct winbindd_request request;
216 struct winbindd_response response;
222 /* Initialise request */
224 ZERO_STRUCT(request);
225 ZERO_STRUCT(response);
227 request.data.gid = gid;
231 result = winbindd_request(WINBINDD_GID_TO_SID, &request, &response);
233 /* Copy out result */
235 if (result == NSS_STATUS_SUCCESS) {
236 string_to_sid(sid, response.data.sid.sid);
238 sid_copy(sid, &global_sid_NULL);
241 return (result == NSS_STATUS_SUCCESS);
244 /* Fetch the list of groups a user is a member of from winbindd. This is
245 used by winbind_initgroups and winbind_getgroups. */
247 static int wb_getgroups(char *user, gid_t **groups)
249 struct winbindd_request request;
250 struct winbindd_response response;
255 fstrcpy(request.data.username, user);
257 ZERO_STRUCT(response);
259 result = winbindd_request(WINBINDD_GETGROUPS, &request, &response);
261 if (result == NSS_STATUS_SUCCESS) {
263 /* Return group list. Don't forget to free the group list
266 *groups = (gid_t *)response.extra_data;
267 return response.data.num_entries;
273 /* Call winbindd to initialise group membership. This is necessary for
274 some systems (i.e RH5.2) that do not have an initgroups function as part
275 of the nss extension. In RH5.2 this is implemented using getgrent()
276 which can be amazingly inefficient as well as having problems with
279 int winbind_initgroups(char *user, gid_t gid)
281 gid_t *groups = NULL;
285 /* Call normal initgroups if we are a local user */
287 sep = lp_winbind_separator();
289 if (!strchr(user, *sep)) {
290 return initgroups(user, gid);
293 result = wb_getgroups(user, &groups);
295 DEBUG(10,("winbind_getgroups: %s: result = %s\n", user,
296 result == -1 ? "FAIL" : "SUCCESS"));
299 int ngroups = result, i;
300 BOOL is_member = False;
302 /* Check to see if the passed gid is already in the list */
304 for (i = 0; i < ngroups; i++) {
305 if (groups[i] == gid) {
310 /* Add group to list if necessary */
313 groups = Realloc(groups, sizeof(gid_t) * ngroups + 1);
321 groups[ngroups] = gid;
327 if (sys_setgroups(ngroups, groups) == -1) {
335 /* The call failed. Set errno to something so we don't get
336 a bogus value from the last failed system call. */
341 /* Free response data if necessary */
349 /* Return a list of groups the user is a member of. This function is
350 useful for large systems where inverting the group database would be too
351 time consuming. If size is zero, list is not modified and the total
352 number of groups for the user is returned. */
354 int winbind_getgroups(char *user, int size, gid_t *list)
356 gid_t *groups = NULL;
359 /* Fetch list of groups */
361 result = wb_getgroups(user, &groups);
363 if (size == 0) goto done;
367 errno = EINVAL; /* This is what getgroups() does */
371 /* Copy list of groups across */
373 for (i = 0; i < result; i++) {
382 /**********************************************************************************
383 Utility function. Convert a uid_t to a name if possible.
384 **********************************************************************************/
386 BOOL winbind_uidtoname(fstring name, uid_t uid)
391 enum SID_NAME_USE name_type;
393 if (!winbind_uid_to_sid(&sid, uid))
395 if (!winbind_lookup_sid(&sid, dom_name, user_name, &name_type))
398 if (name_type != SID_NAME_USER)
401 slprintf(name, sizeof(fstring)-1, "%s%s%s", dom_name, lp_winbind_separator(), user_name );
405 /**********************************************************************************
406 Utility function. Convert a gid_t to a name if possible.
407 **********************************************************************************/
409 BOOL winbind_gidtoname(fstring name, gid_t gid)
414 enum SID_NAME_USE name_type;
416 if (!winbind_gid_to_sid(&sid, gid))
418 if (!winbind_lookup_sid(&sid, dom_name, group_name, &name_type))
421 if (name_type != SID_NAME_USER)
424 slprintf(name, sizeof(fstring)-1, "%s%s%s", dom_name, lp_winbind_separator(), group_name );
428 /**********************************************************************************
429 Utility function. Convert a name to a uid_t if possible.
430 **********************************************************************************/
432 BOOL winbind_nametouid(uid_t *puid, char *name)
435 enum SID_NAME_USE name_type;
437 if (!winbind_lookup_name(name, &sid, &name_type)) {
441 if (name_type != SID_NAME_USER)
444 return winbind_sid_to_uid(puid, &sid);
447 /**********************************************************************************
448 Utility function. Convert a name to a gid_t if possible.
449 **********************************************************************************/
451 BOOL winbind_nametogid(gid_t *pgid, char *gname)
454 enum SID_NAME_USE name_type;
456 if (!winbind_lookup_name(gname, &g_sid, &name_type)) {
460 if (name_type != SID_NAME_DOM_GRP)
463 return winbind_sid_to_gid(pgid, &g_sid);