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 /* Fetch the list of groups a user is a member of from winbindd. This is
261 used by winbind_getgroups. */
263 static int wb_getgroups(const char *user, gid_t **groups)
265 struct winbindd_request request;
266 struct winbindd_response response;
271 ZERO_STRUCT(request);
272 fstrcpy(request.data.username, user);
274 ZERO_STRUCT(response);
276 result = winbindd_request(WINBINDD_GETGROUPS, &request, &response);
278 if (result == NSS_STATUS_SUCCESS) {
280 /* Return group list. Don't forget to free the group list
283 *groups = (gid_t *)response.extra_data;
284 return response.data.num_entries;
290 /* Call winbindd to initialise group membership. This is necessary for
291 some systems (i.e RH5.2) that do not have an initgroups function as part
292 of the nss extension. In RH5.2 this is implemented using getgrent()
293 which can be amazingly inefficient as well as having problems with
296 int winbind_initgroups(char *user, gid_t gid)
298 gid_t *tgr, *groups = NULL;
301 /* Call normal initgroups if we are a local user */
303 if (!strchr(user, *lp_winbind_separator())) {
304 return initgroups(user, gid);
307 result = wb_getgroups(user, &groups);
309 DEBUG(10,("winbind_getgroups: %s: result = %s\n", user,
310 result == -1 ? "FAIL" : "SUCCESS"));
313 int ngroups = result, i;
314 BOOL is_member = False;
316 /* Check to see if the passed gid is already in the list */
318 for (i = 0; i < ngroups; i++) {
319 if (groups[i] == gid) {
324 /* Add group to list if necessary */
327 tgr = SMB_REALLOC_ARRAY(groups, gid_t, ngroups + 1);
336 groups[ngroups] = gid;
342 if (sys_setgroups(ngroups, groups) == -1) {
350 /* The call failed. Set errno to something so we don't get
351 a bogus value from the last failed system call. */
356 /* Free response data if necessary */
364 /* Return a list of groups the user is a member of. This function is
365 useful for large systems where inverting the group database would be too
366 time consuming. If size is zero, list is not modified and the total
367 number of groups for the user is returned. */
369 int winbind_getgroups(const char *user, gid_t **list)
372 * Don't do the lookup if the name has no separator _and_ we are not in
373 * 'winbind use default domain' mode.
376 if (!(strchr(user, *lp_winbind_separator()) || lp_winbind_use_default_domain()))
379 /* Fetch list of groups */
381 return wb_getgroups(user, list);
384 /**********************************************************************
385 simple wrapper function to see if winbindd is alive
386 **********************************************************************/
388 BOOL winbind_ping( void )
392 result = winbindd_request(WINBINDD_PING, NULL, NULL);
394 return result == NSS_STATUS_SUCCESS;
397 /**********************************************************************
400 result == NSS_STATUS_UNAVAIL: winbind not around
401 result == NSS_STATUS_NOTFOUND: winbind around, but domain missing
403 Due to a bad API NSS_STATUS_NOTFOUND is returned both when winbind_off and
404 when winbind return WINBINDD_ERROR. So the semantics of this routine depends
405 on winbind_on. Grepping for winbind_off I just found 3 places where winbind
406 is turned off, and this does not conflict (as far as I have seen) with the
407 callers of is_trusted_domains.
409 I *hate* global variables....
413 **********************************************************************/
415 NSS_STATUS wb_is_trusted_domain(const char *domain)
417 struct winbindd_request request;
418 struct winbindd_response response;
422 ZERO_STRUCT(request);
423 ZERO_STRUCT(response);
425 fstrcpy(request.domain_name, domain);
427 return winbindd_request(WINBINDD_DOMAIN_INFO, &request, &response);