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.
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());
44 fstrcpy(domain
, domuser
);
45 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
,
53 enum SID_NAME_USE
*name_type
)
55 struct winbindd_request request
;
56 struct winbindd_response response
;
59 if (!sid
|| !name_type
)
63 * Don't do the lookup if the name has no separator.
66 if (!strchr(name
, *lp_winbind_separator()))
69 /* Send off 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
;
95 /* Initialise request */
98 ZERO_STRUCT(response
);
100 sid_to_string(sid_str
, sid
);
101 fstrcpy(request
.data
.sid
, sid_str
);
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
;
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
);
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
;
164 /* Initialise request */
166 ZERO_STRUCT(request
);
167 ZERO_STRUCT(response
);
169 request
.data
.uid
= uid
;
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
);
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
;
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
);
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
;
230 /* Initialise request */
232 ZERO_STRUCT(request
);
233 ZERO_STRUCT(response
);
235 request
.data
.gid
= gid
;
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
);
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
;
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
274 *groups
= (gid_t
*)response
.extra_data
;
275 return response
.data
.num_entries
;
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
287 int winbind_initgroups(char *user
, gid_t gid
)
289 gid_t
*tgr
, *groups
= NULL
;
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"));
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
) {
315 /* Add group to list if necessary */
318 tgr
= (gid_t
*)Realloc(groups
, sizeof(gid_t
) * ngroups
+ 1);
327 groups
[ngroups
] = gid
;
333 if (sys_setgroups(ngroups
, groups
) == -1) {
341 /* The call failed. Set errno to something so we don't get
342 a bogus value from the last failed system call. */
347 /* Free response data if necessary */
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
;
366 * Don't do the lookup if the name has no separator.
369 if (!strchr(user
, *lp_winbind_separator()))
372 /* Fetch list of groups */
374 result
= wb_getgroups(user
, &groups
);
381 errno
= EINVAL
; /* This is what getgroups() does */
385 /* Copy list of groups across */
387 for (i
= 0; i
< result
; i
++) {
396 /* Utility function. Convert a uid_t to a name if possible. */
398 BOOL
winbind_uidtoname(fstring name
, uid_t uid
)
403 enum SID_NAME_USE name_type
;
405 if (!winbind_uid_to_sid(&sid
, uid
))
407 if (!winbind_lookup_sid(&sid
, dom_name
, user_name
, &name_type
))
410 if (name_type
!= SID_NAME_USER
)
413 slprintf(name
, sizeof(fstring
)-1, "%s%s%s", dom_name
,
414 lp_winbind_separator(), user_name
);
419 /* Utility function. Convert a gid_t to a name if possible. */
421 BOOL
winbind_gidtoname(fstring name
, gid_t gid
)
426 enum SID_NAME_USE name_type
;
428 if (!winbind_gid_to_sid(&sid
, gid
))
430 if (!winbind_lookup_sid(&sid
, dom_name
, group_name
, &name_type
))
433 if (name_type
!= SID_NAME_DOM_GRP
)
436 slprintf(name
, sizeof(fstring
)-1, "%s%s%s", dom_name
,
437 lp_winbind_separator(), group_name
);
442 /* Utility function. Convert a name to a uid_t if possible. */
444 BOOL
winbind_nametouid(uid_t
*puid
, const char *name
)
447 enum SID_NAME_USE name_type
;
449 if (!winbind_lookup_name(name
, &sid
, &name_type
))
452 if (name_type
!= SID_NAME_USER
)
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
)
463 enum SID_NAME_USE name_type
;
465 if (!winbind_lookup_name(gname
, &g_sid
, &name_type
))
468 if (name_type
!= SID_NAME_DOM_GRP
)
471 return winbind_sid_to_gid(pgid
, &g_sid
);