The branch, master has been updated via 6241380bc52 samba-tool: rewrite dsacl.py to use the new sd_utils helpers via a1109a9bf12 python:sd_utils: add dacl_{prepend,append,delete}_aces() helpers via 8411e6d302e python:sd_utils: introduce update_aces_in_dacl() helper via 4627997ddae python/samba/ndr: add ndr_deepcopy() helper via 9ea06aaf9f5 py_security: allow idx argument to descriptor.[s|d]acl_add() via 2c02378029f libcli/security: add security_descriptor_[s|d]acl_insert() helpers via c3cb915a67a libcli/security: prepare security_descriptor_acl_add() to place the ace at a position via 9d8ff0d1e0b replace: add ARRAY_INSERT_ELEMENT() helper via 9053862b892 lib/ldb-samba: let ldif_read_ntSecurityDescriptor() only try sddl if isupper() from be1aae77b76 libcli/security: Reorder SDDL access flags table to match Windows
https://git.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 6241380bc52e41744d134e31d77ab900e604e0d1 Author: Stefan Metzmacher <me...@samba.org> Date: Thu Mar 16 18:32:49 2023 +0100 samba-tool: rewrite dsacl.py to use the new sd_utils helpers Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> Autobuild-User(master): Stefan Metzmacher <me...@samba.org> Autobuild-Date(master): Wed Mar 22 15:57:15 UTC 2023 on atb-devel-224 commit a1109a9bf12e020636b8d66fc54984aac58bfe6b Author: Stefan Metzmacher <me...@samba.org> Date: Thu Mar 16 18:03:10 2023 +0100 python:sd_utils: add dacl_{prepend,append,delete}_aces() helpers They better represent what they are doing, we keep dacl_add_ace() as wrapper of dacl_prepend_aces() in order to let existing callers work as before. In future it would be good to have a dacl_insert_aces() that would canonicalize the ace order before storing, but that a task for another day. Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit 8411e6d302e25d10f1035ebbdcbde7308566e930 Author: Stefan Metzmacher <me...@samba.org> Date: Fri Mar 10 18:25:18 2023 +0100 python:sd_utils: introduce update_aces_in_dacl() helper This is a more generic api that can be re-used in other places as well in future. It operates on a security descriptor object instead of SDDL. Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit 4627997ddae44265ad35b3234232eb74458c6c34 Author: Stefan Metzmacher <me...@samba.org> Date: Fri Mar 17 14:08:34 2023 +0100 python/samba/ndr: add ndr_deepcopy() helper This uses ndr_pack/unpack in order to create a deep copy of the given object. Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit 9ea06aaf9f57e3c7094553d9ac40fb73057a9b74 Author: Stefan Metzmacher <me...@samba.org> Date: Thu Mar 16 10:11:05 2023 +0100 py_security: allow idx argument to descriptor.[s|d]acl_add() Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit 2c02378029fff6636b8f19e45af78b265f2210ed Author: Stefan Metzmacher <me...@samba.org> Date: Thu Mar 16 10:03:44 2023 +0100 libcli/security: add security_descriptor_[s|d]acl_insert() helpers Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit c3cb915a67aff6739b72b86d7d139609df309ada Author: Stefan Metzmacher <me...@samba.org> Date: Thu Mar 16 10:00:11 2023 +0100 libcli/security: prepare security_descriptor_acl_add() to place the ace at a position Often it is important to insert an ace at a specific position in the ACL. As a default we still append by default by using -1, which is the generic version of passing the number of existing aces. Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit 9d8ff0d1e0b2ba7c84af36e1931f5bc99902a44b Author: Stefan Metzmacher <me...@samba.org> Date: Thu Mar 16 09:57:43 2023 +0100 replace: add ARRAY_INSERT_ELEMENT() helper Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> commit 9053862b89258850c22735cc4123fe5bc0d2e6fa Author: Stefan Metzmacher <me...@samba.org> Date: Mon May 17 17:14:34 2021 +0200 lib/ldb-samba: let ldif_read_ntSecurityDescriptor() only try sddl if isupper() Trying ndr_pull_security_descriptor on SDDL produces just strange debug messages, which can cause confusion. Signed-off-by: Stefan Metzmacher <me...@samba.org> Reviewed-by: Andrew Bartlett <abart...@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagn...@catalyst.net.nz> ----------------------------------------------------------------------- Summary of changes: lib/ldb-samba/ldif_handlers.c | 24 ++++-- lib/replace/replace.h | 15 ++++ libcli/security/security_descriptor.c | 55 ++++++++++-- libcli/security/security_descriptor.h | 6 ++ python/samba/ndr.py | 19 +++++ python/samba/netcmd/dsacl.py | 109 ++++++++---------------- python/samba/sd_utils.py | 153 +++++++++++++++++++++++++++++++--- source4/librpc/ndr/py_security.c | 10 ++- 8 files changed, 288 insertions(+), 103 deletions(-) Changeset truncated at 500 lines: diff --git a/lib/ldb-samba/ldif_handlers.c b/lib/ldb-samba/ldif_handlers.c index b8f04747456..f77a268c1a8 100644 --- a/lib/ldb-samba/ldif_handlers.c +++ b/lib/ldb-samba/ldif_handlers.c @@ -369,6 +369,21 @@ static int ldif_read_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx struct security_descriptor *sd; enum ndr_err_code ndr_err; + if (in->length >= 2 && isupper(in->data[0]) && in->data[1] == ':') { + /* + * If it starts with an upper case character followed by ':', + * we know it's not NDR, but most likely SDDL... + */ + const struct dom_sid *sid = samdb_domain_sid(ldb); + + sd = sddl_decode(mem_ctx, (const char *)in->data, sid); + if (sd == NULL) { + return -1; + } + + goto decoded; + } + sd = talloc(mem_ctx, struct security_descriptor); if (sd == NULL) { return -1; @@ -377,16 +392,11 @@ static int ldif_read_ntSecurityDescriptor(struct ldb_context *ldb, void *mem_ctx ndr_err = ndr_pull_struct_blob(in, sd, sd, (ndr_pull_flags_fn_t)ndr_pull_security_descriptor); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - /* If this does not parse, then it is probably SDDL, and we should try it that way */ - - const struct dom_sid *sid = samdb_domain_sid(ldb); talloc_free(sd); - sd = sddl_decode(mem_ctx, (const char *)in->data, sid); - if (sd == NULL) { - return -1; - } + return -1; } +decoded: ndr_err = ndr_push_struct_blob(out, mem_ctx, sd, (ndr_push_flags_fn_t)ndr_push_security_descriptor); talloc_free(sd); diff --git a/lib/replace/replace.h b/lib/replace/replace.h index b15f3d14c8a..25e6e145eeb 100644 --- a/lib/replace/replace.h +++ b/lib/replace/replace.h @@ -885,6 +885,21 @@ typedef unsigned long long ptrdiff_t ; #define ARRAY_DEL_ELEMENT(a,i,n) \ if((i)<((n)-1)){memmove(&((a)[(i)]),&((a)[(i)+1]),(sizeof(*(a))*((n)-(i)-1)));} +/** + * Insert an array element by moving the rest one up + * + */ +#define ARRAY_INSERT_ELEMENT(__array,__old_last_idx,__new_elem,__new_idx) do { \ + if ((__new_idx) < (__old_last_idx)) { \ + const void *__src = &((__array)[(__new_idx)]); \ + void *__dst = &((__array)[(__new_idx)+1]); \ + size_t __num = (__old_last_idx)-(__new_idx); \ + size_t __len = sizeof(*(__array)) * __num; \ + memmove(__dst, __src, __len); \ + } \ + (__array)[(__new_idx)] = (__new_elem); \ +} while(0) + /** * Pointer difference macro */ diff --git a/libcli/security/security_descriptor.c b/libcli/security/security_descriptor.c index ff3aa07606c..d6a7eda611b 100644 --- a/libcli/security/security_descriptor.c +++ b/libcli/security/security_descriptor.c @@ -268,9 +268,11 @@ NTSTATUS security_descriptor_for_client(TALLOC_CTX *mem_ctx, static NTSTATUS security_descriptor_acl_add(struct security_descriptor *sd, bool add_to_sacl, - const struct security_ace *ace) + const struct security_ace *ace, + ssize_t _idx) { struct security_acl *acl = NULL; + ssize_t idx; if (add_to_sacl) { acl = sd->sacl; @@ -289,15 +291,28 @@ static NTSTATUS security_descriptor_acl_add(struct security_descriptor *sd, acl->aces = NULL; } + if (_idx < 0) { + idx = (acl->num_aces + 1) + _idx; + } else { + idx = _idx; + } + + if (idx < 0) { + return NT_STATUS_ARRAY_BOUNDS_EXCEEDED; + } else if (idx > acl->num_aces) { + return NT_STATUS_ARRAY_BOUNDS_EXCEEDED; + } + acl->aces = talloc_realloc(acl, acl->aces, struct security_ace, acl->num_aces+1); if (acl->aces == NULL) { return NT_STATUS_NO_MEMORY; } - acl->aces[acl->num_aces] = *ace; + ARRAY_INSERT_ELEMENT(acl->aces, acl->num_aces, *ace, idx); + acl->num_aces++; - switch (acl->aces[acl->num_aces].type) { + switch (acl->aces[idx].type) { case SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT: case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT: case SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT: @@ -308,8 +323,6 @@ static NTSTATUS security_descriptor_acl_add(struct security_descriptor *sd, break; } - acl->num_aces++; - if (add_to_sacl) { sd->sacl = acl; sd->type |= SEC_DESC_SACL_PRESENT; @@ -328,7 +341,21 @@ static NTSTATUS security_descriptor_acl_add(struct security_descriptor *sd, NTSTATUS security_descriptor_sacl_add(struct security_descriptor *sd, const struct security_ace *ace) { - return security_descriptor_acl_add(sd, true, ace); + return security_descriptor_acl_add(sd, true, ace, -1); +} + +/* + insert an ACE at a given index to the SACL of a security_descriptor + + idx can be negative, which means it's related to the new size from the + end, so -1 means the ace is appended at the end. +*/ + +NTSTATUS security_descriptor_sacl_insert(struct security_descriptor *sd, + const struct security_ace *ace, + ssize_t idx) +{ + return security_descriptor_acl_add(sd, true, ace, idx); } /* @@ -338,7 +365,21 @@ NTSTATUS security_descriptor_sacl_add(struct security_descriptor *sd, NTSTATUS security_descriptor_dacl_add(struct security_descriptor *sd, const struct security_ace *ace) { - return security_descriptor_acl_add(sd, false, ace); + return security_descriptor_acl_add(sd, false, ace, -1); +} + +/* + insert an ACE at a given index to the DACL of a security_descriptor + + idx can be negative, which means it's related to the new size from the + end, so -1 means the ace is appended at the end. +*/ + +NTSTATUS security_descriptor_dacl_insert(struct security_descriptor *sd, + const struct security_ace *ace, + ssize_t idx) +{ + return security_descriptor_acl_add(sd, false, ace, idx); } /* diff --git a/libcli/security/security_descriptor.h b/libcli/security/security_descriptor.h index 46545321d15..354bc17e925 100644 --- a/libcli/security/security_descriptor.h +++ b/libcli/security/security_descriptor.h @@ -33,8 +33,14 @@ NTSTATUS security_descriptor_for_client(TALLOC_CTX *mem_ctx, struct security_descriptor **_csd); NTSTATUS security_descriptor_sacl_add(struct security_descriptor *sd, const struct security_ace *ace); +NTSTATUS security_descriptor_sacl_insert(struct security_descriptor *sd, + const struct security_ace *ace, + ssize_t idx); NTSTATUS security_descriptor_dacl_add(struct security_descriptor *sd, const struct security_ace *ace); +NTSTATUS security_descriptor_dacl_insert(struct security_descriptor *sd, + const struct security_ace *ace, + ssize_t idx); NTSTATUS security_descriptor_dacl_del(struct security_descriptor *sd, const struct dom_sid *trustee); NTSTATUS security_descriptor_sacl_del(struct security_descriptor *sd, diff --git a/python/samba/ndr.py b/python/samba/ndr.py index 314e57b7f8e..4207ee2a318 100644 --- a/python/samba/ndr.py +++ b/python/samba/ndr.py @@ -56,6 +56,25 @@ def ndr_print(object): return ndr_print() +def ndr_deepcopy(object): + """Create a deep copy of a NDR object, using pack/unpack + + :param object: Object to copy + :return: The object copy + """ + ndr_pack = getattr(object, "__ndr_pack__", None) + if ndr_pack is None: + raise TypeError("%r is not a NDR object" % object) + data = ndr_pack() + cls = type(object) + copy = cls() + ndr_unpack = getattr(copy, "__ndr_unpack__", None) + if ndr_unpack is None: + raise TypeError("%r is not a NDR object" % copy) + ndr_unpack(data, allow_remaining=False) + return copy + + def ndr_pack_in(object, bigendian=False, ndr64=False): """Pack the input of an NDR function object. diff --git a/python/samba/netcmd/dsacl.py b/python/samba/netcmd/dsacl.py index 02be8fd982b..527c53482b6 100644 --- a/python/samba/netcmd/dsacl.py +++ b/python/samba/netcmd/dsacl.py @@ -17,6 +17,7 @@ # import samba.getopt as options +from samba import sd_utils from samba.dcerpc import security from samba.samdb import SamDB from samba.ndr import ndr_unpack, ndr_pack @@ -42,38 +43,6 @@ from samba.netcmd import ( Option, ) -def find_trustee_sid(samdb, trusteedn): - res = samdb.search(base=trusteedn, expression="(objectClass=*)", - scope=SCOPE_BASE) - assert(len(res) == 1) - return ndr_unpack(security.dom_sid, res[0]["objectSid"][0]) - - -def modify_descriptor(samdb, object_dn, desc, controls=None): - assert(isinstance(desc, security.descriptor)) - m = ldb.Message() - m.dn = ldb.Dn(samdb, object_dn) - m["nTSecurityDescriptor"] = ldb.MessageElement( - (ndr_pack(desc)), ldb.FLAG_MOD_REPLACE, - "nTSecurityDescriptor") - samdb.modify(m) - - -def read_descriptor(samdb, object_dn): - res = samdb.search(base=object_dn, scope=SCOPE_BASE, - attrs=["nTSecurityDescriptor"]) - # we should theoretically always have an SD - assert(len(res) == 1) - desc = res[0]["nTSecurityDescriptor"][0] - return ndr_unpack(security.descriptor, desc) - - -def get_domain_sid(samdb): - res = samdb.search(base=samdb.domain_dn(), - expression="(objectClass=*)", scope=SCOPE_BASE) - return ndr_unpack(security.dom_sid, res[0]["objectSid"][0]) - - class cmd_dsacl_base(Command): """Base class for DSACL commands.""" @@ -85,9 +54,8 @@ class cmd_dsacl_base(Command): "versionopts": options.VersionOptions, } - def print_acl(self, samdb, object_dn, prefix=''): - desc = read_descriptor(samdb, object_dn) - desc_sddl = desc.as_sddl(get_domain_sid(samdb)) + def print_acl(self, sd_helper, object_dn, prefix=''): + desc_sddl = sd_helper.get_sd_as_sddl(object_dn) self.outf.write("%sdescriptor for %s:\n" % (prefix, object_dn)) self.outf.write(desc_sddl + "\n") @@ -124,26 +92,21 @@ class cmd_dsacl_set(cmd_dsacl_base): type="string"), ] - def add_ace(self, samdb, object_dn, new_ace): + def find_trustee_sid(self, samdb, trusteedn): + res = samdb.search(base=trusteedn, expression="(objectClass=*)", + scope=SCOPE_BASE) + assert(len(res) == 1) + return ndr_unpack(security.dom_sid, res[0]["objectSid"][0]) + + def add_ace(self, sd_helper, object_dn, new_ace): """Add new ace explicitly.""" - desc = read_descriptor(samdb, object_dn) - new_ace = security.descriptor.from_sddl("D:" + new_ace, get_domain_sid(samdb)) - new_ace_list = re.findall(r"\(.*?\)",new_ace.as_sddl()) - for new_ace in new_ace_list: - desc_sddl = desc.as_sddl(get_domain_sid(samdb)) - # TODO add bindings for descriptor manipulation and get rid of this - desc_aces = re.findall(r"\(.*?\)", desc_sddl) - for ace in desc_aces: - if ("ID" in ace): - desc_sddl = desc_sddl.replace(ace, "") - if new_ace in desc_sddl: - continue - if desc_sddl.find("(") >= 0: - desc_sddl = desc_sddl[:desc_sddl.index("(")] + new_ace + desc_sddl[desc_sddl.index("("):] - else: - desc_sddl = desc_sddl + new_ace - desc = security.descriptor.from_sddl(desc_sddl, get_domain_sid(samdb)) - modify_descriptor(samdb, object_dn, desc) + ai,ii = sd_helper.dacl_prepend_aces(object_dn, new_ace) + for ace in ii: + sddl = ace.as_sddl(sd_helper.domain_sid) + self.outf.write("WARNING: ignored INHERITED_ACE (%s).\n" % sddl) + for ace in ai: + sddl = ace.as_sddl(sd_helper.domain_sid) + self.outf.write("WARNING: (%s) was already found in the current security descriptor.\n" % sddl) def run(self, car, action, objectdn, trusteedn, sddl, H=None, credopts=None, sambaopts=None, versionopts=None): @@ -156,6 +119,7 @@ class cmd_dsacl_set(cmd_dsacl_base): samdb = SamDB(url=H, session_info=system_session(), credentials=creds, lp=lp) + sd_helper = sd_utils.SDUtils(samdb) cars = {'change-rid': GUID_DRS_CHANGE_RID_MASTER, 'change-pdc': GUID_DRS_CHANGE_PDC, 'change-infrastructure': GUID_DRS_CHANGE_INFR_MASTER, @@ -170,7 +134,7 @@ class cmd_dsacl_set(cmd_dsacl_base): 'repl-sync': GUID_DRS_REPL_SYNCRONIZE, 'ro-repl-secret-sync': GUID_DRS_RO_REPL_SECRET_SYNC, } - sid = find_trustee_sid(samdb, trusteedn) + sid = self.find_trustee_sid(samdb, trusteedn) if sddl: new_ace = sddl elif action == "allow": @@ -180,9 +144,9 @@ class cmd_dsacl_set(cmd_dsacl_base): else: raise CommandError("Wrong argument '%s'!" % action) - self.print_acl(samdb, objectdn, prefix='old ') - self.add_ace(samdb, objectdn, new_ace) - self.print_acl(samdb, objectdn, prefix='new ') + self.print_acl(sd_helper, objectdn, prefix='old ') + self.add_ace(sd_helper, objectdn, new_ace) + self.print_acl(sd_helper, objectdn, prefix='new ') class cmd_dsacl_get(cmd_dsacl_base): @@ -202,7 +166,8 @@ class cmd_dsacl_get(cmd_dsacl_base): samdb = SamDB(url=H, session_info=system_session(), credentials=creds, lp=lp) - self.print_acl(samdb, objectdn) + sd_helper = sd_utils.SDUtils(samdb) + self.print_acl(sd_helper, objectdn) class cmd_dsacl_delete(cmd_dsacl_base): @@ -226,23 +191,21 @@ class cmd_dsacl_delete(cmd_dsacl_base): samdb = SamDB(url=H, session_info=system_session(), credentials=creds, lp=lp) + sd_helper = sd_utils.SDUtils(samdb) - self.print_acl(samdb, objectdn, prefix='old ') - self.delete_ace(samdb, objectdn, sddl) - self.print_acl(samdb, objectdn, prefix='new ') + self.print_acl(sd_helper, objectdn, prefix='old ') + self.delete_ace(sd_helper, objectdn, sddl) + self.print_acl(sd_helper, objectdn, prefix='new ') - def delete_ace(self, samdb, object_dn, delete_aces): + def delete_ace(self, sd_helper, object_dn, delete_aces): """Delete ace explicitly.""" - desc = read_descriptor(samdb, object_dn) - domsid = get_domain_sid(samdb) - delete_aces = security.descriptor.from_sddl("D:" + delete_aces, domsid).dacl.aces - for ace in delete_aces: - if ace in desc.dacl.aces: - desc.dacl_del_ace(ace) - else: - sddl = ace.as_sddl(domsid) - self.outf.write("WARNING: (%s) was not found in the current security descriptor.\n" % sddl) - modify_descriptor(samdb, object_dn, desc) + di,ii = sd_helper.dacl_delete_aces(object_dn, delete_aces) + for ace in ii: + sddl = ace.as_sddl(sd_helper.domain_sid) + self.outf.write("WARNING: ignored INHERITED_ACE (%s).\n" % sddl) + for ace in di: + sddl = ace.as_sddl(sd_helper.domain_sid) + self.outf.write("WARNING: (%s) was not found in the current security descriptor.\n" % sddl) class cmd_dsacl(SuperCommand): diff --git a/python/samba/sd_utils.py b/python/samba/sd_utils.py index c42bc602b4d..4e5f6e2aa53 100644 --- a/python/samba/sd_utils.py +++ b/python/samba/sd_utils.py @@ -21,8 +21,11 @@ import samba from ldb import Message, MessageElement, Dn from ldb import FLAG_MOD_REPLACE, SCOPE_BASE -from samba.ndr import ndr_pack, ndr_unpack +from samba.ndr import ndr_pack, ndr_unpack, ndr_deepcopy from samba.dcerpc import security +from samba.ntstatus import ( + NT_STATUS_OBJECT_NAME_NOT_FOUND, +) class SDUtils(object): @@ -63,19 +66,145 @@ class SDUtils(object): res = self.ldb.search(object_dn) return ndr_unpack(security.dom_sid, res[0]["objectSid"][0]) + def update_aces_in_dacl(self, dn, del_aces=None, add_aces=None, + sddl_attr=None, controls=None): + if del_aces is None: + del_aces=[] + if add_aces is None: + add_aces=[] + + def ace_from_sddl(ace_sddl): + ace_sd = security.descriptor.from_sddl("D:" + ace_sddl, self.domain_sid) + assert(len(ace_sd.dacl.aces)==1) + return ace_sd.dacl.aces[0] + + if sddl_attr is None: + if controls is None: + controls=["sd_flags:1:%d" % security.SECINFO_DACL] + sd = self.read_sd_on_dn(dn, controls=controls) + if not sd.type & security.SEC_DESC_DACL_PROTECTED: + # if the DACL is not protected remove all + # inherited aces, as they will be re-inherited + # on the server, we need a ndr_deepcopy in order + # to avoid reference problems while deleting + # the aces while looping over them + dacl_copy = ndr_deepcopy(sd.dacl) + for ace in dacl_copy.aces: + if ace.flags & security.SEC_ACE_FLAG_INHERITED_ACE: + try: + sd.dacl_del_ace(ace) + except samba.NTSTATUSError as err: + if err.args[0] != NT_STATUS_OBJECT_NAME_NOT_FOUND: + raise err + # dacl_del_ace may remove more than + # one ace, so we may not find it anymore + pass + else: + if controls is None: + controls=[] + res = self.ldb.search(dn, SCOPE_BASE, None, + [sddl_attr], controls=controls) + old_sddl = str(res[0][sddl_attr][0]) + sd = security.descriptor.from_sddl(old_sddl, self.domain_sid) + + num_changes = 0 + del_ignored = [] + add_ignored = [] + inherited_ignored = [] + + for ace in del_aces: + if isinstance(ace, str): + ace = ace_from_sddl(ace) + assert(isinstance(ace, security.ace)) + + if ace.flags & security.SEC_ACE_FLAG_INHERITED_ACE: + inherited_ignored.append(ace) + continue + + if ace not in sd.dacl.aces: + del_ignored.append(ace) + continue + + sd.dacl_del_ace(ace) + num_changes += 1 + + for ace in add_aces: + add_idx = -1 + if isinstance(ace, dict): + if "idx" in ace: + add_idx = ace["idx"] + ace = ace["ace"] + if isinstance(ace, str): + ace = ace_from_sddl(ace) + assert(isinstance(ace, security.ace)) + + if ace.flags & security.SEC_ACE_FLAG_INHERITED_ACE: + inherited_ignored.append(ace) + continue + -- Samba Shared Repository