Removed version number from file header.
[kai/samba-autobuild/.git] / source3 / nsswitch / wb_client.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    winbind client code
5
6    Copyright (C) Tim Potter 2000
7    Copyright (C) Andrew Tridgell 2000
8    
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.
13    
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.
18    
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.   
23 */
24
25 #include "includes.h"
26 #include "nsswitch/nss.h"
27
28 NSS_STATUS winbindd_request(int req_type,
29                                  struct winbindd_request *request,
30                                  struct winbindd_response *response);
31
32 /* Call winbindd to convert a name to a sid */
33
34 BOOL winbind_lookup_name(const char *dom_name, const char *name, DOM_SID *sid, 
35                          enum SID_NAME_USE *name_type)
36 {
37         struct winbindd_request request;
38         struct winbindd_response response;
39         NSS_STATUS result;
40         
41         if (!sid || !name_type)
42                 return False;
43
44         /* Send off request */
45
46         ZERO_STRUCT(request);
47         ZERO_STRUCT(response);
48
49         fstrcpy(request.data.name.dom_name, dom_name);
50         fstrcpy(request.data.name.name, name);
51
52         if ((result = winbindd_request(WINBINDD_LOOKUPNAME, &request, 
53                                        &response)) == NSS_STATUS_SUCCESS) {
54                 string_to_sid(sid, response.data.sid.sid);
55                 *name_type = (enum SID_NAME_USE)response.data.sid.type;
56         }
57
58         return result == NSS_STATUS_SUCCESS;
59 }
60
61 /* Call winbindd to convert sid to name */
62
63 BOOL winbind_lookup_sid(DOM_SID *sid, 
64                         fstring dom_name, fstring name, 
65                         enum SID_NAME_USE *name_type)
66 {
67         struct winbindd_request request;
68         struct winbindd_response response;
69         NSS_STATUS result;
70         fstring sid_str;
71         
72         /* Initialise request */
73
74         ZERO_STRUCT(request);
75         ZERO_STRUCT(response);
76
77         sid_to_string(sid_str, sid);
78         fstrcpy(request.data.sid, sid_str);
79         
80         /* Make request */
81
82         result = winbindd_request(WINBINDD_LOOKUPSID, &request, &response);
83
84         /* Copy out result */
85
86         if (result == NSS_STATUS_SUCCESS) {
87                 fstrcpy(dom_name, response.data.name.dom_name);
88                 fstrcpy(name, response.data.name.name);
89                 *name_type = (enum SID_NAME_USE)response.data.name.type;
90
91                 DEBUG(10, ("winbind_lookup_sid: SUCCESS: SID %s -> %s %s\n", 
92                            sid_str, dom_name, name));
93         }
94
95         return (result == NSS_STATUS_SUCCESS);
96 }
97
98 /* Call winbindd to convert SID to uid */
99
100 BOOL winbind_sid_to_uid(uid_t *puid, DOM_SID *sid)
101 {
102         struct winbindd_request request;
103         struct winbindd_response response;
104         int result;
105         fstring sid_str;
106
107         if (!puid)
108                 return False;
109
110         /* Initialise request */
111
112         ZERO_STRUCT(request);
113         ZERO_STRUCT(response);
114
115         sid_to_string(sid_str, sid);
116         fstrcpy(request.data.sid, sid_str);
117         
118         /* Make request */
119
120         result = winbindd_request(WINBINDD_SID_TO_UID, &request, &response);
121
122         /* Copy out result */
123
124         if (result == NSS_STATUS_SUCCESS) {
125                 *puid = response.data.uid;
126         }
127
128         return (result == NSS_STATUS_SUCCESS);
129 }
130
131 /* Call winbindd to convert uid to sid */
132
133 BOOL winbind_uid_to_sid(DOM_SID *sid, uid_t uid)
134 {
135         struct winbindd_request request;
136         struct winbindd_response response;
137         int result;
138
139         if (!sid)
140                 return False;
141
142         /* Initialise request */
143
144         ZERO_STRUCT(request);
145         ZERO_STRUCT(response);
146
147         request.data.uid = uid;
148
149         /* Make request */
150
151         result = winbindd_request(WINBINDD_UID_TO_SID, &request, &response);
152
153         /* Copy out result */
154
155         if (result == NSS_STATUS_SUCCESS) {
156                 string_to_sid(sid, response.data.sid.sid);
157         } else {
158                 sid_copy(sid, &global_sid_NULL);
159         }
160
161         return (result == NSS_STATUS_SUCCESS);
162 }
163
164 /* Call winbindd to convert SID to gid */
165
166 BOOL winbind_sid_to_gid(gid_t *pgid, DOM_SID *sid)
167 {
168         struct winbindd_request request;
169         struct winbindd_response response;
170         int result;
171         fstring sid_str;
172
173         if (!pgid)
174                 return False;
175
176         /* Initialise request */
177
178         ZERO_STRUCT(request);
179         ZERO_STRUCT(response);
180
181         sid_to_string(sid_str, sid);
182         fstrcpy(request.data.sid, sid_str);
183         
184         /* Make request */
185
186         result = winbindd_request(WINBINDD_SID_TO_GID, &request, &response);
187
188         /* Copy out result */
189
190         if (result == NSS_STATUS_SUCCESS) {
191                 *pgid = response.data.gid;
192         }
193
194         return (result == NSS_STATUS_SUCCESS);
195 }
196
197 /* Call winbindd to convert gid to sid */
198
199 BOOL winbind_gid_to_sid(DOM_SID *sid, gid_t gid)
200 {
201         struct winbindd_request request;
202         struct winbindd_response response;
203         int result;
204
205         if (!sid)
206                 return False;
207
208         /* Initialise request */
209
210         ZERO_STRUCT(request);
211         ZERO_STRUCT(response);
212
213         request.data.gid = gid;
214
215         /* Make request */
216
217         result = winbindd_request(WINBINDD_GID_TO_SID, &request, &response);
218
219         /* Copy out result */
220
221         if (result == NSS_STATUS_SUCCESS) {
222                 string_to_sid(sid, response.data.sid.sid);
223         } else {
224                 sid_copy(sid, &global_sid_NULL);
225         }
226
227         return (result == NSS_STATUS_SUCCESS);
228 }
229
230 /* Fetch the list of groups a user is a member of from winbindd.  This is
231    used by winbind_getgroups. */
232
233 static int wb_getgroups(const char *user, gid_t **groups)
234 {
235         struct winbindd_request request;
236         struct winbindd_response response;
237         int result;
238
239         /* Call winbindd */
240
241         fstrcpy(request.data.username, user);
242
243         ZERO_STRUCT(response);
244
245         result = winbindd_request(WINBINDD_GETGROUPS, &request, &response);
246
247         if (result == NSS_STATUS_SUCCESS) {
248                 
249                 /* Return group list.  Don't forget to free the group list
250                    when finished. */
251
252                 *groups = (gid_t *)response.extra_data;
253                 return response.data.num_entries;
254         }
255
256         return -1;
257 }
258
259 /* Return a list of groups the user is a member of.  This function is
260    useful for large systems where inverting the group database would be too
261    time consuming.  If size is zero, list is not modified and the total
262    number of groups for the user is returned. */
263
264 int winbind_getgroups(const char *user, int size, gid_t *list)
265 {
266         gid_t *groups = NULL;
267         int result, i;
268
269         /*
270          * Don't do the lookup if the name has no separator _and_ we are not in
271          * 'winbind use default domain' mode.
272          */
273
274         if (!(strchr(user, *lp_winbind_separator()) || lp_winbind_use_default_domain()))
275                 return -1;
276
277         /* Fetch list of groups */
278
279         result = wb_getgroups(user, &groups);
280
281         if (size == 0)
282                 goto done;
283
284         if (result > size) {
285                 result = -1;
286                 errno = EINVAL; /* This is what getgroups() does */
287                 goto done;
288         }
289
290         /* Copy list of groups across */
291
292         for (i = 0; i < result; i++) {
293                 list[i] = groups[i];
294         }
295
296  done:
297         SAFE_FREE(groups);
298         return result;
299 }