summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/dsdb/samdb/ldb_modules/descriptor.c167
-rw-r--r--source4/dsdb/samdb/ldb_modules/kludge_acl.c20
-rwxr-xr-xsource4/lib/ldb/tests/python/sec_descriptor.py64
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"])