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/util.h"
29 /* Convert a Windows SID to a Unix uid, allocating an uid if needed */
30 wbcErr
wbcCtxSidToUid(struct wbcContext
*ctx
, const struct wbcDomainSid
*sid
,
37 wbc_status
= WBC_ERR_INVALID_PARAM
;
38 BAIL_ON_WBC_ERROR(wbc_status
);
41 wbc_status
= wbcCtxSidsToUnixIds(ctx
, sid
, 1, &xid
);
42 if (!WBC_ERROR_IS_OK(wbc_status
)) {
46 if ((xid
.type
== WBC_ID_TYPE_UID
) || (xid
.type
== WBC_ID_TYPE_BOTH
)) {
48 wbc_status
= WBC_ERR_SUCCESS
;
50 wbc_status
= WBC_ERR_DOMAIN_NOT_FOUND
;
57 wbcErr
wbcSidToUid(const struct wbcDomainSid
*sid
, uid_t
*puid
)
59 return wbcCtxSidToUid(NULL
, sid
, puid
);
62 /* Convert a Windows SID to a Unix uid if there already is a mapping */
63 wbcErr
wbcQuerySidToUid(const struct wbcDomainSid
*sid
,
66 return WBC_ERR_NOT_IMPLEMENTED
;
69 /* Convert a Unix uid to a Windows SID, allocating a SID if needed */
70 wbcErr
wbcCtxUidToSid(struct wbcContext
*ctx
, uid_t uid
,
71 struct wbcDomainSid
*psid
)
74 struct wbcDomainSid sid
;
75 struct wbcDomainSid null_sid
= { 0 };
79 wbc_status
= WBC_ERR_INVALID_PARAM
;
80 BAIL_ON_WBC_ERROR(wbc_status
);
83 xid
= (struct wbcUnixId
) { .type
= WBC_ID_TYPE_UID
, .id
.uid
= uid
};
85 wbc_status
= wbcCtxUnixIdsToSids(ctx
, &xid
, 1, &sid
);
86 if (!WBC_ERROR_IS_OK(wbc_status
)) {
90 if (memcmp(&sid
, &null_sid
, sizeof(sid
)) != 0) {
93 wbc_status
= WBC_ERR_DOMAIN_NOT_FOUND
;
100 wbcErr
wbcUidToSid(uid_t uid
, struct wbcDomainSid
*sid
)
102 return wbcCtxUidToSid(NULL
, uid
, sid
);
105 /* Convert a Unix uid to a Windows SID if there already is a mapping */
106 wbcErr
wbcQueryUidToSid(uid_t uid
,
107 struct wbcDomainSid
*sid
)
109 return WBC_ERR_NOT_IMPLEMENTED
;
112 /** @brief Convert a Windows SID to a Unix gid, allocating a gid if needed
114 * @param *sid Pointer to the domain SID to be resolved
115 * @param *pgid Pointer to the resolved gid_t value
121 wbcErr
wbcCtxSidToGid(struct wbcContext
*ctx
, const struct wbcDomainSid
*sid
,
124 struct wbcUnixId xid
;
128 wbc_status
= WBC_ERR_INVALID_PARAM
;
129 BAIL_ON_WBC_ERROR(wbc_status
);
132 wbc_status
= wbcCtxSidsToUnixIds(ctx
, sid
, 1, &xid
);
133 if (!WBC_ERROR_IS_OK(wbc_status
)) {
137 if ((xid
.type
== WBC_ID_TYPE_GID
) || (xid
.type
== WBC_ID_TYPE_BOTH
)) {
139 wbc_status
= WBC_ERR_SUCCESS
;
141 wbc_status
= WBC_ERR_DOMAIN_NOT_FOUND
;
148 wbcErr
wbcSidToGid(const struct wbcDomainSid
*sid
, gid_t
*pgid
)
150 return wbcCtxSidToGid(NULL
, sid
, pgid
);
153 /* Convert a Windows SID to a Unix gid if there already is a mapping */
155 wbcErr
wbcQuerySidToGid(const struct wbcDomainSid
*sid
,
158 return WBC_ERR_NOT_IMPLEMENTED
;
162 /* Convert a Unix gid to a Windows SID, allocating a SID if needed */
163 wbcErr
wbcCtxGidToSid(struct wbcContext
*ctx
, gid_t gid
,
164 struct wbcDomainSid
*psid
)
166 struct wbcUnixId xid
;
167 struct wbcDomainSid sid
;
168 struct wbcDomainSid null_sid
= { 0 };
172 wbc_status
= WBC_ERR_INVALID_PARAM
;
173 BAIL_ON_WBC_ERROR(wbc_status
);
176 xid
= (struct wbcUnixId
) { .type
= WBC_ID_TYPE_GID
, .id
.gid
= gid
};
178 wbc_status
= wbcCtxUnixIdsToSids(ctx
, &xid
, 1, &sid
);
179 if (!WBC_ERROR_IS_OK(wbc_status
)) {
183 if (memcmp(&sid
, &null_sid
, sizeof(sid
)) != 0) {
186 wbc_status
= WBC_ERR_DOMAIN_NOT_FOUND
;
193 wbcErr
wbcGidToSid(gid_t gid
, struct wbcDomainSid
*sid
)
195 return wbcCtxGidToSid(NULL
, gid
, sid
);
198 /* Convert a Unix gid to a Windows SID if there already is a mapping */
199 wbcErr
wbcQueryGidToSid(gid_t gid
,
200 struct wbcDomainSid
*sid
)
202 return WBC_ERR_NOT_IMPLEMENTED
;
205 /* Obtain a new uid from Winbind */
206 wbcErr
wbcCtxAllocateUid(struct wbcContext
*ctx
, uid_t
*puid
)
208 struct winbindd_request request
;
209 struct winbindd_response response
;
210 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
213 return WBC_ERR_INVALID_PARAM
;
215 /* Initialise request */
217 ZERO_STRUCT(request
);
218 ZERO_STRUCT(response
);
222 wbc_status
= wbcRequestResponsePriv(ctx
, WINBINDD_ALLOCATE_UID
,
223 &request
, &response
);
224 BAIL_ON_WBC_ERROR(wbc_status
);
226 /* Copy out result */
227 *puid
= response
.data
.uid
;
229 wbc_status
= WBC_ERR_SUCCESS
;
235 wbcErr
wbcAllocateUid(uid_t
*puid
)
237 return wbcCtxAllocateUid(NULL
, puid
);
240 /* Obtain a new gid from Winbind */
241 wbcErr
wbcCtxAllocateGid(struct wbcContext
*ctx
, gid_t
*pgid
)
243 struct winbindd_request request
;
244 struct winbindd_response response
;
245 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
248 return WBC_ERR_INVALID_PARAM
;
250 /* Initialise request */
252 ZERO_STRUCT(request
);
253 ZERO_STRUCT(response
);
257 wbc_status
= wbcRequestResponsePriv(ctx
, WINBINDD_ALLOCATE_GID
,
258 &request
, &response
);
259 BAIL_ON_WBC_ERROR(wbc_status
);
261 /* Copy out result */
262 *pgid
= response
.data
.gid
;
264 wbc_status
= WBC_ERR_SUCCESS
;
270 wbcErr
wbcAllocateGid(gid_t
*pgid
)
272 return wbcCtxAllocateGid(NULL
, pgid
);
275 /* we can't include smb.h here... */
276 #define _ID_TYPE_UID 1
277 #define _ID_TYPE_GID 2
279 /* Set an user id mapping - not implemented any more */
280 wbcErr
wbcSetUidMapping(uid_t uid
, const struct wbcDomainSid
*sid
)
282 return WBC_ERR_NOT_IMPLEMENTED
;
285 /* Set a group id mapping - not implemented any more */
286 wbcErr
wbcSetGidMapping(gid_t gid
, const struct wbcDomainSid
*sid
)
288 return WBC_ERR_NOT_IMPLEMENTED
;
291 /* Remove a user id mapping - not implemented any more */
292 wbcErr
wbcRemoveUidMapping(uid_t uid
, const struct wbcDomainSid
*sid
)
294 return WBC_ERR_NOT_IMPLEMENTED
;
297 /* Remove a group id mapping - not implemented any more */
298 wbcErr
wbcRemoveGidMapping(gid_t gid
, const struct wbcDomainSid
*sid
)
300 return WBC_ERR_NOT_IMPLEMENTED
;
303 /* Set the highwater mark for allocated uids - not implemented any more */
304 wbcErr
wbcSetUidHwm(uid_t uid_hwm
)
306 return WBC_ERR_NOT_IMPLEMENTED
;
309 /* Set the highwater mark for allocated gids - not implemented any more */
310 wbcErr
wbcSetGidHwm(gid_t gid_hwm
)
312 return WBC_ERR_NOT_IMPLEMENTED
;
315 /* Convert a list of SIDs */
316 wbcErr
wbcCtxSidsToUnixIds(struct wbcContext
*ctx
,
317 const struct wbcDomainSid
*sids
,
318 uint32_t num_sids
, struct wbcUnixId
*ids
)
320 struct winbindd_request request
;
321 struct winbindd_response response
;
322 wbcErr wbc_status
= WBC_ERR_UNKNOWN_FAILURE
;
323 int buflen
, extra_len
;
325 char *sidlist
, *p
, *extra_data
;
327 buflen
= num_sids
* (WBC_SID_STRING_BUFLEN
+ 1) + 1;
329 sidlist
= (char *)malloc(buflen
);
330 if (sidlist
== NULL
) {
331 return WBC_ERR_NO_MEMORY
;
336 for (i
=0; i
<num_sids
; i
++) {
340 remaining
= buflen
- (p
- sidlist
);
342 len
= wbcSidToStringBuf(&sids
[i
], p
, remaining
);
343 if (len
> remaining
) {
345 return WBC_ERR_UNKNOWN_FAILURE
;
353 ZERO_STRUCT(request
);
354 ZERO_STRUCT(response
);
356 request
.extra_data
.data
= sidlist
;
357 request
.extra_len
= p
- sidlist
;
359 wbc_status
= wbcRequestResponse(ctx
, WINBINDD_SIDS_TO_XIDS
,
360 &request
, &response
);
362 if (!WBC_ERROR_IS_OK(wbc_status
)) {
366 extra_len
= response
.length
- sizeof(struct winbindd_response
);
367 extra_data
= (char *)response
.extra_data
.data
;
369 if ((extra_len
<= 0) || (extra_data
[extra_len
-1] != '\0')) {
370 goto wbc_err_invalid
;
375 for (i
=0; i
<num_sids
; i
++) {
376 struct wbcUnixId
*id
= &ids
[i
];
382 id
->type
= WBC_ID_TYPE_UID
;
383 id
->id
.uid
= strtoul_err(p
+1, &q
, 10, &error
);
386 id
->type
= WBC_ID_TYPE_GID
;
387 id
->id
.gid
= strtoul_err(p
+1, &q
, 10, &error
);
390 id
->type
= WBC_ID_TYPE_BOTH
;
391 id
->id
.uid
= strtoul_err(p
+1, &q
, 10, &error
);
394 id
->type
= WBC_ID_TYPE_NOT_SPECIFIED
;
398 if (q
== NULL
|| q
[0] != '\n' || error
!= 0) {
399 goto wbc_err_invalid
;
403 wbc_status
= WBC_ERR_SUCCESS
;
407 wbc_status
= WBC_ERR_INVALID_RESPONSE
;
409 winbindd_free_response(&response
);
413 wbcErr
wbcSidsToUnixIds(const struct wbcDomainSid
*sids
, uint32_t num_sids
,
414 struct wbcUnixId
*ids
)
416 return wbcCtxSidsToUnixIds(NULL
, sids
, num_sids
, ids
);
419 wbcErr
wbcCtxUnixIdsToSids(struct wbcContext
*ctx
,
420 const struct wbcUnixId
*ids
, uint32_t num_ids
,
421 struct wbcDomainSid
*sids
)
423 struct winbindd_request request
;
424 struct winbindd_response response
;
428 const size_t sidlen
= (1 /* U/G */ + 10 /* 2^32 */ + 1 /* \n */);
432 if (num_ids
> SIZE_MAX
/ sidlen
) {
433 return WBC_ERR_NO_MEMORY
; /* overflow */
435 buflen
= num_ids
* sidlen
;
437 buflen
+= 1; /* trailing \0 */
439 return WBC_ERR_NO_MEMORY
; /* overflow */
442 buf
= malloc(buflen
);
444 return WBC_ERR_NO_MEMORY
;
449 for (i
=0; i
<num_ids
; i
++) {
450 const struct wbcUnixId
*id
= &ids
[i
];
454 case WBC_ID_TYPE_UID
:
455 len
= snprintf(buf
+ofs
, buflen
-ofs
, "U%"PRIu32
"\n",
456 (uint32_t)id
->id
.uid
);
458 case WBC_ID_TYPE_GID
:
459 len
= snprintf(buf
+ofs
, buflen
-ofs
, "G%"PRIu32
"\n",
460 (uint32_t)id
->id
.gid
);
464 return WBC_ERR_INVALID_PARAM
;
467 if (len
+ ofs
>= buflen
) { /* >= for the terminating '\0' */
469 return WBC_ERR_UNKNOWN_FAILURE
;
474 request
= (struct winbindd_request
) {
475 .extra_data
.data
= buf
, .extra_len
= ofs
+1
477 response
= (struct winbindd_response
) {0};
479 wbc_status
= wbcRequestResponse(ctx
, WINBINDD_XIDS_TO_SIDS
,
480 &request
, &response
);
482 if (!WBC_ERROR_IS_OK(wbc_status
)) {
486 s
= response
.extra_data
.data
;
487 for (i
=0; i
<num_ids
; i
++) {
488 char *n
= strchr(s
, '\n');
495 wbc_status
= wbcStringToSid(s
, &sids
[i
]);
496 if (!WBC_ERROR_IS_OK(wbc_status
)) {
497 sids
[i
] = (struct wbcDomainSid
) {0};
502 wbc_status
= WBC_ERR_SUCCESS
;
504 winbindd_free_response(&response
);
508 wbcErr
wbcUnixIdsToSids(const struct wbcUnixId
*ids
, uint32_t num_ids
,
509 struct wbcDomainSid
*sids
)
511 return wbcCtxUnixIdsToSids(NULL
, ids
, num_ids
, sids
);