From 58c6c031f5d81b2c0aff5b282fe758cd668aeff3 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 19 Apr 2021 16:00:27 +0200 Subject: [PATCH] libcli: Fix parsing access flags from multiple tables We have to look at all available mappings for parsing sddl for each special flag set. "GW" and "FX" come from two different tables, but the previous code settled on one table and then expected both "GW" and "FX" to come from that same table. Change the code to look at all tables per special flag set. Signed-off-by: Volker Lendecke Reviewed-by: Jeremy Allison Autobuild-User(master): Jeremy Allison Autobuild-Date(master): Wed Apr 21 00:04:36 UTC 2021 on sn-devel-184 --- libcli/security/sddl.c | 46 +++++++++++++++++++++++++++++++++++++--------- python/samba/tests/sddl.py | 5 +++-- 2 files changed, 40 insertions(+), 11 deletions(-) diff --git a/libcli/security/sddl.c b/libcli/security/sddl.c index 899fdbdddf1..26049ec458a 100644 --- a/libcli/security/sddl.c +++ b/libcli/security/sddl.c @@ -234,6 +234,39 @@ static const struct flag_map decode_ace_access_mask[] = { { NULL, 0 }, }; +static bool sddl_decode_access(const char *str, uint32_t *pmask) +{ + const char *str0 = str; + uint32_t mask = 0; + int cmp; + + cmp = strncmp(str, "0x", 2); + if (cmp == 0) { + *pmask = strtol(str, NULL, 16); + return true; + } + + while ((str[0] != '\0') && isupper(str[0])) { + uint32_t flags = 0; + size_t len = 0; + bool found; + + found = sddl_map_flag( + ace_access_mask, str, &len, &flags); + found |= sddl_map_flag( + decode_ace_access_mask, str, &len, &flags); + if (!found) { + DEBUG(1, ("Unknown flag - %s in %s\n", str, str0)); + return false; + } + mask |= flags; + str += len; + } + + *pmask = mask; + return true; +} + /* decode an ACE return true on success, false on failure @@ -247,6 +280,7 @@ static bool sddl_decode_ace(TALLOC_CTX *mem_ctx, struct security_ace *ace, char int i; uint32_t v; struct dom_sid *sid; + bool ok; ZERO_STRUCTP(ace); @@ -273,15 +307,9 @@ static bool sddl_decode_ace(TALLOC_CTX *mem_ctx, struct security_ace *ace, char ace->flags = v; /* access mask */ - if (strncmp(tok[2], "0x", 2) == 0) { - ace->access_mask = strtol(tok[2], NULL, 16); - } else { - if (!sddl_map_flags(ace_access_mask, tok[2], &v, NULL) && - !sddl_map_flags( - decode_ace_access_mask, tok[2], &v, NULL)) { - return false; - } - ace->access_mask = v; + ok = sddl_decode_access(tok[2], &ace->access_mask); + if (!ok) { + return false; } /* object */ diff --git a/python/samba/tests/sddl.py b/python/samba/tests/sddl.py index 9e1e1147a6a..83df59719c8 100644 --- a/python/samba/tests/sddl.py +++ b/python/samba/tests/sddl.py @@ -182,5 +182,6 @@ class SddlDecodeEncode(TestCase): def test_multiflag(self): sid = security.dom_sid("S-1-2-3-4") raised = False - with self.assertRaises(Exception): - sd = security.descriptor.from_sddl("D:(A;;GWFX;;;DA)", sid) + sd = security.descriptor.from_sddl("D:(A;;GWFX;;;DA)", sid) + sddl = sd.as_sddl(sid) + self.assertEqual(sd, security.descriptor.from_sddl(sddl, sid)) -- 2.11.4.GIT