2 * Unix SMB implementation.
3 * Functions for understanding conditional ACEs
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 #include "librpc/gen_ndr/ndr_security.h"
21 #include "librpc/gen_ndr/conditional_ace.h"
22 #include "libcli/security/security.h"
23 #include "libcli/security/conditional_ace.h"
24 #include "libcli/security/claims-conversions.h"
25 #include "lib/util/tsort.h"
26 #include "lib/util/debug.h"
27 #include "lib/util/bytearray.h"
28 #include "util/discard.h"
31 * Conditional ACE logic truth tables.
33 * Conditional ACES use a ternary logic, with "unknown" as well as true and
34 * false. The ultmate meaning of unknown depends on the context; in a deny
35 * ace, unknown means yes, in an allow ace, unknown means no. That is, we
36 * treat unknown results with maximum suspicion.
38 * AND true false unknown
43 * OR true false unknown
53 * This can be summed up by saying unknown values taint the result except in
54 * the cases where short circuit evaluation could apply (true OR anything,
55 * false AND anything, which hold their value).
57 * What counts as unknown
60 * - certain comparisons between incompatible types
62 * What counts as false
67 * An error means the entire expression is unknown.
71 static bool check_integer_range(const struct ace_condition_token
*tok
)
73 int64_t val
= tok
->data
.int64
.value
;
75 case CONDITIONAL_ACE_TOKEN_INT8
:
76 if (val
< -128 || val
> 127) {
80 case CONDITIONAL_ACE_TOKEN_INT16
:
81 if (val
< INT16_MIN
|| val
> INT16_MAX
) {
85 case CONDITIONAL_ACE_TOKEN_INT32
:
86 if (val
< INT32_MIN
|| val
> INT32_MAX
) {
90 case CONDITIONAL_ACE_TOKEN_INT64
:
91 /* val has these limits naturally */
97 if (tok
->data
.int64
.base
!= CONDITIONAL_ACE_INT_BASE_8
&&
98 tok
->data
.int64
.base
!= CONDITIONAL_ACE_INT_BASE_10
&&
99 tok
->data
.int64
.base
!= CONDITIONAL_ACE_INT_BASE_16
) {
102 if (tok
->data
.int64
.sign
!= CONDITIONAL_ACE_INT_SIGN_POSITIVE
&&
103 tok
->data
.int64
.sign
!= CONDITIONAL_ACE_INT_SIGN_NEGATIVE
&&
104 tok
->data
.int64
.sign
!= CONDITIONAL_ACE_INT_SIGN_NONE
) {
111 static ssize_t
pull_integer(uint8_t *data
, size_t length
,
112 struct ace_condition_int
*tok
)
117 tok
->value
= PULL_LE_I64(data
, 0);
123 static ssize_t
push_integer(uint8_t *data
, size_t length
,
124 const struct ace_condition_int
*tok
)
129 PUSH_LE_I64(data
, 0, tok
->value
);
136 static ssize_t
pull_unicode(TALLOC_CTX
*mem_ctx
, uint8_t *data
, size_t length
,
137 struct ace_condition_unicode
*tok
)
140 uint8_t *utf16
= NULL
;
148 utf16_len
= PULL_LE_U32(data
, 0);
149 if (utf16_len
> length
- 4) {
153 /* we need an even number of bytes */
158 * The string in the ACE blob is utf-16, which we convert to
159 * utf-8 for further processing.
161 * There may be inefficencies here (FIXME, etc, if you dare),
162 * and we might prefer to keep it as utf-16 in the runtime.
165 for (i
= 0; i
< utf16_len
; i
+= 2) {
167 * A 0x0000 codepoint is illegal. The string is length-bound,
168 * not NUL-terminated. If we don't do this the string will be
169 * truncated at the first 0x0000, which is not terrible, but
170 * not expected, and it makes round-trip assertions
173 if (utf16
[i
] == 0 && utf16
[i
+ 1] == 0) {
178 ok
= convert_string_talloc(mem_ctx
,
185 if (utf16_len
== 0) {
187 * This is a special case, because convert_string_talloc()
188 * will turn a length 0 string into a length 1 string
189 * containing a zero byte. This is not the same as returning
190 * the truly allocated size, counting the '\0' for all strings
191 * -- it only happens for the empty string.
196 tok
->length
= utf8_len
;
197 return utf16_len
+ 4;
200 static ssize_t
push_unicode(uint8_t *data
, size_t length
,
201 const struct ace_condition_unicode
*tok
)
204 * The string stored in the token is utf-8, but must be
205 * converted to utf-16 in the compiled ACE.
208 size_t bytes_written
;
209 uint8_t *length_goes_here
= data
;
217 //XXX do we allow an empty string?
218 ok
= convert_string_error(CH_UTF8
, CH_UTF16LE
,
219 tok
->value
, tok
->length
,
222 if (! ok
|| bytes_written
> length
) {
225 PUSH_LE_U32(length_goes_here
, 0, bytes_written
);
226 return bytes_written
+ 4;
230 static ssize_t
pull_bytes(TALLOC_CTX
*mem_ctx
,
231 uint8_t *data
, size_t length
,
232 struct ace_condition_bytes
*tok
)
237 tok
->length
= PULL_LE_U32(data
, 0);
238 if (tok
->length
> length
- 4) {
241 tok
->bytes
= talloc_size(mem_ctx
, tok
->length
+ 1);
242 if (tok
->bytes
== NULL
) {
245 memcpy(tok
->bytes
, data
+ 4, tok
->length
);
246 tok
->bytes
[tok
->length
] = 0;
247 return tok
->length
+ 4;
251 static ssize_t
push_bytes(uint8_t *data
, size_t length
,
252 const struct ace_condition_bytes
*tok
)
254 if (length
< tok
->length
+ 4) {
257 PUSH_LE_U32(data
, 0, tok
->length
);
258 memcpy(data
+ 4, tok
->bytes
, tok
->length
);
259 return tok
->length
+ 4;
263 static ssize_t
pull_sid(TALLOC_CTX
*mem_ctx
,
264 uint8_t *data
, size_t length
,
265 struct ace_condition_sid
*tok
)
272 tok_length
= PULL_LE_U32(data
, 0);
273 if (tok_length
> length
- 4) {
276 tok
->sid
= talloc(mem_ctx
, struct dom_sid
);
277 if (tok
->sid
== NULL
) {
280 sidlen
= sid_parse(data
+ 4, tok_length
, tok
->sid
);
282 talloc_free(tok
->sid
);
285 return tok_length
+ 4;
288 static ssize_t
push_sid(uint8_t *data
, size_t available
,
289 const struct ace_condition_sid
*tok
)
291 enum ndr_err_code ndr_err
;
293 ssize_t total_length
;
294 ndr_err
= ndr_push_struct_blob(&v
, NULL
,
296 (ndr_push_flags_fn_t
)ndr_push_dom_sid
);
297 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
300 total_length
= v
.length
+ 4;
301 if (available
< total_length
) {
305 PUSH_LE_U32(data
, 0, v
.length
);
306 memcpy(data
+ 4, v
.data
, v
.length
);
312 static ssize_t
pull_composite(TALLOC_CTX
*mem_ctx
,
313 uint8_t *data
, size_t length
,
314 struct ace_condition_composite
*tok
)
319 struct ace_condition_token
*tokens
= NULL
;
323 byte_size
= PULL_LE_U32(data
, 0);
324 if (byte_size
> length
- 4) {
328 * There is a list of other literal tokens (possibly including nested
329 * composites), which we will store in an array.
331 * This array can *only* be literals.
333 alloc_length
= byte_size
;
334 tokens
= talloc_array(mem_ctx
,
335 struct ace_condition_token
,
337 if (tokens
== NULL
) {
343 while (i
< byte_size
) {
344 struct ace_condition_token
*el
= &tokens
[j
];
346 uint8_t *el_data
= NULL
;
353 available
= byte_size
- i
;
356 case CONDITIONAL_ACE_TOKEN_INT8
:
357 case CONDITIONAL_ACE_TOKEN_INT16
:
358 case CONDITIONAL_ACE_TOKEN_INT32
:
359 case CONDITIONAL_ACE_TOKEN_INT64
:
360 consumed
= pull_integer(el_data
,
363 ok
= check_integer_range(el
);
368 case CONDITIONAL_ACE_TOKEN_UNICODE
:
369 consumed
= pull_unicode(mem_ctx
,
375 case CONDITIONAL_ACE_TOKEN_OCTET_STRING
:
376 consumed
= pull_bytes(mem_ctx
,
382 case CONDITIONAL_ACE_TOKEN_SID
:
383 consumed
= pull_sid(mem_ctx
,
389 case CONDITIONAL_ACE_TOKEN_COMPOSITE
:
390 consumed
= pull_composite(mem_ctx
,
393 &el
->data
.composite
);
399 if (consumed
< 0 || consumed
+ i
> length
) {
404 if (j
== UINT16_MAX
) {
408 if (j
== alloc_length
) {
410 tokens
= talloc_realloc(mem_ctx
,
412 struct ace_condition_token
,
415 if (tokens
== NULL
) {
421 tok
->tokens
= tokens
;
429 static ssize_t
push_composite(uint8_t *data
, size_t length
,
430 const struct ace_condition_composite
*tok
)
433 uint8_t *byte_length_ptr
;
439 * We have no idea what the eventual length will be, so we keep a
440 * pointer to write it in at the end.
442 byte_length_ptr
= data
;
443 PUSH_LE_U32(data
, 0, 0);
446 for (i
= 0; i
< tok
->n_members
&& used
< length
; i
++) {
447 struct ace_condition_token
*el
= &tok
->tokens
[i
];
449 uint8_t *el_data
= NULL
;
452 data
[used
] = el
->type
;
454 if (used
== length
) {
456 * used == length is not expected here; the token
457 * types that only have an opcode and no data are not
458 * literals that can be in composites.
462 el_data
= data
+ used
;
463 available
= length
- used
;
466 case CONDITIONAL_ACE_TOKEN_INT8
:
467 case CONDITIONAL_ACE_TOKEN_INT16
:
468 case CONDITIONAL_ACE_TOKEN_INT32
:
469 case CONDITIONAL_ACE_TOKEN_INT64
:
470 ok
= check_integer_range(el
);
474 consumed
= push_integer(el_data
,
478 case CONDITIONAL_ACE_TOKEN_UNICODE
:
479 consumed
= push_unicode(el_data
,
484 case CONDITIONAL_ACE_TOKEN_OCTET_STRING
:
485 consumed
= push_bytes(el_data
,
490 case CONDITIONAL_ACE_TOKEN_SID
:
491 consumed
= push_sid(el_data
,
496 case CONDITIONAL_ACE_TOKEN_COMPOSITE
:
497 consumed
= push_composite(el_data
,
499 &el
->data
.composite
);
515 PUSH_LE_U32(byte_length_ptr
, 0, used
- 4);
519 static ssize_t
pull_end_padding(uint8_t *data
, size_t length
)
522 * We just check that we have the right kind of number of zero
523 * bytes. The blob must end on a multiple of 4. One zero byte
524 * has already been swallowed as tok->type, which sends us
525 * here, so we expect 1 or two more -- total padding is 0, 1,
528 * zero is also called CONDITIONAL_ACE_TOKEN_INVALID_OR_PADDING.
534 for (i
= 0; i
< length
; i
++) {
543 struct ace_condition_script
*parse_conditional_ace(TALLOC_CTX
*mem_ctx
,
547 struct ace_condition_token
*tokens
= NULL
;
549 struct ace_condition_script
*program
= NULL
;
551 if (data
.length
< 4 ||
552 data
.data
[0] != 'a' ||
553 data
.data
[1] != 'r' ||
554 data
.data
[2] != 't' ||
555 data
.data
[3] != 'x') {
557 * lacks the "artx" conditional ace identifier magic.
558 * NULL returns will deny access.
562 if (data
.length
> CONDITIONAL_ACE_MAX_LENGTH
||
563 (data
.length
& 3) != 0) {
565 * >= 64k or non-multiples of 4 are not possible in the ACE
571 program
= talloc(mem_ctx
, struct ace_condition_script
);
572 if (program
== NULL
) {
577 * We will normally end up with fewer than data.length tokens, as
578 * values are stored in multiple bytes (all integers are 10 bytes,
579 * strings and attributes are utf16 + length, SIDs are SID-size +
580 * length, etc). But operators are one byte, so something like
581 * !(!(!(!(!(!(x)))))) -- where each '!(..)' is one byte -- will bring
582 * the number of tokens close to the number of bytes.
584 * This is all to say we're guessing a token length that hopes to
585 * avoid reallocs without wasting too much up front.
587 alloc_length
= data
.length
/ 2 + 1;
588 tokens
= talloc_array(program
,
589 struct ace_condition_token
,
591 if (tokens
== NULL
) {
592 TALLOC_FREE(program
);
598 while(i
< data
.length
) {
599 struct ace_condition_token
*tok
= &tokens
[j
];
600 ssize_t consumed
= 0;
601 uint8_t *tok_data
= NULL
;
604 tok
->type
= data
.data
[i
];
606 tok_data
= data
.data
+ i
;
607 available
= data
.length
- i
;
610 case CONDITIONAL_ACE_TOKEN_INT8
:
611 case CONDITIONAL_ACE_TOKEN_INT16
:
612 case CONDITIONAL_ACE_TOKEN_INT32
:
613 case CONDITIONAL_ACE_TOKEN_INT64
:
614 consumed
= pull_integer(tok_data
,
617 ok
= check_integer_range(tok
);
622 case CONDITIONAL_ACE_TOKEN_UNICODE
:
624 * The next four are pulled as unicode, but are
625 * processed as user attribute look-ups.
627 case CONDITIONAL_ACE_LOCAL_ATTRIBUTE
:
628 case CONDITIONAL_ACE_USER_ATTRIBUTE
:
629 case CONDITIONAL_ACE_RESOURCE_ATTRIBUTE
:
630 case CONDITIONAL_ACE_DEVICE_ATTRIBUTE
:
631 consumed
= pull_unicode(program
,
637 case CONDITIONAL_ACE_TOKEN_OCTET_STRING
:
638 consumed
= pull_bytes(program
,
644 case CONDITIONAL_ACE_TOKEN_SID
:
645 consumed
= pull_sid(program
,
651 case CONDITIONAL_ACE_TOKEN_COMPOSITE
:
652 consumed
= pull_composite(program
,
655 &tok
->data
.composite
);
658 case CONDITIONAL_ACE_TOKEN_MEMBER_OF
:
659 case CONDITIONAL_ACE_TOKEN_DEVICE_MEMBER_OF
:
660 case CONDITIONAL_ACE_TOKEN_MEMBER_OF_ANY
:
661 case CONDITIONAL_ACE_TOKEN_DEVICE_MEMBER_OF_ANY
:
662 case CONDITIONAL_ACE_TOKEN_NOT_MEMBER_OF
:
663 case CONDITIONAL_ACE_TOKEN_NOT_DEVICE_MEMBER_OF
:
664 case CONDITIONAL_ACE_TOKEN_NOT_MEMBER_OF_ANY
:
665 case CONDITIONAL_ACE_TOKEN_NOT_DEVICE_MEMBER_OF_ANY
:
667 * these require a SID or composite SID list operand,
668 * and we could check that now in most cases.
671 /* binary relational operators */
672 case CONDITIONAL_ACE_TOKEN_EQUAL
:
673 case CONDITIONAL_ACE_TOKEN_NOT_EQUAL
:
674 case CONDITIONAL_ACE_TOKEN_LESS_THAN
:
675 case CONDITIONAL_ACE_TOKEN_LESS_OR_EQUAL
:
676 case CONDITIONAL_ACE_TOKEN_GREATER_THAN
:
677 case CONDITIONAL_ACE_TOKEN_GREATER_OR_EQUAL
:
678 case CONDITIONAL_ACE_TOKEN_CONTAINS
:
679 case CONDITIONAL_ACE_TOKEN_ANY_OF
:
680 case CONDITIONAL_ACE_TOKEN_NOT_CONTAINS
:
681 case CONDITIONAL_ACE_TOKEN_NOT_ANY_OF
:
682 /* unary logical operators */
683 case CONDITIONAL_ACE_TOKEN_EXISTS
:
684 case CONDITIONAL_ACE_TOKEN_NOT_EXISTS
:
685 case CONDITIONAL_ACE_TOKEN_NOT
:
686 /* binary logical operators */
687 case CONDITIONAL_ACE_TOKEN_AND
:
688 case CONDITIONAL_ACE_TOKEN_OR
:
690 case CONDITIONAL_ACE_TOKEN_INVALID_OR_PADDING
:
691 /* this is only valid at the end */
692 consumed
= pull_end_padding(tok_data
,
694 j
--; /* don't add this token */
700 if (consumed
+ i
< i
|| consumed
+ i
> data
.length
) {
705 if (j
== alloc_length
) {
707 tokens
= talloc_realloc(program
,
709 struct ace_condition_token
,
711 if (tokens
== NULL
) {
717 program
->tokens
= talloc_realloc(program
,
719 struct ace_condition_token
,
720 program
->length
+ 1);
721 if (program
->tokens
== NULL
) {
725 * When interpreting the program we will need a stack, which in the
726 * very worst case can be as deep as the program is long.
728 program
->stack
= talloc_array(program
,
729 struct ace_condition_token
,
730 program
->length
+ 1);
731 if (program
->stack
== NULL
) {
737 talloc_free(program
);
742 static bool claim_lookup_internal(
744 struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1
*claim
,
745 struct ace_condition_token
*result
)
747 bool ok
= claim_v1_to_ace_token(mem_ctx
, claim
, result
);
752 static bool resource_claim_lookup(
754 const struct ace_condition_token
*op
,
755 const struct security_descriptor
*sd
,
756 struct ace_condition_token
*result
)
759 * For a @Resource.attr, the claims come from a resource ACE
760 * in the object's SACL. That's why we need a security descriptor.
762 * If there is no matching resource ACE, a NULL result is returned,
763 * which should compare UNKNOWN to anything. The NULL will have the
764 * CONDITIONAL_ACE_FLAG_NULL_MEANS_ERROR flag set if it seems failure
765 * is not simply due to the sought claim not existing. This useful for
766 * the Exists and Not_Exists operators.
769 struct ace_condition_unicode name
;
771 result
->type
= CONDITIONAL_ACE_SAMBA_RESULT_NULL
;
773 if (op
->type
!= CONDITIONAL_ACE_RESOURCE_ATTRIBUTE
) {
774 /* what are we even doing here? */
775 result
->type
= CONDITIONAL_ACE_SAMBA_RESULT_ERROR
;
779 name
= op
->data
.resource_attr
;
781 if (sd
->sacl
== NULL
) {
782 DBG_NOTICE("Resource attribute ACE '%*s' not found, "
783 "because there is no SACL\n",
784 name
.length
, name
.value
);
788 for (i
= 0; i
< sd
->sacl
->num_aces
; i
++) {
789 struct security_ace
*ace
= &sd
->sacl
->aces
[i
];
792 if (ace
->type
!= SEC_ACE_TYPE_SYSTEM_RESOURCE_ATTRIBUTE
) {
795 if (strncasecmp_m(name
.value
,
796 ace
->coda
.claim
.name
,
800 /* this is the one */
801 ok
= claim_lookup_internal(mem_ctx
, &ace
->coda
.claim
, result
);
806 DBG_NOTICE("Resource attribute ACE '%*s' not found.\n",
807 name
.length
, name
.value
);
812 static bool token_claim_lookup(
814 const struct security_token
*token
,
815 const struct ace_condition_token
*op
,
816 struct ace_condition_token
*result
)
819 * The operator has an attribute name; if there is a claim of
820 * the right type with that name, that is returned as the result.
822 * XXX what happens otherwise? NULL result?
824 struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1
*claims
= NULL
;
827 const struct ace_condition_unicode
*name
= NULL
;
830 result
->type
= CONDITIONAL_ACE_SAMBA_RESULT_NULL
;
833 case CONDITIONAL_ACE_LOCAL_ATTRIBUTE
:
834 claims
= token
->local_claims
;
835 num_claims
= token
->num_local_claims
;
836 name
= &op
->data
.local_attr
;
838 case CONDITIONAL_ACE_USER_ATTRIBUTE
:
839 claims
= token
->user_claims
;
840 num_claims
= token
->num_user_claims
;
841 name
= &op
->data
.user_attr
;
843 case CONDITIONAL_ACE_DEVICE_ATTRIBUTE
:
844 claims
= token
->device_claims
;
845 num_claims
= token
->num_device_claims
;
846 name
= &op
->data
.device_attr
;
849 DBG_WARNING("Conditional ACE claim lookup got bad arg type %u\n",
851 result
->type
= CONDITIONAL_ACE_SAMBA_RESULT_ERROR
;
856 * Loop backwards: a later claim will override an earlier one with the
859 for (i
= num_claims
- 1; i
< num_claims
; i
--) {
860 if (claims
[i
].name
== NULL
) {
861 DBG_ERR("claim %zu has no name!\n", i
);
864 if (strncasecmp_m(claims
[i
].name
, name
->value
, name
->length
) == 0) {
865 /* this is the one */
866 ok
= claim_lookup_internal(mem_ctx
, &claims
[i
], result
);
870 DBG_NOTICE("Claim not found\n");
877 static bool member_lookup(
878 const struct security_token
*token
,
879 const struct ace_condition_token
*op
,
880 const struct ace_condition_token
*arg
,
881 struct ace_condition_token
*result
)
884 * We need to compare the lists of SIDs in the token with the
885 * SID[s] in the argument. There are 8 combinations of
886 * operation, depending on whether we want to match all or any
887 * of the SIDs, whether we're using the device SIDs or user
888 * SIDs, and whether the operator name starts with "Not_".
890 * _MEMBER_OF User has all operand SIDs
891 * _DEVICE_MEMBER_OF Device has all operand SIDs
892 * _MEMBER_OF_ANY User has one or more operand SIDs
893 * _DEVICE_MEMBER_OF_ANY Device has one or more operand SIDs
895 * NOT_* has the effect of !(the operator without NOT_).
897 * The operand can either be a composite of SIDs or a single SID.
898 * This adds an additional branch.
902 bool it_is_an_any_op
;
903 bool it_is_a_device_op
;
904 bool arg_is_a_single_sid
;
905 struct dom_sid
*sid_array
= NULL
;
906 size_t num_sids
, i
, j
;
907 struct dom_sid
*sid
= NULL
;
909 result
->type
= CONDITIONAL_ACE_SAMBA_RESULT_BOOL
;
910 result
->data
.result
.value
= ACE_CONDITION_UNKNOWN
;
913 case CONDITIONAL_ACE_TOKEN_SID
:
914 arg_is_a_single_sid
= true;
916 case CONDITIONAL_ACE_TOKEN_COMPOSITE
:
917 arg_is_a_single_sid
= false;
920 DBG_WARNING("Conditional ACE Member_Of got bad arg type %u\n",
926 case CONDITIONAL_ACE_TOKEN_NOT_MEMBER_OF
:
927 case CONDITIONAL_ACE_TOKEN_NOT_MEMBER_OF_ANY
:
928 it_is_a_not_op
= true;
929 it_is_a_device_op
= false;
931 case CONDITIONAL_ACE_TOKEN_NOT_DEVICE_MEMBER_OF_ANY
:
932 case CONDITIONAL_ACE_TOKEN_NOT_DEVICE_MEMBER_OF
:
933 it_is_a_not_op
= true;
934 it_is_a_device_op
= true;
936 case CONDITIONAL_ACE_TOKEN_MEMBER_OF
:
937 case CONDITIONAL_ACE_TOKEN_MEMBER_OF_ANY
:
938 it_is_a_not_op
= false;
939 it_is_a_device_op
= false;
941 case CONDITIONAL_ACE_TOKEN_DEVICE_MEMBER_OF_ANY
:
942 case CONDITIONAL_ACE_TOKEN_DEVICE_MEMBER_OF
:
943 it_is_a_not_op
= false;
944 it_is_a_device_op
= true;
947 DBG_WARNING("Conditional ACE Member_Of got bad op type %u\n",
953 case CONDITIONAL_ACE_TOKEN_NOT_MEMBER_OF_ANY
:
954 case CONDITIONAL_ACE_TOKEN_NOT_DEVICE_MEMBER_OF_ANY
:
955 case CONDITIONAL_ACE_TOKEN_MEMBER_OF_ANY
:
956 case CONDITIONAL_ACE_TOKEN_DEVICE_MEMBER_OF_ANY
:
957 it_is_an_any_op
= true;
960 it_is_an_any_op
= false;
963 if (it_is_a_device_op
) {
964 sid_array
= token
->device_sids
;
965 num_sids
= token
->num_device_sids
;
967 sid_array
= token
->sids
;
968 num_sids
= token
->num_sids
;
971 if (arg_is_a_single_sid
) {
973 * In this case the any and all operations are the
976 sid
= arg
->data
.sid
.sid
;
978 for (i
= 0; i
< num_sids
; i
++) {
979 match
= dom_sid_equal(sid
, &sid_array
[i
]);
984 if (it_is_a_not_op
) {
988 result
->data
.result
.value
= ACE_CONDITION_TRUE
;
990 result
->data
.result
.value
= ACE_CONDITION_FALSE
;
995 /* This is a composite list (hopefully of SIDs) */
996 if (arg
->data
.composite
.n_members
== 0) {
997 DBG_WARNING("Conditional ACE Member_Of argument is empty\n");
1001 for (j
= 0; j
< arg
->data
.composite
.n_members
; j
++) {
1002 const struct ace_condition_token
*member
=
1003 &arg
->data
.composite
.tokens
[j
];
1004 if (member
->type
!= CONDITIONAL_ACE_TOKEN_SID
) {
1005 DBG_WARNING("Conditional ACE Member_Of argument contains "
1006 "non-sid element [%zu]: %u\n",
1010 sid
= member
->data
.sid
.sid
;
1012 for (i
= 0; i
< num_sids
; i
++) {
1013 match
= dom_sid_equal(sid
, &sid_array
[i
]);
1018 if (it_is_an_any_op
) {
1020 /* we have matched one SID, which is enough */
1023 } else { /* an all op */
1025 /* failing one is enough */
1031 * Reaching the end of that loop means either:
1032 * 1. it was an ALL op and we never failed to find one, or
1033 * 2. it was an ANY op, and we didn't find one.
1035 match
= !it_is_an_any_op
;
1038 if (it_is_a_not_op
) {
1042 result
->data
.result
.value
= ACE_CONDITION_TRUE
;
1044 result
->data
.result
.value
= ACE_CONDITION_FALSE
;
1051 static bool ternary_value(
1052 const struct ace_condition_token
*arg
,
1053 struct ace_condition_token
*result
)
1056 * Find the truth value of the argument, stored in the result token.
1058 * A return value of false means the operation is invalid, and the
1059 * result is undefined.
1061 if (arg
->type
== CONDITIONAL_ACE_SAMBA_RESULT_BOOL
) {
1067 result
->type
= CONDITIONAL_ACE_SAMBA_RESULT_BOOL
;
1068 result
->data
.result
.value
= ACE_CONDITION_UNKNOWN
;
1070 if (IS_INT_TOKEN(arg
)) {
1072 if (arg
->data
.int64
.value
== 0) {
1073 result
->data
.result
.value
= ACE_CONDITION_FALSE
;
1075 result
->data
.result
.value
= ACE_CONDITION_TRUE
;
1079 if (arg
->type
== CONDITIONAL_ACE_TOKEN_UNICODE
) {
1080 /* empty is false */
1081 if (arg
->data
.unicode
.length
== 0) {
1082 result
->data
.result
.value
= ACE_CONDITION_FALSE
;
1084 result
->data
.result
.value
= ACE_CONDITION_TRUE
;
1090 * everything else in UNKNOWN. This includes NULL values (i.e. an
1091 * unsuccessful look-up).
1093 result
->data
.result
.value
= ACE_CONDITION_UNKNOWN
;
1097 static bool not_operator(
1098 const struct ace_condition_token
*arg
,
1099 struct ace_condition_token
*result
)
1102 if (IS_LITERAL_TOKEN(arg
)) {
1104 * Logic operators don't work on literals.
1109 ok
= ternary_value(arg
, result
);
1113 if (result
->data
.result
.value
== ACE_CONDITION_FALSE
) {
1114 result
->data
.result
.value
= ACE_CONDITION_TRUE
;
1115 } else if (result
->data
.result
.value
== ACE_CONDITION_TRUE
) {
1116 result
->data
.result
.value
= ACE_CONDITION_FALSE
;
1118 /* unknown stays unknown */
1123 static bool unary_logic_operator(
1124 TALLOC_CTX
*mem_ctx
,
1125 const struct security_token
*token
,
1126 const struct ace_condition_token
*op
,
1127 const struct ace_condition_token
*arg
,
1128 const struct security_descriptor
*sd
,
1129 struct ace_condition_token
*result
)
1134 struct ace_condition_token claim
= {
1135 .type
= CONDITIONAL_ACE_SAMBA_RESULT_ERROR
1137 if (op
->type
== CONDITIONAL_ACE_TOKEN_NOT
) {
1138 return not_operator(arg
, result
);
1140 result
->type
= CONDITIONAL_ACE_SAMBA_RESULT_BOOL
;
1141 result
->data
.result
.value
= ACE_CONDITION_UNKNOWN
;
1144 * Not_Exists and Exists require the same work, except we negate the
1145 * answer in one case. From [MS-DTYP] 2.4.4.17.7:
1147 * If the type of the operand is "Local Attribute"
1148 * If the value is non-null return TRUE
1150 * Else if the type of the operand is "Resource Attribute"
1151 * Return TRUE if value is non-null; FALSE otherwise.
1155 case CONDITIONAL_ACE_LOCAL_ATTRIBUTE
:
1156 ok
= token_claim_lookup(mem_ctx
, token
, arg
, &claim
);
1158 * "not ok" usually means a failure to find the attribute,
1159 * which is the false condition and not an error.
1161 * XXX or do we need an extra flag?
1164 case CONDITIONAL_ACE_RESOURCE_ATTRIBUTE
:
1165 ok
= resource_claim_lookup(mem_ctx
, arg
, sd
, &claim
);
1175 if (claim
.type
!= CONDITIONAL_ACE_SAMBA_RESULT_NULL
) {
1185 if (op
->type
== CONDITIONAL_ACE_TOKEN_NOT_EXISTS
) {
1187 } else if (op
->type
!= CONDITIONAL_ACE_TOKEN_EXISTS
) {
1188 /* should not get here */
1192 result
->data
.result
.value
= found
? ACE_CONDITION_TRUE
: ACE_CONDITION_FALSE
;
1198 static bool binary_logic_operator(
1199 const struct security_token
*token
,
1200 const struct ace_condition_token
*op
,
1201 const struct ace_condition_token
*lhs
,
1202 const struct ace_condition_token
*rhs
,
1203 struct ace_condition_token
*result
)
1205 struct ace_condition_token at
, bt
;
1209 result
->type
= CONDITIONAL_ACE_SAMBA_RESULT_BOOL
;
1210 result
->data
.result
.value
= ACE_CONDITION_UNKNOWN
;
1212 if (IS_LITERAL_TOKEN(lhs
) || IS_LITERAL_TOKEN(rhs
)) {
1214 * Logic operators don't work on literals.
1219 ok
= ternary_value(lhs
, &at
);
1223 ok
= ternary_value(rhs
, &bt
);
1227 a
= at
.data
.result
.value
;
1228 b
= bt
.data
.result
.value
;
1230 if (op
->type
== CONDITIONAL_ACE_TOKEN_AND
) {
1232 * AND true false unknown
1237 * unknown unless BOTH true or EITHER false
1239 if (a
== ACE_CONDITION_TRUE
&&
1240 b
== ACE_CONDITION_TRUE
) {
1241 result
->data
.result
.value
= ACE_CONDITION_TRUE
;
1244 if (a
== ACE_CONDITION_FALSE
||
1245 b
== ACE_CONDITION_FALSE
) {
1246 result
->data
.result
.value
= ACE_CONDITION_FALSE
;
1250 * Neither value is False, so the result is Unknown,
1251 * as set at the start of this function.
1256 * OR true false unknown
1261 * unknown unless EITHER true or BOTH false
1263 if (a
== ACE_CONDITION_TRUE
||
1264 b
== ACE_CONDITION_TRUE
) {
1265 result
->data
.result
.value
= ACE_CONDITION_TRUE
;
1268 if (a
== ACE_CONDITION_FALSE
&&
1269 b
== ACE_CONDITION_FALSE
) {
1270 result
->data
.result
.value
= ACE_CONDITION_FALSE
;
1277 static bool tokens_are_comparable(const struct ace_condition_token
*op
,
1278 const struct ace_condition_token
*lhs
,
1279 const struct ace_condition_token
*rhs
)
1283 * we can't compare different types *unless* they are both
1284 * integers, or one is a bool and the other is an integer 0 or
1285 * 1, and the operator is == or !=.
1287 //XXX actually it says "literal integers", do we need to check flags?
1289 if (IS_INT_TOKEN(lhs
) && IS_INT_TOKEN(rhs
)) {
1290 /* don't block e.g. comparing an int32 to an int64 */
1294 /* is it == or != */
1295 if (op
->type
!= CONDITIONAL_ACE_TOKEN_EQUAL
&&
1296 op
->type
!= CONDITIONAL_ACE_TOKEN_NOT_EQUAL
) {
1299 /* is one a bool and the other an int? */
1300 if (IS_INT_TOKEN(lhs
) && IS_BOOL_TOKEN(rhs
)) {
1301 n
= lhs
->data
.int64
.value
;
1302 } else if (IS_INT_TOKEN(rhs
) && IS_BOOL_TOKEN(lhs
)) {
1303 n
= rhs
->data
.int64
.value
;
1307 if (n
== 0 || n
== 1) {
1314 static bool cmp_to_result(const struct ace_condition_token
*op
,
1315 struct ace_condition_token
*result
,
1320 case CONDITIONAL_ACE_TOKEN_EQUAL
:
1323 case CONDITIONAL_ACE_TOKEN_NOT_EQUAL
:
1326 case CONDITIONAL_ACE_TOKEN_LESS_THAN
:
1329 case CONDITIONAL_ACE_TOKEN_LESS_OR_EQUAL
:
1332 case CONDITIONAL_ACE_TOKEN_GREATER_THAN
:
1335 case CONDITIONAL_ACE_TOKEN_GREATER_OR_EQUAL
:
1339 result
->data
.result
.value
= ACE_CONDITION_UNKNOWN
;
1342 result
->data
.result
.value
= \
1343 answer
? ACE_CONDITION_TRUE
: ACE_CONDITION_FALSE
;
1349 static bool compare_unicode(const struct ace_condition_token
*op
,
1350 const struct ace_condition_token
*lhs
,
1351 const struct ace_condition_token
*rhs
,
1354 struct ace_condition_unicode a
= lhs
->data
.unicode
;
1355 struct ace_condition_unicode b
= rhs
->data
.unicode
;
1357 * Comparison is case-insensitive UNLESS the claim structure
1358 * has the case-sensitive flag, which is passed through as a
1359 * flag on the token. Usually only the LHS is a claim value,
1360 * but in the event that they both are, we allow either to
1361 * request case-sensitivity.
1363 * For greater than and less than, the sort order is utf-8 order,
1364 * which is not exactly what Windows does, but we don't sort like
1365 * Windows does anywhere else either.
1367 uint8_t flags
= lhs
->flags
| rhs
->flags
;
1368 if (flags
& CLAIM_SECURITY_ATTRIBUTE_VALUE_CASE_SENSITIVE
) {
1369 *cmp
= memcmp(a
.value
, b
.value
, MIN(a
.length
, b
.length
));
1371 *cmp
= strncasecmp_m(a
.value
, b
.value
, MIN(a
.length
, b
.length
));
1374 *cmp
= a
.length
- b
.length
;
1380 static bool compare_bytes(const struct ace_condition_token
*op
,
1381 const struct ace_condition_token
*lhs
,
1382 const struct ace_condition_token
*rhs
,
1385 struct ace_condition_bytes a
= lhs
->data
.bytes
;
1386 struct ace_condition_bytes b
= rhs
->data
.bytes
;
1387 *cmp
= memcmp(a
.bytes
, b
.bytes
, MIN(a
.length
, b
.length
));
1389 *cmp
= a
.length
- b
.length
;
1395 static bool compare_sids(const struct ace_condition_token
*op
,
1396 const struct ace_condition_token
*lhs
,
1397 const struct ace_condition_token
*rhs
,
1400 *cmp
= dom_sid_compare(lhs
->data
.sid
.sid
,
1406 static bool compare_ints(const struct ace_condition_token
*op
,
1407 const struct ace_condition_token
*lhs
,
1408 const struct ace_condition_token
*rhs
,
1411 int64_t a
= lhs
->data
.int64
.value
;
1412 int64_t b
= rhs
->data
.int64
.value
;
1416 } else if (a
== b
) {
1425 static bool compare_bools(const struct ace_condition_token
*op
,
1426 const struct ace_condition_token
*lhs
,
1427 const struct ace_condition_token
*rhs
,
1431 struct ace_condition_token a
, b
;
1434 if (IS_LITERAL_TOKEN(lhs
)) {
1436 * we can compare a boolean LHS to a literal RHS, but not
1441 ok
= ternary_value(lhs
, &a
);
1445 ok
= ternary_value(rhs
, &b
);
1449 if (a
.data
.result
.value
== ACE_CONDITION_UNKNOWN
||
1450 b
.data
.result
.value
== ACE_CONDITION_UNKNOWN
) {
1455 case CONDITIONAL_ACE_TOKEN_EQUAL
:
1456 case CONDITIONAL_ACE_TOKEN_NOT_EQUAL
:
1457 *cmp
= a
.data
.result
.value
- b
.data
.result
.value
;
1460 /* we are not allowing non-equality comparisons with bools */
1467 static bool simple_relational_operator(const struct ace_condition_token
*op
,
1468 const struct ace_condition_token
*lhs
,
1469 const struct ace_condition_token
*rhs
,
1473 static bool compare_composites(const struct ace_condition_token
*op
,
1474 const struct ace_condition_token
*lhs
,
1475 const struct ace_condition_token
*rhs
,
1479 * We treat composites as if they are sets, which is to say we
1480 * don't care about order. This rules out < and > operations.
1482 * In Kerberos clams it is not possible to add duplicate
1483 * values to a composite, but in Conditional ACEs you can do
1484 * that. This means we can't short-cut by comparing the
1487 * THe extra sad thing is we might have to do it both ways
1488 * round. For example, comparing {a, a, b, a} to {a, b, c}, we
1489 * find all of the first group in the second, but that doesn't
1490 * mean all of the second are in the first.
1492 struct ace_condition_composite args
[2] = {
1493 lhs
->data
.composite
,
1498 for (k
= 0; k
< 2; k
++) {
1499 struct ace_condition_composite a
= args
[k
];
1500 struct ace_condition_composite b
= args
[1 - k
];
1502 for (i
= 0; i
< a
.n_members
; i
++) {
1503 const struct ace_condition_token
*lhs2
= &a
.tokens
[i
];
1505 for (j
= 0; j
< b
.n_members
; j
++) {
1506 const struct ace_condition_token
*rhs2
= &b
.tokens
[j
];
1508 bool ok
= simple_relational_operator(op
, lhs2
, rhs2
, &cmp_pair
);
1512 if (cmp_pair
== 0) {
1513 /* This item in A is also in B. */
1529 static bool simple_relational_operator(const struct ace_condition_token
*op
,
1530 const struct ace_condition_token
*lhs
,
1531 const struct ace_condition_token
*rhs
,
1535 if (lhs
->type
!= rhs
->type
) {
1536 if (! tokens_are_comparable(op
, lhs
, rhs
)) {
1540 switch (lhs
->type
) {
1541 case CONDITIONAL_ACE_TOKEN_INT8
:
1542 case CONDITIONAL_ACE_TOKEN_INT16
:
1543 case CONDITIONAL_ACE_TOKEN_INT32
:
1544 case CONDITIONAL_ACE_TOKEN_INT64
:
1545 if (rhs
->type
== CONDITIONAL_ACE_SAMBA_RESULT_BOOL
) {
1546 return compare_bools(op
, lhs
, rhs
, cmp
);
1548 return compare_ints(op
, lhs
, rhs
, cmp
);
1549 case CONDITIONAL_ACE_SAMBA_RESULT_BOOL
:
1550 return compare_bools(op
, lhs
, rhs
, cmp
);
1551 case CONDITIONAL_ACE_TOKEN_UNICODE
:
1552 return compare_unicode(op
, lhs
, rhs
, cmp
);
1553 case CONDITIONAL_ACE_TOKEN_OCTET_STRING
:
1554 return compare_bytes(op
, lhs
, rhs
, cmp
);
1555 case CONDITIONAL_ACE_TOKEN_SID
:
1556 return compare_sids(op
, lhs
, rhs
, cmp
);
1557 case CONDITIONAL_ACE_TOKEN_COMPOSITE
:
1558 return compare_composites(op
, lhs
, rhs
, cmp
);
1559 case CONDITIONAL_ACE_SAMBA_RESULT_NULL
:
1560 /* leave the result unknown */
1563 DBG_ERR("did not expect ace type %u\n", lhs
->type
);
1571 static bool find_in_composite(const struct ace_condition_token
*tok
,
1572 struct ace_condition_composite candidates
,
1578 const struct ace_condition_token equals
= {
1579 .type
= CONDITIONAL_ACE_TOKEN_EQUAL
1584 for (i
= 0; i
< candidates
.n_members
; i
++) {
1585 ok
= simple_relational_operator(&equals
,
1587 &candidates
.tokens
[i
],
1601 static bool contains_operator(const struct ace_condition_token
*lhs
,
1602 const struct ace_condition_token
*rhs
,
1608 const struct ace_condition_token equals
= {
1609 .type
= CONDITIONAL_ACE_TOKEN_EQUAL
1613 * All the required objects must be identical to something in
1614 * candidates. But what do we mean by *identical*? We'll use
1615 * the equality operator to decide that.
1617 * Both the lhs or rhs can be solitary objects or composites.
1618 * This makes it a bit fiddlier.
1620 if (lhs
->type
== CONDITIONAL_ACE_TOKEN_COMPOSITE
) {
1621 struct ace_condition_composite candidates
= lhs
->data
.composite
;
1622 struct ace_condition_composite required
;
1623 if (rhs
->type
!= CONDITIONAL_ACE_TOKEN_COMPOSITE
) {
1624 return find_in_composite(rhs
, candidates
, answer
);
1626 required
= rhs
->data
.composite
;
1627 if (required
.n_members
== 0) {
1630 for (i
= 0; i
< required
.n_members
; i
++) {
1631 const struct ace_condition_token
*t
= &required
.tokens
[i
];
1632 ok
= find_in_composite(t
, candidates
, answer
);
1638 * one required item was not there,
1644 /* all required items are there, *answer will be true */
1647 /* LHS is a single item */
1648 if (rhs
->type
== CONDITIONAL_ACE_TOKEN_COMPOSITE
) {
1650 * There could be more than one RHS member that is
1651 * equal to the single LHS value, so it doesn't help
1652 * to compare lengths or anything.
1654 struct ace_condition_composite required
= rhs
->data
.composite
;
1655 if (required
.n_members
== 0) {
1658 for (i
= 0; i
< required
.n_members
; i
++) {
1659 ok
= simple_relational_operator(&equals
,
1661 &required
.tokens
[i
],
1668 * one required item was not there,
1678 /* LHS and RHS are both single */
1679 ok
= simple_relational_operator(&equals
,
1686 *answer
= (cmp
== 0);
1691 static bool any_of_operator(const struct ace_condition_token
*lhs
,
1692 const struct ace_condition_token
*rhs
,
1698 const struct ace_condition_token equals
= {
1699 .type
= CONDITIONAL_ACE_TOKEN_EQUAL
1703 * There has to be *some* overlap between the LHS and RHS.
1704 * Both sides can be solitary objects or composites.
1706 * We can exploit this symmetry.
1708 if (lhs
->type
!= CONDITIONAL_ACE_TOKEN_COMPOSITE
) {
1709 const struct ace_condition_token
*tmp
= lhs
;
1713 if (lhs
->type
!= CONDITIONAL_ACE_TOKEN_COMPOSITE
) {
1715 ok
= simple_relational_operator(&equals
,
1722 *answer
= (cmp
== 0);
1725 if (rhs
->type
!= CONDITIONAL_ACE_TOKEN_COMPOSITE
) {
1726 return find_in_composite(rhs
, lhs
->data
.composite
, answer
);
1728 /* both are composites */
1729 if (lhs
->data
.composite
.n_members
== 0) {
1732 for (i
= 0; i
< lhs
->data
.composite
.n_members
; i
++) {
1733 ok
= find_in_composite(&lhs
->data
.composite
.tokens
[i
],
1734 rhs
->data
.composite
,
1740 /* We have found one match, which is enough. */
1748 static bool composite_relational_operator(const struct ace_condition_token
*op
,
1749 const struct ace_condition_token
*lhs
,
1750 const struct ace_condition_token
*rhs
,
1751 struct ace_condition_token
*result
)
1755 case CONDITIONAL_ACE_TOKEN_CONTAINS
:
1756 case CONDITIONAL_ACE_TOKEN_NOT_CONTAINS
:
1757 ok
= contains_operator(lhs
, rhs
, &answer
);
1759 case CONDITIONAL_ACE_TOKEN_ANY_OF
:
1760 case CONDITIONAL_ACE_TOKEN_NOT_ANY_OF
:
1761 ok
= any_of_operator(lhs
, rhs
, &answer
);
1770 /* negate the NOTs */
1771 if (op
->type
== CONDITIONAL_ACE_TOKEN_NOT_CONTAINS
||
1772 op
->type
== CONDITIONAL_ACE_TOKEN_NOT_ANY_OF
) {
1777 result
->data
.result
.value
= ACE_CONDITION_TRUE
;
1779 result
->data
.result
.value
= ACE_CONDITION_FALSE
;
1785 static bool relational_operator(
1786 const struct security_token
*token
,
1787 const struct ace_condition_token
*op
,
1788 const struct ace_condition_token
*lhs
,
1789 const struct ace_condition_token
*rhs
,
1790 struct ace_condition_token
*result
)
1794 result
->type
= CONDITIONAL_ACE_SAMBA_RESULT_BOOL
;
1795 result
->data
.result
.value
= ACE_CONDITION_UNKNOWN
;
1797 if ((lhs
->flags
& CONDITIONAL_ACE_FLAG_TOKEN_FROM_ATTR
) == 0) {
1798 /* LHS was not derived from an attribute */
1803 * This first nested switch is ensuring that >, >=, <, <= are
1804 * not being tried on tokens that are not numbers, strings, or
1805 * octet strings. Equality operators are available for all types.
1807 switch (lhs
->type
) {
1808 case CONDITIONAL_ACE_TOKEN_INT8
:
1809 case CONDITIONAL_ACE_TOKEN_INT16
:
1810 case CONDITIONAL_ACE_TOKEN_INT32
:
1811 case CONDITIONAL_ACE_TOKEN_INT64
:
1812 case CONDITIONAL_ACE_TOKEN_UNICODE
:
1813 case CONDITIONAL_ACE_TOKEN_OCTET_STRING
:
1817 case CONDITIONAL_ACE_TOKEN_LESS_THAN
:
1818 case CONDITIONAL_ACE_TOKEN_LESS_OR_EQUAL
:
1819 case CONDITIONAL_ACE_TOKEN_GREATER_THAN
:
1820 case CONDITIONAL_ACE_TOKEN_GREATER_OR_EQUAL
:
1828 * Dispatch according to operator type.
1831 case CONDITIONAL_ACE_TOKEN_EQUAL
:
1832 case CONDITIONAL_ACE_TOKEN_NOT_EQUAL
:
1833 case CONDITIONAL_ACE_TOKEN_LESS_THAN
:
1834 case CONDITIONAL_ACE_TOKEN_LESS_OR_EQUAL
:
1835 case CONDITIONAL_ACE_TOKEN_GREATER_THAN
:
1836 case CONDITIONAL_ACE_TOKEN_GREATER_OR_EQUAL
:
1837 ok
= simple_relational_operator(op
,
1842 ok
= cmp_to_result(op
, result
, cmp
);
1846 case CONDITIONAL_ACE_TOKEN_CONTAINS
:
1847 case CONDITIONAL_ACE_TOKEN_ANY_OF
:
1848 case CONDITIONAL_ACE_TOKEN_NOT_CONTAINS
:
1849 case CONDITIONAL_ACE_TOKEN_NOT_ANY_OF
:
1850 return composite_relational_operator(op
,
1860 int run_conditional_ace(TALLOC_CTX
*mem_ctx
,
1861 const struct security_token
*token
,
1862 struct ace_condition_script
*program
,
1863 const struct security_descriptor
*sd
)
1867 struct ace_condition_token
*lhs
= NULL
;
1868 struct ace_condition_token
*rhs
= NULL
;
1869 struct ace_condition_token result
= {};
1872 for (i
= 0; i
< program
->length
; i
++) {
1873 struct ace_condition_token
*tok
= &program
->tokens
[i
];
1874 switch (tok
->type
) {
1875 case CONDITIONAL_ACE_TOKEN_INT8
:
1876 case CONDITIONAL_ACE_TOKEN_INT16
:
1877 case CONDITIONAL_ACE_TOKEN_INT32
:
1878 case CONDITIONAL_ACE_TOKEN_INT64
:
1879 case CONDITIONAL_ACE_TOKEN_UNICODE
:
1880 case CONDITIONAL_ACE_TOKEN_OCTET_STRING
:
1881 case CONDITIONAL_ACE_TOKEN_SID
:
1882 case CONDITIONAL_ACE_TOKEN_COMPOSITE
:
1883 /* just plonk these literals on the stack */
1884 program
->stack
[depth
] = *tok
;
1888 case CONDITIONAL_ACE_LOCAL_ATTRIBUTE
:
1889 case CONDITIONAL_ACE_USER_ATTRIBUTE
:
1890 case CONDITIONAL_ACE_DEVICE_ATTRIBUTE
:
1891 ok
= token_claim_lookup(mem_ctx
, token
, tok
, &result
);
1895 program
->stack
[depth
] = result
;
1899 case CONDITIONAL_ACE_RESOURCE_ATTRIBUTE
:
1900 ok
= resource_claim_lookup(mem_ctx
,
1907 program
->stack
[depth
] = result
;
1911 case CONDITIONAL_ACE_TOKEN_MEMBER_OF
:
1912 case CONDITIONAL_ACE_TOKEN_DEVICE_MEMBER_OF
:
1913 case CONDITIONAL_ACE_TOKEN_MEMBER_OF_ANY
:
1914 case CONDITIONAL_ACE_TOKEN_DEVICE_MEMBER_OF_ANY
:
1915 case CONDITIONAL_ACE_TOKEN_NOT_MEMBER_OF
:
1916 case CONDITIONAL_ACE_TOKEN_NOT_DEVICE_MEMBER_OF
:
1917 case CONDITIONAL_ACE_TOKEN_NOT_MEMBER_OF_ANY
:
1918 case CONDITIONAL_ACE_TOKEN_NOT_DEVICE_MEMBER_OF_ANY
:
1923 lhs
= &program
->stack
[depth
];
1924 ok
= member_lookup(token
, tok
, lhs
, &result
);
1928 program
->stack
[depth
] = result
;
1931 /* binary relational operators */
1932 case CONDITIONAL_ACE_TOKEN_EQUAL
:
1933 case CONDITIONAL_ACE_TOKEN_NOT_EQUAL
:
1934 case CONDITIONAL_ACE_TOKEN_LESS_THAN
:
1935 case CONDITIONAL_ACE_TOKEN_LESS_OR_EQUAL
:
1936 case CONDITIONAL_ACE_TOKEN_GREATER_THAN
:
1937 case CONDITIONAL_ACE_TOKEN_GREATER_OR_EQUAL
:
1938 case CONDITIONAL_ACE_TOKEN_CONTAINS
:
1939 case CONDITIONAL_ACE_TOKEN_ANY_OF
:
1940 case CONDITIONAL_ACE_TOKEN_NOT_CONTAINS
:
1941 case CONDITIONAL_ACE_TOKEN_NOT_ANY_OF
:
1946 rhs
= &program
->stack
[depth
];
1948 lhs
= &program
->stack
[depth
];
1949 ok
= relational_operator(token
, tok
, lhs
, rhs
, &result
);
1953 program
->stack
[depth
] = result
;
1956 /* unary logical operators */
1957 case CONDITIONAL_ACE_TOKEN_EXISTS
:
1958 case CONDITIONAL_ACE_TOKEN_NOT_EXISTS
:
1959 case CONDITIONAL_ACE_TOKEN_NOT
:
1964 lhs
= &program
->stack
[depth
];
1965 ok
= unary_logic_operator(mem_ctx
, token
, tok
, lhs
, sd
, &result
);
1969 program
->stack
[depth
] = result
;
1972 /* binary logical operators */
1973 case CONDITIONAL_ACE_TOKEN_AND
:
1974 case CONDITIONAL_ACE_TOKEN_OR
:
1979 rhs
= &program
->stack
[depth
];
1981 lhs
= &program
->stack
[depth
];
1982 ok
= binary_logic_operator(token
, tok
, lhs
, rhs
, &result
);
1986 program
->stack
[depth
] = result
;
1994 * The evaluation should have left a single result value (true, false,
1995 * or unknown) on the stack. If not, the expression was malformed.
2000 result
= program
->stack
[0];
2001 if (result
.type
!= CONDITIONAL_ACE_SAMBA_RESULT_BOOL
) {
2005 return result
.data
.result
.value
;
2009 * the result of an error is always UNKNOWN, which should be
2010 * interpreted pessimistically, not allowing access.
2012 return ACE_CONDITION_UNKNOWN
;
2016 /** access_check_conditional_ace()
2018 * Run the conditional ACE from the blob form. Return false if it is
2019 * not a valid conditional ACE, true if it is, even if there is some
2020 * other error in running it. The *result parameter is set to
2021 * ACE_CONDITION_FALSE, ACE_CONDITION_TRUE, or ACE_CONDITION_UNKNOWN.
2023 * ACE_CONDITION_UNKNOWN should be treated pessimistically, as if were
2024 * TRUE for deny ACEs, and FALSE for allow ACEs.
2026 * @param[in] ace - the ACE being processed.
2027 * @param[in] token - the security token the ACE is processing.
2028 * @param[out] result - a ternary result value.
2030 * @return true if it is a valid conditional ACE.
2033 bool access_check_conditional_ace(const struct security_ace
*ace
,
2034 const struct security_token
*token
,
2035 const struct security_descriptor
*sd
,
2038 TALLOC_CTX
*tmp_ctx
= talloc_new(NULL
);
2039 struct ace_condition_script
*program
= NULL
;
2040 program
= parse_conditional_ace(tmp_ctx
, ace
->coda
.conditions
);
2041 if (program
== NULL
) {
2042 *result
= ACE_CONDITION_UNKNOWN
;
2043 TALLOC_FREE(tmp_ctx
);
2047 *result
= run_conditional_ace(tmp_ctx
, token
, program
, sd
);
2049 TALLOC_FREE(tmp_ctx
);
2054 bool conditional_ace_encode_binary(TALLOC_CTX
*mem_ctx
,
2055 struct ace_condition_script
*program
,
2058 size_t i
, j
, alloc_size
, required_size
;
2059 uint8_t *data
= NULL
;
2060 *dest
= (DATA_BLOB
){NULL
, 0};
2062 alloc_size
= CONDITIONAL_ACE_MAX_LENGTH
;
2063 data
= talloc_array(mem_ctx
,
2076 for (i
= 0; i
< program
->length
; i
++) {
2077 struct ace_condition_token
*tok
= &program
->tokens
[i
];
2081 * In all cases we write the token type byte.
2083 data
[j
] = tok
->type
;
2085 if (j
>= alloc_size
) {
2089 switch (tok
->type
) {
2090 case CONDITIONAL_ACE_TOKEN_MEMBER_OF
:
2091 case CONDITIONAL_ACE_TOKEN_DEVICE_MEMBER_OF
:
2092 case CONDITIONAL_ACE_TOKEN_MEMBER_OF_ANY
:
2093 case CONDITIONAL_ACE_TOKEN_DEVICE_MEMBER_OF_ANY
:
2094 case CONDITIONAL_ACE_TOKEN_NOT_MEMBER_OF
:
2095 case CONDITIONAL_ACE_TOKEN_NOT_DEVICE_MEMBER_OF
:
2096 case CONDITIONAL_ACE_TOKEN_NOT_MEMBER_OF_ANY
:
2097 case CONDITIONAL_ACE_TOKEN_NOT_DEVICE_MEMBER_OF_ANY
:
2098 case CONDITIONAL_ACE_TOKEN_EQUAL
:
2099 case CONDITIONAL_ACE_TOKEN_NOT_EQUAL
:
2100 case CONDITIONAL_ACE_TOKEN_LESS_THAN
:
2101 case CONDITIONAL_ACE_TOKEN_LESS_OR_EQUAL
:
2102 case CONDITIONAL_ACE_TOKEN_GREATER_THAN
:
2103 case CONDITIONAL_ACE_TOKEN_GREATER_OR_EQUAL
:
2104 case CONDITIONAL_ACE_TOKEN_CONTAINS
:
2105 case CONDITIONAL_ACE_TOKEN_ANY_OF
:
2106 case CONDITIONAL_ACE_TOKEN_NOT_CONTAINS
:
2107 case CONDITIONAL_ACE_TOKEN_NOT_ANY_OF
:
2108 case CONDITIONAL_ACE_TOKEN_EXISTS
:
2109 case CONDITIONAL_ACE_TOKEN_NOT_EXISTS
:
2110 case CONDITIONAL_ACE_TOKEN_NOT
:
2111 case CONDITIONAL_ACE_TOKEN_AND
:
2112 case CONDITIONAL_ACE_TOKEN_OR
:
2114 * All of these are simple operators that operate on
2115 * the stack. We have already added the tok->type and
2116 * there's nothing else to do.
2120 case CONDITIONAL_ACE_TOKEN_INT8
:
2121 case CONDITIONAL_ACE_TOKEN_INT16
:
2122 case CONDITIONAL_ACE_TOKEN_INT32
:
2123 case CONDITIONAL_ACE_TOKEN_INT64
:
2124 ok
= check_integer_range(tok
);
2128 consumed
= push_integer(data
+ j
,
2132 case CONDITIONAL_ACE_LOCAL_ATTRIBUTE
:
2133 case CONDITIONAL_ACE_USER_ATTRIBUTE
:
2134 case CONDITIONAL_ACE_RESOURCE_ATTRIBUTE
:
2135 case CONDITIONAL_ACE_DEVICE_ATTRIBUTE
:
2136 case CONDITIONAL_ACE_TOKEN_UNICODE
:
2137 consumed
= push_unicode(data
+ j
,
2139 &tok
->data
.unicode
);
2141 case CONDITIONAL_ACE_TOKEN_OCTET_STRING
:
2142 consumed
= push_bytes(data
+ j
,
2146 case CONDITIONAL_ACE_TOKEN_SID
:
2147 consumed
= push_sid(data
+ j
,
2151 case CONDITIONAL_ACE_TOKEN_COMPOSITE
:
2152 consumed
= push_composite(data
+ j
,
2154 &tok
->data
.composite
);
2158 DBG_ERR("unknown token 0x%02x at position %zu\n",
2162 if (consumed
== -1) {
2166 if (j
>= alloc_size
) {
2170 /* align to a 4 byte boundary */
2171 required_size
= (j
+ 3) & ~((size_t)3);
2172 if (required_size
> alloc_size
) {
2175 while (j
< required_size
) {
2179 data
= talloc_realloc(mem_ctx
,
2187 (*dest
).data
= data
;