LCOV - code coverage report
Current view: top level - libcli/security/tests - test_sddl_conditional_ace.c (source / functions) Hit Total Coverage
Test: coverage report for support-claim-type-attributes 6b5c566e Lines: 228 285 80.0 %
Date: 2023-11-21 12:31:41 Functions: 11 11 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Unit tests for conditional ACE SDDL.
       3             :  *
       4             :  *  Copyright (C) Catalyst.NET Ltd 2023
       5             :  *
       6             :  * This program is free software; you can redistribute it and/or modify
       7             :  * it under the terms of the GNU General Public License as published by
       8             :  * the Free Software Foundation; either version 3 of the License, or
       9             :  * (at your option) any later version.
      10             :  *
      11             :  * This program is distributed in the hope that it will be useful,
      12             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :  * GNU General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU General Public License
      17             :  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             :  *
      19             :  */
      20             : 
      21             : #include <stdarg.h>
      22             : #include <stddef.h>
      23             : #include <setjmp.h>
      24             : #include "cmocka.h"
      25             : 
      26             : #include "lib/util/attr.h"
      27             : #include "includes.h"
      28             : #include "librpc/gen_ndr/ndr_security.h"
      29             : #include "libcli/security/security.h"
      30             : #include "libcli/security/conditional_ace.h"
      31             : #include "librpc/gen_ndr/conditional_ace.h"
      32             : 
      33             : /*
      34             :  * Some of the test strings break subunit, so we only print those if
      35             :  * stdout is a terminal.
      36             :  */
      37             : #define debug_message(...)  do {                        \
      38             :                 if (isatty(1)) {                        \
      39             :                         print_message(__VA_ARGS__);     \
      40             :                                 }                       \
      41             :         } while(0)
      42             : 
      43             : #define debug_fail(x, ...) debug_message("\033[1;31m" x "\033[0m", __VA_ARGS__)
      44             : #define debug_ok(x, ...) debug_message("\033[1;32m" x "\033[0m", __VA_ARGS__)
      45             : 
      46             : #define ACEINT64(x, b, s) CONDITIONAL_ACE_TOKEN_INT64,                  \
      47             :                 (x & 0xff), ((x >> 8) & 0xff), ((x >> 16) & 0xff),      \
      48             :                 ((x >> 24) & 0xff), (((uint64_t)x >> 32) & 0xff), (((uint64_t)x >> 40) & 0xff), \
      49             :                 (((uint64_t)x >> 48) & 0xff), (((uint64_t)x >> 56) & 0xff), b, s
      50             : 
      51             : 
      52          25 : static void print_error_message(const char *sddl,
      53             :                                 const char *message,
      54             :                                 size_t message_offset)
      55             : {
      56          25 :         print_message("%s\n\033[1;33m %*c\033[0m\n", sddl,
      57             :                       (int)message_offset, '^');
      58          25 :         print_message("%s\n", message);
      59          23 : }
      60             : 
      61           1 : static void test_sddl_compile(void **state)
      62             : {
      63             :         /*
      64             :          * Example codes:
      65             :          *
      66             :          *    CONDITIONAL_ACE_LOCAL_ATTRIBUTE,  2,0,0,0,     'x',0,
      67             :          *    ^attr byte code                   ^              ^
      68             :          *                       32 bit little-endian length   |
      69             :          *                                             utf-16, little endian
      70             :          *
      71             :          *     CONDITIONAL_ACE_TOKEN_EQUAL
      72             :          *     ^ op byte code with no following data
      73             :          */
      74           1 :         static const char *sddl = "(x==41 &&(x >@device.x ) )";
      75           1 :         static const uint8_t ace[] = {
      76             :                 'a', 'r', 't', 'x',
      77             :                 CONDITIONAL_ACE_LOCAL_ATTRIBUTE, 2, 0, 0, 0, 'x', 0,
      78             :                 ACEINT64(41,
      79             :                          CONDITIONAL_ACE_INT_SIGN_NONE,
      80             :                          CONDITIONAL_ACE_INT_BASE_10),
      81             :                 CONDITIONAL_ACE_TOKEN_EQUAL,
      82             :                 CONDITIONAL_ACE_LOCAL_ATTRIBUTE, 2, 0, 0, 0, 'x', 0,
      83             :                 CONDITIONAL_ACE_DEVICE_ATTRIBUTE, 2, 0, 0, 0, 'x', 0,
      84             :                 CONDITIONAL_ACE_TOKEN_GREATER_THAN,
      85             :                 CONDITIONAL_ACE_TOKEN_AND, 0,0,0,0,
      86             :         };
      87             : 
      88           1 :         size_t i;
      89           1 :         TALLOC_CTX *mem_ctx = talloc_new(NULL);
      90           1 :         struct ace_condition_script *s = NULL;
      91           1 :         const char *message = NULL;
      92           1 :         size_t message_offset;
      93           1 :         bool ok;
      94           1 :         DATA_BLOB compiled;
      95           1 :         size_t length;
      96             : 
      97           1 :         s = ace_conditions_compile_sddl(mem_ctx,
      98             :                                         ACE_CONDITION_FLAG_ALLOW_DEVICE,
      99             :                                         sddl,
     100             :                                         &message,
     101             :                                         &message_offset,
     102             :                                         &length);
     103           1 :         if (message != NULL) {
     104           0 :                 print_error_message(sddl, message, message_offset);
     105             :         }
     106           1 :         if (s == NULL) {
     107           0 :                 debug_fail("%s\n", sddl);
     108           0 :                 fail();
     109             :         }
     110             : 
     111           1 :         ok = conditional_ace_encode_binary(mem_ctx, s, &compiled);
     112           1 :         assert_true(ok);
     113             : 
     114           1 :         assert_true(compiled.length <= ARRAY_SIZE(ace));
     115          42 :         for (i = 0; i < compiled.length; i++) {
     116          40 :                 assert_int_equal(compiled.data[i], ace[i]);
     117             :         }
     118           1 : }
     119             : 
     120           1 : static void test_sddl_compile2(void **state)
     121             : {
     122             :         /* this one is from Windows, not hand-calculated */
     123           1 :         static const char *sddl = "(@USER.Project Any_of 1))";
     124           1 :         static const uint8_t ace[] = ("artx\xf9\x0e\x00\x00\x00P\x00r"
     125             :                                       "\x00o\x00j\x00""e\x00""c\x00t\x00"
     126             :                                       "\x04\x01\x00\x00\x00\x00\x00\x00"
     127             :                                       "\x00\x03\x02\x88\x00");
     128           1 :         size_t i;
     129           1 :         TALLOC_CTX *mem_ctx = talloc_new(NULL);
     130           1 :         struct ace_condition_script *s = NULL;
     131           1 :         const char *message = NULL;
     132           1 :         size_t message_offset;
     133           1 :         bool ok;
     134           1 :         DATA_BLOB compiled;
     135           1 :         size_t length;
     136             : 
     137           1 :         s = ace_conditions_compile_sddl(mem_ctx,
     138             :                                         ACE_CONDITION_FLAG_ALLOW_DEVICE,
     139             :                                         sddl,
     140             :                                         &message,
     141             :                                         &message_offset,
     142             :                                         &length);
     143           1 :         if (message != NULL) {
     144           0 :                 print_error_message(sddl, message, message_offset);
     145             :         }
     146           1 :         if (s == NULL) {
     147           0 :                 debug_fail("%s\n", sddl);
     148           0 :                 fail();
     149             :         }
     150             : 
     151           1 :         ok = conditional_ace_encode_binary(mem_ctx, s, &compiled);
     152           1 :         assert_true(ok);
     153             : 
     154           1 :         assert_true(compiled.length <= ARRAY_SIZE(ace));
     155          38 :         for (i = 0; i < compiled.length; i++) {
     156          36 :                 assert_int_equal(compiled.data[i], ace[i]);
     157             :         }
     158           1 : }
     159             : 
     160           1 : static void test_full_sddl_compile(void **state)
     161             : {
     162             :         /*
     163             :          * This one is from Windows, and annotated by hand.
     164             :          *
     165             :          * We have the bytes of a full security descriptor, in
     166             :          * "relative" form, which is the same as the its NDR
     167             :          * representation.
     168             :          *
     169             :          * *In general* we can't necessarily assert that Samba's NDR
     170             :          * will be the same as Windows, because they could e.g. put
     171             :          * the two ACLs in the reverse order which is also legitimate
     172             :          * (there are hints this may vary on Windows). But in this
     173             :          * particular case Samba and the Windows 2022 sample agree, so
     174             :          * we can compare the bytes here.
     175             :          *
     176             :          * We can assert that unpacking these bytes as a security
     177             :          * descriptor should succeed and give us exactly the same
     178             :          * descriptor as parsing the SDDL.
     179             :          */
     180           1 :         TALLOC_CTX *mem_ctx = talloc_new(NULL);
     181           1 :         struct security_descriptor sec_desc_windows = {};
     182           1 :         struct security_descriptor *sec_desc_samba = NULL;
     183           1 :         DATA_BLOB sd_ndr = {};
     184           1 :         DATA_BLOB sd_win_push = {};
     185           1 :         DATA_BLOB sd_samba_push = {};
     186           1 :         bool ok;
     187           1 :         enum ndr_err_code ndr_err;
     188           1 :         const char *sddl = "D:(XA;;CCDCLCSWRPWP;;;MP;"\
     189             :                 "(@RESOURCE.c))S:(RA;;;;;WD;(\"colOIr\",TU,0xe,29925))";
     190             : 
     191           1 :         uint8_t sd_bytes[] = {
     192             :                 1,          /*  0  version */
     193             :                 0,          /*  1  reserved */
     194             :                 20, 128,    /*  2  control */
     195             :                 0, 0, 0, 0, /*  4  owner (null relative pointer == no owner) */
     196             :                 0, 0, 0, 0, /*  8  group */
     197             :                 20, 0, 0, 0,/* 12  SACL  */
     198             :                 92, 0, 0, 0,/* 16  DACL, i.e. pointer to 92 below */
     199             : 
     200             :                 /*  20  SACL (from pointer above) */
     201             :                 4,          /* 20 revision (ADS) */
     202             :                 0,          /* 21 reserved */
     203             :                 72, 0,      /* 22 size --> takes us to 92 */
     204             :                 1, 0,       /* 24 ace count */
     205             :                 0, 0,       /* 26 reserved */
     206             : 
     207             :                 /*  now come SACL aces, of which there should be one */
     208             :                 18,         /* 28 ace type (SEC_ACE_TYPE_SYSTEM_RESOURCE_ATTRIBUTE) */
     209             :                 0,          /* 29 ace flags */
     210             :                 64, 0,      /* 30 ace size (from start of ACE, again adds to ending at 92) */
     211             :                 0, 0, 0, 0, /* 32 mask */
     212             : 
     213             :                 /*  here's the ACE SID */
     214             :                 1,                 /* 36 revision */
     215             :                 1,                 /* 37 sub-auth count */
     216             :                 0, 0, 0, 0, 0, 1,  /* 38 big endian ident auth */
     217             :                 0, 0, 0, 0,        /* 44 the sub-auth  (so SID is S-1-1-0 (everyone), mandatory with RA ace) */
     218             : 
     219             :                 /*  here starts the actual claim, at 48 */
     220             :                 20, 0, 0, 0,       /* 48 pointer to name (relative to claim, at 68) */
     221             :                 2, 0,              /* 52 value type (uint64) */
     222             :                 0, 0,              /* 54 reserved */
     223             :                 14, 0, 0, 0,       /* 56 flags (case-sensitive|deny-only|disabled-by-default -- the "0xe" in the SDDL) */
     224             :                 1, 0, 0, 0,        /* 60 value count */
     225             :                 34, 0, 0, 0,       /* 64 array of pointers, 1-long, points to 48 + 34 == 82 */
     226             :                                    /* 68 utf-16 letters "colOIr\0", indicated by name pointer at 48 */
     227             :                 'c', 0,
     228             :                 'o', 0,
     229             :                 'l', 0,
     230             :                 'O', 0,            /* unlike conditional ACE strings, this is nul-terminated. */
     231             :                 'I', 0,            /*   where does the next thing start:        */
     232             :                 'r', 0,            /*   6 letters + '\0' * 2 = 14. 68 + 14 = 82 */
     233             :                 0, 0,
     234             :                                    /* 82 is the value pointed to at 64 above (LE uint64) */
     235             :                 229, 116, 0, 0, 0, 0, 0, 0, /* this equals 229 + 116 * 256 == 29925, as we see in the SDDL. */
     236             : 
     237             :                 /*  88 the claim has ended. the ace has NEARLY ended, but we need to round up: */
     238             : 
     239             :                 0, 0,              /* 90 two bytes of padding to get to a multiple of 4. */
     240             :                 /* The ace and SACL have ended */
     241             : 
     242             :                 /*  92 the DACL starts. */
     243             :                 2,              /* 92 version (NT) */
     244             :                 0,              /* 93 reserved  */
     245             :                 40, 0,          /* 94 size */
     246             :                 1, 0,           /* 96 ace count */
     247             :                 0, 0,           /* 98 reserved */
     248             :                 /*  100 the DACL aces start */
     249             :                 9,              /* 100  ace type (SEC_ACE_TYPE_ACCESS_ALLOWED_CALLBACK) */
     250             :                 0,              /* 101  flags */
     251             :                 32, 0,          /* 102  ace size (ending at 132) */
     252             :                 63, 0, 0, 0,    /* 104  mask (let's assume CCDCLCSWRPWP as in sddl, not checked, but it's the right number of bits) */
     253             :                 /*  108 the ACE sid */
     254             :                 1,              /* 108 version */
     255             :                 1,              /* 109 sub-auths */
     256             :                 0, 0, 0, 0, 0, 16,/* 110 bigendian 16 identauth */
     257             :                 0, 33, 0, 0,    /* 116 sub-auth 1, 33 << 8 == 8448;  "S-1-16-8448" == "ML_MEDIUM_PLUS" == "MP" */
     258             :                 /*  120 here starts the callback */
     259             :                 97, 114, 116, 120, /* 120 'artx' */
     260             :                 250,              /* 124 0xfa CONDITIONAL_ACE_RESOURCE_ATTRIBUTE token */
     261             :                 2, 0, 0, 0,       /* 125 length 2 (bytes) */
     262             :                 'c', 0,            /* 129 utf-16 "c" -- NOT nul-terminated */
     263             :                 0                 /* 131 padding to bring length to a multiple of 4 (132) */
     264             :         };
     265           1 :         sd_ndr.length = 132;
     266           1 :         sd_ndr.data = sd_bytes;
     267             : 
     268           1 :         sec_desc_samba = sddl_decode(mem_ctx, sddl, NULL);
     269           1 :         assert_non_null(sec_desc_samba);
     270           1 :         ndr_err = ndr_pull_struct_blob(
     271             :                 &sd_ndr, mem_ctx, &sec_desc_windows,
     272             :                 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
     273             : 
     274           1 :         assert_true(NDR_ERR_CODE_IS_SUCCESS(ndr_err));
     275             : 
     276             :         /*
     277             :          * look, we munge the DACL version byte before comparing,
     278             :          * because Samba currently always does version 4.
     279             :          */
     280           1 :         sec_desc_windows.dacl->revision = SECURITY_ACL_REVISION_ADS;
     281           1 :         sd_bytes[92] = SECURITY_ACL_REVISION_ADS;
     282             : 
     283             :         /* push the structures back into blobs for 3-way comparisons. */
     284           1 :         ndr_err = ndr_push_struct_blob(
     285             :                 &sd_win_push, mem_ctx,
     286             :                 &sec_desc_windows,
     287             :                 (ndr_push_flags_fn_t)ndr_push_security_descriptor);
     288           1 :         assert_true(NDR_ERR_CODE_IS_SUCCESS(ndr_err));
     289             : 
     290           1 :         ndr_err = ndr_push_struct_blob(
     291             :                 &sd_samba_push, mem_ctx,
     292             :                 sec_desc_samba,
     293             :                 (ndr_push_flags_fn_t)ndr_push_security_descriptor);
     294           1 :         assert_true(NDR_ERR_CODE_IS_SUCCESS(ndr_err));
     295             : 
     296           1 :         assert_int_equal(sd_samba_push.length, sd_win_push.length);
     297           1 :         assert_int_equal(sd_samba_push.length, sd_ndr.length);
     298           1 :         assert_memory_equal(sd_samba_push.data,
     299             :                             sd_win_push.data,
     300             :                             sd_win_push.length);
     301           1 :         assert_memory_equal(sd_win_push.data,
     302             :                             sd_ndr.data,
     303             :                             sd_ndr.length);
     304             : 
     305           1 :         ok = security_descriptor_equal(sec_desc_samba, &sec_desc_windows);
     306           1 :         assert_true(ok);
     307           1 :         talloc_free(mem_ctx);
     308           1 : }
     309             : 
     310             : 
     311             : static void debug_conditional_ace_stderr(TALLOC_CTX *mem_ctx,
     312             :                                          struct ace_condition_script *program)
     313             : {
     314             :         char * debug_string = debug_conditional_ace(mem_ctx, program);
     315             : 
     316             :         if (debug_string != NULL) {
     317             :                 fputs(debug_string, stderr);
     318             :                 TALLOC_FREE(debug_string);
     319             :         } else {
     320             :                 print_message("failed to debug!\n");
     321             :         }
     322             : }
     323             : 
     324             : 
     325           1 : static void test_full_sddl_ra_encode(void **state)
     326             : {
     327             :         /*
     328             :          * This is an example from Windows that Samba once had trouble
     329             :          * with.
     330             :          */
     331           1 :         bool ok;
     332           1 :         enum ndr_err_code ndr_err;
     333           1 :         char *sddl = NULL;
     334           1 :         struct dom_sid domain_sid;
     335           1 :         uint8_t win_bytes[] = {
     336             :                 0x01, 0x00, 0x14, 0x80, /* descriptor header */
     337             :                 0x00, 0x00, 0x00, 0x00, /* NULL owner pointer */
     338             :                 0x00, 0x00, 0x00, 0x00, /* NULL group pointer */
     339             :                 0x14, 0x00, 0x00, 0x00, /* SACL at 0x14 (20) */
     340             :                 0x58, 0x01, 0x00, 0x00, /* DACL at 0x158 (344) */
     341             :                 /* SACL starts here (20) */
     342             :                 0x02, 0x00, /* rev 2, NT */
     343             :                 0x44, 0x01, /* size 0x0144 (324) -- ends at 344 */
     344             :                 0x01, 0x00, /* ace count */
     345             :                 0x00, 0x00, /* reserved */
     346             :                 /* ace starts here, 28 */
     347             :                 0x12, 0x00, /* ace type, flags: 0x12(18) is resource attribute  */
     348             :                 0x3c, 0x01, /* ACE size 0x13c == 316, from ACE start, end at 344 */
     349             :                 0x00, 0x00, 0x00, 0x00, /*ACE mask */
     350             :                 0x01, 0x01,  /* SID S-1-<identauth>-<1 subauth>) */
     351             :                 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* -1- indent auth */
     352             :                 0x00, 0x00, 0x00, 0x00,  /* -0  -> S-1-1-0, world */
     353             :                 /* claim starts here, 48 */
     354             :                 0x28, 0x00, 0x00, 0x00, /* pointer to name 40 (from claim start 48) = 88 */
     355             :                 0x10, 0x00,             /* type octet string */
     356             :                 0x00, 0x00,             /* empty */
     357             :                 0x00, 0x00, 0x00, 0x00, /* zero flags */
     358             :                 0x06, 0x00, 0x00, 0x00, /* value count */
     359             :                 /* array of 6 value pointers (at claim + 16, 64) */
     360             :                 0xf2, 0x00, 0x00, 0x00,  /* value 0xf2 = 242 from claim (48) == 290 */
     361             :                 0xf8, 0x00, 0x00, 0x00,  /* 0xf8, 248 */
     362             :                 0x0d, 0x01, 0x00, 0x00,  /* 0x10d, 269 */
     363             :                 0x14, 0x01, 0x00, 0x00,  /* 0x114, 276 */
     364             :                 0x1a, 0x01, 0x00, 0x00,  /* 0x11a, 282 */
     365             :                 0x21, 0x01, 0x00, 0x00,  /* 0x121, 289 */
     366             :                 /* here's the name, at 88 */
     367             :                 'c', 0x00,
     368             :                 'o', 0x00,
     369             :                 'l', 0x00,
     370             :                 'O', 0x00,
     371             :                 'I', 0x00,
     372             :                 'r', 0x00,  /* the following lines are all \x16 */
     373             :                 /* 100 */
     374             :                 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
     375             :                 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
     376             :                 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
     377             :                 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
     378             :                 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
     379             :                 /* 150 */
     380             :                 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
     381             :                 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
     382             :                 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
     383             :                 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
     384             :                 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
     385             :                 /* 200 */
     386             :                 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
     387             :                 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
     388             :                 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
     389             :                 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
     390             :                 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
     391             :                 /* 250 */
     392             :                 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
     393             :                 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
     394             :                 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
     395             :                 /* 280 */
     396             :                 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,  /* 286 */
     397             :                 'r', 0x00,
     398             :                 0x00, 0x00,   /* name is nul-terminated */
     399             :                 /* 290, first octet string blob */
     400             :                 0x02, 0x00, 0x00, 0x00, /* length 2 */
     401             :                 0x00, 0x77,             /* 2 blob bytes */
     402             :                 /* second blob @ 48 + 248 == 296 */
     403             :                 0x11, 0x00, 0x00, 0x00, /* length 0x11 = 17 */
     404             :                 0x00, 0x77, 0x77, 0x71, 0x83, 0x68, 0x96, 0x62, 0x95, 0x93,
     405             :                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
     406             :                 /* third blob at 269 + 48 == 317 */
     407             :                 0x03, 0x00, 0x00, 0x00,
     408             :                 0x00, 0x77, 0x77,
     409             :                 /* fourth blob, 276 + 48 == 324 */
     410             :                 0x02, 0x00, 0x00, 0x00,
     411             :                 0x00, 0x77,
     412             :                 /* fifth blob, 282 + 48 == 330 */
     413             :                 0x03, 0x00, 0x00, 0x00,
     414             :                 0x00, 0x77, 0x77,
     415             :                 /* last blob 289 + 48 == 337 */
     416             :                 0x03, 0x00, 0x00, 0x00,
     417             :                 0x00, 0x77, 0x77,
     418             :                 /* claim ends */
     419             :                 /* 344 DACL starts */
     420             :                 0x02, 0x00, /* rev 2 (NT) */
     421             :                 0x28, 0x00, /* size 40, ending at 384 */
     422             :                 0x01, 0x00, /* ace count */
     423             :                 0x00, 0x00,
     424             :                 /* ACE starts here, 352 */
     425             :                 0x09, 0x00, /* type 9, access allowed callback */
     426             :                 0x20, 0x00, /* size 32 */
     427             :                 0x3f, 0x00, 0x00, 0x00, /*mask */
     428             :                 0x01, 0x01, /* S-1-... (1 subauth) */
     429             :                 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, /*...-16-...*/
     430             :                 0x00, 0x21, 0x00, 0x00, /* -5356. S-1-16-5376 */
     431             :                 'a', 'r', 't', 'x',
     432             :                 0xfa, /* resource attr */
     433             :                 0x02, 0x00, 0x00, 0x00, /*name is 2 bytes long (i.e. 1 UTF-16) */
     434             :                 'c', 0x00, /* name is "c" */
     435             :                 /* here we're at 383, but need to round to a multiple of 4 with zeros: */
     436             :                 0x00
     437             :         };
     438           1 :         DATA_BLOB win_blob = {
     439             :                 .data = win_bytes,
     440             :                 .length = sizeof(win_bytes)
     441             :         };
     442             : 
     443           1 :         TALLOC_CTX *mem_ctx = talloc_new(NULL);
     444           1 :         struct security_descriptor sec_desc_windows = {};
     445           1 :         struct security_descriptor *sec_desc_samba = NULL;
     446             : 
     447           1 :         ndr_err = ndr_pull_struct_blob(
     448             :                 &win_blob, mem_ctx, &sec_desc_windows,
     449             :                 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
     450           1 :         assert_true(NDR_ERR_CODE_IS_SUCCESS(ndr_err));
     451             : 
     452           1 :         string_to_sid(&domain_sid, "S-1-2-3");
     453           1 :         sddl = sddl_encode(mem_ctx, &sec_desc_windows, &domain_sid);
     454           1 :         assert_non_null(sddl);
     455           1 :         sec_desc_samba = sddl_decode(mem_ctx, sddl, &domain_sid);
     456             : 
     457             :         /* hack the acl revision numbers */
     458           1 :         sec_desc_windows.dacl->revision = SECURITY_ACL_REVISION_ADS;
     459           1 :         sec_desc_windows.sacl->revision = SECURITY_ACL_REVISION_ADS;
     460           1 :         ok = security_descriptor_equal(sec_desc_samba, &sec_desc_windows);
     461           1 :         assert_true(ok);
     462           1 :         talloc_free(mem_ctx);
     463           1 : }
     464             : 
     465             : 
     466           1 : static void test_full_sddl_ra_escapes(void **state)
     467             : {
     468             :         /*
     469             :          * This is the security descriptor described in
     470             :          * test_full_sddl_ra_encode(), with SDDL.
     471             :          */
     472           1 :         enum ndr_err_code ndr_err;
     473           1 :         const char *sddl = (
     474             :                 "D:(XA;;CCDCLCSWRPWP;;;MP;(@RESOURCE.c))S:(RA;;;;;WD;(\""
     475             :                 "colOIr%0016%0016%0016%0016%0016%0016%0016%0016%0016%0016"
     476             :                 "%0016%0016%0016%0016%0016%0016%0016%0016%0016%0016%0016"
     477             :                 "%0016%0016%0016%0016%0016%0016%0016%0016%0016%0016%0016"
     478             :                 "%0016%0016%0016%0016%0016%0016%0016%0016%0016%0016%0016"
     479             :                 "%0016%0016%0016%0016%0016%0016%0016%0016%0016%0016%0016"
     480             :                 "%0016%0016%0016%0016%0016%0016%0016%0016%0016%0016%0016"
     481             :                 "%0016%0016%0016%0016%0016%0016%0016%0016%0016%0016%0016"
     482             :                 "%0016%0016%0016%0016%0016%0016%0016%0016%0016%0016%0016"
     483             :                 "%0016%0016%0016%0016%0016%0016%0016%0016%0016%0016%0016"
     484             :                 "%0016%0016%0016%0016%0016%0016%0016%0016%0016%0016%0016"
     485             :                 "%0016%0016%0016%0016%0016%0016r\","
     486             :                 "TX,0x0,"
     487             :                 "#0077,#00,#0077,#00,#0077,#00,#00,#00,#0077,#00,#0077,"
     488             :                 "#00,#0077,#007777,#007777,#0077,#007777,#0077,#007777,"
     489             :                 "#007770,#0077,#00,#0077,#00,#00,#00,#0077,#00,#0077,#00,"
     490             :                 "#0077,#007777,#007777,#0077,#007777,#0077,#007777,#007777))");
     491           1 :         uint8_t win_bytes[] = {
     492             :                 0x01, 0x00, 0x14, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     493             :                 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0xb0, 0x02, 0x00, 0x00,
     494             :                 0x02, 0x00, 0x9c, 0x02, 0x01, 0x00, 0x00, 0x00, 0x12, 0x00,
     495             :                 0x94, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00,
     496             :                 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x00,
     497             :                 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     498             :                 0x26, 0x00, 0x00, 0x00, 0x9e, 0x01, 0x00, 0x00, 0xa4, 0x01,
     499             :                 0x00, 0x00, 0xa9, 0x01, 0x00, 0x00, 0xaf, 0x01, 0x00, 0x00,
     500             :                 0xb4, 0x01, 0x00, 0x00, 0xba, 0x01, 0x00, 0x00, 0xbf, 0x01,
     501             :                 0x00, 0x00, 0xc4, 0x01, 0x00, 0x00, 0xc9, 0x01, 0x00, 0x00,
     502             :                 0xcf, 0x01, 0x00, 0x00, 0xd4, 0x01, 0x00, 0x00, 0xda, 0x01,
     503             :                 0x00, 0x00, 0xdf, 0x01, 0x00, 0x00, 0xe5, 0x01, 0x00, 0x00,
     504             :                 0xec, 0x01, 0x00, 0x00, 0xf3, 0x01, 0x00, 0x00, 0xf9, 0x01,
     505             :                 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x06, 0x02, 0x00, 0x00,
     506             :                 0x0d, 0x02, 0x00, 0x00, 0x14, 0x02, 0x00, 0x00, 0x1a, 0x02,
     507             :                 0x00, 0x00, 0x1f, 0x02, 0x00, 0x00, 0x25, 0x02, 0x00, 0x00,
     508             :                 0x2a, 0x02, 0x00, 0x00, 0x2f, 0x02, 0x00, 0x00, 0x34, 0x02,
     509             :                 0x00, 0x00, 0x3a, 0x02, 0x00, 0x00, 0x3f, 0x02, 0x00, 0x00,
     510             :                 0x45, 0x02, 0x00, 0x00, 0x4a, 0x02, 0x00, 0x00, 0x50, 0x02,
     511             :                 0x00, 0x00, 0x57, 0x02, 0x00, 0x00, 0x5e, 0x02, 0x00, 0x00,
     512             :                 0x64, 0x02, 0x00, 0x00, 0x6b, 0x02, 0x00, 0x00, 0x71, 0x02,
     513             :                 0x00, 0x00, 0x78, 0x02, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00,
     514             :                 0x6c, 0x00, 0x4f, 0x00, 0x49, 0x00, 0x72, 0x00, 0x16, 0x00,
     515             :                 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
     516             :                 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
     517             :                 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
     518             :                 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
     519             :                 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
     520             :                 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
     521             :                 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
     522             :                 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
     523             :                 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
     524             :                 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
     525             :                 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
     526             :                 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
     527             :                 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
     528             :                 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
     529             :                 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
     530             :                 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
     531             :                 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
     532             :                 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
     533             :                 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
     534             :                 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
     535             :                 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
     536             :                 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00,
     537             :                 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x16, 0x00, 0x72, 0x00,
     538             :                 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x77, 0x01, 0x00,
     539             :                 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x77, 0x01,
     540             :                 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x77,
     541             :                 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
     542             :                 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00,
     543             :                 0x77, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
     544             :                 0x00, 0x77, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
     545             :                 0x00, 0x00, 0x77, 0x03, 0x00, 0x00, 0x00, 0x00, 0x77, 0x77,
     546             :                 0x03, 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x02, 0x00, 0x00,
     547             :                 0x00, 0x00, 0x77, 0x03, 0x00, 0x00, 0x00, 0x00, 0x77, 0x77,
     548             :                 0x02, 0x00, 0x00, 0x00, 0x00, 0x77, 0x03, 0x00, 0x00, 0x00,
     549             :                 0x00, 0x77, 0x77, 0x03, 0x00, 0x00, 0x00, 0x00, 0x77, 0x70,
     550             :                 0x02, 0x00, 0x00, 0x00, 0x00, 0x77, 0x01, 0x00, 0x00, 0x00,
     551             :                 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x77, 0x01, 0x00, 0x00,
     552             :                 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
     553             :                 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x77, 0x01, 0x00,
     554             :                 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x77, 0x01,
     555             :                 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x77,
     556             :                 0x03, 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x03, 0x00, 0x00,
     557             :                 0x00, 0x00, 0x77, 0x77, 0x02, 0x00, 0x00, 0x00, 0x00, 0x77,
     558             :                 0x03, 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x02, 0x00, 0x00,
     559             :                 0x00, 0x00, 0x77, 0x03, 0x00, 0x00, 0x00, 0x00, 0x77, 0x77,
     560             :                 0x03, 0x00, 0x00, 0x00, 0x00, 0x77, 0x77, 0x00, 0x02, 0x00,
     561             :                 0x28, 0x00, 0x01, 0x00, 0x00, 0x00, 0x09, 0x00, 0x20, 0x00,
     562             :                 0x3f, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
     563             :                 0x00, 0x10, 0x00, 0x21, 0x00, 0x00, 0x61, 0x72, 0x74, 0x78,
     564             :                 0xfa, 0x02, 0x00, 0x00, 0x00, 0x63, 0x00, 0x00};
     565           1 :         DATA_BLOB win_blob = {
     566             :                 .data = win_bytes,
     567             :                 .length = sizeof(win_bytes)
     568             :         };
     569             : 
     570           1 :         TALLOC_CTX *mem_ctx = talloc_new(NULL);
     571           1 :         struct security_descriptor sec_desc_windows = {};
     572           1 :         struct security_descriptor *sec_desc_samba = sddl_decode(mem_ctx, sddl,
     573             :                                                                  NULL);
     574           1 :         assert_non_null(sec_desc_samba);
     575           1 :         ndr_err = ndr_pull_struct_blob(
     576             :                 &win_blob, mem_ctx, &sec_desc_windows,
     577             :                 (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);
     578             : 
     579           1 :         assert_true(NDR_ERR_CODE_IS_SUCCESS(ndr_err));
     580           1 : }
     581             : 
     582           1 : static void test_round_trips(void **state)
     583             : {
     584             :         /*
     585             :          * These expressions should parse into proper conditional
     586             :          * ACEs, which then decode into the same string.
     587             :          */
     588           1 :         static const char *sddl[] = {
     589             :                 ("(Member_of{SID(AA)})"),
     590             :                 ("(a Contains @USER.b == @device.c)"),
     591             :                 ("(a == @user.b == @resource.c)"),
     592             :                 ("(@Device.bb <= -00624677746777766777767)"),
     593             :                 ("(@Device.bb == 0624677746777766777767)"),
     594             :                 ("(@Device.%025cɜ == 3)"),
     595             :                 ("(17pq == 3||2a==@USER.7)"),
     596             :                 ("(x==1 && x >= 2 && @User.Title == @User.shoes || "
     597             :                  "Member_of{SID(CD)} && !(Member_of_Any{ 3 }) || "
     598             :                  "Device_Member_of{SID(BA), 7, 1, 3} "
     599             :                  "|| Exists hooly)"),
     600             :                 ("(!(!(!(!(!((!(x==1))))))))"),
     601             :                 ("(@User.a == {})"),
     602             :                 ("(Member_of{})"),
     603             :                 ("(Member_of {SID(S-1-33-5), "
     604             :                  "SID(BO)} && @Device.Bitlocker)"),
     605             :                 "(@USER.ad://ext/AuthenticationSilo == \"siloname\")",
     606             :                 "(@User.Division==\"Finance\" || @User.Division ==\"Sales\")",
     607             :                 "(@User.Title == @User.Title)",
     608             :                 "(@User.Title == \"PM\")",
     609             :                 "(OctetStringType==#01020300)",
     610             :                 "(@User.Project Any_of @Resource.Project)",
     611             :                 "(@user.x==1 &&(@user.x >@user.x ) )",
     612             :                 "(x==1) ",
     613             :                 "( x Contains 3)",
     614             :                 "( x < 3)",
     615             :                 "(x Any_of 3)",
     616             :                 "( x == SID(BA))",
     617             :                 "((x) == SID(BA))",
     618             :                 "(OctetStringType==#1#2#3###))",
     619             :         };
     620           1 :         size_t i, length;
     621           1 :         TALLOC_CTX *mem_ctx = talloc_new(NULL);
     622           1 :         bool failed = false;
     623           1 :         bool ok;
     624          28 :         for (i = 0; i < ARRAY_SIZE(sddl); i++) {
     625          26 :                 struct ace_condition_script *s1 = NULL;
     626          26 :                 struct ace_condition_script *s2 = NULL;
     627          26 :                 struct ace_condition_script *s3 = NULL;
     628          26 :                 const char *message = NULL;
     629          26 :                 size_t message_offset;
     630          26 :                 const char *resddl1 = NULL;
     631          26 :                 const char *resddl2 = NULL;
     632          26 :                 DATA_BLOB e1, e2, e3;
     633          26 :                 fputs("=======================\n", stderr);
     634          26 :                 s1 = ace_conditions_compile_sddl(mem_ctx,
     635             :                                                  ACE_CONDITION_FLAG_ALLOW_DEVICE,
     636             :                                                  sddl[i],
     637             :                                                  &message,
     638             :                                                  &message_offset,
     639             :                                                  &length);
     640          26 :                 if (s1 == NULL) {
     641           0 :                         debug_fail("%s\n", sddl[i]);
     642           0 :                         failed = true;
     643           0 :                         print_error_message(sddl[i], message, message_offset);
     644           0 :                         continue;
     645             :                 }
     646          26 :                 if (false) {
     647             :                         debug_conditional_ace_stderr(mem_ctx, s1);
     648             :                 }
     649          26 :                 ok = conditional_ace_encode_binary(mem_ctx, s1, &e1);
     650          26 :                 if (! ok) {
     651           0 :                         failed = true;
     652           0 :                         debug_fail("%s could not encode\n", sddl[i]);
     653           0 :                         continue;
     654             :                 }
     655             : 
     656          26 :                 s2 = parse_conditional_ace(mem_ctx, e1);
     657          26 :                 if (s2 == NULL) {
     658           0 :                         debug_fail("%s failed to decode ace\n", sddl[i]);
     659           0 :                         failed = true;
     660           0 :                         continue;
     661             :                 }
     662             : 
     663          26 :                 ok = conditional_ace_encode_binary(mem_ctx, s2, &e2);
     664          26 :                 if (! ok) {
     665           0 :                         failed = true;
     666           0 :                         debug_fail("%s could not re-encode\n", sddl[i]);
     667           0 :                         continue;
     668             :                 }
     669          26 :                 if (data_blob_cmp(&e1, &e2) != 0) {
     670           0 :                         failed = failed || ok;
     671             :                 }
     672             : 
     673          26 :                 resddl1 = sddl_from_conditional_ace(mem_ctx, s1);
     674          26 :                 if (resddl1 == NULL) {
     675           0 :                         failed = true;
     676           0 :                         debug_fail("could not re-make SDDL of %s\n", sddl[i]);
     677           0 :                         continue;
     678             :                 }
     679          26 :                 resddl2 = sddl_from_conditional_ace(mem_ctx, s2);
     680          26 :                 if (resddl2 == NULL) {
     681           0 :                         failed = true;
     682           0 :                         debug_fail("could not re-make SDDL of %s\n", sddl[i]);
     683           0 :                         continue;
     684             :                 }
     685          26 :                 if (strcmp(resddl1, resddl2) != 0) {
     686           0 :                         print_message("SDDL 2: %s\n", resddl2);
     687           0 :                         failed = failed || ok;
     688             :                 }
     689          26 :                 print_message("SDDL: %s\n", resddl1);
     690          26 :                 s3 = ace_conditions_compile_sddl(mem_ctx,
     691             :                                                  ACE_CONDITION_FLAG_ALLOW_DEVICE,
     692             :                                                  resddl1,
     693             :                                                  &message,
     694             :                                                  &message_offset,
     695             :                                                  &length);
     696          26 :                 if (s3 == NULL) {
     697           0 :                         debug_fail("resddl: %s\n", resddl1);
     698           0 :                         failed = true;
     699           0 :                         print_error_message(resddl1, message, message_offset);
     700           0 :                         continue;
     701             :                 }
     702          26 :                 ok = conditional_ace_encode_binary(mem_ctx, s3, &e3);
     703          26 :                 if (! ok) {
     704           0 :                         failed = true;
     705           0 :                         debug_fail("%s could not encode\n", resddl1);
     706           0 :                         continue;
     707             :                 }
     708          26 :                 if (data_blob_cmp(&e1, &e2) != 0) {
     709           0 :                         debug_fail("'%s' compiled differently\n", resddl1);
     710             :                         failed = failed || ok;
     711             :                 }
     712             :         }
     713           1 :         assert_false(failed);
     714           1 : }
     715             : 
     716           1 : static void test_a_number_of_valid_strings(void **state)
     717             : {
     718             :         /*
     719             :          * These expressions should parse into proper conditional ACEs.
     720             :          */
     721           1 :         static const char *sddl[] = {
     722             :                 "(@User.TEETH == \"5\")",
     723             :                 "(x==1) ",
     724             :                 "( x Contains 3)",
     725             :                 "( x < 3)",
     726             :                 "(x Any_of 3)",
     727             :                 "( x == SID(BA))",
     728             :                 "(x ANY_Of 3)",
     729             :                 "((x) == SID(BA))",
     730             :                 "(x==1 && x >= 2)", /* logical consistency not required */
     731             :         };
     732           1 :         size_t i, length;
     733           1 :         TALLOC_CTX *mem_ctx = talloc_new(NULL);
     734           1 :         bool failed = false;
     735          11 :         for (i = 0; i < ARRAY_SIZE(sddl); i++) {
     736           9 :                 struct ace_condition_script *s = NULL;
     737           9 :                 const char *message = NULL;
     738           9 :                 size_t message_offset;
     739             : 
     740           9 :                 s = ace_conditions_compile_sddl(mem_ctx,
     741             :                                                 ACE_CONDITION_FLAG_ALLOW_DEVICE,
     742             :                                                 sddl[i],
     743             :                                                 &message,
     744             :                                                 &message_offset,
     745             :                                                 &length);
     746           9 :                 if (s == NULL) {
     747           0 :                         debug_fail("%s\n", sddl[i]);
     748             :                         failed = true;
     749           9 :                 } else if (length != strlen(sddl[i])) {
     750           0 :                         debug_fail("%s failed to consume whole string\n",
     751             :                                    sddl[i]);
     752             :                         failed = true;
     753             :                 }
     754           9 :                 if (message != NULL) {
     755           9 :                         print_error_message(sddl[i], message, message_offset);
     756           9 :                 } else if (s == NULL) {
     757           0 :                         print_message("failed without message\n");
     758             :                 }
     759             :         }
     760           1 :         assert_false(failed);
     761           1 : }
     762             : 
     763             : 
     764           1 : static void test_a_number_of_invalid_strings(void **state)
     765             : {
     766             :         /*
     767             :          * These expressions should fail to parse.
     768             :          */
     769           1 :         static const char *sddl[] = {
     770             :                 /* '!' is only allowed before parens or @attr */
     771             :                 "(!!! !!!  !!! Not_Member_of{SID(AA)}))",
     772             :                 /* overflowing numbers can't be sensibly interpreted */
     773             :                 ("(@Device.bb == 055555624677746777766777767)"),
     774             :                 ("(@Device.bb == 0x624677746777766777767)"),
     775             :                 ("(@Device.bb == 624677746777766777767)"),
     776             :                 /* insufficient arguments */
     777             :                 "(!)",
     778             :                 "(x >)",
     779             :                 "(> 3)",
     780             :                 /* keyword as local attribute name */
     781             :                 "( Member_of Contains 3)",
     782             :                 /* no parens */
     783             :                 " x < 3",
     784             :                 /* wants '==' */
     785             :                 "( x = SID(BA))",
     786             :                 /* invalid SID strings */
     787             :                 "( x == SID(ZZ))",
     788             :                 "( x == SID(S-1-))",
     789             :                 "( x == SID())",
     790             :                 /* literal on LHS */
     791             :                 "(\"x\" == \"x\")",
     792             :                 /* odd number of digits following '#' */
     793             :                 "(OctetStringType==#1#2#3##))",
     794             :                 /* empty expression */
     795             :                 "()",
     796             :                 /* relational op with with complex RHS */
     797             :                 "(@Device.bb == (@USER.x < 62))",
     798             :                 /* hex‐escapes that should be literals */
     799             :                 ("(@Device.%002e == 3)"),
     800             :                 ("(@Device.%002f == 3)"),
     801             :                 ("(@Device.%003a == 3)"),
     802             :                 /* trailing comma in composite */
     803             :                 "(Member_of{SID(AA),})",
     804             :                 /* missing comma between elements of a composite */
     805             :                 "(Member_of{SID(AA) SID(AC)})",
     806             :                 /* unexpected comma in composite */
     807             :                 "(Member_of{,})",
     808             :         };
     809           1 :         size_t i, length;
     810           1 :         TALLOC_CTX *mem_ctx = talloc_new(NULL);
     811           1 :         bool failed_to_fail = false;
     812          25 :         for (i = 0; i < ARRAY_SIZE(sddl); i++) {
     813          23 :                 struct ace_condition_script *s = NULL;
     814          23 :                 const char *message = NULL;
     815          23 :                 size_t message_offset;
     816          23 :                 s = ace_conditions_compile_sddl(mem_ctx,
     817             :                                                 ACE_CONDITION_FLAG_ALLOW_DEVICE,
     818             :                                                 sddl[i],
     819             :                                                 &message,
     820             :                                                 &message_offset,
     821             :                                                 &length);
     822          23 :                 if (s != NULL) {
     823           0 :                         print_message("unexpected success: ");
     824           0 :                         debug_fail("%s\n", sddl[i]);
     825             :                         failed_to_fail = true;
     826             :                 }
     827          23 :                 if (message != NULL) {
     828          46 :                         print_error_message(sddl[i], message, message_offset);
     829           0 :                 } else if (s == NULL) {
     830           0 :                         print_message("failed without message\n");
     831             :                 }
     832             :         }
     833           1 :         assert_false(failed_to_fail);
     834           1 : }
     835             : 
     836             : 
     837           1 : static void test_a_number_of_invalid_full_sddl_strings(void **state)
     838             : {
     839             :         /*
     840             :          * These ones are complete SDDL sentences and should fail to parse,
     841             :          * with specific message snippets.
     842             :          */
     843           1 :         static struct {
     844             :                 const char *sddl;
     845             :                 const char *snippet;
     846             :                 ssize_t offset;
     847             :         } cases[] = {
     848             :                 {
     849             :                         "O:SYG:SYD:(A;;;;ZZ)(XA;OICI;CR;;;WD;(Member_of {WD}))",
     850             :                         "malformed ACE with only 4 ';'",
     851             :                         11
     852             :                 },
     853             :                 {
     854             :                         "O:SYG:SYD:QQ(A;;;;ZZ)(XA;OICI;CR;;;WD;(Member_of {WD}))",
     855             :                         "expected '[OGDS]:' section start",
     856             :                         10
     857             :                 }
     858             :         };
     859           1 :         size_t i;
     860           1 :         TALLOC_CTX *mem_ctx = talloc_new(NULL);
     861           1 :         bool failed_to_fail = false;
     862           1 :         bool message_wrong = false;
     863           1 :         enum ace_condition_flags ace_condition_flags = \
     864             :                 ACE_CONDITION_FLAG_ALLOW_DEVICE;
     865           1 :         struct dom_sid domain_sid;
     866           1 :         string_to_sid(&domain_sid, "S-1-2-3");
     867             : 
     868           4 :         for (i = 0; i < ARRAY_SIZE(cases); i++) {
     869           2 :                 struct security_descriptor *sd = NULL;
     870           2 :                 const char *message = NULL;
     871           2 :                 size_t message_offset;
     872           2 :                 sd = sddl_decode_err_msg(mem_ctx,
     873             :                                          cases[i].sddl,
     874             :                                          &domain_sid,
     875             :                                          ace_condition_flags,
     876             :                                          &message,
     877             :                                          &message_offset);
     878           2 :                 if (sd != NULL) {
     879           0 :                         print_message("unexpected success: ");
     880           0 :                         debug_fail("%s\n", cases[i].sddl);
     881             :                         failed_to_fail = true;
     882             :                 }
     883           2 :                 if (cases[i].snippet != NULL) {
     884           2 :                         if (message != NULL) {
     885           2 :                                 char *c = strstr(message, cases[i].snippet);
     886           2 :                                 print_error_message(cases[i].sddl,
     887             :                                                     message,
     888             :                                                     message_offset);
     889           2 :                                 if (c == NULL) {
     890           0 :                                         message_wrong = true;
     891           0 :                                         print_message("expected '%s'\n",
     892             :                                                       cases[i].snippet);
     893             :                                 }
     894             :                         } else {
     895           0 :                                 message_wrong = true;
     896           0 :                                 print_error_message(cases[i].sddl,
     897             :                                                     "NO MESSAGE!",
     898             :                                                     message_offset);
     899           0 :                                 print_message("expected '%s', got no message!\n",
     900             :                                               cases[i].snippet);
     901             :                         }
     902             :                 } else {
     903           0 :                         print_message("no assertion about message, got '%s'\n",
     904             :                                       message);
     905             :                 }
     906           2 :                 if (cases[i].offset >= 0) {
     907           2 :                         if (cases[i].offset != message_offset) {
     908           0 :                                 message_wrong = true;
     909           0 :                                 print_message("expected offset %zd, got %zu\n",
     910             :                                               cases[i].offset,
     911             :                                               message_offset);
     912             :                         }
     913             :                 } else {
     914           0 :                         print_message("no assertion about offset, got '%zu\n",
     915             :                                       message_offset);
     916             :                 }
     917             :         }
     918           1 :         assert_false(failed_to_fail);
     919           1 :         assert_false(message_wrong);
     920           1 : }
     921             : 
     922             : 
     923           1 : static void test_valid_strings_with_trailing_crap(void **state)
     924             : {
     925             :         /*
     926             :          * These expressions should parse even though they have
     927             :          * trailing bytes that look bad.
     928             :          *
     929             :          *  ace_conditions_compile_sddl() will return when it has
     930             :          *  found a complete expression, and tell us how much it used.
     931             :          */
     932           1 :         static struct {
     933             :                 const char *sddl;
     934             :                 size_t length;
     935             :         } pairs[] = {
     936             :                 {"(x==1 &&(x < 5 )) )", 18},
     937             :                 {"(x==1) &&", 7},
     938             :                 {"(x)) ", 3},
     939             :         };
     940           1 :         size_t i, length;
     941           1 :         TALLOC_CTX *mem_ctx = talloc_new(NULL);
     942           1 :         bool failed = false;
     943           5 :         for (i = 0; i < ARRAY_SIZE(pairs); i++) {
     944           3 :                 struct ace_condition_script *s = NULL;
     945           3 :                 const char *message = NULL;
     946           3 :                 size_t message_offset;
     947           3 :                 s = ace_conditions_compile_sddl(mem_ctx,
     948             :                                                 ACE_CONDITION_FLAG_ALLOW_DEVICE,
     949             :                                                 pairs[i].sddl,
     950             :                                                 &message,
     951             :                                                 &message_offset,
     952             :                                                 &length);
     953             : 
     954           3 :                 if (s == NULL) {
     955           0 :                         debug_fail("%s\n", pairs[i].sddl);
     956             :                         failed = true;
     957           3 :                 } else if (pairs[i].length == length) {
     958           3 :                         debug_ok("%s\n", pairs[i].sddl);
     959             :                 } else {
     960           0 :                         debug_fail("expected to consume %zu bytes, actual %zu\n",
     961             :                                    pairs[i].length, length);
     962             :                         failed = true;
     963             :                 }
     964           3 :                 if (message != NULL) {
     965           3 :                         print_error_message(pairs[i].sddl, message, message_offset);
     966           3 :                 } else if (s == NULL) {
     967           0 :                         print_message("failed without message\n");
     968             :                 }
     969             :         }
     970           1 :         assert_false(failed);
     971           1 : }
     972             : 
     973             : 
     974           1 : int main(_UNUSED_ int argc, _UNUSED_ const char **argv)
     975             : {
     976           1 :         const struct CMUnitTest tests[] = {
     977             :                 cmocka_unit_test(test_a_number_of_invalid_full_sddl_strings),
     978             :                 cmocka_unit_test(test_full_sddl_ra_encode),
     979             :                 cmocka_unit_test(test_full_sddl_ra_escapes),
     980             :                 cmocka_unit_test(test_full_sddl_compile),
     981             :                 cmocka_unit_test(test_round_trips),
     982             :                 cmocka_unit_test(test_a_number_of_invalid_strings),
     983             :                 cmocka_unit_test(test_a_number_of_valid_strings),
     984             :                 cmocka_unit_test(test_valid_strings_with_trailing_crap),
     985             :                 cmocka_unit_test(test_sddl_compile),
     986             :                 cmocka_unit_test(test_sddl_compile2),
     987             :         };
     988           1 :         if (!isatty(1)) {
     989           1 :                 cmocka_set_message_output(CM_OUTPUT_SUBUNIT);
     990             :         }
     991           1 :         return cmocka_run_group_tests(tests, NULL, NULL);
     992             : }

Generated by: LCOV version 1.14