1/* Copyright (c) 2012 Apple Inc. All rights reserved. */ 2 3#include "authutilities.h" 4#include "authd_private.h" 5#include "debugging.h" 6 7#include <AssertMacros.h> 8#include <assert.h> 9#include <syslog.h> 10 11xpc_object_t 12SerializeItemSet(const AuthorizationItemSet * itemSet) 13{ 14 xpc_object_t set = NULL; 15 require_quiet(itemSet != NULL, done); 16 require_quiet(itemSet->count != 0, done); 17 18 set = xpc_array_create(NULL, 0); 19 require(set != NULL, done); 20 21 for (uint32_t i = 0; i < itemSet->count; i++) { 22 xpc_object_t item = xpc_dictionary_create(NULL, NULL, 0); 23 require(item != NULL, done); 24 25 xpc_dictionary_set_string(item, AUTH_XPC_ITEM_NAME, itemSet->items[i].name); 26 xpc_dictionary_set_uint64(item, AUTH_XPC_ITEM_FLAGS, itemSet->items[i].flags); 27 xpc_dictionary_set_data(item, AUTH_XPC_ITEM_VALUE, itemSet->items[i].value, itemSet->items[i].valueLength); 28 xpc_array_set_value(set, XPC_ARRAY_APPEND, item); 29 xpc_release(item); 30 } 31 32done: 33 return set; 34} 35 36AuthorizationItemSet * 37DeserializeItemSet(const xpc_object_t data) 38{ 39 AuthorizationItemSet * set = NULL; 40 require_quiet(data != NULL, done); 41 xpc_retain(data); 42 require(xpc_get_type(data) == XPC_TYPE_ARRAY, done); 43 44 set = (AuthorizationItemSet*)calloc(1u, sizeof(AuthorizationItemSet)); 45 require(set != NULL, done); 46 47 set->count = (uint32_t)xpc_array_get_count(data); 48 if (set->count) { 49 set->items = (AuthorizationItem*)calloc(set->count, sizeof(AuthorizationItem)); 50 require_action(set->items != NULL, done, set->count = 0); 51 52 xpc_array_apply(data, ^bool(size_t index, xpc_object_t value) { 53 require(xpc_get_type(value) == XPC_TYPE_DICTIONARY, done); 54 size_t nameLen = 0; 55 const char * name = xpc_dictionary_get_string(value, AUTH_XPC_ITEM_NAME); 56 if (name) { 57 nameLen = strlen(name) + 1; 58 set->items[index].name = calloc(1u, nameLen); 59 require(set->items[index].name != NULL, done); 60 61 strlcpy((char*)set->items[index].name, name, nameLen); 62 } 63 set->items[index].flags = (uint32_t)xpc_dictionary_get_uint64(value, AUTH_XPC_ITEM_FLAGS); 64 size_t len; 65 const void * valueData = xpc_dictionary_get_data(value, AUTH_XPC_ITEM_VALUE, &len); 66 set->items[index].valueLength = len; 67 if (len) { 68 set->items[index].value = calloc(1u, len); 69 require(set->items[index].value != NULL, done); 70 71 memcpy(set->items[index].value, valueData, len); 72 } 73 done: 74 return true; 75 }); 76 } 77 78done: 79 if (data != NULL) { 80 xpc_release(data); 81 } 82 return set; 83} 84 85void FreeItemSet(AuthorizationItemSet * itemSet) 86{ 87 if (!itemSet) { return; } 88 89 for(uint32_t i = 0; i < itemSet->count; i++ ) { 90 if (itemSet->items[i].name) { 91 free((void*)itemSet->items[i].name); 92 } 93 if (itemSet->items[i].value) { 94 free(itemSet->items[i].value); 95 } 96 } 97 if (itemSet->items) { 98 free(itemSet->items); 99 } 100 101 free(itemSet); 102} 103 104char * 105_copy_cf_string(CFTypeRef str, const char * defaultValue) 106{ 107 char * result = NULL; 108 require(str != NULL, done); 109 require(CFGetTypeID(str) == CFStringGetTypeID(), done); 110 111 CFIndex length = CFStringGetLength(str); 112 CFIndex size = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8) + 1; 113 114 result = (char*)calloc(1u, (size_t)size); 115 check(result != NULL); 116 117 if (!CFStringGetCString(str, result, size, kCFStringEncodingUTF8)) { 118 free_safe(result); 119 } 120 121done: 122 if (result == NULL && defaultValue) { 123 size_t len = strlen(defaultValue); 124 result = (char*)calloc(1u, len); 125 check(result != NULL); 126 127 strlcpy(result, defaultValue, len); 128 } 129 130 return result; 131} 132 133int64_t 134_get_cf_int(CFTypeRef num, int64_t defaultValue) 135{ 136 int64_t result = defaultValue; 137 require(num != NULL, done); 138 require(CFGetTypeID(num) == CFNumberGetTypeID(), done); 139 140 if (!CFNumberGetValue(num, kCFNumberSInt64Type, &result)) { 141 result = defaultValue; 142 } 143 144done: 145 return result; 146} 147 148bool 149_get_cf_bool(CFTypeRef value, bool defaultValue) 150{ 151 bool result = defaultValue; 152 require(value != NULL, done); 153 require(CFGetTypeID(value) == CFBooleanGetTypeID(), done); 154 155 result = CFBooleanGetValue(value); 156 157done: 158 return result; 159} 160 161bool 162_compare_string(const char * str1, const char * str2) 163{ 164 if (!(str1 == str2)) { // compare null or same pointer 165 if (str1 && str2) { // check both are non null 166 if (strcasecmp(str1, str2) != 0) { // compare strings 167 return false; // return false if not equal 168 } 169 } else { 170 return false; // return false if one null 171 } 172 } 173 174 return true; 175} 176 177char * 178_copy_string(const char * str) 179{ 180 char * result = NULL; 181 require(str != NULL, done); 182 183 size_t len = strlen(str) + 1; 184 result = calloc(1u, len); 185 require(result != NULL, done); 186 187 strlcpy(result, str, len); 188 189done: 190 return result; 191} 192 193void * 194_copy_data(const void * data, size_t dataLen) 195{ 196 void * result = NULL; 197 require(data != NULL, done); 198 199 result = calloc(1u, dataLen); 200 require(result != NULL, done); 201 202 memcpy(result, data, dataLen); 203 204done: 205 return result; 206} 207 208bool _cf_set_iterate(CFSetRef set, bool(^iterator)(CFTypeRef value)) 209{ 210 bool result = false; 211 CFTypeRef* values = NULL; 212 213 require(set != NULL, done); 214 215 CFIndex count = CFSetGetCount(set); 216 values = calloc((size_t)count, sizeof(CFTypeRef)); 217 require(values != NULL, done); 218 219 CFSetGetValues(set, values); 220 for (CFIndex i = 0; i < count; i++) { 221 result = iterator(values[i]); 222 if (!result) { 223 break; 224 } 225 } 226 227done: 228 free_safe(values); 229 return result; 230} 231 232bool _cf_bag_iterate(CFBagRef bag, bool(^iterator)(CFTypeRef value)) 233{ 234 bool result = false; 235 CFTypeRef* values = NULL; 236 237 require(bag != NULL, done); 238 239 CFIndex count = CFBagGetCount(bag); 240 values = calloc((size_t)count, sizeof(CFTypeRef)); 241 require(values != NULL, done); 242 243 CFBagGetValues(bag, values); 244 for (CFIndex i = 0; i < count; i++) { 245 result = iterator(values[i]); 246 if (!result) { 247 break; 248 } 249 } 250 251done: 252 free_safe(values); 253 return result; 254} 255 256bool _cf_dictionary_iterate(CFDictionaryRef dict, bool(^iterator)(CFTypeRef key, CFTypeRef value)) 257{ 258 bool result = false; 259 CFTypeRef* keys = NULL; 260 CFTypeRef* values = NULL; 261 262 require(dict != NULL, done); 263 264 CFIndex count = CFDictionaryGetCount(dict); 265 keys = calloc((size_t)count, sizeof(CFTypeRef)); 266 require(keys != NULL, done); 267 268 values = calloc((size_t)count, sizeof(CFTypeRef)); 269 require(values != NULL, done); 270 271 CFDictionaryGetKeysAndValues(dict, keys, values); 272 for (CFIndex i = 0; i < count; i++) { 273 result = iterator(keys[i], values[i]); 274 if (!result) { 275 break; 276 } 277 } 278 279done: 280 free_safe(keys); 281 free_safe(values); 282 return result; 283} 284