summaryrefslogtreecommitdiff
path: root/source4
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2020-10-13 12:43:39 +0200
committerStefan Metzmacher <metze@samba.org>2020-10-21 08:48:01 +0000
commit7223f6453b1b38c933c9480c637ffd06d9f39b97 (patch)
tree1a72480573178044d055204b790d3a91af3172e0 /source4
parentffc0bdc6d49e88da1ee408956365da163ff3e1b2 (diff)
downloadsamba-7223f6453b1b38c933c9480c637ffd06d9f39b97.tar.gz
s4:dsdb:acl_read: Implement "List Object" mode feature
See [MS-ADTS] 5.1.3.3.6 Checking Object Visibility I tried to avoid any possible overhead for the common cases: - SEC_ADS_LIST (List Children) is already granted by default - fDoListObject is off by default Overhead is only added if the administrator turned on the fDoListObject feature and removed SEC_ADS_LIST (List Children) from a parent object. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14531 Signed-off-by: Stefan Metzmacher <metze@samba.org> Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz> Autobuild-User(master): Stefan Metzmacher <metze@samba.org> Autobuild-Date(master): Wed Oct 21 08:48:02 UTC 2020 on sn-devel-184
Diffstat (limited to 'source4')
-rw-r--r--source4/dsdb/samdb/ldb_modules/acl_read.c79
1 files changed, 78 insertions, 1 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/acl_read.c b/source4/dsdb/samdb/ldb_modules/acl_read.c
index f217288f3a9..b221dcde445 100644
--- a/source4/dsdb/samdb/ldb_modules/acl_read.c
+++ b/source4/dsdb/samdb/ldb_modules/acl_read.c
@@ -52,6 +52,8 @@ struct aclread_context {
bool added_objectClass;
bool indirsync;
+ bool do_list_object_initialized;
+ bool do_list_object;
bool base_invisible;
uint64_t num_entries;
@@ -162,6 +164,7 @@ static int aclread_check_object_visible(struct aclread_context *ac,
struct ldb_request *req)
{
uint32_t instanceType;
+ int ret;
/* get the object instance type */
instanceType = ldb_msg_find_attr_as_uint(msg,
@@ -173,7 +176,81 @@ static int aclread_check_object_visible(struct aclread_context *ac,
return LDB_SUCCESS;
}
- return aclread_check_parent(ac, msg, req);
+ ret = aclread_check_parent(ac, msg, req);
+ if (ret == LDB_SUCCESS) {
+ /*
+ * SEC_ADS_LIST (List Children) alone
+ * on the parent is enough to make the
+ * object visible.
+ */
+ return LDB_SUCCESS;
+ }
+ if (ret != LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) {
+ return ret;
+ }
+
+ if (!ac->do_list_object_initialized) {
+ /*
+ * We only call dsdb_do_list_object() once
+ * and only when needed in order to
+ * check the dSHeuristics for fDoListObject.
+ */
+ ac->do_list_object = dsdb_do_list_object(ac->module, ac, req);
+ ac->do_list_object_initialized = true;
+ }
+
+ if (ac->do_list_object) {
+ TALLOC_CTX *frame = talloc_stackframe();
+ struct ldb_dn *parent_dn = NULL;
+
+ /*
+ * Here we're in "List Object" mode (fDoListObject=true).
+ *
+ * If SEC_ADS_LIST (List Children) is not
+ * granted on the parent, we need to check if
+ * SEC_ADS_LIST_OBJECT (List Object) is granted
+ * on the parent and also on the object itself.
+ *
+ * We could optimize this similar to aclread_check_parent(),
+ * but that would require quite a bit of restructuring,
+ * so that we cache the granted access bits instead
+ * of just the result for 'SEC_ADS_LIST (List Children)'.
+ *
+ * But as this is the uncommon case and
+ * 'SEC_ADS_LIST (List Children)' is most likely granted
+ * on most of the objects, we'll just implement what
+ * we have to.
+ */
+
+ parent_dn = ldb_dn_get_parent(frame, msg->dn);
+ if (parent_dn == NULL) {
+ TALLOC_FREE(frame);
+ return ldb_oom(ldb_module_get_ctx(ac->module));
+ }
+ ret = dsdb_module_check_access_on_dn(ac->module,
+ frame,
+ parent_dn,
+ SEC_ADS_LIST_OBJECT,
+ NULL, req);
+ if (ret != LDB_SUCCESS) {
+ TALLOC_FREE(frame);
+ return ret;
+ }
+ ret = dsdb_module_check_access_on_dn(ac->module,
+ frame,
+ msg->dn,
+ SEC_ADS_LIST_OBJECT,
+ NULL, req);
+ if (ret != LDB_SUCCESS) {
+ TALLOC_FREE(frame);
+ return ret;
+ }
+
+ TALLOC_FREE(frame);
+ return LDB_SUCCESS;
+ }
+
+ return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
}
/*