s4-dsdb: relax a bit the checks on read acl when dirsync control is specified
authorMatthieu Patou <mat@matws.net>
Mon, 7 Mar 2011 22:02:32 +0000 (01:02 +0300)
committerMatthieu Patou <mat@matws.net>
Tue, 8 Mar 2011 21:54:30 +0000 (00:54 +0300)
source4/dsdb/samdb/ldb_modules/acl_read.c

index cde6d11c75bd07d4f6dd032e9f01d2b8e78eb2a9..e7c54c970bd0ff9aaa8f1e5e85e7754bb845a7c6 100644 (file)
@@ -47,6 +47,7 @@ struct aclread_context {
        bool sd;
        bool instance_type;
        bool object_sid;
+       bool indirsync;
 };
 
 struct aclread_private {
@@ -158,18 +159,38 @@ static int aclread_callback(struct ldb_request *req, struct ldb_reply *ares)
                                                             access_mask,
                                                             attr);
 
-                        if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) {
-                                /* do not return this entry if attribute is
-                                   part of the search filter */
-                                if (dsdb_attr_in_parse_tree(ac->req->op.search.tree,
-                                                            msg->elements[i].name)) {
-                                        talloc_free(tmp_ctx);
-                                        return LDB_SUCCESS;
-                                }
-                                aclread_mark_inaccesslible(&msg->elements[i]);
-                        } else if (ret != LDB_SUCCESS) {
-                                goto fail;
-                        }
+                       /*
+                        * Dirsync control needs the replpropertymetadata attribute
+                        * so return it as it will be removed by the control
+                        * in anycase.
+                        */
+                       if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) {
+                               if (!ac->indirsync) {
+                                       /* do not return this entry if attribute is
+                                       part of the search filter */
+                                       if (dsdb_attr_in_parse_tree(ac->req->op.search.tree,
+                                                               msg->elements[i].name)) {
+                                               talloc_free(tmp_ctx);
+                                               return LDB_SUCCESS;
+                                       }
+                                       aclread_mark_inaccesslible(&msg->elements[i]);
+                               } else {
+                                       /*
+                                        * We are doing dirysnc answers
+                                        * and the object shouldn't be returned (normally)
+                                        * but we will return it without replPropertyMetaData
+                                        * so that the dirysync module will do what is needed
+                                        * (remove the object if it is not deleted, or return
+                                        * just the objectGUID if it's deleted).
+                                        */
+                                       if (dsdb_attr_in_parse_tree(ac->req->op.search.tree,
+                                                               msg->elements[i].name)) {
+                                               ldb_msg_remove_attr(msg, "replPropertyMetaData");
+                                       }
+                               }
+                       } else if (ret != LDB_SUCCESS) {
+                               goto fail;
+                       }
                 }
                 for (i=0; i < msg->num_elements; i++) {
                         if (!aclread_is_inaccessible(&msg->elements[i])) {
@@ -224,6 +245,7 @@ static int aclread_search(struct ldb_module *module, struct ldb_request *req)
        struct aclread_context *ac;
        struct ldb_request *down_req;
        struct ldb_control *as_system = ldb_request_get_control(req, LDB_CONTROL_AS_SYSTEM_OID);
+       struct ldb_control *indirsync = ldb_request_get_control(req, DSDB_CONTROL_DIRSYNC_RELAX_CHECK_OID);
        struct ldb_result *res;
        struct aclread_private *p;
        bool is_untrusted = ldb_req_is_untrusted(req);
@@ -284,6 +306,11 @@ static int aclread_search(struct ldb_module *module, struct ldb_request *req)
        ac->module = module;
        ac->req = req;
        ac->schema = dsdb_get_schema(ldb, req);
+       if (indirsync != NULL) {
+               ac->indirsync = true;
+       } else {
+               ac->indirsync = false;
+       }
        if (!ac->schema) {
                return ldb_operr(ldb);
        }