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
< 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 if (!dom_sid
|| (num_rids
== 0)) {
315 wbc_status
= WBC_ERR_INVALID_PARAM
;
316 BAIL_ON_WBC_ERROR(wbc_status
);
319 /* Initialise request */
321 ZERO_STRUCT(request
);
322 ZERO_STRUCT(response
);
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
);
359 domain_name
= talloc_strdup(NULL
, response
.data
.domain_name
);
360 BAIL_ON_PTR_ERROR(domain_name
, wbc_status
);
362 *names
= talloc_array(NULL
, const char*, num_rids
);
363 BAIL_ON_PTR_ERROR((*names
), wbc_status
);
365 *types
= talloc_array(NULL
, enum wbcSidType
, num_rids
);
366 BAIL_ON_PTR_ERROR((*types
), wbc_status
);
368 p
= (char *)response
.extra_data
.data
;
370 for (i
=0; i
<num_rids
; i
++) {
374 wbc_status
= WBC_INVALID_RESPONSE
;
375 BAIL_ON_WBC_ERROR(wbc_status
);
378 (*types
)[i
] = (enum wbcSidType
)strtoul(p
, &q
, 10);
381 wbc_status
= WBC_INVALID_RESPONSE
;
382 BAIL_ON_WBC_ERROR(wbc_status
);
387 if ((q
= strchr(p
, '\n')) == NULL
) {
388 wbc_status
= WBC_INVALID_RESPONSE
;
389 BAIL_ON_WBC_ERROR(wbc_status
);
394 (*names
)[i
] = talloc_strdup((*names
), p
);
395 BAIL_ON_PTR_ERROR(((*names
)[i
]), wbc_status
);
401 wbc_status
= WBC_INVALID_RESPONSE
;
402 BAIL_ON_WBC_ERROR(wbc_status
);
405 wbc_status
= WBC_ERR_SUCCESS
;
408 if (response
.extra_data
.data
) {
409 free(response
.extra_data
.data
);
412 if (!WBC_ERROR_IS_OK(wbc_status
)) {
414 talloc_free(domain_name
);
420 *pp_domain_name
= domain_name
;