]> git.saurik.com Git - apple/libinfo.git/blame - membership.subproj/membership.c
Libinfo-459.40.1.tar.gz
[apple/libinfo.git] / membership.subproj / membership.c
CommitLineData
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
38static const uuid_t _user_compat_prefix = {0xff, 0xff, 0xee, 0xee, 0xdd, 0xdd, 0xcc, 0xcc, 0xbb, 0xbb, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00};
39static 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
45int _si_opendirectory_disabled;
46static xpc_pipe_t __mbr_pipe; /* use accessor */
47static 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
53static 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
68static 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
76static 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
84XPC_RETURNS_RETAINED
85static 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
129static 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
142int
143mbr_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
285int
286mbr_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
291int
292mbr_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
297int
298mbr_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
327int
328mbr_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
337int
338mbr_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
352int
353mbr_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
388int
389mbr_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 405int
e44d8d47 406mbr_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
411int
412mbr_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
417int
418mbr_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
473int
474mbr_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
479int
480mbr_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
490int
491mbr_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
496int
497mbr_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
502int
503mbr_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
537static char *
538ConvertBytesToDecimal(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
559int
560mbr_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
596int
597mbr_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, &current, 10);
610 if (*current == '\0') return EINVAL;
611 current++;
612 temp = strtoll(current, &current, 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, &current, 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
638int
639mbr_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
646int
647mbr_string_to_uuid(const char *string, uuid_t uu)
c29f2fcc 648{
d31dd049 649 return uuid_parse(string, uu);
c29f2fcc 650}
b3dd680f 651
e44d8d47
A
652int
653mbr_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}