LCOV - code coverage report
Current view: top level - libcli/security - conditional_ace.c (source / functions) Hit Total Coverage
Test: coverage report for support-claim-type-attributes 6b5c566e Lines: 777 1044 74.4 %
Date: 2023-11-21 12:31:41 Functions: 35 38 92.1 %

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

Generated by: LCOV version 1.14