vfs: Remove "sbuf" from readdir_fn()
[Samba.git] / nsswitch / libwbclient / wbc_idmap.c
blobc3accedc248dfbbc741ee90569b978dd30bdb3c5
1 /*
2 Unix SMB/CIFS implementation.
4 Winbind client API
6 Copyright (C) Gerald (Jerry) Carter 2007
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.
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.
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/>.
22 /* Required Headers */
24 #include "replace.h"
25 #include "libwbclient.h"
26 #include "../winbind_client.h"
27 #include "lib/util/smb_strtox.h"
29 /* Convert a Windows SID to a Unix uid, allocating an uid if needed */
30 _PUBLIC_
31 wbcErr wbcCtxSidToUid(struct wbcContext *ctx, const struct wbcDomainSid *sid,
32 uid_t *puid)
34 struct wbcUnixId xid;
35 wbcErr wbc_status;
37 if (!sid || !puid) {
38 wbc_status = WBC_ERR_INVALID_PARAM;
39 BAIL_ON_WBC_ERROR(wbc_status);
42 wbc_status = wbcCtxSidsToUnixIds(ctx, sid, 1, &xid);
43 if (!WBC_ERROR_IS_OK(wbc_status)) {
44 goto done;
47 if ((xid.type == WBC_ID_TYPE_UID) || (xid.type == WBC_ID_TYPE_BOTH)) {
48 *puid = xid.id.uid;
49 wbc_status = WBC_ERR_SUCCESS;
50 } else {
51 wbc_status = WBC_ERR_DOMAIN_NOT_FOUND;
54 done:
55 return wbc_status;
58 _PUBLIC_
59 wbcErr wbcSidToUid(const struct wbcDomainSid *sid, uid_t *puid)
61 return wbcCtxSidToUid(NULL, sid, puid);
64 /* Convert a Windows SID to a Unix uid if there already is a mapping */
65 _PUBLIC_
66 wbcErr wbcQuerySidToUid(const struct wbcDomainSid *sid,
67 uid_t *puid)
69 return WBC_ERR_NOT_IMPLEMENTED;
72 /* Convert a Unix uid to a Windows SID, allocating a SID if needed */
73 _PUBLIC_
74 wbcErr wbcCtxUidToSid(struct wbcContext *ctx, uid_t uid,
75 struct wbcDomainSid *psid)
77 struct wbcUnixId xid;
78 struct wbcDomainSid sid;
79 struct wbcDomainSid null_sid = { 0 };
80 wbcErr wbc_status;
82 if (!psid) {
83 wbc_status = WBC_ERR_INVALID_PARAM;
84 BAIL_ON_WBC_ERROR(wbc_status);
87 xid = (struct wbcUnixId) { .type = WBC_ID_TYPE_UID, .id.uid = uid };
89 wbc_status = wbcCtxUnixIdsToSids(ctx, &xid, 1, &sid);
90 if (!WBC_ERROR_IS_OK(wbc_status)) {
91 goto done;
94 if (memcmp(&sid, &null_sid, sizeof(sid)) != 0) {
95 *psid = sid;
96 } else {
97 wbc_status = WBC_ERR_DOMAIN_NOT_FOUND;
100 done:
101 return wbc_status;
104 _PUBLIC_
105 wbcErr wbcUidToSid(uid_t uid, struct wbcDomainSid *sid)
107 return wbcCtxUidToSid(NULL, uid, sid);
110 /* Convert a Unix uid to a Windows SID if there already is a mapping */
111 _PUBLIC_
112 wbcErr wbcQueryUidToSid(uid_t uid,
113 struct wbcDomainSid *sid)
115 return WBC_ERR_NOT_IMPLEMENTED;
118 /** @brief Convert a Windows SID to a Unix gid, allocating a gid if needed
120 * @param *sid Pointer to the domain SID to be resolved
121 * @param *pgid Pointer to the resolved gid_t value
123 * @return #wbcErr
127 _PUBLIC_
128 wbcErr wbcCtxSidToGid(struct wbcContext *ctx, const struct wbcDomainSid *sid,
129 gid_t *pgid)
131 struct wbcUnixId xid;
132 wbcErr wbc_status;
134 if (!sid || !pgid) {
135 wbc_status = WBC_ERR_INVALID_PARAM;
136 BAIL_ON_WBC_ERROR(wbc_status);
139 wbc_status = wbcCtxSidsToUnixIds(ctx, sid, 1, &xid);
140 if (!WBC_ERROR_IS_OK(wbc_status)) {
141 goto done;
144 if ((xid.type == WBC_ID_TYPE_GID) || (xid.type == WBC_ID_TYPE_BOTH)) {
145 *pgid = xid.id.gid;
146 wbc_status = WBC_ERR_SUCCESS;
147 } else {
148 wbc_status = WBC_ERR_DOMAIN_NOT_FOUND;
151 done:
152 return wbc_status;
155 _PUBLIC_
156 wbcErr wbcSidToGid(const struct wbcDomainSid *sid, gid_t *pgid)
158 return wbcCtxSidToGid(NULL, sid, pgid);
161 /* Convert a Windows SID to a Unix gid if there already is a mapping */
163 _PUBLIC_
164 wbcErr wbcQuerySidToGid(const struct wbcDomainSid *sid,
165 gid_t *pgid)
167 return WBC_ERR_NOT_IMPLEMENTED;
171 /* Convert a Unix gid to a Windows SID, allocating a SID if needed */
172 _PUBLIC_
173 wbcErr wbcCtxGidToSid(struct wbcContext *ctx, gid_t gid,
174 struct wbcDomainSid *psid)
176 struct wbcUnixId xid;
177 struct wbcDomainSid sid;
178 struct wbcDomainSid null_sid = { 0 };
179 wbcErr wbc_status;
181 if (!psid) {
182 wbc_status = WBC_ERR_INVALID_PARAM;
183 BAIL_ON_WBC_ERROR(wbc_status);
186 xid = (struct wbcUnixId) { .type = WBC_ID_TYPE_GID, .id.gid = gid };
188 wbc_status = wbcCtxUnixIdsToSids(ctx, &xid, 1, &sid);
189 if (!WBC_ERROR_IS_OK(wbc_status)) {
190 goto done;
193 if (memcmp(&sid, &null_sid, sizeof(sid)) != 0) {
194 *psid = sid;
195 } else {
196 wbc_status = WBC_ERR_DOMAIN_NOT_FOUND;
199 done:
200 return wbc_status;
203 _PUBLIC_
204 wbcErr wbcGidToSid(gid_t gid, struct wbcDomainSid *sid)
206 return wbcCtxGidToSid(NULL, gid, sid);
209 /* Convert a Unix gid to a Windows SID if there already is a mapping */
210 _PUBLIC_
211 wbcErr wbcQueryGidToSid(gid_t gid,
212 struct wbcDomainSid *sid)
214 return WBC_ERR_NOT_IMPLEMENTED;
217 /* Obtain a new uid from Winbind */
218 _PUBLIC_
219 wbcErr wbcCtxAllocateUid(struct wbcContext *ctx, uid_t *puid)
221 struct winbindd_request request;
222 struct winbindd_response response;
223 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
225 if (!puid)
226 return WBC_ERR_INVALID_PARAM;
228 /* Initialise request */
230 ZERO_STRUCT(request);
231 ZERO_STRUCT(response);
233 /* Make request */
235 wbc_status = wbcRequestResponsePriv(ctx, WINBINDD_ALLOCATE_UID,
236 &request, &response);
237 BAIL_ON_WBC_ERROR(wbc_status);
239 /* Copy out result */
240 *puid = response.data.uid;
242 wbc_status = WBC_ERR_SUCCESS;
244 done:
245 return wbc_status;
248 _PUBLIC_
249 wbcErr wbcAllocateUid(uid_t *puid)
251 return wbcCtxAllocateUid(NULL, puid);
254 /* Obtain a new gid from Winbind */
255 _PUBLIC_
256 wbcErr wbcCtxAllocateGid(struct wbcContext *ctx, gid_t *pgid)
258 struct winbindd_request request;
259 struct winbindd_response response;
260 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
262 if (!pgid)
263 return WBC_ERR_INVALID_PARAM;
265 /* Initialise request */
267 ZERO_STRUCT(request);
268 ZERO_STRUCT(response);
270 /* Make request */
272 wbc_status = wbcRequestResponsePriv(ctx, WINBINDD_ALLOCATE_GID,
273 &request, &response);
274 BAIL_ON_WBC_ERROR(wbc_status);
276 /* Copy out result */
277 *pgid = response.data.gid;
279 wbc_status = WBC_ERR_SUCCESS;
281 done:
282 return wbc_status;
285 _PUBLIC_
286 wbcErr wbcAllocateGid(gid_t *pgid)
288 return wbcCtxAllocateGid(NULL, pgid);
291 /* we can't include smb.h here... */
292 #define _ID_TYPE_UID 1
293 #define _ID_TYPE_GID 2
295 /* Set an user id mapping - not implemented any more */
296 _PUBLIC_
297 wbcErr wbcSetUidMapping(uid_t uid, const struct wbcDomainSid *sid)
299 return WBC_ERR_NOT_IMPLEMENTED;
302 /* Set a group id mapping - not implemented any more */
303 _PUBLIC_
304 wbcErr wbcSetGidMapping(gid_t gid, const struct wbcDomainSid *sid)
306 return WBC_ERR_NOT_IMPLEMENTED;
309 /* Remove a user id mapping - not implemented any more */
310 _PUBLIC_
311 wbcErr wbcRemoveUidMapping(uid_t uid, const struct wbcDomainSid *sid)
313 return WBC_ERR_NOT_IMPLEMENTED;
316 /* Remove a group id mapping - not implemented any more */
317 _PUBLIC_
318 wbcErr wbcRemoveGidMapping(gid_t gid, const struct wbcDomainSid *sid)
320 return WBC_ERR_NOT_IMPLEMENTED;
323 /* Set the highwater mark for allocated uids - not implemented any more */
324 _PUBLIC_
325 wbcErr wbcSetUidHwm(uid_t uid_hwm)
327 return WBC_ERR_NOT_IMPLEMENTED;
330 /* Set the highwater mark for allocated gids - not implemented any more */
331 _PUBLIC_
332 wbcErr wbcSetGidHwm(gid_t gid_hwm)
334 return WBC_ERR_NOT_IMPLEMENTED;
337 /* Convert a list of SIDs */
338 _PUBLIC_
339 wbcErr wbcCtxSidsToUnixIds(struct wbcContext *ctx,
340 const struct wbcDomainSid *sids,
341 uint32_t num_sids, struct wbcUnixId *ids)
343 struct winbindd_request request;
344 struct winbindd_response response;
345 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
346 int buflen, extra_len;
347 uint32_t i;
348 char *sidlist, *p, *extra_data;
350 buflen = num_sids * (WBC_SID_STRING_BUFLEN + 1) + 1;
352 sidlist = (char *)malloc(buflen);
353 if (sidlist == NULL) {
354 return WBC_ERR_NO_MEMORY;
357 p = sidlist;
359 for (i=0; i<num_sids; i++) {
360 int remaining;
361 int len;
363 remaining = buflen - (p - sidlist);
365 len = wbcSidToStringBuf(&sids[i], p, remaining);
366 if (len > remaining) {
367 free(sidlist);
368 return WBC_ERR_UNKNOWN_FAILURE;
371 p += len;
372 *p++ = '\n';
374 *p++ = '\0';
376 ZERO_STRUCT(request);
377 ZERO_STRUCT(response);
379 request.extra_data.data = sidlist;
380 request.extra_len = p - sidlist;
382 wbc_status = wbcRequestResponse(ctx, WINBINDD_SIDS_TO_XIDS,
383 &request, &response);
384 free(sidlist);
385 if (!WBC_ERROR_IS_OK(wbc_status)) {
386 return wbc_status;
389 extra_len = response.length - sizeof(struct winbindd_response);
390 extra_data = (char *)response.extra_data.data;
392 if ((extra_len <= 0) || (extra_data[extra_len-1] != '\0')) {
393 goto wbc_err_invalid;
396 p = extra_data;
398 for (i=0; i<num_sids; i++) {
399 struct wbcUnixId *id = &ids[i];
400 char *q;
401 int error = 0;
403 switch (p[0]) {
404 case 'U':
405 id->type = WBC_ID_TYPE_UID;
406 id->id.uid = smb_strtoul(p+1,
409 &error,
410 SMB_STR_STANDARD);
411 break;
412 case 'G':
413 id->type = WBC_ID_TYPE_GID;
414 id->id.gid = smb_strtoul(p+1,
417 &error,
418 SMB_STR_STANDARD);
419 break;
420 case 'B':
421 id->type = WBC_ID_TYPE_BOTH;
422 id->id.uid = smb_strtoul(p+1,
425 &error,
426 SMB_STR_STANDARD);
427 break;
428 default:
429 id->type = WBC_ID_TYPE_NOT_SPECIFIED;
430 q = strchr(p, '\n');
431 break;
433 if (q == NULL || q[0] != '\n' || error != 0) {
434 goto wbc_err_invalid;
436 p = q+1;
438 wbc_status = WBC_ERR_SUCCESS;
439 goto done;
441 wbc_err_invalid:
442 wbc_status = WBC_ERR_INVALID_RESPONSE;
443 done:
444 winbindd_free_response(&response);
445 return wbc_status;
448 _PUBLIC_
449 wbcErr wbcSidsToUnixIds(const struct wbcDomainSid *sids, uint32_t num_sids,
450 struct wbcUnixId *ids)
452 return wbcCtxSidsToUnixIds(NULL, sids, num_sids, ids);
455 _PUBLIC_
456 wbcErr wbcCtxUnixIdsToSids(struct wbcContext *ctx,
457 const struct wbcUnixId *ids, uint32_t num_ids,
458 struct wbcDomainSid *sids)
460 struct winbindd_request request;
461 struct winbindd_response response;
462 wbcErr wbc_status;
463 char *buf;
464 char *s;
465 const size_t sidlen = (1 /* U/G */ + 10 /* 2^32 */ + 1 /* \n */);
466 size_t ofs, buflen;
467 uint32_t i;
469 if (num_ids > SIZE_MAX / sidlen) {
470 return WBC_ERR_NO_MEMORY; /* overflow */
472 buflen = num_ids * sidlen;
474 buflen += 1; /* trailing \0 */
475 if (buflen < 1) {
476 return WBC_ERR_NO_MEMORY; /* overflow */
479 buf = malloc(buflen);
480 if (buf == NULL) {
481 return WBC_ERR_NO_MEMORY;
484 ofs = 0;
486 for (i=0; i<num_ids; i++) {
487 const struct wbcUnixId *id = &ids[i];
488 int len;
490 switch (id->type) {
491 case WBC_ID_TYPE_UID:
492 len = snprintf(buf+ofs, buflen-ofs, "U%"PRIu32"\n",
493 (uint32_t)id->id.uid);
494 break;
495 case WBC_ID_TYPE_GID:
496 len = snprintf(buf+ofs, buflen-ofs, "G%"PRIu32"\n",
497 (uint32_t)id->id.gid);
498 break;
499 default:
500 free(buf);
501 return WBC_ERR_INVALID_PARAM;
504 if (len + ofs >= buflen) { /* >= for the terminating '\0' */
505 free(buf);
506 return WBC_ERR_UNKNOWN_FAILURE;
508 ofs += len;
511 request = (struct winbindd_request) {
512 .extra_data.data = buf, .extra_len = ofs+1
514 response = (struct winbindd_response) {0};
516 wbc_status = wbcRequestResponse(ctx, WINBINDD_XIDS_TO_SIDS,
517 &request, &response);
518 free(buf);
519 if (!WBC_ERROR_IS_OK(wbc_status)) {
520 return wbc_status;
523 s = response.extra_data.data;
524 for (i=0; i<num_ids; i++) {
525 char *n = strchr(s, '\n');
527 if (n == NULL) {
528 goto fail;
530 *n = '\0';
532 wbc_status = wbcStringToSid(s, &sids[i]);
533 if (!WBC_ERROR_IS_OK(wbc_status)) {
534 sids[i] = (struct wbcDomainSid) {0};
536 s = n+1;
539 wbc_status = WBC_ERR_SUCCESS;
540 fail:
541 winbindd_free_response(&response);
542 return wbc_status;
545 _PUBLIC_
546 wbcErr wbcUnixIdsToSids(const struct wbcUnixId *ids, uint32_t num_ids,
547 struct wbcDomainSid *sids)
549 return wbcCtxUnixIdsToSids(NULL, ids, num_ids, sids);