1*d4514f0bSApple OSS Distributions // 2*d4514f0bSApple OSS Distributions // QueryHelpers.h 3*d4514f0bSApple OSS Distributions // CoreEntitlements 4*d4514f0bSApple OSS Distributions // 5*d4514f0bSApple OSS Distributions 6*d4514f0bSApple OSS Distributions #ifndef CORE_ENTITLEMENTS_HELPERS_H 7*d4514f0bSApple OSS Distributions #define CORE_ENTITLEMENTS_HELPERS_H 8*d4514f0bSApple OSS Distributions 9*d4514f0bSApple OSS Distributions #include <sys/cdefs.h> 10*d4514f0bSApple OSS Distributions __ptrcheck_abi_assume_single(); 11*d4514f0bSApple OSS Distributions 12*d4514f0bSApple OSS Distributions /*! 13*d4514f0bSApple OSS Distributions * @function CEDynamic 14*d4514f0bSApple OSS Distributions * Marks an opcode as being dynamic 15*d4514f0bSApple OSS Distributions * 16*d4514f0bSApple OSS Distributions * @param op 17*d4514f0bSApple OSS Distributions * Opcode 18*d4514f0bSApple OSS Distributions */ 19*d4514f0bSApple OSS Distributions #define CEDynamic(op) (CEQueryOpOpcode_t)((op) | kCEOpDynamic) 20*d4514f0bSApple OSS Distributions 21*d4514f0bSApple OSS Distributions /*! 22*d4514f0bSApple OSS Distributions * @function CESelectIndex 23*d4514f0bSApple OSS Distributions * Returns an operation that when executed will modify the context such that any subsequent operation is performed on the entitlement object at the specified index 24*d4514f0bSApple OSS Distributions * 25*d4514f0bSApple OSS Distributions * @param index 26*d4514f0bSApple OSS Distributions * The index of the object within a container 27*d4514f0bSApple OSS Distributions * 28*d4514f0bSApple OSS Distributions * @discussion 29*d4514f0bSApple OSS Distributions * Using an index that is past the container's size will result in an invalid context 30*d4514f0bSApple OSS Distributions */ 31*d4514f0bSApple OSS Distributions #define CESelectIndex(index) (CEQueryOperation_t){.opcode = kCEOpSelectIndex, .parameters = {.numericParameter = index}} 32*d4514f0bSApple OSS Distributions 33*d4514f0bSApple OSS Distributions /*! 34*d4514f0bSApple OSS Distributions * @function CESelectKey 35*d4514f0bSApple OSS Distributions * Returns an operation that when executed will modify the context such that any subsequent operation is performed on the key of the dictionary pair 36*d4514f0bSApple OSS Distributions * @discussion 37*d4514f0bSApple OSS Distributions * Selecting a key on a non-dictionary-pair object is undefined behavior (i..e. it is implementation defined) 38*d4514f0bSApple OSS Distributions */ 39*d4514f0bSApple OSS Distributions #define CESelectKey() CESelectIndex(0) 40*d4514f0bSApple OSS Distributions 41*d4514f0bSApple OSS Distributions /*! 42*d4514f0bSApple OSS Distributions * @function CESelectValue 43*d4514f0bSApple OSS Distributions * Returns an operation that when executed will modify the context such that any subsequent operation is performed on the value of the dictionary pair 44*d4514f0bSApple OSS Distributions * @discussion 45*d4514f0bSApple OSS Distributions * Selecting a value on a non-dictionary-pair object is undefined behavior (i..e. it is implementation defined) 46*d4514f0bSApple OSS Distributions */ 47*d4514f0bSApple OSS Distributions #define CESelectValue() CESelectIndex(1) 48*d4514f0bSApple OSS Distributions 49*d4514f0bSApple OSS Distributions 50*d4514f0bSApple OSS Distributions /*! 51*d4514f0bSApple OSS Distributions * @function CESelectDictValue 52*d4514f0bSApple OSS Distributions * Returns an operation that when executed will modify the context such that any subsequent operation is performed on the object that corresponds 53*d4514f0bSApple OSS Distributions * to the value pointed to by the specified key 54*d4514f0bSApple OSS Distributions * 55*d4514f0bSApple OSS Distributions * @param key 56*d4514f0bSApple OSS Distributions * The key of the object within a container 57*d4514f0bSApple OSS Distributions * 58*d4514f0bSApple OSS Distributions * @discussion 59*d4514f0bSApple OSS Distributions * Using a key that is not found in the container will result in an invalid context 60*d4514f0bSApple OSS Distributions */ 61*d4514f0bSApple OSS Distributions #define CESelectDictValue(key) (CEQueryOperation_t){.opcode = kCEOpSelectKey, .parameters = {.stringParameter = {.data = key, .length = sizeof(key) - 1}}} 62*d4514f0bSApple OSS Distributions #define CESelectDictValueDynamic(key, len) (CEQueryOperation_t){.opcode = CEDynamic(kCEOpSelectKey), .parameters = {.dynamicParameter = {.data = key, .length = len}}} 63*d4514f0bSApple OSS Distributions 64*d4514f0bSApple OSS Distributions /*! 65*d4514f0bSApple OSS Distributions * @function CEMatchString 66*d4514f0bSApple OSS Distributions * Returns an operation that will return a valid context if and only if the context corresponds to a valid string and matches the string exactly 67*d4514f0bSApple OSS Distributions * 68*d4514f0bSApple OSS Distributions * @param string 69*d4514f0bSApple OSS Distributions * The string to match against (MUST BE A STRING LITERAL) 70*d4514f0bSApple OSS Distributions * 71*d4514f0bSApple OSS Distributions * @discussion 72*d4514f0bSApple OSS Distributions * If a valid context is returned it will be in the same state as the execution context 73*d4514f0bSApple OSS Distributions */ 74*d4514f0bSApple OSS Distributions #define CEMatchString(string) (CEQueryOperation_t){.opcode = kCEOpMatchString, .parameters = {.stringParameter = {.data = string, .length = sizeof(string) - 1}}} 75*d4514f0bSApple OSS Distributions #define CEMatchDynamicString(string, len) (CEQueryOperation_t){.opcode = CEDynamic(kCEOpMatchString), .parameters = {.dynamicParameter = {.data = string, .length = len}}} 76*d4514f0bSApple OSS Distributions 77*d4514f0bSApple OSS Distributions /*! 78*d4514f0bSApple OSS Distributions * @function CEMatchPrefix 79*d4514f0bSApple OSS Distributions * Returns an operation that will return a valid context if and only if the context corresponds to a valid string and it's prefix matched the passed in prefix 80*d4514f0bSApple OSS Distributions * 81*d4514f0bSApple OSS Distributions * @param prefix 82*d4514f0bSApple OSS Distributions * The prefix to match against (MUST BE A STRING LITERAL) 83*d4514f0bSApple OSS Distributions * 84*d4514f0bSApple OSS Distributions * @discussion 85*d4514f0bSApple OSS Distributions * If a valid context is returned it will be in the same state as the execution context 86*d4514f0bSApple OSS Distributions */ 87*d4514f0bSApple OSS Distributions #define CEMatchPrefix(prefix) (CEQueryOperation_t){.opcode = kCEOpMatchStringPrefix, .parameters = {.stringParameter = {.data = prefix, .length = sizeof(prefix) - 1}}} 88*d4514f0bSApple OSS Distributions #define CEMatchDynamicPrefix(prefix, len) (CEQueryOperation_t){.opcode = CEDynamic(kCEOpMatchStringPrefix), .parameters = {.dynamicParameter = {.data = prefix, .length = len}}} 89*d4514f0bSApple OSS Distributions 90*d4514f0bSApple OSS Distributions /*! 91*d4514f0bSApple OSS Distributions * @function CEMatchType 92*d4514f0bSApple OSS Distributions * Returns an operation that will return a valid context if and only if the type selected by the context corresponds to the one passed in. 93*d4514f0bSApple OSS Distributions * 94*d4514f0bSApple OSS Distributions * @param type 95*d4514f0bSApple OSS Distributions * The type to match against 96*d4514f0bSApple OSS Distributions * 97*d4514f0bSApple OSS Distributions * @discussion 98*d4514f0bSApple OSS Distributions * If a valid context is returned it will be in the same state as the execution context 99*d4514f0bSApple OSS Distributions */ 100*d4514f0bSApple OSS Distributions #define CEMatchType(type) (CEQueryOperation_t){.opcode = kCEOpMatchType, .parameters = {.numericParameter = (int64_t)type}} 101*d4514f0bSApple OSS Distributions 102*d4514f0bSApple OSS Distributions /*! 103*d4514f0bSApple OSS Distributions * @function CEMatchBool 104*d4514f0bSApple OSS Distributions * Returns an operation that will return a valid context if and only if the context corresponds to a valid boolean and matches the boolean exactly 105*d4514f0bSApple OSS Distributions * 106*d4514f0bSApple OSS Distributions * @param val 107*d4514f0bSApple OSS Distributions * The bool to match against 108*d4514f0bSApple OSS Distributions * 109*d4514f0bSApple OSS Distributions * @discussion 110*d4514f0bSApple OSS Distributions * If a valid context is returned it will be in the same state as the execution context 111*d4514f0bSApple OSS Distributions */ 112*d4514f0bSApple OSS Distributions #define CEMatchBool(val) (CEQueryOperation_t){.opcode = kCEOpMatchBool, .parameters = {.numericParameter = !!val}} 113*d4514f0bSApple OSS Distributions 114*d4514f0bSApple OSS Distributions /*! 115*d4514f0bSApple OSS Distributions * @function CEMatchInteger 116*d4514f0bSApple OSS Distributions * Returns an operation that will return a valid context if and only if the context corresponds to a valid integer and matches the integer exactly 117*d4514f0bSApple OSS Distributions * 118*d4514f0bSApple OSS Distributions * @param val 119*d4514f0bSApple OSS Distributions * The integer to match against 120*d4514f0bSApple OSS Distributions * 121*d4514f0bSApple OSS Distributions * @discussion 122*d4514f0bSApple OSS Distributions * If a valid context is returned it will be in the same state as the execution context 123*d4514f0bSApple OSS Distributions */ 124*d4514f0bSApple OSS Distributions #define CEMatchInteger(val) (CEQueryOperation_t){.opcode = kCEOpMatchInteger, .parameters = {.numericParameter = val}} 125*d4514f0bSApple OSS Distributions 126*d4514f0bSApple OSS Distributions /*! 127*d4514f0bSApple OSS Distributions * @function CEIsIntegerAllowed 128*d4514f0bSApple OSS Distributions * Returns an operation that will return a valid context if 1) the current context is an integer and allows the integer, or 2) the context is an array of integers that allows the integer 129*d4514f0bSApple OSS Distributions * 130*d4514f0bSApple OSS Distributions * @param integer 131*d4514f0bSApple OSS Distributions * The integer to match against 132*d4514f0bSApple OSS Distributions * 133*d4514f0bSApple OSS Distributions * @discussion 134*d4514f0bSApple OSS Distributions * If a valid context is returned it will be in the same state as the execution context 135*d4514f0bSApple OSS Distributions */ 136*d4514f0bSApple OSS Distributions #define CEIsIntegerAllowed(integer) (CEQueryOperation_t){.opcode = kCEOpIntegerValueAllowed, .parameters = {.numericParameter = integer}} 137*d4514f0bSApple OSS Distributions 138*d4514f0bSApple OSS Distributions /*! 139*d4514f0bSApple OSS Distributions * @function CEIsStringAllowed 140*d4514f0bSApple OSS Distributions * Returns an operation that will return a valid context if 1) the current context is a string and allows the string via wildcard rules, or 2) the context is an array of strings that allows the string 141*d4514f0bSApple OSS Distributions * 142*d4514f0bSApple OSS Distributions * @param string 143*d4514f0bSApple OSS Distributions * The string to match against (MUST BE A STRING LITERAL) 144*d4514f0bSApple OSS Distributions * 145*d4514f0bSApple OSS Distributions * @discussion 146*d4514f0bSApple OSS Distributions * If a valid context is returned it will be in the same state as the execution context 147*d4514f0bSApple OSS Distributions */ 148*d4514f0bSApple OSS Distributions #define CEIsStringAllowed(string) (CEQueryOperation_t){.opcode = kCEOpStringValueAllowed, .parameters = {.stringParameter = {.data = string, .length = sizeof(string) - 1}}} 149*d4514f0bSApple OSS Distributions #define CEIsDynamicStringAllowed(string, len) (CEQueryOperation_t){.opcode = CEDynamic(kCEOpStringValueAllowed), .parameters = {.dynamicParameter = {.data = string, .length = len}}} 150*d4514f0bSApple OSS Distributions 151*d4514f0bSApple OSS Distributions /*! 152*d4514f0bSApple OSS Distributions * @function CEIsStringPrefixAllowed 153*d4514f0bSApple OSS Distributions * Returns an operation that will return a valid context if 1) the current context is a string and matches the prefix or 2) has an array that has the matches the prefix 154*d4514f0bSApple OSS Distributions * 155*d4514f0bSApple OSS Distributions * @param string 156*d4514f0bSApple OSS Distributions * The string to match against (MUST BE A STRING LITERAL) 157*d4514f0bSApple OSS Distributions * 158*d4514f0bSApple OSS Distributions * @discussion 159*d4514f0bSApple OSS Distributions * If a valid context is returned it will be in the same state as the execution context 160*d4514f0bSApple OSS Distributions */ 161*d4514f0bSApple OSS Distributions #define CEIsStringPrefixAllowed(string) (CEQueryOperation_t){.opcode = kCEOpStringPrefixValueAllowed, .parameters = {.stringParameter = {.data = string, .length = sizeof(string) - 1}}} 162*d4514f0bSApple OSS Distributions #define CEIsDynamicStringPrefixAllowed(string, len) (CEQueryOperation_t){.opcode = CEDynamic(kCEOpStringPrefixValueAllowed), .parameters = {.dynamicParameter = {.data = (const uint8_t*)(string), .length = len}}} 163*d4514f0bSApple OSS Distributions 164*d4514f0bSApple OSS Distributions /*! 165*d4514f0bSApple OSS Distributions * @function CEMatchData 166*d4514f0bSApple OSS Distributions * Returns an operation that will return a valid context if and only if the context corresponds to valid data and matches the data exactly 167*d4514f0bSApple OSS Distributions * 168*d4514f0bSApple OSS Distributions * @param string 169*d4514f0bSApple OSS Distributions * The data to match against (MUST BE A BYTE ARRAY) 170*d4514f0bSApple OSS Distributions * 171*d4514f0bSApple OSS Distributions * @discussion 172*d4514f0bSApple OSS Distributions * If a valid context is returned it will be in the same state as the execution context 173*d4514f0bSApple OSS Distributions */ 174*d4514f0bSApple OSS Distributions #define CEMatchDynamicData(d, len) (CEQueryOperation_t){.opcode = CEDynamic(kCEOpMatchData), .parameters = {.dynamicParameter = {.data = d, .length = len}}} 175*d4514f0bSApple OSS Distributions 176*d4514f0bSApple OSS Distributions /*! 177*d4514f0bSApple OSS Distributions * @function CEIsDataAllowed 178*d4514f0bSApple OSS Distributions * Returns an operation that will return a valid context if 1) the current context is data and allows the data, or 2) the context is an array of data elements that allows the data 179*d4514f0bSApple OSS Distributions * 180*d4514f0bSApple OSS Distributions * @param string 181*d4514f0bSApple OSS Distributions * The data to match against (MUST BE A BYTE ARRAY) 182*d4514f0bSApple OSS Distributions * 183*d4514f0bSApple OSS Distributions * @discussion 184*d4514f0bSApple OSS Distributions * If a valid context is returned it will be in the same state as the execution context 185*d4514f0bSApple OSS Distributions */ 186*d4514f0bSApple OSS Distributions #define CEIsDynamicDataAllowed(d, len) (CEQueryOperation_t){.opcode = CEDynamic(kCEOpMatchDataValueAllowed), .parameters = {.dynamicParameter = {.data = d, .length = len}}} 187*d4514f0bSApple OSS Distributions 188*d4514f0bSApple OSS Distributions #pragma mark Helpers 189*d4514f0bSApple OSS Distributions /* 190*d4514f0bSApple OSS Distributions Macro magic 191*d4514f0bSApple OSS Distributions */ 192*d4514f0bSApple OSS Distributions #define _SELECT_NTH_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9, N, ...) N 193*d4514f0bSApple OSS Distributions 194*d4514f0bSApple OSS Distributions #define _mc_1(_call, x) _call(x), 195*d4514f0bSApple OSS Distributions #define _mc_2(_call, x, ...) _call(x), _mc_1(_call, __VA_ARGS__) 196*d4514f0bSApple OSS Distributions #define _mc_3(_call, x, ...) _call(x), _mc_2(_call, __VA_ARGS__) 197*d4514f0bSApple OSS Distributions #define _mc_4(_call, x, ...) _call(x), _mc_3(_call, __VA_ARGS__) 198*d4514f0bSApple OSS Distributions #define _mc_5(_call, x, ...) _call(x), _mc_4(_call, __VA_ARGS__) 199*d4514f0bSApple OSS Distributions #define _mc_6(_call, x, ...) _call(x), _mc_5(_call, __VA_ARGS__) 200*d4514f0bSApple OSS Distributions #define _mc_7(_call, x, ...) _call(x), _mc_6(_call, __VA_ARGS__) 201*d4514f0bSApple OSS Distributions #define _mc_8(_call, x, ...) _call(x), _mc_7(_call, __VA_ARGS__) 202*d4514f0bSApple OSS Distributions #define _mc_9(_call, x, ...) _call(x), _mc_8(_call, __VA_ARGS__) 203*d4514f0bSApple OSS Distributions #define _mc_10(_call, x, ...) _call(x), _mc_9(_call, __VA_ARGS__) 204*d4514f0bSApple OSS Distributions 205*d4514f0bSApple OSS Distributions #define _MACRO_ITER(macro, ...) _SELECT_NTH_ARG(__VA_ARGS__, _mc_10, _mc_9, _mc_8 _mc_7, _mc_6, _mc_5, _mc_4, _mc_3, _mc_2, _mc_1)(macro, __VA_ARGS__) 206*d4514f0bSApple OSS Distributions 207*d4514f0bSApple OSS Distributions /*! 208*d4514f0bSApple OSS Distributions Macro to automatically generate a query path from a list of string sub components 209*d4514f0bSApple OSS Distributions So 210*d4514f0bSApple OSS Distributions @code 211*d4514f0bSApple OSS Distributions CE_SELECT_PATH("hello, "world") will select a key "hello" and then look up "world" in the dictionary stored in the value of "hello" 212*d4514f0bSApple OSS Distributions @endcode 213*d4514f0bSApple OSS Distributions */ 214*d4514f0bSApple OSS Distributions #define CE_SELECT_PATH(...) _MACRO_ITER(CESelectDictValue, __VA_ARGS__) 215*d4514f0bSApple OSS Distributions 216*d4514f0bSApple OSS Distributions // Macro for string equals 217*d4514f0bSApple OSS Distributions #define CE_STRING_EQUALS(str) CEMatchString(str) 218*d4514f0bSApple OSS Distributions 219*d4514f0bSApple OSS Distributions /* 220*d4514f0bSApple OSS Distributions A macro that checks if the passed in context grants (via an explicit true boolean) the entitlement at the passed in path. 221*d4514f0bSApple OSS Distributions */ 222*d4514f0bSApple OSS Distributions #define CE_CONTEXT_GRANTS_ENTITLEMENT(ctx, ...) (CEContextQuery(ctx, (CEQuery_t){CE_SELECT_PATH(__VA_ARGS__) CEMatchBool(true)}, sizeof((CEQuery_t){CE_SELECT_PATH(__VA_ARGS__) CEMatchBool(true)}) / sizeof(CEQueryOperation_t)) == kCENoError) 223*d4514f0bSApple OSS Distributions 224*d4514f0bSApple OSS Distributions #endif 225