Coverage Report

Created: 2026-04-01 06:26

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