libwbclient: added support for WBC_ID_TYPE_BOTH
[ambi/samba-autobuild/.git] / nsswitch / libwbclient / wbc_idmap.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    Winbind client API
5
6    Copyright (C) Gerald (Jerry) Carter 2007
7
8    This library is free software; you can redistribute it and/or
9    modify it under the terms of the GNU Lesser General Public
10    License as published by the Free Software Foundation; either
11    version 3 of the License, or (at your option) any later version.
12
13    This library is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    Library General Public License for more details.
17
18    You should have received a copy of the GNU Lesser General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 /* Required Headers */
23
24 #include "replace.h"
25 #include "libwbclient.h"
26 #include "../winbind_client.h"
27
28 /* Convert a Windows SID to a Unix uid, allocating an uid if needed */
29 wbcErr wbcSidToUid(const struct wbcDomainSid *sid, uid_t *puid)
30 {
31         struct winbindd_request request;
32         struct winbindd_response response;
33         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
34
35         if (!sid || !puid) {
36                 wbc_status = WBC_ERR_INVALID_PARAM;
37                 BAIL_ON_WBC_ERROR(wbc_status);
38         }
39
40         /* Initialize request */
41
42         ZERO_STRUCT(request);
43         ZERO_STRUCT(response);
44
45         wbcSidToStringBuf(sid, request.data.sid, sizeof(request.data.sid));
46
47         /* Make request */
48
49         wbc_status = wbcRequestResponse(WINBINDD_SID_TO_UID,
50                                         &request,
51                                         &response);
52         BAIL_ON_WBC_ERROR(wbc_status);
53
54         *puid = response.data.uid;
55
56         wbc_status = WBC_ERR_SUCCESS;
57
58  done:
59         return wbc_status;
60 }
61
62 /* Convert a Windows SID to a Unix uid if there already is a mapping */
63 wbcErr wbcQuerySidToUid(const struct wbcDomainSid *sid,
64                         uid_t *puid)
65 {
66         return WBC_ERR_NOT_IMPLEMENTED;
67 }
68
69 /* Convert a Unix uid to a Windows SID, allocating a SID if needed */
70 wbcErr wbcUidToSid(uid_t uid, struct wbcDomainSid *sid)
71 {
72         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
73         struct winbindd_request request;
74         struct winbindd_response response;
75
76         if (!sid) {
77                 wbc_status = WBC_ERR_INVALID_PARAM;
78                 BAIL_ON_WBC_ERROR(wbc_status);
79         }
80
81         /* Initialize request */
82
83         ZERO_STRUCT(request);
84         ZERO_STRUCT(response);
85
86         request.data.uid = uid;
87
88         /* Make request */
89
90         wbc_status = wbcRequestResponse(WINBINDD_UID_TO_SID,
91                                         &request,
92                                         &response);
93         BAIL_ON_WBC_ERROR(wbc_status);
94
95         wbc_status = wbcStringToSid(response.data.sid.sid, sid);
96         BAIL_ON_WBC_ERROR(wbc_status);
97
98 done:
99         return wbc_status;
100 }
101
102 /* Convert a Unix uid to a Windows SID if there already is a mapping */
103 wbcErr wbcQueryUidToSid(uid_t uid,
104                         struct wbcDomainSid *sid)
105 {
106         return WBC_ERR_NOT_IMPLEMENTED;
107 }
108
109 /** @brief Convert a Windows SID to a Unix gid, allocating a gid if needed
110  *
111  * @param *sid        Pointer to the domain SID to be resolved
112  * @param *pgid       Pointer to the resolved gid_t value
113  *
114  * @return #wbcErr
115  *
116  **/
117
118 wbcErr wbcSidToGid(const struct wbcDomainSid *sid, gid_t *pgid)
119 {
120         struct winbindd_request request;
121         struct winbindd_response response;
122         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
123
124         if (!sid || !pgid) {
125                 wbc_status = WBC_ERR_INVALID_PARAM;
126                 BAIL_ON_WBC_ERROR(wbc_status);
127         }
128
129         /* Initialize request */
130
131         ZERO_STRUCT(request);
132         ZERO_STRUCT(response);
133
134         wbcSidToStringBuf(sid, request.data.sid, sizeof(request.data.sid));
135
136         /* Make request */
137
138         wbc_status = wbcRequestResponse(WINBINDD_SID_TO_GID,
139                                         &request,
140                                         &response);
141         BAIL_ON_WBC_ERROR(wbc_status);
142
143         *pgid = response.data.gid;
144
145         wbc_status = WBC_ERR_SUCCESS;
146
147  done:
148         return wbc_status;
149 }
150
151
152 /* Convert a Windows SID to a Unix gid if there already is a mapping */
153
154 wbcErr wbcQuerySidToGid(const struct wbcDomainSid *sid,
155                         gid_t *pgid)
156 {
157         return WBC_ERR_NOT_IMPLEMENTED;
158 }
159
160
161 /* Convert a Unix gid to a Windows SID, allocating a SID if needed */
162 wbcErr wbcGidToSid(gid_t gid, struct wbcDomainSid *sid)
163 {
164         struct winbindd_request request;
165         struct winbindd_response response;
166         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
167
168         if (!sid) {
169                 wbc_status = WBC_ERR_INVALID_PARAM;
170                 BAIL_ON_WBC_ERROR(wbc_status);
171         }
172
173         /* Initialize request */
174
175         ZERO_STRUCT(request);
176         ZERO_STRUCT(response);
177
178         request.data.gid = gid;
179
180         /* Make request */
181
182         wbc_status = wbcRequestResponse(WINBINDD_GID_TO_SID,
183                                         &request,
184                                         &response);
185         BAIL_ON_WBC_ERROR(wbc_status);
186
187         wbc_status = wbcStringToSid(response.data.sid.sid, sid);
188         BAIL_ON_WBC_ERROR(wbc_status);
189
190 done:
191         return wbc_status;
192 }
193
194 /* Convert a Unix gid to a Windows SID if there already is a mapping */
195 wbcErr wbcQueryGidToSid(gid_t gid,
196                         struct wbcDomainSid *sid)
197 {
198         return WBC_ERR_NOT_IMPLEMENTED;
199 }
200
201 /* Obtain a new uid from Winbind */
202 wbcErr wbcAllocateUid(uid_t *puid)
203 {
204         struct winbindd_request request;
205         struct winbindd_response response;
206         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
207
208         if (!puid)
209                 return WBC_ERR_INVALID_PARAM;
210
211         /* Initialise request */
212
213         ZERO_STRUCT(request);
214         ZERO_STRUCT(response);
215
216         /* Make request */
217
218         wbc_status = wbcRequestResponsePriv(WINBINDD_ALLOCATE_UID,
219                                             &request, &response);
220         BAIL_ON_WBC_ERROR(wbc_status);
221
222         /* Copy out result */
223         *puid = response.data.uid;
224
225         wbc_status = WBC_ERR_SUCCESS;
226
227  done:
228         return wbc_status;
229 }
230
231 /* Obtain a new gid from Winbind */
232 wbcErr wbcAllocateGid(gid_t *pgid)
233 {
234         struct winbindd_request request;
235         struct winbindd_response response;
236         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
237
238         if (!pgid)
239                 return WBC_ERR_INVALID_PARAM;
240
241         /* Initialise request */
242
243         ZERO_STRUCT(request);
244         ZERO_STRUCT(response);
245
246         /* Make request */
247
248         wbc_status = wbcRequestResponsePriv(WINBINDD_ALLOCATE_GID,
249                                             &request, &response);
250         BAIL_ON_WBC_ERROR(wbc_status);
251
252         /* Copy out result */
253         *pgid = response.data.gid;
254
255         wbc_status = WBC_ERR_SUCCESS;
256
257  done:
258         return wbc_status;
259 }
260
261 /* we can't include smb.h here... */
262 #define _ID_TYPE_UID 1
263 #define _ID_TYPE_GID 2
264
265 /* Set an user id mapping - not implemented any more */
266 wbcErr wbcSetUidMapping(uid_t uid, const struct wbcDomainSid *sid)
267 {
268         return WBC_ERR_NOT_IMPLEMENTED;
269 }
270
271 /* Set a group id mapping - not implemented any more */
272 wbcErr wbcSetGidMapping(gid_t gid, const struct wbcDomainSid *sid)
273 {
274         return WBC_ERR_NOT_IMPLEMENTED;
275 }
276
277 /* Remove a user id mapping - not implemented any more */
278 wbcErr wbcRemoveUidMapping(uid_t uid, const struct wbcDomainSid *sid)
279 {
280         return WBC_ERR_NOT_IMPLEMENTED;
281 }
282
283 /* Remove a group id mapping - not implemented any more */
284 wbcErr wbcRemoveGidMapping(gid_t gid, const struct wbcDomainSid *sid)
285 {
286         return WBC_ERR_NOT_IMPLEMENTED;
287 }
288
289 /* Set the highwater mark for allocated uids - not implemented any more */
290 wbcErr wbcSetUidHwm(uid_t uid_hwm)
291 {
292         return WBC_ERR_NOT_IMPLEMENTED;
293 }
294
295 /* Set the highwater mark for allocated gids - not implemented any more */
296 wbcErr wbcSetGidHwm(gid_t gid_hwm)
297 {
298         return WBC_ERR_NOT_IMPLEMENTED;
299 }
300
301 /* Convert a list of SIDs */
302 wbcErr wbcSidsToUnixIds(const struct wbcDomainSid *sids, uint32_t num_sids,
303                         struct wbcUnixId *ids)
304 {
305         struct winbindd_request request;
306         struct winbindd_response response;
307         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
308         int buflen, extra_len;
309         uint32_t i;
310         char *sidlist, *p, *extra_data;
311
312         buflen = num_sids * (WBC_SID_STRING_BUFLEN + 1) + 1;
313
314         sidlist = (char *)malloc(buflen);
315         if (sidlist == NULL) {
316                 return WBC_ERR_NO_MEMORY;
317         }
318
319         p = sidlist;
320
321         for (i=0; i<num_sids; i++) {
322                 int remaining;
323                 int len;
324
325                 remaining = buflen - (p - sidlist);
326
327                 len = wbcSidToStringBuf(&sids[i], p, remaining);
328                 if (len > remaining) {
329                         free(sidlist);
330                         return WBC_ERR_UNKNOWN_FAILURE;
331                 }
332
333                 p += len;
334                 *p++ = '\n';
335         }
336         *p++ = '\0';
337
338         ZERO_STRUCT(request);
339         ZERO_STRUCT(response);
340
341         request.extra_data.data = sidlist;
342         request.extra_len = p - sidlist;
343
344         wbc_status = wbcRequestResponse(WINBINDD_SIDS_TO_XIDS,
345                                         &request, &response);
346         free(sidlist);
347         if (!WBC_ERROR_IS_OK(wbc_status)) {
348                 return wbc_status;
349         }
350
351         extra_len = response.length - sizeof(struct winbindd_response);
352         extra_data = (char *)response.extra_data.data;
353
354         if ((extra_len <= 0) || (extra_data[extra_len-1] != '\0')) {
355                 goto wbc_err_invalid;
356         }
357
358         p = extra_data;
359
360         for (i=0; i<num_sids; i++) {
361                 struct wbcUnixId *id = &ids[i];
362                 char *q;
363
364                 switch (p[0]) {
365                 case 'U':
366                         id->type = WBC_ID_TYPE_UID;
367                         id->id.uid = strtoul(p+1, &q, 10);
368                         break;
369                 case 'G':
370                         id->type = WBC_ID_TYPE_GID;
371                         id->id.gid = strtoul(p+1, &q, 10);
372                         break;
373                 case 'B':
374                         id->type = WBC_ID_TYPE_BOTH;
375                         id->id.uid = strtoul(p+1, &q, 10);
376                         break;
377                 default:
378                         id->type = WBC_ID_TYPE_NOT_SPECIFIED;
379                         q = strchr(p, '\n');
380                         break;
381                 };
382                 if (q == NULL || q[0] != '\n') {
383                         goto wbc_err_invalid;
384                 }
385                 p = q+1;
386         }
387         wbc_status = WBC_ERR_SUCCESS;
388         goto done;
389
390 wbc_err_invalid:
391         wbc_status = WBC_ERR_INVALID_RESPONSE;
392 done:
393         winbindd_free_response(&response);
394         return wbc_status;
395 }