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/ndr_conditional_ace.h"
22 #include "librpc/gen_ndr/conditional_ace.h"
23 #include "libcli/security/security.h"
24 #include "libcli/security/conditional_ace.h"
25 #include "libcli/security/claims-conversions.h"
26 #include "lib/util/tsort.h"
27 #include "lib/util/debug.h"
28 #include "lib/util/bytearray.h"
29 #include "lib/util/talloc_stack.h"
30 #include "util/discard.h"
31 #include "lib/util/stable_sort.h"
33 * Conditional ACE logic truth tables.
35 * Conditional ACES use a ternary logic, with "unknown" as well as true and
36 * false. The ultimate meaning of unknown depends on the context; in a deny
37 * ace, unknown means yes, in an allow ace, unknown means no. That is, we
38 * treat unknown results with maximum suspicion.
40 * AND true false unknown
45 * OR true false unknown
55 * This can be summed up by saying unknown values taint the result except in
56 * the cases where short circuit evaluation could apply (true OR anything,
57 * false AND anything, which hold their value).
59 * What counts as unknown
62 * - certain comparisons between incompatible types
64 * What counts as false
69 * An error means the entire expression is unknown.
73 static bool check_integer_range(const struct ace_condition_token
*tok
)
75 int64_t val
= tok
->data
.int64
.value
;
77 case CONDITIONAL_ACE_TOKEN_INT8
:
78 if (val
< -128 || val
> 127) {
82 case CONDITIONAL_ACE_TOKEN_INT16
:
83 if (val
< INT16_MIN
|| val
> INT16_MAX
) {
87 case CONDITIONAL_ACE_TOKEN_INT32
:
88 if (val
< INT32_MIN
|| val
> INT32_MAX
) {
92 case CONDITIONAL_ACE_TOKEN_INT64
:
93 /* val has these limits naturally */
99 if (tok
->data
.int64
.base
!= CONDITIONAL_ACE_INT_BASE_8
&&
100 tok
->data
.int64
.base
!= CONDITIONAL_ACE_INT_BASE_10
&&
101 tok
->data
.int64
.base
!= CONDITIONAL_ACE_INT_BASE_16
) {
104 if (tok
->data
.int64
.sign
!= CONDITIONAL_ACE_INT_SIGN_POSITIVE
&&
105 tok
->data
.int64
.sign
!= CONDITIONAL_ACE_INT_SIGN_NEGATIVE
&&
106 tok
->data
.int64
.sign
!= CONDITIONAL_ACE_INT_SIGN_NONE
) {
113 static ssize_t
pull_integer(TALLOC_CTX
*mem_ctx
,
114 uint8_t *data
, size_t length
,
115 struct ace_condition_int
*tok
)
118 enum ndr_err_code ndr_err
;
119 DATA_BLOB v
= data_blob_const(data
, length
);
120 struct ndr_pull
*ndr
= ndr_pull_init_blob(&v
, mem_ctx
);
124 ndr_err
= ndr_pull_ace_condition_int(ndr
, NDR_SCALARS
|NDR_BUFFERS
, tok
);
125 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
129 bytes_used
= ndr
->offset
;
134 static ssize_t
push_integer(uint8_t *data
, size_t available
,
135 const struct ace_condition_int
*tok
)
137 enum ndr_err_code ndr_err
;
139 ndr_err
= ndr_push_struct_blob(&v
, NULL
,
141 (ndr_push_flags_fn_t
)ndr_push_ace_condition_int
);
142 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
145 if (available
< v
.length
) {
149 memcpy(data
, v
.data
, v
.length
);
155 static ssize_t
pull_unicode(TALLOC_CTX
*mem_ctx
,
156 uint8_t *data
, size_t length
,
157 struct ace_condition_unicode
*tok
)
160 enum ndr_err_code ndr_err
;
161 DATA_BLOB v
= data_blob_const(data
, length
);
162 struct ndr_pull
*ndr
= ndr_pull_init_blob(&v
, mem_ctx
);
166 ndr_err
= ndr_pull_ace_condition_unicode(ndr
, NDR_SCALARS
|NDR_BUFFERS
, tok
);
167 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
171 bytes_used
= ndr
->offset
;
176 static ssize_t
push_unicode(uint8_t *data
, size_t available
,
177 const struct ace_condition_unicode
*tok
)
179 enum ndr_err_code ndr_err
;
181 ndr_err
= ndr_push_struct_blob(&v
, NULL
,
183 (ndr_push_flags_fn_t
)ndr_push_ace_condition_unicode
);
184 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
187 if (available
< v
.length
) {
191 memcpy(data
, v
.data
, v
.length
);
197 static ssize_t
pull_bytes(TALLOC_CTX
*mem_ctx
,
198 uint8_t *data
, size_t length
,
202 enum ndr_err_code ndr_err
;
203 DATA_BLOB v
= data_blob_const(data
, length
);
204 struct ndr_pull
*ndr
= ndr_pull_init_blob(&v
, mem_ctx
);
208 ndr_err
= ndr_pull_DATA_BLOB(ndr
, NDR_SCALARS
|NDR_BUFFERS
, tok
);
209 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
213 bytes_used
= ndr
->offset
;
218 static ssize_t
push_bytes(uint8_t *data
, size_t available
,
219 const DATA_BLOB
*tok
)
222 enum ndr_err_code ndr_err
;
223 TALLOC_CTX
*frame
= talloc_stackframe();
224 struct ndr_push
*ndr
= ndr_push_init_ctx(frame
);
230 ndr_err
= ndr_push_DATA_BLOB(ndr
, NDR_SCALARS
|NDR_BUFFERS
, *tok
);
231 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
236 if (available
< ndr
->offset
) {
240 memcpy(data
, ndr
->data
, ndr
->offset
);
241 offset
= ndr
->offset
;
246 static ssize_t
pull_sid(TALLOC_CTX
*mem_ctx
,
247 uint8_t *data
, size_t length
,
248 struct ace_condition_sid
*tok
)
251 enum ndr_err_code ndr_err
;
252 DATA_BLOB v
= data_blob_const(data
, length
);
253 struct ndr_pull
*ndr
= ndr_pull_init_blob(&v
, mem_ctx
);
257 ndr
->flags
|= LIBNDR_FLAG_SUBCONTEXT_NO_UNREAD_BYTES
;
259 ndr_err
= ndr_pull_ace_condition_sid(ndr
, NDR_SCALARS
|NDR_BUFFERS
, tok
);
260 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
264 bytes_used
= ndr
->offset
;
269 static ssize_t
push_sid(uint8_t *data
, size_t available
,
270 const struct ace_condition_sid
*tok
)
272 enum ndr_err_code ndr_err
;
274 ndr_err
= ndr_push_struct_blob(&v
, NULL
,
276 (ndr_push_flags_fn_t
)ndr_push_ace_condition_sid
);
277 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err
)) {
280 if (available
< v
.length
) {
284 memcpy(data
, v
.data
, v
.length
);
290 static ssize_t
pull_composite(TALLOC_CTX
*mem_ctx
,
291 uint8_t *data
, size_t length
,
292 struct ace_condition_composite
*tok
)
297 struct ace_condition_token
*tokens
= NULL
;
301 byte_size
= PULL_LE_U32(data
, 0);
302 if (byte_size
> length
- 4) {
306 * There is a list of other literal tokens (possibly including nested
307 * composites), which we will store in an array.
309 * This array can *only* be literals.
311 alloc_length
= byte_size
;
312 tokens
= talloc_array(mem_ctx
,
313 struct ace_condition_token
,
315 if (tokens
== NULL
) {
321 while (i
< byte_size
) {
322 struct ace_condition_token
*el
= &tokens
[j
];
324 uint8_t *el_data
= NULL
;
327 *el
= (struct ace_condition_token
) { .type
= data
[i
] };
331 available
= byte_size
- i
;
334 case CONDITIONAL_ACE_TOKEN_INT8
:
335 case CONDITIONAL_ACE_TOKEN_INT16
:
336 case CONDITIONAL_ACE_TOKEN_INT32
:
337 case CONDITIONAL_ACE_TOKEN_INT64
:
338 consumed
= pull_integer(mem_ctx
,
342 ok
= check_integer_range(el
);
347 case CONDITIONAL_ACE_TOKEN_UNICODE
:
348 consumed
= pull_unicode(mem_ctx
,
354 case CONDITIONAL_ACE_TOKEN_OCTET_STRING
:
355 consumed
= pull_bytes(mem_ctx
,
361 case CONDITIONAL_ACE_TOKEN_SID
:
362 consumed
= pull_sid(mem_ctx
,
368 case CONDITIONAL_ACE_TOKEN_COMPOSITE
:
369 DBG_ERR("recursive composite tokens in conditional "
370 "ACEs are not currently supported\n");
376 if (consumed
< 0 || consumed
+ i
> length
) {
381 if (j
== UINT16_MAX
) {
385 if (j
== alloc_length
) {
386 struct ace_condition_token
*new_tokens
= NULL
;
389 new_tokens
= talloc_realloc(mem_ctx
,
391 struct ace_condition_token
,
394 if (new_tokens
== NULL
) {
401 tok
->tokens
= tokens
;
409 static ssize_t
push_composite(uint8_t *data
, size_t length
,
410 const struct ace_condition_composite
*tok
)
413 uint8_t *byte_length_ptr
;
419 * We have no idea what the eventual length will be, so we keep a
420 * pointer to write it in at the end.
422 byte_length_ptr
= data
;
423 PUSH_LE_U32(data
, 0, 0);
426 for (i
= 0; i
< tok
->n_members
&& used
< length
; i
++) {
427 struct ace_condition_token
*el
= &tok
->tokens
[i
];
429 uint8_t *el_data
= NULL
;
432 data
[used
] = el
->type
;
434 if (used
== length
) {
436 * used == length is not expected here; the token
437 * types that only have an opcode and no data are not
438 * literals that can be in composites.
442 el_data
= data
+ used
;
443 available
= length
- used
;
446 case CONDITIONAL_ACE_TOKEN_INT8
:
447 case CONDITIONAL_ACE_TOKEN_INT16
:
448 case CONDITIONAL_ACE_TOKEN_INT32
:
449 case CONDITIONAL_ACE_TOKEN_INT64
:
450 ok
= check_integer_range(el
);
454 consumed
= push_integer(el_data
,
458 case CONDITIONAL_ACE_TOKEN_UNICODE
:
459 consumed
= push_unicode(el_data
,
464 case CONDITIONAL_ACE_TOKEN_OCTET_STRING
:
465 consumed
= push_bytes(el_data
,
470 case CONDITIONAL_ACE_TOKEN_SID
:
471 consumed
= push_sid(el_data
,
476 case CONDITIONAL_ACE_TOKEN_COMPOSITE
:
477 consumed
= push_composite(el_data
,
479 &el
->data
.composite
);
495 PUSH_LE_U32(byte_length_ptr
, 0, used
- 4);
499 static ssize_t
pull_end_padding(uint8_t *data
, size_t length
)
502 * We just check that we have the right kind of number of zero
503 * bytes. The blob must end on a multiple of 4. One zero byte
504 * has already been swallowed as tok->type, which sends us
505 * here, so we expect 1 or two more -- total padding is 0, 1,
508 * zero is also called CONDITIONAL_ACE_TOKEN_INVALID_OR_PADDING.
514 for (i
= 0; i
< length
; i
++) {
523 struct ace_condition_script
*parse_conditional_ace(TALLOC_CTX
*mem_ctx
,
527 struct ace_condition_token
*tokens
= NULL
;
529 struct ace_condition_script
*program
= NULL
;
531 if (data
.length
< 4 ||
532 data
.data
[0] != 'a' ||
533 data
.data
[1] != 'r' ||
534 data
.data
[2] != 't' ||
535 data
.data
[3] != 'x') {
537 * lacks the "artx" conditional ace identifier magic.
538 * NULL returns will deny access.
542 if (data
.length
> CONDITIONAL_ACE_MAX_LENGTH
||
543 (data
.length
& 3) != 0) {
545 * >= 64k or non-multiples of 4 are not possible in the ACE
551 program
= talloc(mem_ctx
, struct ace_condition_script
);
552 if (program
== NULL
) {
557 * We will normally end up with fewer than data.length tokens, as
558 * values are stored in multiple bytes (all integers are 10 bytes,
559 * strings and attributes are utf16 + length, SIDs are SID-size +
560 * length, etc). But operators are one byte, so something like
561 * !(!(!(!(!(!(x)))))) -- where each '!(..)' is one byte -- will bring
562 * the number of tokens close to the number of bytes.
564 * This is all to say we're guessing a token length that hopes to
565 * avoid reallocs without wasting too much up front.
567 alloc_length
= data
.length
/ 2 + 1;
568 tokens
= talloc_array(program
,
569 struct ace_condition_token
,
571 if (tokens
== NULL
) {
572 TALLOC_FREE(program
);
578 while(i
< data
.length
) {
579 struct ace_condition_token
*tok
= &tokens
[j
];
580 ssize_t consumed
= 0;
581 uint8_t *tok_data
= NULL
;
584 tok
->type
= data
.data
[i
];
587 tok_data
= data
.data
+ i
;
588 available
= data
.length
- i
;
591 case CONDITIONAL_ACE_TOKEN_INT8
:
592 case CONDITIONAL_ACE_TOKEN_INT16
:
593 case CONDITIONAL_ACE_TOKEN_INT32
:
594 case CONDITIONAL_ACE_TOKEN_INT64
:
595 consumed
= pull_integer(program
,
599 ok
= check_integer_range(tok
);
604 case CONDITIONAL_ACE_TOKEN_UNICODE
:
606 * The next four are pulled as unicode, but are
607 * processed as user attribute look-ups.
609 case CONDITIONAL_ACE_LOCAL_ATTRIBUTE
:
610 case CONDITIONAL_ACE_USER_ATTRIBUTE
:
611 case CONDITIONAL_ACE_RESOURCE_ATTRIBUTE
:
612 case CONDITIONAL_ACE_DEVICE_ATTRIBUTE
:
613 consumed
= pull_unicode(program
,
619 case CONDITIONAL_ACE_TOKEN_OCTET_STRING
:
620 consumed
= pull_bytes(program
,
626 case CONDITIONAL_ACE_TOKEN_SID
:
627 consumed
= pull_sid(program
,
633 case CONDITIONAL_ACE_TOKEN_COMPOSITE
:
634 consumed
= pull_composite(program
,
637 &tok
->data
.composite
);
640 case CONDITIONAL_ACE_TOKEN_MEMBER_OF
:
641 case CONDITIONAL_ACE_TOKEN_DEVICE_MEMBER_OF
:
642 case CONDITIONAL_ACE_TOKEN_MEMBER_OF_ANY
:
643 case CONDITIONAL_ACE_TOKEN_DEVICE_MEMBER_OF_ANY
:
644 case CONDITIONAL_ACE_TOKEN_NOT_MEMBER_OF
:
645 case CONDITIONAL_ACE_TOKEN_NOT_DEVICE_MEMBER_OF
:
646 case CONDITIONAL_ACE_TOKEN_NOT_MEMBER_OF_ANY
:
647 case CONDITIONAL_ACE_TOKEN_NOT_DEVICE_MEMBER_OF_ANY
:
649 * these require a SID or composite SID list operand,
650 * and we could check that now in most cases.
653 /* binary relational operators */
654 case CONDITIONAL_ACE_TOKEN_EQUAL
:
655 case CONDITIONAL_ACE_TOKEN_NOT_EQUAL
:
656 case CONDITIONAL_ACE_TOKEN_LESS_THAN
:
657 case CONDITIONAL_ACE_TOKEN_LESS_OR_EQUAL
:
658 case CONDITIONAL_ACE_TOKEN_GREATER_THAN
:
659 case CONDITIONAL_ACE_TOKEN_GREATER_OR_EQUAL
:
660 case CONDITIONAL_ACE_TOKEN_CONTAINS
:
661 case CONDITIONAL_ACE_TOKEN_ANY_OF
:
662 case CONDITIONAL_ACE_TOKEN_NOT_CONTAINS
:
663 case CONDITIONAL_ACE_TOKEN_NOT_ANY_OF
:
664 /* unary logical operators */
665 case CONDITIONAL_ACE_TOKEN_EXISTS
:
666 case CONDITIONAL_ACE_TOKEN_NOT_EXISTS
:
667 case CONDITIONAL_ACE_TOKEN_NOT
:
668 /* binary logical operators */
669 case CONDITIONAL_ACE_TOKEN_AND
:
670 case CONDITIONAL_ACE_TOKEN_OR
:
672 case CONDITIONAL_ACE_TOKEN_INVALID_OR_PADDING
:
673 /* this is only valid at the end */
674 consumed
= pull_end_padding(tok_data
,
676 j
--; /* don't add this token */
685 if (consumed
+ i
< i
|| consumed
+ i
> data
.length
) {
690 if (j
== alloc_length
) {
692 tokens
= talloc_realloc(program
,
694 struct ace_condition_token
,
696 if (tokens
== NULL
) {
702 program
->tokens
= talloc_realloc(program
,
704 struct ace_condition_token
,
705 program
->length
+ 1);
706 if (program
->tokens
== NULL
) {
711 talloc_free(program
);
716 static bool claim_lookup_internal(
718 struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1
*claim
,
719 struct ace_condition_token
*result
)
721 bool ok
= claim_v1_to_ace_token(mem_ctx
, claim
, result
);
726 static bool resource_claim_lookup(
728 const struct ace_condition_token
*op
,
729 const struct security_descriptor
*sd
,
730 struct ace_condition_token
*result
)
733 * For a @Resource.attr, the claims come from a resource ACE
734 * in the object's SACL. That's why we need a security descriptor.
736 * If there is no matching resource ACE, a NULL result is returned,
737 * which should compare UNKNOWN to anything. The NULL will have the
738 * CONDITIONAL_ACE_FLAG_NULL_MEANS_ERROR flag set if it seems failure
739 * is not simply due to the sought claim not existing. This is useful for
740 * the Exists and Not_Exists operators.
743 struct ace_condition_unicode name
;
745 result
->type
= CONDITIONAL_ACE_SAMBA_RESULT_NULL
;
747 if (op
->type
!= CONDITIONAL_ACE_RESOURCE_ATTRIBUTE
) {
748 /* what are we even doing here? */
749 result
->type
= CONDITIONAL_ACE_SAMBA_RESULT_ERROR
;
753 name
= op
->data
.resource_attr
;
755 if (sd
->sacl
== NULL
) {
756 DBG_NOTICE("Resource attribute ACE '%s' not found, "
757 "because there is no SACL\n",
762 for (i
= 0; i
< sd
->sacl
->num_aces
; i
++) {
763 struct security_ace
*ace
= &sd
->sacl
->aces
[i
];
766 if (ace
->type
!= SEC_ACE_TYPE_SYSTEM_RESOURCE_ATTRIBUTE
) {
769 if (strcasecmp_m(name
.value
,
770 ace
->coda
.claim
.name
) != 0) {
773 /* this is the one */
774 ok
= claim_lookup_internal(mem_ctx
, &ace
->coda
.claim
, result
);
779 DBG_NOTICE("Resource attribute ACE '%s' not found.\n",
785 static bool token_claim_lookup(
787 const struct security_token
*token
,
788 const struct ace_condition_token
*op
,
789 struct ace_condition_token
*result
)
792 * The operator has an attribute name; if there is a claim of
793 * the right type with that name, that is returned as the result.
795 * XXX what happens otherwise? NULL result?
797 struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1
*claims
= NULL
;
800 const struct ace_condition_unicode
*name
= NULL
;
803 result
->type
= CONDITIONAL_ACE_SAMBA_RESULT_NULL
;
806 case CONDITIONAL_ACE_LOCAL_ATTRIBUTE
:
807 claims
= token
->local_claims
;
808 num_claims
= token
->num_local_claims
;
809 name
= &op
->data
.local_attr
;
811 case CONDITIONAL_ACE_USER_ATTRIBUTE
:
812 claims
= token
->user_claims
;
813 num_claims
= token
->num_user_claims
;
814 name
= &op
->data
.user_attr
;
816 case CONDITIONAL_ACE_DEVICE_ATTRIBUTE
:
817 claims
= token
->device_claims
;
818 num_claims
= token
->num_device_claims
;
819 name
= &op
->data
.device_attr
;
822 DBG_WARNING("Conditional ACE claim lookup got bad arg type %u\n",
824 result
->type
= CONDITIONAL_ACE_SAMBA_RESULT_ERROR
;
828 if (num_claims
== 0) {
829 DBG_NOTICE("There are no type %u claims\n", op
->type
);
832 if (claims
== NULL
) {
833 DBG_ERR("Type %u claim list unexpectedly NULL!\n", op
->type
);
834 result
->type
= CONDITIONAL_ACE_SAMBA_RESULT_ERROR
;
838 * Loop backwards: a later claim will override an earlier one with the
841 for (i
= num_claims
- 1; i
< num_claims
; i
--) {
842 if (claims
[i
].name
== NULL
) {
843 DBG_ERR("claim %zu has no name!\n", i
);
846 if (strcasecmp_m(claims
[i
].name
, name
->value
) == 0) {
847 /* this is the one */
848 ok
= claim_lookup_internal(mem_ctx
, &claims
[i
], result
);
852 DBG_NOTICE("Claim not found\n");
859 static bool member_lookup(
860 const struct security_token
*token
,
861 const struct ace_condition_token
*op
,
862 const struct ace_condition_token
*arg
,
863 struct ace_condition_token
*result
)
866 * We need to compare the lists of SIDs in the token with the
867 * SID[s] in the argument. There are 8 combinations of
868 * operation, depending on whether we want to match all or any
869 * of the SIDs, whether we're using the device SIDs or user
870 * SIDs, and whether the operator name starts with "Not_".
872 * _MEMBER_OF User has all operand SIDs
873 * _DEVICE_MEMBER_OF Device has all operand SIDs
874 * _MEMBER_OF_ANY User has one or more operand SIDs
875 * _DEVICE_MEMBER_OF_ANY Device has one or more operand SIDs
877 * NOT_* has the effect of !(the operator without NOT_).
879 * The operand can either be a composite of SIDs or a single SID.
880 * This adds an additional branch.
884 bool it_is_an_any_op
;
885 bool it_is_a_device_op
;
886 bool arg_is_a_single_sid
;
887 struct dom_sid
*sid_array
= NULL
;
888 size_t num_sids
, i
, j
;
889 const struct dom_sid
*sid
= NULL
;
891 result
->type
= CONDITIONAL_ACE_SAMBA_RESULT_BOOL
;
892 result
->data
.result
.value
= ACE_CONDITION_UNKNOWN
;
895 case CONDITIONAL_ACE_TOKEN_SID
:
896 arg_is_a_single_sid
= true;
898 case CONDITIONAL_ACE_TOKEN_COMPOSITE
:
899 arg_is_a_single_sid
= false;
902 DBG_WARNING("Conditional ACE Member_Of got bad arg type %u\n",
908 case CONDITIONAL_ACE_TOKEN_NOT_MEMBER_OF
:
909 case CONDITIONAL_ACE_TOKEN_NOT_MEMBER_OF_ANY
:
910 it_is_a_not_op
= true;
911 it_is_a_device_op
= false;
913 case CONDITIONAL_ACE_TOKEN_NOT_DEVICE_MEMBER_OF_ANY
:
914 case CONDITIONAL_ACE_TOKEN_NOT_DEVICE_MEMBER_OF
:
915 it_is_a_not_op
= true;
916 it_is_a_device_op
= true;
918 case CONDITIONAL_ACE_TOKEN_MEMBER_OF
:
919 case CONDITIONAL_ACE_TOKEN_MEMBER_OF_ANY
:
920 it_is_a_not_op
= false;
921 it_is_a_device_op
= false;
923 case CONDITIONAL_ACE_TOKEN_DEVICE_MEMBER_OF_ANY
:
924 case CONDITIONAL_ACE_TOKEN_DEVICE_MEMBER_OF
:
925 it_is_a_not_op
= false;
926 it_is_a_device_op
= true;
929 DBG_WARNING("Conditional ACE Member_Of got bad op type %u\n",
935 case CONDITIONAL_ACE_TOKEN_NOT_MEMBER_OF_ANY
:
936 case CONDITIONAL_ACE_TOKEN_NOT_DEVICE_MEMBER_OF_ANY
:
937 case CONDITIONAL_ACE_TOKEN_MEMBER_OF_ANY
:
938 case CONDITIONAL_ACE_TOKEN_DEVICE_MEMBER_OF_ANY
:
939 it_is_an_any_op
= true;
942 it_is_an_any_op
= false;
945 if (it_is_a_device_op
) {
946 sid_array
= token
->device_sids
;
947 num_sids
= token
->num_device_sids
;
949 sid_array
= token
->sids
;
950 num_sids
= token
->num_sids
;
953 if (arg_is_a_single_sid
) {
955 * In this case the any and all operations are the
958 sid
= &arg
->data
.sid
.sid
;
960 for (i
= 0; i
< num_sids
; i
++) {
961 match
= dom_sid_equal(sid
, &sid_array
[i
]);
966 if (it_is_a_not_op
) {
970 result
->data
.result
.value
= ACE_CONDITION_TRUE
;
972 result
->data
.result
.value
= ACE_CONDITION_FALSE
;
977 /* This is a composite list (hopefully of SIDs) */
978 if (arg
->data
.composite
.n_members
== 0) {
979 DBG_WARNING("Conditional ACE Member_Of argument is empty\n");
983 for (j
= 0; j
< arg
->data
.composite
.n_members
; j
++) {
984 const struct ace_condition_token
*member
=
985 &arg
->data
.composite
.tokens
[j
];
986 if (member
->type
!= CONDITIONAL_ACE_TOKEN_SID
) {
987 DBG_WARNING("Conditional ACE Member_Of argument contains "
988 "non-sid element [%zu]: %u\n",
992 sid
= &member
->data
.sid
.sid
;
994 for (i
= 0; i
< num_sids
; i
++) {
995 match
= dom_sid_equal(sid
, &sid_array
[i
]);
1000 if (it_is_an_any_op
) {
1002 /* we have matched one SID, which is enough */
1005 } else { /* an all op */
1007 /* failing one is enough */
1013 * Reaching the end of that loop means either:
1014 * 1. it was an ALL op and we never failed to find one, or
1015 * 2. it was an ANY op, and we didn't find one.
1017 match
= !it_is_an_any_op
;
1020 if (it_is_a_not_op
) {
1024 result
->data
.result
.value
= ACE_CONDITION_TRUE
;
1026 result
->data
.result
.value
= ACE_CONDITION_FALSE
;
1033 static bool ternary_value(
1034 const struct ace_condition_token
*arg
,
1035 struct ace_condition_token
*result
)
1038 * Find the truth value of the argument, stored in the result token.
1040 * A return value of false means the operation is invalid, and the
1041 * result is undefined.
1043 if (arg
->type
== CONDITIONAL_ACE_SAMBA_RESULT_BOOL
) {
1049 result
->type
= CONDITIONAL_ACE_SAMBA_RESULT_BOOL
;
1050 result
->data
.result
.value
= ACE_CONDITION_UNKNOWN
;
1052 if (IS_INT_TOKEN(arg
)) {
1054 if (arg
->data
.int64
.value
== 0) {
1055 result
->data
.result
.value
= ACE_CONDITION_FALSE
;
1057 result
->data
.result
.value
= ACE_CONDITION_TRUE
;
1061 if (arg
->type
== CONDITIONAL_ACE_TOKEN_UNICODE
) {
1062 /* empty is false */
1063 if (arg
->data
.unicode
.value
[0] == '\0') {
1064 result
->data
.result
.value
= ACE_CONDITION_FALSE
;
1066 result
->data
.result
.value
= ACE_CONDITION_TRUE
;
1072 * everything else in UNKNOWN. This includes NULL values (i.e. an
1073 * unsuccessful look-up).
1075 result
->data
.result
.value
= ACE_CONDITION_UNKNOWN
;
1079 static bool not_operator(
1080 const struct ace_condition_token
*arg
,
1081 struct ace_condition_token
*result
)
1084 if (IS_LITERAL_TOKEN(arg
)) {
1086 * Logic operators don't work on literals.
1091 ok
= ternary_value(arg
, result
);
1095 if (result
->data
.result
.value
== ACE_CONDITION_FALSE
) {
1096 result
->data
.result
.value
= ACE_CONDITION_TRUE
;
1097 } else if (result
->data
.result
.value
== ACE_CONDITION_TRUE
) {
1098 result
->data
.result
.value
= ACE_CONDITION_FALSE
;
1100 /* unknown stays unknown */
1105 static bool unary_logic_operator(
1106 TALLOC_CTX
*mem_ctx
,
1107 const struct security_token
*token
,
1108 const struct ace_condition_token
*op
,
1109 const struct ace_condition_token
*arg
,
1110 const struct security_descriptor
*sd
,
1111 struct ace_condition_token
*result
)
1116 struct ace_condition_token claim
= {
1117 .type
= CONDITIONAL_ACE_SAMBA_RESULT_ERROR
1119 if (op
->type
== CONDITIONAL_ACE_TOKEN_NOT
) {
1120 return not_operator(arg
, result
);
1122 result
->type
= CONDITIONAL_ACE_SAMBA_RESULT_BOOL
;
1123 result
->data
.result
.value
= ACE_CONDITION_UNKNOWN
;
1126 * Not_Exists and Exists require the same work, except we negate the
1127 * answer in one case. From [MS-DTYP] 2.4.4.17.7:
1129 * If the type of the operand is "Local Attribute"
1130 * If the value is non-null return TRUE
1132 * Else if the type of the operand is "Resource Attribute"
1133 * Return TRUE if value is non-null; FALSE otherwise.
1137 case CONDITIONAL_ACE_LOCAL_ATTRIBUTE
:
1138 ok
= token_claim_lookup(mem_ctx
, token
, arg
, &claim
);
1140 * "not ok" usually means a failure to find the attribute,
1141 * which is the false condition and not an error.
1143 * XXX or do we need an extra flag?
1146 case CONDITIONAL_ACE_RESOURCE_ATTRIBUTE
:
1147 ok
= resource_claim_lookup(mem_ctx
, arg
, sd
, &claim
);
1157 if (claim
.type
!= CONDITIONAL_ACE_SAMBA_RESULT_NULL
) {
1167 if (op
->type
== CONDITIONAL_ACE_TOKEN_NOT_EXISTS
) {
1169 } else if (op
->type
!= CONDITIONAL_ACE_TOKEN_EXISTS
) {
1170 /* should not get here */
1174 result
->data
.result
.value
= found
? ACE_CONDITION_TRUE
: ACE_CONDITION_FALSE
;
1180 static bool binary_logic_operator(
1181 const struct security_token
*token
,
1182 const struct ace_condition_token
*op
,
1183 const struct ace_condition_token
*lhs
,
1184 const struct ace_condition_token
*rhs
,
1185 struct ace_condition_token
*result
)
1187 struct ace_condition_token at
, bt
;
1191 result
->type
= CONDITIONAL_ACE_SAMBA_RESULT_BOOL
;
1192 result
->data
.result
.value
= ACE_CONDITION_UNKNOWN
;
1194 if (IS_LITERAL_TOKEN(lhs
) || IS_LITERAL_TOKEN(rhs
)) {
1196 * Logic operators don't work on literals.
1201 ok
= ternary_value(lhs
, &at
);
1205 ok
= ternary_value(rhs
, &bt
);
1209 a
= at
.data
.result
.value
;
1210 b
= bt
.data
.result
.value
;
1212 if (op
->type
== CONDITIONAL_ACE_TOKEN_AND
) {
1214 * AND true false unknown
1219 * unknown unless BOTH true or EITHER false
1221 if (a
== ACE_CONDITION_TRUE
&&
1222 b
== ACE_CONDITION_TRUE
) {
1223 result
->data
.result
.value
= ACE_CONDITION_TRUE
;
1226 if (a
== ACE_CONDITION_FALSE
||
1227 b
== ACE_CONDITION_FALSE
) {
1228 result
->data
.result
.value
= ACE_CONDITION_FALSE
;
1232 * Neither value is False, so the result is Unknown,
1233 * as set at the start of this function.
1238 * OR true false unknown
1243 * unknown unless EITHER true or BOTH false
1245 if (a
== ACE_CONDITION_TRUE
||
1246 b
== ACE_CONDITION_TRUE
) {
1247 result
->data
.result
.value
= ACE_CONDITION_TRUE
;
1250 if (a
== ACE_CONDITION_FALSE
&&
1251 b
== ACE_CONDITION_FALSE
) {
1252 result
->data
.result
.value
= ACE_CONDITION_FALSE
;
1259 static bool tokens_are_comparable(const struct ace_condition_token
*op
,
1260 const struct ace_condition_token
*lhs
,
1261 const struct ace_condition_token
*rhs
)
1265 * we can't compare different types *unless* they are both
1266 * integers, or one is a bool and the other is an integer 0 or
1267 * 1, and the operator is == or != (or NULL, which for convenience,
1268 * is treated as ==).
1270 //XXX actually it says "literal integers", do we need to check flags?
1271 if (lhs
->type
== rhs
->type
) {
1275 if (IS_INT_TOKEN(lhs
) && IS_INT_TOKEN(rhs
)) {
1276 /* don't block e.g. comparing an int32 to an int64 */
1280 /* is it == or != */
1282 op
->type
!= CONDITIONAL_ACE_TOKEN_EQUAL
&&
1283 op
->type
!= CONDITIONAL_ACE_TOKEN_NOT_EQUAL
) {
1286 /* is one a bool and the other an int? */
1287 if (IS_INT_TOKEN(lhs
) && IS_BOOL_TOKEN(rhs
)) {
1288 n
= lhs
->data
.int64
.value
;
1289 } else if (IS_INT_TOKEN(rhs
) && IS_BOOL_TOKEN(lhs
)) {
1290 n
= rhs
->data
.int64
.value
;
1294 if (n
== 0 || n
== 1) {
1301 static bool cmp_to_result(const struct ace_condition_token
*op
,
1302 struct ace_condition_token
*result
,
1307 case CONDITIONAL_ACE_TOKEN_EQUAL
:
1310 case CONDITIONAL_ACE_TOKEN_NOT_EQUAL
:
1313 case CONDITIONAL_ACE_TOKEN_LESS_THAN
:
1316 case CONDITIONAL_ACE_TOKEN_LESS_OR_EQUAL
:
1319 case CONDITIONAL_ACE_TOKEN_GREATER_THAN
:
1322 case CONDITIONAL_ACE_TOKEN_GREATER_OR_EQUAL
:
1326 result
->data
.result
.value
= ACE_CONDITION_UNKNOWN
;
1329 result
->data
.result
.value
= \
1330 answer
? ACE_CONDITION_TRUE
: ACE_CONDITION_FALSE
;
1336 static bool compare_unicode(const struct ace_condition_token
*op
,
1337 const struct ace_condition_token
*lhs
,
1338 const struct ace_condition_token
*rhs
,
1341 struct ace_condition_unicode a
= lhs
->data
.unicode
;
1342 struct ace_condition_unicode b
= rhs
->data
.unicode
;
1344 * Comparison is case-insensitive UNLESS the claim structure
1345 * has the case-sensitive flag, which is passed through as a
1346 * flag on the token. Usually only the LHS is a claim value,
1347 * but in the event that they both are, we allow either to
1348 * request case-sensitivity.
1350 * For greater than and less than, the sort order is utf-8 order,
1351 * which is not exactly what Windows does, but we don't sort like
1352 * Windows does anywhere else either.
1354 uint8_t flags
= lhs
->flags
| rhs
->flags
;
1355 if (flags
& CLAIM_SECURITY_ATTRIBUTE_VALUE_CASE_SENSITIVE
) {
1356 *cmp
= strcmp(a
.value
, b
.value
);
1358 *cmp
= strcasecmp_m(a
.value
, b
.value
);
1364 static bool compare_bytes(const struct ace_condition_token
*op
,
1365 const struct ace_condition_token
*lhs
,
1366 const struct ace_condition_token
*rhs
,
1369 DATA_BLOB a
= lhs
->data
.bytes
;
1370 DATA_BLOB b
= rhs
->data
.bytes
;
1371 *cmp
= data_blob_cmp(&a
, &b
);
1376 static bool compare_sids(const struct ace_condition_token
*op
,
1377 const struct ace_condition_token
*lhs
,
1378 const struct ace_condition_token
*rhs
,
1381 *cmp
= dom_sid_compare(&lhs
->data
.sid
.sid
,
1382 &rhs
->data
.sid
.sid
);
1387 static bool compare_ints(const struct ace_condition_token
*op
,
1388 const struct ace_condition_token
*lhs
,
1389 const struct ace_condition_token
*rhs
,
1392 int64_t a
= lhs
->data
.int64
.value
;
1393 int64_t b
= rhs
->data
.int64
.value
;
1397 } else if (a
== b
) {
1406 static bool compare_bools(const struct ace_condition_token
*op
,
1407 const struct ace_condition_token
*lhs
,
1408 const struct ace_condition_token
*rhs
,
1412 struct ace_condition_token a
, b
;
1415 if (IS_LITERAL_TOKEN(lhs
)) {
1417 * we can compare a boolean LHS to a literal RHS, but not
1422 ok
= ternary_value(lhs
, &a
);
1426 ok
= ternary_value(rhs
, &b
);
1430 if (a
.data
.result
.value
== ACE_CONDITION_UNKNOWN
||
1431 b
.data
.result
.value
== ACE_CONDITION_UNKNOWN
) {
1436 case CONDITIONAL_ACE_TOKEN_EQUAL
:
1437 case CONDITIONAL_ACE_TOKEN_NOT_EQUAL
:
1438 *cmp
= a
.data
.result
.value
- b
.data
.result
.value
;
1441 /* we are not allowing non-equality comparisons with bools */
1448 static bool simple_relational_operator(const struct ace_condition_token
*op
,
1449 const struct ace_condition_token
*lhs
,
1450 const struct ace_condition_token
*rhs
,
1454 struct composite_sort_context
{
1458 static int composite_sort_cmp(const struct ace_condition_token
*lhs
,
1459 const struct ace_condition_token
*rhs
,
1460 struct composite_sort_context
*ctx
)
1465 * simple_relational_operator uses the operator token only to
1466 * decide whether the comparison is allowed for the type. In
1467 * particular, boolean result and composite arguments can only
1468 * be used with equality operators. We want those to fail (we
1469 * should not see them here, remembering that claim booleans
1470 * become composite integers), so we use a non-equality op.
1472 static const struct ace_condition_token op
= {
1473 .type
= CONDITIONAL_ACE_TOKEN_LESS_THAN
1476 ok
= simple_relational_operator(&op
, lhs
, rhs
, &cmp
);
1481 * This sort isn't going to work out, but the sort function
1482 * will only find out at the end.
1490 * Return a sorted copy of the composite tokens array.
1492 * The copy is shallow, so the actual string pointers are the same, which is
1493 * fine for the purposes of comparison.
1496 static struct ace_condition_token
*composite_sorted_copy(
1497 TALLOC_CTX
*mem_ctx
,
1498 const struct ace_condition_composite
*c
,
1499 bool case_sensitive
)
1501 struct ace_condition_token
*copy
= NULL
;
1504 struct composite_sort_context sort_ctx
= {
1509 * Case sensitivity is a bit tricky. Each token can have a flag saying
1510 * it should be sorted case-sensitively and when comparing two tokens,
1511 * we should respect this flag on either side. The flag can only come
1512 * from claims (including resource attribute ACEs), and as there is only
1513 * one flag per claim, it must apply the same to all members (in fact we
1514 * don't set it on the members, only the composite). So to be sure we
1515 * sort in the way we want, we might need to set the flag on all the
1516 * members of the copy *before* sorting it.
1518 * When it comes to comparing two composites, we want to be
1519 * case-sensitive if either side has the flag. This can have odd
1520 * effects. Think of these RA claims:
1522 * (RA;;;;;WD;("foo",TS,0,"a","A"))
1523 * (RA;;;;;WD;("bar",TS,2,"a","A")) <-- 2 is the case-sensitive flag
1524 * (RA;;;;;WD;("baz",TS,0,"a"))
1526 * (@Resource.foo == @Resource.bar) is true
1527 * (@Resource.bar == @Resource.foo) is true
1528 * (@Resource.bar == @Resource.bar) is true
1529 * (@Resource.foo == @Resource.foo) is an error (duplicate values on LHS)
1530 * (@Resource.baz == @Resource.foo) is true (RHS case-folds down)
1531 * (@Resource.baz == @Resource.bar) is false
1532 * (@Resource.bar == {"A", "a"}) is true
1533 * (@Resource.baz == {"A", "a"}) is true
1534 * (@Resource.foo == {"A", "a"}) is an error
1536 copy
= talloc_array(mem_ctx
, struct ace_condition_token
, c
->n_members
);
1540 memcpy(copy
, c
->tokens
, sizeof(struct ace_condition_token
) * c
->n_members
);
1542 if (case_sensitive
) {
1543 for (i
= 0; i
< c
->n_members
; i
++) {
1544 c
->tokens
[i
].flags
|= CLAIM_SECURITY_ATTRIBUTE_VALUE_CASE_SENSITIVE
;
1548 ok
= stable_sort_talloc_r(mem_ctx
,
1551 sizeof(struct ace_condition_token
),
1552 (samba_compare_with_context_fn_t
)composite_sort_cmp
,
1555 if (!ok
|| sort_ctx
.failed
) {
1556 DBG_NOTICE("composite sort of %"PRIu32
" members failed\n",
1566 * This is a helper for compare composites.
1568 static bool compare_composites_via_sort(const struct ace_condition_token
*lhs
,
1569 const struct ace_condition_token
*rhs
,
1572 const struct ace_condition_composite
*lc
= &lhs
->data
.composite
;
1573 const struct ace_condition_composite
*rc
= &rhs
->data
.composite
;
1575 TALLOC_CTX
*tmp_ctx
= NULL
;
1578 bool case_sensitive
, rhs_case_sensitive
;
1580 struct ace_condition_token
*ltok
= lc
->tokens
;
1581 struct ace_condition_token
*rtok
= rc
->tokens
;
1582 static const struct ace_condition_token eq
= {
1583 .type
= CONDITIONAL_ACE_TOKEN_EQUAL
1586 if (lc
->n_members
== 0 ||
1587 rc
->n_members
< lc
->n_members
) {
1588 /* we should not have got this far */
1592 tmp_ctx
= talloc_new(NULL
);
1593 if (tmp_ctx
== NULL
) {
1597 case_sensitive
= lhs
->flags
& CLAIM_SECURITY_ATTRIBUTE_VALUE_CASE_SENSITIVE
;
1598 rhs_case_sensitive
= rhs
->flags
& CLAIM_SECURITY_ATTRIBUTE_VALUE_CASE_SENSITIVE
;
1599 rhs_sorted
= rhs
->flags
& CLAIM_SECURITY_ATTRIBUTE_UNIQUE_AND_SORTED
;
1601 if (lc
->tokens
[0].type
!= CONDITIONAL_ACE_TOKEN_UNICODE
) {
1603 * All LHS tokens are the same type (because it is a
1604 * claim), and that type is not one that cares about
1605 * case, so nor do we.
1607 case_sensitive
= false;
1608 } else if (case_sensitive
== rhs_case_sensitive
) {
1609 /* phew, no extra work */
1610 } else if (case_sensitive
) {
1611 /* trigger a sorted copy */
1613 } else if (rhs_case_sensitive
) {
1615 * Do we need to rescan for uniqueness, given the new
1616 * comparison function? No! The strings were already
1617 * unique in the looser comparison, and now they can
1618 * only be more so. The number of unique values can't
1619 * change, just their order.
1621 case_sensitive
= true;
1622 ltok
= composite_sorted_copy(tmp_ctx
, lc
, case_sensitive
);
1624 DBG_WARNING("sort of LHS failed\n");
1631 * we need an RHS sorted copy (it's a literal, or
1632 * there was a case sensitivity disagreement).
1634 rtok
= composite_sorted_copy(tmp_ctx
, rc
, case_sensitive
);
1636 DBG_WARNING("sort of RHS failed\n");
1641 * Each member of LHS must match one or more members of RHS.
1642 * Each member of RHS must match at least one of LHS.
1644 * If they are the same length we can compare directly, so let's get
1645 * rid of duplicates in RHS. This can only happen with literal
1648 if (rc
->n_members
> lc
->n_members
) {
1650 for (i
= 1; i
< rc
->n_members
; i
++) {
1651 ok
= simple_relational_operator(&eq
,
1658 if (cmp_pair
== 0) {
1662 rtok
[i
- gap
] = rtok
[i
];
1665 if (rc
->n_members
- lc
->n_members
!= gap
) {
1667 * There were too many or too few duplicates to account
1668 * for the difference, and no further comparison is
1675 * OK, now we know LHS and RHS are the same length and sorted in the
1676 * same way, so we can just iterate over them and check each pair.
1679 for (i
= 0; i
< lc
->n_members
; i
++) {
1680 ok
= simple_relational_operator(&eq
,
1687 if (cmp_pair
!= 0) {
1695 TALLOC_FREE(tmp_ctx
);
1698 TALLOC_FREE(tmp_ctx
);
1703 static bool composite_is_comparable(const struct ace_condition_token
*tok
,
1704 const struct ace_condition_token
*comp
)
1707 * Are all members of the composite comparable to the token?
1710 const struct ace_condition_composite
*rc
= &comp
->data
.composite
;
1711 size_t n
= rc
->n_members
;
1713 if ((comp
->flags
& CLAIM_SECURITY_ATTRIBUTE_UNIQUE_AND_SORTED
) &&
1716 * all members are known to be the same type, so we
1717 * can just check one.
1722 for (i
= 0; i
< n
; i
++) {
1723 if (! tokens_are_comparable(NULL
,
1726 DBG_NOTICE("token type %u != composite type %u\n",
1727 tok
->type
, rc
->tokens
[i
].type
);
1735 static bool compare_composites(const struct ace_condition_token
*op
,
1736 const struct ace_condition_token
*lhs
,
1737 const struct ace_condition_token
*rhs
,
1741 * This is for comparing multivalued sets, which includes
1742 * conditional ACE composites and claim sets. Because these
1743 * are sets, there are no < and > operations, just equality or
1746 * Claims are true sets, while composites are multisets --
1747 * duplicate values are allowed -- but these are reduced to
1748 * sets in evaluation, and the number of duplicates has no
1749 * effect in comparisons. Resource attribute ACEs live in an
1750 * intermediate state -- they can contain duplicates on the
1751 * wire and as ACE structures, but as soon as they are
1752 * evaluated as claims their values must be unique. Windows
1753 * will treat RA ACEs with duplicate values as not existing,
1754 * rather than as UNKNOWN (This is significant for the Exists
1755 * operator). Claims can have a case-sensitive flags set,
1756 * meaning they must be compared case-sensitively.
1758 * Some good news is that the LHS of a comparison must always
1759 * be a claim. That means we can assume it has unique values
1760 * when it comes to pairwise comparisons. Using the magic of
1761 * flags, we try to check this only once per claim.
1763 * Conditional ACE composites, which can have duplicates (and
1764 * mixed types), can only be on the RHS.
1768 * {a, b} vs {a, b} equal
1770 * {a, b} vs {b, a} equal
1771 * {a, b} vs {a, c} not equal
1772 * {a, b} vs {a, a, b} equal
1773 * {b, a} vs {a, b, a} equal
1774 * {a, b} vs {a, a, b, c} not equal
1775 * {a, b, a} vs {a, b} should not happen, error
1776 * {a, b, a} vs {a, b, a} should not happen, error
1779 * {1, 2} vs {1, "2"} error
1780 * {1, "2"} vs {1, "2"} should not happen, error
1782 * case sensitivity (*{ }* indicates case-sensitive flag):
1784 * {"a", "b"} vs {"a", "B"} equal
1785 * {"a", "b"} vs *{"a", "B"}* not equal
1786 * *{"a", "b"}* vs {"a", "B"} not equal
1787 * *{"a", "A"}* vs {"a", "A"} equal (if RHS is composite)
1788 * {"a", "A"} vs *{"a", "A"}* impossible (LHS is not unique)
1789 * *{"a"}* vs {"a", "A"} not equal
1791 * The naive approach is of course O(n * m) with an additional O(n²)
1792 * if the LHS values are not known to be unique (that is, in resource
1793 * attribute claims). We want to avoid that with big sets.
1795 const struct ace_condition_composite
*lc
= &lhs
->data
.composite
;
1796 const struct ace_condition_composite
*rc
= &rhs
->data
.composite
;
1799 if (!(lhs
->flags
& CLAIM_SECURITY_ATTRIBUTE_UNIQUE_AND_SORTED
)) {
1801 * The LHS needs to be a claim, and it should have gone
1802 * through claim_v1_check_and_sort() to get here.
1808 /* if one or both are empty, the answer is easy */
1809 if (lc
->n_members
== 0) {
1810 if (rc
->n_members
== 0) {
1817 if (rc
->n_members
== 0) {
1823 * LHS must be a claim, so it must be unique, so if there are
1824 * fewer members on the RHS, we know they can't be equal.
1826 * If you think about it too much, you might think this is
1827 * affected by case sensitivity, but it isn't. One side can be
1828 * infected by case-sensitivity by the other, but that can't
1829 * shrink the number of elements on the RHS -- it can only
1830 * make a literal {"a", "A"} have effective length 2 rather
1833 * On the other hand, if the RHS is case sensitive, it must be
1834 * a claim and unique in its own terms, and its finer-grained
1835 * distinctions can't collapse members of the case sensitive
1838 if (lc
->n_members
> rc
->n_members
) {
1840 return composite_is_comparable(&lc
->tokens
[0], rhs
);
1844 * It *could* be that RHS is also unique and we know it. In that
1845 * case we can short circuit if RHS has more members. This is
1846 * the case when both sides are claims.
1848 * This is also not affected by case-senstivity.
1850 if (lc
->n_members
< rc
->n_members
&&
1851 (rhs
->flags
& CLAIM_SECURITY_ATTRIBUTE_UNIQUE_AND_SORTED
)) {
1853 return composite_is_comparable(&lc
->tokens
[0], rhs
);
1856 ok
= compare_composites_via_sort(lhs
, rhs
, cmp
);
1864 static bool simple_relational_operator(const struct ace_condition_token
*op
,
1865 const struct ace_condition_token
*lhs
,
1866 const struct ace_condition_token
*rhs
,
1870 if (lhs
->type
!= rhs
->type
) {
1871 if (! tokens_are_comparable(op
, lhs
, rhs
)) {
1875 switch (lhs
->type
) {
1876 case CONDITIONAL_ACE_TOKEN_INT8
:
1877 case CONDITIONAL_ACE_TOKEN_INT16
:
1878 case CONDITIONAL_ACE_TOKEN_INT32
:
1879 case CONDITIONAL_ACE_TOKEN_INT64
:
1880 if (rhs
->type
== CONDITIONAL_ACE_SAMBA_RESULT_BOOL
) {
1881 return compare_bools(op
, lhs
, rhs
, cmp
);
1883 return compare_ints(op
, lhs
, rhs
, cmp
);
1884 case CONDITIONAL_ACE_SAMBA_RESULT_BOOL
:
1885 return compare_bools(op
, lhs
, rhs
, cmp
);
1886 case CONDITIONAL_ACE_TOKEN_UNICODE
:
1887 return compare_unicode(op
, lhs
, rhs
, cmp
);
1888 case CONDITIONAL_ACE_TOKEN_OCTET_STRING
:
1889 return compare_bytes(op
, lhs
, rhs
, cmp
);
1890 case CONDITIONAL_ACE_TOKEN_SID
:
1891 return compare_sids(op
, lhs
, rhs
, cmp
);
1892 case CONDITIONAL_ACE_TOKEN_COMPOSITE
:
1893 return compare_composites(op
, lhs
, rhs
, cmp
);
1894 case CONDITIONAL_ACE_SAMBA_RESULT_NULL
:
1895 /* leave the result unknown */
1898 DBG_ERR("did not expect ace type %u\n", lhs
->type
);
1906 static bool find_in_composite(const struct ace_condition_token
*tok
,
1907 struct ace_condition_composite candidates
,
1913 const struct ace_condition_token equals
= {
1914 .type
= CONDITIONAL_ACE_TOKEN_EQUAL
1919 for (i
= 0; i
< candidates
.n_members
; i
++) {
1920 ok
= simple_relational_operator(&equals
,
1922 &candidates
.tokens
[i
],
1936 static bool contains_operator(const struct ace_condition_token
*lhs
,
1937 const struct ace_condition_token
*rhs
,
1943 const struct ace_condition_token equals
= {
1944 .type
= CONDITIONAL_ACE_TOKEN_EQUAL
1948 * All the required objects must be identical to something in
1949 * candidates. But what do we mean by *identical*? We'll use
1950 * the equality operator to decide that.
1952 * Both the lhs or rhs can be solitary objects or composites.
1953 * This makes it a bit fiddlier.
1955 * NOTE: this operator does not take advantage of the
1956 * CLAIM_SECURITY_ATTRIBUTE_UNIQUE_AND_SORTED flag. It could, but it
1959 if (lhs
->type
== CONDITIONAL_ACE_TOKEN_COMPOSITE
) {
1960 struct ace_condition_composite candidates
= lhs
->data
.composite
;
1961 struct ace_condition_composite required
;
1962 if (rhs
->type
!= CONDITIONAL_ACE_TOKEN_COMPOSITE
) {
1963 return find_in_composite(rhs
, candidates
, answer
);
1965 required
= rhs
->data
.composite
;
1966 if (required
.n_members
== 0) {
1969 for (i
= 0; i
< required
.n_members
; i
++) {
1970 const struct ace_condition_token
*t
= &required
.tokens
[i
];
1971 ok
= find_in_composite(t
, candidates
, answer
);
1977 * one required item was not there,
1983 /* all required items are there, *answer will be true */
1986 /* LHS is a single item */
1987 if (rhs
->type
== CONDITIONAL_ACE_TOKEN_COMPOSITE
) {
1989 * There could be more than one RHS member that is
1990 * equal to the single LHS value, so it doesn't help
1991 * to compare lengths or anything.
1993 struct ace_condition_composite required
= rhs
->data
.composite
;
1994 if (required
.n_members
== 0) {
1997 for (i
= 0; i
< required
.n_members
; i
++) {
1998 ok
= simple_relational_operator(&equals
,
2000 &required
.tokens
[i
],
2007 * one required item was not there,
2017 /* LHS and RHS are both single */
2018 ok
= simple_relational_operator(&equals
,
2025 *answer
= (cmp
== 0);
2030 static bool any_of_operator(const struct ace_condition_token
*lhs
,
2031 const struct ace_condition_token
*rhs
,
2037 const struct ace_condition_token equals
= {
2038 .type
= CONDITIONAL_ACE_TOKEN_EQUAL
2042 * There has to be *some* overlap between the LHS and RHS.
2043 * Both sides can be solitary objects or composites.
2045 * We can exploit this symmetry.
2047 if (lhs
->type
!= CONDITIONAL_ACE_TOKEN_COMPOSITE
) {
2048 const struct ace_condition_token
*tmp
= lhs
;
2052 if (lhs
->type
!= CONDITIONAL_ACE_TOKEN_COMPOSITE
) {
2054 ok
= simple_relational_operator(&equals
,
2061 *answer
= (cmp
== 0);
2064 if (rhs
->type
!= CONDITIONAL_ACE_TOKEN_COMPOSITE
) {
2065 return find_in_composite(rhs
, lhs
->data
.composite
, answer
);
2067 /* both are composites */
2068 if (lhs
->data
.composite
.n_members
== 0) {
2071 for (i
= 0; i
< lhs
->data
.composite
.n_members
; i
++) {
2072 ok
= find_in_composite(&lhs
->data
.composite
.tokens
[i
],
2073 rhs
->data
.composite
,
2079 /* We have found one match, which is enough. */
2087 static bool composite_relational_operator(const struct ace_condition_token
*op
,
2088 const struct ace_condition_token
*lhs
,
2089 const struct ace_condition_token
*rhs
,
2090 struct ace_condition_token
*result
)
2094 case CONDITIONAL_ACE_TOKEN_CONTAINS
:
2095 case CONDITIONAL_ACE_TOKEN_NOT_CONTAINS
:
2096 ok
= contains_operator(lhs
, rhs
, &answer
);
2098 case CONDITIONAL_ACE_TOKEN_ANY_OF
:
2099 case CONDITIONAL_ACE_TOKEN_NOT_ANY_OF
:
2100 ok
= any_of_operator(lhs
, rhs
, &answer
);
2109 /* negate the NOTs */
2110 if (op
->type
== CONDITIONAL_ACE_TOKEN_NOT_CONTAINS
||
2111 op
->type
== CONDITIONAL_ACE_TOKEN_NOT_ANY_OF
)
2117 result
->data
.result
.value
= ACE_CONDITION_TRUE
;
2119 result
->data
.result
.value
= ACE_CONDITION_FALSE
;
2125 static bool relational_operator(
2126 const struct security_token
*token
,
2127 const struct ace_condition_token
*op
,
2128 const struct ace_condition_token
*lhs
,
2129 const struct ace_condition_token
*rhs
,
2130 struct ace_condition_token
*result
)
2134 result
->type
= CONDITIONAL_ACE_SAMBA_RESULT_BOOL
;
2135 result
->data
.result
.value
= ACE_CONDITION_UNKNOWN
;
2137 if ((lhs
->flags
& CONDITIONAL_ACE_FLAG_TOKEN_FROM_ATTR
) == 0) {
2138 /* LHS was not derived from an attribute */
2143 * This first nested switch is ensuring that >, >=, <, <= are
2144 * not being tried on tokens that are not numbers, strings, or
2145 * octet strings. Equality operators are available for all types.
2147 switch (lhs
->type
) {
2148 case CONDITIONAL_ACE_TOKEN_INT8
:
2149 case CONDITIONAL_ACE_TOKEN_INT16
:
2150 case CONDITIONAL_ACE_TOKEN_INT32
:
2151 case CONDITIONAL_ACE_TOKEN_INT64
:
2152 case CONDITIONAL_ACE_TOKEN_UNICODE
:
2153 case CONDITIONAL_ACE_TOKEN_OCTET_STRING
:
2157 case CONDITIONAL_ACE_TOKEN_LESS_THAN
:
2158 case CONDITIONAL_ACE_TOKEN_LESS_OR_EQUAL
:
2159 case CONDITIONAL_ACE_TOKEN_GREATER_THAN
:
2160 case CONDITIONAL_ACE_TOKEN_GREATER_OR_EQUAL
:
2168 * Dispatch according to operator type.
2171 case CONDITIONAL_ACE_TOKEN_EQUAL
:
2172 case CONDITIONAL_ACE_TOKEN_NOT_EQUAL
:
2173 case CONDITIONAL_ACE_TOKEN_LESS_THAN
:
2174 case CONDITIONAL_ACE_TOKEN_LESS_OR_EQUAL
:
2175 case CONDITIONAL_ACE_TOKEN_GREATER_THAN
:
2176 case CONDITIONAL_ACE_TOKEN_GREATER_OR_EQUAL
:
2177 ok
= simple_relational_operator(op
,
2182 ok
= cmp_to_result(op
, result
, cmp
);
2186 case CONDITIONAL_ACE_TOKEN_CONTAINS
:
2187 case CONDITIONAL_ACE_TOKEN_ANY_OF
:
2188 case CONDITIONAL_ACE_TOKEN_NOT_CONTAINS
:
2189 case CONDITIONAL_ACE_TOKEN_NOT_ANY_OF
:
2190 return composite_relational_operator(op
,
2200 int run_conditional_ace(TALLOC_CTX
*mem_ctx
,
2201 const struct security_token
*token
,
2202 struct ace_condition_script
*program
,
2203 const struct security_descriptor
*sd
)
2207 struct ace_condition_token
*lhs
= NULL
;
2208 struct ace_condition_token
*rhs
= NULL
;
2209 struct ace_condition_token result
= {};
2210 struct ace_condition_token
*stack
= NULL
;
2214 * When interpreting the program we will need a stack, which in the
2215 * very worst case can be as deep as the program is long.
2217 stack
= talloc_array(mem_ctx
,
2218 struct ace_condition_token
,
2219 program
->length
+ 1);
2220 if (stack
== NULL
) {
2224 for (i
= 0; i
< program
->length
; i
++) {
2225 struct ace_condition_token
*tok
= &program
->tokens
[i
];
2226 switch (tok
->type
) {
2227 case CONDITIONAL_ACE_TOKEN_INT8
:
2228 case CONDITIONAL_ACE_TOKEN_INT16
:
2229 case CONDITIONAL_ACE_TOKEN_INT32
:
2230 case CONDITIONAL_ACE_TOKEN_INT64
:
2231 case CONDITIONAL_ACE_TOKEN_UNICODE
:
2232 case CONDITIONAL_ACE_TOKEN_OCTET_STRING
:
2233 case CONDITIONAL_ACE_TOKEN_SID
:
2234 case CONDITIONAL_ACE_TOKEN_COMPOSITE
:
2235 /* just plonk these literals on the stack */
2236 stack
[depth
] = *tok
;
2240 case CONDITIONAL_ACE_LOCAL_ATTRIBUTE
:
2241 case CONDITIONAL_ACE_USER_ATTRIBUTE
:
2242 case CONDITIONAL_ACE_DEVICE_ATTRIBUTE
:
2243 ok
= token_claim_lookup(mem_ctx
, token
, tok
, &result
);
2247 stack
[depth
] = result
;
2251 case CONDITIONAL_ACE_RESOURCE_ATTRIBUTE
:
2252 ok
= resource_claim_lookup(mem_ctx
,
2259 stack
[depth
] = result
;
2263 case CONDITIONAL_ACE_TOKEN_MEMBER_OF
:
2264 case CONDITIONAL_ACE_TOKEN_DEVICE_MEMBER_OF
:
2265 case CONDITIONAL_ACE_TOKEN_MEMBER_OF_ANY
:
2266 case CONDITIONAL_ACE_TOKEN_DEVICE_MEMBER_OF_ANY
:
2267 case CONDITIONAL_ACE_TOKEN_NOT_MEMBER_OF
:
2268 case CONDITIONAL_ACE_TOKEN_NOT_DEVICE_MEMBER_OF
:
2269 case CONDITIONAL_ACE_TOKEN_NOT_MEMBER_OF_ANY
:
2270 case CONDITIONAL_ACE_TOKEN_NOT_DEVICE_MEMBER_OF_ANY
:
2275 lhs
= &stack
[depth
];
2276 ok
= member_lookup(token
, tok
, lhs
, &result
);
2280 stack
[depth
] = result
;
2283 /* binary relational operators */
2284 case CONDITIONAL_ACE_TOKEN_EQUAL
:
2285 case CONDITIONAL_ACE_TOKEN_NOT_EQUAL
:
2286 case CONDITIONAL_ACE_TOKEN_LESS_THAN
:
2287 case CONDITIONAL_ACE_TOKEN_LESS_OR_EQUAL
:
2288 case CONDITIONAL_ACE_TOKEN_GREATER_THAN
:
2289 case CONDITIONAL_ACE_TOKEN_GREATER_OR_EQUAL
:
2290 case CONDITIONAL_ACE_TOKEN_CONTAINS
:
2291 case CONDITIONAL_ACE_TOKEN_ANY_OF
:
2292 case CONDITIONAL_ACE_TOKEN_NOT_CONTAINS
:
2293 case CONDITIONAL_ACE_TOKEN_NOT_ANY_OF
:
2298 rhs
= &stack
[depth
];
2300 lhs
= &stack
[depth
];
2301 ok
= relational_operator(token
, tok
, lhs
, rhs
, &result
);
2305 stack
[depth
] = result
;
2308 /* unary logical operators */
2309 case CONDITIONAL_ACE_TOKEN_EXISTS
:
2310 case CONDITIONAL_ACE_TOKEN_NOT_EXISTS
:
2311 case CONDITIONAL_ACE_TOKEN_NOT
:
2316 lhs
= &stack
[depth
];
2317 ok
= unary_logic_operator(mem_ctx
, token
, tok
, lhs
, sd
, &result
);
2321 stack
[depth
] = result
;
2324 /* binary logical operators */
2325 case CONDITIONAL_ACE_TOKEN_AND
:
2326 case CONDITIONAL_ACE_TOKEN_OR
:
2331 rhs
= &stack
[depth
];
2333 lhs
= &stack
[depth
];
2334 ok
= binary_logic_operator(token
, tok
, lhs
, rhs
, &result
);
2338 stack
[depth
] = result
;
2346 * The evaluation should have left a single result value (true, false,
2347 * or unknown) on the stack. If not, the expression was malformed.
2353 if (result
.type
!= CONDITIONAL_ACE_SAMBA_RESULT_BOOL
) {
2357 return result
.data
.result
.value
;
2361 * the result of an error is always UNKNOWN, which should be
2362 * interpreted pessimistically, not allowing access.
2365 return ACE_CONDITION_UNKNOWN
;
2369 /** access_check_conditional_ace()
2371 * Run the conditional ACE from the blob form. Return false if it is
2372 * not a valid conditional ACE, true if it is, even if there is some
2373 * other error in running it. The *result parameter is set to
2374 * ACE_CONDITION_FALSE, ACE_CONDITION_TRUE, or ACE_CONDITION_UNKNOWN.
2376 * ACE_CONDITION_UNKNOWN should be treated pessimistically, as if it were
2377 * TRUE for deny ACEs, and FALSE for allow ACEs.
2379 * @param[in] ace - the ACE being processed.
2380 * @param[in] token - the security token the ACE is processing.
2381 * @param[out] result - a ternary result value.
2383 * @return true if it is a valid conditional ACE.
2386 bool access_check_conditional_ace(const struct security_ace
*ace
,
2387 const struct security_token
*token
,
2388 const struct security_descriptor
*sd
,
2391 TALLOC_CTX
*tmp_ctx
= talloc_new(NULL
);
2392 struct ace_condition_script
*program
= NULL
;
2393 program
= parse_conditional_ace(tmp_ctx
, ace
->coda
.conditions
);
2394 if (program
== NULL
) {
2395 *result
= ACE_CONDITION_UNKNOWN
;
2396 TALLOC_FREE(tmp_ctx
);
2400 *result
= run_conditional_ace(tmp_ctx
, token
, program
, sd
);
2402 TALLOC_FREE(tmp_ctx
);
2407 bool conditional_ace_encode_binary(TALLOC_CTX
*mem_ctx
,
2408 struct ace_condition_script
*program
,
2411 size_t i
, j
, alloc_size
, required_size
;
2412 uint8_t *data
= NULL
;
2413 uint8_t *new_data
= NULL
;
2414 *dest
= (DATA_BLOB
){NULL
, 0};
2416 alloc_size
= CONDITIONAL_ACE_MAX_LENGTH
;
2417 data
= talloc_array(mem_ctx
,
2430 for (i
= 0; i
< program
->length
; i
++) {
2431 struct ace_condition_token
*tok
= &program
->tokens
[i
];
2435 * In all cases we write the token type byte.
2437 data
[j
] = tok
->type
;
2439 if (j
>= alloc_size
) {
2440 DBG_ERR("program exceeds %zu bytes\n", alloc_size
);
2444 switch (tok
->type
) {
2445 case CONDITIONAL_ACE_TOKEN_MEMBER_OF
:
2446 case CONDITIONAL_ACE_TOKEN_DEVICE_MEMBER_OF
:
2447 case CONDITIONAL_ACE_TOKEN_MEMBER_OF_ANY
:
2448 case CONDITIONAL_ACE_TOKEN_DEVICE_MEMBER_OF_ANY
:
2449 case CONDITIONAL_ACE_TOKEN_NOT_MEMBER_OF
:
2450 case CONDITIONAL_ACE_TOKEN_NOT_DEVICE_MEMBER_OF
:
2451 case CONDITIONAL_ACE_TOKEN_NOT_MEMBER_OF_ANY
:
2452 case CONDITIONAL_ACE_TOKEN_NOT_DEVICE_MEMBER_OF_ANY
:
2453 case CONDITIONAL_ACE_TOKEN_EQUAL
:
2454 case CONDITIONAL_ACE_TOKEN_NOT_EQUAL
:
2455 case CONDITIONAL_ACE_TOKEN_LESS_THAN
:
2456 case CONDITIONAL_ACE_TOKEN_LESS_OR_EQUAL
:
2457 case CONDITIONAL_ACE_TOKEN_GREATER_THAN
:
2458 case CONDITIONAL_ACE_TOKEN_GREATER_OR_EQUAL
:
2459 case CONDITIONAL_ACE_TOKEN_CONTAINS
:
2460 case CONDITIONAL_ACE_TOKEN_ANY_OF
:
2461 case CONDITIONAL_ACE_TOKEN_NOT_CONTAINS
:
2462 case CONDITIONAL_ACE_TOKEN_NOT_ANY_OF
:
2463 case CONDITIONAL_ACE_TOKEN_EXISTS
:
2464 case CONDITIONAL_ACE_TOKEN_NOT_EXISTS
:
2465 case CONDITIONAL_ACE_TOKEN_NOT
:
2466 case CONDITIONAL_ACE_TOKEN_AND
:
2467 case CONDITIONAL_ACE_TOKEN_OR
:
2469 * All of these are simple operators that operate on
2470 * the stack. We have already added the tok->type and
2471 * there's nothing else to do.
2475 case CONDITIONAL_ACE_TOKEN_INT8
:
2476 case CONDITIONAL_ACE_TOKEN_INT16
:
2477 case CONDITIONAL_ACE_TOKEN_INT32
:
2478 case CONDITIONAL_ACE_TOKEN_INT64
:
2479 ok
= check_integer_range(tok
);
2483 consumed
= push_integer(data
+ j
,
2487 case CONDITIONAL_ACE_LOCAL_ATTRIBUTE
:
2488 case CONDITIONAL_ACE_USER_ATTRIBUTE
:
2489 case CONDITIONAL_ACE_RESOURCE_ATTRIBUTE
:
2490 case CONDITIONAL_ACE_DEVICE_ATTRIBUTE
:
2491 case CONDITIONAL_ACE_TOKEN_UNICODE
:
2492 consumed
= push_unicode(data
+ j
,
2494 &tok
->data
.unicode
);
2496 case CONDITIONAL_ACE_TOKEN_OCTET_STRING
:
2497 consumed
= push_bytes(data
+ j
,
2501 case CONDITIONAL_ACE_TOKEN_SID
:
2502 consumed
= push_sid(data
+ j
,
2506 case CONDITIONAL_ACE_TOKEN_COMPOSITE
:
2507 consumed
= push_composite(data
+ j
,
2509 &tok
->data
.composite
);
2513 DBG_ERR("unknown token 0x%02x at position %zu\n",
2517 if (consumed
== -1) {
2518 DBG_ERR("program exceeds %zu bytes\n", alloc_size
);
2522 if (j
>= alloc_size
) {
2523 DBG_ERR("program exceeds %zu bytes\n", alloc_size
);
2527 /* align to a 4 byte boundary */
2528 required_size
= (j
+ 3) & ~((size_t)3);
2529 if (required_size
> alloc_size
) {
2530 DBG_ERR("program exceeds %zu bytes\n", alloc_size
);
2533 while (j
< required_size
) {
2537 new_data
= talloc_realloc(mem_ctx
,
2541 if (new_data
== NULL
) {
2546 (*dest
).data
= data
;