X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/c38e3ce98599a410a47dc10253faa4d5830f13b2..427c49bcad63d042b29ada2ac27e3dfc4845c779:/authd/authutilities.c?ds=inline diff --git a/authd/authutilities.c b/authd/authutilities.c new file mode 100644 index 00000000..52e4b0fe --- /dev/null +++ b/authd/authutilities.c @@ -0,0 +1,283 @@ +/* Copyright (c) 2012 Apple Inc. All rights reserved. */ + +#include "authutilities.h" +#include "authd_private.h" +#include "debugging.h" + +#include +#include +#include + +xpc_object_t +SerializeItemSet(const AuthorizationItemSet * itemSet) +{ + xpc_object_t set = NULL; + require_quiet(itemSet != NULL, done); + require_quiet(itemSet->count != 0, done); + + set = xpc_array_create(NULL, 0); + require(set != NULL, done); + + for (uint32_t i = 0; i < itemSet->count; i++) { + xpc_object_t item = xpc_dictionary_create(NULL, NULL, 0); + require(item != NULL, done); + + xpc_dictionary_set_string(item, AUTH_XPC_ITEM_NAME, itemSet->items[i].name); + xpc_dictionary_set_uint64(item, AUTH_XPC_ITEM_FLAGS, itemSet->items[i].flags); + xpc_dictionary_set_data(item, AUTH_XPC_ITEM_VALUE, itemSet->items[i].value, itemSet->items[i].valueLength); + xpc_array_set_value(set, XPC_ARRAY_APPEND, item); + xpc_release(item); + } + +done: + return set; +} + +AuthorizationItemSet * +DeserializeItemSet(const xpc_object_t data) +{ + AuthorizationItemSet * set = NULL; + require_quiet(data != NULL, done); + xpc_retain(data); + require(xpc_get_type(data) == XPC_TYPE_ARRAY, done); + + set = (AuthorizationItemSet*)calloc(1u, sizeof(AuthorizationItemSet)); + require(set != NULL, done); + + set->count = (uint32_t)xpc_array_get_count(data); + if (set->count) { + set->items = (AuthorizationItem*)calloc(set->count, sizeof(AuthorizationItem)); + require_action(set->items != NULL, done, set->count = 0); + + xpc_array_apply(data, ^bool(size_t index, xpc_object_t value) { + require(xpc_get_type(value) == XPC_TYPE_DICTIONARY, done); + size_t nameLen = 0; + const char * name = xpc_dictionary_get_string(value, AUTH_XPC_ITEM_NAME); + if (name) { + nameLen = strlen(name) + 1; + set->items[index].name = calloc(1u, nameLen); + require(set->items[index].name != NULL, done); + + strlcpy((char*)set->items[index].name, name, nameLen); + } + set->items[index].flags = (uint32_t)xpc_dictionary_get_uint64(value, AUTH_XPC_ITEM_FLAGS); + size_t len; + const void * valueData = xpc_dictionary_get_data(value, AUTH_XPC_ITEM_VALUE, &len); + set->items[index].valueLength = len; + if (len) { + set->items[index].value = calloc(1u, len); + require(set->items[index].value != NULL, done); + + memcpy(set->items[index].value, valueData, len); + } + done: + return true; + }); + } + +done: + if (data != NULL) { + xpc_release(data); + } + return set; +} + +void FreeItemSet(AuthorizationItemSet * itemSet) +{ + if (!itemSet) { return; } + + for(uint32_t i = 0; i < itemSet->count; i++ ) { + if (itemSet->items[i].name) { + free((void*)itemSet->items[i].name); + } + if (itemSet->items[i].value) { + free(itemSet->items[i].value); + } + } + if (itemSet->items) { + free(itemSet->items); + } + + free(itemSet); +} + +char * +_copy_cf_string(CFTypeRef str, const char * defaultValue) +{ + char * result = NULL; + require(str != NULL, done); + require(CFGetTypeID(str) == CFStringGetTypeID(), done); + + CFIndex length = CFStringGetLength(str); + CFIndex size = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8) + 1; + + result = (char*)calloc(1u, (size_t)size); + check(result != NULL); + + if (!CFStringGetCString(str, result, size, kCFStringEncodingUTF8)) { + free_safe(result); + } + +done: + if (result == NULL && defaultValue) { + size_t len = strlen(defaultValue); + result = (char*)calloc(1u, len); + check(result != NULL); + + strlcpy(result, defaultValue, len); + } + + return result; +} + +int64_t +_get_cf_int(CFTypeRef num, int64_t defaultValue) +{ + int64_t result = defaultValue; + require(num != NULL, done); + require(CFGetTypeID(num) == CFNumberGetTypeID(), done); + + if (!CFNumberGetValue(num, kCFNumberSInt64Type, &result)) { + result = defaultValue; + } + +done: + return result; +} + +bool +_get_cf_bool(CFTypeRef value, bool defaultValue) +{ + bool result = defaultValue; + require(value != NULL, done); + require(CFGetTypeID(value) == CFBooleanGetTypeID(), done); + + result = CFBooleanGetValue(value); + +done: + return result; +} + +bool +_compare_string(const char * str1, const char * str2) +{ + if (!(str1 == str2)) { // compare null or same pointer + if (str1 && str2) { // check both are non null + if (strcasecmp(str1, str2) != 0) { // compare strings + return false; // return false if not equal + } + } else { + return false; // return false if one null + } + } + + return true; +} + +char * +_copy_string(const char * str) +{ + char * result = NULL; + require(str != NULL, done); + + size_t len = strlen(str) + 1; + result = calloc(1u, len); + require(result != NULL, done); + + strlcpy(result, str, len); + +done: + return result; +} + +void * +_copy_data(const void * data, size_t dataLen) +{ + void * result = NULL; + require(data != NULL, done); + + result = calloc(1u, dataLen); + require(result != NULL, done); + + memcpy(result, data, dataLen); + +done: + return result; +} + +bool _cf_set_iterate(CFSetRef set, bool(^iterator)(CFTypeRef value)) +{ + bool result = false; + CFTypeRef* values = NULL; + + require(set != NULL, done); + + CFIndex count = CFSetGetCount(set); + values = calloc((size_t)count, sizeof(CFTypeRef)); + require(values != NULL, done); + + CFSetGetValues(set, values); + for (CFIndex i = 0; i < count; i++) { + result = iterator(values[i]); + if (!result) { + break; + } + } + +done: + free_safe(values); + return result; +} + +bool _cf_bag_iterate(CFBagRef bag, bool(^iterator)(CFTypeRef value)) +{ + bool result = false; + CFTypeRef* values = NULL; + + require(bag != NULL, done); + + CFIndex count = CFBagGetCount(bag); + values = calloc((size_t)count, sizeof(CFTypeRef)); + require(values != NULL, done); + + CFBagGetValues(bag, values); + for (CFIndex i = 0; i < count; i++) { + result = iterator(values[i]); + if (!result) { + break; + } + } + +done: + free_safe(values); + return result; +} + +bool _cf_dictionary_iterate(CFDictionaryRef dict, bool(^iterator)(CFTypeRef key, CFTypeRef value)) +{ + bool result = false; + CFTypeRef* keys = NULL; + CFTypeRef* values = NULL; + + require(dict != NULL, done); + + CFIndex count = CFDictionaryGetCount(dict); + keys = calloc((size_t)count, sizeof(CFTypeRef)); + require(keys != NULL, done); + + values = calloc((size_t)count, sizeof(CFTypeRef)); + require(values != NULL, done); + + CFDictionaryGetKeysAndValues(dict, keys, values); + for (CFIndex i = 0; i < count; i++) { + result = iterator(keys[i], values[i]); + if (!result) { + break; + } + } + +done: + free_safe(keys); + free_safe(values); + return result; +}