1 /* Copyright (c) 2012-2013 Apple Inc. All Rights Reserved. */
7 #include "authutilities.h"
8 #include <Security/AuthorizationTags.h>
10 typedef struct _auth_item_s
* auth_item_t
;
13 #pragma mark auth_item_t
16 __AUTH_BASE_STRUCT_HEADER__
;
18 AuthorizationItem data
;
26 auth_item_get_string(auth_item_t item
)
28 if (item
->bufLen
<= item
->data
.valueLength
) {
29 item
->bufLen
= item
->data
.valueLength
+1; // make sure buffer has a null char
30 item
->data
.value
= realloc(item
->data
.value
, item
->bufLen
);
31 if (item
->data
.value
== NULL
) {
32 // this is added to prevent running off into random memory if a string buffer doesn't have a null char
33 LOGE("realloc failed");
36 ((uint8_t*)item
->data
.value
)[item
->bufLen
-1] = '\0';
38 return item
->data
.value
;
42 auth_item_get_cf_key(auth_item_t item
)
45 item
->cfKey
= CFStringCreateWithCStringNoCopy(kCFAllocatorDefault
, item
->data
.name
, kCFStringEncodingUTF8
, kCFAllocatorNull
);
50 static AuthorizationItem
*
51 auth_item_get_auth_item(auth_item_t item
)
57 auth_item_copy_auth_item_xpc(auth_item_t item
)
59 xpc_object_t xpc_data
= xpc_dictionary_create(NULL
, NULL
, 0);
60 xpc_dictionary_set_string(xpc_data
, AUTH_XPC_ITEM_NAME
, item
->data
.name
);
61 if (item
->data
.value
) {
62 xpc_dictionary_set_data(xpc_data
, AUTH_XPC_ITEM_VALUE
, item
->data
.value
, item
->data
.valueLength
);
64 xpc_dictionary_set_uint64(xpc_data
, AUTH_XPC_ITEM_FLAGS
, item
->data
.flags
);
65 xpc_dictionary_set_uint64(xpc_data
, AUTH_XPC_ITEM_TYPE
, item
->type
);
70 _auth_item_finalize(CFTypeRef value
)
72 auth_item_t item
= (auth_item_t
)value
;
74 CFReleaseSafe(item
->cfKey
);
76 if (item
->data
.name
) {
77 free((void*)item
->data
.name
);
80 if (item
->data
.value
) {
81 memset(item
->data
.value
, 0, item
->data
.valueLength
);
82 free(item
->data
.value
);
87 _auth_item_equal(CFTypeRef value1
, CFTypeRef value2
)
89 return (CFHash(value1
) == CFHash(value2
));
93 _auth_item_copy_description(CFTypeRef value
)
96 auth_item_t item
= (auth_item_t
)value
;
99 static size_t passLen
= strlen(kAuthorizationEnvironmentPassword
);
100 if (strncasecmp(item
->data
.name
, kAuthorizationEnvironmentPassword
, passLen
) == 0) {
105 CFMutableStringRef desc
= CFStringCreateMutable(kCFAllocatorDefault
, 0);
106 CFStringAppendFormat(desc
, NULL
, CFSTR("auth_item: %s, type=%i, length=%li, flags=%x"),
107 item
->data
.name
, item
->type
,
108 hidden
? 0 : item
->data
.valueLength
, (unsigned int)item
->data
.flags
);
110 switch (item
->type
) {
112 CFStringAppendFormat(desc
, NULL
, CFSTR(" value=%s"), hidden
? "(hidden)" : auth_item_get_string(item
));
115 CFStringAppendFormat(desc
, NULL
, CFSTR(" value=%i"), *(int32_t*)item
->data
.value
);
118 CFStringAppendFormat(desc
, NULL
, CFSTR(" value=%u"), *(uint32_t*)item
->data
.value
);
121 CFStringAppendFormat(desc
, NULL
, CFSTR(" value=%lli"), *(int64_t*)item
->data
.value
);
124 CFStringAppendFormat(desc
, NULL
, CFSTR(" value=%llu"), *(uint64_t*)item
->data
.value
);
127 CFStringAppendFormat(desc
, NULL
, CFSTR(" value=%i"), *(bool*)item
->data
.value
);
130 CFStringAppendFormat(desc
, NULL
, CFSTR(" value=%f"), *(double*)item
->data
.value
);
133 case AI_TYPE_UNKNOWN
:
135 CFStringAppendFormat(desc
, NULL
, CFSTR(" value=(hidden)"));
137 CFStringAppendFormat(desc
, NULL
, CFSTR(" value=0x"));
138 size_t i
= item
->data
.valueLength
< 10 ? item
->data
.valueLength
: 10;
139 uint8_t * data
= item
->data
.value
;
141 CFStringAppendFormat(desc
, NULL
, CFSTR("%02x"), data
[i
-1]);
152 _auth_item_hash(CFTypeRef value
)
154 auth_item_t item
= (auth_item_t
)value
;
155 uint64_t crc
= crc64_init();
156 crc
= crc64_update(crc
, item
->data
.name
, strlen(item
->data
.name
));
157 if (item
->data
.value
) {
158 crc
= crc64_update(crc
, item
->data
.value
, item
->data
.valueLength
);
160 crc
= crc64_update(crc
, &item
->data
.flags
, sizeof(item
->data
.flags
));
162 crc
= crc64_final(crc
);
163 return (CFHashCode
)crc
;
166 AUTH_TYPE_INSTANCE(auth_item
,
169 .finalize
= _auth_item_finalize
,
170 .equal
= _auth_item_equal
,
171 .hash
= _auth_item_hash
,
172 .copyFormattingDesc
= NULL
,
173 .copyDebugDesc
= _auth_item_copy_description
176 static CFTypeID
auth_item_get_type_id() {
177 static CFTypeID type_id
= _kCFRuntimeNotATypeID
;
178 static dispatch_once_t onceToken
;
180 dispatch_once(&onceToken
, ^{
181 type_id
= _CFRuntimeRegisterClass(&_auth_type_auth_item
);
190 auth_item_t item
= NULL
;
192 item
= (auth_item_t
)_CFRuntimeCreateInstance(kCFAllocatorDefault
, auth_item_get_type_id(), AUTH_CLASS_SIZE(auth_item
), NULL
);
193 require(item
!= NULL
, done
);
200 auth_item_create(uint32_t type
, const char * name
, const void * value
, size_t valueLen
, uint32_t flags
)
202 auth_item_t item
= NULL
;
203 require(name
!= NULL
, done
);
205 item
= _auth_item_create();
206 require(item
!= NULL
, done
);
209 item
->data
.flags
= flags
;
210 item
->data
.name
= _copy_string(name
);
211 item
->data
.valueLength
= valueLen
;
212 item
->bufLen
= valueLen
;
214 if (item
->type
== AI_TYPE_STRING
) {
216 item
->data
.value
= calloc(1u, item
->bufLen
);
217 } else if (valueLen
) {
218 item
->data
.value
= calloc(1u, item
->bufLen
);
221 memcpy(item
->data
.value
, value
, valueLen
);
230 auth_item_create_with_xpc(xpc_object_t data
)
232 auth_item_t item
= NULL
;
233 require(data
!= NULL
, done
);
234 require(xpc_get_type(data
) == XPC_TYPE_DICTIONARY
, done
);
235 require(xpc_dictionary_get_string(data
, AUTH_XPC_ITEM_NAME
) != NULL
, done
);
237 item
= _auth_item_create();
238 require(item
!= NULL
, done
);
240 item
->data
.name
= _copy_string(xpc_dictionary_get_string(data
, AUTH_XPC_ITEM_NAME
));
241 item
->data
.flags
= (uint32_t)xpc_dictionary_get_uint64(data
, AUTH_XPC_ITEM_FLAGS
);
242 item
->type
= (uint32_t)xpc_dictionary_get_uint64(data
, AUTH_XPC_ITEM_TYPE
);
245 const void * value
= xpc_dictionary_get_data(data
, AUTH_XPC_ITEM_VALUE
, &len
);
248 item
->data
.valueLength
= len
;
249 item
->data
.value
= calloc(1u, len
);
250 memcpy(item
->data
.value
, value
, len
);
258 #pragma mark auth_items_t
260 struct _auth_items_s
{
261 __AUTH_BASE_STRUCT_HEADER__
;
263 CFMutableDictionaryRef dictionary
;
264 AuthorizationItemSet set
;
268 _auth_items_finalize(CFTypeRef value
)
270 auth_items_t items
= (auth_items_t
)value
;
272 CFReleaseNull(items
->dictionary
);
273 free_safe(items
->set
.items
)
277 _auth_items_equal(CFTypeRef value1
, CFTypeRef value2
)
279 auth_items_t items1
= (auth_items_t
)value1
;
280 auth_items_t items2
= (auth_items_t
)value2
;
282 return CFEqual(items1
->dictionary
, items2
->dictionary
);
286 _auth_items_copy_description(CFTypeRef value
)
288 auth_items_t items
= (auth_items_t
)value
;
289 return CFCopyDescription(items
->dictionary
);
292 AUTH_TYPE_INSTANCE(auth_items
,
295 .finalize
= _auth_items_finalize
,
296 .equal
= _auth_items_equal
,
298 .copyFormattingDesc
= NULL
,
299 .copyDebugDesc
= _auth_items_copy_description
302 CFTypeID
auth_items_get_type_id()
304 static CFTypeID type_id
= _kCFRuntimeNotATypeID
;
305 static dispatch_once_t onceToken
;
307 dispatch_once(&onceToken
, ^{
308 type_id
= _CFRuntimeRegisterClass(&_auth_type_auth_items
);
315 _auth_items_create(bool createDict
)
317 auth_items_t items
= NULL
;
319 items
= (auth_items_t
)_CFRuntimeCreateInstance(kCFAllocatorDefault
, auth_items_get_type_id(), AUTH_CLASS_SIZE(auth_items
), NULL
);
320 require(items
!= NULL
, done
);
323 items
->dictionary
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
333 auth_items_t items
= NULL
;
335 items
= _auth_items_create(true);
336 require(items
!= NULL
, done
);
343 _auth_items_parse_xpc(auth_items_t items
, const xpc_object_t data
)
346 require(data
!= NULL
, done
);
347 require(xpc_get_type(data
) == XPC_TYPE_ARRAY
, done
);
349 result
= xpc_array_apply(data
, ^bool(size_t index AUTH_UNUSED
, xpc_object_t value
) {
351 auth_item_t item
= auth_item_create_with_xpc(value
);
353 CFDictionarySetValue(items
->dictionary
, auth_item_get_cf_key(item
), item
);
364 auth_items_t
auth_items_create_with_xpc(const xpc_object_t data
)
366 auth_items_t items
= NULL
;
368 items
= _auth_items_create(true);
369 require(items
!= NULL
, done
);
371 _auth_items_parse_xpc(items
, data
);
378 auth_items_create_copy(auth_items_t copy
)
380 auth_items_t items
= NULL
;
382 items
= _auth_items_create(false);
383 require(items
!= NULL
, done
);
385 items
->dictionary
= CFDictionaryCreateMutableCopy(kCFAllocatorDefault
, CFDictionaryGetCount(copy
->dictionary
), copy
->dictionary
);
392 auth_items_get_count(auth_items_t items
)
394 return (size_t)CFDictionaryGetCount(items
->dictionary
);
397 AuthorizationItemSet
*
398 auth_items_get_item_set(auth_items_t items
)
400 uint32_t count
= (uint32_t)CFDictionaryGetCount(items
->dictionary
);
402 size_t size
= count
* sizeof(AuthorizationItem
);
403 if (items
->set
.items
== NULL
) {
404 items
->set
.items
= calloc(1u, size
);
405 require(items
->set
.items
!= NULL
, done
);
407 if (count
> items
->set
.count
) {
408 items
->set
.items
= realloc(items
->set
.items
, size
);
409 require_action(items
->set
.items
!= NULL
, done
, items
->set
.count
= 0);
412 items
->set
.count
= count
;
413 CFTypeRef keys
[count
], values
[count
];
414 CFDictionaryGetKeysAndValues(items
->dictionary
, keys
, values
);
415 for (uint32_t i
= 0; i
< count
; i
++) {
416 auth_item_t item
= (auth_item_t
)values
[i
];
417 items
->set
.items
[i
] = *auth_item_get_auth_item(item
);
420 items
->set
.count
= 0;
428 auth_items_export_xpc(auth_items_t items
)
430 xpc_object_t array
= xpc_array_create(NULL
, 0);
432 _cf_dictionary_iterate(items
->dictionary
, ^bool(CFTypeRef key AUTH_UNUSED
, CFTypeRef value
) {
433 auth_item_t item
= (auth_item_t
)value
;
434 xpc_object_t xpc_data
= auth_item_copy_auth_item_xpc(item
);
435 xpc_array_append_value(array
, xpc_data
);
436 xpc_release_safe(xpc_data
);
444 _find_item(auth_items_t items
, const char * key
)
446 auth_item_t item
= NULL
;
447 CFStringRef lookup
= NULL
;
448 require(key
!= NULL
, done
);
450 lookup
= CFStringCreateWithCStringNoCopy(kCFAllocatorDefault
, key
, kCFStringEncodingUTF8
, kCFAllocatorNull
);
451 require(lookup
!= NULL
, done
);
453 item
= (auth_item_t
)CFDictionaryGetValue(items
->dictionary
, lookup
);
456 CFReleaseSafe(lookup
);
461 auth_items_set_flags(auth_items_t items
, const char *key
, uint32_t flags
)
463 auth_item_t item
= _find_item(items
,key
);
465 item
->data
.flags
|= flags
;
470 auth_items_clear_flags(auth_items_t items
, const char *key
, uint32_t flags
)
472 auth_item_t item
= _find_item(items
,key
);
474 item
->data
.flags
&= ~flags
;
479 auth_items_get_flags(auth_items_t items
, const char *key
)
481 auth_item_t item
= _find_item(items
,key
);
483 return item
->data
.flags
;
490 auth_items_check_flags(auth_items_t items
, const char *key
, uint32_t flags
)
492 // When several bits are set in uint32_t flags, "(current & flags) != 0" checks if ANY flag is set, not all flags!
493 // This odd behavior is currently being relied upon in several places, so be careful when changing / fixing this.
494 // However, this also risks unwanted information leakage in
495 // AuthorizationCopyInfo ==> authorization_copy_info ==> [all info] auth_items_copy_with_flags
496 uint32_t current
= auth_items_get_flags(items
,key
);
497 return flags
? (current
& flags
) != 0 : current
== 0;
501 auth_items_set_key(auth_items_t items
, const char *key
)
503 auth_item_t item
= _find_item(items
,key
);
505 item
= auth_item_create(AI_TYPE_RIGHT
, key
, NULL
, 0, 0);
507 CFDictionarySetValue(items
->dictionary
, auth_item_get_cf_key(item
), item
);
514 auth_items_exist(auth_items_t items
, const char *key
)
516 return _find_item(items
,key
) != NULL
;
520 auth_items_remove(auth_items_t items
, const char *key
)
522 CFStringRef lookup
= CFStringCreateWithCStringNoCopy(kCFAllocatorDefault
, key
, kCFStringEncodingUTF8
, kCFAllocatorNull
);
523 CFDictionaryRemoveValue(items
->dictionary
, lookup
);
524 CFReleaseSafe(lookup
);
528 auth_items_remove_with_flags(auth_items_t items
, uint32_t flags
)
530 auth_items_iterate(items
, ^bool(const char *key
) {
531 if (auth_items_check_flags(items
, key
, flags
)) {
532 auth_items_remove(items
,key
);
539 auth_items_clear(auth_items_t items
)
541 CFDictionaryRemoveAllValues(items
->dictionary
);
545 auth_items_copy(auth_items_t items
, auth_items_t src
)
547 auth_items_iterate(src
, ^bool(const char *key
) {
548 CFStringRef lookup
= CFStringCreateWithCStringNoCopy(kCFAllocatorDefault
, key
, kCFStringEncodingUTF8
, kCFAllocatorNull
);
549 auth_item_t item
= (auth_item_t
)CFDictionaryGetValue(src
->dictionary
, lookup
);
550 CFDictionarySetValue(items
->dictionary
, auth_item_get_cf_key(item
), item
);
551 CFReleaseSafe(lookup
);
557 auth_items_copy_xpc(auth_items_t items
, const xpc_object_t src
)
559 _auth_items_parse_xpc(items
,src
);
563 auth_items_copy_with_flags(auth_items_t items
, auth_items_t src
, uint32_t flags
)
565 auth_items_iterate(src
, ^bool(const char *key
) {
566 if (auth_items_check_flags(src
, key
, flags
)) {
567 CFStringRef lookup
= CFStringCreateWithCStringNoCopy(kCFAllocatorDefault
, key
, kCFStringEncodingUTF8
, kCFAllocatorNull
);
568 auth_item_t item
= (auth_item_t
)CFDictionaryGetValue(src
->dictionary
, lookup
);
569 CFDictionarySetValue(items
->dictionary
, auth_item_get_cf_key(item
), item
);
570 CFReleaseSafe(lookup
);
577 auth_items_iterate(auth_items_t items
, auth_items_iterator_t iter
)
580 CFTypeRef
* keys
= NULL
;
581 CFTypeRef
* values
= NULL
;
583 CFIndex count
= CFDictionaryGetCount(items
->dictionary
);
584 keys
= calloc((size_t)count
, sizeof(CFTypeRef
));
585 require(keys
!= NULL
, done
);
587 values
= calloc((size_t)count
, sizeof(CFTypeRef
));
588 require(values
!= NULL
, done
);
590 CFDictionaryGetKeysAndValues(items
->dictionary
, keys
, values
);
591 for (CFIndex i
= 0; i
< count
; i
++) {
592 auth_item_t item
= (auth_item_t
)values
[i
];
593 result
= iter(item
->data
.name
);
606 auth_items_set_string(auth_items_t items
, const char *key
, const char *value
)
608 assert(value
); // marked non-null
610 size_t valLen
= strlen(value
);
611 auth_item_t item
= _find_item(items
,key
);
612 if (item
&& item
->type
== AI_TYPE_STRING
&& valLen
< item
->bufLen
) {
613 memcpy(item
->data
.value
, value
, valLen
+1); // copy null
614 item
->data
.valueLength
= valLen
;
616 item
= auth_item_create(AI_TYPE_STRING
, key
, value
, valLen
, 0);
618 CFDictionarySetValue(items
->dictionary
, auth_item_get_cf_key(item
), item
);
625 auth_items_get_string(auth_items_t items
, const char *key
)
627 auth_item_t item
= _find_item(items
,key
);
630 if (!(item
->type
== AI_TYPE_STRING
|| item
->type
== AI_TYPE_UNKNOWN
)) {
631 LOGV("auth_items: key = %s, invalid type=%i expected=%i",
632 item
->data
.name
, item
->type
, AI_TYPE_STRING
);
635 return auth_item_get_string(item
);
642 auth_items_set_data(auth_items_t items
, const char *key
, const void *value
, size_t len
)
644 assert(value
); // marked non-null
647 auth_item_t item
= _find_item(items
,key
);
648 if (item
&& item
->type
== AI_TYPE_DATA
&& len
<= item
->bufLen
) {
649 memcpy(item
->data
.value
, value
, len
);
650 item
->data
.valueLength
= len
;
652 item
= auth_item_create(AI_TYPE_DATA
, key
, value
, len
, 0);
654 CFDictionarySetValue(items
->dictionary
, auth_item_get_cf_key(item
), item
);
662 auth_items_get_data(auth_items_t items
, const char *key
, size_t *len
)
664 assert(len
); // marked non-null
666 auth_item_t item
= _find_item(items
,key
);
669 if (!(item
->type
== AI_TYPE_DATA
|| item
->type
== AI_TYPE_UNKNOWN
)) {
670 LOGV("auth_items: key = %s, invalid type=%i expected=%i",
671 item
->data
.name
, item
->type
, AI_TYPE_DATA
);
674 *len
= item
->data
.valueLength
;
675 return item
->data
.value
;
682 auth_items_get_data_with_flags(auth_items_t items
, const char *key
, size_t *len
, uint32_t flags
)
684 assert(len
); // marked non-null
686 auth_item_t item
= _find_item(items
,key
);
687 if (item
&& (item
->data
.flags
& flags
) == flags
) {
689 if (!(item
->type
== AI_TYPE_DATA
|| item
->type
== AI_TYPE_UNKNOWN
)) {
690 LOGV("auth_items: key = %s, invalid type=%i expected=%i",
691 item
->data
.name
, item
->type
, AI_TYPE_DATA
);
694 *len
= item
->data
.valueLength
;
696 return item
->data
.value
;
703 auth_items_set_bool(auth_items_t items
, const char *key
, bool value
)
705 auth_item_t item
= _find_item(items
,key
);
706 if (item
&& item
->type
== AI_TYPE_BOOL
) {
707 *(bool*)item
->data
.value
= value
;
709 item
= auth_item_create(AI_TYPE_BOOL
, key
, &value
, sizeof(bool), 0);
711 CFDictionarySetValue(items
->dictionary
, auth_item_get_cf_key(item
), item
);
718 auth_items_get_bool(auth_items_t items
, const char *key
)
720 auth_item_t item
= _find_item(items
,key
);
723 if (!(item
->type
== AI_TYPE_BOOL
|| item
->type
== AI_TYPE_UNKNOWN
) || (item
->data
.valueLength
!= sizeof(bool))) {
724 LOGV("auth_items: key = %s, invalid type=%i expected=%i or size=%li expected=%li",
725 item
->data
.name
, item
->type
, AI_TYPE_BOOL
, item
->data
.valueLength
, sizeof(bool));
728 if (item
->type
== AI_TYPE_STRING
) {
729 return atoi(auth_item_get_string(item
));
732 require(item
->data
.value
!= NULL
, done
);
733 require(item
->data
.valueLength
== sizeof(bool), done
);
735 return *(bool*)item
->data
.value
;
743 auth_items_set_int(auth_items_t items
, const char *key
, int32_t value
)
745 auth_item_t item
= _find_item(items
,key
);
746 if (item
&& item
->type
== AI_TYPE_INT
) {
747 *(int32_t*)item
->data
.value
= value
;
749 item
= auth_item_create(AI_TYPE_INT
, key
, &value
, sizeof(int32_t), 0);
751 CFDictionarySetValue(items
->dictionary
, auth_item_get_cf_key(item
), item
);
758 auth_items_get_int(auth_items_t items
, const char *key
)
760 auth_item_t item
= _find_item(items
,key
);
763 if (!(item
->type
==AI_TYPE_INT
|| item
->type
== AI_TYPE_UNKNOWN
) || (item
->data
.valueLength
!= sizeof(int32_t))) {
764 LOGV("auth_items: key = %s, invalid type=%i expected=%i or size=%li expected=%li",
765 item
->data
.name
, item
->type
, AI_TYPE_INT
, item
->data
.valueLength
, sizeof(int32_t));
768 if (item
->type
== AI_TYPE_STRING
) {
769 return atoi(auth_item_get_string(item
));
772 require(item
->data
.value
!= NULL
, done
);
773 require(item
->data
.valueLength
== sizeof(int32_t), done
);
775 return *(int32_t*)item
->data
.value
;
783 auth_items_set_uint(auth_items_t items
, const char *key
, uint32_t value
)
785 auth_item_t item
= _find_item(items
,key
);
786 if (item
&& item
->type
== AI_TYPE_UINT
) {
787 *(uint32_t*)item
->data
.value
= value
;
789 item
= auth_item_create(AI_TYPE_UINT
, key
, &value
, sizeof(uint32_t), 0);
791 CFDictionarySetValue(items
->dictionary
, auth_item_get_cf_key(item
), item
);
798 auth_items_get_uint(auth_items_t items
, const char *key
)
800 auth_item_t item
= _find_item(items
,key
);
803 if (!(item
->type
==AI_TYPE_UINT
|| item
->type
== AI_TYPE_UNKNOWN
) || (item
->data
.valueLength
!= sizeof(uint32_t))) {
804 LOGV("auth_items: key = %s, invalid type=%i expected=%i or size=%li expected=%li",
805 item
->data
.name
, item
->type
, AI_TYPE_UINT
, item
->data
.valueLength
, sizeof(uint32_t));
808 if (item
->type
== AI_TYPE_STRING
) {
809 return (uint32_t)atoi(auth_item_get_string(item
));
812 require(item
->data
.value
!= NULL
, done
);
813 require(item
->data
.valueLength
== sizeof(uint32_t), done
);
815 return *(uint32_t*)item
->data
.value
;
823 auth_items_set_int64(auth_items_t items
, const char *key
, int64_t value
)
825 auth_item_t item
= _find_item(items
,key
);
826 if (item
&& item
->type
== AI_TYPE_INT64
) {
827 *(int64_t*)item
->data
.value
= value
;
829 item
= auth_item_create(AI_TYPE_INT64
, key
, &value
, sizeof(int64_t), 0);
831 CFDictionarySetValue(items
->dictionary
, auth_item_get_cf_key(item
), item
);
838 auth_items_get_int64(auth_items_t items
, const char *key
)
840 auth_item_t item
= _find_item(items
,key
);
843 if (!(item
->type
==AI_TYPE_INT64
|| item
->type
== AI_TYPE_UNKNOWN
) || (item
->data
.valueLength
!= sizeof(int64_t))) {
844 LOGV("auth_items: key = %s, invalid type=%i expected=%i or size=%li expected=%li",
845 item
->data
.name
, item
->type
, AI_TYPE_INT64
, item
->data
.valueLength
, sizeof(int64_t));
848 if (item
->type
== AI_TYPE_STRING
) {
849 return atoll(auth_item_get_string(item
));
852 require(item
->data
.value
!= NULL
, done
);
853 require(item
->data
.valueLength
== sizeof(int64_t), done
);
855 return *(int64_t*)item
->data
.value
;
863 auth_items_set_uint64(auth_items_t items
, const char *key
, uint64_t value
)
865 auth_item_t item
= _find_item(items
,key
);
866 if (item
&& item
->type
== AI_TYPE_UINT64
) {
867 *(uint64_t*)item
->data
.value
= value
;
869 item
= auth_item_create(AI_TYPE_UINT64
, key
, &value
, sizeof(uint64_t), 0);
871 CFDictionarySetValue(items
->dictionary
, auth_item_get_cf_key(item
), item
);
878 auth_items_get_uint64(auth_items_t items
, const char *key
)
880 auth_item_t item
= _find_item(items
,key
);
883 if (!(item
->type
==AI_TYPE_UINT64
|| item
->type
== AI_TYPE_UNKNOWN
) || (item
->data
.valueLength
!= sizeof(uint64_t))) {
884 LOGV("auth_items: key = %s, invalid type=%i expected=%i or size=%li expected=%li",
885 item
->data
.name
, item
->type
, AI_TYPE_UINT64
, item
->data
.valueLength
, sizeof(uint64_t));
888 if (item
->type
== AI_TYPE_STRING
) {
889 return (uint64_t)atoll(auth_item_get_string(item
));
892 require(item
->data
.value
!= NULL
, done
);
893 require(item
->data
.valueLength
== sizeof(uint64_t), done
);
895 return *(uint64_t*)item
->data
.value
;
902 void auth_items_set_double(auth_items_t items
, const char *key
, double value
)
904 auth_item_t item
= _find_item(items
,key
);
905 if (item
&& item
->type
== AI_TYPE_DOUBLE
) {
906 *(double*)item
->data
.value
= value
;
908 item
= auth_item_create(AI_TYPE_DOUBLE
, key
, &value
, sizeof(double), 0);
910 CFDictionarySetValue(items
->dictionary
, auth_item_get_cf_key(item
), item
);
916 double auth_items_get_double(auth_items_t items
, const char *key
)
918 auth_item_t item
= _find_item(items
,key
);
921 if (!(item
->type
==AI_TYPE_DOUBLE
|| item
->type
== AI_TYPE_UNKNOWN
) || (item
->data
.valueLength
!= sizeof(double))) {
922 LOGV("auth_items: key = %s, invalid type=%i expected=%i or size=%li expected=%li",
923 item
->data
.name
, item
->type
, AI_TYPE_DOUBLE
, item
->data
.valueLength
, sizeof(double));
926 if (item
->type
== AI_TYPE_STRING
) {
927 return atof(auth_item_get_string(item
));
930 require(item
->data
.value
!= NULL
, done
);
931 require(item
->data
.valueLength
== sizeof(double), done
);
933 return *(double*)item
->data
.value
;
940 uint32_t auth_items_get_type(auth_items_t items
, const char *key
)
942 auth_item_t item
= _find_item(items
,key
);
947 return AI_TYPE_UNKNOWN
;
950 size_t auth_items_get_length(auth_items_t items
, const char *key
)
952 auth_item_t item
= _find_item(items
,key
);
954 return item
->data
.valueLength
;
960 void auth_items_set_value(auth_items_t items
, const char *key
, uint32_t type
, uint32_t flags
, const void *value
, size_t len
)
962 auth_item_t item
= auth_item_create(type
, key
, value
, len
, flags
);
964 CFDictionarySetValue(items
->dictionary
, auth_item_get_cf_key(item
), item
);
970 #pragma mark auth_rights_t
972 struct _auth_rights_s
{
973 __AUTH_BASE_STRUCT_HEADER__
;
975 CFMutableArrayRef array
;
979 _auth_rights_finalize(CFTypeRef value
)
981 auth_rights_t rights
= (auth_rights_t
)value
;
983 CFReleaseNull(rights
->array
);
987 _auth_rights_equal(CFTypeRef value1
, CFTypeRef value2
)
989 auth_rights_t rights1
= (auth_rights_t
)value1
;
990 auth_rights_t rights2
= (auth_rights_t
)value2
;
992 return CFEqual(rights1
->array
, rights2
->array
);
996 _auth_rights_copy_description(CFTypeRef value
)
998 auth_rights_t rights
= (auth_rights_t
)value
;
999 return CFCopyDescription(rights
->array
);
1002 AUTH_TYPE_INSTANCE(auth_rights
,
1005 .finalize
= _auth_rights_finalize
,
1006 .equal
= _auth_rights_equal
,
1008 .copyFormattingDesc
= NULL
,
1009 .copyDebugDesc
= _auth_rights_copy_description
1012 static CFTypeID
auth_rights_get_type_id()
1014 static CFTypeID type_id
= _kCFRuntimeNotATypeID
;
1015 static dispatch_once_t onceToken
;
1017 dispatch_once(&onceToken
, ^{
1018 type_id
= _CFRuntimeRegisterClass(&_auth_type_auth_rights
);
1024 static auth_rights_t
1025 _auth_rights_create()
1027 auth_rights_t rights
= NULL
;
1029 rights
= (auth_rights_t
)_CFRuntimeCreateInstance(kCFAllocatorDefault
, auth_rights_get_type_id(), AUTH_CLASS_SIZE(auth_rights
), NULL
);
1030 require(rights
!= NULL
, done
);
1032 rights
->array
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
);
1039 auth_rights_create()
1041 auth_rights_t rights
= _auth_rights_create();
1042 require(rights
!= NULL
, done
);
1048 auth_rights_t
auth_rights_create_with_xpc(const xpc_object_t data
)
1050 auth_rights_t rights
= _auth_rights_create();
1051 require(rights
!= NULL
, done
);
1052 require(data
!= NULL
, done
);
1053 require(xpc_get_type(data
) == XPC_TYPE_ARRAY
, done
);
1055 xpc_array_apply(data
, ^bool(size_t index AUTH_UNUSED
, xpc_object_t value
) {
1057 auth_item_t item
= auth_item_create_with_xpc(value
);
1059 CFArrayAppendValue(rights
->array
, item
);
1060 CFReleaseSafe(item
);
1070 xpc_object_t
auth_rights_export_xpc(auth_rights_t rights
)
1072 xpc_object_t array
= xpc_array_create(NULL
, 0);
1074 CFIndex count
= CFArrayGetCount(rights
->array
);
1075 for (CFIndex i
= 0; i
< count
; i
++) {
1076 auth_item_t item
= (auth_item_t
)CFArrayGetValueAtIndex(rights
->array
, i
);
1077 xpc_object_t xpc_data
= auth_item_copy_auth_item_xpc(item
);
1078 xpc_array_append_value(array
, xpc_data
);
1079 xpc_release_safe(xpc_data
);
1086 _find_right_item(auth_rights_t rights
, const char * key
)
1088 auth_item_t item
= NULL
;
1089 CFStringRef lookup
= NULL
;
1090 require(key
!= NULL
, done
);
1092 lookup
= CFStringCreateWithCStringNoCopy(kCFAllocatorDefault
, key
, kCFStringEncodingUTF8
, kCFAllocatorNull
);
1093 require(lookup
!= NULL
, done
);
1095 CFIndex count
= CFArrayGetCount(rights
->array
);
1096 for (CFIndex i
= 0; i
< count
; i
++) {
1097 auth_item_t tmp
= (auth_item_t
)CFArrayGetValueAtIndex(rights
->array
, i
);
1098 if (tmp
&& CFEqual(auth_item_get_cf_key(tmp
), lookup
)) {
1105 CFReleaseSafe(lookup
);
1109 void auth_rights_set_flags(auth_rights_t rights
, const char *key
, uint32_t flags
)
1111 auth_item_t item
= _find_right_item(rights
,key
);
1113 item
->data
.flags
|= flags
;
1117 void auth_rights_clear_flags(auth_rights_t rights
, const char *key
, uint32_t flags
)
1119 auth_item_t item
= _find_right_item(rights
,key
);
1121 item
->data
.flags
&= ~flags
;
1125 uint32_t auth_rights_get_flags(auth_rights_t rights
, const char *key
)
1127 auth_item_t item
= _find_right_item(rights
,key
);
1129 return item
->data
.flags
;
1135 bool auth_rights_check_flags(auth_rights_t rights
, const char *key
, uint32_t flags
)
1137 uint32_t current
= auth_rights_get_flags(rights
,key
);
1138 return flags
? (current
& flags
) != 0 : current
== 0;
1141 size_t auth_rights_get_count(auth_rights_t rights
)
1143 return (size_t)CFArrayGetCount(rights
->array
);
1146 void auth_rights_add(auth_rights_t rights
, const char *key
)
1148 auth_item_t item
= auth_item_create(AI_TYPE_RIGHT
, key
, NULL
, 0, 0);
1150 CFArrayAppendValue(rights
->array
, item
);
1151 CFReleaseSafe(item
);
1155 bool auth_rights_exist(auth_rights_t rights
, const char *key
)
1157 return (_find_right_item(rights
,key
) != NULL
);
1160 void auth_rights_remove(auth_rights_t rights
, const char *key
)
1162 CFStringRef lookup
= CFStringCreateWithCStringNoCopy(kCFAllocatorDefault
, key
, kCFStringEncodingUTF8
, kCFAllocatorNull
);
1163 CFIndex count
= CFArrayGetCount(rights
->array
);
1164 for (CFIndex i
= 0; i
< count
; i
++) {
1165 auth_item_t item
= (auth_item_t
)CFArrayGetValueAtIndex(rights
->array
, i
);
1166 if (CFEqual(auth_item_get_cf_key(item
), lookup
)) {
1167 CFArrayRemoveValueAtIndex(rights
->array
, i
);
1172 CFReleaseSafe(lookup
);
1175 void auth_rights_clear(auth_rights_t rights
)
1177 CFArrayRemoveAllValues(rights
->array
);
1181 auth_rights_iterate(auth_rights_t rights
, bool(^iter
)(const char * key
))
1183 bool result
= false;
1185 CFIndex count
= CFArrayGetCount(rights
->array
);
1186 for (CFIndex i
= 0; i
< count
; i
++) {
1187 auth_item_t item
= (auth_item_t
)CFArrayGetValueAtIndex(rights
->array
, i
);
1188 result
= iter(item
->data
.name
);