From: Andrew Bartlett Date: Mon, 1 Nov 2021 04:19:29 +0000 (+1300) Subject: CVE-2020-25722 Check all elements in acl_check_spn() not just the first one X-Git-Tag: samba-4.13.14~131 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f1c64ed29ea0911beaa1cd3b80915ef5b44085af;p=thirdparty%2Fsamba.git CVE-2020-25722 Check all elements in acl_check_spn() not just the first one Thankfully we are aleady in a loop over all the message elements in acl_modify() so this is an easy and safe change to make. BUG: https://bugzilla.samba.org/show_bug.cgi?id=14876 Signed-off-by: Andrew Bartlett Reviewed-by: Joseph Sutton --- diff --git a/selftest/knownfail.d/acl-spn b/selftest/knownfail.d/acl-spn deleted file mode 100644 index e68add920a6..00000000000 --- a/selftest/knownfail.d/acl-spn +++ /dev/null @@ -1 +0,0 @@ -^samba4.ldap.acl.python.*AclSPNTests.test_delete_add_spn diff --git a/source4/dsdb/samdb/ldb_modules/acl.c b/source4/dsdb/samdb/ldb_modules/acl.c index 9cae15881de..d0b3da4d9e8 100644 --- a/source4/dsdb/samdb/ldb_modules/acl.c +++ b/source4/dsdb/samdb/ldb_modules/acl.c @@ -653,9 +653,14 @@ success: return LDB_SUCCESS; } +/* + * Passing in 'el' is critical, we want to check all the values. + * + */ static int acl_check_spn(TALLOC_CTX *mem_ctx, struct ldb_module *module, struct ldb_request *req, + const struct ldb_message_element *el, struct security_descriptor *sd, struct dom_sid *sid, const struct dsdb_attribute *attr, @@ -667,7 +672,6 @@ static int acl_check_spn(TALLOC_CTX *mem_ctx, struct ldb_context *ldb = ldb_module_get_ctx(module); struct ldb_result *acl_res; struct ldb_result *netbios_res; - struct ldb_message_element *el; struct ldb_dn *partitions_dn = samdb_partitions_dn(ldb, tmp_ctx); uint32_t userAccountControl; const char *samAccountName; @@ -717,6 +721,23 @@ static int acl_check_spn(TALLOC_CTX *mem_ctx, return ret; } + /* + * If we have "validated write spn", allow delete of any + * existing value (this keeps constrained delete to the same + * rules as unconstrained) + */ + if (req->operation == LDB_MODIFY) { + /* + * If not add or replace (eg delete), + * return success + */ + if ((el->flags + & (LDB_FLAG_MOD_ADD|LDB_FLAG_MOD_REPLACE)) == 0) { + talloc_free(tmp_ctx); + return LDB_SUCCESS; + } + } + ret = dsdb_module_search_dn(module, tmp_ctx, &acl_res, req->op.mod.message->dn, acl_attrs, @@ -745,13 +766,6 @@ static int acl_check_spn(TALLOC_CTX *mem_ctx, netbios_name = ldb_msg_find_attr_as_string(netbios_res->msgs[0], "nETBIOSName", NULL); - el = ldb_msg_find_element(req->op.mod.message, "servicePrincipalName"); - if (!el) { - talloc_free(tmp_ctx); - return ldb_error(ldb, LDB_ERR_OPERATIONS_ERROR, - "Error finding element for servicePrincipalName."); - } - /* NTDSDSA objectGuid of object we are checking SPN for */ if (userAccountControl & (UF_SERVER_TRUST_ACCOUNT | UF_PARTIAL_SECRETS_ACCOUNT)) { ret = dsdb_module_find_ntdsguid_for_computer(module, tmp_ctx, @@ -1510,6 +1524,7 @@ static int acl_modify(struct ldb_module *module, struct ldb_request *req) ret = acl_check_spn(tmp_ctx, module, req, + el, sd, sid, attr,