Implemented LDAP_SERVER_SD_FLAGS_OID on search requests.
authorNadezhda Ivanova <nadezhda.ivanova@postpath.com>
Sat, 21 Nov 2009 16:40:51 +0000 (18:40 +0200)
committerNadezhda Ivanova <nadezhda.ivanova@postpath.com>
Sat, 21 Nov 2009 16:40:51 +0000 (18:40 +0200)
source4/dsdb/samdb/ldb_modules/descriptor.c
source4/dsdb/samdb/ldb_modules/kludge_acl.c
source4/lib/ldb/tests/python/sec_descriptor.py

index 98e54b1..c3413e1 100644 (file)
@@ -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,
index 0cec95b..7a51aa1 100644 (file)
@@ -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);
index 8763579..3e0be64 100755 (executable)
@@ -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"])