diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 17:20:00 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 17:20:00 +0000 |
commit | 8daa83a594a2e98f39d764422bfbdbc62c9efd44 (patch) | |
tree | 4099e8021376c7d8c05bdf8503093d80e9c7bad0 /lib/fuzzing/fuzz_sddl_access_check.c | |
parent | Initial commit. (diff) | |
download | samba-8daa83a594a2e98f39d764422bfbdbc62c9efd44.tar.xz samba-8daa83a594a2e98f39d764422bfbdbc62c9efd44.zip |
Adding upstream version 2:4.20.0+dfsg.upstream/2%4.20.0+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'lib/fuzzing/fuzz_sddl_access_check.c')
-rw-r--r-- | lib/fuzzing/fuzz_sddl_access_check.c | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/lib/fuzzing/fuzz_sddl_access_check.c b/lib/fuzzing/fuzz_sddl_access_check.c new file mode 100644 index 0000000..a7bf7b3 --- /dev/null +++ b/lib/fuzzing/fuzz_sddl_access_check.c @@ -0,0 +1,206 @@ +/* + Fuzz access check using SDDL strings and a known token + Copyright (C) Catalyst IT 2023 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#include "libcli/security/security.h" +#include "libcli/security/conditional_ace.h" +#include "libcli/security/claims-conversions.h" +#include "lib/util/attr.h" +#include "librpc/gen_ndr/ndr_security.h" +#include "librpc/gen_ndr/ndr_conditional_ace.h" +#include "lib/util/bytearray.h" +#include "fuzzing/fuzzing.h" + + +static struct security_token token = {0}; + +static struct dom_sid dom_sid = {0}; + +/* + * For this one we initialise a security token to have a few claims + * and SIDs. The fuzz strings contain SDDL that will be tested against + * this token in se_access_check() or sec_access_check_ds() -- + * supposing they compile. + */ + +int LLVMFuzzerInitialize(int *argc, char ***argv) +{ + size_t i; + TALLOC_CTX *mem_ctx = talloc_new(NULL); + struct dom_sid *sid = NULL; + + struct claim_def { + const char *type; + const char *name; + const char *claim_sddl; + } claims[] = { + { + "user", + "shoe size", + "44" + }, + { + "user", + "©", + "{\"unknown\", \"\", \" ←ā\"}" + }, + { + "device", + "©", + "{\"unknown\", \" \", \" ←ā\"}" + }, + { + "device", + "least favourite groups", + "{SID(S-1-1-0),SID(S-1-5-3),SID(S-1-57777-333-33-33-2)}" + }, + { + "local", + "birds", + "{\"tern\"}" + }, + }; + + const char * device_sids[] = { + "S-1-1-0", + "S-1-333-66", + "S-1-2-3-4-5-6-7-8-9", + }; + const char * user_sids[] = { + "S-1-333-66", + "S-1-16-8448", + "S-1-9-8-7", + }; + + for (i = 0; i < ARRAY_SIZE(user_sids); i++) { + sid = sddl_decode_sid(mem_ctx, &user_sids[i], NULL); + if (sid == NULL) { + abort(); + } + add_sid_to_array(mem_ctx, sid, + &token.sids, + &token.num_sids); + } + + for (i = 0; i < ARRAY_SIZE(device_sids); i++) { + sid = sddl_decode_sid(mem_ctx, &device_sids[i], NULL); + if (sid == NULL) { + abort(); + } + add_sid_to_array(mem_ctx, sid, + &token.device_sids, + &token.num_device_sids); + } + + for (i = 0; i < ARRAY_SIZE(claims); i++) { + struct CLAIM_SECURITY_ATTRIBUTE_RELATIVE_V1 *claim = NULL; + struct claim_def c = claims[i]; + + claim = parse_sddl_literal_as_claim(mem_ctx, + c.name, + c.claim_sddl); + if (claim == NULL) { + abort(); + } + add_claim_to_token(mem_ctx, &token, claim, c.type); + } + + /* we also need a global domain SID */ + string_to_sid(&dom_sid, device_sids[2]); + return 0; +} + + +int LLVMFuzzerTestOneInput(const uint8_t *input, size_t len) +{ + TALLOC_CTX *mem_ctx = NULL; + struct security_descriptor *sd = NULL; + uint32_t access_desired; + uint32_t access_granted; + const char *sddl; + ssize_t i; + if (len < 5) { + return 0; + } + access_desired = PULL_LE_U32(input + len - 4, 0); + + /* + * check there is a '\0'. + * + * Note this allows double-dealing for the last 4 bytes: they are used + * as the access_desired mask (see just above) but also *could* be + * part of the sddl string. But this doesn't matter, for three + * reasons: + * + * 1. the desired access mask doesn't usually matter much. + * + * 2. the final '\0' is rarely the operative one. Usually the + * effective string ends a long time before the end of the input, and + * the tail is just junk that comes along for the ride. + * + * 3. Even if there is a case where the end of the SDDL is part of the + * mask, the evolution strategy is very likely to try a different mask, + * because it likes to add junk on the end. + * + * But still, you ask, WHY? So that the seeds from here can be shared + * back and forth with the fuzz_sddl_parse seeds, which have the same + * form of a null-terminated-string-with-trailing-junk. If we started + * the loop at `len - 5` instead of `len - 1`, there might be + * interesting seeds that are valid there that would fail here. That's + * all. + */ + for (i = len - 1; i >= 0; i--) { + if (input[i] == 0) { + break; + } + } + if (i < 0) { + return 0; + } + + sddl = (const char *)input; + mem_ctx = talloc_new(NULL); + + sd = sddl_decode(mem_ctx, sddl, &dom_sid); + if (sd == NULL) { + goto end; + } + +#ifdef FUZZ_SEC_ACCESS_CHECK_DS + /* + * The sec_access_check_ds() function has two arguments not found in + * se_access_check, and also not found in our fuzzing examples. + * + * One is a struct object_tree, which is used for object ACE types. + * The other is a SID, which is used as a default if an ACE lacks a + * SID. + */ + sec_access_check_ds(sd, + &token, + access_desired, + &access_granted, + NULL, + NULL); +#else + se_access_check(sd, &token, access_desired, &access_granted); +#endif + +end: + talloc_free(mem_ctx); + return 0; +} |