LCOV - code coverage report
Current view: top level - libcli/security - conditional_ace.c (source / functions) Hit Total Coverage
Test: coverage report for fix-15632 9995c5c2 Lines: 875 1160 75.4 %
Date: 2024-04-13 12:30:31 Functions: 39 42 92.9 %

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

Generated by: LCOV version 1.14