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";