r7838: lie about the printer status when doing the queryvalue() registry call. Note...
[Samba/gbeck.git] / source / nsswitch / wb_client.c
blob32ac4319a0382bd65f0b10ed1f886d0c45de0f24
1 /*
2 Unix SMB/CIFS implementation.
4 winbind client code
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.
25 #include "includes.h"
26 #include "nsswitch/winbind_nss.h"
28 #undef DBGC_CLASS
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;
42 NSS_STATUS result;
44 if (!sid || !name_type)
45 return False;
47 /* Send off request */
49 ZERO_STRUCT(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))
58 return False;
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;
73 NSS_STATUS result;
74 fstring sid_str;
76 /* Initialise request */
78 ZERO_STRUCT(request);
79 ZERO_STRUCT(response);
81 sid_to_string(sid_str, sid);
82 fstrcpy(request.data.sid, sid_str);
84 /* Make request */
86 result = winbindd_request(WINBINDD_LOOKUPSID, &request, &response);
88 /* Copy out result */
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;
108 int result;
109 fstring sid_str;
111 if (!puid)
112 return False;
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);
122 /* Make request */
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;
141 int result;
143 if (!sid)
144 return False;
146 /* Initialise request */
148 ZERO_STRUCT(request);
149 ZERO_STRUCT(response);
151 request.data.uid = uid;
153 /* Make request */
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))
161 return False;
162 } else {
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;
175 int result;
176 fstring sid_str;
178 if (!pgid)
179 return False;
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);
189 /* Make request */
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;
208 int result;
210 if (!sid)
211 return False;
213 /* Initialise request */
215 ZERO_STRUCT(request);
216 ZERO_STRUCT(response);
218 request.data.gid = gid;
220 /* Make request */
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))
228 return False;
229 } else {
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;
240 int result;
242 /* Initialise request */
244 ZERO_STRUCT(request);
245 ZERO_STRUCT(response);
247 /* Make request */
249 result = winbindd_request(WINBINDD_ALLOCATE_RID, &request, &response);
251 if (result != NSS_STATUS_SUCCESS)
252 return False;
254 /* Copy out result */
255 *rid = response.data.rid;
257 return True;
260 BOOL winbind_allocate_rid_and_gid(uint32 *rid, gid_t *gid)
262 struct winbindd_request request;
263 struct winbindd_response response;
264 int result;
266 /* Initialise request */
268 ZERO_STRUCT(request);
269 ZERO_STRUCT(response);
271 /* Make request */
273 result = winbindd_request(WINBINDD_ALLOCATE_RID_AND_GID, &request,
274 &response);
276 if (result != NSS_STATUS_SUCCESS)
277 return False;
279 /* Copy out result */
280 *rid = response.data.rid_and_gid.rid;
281 *gid = response.data.rid_and_gid.gid;
283 return True;
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;
293 int result;
295 /* Call winbindd */
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
307 when finished. */
309 *groups = (gid_t *)response.extra_data;
310 return response.data.num_entries;
313 return -1;
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
320 username case. */
322 int winbind_initgroups(char *user, gid_t gid)
324 gid_t *tgr, *groups = NULL;
325 int result;
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"));
338 if (result != -1) {
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) {
346 is_member = True;
350 /* Add group to list if necessary */
352 if (!is_member) {
353 tgr = SMB_REALLOC_ARRAY(groups, gid_t, ngroups + 1);
355 if (!tgr) {
356 errno = ENOMEM;
357 result = -1;
358 goto done;
360 else groups = tgr;
362 groups[ngroups] = gid;
363 ngroups++;
366 /* Set the groups */
368 if (sys_setgroups(ngroups, groups) == -1) {
369 errno = EPERM;
370 result = -1;
371 goto done;
374 } else {
376 /* The call failed. Set errno to something so we don't get
377 a bogus value from the last failed system call. */
379 errno = EIO;
382 /* Free response data if necessary */
384 done:
385 SAFE_FREE(groups);
387 return result;
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()))
403 return -1;
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 )
416 NSS_STATUS result;
418 result = winbindd_request(WINBINDD_PING, NULL, NULL);
420 return result == NSS_STATUS_SUCCESS;
423 /**********************************************************************
424 Is a domain trusted?
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....
437 Volker
439 **********************************************************************/
441 NSS_STATUS wb_is_trusted_domain(const char *domain)
443 struct winbindd_request request;
444 struct winbindd_response response;
446 /* Call winbindd */
448 ZERO_STRUCT(request);
449 ZERO_STRUCT(response);
451 fstrcpy(request.domain_name, domain);
453 return winbindd_request(WINBINDD_DOMAIN_INFO, &request, &response);