]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
CVE-2023-0614 ldb: Filter on search base before redacting message
authorJoseph Sutton <josephsutton@catalyst.net.nz>
Fri, 3 Mar 2023 04:35:55 +0000 (17:35 +1300)
committerAndrew Bartlett <abartlet@samba.org>
Wed, 5 Apr 2023 02:10:35 +0000 (02:10 +0000)
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 <josephsutton@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
lib/ldb/ABI/ldb-2.8.0.sigs
lib/ldb/common/ldb_match.c
lib/ldb/include/ldb_private.h
lib/ldb/ldb_key_value/ldb_kv_index.c
lib/ldb/ldb_key_value/ldb_kv_search.c

index 79111732c9788bb41d21d90d7386b2d17d024f52..759659a22f94083379a1aba541d36e852d7b83cb 100644 (file)
@@ -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 *)
index 4a549474995d5b3f14a586471f09f6e768ce0a22..1f74ebb84ce8d4cd907af98b4cabe2b5755ece9f 100644 (file)
 /*
   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;
 
index 47ddaa4ff14b095e76b00fed5188c1883206dcca..a7064f41f1b7faa54b53cbc2537b3bd24dd4b744 100644 (file)
@@ -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);
 
index e194046314a6afe09ff94b99595742228c19dfa4..bcbd903f6fb2b17a331c92d3138774ade1904929 100644 (file)
@@ -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);
index 5b35699df5a3cf48e7852ba27168d8345c1c5f8c..5dbbae6b15c32c61ca190265b95fb03d9ad6f510 100644 (file)
@@ -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;