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 1020 : wbcErr wbcCtxSidToUid(struct wbcContext *ctx, const struct wbcDomainSid *sid,
32 : uid_t *puid)
33 : {
34 : struct wbcUnixId xid;
35 : wbcErr wbc_status;
36 :
37 1020 : if (!sid || !puid) {
38 0 : wbc_status = WBC_ERR_INVALID_PARAM;
39 0 : BAIL_ON_WBC_ERROR(wbc_status);
40 : }
41 :
42 1020 : wbc_status = wbcCtxSidsToUnixIds(ctx, sid, 1, &xid);
43 1020 : if (!WBC_ERROR_IS_OK(wbc_status)) {
44 39 : goto done;
45 : }
46 :
47 981 : if ((xid.type == WBC_ID_TYPE_UID) || (xid.type == WBC_ID_TYPE_BOTH)) {
48 969 : *puid = xid.id.uid;
49 969 : wbc_status = WBC_ERR_SUCCESS;
50 : } else {
51 12 : wbc_status = WBC_ERR_DOMAIN_NOT_FOUND;
52 : }
53 :
54 1020 : done:
55 1020 : return wbc_status;
56 : }
57 :
58 : _PUBLIC_
59 998 : wbcErr wbcSidToUid(const struct wbcDomainSid *sid, uid_t *puid)
60 : {
61 998 : 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 28 : wbcErr wbcCtxUidToSid(struct wbcContext *ctx, uid_t uid,
75 : struct wbcDomainSid *psid)
76 : {
77 : struct wbcUnixId xid;
78 : struct wbcDomainSid sid;
79 28 : struct wbcDomainSid null_sid = { 0 };
80 : wbcErr wbc_status;
81 :
82 28 : if (!psid) {
83 0 : wbc_status = WBC_ERR_INVALID_PARAM;
84 0 : BAIL_ON_WBC_ERROR(wbc_status);
85 : }
86 :
87 28 : xid = (struct wbcUnixId) { .type = WBC_ID_TYPE_UID, .id.uid = uid };
88 :
89 28 : wbc_status = wbcCtxUnixIdsToSids(ctx, &xid, 1, &sid);
90 28 : if (!WBC_ERROR_IS_OK(wbc_status)) {
91 0 : goto done;
92 : }
93 :
94 28 : if (memcmp(&sid, &null_sid, sizeof(sid)) != 0) {
95 24 : *psid = sid;
96 : } else {
97 4 : wbc_status = WBC_ERR_DOMAIN_NOT_FOUND;
98 : }
99 :
100 28 : done:
101 28 : return wbc_status;
102 : }
103 :
104 : _PUBLIC_
105 28 : wbcErr wbcUidToSid(uid_t uid, struct wbcDomainSid *sid)
106 : {
107 28 : 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 420 : wbcErr wbcCtxSidToGid(struct wbcContext *ctx, const struct wbcDomainSid *sid,
129 : gid_t *pgid)
130 : {
131 : struct wbcUnixId xid;
132 : wbcErr wbc_status;
133 :
134 420 : if (!sid || !pgid) {
135 0 : wbc_status = WBC_ERR_INVALID_PARAM;
136 0 : BAIL_ON_WBC_ERROR(wbc_status);
137 : }
138 :
139 420 : wbc_status = wbcCtxSidsToUnixIds(ctx, sid, 1, &xid);
140 420 : if (!WBC_ERROR_IS_OK(wbc_status)) {
141 33 : goto done;
142 : }
143 :
144 387 : if ((xid.type == WBC_ID_TYPE_GID) || (xid.type == WBC_ID_TYPE_BOTH)) {
145 365 : *pgid = xid.id.gid;
146 365 : wbc_status = WBC_ERR_SUCCESS;
147 : } else {
148 22 : wbc_status = WBC_ERR_DOMAIN_NOT_FOUND;
149 : }
150 :
151 420 : done:
152 420 : return wbc_status;
153 : }
154 :
155 : _PUBLIC_
156 420 : wbcErr wbcSidToGid(const struct wbcDomainSid *sid, gid_t *pgid)
157 : {
158 420 : 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 46 : wbcErr wbcCtxGidToSid(struct wbcContext *ctx, gid_t gid,
174 : struct wbcDomainSid *psid)
175 : {
176 : struct wbcUnixId xid;
177 : struct wbcDomainSid sid;
178 46 : struct wbcDomainSid null_sid = { 0 };
179 : wbcErr wbc_status;
180 :
181 46 : if (!psid) {
182 0 : wbc_status = WBC_ERR_INVALID_PARAM;
183 0 : BAIL_ON_WBC_ERROR(wbc_status);
184 : }
185 :
186 46 : xid = (struct wbcUnixId) { .type = WBC_ID_TYPE_GID, .id.gid = gid };
187 :
188 46 : wbc_status = wbcCtxUnixIdsToSids(ctx, &xid, 1, &sid);
189 46 : if (!WBC_ERROR_IS_OK(wbc_status)) {
190 0 : goto done;
191 : }
192 :
193 46 : if (memcmp(&sid, &null_sid, sizeof(sid)) != 0) {
194 42 : *psid = sid;
195 : } else {
196 4 : wbc_status = WBC_ERR_DOMAIN_NOT_FOUND;
197 : }
198 :
199 46 : done:
200 46 : return wbc_status;
201 : }
202 :
203 : _PUBLIC_
204 46 : wbcErr wbcGidToSid(gid_t gid, struct wbcDomainSid *sid)
205 : {
206 46 : 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 4 : wbcErr wbcCtxAllocateUid(struct wbcContext *ctx, uid_t *puid)
220 : {
221 : struct winbindd_request request;
222 : struct winbindd_response response;
223 4 : wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
224 :
225 4 : if (!puid)
226 0 : return WBC_ERR_INVALID_PARAM;
227 :
228 : /* Initialise request */
229 :
230 4 : ZERO_STRUCT(request);
231 4 : ZERO_STRUCT(response);
232 :
233 : /* Make request */
234 :
235 4 : wbc_status = wbcRequestResponsePriv(ctx, WINBINDD_ALLOCATE_UID,
236 : &request, &response);
237 4 : BAIL_ON_WBC_ERROR(wbc_status);
238 :
239 : /* Copy out result */
240 2 : *puid = response.data.uid;
241 :
242 2 : wbc_status = WBC_ERR_SUCCESS;
243 :
244 4 : done:
245 4 : return wbc_status;
246 : }
247 :
248 : _PUBLIC_
249 4 : wbcErr wbcAllocateUid(uid_t *puid)
250 : {
251 4 : return wbcCtxAllocateUid(NULL, puid);
252 : }
253 :
254 : /* Obtain a new gid from Winbind */
255 : _PUBLIC_
256 3026 : wbcErr wbcCtxAllocateGid(struct wbcContext *ctx, gid_t *pgid)
257 : {
258 : struct winbindd_request request;
259 : struct winbindd_response response;
260 3026 : wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
261 :
262 3026 : if (!pgid)
263 0 : return WBC_ERR_INVALID_PARAM;
264 :
265 : /* Initialise request */
266 :
267 3026 : ZERO_STRUCT(request);
268 3026 : ZERO_STRUCT(response);
269 :
270 : /* Make request */
271 :
272 3026 : wbc_status = wbcRequestResponsePriv(ctx, WINBINDD_ALLOCATE_GID,
273 : &request, &response);
274 3026 : BAIL_ON_WBC_ERROR(wbc_status);
275 :
276 : /* Copy out result */
277 3012 : *pgid = response.data.gid;
278 :
279 3012 : wbc_status = WBC_ERR_SUCCESS;
280 :
281 3026 : done:
282 3026 : return wbc_status;
283 : }
284 :
285 : _PUBLIC_
286 3026 : wbcErr wbcAllocateGid(gid_t *pgid)
287 : {
288 3026 : 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 18288 : wbcErr wbcCtxSidsToUnixIds(struct wbcContext *ctx,
340 : const struct wbcDomainSid *sids,
341 : uint32_t num_sids, struct wbcUnixId *ids)
342 : {
343 : struct winbindd_request request;
344 : struct winbindd_response response;
345 18288 : wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
346 : int buflen, extra_len;
347 : uint32_t i;
348 : char *sidlist, *p, *extra_data;
349 :
350 18288 : buflen = num_sids * (WBC_SID_STRING_BUFLEN + 1) + 1;
351 :
352 18288 : sidlist = (char *)malloc(buflen);
353 18288 : if (sidlist == NULL) {
354 0 : return WBC_ERR_NO_MEMORY;
355 : }
356 :
357 18288 : p = sidlist;
358 :
359 117165 : for (i=0; i<num_sids; i++) {
360 : int remaining;
361 : int len;
362 :
363 98877 : remaining = buflen - (p - sidlist);
364 :
365 98877 : len = wbcSidToStringBuf(&sids[i], p, remaining);
366 98877 : if (len > remaining) {
367 0 : free(sidlist);
368 0 : return WBC_ERR_UNKNOWN_FAILURE;
369 : }
370 :
371 98877 : p += len;
372 98877 : *p++ = '\n';
373 : }
374 18288 : *p++ = '\0';
375 :
376 18288 : ZERO_STRUCT(request);
377 18288 : ZERO_STRUCT(response);
378 :
379 18288 : request.extra_data.data = sidlist;
380 18288 : request.extra_len = p - sidlist;
381 :
382 18288 : wbc_status = wbcRequestResponse(ctx, WINBINDD_SIDS_TO_XIDS,
383 : &request, &response);
384 18288 : free(sidlist);
385 18288 : if (!WBC_ERROR_IS_OK(wbc_status)) {
386 8675 : return wbc_status;
387 : }
388 :
389 9613 : extra_len = response.length - sizeof(struct winbindd_response);
390 9613 : extra_data = (char *)response.extra_data.data;
391 :
392 9613 : if ((extra_len <= 0) || (extra_data[extra_len-1] != '\0')) {
393 0 : goto wbc_err_invalid;
394 : }
395 :
396 9613 : p = extra_data;
397 :
398 82709 : for (i=0; i<num_sids; i++) {
399 73096 : struct wbcUnixId *id = &ids[i];
400 : char *q;
401 73096 : int error = 0;
402 :
403 73096 : switch (p[0]) {
404 5506 : case 'U':
405 5506 : id->type = WBC_ID_TYPE_UID;
406 5506 : id->id.uid = smb_strtoul(p+1,
407 : &q,
408 : 10,
409 : &error,
410 : SMB_STR_STANDARD);
411 5506 : break;
412 8323 : case 'G':
413 8323 : id->type = WBC_ID_TYPE_GID;
414 8323 : id->id.gid = smb_strtoul(p+1,
415 : &q,
416 : 10,
417 : &error,
418 : SMB_STR_STANDARD);
419 8323 : break;
420 58223 : case 'B':
421 58223 : id->type = WBC_ID_TYPE_BOTH;
422 58223 : id->id.uid = smb_strtoul(p+1,
423 : &q,
424 : 10,
425 : &error,
426 : SMB_STR_STANDARD);
427 58223 : break;
428 1044 : default:
429 1044 : id->type = WBC_ID_TYPE_NOT_SPECIFIED;
430 1044 : q = strchr(p, '\n');
431 1044 : break;
432 : };
433 73096 : if (q == NULL || q[0] != '\n' || error != 0) {
434 0 : goto wbc_err_invalid;
435 : }
436 73096 : p = q+1;
437 : }
438 9613 : wbc_status = WBC_ERR_SUCCESS;
439 9613 : goto done;
440 :
441 0 : wbc_err_invalid:
442 0 : wbc_status = WBC_ERR_INVALID_RESPONSE;
443 9613 : done:
444 9613 : winbindd_free_response(&response);
445 9613 : return wbc_status;
446 : }
447 :
448 : _PUBLIC_
449 16848 : wbcErr wbcSidsToUnixIds(const struct wbcDomainSid *sids, uint32_t num_sids,
450 : struct wbcUnixId *ids)
451 : {
452 16848 : return wbcCtxSidsToUnixIds(NULL, sids, num_sids, ids);
453 : }
454 :
455 : _PUBLIC_
456 16419 : wbcErr wbcCtxUnixIdsToSids(struct wbcContext *ctx,
457 : const struct wbcUnixId *ids, uint32_t num_ids,
458 : struct wbcDomainSid *sids)
459 : {
460 : struct winbindd_request request;
461 : struct winbindd_response response;
462 : wbcErr wbc_status;
463 : char *buf;
464 : char *s;
465 16419 : const size_t sidlen = (1 /* U/G */ + 10 /* 2^32 */ + 1 /* \n */);
466 : size_t ofs, buflen;
467 : uint32_t i;
468 :
469 16419 : if (num_ids > SIZE_MAX / sidlen) {
470 0 : return WBC_ERR_NO_MEMORY; /* overflow */
471 : }
472 16419 : buflen = num_ids * sidlen;
473 :
474 16419 : buflen += 1; /* trailing \0 */
475 16419 : if (buflen < 1) {
476 0 : return WBC_ERR_NO_MEMORY; /* overflow */
477 : }
478 :
479 16419 : buf = malloc(buflen);
480 16419 : if (buf == NULL) {
481 0 : return WBC_ERR_NO_MEMORY;
482 : }
483 :
484 16419 : ofs = 0;
485 :
486 34067 : for (i=0; i<num_ids; i++) {
487 17648 : const struct wbcUnixId *id = &ids[i];
488 : int len;
489 :
490 17648 : switch (id->type) {
491 2796 : case WBC_ID_TYPE_UID:
492 2796 : len = snprintf(buf+ofs, buflen-ofs, "U%"PRIu32"\n",
493 2796 : (uint32_t)id->id.uid);
494 2796 : break;
495 14852 : case WBC_ID_TYPE_GID:
496 14852 : len = snprintf(buf+ofs, buflen-ofs, "G%"PRIu32"\n",
497 14852 : (uint32_t)id->id.gid);
498 14852 : break;
499 0 : default:
500 0 : free(buf);
501 0 : return WBC_ERR_INVALID_PARAM;
502 : }
503 :
504 17648 : if (len + ofs >= buflen) { /* >= for the terminating '\0' */
505 0 : free(buf);
506 0 : return WBC_ERR_UNKNOWN_FAILURE;
507 : }
508 17648 : ofs += len;
509 : }
510 :
511 16419 : request = (struct winbindd_request) {
512 16419 : .extra_data.data = buf, .extra_len = ofs+1
513 : };
514 16419 : response = (struct winbindd_response) {0};
515 :
516 16419 : wbc_status = wbcRequestResponse(ctx, WINBINDD_XIDS_TO_SIDS,
517 : &request, &response);
518 16419 : free(buf);
519 16419 : if (!WBC_ERROR_IS_OK(wbc_status)) {
520 9513 : return wbc_status;
521 : }
522 :
523 6906 : s = response.extra_data.data;
524 15041 : for (i=0; i<num_ids; i++) {
525 8135 : char *n = strchr(s, '\n');
526 :
527 8135 : if (n == NULL) {
528 0 : goto fail;
529 : }
530 8135 : *n = '\0';
531 :
532 8135 : wbc_status = wbcStringToSid(s, &sids[i]);
533 8135 : if (!WBC_ERROR_IS_OK(wbc_status)) {
534 2055 : sids[i] = (struct wbcDomainSid) {0};
535 : }
536 8135 : s = n+1;
537 : }
538 :
539 6906 : wbc_status = WBC_ERR_SUCCESS;
540 6906 : fail:
541 6906 : winbindd_free_response(&response);
542 6906 : return wbc_status;
543 : }
544 :
545 : _PUBLIC_
546 16345 : wbcErr wbcUnixIdsToSids(const struct wbcUnixId *ids, uint32_t num_ids,
547 : struct wbcDomainSid *sids)
548 : {
549 16345 : return wbcCtxUnixIdsToSids(NULL, ids, num_ids, sids);
550 : }
|