diff options
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/descriptor.c | 167 | ||||
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/kludge_acl.c | 20 | ||||
-rwxr-xr-x | source4/lib/ldb/tests/python/sec_descriptor.py | 64 |
3 files changed, 225 insertions, 26 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/descriptor.c b/source4/dsdb/samdb/ldb_modules/descriptor.c index 98e54b19c1..c3413e1584 100644 --- a/source4/dsdb/samdb/ldb_modules/descriptor.c +++ b/source4/dsdb/samdb/ldb_modules/descriptor.c @@ -160,7 +160,7 @@ static struct security_descriptor *descr_handle_sd_flags(TALLOC_CTX *mem_ctx, uint32_t sd_flags) { struct security_descriptor *final_sd; - /* if there is no control or contlol == 0 modify everything */ + /* if there is no control or control == 0 modify everything */ if (!sd_flags) { return new_sd; } @@ -325,6 +325,51 @@ static DATA_BLOB *get_new_descriptor(struct ldb_module *module, return linear_sd; } +static DATA_BLOB *descr_get_descriptor_to_show(struct ldb_module *module, + TALLOC_CTX *mem_ctx, + struct ldb_val *sd, + uint32_t sd_flags) +{ + struct security_descriptor *old_sd, *final_sd; + DATA_BLOB *linear_sd; + enum ndr_err_code ndr_err; + struct ldb_context *ldb = ldb_module_get_ctx(module); + + old_sd = talloc(mem_ctx, struct security_descriptor); + if (!old_sd) { + return NULL; + } + ndr_err = ndr_pull_struct_blob(sd, old_sd, NULL, + old_sd, + (ndr_pull_flags_fn_t)ndr_pull_security_descriptor); + + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + talloc_free(old_sd); + return NULL; + } + + final_sd = descr_handle_sd_flags(mem_ctx, old_sd, NULL, sd_flags); + + if (!final_sd) { + return NULL; + } + + linear_sd = talloc(mem_ctx, DATA_BLOB); + if (!linear_sd) { + return NULL; + } + + ndr_err = ndr_push_struct_blob(linear_sd, mem_ctx, + lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")), + final_sd, + (ndr_push_flags_fn_t)ndr_push_security_descriptor); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + return NULL; + } + + return linear_sd; +} + static struct descriptor_context *descriptor_init_context(struct ldb_module *module, struct ldb_request *req) { @@ -470,6 +515,74 @@ static int descriptor_op_callback(struct ldb_request *req, struct ldb_reply *are ares->response, ares->error); } +static int descriptor_search_callback(struct ldb_request *req, struct ldb_reply *ares) +{ + struct descriptor_context *ac; + struct ldb_control *sd_control; + struct ldb_val *sd_val = NULL; + struct ldb_message_element *sd_el; + DATA_BLOB *show_sd; + int ret; + uint32_t sd_flags = 0; + + ac = talloc_get_type(req->context, struct descriptor_context); + + if (!ares) { + ret = LDB_ERR_OPERATIONS_ERROR; + goto fail; + } + if (ares->error != LDB_SUCCESS) { + return ldb_module_done(ac->req, ares->controls, + ares->response, ares->error); + } + + sd_control = ldb_request_get_control(ac->req, LDB_CONTROL_SD_FLAGS_OID); + if (sd_control) { + struct ldb_sd_flags_control *sdctr = (struct ldb_sd_flags_control *)sd_control->data; + sd_flags = sdctr->secinfo_flags; + /* we only care for the last 4 bits */ + sd_flags = sd_flags & 0x0000000F; + } + + switch (ares->type) { + case LDB_REPLY_ENTRY: + if (sd_flags != 0) { + sd_el = ldb_msg_find_element(ares->message, "nTSecurityDescriptor"); + if (sd_el) { + sd_val = sd_el->values; + } + } + if (sd_val) { + show_sd = descr_get_descriptor_to_show(ac->module, ac->req, + sd_val, sd_flags); + if (!show_sd) { + ret = LDB_ERR_OPERATIONS_ERROR; + goto fail; + } + ldb_msg_remove_attr(ares->message, "nTSecurityDescriptor"); + ret = ldb_msg_add_steal_value(ares->message, "nTSecurityDescriptor", show_sd); + if (ret != LDB_SUCCESS) { + goto fail; + } + } + return ldb_module_send_entry(ac->req, ares->message, ares->controls); + + case LDB_REPLY_REFERRAL: + /* ignore referrals */ + break; + + case LDB_REPLY_DONE: + + return ldb_module_done(ac->req, ares->controls, + ares->response, ares->error); + } + + talloc_free(ares); + return LDB_SUCCESS; +fail: + return ldb_module_done(ac->req, NULL, NULL, ret); +} + static int descriptor_do_mod(struct descriptor_context *ac) { struct ldb_context *ldb; @@ -718,6 +831,48 @@ static int descriptor_change(struct ldb_module *module, struct ldb_request *req) return ldb_next_request(ac->module, search_req); } +static int descriptor_search(struct ldb_module *module, struct ldb_request *req) +{ + int ret; + struct ldb_context *ldb; + struct ldb_control *sd_control; + struct ldb_control **saved_controls; + struct ldb_request *down_req; + struct descriptor_context *ac; + + sd_control = ldb_request_get_control(req, LDB_CONTROL_SD_FLAGS_OID); + if (!sd_control) { + return ldb_next_request(module, req); + } + + ldb = ldb_module_get_ctx(module); + ac = descriptor_init_context(module, req); + if (ac == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = ldb_build_search_req_ex(&down_req, ldb, ac, + req->op.search.base, + req->op.search.scope, + req->op.search.tree, + req->op.search.attrs, + req->controls, + ac, descriptor_search_callback, + ac->req); + if (ret != LDB_SUCCESS) { + return ret; + } + /* save it locally and remove it from the list */ + /* we do not need to replace them later as we + * are keeping the original req intact */ + if (sd_control) { + if (!save_controls(sd_control, down_req, &saved_controls)) { + return LDB_ERR_OPERATIONS_ERROR; + } + } + + return ldb_next_request(ac->module, down_req); +} /* TODO */ static int descriptor_rename(struct ldb_module *module, struct ldb_request *req) { @@ -728,12 +883,20 @@ static int descriptor_rename(struct ldb_module *module, struct ldb_request *req) static int descriptor_init(struct ldb_module *module) { + int ret = ldb_mod_register_control(module, LDB_CONTROL_SD_FLAGS_OID); + struct ldb_context *ldb = ldb_module_get_ctx(module); + if (ret != LDB_SUCCESS) { + ldb_debug(ldb, LDB_DEBUG_ERROR, + "descriptor: Unable to register control with rootdse!\n"); + return LDB_ERR_OPERATIONS_ERROR; + } return ldb_next_init(module); } _PUBLIC_ const struct ldb_module_ops ldb_descriptor_module_ops = { - .name = "descriptor", + .name = "descriptor", + .search = descriptor_search, .add = descriptor_change, .modify = descriptor_change, .rename = descriptor_rename, diff --git a/source4/dsdb/samdb/ldb_modules/kludge_acl.c b/source4/dsdb/samdb/ldb_modules/kludge_acl.c index 0cec95b1c2..7a51aa1802 100644 --- a/source4/dsdb/samdb/ldb_modules/kludge_acl.c +++ b/source4/dsdb/samdb/ldb_modules/kludge_acl.c @@ -314,8 +314,6 @@ static int kludge_acl_search(struct ldb_module *module, struct ldb_request *req) struct kludge_private_data *data; const char * const *attrs; int ret, i; - struct ldb_control *sd_control; - struct ldb_control **sd_saved_controls; ldb = ldb_module_get_ctx(module); @@ -382,17 +380,6 @@ static int kludge_acl_search(struct ldb_module *module, struct ldb_request *req) return ret; } - /* check if there's an SD_FLAGS control */ - sd_control = ldb_request_get_control(down_req, LDB_CONTROL_SD_FLAGS_OID); - if (sd_control) { - /* save it locally and remove it from the list */ - /* we do not need to replace them later as we - * are keeping the original req intact */ - if (!save_controls(sd_control, down_req, &sd_saved_controls)) { - return LDB_ERR_OPERATIONS_ERROR; - } - } - /* perform the search */ return ldb_next_request(module, down_req); } @@ -512,13 +499,6 @@ static int kludge_acl_init(struct ldb_module *module) } data->password_attrs[i] = NULL; - ret = ldb_mod_register_control(module, LDB_CONTROL_SD_FLAGS_OID); - if (ret != LDB_SUCCESS) { - ldb_debug(ldb, LDB_DEBUG_ERROR, - "kludge_acl: Unable to register control with rootdse!\n"); - return LDB_ERR_OPERATIONS_ERROR; - } - done: talloc_free(mem_ctx); return ldb_next_init(module); diff --git a/source4/lib/ldb/tests/python/sec_descriptor.py b/source4/lib/ldb/tests/python/sec_descriptor.py index 8763579dc0..3e0be64f9b 100755 --- a/source4/lib/ldb/tests/python/sec_descriptor.py +++ b/source4/lib/ldb/tests/python/sec_descriptor.py @@ -208,8 +208,8 @@ showInAdvancedViewOnly: TRUE ldif += "nTSecurityDescriptor:: %s" % base64.b64encode(ndr_pack(desc)) _ldb.add_ldif(ldif) - def read_desc(self, object_dn): - res = self.ldb_admin.search(base=object_dn, scope=SCOPE_BASE, attrs=["nTSecurityDescriptor"]) + def read_desc(self, object_dn, controls=None): + res = self.ldb_admin.search(base=object_dn, scope=SCOPE_BASE, attrs=["nTSecurityDescriptor"], controls=controls) desc = res[0]["nTSecurityDescriptor"][0] return ndr_unpack(security.descriptor, desc) @@ -257,10 +257,10 @@ userAccountControl: %s""" % userAccountControl desc_sddl = desc_sddl + ace self.modify_desc(self.ldb_admin, object_dn, desc_sddl) - def get_desc_sddl(self, object_dn): + def get_desc_sddl(self, object_dn, controls=None): """ Return object nTSecutiryDescriptor in SDDL format """ - desc = self.read_desc(object_dn) + desc = self.read_desc(object_dn, controls) return desc.as_sddl(self.domain_sid) def setUp(self): @@ -1783,6 +1783,62 @@ class SdFlagsDescriptorTests(DescriptorTests): self.assertTrue("G:AU" in desc_sddl) self.assertTrue("(D;;CC;;;LG)" in desc_sddl) + def test_307(self): + """ Read a descriptor with OWNER_SECURITY_INFORMATION + Only the owner part should be returned. + """ + ou_dn = "OU=test_sdflags_ou," + self.base_dn + self.create_domain_ou(self.ldb_admin, ou_dn) + desc_sddl = self.get_desc_sddl(ou_dn, controls=["sd_flags:1:%d" % (SECINFO_OWNER)]) + # make sure we have read the owner + self.assertTrue("O:" in desc_sddl) + # make sure we have read nothing else + self.assertFalse("G:" in desc_sddl) + self.assertFalse("D:" in desc_sddl) + self.assertFalse("S:" in desc_sddl) + + def test_308(self): + """ Read a descriptor with GROUP_SECURITY_INFORMATION + Only the group part should be returned. + """ + ou_dn = "OU=test_sdflags_ou," + self.base_dn + self.create_domain_ou(self.ldb_admin, ou_dn) + desc_sddl = self.get_desc_sddl(ou_dn, controls=["sd_flags:1:%d" % (SECINFO_GROUP)]) + # make sure we have read the owner + self.assertTrue("G:" in desc_sddl) + # make sure we have read nothing else + self.assertFalse("O:" in desc_sddl) + self.assertFalse("D:" in desc_sddl) + self.assertFalse("S:" in desc_sddl) + + def test_309(self): + """ Read a descriptor with SACL_SECURITY_INFORMATION + Only the sacl part should be returned. + """ + ou_dn = "OU=test_sdflags_ou," + self.base_dn + self.create_domain_ou(self.ldb_admin, ou_dn) + desc_sddl = self.get_desc_sddl(ou_dn, controls=["sd_flags:1:%d" % (SECINFO_SACL)]) + # make sure we have read the owner + self.assertTrue("S:" in desc_sddl) + # make sure we have read nothing else + self.assertFalse("O:" in desc_sddl) + self.assertFalse("D:" in desc_sddl) + self.assertFalse("G:" in desc_sddl) + + def test_310(self): + """ Read a descriptor with DACL_SECURITY_INFORMATION + Only the dacl part should be returned. + """ + ou_dn = "OU=test_sdflags_ou," + self.base_dn + self.create_domain_ou(self.ldb_admin, ou_dn) + desc_sddl = self.get_desc_sddl(ou_dn, controls=["sd_flags:1:%d" % (SECINFO_DACL)]) + # make sure we have read the owner + self.assertTrue("D:" in desc_sddl) + # make sure we have read nothing else + self.assertFalse("O:" in desc_sddl) + self.assertFalse("S:" in desc_sddl) + self.assertFalse("G:" in desc_sddl) + if not "://" in host: host = "ldap://%s" % host ldb = Ldb(host, credentials=creds, session_info=system_session(), lp=lp, options=["modules:paged_searches"]) |