From: Joseph Sutton Date: Fri, 22 Apr 2022 03:01:00 +0000 (+1200) Subject: CVE-2020-25720: s4-acl: Move definition of acl_check_self_membership() X-Git-Tag: talloc-2.4.0~998 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0e1d8929f872708e79edf802e5d2ff847c9b3ee5;p=thirdparty%2Fsamba.git CVE-2020-25720: s4-acl: Move definition of acl_check_self_membership() This allows us to make use of it in acl_add(). BUG: https://bugzilla.samba.org/show_bug.cgi?id=14810 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- diff --git a/source4/dsdb/samdb/ldb_modules/acl.c b/source4/dsdb/samdb/ldb_modules/acl.c index 4098ae2d671..038eb1dad2f 100644 --- a/source4/dsdb/samdb/ldb_modules/acl.c +++ b/source4/dsdb/samdb/ldb_modules/acl.c @@ -1148,6 +1148,78 @@ fail: return LDB_ERR_CONSTRAINT_VIOLATION; } +/* checks if modifications are allowed on "Member" attribute */ +static int acl_check_self_membership(TALLOC_CTX *mem_ctx, + struct ldb_module *module, + struct ldb_request *req, + struct security_descriptor *sd, + struct dom_sid *sid, + const struct dsdb_attribute *attr, + const struct dsdb_class *objectclass) +{ + int ret; + unsigned int i; + struct ldb_context *ldb = ldb_module_get_ctx(module); + struct ldb_dn *user_dn; + struct ldb_message_element *member_el; + const struct ldb_message *msg = NULL; + + if (req->operation == LDB_MODIFY) { + msg = req->op.mod.message; + } else if (req->operation == LDB_ADD) { + msg = req->op.add.message; + } else { + return LDB_ERR_OPERATIONS_ERROR; + } + + /* if we have wp, we can do whatever we like */ + if (acl_check_access_on_attribute(module, + mem_ctx, + sd, + sid, + SEC_ADS_WRITE_PROP, + attr, objectclass) == LDB_SUCCESS) { + return LDB_SUCCESS; + } + /* if we are adding/deleting ourselves, check for self membership */ + ret = dsdb_find_dn_by_sid(ldb, mem_ctx, + &acl_user_token(module)->sids[PRIMARY_USER_SID_INDEX], + &user_dn); + if (ret != LDB_SUCCESS) { + return ret; + } + member_el = ldb_msg_find_element(msg, "member"); + if (!member_el) { + return ldb_operr(ldb); + } + /* user can only remove oneself */ + if (member_el->num_values == 0) { + return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS; + } + for (i = 0; i < member_el->num_values; i++) { + if (strcasecmp((const char *)member_el->values[i].data, + ldb_dn_get_extended_linearized(mem_ctx, user_dn, 1)) != 0) { + return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS; + } + } + ret = acl_check_extended_right(mem_ctx, + module, + req, + objectclass, + sd, + acl_user_token(module), + GUID_DRS_SELF_MEMBERSHIP, + SEC_ADS_SELF_WRITE, + sid); + if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) { + dsdb_acl_debug(sd, acl_user_token(module), + msg->dn, + true, + 10); + } + return ret; +} + static int acl_add(struct ldb_module *module, struct ldb_request *req) { int ret; @@ -1280,78 +1352,6 @@ static int acl_add(struct ldb_module *module, struct ldb_request *req) return ldb_next_request(module, req); } -/* checks if modifications are allowed on "Member" attribute */ -static int acl_check_self_membership(TALLOC_CTX *mem_ctx, - struct ldb_module *module, - struct ldb_request *req, - struct security_descriptor *sd, - struct dom_sid *sid, - const struct dsdb_attribute *attr, - const struct dsdb_class *objectclass) -{ - int ret; - unsigned int i; - struct ldb_context *ldb = ldb_module_get_ctx(module); - struct ldb_dn *user_dn; - struct ldb_message_element *member_el; - const struct ldb_message *msg = NULL; - - if (req->operation == LDB_MODIFY) { - msg = req->op.mod.message; - } else if (req->operation == LDB_ADD) { - msg = req->op.add.message; - } else { - return LDB_ERR_OPERATIONS_ERROR; - } - - /* if we have wp, we can do whatever we like */ - if (acl_check_access_on_attribute(module, - mem_ctx, - sd, - sid, - SEC_ADS_WRITE_PROP, - attr, objectclass) == LDB_SUCCESS) { - return LDB_SUCCESS; - } - /* if we are adding/deleting ourselves, check for self membership */ - ret = dsdb_find_dn_by_sid(ldb, mem_ctx, - &acl_user_token(module)->sids[PRIMARY_USER_SID_INDEX], - &user_dn); - if (ret != LDB_SUCCESS) { - return ret; - } - member_el = ldb_msg_find_element(msg, "member"); - if (!member_el) { - return ldb_operr(ldb); - } - /* user can only remove oneself */ - if (member_el->num_values == 0) { - return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS; - } - for (i = 0; i < member_el->num_values; i++) { - if (strcasecmp((const char *)member_el->values[i].data, - ldb_dn_get_extended_linearized(mem_ctx, user_dn, 1)) != 0) { - return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS; - } - } - ret = acl_check_extended_right(mem_ctx, - module, - req, - objectclass, - sd, - acl_user_token(module), - GUID_DRS_SELF_MEMBERSHIP, - SEC_ADS_SELF_WRITE, - sid); - if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) { - dsdb_acl_debug(sd, acl_user_token(module), - msg->dn, - true, - 10); - } - return ret; -} - static int acl_check_password_rights( TALLOC_CTX *mem_ctx, struct ldb_module *module,