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