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 /** @brief Convert a binary SID to a character string
30 * @param sid Binary Security Identifier
31 * @param **sid_string Resulting character string
36 wbcErr
wbcSidToString(const struct wbcDomainSid
*sid
,
39 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
43 TALLOC_CTX
*ctx
= NULL
;
46 wbc_status
= WBC_ERR_INVALID_SID
;
47 BAIL_ON_WBC_ERROR(wbc_status
);
50 ctx
= talloc_init("wbcSidToString");
51 BAIL_ON_PTR_ERROR(ctx
, wbc_status
);
53 id_auth
= sid
->id_auth
[5] +
54 (sid
->id_auth
[4] << 8) +
55 (sid
->id_auth
[3] << 16) +
56 (sid
->id_auth
[2] << 24);
58 tmp
= talloc_asprintf(ctx
, "S-%d-%d", sid
->sid_rev_num
, id_auth
);
59 BAIL_ON_PTR_ERROR(tmp
, wbc_status
);
61 for (i
=0; i
<sid
->num_auths
; i
++) {
63 tmp2
= talloc_asprintf_append(tmp
, "-%u", sid
->sub_auths
[i
]);
64 BAIL_ON_PTR_ERROR(tmp2
, wbc_status
);
69 *sid_string
=talloc_strdup(NULL
, tmp
);
70 BAIL_ON_PTR_ERROR((*sid_string
), wbc_status
);
72 wbc_status
= WBC_ERR_SUCCESS
;
80 /** @brief Convert a character string to a binary SID
82 * @param *str Character string in the form of S-...
83 * @param sid Resulting binary SID
88 wbcErr
wbcStringToSid(const char *str
,
89 struct wbcDomainSid
*sid
)
94 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
97 wbc_status
= WBC_ERR_INVALID_PARAM
;
98 BAIL_ON_WBC_ERROR(wbc_status
);
101 /* Sanity check for either "S-" or "s-" */
104 || (str
[0]!='S' && str
[0]!='s')
107 wbc_status
= WBC_ERR_INVALID_PARAM
;
108 BAIL_ON_WBC_ERROR(wbc_status
);
111 /* Get the SID revision number */
114 x
= (uint32_t)strtol(p
, &q
, 10);
115 if (x
==0 || !q
|| *q
!='-') {
116 wbc_status
= WBC_ERR_INVALID_SID
;
117 BAIL_ON_WBC_ERROR(wbc_status
);
119 sid
->sid_rev_num
= (uint8_t)x
;
121 /* Next the Identifier Authority. This is stored in big-endian
122 in a 6 byte array. */
125 x
= (uint32_t)strtol(p
, &q
, 10);
127 wbc_status
= WBC_ERR_INVALID_SID
;
128 BAIL_ON_WBC_ERROR(wbc_status
);
130 sid
->id_auth
[5] = (x
& 0x000000ff);
131 sid
->id_auth
[4] = (x
& 0x0000ff00) >> 8;
132 sid
->id_auth
[3] = (x
& 0x00ff0000) >> 16;
133 sid
->id_auth
[2] = (x
& 0xff000000) >> 24;
137 /* now read the the subauthorities */
141 while (sid
->num_auths
< WBC_MAXSUBAUTHS
) {
142 x
=(uint32_t)strtoul(p
, &q
, 10);
146 wbc_status
= WBC_ERR_INVALID_SID
;
147 BAIL_ON_WBC_ERROR(wbc_status
);
149 sid
->sub_auths
[sid
->num_auths
++] = x
;
151 if ((*q
!='-') || (*q
=='\0'))
156 /* IF we ended early, then the SID could not be converted */
159 wbc_status
= WBC_ERR_INVALID_SID
;
160 BAIL_ON_WBC_ERROR(wbc_status
);
163 wbc_status
= WBC_ERR_SUCCESS
;
170 /** @brief Convert a domain and name to SID
172 * @param domain Domain name (possibly "")
173 * @param name User or group name
174 * @param *sid Pointer to the resolved domain SID
175 * @param *name_type Pointet to the SID type
181 wbcErr
wbcLookupName(const char *domain
,
183 struct wbcDomainSid
*sid
,
184 enum wbcSidType
*name_type
)
186 struct winbindd_request request
;
187 struct winbindd_response response
;
188 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
190 if (!sid
|| !name_type
) {
191 wbc_status
= WBC_ERR_INVALID_PARAM
;
192 BAIL_ON_WBC_ERROR(wbc_status
);
195 /* Initialize request */
197 ZERO_STRUCT(request
);
198 ZERO_STRUCT(response
);
200 /* dst is already null terminated from the memset above */
202 strncpy(request
.data
.name
.dom_name
, domain
,
203 sizeof(request
.data
.name
.dom_name
)-1);
204 strncpy(request
.data
.name
.name
, name
,
205 sizeof(request
.data
.name
.name
)-1);
207 wbc_status
= wbcRequestResponse(WINBINDD_LOOKUPNAME
,
210 BAIL_ON_WBC_ERROR(wbc_status
);
212 wbc_status
= wbcStringToSid(response
.data
.sid
.sid
, sid
);
213 BAIL_ON_WBC_ERROR(wbc_status
);
215 *name_type
= (enum wbcSidType
)response
.data
.sid
.type
;
217 wbc_status
= WBC_ERR_SUCCESS
;
223 /** @brief Convert a SID to a domain and name
225 * @param *sid Pointer to the domain SID to be resolved
226 * @param domain Resolved Domain name (possibly "")
227 * @param name Resolved User or group name
228 * @param *name_type Pointet to the resolved SID type
234 wbcErr
wbcLookupSid(const struct wbcDomainSid
*sid
,
237 enum wbcSidType
*pname_type
)
239 struct winbindd_request request
;
240 struct winbindd_response response
;
241 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
242 char *sid_string
= NULL
;
245 enum wbcSidType name_type
= WBC_SID_NAME_USE_NONE
;
248 wbc_status
= WBC_ERR_INVALID_PARAM
;
249 BAIL_ON_WBC_ERROR(wbc_status
);
252 /* Initialize request */
254 ZERO_STRUCT(request
);
255 ZERO_STRUCT(response
);
257 /* dst is already null terminated from the memset above */
259 wbc_status
= wbcSidToString(sid
, &sid_string
);
260 BAIL_ON_WBC_ERROR(wbc_status
);
262 strncpy(request
.data
.sid
, sid_string
, sizeof(request
.data
.sid
)-1);
263 wbcFreeMemory(sid_string
);
267 wbc_status
= wbcRequestResponse(WINBINDD_LOOKUPSID
,
270 BAIL_ON_WBC_ERROR(wbc_status
);
272 /* Copy out result */
274 domain
= talloc_strdup(NULL
, response
.data
.name
.dom_name
);
275 BAIL_ON_PTR_ERROR(domain
, wbc_status
);
277 name
= talloc_strdup(NULL
, response
.data
.name
.name
);
278 BAIL_ON_PTR_ERROR(name
, wbc_status
);
280 name_type
= (enum wbcSidType
)response
.data
.name
.type
;
282 wbc_status
= WBC_ERR_SUCCESS
;
285 if (WBC_ERROR_IS_OK(wbc_status
)) {
286 if (pdomain
!= NULL
) {
292 if (pname_type
!= NULL
) {
293 *pname_type
= name_type
;
300 if (domain
!= NULL
) {
308 /** @brief Translate a collection of RIDs within a domain to names
312 wbcErr
wbcLookupRids(struct wbcDomainSid
*dom_sid
,
315 const char **pp_domain_name
,
316 const char ***pnames
,
317 enum wbcSidType
**ptypes
)
319 size_t i
, len
, ridbuf_size
;
322 struct winbindd_request request
;
323 struct winbindd_response response
;
324 char *sid_string
= NULL
;
325 char *domain_name
= NULL
;
326 const char **names
= NULL
;
327 enum wbcSidType
*types
= NULL
;
328 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
330 /* Initialise request */
332 ZERO_STRUCT(request
);
333 ZERO_STRUCT(response
);
335 if (!dom_sid
|| (num_rids
== 0)) {
336 wbc_status
= WBC_ERR_INVALID_PARAM
;
337 BAIL_ON_WBC_ERROR(wbc_status
);
340 wbc_status
= wbcSidToString(dom_sid
, &sid_string
);
341 BAIL_ON_WBC_ERROR(wbc_status
);
343 strncpy(request
.data
.sid
, sid_string
, sizeof(request
.data
.sid
)-1);
344 wbcFreeMemory(sid_string
);
346 /* Even if all the Rids were of maximum 32bit values,
347 we would only have 11 bytes per rid in the final array
348 ("4294967296" + \n). Add one more byte for the
351 ridbuf_size
= (sizeof(char)*11) * num_rids
+ 1;
353 ridlist
= talloc_zero_array(NULL
, char, ridbuf_size
);
354 BAIL_ON_PTR_ERROR(ridlist
, wbc_status
);
357 for (i
=0; i
<num_rids
&& (len
-1)>0; i
++) {
360 len
= strlen(ridlist
);
363 snprintf( ridstr
, sizeof(ridstr
)-1, "%u\n", rids
[i
]);
364 strncat(p
, ridstr
, ridbuf_size
-len
-1);
367 request
.extra_data
.data
= ridlist
;
368 request
.extra_len
= strlen(ridlist
)+1;
370 wbc_status
= wbcRequestResponse(WINBINDD_LOOKUPRIDS
,
373 talloc_free(ridlist
);
374 BAIL_ON_WBC_ERROR(wbc_status
);
376 domain_name
= talloc_strdup(NULL
, response
.data
.domain_name
);
377 BAIL_ON_PTR_ERROR(domain_name
, wbc_status
);
379 names
= talloc_array(NULL
, const char*, num_rids
);
380 BAIL_ON_PTR_ERROR(names
, wbc_status
);
382 types
= talloc_array(NULL
, enum wbcSidType
, num_rids
);
383 BAIL_ON_PTR_ERROR(types
, wbc_status
);
385 p
= (char *)response
.extra_data
.data
;
387 for (i
=0; i
<num_rids
; i
++) {
391 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
392 BAIL_ON_WBC_ERROR(wbc_status
);
395 types
[i
] = (enum wbcSidType
)strtoul(p
, &q
, 10);
398 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
399 BAIL_ON_WBC_ERROR(wbc_status
);
404 if ((q
= strchr(p
, '\n')) == NULL
) {
405 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
406 BAIL_ON_WBC_ERROR(wbc_status
);
411 names
[i
] = talloc_strdup(names
, p
);
412 BAIL_ON_PTR_ERROR(names
[i
], wbc_status
);
418 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
419 BAIL_ON_WBC_ERROR(wbc_status
);
422 wbc_status
= WBC_ERR_SUCCESS
;
425 if (response
.extra_data
.data
) {
426 free(response
.extra_data
.data
);
429 if (WBC_ERROR_IS_OK(wbc_status
)) {
430 *pp_domain_name
= domain_name
;
436 talloc_free(domain_name
);
446 /** @brief Get the groups a user belongs to
450 wbcErr
wbcLookupUserSids(const struct wbcDomainSid
*user_sid
,
451 bool domain_groups_only
,
453 struct wbcDomainSid
**_sids
)
457 struct winbindd_request request
;
458 struct winbindd_response response
;
459 char *sid_string
= NULL
;
460 struct wbcDomainSid
*sids
= NULL
;
461 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
464 /* Initialise request */
466 ZERO_STRUCT(request
);
467 ZERO_STRUCT(response
);
470 wbc_status
= WBC_ERR_INVALID_PARAM
;
471 BAIL_ON_WBC_ERROR(wbc_status
);
474 wbc_status
= wbcSidToString(user_sid
, &sid_string
);
475 BAIL_ON_WBC_ERROR(wbc_status
);
477 strncpy(request
.data
.sid
, sid_string
, sizeof(request
.data
.sid
)-1);
478 wbcFreeMemory(sid_string
);
480 if (domain_groups_only
) {
481 cmd
= WINBINDD_GETUSERDOMGROUPS
;
483 cmd
= WINBINDD_GETUSERSIDS
;
486 wbc_status
= wbcRequestResponse(cmd
,
489 BAIL_ON_WBC_ERROR(wbc_status
);
491 if (response
.data
.num_entries
&&
492 !response
.extra_data
.data
) {
493 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
494 BAIL_ON_WBC_ERROR(wbc_status
);
497 sids
= talloc_array(NULL
, struct wbcDomainSid
,
498 response
.data
.num_entries
);
499 BAIL_ON_PTR_ERROR(sids
, wbc_status
);
501 s
= (const char *)response
.extra_data
.data
;
502 for (i
= 0; i
< response
.data
.num_entries
; i
++) {
503 char *n
= strchr(s
, '\n');
507 wbc_status
= wbcStringToSid(s
, &sids
[i
]);
508 BAIL_ON_WBC_ERROR(wbc_status
);
512 *num_sids
= response
.data
.num_entries
;
515 wbc_status
= WBC_ERR_SUCCESS
;
518 if (response
.extra_data
.data
) {
519 free(response
.extra_data
.data
);
528 /** @brief Lists Users
532 wbcErr
wbcListUsers(const char *domain_name
,
533 uint32_t *_num_users
,
534 const char ***_users
)
536 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
537 struct winbindd_request request
;
538 struct winbindd_response response
;
539 uint32_t num_users
= 0;
540 const char **users
= NULL
;
543 /* Initialise request */
545 ZERO_STRUCT(request
);
546 ZERO_STRUCT(response
);
549 strncpy(request
.domain_name
, domain_name
,
550 sizeof(request
.domain_name
)-1);
553 wbc_status
= wbcRequestResponse(WINBINDD_LIST_USERS
,
556 BAIL_ON_WBC_ERROR(wbc_status
);
558 /* Look through extra data */
560 next
= (const char *)response
.extra_data
.data
;
563 const char *current
= next
;
564 char *k
= strchr(next
, ',');
572 tmp
= talloc_realloc(NULL
, users
,
575 BAIL_ON_PTR_ERROR(tmp
, wbc_status
);
578 users
[num_users
] = talloc_strdup(users
, current
);
579 BAIL_ON_PTR_ERROR(users
[num_users
], wbc_status
);
584 *_num_users
= num_users
;
587 wbc_status
= WBC_ERR_SUCCESS
;
590 if (response
.extra_data
.data
) {
591 free(response
.extra_data
.data
);
599 /** @brief Lists Groups
603 wbcErr
wbcListGroups(const char *domain_name
,
604 uint32_t *_num_groups
,
605 const char ***_groups
)
607 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
608 struct winbindd_request request
;
609 struct winbindd_response response
;
610 uint32_t num_groups
= 0;
611 const char **groups
= NULL
;
614 /* Initialise request */
616 ZERO_STRUCT(request
);
617 ZERO_STRUCT(response
);
620 strncpy(request
.domain_name
, domain_name
,
621 sizeof(request
.domain_name
)-1);
624 wbc_status
= wbcRequestResponse(WINBINDD_LIST_GROUPS
,
627 BAIL_ON_WBC_ERROR(wbc_status
);
629 /* Look through extra data */
631 next
= (const char *)response
.extra_data
.data
;
634 const char *current
= next
;
635 char *k
= strchr(next
, ',');
643 tmp
= talloc_realloc(NULL
, groups
,
646 BAIL_ON_PTR_ERROR(tmp
, wbc_status
);
649 groups
[num_groups
] = talloc_strdup(groups
, current
);
650 BAIL_ON_PTR_ERROR(groups
[num_groups
], wbc_status
);
655 *_num_groups
= num_groups
;
658 wbc_status
= WBC_ERR_SUCCESS
;
661 if (response
.extra_data
.data
) {
662 free(response
.extra_data
.data
);