]>
Commit | Line | Data |
---|---|---|
c29f2fcc | 1 | /* |
e44d8d47 | 2 | * Copyright (c) 2004-2010 Apple Inc. All rights reserved. |
c29f2fcc A |
3 | * |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
6 | * The contents of this file constitute Original Code as defined in and | |
7 | * are subject to the Apple Public Source License Version 1.1 (the | |
8 | * "License"). You may not use this file except in compliance with the | |
9 | * License. Please obtain a copy of the License at | |
10 | * http://www.apple.com/publicsource and read it before using this file. | |
11 | * | |
12 | * This Original Code and all software distributed under the License are | |
13 | * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
14 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
15 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
16 | * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the | |
17 | * License for the specific language governing rights and limitations | |
18 | * under the License. | |
19 | * | |
20 | * @APPLE_LICENSE_HEADER_END@ | |
21 | */ | |
22 | ||
d49d4c81 | 23 | #include <stdlib.h> |
c29f2fcc | 24 | #include <sys/errno.h> |
c29f2fcc | 25 | #include <mach/mach.h> |
d49d4c81 A |
26 | #include "membership.h" |
27 | #include "membershipPriv.h" | |
b3dd680f | 28 | #include <servers/bootstrap.h> |
caa31c11 | 29 | #include <libkern/OSByteOrder.h> |
d49d4c81 | 30 | #ifdef DS_AVAILABLE |
d31dd049 A |
31 | #include <xpc/xpc.h> |
32 | #include <xpc/private.h> | |
33 | #include <opendirectory/odipc.h> | |
34 | #include <pthread.h> | |
0eb52ff2 A |
35 | #include <mach-o/dyld_priv.h> |
36 | #endif | |
b3dd680f | 37 | |
e44d8d47 A |
38 | static const uuid_t _user_compat_prefix = {0xff, 0xff, 0xee, 0xee, 0xdd, 0xdd, 0xcc, 0xcc, 0xbb, 0xbb, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00}; |
39 | static const uuid_t _group_compat_prefix = {0xab, 0xcd, 0xef, 0xab, 0xcd, 0xef, 0xab, 0xcd, 0xef, 0xab, 0xcd, 0xef, 0x00, 0x00, 0x00, 0x00}; | |
40 | ||
41 | #define COMPAT_PREFIX_LEN (sizeof(uuid_t) - sizeof(id_t)) | |
b3dd680f | 42 | |
d31dd049 A |
43 | #ifdef DS_AVAILABLE |
44 | ||
45 | int _si_opendirectory_disabled; | |
46 | static xpc_pipe_t __mbr_pipe; /* use accessor */ | |
47 | static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; | |
48 | __private_extern__ xpc_object_t _od_rpc_call(const char *procname, xpc_object_t payload, xpc_pipe_t (*get_pipe)(bool)); | |
49 | ||
d49d4c81 | 50 | #endif |
b3dd680f | 51 | |
d31dd049 A |
52 | #ifdef DS_AVAILABLE |
53 | static void | |
54 | _mbr_fork_child(void) | |
c29f2fcc | 55 | { |
d31dd049 A |
56 | if (__mbr_pipe != NULL) { |
57 | xpc_pipe_invalidate(__mbr_pipe); | |
58 | /* disable release due to 10649340, it will cause a minor leak for each fork without exec */ | |
59 | // xpc_release(__mbr_pipe); | |
60 | __mbr_pipe = NULL; | |
61 | } | |
62 | ||
63 | pthread_mutex_unlock(&mutex); | |
b3dd680f | 64 | } |
d31dd049 | 65 | #endif |
caa31c11 | 66 | |
d49d4c81 | 67 | #ifdef DS_AVAILABLE |
d31dd049 A |
68 | static void |
69 | _mbr_fork_prepare(void) | |
b3dd680f | 70 | { |
d31dd049 | 71 | pthread_mutex_lock(&mutex); |
b3dd680f | 72 | } |
d49d4c81 | 73 | #endif |
b3dd680f | 74 | |
d49d4c81 | 75 | #ifdef DS_AVAILABLE |
d31dd049 A |
76 | static void |
77 | _mbr_fork_parent(void) | |
b3dd680f | 78 | { |
d31dd049 | 79 | pthread_mutex_unlock(&mutex); |
b3dd680f | 80 | } |
d49d4c81 | 81 | #endif |
b3dd680f | 82 | |
d49d4c81 | 83 | #ifdef DS_AVAILABLE |
d31dd049 A |
84 | XPC_RETURNS_RETAINED |
85 | static xpc_pipe_t | |
86 | _mbr_xpc_pipe(bool resetPipe) | |
b3dd680f | 87 | { |
d31dd049 A |
88 | static dispatch_once_t once; |
89 | xpc_pipe_t pipe = NULL; | |
0eb52ff2 | 90 | |
d31dd049 | 91 | dispatch_once(&once, ^(void) { |
0eb52ff2 | 92 | char *xbs_disable; |
d31dd049 A |
93 | |
94 | /* if this is a build environment we ignore opendirectoryd */ | |
0eb52ff2 A |
95 | xbs_disable = getenv("XBS_DISABLE_LIBINFO"); |
96 | if (xbs_disable != NULL && strcmp(xbs_disable, "YES") == 0) { | |
d31dd049 A |
97 | _si_opendirectory_disabled = 1; |
98 | return; | |
b3dd680f | 99 | } |
d31dd049 A |
100 | |
101 | pthread_atfork(_mbr_fork_prepare, _mbr_fork_parent, _mbr_fork_child); | |
102 | }); | |
103 | ||
104 | if (_si_opendirectory_disabled == 1) { | |
105 | return NULL; | |
b3dd680f | 106 | } |
d31dd049 A |
107 | |
108 | pthread_mutex_lock(&mutex); | |
109 | if (resetPipe) { | |
110 | xpc_release(__mbr_pipe); | |
111 | __mbr_pipe = NULL; | |
112 | } | |
113 | ||
114 | if (__mbr_pipe == NULL) { | |
0eb52ff2 | 115 | if (!dyld_process_is_restricted() && getenv("OD_DEBUG_MODE") != NULL) { |
d31dd049 A |
116 | __mbr_pipe = xpc_pipe_create(kODMachMembershipPortNameDebug, 0); |
117 | } else { | |
118 | __mbr_pipe = xpc_pipe_create(kODMachMembershipPortName, XPC_PIPE_FLAG_PRIVILEGED); | |
119 | } | |
120 | } | |
121 | ||
122 | if (__mbr_pipe != NULL) pipe = xpc_retain(__mbr_pipe); | |
123 | pthread_mutex_unlock(&mutex); | |
124 | ||
125 | return pipe; | |
c29f2fcc | 126 | } |
d49d4c81 | 127 | #endif |
c29f2fcc | 128 | |
d31dd049 A |
129 | static bool |
130 | _mbr_od_available(void) | |
e44d8d47 | 131 | { |
d31dd049 A |
132 | #if DS_AVAILABLE |
133 | xpc_pipe_t pipe = _mbr_xpc_pipe(false); | |
134 | if (pipe != NULL) { | |
135 | xpc_release(pipe); | |
136 | return true; | |
137 | } | |
138 | #endif | |
139 | return false; | |
140 | } | |
141 | ||
142 | int | |
143 | mbr_identifier_translate(int id_type, const void *identifier, size_t identifier_size, int target_type, void **result, int *rec_type) | |
144 | { | |
145 | #if DS_AVAILABLE | |
146 | xpc_object_t payload, reply; | |
147 | #endif | |
148 | id_t tempID; | |
149 | size_t identifier_len; | |
150 | int rc = EIO; | |
e44d8d47 | 151 | |
d31dd049 | 152 | if (identifier == NULL || result == NULL || identifier_size == 0) return EIO; |
e44d8d47 | 153 | |
d31dd049 A |
154 | if (identifier_size == -1) { |
155 | identifier_size = strlen(identifier); | |
156 | } else { | |
157 | /* 10898647: For types that are known to be strings, send the smallest necessary amount of data. */ | |
158 | switch (id_type) { | |
159 | case ID_TYPE_USERNAME: | |
160 | case ID_TYPE_GROUPNAME: | |
161 | case ID_TYPE_GROUP_NFS: | |
162 | case ID_TYPE_USER_NFS: | |
163 | case ID_TYPE_X509_DN: | |
164 | case ID_TYPE_KERBEROS: | |
165 | case ID_TYPE_NAME: | |
166 | identifier_len = strlen(identifier); | |
167 | if (identifier_size > identifier_len) { | |
168 | identifier_size = identifier_len; | |
169 | } | |
170 | break; | |
171 | } | |
172 | } | |
173 | ||
174 | switch (target_type) { | |
175 | case ID_TYPE_GID: | |
176 | case ID_TYPE_UID: | |
177 | case ID_TYPE_UID_OR_GID: | |
178 | /* shortcut UUIDs using compatibilty prefixes */ | |
179 | if (id_type == ID_TYPE_UUID) { | |
180 | const uint8_t *uu = identifier; | |
181 | ||
182 | if (identifier_size != sizeof(uuid_t)) return EINVAL; | |
183 | ||
184 | if (memcmp(uu, _user_compat_prefix, COMPAT_PREFIX_LEN) == 0) { | |
185 | id_t *tempRes = malloc(sizeof(*tempRes)); | |
186 | memcpy(&tempID, &uu[COMPAT_PREFIX_LEN], sizeof(tempID)); | |
187 | (*tempRes) = ntohl(tempID); | |
188 | (*result) = tempRes; | |
189 | if (rec_type != NULL) { | |
190 | (*rec_type) = MBR_REC_TYPE_USER; | |
191 | } | |
192 | return 0; | |
193 | } else if (memcmp(uu, _group_compat_prefix, COMPAT_PREFIX_LEN) == 0) { | |
194 | id_t *tempRes = malloc(sizeof(*tempRes)); | |
195 | memcpy(&tempID, &uu[COMPAT_PREFIX_LEN], sizeof(tempID)); | |
196 | (*tempRes) = ntohl(tempID); | |
197 | (*result) = tempRes; | |
198 | if (rec_type != NULL) { | |
199 | (*rec_type) = MBR_REC_TYPE_GROUP; | |
200 | } | |
201 | return 0; | |
202 | } | |
203 | } | |
204 | break; | |
205 | ||
206 | case ID_TYPE_UUID: | |
207 | /* if this is a UID or GID translation, we shortcut UID/GID 0 */ | |
208 | /* or if no OD, we return compatibility UUIDs */ | |
209 | switch (id_type) { | |
210 | case ID_TYPE_UID: | |
211 | if (identifier_size != sizeof(tempID)) return EINVAL; | |
212 | ||
213 | tempID = *((id_t *) identifier); | |
214 | if ((tempID == 0) || (_mbr_od_available() == false)) { | |
215 | uint8_t *tempUU = malloc(sizeof(uuid_t)); | |
216 | uuid_copy(tempUU, _user_compat_prefix); | |
217 | *((id_t *) &tempUU[COMPAT_PREFIX_LEN]) = htonl(tempID); | |
218 | (*result) = tempUU; | |
219 | if (rec_type != NULL) { | |
220 | (*rec_type) = MBR_REC_TYPE_USER; | |
221 | } | |
222 | return 0; | |
223 | } | |
224 | break; | |
225 | ||
226 | case ID_TYPE_GID: | |
227 | if (identifier_size != sizeof(tempID)) return EINVAL; | |
228 | ||
229 | tempID = *((id_t *) identifier); | |
230 | if ((tempID == 0) || (_mbr_od_available() == false)) { | |
231 | uint8_t *tempUU = malloc(sizeof(uuid_t)); | |
232 | uuid_copy(tempUU, _group_compat_prefix); | |
233 | *((id_t *) &tempUU[COMPAT_PREFIX_LEN]) = htonl(tempID); | |
234 | (*result) = tempUU; | |
235 | if (rec_type != NULL) { | |
236 | (*rec_type) = MBR_REC_TYPE_GROUP; | |
237 | } | |
238 | return 0; | |
239 | } | |
240 | break; | |
241 | } | |
242 | break; | |
243 | } | |
244 | ||
245 | #if DS_AVAILABLE | |
246 | payload = xpc_dictionary_create(NULL, NULL, 0); | |
247 | if (payload == NULL) return EIO; | |
248 | ||
249 | xpc_dictionary_set_int64(payload, "requesting", target_type); | |
250 | xpc_dictionary_set_int64(payload, "type", id_type); | |
251 | xpc_dictionary_set_data(payload, "identifier", identifier, identifier_size); | |
252 | ||
253 | reply = _od_rpc_call("mbr_identifier_translate", payload, _mbr_xpc_pipe); | |
254 | if (reply != NULL) { | |
255 | const void *reply_id; | |
256 | size_t idLen; | |
257 | ||
258 | rc = (int) xpc_dictionary_get_int64(reply, "error"); | |
259 | if (rc == 0) { | |
260 | reply_id = xpc_dictionary_get_data(reply, "identifier", &idLen); | |
261 | if (reply_id != NULL) { | |
262 | char *identifier = malloc(idLen); | |
263 | ||
264 | memcpy(identifier, reply_id, idLen); // should already be NULL terminated, etc. | |
265 | (*result) = identifier; | |
266 | ||
267 | if (rec_type != NULL) { | |
268 | (*rec_type) = (int) xpc_dictionary_get_int64(reply, "rectype"); | |
269 | } | |
270 | } else { | |
271 | (*result) = NULL; | |
272 | rc = ENOENT; | |
273 | } | |
e44d8d47 | 274 | } |
d31dd049 A |
275 | |
276 | xpc_release(reply); | |
b3dd680f | 277 | } |
e44d8d47 | 278 | |
d31dd049 A |
279 | xpc_release(payload); |
280 | #endif | |
e44d8d47 | 281 | |
d31dd049 | 282 | return rc; |
e44d8d47 | 283 | } |
e44d8d47 A |
284 | |
285 | int | |
286 | mbr_uid_to_uuid(uid_t id, uuid_t uu) | |
287 | { | |
288 | return mbr_identifier_to_uuid(ID_TYPE_UID, &id, sizeof(id), uu); | |
c29f2fcc A |
289 | } |
290 | ||
d49d4c81 A |
291 | int |
292 | mbr_gid_to_uuid(gid_t id, uuid_t uu) | |
c29f2fcc | 293 | { |
e44d8d47 | 294 | return mbr_identifier_to_uuid(ID_TYPE_GID, &id, sizeof(id), uu); |
c29f2fcc A |
295 | } |
296 | ||
d49d4c81 A |
297 | int |
298 | mbr_uuid_to_id(const uuid_t uu, uid_t *id, int *id_type) | |
c29f2fcc | 299 | { |
d31dd049 A |
300 | id_t *result; |
301 | int local_type; | |
302 | int rc; | |
303 | ||
304 | rc = mbr_identifier_translate(ID_TYPE_UUID, uu, sizeof(uuid_t), ID_TYPE_UID_OR_GID, (void **) &result, &local_type); | |
305 | if (rc == 0) { | |
306 | switch (local_type) { | |
307 | case MBR_REC_TYPE_GROUP: | |
308 | (*id_type) = ID_TYPE_GID; | |
309 | break; | |
310 | ||
311 | case MBR_REC_TYPE_USER: | |
312 | (*id_type) = ID_TYPE_UID; | |
313 | break; | |
314 | ||
315 | default: | |
316 | (*id_type) = -1; | |
317 | break; | |
318 | } | |
319 | ||
320 | (*id) = (*result); | |
321 | free(result); | |
caa31c11 | 322 | } |
d31dd049 A |
323 | |
324 | return rc; | |
c29f2fcc A |
325 | } |
326 | ||
d49d4c81 A |
327 | int |
328 | mbr_sid_to_uuid(const nt_sid_t *sid, uuid_t uu) | |
c29f2fcc | 329 | { |
d49d4c81 | 330 | #ifdef DS_AVAILABLE |
d31dd049 | 331 | return mbr_identifier_to_uuid(ID_TYPE_SID, sid, sizeof(*sid), uu); |
d49d4c81 A |
332 | #else |
333 | return EIO; | |
334 | #endif | |
335 | } | |
336 | ||
337 | int | |
338 | mbr_identifier_to_uuid(int id_type, const void *identifier, size_t identifier_size, uuid_t uu) | |
339 | { | |
d31dd049 A |
340 | uint8_t *result; |
341 | int rc; | |
342 | ||
343 | rc = mbr_identifier_translate(id_type, identifier, identifier_size, ID_TYPE_UUID, (void **) &result, NULL); | |
344 | if (rc == 0) { | |
345 | uuid_copy(uu, result); | |
346 | free(result); | |
d49d4c81 | 347 | } |
d31dd049 A |
348 | |
349 | return rc; | |
c29f2fcc A |
350 | } |
351 | ||
d49d4c81 A |
352 | int |
353 | mbr_uuid_to_sid_type(const uuid_t uu, nt_sid_t *sid, int *id_type) | |
c29f2fcc | 354 | { |
d49d4c81 | 355 | #ifdef DS_AVAILABLE |
d31dd049 A |
356 | void *result; |
357 | int local_type; | |
358 | int rc; | |
359 | ||
360 | rc = mbr_identifier_translate(ID_TYPE_UUID, uu, sizeof(uuid_t), ID_TYPE_SID, &result, &local_type); | |
361 | if (rc == 0) { | |
362 | memcpy(sid, result, sizeof(nt_sid_t)); | |
363 | if (id_type != NULL) { | |
364 | /* remap ID types */ | |
365 | switch (local_type) { | |
366 | case MBR_REC_TYPE_USER: | |
367 | (*id_type) = SID_TYPE_USER; | |
368 | break; | |
369 | ||
370 | case MBR_REC_TYPE_GROUP: | |
371 | (*id_type) = SID_TYPE_GROUP; | |
372 | break; | |
373 | ||
374 | default: | |
375 | break; | |
376 | } | |
377 | } | |
378 | ||
379 | free(result); | |
b3dd680f | 380 | } |
d31dd049 A |
381 | |
382 | return rc; | |
d49d4c81 A |
383 | #else |
384 | return EIO; | |
385 | #endif | |
b3dd680f A |
386 | } |
387 | ||
d49d4c81 A |
388 | int |
389 | mbr_uuid_to_sid(const uuid_t uu, nt_sid_t *sid) | |
b3dd680f | 390 | { |
d49d4c81 | 391 | #ifdef DS_AVAILABLE |
b3dd680f | 392 | int type, status; |
caa31c11 | 393 | |
b3dd680f A |
394 | type = 0; |
395 | ||
396 | status = mbr_uuid_to_sid_type(uu, sid, &type); | |
397 | if (status != 0) return status; | |
398 | ||
399 | return 0; | |
d49d4c81 A |
400 | #else |
401 | return EIO; | |
402 | #endif | |
c29f2fcc A |
403 | } |
404 | ||
d49d4c81 | 405 | int |
e44d8d47 | 406 | mbr_check_membership(const uuid_t user, const uuid_t group, int *ismember) |
c29f2fcc | 407 | { |
d31dd049 | 408 | return mbr_check_membership_ext(ID_TYPE_UUID, user, sizeof(uuid_t), ID_TYPE_UUID, group, 0, ismember); |
c29f2fcc A |
409 | } |
410 | ||
d49d4c81 A |
411 | int |
412 | mbr_check_membership_refresh(const uuid_t user, uuid_t group, int *ismember) | |
918ca66e | 413 | { |
d31dd049 A |
414 | return mbr_check_membership_ext(ID_TYPE_UUID, user, sizeof(uuid_t), ID_TYPE_UUID, group, 1, ismember); |
415 | } | |
caa31c11 | 416 | |
d31dd049 A |
417 | int |
418 | mbr_check_membership_ext(int userid_type, const void *userid, size_t userid_size, int groupid_type, const void *groupid, int refresh, int *isMember) | |
419 | { | |
420 | #ifdef DS_AVAILABLE | |
421 | xpc_object_t payload, reply; | |
422 | int rc = 0; | |
423 | ||
424 | payload = xpc_dictionary_create(NULL, NULL, 0); | |
425 | if (payload == NULL) return ENOMEM; | |
caa31c11 | 426 | |
d31dd049 A |
427 | xpc_dictionary_set_int64(payload, "user_idtype", userid_type); |
428 | xpc_dictionary_set_data(payload, "user_id", userid, userid_size); | |
429 | xpc_dictionary_set_int64(payload, "group_idtype", groupid_type); | |
430 | ||
431 | switch (groupid_type) { | |
432 | case ID_TYPE_GROUPNAME: | |
433 | case ID_TYPE_GROUP_NFS: | |
434 | xpc_dictionary_set_data(payload, "group_id", groupid, strlen(groupid)); | |
435 | break; | |
436 | ||
437 | case ID_TYPE_GID: | |
438 | xpc_dictionary_set_data(payload, "group_id", groupid, sizeof(id_t)); | |
439 | break; | |
440 | ||
441 | case ID_TYPE_SID: | |
442 | xpc_dictionary_set_data(payload, "group_id", groupid, sizeof(nt_sid_t)); | |
443 | break; | |
444 | ||
445 | case ID_TYPE_UUID: | |
446 | xpc_dictionary_set_data(payload, "group_id", groupid, sizeof(uuid_t)); | |
447 | break; | |
448 | ||
449 | default: | |
450 | rc = EINVAL; | |
451 | break; | |
452 | } | |
453 | ||
454 | if (rc == 0) { | |
455 | reply = _od_rpc_call("mbr_check_membership", payload, _mbr_xpc_pipe); | |
456 | if (reply != NULL) { | |
457 | rc = (int) xpc_dictionary_get_int64(reply, "error"); | |
458 | (*isMember) = xpc_dictionary_get_bool(reply, "ismember"); | |
459 | xpc_release(reply); | |
460 | } else { | |
461 | rc = EIO; | |
462 | } | |
463 | } | |
464 | ||
465 | xpc_release(payload); | |
466 | ||
467 | return rc; | |
d49d4c81 A |
468 | #else |
469 | return EIO; | |
470 | #endif | |
918ca66e A |
471 | } |
472 | ||
d49d4c81 A |
473 | int |
474 | mbr_check_membership_by_id(uuid_t user, gid_t group, int *ismember) | |
c29f2fcc | 475 | { |
d31dd049 | 476 | return mbr_check_membership_ext(ID_TYPE_UUID, user, sizeof(uuid_t), ID_TYPE_GID, &group, 0, ismember); |
c29f2fcc A |
477 | } |
478 | ||
d49d4c81 A |
479 | int |
480 | mbr_reset_cache() | |
c29f2fcc | 481 | { |
d49d4c81 | 482 | #ifdef DS_AVAILABLE |
d31dd049 A |
483 | _od_rpc_call("mbr_cache_flush", NULL, _mbr_xpc_pipe); |
484 | return 0; | |
d49d4c81 A |
485 | #else |
486 | return EIO; | |
487 | #endif | |
c29f2fcc A |
488 | } |
489 | ||
d49d4c81 A |
490 | int |
491 | mbr_user_name_to_uuid(const char *name, uuid_t uu) | |
c29f2fcc | 492 | { |
d31dd049 | 493 | return mbr_identifier_to_uuid(ID_TYPE_USERNAME, name, -1, uu); |
c29f2fcc A |
494 | } |
495 | ||
d49d4c81 A |
496 | int |
497 | mbr_group_name_to_uuid(const char *name, uuid_t uu) | |
c29f2fcc | 498 | { |
d31dd049 | 499 | return mbr_identifier_to_uuid(ID_TYPE_GROUPNAME, name, -1, uu); |
c29f2fcc A |
500 | } |
501 | ||
d49d4c81 A |
502 | int |
503 | mbr_check_service_membership(const uuid_t user, const char *servicename, int *ismember) | |
c29f2fcc | 504 | { |
d49d4c81 | 505 | #ifdef DS_AVAILABLE |
d31dd049 A |
506 | xpc_object_t payload, reply; |
507 | int result = EIO; | |
caa31c11 | 508 | |
d31dd049 A |
509 | if (ismember == NULL || servicename == NULL) return EINVAL; |
510 | ||
511 | payload = xpc_dictionary_create(NULL, NULL, 0); | |
512 | if (payload == NULL) return EIO; | |
513 | ||
514 | xpc_dictionary_set_data(payload, "user_id", user, sizeof(uuid_t)); | |
515 | xpc_dictionary_set_int64(payload, "user_idtype", ID_TYPE_UUID); | |
516 | xpc_dictionary_set_string(payload, "service", servicename); | |
517 | ||
518 | reply = _od_rpc_call("mbr_check_service_membership", payload, _mbr_xpc_pipe); | |
519 | if (reply != NULL) { | |
520 | result = (int) xpc_dictionary_get_int64(reply, "error"); | |
521 | (*ismember) = xpc_dictionary_get_bool(reply, "ismember"); | |
522 | ||
523 | xpc_release(reply); | |
524 | } else { | |
525 | (*ismember) = 0; | |
918ca66e | 526 | } |
d31dd049 A |
527 | |
528 | xpc_release(payload); | |
caa31c11 | 529 | |
c29f2fcc | 530 | return result; |
d49d4c81 A |
531 | #else |
532 | return EIO; | |
533 | #endif | |
c29f2fcc A |
534 | } |
535 | ||
d49d4c81 A |
536 | #ifdef DS_AVAILABLE |
537 | static char * | |
538 | ConvertBytesToDecimal(char *buffer, unsigned long long value) | |
c29f2fcc | 539 | { |
caa31c11 | 540 | char *temp; |
c29f2fcc A |
541 | buffer[24] = '\0'; |
542 | buffer[23] = '0'; | |
caa31c11 | 543 | |
b3dd680f A |
544 | if (value == 0) |
545 | return &buffer[23]; | |
caa31c11 | 546 | |
c29f2fcc A |
547 | temp = &buffer[24]; |
548 | while (value != 0) | |
549 | { | |
550 | temp--; | |
551 | *temp = '0' + (value % 10); | |
552 | value /= 10; | |
553 | } | |
caa31c11 | 554 | |
c29f2fcc A |
555 | return temp; |
556 | } | |
d49d4c81 | 557 | #endif |
c29f2fcc | 558 | |
d49d4c81 A |
559 | int |
560 | mbr_sid_to_string(const nt_sid_t *sid, char *string) | |
c29f2fcc | 561 | { |
d49d4c81 | 562 | #ifdef DS_AVAILABLE |
caa31c11 | 563 | char *current = string; |
c29f2fcc A |
564 | long long temp = 0; |
565 | int i; | |
566 | char tempBuffer[25]; | |
caa31c11 A |
567 | |
568 | if (sid->sid_authcount > NTSID_MAX_AUTHORITIES) return EINVAL; | |
569 | ||
918ca66e A |
570 | for (i = 0; i < 6; i++) |
571 | temp = (temp << 8) | sid->sid_authority[i]; | |
caa31c11 | 572 | |
c29f2fcc A |
573 | current[0] = 'S'; |
574 | current[1] = '-'; | |
575 | current += 2; | |
576 | strcpy(current, ConvertBytesToDecimal(tempBuffer, sid->sid_kind)); | |
577 | current = current + strlen(current); | |
578 | *current = '-'; | |
579 | current++; | |
580 | strcpy(current, ConvertBytesToDecimal(tempBuffer, temp)); | |
caa31c11 | 581 | |
b3dd680f | 582 | for(i=0; i < sid->sid_authcount; i++) |
c29f2fcc A |
583 | { |
584 | current = current + strlen(current); | |
585 | *current = '-'; | |
586 | current++; | |
587 | strcpy(current, ConvertBytesToDecimal(tempBuffer, sid->sid_authorities[i])); | |
588 | } | |
caa31c11 | 589 | |
c29f2fcc | 590 | return 0; |
d49d4c81 A |
591 | #else |
592 | return EIO; | |
593 | #endif | |
c29f2fcc A |
594 | } |
595 | ||
d49d4c81 A |
596 | int |
597 | mbr_string_to_sid(const char *string, nt_sid_t *sid) | |
c29f2fcc | 598 | { |
d49d4c81 | 599 | #ifdef DS_AVAILABLE |
b3dd680f | 600 | char *current = (char *)string+2; |
c29f2fcc A |
601 | int count = 0; |
602 | long long temp; | |
603 | ||
b3dd680f A |
604 | if (string == NULL) return EINVAL; |
605 | ||
c29f2fcc | 606 | memset(sid, 0, sizeof(nt_sid_t)); |
b3dd680f | 607 | if (string[0] != 'S' || string[1] != '-') return EINVAL; |
caa31c11 | 608 | |
c29f2fcc A |
609 | sid->sid_kind = strtol(current, ¤t, 10); |
610 | if (*current == '\0') return EINVAL; | |
611 | current++; | |
612 | temp = strtoll(current, ¤t, 10); | |
caa31c11 A |
613 | |
614 | /* convert to BigEndian before copying */ | |
918ca66e | 615 | temp = OSSwapHostToBigInt64(temp); |
c29f2fcc | 616 | memcpy(sid->sid_authority, ((char*)&temp)+2, 6); |
b3dd680f | 617 | while (*current != '\0' && count < NTSID_MAX_AUTHORITIES) |
c29f2fcc A |
618 | { |
619 | current++; | |
e44d8d47 | 620 | errno = 0; |
84e6ee29 | 621 | sid->sid_authorities[count] = (u_int32_t)strtoll(current, ¤t, 10); |
e44d8d47 A |
622 | if ((sid->sid_authorities[count] == 0) && (errno == EINVAL)) { |
623 | return EINVAL; | |
624 | } | |
c29f2fcc A |
625 | count++; |
626 | } | |
caa31c11 A |
627 | |
628 | if (*current != '\0') return EINVAL; | |
629 | ||
c29f2fcc | 630 | sid->sid_authcount = count; |
caa31c11 | 631 | |
c29f2fcc | 632 | return 0; |
d49d4c81 A |
633 | #else |
634 | return EIO; | |
635 | #endif | |
c29f2fcc A |
636 | } |
637 | ||
d49d4c81 A |
638 | int |
639 | mbr_uuid_to_string(const uuid_t uu, char *string) | |
c29f2fcc | 640 | { |
d31dd049 A |
641 | uuid_unparse_upper(uu, string); |
642 | ||
c29f2fcc A |
643 | return 0; |
644 | } | |
645 | ||
d49d4c81 A |
646 | int |
647 | mbr_string_to_uuid(const char *string, uuid_t uu) | |
c29f2fcc | 648 | { |
d31dd049 | 649 | return uuid_parse(string, uu); |
c29f2fcc | 650 | } |
b3dd680f | 651 | |
e44d8d47 A |
652 | int |
653 | mbr_set_identifier_ttl(int id_type, const void *identifier, size_t identifier_size, unsigned int seconds) | |
654 | { | |
655 | #ifdef DS_AVAILABLE | |
d31dd049 A |
656 | xpc_object_t payload, reply; |
657 | int rc = 0; | |
658 | ||
659 | payload = xpc_dictionary_create(NULL, NULL, 0); | |
660 | if (payload == NULL) return ENOMEM; | |
661 | ||
662 | xpc_dictionary_set_int64(payload, "type", id_type); | |
663 | xpc_dictionary_set_data(payload, "identifier", identifier, identifier_size); | |
664 | xpc_dictionary_set_int64(payload, "ttl", seconds); | |
665 | ||
666 | if (rc == 0) { | |
667 | reply = _od_rpc_call("mbr_set_identifier_ttl", payload, _mbr_xpc_pipe); | |
668 | if (reply != NULL) { | |
669 | rc = (int) xpc_dictionary_get_int64(reply, "error"); | |
670 | xpc_release(reply); | |
671 | } else { | |
672 | rc = EIO; | |
673 | } | |
674 | } | |
675 | ||
676 | xpc_release(payload); | |
677 | ||
678 | return rc; | |
e44d8d47 A |
679 | #else |
680 | return EIO; | |
681 | #endif | |
682 | } |