2 Unix SMB/CIFS implementation.
6 Copyright (C) Tim Potter 2000
7 Copyright (C) Andrew Tridgell 2000
9 This library is free software; you can redistribute it and/or
10 modify it under the terms of the GNU Library General Public
11 License as published by the Free Software Foundation; either
12 version 2 of the License, or (at your option) any later version.
14 This library is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Library General Public License for more details.
19 You should have received a copy of the GNU Library General Public
20 License along with this library; if not, write to the
21 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 Boston, MA 02111-1307, USA.
26 #include "nsswitch/winbind_nss.h"
29 #define DBGC_CLASS DBGC_WINBIND
31 NSS_STATUS
winbindd_request(int req_type
,
32 struct winbindd_request
*request
,
33 struct winbindd_response
*response
);
35 /* Call winbindd to convert a name to a sid */
37 BOOL
winbind_lookup_name(const char *dom_name
, const char *name
, DOM_SID
*sid
,
38 enum SID_NAME_USE
*name_type
)
40 struct winbindd_request request
;
41 struct winbindd_response response
;
44 if (!sid
|| !name_type
)
47 /* Send off request */
50 ZERO_STRUCT(response
);
52 fstrcpy(request
.data
.name
.dom_name
, dom_name
);
53 fstrcpy(request
.data
.name
.name
, name
);
55 if ((result
= winbindd_request(WINBINDD_LOOKUPNAME
, &request
,
56 &response
)) == NSS_STATUS_SUCCESS
) {
57 if (!string_to_sid(sid
, response
.data
.sid
.sid
))
59 *name_type
= (enum SID_NAME_USE
)response
.data
.sid
.type
;
62 return result
== NSS_STATUS_SUCCESS
;
65 /* Call winbindd to convert sid to name */
67 BOOL
winbind_lookup_sid(const DOM_SID
*sid
,
68 fstring dom_name
, fstring name
,
69 enum SID_NAME_USE
*name_type
)
71 struct winbindd_request request
;
72 struct winbindd_response response
;
76 /* Initialise request */
79 ZERO_STRUCT(response
);
81 sid_to_string(sid_str
, sid
);
82 fstrcpy(request
.data
.sid
, sid_str
);
86 result
= winbindd_request(WINBINDD_LOOKUPSID
, &request
, &response
);
90 if (result
== NSS_STATUS_SUCCESS
) {
91 fstrcpy(dom_name
, response
.data
.name
.dom_name
);
92 fstrcpy(name
, response
.data
.name
.name
);
93 *name_type
= (enum SID_NAME_USE
)response
.data
.name
.type
;
95 DEBUG(10, ("winbind_lookup_sid: SUCCESS: SID %s -> %s %s\n",
96 sid_str
, dom_name
, name
));
99 return (result
== NSS_STATUS_SUCCESS
);
102 /* Call winbindd to convert SID to uid */
104 BOOL
winbind_sid_to_uid(uid_t
*puid
, const DOM_SID
*sid
)
106 struct winbindd_request request
;
107 struct winbindd_response response
;
114 /* Initialise request */
116 ZERO_STRUCT(request
);
117 ZERO_STRUCT(response
);
119 sid_to_string(sid_str
, sid
);
120 fstrcpy(request
.data
.sid
, sid_str
);
124 result
= winbindd_request(WINBINDD_SID_TO_UID
, &request
, &response
);
126 /* Copy out result */
128 if (result
== NSS_STATUS_SUCCESS
) {
129 *puid
= response
.data
.uid
;
132 return (result
== NSS_STATUS_SUCCESS
);
135 /* Call winbindd to convert uid to sid */
137 BOOL
winbind_uid_to_sid(DOM_SID
*sid
, uid_t uid
)
139 struct winbindd_request request
;
140 struct winbindd_response response
;
146 /* Initialise request */
148 ZERO_STRUCT(request
);
149 ZERO_STRUCT(response
);
151 request
.data
.uid
= uid
;
155 result
= winbindd_request(WINBINDD_UID_TO_SID
, &request
, &response
);
157 /* Copy out result */
159 if (result
== NSS_STATUS_SUCCESS
) {
160 if (!string_to_sid(sid
, response
.data
.sid
.sid
))
163 sid_copy(sid
, &global_sid_NULL
);
166 return (result
== NSS_STATUS_SUCCESS
);
169 /* Call winbindd to convert SID to gid */
171 BOOL
winbind_sid_to_gid(gid_t
*pgid
, const DOM_SID
*sid
)
173 struct winbindd_request request
;
174 struct winbindd_response response
;
181 /* Initialise request */
183 ZERO_STRUCT(request
);
184 ZERO_STRUCT(response
);
186 sid_to_string(sid_str
, sid
);
187 fstrcpy(request
.data
.sid
, sid_str
);
191 result
= winbindd_request(WINBINDD_SID_TO_GID
, &request
, &response
);
193 /* Copy out result */
195 if (result
== NSS_STATUS_SUCCESS
) {
196 *pgid
= response
.data
.gid
;
199 return (result
== NSS_STATUS_SUCCESS
);
202 /* Call winbindd to convert gid to sid */
204 BOOL
winbind_gid_to_sid(DOM_SID
*sid
, gid_t gid
)
206 struct winbindd_request request
;
207 struct winbindd_response response
;
213 /* Initialise request */
215 ZERO_STRUCT(request
);
216 ZERO_STRUCT(response
);
218 request
.data
.gid
= gid
;
222 result
= winbindd_request(WINBINDD_GID_TO_SID
, &request
, &response
);
224 /* Copy out result */
226 if (result
== NSS_STATUS_SUCCESS
) {
227 if (!string_to_sid(sid
, response
.data
.sid
.sid
))
230 sid_copy(sid
, &global_sid_NULL
);
233 return (result
== NSS_STATUS_SUCCESS
);
236 BOOL
winbind_allocate_rid(uint32
*rid
)
238 struct winbindd_request request
;
239 struct winbindd_response response
;
242 /* Initialise request */
244 ZERO_STRUCT(request
);
245 ZERO_STRUCT(response
);
249 result
= winbindd_request(WINBINDD_ALLOCATE_RID
, &request
, &response
);
251 if (result
!= NSS_STATUS_SUCCESS
)
254 /* Copy out result */
255 *rid
= response
.data
.rid
;
260 BOOL
winbind_allocate_rid_and_gid(uint32
*rid
, gid_t
*gid
)
262 struct winbindd_request request
;
263 struct winbindd_response response
;
266 /* Initialise request */
268 ZERO_STRUCT(request
);
269 ZERO_STRUCT(response
);
273 result
= winbindd_request(WINBINDD_ALLOCATE_RID_AND_GID
, &request
,
276 if (result
!= NSS_STATUS_SUCCESS
)
279 /* Copy out result */
280 *rid
= response
.data
.rid_and_gid
.rid
;
281 *gid
= response
.data
.rid_and_gid
.gid
;
286 /* Fetch the list of groups a user is a member of from winbindd. This is
287 used by winbind_getgroups. */
289 static int wb_getgroups(const char *user
, gid_t
**groups
)
291 struct winbindd_request request
;
292 struct winbindd_response response
;
297 ZERO_STRUCT(request
);
298 fstrcpy(request
.data
.username
, user
);
300 ZERO_STRUCT(response
);
302 result
= winbindd_request(WINBINDD_GETGROUPS
, &request
, &response
);
304 if (result
== NSS_STATUS_SUCCESS
) {
306 /* Return group list. Don't forget to free the group list
309 *groups
= (gid_t
*)response
.extra_data
;
310 return response
.data
.num_entries
;
316 /* Call winbindd to initialise group membership. This is necessary for
317 some systems (i.e RH5.2) that do not have an initgroups function as part
318 of the nss extension. In RH5.2 this is implemented using getgrent()
319 which can be amazingly inefficient as well as having problems with
322 int winbind_initgroups(char *user
, gid_t gid
)
324 gid_t
*tgr
, *groups
= NULL
;
327 /* Call normal initgroups if we are a local user */
329 if (!strchr(user
, *lp_winbind_separator())) {
330 return initgroups(user
, gid
);
333 result
= wb_getgroups(user
, &groups
);
335 DEBUG(10,("winbind_getgroups: %s: result = %s\n", user
,
336 result
== -1 ? "FAIL" : "SUCCESS"));
339 int ngroups
= result
, i
;
340 BOOL is_member
= False
;
342 /* Check to see if the passed gid is already in the list */
344 for (i
= 0; i
< ngroups
; i
++) {
345 if (groups
[i
] == gid
) {
350 /* Add group to list if necessary */
353 tgr
= SMB_REALLOC_ARRAY(groups
, gid_t
, ngroups
+ 1);
362 groups
[ngroups
] = gid
;
368 if (sys_setgroups(ngroups
, groups
) == -1) {
376 /* The call failed. Set errno to something so we don't get
377 a bogus value from the last failed system call. */
382 /* Free response data if necessary */
390 /* Return a list of groups the user is a member of. This function is
391 useful for large systems where inverting the group database would be too
392 time consuming. If size is zero, list is not modified and the total
393 number of groups for the user is returned. */
395 int winbind_getgroups(const char *user
, gid_t
**list
)
398 * Don't do the lookup if the name has no separator _and_ we are not in
399 * 'winbind use default domain' mode.
402 if (!(strchr(user
, *lp_winbind_separator()) || lp_winbind_use_default_domain()))
405 /* Fetch list of groups */
407 return wb_getgroups(user
, list
);
410 /**********************************************************************
411 simple wrapper function to see if winbindd is alive
412 **********************************************************************/
414 BOOL
winbind_ping( void )
418 result
= winbindd_request(WINBINDD_PING
, NULL
, NULL
);
420 return result
== NSS_STATUS_SUCCESS
;
423 /**********************************************************************
426 result == NSS_STATUS_UNAVAIL: winbind not around
427 result == NSS_STATUS_NOTFOUND: winbind around, but domain missing
429 Due to a bad API NSS_STATUS_NOTFOUND is returned both when winbind_off and
430 when winbind return WINBINDD_ERROR. So the semantics of this routine depends
431 on winbind_on. Grepping for winbind_off I just found 3 places where winbind
432 is turned off, and this does not conflict (as far as I have seen) with the
433 callers of is_trusted_domains.
435 I *hate* global variables....
439 **********************************************************************/
441 NSS_STATUS
wb_is_trusted_domain(const char *domain
)
443 struct winbindd_request request
;
444 struct winbindd_response response
;
448 ZERO_STRUCT(request
);
449 ZERO_STRUCT(response
);
451 fstrcpy(request
.domain_name
, domain
);
453 return winbindd_request(WINBINDD_DOMAIN_INFO
, &request
, &response
);