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 : }
|