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 master 2f515e9b Lines: 228 285 80.0 %
Date: 2024-04-21 15:09:00 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 encode into an equivalent SDDL string,
     587             :          * which then parses again into the same conditional ACE.
     588             :          */
     589           1 :         static const char *sddl[] = {
     590             :                 "(0>-0)",
     591             :                 "(0>+0)",
     592             :                 ("(Member_of{SID(AA)})"),
     593             :                 ("(a Contains @USER.b == @device.c)"),
     594             :                 ("(a == @user.b == @resource.c)"),
     595             :                 ("(@Device.bb <= -00624677746777766777767)"),
     596             :                 ("(@Device.bb == 0624677746777766777767)"),
     597             :                 ("(@Device.%025cɜ == 3)"),
     598             :                 ("(17pq == 3||2a==@USER.7)"),
     599             :                 ("(x==1 && x >= 2 && @User.Title == @User.shoes || "
     600             :                  "Member_of{SID(CD)} && !(Member_of_Any{ 3 }) || "
     601             :                  "Device_Member_of{SID(BA), 7, 1, 3} "
     602             :                  "|| Exists hooly)"),
     603             :                 ("(!(!(!(!(!((!(x==1))))))))"),
     604             :                 ("(@User.a == {})"),
     605             :                 ("(Member_of{})"),
     606             :                 ("(Member_of {SID(S-1-33-5), "
     607             :                  "SID(BO)} && @Device.Bitlocker)"),
     608             :                 "(@USER.ad://ext/AuthenticationSilo == \"siloname\")",
     609             :                 "(@User.Division==\"Finance\" || @User.Division ==\"Sales\")",
     610             :                 "(@User.Title == @User.Title)",
     611             :                 "(@User.Title == \"PM\")",
     612             :                 "(OctetStringType==#01020300)",
     613             :                 "(@User.Project Any_of @Resource.Project)",
     614             :                 "(@user.x==1 &&(@user.x >@user.x ) )",
     615             :                 "(x==1) ",
     616             :                 "( x Contains 3)",
     617             :                 "( x < 3)",
     618             :                 "(x Any_of 3)",
     619             :                 "( x == SID(BA))",
     620             :                 "((x) == SID(BA))",
     621             :                 "(OctetStringType==#1#2#3###))",
     622             :                 "(@user.x == 00)",
     623             :                 "(@user.x == 01)",
     624             :                 "(@user.x == -00)",
     625             :                 "(@user.x == -01)",
     626             :                 "(@user.x == 0x0)",
     627             :                 "(@user.x == 0x1)",
     628             :                 "(@user.x == -0x0)",
     629             :                 "(@user.x == -0x1)",
     630             :         };
     631           1 :         size_t i, length;
     632           1 :         TALLOC_CTX *mem_ctx = talloc_new(NULL);
     633           1 :         bool failed = false;
     634           1 :         bool ok;
     635          38 :         for (i = 0; i < ARRAY_SIZE(sddl); i++) {
     636          36 :                 struct ace_condition_script *s1 = NULL;
     637          36 :                 struct ace_condition_script *s2 = NULL;
     638          36 :                 struct ace_condition_script *s3 = NULL;
     639          36 :                 const char *message = NULL;
     640          36 :                 size_t message_offset;
     641          36 :                 const char *resddl1 = NULL;
     642          36 :                 const char *resddl2 = NULL;
     643          36 :                 DATA_BLOB e1, e2, e3;
     644          36 :                 fputs("=======================\n", stderr);
     645          36 :                 s1 = ace_conditions_compile_sddl(mem_ctx,
     646             :                                                  ACE_CONDITION_FLAG_ALLOW_DEVICE,
     647             :                                                  sddl[i],
     648             :                                                  &message,
     649             :                                                  &message_offset,
     650             :                                                  &length);
     651          36 :                 if (s1 == NULL) {
     652           0 :                         debug_fail("%s\n", sddl[i]);
     653           0 :                         failed = true;
     654           0 :                         print_error_message(sddl[i], message, message_offset);
     655           0 :                         continue;
     656             :                 }
     657          36 :                 if (false) {
     658             :                         debug_conditional_ace_stderr(mem_ctx, s1);
     659             :                 }
     660          36 :                 ok = conditional_ace_encode_binary(mem_ctx, s1, &e1);
     661          36 :                 if (! ok) {
     662           0 :                         failed = true;
     663           0 :                         debug_fail("%s could not encode\n", sddl[i]);
     664           0 :                         continue;
     665             :                 }
     666             : 
     667          36 :                 s2 = parse_conditional_ace(mem_ctx, e1);
     668          36 :                 if (s2 == NULL) {
     669           0 :                         debug_fail("%s failed to decode ace\n", sddl[i]);
     670           0 :                         failed = true;
     671           0 :                         continue;
     672             :                 }
     673             : 
     674          36 :                 ok = conditional_ace_encode_binary(mem_ctx, s2, &e2);
     675          36 :                 if (! ok) {
     676           0 :                         failed = true;
     677           0 :                         debug_fail("%s could not re-encode\n", sddl[i]);
     678           0 :                         continue;
     679             :                 }
     680          36 :                 if (data_blob_cmp(&e1, &e2) != 0) {
     681           0 :                         failed = true;
     682             :                 }
     683             : 
     684          36 :                 resddl1 = sddl_from_conditional_ace(mem_ctx, s1);
     685          36 :                 if (resddl1 == NULL) {
     686           0 :                         failed = true;
     687           0 :                         debug_fail("could not re-make SDDL of %s\n", sddl[i]);
     688           0 :                         continue;
     689             :                 }
     690          36 :                 resddl2 = sddl_from_conditional_ace(mem_ctx, s2);
     691          36 :                 if (resddl2 == NULL) {
     692           0 :                         failed = true;
     693           0 :                         debug_fail("could not re-make SDDL of %s\n", sddl[i]);
     694           0 :                         continue;
     695             :                 }
     696          36 :                 if (strcmp(resddl1, resddl2) != 0) {
     697           0 :                         print_message("SDDL 2: %s\n", resddl2);
     698           0 :                         failed = true;
     699             :                 }
     700          36 :                 print_message("SDDL: '%s' -> '%s'\n", sddl[i], resddl1);
     701          36 :                 s3 = ace_conditions_compile_sddl(mem_ctx,
     702             :                                                  ACE_CONDITION_FLAG_ALLOW_DEVICE,
     703             :                                                  resddl1,
     704             :                                                  &message,
     705             :                                                  &message_offset,
     706             :                                                  &length);
     707          36 :                 if (s3 == NULL) {
     708           0 :                         debug_fail("resddl: %s\n", resddl1);
     709           0 :                         failed = true;
     710           0 :                         print_error_message(resddl1, message, message_offset);
     711           0 :                         continue;
     712             :                 }
     713          36 :                 ok = conditional_ace_encode_binary(mem_ctx, s3, &e3);
     714          36 :                 if (! ok) {
     715           0 :                         failed = true;
     716           0 :                         debug_fail("%s could not encode\n", resddl1);
     717           0 :                         continue;
     718             :                 }
     719          36 :                 if (data_blob_cmp(&e1, &e3) != 0) {
     720           0 :                         debug_fail("'%s' and '%s' compiled differently\n", sddl[i], resddl1);
     721             :                         failed = true;
     722             :                 }
     723             :         }
     724           1 :         assert_false(failed);
     725           1 : }
     726             : 
     727           1 : static void test_a_number_of_valid_strings(void **state)
     728             : {
     729             :         /*
     730             :          * These expressions should parse into proper conditional ACEs.
     731             :          */
     732           1 :         static const char *sddl[] = {
     733             :                 "(@User.TEETH == \"5\")",
     734             :                 "(x==1) ",
     735             :                 "( x Contains 3)",
     736             :                 "( x < 3)",
     737             :                 "(x Any_of 3)",
     738             :                 "( x == SID(BA))",
     739             :                 "(x ANY_Of 3)",
     740             :                 "((x) == SID(BA))",
     741             :                 "(x==1 && x >= 2)", /* logical consistency not required */
     742             :         };
     743           1 :         size_t i, length;
     744           1 :         TALLOC_CTX *mem_ctx = talloc_new(NULL);
     745           1 :         bool failed = false;
     746          11 :         for (i = 0; i < ARRAY_SIZE(sddl); i++) {
     747           9 :                 struct ace_condition_script *s = NULL;
     748           9 :                 const char *message = NULL;
     749           9 :                 size_t message_offset;
     750             : 
     751           9 :                 s = ace_conditions_compile_sddl(mem_ctx,
     752             :                                                 ACE_CONDITION_FLAG_ALLOW_DEVICE,
     753             :                                                 sddl[i],
     754             :                                                 &message,
     755             :                                                 &message_offset,
     756             :                                                 &length);
     757           9 :                 if (s == NULL) {
     758           0 :                         debug_fail("%s\n", sddl[i]);
     759             :                         failed = true;
     760           9 :                 } else if (length != strlen(sddl[i])) {
     761           0 :                         debug_fail("%s failed to consume whole string\n",
     762             :                                    sddl[i]);
     763             :                         failed = true;
     764             :                 }
     765           9 :                 if (message != NULL) {
     766           9 :                         print_error_message(sddl[i], message, message_offset);
     767           9 :                 } else if (s == NULL) {
     768           0 :                         print_message("failed without message\n");
     769             :                 }
     770             :         }
     771           1 :         assert_false(failed);
     772           1 : }
     773             : 
     774             : 
     775           1 : static void test_a_number_of_invalid_strings(void **state)
     776             : {
     777             :         /*
     778             :          * These expressions should fail to parse.
     779             :          */
     780           1 :         static const char *sddl[] = {
     781             :                 /* '!' is only allowed before parens or @attr */
     782             :                 "(!!! !!!  !!! Not_Member_of{SID(AA)}))",
     783             :                 /* overflowing numbers can't be sensibly interpreted */
     784             :                 ("(@Device.bb == 055555624677746777766777767)"),
     785             :                 ("(@Device.bb == 0x624677746777766777767)"),
     786             :                 ("(@Device.bb == 624677746777766777767)"),
     787             :                 /* insufficient arguments */
     788             :                 "(!)",
     789             :                 "(x >)",
     790             :                 "(> 3)",
     791             :                 /* keyword as local attribute name */
     792             :                 "( Member_of Contains 3)",
     793             :                 /* no parens */
     794             :                 " x < 3",
     795             :                 /* wants '==' */
     796             :                 "( x = SID(BA))",
     797             :                 /* invalid SID strings */
     798             :                 "( x == SID(ZZ))",
     799             :                 "( x == SID(S-1-))",
     800             :                 "( x == SID())",
     801             :                 /* literal on LHS */
     802             :                 "(\"x\" == \"x\")",
     803             :                 /* odd number of digits following '#' */
     804             :                 "(OctetStringType==#1#2#3##))",
     805             :                 /* empty expression */
     806             :                 "()",
     807             :                 /* relational op with with complex RHS */
     808             :                 "(@Device.bb == (@USER.x < 62))",
     809             :                 /* hex‐escapes that should be literals */
     810             :                 ("(@Device.%002e == 3)"),
     811             :                 ("(@Device.%002f == 3)"),
     812             :                 ("(@Device.%003a == 3)"),
     813             :                 /* trailing comma in composite */
     814             :                 "(Member_of{SID(AA),})",
     815             :                 /* missing comma between elements of a composite */
     816             :                 "(Member_of{SID(AA) SID(AC)})",
     817             :                 /* unexpected comma in composite */
     818             :                 "(Member_of{,})",
     819             :         };
     820           1 :         size_t i, length;
     821           1 :         TALLOC_CTX *mem_ctx = talloc_new(NULL);
     822           1 :         bool failed_to_fail = false;
     823          25 :         for (i = 0; i < ARRAY_SIZE(sddl); i++) {
     824          23 :                 struct ace_condition_script *s = NULL;
     825          23 :                 const char *message = NULL;
     826          23 :                 size_t message_offset;
     827          23 :                 s = ace_conditions_compile_sddl(mem_ctx,
     828             :                                                 ACE_CONDITION_FLAG_ALLOW_DEVICE,
     829             :                                                 sddl[i],
     830             :                                                 &message,
     831             :                                                 &message_offset,
     832             :                                                 &length);
     833          23 :                 if (s != NULL) {
     834           0 :                         print_message("unexpected success: ");
     835           0 :                         debug_fail("%s\n", sddl[i]);
     836             :                         failed_to_fail = true;
     837             :                 }
     838          23 :                 if (message != NULL) {
     839          46 :                         print_error_message(sddl[i], message, message_offset);
     840           0 :                 } else if (s == NULL) {
     841           0 :                         print_message("failed without message\n");
     842             :                 }
     843             :         }
     844           1 :         assert_false(failed_to_fail);
     845           1 : }
     846             : 
     847             : 
     848           1 : static void test_a_number_of_invalid_full_sddl_strings(void **state)
     849             : {
     850             :         /*
     851             :          * These ones are complete SDDL sentences and should fail to parse,
     852             :          * with specific message snippets.
     853             :          */
     854           1 :         static struct {
     855             :                 const char *sddl;
     856             :                 const char *snippet;
     857             :                 ssize_t offset;
     858             :         } cases[] = {
     859             :                 {
     860             :                         "O:SYG:SYD:(A;;;;ZZ)(XA;OICI;CR;;;WD;(Member_of {WD}))",
     861             :                         "malformed ACE with only 4 ';'",
     862             :                         11
     863             :                 },
     864             :                 {
     865             :                         "O:SYG:SYD:QQ(A;;;;ZZ)(XA;OICI;CR;;;WD;(Member_of {WD}))",
     866             :                         "expected '[OGDS]:' section start",
     867             :                         10
     868             :                 }
     869             :         };
     870           1 :         size_t i;
     871           1 :         TALLOC_CTX *mem_ctx = talloc_new(NULL);
     872           1 :         bool failed_to_fail = false;
     873           1 :         bool message_wrong = false;
     874           1 :         enum ace_condition_flags ace_condition_flags = \
     875             :                 ACE_CONDITION_FLAG_ALLOW_DEVICE;
     876           1 :         struct dom_sid domain_sid;
     877           1 :         string_to_sid(&domain_sid, "S-1-2-3");
     878             : 
     879           4 :         for (i = 0; i < ARRAY_SIZE(cases); i++) {
     880           2 :                 struct security_descriptor *sd = NULL;
     881           2 :                 const char *message = NULL;
     882           2 :                 size_t message_offset;
     883           2 :                 sd = sddl_decode_err_msg(mem_ctx,
     884             :                                          cases[i].sddl,
     885             :                                          &domain_sid,
     886             :                                          ace_condition_flags,
     887             :                                          &message,
     888             :                                          &message_offset);
     889           2 :                 if (sd != NULL) {
     890           0 :                         print_message("unexpected success: ");
     891           0 :                         debug_fail("%s\n", cases[i].sddl);
     892             :                         failed_to_fail = true;
     893             :                 }
     894           2 :                 if (cases[i].snippet != NULL) {
     895           2 :                         if (message != NULL) {
     896           2 :                                 char *c = strstr(message, cases[i].snippet);
     897           2 :                                 print_error_message(cases[i].sddl,
     898             :                                                     message,
     899             :                                                     message_offset);
     900           2 :                                 if (c == NULL) {
     901           0 :                                         message_wrong = true;
     902           0 :                                         print_message("expected '%s'\n",
     903             :                                                       cases[i].snippet);
     904             :                                 }
     905             :                         } else {
     906           0 :                                 message_wrong = true;
     907           0 :                                 print_error_message(cases[i].sddl,
     908             :                                                     "NO MESSAGE!",
     909             :                                                     message_offset);
     910           0 :                                 print_message("expected '%s', got no message!\n",
     911             :                                               cases[i].snippet);
     912             :                         }
     913             :                 } else {
     914           0 :                         print_message("no assertion about message, got '%s'\n",
     915             :                                       message);
     916             :                 }
     917           2 :                 if (cases[i].offset >= 0) {
     918           2 :                         if (cases[i].offset != message_offset) {
     919           0 :                                 message_wrong = true;
     920           0 :                                 print_message("expected offset %zd, got %zu\n",
     921             :                                               cases[i].offset,
     922             :                                               message_offset);
     923             :                         }
     924             :                 } else {
     925           0 :                         print_message("no assertion about offset, got '%zu\n",
     926             :                                       message_offset);
     927             :                 }
     928             :         }
     929           1 :         assert_false(failed_to_fail);
     930           1 :         assert_false(message_wrong);
     931           1 : }
     932             : 
     933             : 
     934           1 : static void test_valid_strings_with_trailing_crap(void **state)
     935             : {
     936             :         /*
     937             :          * These expressions should parse even though they have
     938             :          * trailing bytes that look bad.
     939             :          *
     940             :          *  ace_conditions_compile_sddl() will return when it has
     941             :          *  found a complete expression, and tell us how much it used.
     942             :          */
     943           1 :         static struct {
     944             :                 const char *sddl;
     945             :                 size_t length;
     946             :         } pairs[] = {
     947             :                 {"(x==1 &&(x < 5 )) )", 18},
     948             :                 {"(x==1) &&", 7},
     949             :                 {"(x)) ", 3},
     950             :         };
     951           1 :         size_t i, length;
     952           1 :         TALLOC_CTX *mem_ctx = talloc_new(NULL);
     953           1 :         bool failed = false;
     954           5 :         for (i = 0; i < ARRAY_SIZE(pairs); i++) {
     955           3 :                 struct ace_condition_script *s = NULL;
     956           3 :                 const char *message = NULL;
     957           3 :                 size_t message_offset;
     958           3 :                 s = ace_conditions_compile_sddl(mem_ctx,
     959             :                                                 ACE_CONDITION_FLAG_ALLOW_DEVICE,
     960             :                                                 pairs[i].sddl,
     961             :                                                 &message,
     962             :                                                 &message_offset,
     963             :                                                 &length);
     964             : 
     965           3 :                 if (s == NULL) {
     966           0 :                         debug_fail("%s\n", pairs[i].sddl);
     967             :                         failed = true;
     968           3 :                 } else if (pairs[i].length == length) {
     969           3 :                         debug_ok("%s\n", pairs[i].sddl);
     970             :                 } else {
     971           0 :                         debug_fail("expected to consume %zu bytes, actual %zu\n",
     972             :                                    pairs[i].length, length);
     973             :                         failed = true;
     974             :                 }
     975           3 :                 if (message != NULL) {
     976           3 :                         print_error_message(pairs[i].sddl, message, message_offset);
     977           3 :                 } else if (s == NULL) {
     978           0 :                         print_message("failed without message\n");
     979             :                 }
     980             :         }
     981           1 :         assert_false(failed);
     982           1 : }
     983             : 
     984             : 
     985           1 : int main(_UNUSED_ int argc, _UNUSED_ const char **argv)
     986             : {
     987           1 :         const struct CMUnitTest tests[] = {
     988             :                 cmocka_unit_test(test_a_number_of_invalid_full_sddl_strings),
     989             :                 cmocka_unit_test(test_full_sddl_ra_encode),
     990             :                 cmocka_unit_test(test_full_sddl_ra_escapes),
     991             :                 cmocka_unit_test(test_full_sddl_compile),
     992             :                 cmocka_unit_test(test_round_trips),
     993             :                 cmocka_unit_test(test_a_number_of_invalid_strings),
     994             :                 cmocka_unit_test(test_a_number_of_valid_strings),
     995             :                 cmocka_unit_test(test_valid_strings_with_trailing_crap),
     996             :                 cmocka_unit_test(test_sddl_compile),
     997             :                 cmocka_unit_test(test_sddl_compile2),
     998             :         };
     999           1 :         if (!isatty(1)) {
    1000           1 :                 cmocka_set_message_output(CM_OUTPUT_SUBUNIT);
    1001             :         }
    1002           1 :         return cmocka_run_group_tests(tests, NULL, NULL);
    1003             : }

Generated by: LCOV version 1.14