From 8daa83a594a2e98f39d764422bfbdbc62c9efd44 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 19:20:00 +0200 Subject: Adding upstream version 2:4.20.0+dfsg. Signed-off-by: Daniel Baumann --- librpc/idl/conditional_ace.idl | 458 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 458 insertions(+) create mode 100644 librpc/idl/conditional_ace.idl (limited to 'librpc/idl/conditional_ace.idl') diff --git a/librpc/idl/conditional_ace.idl b/librpc/idl/conditional_ace.idl new file mode 100644 index 0000000..8db0ed6 --- /dev/null +++ b/librpc/idl/conditional_ace.idl @@ -0,0 +1,458 @@ +#include "idl_types.h" + +/* + IDL structures and constants for conditional aces. +*/ + +import "security.idl"; + +interface conditional_ace +{ + /* + * Conditional ACEs have an expression at the end of the ACE. + * We know it is there because the ACE type has CALLBACK in + * its name, and we know how long it is because the size field + * in the ACE points somewhere beyond the otherwise accounted + * for objects: + * + * | type | flags | size | access_mask | trustee | | + * `---------------------------------->| + * + * If the first 4 bytes of the extra bit (called "coda" in our + * structs) are {'a', 'r', 't', 'x'}, the callback ACE is a + * conditional ACE. On Windows it is possible to register + * other kinds of callback ACEs with different magic strings + * that get handled by callback functions. There is little + * evidence of this ever happening, but that explains the + * name. + * + * After the "artx", a conditional ACE consists of a series of + * tokens that describe an expression tree in reverse Polish + * order. The expression can work with claim and SID values + * from the security token, comparing them to each other and + * to literal values. [MS-DTYP] is reasonably clear about how + * they work. + */ + + /* + * Token types from [MS-DTYP] 2.4.4.17 "Conditional ACEs". + */ + typedef [enum8bit] enum { + /* + * Microsoft counts padding zeroes as a kind of token. + * There should be up to three of these at the end, to + * round out the size to a multiple of four. + */ + CONDITIONAL_ACE_TOKEN_INVALID_OR_PADDING = 0x00, + + /* Literal tokens + * ============== + * + * Literal integers. These are *all* stored using 10 + * bytes: + * + * - 8 bytes for the value, limited to the correct range + * (e.g. -128 to 127 for INT8) + * - 1 byte for sign, probably just used for display + * - 1 byte for base, just used for display + * + * SDDL integers are all stored using 64 bits, but + * different token types can be used to pretend they + * have smaller width. In comparisons (which is all + * they can be used for) the type does not matter. The + * only special thing a non-64 bit literal can do is + * to cause a parsing error by being out of range (it + * is an open question as to how you would end up with + * short integers, let alone invalid ones, as the SDDL + * syntax does not have a way of specifying them). + */ + CONDITIONAL_ACE_TOKEN_INT8 = 0x01, + CONDITIONAL_ACE_TOKEN_INT16 = 0x02, + CONDITIONAL_ACE_TOKEN_INT32 = 0x03, + CONDITIONAL_ACE_TOKEN_INT64 = 0x04, + + /* + * Literal strings and structured types. + * + * These have an unsigned 32 bit byte length, followed + * by data. + * + * for unicode the data is UTF-16. + * octet strings are bytes. + * the composite type is a list type. + * the sid type has an ordinary binary sid after the length. + */ + CONDITIONAL_ACE_TOKEN_UNICODE = 0x10, + CONDITIONAL_ACE_TOKEN_OCTET_STRING = 0x18, + CONDITIONAL_ACE_TOKEN_COMPOSITE = 0x50, + CONDITIONAL_ACE_TOKEN_SID = 0x51, + + CONDITIONAL_ACE_LOCAL_ATTRIBUTE = 0xf8, + CONDITIONAL_ACE_USER_ATTRIBUTE = 0xf9, + CONDITIONAL_ACE_RESOURCE_ATTRIBUTE = 0xfa, + CONDITIONAL_ACE_DEVICE_ATTRIBUTE = 0xfb, + + /* + * Unary relational operator tokens + * ================================ + * + * For the membership ops, the operand can be a single + * SID or a composite list of SIDs. + * + * Member_Of: true if the security token user SIDs + * array contains all of the SIDs in the operand. + */ + CONDITIONAL_ACE_TOKEN_MEMBER_OF = 0x89, + /* + * Device_Member_Of: true if the security token device + * SIDs array contains all of the SIDs in the operand. + */ + CONDITIONAL_ACE_TOKEN_DEVICE_MEMBER_OF = 0x8a, + /* + * Member_Of_Any: true if the user SIDs array contains any of + * the SIDs in the operand. + */ + CONDITIONAL_ACE_TOKEN_MEMBER_OF_ANY = 0x8b, + /* + * Device_Member_Of_Any: true if the device SIDs array + * contains any of the SIDs in the operand. + */ + CONDITIONAL_ACE_TOKEN_DEVICE_MEMBER_OF_ANY = 0x8c, + + /* + * Logical inverses of the member-of crew. + */ + CONDITIONAL_ACE_TOKEN_NOT_MEMBER_OF = 0x90, + CONDITIONAL_ACE_TOKEN_NOT_DEVICE_MEMBER_OF = 0x91, + CONDITIONAL_ACE_TOKEN_NOT_MEMBER_OF_ANY = 0x92, + CONDITIONAL_ACE_TOKEN_NOT_DEVICE_MEMBER_OF_ANY = 0x93, + + /* + * Binary relational operators + * =========================== + * + * The left hand side argument (LHS) is an attribute. + * The RHS is an attribute or a value or composite + * list of values (depending on the operation). + * + * If the types mismatch, the result is UNKNOWN. + */ + CONDITIONAL_ACE_TOKEN_EQUAL = 0x80, /* == */ + CONDITIONAL_ACE_TOKEN_NOT_EQUAL = 0x81, /* != */ + CONDITIONAL_ACE_TOKEN_LESS_THAN = 0x82, /* < */ + CONDITIONAL_ACE_TOKEN_LESS_OR_EQUAL = 0x83, /* <= */ + CONDITIONAL_ACE_TOKEN_GREATER_THAN = 0x84, /* > */ + CONDITIONAL_ACE_TOKEN_GREATER_OR_EQUAL = 0x85, /* >= */ + + /* + * "contains" implies "all of", in contrast to the "any of" + * operators. + */ + CONDITIONAL_ACE_TOKEN_CONTAINS = 0x86, + CONDITIONAL_ACE_TOKEN_ANY_OF = 0x88, + CONDITIONAL_ACE_TOKEN_NOT_CONTAINS = 0x8e, + CONDITIONAL_ACE_TOKEN_NOT_ANY_OF = 0x8f, + + /* + * Unary logical operators + * ======================= + * + * The operand for the existence operators must be a + * local attribute or a resource attribute. + */ + CONDITIONAL_ACE_TOKEN_EXISTS = 0x87, /* Exists */ + CONDITIONAL_ACE_TOKEN_NOT_EXISTS = 0x8d, /* Not_Exists */ + /* NOT operator */ + CONDITIONAL_ACE_TOKEN_NOT = 0xa2, /* ! */ + + /* + * Binary logical operators + * ======================== + */ + CONDITIONAL_ACE_TOKEN_AND = 0xa0, /* && */ + CONDITIONAL_ACE_TOKEN_OR = 0xa1, /* || */ + + /* + * Samba specific pseudo-tokens + * ============================ + * + * In running the conditional ace we maintain a stack + * that is used as operands to the operators. Some of + * the values on the stack are literals found inline + * in the data, some are primitives resulting from + * attribute look-up operations, and some are logical + * results from comparison operations, which are in + * the ternary form just mentioned. [MS-DTYP] + * describes no token form for these ternary values, + * as they are not used on the wire (that is, you + * can't have a literal 'true' in a conditional ace). + * So we add a token representation for Boolean result + * types to use on the stack, using an available + * opcode. The result of a lookup can also be 'NULL', + * or an error, and we have opcodes for those too. + * + * These token types raise an error if they show up in + * a conditional ACE, just like any other unknown + * token type. They are for internal use only. + * + * In [MS-DTYP] these are called "Result Value". + */ + + CONDITIONAL_ACE_SAMBA_RESULT_BOOL = 0x0f, + CONDITIONAL_ACE_SAMBA_RESULT_NULL = 0x0e, + CONDITIONAL_ACE_SAMBA_RESULT_ERROR = 0x0d, + + /* + * Samba specific parentheses pseudo-tokens + * ======================================== + * + * These are useful for compiling SDDL, but will never show + * up in the compiled ACE or during evaluation. + */ + CONDITIONAL_ACE_SAMBA_SDDL_PAREN = 0x09, + CONDITIONAL_ACE_SAMBA_SDDL_PAREN_END = 0x08 + } token_type; + + /* + * Integer attributes. + * ================== + * + * Integers are stored with a base indicator and a sign + * indicator. + * + * Integer base is stored for display purposes. For example, + * the number 17 will be shown as "021" with option 1, "17" + * with 2, and "0x11" with 3. Comparisons are not affected. + */ + typedef [enum8bit] enum { + CONDITIONAL_ACE_INT_BASE_8 = 0x01, + CONDITIONAL_ACE_INT_BASE_10 = 0x02, + CONDITIONAL_ACE_INT_BASE_16 = 0x03 + } int_base; + + /* + * Integer sign, mostly for display purposes[1]. It seems + * negative numbers should be flagged here as negative (i.e. + * with 2), while positive numbers should be flagged with + * "none" (3), unless you want them to show up with a plus + * sign in SDDL. + * + * [1] it is possible this has some real significance, perhaps + * acting as an unsigned flag. TO BE DETERMINED. + */ + typedef [enum8bit] enum { + CONDITIONAL_ACE_INT_SIGN_POSITIVE = 0x01, + CONDITIONAL_ACE_INT_SIGN_NEGATIVE = 0x02, + CONDITIONAL_ACE_INT_SIGN_NONE = 0x03 + } int_sign; + + /* + * Ternary logical values + * + * Conditional ACEs use a ternary logic where values can be + * unknown as well as true or false. + * + * The "Bool" result token can take any of these three values. + * There is no literal Boolean value, but an integer of value + * 0 or 1 can be compared with a Boolean result. + */ + typedef enum { + ACE_CONDITION_FALSE = 0, + ACE_CONDITION_TRUE = 1, + ACE_CONDITION_UNKNOWN = -1 + } ternary_logic_value; + /* + * Sub-structures for struct ace_condition_token -> data, + * which vary according to the token->type. + */ + typedef [flag(NDR_NOALIGN)] struct { + int64 value; + } ace_condition_result; + + typedef [public] struct { + int64 value; + uint8 sign; + uint8 base; + } ace_condition_int; + + typedef [public] struct { + /* + * Zeroes are not allowed in the binary format (which + * is otherwise UTF-16), and if we did let them + * through we would end up with a truncated string. + */ + [flag(STR_SIZE4|STR_NOTERM|STR_BYTESIZE|STR_NO_EMBEDDED_NUL)] string value; + } ace_condition_unicode; + + typedef [public] struct { + [subcontext(4)] dom_sid sid; + } ace_condition_sid; + + /* + * The composite type has an array of sub-tokens, which can + * themselves be composites containing composites, though this + * is unlikely to be useful when dealing with claims. + * + * This structure is not representative of the wire format. + */ + typedef struct { + ace_condition_token *tokens; + uint32 n_members; + } ace_condition_composite; + + /* + * Operators have no data, but it is sometimes helpful for + * SDDL compilation messages to record the position in the + * string. + */ + typedef struct { + uint32 sddl_position; + } ace_condition_op; + + /* + * struct ace_condition_sddl_op is not as real token, but is + * used in compiling sddl. The idea is, for example, that if + * popping with a ')' doesn't match the right '(', the details + * of the '(' are there for the error message. + */ + typedef struct { + uint32 start; + uint32 position; + } ace_condition_sddl_op; + + + typedef [nodiscriminant] union { + [case(CONDITIONAL_ACE_TOKEN_SID)] ace_condition_sid sid; + [case(CONDITIONAL_ACE_TOKEN_COMPOSITE)]ace_condition_composite composite; + [case(CONDITIONAL_ACE_TOKEN_OCTET_STRING)] DATA_BLOB bytes; + [case(CONDITIONAL_ACE_TOKEN_UNICODE)]ace_condition_unicode unicode; + + [case(CONDITIONAL_ACE_LOCAL_ATTRIBUTE)]ace_condition_unicode local_attr; + [case(CONDITIONAL_ACE_USER_ATTRIBUTE)]ace_condition_unicode user_attr; + [case(CONDITIONAL_ACE_DEVICE_ATTRIBUTE)]ace_condition_unicode device_attr; + [case(CONDITIONAL_ACE_RESOURCE_ATTRIBUTE)]ace_condition_unicode resource_attr; + + [case(CONDITIONAL_ACE_TOKEN_INT64)]ace_condition_int int64; + [case(CONDITIONAL_ACE_TOKEN_INT32)]ace_condition_int int32; + [case(CONDITIONAL_ACE_TOKEN_INT16)]ace_condition_int int16; + [case(CONDITIONAL_ACE_TOKEN_INT8)]ace_condition_int int8; + [case(CONDITIONAL_ACE_SAMBA_SDDL_PAREN)]ace_condition_sddl_op sddl_op; + + [case(CONDITIONAL_ACE_SAMBA_RESULT_BOOL)]ace_condition_result result; + /* NULL and Error results are empty */ + [case(CONDITIONAL_ACE_SAMBA_RESULT_NULL)]ace_condition_result result_null; + [case(CONDITIONAL_ACE_SAMBA_RESULT_ERROR)]ace_condition_result result_error; + + /* operations */ + [case(CONDITIONAL_ACE_TOKEN_MEMBER_OF)]ace_condition_op member_of; + [case(CONDITIONAL_ACE_TOKEN_DEVICE_MEMBER_OF)]ace_condition_op device_member_of; + [case(CONDITIONAL_ACE_TOKEN_MEMBER_OF_ANY)]ace_condition_op member_of_any; + [case(CONDITIONAL_ACE_TOKEN_DEVICE_MEMBER_OF_ANY)]ace_condition_op device_member_of_any; + [case(CONDITIONAL_ACE_TOKEN_NOT_MEMBER_OF)]ace_condition_op not_member_of; + [case(CONDITIONAL_ACE_TOKEN_NOT_DEVICE_MEMBER_OF)]ace_condition_op not_device_member_of; + [case(CONDITIONAL_ACE_TOKEN_NOT_MEMBER_OF_ANY)]ace_condition_op not_member_of_any; + [case(CONDITIONAL_ACE_TOKEN_NOT_DEVICE_MEMBER_OF_ANY)]ace_condition_op not_device_member_of_any; + [case(CONDITIONAL_ACE_TOKEN_EQUAL)]ace_condition_op equal; + [case(CONDITIONAL_ACE_TOKEN_NOT_EQUAL)]ace_condition_op not_equal; + [case(CONDITIONAL_ACE_TOKEN_LESS_THAN)]ace_condition_op less_than; + [case(CONDITIONAL_ACE_TOKEN_LESS_OR_EQUAL)]ace_condition_op less_or_equal; + [case(CONDITIONAL_ACE_TOKEN_GREATER_THAN)]ace_condition_op greater_than; + [case(CONDITIONAL_ACE_TOKEN_GREATER_OR_EQUAL)]ace_condition_op greater_or_equal; + [case(CONDITIONAL_ACE_TOKEN_CONTAINS)]ace_condition_op contains; + [case(CONDITIONAL_ACE_TOKEN_ANY_OF)]ace_condition_op any_of; + [case(CONDITIONAL_ACE_TOKEN_NOT_CONTAINS)]ace_condition_op not_contains; + [case(CONDITIONAL_ACE_TOKEN_NOT_ANY_OF)]ace_condition_op not_any_of; + [case(CONDITIONAL_ACE_TOKEN_AND)]ace_condition_op and; + [case(CONDITIONAL_ACE_TOKEN_OR)]ace_condition_op or; + [case(CONDITIONAL_ACE_TOKEN_NOT)]ace_condition_op not; + [case(CONDITIONAL_ACE_TOKEN_EXISTS)]ace_condition_op exists; + [case(CONDITIONAL_ACE_TOKEN_NOT_EXISTS)]ace_condition_op not_exists; + + [default] ace_condition_op op; + } ace_condition_token_data; + + /* + * struct ace_condition_token is the fundamental building + * block of a conditional ACE expression. + */ + typedef [public] struct { + [switch_is(type)] ace_condition_token_data data; + uint32 flags; + token_type type; + } ace_condition_token; + + /* + * The expression as a whole is an just an array of tokens. + * + * But because we are always going to need a stack for + * evaluating the expression, we allocate that and keep it + * handy. + */ + typedef [public] struct { + ace_condition_token *tokens; + ace_condition_token *stack; + uint32 length; + } ace_condition_script; + + typedef enum { + ACE_CONDITION_FLAG_ALLOW_DEVICE = 0x01 + } ace_condition_flags; + + /* + * Flags for ace_condition_token.flags field. + * + * The following flags from security claims are used: + * + * CLAIM_SECURITY_ATTRIBUTE_NON_INHERITABLE = 1 + * CLAIM_SECURITY_ATTRIBUTE_VALUE_CASE_SENSITIVE = 2 + * + * CLAIM_SECURITY_ATTRIBUTE_UNIQUE_AND_SORTED = 1 << 30 + * + * The first two of these are used on the wire in + * CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1 structures, while the + * latter is in an application specific range that is not + * seen on the wire. It is used to indicate that a composite + * token contains no duplicate values, which is supposed to + * be true for composite values from claims (including from + * resource attribute ACEs), but not literal composites. It's + * expensive to check, so this flag helps us avoid extra work + * can avoid doing it over and over if we remember. + * + * + * CONDITIONAL_ACE_FLAG_TOKEN_FROM_ATTR is set when a token + * value on the stack is set from an attribute lookup. + * + * This is necessary because for binary relational operators + * (MS-DTYP 2.4.4.17.6), the left-hand argument must be an + * attribute lookup, but by the time we have come to the + * operator that argument has been resolved into an ordinary + * token. So we set the flag so the operator can know. + */ + const uint32 CONDITIONAL_ACE_FLAG_TOKEN_FROM_ATTR = UINT32_C(1) << 31; + + /* + * The maximum size of the conditional ACE conditions in the + * binary form. There is an absolute limit of slightly less + * than 64k, as the security descriptor, the ACL, and the ace + * all have 16 bit length fields, and each adds some overhead. + * + * In practice, a couple of hundred bytes would do, and people + * making extremely large conditional expressions probably + * don't have good intentions. + */ + const int CONDITIONAL_ACE_MAX_LENGTH = 10000; + /* + * CONDITIONAL_ACE_MAX_TOKENS is another arbitrarily chosen + * number used to allocate token arrays and stacks. + * + * The relationship between the number of tokens and the byte + * length is variable, depending on the nature of the + * conditions. An operator token takes up one byte in the + * binary format (which CONDITIONAL_ACE_MAX_LENGTH above + * measures), an integer 10 bytes, and attributes and strings + * at least two bytes per character plus four for the length. + * SIDs are stored as struct dom_sid, around sixty-eight + * bytes, plus a four byte length field. + */ + const int CONDITIONAL_ACE_MAX_TOKENS = 2000; +} -- cgit v1.2.3