Line data Source code
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 : #include "lib/util/smb_strtox.h"
28 :
29 : /* Convert a Windows SID to a Unix uid, allocating an uid if needed */
30 : _PUBLIC_
31 2729 : wbcErr wbcCtxSidToUid(struct wbcContext *ctx, const struct wbcDomainSid *sid,
32 : uid_t *puid)
33 : {
34 8 : struct wbcUnixId xid;
35 8 : wbcErr wbc_status;
36 :
37 2729 : if (!sid || !puid) {
38 0 : wbc_status = WBC_ERR_INVALID_PARAM;
39 0 : BAIL_ON_WBC_ERROR(wbc_status);
40 : }
41 :
42 2729 : wbc_status = wbcCtxSidsToUnixIds(ctx, sid, 1, &xid);
43 2729 : if (!WBC_ERROR_IS_OK(wbc_status)) {
44 64 : goto done;
45 : }
46 :
47 2665 : if ((xid.type == WBC_ID_TYPE_UID) || (xid.type == WBC_ID_TYPE_BOTH)) {
48 2645 : *puid = xid.id.uid;
49 2645 : wbc_status = WBC_ERR_SUCCESS;
50 : } else {
51 20 : wbc_status = WBC_ERR_DOMAIN_NOT_FOUND;
52 : }
53 :
54 2729 : done:
55 2729 : return wbc_status;
56 : }
57 :
58 : _PUBLIC_
59 2507 : wbcErr wbcSidToUid(const struct wbcDomainSid *sid, uid_t *puid)
60 : {
61 2507 : return wbcCtxSidToUid(NULL, sid, puid);
62 : }
63 :
64 : /* Convert a Windows SID to a Unix uid if there already is a mapping */
65 : _PUBLIC_
66 0 : wbcErr wbcQuerySidToUid(const struct wbcDomainSid *sid,
67 : uid_t *puid)
68 : {
69 0 : return WBC_ERR_NOT_IMPLEMENTED;
70 : }
71 :
72 : /* Convert a Unix uid to a Windows SID, allocating a SID if needed */
73 : _PUBLIC_
74 44 : wbcErr wbcCtxUidToSid(struct wbcContext *ctx, uid_t uid,
75 : struct wbcDomainSid *psid)
76 : {
77 0 : struct wbcUnixId xid;
78 0 : struct wbcDomainSid sid;
79 44 : struct wbcDomainSid null_sid = { 0 };
80 0 : wbcErr wbc_status;
81 :
82 44 : if (!psid) {
83 0 : wbc_status = WBC_ERR_INVALID_PARAM;
84 0 : BAIL_ON_WBC_ERROR(wbc_status);
85 : }
86 :
87 44 : xid = (struct wbcUnixId) { .type = WBC_ID_TYPE_UID, .id.uid = uid };
88 :
89 44 : wbc_status = wbcCtxUnixIdsToSids(ctx, &xid, 1, &sid);
90 44 : if (!WBC_ERROR_IS_OK(wbc_status)) {
91 0 : goto done;
92 : }
93 :
94 44 : if (memcmp(&sid, &null_sid, sizeof(sid)) != 0) {
95 40 : *psid = sid;
96 : } else {
97 4 : wbc_status = WBC_ERR_DOMAIN_NOT_FOUND;
98 : }
99 :
100 44 : done:
101 44 : return wbc_status;
102 : }
103 :
104 : _PUBLIC_
105 44 : wbcErr wbcUidToSid(uid_t uid, struct wbcDomainSid *sid)
106 : {
107 44 : return wbcCtxUidToSid(NULL, uid, sid);
108 : }
109 :
110 : /* Convert a Unix uid to a Windows SID if there already is a mapping */
111 : _PUBLIC_
112 0 : wbcErr wbcQueryUidToSid(uid_t uid,
113 : struct wbcDomainSid *sid)
114 : {
115 0 : return WBC_ERR_NOT_IMPLEMENTED;
116 : }
117 :
118 : /** @brief Convert a Windows SID to a Unix gid, allocating a gid if needed
119 : *
120 : * @param *sid Pointer to the domain SID to be resolved
121 : * @param *pgid Pointer to the resolved gid_t value
122 : *
123 : * @return #wbcErr
124 : *
125 : **/
126 :
127 : _PUBLIC_
128 1536 : wbcErr wbcCtxSidToGid(struct wbcContext *ctx, const struct wbcDomainSid *sid,
129 : gid_t *pgid)
130 : {
131 20 : struct wbcUnixId xid;
132 20 : wbcErr wbc_status;
133 :
134 1536 : if (!sid || !pgid) {
135 0 : wbc_status = WBC_ERR_INVALID_PARAM;
136 0 : BAIL_ON_WBC_ERROR(wbc_status);
137 : }
138 :
139 1536 : wbc_status = wbcCtxSidsToUnixIds(ctx, sid, 1, &xid);
140 1536 : if (!WBC_ERROR_IS_OK(wbc_status)) {
141 63 : goto done;
142 : }
143 :
144 1473 : if ((xid.type == WBC_ID_TYPE_GID) || (xid.type == WBC_ID_TYPE_BOTH)) {
145 1445 : *pgid = xid.id.gid;
146 1445 : wbc_status = WBC_ERR_SUCCESS;
147 : } else {
148 28 : wbc_status = WBC_ERR_DOMAIN_NOT_FOUND;
149 : }
150 :
151 1536 : done:
152 1536 : return wbc_status;
153 : }
154 :
155 : _PUBLIC_
156 1536 : wbcErr wbcSidToGid(const struct wbcDomainSid *sid, gid_t *pgid)
157 : {
158 1536 : return wbcCtxSidToGid(NULL, sid, pgid);
159 : }
160 :
161 : /* Convert a Windows SID to a Unix gid if there already is a mapping */
162 :
163 : _PUBLIC_
164 0 : wbcErr wbcQuerySidToGid(const struct wbcDomainSid *sid,
165 : gid_t *pgid)
166 : {
167 0 : return WBC_ERR_NOT_IMPLEMENTED;
168 : }
169 :
170 :
171 : /* Convert a Unix gid to a Windows SID, allocating a SID if needed */
172 : _PUBLIC_
173 2503 : wbcErr wbcCtxGidToSid(struct wbcContext *ctx, gid_t gid,
174 : struct wbcDomainSid *psid)
175 : {
176 0 : struct wbcUnixId xid;
177 0 : struct wbcDomainSid sid;
178 2503 : struct wbcDomainSid null_sid = { 0 };
179 0 : wbcErr wbc_status;
180 :
181 2503 : if (!psid) {
182 0 : wbc_status = WBC_ERR_INVALID_PARAM;
183 0 : BAIL_ON_WBC_ERROR(wbc_status);
184 : }
185 :
186 2503 : xid = (struct wbcUnixId) { .type = WBC_ID_TYPE_GID, .id.gid = gid };
187 :
188 2503 : wbc_status = wbcCtxUnixIdsToSids(ctx, &xid, 1, &sid);
189 2503 : if (!WBC_ERROR_IS_OK(wbc_status)) {
190 0 : goto done;
191 : }
192 :
193 2503 : if (memcmp(&sid, &null_sid, sizeof(sid)) != 0) {
194 2499 : *psid = sid;
195 : } else {
196 4 : wbc_status = WBC_ERR_DOMAIN_NOT_FOUND;
197 : }
198 :
199 2503 : done:
200 2503 : return wbc_status;
201 : }
202 :
203 : _PUBLIC_
204 2503 : wbcErr wbcGidToSid(gid_t gid, struct wbcDomainSid *sid)
205 : {
206 2503 : return wbcCtxGidToSid(NULL, gid, sid);
207 : }
208 :
209 : /* Convert a Unix gid to a Windows SID if there already is a mapping */
210 : _PUBLIC_
211 0 : wbcErr wbcQueryGidToSid(gid_t gid,
212 : struct wbcDomainSid *sid)
213 : {
214 0 : return WBC_ERR_NOT_IMPLEMENTED;
215 : }
216 :
217 : /* Obtain a new uid from Winbind */
218 : _PUBLIC_
219 10 : wbcErr wbcCtxAllocateUid(struct wbcContext *ctx, uid_t *puid)
220 : {
221 0 : struct winbindd_request request;
222 0 : struct winbindd_response response;
223 10 : wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
224 :
225 10 : if (!puid)
226 0 : return WBC_ERR_INVALID_PARAM;
227 :
228 : /* Initialise request */
229 :
230 10 : ZERO_STRUCT(request);
231 10 : ZERO_STRUCT(response);
232 :
233 : /* Make request */
234 :
235 10 : wbc_status = wbcRequestResponsePriv(ctx, WINBINDD_ALLOCATE_UID,
236 : &request, &response);
237 10 : BAIL_ON_WBC_ERROR(wbc_status);
238 :
239 : /* Copy out result */
240 6 : *puid = response.data.uid;
241 :
242 6 : wbc_status = WBC_ERR_SUCCESS;
243 :
244 10 : done:
245 10 : return wbc_status;
246 : }
247 :
248 : _PUBLIC_
249 10 : wbcErr wbcAllocateUid(uid_t *puid)
250 : {
251 10 : return wbcCtxAllocateUid(NULL, puid);
252 : }
253 :
254 : /* Obtain a new gid from Winbind */
255 : _PUBLIC_
256 16064 : wbcErr wbcCtxAllocateGid(struct wbcContext *ctx, gid_t *pgid)
257 : {
258 0 : struct winbindd_request request;
259 0 : struct winbindd_response response;
260 16064 : wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
261 :
262 16064 : if (!pgid)
263 0 : return WBC_ERR_INVALID_PARAM;
264 :
265 : /* Initialise request */
266 :
267 16064 : ZERO_STRUCT(request);
268 16064 : ZERO_STRUCT(response);
269 :
270 : /* Make request */
271 :
272 16064 : wbc_status = wbcRequestResponsePriv(ctx, WINBINDD_ALLOCATE_GID,
273 : &request, &response);
274 16064 : BAIL_ON_WBC_ERROR(wbc_status);
275 :
276 : /* Copy out result */
277 15928 : *pgid = response.data.gid;
278 :
279 15928 : wbc_status = WBC_ERR_SUCCESS;
280 :
281 16064 : done:
282 16064 : return wbc_status;
283 : }
284 :
285 : _PUBLIC_
286 16064 : wbcErr wbcAllocateGid(gid_t *pgid)
287 : {
288 16064 : return wbcCtxAllocateGid(NULL, pgid);
289 : }
290 :
291 : /* we can't include smb.h here... */
292 : #define _ID_TYPE_UID 1
293 : #define _ID_TYPE_GID 2
294 :
295 : /* Set an user id mapping - not implemented any more */
296 : _PUBLIC_
297 0 : wbcErr wbcSetUidMapping(uid_t uid, const struct wbcDomainSid *sid)
298 : {
299 0 : return WBC_ERR_NOT_IMPLEMENTED;
300 : }
301 :
302 : /* Set a group id mapping - not implemented any more */
303 : _PUBLIC_
304 0 : wbcErr wbcSetGidMapping(gid_t gid, const struct wbcDomainSid *sid)
305 : {
306 0 : return WBC_ERR_NOT_IMPLEMENTED;
307 : }
308 :
309 : /* Remove a user id mapping - not implemented any more */
310 : _PUBLIC_
311 0 : wbcErr wbcRemoveUidMapping(uid_t uid, const struct wbcDomainSid *sid)
312 : {
313 0 : return WBC_ERR_NOT_IMPLEMENTED;
314 : }
315 :
316 : /* Remove a group id mapping - not implemented any more */
317 : _PUBLIC_
318 0 : wbcErr wbcRemoveGidMapping(gid_t gid, const struct wbcDomainSid *sid)
319 : {
320 0 : return WBC_ERR_NOT_IMPLEMENTED;
321 : }
322 :
323 : /* Set the highwater mark for allocated uids - not implemented any more */
324 : _PUBLIC_
325 0 : wbcErr wbcSetUidHwm(uid_t uid_hwm)
326 : {
327 0 : return WBC_ERR_NOT_IMPLEMENTED;
328 : }
329 :
330 : /* Set the highwater mark for allocated gids - not implemented any more */
331 : _PUBLIC_
332 0 : wbcErr wbcSetGidHwm(gid_t gid_hwm)
333 : {
334 0 : return WBC_ERR_NOT_IMPLEMENTED;
335 : }
336 :
337 : /* Convert a list of SIDs */
338 : _PUBLIC_
339 122019 : wbcErr wbcCtxSidsToUnixIds(struct wbcContext *ctx,
340 : const struct wbcDomainSid *sids,
341 : uint32_t num_sids, struct wbcUnixId *ids)
342 : {
343 2535 : struct winbindd_request request;
344 2535 : struct winbindd_response response;
345 122019 : wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
346 2535 : int buflen, extra_len;
347 2535 : uint32_t i;
348 2535 : char *sidlist, *p, *extra_data;
349 :
350 122019 : buflen = num_sids * (WBC_SID_STRING_BUFLEN + 1) + 1;
351 :
352 122019 : sidlist = (char *)malloc(buflen);
353 122019 : if (sidlist == NULL) {
354 0 : return WBC_ERR_NO_MEMORY;
355 : }
356 :
357 119484 : p = sidlist;
358 :
359 591117 : for (i=0; i<num_sids; i++) {
360 15746 : int remaining;
361 15746 : int len;
362 :
363 469098 : remaining = buflen - (p - sidlist);
364 :
365 469098 : len = wbcSidToStringBuf(&sids[i], p, remaining);
366 469098 : if (len > remaining) {
367 0 : free(sidlist);
368 0 : return WBC_ERR_UNKNOWN_FAILURE;
369 : }
370 :
371 469098 : p += len;
372 469098 : *p++ = '\n';
373 : }
374 122019 : *p++ = '\0';
375 :
376 122019 : ZERO_STRUCT(request);
377 122019 : ZERO_STRUCT(response);
378 :
379 122019 : request.extra_data.data = sidlist;
380 122019 : request.extra_len = p - sidlist;
381 :
382 122019 : wbc_status = wbcRequestResponse(ctx, WINBINDD_SIDS_TO_XIDS,
383 : &request, &response);
384 122019 : free(sidlist);
385 122019 : if (!WBC_ERROR_IS_OK(wbc_status)) {
386 84433 : return wbc_status;
387 : }
388 :
389 35853 : extra_len = response.length - sizeof(struct winbindd_response);
390 35853 : extra_data = (char *)response.extra_data.data;
391 :
392 35853 : if ((extra_len <= 0) || (extra_data[extra_len-1] != '\0')) {
393 0 : goto wbc_err_invalid;
394 : }
395 :
396 35051 : p = extra_data;
397 :
398 240071 : for (i=0; i<num_sids; i++) {
399 204218 : struct wbcUnixId *id = &ids[i];
400 10645 : char *q;
401 204218 : int error = 0;
402 :
403 204218 : switch (p[0]) {
404 13292 : case 'U':
405 13292 : id->type = WBC_ID_TYPE_UID;
406 13292 : id->id.uid = smb_strtoul(p+1,
407 : &q,
408 : 10,
409 : &error,
410 : SMB_STR_STANDARD);
411 13292 : break;
412 30402 : case 'G':
413 30402 : id->type = WBC_ID_TYPE_GID;
414 30402 : id->id.gid = smb_strtoul(p+1,
415 : &q,
416 : 10,
417 : &error,
418 : SMB_STR_STANDARD);
419 30402 : break;
420 153283 : case 'B':
421 153283 : id->type = WBC_ID_TYPE_BOTH;
422 153283 : id->id.uid = smb_strtoul(p+1,
423 : &q,
424 : 10,
425 : &error,
426 : SMB_STR_STANDARD);
427 153283 : break;
428 7241 : default:
429 7241 : id->type = WBC_ID_TYPE_NOT_SPECIFIED;
430 7241 : q = strchr(p, '\n');
431 7241 : break;
432 10645 : };
433 204218 : if (q == NULL || q[0] != '\n' || error != 0) {
434 0 : goto wbc_err_invalid;
435 : }
436 204218 : p = q+1;
437 : }
438 35853 : wbc_status = WBC_ERR_SUCCESS;
439 35853 : goto done;
440 :
441 0 : wbc_err_invalid:
442 0 : wbc_status = WBC_ERR_INVALID_RESPONSE;
443 35853 : done:
444 35853 : winbindd_free_response(&response);
445 35051 : return wbc_status;
446 : }
447 :
448 : _PUBLIC_
449 117754 : wbcErr wbcSidsToUnixIds(const struct wbcDomainSid *sids, uint32_t num_sids,
450 : struct wbcUnixId *ids)
451 : {
452 117754 : return wbcCtxSidsToUnixIds(NULL, sids, num_sids, ids);
453 : }
454 :
455 : _PUBLIC_
456 285197 : wbcErr wbcCtxUnixIdsToSids(struct wbcContext *ctx,
457 : const struct wbcUnixId *ids, uint32_t num_ids,
458 : struct wbcDomainSid *sids)
459 : {
460 1696 : struct winbindd_request request;
461 1696 : struct winbindd_response response;
462 1696 : wbcErr wbc_status;
463 1696 : char *buf;
464 1696 : char *s;
465 285197 : const size_t sidlen = (1 /* U/G */ + 10 /* 2^32 */ + 1 /* \n */);
466 1696 : size_t ofs, buflen;
467 1696 : uint32_t i;
468 :
469 285197 : if (num_ids > SIZE_MAX / sidlen) {
470 0 : return WBC_ERR_NO_MEMORY; /* overflow */
471 : }
472 285197 : buflen = num_ids * sidlen;
473 :
474 285197 : buflen += 1; /* trailing \0 */
475 285197 : if (buflen < 1) {
476 0 : return WBC_ERR_NO_MEMORY; /* overflow */
477 : }
478 :
479 285197 : buf = malloc(buflen);
480 285197 : if (buf == NULL) {
481 0 : return WBC_ERR_NO_MEMORY;
482 : }
483 :
484 283501 : ofs = 0;
485 :
486 571643 : for (i=0; i<num_ids; i++) {
487 286446 : const struct wbcUnixId *id = &ids[i];
488 1696 : int len;
489 :
490 286446 : switch (id->type) {
491 7152 : case WBC_ID_TYPE_UID:
492 7152 : len = snprintf(buf+ofs, buflen-ofs, "U%"PRIu32"\n",
493 7152 : (uint32_t)id->id.uid);
494 7152 : break;
495 279294 : case WBC_ID_TYPE_GID:
496 279294 : len = snprintf(buf+ofs, buflen-ofs, "G%"PRIu32"\n",
497 279294 : (uint32_t)id->id.gid);
498 279294 : break;
499 0 : default:
500 0 : free(buf);
501 0 : return WBC_ERR_INVALID_PARAM;
502 : }
503 :
504 286446 : if (len + ofs >= buflen) { /* >= for the terminating '\0' */
505 0 : free(buf);
506 0 : return WBC_ERR_UNKNOWN_FAILURE;
507 : }
508 286446 : ofs += len;
509 : }
510 :
511 285197 : request = (struct winbindd_request) {
512 285197 : .extra_data.data = buf, .extra_len = ofs+1
513 : };
514 285197 : response = (struct winbindd_response) {0};
515 :
516 285197 : wbc_status = wbcRequestResponse(ctx, WINBINDD_XIDS_TO_SIDS,
517 : &request, &response);
518 285197 : free(buf);
519 285197 : if (!WBC_ERROR_IS_OK(wbc_status)) {
520 250578 : return wbc_status;
521 : }
522 :
523 32923 : s = response.extra_data.data;
524 67095 : for (i=0; i<num_ids; i++) {
525 34172 : char *n = strchr(s, '\n');
526 :
527 34172 : if (n == NULL) {
528 0 : goto fail;
529 : }
530 34172 : *n = '\0';
531 :
532 34172 : wbc_status = wbcStringToSid(s, &sids[i]);
533 34172 : if (!WBC_ERROR_IS_OK(wbc_status)) {
534 14248 : sids[i] = (struct wbcDomainSid) {0};
535 : }
536 34172 : s = n+1;
537 : }
538 :
539 32923 : wbc_status = WBC_ERR_SUCCESS;
540 32923 : fail:
541 32923 : winbindd_free_response(&response);
542 32923 : return wbc_status;
543 : }
544 :
545 : _PUBLIC_
546 282650 : wbcErr wbcUnixIdsToSids(const struct wbcUnixId *ids, uint32_t num_ids,
547 : struct wbcDomainSid *sids)
548 : {
549 282650 : return wbcCtxUnixIdsToSids(NULL, ids, num_ids, sids);
550 : }
|