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 uint32_t current
= auth_items_get_flags(items
,key
);
493 return flags
? (current
& flags
) != 0 : current
== 0;
497 auth_items_set_key(auth_items_t items
, const char *key
)
499 auth_item_t item
= _find_item(items
,key
);
501 item
= auth_item_create(AI_TYPE_RIGHT
, key
, NULL
, 0, 0);
503 CFDictionarySetValue(items
->dictionary
, auth_item_get_cf_key(item
), item
);
510 auth_items_exist(auth_items_t items
, const char *key
)
512 return _find_item(items
,key
) != NULL
;
516 auth_items_remove(auth_items_t items
, const char *key
)
518 CFStringRef lookup
= CFStringCreateWithCStringNoCopy(kCFAllocatorDefault
, key
, kCFStringEncodingUTF8
, kCFAllocatorNull
);
519 CFDictionaryRemoveValue(items
->dictionary
, lookup
);
520 CFReleaseSafe(lookup
);
524 auth_items_remove_with_flags(auth_items_t items
, uint32_t flags
)
526 auth_items_iterate(items
, ^bool(const char *key
) {
527 if (auth_items_check_flags(items
, key
, flags
)) {
528 auth_items_remove(items
,key
);
535 auth_items_clear(auth_items_t items
)
537 CFDictionaryRemoveAllValues(items
->dictionary
);
541 auth_items_copy(auth_items_t items
, auth_items_t src
)
543 auth_items_iterate(src
, ^bool(const char *key
) {
544 CFStringRef lookup
= CFStringCreateWithCStringNoCopy(kCFAllocatorDefault
, key
, kCFStringEncodingUTF8
, kCFAllocatorNull
);
545 auth_item_t item
= (auth_item_t
)CFDictionaryGetValue(src
->dictionary
, lookup
);
546 CFDictionarySetValue(items
->dictionary
, auth_item_get_cf_key(item
), item
);
547 CFReleaseSafe(lookup
);
553 auth_items_copy_xpc(auth_items_t items
, const xpc_object_t src
)
555 _auth_items_parse_xpc(items
,src
);
559 auth_items_copy_with_flags(auth_items_t items
, auth_items_t src
, uint32_t flags
)
561 auth_items_iterate(src
, ^bool(const char *key
) {
562 if (auth_items_check_flags(src
, key
, flags
)) {
563 CFStringRef lookup
= CFStringCreateWithCStringNoCopy(kCFAllocatorDefault
, key
, kCFStringEncodingUTF8
, kCFAllocatorNull
);
564 auth_item_t item
= (auth_item_t
)CFDictionaryGetValue(src
->dictionary
, lookup
);
565 CFDictionarySetValue(items
->dictionary
, auth_item_get_cf_key(item
), item
);
566 CFReleaseSafe(lookup
);
573 auth_items_iterate(auth_items_t items
, auth_items_iterator_t iter
)
576 CFTypeRef
* keys
= NULL
;
577 CFTypeRef
* values
= NULL
;
579 CFIndex count
= CFDictionaryGetCount(items
->dictionary
);
580 keys
= calloc((size_t)count
, sizeof(CFTypeRef
));
581 require(keys
!= NULL
, done
);
583 values
= calloc((size_t)count
, sizeof(CFTypeRef
));
584 require(values
!= NULL
, done
);
586 CFDictionaryGetKeysAndValues(items
->dictionary
, keys
, values
);
587 for (CFIndex i
= 0; i
< count
; i
++) {
588 auth_item_t item
= (auth_item_t
)values
[i
];
589 result
= iter(item
->data
.name
);
602 auth_items_set_string(auth_items_t items
, const char *key
, const char *value
)
605 size_t valLen
= strlen(value
);
606 auth_item_t item
= _find_item(items
,key
);
607 if (item
&& item
->type
== AI_TYPE_STRING
&& valLen
< item
->bufLen
) {
608 memcpy(item
->data
.value
, value
, valLen
+1); // copy null
609 item
->data
.valueLength
= valLen
;
611 item
= auth_item_create(AI_TYPE_STRING
, key
, value
, valLen
, 0);
613 CFDictionarySetValue(items
->dictionary
, auth_item_get_cf_key(item
), item
);
621 auth_items_get_string(auth_items_t items
, const char *key
)
623 auth_item_t item
= _find_item(items
,key
);
626 if (!(item
->type
== AI_TYPE_STRING
|| item
->type
== AI_TYPE_UNKNOWN
)) {
627 LOGV("auth_items: key = %s, invalid type=%i expected=%i",
628 item
->data
.name
, item
->type
, AI_TYPE_STRING
);
631 return auth_item_get_string(item
);
638 auth_items_set_data(auth_items_t items
, const char *key
, const void *value
, size_t len
)
641 auth_item_t item
= _find_item(items
,key
);
642 if (item
&& item
->type
== AI_TYPE_DATA
&& len
<= item
->bufLen
) {
643 memcpy(item
->data
.value
, value
, len
);
644 item
->data
.valueLength
= len
;
646 item
= auth_item_create(AI_TYPE_DATA
, key
, value
, len
, 0);
648 CFDictionarySetValue(items
->dictionary
, auth_item_get_cf_key(item
), item
);
656 auth_items_get_data(auth_items_t items
, const char *key
, size_t *len
)
658 auth_item_t item
= _find_item(items
,key
);
661 if (!(item
->type
== AI_TYPE_DATA
|| item
->type
== AI_TYPE_UNKNOWN
)) {
662 LOGV("auth_items: key = %s, invalid type=%i expected=%i",
663 item
->data
.name
, item
->type
, AI_TYPE_DATA
);
667 *len
= item
->data
.valueLength
;
669 return item
->data
.value
;
676 auth_items_set_bool(auth_items_t items
, const char *key
, bool value
)
678 auth_item_t item
= _find_item(items
,key
);
679 if (item
&& item
->type
== AI_TYPE_BOOL
) {
680 *(bool*)item
->data
.value
= value
;
682 item
= auth_item_create(AI_TYPE_BOOL
, key
, &value
, sizeof(bool), 0);
684 CFDictionarySetValue(items
->dictionary
, auth_item_get_cf_key(item
), item
);
691 auth_items_get_bool(auth_items_t items
, const char *key
)
693 auth_item_t item
= _find_item(items
,key
);
696 if (!(item
->type
== AI_TYPE_BOOL
|| item
->type
== AI_TYPE_UNKNOWN
) || (item
->data
.valueLength
!= sizeof(bool))) {
697 LOGV("auth_items: key = %s, invalid type=%i expected=%i or size=%li expected=%li",
698 item
->data
.name
, item
->type
, AI_TYPE_BOOL
, item
->data
.valueLength
, sizeof(bool));
701 if (item
->type
== AI_TYPE_STRING
) {
702 return atoi(auth_item_get_string(item
));
705 require(item
->data
.value
!= NULL
, done
);
706 require(item
->data
.valueLength
== sizeof(bool), done
);
708 return *(bool*)item
->data
.value
;
716 auth_items_set_int(auth_items_t items
, const char *key
, int32_t value
)
718 auth_item_t item
= _find_item(items
,key
);
719 if (item
&& item
->type
== AI_TYPE_INT
) {
720 *(int32_t*)item
->data
.value
= value
;
722 item
= auth_item_create(AI_TYPE_INT
, key
, &value
, sizeof(int32_t), 0);
724 CFDictionarySetValue(items
->dictionary
, auth_item_get_cf_key(item
), item
);
731 auth_items_get_int(auth_items_t items
, const char *key
)
733 auth_item_t item
= _find_item(items
,key
);
736 if (!(item
->type
==AI_TYPE_INT
|| item
->type
== AI_TYPE_UNKNOWN
) || (item
->data
.valueLength
!= sizeof(int32_t))) {
737 LOGV("auth_items: key = %s, invalid type=%i expected=%i or size=%li expected=%li",
738 item
->data
.name
, item
->type
, AI_TYPE_INT
, item
->data
.valueLength
, sizeof(int32_t));
741 if (item
->type
== AI_TYPE_STRING
) {
742 return atoi(auth_item_get_string(item
));
745 require(item
->data
.value
!= NULL
, done
);
746 require(item
->data
.valueLength
== sizeof(int32_t), done
);
748 return *(int32_t*)item
->data
.value
;
756 auth_items_set_uint(auth_items_t items
, const char *key
, uint32_t value
)
758 auth_item_t item
= _find_item(items
,key
);
759 if (item
&& item
->type
== AI_TYPE_UINT
) {
760 *(uint32_t*)item
->data
.value
= value
;
762 item
= auth_item_create(AI_TYPE_UINT
, key
, &value
, sizeof(uint32_t), 0);
764 CFDictionarySetValue(items
->dictionary
, auth_item_get_cf_key(item
), item
);
771 auth_items_get_uint(auth_items_t items
, const char *key
)
773 auth_item_t item
= _find_item(items
,key
);
776 if (!(item
->type
==AI_TYPE_UINT
|| item
->type
== AI_TYPE_UNKNOWN
) || (item
->data
.valueLength
!= sizeof(uint32_t))) {
777 LOGV("auth_items: key = %s, invalid type=%i expected=%i or size=%li expected=%li",
778 item
->data
.name
, item
->type
, AI_TYPE_UINT
, item
->data
.valueLength
, sizeof(uint32_t));
781 if (item
->type
== AI_TYPE_STRING
) {
782 return (uint32_t)atoi(auth_item_get_string(item
));
785 require(item
->data
.value
!= NULL
, done
);
786 require(item
->data
.valueLength
== sizeof(uint32_t), done
);
788 return *(uint32_t*)item
->data
.value
;
796 auth_items_set_int64(auth_items_t items
, const char *key
, int64_t value
)
798 auth_item_t item
= _find_item(items
,key
);
799 if (item
&& item
->type
== AI_TYPE_INT64
) {
800 *(int64_t*)item
->data
.value
= value
;
802 item
= auth_item_create(AI_TYPE_INT64
, key
, &value
, sizeof(int64_t), 0);
804 CFDictionarySetValue(items
->dictionary
, auth_item_get_cf_key(item
), item
);
811 auth_items_get_int64(auth_items_t items
, const char *key
)
813 auth_item_t item
= _find_item(items
,key
);
816 if (!(item
->type
==AI_TYPE_INT64
|| item
->type
== AI_TYPE_UNKNOWN
) || (item
->data
.valueLength
!= sizeof(int64_t))) {
817 LOGV("auth_items: key = %s, invalid type=%i expected=%i or size=%li expected=%li",
818 item
->data
.name
, item
->type
, AI_TYPE_INT64
, item
->data
.valueLength
, sizeof(int64_t));
821 if (item
->type
== AI_TYPE_STRING
) {
822 return atoll(auth_item_get_string(item
));
825 require(item
->data
.value
!= NULL
, done
);
826 require(item
->data
.valueLength
== sizeof(int64_t), done
);
828 return *(int64_t*)item
->data
.value
;
836 auth_items_set_uint64(auth_items_t items
, const char *key
, uint64_t value
)
838 auth_item_t item
= _find_item(items
,key
);
839 if (item
&& item
->type
== AI_TYPE_UINT64
) {
840 *(uint64_t*)item
->data
.value
= value
;
842 item
= auth_item_create(AI_TYPE_UINT64
, key
, &value
, sizeof(uint64_t), 0);
844 CFDictionarySetValue(items
->dictionary
, auth_item_get_cf_key(item
), item
);
851 auth_items_get_uint64(auth_items_t items
, const char *key
)
853 auth_item_t item
= _find_item(items
,key
);
856 if (!(item
->type
==AI_TYPE_UINT64
|| item
->type
== AI_TYPE_UNKNOWN
) || (item
->data
.valueLength
!= sizeof(uint64_t))) {
857 LOGV("auth_items: key = %s, invalid type=%i expected=%i or size=%li expected=%li",
858 item
->data
.name
, item
->type
, AI_TYPE_UINT64
, item
->data
.valueLength
, sizeof(uint64_t));
861 if (item
->type
== AI_TYPE_STRING
) {
862 return (uint64_t)atoll(auth_item_get_string(item
));
865 require(item
->data
.value
!= NULL
, done
);
866 require(item
->data
.valueLength
== sizeof(uint64_t), done
);
868 return *(uint64_t*)item
->data
.value
;
875 void auth_items_set_double(auth_items_t items
, const char *key
, double value
)
877 auth_item_t item
= _find_item(items
,key
);
878 if (item
&& item
->type
== AI_TYPE_DOUBLE
) {
879 *(double*)item
->data
.value
= value
;
881 item
= auth_item_create(AI_TYPE_DOUBLE
, key
, &value
, sizeof(double), 0);
883 CFDictionarySetValue(items
->dictionary
, auth_item_get_cf_key(item
), item
);
889 double auth_items_get_double(auth_items_t items
, const char *key
)
891 auth_item_t item
= _find_item(items
,key
);
894 if (!(item
->type
==AI_TYPE_DOUBLE
|| item
->type
== AI_TYPE_UNKNOWN
) || (item
->data
.valueLength
!= sizeof(double))) {
895 LOGV("auth_items: key = %s, invalid type=%i expected=%i or size=%li expected=%li",
896 item
->data
.name
, item
->type
, AI_TYPE_DOUBLE
, item
->data
.valueLength
, sizeof(double));
899 if (item
->type
== AI_TYPE_STRING
) {
900 return atof(auth_item_get_string(item
));
903 require(item
->data
.value
!= NULL
, done
);
904 require(item
->data
.valueLength
== sizeof(double), done
);
906 return *(double*)item
->data
.value
;
913 uint32_t auth_items_get_type(auth_items_t items
, const char *key
)
915 auth_item_t item
= _find_item(items
,key
);
920 return AI_TYPE_UNKNOWN
;
923 size_t auth_items_get_length(auth_items_t items
, const char *key
)
925 auth_item_t item
= _find_item(items
,key
);
927 return item
->data
.valueLength
;
933 void auth_items_set_value(auth_items_t items
, const char *key
, uint32_t type
, uint32_t flags
, const void *value
, size_t len
)
935 auth_item_t item
= auth_item_create(type
, key
, value
, len
, flags
);
937 CFDictionarySetValue(items
->dictionary
, auth_item_get_cf_key(item
), item
);
943 #pragma mark auth_rights_t
945 struct _auth_rights_s
{
946 __AUTH_BASE_STRUCT_HEADER__
;
948 CFMutableArrayRef array
;
952 _auth_rights_finalize(CFTypeRef value
)
954 auth_rights_t rights
= (auth_rights_t
)value
;
956 CFReleaseNull(rights
->array
);
960 _auth_rights_equal(CFTypeRef value1
, CFTypeRef value2
)
962 auth_rights_t rights1
= (auth_rights_t
)value1
;
963 auth_rights_t rights2
= (auth_rights_t
)value2
;
965 return CFEqual(rights1
->array
, rights2
->array
);
969 _auth_rights_copy_description(CFTypeRef value
)
971 auth_rights_t rights
= (auth_rights_t
)value
;
972 return CFCopyDescription(rights
->array
);
975 AUTH_TYPE_INSTANCE(auth_rights
,
978 .finalize
= _auth_rights_finalize
,
979 .equal
= _auth_rights_equal
,
981 .copyFormattingDesc
= NULL
,
982 .copyDebugDesc
= _auth_rights_copy_description
985 static CFTypeID
auth_rights_get_type_id()
987 static CFTypeID type_id
= _kCFRuntimeNotATypeID
;
988 static dispatch_once_t onceToken
;
990 dispatch_once(&onceToken
, ^{
991 type_id
= _CFRuntimeRegisterClass(&_auth_type_auth_rights
);
998 _auth_rights_create()
1000 auth_rights_t rights
= NULL
;
1002 rights
= (auth_rights_t
)_CFRuntimeCreateInstance(kCFAllocatorDefault
, auth_rights_get_type_id(), AUTH_CLASS_SIZE(auth_rights
), NULL
);
1003 require(rights
!= NULL
, done
);
1005 rights
->array
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
);
1012 auth_rights_create()
1014 auth_rights_t rights
= _auth_rights_create();
1015 require(rights
!= NULL
, done
);
1021 auth_rights_t
auth_rights_create_with_xpc(const xpc_object_t data
)
1023 auth_rights_t rights
= _auth_rights_create();
1024 require(rights
!= NULL
, done
);
1025 require(data
!= NULL
, done
);
1026 require(xpc_get_type(data
) == XPC_TYPE_ARRAY
, done
);
1028 xpc_array_apply(data
, ^bool(size_t index AUTH_UNUSED
, xpc_object_t value
) {
1030 auth_item_t item
= auth_item_create_with_xpc(value
);
1032 CFArrayAppendValue(rights
->array
, item
);
1033 CFReleaseSafe(item
);
1043 xpc_object_t
auth_rights_export_xpc(auth_rights_t rights
)
1045 xpc_object_t array
= xpc_array_create(NULL
, 0);
1047 CFIndex count
= CFArrayGetCount(rights
->array
);
1048 for (CFIndex i
= 0; i
< count
; i
++) {
1049 auth_item_t item
= (auth_item_t
)CFArrayGetValueAtIndex(rights
->array
, i
);
1050 xpc_object_t xpc_data
= auth_item_copy_auth_item_xpc(item
);
1051 xpc_array_append_value(array
, xpc_data
);
1052 xpc_release_safe(xpc_data
);
1059 _find_right_item(auth_rights_t rights
, const char * key
)
1061 auth_item_t item
= NULL
;
1062 CFStringRef lookup
= NULL
;
1063 require(key
!= NULL
, done
);
1065 lookup
= CFStringCreateWithCStringNoCopy(kCFAllocatorDefault
, key
, kCFStringEncodingUTF8
, kCFAllocatorNull
);
1066 require(lookup
!= NULL
, done
);
1068 CFIndex count
= CFArrayGetCount(rights
->array
);
1069 for (CFIndex i
= 0; i
< count
; i
++) {
1070 auth_item_t tmp
= (auth_item_t
)CFArrayGetValueAtIndex(rights
->array
, i
);
1071 if (tmp
&& CFEqual(auth_item_get_cf_key(tmp
), lookup
)) {
1078 CFReleaseSafe(lookup
);
1082 void auth_rights_set_flags(auth_rights_t rights
, const char *key
, uint32_t flags
)
1084 auth_item_t item
= _find_right_item(rights
,key
);
1086 item
->data
.flags
|= flags
;
1090 void auth_rights_clear_flags(auth_rights_t rights
, const char *key
, uint32_t flags
)
1092 auth_item_t item
= _find_right_item(rights
,key
);
1094 item
->data
.flags
&= ~flags
;
1098 uint32_t auth_rights_get_flags(auth_rights_t rights
, const char *key
)
1100 auth_item_t item
= _find_right_item(rights
,key
);
1102 return item
->data
.flags
;
1108 bool auth_rights_check_flags(auth_rights_t rights
, const char *key
, uint32_t flags
)
1110 uint32_t current
= auth_rights_get_flags(rights
,key
);
1111 return flags
? (current
& flags
) != 0 : current
== 0;
1114 size_t auth_rights_get_count(auth_rights_t rights
)
1116 return (size_t)CFArrayGetCount(rights
->array
);
1119 void auth_rights_add(auth_rights_t rights
, const char *key
)
1121 auth_item_t item
= auth_item_create(AI_TYPE_RIGHT
, key
, NULL
, 0, 0);
1123 CFArrayAppendValue(rights
->array
, item
);
1124 CFReleaseSafe(item
);
1128 bool auth_rights_exist(auth_rights_t rights
, const char *key
)
1130 return (_find_right_item(rights
,key
) != NULL
);
1133 void auth_rights_remove(auth_rights_t rights
, const char *key
)
1135 CFStringRef lookup
= CFStringCreateWithCStringNoCopy(kCFAllocatorDefault
, key
, kCFStringEncodingUTF8
, kCFAllocatorNull
);
1136 CFIndex count
= CFArrayGetCount(rights
->array
);
1137 for (CFIndex i
= 0; i
< count
; i
++) {
1138 auth_item_t item
= (auth_item_t
)CFArrayGetValueAtIndex(rights
->array
, i
);
1139 if (CFEqual(auth_item_get_cf_key(item
), lookup
)) {
1140 CFArrayRemoveValueAtIndex(rights
->array
, i
);
1145 CFReleaseSafe(lookup
);
1148 void auth_rights_clear(auth_rights_t rights
)
1150 CFArrayRemoveAllValues(rights
->array
);
1154 auth_rights_iterate(auth_rights_t rights
, bool(^iter
)(const char * key
))
1156 bool result
= false;
1158 CFIndex count
= CFArrayGetCount(rights
->array
);
1159 for (CFIndex i
= 0; i
< count
; i
++) {
1160 auth_item_t item
= (auth_item_t
)CFArrayGetValueAtIndex(rights
->array
, i
);
1161 result
= iter(item
->data
.name
);