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"
30 /* Convert a sid to a string into a buffer. Return the string
31 * length. If buflen is too small, return the string length that would
32 * result if it was long enough. */
33 int wbcSidToStringBuf(const struct wbcDomainSid
*sid
, char *buf
, int buflen
)
39 strlcpy(buf
, "(NULL SID)", buflen
);
40 return 10; /* strlen("(NULL SID)") */
43 id_auth
= (uint64_t)sid
->id_auth
[5] +
44 ((uint64_t)sid
->id_auth
[4] << 8) +
45 ((uint64_t)sid
->id_auth
[3] << 16) +
46 ((uint64_t)sid
->id_auth
[2] << 24) +
47 ((uint64_t)sid
->id_auth
[1] << 32) +
48 ((uint64_t)sid
->id_auth
[0] << 40);
50 ofs
= snprintf(buf
, buflen
, "S-%hhu-", (unsigned char)sid
->sid_rev_num
);
51 if (id_auth
>= UINT32_MAX
) {
52 ofs
+= snprintf(buf
+ ofs
, MAX(buflen
- ofs
, 0), "0x%llx",
53 (unsigned long long)id_auth
);
55 ofs
+= snprintf(buf
+ ofs
, MAX(buflen
- ofs
, 0), "%llu",
56 (unsigned long long)id_auth
);
59 for (i
= 0; i
< sid
->num_auths
; i
++) {
60 ofs
+= snprintf(buf
+ ofs
, MAX(buflen
- ofs
, 0), "-%u",
61 (unsigned int)sid
->sub_auths
[i
]);
66 /* Convert a binary SID to a character string */
67 wbcErr
wbcSidToString(const struct wbcDomainSid
*sid
,
70 char buf
[WBC_SID_STRING_BUFLEN
];
75 return WBC_ERR_INVALID_SID
;
78 len
= wbcSidToStringBuf(sid
, buf
, sizeof(buf
));
80 if (len
+1 > sizeof(buf
)) {
81 return WBC_ERR_INVALID_SID
;
84 result
= (char *)wbcAllocateMemory(len
+1, 1, NULL
);
86 return WBC_ERR_NO_MEMORY
;
88 memcpy(result
, buf
, len
+1);
91 return WBC_ERR_SUCCESS
;
94 #define AUTHORITY_MASK (~(0xffffffffffffULL))
96 /* Convert a character string to a binary SID */
97 wbcErr
wbcStringToSid(const char *str
,
98 struct wbcDomainSid
*sid
)
103 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
106 wbc_status
= WBC_ERR_INVALID_PARAM
;
107 BAIL_ON_WBC_ERROR(wbc_status
);
110 /* Sanity check for either "S-" or "s-" */
113 || (str
[0]!='S' && str
[0]!='s')
116 wbc_status
= WBC_ERR_INVALID_PARAM
;
117 BAIL_ON_WBC_ERROR(wbc_status
);
120 /* Get the SID revision number */
123 x
= (uint64_t)strtoul(p
, &q
, 10);
124 if (x
==0 || x
> UINT8_MAX
|| !q
|| *q
!='-') {
125 wbc_status
= WBC_ERR_INVALID_SID
;
126 BAIL_ON_WBC_ERROR(wbc_status
);
128 sid
->sid_rev_num
= (uint8_t)x
;
131 * Next the Identifier Authority. This is stored big-endian in a
132 * 6 byte array. If the authority value is >= UINT_MAX, then it should
133 * be expressed as a hex value, according to MS-DTYP.
136 x
= strtoull(p
, &q
, 0);
137 if (!q
|| *q
!='-' || (x
& AUTHORITY_MASK
)) {
138 wbc_status
= WBC_ERR_INVALID_SID
;
139 BAIL_ON_WBC_ERROR(wbc_status
);
141 sid
->id_auth
[5] = (x
& 0x0000000000ffULL
);
142 sid
->id_auth
[4] = (x
& 0x00000000ff00ULL
) >> 8;
143 sid
->id_auth
[3] = (x
& 0x000000ff0000ULL
) >> 16;
144 sid
->id_auth
[2] = (x
& 0x0000ff000000ULL
) >> 24;
145 sid
->id_auth
[1] = (x
& 0x00ff00000000ULL
) >> 32;
146 sid
->id_auth
[0] = (x
& 0xff0000000000ULL
) >> 40;
148 /* now read the the subauthorities */
151 while (sid
->num_auths
< WBC_MAXSUBAUTHS
) {
152 x
= strtoull(p
, &q
, 10);
155 if (x
> UINT32_MAX
) {
156 wbc_status
= WBC_ERR_INVALID_SID
;
157 BAIL_ON_WBC_ERROR(wbc_status
);
159 sid
->sub_auths
[sid
->num_auths
++] = x
;
167 /* IF we ended early, then the SID could not be converted */
170 wbc_status
= WBC_ERR_INVALID_SID
;
171 BAIL_ON_WBC_ERROR(wbc_status
);
174 wbc_status
= WBC_ERR_SUCCESS
;
182 /* Convert a domain and name to SID */
183 wbcErr
wbcCtxLookupName(struct wbcContext
*ctx
,
186 struct wbcDomainSid
*sid
,
187 enum wbcSidType
*name_type
)
189 struct winbindd_request request
;
190 struct winbindd_response response
;
191 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
193 if (!sid
|| !name_type
) {
194 wbc_status
= WBC_ERR_INVALID_PARAM
;
195 BAIL_ON_WBC_ERROR(wbc_status
);
198 /* Initialize request */
200 ZERO_STRUCT(request
);
201 ZERO_STRUCT(response
);
203 /* dst is already null terminated from the memset above */
205 strncpy(request
.data
.name
.dom_name
, domain
,
206 sizeof(request
.data
.name
.dom_name
)-1);
207 strncpy(request
.data
.name
.name
, name
,
208 sizeof(request
.data
.name
.name
)-1);
210 wbc_status
= wbcRequestResponse(ctx
, WINBINDD_LOOKUPNAME
,
213 BAIL_ON_WBC_ERROR(wbc_status
);
215 wbc_status
= wbcStringToSid(response
.data
.sid
.sid
, sid
);
216 BAIL_ON_WBC_ERROR(wbc_status
);
218 *name_type
= (enum wbcSidType
)response
.data
.sid
.type
;
220 wbc_status
= WBC_ERR_SUCCESS
;
226 wbcErr
wbcLookupName(const char *domain
,
228 struct wbcDomainSid
*sid
,
229 enum wbcSidType
*name_type
)
231 return wbcCtxLookupName(NULL
, domain
, name
, sid
, name_type
);
235 /* Convert a SID to a domain and name */
236 wbcErr
wbcCtxLookupSid(struct wbcContext
*ctx
,
237 const struct wbcDomainSid
*sid
,
240 enum wbcSidType
*pname_type
)
242 struct winbindd_request request
;
243 struct winbindd_response response
;
244 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
248 return WBC_ERR_INVALID_PARAM
;
251 /* Initialize request */
253 ZERO_STRUCT(request
);
254 ZERO_STRUCT(response
);
256 wbcSidToStringBuf(sid
, request
.data
.sid
, sizeof(request
.data
.sid
));
260 wbc_status
= wbcRequestResponse(ctx
, WINBINDD_LOOKUPSID
,
263 if (!WBC_ERROR_IS_OK(wbc_status
)) {
267 /* Copy out result */
269 wbc_status
= WBC_ERR_NO_MEMORY
;
273 domain
= wbcStrDup(response
.data
.name
.dom_name
);
274 if (domain
== NULL
) {
277 name
= wbcStrDup(response
.data
.name
.name
);
281 if (pdomain
!= NULL
) {
289 if (pname_type
!= NULL
) {
290 *pname_type
= (enum wbcSidType
)response
.data
.name
.type
;
292 wbc_status
= WBC_ERR_SUCCESS
;
295 wbcFreeMemory(domain
);
299 wbcErr
wbcLookupSid(const struct wbcDomainSid
*sid
,
302 enum wbcSidType
*pname_type
)
304 return wbcCtxLookupSid(NULL
, sid
, pdomain
, pname
, pname_type
);
307 static void wbcDomainInfosDestructor(void *ptr
)
309 struct wbcDomainInfo
*i
= (struct wbcDomainInfo
*)ptr
;
311 while (i
->short_name
!= NULL
) {
312 wbcFreeMemory(i
->short_name
);
313 wbcFreeMemory(i
->dns_name
);
318 static void wbcTranslatedNamesDestructor(void *ptr
)
320 struct wbcTranslatedName
*n
= (struct wbcTranslatedName
*)ptr
;
322 while (n
->name
!= NULL
) {
323 wbcFreeMemory(n
->name
);
328 wbcErr
wbcCtxLookupSids(struct wbcContext
*ctx
,
329 const struct wbcDomainSid
*sids
, int num_sids
,
330 struct wbcDomainInfo
**pdomains
, int *pnum_domains
,
331 struct wbcTranslatedName
**pnames
)
333 struct winbindd_request request
;
334 struct winbindd_response response
;
335 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
336 int buflen
, i
, extra_len
, num_domains
, num_names
;
337 char *sidlist
, *p
, *q
, *extra_data
;
338 struct wbcDomainInfo
*domains
= NULL
;
339 struct wbcTranslatedName
*names
= NULL
;
341 buflen
= num_sids
* (WBC_SID_STRING_BUFLEN
+ 1) + 1;
343 sidlist
= (char *)malloc(buflen
);
344 if (sidlist
== NULL
) {
345 return WBC_ERR_NO_MEMORY
;
350 for (i
=0; i
<num_sids
; i
++) {
354 remaining
= buflen
- (p
- sidlist
);
356 len
= wbcSidToStringBuf(&sids
[i
], p
, remaining
);
357 if (len
> remaining
) {
359 return WBC_ERR_UNKNOWN_FAILURE
;
367 ZERO_STRUCT(request
);
368 ZERO_STRUCT(response
);
370 request
.extra_data
.data
= sidlist
;
371 request
.extra_len
= p
- sidlist
;
373 wbc_status
= wbcRequestResponse(ctx
, WINBINDD_LOOKUPSIDS
,
374 &request
, &response
);
376 if (!WBC_ERROR_IS_OK(wbc_status
)) {
380 extra_len
= response
.length
- sizeof(struct winbindd_response
);
381 extra_data
= (char *)response
.extra_data
.data
;
383 if ((extra_len
<= 0) || (extra_data
[extra_len
-1] != '\0')) {
384 goto wbc_err_invalid
;
389 num_domains
= strtoul(p
, &q
, 10);
391 goto wbc_err_invalid
;
395 domains
= (struct wbcDomainInfo
*)wbcAllocateMemory(
396 num_domains
+1, sizeof(struct wbcDomainInfo
),
397 wbcDomainInfosDestructor
);
398 if (domains
== NULL
) {
399 wbc_status
= WBC_ERR_NO_MEMORY
;
403 for (i
=0; i
<num_domains
; i
++) {
407 goto wbc_err_invalid
;
410 wbc_status
= wbcStringToSid(p
, &domains
[i
].sid
);
411 if (!WBC_ERROR_IS_OK(wbc_status
)) {
418 goto wbc_err_invalid
;
421 domains
[i
].short_name
= wbcStrDup(p
);
422 if (domains
[i
].short_name
== NULL
) {
423 wbc_status
= WBC_ERR_NO_MEMORY
;
429 num_names
= strtoul(p
, &q
, 10);
431 goto wbc_err_invalid
;
435 if (num_names
!= num_sids
) {
436 goto wbc_err_invalid
;
439 names
= (struct wbcTranslatedName
*)wbcAllocateMemory(
440 num_names
+1, sizeof(struct wbcTranslatedName
),
441 wbcTranslatedNamesDestructor
);
443 wbc_status
= WBC_ERR_NO_MEMORY
;
447 for (i
=0; i
<num_names
; i
++) {
449 names
[i
].domain_index
= strtoul(p
, &q
, 10);
450 if (names
[i
].domain_index
< 0) {
451 goto wbc_err_invalid
;
453 if (names
[i
].domain_index
>= num_domains
) {
454 goto wbc_err_invalid
;
458 goto wbc_err_invalid
;
462 names
[i
].type
= strtoul(p
, &q
, 10);
464 goto wbc_err_invalid
;
470 goto wbc_err_invalid
;
473 names
[i
].name
= wbcStrDup(p
);
474 if (names
[i
].name
== NULL
) {
475 wbc_status
= WBC_ERR_NO_MEMORY
;
481 goto wbc_err_invalid
;
486 winbindd_free_response(&response
);
487 return WBC_ERR_SUCCESS
;
490 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
492 winbindd_free_response(&response
);
493 wbcFreeMemory(domains
);
494 wbcFreeMemory(names
);
498 wbcErr
wbcLookupSids(const struct wbcDomainSid
*sids
, int num_sids
,
499 struct wbcDomainInfo
**pdomains
, int *pnum_domains
,
500 struct wbcTranslatedName
**pnames
)
502 return wbcCtxLookupSids(NULL
, sids
, num_sids
, pdomains
,
503 pnum_domains
, pnames
);
506 /* Translate a collection of RIDs within a domain to names */
508 wbcErr
wbcCtxLookupRids(struct wbcContext
*ctx
, struct wbcDomainSid
*dom_sid
,
511 const char **pp_domain_name
,
512 const char ***pnames
,
513 enum wbcSidType
**ptypes
)
515 size_t i
, len
, ridbuf_size
;
518 struct winbindd_request request
;
519 struct winbindd_response response
;
520 char *domain_name
= NULL
;
521 const char **names
= NULL
;
522 enum wbcSidType
*types
= NULL
;
523 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
525 /* Initialise request */
527 ZERO_STRUCT(request
);
528 ZERO_STRUCT(response
);
530 if (!dom_sid
|| (num_rids
== 0)) {
531 wbc_status
= WBC_ERR_INVALID_PARAM
;
532 BAIL_ON_WBC_ERROR(wbc_status
);
535 wbcSidToStringBuf(dom_sid
, request
.data
.sid
, sizeof(request
.data
.sid
));
537 /* Even if all the Rids were of maximum 32bit values,
538 we would only have 11 bytes per rid in the final array
539 ("4294967296" + \n). Add one more byte for the
542 ridbuf_size
= (sizeof(char)*11) * num_rids
+ 1;
544 ridlist
= (char *)malloc(ridbuf_size
);
545 BAIL_ON_PTR_ERROR(ridlist
, wbc_status
);
548 for (i
=0; i
<num_rids
; i
++) {
549 len
+= snprintf(ridlist
+ len
, ridbuf_size
- len
, "%u\n",
555 request
.extra_data
.data
= ridlist
;
556 request
.extra_len
= len
;
558 wbc_status
= wbcRequestResponse(ctx
, WINBINDD_LOOKUPRIDS
,
562 BAIL_ON_WBC_ERROR(wbc_status
);
564 domain_name
= wbcStrDup(response
.data
.domain_name
);
565 BAIL_ON_PTR_ERROR(domain_name
, wbc_status
);
567 names
= wbcAllocateStringArray(num_rids
);
568 BAIL_ON_PTR_ERROR(names
, wbc_status
);
570 types
= (enum wbcSidType
*)wbcAllocateMemory(
571 num_rids
, sizeof(enum wbcSidType
), NULL
);
572 BAIL_ON_PTR_ERROR(types
, wbc_status
);
574 p
= (char *)response
.extra_data
.data
;
576 for (i
=0; i
<num_rids
; i
++) {
580 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
584 types
[i
] = (enum wbcSidType
)strtoul(p
, &q
, 10);
587 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
593 if ((q
= strchr(p
, '\n')) == NULL
) {
594 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
600 names
[i
] = strdup(p
);
601 BAIL_ON_PTR_ERROR(names
[i
], wbc_status
);
607 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
611 wbc_status
= WBC_ERR_SUCCESS
;
614 winbindd_free_response(&response
);
616 if (WBC_ERROR_IS_OK(wbc_status
)) {
617 *pp_domain_name
= domain_name
;
622 wbcFreeMemory(domain_name
);
623 wbcFreeMemory(names
);
624 wbcFreeMemory(types
);
630 wbcErr
wbcLookupRids(struct wbcDomainSid
*dom_sid
,
633 const char **pp_domain_name
,
634 const char ***pnames
,
635 enum wbcSidType
**ptypes
)
637 return wbcCtxLookupRids(NULL
, dom_sid
, num_rids
, rids
,
638 pp_domain_name
, pnames
, ptypes
);
641 /* Get the groups a user belongs to */
642 wbcErr
wbcCtxLookupUserSids(struct wbcContext
*ctx
,
643 const struct wbcDomainSid
*user_sid
,
644 bool domain_groups_only
,
646 struct wbcDomainSid
**_sids
)
650 struct winbindd_request request
;
651 struct winbindd_response response
;
652 struct wbcDomainSid
*sids
= NULL
;
653 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
656 /* Initialise request */
658 ZERO_STRUCT(request
);
659 ZERO_STRUCT(response
);
662 wbc_status
= WBC_ERR_INVALID_PARAM
;
663 BAIL_ON_WBC_ERROR(wbc_status
);
666 wbcSidToStringBuf(user_sid
, request
.data
.sid
, sizeof(request
.data
.sid
));
668 if (domain_groups_only
) {
669 cmd
= WINBINDD_GETUSERDOMGROUPS
;
671 cmd
= WINBINDD_GETUSERSIDS
;
674 wbc_status
= wbcRequestResponse(ctx
, cmd
,
677 BAIL_ON_WBC_ERROR(wbc_status
);
679 if (response
.data
.num_entries
&&
680 !response
.extra_data
.data
) {
681 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
682 BAIL_ON_WBC_ERROR(wbc_status
);
685 sids
= (struct wbcDomainSid
*)wbcAllocateMemory(
686 response
.data
.num_entries
, sizeof(struct wbcDomainSid
),
688 BAIL_ON_PTR_ERROR(sids
, wbc_status
);
690 s
= (const char *)response
.extra_data
.data
;
691 for (i
= 0; i
< response
.data
.num_entries
; i
++) {
692 char *n
= strchr(s
, '\n');
696 wbc_status
= wbcStringToSid(s
, &sids
[i
]);
697 BAIL_ON_WBC_ERROR(wbc_status
);
701 *num_sids
= response
.data
.num_entries
;
704 wbc_status
= WBC_ERR_SUCCESS
;
707 winbindd_free_response(&response
);
715 wbcErr
wbcLookupUserSids(const struct wbcDomainSid
*user_sid
,
716 bool domain_groups_only
,
718 struct wbcDomainSid
**_sids
)
720 return wbcCtxLookupUserSids(NULL
, user_sid
, domain_groups_only
,
725 wbcErr
_sid_to_rid(struct wbcDomainSid
*sid
, uint32_t *rid
)
727 if (sid
->num_auths
< 1) {
728 return WBC_ERR_INVALID_RESPONSE
;
730 *rid
= sid
->sub_auths
[sid
->num_auths
- 1];
732 return WBC_ERR_SUCCESS
;
735 /* Get alias membership for sids */
736 wbcErr
wbcCtxGetSidAliases(struct wbcContext
*ctx
,
737 const struct wbcDomainSid
*dom_sid
,
738 struct wbcDomainSid
*sids
,
740 uint32_t **alias_rids
,
741 uint32_t *num_alias_rids
)
745 struct winbindd_request request
;
746 struct winbindd_response response
;
747 ssize_t extra_data_len
= 0;
748 char * extra_data
= NULL
;
750 struct wbcDomainSid sid
;
751 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
752 uint32_t * rids
= NULL
;
754 /* Initialise request */
756 ZERO_STRUCT(request
);
757 ZERO_STRUCT(response
);
760 wbc_status
= WBC_ERR_INVALID_PARAM
;
764 wbcSidToStringBuf(dom_sid
, request
.data
.sid
, sizeof(request
.data
.sid
));
766 /* Lets assume each sid is around 57 characters
767 * S-1-5-21-AAAAAAAAAAA-BBBBBBBBBBB-CCCCCCCCCCC-DDDDDDDDDDD\n */
768 buflen
= 57 * num_sids
;
769 extra_data
= (char *)malloc(buflen
);
771 wbc_status
= WBC_ERR_NO_MEMORY
;
775 /* Build the sid list */
776 for (i
=0; i
<num_sids
; i
++) {
777 char sid_str
[WBC_SID_STRING_BUFLEN
];
780 sid_len
= wbcSidToStringBuf(&sids
[i
], sid_str
, sizeof(sid_str
));
782 if (buflen
< extra_data_len
+ sid_len
+ 2) {
784 extra_data
= (char *)realloc(extra_data
, buflen
);
786 wbc_status
= WBC_ERR_NO_MEMORY
;
787 BAIL_ON_WBC_ERROR(wbc_status
);
791 strncpy(&extra_data
[extra_data_len
], sid_str
,
792 buflen
- extra_data_len
);
793 extra_data_len
+= sid_len
;
794 extra_data
[extra_data_len
++] = '\n';
795 extra_data
[extra_data_len
] = '\0';
799 request
.extra_data
.data
= extra_data
;
800 request
.extra_len
= extra_data_len
;
802 wbc_status
= wbcRequestResponse(ctx
, WINBINDD_GETSIDALIASES
,
805 BAIL_ON_WBC_ERROR(wbc_status
);
807 if (response
.data
.num_entries
&&
808 !response
.extra_data
.data
) {
809 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
813 rids
= (uint32_t *)wbcAllocateMemory(response
.data
.num_entries
,
814 sizeof(uint32_t), NULL
);
815 BAIL_ON_PTR_ERROR(sids
, wbc_status
);
817 s
= (const char *)response
.extra_data
.data
;
818 for (i
= 0; i
< response
.data
.num_entries
; i
++) {
819 char *n
= strchr(s
, '\n');
823 wbc_status
= wbcStringToSid(s
, &sid
);
824 BAIL_ON_WBC_ERROR(wbc_status
);
825 wbc_status
= _sid_to_rid(&sid
, &rids
[i
]);
826 BAIL_ON_WBC_ERROR(wbc_status
);
830 *num_alias_rids
= response
.data
.num_entries
;
833 wbc_status
= WBC_ERR_SUCCESS
;
837 winbindd_free_response(&response
);
842 wbcErr
wbcGetSidAliases(const struct wbcDomainSid
*dom_sid
,
843 struct wbcDomainSid
*sids
,
845 uint32_t **alias_rids
,
846 uint32_t *num_alias_rids
)
848 return wbcCtxGetSidAliases(NULL
, dom_sid
, sids
, num_sids
,
849 alias_rids
, num_alias_rids
);
854 wbcErr
wbcCtxListUsers(struct wbcContext
*ctx
,
855 const char *domain_name
,
856 uint32_t *_num_users
,
857 const char ***_users
)
859 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
860 struct winbindd_request request
;
861 struct winbindd_response response
;
862 uint32_t num_users
= 0;
863 const char **users
= NULL
;
866 /* Initialise request */
868 ZERO_STRUCT(request
);
869 ZERO_STRUCT(response
);
872 strncpy(request
.domain_name
, domain_name
,
873 sizeof(request
.domain_name
)-1);
876 wbc_status
= wbcRequestResponse(ctx
, WINBINDD_LIST_USERS
,
879 BAIL_ON_WBC_ERROR(wbc_status
);
881 users
= wbcAllocateStringArray(response
.data
.num_entries
);
883 return WBC_ERR_NO_MEMORY
;
886 /* Look through extra data */
888 next
= (const char *)response
.extra_data
.data
;
893 if (num_users
>= response
.data
.num_entries
) {
894 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
899 k
= strchr(next
, ',');
908 users
[num_users
] = strdup(current
);
909 BAIL_ON_PTR_ERROR(users
[num_users
], wbc_status
);
912 if (num_users
!= response
.data
.num_entries
) {
913 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
917 *_num_users
= response
.data
.num_entries
;
920 wbc_status
= WBC_ERR_SUCCESS
;
923 winbindd_free_response(&response
);
924 wbcFreeMemory(users
);
928 wbcErr
wbcListUsers(const char *domain_name
,
929 uint32_t *_num_users
,
930 const char ***_users
)
932 return wbcCtxListUsers(NULL
, domain_name
, _num_users
, _users
);
936 wbcErr
wbcCtxListGroups(struct wbcContext
*ctx
,
937 const char *domain_name
,
938 uint32_t *_num_groups
,
939 const char ***_groups
)
941 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
942 struct winbindd_request request
;
943 struct winbindd_response response
;
944 uint32_t num_groups
= 0;
945 const char **groups
= NULL
;
948 /* Initialise request */
950 ZERO_STRUCT(request
);
951 ZERO_STRUCT(response
);
954 strncpy(request
.domain_name
, domain_name
,
955 sizeof(request
.domain_name
)-1);
958 wbc_status
= wbcRequestResponse(ctx
, WINBINDD_LIST_GROUPS
,
961 BAIL_ON_WBC_ERROR(wbc_status
);
963 groups
= wbcAllocateStringArray(response
.data
.num_entries
);
964 if (groups
== NULL
) {
965 return WBC_ERR_NO_MEMORY
;
968 /* Look through extra data */
970 next
= (const char *)response
.extra_data
.data
;
975 if (num_groups
>= response
.data
.num_entries
) {
976 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
981 k
= strchr(next
, ',');
990 groups
[num_groups
] = strdup(current
);
991 BAIL_ON_PTR_ERROR(groups
[num_groups
], wbc_status
);
994 if (num_groups
!= response
.data
.num_entries
) {
995 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
999 *_num_groups
= response
.data
.num_entries
;
1002 wbc_status
= WBC_ERR_SUCCESS
;
1005 winbindd_free_response(&response
);
1006 wbcFreeMemory(groups
);
1010 wbcErr
wbcListGroups(const char *domain_name
,
1011 uint32_t *_num_groups
,
1012 const char ***_groups
)
1014 return wbcCtxListGroups(NULL
, domain_name
, _num_groups
, _groups
);
1017 wbcErr
wbcCtxGetDisplayName(struct wbcContext
*ctx
,
1018 const struct wbcDomainSid
*sid
,
1021 enum wbcSidType
*pname_type
)
1024 char *domain
= NULL
;
1026 enum wbcSidType name_type
;
1028 wbc_status
= wbcCtxLookupSid(ctx
, sid
, &domain
, &name
, &name_type
);
1029 BAIL_ON_WBC_ERROR(wbc_status
);
1031 if (name_type
== WBC_SID_NAME_USER
) {
1035 wbc_status
= wbcCtxSidToUid(ctx
, sid
, &uid
);
1036 BAIL_ON_WBC_ERROR(wbc_status
);
1038 wbc_status
= wbcCtxGetpwuid(ctx
, uid
, &pwd
);
1039 BAIL_ON_WBC_ERROR(wbc_status
);
1041 wbcFreeMemory(name
);
1043 name
= wbcStrDup(pwd
->pw_gecos
);
1045 BAIL_ON_PTR_ERROR(name
, wbc_status
);
1048 wbc_status
= WBC_ERR_SUCCESS
;
1051 if (WBC_ERROR_IS_OK(wbc_status
)) {
1054 *pname_type
= name_type
;
1056 wbcFreeMemory(domain
);
1057 wbcFreeMemory(name
);
1063 wbcErr
wbcGetDisplayName(const struct wbcDomainSid
*sid
,
1066 enum wbcSidType
*pname_type
)
1068 return wbcCtxGetDisplayName(NULL
, sid
, pdomain
, pfullname
, pname_type
);
1071 const char* wbcSidTypeString(enum wbcSidType type
)
1074 case WBC_SID_NAME_USE_NONE
: return "SID_NONE";
1075 case WBC_SID_NAME_USER
: return "SID_USER";
1076 case WBC_SID_NAME_DOM_GRP
: return "SID_DOM_GROUP";
1077 case WBC_SID_NAME_DOMAIN
: return "SID_DOMAIN";
1078 case WBC_SID_NAME_ALIAS
: return "SID_ALIAS";
1079 case WBC_SID_NAME_WKN_GRP
: return "SID_WKN_GROUP";
1080 case WBC_SID_NAME_DELETED
: return "SID_DELETED";
1081 case WBC_SID_NAME_INVALID
: return "SID_INVALID";
1082 case WBC_SID_NAME_UNKNOWN
: return "SID_UNKNOWN";
1083 case WBC_SID_NAME_COMPUTER
: return "SID_COMPUTER";
1084 case WBC_SID_NAME_LABEL
: return "SID_LABEL";
1085 default: return "Unknown type";