From: Volker Lendecke Date: Mon, 19 Apr 2021 14:00:27 +0000 (+0200) Subject: libcli: Fix parsing access flags from multiple tables X-Git-Tag: tevent-0.11.0~1062 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=58c6c031f5d81b2c0aff5b282fe758cd668aeff3;p=thirdparty%2Fsamba.git 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 --- 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))