dsdb-acl: make use of acl_check_access_on_objectclass() for the object in acl_delete()
authorStefan Metzmacher <metze@samba.org>
Thu, 17 Jan 2013 15:21:10 +0000 (16:21 +0100)
committerStefan Metzmacher <metze@samba.org>
Mon, 21 Jan 2013 15:12:45 +0000 (16:12 +0100)
We should only use dsdb_module_check_access_on_dn() on the parent.

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
source4/dsdb/samdb/ldb_modules/acl.c

index 0ab96709be1981d30c9b6506739a5d7845e99469..41c257b999dcd1d2cecbdf473ed67db117c2df89 100644 (file)
@@ -1163,6 +1163,17 @@ static int acl_delete(struct ldb_module *module, struct ldb_request *req)
        struct ldb_context *ldb;
        struct ldb_dn *nc_root;
        struct ldb_control *as_system;
+       const struct dsdb_schema *schema;
+       const struct dsdb_class *objectclass;
+       struct security_descriptor *sd = NULL;
+       struct dom_sid *sid = NULL;
+       struct ldb_result *acl_res;
+       static const char *acl_attrs[] = {
+               "nTSecurityDescriptor",
+               "objectClass",
+               "objectSid",
+               NULL
+       };
 
        if (ldb_dn_is_special(req->op.del.dn)) {
                return ldb_next_request(module, req);
@@ -1201,11 +1212,43 @@ static int acl_delete(struct ldb_module *module, struct ldb_request *req)
        }
        talloc_free(nc_root);
 
+       ret = dsdb_module_search_dn(module, req, &acl_res,
+                                   req->op.del.dn, acl_attrs,
+                                   DSDB_FLAG_NEXT_MODULE |
+                                   DSDB_FLAG_AS_SYSTEM |
+                                   DSDB_SEARCH_SHOW_RECYCLED, req);
+       /* we sould be able to find the parent */
+       if (ret != LDB_SUCCESS) {
+               DEBUG(10,("acl: failed to find object %s\n",
+                         ldb_dn_get_linearized(req->op.rename.olddn)));
+               return ret;
+       }
+
+       ret = dsdb_get_sd_from_ldb_message(ldb, req, acl_res->msgs[0], &sd);
+       if (ret != LDB_SUCCESS) {
+               return ldb_operr(ldb);
+       }
+       if (!sd) {
+               return ldb_operr(ldb);
+       }
+
+       schema = dsdb_get_schema(ldb, req);
+       if (!schema) {
+               return ldb_operr(ldb);
+       }
+
+       sid = samdb_result_dom_sid(req, acl_res->msgs[0], "objectSid");
+
+       objectclass = dsdb_get_structural_oc_from_msg(schema, acl_res->msgs[0]);
+       if (!objectclass) {
+               return ldb_error(ldb, LDB_ERR_OPERATIONS_ERROR,
+                                "acl_modify: Error retrieving object class for GUID.");
+       }
+
        if (ldb_request_get_control(req, LDB_CONTROL_TREE_DELETE_OID)) {
-               ret = dsdb_module_check_access_on_dn(module, req,
-                                                    req->op.del.dn,
-                                                    SEC_ADS_DELETE_TREE, NULL,
-                                                    req);
+               ret = acl_check_access_on_objectclass(module, req, sd, sid,
+                                                     SEC_ADS_DELETE_TREE,
+                                                     objectclass);
                if (ret != LDB_SUCCESS) {
                        return ret;
                }
@@ -1214,8 +1257,9 @@ static int acl_delete(struct ldb_module *module, struct ldb_request *req)
        }
 
        /* First check if we have delete object right */
-       ret = dsdb_module_check_access_on_dn(module, req, req->op.del.dn,
-                                            SEC_STD_DELETE, NULL, req);
+       ret = acl_check_access_on_objectclass(module, req, sd, sid,
+                                             SEC_STD_DELETE,
+                                             objectclass);
        if (ret == LDB_SUCCESS) {
                return ldb_next_request(module, req);
        }