1#include "MISEntitlement.h" 2 3static const CFStringRef kEntitlementAllValuesAllowed = CFSTR("*"); 4 5static Boolean whitelistArrayAllowsEntitlementValue(CFArrayRef whitelist, CFStringRef value) 6{ 7 Boolean allowed = false; 8 9 CFIndex i, count = CFArrayGetCount(whitelist); 10 for (i = 0; (i < count) && (allowed == false); i++) { 11 CFStringRef item = (CFStringRef) CFArrayGetValueAtIndex(whitelist, i); 12 if (CFGetTypeID(item) == CFStringGetTypeID()) { 13 14 CFIndex len = CFStringGetLength(item); 15 if (len > 0) { 16 if (CFStringGetCharacterAtIndex(item, len-1) != '*') { 17 18 /* Not a wildcard, must be an exact match */ 19 allowed = CFStringCompare(item, value, 0) == kCFCompareEqualTo; 20 } else { 21 22 /* Last character is a wildcard - do some matching */ 23 CFStringRef wildcardPrefix = CFStringCreateWithSubstring(kCFAllocatorDefault, item, CFRangeMake(0, len-1)); 24 allowed = CFStringHasPrefix(value, wildcardPrefix); 25 CFRelease(wildcardPrefix); 26 } 27 } 28 } else { 29 30 /* Unexpected item in whitelist - bail */ 31 break; 32 } 33 } 34 35 return allowed; 36} 37 38Boolean MISEntitlementDictionaryAllowsEntitlementValue(CFDictionaryRef entitlements, CFStringRef entitlement, CFTypeRef value) 39{ 40 Boolean allowsEntitlement = false; 41 42 /* NULL is never a valid entitlement value */ 43 if (value != NULL) { 44 45 /* Make sure the entitlement is present */ 46 CFTypeRef storedValue = CFDictionaryGetValue(entitlements, entitlement); 47 if (storedValue != NULL) { 48 49 /* 50 * Handling depends on the type 51 * If the value matches our constant, the entitlement is permitted 52 * to have any value. 53 * If the value in the dictionary is a boolean, then the entitlement 54 * value must be a boolean with the same value 55 * If the value in the dictionary is an array (of strings), then the 56 * entitlement must be either one of those strings OR an array that 57 * includes only present strings 58 */ 59 if (CFEqual(storedValue, kEntitlementAllValuesAllowed) == true) { 60 61 /* XXX: Does this need to restrict the value to some types */ 62 allowsEntitlement = true; 63 } else if (CFGetTypeID(storedValue) == CFBooleanGetTypeID()) { 64 allowsEntitlement = CFEqual(storedValue, value); 65 } else if (CFGetTypeID(storedValue) == CFStringGetTypeID()) { 66 if (CFGetTypeID(value) == CFStringGetTypeID()) { 67 CFArrayRef array = CFArrayCreate(kCFAllocatorDefault, (const void **) &storedValue, 1, &kCFTypeArrayCallBacks); 68 allowsEntitlement = whitelistArrayAllowsEntitlementValue(array, (CFStringRef) value); 69 CFRelease(array); 70 } 71 } else if (CFGetTypeID(storedValue) == CFArrayGetTypeID()) { 72 73 /* value is either a single string or array of strings */ 74 if (CFGetTypeID(value) == CFStringGetTypeID()) { 75 allowsEntitlement = whitelistArrayAllowsEntitlementValue((CFArrayRef) storedValue, (CFStringRef) value); 76 } else if (CFGetTypeID(value) == CFArrayGetTypeID()) { 77 78 /* 79 * Assume allowed, will set back to false if we encounter 80 * elements that are not permitted 81 */ 82 allowsEntitlement = true; 83 84 /* Make sure each element is a string and in the array */ 85 CFIndex i, count = CFArrayGetCount((CFArrayRef) value); 86 for (i = 0; (i < count) && (allowsEntitlement == true); i++) { 87 CFTypeRef element = CFArrayGetValueAtIndex((CFArrayRef) value, i); 88 if (CFGetTypeID(element) == CFStringGetTypeID()) { 89 allowsEntitlement = whitelistArrayAllowsEntitlementValue((CFArrayRef) storedValue, (CFStringRef) element); 90 } else { 91 allowsEntitlement = false; 92 } 93 } 94 } 95 } 96 } 97 } 98 99 return allowsEntitlement; 100} 101