]> git.saurik.com Git - apple/security.git/blob - codesign_wrapper/MISEntitlement.c
Security-57337.40.85.tar.gz
[apple/security.git] / codesign_wrapper / MISEntitlement.c
1 #include "MISEntitlement.h"
2
3 static const CFStringRef kEntitlementAllValuesAllowed = CFSTR("*");
4
5 static 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
38 Boolean 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 }