Line data Source code
1 : /*
2 : * Unix SMB implementation.
3 : * Functions for understanding conditional ACEs
4 : *
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.
9 : *
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.
14 : *
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/>.
17 : */
18 :
19 : #include "replace.h"
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 :
32 : /*
33 : * Conditional ACE logic truth tables.
34 : *
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.
39 : *
40 : * AND true false unknown
41 : * true T F ?
42 : * false F F F
43 : * unknown ? F ?
44 : *
45 : * OR true false unknown
46 : * true T T T
47 : * false T F ?
48 : * unknown T ? ?
49 : *
50 : * NOT
51 : * true F
52 : * false T
53 : * unknown ?
54 : *
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).
58 : *
59 : * What counts as unknown
60 : *
61 : * - NULL attributes.
62 : * - certain comparisons between incompatible types
63 : *
64 : * What counts as false
65 : *
66 : * - zero
67 : * - empty strings
68 : *
69 : * An error means the entire expression is unknown.
70 : */
71 :
72 :
73 792 : static bool check_integer_range(const struct ace_condition_token *tok)
74 : {
75 792 : int64_t val = tok->data.int64.value;
76 792 : switch (tok->type) {
77 0 : case CONDITIONAL_ACE_TOKEN_INT8:
78 0 : if (val < -128 || val > 127) {
79 0 : return false;
80 : }
81 0 : break;
82 0 : case CONDITIONAL_ACE_TOKEN_INT16:
83 0 : if (val < INT16_MIN || val > INT16_MAX) {
84 0 : return false;
85 : }
86 0 : break;
87 0 : case CONDITIONAL_ACE_TOKEN_INT32:
88 0 : if (val < INT32_MIN || val > INT32_MAX) {
89 0 : return false;
90 : }
91 0 : break;
92 180 : case CONDITIONAL_ACE_TOKEN_INT64:
93 : /* val has these limits naturally */
94 180 : break;
95 0 : default:
96 0 : return false;
97 : }
98 :
99 792 : if (tok->data.int64.base != CONDITIONAL_ACE_INT_BASE_8 &&
100 792 : tok->data.int64.base != CONDITIONAL_ACE_INT_BASE_10 &&
101 0 : tok->data.int64.base != CONDITIONAL_ACE_INT_BASE_16) {
102 0 : return false;
103 : }
104 792 : if (tok->data.int64.sign != CONDITIONAL_ACE_INT_SIGN_POSITIVE &&
105 792 : tok->data.int64.sign != CONDITIONAL_ACE_INT_SIGN_NEGATIVE &&
106 180 : tok->data.int64.sign != CONDITIONAL_ACE_INT_SIGN_NONE) {
107 0 : return false;
108 : }
109 180 : return true;
110 : }
111 :
112 :
113 156 : static ssize_t pull_integer(TALLOC_CTX *mem_ctx,
114 : uint8_t *data, size_t length,
115 : struct ace_condition_int *tok)
116 : {
117 48 : ssize_t bytes_used;
118 48 : enum ndr_err_code ndr_err;
119 156 : DATA_BLOB v = data_blob_const(data, length);
120 156 : struct ndr_pull *ndr = ndr_pull_init_blob(&v, mem_ctx);
121 156 : if (ndr == NULL) {
122 0 : return -1;
123 : }
124 156 : ndr_err = ndr_pull_ace_condition_int(ndr, NDR_SCALARS|NDR_BUFFERS, tok);
125 156 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
126 0 : TALLOC_FREE(ndr);
127 0 : return -1;
128 : }
129 156 : bytes_used = ndr->offset;
130 156 : TALLOC_FREE(ndr);
131 156 : return bytes_used;
132 : }
133 :
134 636 : static ssize_t push_integer(uint8_t *data, size_t available,
135 : const struct ace_condition_int *tok)
136 : {
137 564 : enum ndr_err_code ndr_err;
138 564 : DATA_BLOB v;
139 636 : ndr_err = ndr_push_struct_blob(&v, NULL,
140 : tok,
141 : (ndr_push_flags_fn_t)ndr_push_ace_condition_int);
142 636 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
143 0 : return -1;
144 : }
145 636 : if (available < v.length) {
146 0 : talloc_free(v.data);
147 0 : return -1;
148 : }
149 636 : memcpy(data, v.data, v.length);
150 636 : talloc_free(v.data);
151 636 : return v.length;
152 : }
153 :
154 :
155 1699 : static ssize_t pull_unicode(TALLOC_CTX *mem_ctx,
156 : uint8_t *data, size_t length,
157 : struct ace_condition_unicode *tok)
158 : {
159 241 : ssize_t bytes_used;
160 241 : enum ndr_err_code ndr_err;
161 1699 : DATA_BLOB v = data_blob_const(data, length);
162 1699 : struct ndr_pull *ndr = ndr_pull_init_blob(&v, mem_ctx);
163 1699 : if (ndr == NULL) {
164 0 : return -1;
165 : }
166 1699 : ndr_err = ndr_pull_ace_condition_unicode(ndr, NDR_SCALARS|NDR_BUFFERS, tok);
167 1699 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
168 0 : TALLOC_FREE(ndr);
169 0 : return -1;
170 : }
171 1699 : bytes_used = ndr->offset;
172 1699 : TALLOC_FREE(ndr);
173 1699 : return bytes_used;
174 : }
175 :
176 2737 : static ssize_t push_unicode(uint8_t *data, size_t available,
177 : const struct ace_condition_unicode *tok)
178 : {
179 1893 : enum ndr_err_code ndr_err;
180 1893 : DATA_BLOB v;
181 2737 : ndr_err = ndr_push_struct_blob(&v, NULL,
182 : tok,
183 : (ndr_push_flags_fn_t)ndr_push_ace_condition_unicode);
184 2737 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
185 0 : return -1;
186 : }
187 2737 : if (available < v.length) {
188 0 : talloc_free(v.data);
189 0 : return -1;
190 : }
191 2737 : memcpy(data, v.data, v.length);
192 2737 : talloc_free(v.data);
193 2737 : return v.length;
194 : }
195 :
196 :
197 5 : static ssize_t pull_bytes(TALLOC_CTX *mem_ctx,
198 : uint8_t *data, size_t length,
199 : DATA_BLOB *tok)
200 : {
201 5 : ssize_t bytes_used;
202 5 : enum ndr_err_code ndr_err;
203 5 : DATA_BLOB v = data_blob_const(data, length);
204 5 : struct ndr_pull *ndr = ndr_pull_init_blob(&v, mem_ctx);
205 5 : if (ndr == NULL) {
206 0 : return -1;
207 : }
208 5 : ndr_err = ndr_pull_DATA_BLOB(ndr, NDR_SCALARS|NDR_BUFFERS, tok);
209 5 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
210 0 : TALLOC_FREE(ndr);
211 0 : return -1;
212 : }
213 5 : bytes_used = ndr->offset;
214 5 : talloc_free(ndr);
215 5 : return bytes_used;
216 : }
217 :
218 15 : static ssize_t push_bytes(uint8_t *data, size_t available,
219 : const DATA_BLOB *tok)
220 : {
221 15 : size_t offset;
222 15 : enum ndr_err_code ndr_err;
223 15 : TALLOC_CTX *frame = talloc_stackframe();
224 15 : struct ndr_push *ndr = ndr_push_init_ctx(frame);
225 15 : if (ndr == NULL) {
226 0 : TALLOC_FREE(frame);
227 0 : return -1;
228 : }
229 :
230 15 : ndr_err = ndr_push_DATA_BLOB(ndr, NDR_SCALARS|NDR_BUFFERS, *tok);
231 15 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
232 0 : TALLOC_FREE(frame);
233 0 : return -1;
234 : }
235 :
236 15 : if (available < ndr->offset) {
237 0 : TALLOC_FREE(frame);
238 0 : return -1;
239 : }
240 15 : memcpy(data, ndr->data, ndr->offset);
241 15 : offset = ndr->offset;
242 15 : TALLOC_FREE(frame);
243 15 : return offset;
244 : }
245 :
246 515 : static ssize_t pull_sid(TALLOC_CTX *mem_ctx,
247 : uint8_t *data, size_t length,
248 : struct ace_condition_sid *tok)
249 : {
250 92 : ssize_t bytes_used;
251 92 : enum ndr_err_code ndr_err;
252 515 : DATA_BLOB v = data_blob_const(data, length);
253 515 : struct ndr_pull *ndr = ndr_pull_init_blob(&v, mem_ctx);
254 515 : if (ndr == NULL) {
255 0 : return -1;
256 : }
257 515 : ndr_err = ndr_pull_ace_condition_sid(ndr, NDR_SCALARS|NDR_BUFFERS, tok);
258 515 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
259 0 : TALLOC_FREE(ndr);
260 0 : return -1;
261 : }
262 515 : bytes_used = ndr->offset;
263 515 : TALLOC_FREE(ndr);
264 515 : return bytes_used;
265 : }
266 :
267 755 : static ssize_t push_sid(uint8_t *data, size_t available,
268 : const struct ace_condition_sid *tok)
269 : {
270 479 : enum ndr_err_code ndr_err;
271 479 : DATA_BLOB v;
272 755 : ndr_err = ndr_push_struct_blob(&v, NULL,
273 : tok,
274 : (ndr_push_flags_fn_t)ndr_push_ace_condition_sid);
275 755 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
276 0 : return -1;
277 : }
278 755 : if (available < v.length) {
279 0 : talloc_free(v.data);
280 0 : return -1;
281 : }
282 755 : memcpy(data, v.data, v.length);
283 755 : talloc_free(v.data);
284 755 : return v.length;
285 : }
286 :
287 :
288 458 : static ssize_t pull_composite(TALLOC_CTX *mem_ctx,
289 : uint8_t *data, size_t length,
290 : struct ace_condition_composite *tok)
291 : {
292 96 : size_t i, j;
293 96 : size_t alloc_length;
294 96 : size_t byte_size;
295 458 : struct ace_condition_token *tokens = NULL;
296 458 : if (length < 4) {
297 0 : return -1;
298 : }
299 458 : byte_size = PULL_LE_U32(data, 0);
300 458 : if (byte_size > length - 4) {
301 0 : return -1;
302 : }
303 : /*
304 : * There is a list of other literal tokens (possibly including nested
305 : * composites), which we will store in an array.
306 : *
307 : * This array can *only* be literals.
308 : */
309 458 : alloc_length = byte_size;
310 458 : tokens = talloc_array(mem_ctx,
311 : struct ace_condition_token,
312 : alloc_length);
313 458 : if (tokens == NULL) {
314 0 : return -1;
315 : }
316 458 : byte_size += 4;
317 458 : i = 4;
318 458 : j = 0;
319 1137 : while (i < byte_size) {
320 679 : struct ace_condition_token *el = &tokens[j];
321 146 : ssize_t consumed;
322 679 : uint8_t *el_data = NULL;
323 146 : size_t available;
324 146 : bool ok;
325 679 : *el = (struct ace_condition_token) { .type = data[i] };
326 679 : i++;
327 :
328 679 : el_data = data + i;
329 679 : available = byte_size - i;
330 :
331 679 : switch (el->type) {
332 90 : case CONDITIONAL_ACE_TOKEN_INT8:
333 : case CONDITIONAL_ACE_TOKEN_INT16:
334 : case CONDITIONAL_ACE_TOKEN_INT32:
335 : case CONDITIONAL_ACE_TOKEN_INT64:
336 90 : consumed = pull_integer(mem_ctx,
337 : el_data,
338 : available,
339 : &el->data.int64);
340 90 : ok = check_integer_range(el);
341 90 : if (! ok) {
342 0 : goto error;
343 : }
344 66 : break;
345 193 : case CONDITIONAL_ACE_TOKEN_UNICODE:
346 193 : consumed = pull_unicode(mem_ctx,
347 : el_data,
348 : available,
349 : &el->data.unicode);
350 193 : break;
351 :
352 0 : case CONDITIONAL_ACE_TOKEN_OCTET_STRING:
353 0 : consumed = pull_bytes(mem_ctx,
354 : el_data,
355 : available,
356 : &el->data.bytes);
357 0 : break;
358 :
359 396 : case CONDITIONAL_ACE_TOKEN_SID:
360 396 : consumed = pull_sid(mem_ctx,
361 : el_data,
362 : available,
363 : &el->data.sid);
364 396 : break;
365 :
366 0 : case CONDITIONAL_ACE_TOKEN_COMPOSITE:
367 0 : DBG_ERR("recursive composite tokens in conditional "
368 : "ACEs are not currently supported\n");
369 0 : goto error;
370 0 : default:
371 0 : goto error;
372 : }
373 :
374 679 : if (consumed < 0 || consumed + i > length) {
375 0 : goto error;
376 : }
377 679 : i += consumed;
378 679 : j++;
379 679 : if (j == UINT16_MAX) {
380 0 : talloc_free(tokens);
381 0 : return -1;
382 : }
383 679 : if (j == alloc_length) {
384 0 : struct ace_condition_token *new_tokens = NULL;
385 :
386 0 : alloc_length += 5;
387 0 : new_tokens = talloc_realloc(mem_ctx,
388 : tokens,
389 : struct ace_condition_token,
390 : alloc_length);
391 :
392 0 : if (new_tokens == NULL) {
393 0 : goto error;
394 : }
395 0 : tokens = new_tokens;
396 : }
397 : }
398 458 : tok->n_members = j;
399 458 : tok->tokens = tokens;
400 458 : return byte_size;
401 0 : error:
402 0 : talloc_free(tokens);
403 0 : return -1;
404 : }
405 :
406 :
407 722 : static ssize_t push_composite(uint8_t *data, size_t length,
408 : const struct ace_condition_composite *tok)
409 : {
410 484 : size_t i;
411 484 : uint8_t *byte_length_ptr;
412 722 : size_t used = 0;
413 722 : if (length < 4) {
414 0 : return -1;
415 : }
416 : /*
417 : * We have no idea what the eventual length will be, so we keep a
418 : * pointer to write it in at the end.
419 : */
420 722 : byte_length_ptr = data;
421 722 : PUSH_LE_U32(data, 0, 0);
422 722 : used = 4;
423 :
424 2700 : for (i = 0; i < tok->n_members && used < length; i++) {
425 1978 : struct ace_condition_token *el = &tok->tokens[i];
426 1642 : ssize_t consumed;
427 1978 : uint8_t *el_data = NULL;
428 1642 : size_t available;
429 1642 : bool ok;
430 1978 : data[used] = el->type;
431 1978 : used++;
432 1978 : if (used == length) {
433 : /*
434 : * used == length is not expected here; the token
435 : * types that only have an opcode and no data are not
436 : * literals that can be in composites.
437 : */
438 0 : return -1;
439 : }
440 1978 : el_data = data + used;
441 1978 : available = length - used;
442 :
443 1978 : switch (el->type) {
444 474 : case CONDITIONAL_ACE_TOKEN_INT8:
445 : case CONDITIONAL_ACE_TOKEN_INT16:
446 : case CONDITIONAL_ACE_TOKEN_INT32:
447 : case CONDITIONAL_ACE_TOKEN_INT64:
448 474 : ok = check_integer_range(el);
449 474 : if (! ok) {
450 0 : return -1;
451 : }
452 474 : consumed = push_integer(el_data,
453 : available,
454 474 : &el->data.int64);
455 474 : break;
456 893 : case CONDITIONAL_ACE_TOKEN_UNICODE:
457 893 : consumed = push_unicode(el_data,
458 : available,
459 893 : &el->data.unicode);
460 893 : break;
461 :
462 0 : case CONDITIONAL_ACE_TOKEN_OCTET_STRING:
463 0 : consumed = push_bytes(el_data,
464 : available,
465 0 : &el->data.bytes);
466 0 : break;
467 :
468 611 : case CONDITIONAL_ACE_TOKEN_SID:
469 611 : consumed = push_sid(el_data,
470 : available,
471 611 : &el->data.sid);
472 611 : break;
473 :
474 0 : case CONDITIONAL_ACE_TOKEN_COMPOSITE:
475 0 : consumed = push_composite(el_data,
476 : available,
477 0 : &el->data.composite);
478 0 : break;
479 :
480 0 : default:
481 0 : return -1;
482 : }
483 :
484 1978 : if (consumed < 0) {
485 0 : return -1;
486 : }
487 1978 : used += consumed;
488 : }
489 722 : if (used > length) {
490 0 : return -1;
491 : }
492 :
493 722 : PUSH_LE_U32(byte_length_ptr, 0, used - 4);
494 722 : return used;
495 : }
496 :
497 1150 : static ssize_t pull_end_padding(uint8_t *data, size_t length)
498 : {
499 : /*
500 : * We just check that we have the right kind of number of zero
501 : * bytes. The blob must end on a multiple of 4. One zero byte
502 : * has already been swallowed as tok->type, which sends us
503 : * here, so we expect 1 or two more -- total padding is 0, 1,
504 : * 2, or 3.
505 : *
506 : * zero is also called CONDITIONAL_ACE_TOKEN_INVALID_OR_PADDING.
507 : */
508 158 : ssize_t i;
509 1150 : if (length > 2) {
510 0 : return -1;
511 : }
512 2113 : for (i = 0; i < length; i++) {
513 963 : if (data[i] != 0) {
514 0 : return -1;
515 : }
516 : }
517 1150 : return length;
518 : }
519 :
520 :
521 1305 : struct ace_condition_script *parse_conditional_ace(TALLOC_CTX *mem_ctx,
522 : DATA_BLOB data)
523 : {
524 182 : size_t i, j;
525 1305 : struct ace_condition_token *tokens = NULL;
526 182 : size_t alloc_length;
527 1305 : struct ace_condition_script *program = NULL;
528 :
529 1305 : if (data.length < 4 ||
530 1305 : data.data[0] != 'a' ||
531 1305 : data.data[1] != 'r' ||
532 1305 : data.data[2] != 't' ||
533 1305 : data.data[3] != 'x') {
534 : /*
535 : * lacks the "artx" conditional ace identifier magic.
536 : * NULL returns will deny access.
537 : */
538 0 : return NULL;
539 : }
540 1305 : if (data.length > CONDITIONAL_ACE_MAX_LENGTH ||
541 1305 : (data.length & 3) != 0) {
542 : /*
543 : * >= 64k or non-multiples of 4 are not possible in the ACE
544 : * wire format.
545 : */
546 0 : return NULL;
547 : }
548 :
549 1305 : program = talloc(mem_ctx, struct ace_condition_script);
550 1305 : if (program == NULL) {
551 0 : return NULL;
552 : }
553 :
554 : /*
555 : * We will normally end up with fewer than data.length tokens, as
556 : * values are stored in multiple bytes (all integers are 10 bytes,
557 : * strings and attributes are utf16 + length, SIDs are SID-size +
558 : * length, etc). But operators are one byte, so something like
559 : * !(!(!(!(!(!(x)))))) -- where each '!(..)' is one byte -- will bring
560 : * the number of tokens close to the number of bytes.
561 : *
562 : * This is all to say we're guessing a token length that hopes to
563 : * avoid reallocs without wasting too much up front.
564 : */
565 1305 : alloc_length = data.length / 2 + 1;
566 1305 : tokens = talloc_array(program,
567 : struct ace_condition_token,
568 : alloc_length);
569 1305 : if (tokens == NULL) {
570 0 : TALLOC_FREE(program);
571 0 : return NULL;
572 : }
573 :
574 1123 : i = 4;
575 1123 : j = 0;
576 6012 : while(i < data.length) {
577 4707 : struct ace_condition_token *tok = &tokens[j];
578 4707 : ssize_t consumed = 0;
579 4707 : uint8_t *tok_data = NULL;
580 806 : size_t available;
581 806 : bool ok;
582 4707 : tok->type = data.data[i];
583 4707 : i++;
584 4707 : tok_data = data.data + i;
585 4707 : available = data.length - i;
586 :
587 4707 : switch (tok->type) {
588 66 : case CONDITIONAL_ACE_TOKEN_INT8:
589 : case CONDITIONAL_ACE_TOKEN_INT16:
590 : case CONDITIONAL_ACE_TOKEN_INT32:
591 : case CONDITIONAL_ACE_TOKEN_INT64:
592 66 : consumed = pull_integer(program,
593 : tok_data,
594 : available,
595 : &tok->data.int64);
596 66 : ok = check_integer_range(tok);
597 66 : if (! ok) {
598 0 : goto fail;
599 : }
600 42 : break;
601 1506 : case CONDITIONAL_ACE_TOKEN_UNICODE:
602 : /*
603 : * The next four are pulled as unicode, but are
604 : * processed as user attribute look-ups.
605 : */
606 : case CONDITIONAL_ACE_LOCAL_ATTRIBUTE:
607 : case CONDITIONAL_ACE_USER_ATTRIBUTE:
608 : case CONDITIONAL_ACE_RESOURCE_ATTRIBUTE:
609 : case CONDITIONAL_ACE_DEVICE_ATTRIBUTE:
610 1506 : consumed = pull_unicode(program,
611 : tok_data,
612 : available,
613 : &tok->data.unicode);
614 1506 : break;
615 :
616 5 : case CONDITIONAL_ACE_TOKEN_OCTET_STRING:
617 5 : consumed = pull_bytes(program,
618 : tok_data,
619 : available,
620 : &tok->data.bytes);
621 5 : break;
622 :
623 119 : case CONDITIONAL_ACE_TOKEN_SID:
624 119 : consumed = pull_sid(program,
625 : tok_data,
626 : available,
627 : &tok->data.sid);
628 119 : break;
629 :
630 458 : case CONDITIONAL_ACE_TOKEN_COMPOSITE:
631 458 : consumed = pull_composite(program,
632 : tok_data,
633 : available,
634 : &tok->data.composite);
635 458 : break;
636 :
637 324 : case CONDITIONAL_ACE_TOKEN_MEMBER_OF:
638 : case CONDITIONAL_ACE_TOKEN_DEVICE_MEMBER_OF:
639 : case CONDITIONAL_ACE_TOKEN_MEMBER_OF_ANY:
640 : case CONDITIONAL_ACE_TOKEN_DEVICE_MEMBER_OF_ANY:
641 : case CONDITIONAL_ACE_TOKEN_NOT_MEMBER_OF:
642 : case CONDITIONAL_ACE_TOKEN_NOT_DEVICE_MEMBER_OF:
643 : case CONDITIONAL_ACE_TOKEN_NOT_MEMBER_OF_ANY:
644 : case CONDITIONAL_ACE_TOKEN_NOT_DEVICE_MEMBER_OF_ANY:
645 : /*
646 : * these require a SID or composite SID list operand,
647 : * and we could check that now in most cases.
648 : */
649 324 : break;
650 : /* binary relational operators */
651 767 : case CONDITIONAL_ACE_TOKEN_EQUAL:
652 : case CONDITIONAL_ACE_TOKEN_NOT_EQUAL:
653 : case CONDITIONAL_ACE_TOKEN_LESS_THAN:
654 : case CONDITIONAL_ACE_TOKEN_LESS_OR_EQUAL:
655 : case CONDITIONAL_ACE_TOKEN_GREATER_THAN:
656 : case CONDITIONAL_ACE_TOKEN_GREATER_OR_EQUAL:
657 : case CONDITIONAL_ACE_TOKEN_CONTAINS:
658 : case CONDITIONAL_ACE_TOKEN_ANY_OF:
659 : case CONDITIONAL_ACE_TOKEN_NOT_CONTAINS:
660 : case CONDITIONAL_ACE_TOKEN_NOT_ANY_OF:
661 : /* unary logical operators */
662 : case CONDITIONAL_ACE_TOKEN_EXISTS:
663 : case CONDITIONAL_ACE_TOKEN_NOT_EXISTS:
664 : case CONDITIONAL_ACE_TOKEN_NOT:
665 : /* binary logical operators */
666 : case CONDITIONAL_ACE_TOKEN_AND:
667 : case CONDITIONAL_ACE_TOKEN_OR:
668 767 : break;
669 992 : case CONDITIONAL_ACE_TOKEN_INVALID_OR_PADDING:
670 : /* this is only valid at the end */
671 1150 : consumed = pull_end_padding(tok_data,
672 : available);
673 1150 : j--; /* don't add this token */
674 1150 : break;
675 0 : default:
676 0 : goto fail;
677 : }
678 :
679 4395 : if (consumed < 0) {
680 0 : goto fail;
681 : }
682 4707 : if (consumed + i < i || consumed + i > data.length) {
683 0 : goto fail;
684 : }
685 4707 : i += consumed;
686 4707 : j++;
687 4707 : if (j == alloc_length) {
688 0 : alloc_length *= 2;
689 0 : tokens = talloc_realloc(program,
690 : tokens,
691 : struct ace_condition_token,
692 : alloc_length);
693 0 : if (tokens == NULL) {
694 0 : goto fail;
695 : }
696 : }
697 : }
698 1305 : program->length = j;
699 1305 : program->tokens = talloc_realloc(program,
700 : tokens,
701 : struct ace_condition_token,
702 : program->length + 1);
703 1305 : if (program->tokens == NULL) {
704 0 : goto fail;
705 : }
706 : /*
707 : * When interpreting the program we will need a stack, which in the
708 : * very worst case can be as deep as the program is long.
709 : */
710 1305 : program->stack = talloc_array(program,
711 : struct ace_condition_token,
712 : program->length + 1);
713 1305 : if (program->stack == NULL) {
714 0 : goto fail;
715 : }
716 :
717 1123 : return program;
718 0 : fail:
719 0 : talloc_free(program);
720 0 : return NULL;
721 : }
722 :
723 :
724 445 : static bool claim_lookup_internal(
725 : TALLOC_CTX *mem_ctx,
726 : struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1 *claim,
727 : struct ace_condition_token *result)
728 : {
729 454 : bool ok = claim_v1_to_ace_token(mem_ctx, claim, result);
730 445 : return ok;
731 : }
732 :
733 :
734 10 : static bool resource_claim_lookup(
735 : TALLOC_CTX *mem_ctx,
736 : const struct ace_condition_token *op,
737 : const struct security_descriptor *sd,
738 : struct ace_condition_token *result)
739 : {
740 : /*
741 : * For a @Resource.attr, the claims come from a resource ACE
742 : * in the object's SACL. That's why we need a security descriptor.
743 : *
744 : * If there is no matching resource ACE, a NULL result is returned,
745 : * which should compare UNKNOWN to anything. The NULL will have the
746 : * CONDITIONAL_ACE_FLAG_NULL_MEANS_ERROR flag set if it seems failure
747 : * is not simply due to the sought claim not existing. This is useful for
748 : * the Exists and Not_Exists operators.
749 : */
750 10 : size_t i;
751 10 : struct ace_condition_unicode name;
752 :
753 10 : result->type = CONDITIONAL_ACE_SAMBA_RESULT_NULL;
754 :
755 10 : if (op->type != CONDITIONAL_ACE_RESOURCE_ATTRIBUTE) {
756 : /* what are we even doing here? */
757 0 : result->type = CONDITIONAL_ACE_SAMBA_RESULT_ERROR;
758 0 : return false;
759 : }
760 :
761 10 : name = op->data.resource_attr;
762 :
763 10 : if (sd->sacl == NULL) {
764 1 : DBG_NOTICE("Resource attribute ACE '%s' not found, "
765 : "because there is no SACL\n",
766 : name.value);
767 1 : return true;
768 : }
769 :
770 9 : for (i = 0; i < sd->sacl->num_aces; i++) {
771 9 : struct security_ace *ace = &sd->sacl->aces[i];
772 9 : bool ok;
773 :
774 9 : if (ace->type != SEC_ACE_TYPE_SYSTEM_RESOURCE_ATTRIBUTE) {
775 0 : continue;
776 : }
777 9 : if (strcasecmp_m(name.value,
778 : ace->coda.claim.name) != 0) {
779 0 : continue;
780 : }
781 : /* this is the one */
782 9 : ok = claim_lookup_internal(mem_ctx, &ace->coda.claim, result);
783 9 : if (ok) {
784 0 : return true;
785 : }
786 : }
787 0 : DBG_NOTICE("Resource attribute ACE '%s' not found.\n",
788 : name.value);
789 0 : return false;
790 : }
791 :
792 :
793 500 : static bool token_claim_lookup(
794 : TALLOC_CTX *mem_ctx,
795 : const struct security_token *token,
796 : const struct ace_condition_token *op,
797 : struct ace_condition_token *result)
798 : {
799 : /*
800 : * The operator has an attribute name; if there is a claim of
801 : * the right type with that name, that is returned as the result.
802 : *
803 : * XXX what happens otherwise? NULL result?
804 : */
805 500 : struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1 *claims = NULL;
806 47 : size_t num_claims;
807 47 : bool ok;
808 500 : const struct ace_condition_unicode *name = NULL;
809 47 : size_t i;
810 :
811 500 : result->type = CONDITIONAL_ACE_SAMBA_RESULT_NULL;
812 :
813 500 : switch (op->type) {
814 0 : case CONDITIONAL_ACE_LOCAL_ATTRIBUTE:
815 0 : claims = token->local_claims;
816 0 : num_claims = token->num_local_claims;
817 0 : name = &op->data.local_attr;
818 0 : break;
819 452 : case CONDITIONAL_ACE_USER_ATTRIBUTE:
820 452 : claims = token->user_claims;
821 452 : num_claims = token->num_user_claims;
822 452 : name = &op->data.user_attr;
823 452 : break;
824 48 : case CONDITIONAL_ACE_DEVICE_ATTRIBUTE:
825 48 : claims = token->device_claims;
826 48 : num_claims = token->num_device_claims;
827 48 : name = &op->data.device_attr;
828 48 : break;
829 0 : default:
830 0 : DBG_WARNING("Conditional ACE claim lookup got bad arg type %u\n",
831 : op->type);
832 0 : result->type = CONDITIONAL_ACE_SAMBA_RESULT_ERROR;
833 0 : return false;
834 : }
835 :
836 500 : if (num_claims == 0) {
837 60 : DBG_NOTICE("There are no type %u claims\n", op->type);
838 60 : return false;
839 : }
840 440 : if (claims == NULL) {
841 0 : DBG_ERR("Type %u claim list unexpectedly NULL!\n", op->type);
842 0 : result->type = CONDITIONAL_ACE_SAMBA_RESULT_ERROR;
843 0 : return false;
844 : }
845 : /*
846 : * Loop backwards: a later claim will override an earlier one with the
847 : * same name.
848 : */
849 576 : for (i = num_claims - 1; i < num_claims; i--) {
850 572 : if (claims[i].name == NULL) {
851 0 : DBG_ERR("claim %zu has no name!\n", i);
852 0 : continue;
853 : }
854 572 : if (strcasecmp_m(claims[i].name, name->value) == 0) {
855 : /* this is the one */
856 436 : ok = claim_lookup_internal(mem_ctx, &claims[i], result);
857 436 : return ok;
858 : }
859 : }
860 4 : DBG_NOTICE("Claim not found\n");
861 4 : return false;
862 : }
863 :
864 :
865 :
866 :
867 243 : static bool member_lookup(
868 : const struct security_token *token,
869 : const struct ace_condition_token *op,
870 : const struct ace_condition_token *arg,
871 : struct ace_condition_token *result)
872 : {
873 : /*
874 : * We need to compare the lists of SIDs in the token with the
875 : * SID[s] in the argument. There are 8 combinations of
876 : * operation, depending on whether we want to match all or any
877 : * of the SIDs, whether we're using the device SIDs or user
878 : * SIDs, and whether the operator name starts with "Not_".
879 : *
880 : * _MEMBER_OF User has all operand SIDs
881 : * _DEVICE_MEMBER_OF Device has all operand SIDs
882 : * _MEMBER_OF_ANY User has one or more operand SIDs
883 : * _DEVICE_MEMBER_OF_ANY Device has one or more operand SIDs
884 : *
885 : * NOT_* has the effect of !(the operator without NOT_).
886 : *
887 : * The operand can either be a composite of SIDs or a single SID.
888 : * This adds an additional branch.
889 : */
890 243 : bool match = false;
891 46 : bool it_is_a_not_op;
892 46 : bool it_is_an_any_op;
893 46 : bool it_is_a_device_op;
894 46 : bool arg_is_a_single_sid;
895 243 : struct dom_sid *sid_array = NULL;
896 46 : size_t num_sids, i, j;
897 243 : const struct dom_sid *sid = NULL;
898 :
899 243 : result->type = CONDITIONAL_ACE_SAMBA_RESULT_BOOL;
900 243 : result->data.result.value = ACE_CONDITION_UNKNOWN;
901 :
902 243 : switch (arg->type) {
903 86 : case CONDITIONAL_ACE_TOKEN_SID:
904 86 : arg_is_a_single_sid = true;
905 86 : break;
906 154 : case CONDITIONAL_ACE_TOKEN_COMPOSITE:
907 154 : arg_is_a_single_sid = false;
908 154 : break;
909 0 : default:
910 0 : DBG_WARNING("Conditional ACE Member_Of got bad arg type %u\n",
911 : arg->type);
912 0 : return false;
913 : }
914 :
915 243 : switch (op->type) {
916 24 : case CONDITIONAL_ACE_TOKEN_NOT_MEMBER_OF:
917 : case CONDITIONAL_ACE_TOKEN_NOT_MEMBER_OF_ANY:
918 24 : it_is_a_not_op = true;
919 24 : it_is_a_device_op = false;
920 24 : break;
921 14 : case CONDITIONAL_ACE_TOKEN_NOT_DEVICE_MEMBER_OF_ANY:
922 : case CONDITIONAL_ACE_TOKEN_NOT_DEVICE_MEMBER_OF:
923 14 : it_is_a_not_op = true;
924 14 : it_is_a_device_op = true;
925 14 : break;
926 144 : case CONDITIONAL_ACE_TOKEN_MEMBER_OF:
927 : case CONDITIONAL_ACE_TOKEN_MEMBER_OF_ANY:
928 144 : it_is_a_not_op = false;
929 144 : it_is_a_device_op = false;
930 144 : break;
931 56 : case CONDITIONAL_ACE_TOKEN_DEVICE_MEMBER_OF_ANY:
932 : case CONDITIONAL_ACE_TOKEN_DEVICE_MEMBER_OF:
933 56 : it_is_a_not_op = false;
934 56 : it_is_a_device_op = true;
935 56 : break;
936 0 : default:
937 0 : DBG_WARNING("Conditional ACE Member_Of got bad op type %u\n",
938 : op->type);
939 0 : return false;
940 : }
941 :
942 243 : switch (op->type) {
943 10 : case CONDITIONAL_ACE_TOKEN_NOT_MEMBER_OF_ANY:
944 : case CONDITIONAL_ACE_TOKEN_NOT_DEVICE_MEMBER_OF_ANY:
945 : case CONDITIONAL_ACE_TOKEN_MEMBER_OF_ANY:
946 : case CONDITIONAL_ACE_TOKEN_DEVICE_MEMBER_OF_ANY:
947 10 : it_is_an_any_op = true;
948 10 : break;
949 226 : default:
950 226 : it_is_an_any_op = false;
951 : }
952 :
953 243 : if (it_is_a_device_op) {
954 70 : sid_array = token->device_sids;
955 70 : num_sids = token->num_device_sids;
956 : } else {
957 173 : sid_array = token->sids;
958 173 : num_sids = token->num_sids;
959 : }
960 :
961 243 : if (arg_is_a_single_sid) {
962 : /*
963 : * In this case the any and all operations are the
964 : * same.
965 : */
966 89 : sid = &arg->data.sid.sid;
967 89 : match = false;
968 433 : for (i = 0; i < num_sids; i++) {
969 395 : match = dom_sid_equal(sid, &sid_array[i]);
970 395 : if (match) {
971 48 : break;
972 : }
973 : }
974 89 : if (it_is_a_not_op) {
975 6 : match = ! match;
976 : }
977 89 : if (match) {
978 57 : result->data.result.value = ACE_CONDITION_TRUE;
979 : } else {
980 32 : result->data.result.value = ACE_CONDITION_FALSE;
981 : }
982 89 : return true;
983 : }
984 :
985 : /* This is a composite list (hopefully of SIDs) */
986 154 : if (arg->data.composite.n_members == 0) {
987 0 : DBG_WARNING("Conditional ACE Member_Of argument is empty\n");
988 0 : return false;
989 : }
990 :
991 280 : for (j = 0; j < arg->data.composite.n_members; j++) {
992 185 : const struct ace_condition_token *member =
993 185 : &arg->data.composite.tokens[j];
994 185 : if (member->type != CONDITIONAL_ACE_TOKEN_SID) {
995 0 : DBG_WARNING("Conditional ACE Member_Of argument contains "
996 : "non-sid element [%zu]: %u\n",
997 : j, member->type);
998 0 : return false;
999 : }
1000 185 : sid = &member->data.sid.sid;
1001 185 : match = false;
1002 924 : for (i = 0; i < num_sids; i++) {
1003 851 : match = dom_sid_equal(sid, &sid_array[i]);
1004 851 : if (match) {
1005 85 : break;
1006 : }
1007 : }
1008 185 : if (it_is_an_any_op) {
1009 32 : if (match) {
1010 : /* we have matched one SID, which is enough */
1011 9 : goto apply_not;
1012 : }
1013 : } else { /* an all op */
1014 153 : if (! match) {
1015 : /* failing one is enough */
1016 50 : goto apply_not;
1017 : }
1018 : }
1019 : }
1020 : /*
1021 : * Reaching the end of that loop means either:
1022 : * 1. it was an ALL op and we never failed to find one, or
1023 : * 2. it was an ANY op, and we didn't find one.
1024 : */
1025 95 : match = !it_is_an_any_op;
1026 :
1027 154 : apply_not:
1028 154 : if (it_is_a_not_op) {
1029 37 : match = ! match;
1030 : }
1031 154 : if (match) {
1032 88 : result->data.result.value = ACE_CONDITION_TRUE;
1033 : } else {
1034 66 : result->data.result.value = ACE_CONDITION_FALSE;
1035 : }
1036 :
1037 111 : return true;
1038 : }
1039 :
1040 :
1041 79 : static bool ternary_value(
1042 : const struct ace_condition_token *arg,
1043 : struct ace_condition_token *result)
1044 : {
1045 : /*
1046 : * Find the truth value of the argument, stored in the result token.
1047 : *
1048 : * A return value of false means the operation is invalid, and the
1049 : * result is undefined.
1050 : */
1051 79 : if (arg->type == CONDITIONAL_ACE_SAMBA_RESULT_BOOL) {
1052 : /* pass through */
1053 79 : *result = *arg;
1054 79 : return true;
1055 : }
1056 :
1057 0 : result->type = CONDITIONAL_ACE_SAMBA_RESULT_BOOL;
1058 0 : result->data.result.value = ACE_CONDITION_UNKNOWN;
1059 :
1060 0 : if (IS_INT_TOKEN(arg)) {
1061 : /* zero is false */
1062 0 : if (arg->data.int64.value == 0) {
1063 0 : result->data.result.value = ACE_CONDITION_FALSE;
1064 : } else {
1065 0 : result->data.result.value = ACE_CONDITION_TRUE;
1066 : }
1067 0 : return true;
1068 : }
1069 0 : if (arg->type == CONDITIONAL_ACE_TOKEN_UNICODE) {
1070 : /* empty is false */
1071 0 : if (arg->data.unicode.value[0] == '\0') {
1072 0 : result->data.result.value = ACE_CONDITION_FALSE;
1073 : } else {
1074 0 : result->data.result.value = ACE_CONDITION_TRUE;
1075 : }
1076 0 : return true;
1077 : }
1078 :
1079 : /*
1080 : * everything else in UNKNOWN. This includes NULL values (i.e. an
1081 : * unsuccessful look-up).
1082 : */
1083 0 : result->data.result.value = ACE_CONDITION_UNKNOWN;
1084 0 : return true;
1085 : }
1086 :
1087 70 : static bool not_operator(
1088 : const struct ace_condition_token *arg,
1089 : struct ace_condition_token *result)
1090 : {
1091 61 : bool ok;
1092 70 : if (IS_LITERAL_TOKEN(arg)) {
1093 : /*
1094 : * Logic operators don't work on literals.
1095 : */
1096 9 : return false;
1097 : }
1098 :
1099 61 : ok = ternary_value(arg, result);
1100 61 : if (! ok) {
1101 0 : return false;
1102 : }
1103 61 : if (result->data.result.value == ACE_CONDITION_FALSE) {
1104 31 : result->data.result.value = ACE_CONDITION_TRUE;
1105 30 : } else if (result->data.result.value == ACE_CONDITION_TRUE) {
1106 30 : result->data.result.value = ACE_CONDITION_FALSE;
1107 : }
1108 : /* unknown stays unknown */
1109 0 : return true;
1110 : }
1111 :
1112 :
1113 70 : static bool unary_logic_operator(
1114 : TALLOC_CTX *mem_ctx,
1115 : const struct security_token *token,
1116 : const struct ace_condition_token *op,
1117 : const struct ace_condition_token *arg,
1118 : const struct security_descriptor *sd,
1119 : struct ace_condition_token *result)
1120 : {
1121 :
1122 61 : bool ok;
1123 61 : bool found;
1124 70 : struct ace_condition_token claim = {
1125 : .type = CONDITIONAL_ACE_SAMBA_RESULT_ERROR
1126 : };
1127 70 : if (op->type == CONDITIONAL_ACE_TOKEN_NOT) {
1128 70 : return not_operator(arg, result);
1129 : }
1130 0 : result->type = CONDITIONAL_ACE_SAMBA_RESULT_BOOL;
1131 0 : result->data.result.value = ACE_CONDITION_UNKNOWN;
1132 :
1133 : /*
1134 : * Not_Exists and Exists require the same work, except we negate the
1135 : * answer in one case. From [MS-DTYP] 2.4.4.17.7:
1136 : *
1137 : * If the type of the operand is "Local Attribute"
1138 : * If the value is non-null return TRUE
1139 : * Else return FALSE
1140 : * Else if the type of the operand is "Resource Attribute"
1141 : * Return TRUE if value is non-null; FALSE otherwise.
1142 : * Else return Error
1143 : */
1144 0 : switch (op->type) {
1145 0 : case CONDITIONAL_ACE_LOCAL_ATTRIBUTE:
1146 0 : ok = token_claim_lookup(mem_ctx, token, arg, &claim);
1147 : /*
1148 : * "not ok" usually means a failure to find the attribute,
1149 : * which is the false condition and not an error.
1150 : *
1151 : * XXX or do we need an extra flag?
1152 : */
1153 0 : break;
1154 0 : case CONDITIONAL_ACE_RESOURCE_ATTRIBUTE:
1155 0 : ok = resource_claim_lookup(mem_ctx, arg, sd, &claim);
1156 0 : break;
1157 0 : default:
1158 0 : return false;
1159 : }
1160 :
1161 : /*
1162 : *
1163 : */
1164 :
1165 0 : if (claim.type != CONDITIONAL_ACE_SAMBA_RESULT_NULL) {
1166 0 : found = true;
1167 0 : } else if (ok) {
1168 0 : found = false;
1169 : } else {
1170 0 : return false;
1171 : }
1172 :
1173 :
1174 :
1175 0 : if (op->type == CONDITIONAL_ACE_TOKEN_NOT_EXISTS) {
1176 0 : found = ! found;
1177 0 : } else if (op->type != CONDITIONAL_ACE_TOKEN_EXISTS) {
1178 : /* should not get here */
1179 0 : return false;
1180 : }
1181 :
1182 0 : result->data.result.value = found ? ACE_CONDITION_TRUE: ACE_CONDITION_FALSE;
1183 0 : return true;
1184 : }
1185 :
1186 :
1187 :
1188 22 : static bool binary_logic_operator(
1189 : const struct security_token *token,
1190 : const struct ace_condition_token *op,
1191 : const struct ace_condition_token *lhs,
1192 : const struct ace_condition_token *rhs,
1193 : struct ace_condition_token *result)
1194 : {
1195 9 : struct ace_condition_token at, bt;
1196 9 : int a, b;
1197 9 : bool ok;
1198 :
1199 22 : result->type = CONDITIONAL_ACE_SAMBA_RESULT_BOOL;
1200 22 : result->data.result.value = ACE_CONDITION_UNKNOWN;
1201 :
1202 22 : if (IS_LITERAL_TOKEN(lhs) || IS_LITERAL_TOKEN(rhs)) {
1203 : /*
1204 : * Logic operators don't work on literals.
1205 : */
1206 13 : return false;
1207 : }
1208 :
1209 9 : ok = ternary_value(lhs, &at);
1210 9 : if (! ok) {
1211 0 : return false;
1212 : }
1213 9 : ok = ternary_value(rhs, &bt);
1214 9 : if (! ok) {
1215 0 : return false;
1216 : }
1217 9 : a = at.data.result.value;
1218 9 : b = bt.data.result.value;
1219 :
1220 9 : if (op->type == CONDITIONAL_ACE_TOKEN_AND) {
1221 : /*
1222 : * AND true false unknown
1223 : * true T F ?
1224 : * false F F F
1225 : * unknown ? F ?
1226 : *
1227 : * unknown unless BOTH true or EITHER false
1228 : */
1229 5 : if (a == ACE_CONDITION_TRUE &&
1230 5 : b == ACE_CONDITION_TRUE) {
1231 2 : result->data.result.value = ACE_CONDITION_TRUE;
1232 2 : return true;
1233 : }
1234 3 : if (a == ACE_CONDITION_FALSE ||
1235 3 : b == ACE_CONDITION_FALSE) {
1236 3 : result->data.result.value = ACE_CONDITION_FALSE;
1237 3 : return true;
1238 : }
1239 : /*
1240 : * Neither value is False, so the result is Unknown,
1241 : * as set at the start of this function.
1242 : */
1243 0 : return true;
1244 : }
1245 : /*
1246 : * OR true false unknown
1247 : * true T T T
1248 : * false T F ?
1249 : * unknown T ? ?
1250 : *
1251 : * unknown unless EITHER true or BOTH false
1252 : */
1253 4 : if (a == ACE_CONDITION_TRUE ||
1254 4 : b == ACE_CONDITION_TRUE) {
1255 3 : result->data.result.value = ACE_CONDITION_TRUE;
1256 3 : return true;
1257 : }
1258 1 : if (a == ACE_CONDITION_FALSE &&
1259 : b == ACE_CONDITION_FALSE) {
1260 1 : result->data.result.value = ACE_CONDITION_FALSE;
1261 1 : return true;
1262 : }
1263 0 : return true;
1264 : }
1265 :
1266 :
1267 12 : static bool tokens_are_comparable(const struct ace_condition_token *op,
1268 : const struct ace_condition_token *lhs,
1269 : const struct ace_condition_token *rhs)
1270 : {
1271 3 : uint64_t n;
1272 : /*
1273 : * we can't compare different types *unless* they are both
1274 : * integers, or one is a bool and the other is an integer 0 or
1275 : * 1, and the operator is == or !=.
1276 : */
1277 : //XXX actually it says "literal integers", do we need to check flags?
1278 :
1279 12 : if (IS_INT_TOKEN(lhs) && IS_INT_TOKEN(rhs)) {
1280 : /* don't block e.g. comparing an int32 to an int64 */
1281 0 : return true;
1282 : }
1283 :
1284 : /* is it == or != */
1285 12 : if (op->type != CONDITIONAL_ACE_TOKEN_EQUAL &&
1286 2 : op->type != CONDITIONAL_ACE_TOKEN_NOT_EQUAL) {
1287 0 : return false;
1288 : }
1289 : /* is one a bool and the other an int? */
1290 12 : if (IS_INT_TOKEN(lhs) && IS_BOOL_TOKEN(rhs)) {
1291 0 : n = lhs->data.int64.value;
1292 12 : } else if (IS_INT_TOKEN(rhs) && IS_BOOL_TOKEN(lhs)) {
1293 0 : n = rhs->data.int64.value;
1294 : } else {
1295 9 : return false;
1296 : }
1297 0 : if (n == 0 || n == 1) {
1298 0 : return true;
1299 : }
1300 0 : return false;
1301 : }
1302 :
1303 :
1304 162 : static bool cmp_to_result(const struct ace_condition_token *op,
1305 : struct ace_condition_token *result,
1306 : int cmp)
1307 : {
1308 18 : bool answer;
1309 162 : switch (op->type) {
1310 99 : case CONDITIONAL_ACE_TOKEN_EQUAL:
1311 99 : answer = cmp == 0;
1312 99 : break;
1313 15 : case CONDITIONAL_ACE_TOKEN_NOT_EQUAL:
1314 15 : answer = cmp != 0;
1315 15 : break;
1316 25 : case CONDITIONAL_ACE_TOKEN_LESS_THAN:
1317 25 : answer = cmp < 0;
1318 25 : break;
1319 4 : case CONDITIONAL_ACE_TOKEN_LESS_OR_EQUAL:
1320 4 : answer = cmp <= 0;
1321 4 : break;
1322 14 : case CONDITIONAL_ACE_TOKEN_GREATER_THAN:
1323 14 : answer = cmp > 0;
1324 14 : break;
1325 5 : case CONDITIONAL_ACE_TOKEN_GREATER_OR_EQUAL:
1326 5 : answer = cmp >= 0;
1327 5 : break;
1328 0 : default:
1329 0 : result->data.result.value = ACE_CONDITION_UNKNOWN;
1330 0 : return false;
1331 : }
1332 162 : result->data.result.value = \
1333 162 : answer ? ACE_CONDITION_TRUE : ACE_CONDITION_FALSE;
1334 162 : return true;
1335 : }
1336 :
1337 :
1338 :
1339 464 : static bool compare_unicode(const struct ace_condition_token *op,
1340 : const struct ace_condition_token *lhs,
1341 : const struct ace_condition_token *rhs,
1342 : int *cmp)
1343 : {
1344 464 : struct ace_condition_unicode a = lhs->data.unicode;
1345 464 : struct ace_condition_unicode b = rhs->data.unicode;
1346 : /*
1347 : * Comparison is case-insensitive UNLESS the claim structure
1348 : * has the case-sensitive flag, which is passed through as a
1349 : * flag on the token. Usually only the LHS is a claim value,
1350 : * but in the event that they both are, we allow either to
1351 : * request case-sensitivity.
1352 : *
1353 : * For greater than and less than, the sort order is utf-8 order,
1354 : * which is not exactly what Windows does, but we don't sort like
1355 : * Windows does anywhere else either.
1356 : */
1357 464 : uint8_t flags = lhs->flags | rhs->flags;
1358 464 : if (flags & CLAIM_SECURITY_ATTRIBUTE_VALUE_CASE_SENSITIVE) {
1359 15 : *cmp = strcmp(a.value, b.value);
1360 : } else {
1361 449 : *cmp = strcasecmp_m(a.value, b.value);
1362 : }
1363 464 : return true;
1364 : }
1365 :
1366 :
1367 0 : static bool compare_bytes(const struct ace_condition_token *op,
1368 : const struct ace_condition_token *lhs,
1369 : const struct ace_condition_token *rhs,
1370 : int *cmp)
1371 : {
1372 0 : DATA_BLOB a = lhs->data.bytes;
1373 0 : DATA_BLOB b = rhs->data.bytes;
1374 0 : *cmp = data_blob_cmp(&a, &b);
1375 0 : return true;
1376 : }
1377 :
1378 :
1379 12 : static bool compare_sids(const struct ace_condition_token *op,
1380 : const struct ace_condition_token *lhs,
1381 : const struct ace_condition_token *rhs,
1382 : int *cmp)
1383 : {
1384 24 : *cmp = dom_sid_compare(&lhs->data.sid.sid,
1385 : &rhs->data.sid.sid);
1386 12 : return true;
1387 : }
1388 :
1389 :
1390 47 : static bool compare_ints(const struct ace_condition_token *op,
1391 : const struct ace_condition_token *lhs,
1392 : const struct ace_condition_token *rhs,
1393 : int *cmp)
1394 : {
1395 47 : int64_t a = lhs->data.int64.value;
1396 47 : int64_t b = rhs->data.int64.value;
1397 :
1398 47 : if (a < b) {
1399 4 : *cmp = -1;
1400 43 : } else if (a == b) {
1401 22 : *cmp = 0;
1402 : } else {
1403 21 : *cmp = 1;
1404 : }
1405 45 : return true;
1406 : }
1407 :
1408 :
1409 0 : static bool compare_bools(const struct ace_condition_token *op,
1410 : const struct ace_condition_token *lhs,
1411 : const struct ace_condition_token *rhs,
1412 : int *cmp)
1413 : {
1414 0 : bool ok;
1415 0 : struct ace_condition_token a, b;
1416 0 : *cmp = -1;
1417 :
1418 0 : if (IS_LITERAL_TOKEN(lhs)) {
1419 : /*
1420 : * we can compare a boolean LHS to a literal RHS, but not
1421 : * vice versa
1422 : */
1423 0 : return false;
1424 : }
1425 0 : ok = ternary_value(lhs, &a);
1426 0 : if (! ok) {
1427 0 : return false;
1428 : }
1429 0 : ok = ternary_value(rhs, &b);
1430 0 : if (! ok) {
1431 0 : return false;
1432 : }
1433 0 : if (a.data.result.value == ACE_CONDITION_UNKNOWN ||
1434 0 : b.data.result.value == ACE_CONDITION_UNKNOWN) {
1435 0 : return false;
1436 : }
1437 :
1438 0 : switch (op->type) {
1439 0 : case CONDITIONAL_ACE_TOKEN_EQUAL:
1440 : case CONDITIONAL_ACE_TOKEN_NOT_EQUAL:
1441 0 : *cmp = a.data.result.value - b.data.result.value;
1442 0 : break;
1443 0 : default:
1444 : /* we are not allowing non-equality comparisons with bools */
1445 0 : return false;
1446 : }
1447 0 : return true;
1448 : }
1449 :
1450 :
1451 : static bool simple_relational_operator(const struct ace_condition_token *op,
1452 : const struct ace_condition_token *lhs,
1453 : const struct ace_condition_token *rhs,
1454 : int *cmp);
1455 :
1456 :
1457 39 : static bool compare_composites(const struct ace_condition_token *op,
1458 : const struct ace_condition_token *lhs,
1459 : const struct ace_condition_token *rhs,
1460 : int *cmp)
1461 : {
1462 : /*
1463 : * We treat composites as if they are sets, which is to say we
1464 : * don't care about order. This rules out < and > operations.
1465 : *
1466 : * In Kerberos clams it is not possible to add duplicate
1467 : * values to a composite, but in Conditional ACEs you can do
1468 : * that. This means we can't short-cut by comparing the
1469 : * lengths.
1470 : *
1471 : * The extra sad thing is we might have to do it both ways
1472 : * round. For example, comparing {a, a, b, a} to {a, b, c}, we
1473 : * find all of the first group in the second, but that doesn't
1474 : * mean all of the second are in the first.
1475 : */
1476 39 : struct ace_condition_composite args[2] = {
1477 : lhs->data.composite,
1478 : rhs->data.composite
1479 : };
1480 12 : size_t i, j, k;
1481 :
1482 98 : for (k = 0; k < 2; k++) {
1483 70 : struct ace_condition_composite a = args[k];
1484 70 : struct ace_condition_composite b = args[1 - k];
1485 :
1486 209 : for (i = 0; i < a.n_members; i++) {
1487 150 : const struct ace_condition_token *lhs2 = &a.tokens[i];
1488 150 : bool found = false;
1489 252 : for (j = 0; j < b.n_members; j++) {
1490 244 : const struct ace_condition_token *rhs2 = &b.tokens[j];
1491 75 : int cmp_pair;
1492 244 : bool ok = simple_relational_operator(op, lhs2, rhs2, &cmp_pair);
1493 244 : if (! ok) {
1494 3 : return false;
1495 : }
1496 241 : if (cmp_pair == 0) {
1497 : /* This item in A is also in B. */
1498 139 : found = true;
1499 139 : break;
1500 : }
1501 : }
1502 145 : if (! found) {
1503 8 : *cmp = -1;
1504 8 : return true;
1505 : }
1506 : }
1507 : }
1508 28 : *cmp = 0;
1509 28 : return true;
1510 : }
1511 :
1512 :
1513 574 : static bool simple_relational_operator(const struct ace_condition_token *op,
1514 : const struct ace_condition_token *lhs,
1515 : const struct ace_condition_token *rhs,
1516 : int *cmp)
1517 :
1518 : {
1519 574 : if (lhs->type != rhs->type) {
1520 12 : if (! tokens_are_comparable(op, lhs, rhs)) {
1521 9 : return false;
1522 : }
1523 : }
1524 562 : switch (lhs->type) {
1525 47 : case CONDITIONAL_ACE_TOKEN_INT8:
1526 : case CONDITIONAL_ACE_TOKEN_INT16:
1527 : case CONDITIONAL_ACE_TOKEN_INT32:
1528 : case CONDITIONAL_ACE_TOKEN_INT64:
1529 47 : if (rhs->type == CONDITIONAL_ACE_SAMBA_RESULT_BOOL) {
1530 0 : return compare_bools(op, lhs, rhs, cmp);
1531 : }
1532 47 : return compare_ints(op, lhs, rhs, cmp);
1533 0 : case CONDITIONAL_ACE_SAMBA_RESULT_BOOL:
1534 0 : return compare_bools(op, lhs, rhs, cmp);
1535 464 : case CONDITIONAL_ACE_TOKEN_UNICODE:
1536 464 : return compare_unicode(op, lhs, rhs, cmp);
1537 0 : case CONDITIONAL_ACE_TOKEN_OCTET_STRING:
1538 0 : return compare_bytes(op, lhs, rhs, cmp);
1539 0 : case CONDITIONAL_ACE_TOKEN_SID:
1540 12 : return compare_sids(op, lhs, rhs, cmp);
1541 39 : case CONDITIONAL_ACE_TOKEN_COMPOSITE:
1542 39 : return compare_composites(op, lhs, rhs, cmp);
1543 0 : case CONDITIONAL_ACE_SAMBA_RESULT_NULL:
1544 : /* leave the result unknown */
1545 0 : return false;
1546 0 : default:
1547 0 : DBG_ERR("did not expect ace type %u\n", lhs->type);
1548 0 : return false;
1549 : }
1550 :
1551 : return false;
1552 : }
1553 :
1554 :
1555 96 : static bool find_in_composite(const struct ace_condition_token *tok,
1556 : struct ace_condition_composite candidates,
1557 : bool *answer)
1558 : {
1559 25 : size_t i;
1560 25 : int cmp;
1561 25 : bool ok;
1562 96 : const struct ace_condition_token equals = {
1563 : .type = CONDITIONAL_ACE_TOKEN_EQUAL
1564 : };
1565 :
1566 96 : *answer = false;
1567 :
1568 180 : for (i = 0; i < candidates.n_members; i++) {
1569 192 : ok = simple_relational_operator(&equals,
1570 : tok,
1571 147 : &candidates.tokens[i],
1572 : &cmp);
1573 147 : if (! ok) {
1574 2 : return false;
1575 : }
1576 145 : if (cmp == 0) {
1577 61 : *answer = true;
1578 61 : return true;
1579 : }
1580 : }
1581 25 : return true;
1582 : }
1583 :
1584 :
1585 39 : static bool contains_operator(const struct ace_condition_token *lhs,
1586 : const struct ace_condition_token *rhs,
1587 : bool *answer)
1588 : {
1589 13 : size_t i;
1590 13 : bool ok;
1591 13 : int cmp;
1592 39 : const struct ace_condition_token equals = {
1593 : .type = CONDITIONAL_ACE_TOKEN_EQUAL
1594 : };
1595 :
1596 : /*
1597 : * All the required objects must be identical to something in
1598 : * candidates. But what do we mean by *identical*? We'll use
1599 : * the equality operator to decide that.
1600 : *
1601 : * Both the lhs or rhs can be solitary objects or composites.
1602 : * This makes it a bit fiddlier.
1603 : */
1604 39 : if (lhs->type == CONDITIONAL_ACE_TOKEN_COMPOSITE) {
1605 29 : struct ace_condition_composite candidates = lhs->data.composite;
1606 9 : struct ace_condition_composite required;
1607 29 : if (rhs->type != CONDITIONAL_ACE_TOKEN_COMPOSITE) {
1608 9 : return find_in_composite(rhs, candidates, answer);
1609 : }
1610 20 : required = rhs->data.composite;
1611 20 : if (required.n_members == 0) {
1612 0 : return false;
1613 : }
1614 58 : for (i = 0; i < required.n_members; i++) {
1615 47 : const struct ace_condition_token *t = &required.tokens[i];
1616 47 : ok = find_in_composite(t, candidates, answer);
1617 47 : if (! ok) {
1618 2 : return false;
1619 : }
1620 45 : if (! *answer) {
1621 : /*
1622 : * one required item was not there,
1623 : * *answer is false
1624 : */
1625 6 : return true;
1626 : }
1627 : }
1628 : /* all required items are there, *answer will be true */
1629 8 : return true;
1630 : }
1631 : /* LHS is a single item */
1632 10 : if (rhs->type == CONDITIONAL_ACE_TOKEN_COMPOSITE) {
1633 : /*
1634 : * There could be more than one RHS member that is
1635 : * equal to the single LHS value, so it doesn't help
1636 : * to compare lengths or anything.
1637 : */
1638 4 : struct ace_condition_composite required = rhs->data.composite;
1639 4 : if (required.n_members == 0) {
1640 2 : return false;
1641 : }
1642 4 : for (i = 0; i < required.n_members; i++) {
1643 2 : ok = simple_relational_operator(&equals,
1644 : lhs,
1645 2 : &required.tokens[i],
1646 : &cmp);
1647 2 : if (! ok) {
1648 0 : return false;
1649 : }
1650 2 : if (cmp != 0) {
1651 : /*
1652 : * one required item was not there,
1653 : * *answer is false
1654 : */
1655 0 : *answer = false;
1656 0 : return true;
1657 : }
1658 : }
1659 2 : *answer = true;
1660 2 : return true;
1661 : }
1662 : /* LHS and RHS are both single */
1663 6 : ok = simple_relational_operator(&equals,
1664 : lhs,
1665 : rhs,
1666 : &cmp);
1667 6 : if (! ok) {
1668 0 : return false;
1669 : }
1670 6 : *answer = (cmp == 0);
1671 6 : return true;
1672 : }
1673 :
1674 :
1675 34 : static bool any_of_operator(const struct ace_condition_token *lhs,
1676 : const struct ace_condition_token *rhs,
1677 : bool *answer)
1678 : {
1679 10 : size_t i;
1680 10 : bool ok;
1681 10 : int cmp;
1682 34 : const struct ace_condition_token equals = {
1683 : .type = CONDITIONAL_ACE_TOKEN_EQUAL
1684 : };
1685 :
1686 : /*
1687 : * There has to be *some* overlap between the LHS and RHS.
1688 : * Both sides can be solitary objects or composites.
1689 : *
1690 : * We can exploit this symmetry.
1691 : */
1692 34 : if (lhs->type != CONDITIONAL_ACE_TOKEN_COMPOSITE) {
1693 11 : const struct ace_condition_token *tmp = lhs;
1694 11 : lhs = rhs;
1695 11 : rhs = tmp;
1696 : }
1697 34 : if (lhs->type != CONDITIONAL_ACE_TOKEN_COMPOSITE) {
1698 : /* both singles */
1699 4 : ok = simple_relational_operator(&equals,
1700 : lhs,
1701 : rhs,
1702 : &cmp);
1703 4 : if (! ok) {
1704 0 : return false;
1705 : }
1706 3 : *answer = (cmp == 0);
1707 3 : return true;
1708 : }
1709 30 : if (rhs->type != CONDITIONAL_ACE_TOKEN_COMPOSITE) {
1710 19 : return find_in_composite(rhs, lhs->data.composite, answer);
1711 : }
1712 : /* both are composites */
1713 11 : if (lhs->data.composite.n_members == 0) {
1714 0 : return false;
1715 : }
1716 23 : for (i = 0; i < lhs->data.composite.n_members; i++) {
1717 21 : ok = find_in_composite(&lhs->data.composite.tokens[i],
1718 : rhs->data.composite,
1719 : answer);
1720 21 : if (! ok) {
1721 0 : return false;
1722 : }
1723 21 : if (*answer) {
1724 : /* We have found one match, which is enough. */
1725 6 : return true;
1726 : }
1727 : }
1728 2 : return true;
1729 : }
1730 :
1731 :
1732 73 : static bool composite_relational_operator(const struct ace_condition_token *op,
1733 : const struct ace_condition_token *lhs,
1734 : const struct ace_condition_token *rhs,
1735 : struct ace_condition_token *result)
1736 : {
1737 23 : bool ok, answer;
1738 73 : switch(op->type) {
1739 39 : case CONDITIONAL_ACE_TOKEN_CONTAINS:
1740 : case CONDITIONAL_ACE_TOKEN_NOT_CONTAINS:
1741 39 : ok = contains_operator(lhs, rhs, &answer);
1742 39 : break;
1743 34 : case CONDITIONAL_ACE_TOKEN_ANY_OF:
1744 : case CONDITIONAL_ACE_TOKEN_NOT_ANY_OF:
1745 34 : ok = any_of_operator(lhs, rhs, &answer);
1746 34 : break;
1747 0 : default:
1748 0 : return false;
1749 : }
1750 73 : if (!ok) {
1751 4 : return false;
1752 : }
1753 :
1754 : /* negate the NOTs */
1755 68 : if (op->type == CONDITIONAL_ACE_TOKEN_NOT_CONTAINS ||
1756 40 : op->type == CONDITIONAL_ACE_TOKEN_NOT_ANY_OF)
1757 : {
1758 20 : answer = !answer;
1759 : }
1760 :
1761 68 : if (answer) {
1762 45 : result->data.result.value = ACE_CONDITION_TRUE;
1763 : } else {
1764 23 : result->data.result.value = ACE_CONDITION_FALSE;
1765 : }
1766 46 : return true;
1767 : }
1768 :
1769 :
1770 252 : static bool relational_operator(
1771 : const struct security_token *token,
1772 : const struct ace_condition_token *op,
1773 : const struct ace_condition_token *lhs,
1774 : const struct ace_condition_token *rhs,
1775 : struct ace_condition_token *result)
1776 : {
1777 43 : int cmp;
1778 43 : bool ok;
1779 252 : result->type = CONDITIONAL_ACE_SAMBA_RESULT_BOOL;
1780 252 : result->data.result.value = ACE_CONDITION_UNKNOWN;
1781 :
1782 252 : if ((lhs->flags & CONDITIONAL_ACE_FLAG_TOKEN_FROM_ATTR) == 0) {
1783 : /* LHS was not derived from an attribute */
1784 0 : return false;
1785 : }
1786 :
1787 : /*
1788 : * This first nested switch is ensuring that >, >=, <, <= are
1789 : * not being tried on tokens that are not numbers, strings, or
1790 : * octet strings. Equality operators are available for all types.
1791 : */
1792 252 : switch (lhs->type) {
1793 138 : case CONDITIONAL_ACE_TOKEN_INT8:
1794 : case CONDITIONAL_ACE_TOKEN_INT16:
1795 : case CONDITIONAL_ACE_TOKEN_INT32:
1796 : case CONDITIONAL_ACE_TOKEN_INT64:
1797 : case CONDITIONAL_ACE_TOKEN_UNICODE:
1798 : case CONDITIONAL_ACE_TOKEN_OCTET_STRING:
1799 138 : break;
1800 101 : default:
1801 101 : switch(op->type) {
1802 8 : case CONDITIONAL_ACE_TOKEN_LESS_THAN:
1803 : case CONDITIONAL_ACE_TOKEN_LESS_OR_EQUAL:
1804 : case CONDITIONAL_ACE_TOKEN_GREATER_THAN:
1805 : case CONDITIONAL_ACE_TOKEN_GREATER_OR_EQUAL:
1806 8 : return false;
1807 63 : default:
1808 63 : break;
1809 : }
1810 : }
1811 :
1812 : /*
1813 : * Dispatch according to operator type.
1814 : */
1815 244 : switch (op->type) {
1816 171 : case CONDITIONAL_ACE_TOKEN_EQUAL:
1817 : case CONDITIONAL_ACE_TOKEN_NOT_EQUAL:
1818 : case CONDITIONAL_ACE_TOKEN_LESS_THAN:
1819 : case CONDITIONAL_ACE_TOKEN_LESS_OR_EQUAL:
1820 : case CONDITIONAL_ACE_TOKEN_GREATER_THAN:
1821 : case CONDITIONAL_ACE_TOKEN_GREATER_OR_EQUAL:
1822 171 : ok = simple_relational_operator(op,
1823 : lhs,
1824 : rhs,
1825 : &cmp);
1826 171 : if (ok) {
1827 162 : ok = cmp_to_result(op, result, cmp);
1828 : }
1829 151 : return ok;
1830 :
1831 73 : case CONDITIONAL_ACE_TOKEN_CONTAINS:
1832 : case CONDITIONAL_ACE_TOKEN_ANY_OF:
1833 : case CONDITIONAL_ACE_TOKEN_NOT_CONTAINS:
1834 : case CONDITIONAL_ACE_TOKEN_NOT_ANY_OF:
1835 73 : return composite_relational_operator(op,
1836 : lhs,
1837 : rhs,
1838 : result);
1839 0 : default:
1840 0 : return false;
1841 : }
1842 : }
1843 :
1844 :
1845 597 : int run_conditional_ace(TALLOC_CTX *mem_ctx,
1846 : const struct security_token *token,
1847 : struct ace_condition_script *program,
1848 : const struct security_descriptor *sd)
1849 : {
1850 82 : size_t i;
1851 597 : size_t depth = 0;
1852 597 : struct ace_condition_token *lhs = NULL;
1853 597 : struct ace_condition_token *rhs = NULL;
1854 597 : struct ace_condition_token result = {};
1855 82 : bool ok;
1856 :
1857 1948 : for (i = 0; i < program->length; i++) {
1858 1466 : struct ace_condition_token *tok = &program->tokens[i];
1859 1466 : switch (tok->type) {
1860 369 : case CONDITIONAL_ACE_TOKEN_INT8:
1861 : case CONDITIONAL_ACE_TOKEN_INT16:
1862 : case CONDITIONAL_ACE_TOKEN_INT32:
1863 : case CONDITIONAL_ACE_TOKEN_INT64:
1864 : case CONDITIONAL_ACE_TOKEN_UNICODE:
1865 : case CONDITIONAL_ACE_TOKEN_OCTET_STRING:
1866 : case CONDITIONAL_ACE_TOKEN_SID:
1867 : case CONDITIONAL_ACE_TOKEN_COMPOSITE:
1868 : /* just plonk these literals on the stack */
1869 369 : program->stack[depth] = *tok;
1870 369 : depth++;
1871 369 : break;
1872 :
1873 500 : case CONDITIONAL_ACE_LOCAL_ATTRIBUTE:
1874 : case CONDITIONAL_ACE_USER_ATTRIBUTE:
1875 : case CONDITIONAL_ACE_DEVICE_ATTRIBUTE:
1876 500 : ok = token_claim_lookup(mem_ctx, token, tok, &result);
1877 500 : if (! ok) {
1878 71 : goto error;
1879 : }
1880 429 : program->stack[depth] = result;
1881 429 : depth++;
1882 429 : break;
1883 :
1884 10 : case CONDITIONAL_ACE_RESOURCE_ATTRIBUTE:
1885 10 : ok = resource_claim_lookup(mem_ctx,
1886 : tok,
1887 : sd,
1888 : &result);
1889 10 : if (! ok) {
1890 0 : goto error;
1891 : }
1892 10 : program->stack[depth] = result;
1893 10 : depth++;
1894 10 : break;
1895 :
1896 243 : case CONDITIONAL_ACE_TOKEN_MEMBER_OF:
1897 : case CONDITIONAL_ACE_TOKEN_DEVICE_MEMBER_OF:
1898 : case CONDITIONAL_ACE_TOKEN_MEMBER_OF_ANY:
1899 : case CONDITIONAL_ACE_TOKEN_DEVICE_MEMBER_OF_ANY:
1900 : case CONDITIONAL_ACE_TOKEN_NOT_MEMBER_OF:
1901 : case CONDITIONAL_ACE_TOKEN_NOT_DEVICE_MEMBER_OF:
1902 : case CONDITIONAL_ACE_TOKEN_NOT_MEMBER_OF_ANY:
1903 : case CONDITIONAL_ACE_TOKEN_NOT_DEVICE_MEMBER_OF_ANY:
1904 243 : if (depth == 0) {
1905 0 : goto error;
1906 : }
1907 243 : depth--;
1908 243 : lhs = &program->stack[depth];
1909 243 : ok = member_lookup(token, tok, lhs, &result);
1910 243 : if (! ok) {
1911 0 : goto error;
1912 : }
1913 243 : program->stack[depth] = result;
1914 243 : depth++;
1915 243 : break;
1916 : /* binary relational operators */
1917 252 : case CONDITIONAL_ACE_TOKEN_EQUAL:
1918 : case CONDITIONAL_ACE_TOKEN_NOT_EQUAL:
1919 : case CONDITIONAL_ACE_TOKEN_LESS_THAN:
1920 : case CONDITIONAL_ACE_TOKEN_LESS_OR_EQUAL:
1921 : case CONDITIONAL_ACE_TOKEN_GREATER_THAN:
1922 : case CONDITIONAL_ACE_TOKEN_GREATER_OR_EQUAL:
1923 : case CONDITIONAL_ACE_TOKEN_CONTAINS:
1924 : case CONDITIONAL_ACE_TOKEN_ANY_OF:
1925 : case CONDITIONAL_ACE_TOKEN_NOT_CONTAINS:
1926 : case CONDITIONAL_ACE_TOKEN_NOT_ANY_OF:
1927 252 : if (depth < 2) {
1928 0 : goto error;
1929 : }
1930 252 : depth--;
1931 252 : rhs = &program->stack[depth];
1932 252 : depth--;
1933 252 : lhs = &program->stack[depth];
1934 252 : ok = relational_operator(token, tok, lhs, rhs, &result);
1935 252 : if (! ok) {
1936 22 : goto error;
1937 : }
1938 230 : program->stack[depth] = result;
1939 230 : depth++;
1940 230 : break;
1941 : /* unary logical operators */
1942 70 : case CONDITIONAL_ACE_TOKEN_EXISTS:
1943 : case CONDITIONAL_ACE_TOKEN_NOT_EXISTS:
1944 : case CONDITIONAL_ACE_TOKEN_NOT:
1945 70 : if (depth == 0) {
1946 0 : goto error;
1947 : }
1948 70 : depth--;
1949 70 : lhs = &program->stack[depth];
1950 70 : ok = unary_logic_operator(mem_ctx, token, tok, lhs, sd, &result);
1951 70 : if (!ok) {
1952 9 : goto error;
1953 : }
1954 61 : program->stack[depth] = result;
1955 61 : depth++;
1956 61 : break;
1957 : /* binary logical operators */
1958 22 : case CONDITIONAL_ACE_TOKEN_AND:
1959 : case CONDITIONAL_ACE_TOKEN_OR:
1960 22 : if (depth < 2) {
1961 0 : goto error;
1962 : }
1963 22 : depth--;
1964 22 : rhs = &program->stack[depth];
1965 22 : depth--;
1966 22 : lhs = &program->stack[depth];
1967 22 : ok = binary_logic_operator(token, tok, lhs, rhs, &result);
1968 22 : if (! ok) {
1969 13 : goto error;
1970 : }
1971 9 : program->stack[depth] = result;
1972 9 : depth++;
1973 9 : break;
1974 0 : default:
1975 0 : goto error;
1976 : }
1977 : }
1978 : /*
1979 : * The evaluation should have left a single result value (true, false,
1980 : * or unknown) on the stack. If not, the expression was malformed.
1981 : */
1982 482 : if (depth != 1) {
1983 0 : goto error;
1984 : }
1985 482 : result = program->stack[0];
1986 482 : if (result.type != CONDITIONAL_ACE_SAMBA_RESULT_BOOL) {
1987 18 : goto error;
1988 : }
1989 :
1990 464 : return result.data.result.value;
1991 :
1992 128 : error:
1993 : /*
1994 : * the result of an error is always UNKNOWN, which should be
1995 : * interpreted pessimistically, not allowing access.
1996 : */
1997 128 : return ACE_CONDITION_UNKNOWN;
1998 : }
1999 :
2000 :
2001 : /** access_check_conditional_ace()
2002 : *
2003 : * Run the conditional ACE from the blob form. Return false if it is
2004 : * not a valid conditional ACE, true if it is, even if there is some
2005 : * other error in running it. The *result parameter is set to
2006 : * ACE_CONDITION_FALSE, ACE_CONDITION_TRUE, or ACE_CONDITION_UNKNOWN.
2007 : *
2008 : * ACE_CONDITION_UNKNOWN should be treated pessimistically, as if it were
2009 : * TRUE for deny ACEs, and FALSE for allow ACEs.
2010 : *
2011 : * @param[in] ace - the ACE being processed.
2012 : * @param[in] token - the security token the ACE is processing.
2013 : * @param[out] result - a ternary result value.
2014 : *
2015 : * @return true if it is a valid conditional ACE.
2016 : */
2017 :
2018 597 : bool access_check_conditional_ace(const struct security_ace *ace,
2019 : const struct security_token *token,
2020 : const struct security_descriptor *sd,
2021 : int *result)
2022 : {
2023 597 : TALLOC_CTX *tmp_ctx = talloc_new(NULL);
2024 597 : struct ace_condition_script *program = NULL;
2025 597 : program = parse_conditional_ace(tmp_ctx, ace->coda.conditions);
2026 597 : if (program == NULL) {
2027 0 : *result = ACE_CONDITION_UNKNOWN;
2028 0 : TALLOC_FREE(tmp_ctx);
2029 0 : return false;
2030 : }
2031 :
2032 597 : *result = run_conditional_ace(tmp_ctx, token, program, sd);
2033 :
2034 597 : TALLOC_FREE(tmp_ctx);
2035 515 : return true;
2036 : }
2037 :
2038 :
2039 1372 : bool conditional_ace_encode_binary(TALLOC_CTX *mem_ctx,
2040 : struct ace_condition_script *program,
2041 : DATA_BLOB *dest)
2042 : {
2043 675 : size_t i, j, alloc_size, required_size;
2044 1372 : uint8_t *data = NULL;
2045 1372 : uint8_t *new_data = NULL;
2046 1372 : *dest = (DATA_BLOB){NULL, 0};
2047 :
2048 1372 : alloc_size = CONDITIONAL_ACE_MAX_LENGTH;
2049 1372 : data = talloc_array(mem_ctx,
2050 : uint8_t,
2051 : alloc_size);
2052 1372 : if (data == NULL) {
2053 0 : return false;
2054 : }
2055 :
2056 1372 : data[0] = 'a';
2057 1372 : data[1] = 'r';
2058 1372 : data[2] = 't';
2059 1372 : data[3] = 'x';
2060 :
2061 1372 : j = 4;
2062 6379 : for (i = 0; i < program->length; i++) {
2063 5007 : struct ace_condition_token *tok = &program->tokens[i];
2064 3234 : ssize_t consumed;
2065 3234 : bool ok;
2066 : /*
2067 : * In all cases we write the token type byte.
2068 : */
2069 5007 : data[j] = tok->type;
2070 5007 : j++;
2071 5007 : if (j >= alloc_size) {
2072 0 : DBG_ERR("program exceeds %zu bytes\n", alloc_size);
2073 0 : goto error;
2074 : }
2075 :
2076 5007 : switch (tok->type) {
2077 2120 : case CONDITIONAL_ACE_TOKEN_MEMBER_OF:
2078 : case CONDITIONAL_ACE_TOKEN_DEVICE_MEMBER_OF:
2079 : case CONDITIONAL_ACE_TOKEN_MEMBER_OF_ANY:
2080 : case CONDITIONAL_ACE_TOKEN_DEVICE_MEMBER_OF_ANY:
2081 : case CONDITIONAL_ACE_TOKEN_NOT_MEMBER_OF:
2082 : case CONDITIONAL_ACE_TOKEN_NOT_DEVICE_MEMBER_OF:
2083 : case CONDITIONAL_ACE_TOKEN_NOT_MEMBER_OF_ANY:
2084 : case CONDITIONAL_ACE_TOKEN_NOT_DEVICE_MEMBER_OF_ANY:
2085 : case CONDITIONAL_ACE_TOKEN_EQUAL:
2086 : case CONDITIONAL_ACE_TOKEN_NOT_EQUAL:
2087 : case CONDITIONAL_ACE_TOKEN_LESS_THAN:
2088 : case CONDITIONAL_ACE_TOKEN_LESS_OR_EQUAL:
2089 : case CONDITIONAL_ACE_TOKEN_GREATER_THAN:
2090 : case CONDITIONAL_ACE_TOKEN_GREATER_OR_EQUAL:
2091 : case CONDITIONAL_ACE_TOKEN_CONTAINS:
2092 : case CONDITIONAL_ACE_TOKEN_ANY_OF:
2093 : case CONDITIONAL_ACE_TOKEN_NOT_CONTAINS:
2094 : case CONDITIONAL_ACE_TOKEN_NOT_ANY_OF:
2095 : case CONDITIONAL_ACE_TOKEN_EXISTS:
2096 : case CONDITIONAL_ACE_TOKEN_NOT_EXISTS:
2097 : case CONDITIONAL_ACE_TOKEN_NOT:
2098 : case CONDITIONAL_ACE_TOKEN_AND:
2099 : case CONDITIONAL_ACE_TOKEN_OR:
2100 : /*
2101 : * All of these are simple operators that operate on
2102 : * the stack. We have already added the tok->type and
2103 : * there's nothing else to do.
2104 : */
2105 2120 : continue;
2106 :
2107 162 : case CONDITIONAL_ACE_TOKEN_INT8:
2108 : case CONDITIONAL_ACE_TOKEN_INT16:
2109 : case CONDITIONAL_ACE_TOKEN_INT32:
2110 : case CONDITIONAL_ACE_TOKEN_INT64:
2111 162 : ok = check_integer_range(tok);
2112 162 : if (! ok) {
2113 0 : goto error;
2114 : }
2115 162 : consumed = push_integer(data + j,
2116 : alloc_size - j,
2117 162 : &tok->data.int64);
2118 162 : break;
2119 1844 : case CONDITIONAL_ACE_LOCAL_ATTRIBUTE:
2120 : case CONDITIONAL_ACE_USER_ATTRIBUTE:
2121 : case CONDITIONAL_ACE_RESOURCE_ATTRIBUTE:
2122 : case CONDITIONAL_ACE_DEVICE_ATTRIBUTE:
2123 : case CONDITIONAL_ACE_TOKEN_UNICODE:
2124 1844 : consumed = push_unicode(data + j,
2125 : alloc_size - j,
2126 1844 : &tok->data.unicode);
2127 1844 : break;
2128 15 : case CONDITIONAL_ACE_TOKEN_OCTET_STRING:
2129 15 : consumed = push_bytes(data + j,
2130 : alloc_size - j,
2131 15 : &tok->data.bytes);
2132 15 : break;
2133 144 : case CONDITIONAL_ACE_TOKEN_SID:
2134 144 : consumed = push_sid(data + j,
2135 : alloc_size - j,
2136 144 : &tok->data.sid);
2137 144 : break;
2138 722 : case CONDITIONAL_ACE_TOKEN_COMPOSITE:
2139 722 : consumed = push_composite(data + j,
2140 : alloc_size - j,
2141 722 : &tok->data.composite);
2142 722 : break;
2143 :
2144 0 : default:
2145 0 : DBG_ERR("unknown token 0x%02x at position %zu\n",
2146 : tok->type, i);
2147 0 : goto error;
2148 : }
2149 2887 : if (consumed == -1) {
2150 0 : DBG_ERR("program exceeds %zu bytes\n", alloc_size);
2151 0 : goto error;
2152 : }
2153 2887 : j += consumed;
2154 2887 : if (j >= alloc_size) {
2155 0 : DBG_ERR("program exceeds %zu bytes\n", alloc_size);
2156 0 : goto error;
2157 : }
2158 : }
2159 : /* align to a 4 byte boundary */
2160 1372 : required_size = (j + 3) & ~((size_t)3);
2161 1372 : if (required_size > alloc_size) {
2162 0 : DBG_ERR("program exceeds %zu bytes\n", alloc_size);
2163 0 : goto error;
2164 : }
2165 3592 : while (j < required_size) {
2166 2220 : data[j] = 0;
2167 2220 : j++;
2168 : }
2169 1372 : new_data = talloc_realloc(mem_ctx,
2170 : data,
2171 : uint8_t,
2172 : required_size);
2173 1372 : if (new_data == NULL) {
2174 0 : goto error;
2175 : }
2176 1372 : data = new_data;
2177 :
2178 1372 : (*dest).data = data;
2179 1372 : (*dest).length = j;
2180 1372 : return true;
2181 0 : error:
2182 0 : TALLOC_FREE(data);
2183 0 : return false;
2184 : }
|