summaryrefslogtreecommitdiff
path: root/source4
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2020-10-13 12:43:39 +0200
committerKarolin Seeger <kseeger@samba.org>2020-10-27 08:22:01 +0000
commitb15f35b573817b0e39425ae05962a9b1028bdc32 (patch)
tree461842ac1f8aed46a5d807825e6bc057318e1f2f /source4
parent0918966f9d5673112a913d3be2b4cb8320be6b27 (diff)
downloadsamba-b15f35b573817b0e39425ae05962a9b1028bdc32.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 (cherry picked from commit 7223f6453b1b38c933c9480c637ffd06d9f39b97)
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 d3cd5d5e1bd..f3acf08c021 100644
--- a/source4/dsdb/samdb/ldb_modules/acl_read.c
+++ b/source4/dsdb/samdb/ldb_modules/acl_read.c
@@ -50,6 +50,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;
@@ -160,6 +162,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,
@@ -171,7 +174,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;
}
/*