2 Unix SMB/CIFS implementation.
6 Copyright (C) Gerald (Jerry) Carter 2007
9 This library is free software; you can redistribute it and/or
10 modify it under the terms of the GNU Lesser General Public
11 License as published by the Free Software Foundation; either
12 version 3 of the License, or (at your option) any later version.
14 This library is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Library General Public License for more details.
19 You should have received a copy of the GNU Lesser General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 /* Required Headers */
25 #include "libwbclient.h"
28 /* Convert a binary SID to a character string */
29 wbcErr
wbcSidToString(const struct wbcDomainSid
*sid
,
32 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
38 wbc_status
= WBC_ERR_INVALID_SID
;
39 BAIL_ON_WBC_ERROR(wbc_status
);
42 id_auth
= sid
->id_auth
[5] +
43 (sid
->id_auth
[4] << 8) +
44 (sid
->id_auth
[3] << 16) +
45 (sid
->id_auth
[2] << 24);
47 tmp
= talloc_asprintf(NULL
, "S-%d-%d", sid
->sid_rev_num
, id_auth
);
48 BAIL_ON_PTR_ERROR(tmp
, wbc_status
);
50 for (i
=0; i
<sid
->num_auths
; i
++) {
52 tmp2
= talloc_asprintf_append(tmp
, "-%u", sid
->sub_auths
[i
]);
53 BAIL_ON_PTR_ERROR(tmp2
, wbc_status
);
61 wbc_status
= WBC_ERR_SUCCESS
;
69 /* Convert a character string to a binary SID */
70 wbcErr
wbcStringToSid(const char *str
,
71 struct wbcDomainSid
*sid
)
76 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
79 wbc_status
= WBC_ERR_INVALID_PARAM
;
80 BAIL_ON_WBC_ERROR(wbc_status
);
83 /* Sanity check for either "S-" or "s-" */
86 || (str
[0]!='S' && str
[0]!='s')
89 wbc_status
= WBC_ERR_INVALID_PARAM
;
90 BAIL_ON_WBC_ERROR(wbc_status
);
93 /* Get the SID revision number */
96 x
= (uint32_t)strtol(p
, &q
, 10);
97 if (x
==0 || !q
|| *q
!='-') {
98 wbc_status
= WBC_ERR_INVALID_SID
;
99 BAIL_ON_WBC_ERROR(wbc_status
);
101 sid
->sid_rev_num
= (uint8_t)x
;
103 /* Next the Identifier Authority. This is stored in big-endian
104 in a 6 byte array. */
107 x
= (uint32_t)strtol(p
, &q
, 10);
109 wbc_status
= WBC_ERR_INVALID_SID
;
110 BAIL_ON_WBC_ERROR(wbc_status
);
112 sid
->id_auth
[5] = (x
& 0x000000ff);
113 sid
->id_auth
[4] = (x
& 0x0000ff00) >> 8;
114 sid
->id_auth
[3] = (x
& 0x00ff0000) >> 16;
115 sid
->id_auth
[2] = (x
& 0xff000000) >> 24;
119 /* now read the the subauthorities */
123 while (sid
->num_auths
< WBC_MAXSUBAUTHS
) {
124 x
=(uint32_t)strtoul(p
, &q
, 10);
128 wbc_status
= WBC_ERR_INVALID_SID
;
129 BAIL_ON_WBC_ERROR(wbc_status
);
131 sid
->sub_auths
[sid
->num_auths
++] = x
;
133 if ((*q
!='-') || (*q
=='\0'))
138 /* IF we ended early, then the SID could not be converted */
141 wbc_status
= WBC_ERR_INVALID_SID
;
142 BAIL_ON_WBC_ERROR(wbc_status
);
145 wbc_status
= WBC_ERR_SUCCESS
;
152 /* Convert a domain and name to SID */
153 wbcErr
wbcLookupName(const char *domain
,
155 struct wbcDomainSid
*sid
,
156 enum wbcSidType
*name_type
)
158 struct winbindd_request request
;
159 struct winbindd_response response
;
160 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
162 if (!sid
|| !name_type
) {
163 wbc_status
= WBC_ERR_INVALID_PARAM
;
164 BAIL_ON_WBC_ERROR(wbc_status
);
167 /* Initialize request */
169 ZERO_STRUCT(request
);
170 ZERO_STRUCT(response
);
172 /* dst is already null terminated from the memset above */
174 strncpy(request
.data
.name
.dom_name
, domain
,
175 sizeof(request
.data
.name
.dom_name
)-1);
176 strncpy(request
.data
.name
.name
, name
,
177 sizeof(request
.data
.name
.name
)-1);
179 wbc_status
= wbcRequestResponse(WINBINDD_LOOKUPNAME
,
182 BAIL_ON_WBC_ERROR(wbc_status
);
184 wbc_status
= wbcStringToSid(response
.data
.sid
.sid
, sid
);
185 BAIL_ON_WBC_ERROR(wbc_status
);
187 *name_type
= (enum wbcSidType
)response
.data
.sid
.type
;
189 wbc_status
= WBC_ERR_SUCCESS
;
195 /* Convert a SID to a domain and name */
196 wbcErr
wbcLookupSid(const struct wbcDomainSid
*sid
,
199 enum wbcSidType
*pname_type
)
201 struct winbindd_request request
;
202 struct winbindd_response response
;
203 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
204 char *sid_string
= NULL
;
207 enum wbcSidType name_type
= WBC_SID_NAME_USE_NONE
;
210 wbc_status
= WBC_ERR_INVALID_PARAM
;
211 BAIL_ON_WBC_ERROR(wbc_status
);
214 /* Initialize request */
216 ZERO_STRUCT(request
);
217 ZERO_STRUCT(response
);
219 /* dst is already null terminated from the memset above */
221 wbc_status
= wbcSidToString(sid
, &sid_string
);
222 BAIL_ON_WBC_ERROR(wbc_status
);
224 strncpy(request
.data
.sid
, sid_string
, sizeof(request
.data
.sid
)-1);
225 wbcFreeMemory(sid_string
);
229 wbc_status
= wbcRequestResponse(WINBINDD_LOOKUPSID
,
232 BAIL_ON_WBC_ERROR(wbc_status
);
234 /* Copy out result */
236 domain
= talloc_strdup(NULL
, response
.data
.name
.dom_name
);
237 BAIL_ON_PTR_ERROR(domain
, wbc_status
);
239 name
= talloc_strdup(NULL
, response
.data
.name
.name
);
240 BAIL_ON_PTR_ERROR(name
, wbc_status
);
242 name_type
= (enum wbcSidType
)response
.data
.name
.type
;
244 wbc_status
= WBC_ERR_SUCCESS
;
247 if (WBC_ERROR_IS_OK(wbc_status
)) {
248 if (pdomain
!= NULL
) {
254 if (pname_type
!= NULL
) {
255 *pname_type
= name_type
;
261 * Found by Coverity: In this particular routine we can't end
262 * up here with a non-NULL name. Further up there are just two
263 * exit paths that lead here, neither of which leave an
264 * allocated name. If you add more paths up there, re-activate
271 if (domain
!= NULL
) {
279 /* Translate a collection of RIDs within a domain to names */
281 wbcErr
wbcLookupRids(struct wbcDomainSid
*dom_sid
,
284 const char **pp_domain_name
,
285 const char ***pnames
,
286 enum wbcSidType
**ptypes
)
288 size_t i
, len
, ridbuf_size
;
291 struct winbindd_request request
;
292 struct winbindd_response response
;
293 char *sid_string
= NULL
;
294 char *domain_name
= NULL
;
295 const char **names
= NULL
;
296 enum wbcSidType
*types
= NULL
;
297 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
299 /* Initialise request */
301 ZERO_STRUCT(request
);
302 ZERO_STRUCT(response
);
304 if (!dom_sid
|| (num_rids
== 0)) {
305 wbc_status
= WBC_ERR_INVALID_PARAM
;
306 BAIL_ON_WBC_ERROR(wbc_status
);
309 wbc_status
= wbcSidToString(dom_sid
, &sid_string
);
310 BAIL_ON_WBC_ERROR(wbc_status
);
312 strncpy(request
.data
.sid
, sid_string
, sizeof(request
.data
.sid
)-1);
313 wbcFreeMemory(sid_string
);
315 /* Even if all the Rids were of maximum 32bit values,
316 we would only have 11 bytes per rid in the final array
317 ("4294967296" + \n). Add one more byte for the
320 ridbuf_size
= (sizeof(char)*11) * num_rids
+ 1;
322 ridlist
= talloc_zero_array(NULL
, char, ridbuf_size
);
323 BAIL_ON_PTR_ERROR(ridlist
, wbc_status
);
326 for (i
=0; i
<num_rids
&& (len
-1)>0; i
++) {
329 len
= strlen(ridlist
);
332 snprintf( ridstr
, sizeof(ridstr
)-1, "%u\n", rids
[i
]);
333 strncat(p
, ridstr
, ridbuf_size
-len
-1);
336 request
.extra_data
.data
= ridlist
;
337 request
.extra_len
= strlen(ridlist
)+1;
339 wbc_status
= wbcRequestResponse(WINBINDD_LOOKUPRIDS
,
342 talloc_free(ridlist
);
343 BAIL_ON_WBC_ERROR(wbc_status
);
345 domain_name
= talloc_strdup(NULL
, response
.data
.domain_name
);
346 BAIL_ON_PTR_ERROR(domain_name
, wbc_status
);
348 names
= talloc_array(NULL
, const char*, num_rids
);
349 BAIL_ON_PTR_ERROR(names
, wbc_status
);
351 types
= talloc_array(NULL
, enum wbcSidType
, num_rids
);
352 BAIL_ON_PTR_ERROR(types
, wbc_status
);
354 p
= (char *)response
.extra_data
.data
;
356 for (i
=0; i
<num_rids
; i
++) {
360 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
361 BAIL_ON_WBC_ERROR(wbc_status
);
364 types
[i
] = (enum wbcSidType
)strtoul(p
, &q
, 10);
367 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
368 BAIL_ON_WBC_ERROR(wbc_status
);
373 if ((q
= strchr(p
, '\n')) == NULL
) {
374 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
375 BAIL_ON_WBC_ERROR(wbc_status
);
380 names
[i
] = talloc_strdup(names
, p
);
381 BAIL_ON_PTR_ERROR(names
[i
], wbc_status
);
387 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
388 BAIL_ON_WBC_ERROR(wbc_status
);
391 wbc_status
= WBC_ERR_SUCCESS
;
394 if (response
.extra_data
.data
) {
395 free(response
.extra_data
.data
);
398 if (WBC_ERROR_IS_OK(wbc_status
)) {
399 *pp_domain_name
= domain_name
;
405 talloc_free(domain_name
);
415 /* Get the groups a user belongs to */
416 wbcErr
wbcLookupUserSids(const struct wbcDomainSid
*user_sid
,
417 bool domain_groups_only
,
419 struct wbcDomainSid
**_sids
)
423 struct winbindd_request request
;
424 struct winbindd_response response
;
425 char *sid_string
= NULL
;
426 struct wbcDomainSid
*sids
= NULL
;
427 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
430 /* Initialise request */
432 ZERO_STRUCT(request
);
433 ZERO_STRUCT(response
);
436 wbc_status
= WBC_ERR_INVALID_PARAM
;
437 BAIL_ON_WBC_ERROR(wbc_status
);
440 wbc_status
= wbcSidToString(user_sid
, &sid_string
);
441 BAIL_ON_WBC_ERROR(wbc_status
);
443 strncpy(request
.data
.sid
, sid_string
, sizeof(request
.data
.sid
)-1);
444 wbcFreeMemory(sid_string
);
446 if (domain_groups_only
) {
447 cmd
= WINBINDD_GETUSERDOMGROUPS
;
449 cmd
= WINBINDD_GETUSERSIDS
;
452 wbc_status
= wbcRequestResponse(cmd
,
455 BAIL_ON_WBC_ERROR(wbc_status
);
457 if (response
.data
.num_entries
&&
458 !response
.extra_data
.data
) {
459 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
460 BAIL_ON_WBC_ERROR(wbc_status
);
463 sids
= talloc_array(NULL
, struct wbcDomainSid
,
464 response
.data
.num_entries
);
465 BAIL_ON_PTR_ERROR(sids
, wbc_status
);
467 s
= (const char *)response
.extra_data
.data
;
468 for (i
= 0; i
< response
.data
.num_entries
; i
++) {
469 char *n
= strchr(s
, '\n');
473 wbc_status
= wbcStringToSid(s
, &sids
[i
]);
474 BAIL_ON_WBC_ERROR(wbc_status
);
478 *num_sids
= response
.data
.num_entries
;
481 wbc_status
= WBC_ERR_SUCCESS
;
484 if (response
.extra_data
.data
) {
485 free(response
.extra_data
.data
);
495 wbcErr
wbcListUsers(const char *domain_name
,
496 uint32_t *_num_users
,
497 const char ***_users
)
499 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
500 struct winbindd_request request
;
501 struct winbindd_response response
;
502 uint32_t num_users
= 0;
503 const char **users
= NULL
;
506 /* Initialise request */
508 ZERO_STRUCT(request
);
509 ZERO_STRUCT(response
);
512 strncpy(request
.domain_name
, domain_name
,
513 sizeof(request
.domain_name
)-1);
516 wbc_status
= wbcRequestResponse(WINBINDD_LIST_USERS
,
519 BAIL_ON_WBC_ERROR(wbc_status
);
521 /* Look through extra data */
523 next
= (const char *)response
.extra_data
.data
;
526 const char *current
= next
;
527 char *k
= strchr(next
, ',');
535 tmp
= talloc_realloc(NULL
, users
,
538 BAIL_ON_PTR_ERROR(tmp
, wbc_status
);
541 users
[num_users
] = talloc_strdup(users
, current
);
542 BAIL_ON_PTR_ERROR(users
[num_users
], wbc_status
);
547 *_num_users
= num_users
;
550 wbc_status
= WBC_ERR_SUCCESS
;
553 if (response
.extra_data
.data
) {
554 free(response
.extra_data
.data
);
563 wbcErr
wbcListGroups(const char *domain_name
,
564 uint32_t *_num_groups
,
565 const char ***_groups
)
567 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
568 struct winbindd_request request
;
569 struct winbindd_response response
;
570 uint32_t num_groups
= 0;
571 const char **groups
= NULL
;
574 /* Initialise request */
576 ZERO_STRUCT(request
);
577 ZERO_STRUCT(response
);
580 strncpy(request
.domain_name
, domain_name
,
581 sizeof(request
.domain_name
)-1);
584 wbc_status
= wbcRequestResponse(WINBINDD_LIST_GROUPS
,
587 BAIL_ON_WBC_ERROR(wbc_status
);
589 /* Look through extra data */
591 next
= (const char *)response
.extra_data
.data
;
594 const char *current
= next
;
595 char *k
= strchr(next
, ',');
603 tmp
= talloc_realloc(NULL
, groups
,
606 BAIL_ON_PTR_ERROR(tmp
, wbc_status
);
609 groups
[num_groups
] = talloc_strdup(groups
, current
);
610 BAIL_ON_PTR_ERROR(groups
[num_groups
], wbc_status
);
615 *_num_groups
= num_groups
;
618 wbc_status
= WBC_ERR_SUCCESS
;
621 if (response
.extra_data
.data
) {
622 free(response
.extra_data
.data
);
630 wbcErr
wbcGetDisplayName(const struct wbcDomainSid
*sid
,
633 enum wbcSidType
*pname_type
)
638 enum wbcSidType name_type
;
640 wbc_status
= wbcLookupSid(sid
, &domain
, &name
, &name_type
);
641 BAIL_ON_WBC_ERROR(wbc_status
);
643 if (name_type
== WBC_SID_NAME_USER
) {
647 wbc_status
= wbcSidToUid(sid
, &uid
);
648 BAIL_ON_WBC_ERROR(wbc_status
);
650 wbc_status
= wbcGetpwuid(uid
, &pwd
);
651 BAIL_ON_WBC_ERROR(wbc_status
);
655 name
= talloc_strdup(NULL
, pwd
->pw_gecos
);
656 BAIL_ON_PTR_ERROR(name
, wbc_status
);
659 wbc_status
= WBC_ERR_SUCCESS
;
662 if (WBC_ERROR_IS_OK(wbc_status
)) {
665 *pname_type
= name_type
;
667 wbcFreeMemory(domain
);