LCOV - code coverage report
Current view: top level - lib/ldb/ldb_key_value - ldb_kv_search.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 246 311 79.1 %
Date: 2024-02-28 12:06:22 Functions: 9 9 100.0 %

          Line data    Source code
       1             : /*
       2             :    ldb database library
       3             : 
       4             :    Copyright (C) Andrew Tridgell  2004
       5             : 
       6             :      ** NOTE! The following LGPL license applies to the ldb
       7             :      ** library. This does NOT imply that all of Samba is released
       8             :      ** under the LGPL
       9             : 
      10             :    This library is free software; you can redistribute it and/or
      11             :    modify it under the terms of the GNU Lesser General Public
      12             :    License as published by the Free Software Foundation; either
      13             :    version 3 of the License, or (at your option) any later version.
      14             : 
      15             :    This library is distributed in the hope that it will be useful,
      16             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      18             :    Lesser General Public License for more details.
      19             : 
      20             :    You should have received a copy of the GNU Lesser General Public
      21             :    License along with this library; if not, see <http://www.gnu.org/licenses/>.
      22             : */
      23             : 
      24             : /*
      25             :  *  Name: ldb
      26             :  *
      27             :  *  Component: ldb search functions
      28             :  *
      29             :  *  Description: functions to search ldb+tdb databases
      30             :  *
      31             :  *  Author: Andrew Tridgell
      32             :  */
      33             : 
      34             : #include "ldb_kv.h"
      35             : #include "ldb_private.h"
      36             : #include "lib/util/attr.h"
      37             : /*
      38             :   search the database for a single simple dn.
      39             :   return LDB_ERR_NO_SUCH_OBJECT on record-not-found
      40             :   and LDB_SUCCESS on success
      41             : */
      42    95269798 : int ldb_kv_search_base(struct ldb_module *module,
      43             :                        TALLOC_CTX *mem_ctx,
      44             :                        struct ldb_dn *dn,
      45             :                        struct ldb_dn **ret_dn)
      46             : {
      47     2292075 :         int exists;
      48     2292075 :         int ret;
      49    95269798 :         struct ldb_message *msg = NULL;
      50             : 
      51    95269798 :         if (ldb_dn_is_null(dn)) {
      52           0 :                 return LDB_ERR_NO_SUCH_OBJECT;
      53             :         }
      54             : 
      55             :         /*
      56             :          * We can't use tdb_exists() directly on a key when the TDB
      57             :          * key is the GUID one, not the DN based one.  So we just do a
      58             :          * normal search and avoid most of the allocation with the
      59             :          * LDB_UNPACK_DATA_FLAG_NO_ATTRS flag
      60             :          */
      61    95269798 :         msg = ldb_msg_new(module);
      62    95269798 :         if (msg == NULL) {
      63           0 :                 return LDB_ERR_OPERATIONS_ERROR;
      64             :         }
      65             : 
      66    95269798 :         ret = ldb_kv_search_dn1(module, dn, msg, LDB_UNPACK_DATA_FLAG_NO_ATTRS);
      67    95269798 :         if (ret == LDB_SUCCESS) {
      68     2291848 :                 const char *dn_linearized
      69    95187625 :                         = ldb_dn_get_linearized(dn);
      70     2291848 :                 const char *msg_dn_linearized
      71    95187625 :                         = ldb_dn_get_linearized(msg->dn);
      72             : 
      73    95187625 :                 if (strcmp(dn_linearized, msg_dn_linearized) == 0) {
      74             :                         /*
      75             :                          * Re-use the full incoming DN for
      76             :                          * subtree checks
      77             :                          */
      78    95162818 :                         *ret_dn = dn;
      79             :                 } else {
      80             :                         /*
      81             :                          * Use the string DN from the unpack, so that
      82             :                          * we have a case-exact match of the base
      83             :                          */
      84       24807 :                         *ret_dn = talloc_steal(mem_ctx, msg->dn);
      85             :                 }
      86    92895777 :                 exists = true;
      87       82173 :         } else if (ret == LDB_ERR_NO_SUCH_OBJECT) {
      88       81946 :                 exists = false;
      89             :         } else {
      90           0 :                 talloc_free(msg);
      91           0 :                 return ret;
      92             :         }
      93    95269798 :         talloc_free(msg);
      94    95269798 :         if (exists) {
      95    95187625 :                 return LDB_SUCCESS;
      96             :         }
      97       81946 :         return LDB_ERR_NO_SUCH_OBJECT;
      98             : }
      99             : 
     100             : struct ldb_kv_parse_data_unpack_ctx {
     101             :         struct ldb_message *msg;
     102             :         struct ldb_module *module;
     103             :         struct ldb_kv_private *ldb_kv;
     104             :         unsigned int unpack_flags;
     105             : };
     106             : 
     107   381563551 : static int ldb_kv_parse_data_unpack(struct ldb_val key,
     108             :                                     struct ldb_val data,
     109             :                                     void *private_data)
     110             : {
     111   381563551 :         struct ldb_kv_parse_data_unpack_ctx *ctx = private_data;
     112    10929385 :         int ret;
     113   381563551 :         struct ldb_context *ldb = ldb_module_get_ctx(ctx->module);
     114   381563551 :         struct ldb_val data_parse = data;
     115             : 
     116   381563551 :         struct ldb_kv_private *ldb_kv = ctx->ldb_kv;
     117             : 
     118   381563551 :         if ((ldb_kv->kv_ops->options & LDB_KV_OPTION_STABLE_READ_LOCK) &&
     119   170282479 :             (ctx->unpack_flags & LDB_UNPACK_DATA_FLAG_READ_LOCKED) &&
     120    81653028 :             !ldb_kv->kv_ops->transaction_active(ldb_kv)) {
     121             :                 /*
     122             :                  * In the case where no transactions are active and
     123             :                  * we're in a read-lock, we can point directly into
     124             :                  * database memory.
     125             :                  *
     126             :                  * The database can't be changed underneath us and we
     127             :                  * will duplicate this data in the call to filter.
     128             :                  *
     129             :                  * This is seen in:
     130             :                  * - ldb_kv_index_filter
     131             :                  * - ldb_kv_search_and_return_base
     132             :                  */
     133             :         } else {
     134             :                 /*
     135             :                  * In every other case, since unpack doesn't memdup, we need
     136             :                  * to at least do a memdup on the whole data buffer as that
     137             :                  * may change later and the caller needs a stable result.
     138             :                  *
     139             :                  * During transactions, pointers could change and in
     140             :                  * TDB, there just aren't the same guarantees.
     141             :                  */
     142   326962670 :                 data_parse.data = talloc_memdup(ctx->msg,
     143             :                                                 data.data,
     144             :                                                 data.length);
     145   326962670 :                 if (data_parse.data == NULL) {
     146           0 :                         ldb_debug(ldb, LDB_DEBUG_ERROR,
     147             :                                   "Unable to allocate data(%d) for %*.*s\n",
     148           0 :                                   (int)data.length,
     149           0 :                                   (int)key.length, (int)key.length, key.data);
     150           0 :                         return LDB_ERR_OPERATIONS_ERROR;
     151             :                 }
     152             :         }
     153             : 
     154   381563551 :         ret = ldb_unpack_data_flags(ldb, &data_parse,
     155             :                                     ctx->msg, ctx->unpack_flags);
     156   381563551 :         if (ret == -1) {
     157           0 :                 if (data_parse.data != data.data) {
     158           0 :                         talloc_free(data_parse.data);
     159             :                 }
     160             : 
     161           0 :                 ldb_debug(ldb, LDB_DEBUG_ERROR,
     162             :                           __location__ ": Invalid data for index %*.*s\n",
     163           0 :                           (int)key.length, (int)key.length, key.data);
     164           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     165             :         }
     166   370634166 :         return ret;
     167             : }
     168             : 
     169             : /*
     170             :   search the database for a single simple dn, returning all attributes
     171             :   in a single message
     172             : 
     173             :   return LDB_ERR_NO_SUCH_OBJECT on record-not-found
     174             :   and LDB_SUCCESS on success
     175             : */
     176   464618766 : int ldb_kv_search_key(struct ldb_module *module,
     177             :                       struct ldb_kv_private *ldb_kv,
     178             :                       const struct ldb_val ldb_key,
     179             :                       struct ldb_message *msg,
     180             :                       unsigned int unpack_flags)
     181             : {
     182    13770536 :         int ret;
     183   464618766 :         struct ldb_kv_parse_data_unpack_ctx ctx = {
     184             :                 .msg = msg,
     185             :                 .module = module,
     186             :                 .unpack_flags = unpack_flags,
     187             :                 .ldb_kv = ldb_kv
     188             :         };
     189             : 
     190   464618766 :         memset(msg, 0, sizeof(*msg));
     191             : 
     192   464618766 :         msg->num_elements = 0;
     193   464618766 :         msg->elements = NULL;
     194             : 
     195   464618766 :         ret = ldb_kv->kv_ops->fetch_and_parse(
     196             :             ldb_kv, ldb_key, ldb_kv_parse_data_unpack, &ctx);
     197             : 
     198   464618766 :         if (ret == -1) {
     199           0 :                 ret = ldb_kv->kv_ops->error(ldb_kv);
     200           0 :                 if (ret == LDB_SUCCESS) {
     201             :                         /*
     202             :                          * Just to be sure we don't turn errors
     203             :                          * into success
     204             :                          */
     205           0 :                         return LDB_ERR_OPERATIONS_ERROR;
     206             :                 }
     207           0 :                 return ret;
     208   464618766 :         } else if (ret != LDB_SUCCESS) {
     209    83055215 :                 return ret;
     210             :         }
     211             : 
     212   370634166 :         return LDB_SUCCESS;
     213             : }
     214             : 
     215             : /*
     216             :   search the database for a single simple dn, returning all attributes
     217             :   in a single message
     218             : 
     219             :   return LDB_ERR_NO_SUCH_OBJECT on record-not-found
     220             :   and LDB_SUCCESS on success
     221             : */
     222   324546783 : int ldb_kv_search_dn1(struct ldb_module *module,
     223             :                       struct ldb_dn *dn,
     224             :                       struct ldb_message *msg,
     225             :                       unsigned int unpack_flags)
     226             : {
     227   324546783 :         void *data = ldb_module_get_private(module);
     228    11465425 :         struct ldb_kv_private *ldb_kv =
     229   324546783 :             talloc_get_type(data, struct ldb_kv_private);
     230    11465425 :         int ret;
     231    11465425 :         uint8_t guid_key[LDB_KV_GUID_KEY_SIZE];
     232   324546783 :         struct ldb_val key = {
     233             :                 .data = guid_key,
     234             :                 .length = sizeof(guid_key)
     235             :         };
     236   324546783 :         TALLOC_CTX *tdb_key_ctx = NULL;
     237             : 
     238   324546783 :         bool valid_dn = ldb_dn_validate(dn);
     239   324546783 :         if (valid_dn == false) {
     240           0 :                 ldb_asprintf_errstring(ldb_module_get_ctx(module),
     241             :                                        "Invalid Base DN: %s",
     242             :                                        ldb_dn_get_linearized(dn));
     243           0 :                 return LDB_ERR_INVALID_DN_SYNTAX;
     244             :         }
     245             : 
     246   645108764 :         if (ldb_kv->cache->GUID_index_attribute == NULL ||
     247   320561981 :             ldb_dn_is_special(dn)) {
     248             : 
     249   197638163 :                 tdb_key_ctx = talloc_new(msg);
     250   197638163 :                 if (!tdb_key_ctx) {
     251           0 :                         return ldb_module_oom(module);
     252             :                 }
     253             : 
     254             :                 /* form the key */
     255   197638163 :                 key = ldb_kv_key_dn(tdb_key_ctx, dn);
     256   197638163 :                 if (!key.data) {
     257           0 :                         TALLOC_FREE(tdb_key_ctx);
     258           0 :                         return LDB_ERR_OPERATIONS_ERROR;
     259             :                 }
     260             :         } else {
     261             :                 /*
     262             :                  * Look in the index to find the key for this DN.
     263             :                  *
     264             :                  * the tdb_key memory is allocated above, msg is just
     265             :                  * used for internal memory.
     266             :                  *
     267             :                  */
     268   126908620 :                 ret = ldb_kv_key_dn_from_idx(module, ldb_kv, msg, dn, &key);
     269   126908620 :                 if (ret != LDB_SUCCESS) {
     270     1914137 :                         return ret;
     271             :                 }
     272             :         }
     273             : 
     274   322290902 :         ret = ldb_kv_search_key(module, ldb_kv, key, msg, unpack_flags);
     275             : 
     276   322290902 :         TALLOC_FREE(tdb_key_ctx);
     277             : 
     278   322290902 :         if (ret != LDB_SUCCESS) {
     279    15342082 :                 return ret;
     280             :         }
     281             : 
     282   305615489 :         if ((unpack_flags & LDB_UNPACK_DATA_FLAG_NO_DN) == 0) {
     283   200818215 :                 if (!msg->dn) {
     284           0 :                         msg->dn = ldb_dn_copy(msg, dn);
     285             :                 }
     286   200818215 :                 if (!msg->dn) {
     287           0 :                         return LDB_ERR_OPERATIONS_ERROR;
     288             :                 }
     289             :         }
     290             : 
     291   295825139 :         return LDB_SUCCESS;
     292             : }
     293             : 
     294             : /*
     295             :  * filter the specified list of attributes from msg,
     296             :  * adding requested attributes, and perhaps all for *.
     297             :  * The DN will not be added if it is missing.
     298             :  */
     299   102679454 : int ldb_kv_filter_attrs_in_place(struct ldb_message *msg,
     300             :                                  const char *const *attrs)
     301             : {
     302   102679454 :         return ldb_filter_attrs_in_place(msg, attrs);
     303             : }
     304             : 
     305             : /*
     306             :   search function for a non-indexed search
     307             :  */
     308   536937247 : static int search_func(_UNUSED_ struct ldb_kv_private *ldb_kv,
     309             :                        struct ldb_val key,
     310             :                        struct ldb_val val,
     311             :                        void *state)
     312             : {
     313     1220835 :         struct ldb_context *ldb;
     314     1220835 :         struct ldb_kv_context *ac;
     315     1220835 :         struct ldb_message *msg;
     316     1220835 :         struct timeval now;
     317     1220835 :         int ret, timeval_cmp;
     318     1220835 :         bool matched;
     319             : 
     320   536937247 :         ac = talloc_get_type(state, struct ldb_kv_context);
     321   536937247 :         ldb = ldb_module_get_ctx(ac->module);
     322             : 
     323             :         /*
     324             :          * We want to skip @ records early in a search full scan
     325             :          *
     326             :          * @ records like @IDXLIST are only available via a base
     327             :          * search on the specific name but the method by which they
     328             :          * were excluded was expensive, after the unpack the DN is
     329             :          * exploded and ldb_match_msg_error() would reject it for
     330             :          * failing to match the scope.
     331             :          *
     332             :          * ldb_kv_key_is_normal_record() uses the fact that @ records
     333             :          * have the DN=@ prefix on their TDB/LMDB key to quickly
     334             :          * exclude them from consideration.
     335             :          *
     336             :          * (any other non-records are also excluded by the same key
     337             :          * match)
     338             :          */
     339             : 
     340   536937247 :         if (ldb_kv_key_is_normal_record(key) == false) {
     341   428855421 :                 return 0;
     342             :         }
     343             : 
     344             :         /*
     345             :          * Check the time every 64 records, to reduce calls to
     346             :          * gettimeofday().  This is a compromise, not all calls to
     347             :          * ldb_match_message() will take the same time, most will fail
     348             :          * quickly but by luck it might be possible to have 64 records
     349             :          * that are slow, doing a recursive search via
     350             :          * LDAP_MATCHING_RULE_IN_CHAIN.
     351             :          */
     352   107145857 :         if (ac->timeout_counter++ % 64 == 0) {
     353     1706293 :                 now = tevent_timeval_current();
     354     1706293 :                 timeval_cmp = tevent_timeval_compare(&ac->timeout_timeval,
     355             :                                                      &now);
     356             : 
     357             :                 /*
     358             :                  * The search has taken too long.  This is the most
     359             :                  * likely place for our time to expire, as we are in
     360             :                  * an un-indexed search and we return the data from
     361             :                  * within this loop.  The tevent based timeout is not
     362             :                  * likely to be hit, sadly.
     363             :                  *
     364             :                  * ldb_match_msg_error() can be quite expensive if a
     365             :                  * LDAP_MATCHING_RULE_IN_CHAIN extended match was
     366             :                  * specified.
     367             :                  */
     368     1706293 :                 if (timeval_cmp <= 0) {
     369           5 :                         ac->error = LDB_ERR_TIME_LIMIT_EXCEEDED;
     370           5 :                         return -1;
     371             :                 }
     372             :         }
     373             : 
     374   107145852 :         msg = ldb_msg_new(ac);
     375   107145852 :         if (!msg) {
     376           0 :                 ac->error = LDB_ERR_OPERATIONS_ERROR;
     377           0 :                 return -1;
     378             :         }
     379             : 
     380             :         /* unpack the record */
     381   107145852 :         ret = ldb_unpack_data_flags(ldb, &val, msg,
     382             :                                     LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC);
     383   107145852 :         if (ret == -1) {
     384           0 :                 talloc_free(msg);
     385           0 :                 ac->error = LDB_ERR_OPERATIONS_ERROR;
     386           0 :                 return -1;
     387             :         }
     388             : 
     389   107145852 :         if (!msg->dn) {
     390           0 :                 msg->dn = ldb_dn_new(msg, ldb,
     391           0 :                                      (char *)key.data + 3);
     392           0 :                 if (msg->dn == NULL) {
     393           0 :                         talloc_free(msg);
     394           0 :                         ac->error = LDB_ERR_OPERATIONS_ERROR;
     395           0 :                         return -1;
     396             :                 }
     397             :         }
     398             : 
     399             :         /*
     400             :          * The redaction callback may be expensive to call if it fetches a
     401             :          * security descriptor. Check the DN early and bail out if it doesn't
     402             :          * match the base.
     403             :          */
     404   107145852 :         if (!ldb_match_scope(ldb, ac->base, msg->dn, ac->scope)) {
     405    92516050 :                 talloc_free(msg);
     406    92516050 :                 return 0;
     407             :         }
     408             : 
     409    14629802 :         if (ldb->redact.callback != NULL) {
     410    14557838 :                 ret = ldb->redact.callback(ldb->redact.module, ac->req, msg);
     411    14557838 :                 if (ret != LDB_SUCCESS) {
     412           0 :                         talloc_free(msg);
     413           0 :                         return ret;
     414             :                 }
     415             :         }
     416             : 
     417             :         /* see if it matches the given expression */
     418    14629802 :         ret = ldb_match_message(ldb, msg,
     419             :                                 ac->tree, ac->scope, &matched);
     420    14629802 :         if (ret != LDB_SUCCESS) {
     421          23 :                 talloc_free(msg);
     422          23 :                 ac->error = LDB_ERR_OPERATIONS_ERROR;
     423          23 :                 return -1;
     424             :         }
     425    14629779 :         if (!matched) {
     426    10780941 :                 talloc_free(msg);
     427    10780941 :                 return 0;
     428             :         }
     429             : 
     430     3848838 :         ret = ldb_msg_add_distinguished_name(msg);
     431     3848838 :         if (ret == -1) {
     432           0 :                 talloc_free(msg);
     433           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     434             :         }
     435             : 
     436             :         /* filter the attributes that the user wants */
     437     3848838 :         ret = ldb_kv_filter_attrs_in_place(msg, ac->attrs);
     438     3848838 :         if (ret != LDB_SUCCESS) {
     439           0 :                 talloc_free(msg);
     440           0 :                 ac->error = LDB_ERR_OPERATIONS_ERROR;
     441           0 :                 return -1;
     442             :         }
     443             : 
     444     3848838 :         ldb_msg_shrink_to_fit(msg);
     445             : 
     446             :         /* Ensure the message elements are all talloc'd. */
     447     3848838 :         ret = ldb_msg_elements_take_ownership(msg);
     448     3848838 :         if (ret != LDB_SUCCESS) {
     449           0 :                 talloc_free(msg);
     450           0 :                 ac->error = LDB_ERR_OPERATIONS_ERROR;
     451           0 :                 return -1;
     452             :         }
     453             : 
     454     3848838 :         ret = ldb_module_send_entry(ac->req, msg, NULL);
     455     3848834 :         if (ret != LDB_SUCCESS) {
     456           5 :                 ac->request_terminated = true;
     457             :                 /* the callback failed, abort the operation */
     458           5 :                 ac->error = LDB_ERR_OPERATIONS_ERROR;
     459           5 :                 return -1;
     460             :         }
     461             : 
     462     3604356 :         return 0;
     463             : }
     464             : 
     465             : /*
     466             :  * Key pointing to just before the first GUID indexed record for
     467             :  * iterate_range
     468             :  */
     469             : struct ldb_val start_of_db_key = {.data=discard_const_p(uint8_t, "GUID<"),
     470             :                                   .length=6};
     471             : /*
     472             :  * Key pointing to just after the last GUID indexed record for
     473             :  * iterate_range
     474             :  */
     475             : struct ldb_val end_of_db_key = {.data=discard_const_p(uint8_t, "GUID>"),
     476             :                                 .length=6};
     477             : 
     478             : /*
     479             :   search the database with a LDAP-like expression.
     480             :   this is the "full search" non-indexed variant
     481             : */
     482       60414 : static int ldb_kv_search_full(struct ldb_kv_context *ctx)
     483             : {
     484       60414 :         void *data = ldb_module_get_private(ctx->module);
     485         946 :         struct ldb_kv_private *ldb_kv =
     486       60414 :             talloc_get_type(data, struct ldb_kv_private);
     487         946 :         int ret;
     488             : 
     489             :         /*
     490             :          * If the backend has an iterate_range op, use it to start the search
     491             :          * at the first GUID indexed record, skipping the indexes section.
     492             :          */
     493       60414 :         ctx->error = LDB_SUCCESS;
     494       60414 :         ret = ldb_kv->kv_ops->iterate_range(ldb_kv,
     495             :                                             start_of_db_key,
     496             :                                             end_of_db_key,
     497             :                                             search_func,
     498             :                                             ctx);
     499       60414 :         if (ret == LDB_ERR_OPERATIONS_ERROR) {
     500             :                 /*
     501             :                  * If iterate_range isn't defined, it'll return an error,
     502             :                  * so just iterate over the whole DB.
     503             :                  */
     504       47882 :                 ret = ldb_kv->kv_ops->iterate(ldb_kv, search_func, ctx);
     505             :         }
     506             : 
     507       60410 :         if (ret < 0) {
     508           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     509             :         }
     510             : 
     511       60410 :         return ctx->error;
     512             : }
     513             : 
     514    33461209 : static int ldb_kv_search_and_return_base(struct ldb_kv_private *ldb_kv,
     515             :                                          struct ldb_kv_context *ctx)
     516             : {
     517     1930831 :         struct ldb_message *msg;
     518    33461209 :         struct ldb_context *ldb = ldb_module_get_ctx(ctx->module);
     519     1930831 :         const char *dn_linearized;
     520     1930831 :         const char *msg_dn_linearized;
     521     1930831 :         int ret;
     522     1930831 :         bool matched;
     523             : 
     524    33461209 :         msg = ldb_msg_new(ctx);
     525    33461209 :         if (!msg) {
     526           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     527             :         }
     528    33461209 :         ret = ldb_kv_search_dn1(ctx->module,
     529             :                                 ctx->base,
     530             :                                 msg,
     531             :                                 LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC |
     532             :                                 LDB_UNPACK_DATA_FLAG_READ_LOCKED);
     533             : 
     534    33461209 :         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
     535     2261244 :                 if (ldb_kv->check_base == false) {
     536             :                         /*
     537             :                          * In this case, we are done, as no base
     538             :                          * checking is allowed in this DB
     539             :                          */
     540       85571 :                         talloc_free(msg);
     541       85571 :                         return LDB_SUCCESS;
     542             :                 }
     543     2175673 :                 ldb_asprintf_errstring(ldb,
     544             :                                        "No such Base DN: %s",
     545             :                                        ldb_dn_get_linearized(ctx->base));
     546             :         }
     547    33375638 :         if (ret != LDB_SUCCESS) {
     548     2175673 :                 talloc_free(msg);
     549     2175673 :                 return ret;
     550             :         }
     551             : 
     552    31199965 :         if (ldb->redact.callback != NULL) {
     553    28892045 :                 ret = ldb->redact.callback(ldb->redact.module, ctx->req, msg);
     554    28892045 :                 if (ret != LDB_SUCCESS) {
     555           0 :                         talloc_free(msg);
     556           0 :                         return ret;
     557             :                 }
     558             :         }
     559             : 
     560             :         /*
     561             :          * We use this, not ldb_match_msg_error() as we know
     562             :          * we matched on the scope BASE, as we just fetched
     563             :          * the base DN
     564             :          */
     565             : 
     566    31199965 :         ret = ldb_match_message(ldb, msg,
     567             :                                 ctx->tree,
     568             :                                 ctx->scope,
     569             :                                 &matched);
     570    31199965 :         if (ret != LDB_SUCCESS) {
     571           0 :                 talloc_free(msg);
     572           0 :                 return ret;
     573             :         }
     574    31199965 :         if (!matched) {
     575      714943 :                 talloc_free(msg);
     576      714943 :                 return LDB_SUCCESS;
     577             :         }
     578             : 
     579    30485022 :         dn_linearized = ldb_dn_get_linearized(ctx->base);
     580    30485022 :         msg_dn_linearized = ldb_dn_get_linearized(msg->dn);
     581             : 
     582    30485022 :         if (strcmp(dn_linearized, msg_dn_linearized) == 0) {
     583             :                 /*
     584             :                  * If the DN is exactly the same string, then
     585             :                  * re-use the full incoming DN for the
     586             :                  * returned result, as it has already been
     587             :                  * casefolded
     588             :                  */
     589    29156977 :                 struct ldb_dn *dn = ldb_dn_copy(msg, ctx->base);
     590    29156977 :                 if (dn != NULL) {
     591    29156977 :                         msg->dn = dn;
     592             :                 }
     593             :         }
     594             : 
     595    30485022 :         ret = ldb_msg_add_distinguished_name(msg);
     596    30485022 :         if (ret == -1) {
     597           0 :                 talloc_free(msg);
     598           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     599             :         }
     600             : 
     601             :         /*
     602             :          * filter the attributes that the user wants.
     603             :          */
     604    30485022 :         ret = ldb_kv_filter_attrs_in_place(msg, ctx->attrs);
     605    30485022 :         if (ret != LDB_SUCCESS) {
     606           0 :                 talloc_free(msg);
     607           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     608             :         }
     609             : 
     610    30485022 :         ldb_msg_shrink_to_fit(msg);
     611             : 
     612             :         /* Ensure the message elements are all talloc'd. */
     613    30485022 :         ret = ldb_msg_elements_take_ownership(msg);
     614    30485022 :         if (ret != LDB_SUCCESS) {
     615           0 :                 talloc_free(msg);
     616           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     617             :         }
     618             : 
     619             :         /*
     620             :          * Remove any extended components, we just want the casefold components
     621             :          */
     622    30485022 :         ldb_dn_remove_extended_components(msg->dn);
     623             : 
     624    30485022 :         ret = ldb_module_send_entry(ctx->req, msg, NULL);
     625    30485020 :         if (ret != LDB_SUCCESS) {
     626             :                 /* Regardless of success or failure, the msg
     627             :                  * is the callbacks responsibility, and should
     628             :                  * not be talloc_free()'ed */
     629          30 :                 ctx->request_terminated = true;
     630          30 :                 return ret;
     631             :         }
     632             : 
     633    28923888 :         return LDB_SUCCESS;
     634             : }
     635             : 
     636             : /*
     637             :   search the database with a LDAP-like expression.
     638             :   choses a search method
     639             : */
     640   129545971 : int ldb_kv_search(struct ldb_kv_context *ctx)
     641             : {
     642     4301109 :         struct ldb_context *ldb;
     643   129545971 :         struct ldb_module *module = ctx->module;
     644   129545971 :         struct ldb_request *req = ctx->req;
     645   129545971 :         void *data = ldb_module_get_private(module);
     646     4301109 :         struct ldb_kv_private *ldb_kv =
     647   129545971 :             talloc_get_type(data, struct ldb_kv_private);
     648     4301109 :         int ret;
     649             : 
     650   129545971 :         ldb = ldb_module_get_ctx(module);
     651             : 
     652   129545971 :         ldb_request_set_state(req, LDB_ASYNC_PENDING);
     653             : 
     654   129545971 :         if (ldb_kv->kv_ops->lock_read(module) != 0) {
     655           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     656             :         }
     657             : 
     658   129545971 :         if (ldb_kv_cache_load(module) != 0) {
     659           0 :                 ldb_kv->kv_ops->unlock_read(module);
     660           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     661             :         }
     662             : 
     663   129545971 :         if (req->op.search.tree == NULL) {
     664           0 :                 ldb_kv->kv_ops->unlock_read(module);
     665           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     666             :         }
     667             : 
     668   129545971 :         ctx->tree = req->op.search.tree;
     669   129545971 :         ctx->scope = req->op.search.scope;
     670   129545971 :         ctx->base = req->op.search.base;
     671   129545971 :         ctx->attrs = req->op.search.attrs;
     672             : 
     673   129545971 :         if ((req->op.search.base == NULL) || (ldb_dn_is_null(req->op.search.base) == true)) {
     674             : 
     675             :                 /* Check what we should do with a NULL dn */
     676      815518 :                 switch (req->op.search.scope) {
     677      134632 :                 case LDB_SCOPE_BASE:
     678      134632 :                         ldb_asprintf_errstring(ldb,
     679             :                                                "NULL Base DN invalid for a base search");
     680      134632 :                         ret = LDB_ERR_INVALID_DN_SYNTAX;
     681      134632 :                         break;
     682           2 :                 case LDB_SCOPE_ONELEVEL:
     683           2 :                         ldb_asprintf_errstring(ldb,
     684             :                                                "NULL Base DN invalid for a one-level search");
     685           2 :                         ret = LDB_ERR_INVALID_DN_SYNTAX;
     686           2 :                         break;
     687      611275 :                 case LDB_SCOPE_SUBTREE:
     688             :                 default:
     689             :                         /* We accept subtree searches from a NULL base DN, ie over the whole DB */
     690      611275 :                         ret = LDB_SUCCESS;
     691             :                 }
     692   128730453 :         } else if (req->op.search.scope == LDB_SCOPE_BASE) {
     693             : 
     694             :                 /*
     695             :                  * If we are LDB_SCOPE_BASE, do just one search and
     696             :                  * return early.  This is critical to ensure we do not
     697             :                  * go into the index code for special DNs, as that
     698             :                  * will try to look up an index record for a special
     699             :                  * record (which doesn't exist).
     700             :                  */
     701    33461209 :                 ret = ldb_kv_search_and_return_base(ldb_kv, ctx);
     702             : 
     703    33461207 :                 ldb_kv->kv_ops->unlock_read(module);
     704             : 
     705    33461207 :                 return ret;
     706             : 
     707    95269244 :         } else if (ldb_kv->check_base) {
     708             :                 /*
     709             :                  * This database has been marked as
     710             :                  * 'checkBaseOnSearch', so do a spot check of the base
     711             :                  * dn.  Also optimise the subsequent filter by filling
     712             :                  * in the ctx->base to be exactly case correct
     713             :                  */
     714    95188525 :                 ret = ldb_kv_search_base(
     715             :                     module, ctx, req->op.search.base, &ctx->base);
     716             : 
     717    95188525 :                 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
     718         971 :                         ldb_asprintf_errstring(ldb,
     719             :                                                "No such Base DN: %s",
     720             :                                                ldb_dn_get_linearized(req->op.search.base));
     721             :                 }
     722             : 
     723       80719 :         } else if (ldb_dn_validate(req->op.search.base) == false) {
     724             : 
     725             :                 /* We don't want invalid base DNs here */
     726           0 :                 ldb_asprintf_errstring(ldb,
     727             :                                        "Invalid Base DN: %s",
     728             :                                        ldb_dn_get_linearized(req->op.search.base));
     729           0 :                 ret = LDB_ERR_INVALID_DN_SYNTAX;
     730             : 
     731             :         } else {
     732             :                 /* If we are not checking the base DN life is easy */
     733       77237 :                 ret = LDB_SUCCESS;
     734             :         }
     735             : 
     736    96011671 :         if (ret == LDB_SUCCESS) {
     737    95949157 :                 uint32_t match_count = 0;
     738             : 
     739    95949157 :                 ret = ldb_kv_search_indexed(ctx, &match_count);
     740    95949153 :                 if (ret == LDB_ERR_NO_SUCH_OBJECT) {
     741             :                         /* Not in the index, therefore OK! */
     742     8070422 :                         ret = LDB_SUCCESS;
     743             : 
     744             :                 }
     745             :                 /* Check if we got just a normal error.
     746             :                  * In that case proceed to a full search unless we got a
     747             :                  * callback error */
     748    95949153 :                 if (!ctx->request_terminated && ret != LDB_SUCCESS) {
     749             :                         /* Not indexed, so we need to do a full scan */
     750       60450 :                         if (ldb_kv->warn_unindexed ||
     751       60450 :                             ldb_kv->disable_full_db_scan) {
     752             :                                 /* useful for debugging when slow performance
     753             :                                  * is caused by unindexed searches */
     754          36 :                                 char *expression = ldb_filter_from_tree(ctx, ctx->tree);
     755          72 :                                 ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb FULL SEARCH: %s SCOPE: %s DN: %s",
     756             :                                                         expression,
     757          36 :                                                         req->op.search.scope==LDB_SCOPE_BASE?"base":
     758          60 :                                                         req->op.search.scope==LDB_SCOPE_ONELEVEL?"one":
     759          24 :                                                         req->op.search.scope==LDB_SCOPE_SUBTREE?"sub":"UNKNOWN",
     760             :                                                         ldb_dn_get_linearized(req->op.search.base));
     761             : 
     762          36 :                                 talloc_free(expression);
     763             :                         }
     764             : 
     765       60450 :                         if (match_count != 0) {
     766             :                                 /* the indexing code gave an error
     767             :                                  * after having returned at least one
     768             :                                  * entry. This means the indexes are
     769             :                                  * corrupt or a database record is
     770             :                                  * corrupt. We cannot continue with a
     771             :                                  * full search or we may return
     772             :                                  * duplicate entries
     773             :                                  */
     774           0 :                                 ldb_kv->kv_ops->unlock_read(module);
     775          36 :                                 return LDB_ERR_OPERATIONS_ERROR;
     776             :                         }
     777             : 
     778       60450 :                         if (ldb_kv->disable_full_db_scan) {
     779          36 :                                 ldb_set_errstring(ldb,
     780             :                                                   "ldb FULL SEARCH disabled");
     781          36 :                                 ldb_kv->kv_ops->unlock_read(module);
     782          36 :                                 return LDB_ERR_INAPPROPRIATE_MATCHING;
     783             :                         }
     784             : 
     785       60414 :                         ret = ldb_kv_search_full(ctx);
     786       60410 :                         if (ret != LDB_SUCCESS) {
     787          33 :                                 ldb_set_errstring(ldb, "Indexed and full searches both failed!\n");
     788             :                         }
     789             :                 }
     790             :         }
     791             : 
     792    96084718 :         ldb_kv->kv_ops->unlock_read(module);
     793             : 
     794    96084718 :         return ret;
     795             : }

Generated by: LCOV version 1.14