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"
28 /* Convert a Windows SID to a Unix uid, allocating an uid if needed */
29 wbcErr
wbcCtxSidToUid(struct wbcContext
*ctx
, const struct wbcDomainSid
*sid
,
36 wbc_status
= WBC_ERR_INVALID_PARAM
;
37 BAIL_ON_WBC_ERROR(wbc_status
);
40 wbc_status
= wbcCtxSidsToUnixIds(ctx
, sid
, 1, &xid
);
41 if (!WBC_ERROR_IS_OK(wbc_status
)) {
45 if ((xid
.type
== WBC_ID_TYPE_UID
) || (xid
.type
== WBC_ID_TYPE_BOTH
)) {
47 wbc_status
= WBC_ERR_SUCCESS
;
49 wbc_status
= WBC_ERR_DOMAIN_NOT_FOUND
;
56 wbcErr
wbcSidToUid(const struct wbcDomainSid
*sid
, uid_t
*puid
)
58 return wbcCtxSidToUid(NULL
, sid
, puid
);
61 /* Convert a Windows SID to a Unix uid if there already is a mapping */
62 wbcErr
wbcQuerySidToUid(const struct wbcDomainSid
*sid
,
65 return WBC_ERR_NOT_IMPLEMENTED
;
68 /* Convert a Unix uid to a Windows SID, allocating a SID if needed */
69 wbcErr
wbcCtxUidToSid(struct wbcContext
*ctx
, uid_t uid
,
70 struct wbcDomainSid
*psid
)
73 struct wbcDomainSid sid
;
74 struct wbcDomainSid null_sid
= { 0 };
78 wbc_status
= WBC_ERR_INVALID_PARAM
;
79 BAIL_ON_WBC_ERROR(wbc_status
);
82 xid
= (struct wbcUnixId
) { .type
= WBC_ID_TYPE_UID
, .id
.uid
= uid
};
84 wbc_status
= wbcCtxUnixIdsToSids(ctx
, &xid
, 1, &sid
);
85 if (!WBC_ERROR_IS_OK(wbc_status
)) {
89 if (memcmp(&sid
, &null_sid
, sizeof(sid
)) != 0) {
92 wbc_status
= WBC_ERR_DOMAIN_NOT_FOUND
;
99 wbcErr
wbcUidToSid(uid_t uid
, struct wbcDomainSid
*sid
)
101 return wbcCtxUidToSid(NULL
, uid
, sid
);
104 /* Convert a Unix uid to a Windows SID if there already is a mapping */
105 wbcErr
wbcQueryUidToSid(uid_t uid
,
106 struct wbcDomainSid
*sid
)
108 return WBC_ERR_NOT_IMPLEMENTED
;
111 /** @brief Convert a Windows SID to a Unix gid, allocating a gid if needed
113 * @param *sid Pointer to the domain SID to be resolved
114 * @param *pgid Pointer to the resolved gid_t value
120 wbcErr
wbcCtxSidToGid(struct wbcContext
*ctx
, const struct wbcDomainSid
*sid
,
123 struct wbcUnixId xid
;
127 wbc_status
= WBC_ERR_INVALID_PARAM
;
128 BAIL_ON_WBC_ERROR(wbc_status
);
131 wbc_status
= wbcCtxSidsToUnixIds(ctx
, sid
, 1, &xid
);
132 if (!WBC_ERROR_IS_OK(wbc_status
)) {
136 if ((xid
.type
== WBC_ID_TYPE_GID
) || (xid
.type
== WBC_ID_TYPE_BOTH
)) {
138 wbc_status
= WBC_ERR_SUCCESS
;
140 wbc_status
= WBC_ERR_DOMAIN_NOT_FOUND
;
147 wbcErr
wbcSidToGid(const struct wbcDomainSid
*sid
, gid_t
*pgid
)
149 return wbcCtxSidToGid(NULL
, sid
, pgid
);
152 /* Convert a Windows SID to a Unix gid if there already is a mapping */
154 wbcErr
wbcQuerySidToGid(const struct wbcDomainSid
*sid
,
157 return WBC_ERR_NOT_IMPLEMENTED
;
161 /* Convert a Unix gid to a Windows SID, allocating a SID if needed */
162 wbcErr
wbcCtxGidToSid(struct wbcContext
*ctx
, gid_t gid
,
163 struct wbcDomainSid
*psid
)
165 struct wbcUnixId xid
;
166 struct wbcDomainSid sid
;
167 struct wbcDomainSid null_sid
= { 0 };
171 wbc_status
= WBC_ERR_INVALID_PARAM
;
172 BAIL_ON_WBC_ERROR(wbc_status
);
175 xid
= (struct wbcUnixId
) { .type
= WBC_ID_TYPE_GID
, .id
.gid
= gid
};
177 wbc_status
= wbcCtxUnixIdsToSids(ctx
, &xid
, 1, &sid
);
178 if (!WBC_ERROR_IS_OK(wbc_status
)) {
182 if (memcmp(&sid
, &null_sid
, sizeof(sid
)) != 0) {
185 wbc_status
= WBC_ERR_DOMAIN_NOT_FOUND
;
192 wbcErr
wbcGidToSid(gid_t gid
, struct wbcDomainSid
*sid
)
194 return wbcCtxGidToSid(NULL
, gid
, sid
);
197 /* Convert a Unix gid to a Windows SID if there already is a mapping */
198 wbcErr
wbcQueryGidToSid(gid_t gid
,
199 struct wbcDomainSid
*sid
)
201 return WBC_ERR_NOT_IMPLEMENTED
;
204 /* Obtain a new uid from Winbind */
205 wbcErr
wbcCtxAllocateUid(struct wbcContext
*ctx
, uid_t
*puid
)
207 struct winbindd_request request
;
208 struct winbindd_response response
;
209 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
212 return WBC_ERR_INVALID_PARAM
;
214 /* Initialise request */
216 ZERO_STRUCT(request
);
217 ZERO_STRUCT(response
);
221 wbc_status
= wbcRequestResponsePriv(ctx
, WINBINDD_ALLOCATE_UID
,
222 &request
, &response
);
223 BAIL_ON_WBC_ERROR(wbc_status
);
225 /* Copy out result */
226 *puid
= response
.data
.uid
;
228 wbc_status
= WBC_ERR_SUCCESS
;
234 wbcErr
wbcAllocateUid(uid_t
*puid
)
236 return wbcCtxAllocateUid(NULL
, puid
);
239 /* Obtain a new gid from Winbind */
240 wbcErr
wbcCtxAllocateGid(struct wbcContext
*ctx
, gid_t
*pgid
)
242 struct winbindd_request request
;
243 struct winbindd_response response
;
244 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
247 return WBC_ERR_INVALID_PARAM
;
249 /* Initialise request */
251 ZERO_STRUCT(request
);
252 ZERO_STRUCT(response
);
256 wbc_status
= wbcRequestResponsePriv(ctx
, WINBINDD_ALLOCATE_GID
,
257 &request
, &response
);
258 BAIL_ON_WBC_ERROR(wbc_status
);
260 /* Copy out result */
261 *pgid
= response
.data
.gid
;
263 wbc_status
= WBC_ERR_SUCCESS
;
269 wbcErr
wbcAllocateGid(gid_t
*pgid
)
271 return wbcCtxAllocateGid(NULL
, pgid
);
274 /* we can't include smb.h here... */
275 #define _ID_TYPE_UID 1
276 #define _ID_TYPE_GID 2
278 /* Set an user id mapping - not implemented any more */
279 wbcErr
wbcSetUidMapping(uid_t uid
, const struct wbcDomainSid
*sid
)
281 return WBC_ERR_NOT_IMPLEMENTED
;
284 /* Set a group id mapping - not implemented any more */
285 wbcErr
wbcSetGidMapping(gid_t gid
, const struct wbcDomainSid
*sid
)
287 return WBC_ERR_NOT_IMPLEMENTED
;
290 /* Remove a user id mapping - not implemented any more */
291 wbcErr
wbcRemoveUidMapping(uid_t uid
, const struct wbcDomainSid
*sid
)
293 return WBC_ERR_NOT_IMPLEMENTED
;
296 /* Remove a group id mapping - not implemented any more */
297 wbcErr
wbcRemoveGidMapping(gid_t gid
, const struct wbcDomainSid
*sid
)
299 return WBC_ERR_NOT_IMPLEMENTED
;
302 /* Set the highwater mark for allocated uids - not implemented any more */
303 wbcErr
wbcSetUidHwm(uid_t uid_hwm
)
305 return WBC_ERR_NOT_IMPLEMENTED
;
308 /* Set the highwater mark for allocated gids - not implemented any more */
309 wbcErr
wbcSetGidHwm(gid_t gid_hwm
)
311 return WBC_ERR_NOT_IMPLEMENTED
;
314 /* Convert a list of SIDs */
315 wbcErr
wbcCtxSidsToUnixIds(struct wbcContext
*ctx
,
316 const struct wbcDomainSid
*sids
,
317 uint32_t num_sids
, struct wbcUnixId
*ids
)
319 struct winbindd_request request
;
320 struct winbindd_response response
;
321 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
322 int buflen
, extra_len
;
324 char *sidlist
, *p
, *extra_data
;
326 buflen
= num_sids
* (WBC_SID_STRING_BUFLEN
+ 1) + 1;
328 sidlist
= (char *)malloc(buflen
);
329 if (sidlist
== NULL
) {
330 return WBC_ERR_NO_MEMORY
;
335 for (i
=0; i
<num_sids
; i
++) {
339 remaining
= buflen
- (p
- sidlist
);
341 len
= wbcSidToStringBuf(&sids
[i
], p
, remaining
);
342 if (len
> remaining
) {
344 return WBC_ERR_UNKNOWN_FAILURE
;
352 ZERO_STRUCT(request
);
353 ZERO_STRUCT(response
);
355 request
.extra_data
.data
= sidlist
;
356 request
.extra_len
= p
- sidlist
;
358 wbc_status
= wbcRequestResponse(ctx
, WINBINDD_SIDS_TO_XIDS
,
359 &request
, &response
);
361 if (!WBC_ERROR_IS_OK(wbc_status
)) {
365 extra_len
= response
.length
- sizeof(struct winbindd_response
);
366 extra_data
= (char *)response
.extra_data
.data
;
368 if ((extra_len
<= 0) || (extra_data
[extra_len
-1] != '\0')) {
369 goto wbc_err_invalid
;
374 for (i
=0; i
<num_sids
; i
++) {
375 struct wbcUnixId
*id
= &ids
[i
];
380 id
->type
= WBC_ID_TYPE_UID
;
381 id
->id
.uid
= strtoul(p
+1, &q
, 10);
384 id
->type
= WBC_ID_TYPE_GID
;
385 id
->id
.gid
= strtoul(p
+1, &q
, 10);
388 id
->type
= WBC_ID_TYPE_BOTH
;
389 id
->id
.uid
= strtoul(p
+1, &q
, 10);
392 id
->type
= WBC_ID_TYPE_NOT_SPECIFIED
;
396 if (q
== NULL
|| q
[0] != '\n') {
397 goto wbc_err_invalid
;
401 wbc_status
= WBC_ERR_SUCCESS
;
405 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
407 winbindd_free_response(&response
);
411 wbcErr
wbcSidsToUnixIds(const struct wbcDomainSid
*sids
, uint32_t num_sids
,
412 struct wbcUnixId
*ids
)
414 return wbcCtxSidsToUnixIds(NULL
, sids
, num_sids
, ids
);
417 wbcErr
wbcCtxUnixIdsToSids(struct wbcContext
*ctx
,
418 const struct wbcUnixId
*ids
, uint32_t num_ids
,
419 struct wbcDomainSid
*sids
)
421 struct winbindd_request request
;
422 struct winbindd_response response
;
429 buflen
= num_ids
* (1 /* U/G */ + 10 /* 2^32 */ + 1 /* \n */) + 1;
430 buf
= malloc(buflen
);
432 return WBC_ERR_NO_MEMORY
;
437 for (i
=0; i
<num_ids
; i
++) {
438 const struct wbcUnixId
*id
= &ids
[i
];
442 case WBC_ID_TYPE_UID
:
443 len
= snprintf(buf
+ofs
, buflen
-ofs
, "U%"PRIu32
"\n",
444 (uint32_t)id
->id
.uid
);
446 case WBC_ID_TYPE_GID
:
447 len
= snprintf(buf
+ofs
, buflen
-ofs
, "G%"PRIu32
"\n",
448 (uint32_t)id
->id
.gid
);
452 return WBC_ERR_INVALID_PARAM
;
455 if (len
+ ofs
>= buflen
) { /* >= for the terminating '\0' */
457 return WBC_ERR_UNKNOWN_FAILURE
;
462 request
= (struct winbindd_request
) {
463 .extra_data
.data
= buf
, .extra_len
= ofs
+1
465 response
= (struct winbindd_response
) {0};
467 wbc_status
= wbcRequestResponse(ctx
, WINBINDD_XIDS_TO_SIDS
,
468 &request
, &response
);
470 if (!WBC_ERROR_IS_OK(wbc_status
)) {
474 s
= response
.extra_data
.data
;
475 for (i
=0; i
<num_ids
; i
++) {
476 char *n
= strchr(s
, '\n');
483 wbc_status
= wbcStringToSid(s
, &sids
[i
]);
484 if (!WBC_ERROR_IS_OK(wbc_status
)) {
485 sids
[i
] = (struct wbcDomainSid
) {0};
490 wbc_status
= WBC_ERR_SUCCESS
;
492 winbindd_free_response(&response
);
496 wbcErr
wbcUnixIdsToSids(const struct wbcUnixId
*ids
, uint32_t num_ids
,
497 struct wbcDomainSid
*sids
)
499 return wbcCtxUnixIdsToSids(NULL
, ids
, num_ids
, sids
);