2 Unix SMB/CIFS implementation.
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 */
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)
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);
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]);
67 /* Convert a binary SID to a character string */
68 wbcErr wbcSidToString(const struct wbcDomainSid *sid,
71 char buf[WBC_SID_STRING_BUFLEN];
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);
87 return WBC_ERR_NO_MEMORY;
89 memcpy(result, buf, len+1);
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)
105 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
108 wbc_status = WBC_ERR_INVALID_PARAM;
109 BAIL_ON_WBC_ERROR(wbc_status);
112 /* Sanity check for either "S-" or "s-" */
115 || (str[0]!='S' && str[0]!='s')
118 wbc_status = WBC_ERR_INVALID_PARAM;
119 BAIL_ON_WBC_ERROR(wbc_status);
122 /* Get the SID revision number */
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.
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 */
153 while (sid->num_auths < WBC_MAXSUBAUTHS) {
154 x = strtoull_err(p, &q, 10, &error);
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;
169 /* IF we ended early, then the SID could not be converted */
172 wbc_status = WBC_ERR_INVALID_SID;
173 BAIL_ON_WBC_ERROR(wbc_status);
176 wbc_status = WBC_ERR_SUCCESS;
184 /* Convert a domain and name to SID */
185 wbcErr wbcCtxLookupName(struct wbcContext *ctx,
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,
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;
228 wbcErr wbcLookupName(const char *domain,
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,
242 enum wbcSidType *pname_type)
244 struct winbindd_request request;
245 struct winbindd_response response;
246 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
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));
262 wbc_status = wbcRequestResponse(ctx, WINBINDD_LOOKUPSID,
265 if (!WBC_ERROR_IS_OK(wbc_status)) {
269 /* Copy out result */
271 wbc_status = WBC_ERR_NO_MEMORY;
275 domain = wbcStrDup(response.data.name.dom_name);
276 if (domain == NULL) {
279 name = wbcStrDup(response.data.name.name);
283 if (pdomain != NULL) {
291 if (pname_type != NULL) {
292 *pname_type = (enum wbcSidType)response.data.name.type;
294 wbc_status = WBC_ERR_SUCCESS;
297 wbcFreeMemory(domain);
301 wbcErr wbcLookupSid(const struct wbcDomainSid *sid,
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);
320 static void wbcTranslatedNamesDestructor(void *ptr)
322 struct wbcTranslatedName *n = (struct wbcTranslatedName *)ptr;
324 while (n->name != NULL) {
325 wbcFreeMemory(n->name);
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;
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;
353 for (i=0; i<num_sids; i++) {
357 remaining = buflen - (p - sidlist);
359 len = wbcSidToStringBuf(&sids[i], p, remaining);
360 if (len > remaining) {
362 return WBC_ERR_UNKNOWN_FAILURE;
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);
379 if (!WBC_ERROR_IS_OK(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;
392 num_domains = strtoul_err(p, &q, 10, &error);
393 if (*q != '\n' || error != 0) {
394 goto wbc_err_invalid;
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;
406 for (i=0; i<num_domains; i++) {
410 goto wbc_err_invalid;
413 wbc_status = wbcStringToSid(p, &domains[i].sid);
414 if (!WBC_ERROR_IS_OK(wbc_status)) {
421 goto wbc_err_invalid;
424 domains[i].short_name = wbcStrDup(p);
425 if (domains[i].short_name == NULL) {
426 wbc_status = WBC_ERR_NO_MEMORY;
432 num_names = strtoul_err(p, &q, 10, &error);
433 if (*q != '\n' || error != 0) {
434 goto wbc_err_invalid;
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);
446 wbc_status = WBC_ERR_NO_MEMORY;
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;
461 goto wbc_err_invalid;
465 names[i].type = strtoul_err(p, &q, 10, &error);
466 if (*q != ' ' || error != 0) {
467 goto wbc_err_invalid;
473 goto wbc_err_invalid;
476 names[i].name = wbcStrDup(p);
477 if (names[i].name == NULL) {
478 wbc_status = WBC_ERR_NO_MEMORY;
484 goto wbc_err_invalid;
489 winbindd_free_response(&response);
490 return WBC_ERR_SUCCESS;
493 wbc_status = WBC_ERR_INVALID_RESPONSE;
495 winbindd_free_response(&response);
496 wbcFreeMemory(domains);
497 wbcFreeMemory(names);
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,
514 const char **pp_domain_name,
515 const char ***pnames,
516 enum wbcSidType **ptypes)
518 size_t i, len, ridbuf_size;
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
546 ridbuf_size = (sizeof(char)*11) * num_rids + 1;
548 ridlist = (char *)malloc(ridbuf_size);
549 BAIL_ON_PTR_ERROR(ridlist, wbc_status);
552 for (i=0; i<num_rids; i++) {
553 len += snprintf(ridlist + len, ridbuf_size - len, "%u\n",
559 request.extra_data.data = ridlist;
560 request.extra_len = len;
562 wbc_status = wbcRequestResponse(ctx, WINBINDD_LOOKUPRIDS,
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++) {
584 wbc_status = WBC_ERR_INVALID_RESPONSE;
588 types[i] = (enum wbcSidType)strtoul_err(p, &q, 10, &error);
590 if (*q != ' ' || error != 0) {
591 wbc_status = WBC_ERR_INVALID_RESPONSE;
597 if ((q = strchr(p, '\n')) == NULL) {
598 wbc_status = WBC_ERR_INVALID_RESPONSE;
604 names[i] = strdup(p);
605 BAIL_ON_PTR_ERROR(names[i], wbc_status);
611 wbc_status = WBC_ERR_INVALID_RESPONSE;
615 wbc_status = WBC_ERR_SUCCESS;
618 winbindd_free_response(&response);
620 if (WBC_ERROR_IS_OK(wbc_status)) {
621 *pp_domain_name = domain_name;
626 wbcFreeMemory(domain_name);
627 wbcFreeMemory(names);
628 wbcFreeMemory(types);
634 wbcErr wbcLookupRids(struct wbcDomainSid *dom_sid,
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,
650 struct wbcDomainSid **_sids)
654 struct winbindd_request request;
655 struct winbindd_response response;
656 struct wbcDomainSid *sids = NULL;
657 wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
660 /* Initialise request */
662 ZERO_STRUCT(request);
663 ZERO_STRUCT(response);
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;
675 cmd = WINBINDD_GETUSERSIDS;
678 wbc_status = wbcRequestResponse(ctx, cmd,
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),
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');
700 wbc_status = wbcStringToSid(s, &sids[i]);
701 BAIL_ON_WBC_ERROR(wbc_status);
705 *num_sids = response.data.num_entries;
708 wbc_status = WBC_ERR_SUCCESS;
711 winbindd_free_response(&response);
719 wbcErr wbcLookupUserSids(const struct wbcDomainSid *user_sid,
720 bool domain_groups_only,
722 struct wbcDomainSid **_sids)
724 return wbcCtxLookupUserSids(NULL, user_sid, domain_groups_only,
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,
744 uint32_t **alias_rids,
745 uint32_t *num_alias_rids)
749 struct winbindd_request request;
750 struct winbindd_response response;
751 ssize_t extra_data_len = 0;
752 char * extra_data = NULL;
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);
764 wbc_status = WBC_ERR_INVALID_PARAM;
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);
775 wbc_status = WBC_ERR_NO_MEMORY;
779 /* Build the sid list */
780 for (i=0; i<num_sids; i++) {
781 char sid_str[WBC_SID_STRING_BUFLEN];
784 sid_len = wbcSidToStringBuf(&sids[i], sid_str, sizeof(sid_str));
786 if (buflen < extra_data_len + sid_len + 2) {
788 extra_data = (char *)realloc(extra_data, buflen);
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';
803 request.extra_data.data = extra_data;
804 request.extra_len = extra_data_len;
806 wbc_status = wbcRequestResponse(ctx, WINBINDD_GETSIDALIASES,
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;
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');
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);
834 *num_alias_rids = response.data.num_entries;
837 wbc_status = WBC_ERR_SUCCESS;
841 winbindd_free_response(&response);
846 wbcErr wbcGetSidAliases(const struct wbcDomainSid *dom_sid,
847 struct wbcDomainSid *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);
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;
870 /* Initialise request */
872 ZERO_STRUCT(request);
873 ZERO_STRUCT(response);
876 strncpy(request.domain_name, domain_name,
877 sizeof(request.domain_name)-1);
880 wbc_status = wbcRequestResponse(ctx, WINBINDD_LIST_USERS,
883 BAIL_ON_WBC_ERROR(wbc_status);
885 users = wbcAllocateStringArray(response.data.num_entries);
887 return WBC_ERR_NO_MEMORY;
890 /* Look through extra data */
892 next = (const char *)response.extra_data.data;
897 if (num_users >= response.data.num_entries) {
898 wbc_status = WBC_ERR_INVALID_RESPONSE;
903 k = strchr(next, ',');
912 users[num_users] = strdup(current);
913 BAIL_ON_PTR_ERROR(users[num_users], wbc_status);
916 if (num_users != response.data.num_entries) {
917 wbc_status = WBC_ERR_INVALID_RESPONSE;
921 *_num_users = response.data.num_entries;
924 wbc_status = WBC_ERR_SUCCESS;
927 winbindd_free_response(&response);
928 wbcFreeMemory(users);
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);
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;
952 /* Initialise request */
954 ZERO_STRUCT(request);
955 ZERO_STRUCT(response);
958 strncpy(request.domain_name, domain_name,
959 sizeof(request.domain_name)-1);
962 wbc_status = wbcRequestResponse(ctx, WINBINDD_LIST_GROUPS,
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;
979 if (num_groups >= response.data.num_entries) {
980 wbc_status = WBC_ERR_INVALID_RESPONSE;
985 k = strchr(next, ',');
994 groups[num_groups] = strdup(current);
995 BAIL_ON_PTR_ERROR(groups[num_groups], wbc_status);
998 if (num_groups != response.data.num_entries) {
999 wbc_status = WBC_ERR_INVALID_RESPONSE;
1003 *_num_groups = response.data.num_entries;
1006 wbc_status = WBC_ERR_SUCCESS;
1009 winbindd_free_response(&response);
1010 wbcFreeMemory(groups);
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,
1025 enum wbcSidType *pname_type)
1028 char *domain = 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) {
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);
1049 BAIL_ON_PTR_ERROR(name, wbc_status);
1052 wbc_status = WBC_ERR_SUCCESS;
1055 if (WBC_ERROR_IS_OK(wbc_status)) {
1058 *pname_type = name_type;
1060 wbcFreeMemory(domain);
1061 wbcFreeMemory(name);
1067 wbcErr wbcGetDisplayName(const struct wbcDomainSid *sid,
1070 enum wbcSidType *pname_type)
1072 return wbcCtxGetDisplayName(NULL, sid, pdomain, pfullname, pname_type);
1075 const char* wbcSidTypeString(enum wbcSidType 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";