tstream_npa: Avoid an unnecessary ZERO_STRUCTP
[Samba.git] / nsswitch / libwbclient / wbc_sid.c
blob514a7e8d7380186944310b478c2d5ca190a1a71f
1 /*
2 Unix SMB/CIFS implementation.
4 Winbind client API
6 Copyright (C) Gerald (Jerry) Carter 2007
7 Copyright (C) Volker Lendecke 2010
10 This library is free software; you can redistribute it and/or
11 modify it under the terms of the GNU Lesser General Public
12 License as published by the Free Software Foundation; either
13 version 3 of the License, or (at your option) any later version.
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Library General Public License for more details.
20 You should have received a copy of the GNU Lesser General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 /* Required Headers */
26 #include "replace.h"
27 #include "libwbclient.h"
28 #include "../winbind_client.h"
29 #include "lib/util/util.h"
31 /* Convert a sid to a string into a buffer. Return the string
32 * length. If buflen is too small, return the string length that would
33 * result if it was long enough. */
34 int wbcSidToStringBuf(const struct wbcDomainSid *sid, char *buf, int buflen)
36 uint64_t id_auth;
37 int i, ofs;
39 if (!sid) {
40 strlcpy(buf, "(NULL SID)", buflen);
41 return 10; /* strlen("(NULL SID)") */
44 id_auth = (uint64_t)sid->id_auth[5] +
45 ((uint64_t)sid->id_auth[4] << 8) +
46 ((uint64_t)sid->id_auth[3] << 16) +
47 ((uint64_t)sid->id_auth[2] << 24) +
48 ((uint64_t)sid->id_auth[1] << 32) +
49 ((uint64_t)sid->id_auth[0] << 40);
51 ofs = snprintf(buf, buflen, "S-%hhu-", (unsigned char)sid->sid_rev_num);
52 if (id_auth >= UINT32_MAX) {
53 ofs += snprintf(buf + ofs, MAX(buflen - ofs, 0), "0x%llx",
54 (unsigned long long)id_auth);
55 } else {
56 ofs += snprintf(buf + ofs, MAX(buflen - ofs, 0), "%llu",
57 (unsigned long long)id_auth);
60 for (i = 0; i < sid->num_auths; i++) {
61 ofs += snprintf(buf + ofs, MAX(buflen - ofs, 0), "-%u",
62 (unsigned int)sid->sub_auths[i]);
64 return ofs;
67 /* Convert a binary SID to a character string */
68 wbcErr wbcSidToString(const struct wbcDomainSid *sid,
69 char **sid_string)
71 char buf[WBC_SID_STRING_BUFLEN];
72 char *result;
73 int len;
75 if (!sid) {
76 return WBC_ERR_INVALID_SID;
79 len = wbcSidToStringBuf(sid, buf, sizeof(buf));
81 if (len+1 > sizeof(buf)) {
82 return WBC_ERR_INVALID_SID;
85 result = (char *)wbcAllocateMemory(len+1, 1, NULL);
86 if (result == NULL) {
87 return WBC_ERR_NO_MEMORY;
89 memcpy(result, buf, len+1);
91 *sid_string = result;
92 return WBC_ERR_SUCCESS;
95 #define AUTHORITY_MASK (~(0xffffffffffffULL))
97 /* Convert a character string to a binary SID */
98 wbcErr wbcStringToSid(const char *str,
99 struct wbcDomainSid *sid)
101 const char *p;
102 char *q;
103 int error = 0;
104 uint64_t x;
105 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
107 if (!sid) {
108 wbc_status = WBC_ERR_INVALID_PARAM;
109 BAIL_ON_WBC_ERROR(wbc_status);
112 /* Sanity check for either "S-" or "s-" */
114 if (!str
115 || (str[0]!='S' && str[0]!='s')
116 || (str[1]!='-'))
118 wbc_status = WBC_ERR_INVALID_PARAM;
119 BAIL_ON_WBC_ERROR(wbc_status);
122 /* Get the SID revision number */
124 p = str+2;
125 x = (uint64_t)strtoul_err(p, &q, 10, &error);
126 if (x == 0 || x > UINT8_MAX || !q || *q != '-' || error != 0) {
127 wbc_status = WBC_ERR_INVALID_SID;
128 BAIL_ON_WBC_ERROR(wbc_status);
130 sid->sid_rev_num = (uint8_t)x;
133 * Next the Identifier Authority. This is stored big-endian in a
134 * 6 byte array. If the authority value is >= UINT_MAX, then it should
135 * be expressed as a hex value, according to MS-DTYP.
137 p = q+1;
138 x = strtoull_err(p, &q, 0, &error);
139 if (!q || *q != '-' || (x & AUTHORITY_MASK) || error != 0) {
140 wbc_status = WBC_ERR_INVALID_SID;
141 BAIL_ON_WBC_ERROR(wbc_status);
143 sid->id_auth[5] = (x & 0x0000000000ffULL);
144 sid->id_auth[4] = (x & 0x00000000ff00ULL) >> 8;
145 sid->id_auth[3] = (x & 0x000000ff0000ULL) >> 16;
146 sid->id_auth[2] = (x & 0x0000ff000000ULL) >> 24;
147 sid->id_auth[1] = (x & 0x00ff00000000ULL) >> 32;
148 sid->id_auth[0] = (x & 0xff0000000000ULL) >> 40;
150 /* now read the the subauthorities */
151 p = q +1;
152 sid->num_auths = 0;
153 while (sid->num_auths < WBC_MAXSUBAUTHS) {
154 x = strtoull_err(p, &q, 10, &error);
155 if (p == q)
156 break;
157 if (x > UINT32_MAX || error != 0) {
158 wbc_status = WBC_ERR_INVALID_SID;
159 BAIL_ON_WBC_ERROR(wbc_status);
161 sid->sub_auths[sid->num_auths++] = x;
163 if (*q != '-') {
164 break;
166 p = q + 1;
169 /* IF we ended early, then the SID could not be converted */
171 if (q && *q!='\0') {
172 wbc_status = WBC_ERR_INVALID_SID;
173 BAIL_ON_WBC_ERROR(wbc_status);
176 wbc_status = WBC_ERR_SUCCESS;
178 done:
179 return wbc_status;
184 /* Convert a domain and name to SID */
185 wbcErr wbcCtxLookupName(struct wbcContext *ctx,
186 const char *domain,
187 const char *name,
188 struct wbcDomainSid *sid,
189 enum wbcSidType *name_type)
191 struct winbindd_request request;
192 struct winbindd_response response;
193 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
195 if (!sid || !name_type) {
196 wbc_status = WBC_ERR_INVALID_PARAM;
197 BAIL_ON_WBC_ERROR(wbc_status);
200 /* Initialize request */
202 ZERO_STRUCT(request);
203 ZERO_STRUCT(response);
205 /* dst is already null terminated from the memset above */
207 strncpy(request.data.name.dom_name, domain,
208 sizeof(request.data.name.dom_name)-1);
209 strncpy(request.data.name.name, name,
210 sizeof(request.data.name.name)-1);
212 wbc_status = wbcRequestResponse(ctx, WINBINDD_LOOKUPNAME,
213 &request,
214 &response);
215 BAIL_ON_WBC_ERROR(wbc_status);
217 wbc_status = wbcStringToSid(response.data.sid.sid, sid);
218 BAIL_ON_WBC_ERROR(wbc_status);
220 *name_type = (enum wbcSidType)response.data.sid.type;
222 wbc_status = WBC_ERR_SUCCESS;
224 done:
225 return wbc_status;
228 wbcErr wbcLookupName(const char *domain,
229 const char *name,
230 struct wbcDomainSid *sid,
231 enum wbcSidType *name_type)
233 return wbcCtxLookupName(NULL, domain, name, sid, name_type);
237 /* Convert a SID to a domain and name */
238 wbcErr wbcCtxLookupSid(struct wbcContext *ctx,
239 const struct wbcDomainSid *sid,
240 char **pdomain,
241 char **pname,
242 enum wbcSidType *pname_type)
244 struct winbindd_request request;
245 struct winbindd_response response;
246 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
247 char *domain, *name;
249 if (!sid) {
250 return WBC_ERR_INVALID_PARAM;
253 /* Initialize request */
255 ZERO_STRUCT(request);
256 ZERO_STRUCT(response);
258 wbcSidToStringBuf(sid, request.data.sid, sizeof(request.data.sid));
260 /* Make request */
262 wbc_status = wbcRequestResponse(ctx, WINBINDD_LOOKUPSID,
263 &request,
264 &response);
265 if (!WBC_ERROR_IS_OK(wbc_status)) {
266 return wbc_status;
269 /* Copy out result */
271 wbc_status = WBC_ERR_NO_MEMORY;
272 domain = NULL;
273 name = NULL;
275 domain = wbcStrDup(response.data.name.dom_name);
276 if (domain == NULL) {
277 goto done;
279 name = wbcStrDup(response.data.name.name);
280 if (name == NULL) {
281 goto done;
283 if (pdomain != NULL) {
284 *pdomain = domain;
285 domain = NULL;
287 if (pname != NULL) {
288 *pname = name;
289 name = NULL;
291 if (pname_type != NULL) {
292 *pname_type = (enum wbcSidType)response.data.name.type;
294 wbc_status = WBC_ERR_SUCCESS;
295 done:
296 wbcFreeMemory(name);
297 wbcFreeMemory(domain);
298 return wbc_status;
301 wbcErr wbcLookupSid(const struct wbcDomainSid *sid,
302 char **pdomain,
303 char **pname,
304 enum wbcSidType *pname_type)
306 return wbcCtxLookupSid(NULL, sid, pdomain, pname, pname_type);
309 static void wbcDomainInfosDestructor(void *ptr)
311 struct wbcDomainInfo *i = (struct wbcDomainInfo *)ptr;
313 while (i->short_name != NULL) {
314 wbcFreeMemory(i->short_name);
315 wbcFreeMemory(i->dns_name);
316 i += 1;
320 static void wbcTranslatedNamesDestructor(void *ptr)
322 struct wbcTranslatedName *n = (struct wbcTranslatedName *)ptr;
324 while (n->name != NULL) {
325 wbcFreeMemory(n->name);
326 n += 1;
330 wbcErr wbcCtxLookupSids(struct wbcContext *ctx,
331 const struct wbcDomainSid *sids, int num_sids,
332 struct wbcDomainInfo **pdomains, int *pnum_domains,
333 struct wbcTranslatedName **pnames)
335 struct winbindd_request request;
336 struct winbindd_response response;
337 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
338 int buflen, i, extra_len, num_domains, num_names;
339 char *sidlist, *p, *q, *extra_data;
340 struct wbcDomainInfo *domains = NULL;
341 struct wbcTranslatedName *names = NULL;
342 int error = 0;
344 buflen = num_sids * (WBC_SID_STRING_BUFLEN + 1) + 1;
346 sidlist = (char *)malloc(buflen);
347 if (sidlist == NULL) {
348 return WBC_ERR_NO_MEMORY;
351 p = sidlist;
353 for (i=0; i<num_sids; i++) {
354 int remaining;
355 int len;
357 remaining = buflen - (p - sidlist);
359 len = wbcSidToStringBuf(&sids[i], p, remaining);
360 if (len > remaining) {
361 free(sidlist);
362 return WBC_ERR_UNKNOWN_FAILURE;
365 p += len;
366 *p++ = '\n';
368 *p++ = '\0';
370 ZERO_STRUCT(request);
371 ZERO_STRUCT(response);
373 request.extra_data.data = sidlist;
374 request.extra_len = p - sidlist;
376 wbc_status = wbcRequestResponse(ctx, WINBINDD_LOOKUPSIDS,
377 &request, &response);
378 free(sidlist);
379 if (!WBC_ERROR_IS_OK(wbc_status)) {
380 return wbc_status;
383 extra_len = response.length - sizeof(struct winbindd_response);
384 extra_data = (char *)response.extra_data.data;
386 if ((extra_len <= 0) || (extra_data[extra_len-1] != '\0')) {
387 goto wbc_err_invalid;
390 p = extra_data;
392 num_domains = strtoul_err(p, &q, 10, &error);
393 if (*q != '\n' || error != 0) {
394 goto wbc_err_invalid;
396 p = q+1;
398 domains = (struct wbcDomainInfo *)wbcAllocateMemory(
399 num_domains+1, sizeof(struct wbcDomainInfo),
400 wbcDomainInfosDestructor);
401 if (domains == NULL) {
402 wbc_status = WBC_ERR_NO_MEMORY;
403 goto fail;
406 for (i=0; i<num_domains; i++) {
408 q = strchr(p, ' ');
409 if (q == NULL) {
410 goto wbc_err_invalid;
412 *q = '\0';
413 wbc_status = wbcStringToSid(p, &domains[i].sid);
414 if (!WBC_ERROR_IS_OK(wbc_status)) {
415 goto fail;
417 p = q+1;
419 q = strchr(p, '\n');
420 if (q == NULL) {
421 goto wbc_err_invalid;
423 *q = '\0';
424 domains[i].short_name = wbcStrDup(p);
425 if (domains[i].short_name == NULL) {
426 wbc_status = WBC_ERR_NO_MEMORY;
427 goto fail;
429 p = q+1;
432 num_names = strtoul_err(p, &q, 10, &error);
433 if (*q != '\n' || error != 0) {
434 goto wbc_err_invalid;
436 p = q+1;
438 if (num_names != num_sids) {
439 goto wbc_err_invalid;
442 names = (struct wbcTranslatedName *)wbcAllocateMemory(
443 num_names+1, sizeof(struct wbcTranslatedName),
444 wbcTranslatedNamesDestructor);
445 if (names == NULL) {
446 wbc_status = WBC_ERR_NO_MEMORY;
447 goto fail;
450 for (i=0; i<num_names; i++) {
452 names[i].domain_index = strtoul_err(p, &q, 10, &error);
453 if (names[i].domain_index < 0 || error != 0) {
454 goto wbc_err_invalid;
456 if (names[i].domain_index >= num_domains) {
457 goto wbc_err_invalid;
460 if (*q != ' ') {
461 goto wbc_err_invalid;
463 p = q+1;
465 names[i].type = strtoul_err(p, &q, 10, &error);
466 if (*q != ' ' || error != 0) {
467 goto wbc_err_invalid;
469 p = q+1;
471 q = strchr(p, '\n');
472 if (q == NULL) {
473 goto wbc_err_invalid;
475 *q = '\0';
476 names[i].name = wbcStrDup(p);
477 if (names[i].name == NULL) {
478 wbc_status = WBC_ERR_NO_MEMORY;
479 goto fail;
481 p = q+1;
483 if (*p != '\0') {
484 goto wbc_err_invalid;
487 *pdomains = domains;
488 *pnames = names;
489 winbindd_free_response(&response);
490 return WBC_ERR_SUCCESS;
492 wbc_err_invalid:
493 wbc_status = WBC_ERR_INVALID_RESPONSE;
494 fail:
495 winbindd_free_response(&response);
496 wbcFreeMemory(domains);
497 wbcFreeMemory(names);
498 return wbc_status;
501 wbcErr wbcLookupSids(const struct wbcDomainSid *sids, int num_sids,
502 struct wbcDomainInfo **pdomains, int *pnum_domains,
503 struct wbcTranslatedName **pnames)
505 return wbcCtxLookupSids(NULL, sids, num_sids, pdomains,
506 pnum_domains, pnames);
509 /* Translate a collection of RIDs within a domain to names */
511 wbcErr wbcCtxLookupRids(struct wbcContext *ctx, struct wbcDomainSid *dom_sid,
512 int num_rids,
513 uint32_t *rids,
514 const char **pp_domain_name,
515 const char ***pnames,
516 enum wbcSidType **ptypes)
518 size_t i, len, ridbuf_size;
519 char *ridlist;
520 char *p;
521 int error = 0;
522 struct winbindd_request request;
523 struct winbindd_response response;
524 char *domain_name = NULL;
525 const char **names = NULL;
526 enum wbcSidType *types = NULL;
527 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
529 /* Initialise request */
531 ZERO_STRUCT(request);
532 ZERO_STRUCT(response);
534 if (!dom_sid || (num_rids == 0)) {
535 wbc_status = WBC_ERR_INVALID_PARAM;
536 BAIL_ON_WBC_ERROR(wbc_status);
539 wbcSidToStringBuf(dom_sid, request.data.sid, sizeof(request.data.sid));
541 /* Even if all the Rids were of maximum 32bit values,
542 we would only have 11 bytes per rid in the final array
543 ("4294967296" + \n). Add one more byte for the
544 terminating '\0' */
546 ridbuf_size = (sizeof(char)*11) * num_rids + 1;
548 ridlist = (char *)malloc(ridbuf_size);
549 BAIL_ON_PTR_ERROR(ridlist, wbc_status);
551 len = 0;
552 for (i=0; i<num_rids; i++) {
553 len += snprintf(ridlist + len, ridbuf_size - len, "%u\n",
554 rids[i]);
556 ridlist[len] = '\0';
557 len += 1;
559 request.extra_data.data = ridlist;
560 request.extra_len = len;
562 wbc_status = wbcRequestResponse(ctx, WINBINDD_LOOKUPRIDS,
563 &request,
564 &response);
565 free(ridlist);
566 BAIL_ON_WBC_ERROR(wbc_status);
568 domain_name = wbcStrDup(response.data.domain_name);
569 BAIL_ON_PTR_ERROR(domain_name, wbc_status);
571 names = wbcAllocateStringArray(num_rids);
572 BAIL_ON_PTR_ERROR(names, wbc_status);
574 types = (enum wbcSidType *)wbcAllocateMemory(
575 num_rids, sizeof(enum wbcSidType), NULL);
576 BAIL_ON_PTR_ERROR(types, wbc_status);
578 p = (char *)response.extra_data.data;
580 for (i=0; i<num_rids; i++) {
581 char *q;
583 if (*p == '\0') {
584 wbc_status = WBC_ERR_INVALID_RESPONSE;
585 goto done;
588 types[i] = (enum wbcSidType)strtoul_err(p, &q, 10, &error);
590 if (*q != ' ' || error != 0) {
591 wbc_status = WBC_ERR_INVALID_RESPONSE;
592 goto done;
595 p = q+1;
597 if ((q = strchr(p, '\n')) == NULL) {
598 wbc_status = WBC_ERR_INVALID_RESPONSE;
599 goto done;
602 *q = '\0';
604 names[i] = strdup(p);
605 BAIL_ON_PTR_ERROR(names[i], wbc_status);
607 p = q+1;
610 if (*p != '\0') {
611 wbc_status = WBC_ERR_INVALID_RESPONSE;
612 goto done;
615 wbc_status = WBC_ERR_SUCCESS;
617 done:
618 winbindd_free_response(&response);
620 if (WBC_ERROR_IS_OK(wbc_status)) {
621 *pp_domain_name = domain_name;
622 *pnames = names;
623 *ptypes = types;
625 else {
626 wbcFreeMemory(domain_name);
627 wbcFreeMemory(names);
628 wbcFreeMemory(types);
631 return wbc_status;
634 wbcErr wbcLookupRids(struct wbcDomainSid *dom_sid,
635 int num_rids,
636 uint32_t *rids,
637 const char **pp_domain_name,
638 const char ***pnames,
639 enum wbcSidType **ptypes)
641 return wbcCtxLookupRids(NULL, dom_sid, num_rids, rids,
642 pp_domain_name, pnames, ptypes);
645 /* Get the groups a user belongs to */
646 wbcErr wbcCtxLookupUserSids(struct wbcContext *ctx,
647 const struct wbcDomainSid *user_sid,
648 bool domain_groups_only,
649 uint32_t *num_sids,
650 struct wbcDomainSid **_sids)
652 uint32_t i;
653 const char *s;
654 struct winbindd_request request;
655 struct winbindd_response response;
656 struct wbcDomainSid *sids = NULL;
657 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
658 int cmd;
660 /* Initialise request */
662 ZERO_STRUCT(request);
663 ZERO_STRUCT(response);
665 if (!user_sid) {
666 wbc_status = WBC_ERR_INVALID_PARAM;
667 BAIL_ON_WBC_ERROR(wbc_status);
670 wbcSidToStringBuf(user_sid, request.data.sid, sizeof(request.data.sid));
672 if (domain_groups_only) {
673 cmd = WINBINDD_GETUSERDOMGROUPS;
674 } else {
675 cmd = WINBINDD_GETUSERSIDS;
678 wbc_status = wbcRequestResponse(ctx, cmd,
679 &request,
680 &response);
681 BAIL_ON_WBC_ERROR(wbc_status);
683 if (response.data.num_entries &&
684 !response.extra_data.data) {
685 wbc_status = WBC_ERR_INVALID_RESPONSE;
686 BAIL_ON_WBC_ERROR(wbc_status);
689 sids = (struct wbcDomainSid *)wbcAllocateMemory(
690 response.data.num_entries, sizeof(struct wbcDomainSid),
691 NULL);
692 BAIL_ON_PTR_ERROR(sids, wbc_status);
694 s = (const char *)response.extra_data.data;
695 for (i = 0; i < response.data.num_entries; i++) {
696 char *n = strchr(s, '\n');
697 if (n) {
698 *n = '\0';
700 wbc_status = wbcStringToSid(s, &sids[i]);
701 BAIL_ON_WBC_ERROR(wbc_status);
702 s += strlen(s) + 1;
705 *num_sids = response.data.num_entries;
706 *_sids = sids;
707 sids = NULL;
708 wbc_status = WBC_ERR_SUCCESS;
710 done:
711 winbindd_free_response(&response);
712 if (sids) {
713 wbcFreeMemory(sids);
716 return wbc_status;
719 wbcErr wbcLookupUserSids(const struct wbcDomainSid *user_sid,
720 bool domain_groups_only,
721 uint32_t *num_sids,
722 struct wbcDomainSid **_sids)
724 return wbcCtxLookupUserSids(NULL, user_sid, domain_groups_only,
725 num_sids, _sids);
728 static inline
729 wbcErr _sid_to_rid(struct wbcDomainSid *sid, uint32_t *rid)
731 if (sid->num_auths < 1) {
732 return WBC_ERR_INVALID_RESPONSE;
734 *rid = sid->sub_auths[sid->num_auths - 1];
736 return WBC_ERR_SUCCESS;
739 /* Get alias membership for sids */
740 wbcErr wbcCtxGetSidAliases(struct wbcContext *ctx,
741 const struct wbcDomainSid *dom_sid,
742 struct wbcDomainSid *sids,
743 uint32_t num_sids,
744 uint32_t **alias_rids,
745 uint32_t *num_alias_rids)
747 uint32_t i;
748 const char *s;
749 struct winbindd_request request;
750 struct winbindd_response response;
751 ssize_t extra_data_len = 0;
752 char * extra_data = NULL;
753 ssize_t buflen = 0;
754 struct wbcDomainSid sid;
755 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
756 uint32_t * rids = NULL;
758 /* Initialise request */
760 ZERO_STRUCT(request);
761 ZERO_STRUCT(response);
763 if (!dom_sid) {
764 wbc_status = WBC_ERR_INVALID_PARAM;
765 goto done;
768 wbcSidToStringBuf(dom_sid, request.data.sid, sizeof(request.data.sid));
770 /* Lets assume each sid is around 57 characters
771 * S-1-5-21-AAAAAAAAAAA-BBBBBBBBBBB-CCCCCCCCCCC-DDDDDDDDDDD\n */
772 buflen = 57 * num_sids;
773 extra_data = (char *)malloc(buflen);
774 if (!extra_data) {
775 wbc_status = WBC_ERR_NO_MEMORY;
776 goto done;
779 /* Build the sid list */
780 for (i=0; i<num_sids; i++) {
781 char sid_str[WBC_SID_STRING_BUFLEN];
782 size_t sid_len;
784 sid_len = wbcSidToStringBuf(&sids[i], sid_str, sizeof(sid_str));
786 if (buflen < extra_data_len + sid_len + 2) {
787 buflen *= 2;
788 extra_data = (char *)realloc(extra_data, buflen);
789 if (!extra_data) {
790 wbc_status = WBC_ERR_NO_MEMORY;
791 BAIL_ON_WBC_ERROR(wbc_status);
795 strncpy(&extra_data[extra_data_len], sid_str,
796 buflen - extra_data_len);
797 extra_data_len += sid_len;
798 extra_data[extra_data_len++] = '\n';
799 extra_data[extra_data_len] = '\0';
801 extra_data_len += 1;
803 request.extra_data.data = extra_data;
804 request.extra_len = extra_data_len;
806 wbc_status = wbcRequestResponse(ctx, WINBINDD_GETSIDALIASES,
807 &request,
808 &response);
809 BAIL_ON_WBC_ERROR(wbc_status);
811 if (response.data.num_entries &&
812 !response.extra_data.data) {
813 wbc_status = WBC_ERR_INVALID_RESPONSE;
814 goto done;
817 rids = (uint32_t *)wbcAllocateMemory(response.data.num_entries,
818 sizeof(uint32_t), NULL);
819 BAIL_ON_PTR_ERROR(rids, wbc_status);
821 s = (const char *)response.extra_data.data;
822 for (i = 0; i < response.data.num_entries; i++) {
823 char *n = strchr(s, '\n');
824 if (n) {
825 *n = '\0';
827 wbc_status = wbcStringToSid(s, &sid);
828 BAIL_ON_WBC_ERROR(wbc_status);
829 wbc_status = _sid_to_rid(&sid, &rids[i]);
830 BAIL_ON_WBC_ERROR(wbc_status);
831 s += strlen(s) + 1;
834 *num_alias_rids = response.data.num_entries;
835 *alias_rids = rids;
836 rids = NULL;
837 wbc_status = WBC_ERR_SUCCESS;
839 done:
840 free(extra_data);
841 winbindd_free_response(&response);
842 wbcFreeMemory(rids);
843 return wbc_status;
846 wbcErr wbcGetSidAliases(const struct wbcDomainSid *dom_sid,
847 struct wbcDomainSid *sids,
848 uint32_t num_sids,
849 uint32_t **alias_rids,
850 uint32_t *num_alias_rids)
852 return wbcCtxGetSidAliases(NULL, dom_sid, sids, num_sids,
853 alias_rids, num_alias_rids);
857 /* Lists Users */
858 wbcErr wbcCtxListUsers(struct wbcContext *ctx,
859 const char *domain_name,
860 uint32_t *_num_users,
861 const char ***_users)
863 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
864 struct winbindd_request request;
865 struct winbindd_response response;
866 uint32_t num_users = 0;
867 const char **users = NULL;
868 const char *next;
870 /* Initialise request */
872 ZERO_STRUCT(request);
873 ZERO_STRUCT(response);
875 if (domain_name) {
876 strncpy(request.domain_name, domain_name,
877 sizeof(request.domain_name)-1);
880 wbc_status = wbcRequestResponse(ctx, WINBINDD_LIST_USERS,
881 &request,
882 &response);
883 BAIL_ON_WBC_ERROR(wbc_status);
885 users = wbcAllocateStringArray(response.data.num_entries);
886 if (users == NULL) {
887 return WBC_ERR_NO_MEMORY;
890 /* Look through extra data */
892 next = (const char *)response.extra_data.data;
893 while (next) {
894 const char *current;
895 char *k;
897 if (num_users >= response.data.num_entries) {
898 wbc_status = WBC_ERR_INVALID_RESPONSE;
899 goto done;
902 current = next;
903 k = strchr(next, ',');
905 if (k) {
906 k[0] = '\0';
907 next = k+1;
908 } else {
909 next = NULL;
912 users[num_users] = strdup(current);
913 BAIL_ON_PTR_ERROR(users[num_users], wbc_status);
914 num_users += 1;
916 if (num_users != response.data.num_entries) {
917 wbc_status = WBC_ERR_INVALID_RESPONSE;
918 goto done;
921 *_num_users = response.data.num_entries;
922 *_users = users;
923 users = NULL;
924 wbc_status = WBC_ERR_SUCCESS;
926 done:
927 winbindd_free_response(&response);
928 wbcFreeMemory(users);
929 return wbc_status;
932 wbcErr wbcListUsers(const char *domain_name,
933 uint32_t *_num_users,
934 const char ***_users)
936 return wbcCtxListUsers(NULL, domain_name, _num_users, _users);
939 /* Lists Groups */
940 wbcErr wbcCtxListGroups(struct wbcContext *ctx,
941 const char *domain_name,
942 uint32_t *_num_groups,
943 const char ***_groups)
945 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
946 struct winbindd_request request;
947 struct winbindd_response response;
948 uint32_t num_groups = 0;
949 const char **groups = NULL;
950 const char *next;
952 /* Initialise request */
954 ZERO_STRUCT(request);
955 ZERO_STRUCT(response);
957 if (domain_name) {
958 strncpy(request.domain_name, domain_name,
959 sizeof(request.domain_name)-1);
962 wbc_status = wbcRequestResponse(ctx, WINBINDD_LIST_GROUPS,
963 &request,
964 &response);
965 BAIL_ON_WBC_ERROR(wbc_status);
967 groups = wbcAllocateStringArray(response.data.num_entries);
968 if (groups == NULL) {
969 return WBC_ERR_NO_MEMORY;
972 /* Look through extra data */
974 next = (const char *)response.extra_data.data;
975 while (next) {
976 const char *current;
977 char *k;
979 if (num_groups >= response.data.num_entries) {
980 wbc_status = WBC_ERR_INVALID_RESPONSE;
981 goto done;
984 current = next;
985 k = strchr(next, ',');
987 if (k) {
988 k[0] = '\0';
989 next = k+1;
990 } else {
991 next = NULL;
994 groups[num_groups] = strdup(current);
995 BAIL_ON_PTR_ERROR(groups[num_groups], wbc_status);
996 num_groups += 1;
998 if (num_groups != response.data.num_entries) {
999 wbc_status = WBC_ERR_INVALID_RESPONSE;
1000 goto done;
1003 *_num_groups = response.data.num_entries;
1004 *_groups = groups;
1005 groups = NULL;
1006 wbc_status = WBC_ERR_SUCCESS;
1008 done:
1009 winbindd_free_response(&response);
1010 wbcFreeMemory(groups);
1011 return wbc_status;
1014 wbcErr wbcListGroups(const char *domain_name,
1015 uint32_t *_num_groups,
1016 const char ***_groups)
1018 return wbcCtxListGroups(NULL, domain_name, _num_groups, _groups);
1021 wbcErr wbcCtxGetDisplayName(struct wbcContext *ctx,
1022 const struct wbcDomainSid *sid,
1023 char **pdomain,
1024 char **pfullname,
1025 enum wbcSidType *pname_type)
1027 wbcErr wbc_status;
1028 char *domain = NULL;
1029 char *name = NULL;
1030 enum wbcSidType name_type;
1032 wbc_status = wbcCtxLookupSid(ctx, sid, &domain, &name, &name_type);
1033 BAIL_ON_WBC_ERROR(wbc_status);
1035 if (name_type == WBC_SID_NAME_USER) {
1036 uid_t uid;
1037 struct passwd *pwd;
1039 wbc_status = wbcCtxSidToUid(ctx, sid, &uid);
1040 BAIL_ON_WBC_ERROR(wbc_status);
1042 wbc_status = wbcCtxGetpwuid(ctx, uid, &pwd);
1043 BAIL_ON_WBC_ERROR(wbc_status);
1045 wbcFreeMemory(name);
1047 name = wbcStrDup(pwd->pw_gecos);
1048 wbcFreeMemory(pwd);
1049 BAIL_ON_PTR_ERROR(name, wbc_status);
1052 wbc_status = WBC_ERR_SUCCESS;
1054 done:
1055 if (WBC_ERROR_IS_OK(wbc_status)) {
1056 *pdomain = domain;
1057 *pfullname = name;
1058 *pname_type = name_type;
1059 } else {
1060 wbcFreeMemory(domain);
1061 wbcFreeMemory(name);
1064 return wbc_status;
1067 wbcErr wbcGetDisplayName(const struct wbcDomainSid *sid,
1068 char **pdomain,
1069 char **pfullname,
1070 enum wbcSidType *pname_type)
1072 return wbcCtxGetDisplayName(NULL, sid, pdomain, pfullname, pname_type);
1075 const char* wbcSidTypeString(enum wbcSidType type)
1077 switch (type) {
1078 case WBC_SID_NAME_USE_NONE: return "SID_NONE";
1079 case WBC_SID_NAME_USER: return "SID_USER";
1080 case WBC_SID_NAME_DOM_GRP: return "SID_DOM_GROUP";
1081 case WBC_SID_NAME_DOMAIN: return "SID_DOMAIN";
1082 case WBC_SID_NAME_ALIAS: return "SID_ALIAS";
1083 case WBC_SID_NAME_WKN_GRP: return "SID_WKN_GROUP";
1084 case WBC_SID_NAME_DELETED: return "SID_DELETED";
1085 case WBC_SID_NAME_INVALID: return "SID_INVALID";
1086 case WBC_SID_NAME_UNKNOWN: return "SID_UNKNOWN";
1087 case WBC_SID_NAME_COMPUTER: return "SID_COMPUTER";
1088 case WBC_SID_NAME_LABEL: return "SID_LABEL";
1089 default: return "Unknown type";