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')
108 wbc_status
= WBC_ERR_INVALID_PARAM
;
109 BAIL_ON_WBC_ERROR(wbc_status
);
112 /* Get the SID revision number */
115 x
= (uint32_t)strtol(p
, &q
, 10);
116 if (x
==0 || !q
|| *q
!='-') {
117 wbc_status
= WBC_ERR_INVALID_SID
;
118 BAIL_ON_WBC_ERROR(wbc_status
);
120 sid
->sid_rev_num
= (uint8_t)x
;
122 /* Next the Identifier Authority. This is stored in big-endian
123 in a 6 byte array. */
126 x
= (uint32_t)strtol(p
, &q
, 10);
127 if (x
==0 || !q
|| *q
!='-') {
128 wbc_status
= WBC_ERR_INVALID_SID
;
129 BAIL_ON_WBC_ERROR(wbc_status
);
131 sid
->id_auth
[5] = (x
& 0x000000ff);
132 sid
->id_auth
[4] = (x
& 0x0000ff00) >> 8;
133 sid
->id_auth
[3] = (x
& 0x00ff0000) >> 16;
134 sid
->id_auth
[2] = (x
& 0xff000000) >> 24;
138 /* now read the the subauthorities */
142 while (sid
->num_auths
< WBC_MAXSUBAUTHS
) {
143 if ((x
=(uint32_t)strtoul(p
, &q
, 10)) == 0)
145 sid
->sub_auths
[sid
->num_auths
++] = x
;
147 if (q
&& ((*q
!='-') || (*q
=='\0')))
152 /* IF we ended early, then the SID could not be converted */
155 wbc_status
= WBC_ERR_INVALID_SID
;
156 BAIL_ON_WBC_ERROR(wbc_status
);
159 wbc_status
= WBC_ERR_SUCCESS
;
166 /** @brief Convert a domain and name to SID
168 * @param domain Domain name (possibly "")
169 * @param name User or group name
170 * @param *sid Pointer to the resolved domain SID
171 * @param *name_type Pointet to the SID type
177 wbcErr
wbcLookupName(const char *domain
,
179 struct wbcDomainSid
*sid
,
180 enum wbcSidType
*name_type
)
182 struct winbindd_request request
;
183 struct winbindd_response response
;
184 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
186 if (!sid
|| !name_type
) {
187 wbc_status
= WBC_ERR_INVALID_PARAM
;
188 BAIL_ON_WBC_ERROR(wbc_status
);
191 /* Initialize request */
193 ZERO_STRUCT(request
);
194 ZERO_STRUCT(response
);
196 /* dst is already null terminated from the memset above */
198 strncpy(request
.data
.name
.dom_name
, domain
,
199 sizeof(request
.data
.name
.dom_name
)-1);
200 strncpy(request
.data
.name
.name
, name
,
201 sizeof(request
.data
.name
.name
)-1);
203 wbc_status
= wbcRequestResponse(WINBINDD_LOOKUPNAME
,
206 BAIL_ON_WBC_ERROR(wbc_status
);
208 wbc_status
= wbcStringToSid(response
.data
.sid
.sid
, sid
);
209 BAIL_ON_WBC_ERROR(wbc_status
);
211 *name_type
= (enum wbcSidType
)response
.data
.sid
.type
;
213 wbc_status
= WBC_ERR_SUCCESS
;
219 /** @brief Convert a SID to a domain and name
221 * @param *sid Pointer to the domain SID to be resolved
222 * @param domain Resolved Domain name (possibly "")
223 * @param name Resolved User or group name
224 * @param *name_type Pointet to the resolved SID type
230 wbcErr
wbcLookupSid(const struct wbcDomainSid
*sid
,
233 enum wbcSidType
*name_type
)
235 struct winbindd_request request
;
236 struct winbindd_response response
;
237 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
238 char *sid_string
= NULL
;
241 wbc_status
= WBC_ERR_INVALID_PARAM
;
242 BAIL_ON_WBC_ERROR(wbc_status
);
245 /* Initialize request */
247 ZERO_STRUCT(request
);
248 ZERO_STRUCT(response
);
250 /* dst is already null terminated from the memset above */
252 wbc_status
= wbcSidToString(sid
, &sid_string
);
253 BAIL_ON_WBC_ERROR(wbc_status
);
255 strncpy(request
.data
.sid
, sid_string
, sizeof(request
.data
.sid
)-1);
256 wbcFreeMemory(sid_string
);
260 wbc_status
= wbcRequestResponse(WINBINDD_LOOKUPSID
,
263 BAIL_ON_WBC_ERROR(wbc_status
);
265 /* Copy out result */
267 if (domain
!= NULL
) {
268 *domain
= talloc_strdup(NULL
, response
.data
.name
.dom_name
);
269 BAIL_ON_PTR_ERROR((*domain
), wbc_status
);
273 *name
= talloc_strdup(NULL
, response
.data
.name
.name
);
274 BAIL_ON_PTR_ERROR((*name
), wbc_status
);
278 *name_type
= (enum wbcSidType
)response
.data
.name
.type
;
281 wbc_status
= WBC_ERR_SUCCESS
;
284 if (!WBC_ERROR_IS_OK(wbc_status
)) {
286 talloc_free(*domain
);
294 /** @brief Translate a collection of RIDs within a domain to names
298 wbcErr
wbcLookupRids(struct wbcDomainSid
*dom_sid
,
301 const char **pp_domain_name
,
303 enum wbcSidType
**types
)
305 size_t i
, len
, ridbuf_size
;
308 struct winbindd_request request
;
309 struct winbindd_response response
;
310 char *sid_string
= NULL
;
311 char *domain_name
= NULL
;
312 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
314 /* Initialise request */
316 ZERO_STRUCT(request
);
317 ZERO_STRUCT(response
);
319 if (!dom_sid
|| (num_rids
== 0)) {
320 wbc_status
= WBC_ERR_INVALID_PARAM
;
321 BAIL_ON_WBC_ERROR(wbc_status
);
324 wbc_status
= wbcSidToString(dom_sid
, &sid_string
);
325 BAIL_ON_WBC_ERROR(wbc_status
);
327 strncpy(request
.data
.sid
, sid_string
, sizeof(request
.data
.sid
)-1);
328 wbcFreeMemory(sid_string
);
330 /* Even if all the Rids were of maximum 32bit values,
331 we would only have 11 bytes per rid in the final array
332 ("4294967296" + \n). Add one more byte for the
335 ridbuf_size
= (sizeof(char)*11) * num_rids
+ 1;
337 ridlist
= talloc_zero_array(NULL
, char, ridbuf_size
);
338 BAIL_ON_PTR_ERROR(ridlist
, wbc_status
);
341 for (i
=0; i
<num_rids
&& (len
-1)>0; i
++) {
344 len
= strlen(ridlist
);
347 snprintf( ridstr
, sizeof(ridstr
)-1, "%u\n", rids
[i
]);
348 strncat(p
, ridstr
, ridbuf_size
-len
-1);
351 request
.extra_data
.data
= ridlist
;
352 request
.extra_len
= strlen(ridlist
)+1;
354 wbc_status
= wbcRequestResponse(WINBINDD_LOOKUPRIDS
,
357 talloc_free(ridlist
);
358 BAIL_ON_WBC_ERROR(wbc_status
);
360 domain_name
= talloc_strdup(NULL
, response
.data
.domain_name
);
361 BAIL_ON_PTR_ERROR(domain_name
, wbc_status
);
363 *names
= talloc_array(NULL
, const char*, num_rids
);
364 BAIL_ON_PTR_ERROR((*names
), wbc_status
);
366 *types
= talloc_array(NULL
, enum wbcSidType
, num_rids
);
367 BAIL_ON_PTR_ERROR((*types
), wbc_status
);
369 p
= (char *)response
.extra_data
.data
;
371 for (i
=0; i
<num_rids
; i
++) {
375 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
376 BAIL_ON_WBC_ERROR(wbc_status
);
379 (*types
)[i
] = (enum wbcSidType
)strtoul(p
, &q
, 10);
382 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
383 BAIL_ON_WBC_ERROR(wbc_status
);
388 if ((q
= strchr(p
, '\n')) == NULL
) {
389 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
390 BAIL_ON_WBC_ERROR(wbc_status
);
395 (*names
)[i
] = talloc_strdup((*names
), p
);
396 BAIL_ON_PTR_ERROR(((*names
)[i
]), wbc_status
);
402 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
403 BAIL_ON_WBC_ERROR(wbc_status
);
406 wbc_status
= WBC_ERR_SUCCESS
;
409 if (response
.extra_data
.data
) {
410 free(response
.extra_data
.data
);
413 if (!WBC_ERROR_IS_OK(wbc_status
)) {
415 talloc_free(domain_name
);
421 *pp_domain_name
= domain_name
;
427 /** @brief Get the groups a user belongs to
431 wbcErr
wbcLookupUserSids(const struct wbcDomainSid
*user_sid
,
432 bool domain_groups_only
,
434 struct wbcDomainSid
**_sids
)
438 struct winbindd_request request
;
439 struct winbindd_response response
;
440 char *sid_string
= NULL
;
441 struct wbcDomainSid
*sids
= NULL
;
442 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
445 /* Initialise request */
447 ZERO_STRUCT(request
);
448 ZERO_STRUCT(response
);
451 wbc_status
= WBC_ERR_INVALID_PARAM
;
452 BAIL_ON_WBC_ERROR(wbc_status
);
455 wbc_status
= wbcSidToString(user_sid
, &sid_string
);
456 BAIL_ON_WBC_ERROR(wbc_status
);
458 strncpy(request
.data
.sid
, sid_string
, sizeof(request
.data
.sid
)-1);
459 wbcFreeMemory(sid_string
);
461 if (domain_groups_only
) {
462 cmd
= WINBINDD_GETUSERDOMGROUPS
;
464 cmd
= WINBINDD_GETUSERSIDS
;
467 wbc_status
= wbcRequestResponse(cmd
,
470 BAIL_ON_WBC_ERROR(wbc_status
);
472 if (response
.data
.num_entries
&&
473 !response
.extra_data
.data
) {
474 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
475 BAIL_ON_WBC_ERROR(wbc_status
);
478 sids
= talloc_array(NULL
, struct wbcDomainSid
,
479 response
.data
.num_entries
);
480 BAIL_ON_PTR_ERROR(sids
, wbc_status
);
482 s
= (const char *)response
.extra_data
.data
;
483 for (i
= 0; i
< response
.data
.num_entries
; i
++) {
484 char *n
= strchr(s
, '\n');
488 wbc_status
= wbcStringToSid(s
, &sids
[i
]);
489 BAIL_ON_WBC_ERROR(wbc_status
);
493 *num_sids
= response
.data
.num_entries
;
496 wbc_status
= WBC_ERR_SUCCESS
;
499 if (response
.extra_data
.data
) {
500 free(response
.extra_data
.data
);
509 /** @brief Lists Users
513 wbcErr
wbcListUsers(const char *domain_name
,
514 uint32_t *_num_users
,
515 const char ***_users
)
517 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
518 struct winbindd_request request
;
519 struct winbindd_response response
;
520 uint32_t num_users
= 0;
521 const char **users
= NULL
;
524 /* Initialise request */
526 ZERO_STRUCT(request
);
527 ZERO_STRUCT(response
);
530 strncpy(request
.domain_name
, domain_name
,
531 sizeof(request
.domain_name
)-1);
534 wbc_status
= wbcRequestResponse(WINBINDD_LIST_USERS
,
537 BAIL_ON_WBC_ERROR(wbc_status
);
539 /* Look through extra data */
541 next
= (const char *)response
.extra_data
.data
;
544 const char *current
= next
;
545 char *k
= strchr(next
, ',');
553 tmp
= talloc_realloc(NULL
, users
,
556 BAIL_ON_PTR_ERROR(tmp
, wbc_status
);
559 users
[num_users
] = talloc_strdup(users
, current
);
560 BAIL_ON_PTR_ERROR(users
[num_users
], wbc_status
);
565 *_num_users
= num_users
;
568 wbc_status
= WBC_ERR_SUCCESS
;
571 if (response
.extra_data
.data
) {
572 free(response
.extra_data
.data
);
580 /** @brief Lists Groups
584 wbcErr
wbcListGroups(const char *domain_name
,
585 uint32_t *_num_groups
,
586 const char ***_groups
)
588 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
589 struct winbindd_request request
;
590 struct winbindd_response response
;
591 uint32_t num_groups
= 0;
592 const char **groups
= NULL
;
595 /* Initialise request */
597 ZERO_STRUCT(request
);
598 ZERO_STRUCT(response
);
601 strncpy(request
.domain_name
, domain_name
,
602 sizeof(request
.domain_name
)-1);
605 wbc_status
= wbcRequestResponse(WINBINDD_LIST_GROUPS
,
608 BAIL_ON_WBC_ERROR(wbc_status
);
610 /* Look through extra data */
612 next
= (const char *)response
.extra_data
.data
;
615 const char *current
= next
;
616 char *k
= strchr(next
, ',');
624 tmp
= talloc_realloc(NULL
, groups
,
627 BAIL_ON_PTR_ERROR(tmp
, wbc_status
);
630 groups
[num_groups
] = talloc_strdup(groups
, current
);
631 BAIL_ON_PTR_ERROR(groups
[num_groups
], wbc_status
);
636 *_num_groups
= num_groups
;
639 wbc_status
= WBC_ERR_SUCCESS
;
642 if (response
.extra_data
.data
) {
643 free(response
.extra_data
.data
);