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 : #include "lib/util/stable_sort.h"
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 764 : static bool check_integer_range(const struct ace_condition_token *tok)
74 : {
75 764 : int64_t val = tok->data.int64.value;
76 764 : 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 108 : case CONDITIONAL_ACE_TOKEN_INT64:
93 : /* val has these limits naturally */
94 108 : break;
95 0 : default:
96 0 : return false;
97 : }
98 :
99 764 : if (tok->data.int64.base != CONDITIONAL_ACE_INT_BASE_8 &&
100 764 : 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 764 : if (tok->data.int64.sign != CONDITIONAL_ACE_INT_SIGN_POSITIVE &&
105 764 : tok->data.int64.sign != CONDITIONAL_ACE_INT_SIGN_NEGATIVE &&
106 108 : tok->data.int64.sign != CONDITIONAL_ACE_INT_SIGN_NONE) {
107 0 : return false;
108 : }
109 108 : return true;
110 : }
111 :
112 :
113 96 : static ssize_t pull_integer(TALLOC_CTX *mem_ctx,
114 : uint8_t *data, size_t length,
115 : struct ace_condition_int *tok)
116 : {
117 60 : ssize_t bytes_used;
118 60 : enum ndr_err_code ndr_err;
119 96 : DATA_BLOB v = data_blob_const(data, length);
120 96 : struct ndr_pull *ndr = ndr_pull_init_blob(&v, mem_ctx);
121 96 : if (ndr == NULL) {
122 0 : return -1;
123 : }
124 96 : ndr_err = ndr_pull_ace_condition_int(ndr, NDR_SCALARS|NDR_BUFFERS, tok);
125 96 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
126 0 : TALLOC_FREE(ndr);
127 0 : return -1;
128 : }
129 96 : bytes_used = ndr->offset;
130 96 : TALLOC_FREE(ndr);
131 96 : return bytes_used;
132 : }
133 :
134 668 : static ssize_t push_integer(uint8_t *data, size_t available,
135 : const struct ace_condition_int *tok)
136 : {
137 596 : enum ndr_err_code ndr_err;
138 596 : DATA_BLOB v;
139 668 : ndr_err = ndr_push_struct_blob(&v, NULL,
140 : tok,
141 : (ndr_push_flags_fn_t)ndr_push_ace_condition_int);
142 668 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
143 0 : return -1;
144 : }
145 668 : if (available < v.length) {
146 0 : talloc_free(v.data);
147 0 : return -1;
148 : }
149 668 : memcpy(data, v.data, v.length);
150 668 : talloc_free(v.data);
151 668 : return v.length;
152 : }
153 :
154 :
155 5129 : static ssize_t pull_unicode(TALLOC_CTX *mem_ctx,
156 : uint8_t *data, size_t length,
157 : struct ace_condition_unicode *tok)
158 : {
159 4499 : ssize_t bytes_used;
160 4499 : enum ndr_err_code ndr_err;
161 5129 : DATA_BLOB v = data_blob_const(data, length);
162 5129 : struct ndr_pull *ndr = ndr_pull_init_blob(&v, mem_ctx);
163 5129 : if (ndr == NULL) {
164 0 : return -1;
165 : }
166 5129 : ndr_err = ndr_pull_ace_condition_unicode(ndr, NDR_SCALARS|NDR_BUFFERS, tok);
167 5129 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
168 0 : TALLOC_FREE(ndr);
169 0 : return -1;
170 : }
171 5129 : bytes_used = ndr->offset;
172 5129 : TALLOC_FREE(ndr);
173 5129 : return bytes_used;
174 : }
175 :
176 7018 : static ssize_t push_unicode(uint8_t *data, size_t available,
177 : const struct ace_condition_unicode *tok)
178 : {
179 6160 : enum ndr_err_code ndr_err;
180 6160 : DATA_BLOB v;
181 7018 : ndr_err = ndr_push_struct_blob(&v, NULL,
182 : tok,
183 : (ndr_push_flags_fn_t)ndr_push_ace_condition_unicode);
184 7018 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
185 0 : return -1;
186 : }
187 7018 : if (available < v.length) {
188 0 : talloc_free(v.data);
189 0 : return -1;
190 : }
191 7018 : memcpy(data, v.data, v.length);
192 7018 : talloc_free(v.data);
193 7018 : 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 367 : static ssize_t pull_sid(TALLOC_CTX *mem_ctx,
247 : uint8_t *data, size_t length,
248 : struct ace_condition_sid *tok)
249 : {
250 100 : ssize_t bytes_used;
251 100 : enum ndr_err_code ndr_err;
252 367 : DATA_BLOB v = data_blob_const(data, length);
253 367 : struct ndr_pull *ndr = ndr_pull_init_blob(&v, mem_ctx);
254 367 : if (ndr == NULL) {
255 0 : return -1;
256 : }
257 367 : ndr->flags |= LIBNDR_FLAG_SUBCONTEXT_NO_UNREAD_BYTES;
258 :
259 367 : ndr_err = ndr_pull_ace_condition_sid(ndr, NDR_SCALARS|NDR_BUFFERS, tok);
260 367 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
261 0 : TALLOC_FREE(ndr);
262 0 : return -1;
263 : }
264 367 : bytes_used = ndr->offset;
265 367 : TALLOC_FREE(ndr);
266 367 : return bytes_used;
267 : }
268 :
269 785 : static ssize_t push_sid(uint8_t *data, size_t available,
270 : const struct ace_condition_sid *tok)
271 : {
272 487 : enum ndr_err_code ndr_err;
273 487 : DATA_BLOB v;
274 785 : ndr_err = ndr_push_struct_blob(&v, NULL,
275 : tok,
276 : (ndr_push_flags_fn_t)ndr_push_ace_condition_sid);
277 785 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
278 0 : return -1;
279 : }
280 785 : if (available < v.length) {
281 0 : talloc_free(v.data);
282 0 : return -1;
283 : }
284 785 : memcpy(data, v.data, v.length);
285 785 : talloc_free(v.data);
286 785 : return v.length;
287 : }
288 :
289 :
290 310 : static ssize_t pull_composite(TALLOC_CTX *mem_ctx,
291 : uint8_t *data, size_t length,
292 : struct ace_condition_composite *tok)
293 : {
294 132 : size_t i, j;
295 132 : size_t alloc_length;
296 132 : size_t byte_size;
297 310 : struct ace_condition_token *tokens = NULL;
298 310 : if (length < 4) {
299 0 : return -1;
300 : }
301 310 : byte_size = PULL_LE_U32(data, 0);
302 310 : if (byte_size > length - 4) {
303 0 : return -1;
304 : }
305 : /*
306 : * There is a list of other literal tokens (possibly including nested
307 : * composites), which we will store in an array.
308 : *
309 : * This array can *only* be literals.
310 : */
311 310 : alloc_length = byte_size;
312 310 : tokens = talloc_array(mem_ctx,
313 : struct ace_condition_token,
314 : alloc_length);
315 310 : if (tokens == NULL) {
316 0 : return -1;
317 : }
318 310 : byte_size += 4;
319 310 : i = 4;
320 310 : j = 0;
321 4887 : while (i < byte_size) {
322 4577 : struct ace_condition_token *el = &tokens[j];
323 4326 : ssize_t consumed;
324 4577 : uint8_t *el_data = NULL;
325 4326 : size_t available;
326 4326 : bool ok;
327 4577 : *el = (struct ace_condition_token) { .type = data[i] };
328 4577 : i++;
329 :
330 4577 : el_data = data + i;
331 4577 : available = byte_size - i;
332 :
333 4577 : switch (el->type) {
334 48 : case CONDITIONAL_ACE_TOKEN_INT8:
335 : case CONDITIONAL_ACE_TOKEN_INT16:
336 : case CONDITIONAL_ACE_TOKEN_INT32:
337 : case CONDITIONAL_ACE_TOKEN_INT64:
338 48 : consumed = pull_integer(mem_ctx,
339 : el_data,
340 : available,
341 : &el->data.int64);
342 48 : ok = check_integer_range(el);
343 48 : if (! ok) {
344 0 : goto error;
345 : }
346 22 : break;
347 4259 : case CONDITIONAL_ACE_TOKEN_UNICODE:
348 4259 : consumed = pull_unicode(mem_ctx,
349 : el_data,
350 : available,
351 : &el->data.unicode);
352 4259 : break;
353 :
354 0 : case CONDITIONAL_ACE_TOKEN_OCTET_STRING:
355 0 : consumed = pull_bytes(mem_ctx,
356 : el_data,
357 : available,
358 : &el->data.bytes);
359 0 : break;
360 :
361 270 : case CONDITIONAL_ACE_TOKEN_SID:
362 270 : consumed = pull_sid(mem_ctx,
363 : el_data,
364 : available,
365 : &el->data.sid);
366 270 : break;
367 :
368 0 : case CONDITIONAL_ACE_TOKEN_COMPOSITE:
369 0 : DBG_ERR("recursive composite tokens in conditional "
370 : "ACEs are not currently supported\n");
371 0 : goto error;
372 0 : default:
373 0 : goto error;
374 : }
375 :
376 4577 : if (consumed < 0 || consumed + i > length) {
377 0 : goto error;
378 : }
379 4577 : i += consumed;
380 4577 : j++;
381 4577 : if (j == UINT16_MAX) {
382 0 : talloc_free(tokens);
383 0 : return -1;
384 : }
385 4577 : if (j == alloc_length) {
386 0 : struct ace_condition_token *new_tokens = NULL;
387 :
388 0 : alloc_length += 5;
389 0 : new_tokens = talloc_realloc(mem_ctx,
390 : tokens,
391 : struct ace_condition_token,
392 : alloc_length);
393 :
394 0 : if (new_tokens == NULL) {
395 0 : goto error;
396 : }
397 0 : tokens = new_tokens;
398 : }
399 : }
400 310 : tok->n_members = j;
401 310 : tok->tokens = tokens;
402 310 : return byte_size;
403 0 : error:
404 0 : talloc_free(tokens);
405 0 : return -1;
406 : }
407 :
408 :
409 780 : static ssize_t push_composite(uint8_t *data, size_t length,
410 : const struct ace_condition_composite *tok)
411 : {
412 520 : size_t i;
413 520 : uint8_t *byte_length_ptr;
414 780 : size_t used = 0;
415 780 : if (length < 4) {
416 0 : return -1;
417 : }
418 : /*
419 : * We have no idea what the eventual length will be, so we keep a
420 : * pointer to write it in at the end.
421 : */
422 780 : byte_length_ptr = data;
423 780 : PUSH_LE_U32(data, 0, 0);
424 780 : used = 4;
425 :
426 6960 : for (i = 0; i < tok->n_members && used < length; i++) {
427 6180 : struct ace_condition_token *el = &tok->tokens[i];
428 5822 : ssize_t consumed;
429 6180 : uint8_t *el_data = NULL;
430 5822 : size_t available;
431 5822 : bool ok;
432 6180 : data[used] = el->type;
433 6180 : used++;
434 6180 : if (used == length) {
435 : /*
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.
439 : */
440 0 : return -1;
441 : }
442 6180 : el_data = data + used;
443 6180 : available = length - used;
444 :
445 6180 : switch (el->type) {
446 476 : case CONDITIONAL_ACE_TOKEN_INT8:
447 : case CONDITIONAL_ACE_TOKEN_INT16:
448 : case CONDITIONAL_ACE_TOKEN_INT32:
449 : case CONDITIONAL_ACE_TOKEN_INT64:
450 476 : ok = check_integer_range(el);
451 476 : if (! ok) {
452 0 : return -1;
453 : }
454 476 : consumed = push_integer(el_data,
455 : available,
456 476 : &el->data.int64);
457 476 : break;
458 5063 : case CONDITIONAL_ACE_TOKEN_UNICODE:
459 5063 : consumed = push_unicode(el_data,
460 : available,
461 5063 : &el->data.unicode);
462 5063 : break;
463 :
464 0 : case CONDITIONAL_ACE_TOKEN_OCTET_STRING:
465 0 : consumed = push_bytes(el_data,
466 : available,
467 0 : &el->data.bytes);
468 0 : break;
469 :
470 641 : case CONDITIONAL_ACE_TOKEN_SID:
471 641 : consumed = push_sid(el_data,
472 : available,
473 641 : &el->data.sid);
474 641 : break;
475 :
476 0 : case CONDITIONAL_ACE_TOKEN_COMPOSITE:
477 0 : consumed = push_composite(el_data,
478 : available,
479 0 : &el->data.composite);
480 0 : break;
481 :
482 0 : default:
483 0 : return -1;
484 : }
485 :
486 6180 : if (consumed < 0) {
487 0 : return -1;
488 : }
489 6180 : used += consumed;
490 : }
491 780 : if (used > length) {
492 0 : return -1;
493 : }
494 :
495 780 : PUSH_LE_U32(byte_length_ptr, 0, used - 4);
496 780 : return used;
497 : }
498 :
499 697 : static ssize_t pull_end_padding(uint8_t *data, size_t length)
500 : {
501 : /*
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,
506 : * 2, or 3.
507 : *
508 : * zero is also called CONDITIONAL_ACE_TOKEN_INVALID_OR_PADDING.
509 : */
510 206 : ssize_t i;
511 697 : if (length > 2) {
512 0 : return -1;
513 : }
514 1177 : for (i = 0; i < length; i++) {
515 480 : if (data[i] != 0) {
516 0 : return -1;
517 : }
518 : }
519 697 : return length;
520 : }
521 :
522 :
523 797 : struct ace_condition_script *parse_conditional_ace(TALLOC_CTX *mem_ctx,
524 : DATA_BLOB data)
525 : {
526 249 : size_t i, j;
527 797 : struct ace_condition_token *tokens = NULL;
528 249 : size_t alloc_length;
529 797 : struct ace_condition_script *program = NULL;
530 :
531 797 : if (data.length < 4 ||
532 797 : data.data[0] != 'a' ||
533 797 : data.data[1] != 'r' ||
534 797 : data.data[2] != 't' ||
535 797 : data.data[3] != 'x') {
536 : /*
537 : * lacks the "artx" conditional ace identifier magic.
538 : * NULL returns will deny access.
539 : */
540 0 : return NULL;
541 : }
542 797 : if (data.length > CONDITIONAL_ACE_MAX_LENGTH ||
543 797 : (data.length & 3) != 0) {
544 : /*
545 : * >= 64k or non-multiples of 4 are not possible in the ACE
546 : * wire format.
547 : */
548 0 : return NULL;
549 : }
550 :
551 797 : program = talloc(mem_ctx, struct ace_condition_script);
552 797 : if (program == NULL) {
553 0 : return NULL;
554 : }
555 :
556 : /*
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.
563 : *
564 : * This is all to say we're guessing a token length that hopes to
565 : * avoid reallocs without wasting too much up front.
566 : */
567 797 : alloc_length = data.length / 2 + 1;
568 797 : tokens = talloc_array(program,
569 : struct ace_condition_token,
570 : alloc_length);
571 797 : if (tokens == NULL) {
572 0 : TALLOC_FREE(program);
573 0 : return NULL;
574 : }
575 :
576 548 : i = 4;
577 548 : j = 0;
578 3749 : while(i < data.length) {
579 2952 : struct ace_condition_token *tok = &tokens[j];
580 2952 : ssize_t consumed = 0;
581 2952 : uint8_t *tok_data = NULL;
582 1055 : size_t available;
583 1055 : bool ok;
584 2952 : tok->type = data.data[i];
585 2952 : tok->flags = 0;
586 2952 : i++;
587 2952 : tok_data = data.data + i;
588 2952 : available = data.length - i;
589 :
590 2952 : switch (tok->type) {
591 48 : case CONDITIONAL_ACE_TOKEN_INT8:
592 : case CONDITIONAL_ACE_TOKEN_INT16:
593 : case CONDITIONAL_ACE_TOKEN_INT32:
594 : case CONDITIONAL_ACE_TOKEN_INT64:
595 48 : consumed = pull_integer(program,
596 : tok_data,
597 : available,
598 : &tok->data.int64);
599 48 : ok = check_integer_range(tok);
600 48 : if (! ok) {
601 0 : goto fail;
602 : }
603 14 : break;
604 870 : case CONDITIONAL_ACE_TOKEN_UNICODE:
605 : /*
606 : * The next four are pulled as unicode, but are
607 : * processed as user attribute look-ups.
608 : */
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 870 : consumed = pull_unicode(program,
614 : tok_data,
615 : available,
616 : &tok->data.unicode);
617 870 : break;
618 :
619 5 : case CONDITIONAL_ACE_TOKEN_OCTET_STRING:
620 5 : consumed = pull_bytes(program,
621 : tok_data,
622 : available,
623 : &tok->data.bytes);
624 5 : break;
625 :
626 97 : case CONDITIONAL_ACE_TOKEN_SID:
627 97 : consumed = pull_sid(program,
628 : tok_data,
629 : available,
630 : &tok->data.sid);
631 97 : break;
632 :
633 310 : case CONDITIONAL_ACE_TOKEN_COMPOSITE:
634 310 : consumed = pull_composite(program,
635 : tok_data,
636 : available,
637 : &tok->data.composite);
638 310 : break;
639 :
640 214 : 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:
648 : /*
649 : * these require a SID or composite SID list operand,
650 : * and we could check that now in most cases.
651 : */
652 214 : break;
653 : /* binary relational operators */
654 332 : 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:
671 332 : break;
672 491 : case CONDITIONAL_ACE_TOKEN_INVALID_OR_PADDING:
673 : /* this is only valid at the end */
674 697 : consumed = pull_end_padding(tok_data,
675 : available);
676 697 : j--; /* don't add this token */
677 697 : break;
678 0 : default:
679 0 : goto fail;
680 : }
681 :
682 2573 : if (consumed < 0) {
683 0 : goto fail;
684 : }
685 2952 : if (consumed + i < i || consumed + i > data.length) {
686 0 : goto fail;
687 : }
688 2952 : i += consumed;
689 2952 : j++;
690 2952 : if (j == alloc_length) {
691 0 : alloc_length *= 2;
692 0 : tokens = talloc_realloc(program,
693 : tokens,
694 : struct ace_condition_token,
695 : alloc_length);
696 0 : if (tokens == NULL) {
697 0 : goto fail;
698 : }
699 : }
700 : }
701 797 : program->length = j;
702 797 : program->tokens = talloc_realloc(program,
703 : tokens,
704 : struct ace_condition_token,
705 : program->length + 1);
706 797 : if (program->tokens == NULL) {
707 0 : goto fail;
708 : }
709 : /*
710 : * When interpreting the program we will need a stack, which in the
711 : * very worst case can be as deep as the program is long.
712 : */
713 797 : program->stack = talloc_array(program,
714 : struct ace_condition_token,
715 : program->length + 1);
716 797 : if (program->stack == NULL) {
717 0 : goto fail;
718 : }
719 :
720 548 : return program;
721 0 : fail:
722 0 : talloc_free(program);
723 0 : return NULL;
724 : }
725 :
726 :
727 512 : static bool claim_lookup_internal(
728 : TALLOC_CTX *mem_ctx,
729 : struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1 *claim,
730 : struct ace_condition_token *result)
731 : {
732 521 : bool ok = claim_v1_to_ace_token(mem_ctx, claim, result);
733 512 : return ok;
734 : }
735 :
736 :
737 15 : static bool resource_claim_lookup(
738 : TALLOC_CTX *mem_ctx,
739 : const struct ace_condition_token *op,
740 : const struct security_descriptor *sd,
741 : struct ace_condition_token *result)
742 : {
743 : /*
744 : * For a @Resource.attr, the claims come from a resource ACE
745 : * in the object's SACL. That's why we need a security descriptor.
746 : *
747 : * If there is no matching resource ACE, a NULL result is returned,
748 : * which should compare UNKNOWN to anything. The NULL will have the
749 : * CONDITIONAL_ACE_FLAG_NULL_MEANS_ERROR flag set if it seems failure
750 : * is not simply due to the sought claim not existing. This is useful for
751 : * the Exists and Not_Exists operators.
752 : */
753 15 : size_t i;
754 15 : struct ace_condition_unicode name;
755 :
756 15 : result->type = CONDITIONAL_ACE_SAMBA_RESULT_NULL;
757 :
758 15 : if (op->type != CONDITIONAL_ACE_RESOURCE_ATTRIBUTE) {
759 : /* what are we even doing here? */
760 0 : result->type = CONDITIONAL_ACE_SAMBA_RESULT_ERROR;
761 0 : return false;
762 : }
763 :
764 15 : name = op->data.resource_attr;
765 :
766 15 : if (sd->sacl == NULL) {
767 1 : DBG_NOTICE("Resource attribute ACE '%s' not found, "
768 : "because there is no SACL\n",
769 : name.value);
770 1 : return true;
771 : }
772 :
773 19 : for (i = 0; i < sd->sacl->num_aces; i++) {
774 14 : struct security_ace *ace = &sd->sacl->aces[i];
775 14 : bool ok;
776 :
777 14 : if (ace->type != SEC_ACE_TYPE_SYSTEM_RESOURCE_ATTRIBUTE) {
778 0 : continue;
779 : }
780 14 : if (strcasecmp_m(name.value,
781 : ace->coda.claim.name) != 0) {
782 5 : continue;
783 : }
784 : /* this is the one */
785 9 : ok = claim_lookup_internal(mem_ctx, &ace->coda.claim, result);
786 9 : if (ok) {
787 0 : return true;
788 : }
789 : }
790 5 : DBG_NOTICE("Resource attribute ACE '%s' not found.\n",
791 : name.value);
792 0 : return false;
793 : }
794 :
795 :
796 577 : static bool token_claim_lookup(
797 : TALLOC_CTX *mem_ctx,
798 : const struct security_token *token,
799 : const struct ace_condition_token *op,
800 : struct ace_condition_token *result)
801 : {
802 : /*
803 : * The operator has an attribute name; if there is a claim of
804 : * the right type with that name, that is returned as the result.
805 : *
806 : * XXX what happens otherwise? NULL result?
807 : */
808 577 : struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1 *claims = NULL;
809 114 : size_t num_claims;
810 114 : bool ok;
811 577 : const struct ace_condition_unicode *name = NULL;
812 114 : size_t i;
813 :
814 577 : result->type = CONDITIONAL_ACE_SAMBA_RESULT_NULL;
815 :
816 577 : switch (op->type) {
817 0 : case CONDITIONAL_ACE_LOCAL_ATTRIBUTE:
818 0 : claims = token->local_claims;
819 0 : num_claims = token->num_local_claims;
820 0 : name = &op->data.local_attr;
821 0 : break;
822 525 : case CONDITIONAL_ACE_USER_ATTRIBUTE:
823 525 : claims = token->user_claims;
824 525 : num_claims = token->num_user_claims;
825 525 : name = &op->data.user_attr;
826 525 : break;
827 52 : case CONDITIONAL_ACE_DEVICE_ATTRIBUTE:
828 52 : claims = token->device_claims;
829 52 : num_claims = token->num_device_claims;
830 52 : name = &op->data.device_attr;
831 52 : break;
832 0 : default:
833 0 : DBG_WARNING("Conditional ACE claim lookup got bad arg type %u\n",
834 : op->type);
835 0 : result->type = CONDITIONAL_ACE_SAMBA_RESULT_ERROR;
836 0 : return false;
837 : }
838 :
839 577 : if (num_claims == 0) {
840 68 : DBG_NOTICE("There are no type %u claims\n", op->type);
841 68 : return false;
842 : }
843 509 : if (claims == NULL) {
844 0 : DBG_ERR("Type %u claim list unexpectedly NULL!\n", op->type);
845 0 : result->type = CONDITIONAL_ACE_SAMBA_RESULT_ERROR;
846 0 : return false;
847 : }
848 : /*
849 : * Loop backwards: a later claim will override an earlier one with the
850 : * same name.
851 : */
852 1060 : for (i = num_claims - 1; i < num_claims; i--) {
853 1054 : if (claims[i].name == NULL) {
854 0 : DBG_ERR("claim %zu has no name!\n", i);
855 0 : continue;
856 : }
857 1054 : if (strcasecmp_m(claims[i].name, name->value) == 0) {
858 : /* this is the one */
859 503 : ok = claim_lookup_internal(mem_ctx, &claims[i], result);
860 503 : return ok;
861 : }
862 : }
863 6 : DBG_NOTICE("Claim not found\n");
864 4 : return false;
865 : }
866 :
867 :
868 :
869 :
870 249 : static bool member_lookup(
871 : const struct security_token *token,
872 : const struct ace_condition_token *op,
873 : const struct ace_condition_token *arg,
874 : struct ace_condition_token *result)
875 : {
876 : /*
877 : * We need to compare the lists of SIDs in the token with the
878 : * SID[s] in the argument. There are 8 combinations of
879 : * operation, depending on whether we want to match all or any
880 : * of the SIDs, whether we're using the device SIDs or user
881 : * SIDs, and whether the operator name starts with "Not_".
882 : *
883 : * _MEMBER_OF User has all operand SIDs
884 : * _DEVICE_MEMBER_OF Device has all operand SIDs
885 : * _MEMBER_OF_ANY User has one or more operand SIDs
886 : * _DEVICE_MEMBER_OF_ANY Device has one or more operand SIDs
887 : *
888 : * NOT_* has the effect of !(the operator without NOT_).
889 : *
890 : * The operand can either be a composite of SIDs or a single SID.
891 : * This adds an additional branch.
892 : */
893 249 : bool match = false;
894 46 : bool it_is_a_not_op;
895 46 : bool it_is_an_any_op;
896 46 : bool it_is_a_device_op;
897 46 : bool arg_is_a_single_sid;
898 249 : struct dom_sid *sid_array = NULL;
899 46 : size_t num_sids, i, j;
900 249 : const struct dom_sid *sid = NULL;
901 :
902 249 : result->type = CONDITIONAL_ACE_SAMBA_RESULT_BOOL;
903 249 : result->data.result.value = ACE_CONDITION_UNKNOWN;
904 :
905 249 : switch (arg->type) {
906 86 : case CONDITIONAL_ACE_TOKEN_SID:
907 86 : arg_is_a_single_sid = true;
908 86 : break;
909 160 : case CONDITIONAL_ACE_TOKEN_COMPOSITE:
910 160 : arg_is_a_single_sid = false;
911 160 : break;
912 0 : default:
913 0 : DBG_WARNING("Conditional ACE Member_Of got bad arg type %u\n",
914 : arg->type);
915 0 : return false;
916 : }
917 :
918 249 : switch (op->type) {
919 24 : case CONDITIONAL_ACE_TOKEN_NOT_MEMBER_OF:
920 : case CONDITIONAL_ACE_TOKEN_NOT_MEMBER_OF_ANY:
921 24 : it_is_a_not_op = true;
922 24 : it_is_a_device_op = false;
923 24 : break;
924 14 : case CONDITIONAL_ACE_TOKEN_NOT_DEVICE_MEMBER_OF_ANY:
925 : case CONDITIONAL_ACE_TOKEN_NOT_DEVICE_MEMBER_OF:
926 14 : it_is_a_not_op = true;
927 14 : it_is_a_device_op = true;
928 14 : break;
929 150 : case CONDITIONAL_ACE_TOKEN_MEMBER_OF:
930 : case CONDITIONAL_ACE_TOKEN_MEMBER_OF_ANY:
931 150 : it_is_a_not_op = false;
932 150 : it_is_a_device_op = false;
933 150 : break;
934 56 : case CONDITIONAL_ACE_TOKEN_DEVICE_MEMBER_OF_ANY:
935 : case CONDITIONAL_ACE_TOKEN_DEVICE_MEMBER_OF:
936 56 : it_is_a_not_op = false;
937 56 : it_is_a_device_op = true;
938 56 : break;
939 0 : default:
940 0 : DBG_WARNING("Conditional ACE Member_Of got bad op type %u\n",
941 : op->type);
942 0 : return false;
943 : }
944 :
945 249 : switch (op->type) {
946 16 : case CONDITIONAL_ACE_TOKEN_NOT_MEMBER_OF_ANY:
947 : case CONDITIONAL_ACE_TOKEN_NOT_DEVICE_MEMBER_OF_ANY:
948 : case CONDITIONAL_ACE_TOKEN_MEMBER_OF_ANY:
949 : case CONDITIONAL_ACE_TOKEN_DEVICE_MEMBER_OF_ANY:
950 16 : it_is_an_any_op = true;
951 16 : break;
952 226 : default:
953 226 : it_is_an_any_op = false;
954 : }
955 :
956 249 : if (it_is_a_device_op) {
957 70 : sid_array = token->device_sids;
958 70 : num_sids = token->num_device_sids;
959 : } else {
960 179 : sid_array = token->sids;
961 179 : num_sids = token->num_sids;
962 : }
963 :
964 249 : if (arg_is_a_single_sid) {
965 : /*
966 : * In this case the any and all operations are the
967 : * same.
968 : */
969 89 : sid = &arg->data.sid.sid;
970 89 : match = false;
971 433 : for (i = 0; i < num_sids; i++) {
972 395 : match = dom_sid_equal(sid, &sid_array[i]);
973 395 : if (match) {
974 48 : break;
975 : }
976 : }
977 89 : if (it_is_a_not_op) {
978 6 : match = ! match;
979 : }
980 89 : if (match) {
981 57 : result->data.result.value = ACE_CONDITION_TRUE;
982 : } else {
983 32 : result->data.result.value = ACE_CONDITION_FALSE;
984 : }
985 89 : return true;
986 : }
987 :
988 : /* This is a composite list (hopefully of SIDs) */
989 160 : if (arg->data.composite.n_members == 0) {
990 0 : DBG_WARNING("Conditional ACE Member_Of argument is empty\n");
991 0 : return false;
992 : }
993 :
994 289 : for (j = 0; j < arg->data.composite.n_members; j++) {
995 191 : const struct ace_condition_token *member =
996 191 : &arg->data.composite.tokens[j];
997 191 : if (member->type != CONDITIONAL_ACE_TOKEN_SID) {
998 0 : DBG_WARNING("Conditional ACE Member_Of argument contains "
999 : "non-sid element [%zu]: %u\n",
1000 : j, member->type);
1001 0 : return false;
1002 : }
1003 191 : sid = &member->data.sid.sid;
1004 191 : match = false;
1005 963 : for (i = 0; i < num_sids; i++) {
1006 887 : match = dom_sid_equal(sid, &sid_array[i]);
1007 887 : if (match) {
1008 88 : break;
1009 : }
1010 : }
1011 191 : if (it_is_an_any_op) {
1012 38 : if (match) {
1013 : /* we have matched one SID, which is enough */
1014 12 : goto apply_not;
1015 : }
1016 : } else { /* an all op */
1017 153 : if (! match) {
1018 : /* failing one is enough */
1019 50 : goto apply_not;
1020 : }
1021 : }
1022 : }
1023 : /*
1024 : * Reaching the end of that loop means either:
1025 : * 1. it was an ALL op and we never failed to find one, or
1026 : * 2. it was an ANY op, and we didn't find one.
1027 : */
1028 98 : match = !it_is_an_any_op;
1029 :
1030 160 : apply_not:
1031 160 : if (it_is_a_not_op) {
1032 37 : match = ! match;
1033 : }
1034 160 : if (match) {
1035 91 : result->data.result.value = ACE_CONDITION_TRUE;
1036 : } else {
1037 69 : result->data.result.value = ACE_CONDITION_FALSE;
1038 : }
1039 :
1040 117 : return true;
1041 : }
1042 :
1043 :
1044 79 : static bool ternary_value(
1045 : const struct ace_condition_token *arg,
1046 : struct ace_condition_token *result)
1047 : {
1048 : /*
1049 : * Find the truth value of the argument, stored in the result token.
1050 : *
1051 : * A return value of false means the operation is invalid, and the
1052 : * result is undefined.
1053 : */
1054 79 : if (arg->type == CONDITIONAL_ACE_SAMBA_RESULT_BOOL) {
1055 : /* pass through */
1056 79 : *result = *arg;
1057 79 : return true;
1058 : }
1059 :
1060 0 : result->type = CONDITIONAL_ACE_SAMBA_RESULT_BOOL;
1061 0 : result->data.result.value = ACE_CONDITION_UNKNOWN;
1062 :
1063 0 : if (IS_INT_TOKEN(arg)) {
1064 : /* zero is false */
1065 0 : if (arg->data.int64.value == 0) {
1066 0 : result->data.result.value = ACE_CONDITION_FALSE;
1067 : } else {
1068 0 : result->data.result.value = ACE_CONDITION_TRUE;
1069 : }
1070 0 : return true;
1071 : }
1072 0 : if (arg->type == CONDITIONAL_ACE_TOKEN_UNICODE) {
1073 : /* empty is false */
1074 0 : if (arg->data.unicode.value[0] == '\0') {
1075 0 : result->data.result.value = ACE_CONDITION_FALSE;
1076 : } else {
1077 0 : result->data.result.value = ACE_CONDITION_TRUE;
1078 : }
1079 0 : return true;
1080 : }
1081 :
1082 : /*
1083 : * everything else in UNKNOWN. This includes NULL values (i.e. an
1084 : * unsuccessful look-up).
1085 : */
1086 0 : result->data.result.value = ACE_CONDITION_UNKNOWN;
1087 0 : return true;
1088 : }
1089 :
1090 70 : static bool not_operator(
1091 : const struct ace_condition_token *arg,
1092 : struct ace_condition_token *result)
1093 : {
1094 61 : bool ok;
1095 70 : if (IS_LITERAL_TOKEN(arg)) {
1096 : /*
1097 : * Logic operators don't work on literals.
1098 : */
1099 9 : return false;
1100 : }
1101 :
1102 61 : ok = ternary_value(arg, result);
1103 61 : if (! ok) {
1104 0 : return false;
1105 : }
1106 61 : if (result->data.result.value == ACE_CONDITION_FALSE) {
1107 31 : result->data.result.value = ACE_CONDITION_TRUE;
1108 30 : } else if (result->data.result.value == ACE_CONDITION_TRUE) {
1109 30 : result->data.result.value = ACE_CONDITION_FALSE;
1110 : }
1111 : /* unknown stays unknown */
1112 0 : return true;
1113 : }
1114 :
1115 :
1116 70 : static bool unary_logic_operator(
1117 : TALLOC_CTX *mem_ctx,
1118 : const struct security_token *token,
1119 : const struct ace_condition_token *op,
1120 : const struct ace_condition_token *arg,
1121 : const struct security_descriptor *sd,
1122 : struct ace_condition_token *result)
1123 : {
1124 :
1125 61 : bool ok;
1126 61 : bool found;
1127 70 : struct ace_condition_token claim = {
1128 : .type = CONDITIONAL_ACE_SAMBA_RESULT_ERROR
1129 : };
1130 70 : if (op->type == CONDITIONAL_ACE_TOKEN_NOT) {
1131 70 : return not_operator(arg, result);
1132 : }
1133 0 : result->type = CONDITIONAL_ACE_SAMBA_RESULT_BOOL;
1134 0 : result->data.result.value = ACE_CONDITION_UNKNOWN;
1135 :
1136 : /*
1137 : * Not_Exists and Exists require the same work, except we negate the
1138 : * answer in one case. From [MS-DTYP] 2.4.4.17.7:
1139 : *
1140 : * If the type of the operand is "Local Attribute"
1141 : * If the value is non-null return TRUE
1142 : * Else return FALSE
1143 : * Else if the type of the operand is "Resource Attribute"
1144 : * Return TRUE if value is non-null; FALSE otherwise.
1145 : * Else return Error
1146 : */
1147 0 : switch (op->type) {
1148 0 : case CONDITIONAL_ACE_LOCAL_ATTRIBUTE:
1149 0 : ok = token_claim_lookup(mem_ctx, token, arg, &claim);
1150 : /*
1151 : * "not ok" usually means a failure to find the attribute,
1152 : * which is the false condition and not an error.
1153 : *
1154 : * XXX or do we need an extra flag?
1155 : */
1156 0 : break;
1157 0 : case CONDITIONAL_ACE_RESOURCE_ATTRIBUTE:
1158 0 : ok = resource_claim_lookup(mem_ctx, arg, sd, &claim);
1159 0 : break;
1160 0 : default:
1161 0 : return false;
1162 : }
1163 :
1164 : /*
1165 : *
1166 : */
1167 :
1168 0 : if (claim.type != CONDITIONAL_ACE_SAMBA_RESULT_NULL) {
1169 0 : found = true;
1170 0 : } else if (ok) {
1171 0 : found = false;
1172 : } else {
1173 0 : return false;
1174 : }
1175 :
1176 :
1177 :
1178 0 : if (op->type == CONDITIONAL_ACE_TOKEN_NOT_EXISTS) {
1179 0 : found = ! found;
1180 0 : } else if (op->type != CONDITIONAL_ACE_TOKEN_EXISTS) {
1181 : /* should not get here */
1182 0 : return false;
1183 : }
1184 :
1185 0 : result->data.result.value = found ? ACE_CONDITION_TRUE: ACE_CONDITION_FALSE;
1186 0 : return true;
1187 : }
1188 :
1189 :
1190 :
1191 22 : static bool binary_logic_operator(
1192 : const struct security_token *token,
1193 : const struct ace_condition_token *op,
1194 : const struct ace_condition_token *lhs,
1195 : const struct ace_condition_token *rhs,
1196 : struct ace_condition_token *result)
1197 : {
1198 9 : struct ace_condition_token at, bt;
1199 9 : int a, b;
1200 9 : bool ok;
1201 :
1202 22 : result->type = CONDITIONAL_ACE_SAMBA_RESULT_BOOL;
1203 22 : result->data.result.value = ACE_CONDITION_UNKNOWN;
1204 :
1205 22 : if (IS_LITERAL_TOKEN(lhs) || IS_LITERAL_TOKEN(rhs)) {
1206 : /*
1207 : * Logic operators don't work on literals.
1208 : */
1209 13 : return false;
1210 : }
1211 :
1212 9 : ok = ternary_value(lhs, &at);
1213 9 : if (! ok) {
1214 0 : return false;
1215 : }
1216 9 : ok = ternary_value(rhs, &bt);
1217 9 : if (! ok) {
1218 0 : return false;
1219 : }
1220 9 : a = at.data.result.value;
1221 9 : b = bt.data.result.value;
1222 :
1223 9 : if (op->type == CONDITIONAL_ACE_TOKEN_AND) {
1224 : /*
1225 : * AND true false unknown
1226 : * true T F ?
1227 : * false F F F
1228 : * unknown ? F ?
1229 : *
1230 : * unknown unless BOTH true or EITHER false
1231 : */
1232 5 : if (a == ACE_CONDITION_TRUE &&
1233 5 : b == ACE_CONDITION_TRUE) {
1234 2 : result->data.result.value = ACE_CONDITION_TRUE;
1235 2 : return true;
1236 : }
1237 3 : if (a == ACE_CONDITION_FALSE ||
1238 3 : b == ACE_CONDITION_FALSE) {
1239 3 : result->data.result.value = ACE_CONDITION_FALSE;
1240 3 : return true;
1241 : }
1242 : /*
1243 : * Neither value is False, so the result is Unknown,
1244 : * as set at the start of this function.
1245 : */
1246 0 : return true;
1247 : }
1248 : /*
1249 : * OR true false unknown
1250 : * true T T T
1251 : * false T F ?
1252 : * unknown T ? ?
1253 : *
1254 : * unknown unless EITHER true or BOTH false
1255 : */
1256 4 : if (a == ACE_CONDITION_TRUE ||
1257 4 : b == ACE_CONDITION_TRUE) {
1258 3 : result->data.result.value = ACE_CONDITION_TRUE;
1259 3 : return true;
1260 : }
1261 1 : if (a == ACE_CONDITION_FALSE &&
1262 : b == ACE_CONDITION_FALSE) {
1263 1 : result->data.result.value = ACE_CONDITION_FALSE;
1264 1 : return true;
1265 : }
1266 0 : return true;
1267 : }
1268 :
1269 :
1270 21 : static bool tokens_are_comparable(const struct ace_condition_token *op,
1271 : const struct ace_condition_token *lhs,
1272 : const struct ace_condition_token *rhs)
1273 : {
1274 10 : uint64_t n;
1275 : /*
1276 : * we can't compare different types *unless* they are both
1277 : * integers, or one is a bool and the other is an integer 0 or
1278 : * 1, and the operator is == or != (or NULL, which for convenience,
1279 : * is treated as ==).
1280 : */
1281 : //XXX actually it says "literal integers", do we need to check flags?
1282 21 : if (lhs->type == rhs->type) {
1283 2 : return true;
1284 : }
1285 :
1286 19 : if (IS_INT_TOKEN(lhs) && IS_INT_TOKEN(rhs)) {
1287 : /* don't block e.g. comparing an int32 to an int64 */
1288 0 : return true;
1289 : }
1290 :
1291 : /* is it == or != */
1292 19 : if (op != NULL &&
1293 19 : op->type != CONDITIONAL_ACE_TOKEN_EQUAL &&
1294 2 : op->type != CONDITIONAL_ACE_TOKEN_NOT_EQUAL) {
1295 0 : return false;
1296 : }
1297 : /* is one a bool and the other an int? */
1298 11 : if (IS_INT_TOKEN(lhs) && IS_BOOL_TOKEN(rhs)) {
1299 0 : n = lhs->data.int64.value;
1300 11 : } else if (IS_INT_TOKEN(rhs) && IS_BOOL_TOKEN(lhs)) {
1301 0 : n = rhs->data.int64.value;
1302 : } else {
1303 9 : return false;
1304 : }
1305 0 : if (n == 0 || n == 1) {
1306 0 : return true;
1307 : }
1308 0 : return false;
1309 : }
1310 :
1311 :
1312 206 : static bool cmp_to_result(const struct ace_condition_token *op,
1313 : struct ace_condition_token *result,
1314 : int cmp)
1315 : {
1316 57 : bool answer;
1317 206 : switch (op->type) {
1318 141 : case CONDITIONAL_ACE_TOKEN_EQUAL:
1319 141 : answer = cmp == 0;
1320 141 : break;
1321 17 : case CONDITIONAL_ACE_TOKEN_NOT_EQUAL:
1322 17 : answer = cmp != 0;
1323 17 : break;
1324 25 : case CONDITIONAL_ACE_TOKEN_LESS_THAN:
1325 25 : answer = cmp < 0;
1326 25 : break;
1327 4 : case CONDITIONAL_ACE_TOKEN_LESS_OR_EQUAL:
1328 4 : answer = cmp <= 0;
1329 4 : break;
1330 14 : case CONDITIONAL_ACE_TOKEN_GREATER_THAN:
1331 14 : answer = cmp > 0;
1332 14 : break;
1333 5 : case CONDITIONAL_ACE_TOKEN_GREATER_OR_EQUAL:
1334 5 : answer = cmp >= 0;
1335 5 : break;
1336 0 : default:
1337 0 : result->data.result.value = ACE_CONDITION_UNKNOWN;
1338 0 : return false;
1339 : }
1340 206 : result->data.result.value = \
1341 206 : answer ? ACE_CONDITION_TRUE : ACE_CONDITION_FALSE;
1342 206 : return true;
1343 : }
1344 :
1345 :
1346 :
1347 31278 : static bool compare_unicode(const struct ace_condition_token *op,
1348 : const struct ace_condition_token *lhs,
1349 : const struct ace_condition_token *rhs,
1350 : int *cmp)
1351 : {
1352 31278 : struct ace_condition_unicode a = lhs->data.unicode;
1353 31278 : struct ace_condition_unicode b = rhs->data.unicode;
1354 : /*
1355 : * Comparison is case-insensitive UNLESS the claim structure
1356 : * has the case-sensitive flag, which is passed through as a
1357 : * flag on the token. Usually only the LHS is a claim value,
1358 : * but in the event that they both are, we allow either to
1359 : * request case-sensitivity.
1360 : *
1361 : * For greater than and less than, the sort order is utf-8 order,
1362 : * which is not exactly what Windows does, but we don't sort like
1363 : * Windows does anywhere else either.
1364 : */
1365 31278 : uint8_t flags = lhs->flags | rhs->flags;
1366 31278 : if (flags & CLAIM_SECURITY_ATTRIBUTE_VALUE_CASE_SENSITIVE) {
1367 19 : *cmp = strcmp(a.value, b.value);
1368 : } else {
1369 31259 : *cmp = strcasecmp_m(a.value, b.value);
1370 : }
1371 31278 : return true;
1372 : }
1373 :
1374 :
1375 0 : static bool compare_bytes(const struct ace_condition_token *op,
1376 : const struct ace_condition_token *lhs,
1377 : const struct ace_condition_token *rhs,
1378 : int *cmp)
1379 : {
1380 0 : DATA_BLOB a = lhs->data.bytes;
1381 0 : DATA_BLOB b = rhs->data.bytes;
1382 0 : *cmp = data_blob_cmp(&a, &b);
1383 0 : return true;
1384 : }
1385 :
1386 :
1387 14 : static bool compare_sids(const struct ace_condition_token *op,
1388 : const struct ace_condition_token *lhs,
1389 : const struct ace_condition_token *rhs,
1390 : int *cmp)
1391 : {
1392 28 : *cmp = dom_sid_compare(&lhs->data.sid.sid,
1393 : &rhs->data.sid.sid);
1394 14 : return true;
1395 : }
1396 :
1397 :
1398 34 : static bool compare_ints(const struct ace_condition_token *op,
1399 : const struct ace_condition_token *lhs,
1400 : const struct ace_condition_token *rhs,
1401 : int *cmp)
1402 : {
1403 34 : int64_t a = lhs->data.int64.value;
1404 34 : int64_t b = rhs->data.int64.value;
1405 :
1406 34 : if (a < b) {
1407 6 : *cmp = -1;
1408 28 : } else if (a == b) {
1409 15 : *cmp = 0;
1410 : } else {
1411 13 : *cmp = 1;
1412 : }
1413 32 : return true;
1414 : }
1415 :
1416 :
1417 0 : static bool compare_bools(const struct ace_condition_token *op,
1418 : const struct ace_condition_token *lhs,
1419 : const struct ace_condition_token *rhs,
1420 : int *cmp)
1421 : {
1422 0 : bool ok;
1423 0 : struct ace_condition_token a, b;
1424 0 : *cmp = -1;
1425 :
1426 0 : if (IS_LITERAL_TOKEN(lhs)) {
1427 : /*
1428 : * we can compare a boolean LHS to a literal RHS, but not
1429 : * vice versa
1430 : */
1431 0 : return false;
1432 : }
1433 0 : ok = ternary_value(lhs, &a);
1434 0 : if (! ok) {
1435 0 : return false;
1436 : }
1437 0 : ok = ternary_value(rhs, &b);
1438 0 : if (! ok) {
1439 0 : return false;
1440 : }
1441 0 : if (a.data.result.value == ACE_CONDITION_UNKNOWN ||
1442 0 : b.data.result.value == ACE_CONDITION_UNKNOWN) {
1443 0 : return false;
1444 : }
1445 :
1446 0 : switch (op->type) {
1447 0 : case CONDITIONAL_ACE_TOKEN_EQUAL:
1448 : case CONDITIONAL_ACE_TOKEN_NOT_EQUAL:
1449 0 : *cmp = a.data.result.value - b.data.result.value;
1450 0 : break;
1451 0 : default:
1452 : /* we are not allowing non-equality comparisons with bools */
1453 0 : return false;
1454 : }
1455 0 : return true;
1456 : }
1457 :
1458 :
1459 : static bool simple_relational_operator(const struct ace_condition_token *op,
1460 : const struct ace_condition_token *lhs,
1461 : const struct ace_condition_token *rhs,
1462 : int *cmp);
1463 :
1464 :
1465 : struct composite_sort_context {
1466 : bool failed;
1467 : };
1468 :
1469 25835 : static int composite_sort_cmp(const struct ace_condition_token *lhs,
1470 : const struct ace_condition_token *rhs,
1471 : struct composite_sort_context *ctx)
1472 : {
1473 25816 : bool ok;
1474 25835 : int cmp = -1;
1475 : /*
1476 : * simple_relational_operator uses the operator token only to
1477 : * decide whether the comparison is allowed for the type. In
1478 : * particular, boolean result and composite arguments can only
1479 : * be used with equality operators. We want those to fail (we
1480 : * should not see them here, remembering that claim booleans
1481 : * become composite integers), so we use a non-equality op.
1482 : */
1483 25816 : static const struct ace_condition_token op = {
1484 : .type = CONDITIONAL_ACE_TOKEN_LESS_THAN
1485 : };
1486 :
1487 25835 : ok = simple_relational_operator(&op, lhs, rhs, &cmp);
1488 25835 : if (ok) {
1489 25827 : return cmp;
1490 : }
1491 : /*
1492 : * This sort isn't going to work out, but the sort function
1493 : * will only find out at the end.
1494 : */
1495 8 : ctx->failed = true;
1496 8 : return cmp;
1497 : }
1498 :
1499 :
1500 : /*
1501 : * Return a sorted copy of the composite tokens array.
1502 : *
1503 : * The copy is shallow, so the actual string pointers are the same, which is
1504 : * fine for the purposes of comparison.
1505 : */
1506 :
1507 59 : static struct ace_condition_token *composite_sorted_copy(
1508 : TALLOC_CTX *mem_ctx,
1509 : const struct ace_condition_composite *c,
1510 : bool case_sensitive)
1511 : {
1512 59 : struct ace_condition_token *copy = NULL;
1513 46 : bool ok;
1514 46 : size_t i;
1515 59 : struct composite_sort_context sort_ctx = {
1516 : .failed = false
1517 : };
1518 :
1519 : /*
1520 : * Case sensitivity is a bit tricky. Each token can have a flag saying
1521 : * it should be sorted case-sensitively and when comparing two tokens,
1522 : * we should respect this flag on either side. The flag can only come
1523 : * from claims (including resource attribute ACEs), and as there is only
1524 : * one flag per claim, it must apply the same to all members (in fact we
1525 : * don't set it on the members, only the composite). So to be sure we
1526 : * sort in the way we want, we might need to set the flag on all the
1527 : * members of the copy *before* sorting it.
1528 : *
1529 : * When it comes to comparing two composites, we want to be
1530 : * case-sensitive if either side has the flag. This can have odd
1531 : * effects. Think of these RA claims:
1532 : *
1533 : * (RA;;;;;WD;("foo",TS,0,"a","A"))
1534 : * (RA;;;;;WD;("bar",TS,2,"a","A")) <-- 2 is the case-sensitive flag
1535 : * (RA;;;;;WD;("baz",TS,0,"a"))
1536 : *
1537 : * (@Resource.foo == @Resource.bar) is true
1538 : * (@Resource.bar == @Resource.foo) is true
1539 : * (@Resource.bar == @Resource.bar) is true
1540 : * (@Resource.foo == @Resource.foo) is an error (duplicate values on LHS)
1541 : * (@Resource.baz == @Resource.foo) is true (RHS case-folds down)
1542 : * (@Resource.baz == @Resource.bar) is false
1543 : * (@Resource.bar == {"A", "a"}) is true
1544 : * (@Resource.baz == {"A", "a"}) is true
1545 : * (@Resource.foo == {"A", "a"}) is an error
1546 : */
1547 59 : copy = talloc_array(mem_ctx, struct ace_condition_token, c->n_members);
1548 59 : if (copy == NULL) {
1549 0 : return NULL;
1550 : }
1551 59 : memcpy(copy, c->tokens, sizeof(struct ace_condition_token) * c->n_members);
1552 :
1553 59 : if (case_sensitive) {
1554 246 : for (i = 0; i < c->n_members; i++) {
1555 238 : c->tokens[i].flags |= CLAIM_SECURITY_ATTRIBUTE_VALUE_CASE_SENSITIVE;
1556 : }
1557 : }
1558 :
1559 105 : ok = stable_sort_talloc_r(mem_ctx,
1560 : copy,
1561 59 : c->n_members,
1562 : sizeof(struct ace_condition_token),
1563 : (samba_compare_with_context_fn_t)composite_sort_cmp,
1564 : &sort_ctx);
1565 :
1566 59 : if (!ok || sort_ctx.failed) {
1567 3 : DBG_NOTICE("composite sort of %"PRIu32" members failed\n",
1568 : c->n_members);
1569 3 : TALLOC_FREE(copy);
1570 3 : return NULL;
1571 : }
1572 13 : return copy;
1573 : }
1574 :
1575 :
1576 : /*
1577 : * This is a helper for compare composites.
1578 : */
1579 76 : static bool compare_composites_via_sort(const struct ace_condition_token *lhs,
1580 : const struct ace_condition_token *rhs,
1581 : int *cmp)
1582 : {
1583 76 : const struct ace_condition_composite *lc = &lhs->data.composite;
1584 76 : const struct ace_condition_composite *rc = &rhs->data.composite;
1585 51 : size_t i;
1586 76 : TALLOC_CTX *tmp_ctx = NULL;
1587 51 : bool ok;
1588 51 : int cmp_pair;
1589 51 : bool case_sensitive, rhs_case_sensitive;
1590 51 : bool rhs_sorted;
1591 76 : struct ace_condition_token *ltok = lc->tokens;
1592 76 : struct ace_condition_token *rtok = rc->tokens;
1593 51 : static const struct ace_condition_token eq = {
1594 : .type = CONDITIONAL_ACE_TOKEN_EQUAL
1595 : };
1596 76 : *cmp = -1;
1597 76 : if (lc->n_members == 0 ||
1598 76 : rc->n_members < lc->n_members) {
1599 : /* we should not have got this far */
1600 0 : return false;
1601 : }
1602 :
1603 76 : tmp_ctx = talloc_new(NULL);
1604 76 : if (tmp_ctx == NULL) {
1605 0 : return false;
1606 : }
1607 :
1608 76 : case_sensitive = lhs->flags & CLAIM_SECURITY_ATTRIBUTE_VALUE_CASE_SENSITIVE;
1609 76 : rhs_case_sensitive = rhs->flags & CLAIM_SECURITY_ATTRIBUTE_VALUE_CASE_SENSITIVE;
1610 76 : rhs_sorted = rhs->flags & CLAIM_SECURITY_ATTRIBUTE_UNIQUE_AND_SORTED;
1611 :
1612 76 : if (lc->tokens[0].type != CONDITIONAL_ACE_TOKEN_UNICODE) {
1613 : /*
1614 : * All LHS tokens are the same type (because it is a
1615 : * claim), and that type is not one that cares about
1616 : * case, so nor do we.
1617 : */
1618 4 : case_sensitive = false;
1619 68 : } else if (case_sensitive == rhs_case_sensitive) {
1620 : /* phew, no extra work */
1621 8 : } else if (case_sensitive) {
1622 : /* trigger a sorted copy */
1623 0 : rhs_sorted = false;
1624 4 : } else if (rhs_case_sensitive) {
1625 : /*
1626 : * Do we need to rescan for uniqueness, given the new
1627 : * comparison function? No! The strings were already
1628 : * unique in the looser comparison, and now they can
1629 : * only be more so. The number of unique values can't
1630 : * change, just their order.
1631 : */
1632 4 : case_sensitive = true;
1633 4 : ltok = composite_sorted_copy(tmp_ctx, lc, case_sensitive);
1634 4 : if (ltok == NULL) {
1635 0 : DBG_WARNING("sort of LHS failed\n");
1636 0 : goto error;
1637 : }
1638 : }
1639 :
1640 76 : if (! rhs_sorted) {
1641 : /*
1642 : * we need an RHS sorted copy (it's a literal, or
1643 : * there was a case sensitivity disagreement).
1644 : */
1645 55 : rtok = composite_sorted_copy(tmp_ctx, rc, case_sensitive);
1646 55 : if (rtok == NULL) {
1647 3 : DBG_WARNING("sort of RHS failed\n");
1648 3 : goto error;
1649 : }
1650 : }
1651 : /*
1652 : * Each member of LHS must match one or more members of RHS.
1653 : * Each member of RHS must match at least one of LHS.
1654 : *
1655 : * If they are the same length we can compare directly, so let's get
1656 : * rid of duplicates in RHS. This can only happen with literal
1657 : * composites.
1658 : */
1659 73 : if (rc->n_members > lc->n_members) {
1660 1 : size_t gap = 0;
1661 2845 : for (i = 1; i < rc->n_members; i++) {
1662 5650 : ok = simple_relational_operator(&eq,
1663 2826 : &rtok[i - 1],
1664 2826 : &rtok[i],
1665 : &cmp_pair);
1666 2826 : if (! ok) {
1667 0 : goto error;
1668 : }
1669 2826 : if (cmp_pair == 0) {
1670 2504 : gap++;
1671 : }
1672 2826 : if (gap != 0) {
1673 2823 : rtok[i - gap] = rtok[i];
1674 : }
1675 : }
1676 19 : if (rc->n_members - lc->n_members != gap) {
1677 : /*
1678 : * There were too many or too few duplicates to account
1679 : * for the difference, and no further comparison is
1680 : * necessary.
1681 : */
1682 2 : goto not_equal;
1683 : }
1684 : }
1685 : /*
1686 : * OK, now we know LHS and RHS are the same length and sorted in the
1687 : * same way, so we can just iterate over them and check each pair.
1688 : */
1689 :
1690 2469 : for (i = 0; i < lc->n_members; i++) {
1691 4782 : ok = simple_relational_operator(&eq,
1692 2415 : <ok[i],
1693 2415 : &rtok[i],
1694 : &cmp_pair);
1695 2415 : if (! ok){
1696 2 : goto error;
1697 : }
1698 2413 : if (cmp_pair != 0) {
1699 15 : goto not_equal;
1700 : }
1701 : }
1702 :
1703 54 : *cmp = 0;
1704 :
1705 71 : not_equal:
1706 71 : TALLOC_FREE(tmp_ctx);
1707 71 : return true;
1708 5 : error:
1709 5 : TALLOC_FREE(tmp_ctx);
1710 5 : return false;
1711 : }
1712 :
1713 :
1714 2 : static bool composite_is_comparable(const struct ace_condition_token *tok,
1715 : const struct ace_condition_token *comp)
1716 : {
1717 : /*
1718 : * Are all members of the composite comparable to the token?
1719 : */
1720 0 : size_t i;
1721 2 : const struct ace_condition_composite *rc = &comp->data.composite;
1722 2 : size_t n = rc->n_members;
1723 :
1724 2 : if ((comp->flags & CLAIM_SECURITY_ATTRIBUTE_UNIQUE_AND_SORTED) &&
1725 : n > 1) {
1726 : /*
1727 : * all members are known to be the same type, so we
1728 : * can just check one.
1729 : */
1730 2 : n = 1;
1731 : }
1732 :
1733 4 : for (i = 0; i < n; i++) {
1734 2 : if (! tokens_are_comparable(NULL,
1735 : tok,
1736 2 : &rc->tokens[i])) {
1737 0 : DBG_NOTICE("token type %u != composite type %u\n",
1738 : tok->type, rc->tokens[i].type);
1739 0 : return false;
1740 : }
1741 : }
1742 2 : return true;
1743 : }
1744 :
1745 :
1746 78 : static bool compare_composites(const struct ace_condition_token *op,
1747 : const struct ace_condition_token *lhs,
1748 : const struct ace_condition_token *rhs,
1749 : int *cmp)
1750 : {
1751 : /*
1752 : * This is for comparing multivalued sets, which includes
1753 : * conditional ACE composites and claim sets. Because these
1754 : * are sets, there are no < and > operations, just equality or
1755 : * otherwise.
1756 : *
1757 : * Claims are true sets, while composites are multisets --
1758 : * duplicate values are allowed -- but these are reduced to
1759 : * sets in evaluation, and the number of duplicates has no
1760 : * effect in comparisons. Resource attribute ACEs live in an
1761 : * intermediate state -- they can contain duplicates on the
1762 : * wire and as ACE structures, but as soon as they are
1763 : * evaluated as claims their values must be unique. Windows
1764 : * will treat RA ACEs with duplicate values as not existing,
1765 : * rather than as UNKNOWN (This is significant for the Exists
1766 : * operator). Claims can have a case-sensitive flags set,
1767 : * meaning they must be compared case-sensitively.
1768 : *
1769 : * Some good news is that the LHS of a comparison must always
1770 : * be a claim. That means we can assume it has unique values
1771 : * when it comes to pairwise comparisons. Using the magic of
1772 : * flags, we try to check this only once per claim.
1773 : *
1774 : * Conditional ACE composites, which can have duplicates (and
1775 : * mixed types), can only be on the RHS.
1776 : *
1777 : * To summarise:
1778 : *
1779 : * {a, b} vs {a, b} equal
1780 : * { } vs { } equal
1781 : * {a, b} vs {b, a} equal
1782 : * {a, b} vs {a, c} not equal
1783 : * {a, b} vs {a, a, b} equal
1784 : * {b, a} vs {a, b, a} equal
1785 : * {a, b} vs {a, a, b, c} not equal
1786 : * {a, b, a} vs {a, b} should not happen, error
1787 : * {a, b, a} vs {a, b, a} should not happen, error
1788 : *
1789 : * mixed types:
1790 : * {1, 2} vs {1, "2"} error
1791 : * {1, "2"} vs {1, "2"} should not happen, error
1792 : *
1793 : * case sensitivity (*{ }* indicates case-sensitive flag):
1794 : *
1795 : * {"a", "b"} vs {"a", "B"} equal
1796 : * {"a", "b"} vs *{"a", "B"}* not equal
1797 : * *{"a", "b"}* vs {"a", "B"} not equal
1798 : * *{"a", "A"}* vs {"a", "A"} equal (if RHS is composite)
1799 : * {"a", "A"} vs *{"a", "A"}* impossible (LHS is not unique)
1800 : * *{"a"}* vs {"a", "A"} not equal
1801 : *
1802 : * The naive approach is of course O(n * m) with an additional O(n²)
1803 : * if the LHS values are not known to be unique (that is, in resource
1804 : * attribute claims). We want to avoid that with big sets.
1805 : */
1806 78 : const struct ace_condition_composite *lc = &lhs->data.composite;
1807 78 : const struct ace_condition_composite *rc = &rhs->data.composite;
1808 51 : bool ok;
1809 :
1810 78 : if (!(lhs->flags & CLAIM_SECURITY_ATTRIBUTE_UNIQUE_AND_SORTED)) {
1811 : /*
1812 : * The LHS needs to be a claim, and it should have gone
1813 : * through claim_v1_check_and_sort() to get here.
1814 : */
1815 0 : *cmp = -1;
1816 0 : return false;
1817 : }
1818 :
1819 : /* if one or both are empty, the answer is easy */
1820 78 : if (lc->n_members == 0) {
1821 0 : if (rc->n_members == 0) {
1822 0 : *cmp = 0;
1823 0 : return true;
1824 : }
1825 0 : *cmp = -1;
1826 0 : return true;
1827 : }
1828 78 : if (rc->n_members == 0) {
1829 0 : *cmp = -1;
1830 0 : return true;
1831 : }
1832 :
1833 : /*
1834 : * LHS must be a claim, so it must be unique, so if there are
1835 : * fewer members on the RHS, we know they can't be equal.
1836 : *
1837 : * If you think about it too much, you might think this is
1838 : * affected by case sensitivity, but it isn't. One side can be
1839 : * infected by case-sensitivity by the other, but that can't
1840 : * shrink the number of elements on the RHS -- it can only
1841 : * make a literal {"a", "A"} have effective length 2 rather
1842 : * than 1.
1843 : *
1844 : * On the other hand, if the RHS is case sensitive, it must be
1845 : * a claim and unique in its own terms, and its finer-grained
1846 : * distinctions can't collapse members of the case sensitive
1847 : * LHS.
1848 : */
1849 78 : if (lc->n_members > rc->n_members) {
1850 0 : *cmp = -1;
1851 0 : return composite_is_comparable(&lc->tokens[0], rhs);
1852 : }
1853 :
1854 : /*
1855 : * It *could* be that RHS is also unique and we know it. In that
1856 : * case we can short circuit if RHS has more members. This is
1857 : * the case when both sides are claims.
1858 : *
1859 : * This is also not affected by case-senstivity.
1860 : */
1861 78 : if (lc->n_members < rc->n_members &&
1862 24 : (rhs->flags & CLAIM_SECURITY_ATTRIBUTE_UNIQUE_AND_SORTED)) {
1863 2 : *cmp = -1;
1864 2 : return composite_is_comparable(&lc->tokens[0], rhs);
1865 : }
1866 :
1867 76 : ok = compare_composites_via_sort(lhs, rhs, cmp);
1868 76 : if (! ok) {
1869 5 : return false;
1870 : }
1871 23 : return true;
1872 : }
1873 :
1874 :
1875 31423 : static bool simple_relational_operator(const struct ace_condition_token *op,
1876 : const struct ace_condition_token *lhs,
1877 : const struct ace_condition_token *rhs,
1878 : int *cmp)
1879 :
1880 : {
1881 31423 : if (lhs->type != rhs->type) {
1882 19 : if (! tokens_are_comparable(op, lhs, rhs)) {
1883 9 : return false;
1884 : }
1885 : }
1886 31404 : switch (lhs->type) {
1887 34 : case CONDITIONAL_ACE_TOKEN_INT8:
1888 : case CONDITIONAL_ACE_TOKEN_INT16:
1889 : case CONDITIONAL_ACE_TOKEN_INT32:
1890 : case CONDITIONAL_ACE_TOKEN_INT64:
1891 34 : if (rhs->type == CONDITIONAL_ACE_SAMBA_RESULT_BOOL) {
1892 0 : return compare_bools(op, lhs, rhs, cmp);
1893 : }
1894 34 : return compare_ints(op, lhs, rhs, cmp);
1895 0 : case CONDITIONAL_ACE_SAMBA_RESULT_BOOL:
1896 0 : return compare_bools(op, lhs, rhs, cmp);
1897 31278 : case CONDITIONAL_ACE_TOKEN_UNICODE:
1898 31278 : return compare_unicode(op, lhs, rhs, cmp);
1899 0 : case CONDITIONAL_ACE_TOKEN_OCTET_STRING:
1900 0 : return compare_bytes(op, lhs, rhs, cmp);
1901 0 : case CONDITIONAL_ACE_TOKEN_SID:
1902 14 : return compare_sids(op, lhs, rhs, cmp);
1903 78 : case CONDITIONAL_ACE_TOKEN_COMPOSITE:
1904 78 : return compare_composites(op, lhs, rhs, cmp);
1905 0 : case CONDITIONAL_ACE_SAMBA_RESULT_NULL:
1906 : /* leave the result unknown */
1907 0 : return false;
1908 0 : default:
1909 0 : DBG_ERR("did not expect ace type %u\n", lhs->type);
1910 0 : return false;
1911 : }
1912 :
1913 : return false;
1914 : }
1915 :
1916 :
1917 84 : static bool find_in_composite(const struct ace_condition_token *tok,
1918 : struct ace_condition_composite candidates,
1919 : bool *answer)
1920 : {
1921 23 : size_t i;
1922 23 : int cmp;
1923 23 : bool ok;
1924 84 : const struct ace_condition_token equals = {
1925 : .type = CONDITIONAL_ACE_TOKEN_EQUAL
1926 : };
1927 :
1928 84 : *answer = false;
1929 :
1930 143 : for (i = 0; i < candidates.n_members; i++) {
1931 154 : ok = simple_relational_operator(&equals,
1932 : tok,
1933 118 : &candidates.tokens[i],
1934 : &cmp);
1935 118 : if (! ok) {
1936 2 : return false;
1937 : }
1938 116 : if (cmp == 0) {
1939 57 : *answer = true;
1940 57 : return true;
1941 : }
1942 : }
1943 19 : return true;
1944 : }
1945 :
1946 :
1947 39 : static bool contains_operator(const struct ace_condition_token *lhs,
1948 : const struct ace_condition_token *rhs,
1949 : bool *answer)
1950 : {
1951 13 : size_t i;
1952 13 : bool ok;
1953 13 : int cmp;
1954 39 : const struct ace_condition_token equals = {
1955 : .type = CONDITIONAL_ACE_TOKEN_EQUAL
1956 : };
1957 :
1958 : /*
1959 : * All the required objects must be identical to something in
1960 : * candidates. But what do we mean by *identical*? We'll use
1961 : * the equality operator to decide that.
1962 : *
1963 : * Both the lhs or rhs can be solitary objects or composites.
1964 : * This makes it a bit fiddlier.
1965 : *
1966 : * NOTE: this operator does not take advantage of the
1967 : * CLAIM_SECURITY_ATTRIBUTE_UNIQUE_AND_SORTED flag. It could, but it
1968 : * doesn't.
1969 : */
1970 39 : if (lhs->type == CONDITIONAL_ACE_TOKEN_COMPOSITE) {
1971 29 : struct ace_condition_composite candidates = lhs->data.composite;
1972 9 : struct ace_condition_composite required;
1973 29 : if (rhs->type != CONDITIONAL_ACE_TOKEN_COMPOSITE) {
1974 9 : return find_in_composite(rhs, candidates, answer);
1975 : }
1976 20 : required = rhs->data.composite;
1977 20 : if (required.n_members == 0) {
1978 0 : return false;
1979 : }
1980 54 : for (i = 0; i < required.n_members; i++) {
1981 43 : const struct ace_condition_token *t = &required.tokens[i];
1982 43 : ok = find_in_composite(t, candidates, answer);
1983 43 : if (! ok) {
1984 2 : return false;
1985 : }
1986 41 : if (! *answer) {
1987 : /*
1988 : * one required item was not there,
1989 : * *answer is false
1990 : */
1991 6 : return true;
1992 : }
1993 : }
1994 : /* all required items are there, *answer will be true */
1995 8 : return true;
1996 : }
1997 : /* LHS is a single item */
1998 10 : if (rhs->type == CONDITIONAL_ACE_TOKEN_COMPOSITE) {
1999 : /*
2000 : * There could be more than one RHS member that is
2001 : * equal to the single LHS value, so it doesn't help
2002 : * to compare lengths or anything.
2003 : */
2004 4 : struct ace_condition_composite required = rhs->data.composite;
2005 4 : if (required.n_members == 0) {
2006 2 : return false;
2007 : }
2008 4 : for (i = 0; i < required.n_members; i++) {
2009 2 : ok = simple_relational_operator(&equals,
2010 : lhs,
2011 2 : &required.tokens[i],
2012 : &cmp);
2013 2 : if (! ok) {
2014 0 : return false;
2015 : }
2016 2 : if (cmp != 0) {
2017 : /*
2018 : * one required item was not there,
2019 : * *answer is false
2020 : */
2021 0 : *answer = false;
2022 0 : return true;
2023 : }
2024 : }
2025 2 : *answer = true;
2026 2 : return true;
2027 : }
2028 : /* LHS and RHS are both single */
2029 6 : ok = simple_relational_operator(&equals,
2030 : lhs,
2031 : rhs,
2032 : &cmp);
2033 6 : if (! ok) {
2034 0 : return false;
2035 : }
2036 6 : *answer = (cmp == 0);
2037 6 : return true;
2038 : }
2039 :
2040 :
2041 34 : static bool any_of_operator(const struct ace_condition_token *lhs,
2042 : const struct ace_condition_token *rhs,
2043 : bool *answer)
2044 : {
2045 10 : size_t i;
2046 10 : bool ok;
2047 10 : int cmp;
2048 34 : const struct ace_condition_token equals = {
2049 : .type = CONDITIONAL_ACE_TOKEN_EQUAL
2050 : };
2051 :
2052 : /*
2053 : * There has to be *some* overlap between the LHS and RHS.
2054 : * Both sides can be solitary objects or composites.
2055 : *
2056 : * We can exploit this symmetry.
2057 : */
2058 34 : if (lhs->type != CONDITIONAL_ACE_TOKEN_COMPOSITE) {
2059 11 : const struct ace_condition_token *tmp = lhs;
2060 11 : lhs = rhs;
2061 11 : rhs = tmp;
2062 : }
2063 34 : if (lhs->type != CONDITIONAL_ACE_TOKEN_COMPOSITE) {
2064 : /* both singles */
2065 4 : ok = simple_relational_operator(&equals,
2066 : lhs,
2067 : rhs,
2068 : &cmp);
2069 4 : if (! ok) {
2070 0 : return false;
2071 : }
2072 3 : *answer = (cmp == 0);
2073 3 : return true;
2074 : }
2075 30 : if (rhs->type != CONDITIONAL_ACE_TOKEN_COMPOSITE) {
2076 19 : return find_in_composite(rhs, lhs->data.composite, answer);
2077 : }
2078 : /* both are composites */
2079 11 : if (lhs->data.composite.n_members == 0) {
2080 0 : return false;
2081 : }
2082 15 : for (i = 0; i < lhs->data.composite.n_members; i++) {
2083 13 : ok = find_in_composite(&lhs->data.composite.tokens[i],
2084 : rhs->data.composite,
2085 : answer);
2086 13 : if (! ok) {
2087 0 : return false;
2088 : }
2089 13 : if (*answer) {
2090 : /* We have found one match, which is enough. */
2091 6 : return true;
2092 : }
2093 : }
2094 2 : return true;
2095 : }
2096 :
2097 :
2098 73 : static bool composite_relational_operator(const struct ace_condition_token *op,
2099 : const struct ace_condition_token *lhs,
2100 : const struct ace_condition_token *rhs,
2101 : struct ace_condition_token *result)
2102 : {
2103 23 : bool ok, answer;
2104 73 : switch(op->type) {
2105 39 : case CONDITIONAL_ACE_TOKEN_CONTAINS:
2106 : case CONDITIONAL_ACE_TOKEN_NOT_CONTAINS:
2107 39 : ok = contains_operator(lhs, rhs, &answer);
2108 39 : break;
2109 34 : case CONDITIONAL_ACE_TOKEN_ANY_OF:
2110 : case CONDITIONAL_ACE_TOKEN_NOT_ANY_OF:
2111 34 : ok = any_of_operator(lhs, rhs, &answer);
2112 34 : break;
2113 0 : default:
2114 0 : return false;
2115 : }
2116 73 : if (!ok) {
2117 4 : return false;
2118 : }
2119 :
2120 : /* negate the NOTs */
2121 68 : if (op->type == CONDITIONAL_ACE_TOKEN_NOT_CONTAINS ||
2122 40 : op->type == CONDITIONAL_ACE_TOKEN_NOT_ANY_OF)
2123 : {
2124 20 : answer = !answer;
2125 : }
2126 :
2127 68 : if (answer) {
2128 45 : result->data.result.value = ACE_CONDITION_TRUE;
2129 : } else {
2130 23 : result->data.result.value = ACE_CONDITION_FALSE;
2131 : }
2132 46 : return true;
2133 : }
2134 :
2135 :
2136 298 : static bool relational_operator(
2137 : const struct security_token *token,
2138 : const struct ace_condition_token *op,
2139 : const struct ace_condition_token *lhs,
2140 : const struct ace_condition_token *rhs,
2141 : struct ace_condition_token *result)
2142 : {
2143 84 : int cmp;
2144 84 : bool ok;
2145 298 : result->type = CONDITIONAL_ACE_SAMBA_RESULT_BOOL;
2146 298 : result->data.result.value = ACE_CONDITION_UNKNOWN;
2147 :
2148 298 : if ((lhs->flags & CONDITIONAL_ACE_FLAG_TOKEN_FROM_ATTR) == 0) {
2149 : /* LHS was not derived from an attribute */
2150 0 : return false;
2151 : }
2152 :
2153 : /*
2154 : * This first nested switch is ensuring that >, >=, <, <= are
2155 : * not being tried on tokens that are not numbers, strings, or
2156 : * octet strings. Equality operators are available for all types.
2157 : */
2158 298 : switch (lhs->type) {
2159 143 : case CONDITIONAL_ACE_TOKEN_INT8:
2160 : case CONDITIONAL_ACE_TOKEN_INT16:
2161 : case CONDITIONAL_ACE_TOKEN_INT32:
2162 : case CONDITIONAL_ACE_TOKEN_INT64:
2163 : case CONDITIONAL_ACE_TOKEN_UNICODE:
2164 : case CONDITIONAL_ACE_TOKEN_OCTET_STRING:
2165 143 : break;
2166 140 : default:
2167 140 : switch(op->type) {
2168 8 : case CONDITIONAL_ACE_TOKEN_LESS_THAN:
2169 : case CONDITIONAL_ACE_TOKEN_LESS_OR_EQUAL:
2170 : case CONDITIONAL_ACE_TOKEN_GREATER_THAN:
2171 : case CONDITIONAL_ACE_TOKEN_GREATER_OR_EQUAL:
2172 8 : return false;
2173 63 : default:
2174 63 : break;
2175 : }
2176 : }
2177 :
2178 : /*
2179 : * Dispatch according to operator type.
2180 : */
2181 290 : switch (op->type) {
2182 217 : case CONDITIONAL_ACE_TOKEN_EQUAL:
2183 : case CONDITIONAL_ACE_TOKEN_NOT_EQUAL:
2184 : case CONDITIONAL_ACE_TOKEN_LESS_THAN:
2185 : case CONDITIONAL_ACE_TOKEN_LESS_OR_EQUAL:
2186 : case CONDITIONAL_ACE_TOKEN_GREATER_THAN:
2187 : case CONDITIONAL_ACE_TOKEN_GREATER_OR_EQUAL:
2188 217 : ok = simple_relational_operator(op,
2189 : lhs,
2190 : rhs,
2191 : &cmp);
2192 217 : if (ok) {
2193 206 : ok = cmp_to_result(op, result, cmp);
2194 : }
2195 156 : return ok;
2196 :
2197 73 : case CONDITIONAL_ACE_TOKEN_CONTAINS:
2198 : case CONDITIONAL_ACE_TOKEN_ANY_OF:
2199 : case CONDITIONAL_ACE_TOKEN_NOT_CONTAINS:
2200 : case CONDITIONAL_ACE_TOKEN_NOT_ANY_OF:
2201 73 : return composite_relational_operator(op,
2202 : lhs,
2203 : rhs,
2204 : result);
2205 0 : default:
2206 0 : return false;
2207 : }
2208 : }
2209 :
2210 :
2211 671 : int run_conditional_ace(TALLOC_CTX *mem_ctx,
2212 : const struct security_token *token,
2213 : struct ace_condition_script *program,
2214 : const struct security_descriptor *sd)
2215 : {
2216 139 : size_t i;
2217 671 : size_t depth = 0;
2218 671 : struct ace_condition_token *lhs = NULL;
2219 671 : struct ace_condition_token *rhs = NULL;
2220 671 : struct ace_condition_token result = {};
2221 139 : bool ok;
2222 :
2223 2174 : for (i = 0; i < program->length; i++) {
2224 1642 : struct ace_condition_token *tok = &program->tokens[i];
2225 1642 : switch (tok->type) {
2226 411 : case CONDITIONAL_ACE_TOKEN_INT8:
2227 : case CONDITIONAL_ACE_TOKEN_INT16:
2228 : case CONDITIONAL_ACE_TOKEN_INT32:
2229 : case CONDITIONAL_ACE_TOKEN_INT64:
2230 : case CONDITIONAL_ACE_TOKEN_UNICODE:
2231 : case CONDITIONAL_ACE_TOKEN_OCTET_STRING:
2232 : case CONDITIONAL_ACE_TOKEN_SID:
2233 : case CONDITIONAL_ACE_TOKEN_COMPOSITE:
2234 : /* just plonk these literals on the stack */
2235 411 : program->stack[depth] = *tok;
2236 411 : depth++;
2237 411 : break;
2238 :
2239 577 : case CONDITIONAL_ACE_LOCAL_ATTRIBUTE:
2240 : case CONDITIONAL_ACE_USER_ATTRIBUTE:
2241 : case CONDITIONAL_ACE_DEVICE_ATTRIBUTE:
2242 577 : ok = token_claim_lookup(mem_ctx, token, tok, &result);
2243 577 : if (! ok) {
2244 88 : goto error;
2245 : }
2246 489 : program->stack[depth] = result;
2247 489 : depth++;
2248 489 : break;
2249 :
2250 15 : case CONDITIONAL_ACE_RESOURCE_ATTRIBUTE:
2251 15 : ok = resource_claim_lookup(mem_ctx,
2252 : tok,
2253 : sd,
2254 : &result);
2255 15 : if (! ok) {
2256 5 : goto error;
2257 : }
2258 10 : program->stack[depth] = result;
2259 10 : depth++;
2260 10 : break;
2261 :
2262 249 : case CONDITIONAL_ACE_TOKEN_MEMBER_OF:
2263 : case CONDITIONAL_ACE_TOKEN_DEVICE_MEMBER_OF:
2264 : case CONDITIONAL_ACE_TOKEN_MEMBER_OF_ANY:
2265 : case CONDITIONAL_ACE_TOKEN_DEVICE_MEMBER_OF_ANY:
2266 : case CONDITIONAL_ACE_TOKEN_NOT_MEMBER_OF:
2267 : case CONDITIONAL_ACE_TOKEN_NOT_DEVICE_MEMBER_OF:
2268 : case CONDITIONAL_ACE_TOKEN_NOT_MEMBER_OF_ANY:
2269 : case CONDITIONAL_ACE_TOKEN_NOT_DEVICE_MEMBER_OF_ANY:
2270 249 : if (depth == 0) {
2271 0 : goto error;
2272 : }
2273 249 : depth--;
2274 249 : lhs = &program->stack[depth];
2275 249 : ok = member_lookup(token, tok, lhs, &result);
2276 249 : if (! ok) {
2277 0 : goto error;
2278 : }
2279 249 : program->stack[depth] = result;
2280 249 : depth++;
2281 249 : break;
2282 : /* binary relational operators */
2283 298 : case CONDITIONAL_ACE_TOKEN_EQUAL:
2284 : case CONDITIONAL_ACE_TOKEN_NOT_EQUAL:
2285 : case CONDITIONAL_ACE_TOKEN_LESS_THAN:
2286 : case CONDITIONAL_ACE_TOKEN_LESS_OR_EQUAL:
2287 : case CONDITIONAL_ACE_TOKEN_GREATER_THAN:
2288 : case CONDITIONAL_ACE_TOKEN_GREATER_OR_EQUAL:
2289 : case CONDITIONAL_ACE_TOKEN_CONTAINS:
2290 : case CONDITIONAL_ACE_TOKEN_ANY_OF:
2291 : case CONDITIONAL_ACE_TOKEN_NOT_CONTAINS:
2292 : case CONDITIONAL_ACE_TOKEN_NOT_ANY_OF:
2293 298 : if (depth < 2) {
2294 0 : goto error;
2295 : }
2296 298 : depth--;
2297 298 : rhs = &program->stack[depth];
2298 298 : depth--;
2299 298 : lhs = &program->stack[depth];
2300 298 : ok = relational_operator(token, tok, lhs, rhs, &result);
2301 298 : if (! ok) {
2302 24 : goto error;
2303 : }
2304 274 : program->stack[depth] = result;
2305 274 : depth++;
2306 274 : break;
2307 : /* unary logical operators */
2308 70 : case CONDITIONAL_ACE_TOKEN_EXISTS:
2309 : case CONDITIONAL_ACE_TOKEN_NOT_EXISTS:
2310 : case CONDITIONAL_ACE_TOKEN_NOT:
2311 70 : if (depth == 0) {
2312 0 : goto error;
2313 : }
2314 70 : depth--;
2315 70 : lhs = &program->stack[depth];
2316 70 : ok = unary_logic_operator(mem_ctx, token, tok, lhs, sd, &result);
2317 70 : if (!ok) {
2318 9 : goto error;
2319 : }
2320 61 : program->stack[depth] = result;
2321 61 : depth++;
2322 61 : break;
2323 : /* binary logical operators */
2324 22 : case CONDITIONAL_ACE_TOKEN_AND:
2325 : case CONDITIONAL_ACE_TOKEN_OR:
2326 22 : if (depth < 2) {
2327 0 : goto error;
2328 : }
2329 22 : depth--;
2330 22 : rhs = &program->stack[depth];
2331 22 : depth--;
2332 22 : lhs = &program->stack[depth];
2333 22 : ok = binary_logic_operator(token, tok, lhs, rhs, &result);
2334 22 : if (! ok) {
2335 13 : goto error;
2336 : }
2337 9 : program->stack[depth] = result;
2338 9 : depth++;
2339 9 : break;
2340 0 : default:
2341 0 : goto error;
2342 : }
2343 : }
2344 : /*
2345 : * The evaluation should have left a single result value (true, false,
2346 : * or unknown) on the stack. If not, the expression was malformed.
2347 : */
2348 532 : if (depth != 1) {
2349 0 : goto error;
2350 : }
2351 532 : result = program->stack[0];
2352 532 : if (result.type != CONDITIONAL_ACE_SAMBA_RESULT_BOOL) {
2353 18 : goto error;
2354 : }
2355 :
2356 514 : return result.data.result.value;
2357 :
2358 134 : error:
2359 : /*
2360 : * the result of an error is always UNKNOWN, which should be
2361 : * interpreted pessimistically, not allowing access.
2362 : */
2363 134 : return ACE_CONDITION_UNKNOWN;
2364 : }
2365 :
2366 :
2367 : /** access_check_conditional_ace()
2368 : *
2369 : * Run the conditional ACE from the blob form. Return false if it is
2370 : * not a valid conditional ACE, true if it is, even if there is some
2371 : * other error in running it. The *result parameter is set to
2372 : * ACE_CONDITION_FALSE, ACE_CONDITION_TRUE, or ACE_CONDITION_UNKNOWN.
2373 : *
2374 : * ACE_CONDITION_UNKNOWN should be treated pessimistically, as if it were
2375 : * TRUE for deny ACEs, and FALSE for allow ACEs.
2376 : *
2377 : * @param[in] ace - the ACE being processed.
2378 : * @param[in] token - the security token the ACE is processing.
2379 : * @param[out] result - a ternary result value.
2380 : *
2381 : * @return true if it is a valid conditional ACE.
2382 : */
2383 :
2384 671 : bool access_check_conditional_ace(const struct security_ace *ace,
2385 : const struct security_token *token,
2386 : const struct security_descriptor *sd,
2387 : int *result)
2388 : {
2389 671 : TALLOC_CTX *tmp_ctx = talloc_new(NULL);
2390 671 : struct ace_condition_script *program = NULL;
2391 671 : program = parse_conditional_ace(tmp_ctx, ace->coda.conditions);
2392 671 : if (program == NULL) {
2393 0 : *result = ACE_CONDITION_UNKNOWN;
2394 0 : TALLOC_FREE(tmp_ctx);
2395 0 : return false;
2396 : }
2397 :
2398 671 : *result = run_conditional_ace(tmp_ctx, token, program, sd);
2399 :
2400 671 : TALLOC_FREE(tmp_ctx);
2401 532 : return true;
2402 : }
2403 :
2404 :
2405 1472 : bool conditional_ace_encode_binary(TALLOC_CTX *mem_ctx,
2406 : struct ace_condition_script *program,
2407 : DATA_BLOB *dest)
2408 : {
2409 751 : size_t i, j, alloc_size, required_size;
2410 1472 : uint8_t *data = NULL;
2411 1472 : uint8_t *new_data = NULL;
2412 1472 : *dest = (DATA_BLOB){NULL, 0};
2413 :
2414 1472 : alloc_size = CONDITIONAL_ACE_MAX_LENGTH;
2415 1472 : data = talloc_array(mem_ctx,
2416 : uint8_t,
2417 : alloc_size);
2418 1472 : if (data == NULL) {
2419 0 : return false;
2420 : }
2421 :
2422 1472 : data[0] = 'a';
2423 1472 : data[1] = 'r';
2424 1472 : data[2] = 't';
2425 1472 : data[3] = 'x';
2426 :
2427 1472 : j = 4;
2428 6799 : for (i = 0; i < program->length; i++) {
2429 5327 : struct ace_condition_token *tok = &program->tokens[i];
2430 3484 : ssize_t consumed;
2431 3484 : bool ok;
2432 : /*
2433 : * In all cases we write the token type byte.
2434 : */
2435 5327 : data[j] = tok->type;
2436 5327 : j++;
2437 5327 : if (j >= alloc_size) {
2438 0 : DBG_ERR("program exceeds %zu bytes\n", alloc_size);
2439 0 : goto error;
2440 : }
2441 :
2442 5327 : switch (tok->type) {
2443 2241 : case CONDITIONAL_ACE_TOKEN_MEMBER_OF:
2444 : case CONDITIONAL_ACE_TOKEN_DEVICE_MEMBER_OF:
2445 : case CONDITIONAL_ACE_TOKEN_MEMBER_OF_ANY:
2446 : case CONDITIONAL_ACE_TOKEN_DEVICE_MEMBER_OF_ANY:
2447 : case CONDITIONAL_ACE_TOKEN_NOT_MEMBER_OF:
2448 : case CONDITIONAL_ACE_TOKEN_NOT_DEVICE_MEMBER_OF:
2449 : case CONDITIONAL_ACE_TOKEN_NOT_MEMBER_OF_ANY:
2450 : case CONDITIONAL_ACE_TOKEN_NOT_DEVICE_MEMBER_OF_ANY:
2451 : case CONDITIONAL_ACE_TOKEN_EQUAL:
2452 : case CONDITIONAL_ACE_TOKEN_NOT_EQUAL:
2453 : case CONDITIONAL_ACE_TOKEN_LESS_THAN:
2454 : case CONDITIONAL_ACE_TOKEN_LESS_OR_EQUAL:
2455 : case CONDITIONAL_ACE_TOKEN_GREATER_THAN:
2456 : case CONDITIONAL_ACE_TOKEN_GREATER_OR_EQUAL:
2457 : case CONDITIONAL_ACE_TOKEN_CONTAINS:
2458 : case CONDITIONAL_ACE_TOKEN_ANY_OF:
2459 : case CONDITIONAL_ACE_TOKEN_NOT_CONTAINS:
2460 : case CONDITIONAL_ACE_TOKEN_NOT_ANY_OF:
2461 : case CONDITIONAL_ACE_TOKEN_EXISTS:
2462 : case CONDITIONAL_ACE_TOKEN_NOT_EXISTS:
2463 : case CONDITIONAL_ACE_TOKEN_NOT:
2464 : case CONDITIONAL_ACE_TOKEN_AND:
2465 : case CONDITIONAL_ACE_TOKEN_OR:
2466 : /*
2467 : * All of these are simple operators that operate on
2468 : * the stack. We have already added the tok->type and
2469 : * there's nothing else to do.
2470 : */
2471 2241 : continue;
2472 :
2473 192 : case CONDITIONAL_ACE_TOKEN_INT8:
2474 : case CONDITIONAL_ACE_TOKEN_INT16:
2475 : case CONDITIONAL_ACE_TOKEN_INT32:
2476 : case CONDITIONAL_ACE_TOKEN_INT64:
2477 192 : ok = check_integer_range(tok);
2478 192 : if (! ok) {
2479 0 : goto error;
2480 : }
2481 192 : consumed = push_integer(data + j,
2482 : alloc_size - j,
2483 192 : &tok->data.int64);
2484 192 : break;
2485 1955 : case CONDITIONAL_ACE_LOCAL_ATTRIBUTE:
2486 : case CONDITIONAL_ACE_USER_ATTRIBUTE:
2487 : case CONDITIONAL_ACE_RESOURCE_ATTRIBUTE:
2488 : case CONDITIONAL_ACE_DEVICE_ATTRIBUTE:
2489 : case CONDITIONAL_ACE_TOKEN_UNICODE:
2490 1955 : consumed = push_unicode(data + j,
2491 : alloc_size - j,
2492 1955 : &tok->data.unicode);
2493 1955 : break;
2494 15 : case CONDITIONAL_ACE_TOKEN_OCTET_STRING:
2495 15 : consumed = push_bytes(data + j,
2496 : alloc_size - j,
2497 15 : &tok->data.bytes);
2498 15 : break;
2499 144 : case CONDITIONAL_ACE_TOKEN_SID:
2500 144 : consumed = push_sid(data + j,
2501 : alloc_size - j,
2502 144 : &tok->data.sid);
2503 144 : break;
2504 780 : case CONDITIONAL_ACE_TOKEN_COMPOSITE:
2505 780 : consumed = push_composite(data + j,
2506 : alloc_size - j,
2507 780 : &tok->data.composite);
2508 780 : break;
2509 :
2510 0 : default:
2511 0 : DBG_ERR("unknown token 0x%02x at position %zu\n",
2512 : tok->type, i);
2513 0 : goto error;
2514 : }
2515 3086 : if (consumed == -1) {
2516 0 : DBG_ERR("program exceeds %zu bytes\n", alloc_size);
2517 0 : goto error;
2518 : }
2519 3086 : j += consumed;
2520 3086 : if (j >= alloc_size) {
2521 0 : DBG_ERR("program exceeds %zu bytes\n", alloc_size);
2522 0 : goto error;
2523 : }
2524 : }
2525 : /* align to a 4 byte boundary */
2526 1472 : required_size = (j + 3) & ~((size_t)3);
2527 1472 : if (required_size > alloc_size) {
2528 0 : DBG_ERR("program exceeds %zu bytes\n", alloc_size);
2529 0 : goto error;
2530 : }
2531 3792 : while (j < required_size) {
2532 2320 : data[j] = 0;
2533 2320 : j++;
2534 : }
2535 1472 : new_data = talloc_realloc(mem_ctx,
2536 : data,
2537 : uint8_t,
2538 : required_size);
2539 1472 : if (new_data == NULL) {
2540 0 : goto error;
2541 : }
2542 1472 : data = new_data;
2543 :
2544 1472 : (*dest).data = data;
2545 1472 : (*dest).length = j;
2546 1472 : return true;
2547 0 : error:
2548 0 : TALLOC_FREE(data);
2549 0 : return false;
2550 : }
|