2 Unix SMB/CIFS implementation.
6 Copyright (C) Gerald (Jerry) Carter 2007
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public
10 License as published by the Free Software Foundation; either
11 version 3 of the License, or (at your option) any later version.
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Library General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 /* Required Headers */
25 #include "libwbclient.h"
26 #include "../winbind_client.h"
27 #include "lib/util/smb_strtox.h"
29 /* Convert a Windows SID to a Unix uid, allocating an uid if needed */
31 wbcErr
wbcCtxSidToUid(struct wbcContext
*ctx
, const struct wbcDomainSid
*sid
,
38 wbc_status
= WBC_ERR_INVALID_PARAM
;
39 BAIL_ON_WBC_ERROR(wbc_status
);
42 wbc_status
= wbcCtxSidsToUnixIds(ctx
, sid
, 1, &xid
);
43 if (!WBC_ERROR_IS_OK(wbc_status
)) {
47 if ((xid
.type
== WBC_ID_TYPE_UID
) || (xid
.type
== WBC_ID_TYPE_BOTH
)) {
49 wbc_status
= WBC_ERR_SUCCESS
;
51 wbc_status
= WBC_ERR_DOMAIN_NOT_FOUND
;
59 wbcErr
wbcSidToUid(const struct wbcDomainSid
*sid
, uid_t
*puid
)
61 return wbcCtxSidToUid(NULL
, sid
, puid
);
64 /* Convert a Windows SID to a Unix uid if there already is a mapping */
66 wbcErr
wbcQuerySidToUid(const struct wbcDomainSid
*sid
,
69 return WBC_ERR_NOT_IMPLEMENTED
;
72 /* Convert a Unix uid to a Windows SID, allocating a SID if needed */
74 wbcErr
wbcCtxUidToSid(struct wbcContext
*ctx
, uid_t uid
,
75 struct wbcDomainSid
*psid
)
78 struct wbcDomainSid sid
;
79 struct wbcDomainSid null_sid
= { 0 };
83 wbc_status
= WBC_ERR_INVALID_PARAM
;
84 BAIL_ON_WBC_ERROR(wbc_status
);
87 xid
= (struct wbcUnixId
) { .type
= WBC_ID_TYPE_UID
, .id
.uid
= uid
};
89 wbc_status
= wbcCtxUnixIdsToSids(ctx
, &xid
, 1, &sid
);
90 if (!WBC_ERROR_IS_OK(wbc_status
)) {
94 if (memcmp(&sid
, &null_sid
, sizeof(sid
)) != 0) {
97 wbc_status
= WBC_ERR_DOMAIN_NOT_FOUND
;
105 wbcErr
wbcUidToSid(uid_t uid
, struct wbcDomainSid
*sid
)
107 return wbcCtxUidToSid(NULL
, uid
, sid
);
110 /* Convert a Unix uid to a Windows SID if there already is a mapping */
112 wbcErr
wbcQueryUidToSid(uid_t uid
,
113 struct wbcDomainSid
*sid
)
115 return WBC_ERR_NOT_IMPLEMENTED
;
118 /** @brief Convert a Windows SID to a Unix gid, allocating a gid if needed
120 * @param *sid Pointer to the domain SID to be resolved
121 * @param *pgid Pointer to the resolved gid_t value
128 wbcErr
wbcCtxSidToGid(struct wbcContext
*ctx
, const struct wbcDomainSid
*sid
,
131 struct wbcUnixId xid
;
135 wbc_status
= WBC_ERR_INVALID_PARAM
;
136 BAIL_ON_WBC_ERROR(wbc_status
);
139 wbc_status
= wbcCtxSidsToUnixIds(ctx
, sid
, 1, &xid
);
140 if (!WBC_ERROR_IS_OK(wbc_status
)) {
144 if ((xid
.type
== WBC_ID_TYPE_GID
) || (xid
.type
== WBC_ID_TYPE_BOTH
)) {
146 wbc_status
= WBC_ERR_SUCCESS
;
148 wbc_status
= WBC_ERR_DOMAIN_NOT_FOUND
;
156 wbcErr
wbcSidToGid(const struct wbcDomainSid
*sid
, gid_t
*pgid
)
158 return wbcCtxSidToGid(NULL
, sid
, pgid
);
161 /* Convert a Windows SID to a Unix gid if there already is a mapping */
164 wbcErr
wbcQuerySidToGid(const struct wbcDomainSid
*sid
,
167 return WBC_ERR_NOT_IMPLEMENTED
;
171 /* Convert a Unix gid to a Windows SID, allocating a SID if needed */
173 wbcErr
wbcCtxGidToSid(struct wbcContext
*ctx
, gid_t gid
,
174 struct wbcDomainSid
*psid
)
176 struct wbcUnixId xid
;
177 struct wbcDomainSid sid
;
178 struct wbcDomainSid null_sid
= { 0 };
182 wbc_status
= WBC_ERR_INVALID_PARAM
;
183 BAIL_ON_WBC_ERROR(wbc_status
);
186 xid
= (struct wbcUnixId
) { .type
= WBC_ID_TYPE_GID
, .id
.gid
= gid
};
188 wbc_status
= wbcCtxUnixIdsToSids(ctx
, &xid
, 1, &sid
);
189 if (!WBC_ERROR_IS_OK(wbc_status
)) {
193 if (memcmp(&sid
, &null_sid
, sizeof(sid
)) != 0) {
196 wbc_status
= WBC_ERR_DOMAIN_NOT_FOUND
;
204 wbcErr
wbcGidToSid(gid_t gid
, struct wbcDomainSid
*sid
)
206 return wbcCtxGidToSid(NULL
, gid
, sid
);
209 /* Convert a Unix gid to a Windows SID if there already is a mapping */
211 wbcErr
wbcQueryGidToSid(gid_t gid
,
212 struct wbcDomainSid
*sid
)
214 return WBC_ERR_NOT_IMPLEMENTED
;
217 /* Obtain a new uid from Winbind */
219 wbcErr
wbcCtxAllocateUid(struct wbcContext
*ctx
, uid_t
*puid
)
221 struct winbindd_request request
;
222 struct winbindd_response response
;
223 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
226 return WBC_ERR_INVALID_PARAM
;
228 /* Initialise request */
230 ZERO_STRUCT(request
);
231 ZERO_STRUCT(response
);
235 wbc_status
= wbcRequestResponsePriv(ctx
, WINBINDD_ALLOCATE_UID
,
236 &request
, &response
);
237 BAIL_ON_WBC_ERROR(wbc_status
);
239 /* Copy out result */
240 *puid
= response
.data
.uid
;
242 wbc_status
= WBC_ERR_SUCCESS
;
249 wbcErr
wbcAllocateUid(uid_t
*puid
)
251 return wbcCtxAllocateUid(NULL
, puid
);
254 /* Obtain a new gid from Winbind */
256 wbcErr
wbcCtxAllocateGid(struct wbcContext
*ctx
, gid_t
*pgid
)
258 struct winbindd_request request
;
259 struct winbindd_response response
;
260 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
263 return WBC_ERR_INVALID_PARAM
;
265 /* Initialise request */
267 ZERO_STRUCT(request
);
268 ZERO_STRUCT(response
);
272 wbc_status
= wbcRequestResponsePriv(ctx
, WINBINDD_ALLOCATE_GID
,
273 &request
, &response
);
274 BAIL_ON_WBC_ERROR(wbc_status
);
276 /* Copy out result */
277 *pgid
= response
.data
.gid
;
279 wbc_status
= WBC_ERR_SUCCESS
;
286 wbcErr
wbcAllocateGid(gid_t
*pgid
)
288 return wbcCtxAllocateGid(NULL
, pgid
);
291 /* we can't include smb.h here... */
292 #define _ID_TYPE_UID 1
293 #define _ID_TYPE_GID 2
295 /* Set an user id mapping - not implemented any more */
297 wbcErr
wbcSetUidMapping(uid_t uid
, const struct wbcDomainSid
*sid
)
299 return WBC_ERR_NOT_IMPLEMENTED
;
302 /* Set a group id mapping - not implemented any more */
304 wbcErr
wbcSetGidMapping(gid_t gid
, const struct wbcDomainSid
*sid
)
306 return WBC_ERR_NOT_IMPLEMENTED
;
309 /* Remove a user id mapping - not implemented any more */
311 wbcErr
wbcRemoveUidMapping(uid_t uid
, const struct wbcDomainSid
*sid
)
313 return WBC_ERR_NOT_IMPLEMENTED
;
316 /* Remove a group id mapping - not implemented any more */
318 wbcErr
wbcRemoveGidMapping(gid_t gid
, const struct wbcDomainSid
*sid
)
320 return WBC_ERR_NOT_IMPLEMENTED
;
323 /* Set the highwater mark for allocated uids - not implemented any more */
325 wbcErr
wbcSetUidHwm(uid_t uid_hwm
)
327 return WBC_ERR_NOT_IMPLEMENTED
;
330 /* Set the highwater mark for allocated gids - not implemented any more */
332 wbcErr
wbcSetGidHwm(gid_t gid_hwm
)
334 return WBC_ERR_NOT_IMPLEMENTED
;
337 /* Convert a list of SIDs */
339 wbcErr
wbcCtxSidsToUnixIds(struct wbcContext
*ctx
,
340 const struct wbcDomainSid
*sids
,
341 uint32_t num_sids
, struct wbcUnixId
*ids
)
343 struct winbindd_request request
;
344 struct winbindd_response response
;
345 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
346 int buflen
, extra_len
;
348 char *sidlist
, *p
, *extra_data
;
350 buflen
= num_sids
* (WBC_SID_STRING_BUFLEN
+ 1) + 1;
352 sidlist
= (char *)malloc(buflen
);
353 if (sidlist
== NULL
) {
354 return WBC_ERR_NO_MEMORY
;
359 for (i
=0; i
<num_sids
; i
++) {
363 remaining
= buflen
- (p
- sidlist
);
365 len
= wbcSidToStringBuf(&sids
[i
], p
, remaining
);
366 if (len
> remaining
) {
368 return WBC_ERR_UNKNOWN_FAILURE
;
376 ZERO_STRUCT(request
);
377 ZERO_STRUCT(response
);
379 request
.extra_data
.data
= sidlist
;
380 request
.extra_len
= p
- sidlist
;
382 wbc_status
= wbcRequestResponse(ctx
, WINBINDD_SIDS_TO_XIDS
,
383 &request
, &response
);
385 if (!WBC_ERROR_IS_OK(wbc_status
)) {
389 extra_len
= response
.length
- sizeof(struct winbindd_response
);
390 extra_data
= (char *)response
.extra_data
.data
;
392 if ((extra_len
<= 0) || (extra_data
[extra_len
-1] != '\0')) {
393 goto wbc_err_invalid
;
398 for (i
=0; i
<num_sids
; i
++) {
399 struct wbcUnixId
*id
= &ids
[i
];
405 id
->type
= WBC_ID_TYPE_UID
;
406 id
->id
.uid
= smb_strtoul(p
+1,
413 id
->type
= WBC_ID_TYPE_GID
;
414 id
->id
.gid
= smb_strtoul(p
+1,
421 id
->type
= WBC_ID_TYPE_BOTH
;
422 id
->id
.uid
= smb_strtoul(p
+1,
429 id
->type
= WBC_ID_TYPE_NOT_SPECIFIED
;
433 if (q
== NULL
|| q
[0] != '\n' || error
!= 0) {
434 goto wbc_err_invalid
;
438 wbc_status
= WBC_ERR_SUCCESS
;
442 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
444 winbindd_free_response(&response
);
449 wbcErr
wbcSidsToUnixIds(const struct wbcDomainSid
*sids
, uint32_t num_sids
,
450 struct wbcUnixId
*ids
)
452 return wbcCtxSidsToUnixIds(NULL
, sids
, num_sids
, ids
);
456 wbcErr
wbcCtxUnixIdsToSids(struct wbcContext
*ctx
,
457 const struct wbcUnixId
*ids
, uint32_t num_ids
,
458 struct wbcDomainSid
*sids
)
460 struct winbindd_request request
;
461 struct winbindd_response response
;
465 const size_t sidlen
= (1 /* U/G */ + 10 /* 2^32 */ + 1 /* \n */);
469 if (num_ids
> SIZE_MAX
/ sidlen
) {
470 return WBC_ERR_NO_MEMORY
; /* overflow */
472 buflen
= num_ids
* sidlen
;
474 buflen
+= 1; /* trailing \0 */
476 return WBC_ERR_NO_MEMORY
; /* overflow */
479 buf
= malloc(buflen
);
481 return WBC_ERR_NO_MEMORY
;
486 for (i
=0; i
<num_ids
; i
++) {
487 const struct wbcUnixId
*id
= &ids
[i
];
491 case WBC_ID_TYPE_UID
:
492 len
= snprintf(buf
+ofs
, buflen
-ofs
, "U%"PRIu32
"\n",
493 (uint32_t)id
->id
.uid
);
495 case WBC_ID_TYPE_GID
:
496 len
= snprintf(buf
+ofs
, buflen
-ofs
, "G%"PRIu32
"\n",
497 (uint32_t)id
->id
.gid
);
501 return WBC_ERR_INVALID_PARAM
;
504 if (len
+ ofs
>= buflen
) { /* >= for the terminating '\0' */
506 return WBC_ERR_UNKNOWN_FAILURE
;
511 request
= (struct winbindd_request
) {
512 .extra_data
.data
= buf
, .extra_len
= ofs
+1
514 response
= (struct winbindd_response
) {0};
516 wbc_status
= wbcRequestResponse(ctx
, WINBINDD_XIDS_TO_SIDS
,
517 &request
, &response
);
519 if (!WBC_ERROR_IS_OK(wbc_status
)) {
523 s
= response
.extra_data
.data
;
524 for (i
=0; i
<num_ids
; i
++) {
525 char *n
= strchr(s
, '\n');
532 wbc_status
= wbcStringToSid(s
, &sids
[i
]);
533 if (!WBC_ERROR_IS_OK(wbc_status
)) {
534 sids
[i
] = (struct wbcDomainSid
) {0};
539 wbc_status
= WBC_ERR_SUCCESS
;
541 winbindd_free_response(&response
);
546 wbcErr
wbcUnixIdsToSids(const struct wbcUnixId
*ids
, uint32_t num_ids
,
547 struct wbcDomainSid
*sids
)
549 return wbcCtxUnixIdsToSids(NULL
, ids
, num_ids
, sids
);