From: Joseph Sutton Date: Fri, 3 Mar 2023 04:35:55 +0000 (+1300) Subject: CVE-2023-0614 ldb: Filter on search base before redacting message X-Git-Tag: talloc-2.4.1~1065 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=449c2e99e27b472fa87153e17b25446cd35a5577;p=thirdparty%2Fsamba.git CVE-2023-0614 ldb: Filter on search base before redacting message Redaction may be expensive if we end up needing to fetch a security descriptor to verify rights to an attribute. Checking the search scope is probably cheaper, so do that first. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15270 Signed-off-by: Joseph Sutton Reviewed-by: Andrew Bartlett --- diff --git a/lib/ldb/ABI/ldb-2.8.0.sigs b/lib/ldb/ABI/ldb-2.8.0.sigs index 79111732c97..759659a22f9 100644 --- a/lib/ldb/ABI/ldb-2.8.0.sigs +++ b/lib/ldb/ABI/ldb-2.8.0.sigs @@ -126,6 +126,7 @@ ldb_match_message: int (struct ldb_context *, const struct ldb_message *, const ldb_match_msg: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, struct ldb_dn *, enum ldb_scope) ldb_match_msg_error: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, struct ldb_dn *, enum ldb_scope, bool *) ldb_match_msg_objectclass: int (const struct ldb_message *, const char *) +ldb_match_scope: int (struct ldb_context *, struct ldb_dn *, struct ldb_dn *, enum ldb_scope) ldb_mod_register_control: int (struct ldb_module *, const char *) ldb_modify: int (struct ldb_context *, const struct ldb_message *) ldb_modify_default_callback: int (struct ldb_request *, struct ldb_reply *) diff --git a/lib/ldb/common/ldb_match.c b/lib/ldb/common/ldb_match.c index 4a549474995..1f74ebb84ce 100644 --- a/lib/ldb/common/ldb_match.c +++ b/lib/ldb/common/ldb_match.c @@ -39,10 +39,10 @@ /* check if the scope matches in a search result */ -static int ldb_match_scope(struct ldb_context *ldb, - struct ldb_dn *base, - struct ldb_dn *dn, - enum ldb_scope scope) +int ldb_match_scope(struct ldb_context *ldb, + struct ldb_dn *base, + struct ldb_dn *dn, + enum ldb_scope scope) { int ret = 0; diff --git a/lib/ldb/include/ldb_private.h b/lib/ldb/include/ldb_private.h index 47ddaa4ff14..a7064f41f1b 100644 --- a/lib/ldb/include/ldb_private.h +++ b/lib/ldb/include/ldb_private.h @@ -322,6 +322,14 @@ int ldb_match_message(struct ldb_context *ldb, const struct ldb_parse_tree *tree, enum ldb_scope scope, bool *matched); +/* + check if the scope matches in a search result +*/ +int ldb_match_scope(struct ldb_context *ldb, + struct ldb_dn *base, + struct ldb_dn *dn, + enum ldb_scope scope); + /* Reallocate elements to drop any excess capacity. */ void ldb_msg_shrink_to_fit(struct ldb_message *msg); diff --git a/lib/ldb/ldb_key_value/ldb_kv_index.c b/lib/ldb/ldb_key_value/ldb_kv_index.c index e194046314a..bcbd903f6fb 100644 --- a/lib/ldb/ldb_key_value/ldb_kv_index.c +++ b/lib/ldb/ldb_key_value/ldb_kv_index.c @@ -2428,31 +2428,37 @@ static int ldb_kv_index_filter(struct ldb_kv_private *ldb_kv, return LDB_ERR_OPERATIONS_ERROR; } - if (ldb->redact.callback != NULL) { - ret = ldb->redact.callback(ldb->redact.module, ac->req, msg); - if (ret != LDB_SUCCESS) { - talloc_free(msg); - return ret; - } - } - /* * We trust the index for LDB_SCOPE_ONELEVEL * unless the index key has been truncated. * * LDB_SCOPE_BASE is not passed in by our only caller. */ - if (ac->scope == LDB_SCOPE_ONELEVEL && - ldb_kv->cache->one_level_indexes && - scope_one_truncation == KEY_NOT_TRUNCATED) { - ret = ldb_match_message(ldb, msg, ac->tree, - ac->scope, &matched); - } else { - ret = ldb_match_msg_error(ldb, msg, - ac->tree, ac->base, - ac->scope, &matched); + if (ac->scope != LDB_SCOPE_ONELEVEL || + !ldb_kv->cache->one_level_indexes || + scope_one_truncation != KEY_NOT_TRUNCATED) + { + /* + * The redaction callback may be expensive to call if it + * fetches a security descriptor. Check the DN early and + * bail out if it doesn't match the base. + */ + if (!ldb_match_scope(ldb, ac->base, msg->dn, ac->scope)) { + talloc_free(msg); + continue; + } + } + + if (ldb->redact.callback != NULL) { + ret = ldb->redact.callback(ldb->redact.module, ac->req, msg); + if (ret != LDB_SUCCESS) { + talloc_free(msg); + return ret; + } } + ret = ldb_match_message(ldb, msg, ac->tree, + ac->scope, &matched); if (ret != LDB_SUCCESS) { talloc_free(keys); talloc_free(msg); diff --git a/lib/ldb/ldb_key_value/ldb_kv_search.c b/lib/ldb/ldb_key_value/ldb_kv_search.c index 5b35699df5a..5dbbae6b15c 100644 --- a/lib/ldb/ldb_key_value/ldb_kv_search.c +++ b/lib/ldb/ldb_key_value/ldb_kv_search.c @@ -396,6 +396,16 @@ static int search_func(_UNUSED_ struct ldb_kv_private *ldb_kv, } } + /* + * The redaction callback may be expensive to call if it fetches a + * security descriptor. Check the DN early and bail out if it doesn't + * match the base. + */ + if (!ldb_match_scope(ldb, ac->base, msg->dn, ac->scope)) { + talloc_free(msg); + return 0; + } + if (ldb->redact.callback != NULL) { ret = ldb->redact.callback(ldb->redact.module, ac->req, msg); if (ret != LDB_SUCCESS) { @@ -405,8 +415,8 @@ static int search_func(_UNUSED_ struct ldb_kv_private *ldb_kv, } /* see if it matches the given expression */ - ret = ldb_match_msg_error(ldb, msg, - ac->tree, ac->base, ac->scope, &matched); + ret = ldb_match_message(ldb, msg, + ac->tree, ac->scope, &matched); if (ret != LDB_SUCCESS) { talloc_free(msg); ac->error = LDB_ERR_OPERATIONS_ERROR;