diff options
author | Stefan Metzmacher <metze@samba.org> | 2020-10-13 12:43:39 +0200 |
---|---|---|
committer | Stefan Metzmacher <metze@samba.org> | 2020-10-21 08:48:01 +0000 |
commit | 7223f6453b1b38c933c9480c637ffd06d9f39b97 (patch) | |
tree | 1a72480573178044d055204b790d3a91af3172e0 /source4 | |
parent | ffc0bdc6d49e88da1ee408956365da163ff3e1b2 (diff) | |
download | samba-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.c | 79 |
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; } /* |