LCOV - code coverage report
Current view: top level - lib/ldb/tools - ldbsearch.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 141 159 88.7 %
Date: 2024-05-31 13:13:24 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: ldbsearch
      28             :  *
      29             :  *  Description: utility for ldb search - modelled on ldapsearch
      30             :  *
      31             :  *  Author: Andrew Tridgell
      32             :  */
      33             : 
      34             : #include "replace.h"
      35             : #include "system/filesys.h"
      36             : #include "system/time.h"
      37             : #include "ldb.h"
      38             : #include "tools/cmdline.h"
      39             : 
      40           1 : static void usage(struct ldb_context *ldb)
      41             : {
      42           1 :         printf("Usage: ldbsearch <options> <expression> <attrs...>\n");
      43           1 :         ldb_cmdline_help(ldb, "ldbsearch", stdout);
      44           1 :         exit(LDB_ERR_OPERATIONS_ERROR);
      45             : }
      46             : 
      47        3175 : static int do_compare_msg(struct ldb_message **el1,
      48             :                           struct ldb_message **el2)
      49             : {
      50        3175 :         return ldb_dn_compare((*el1)->dn, (*el2)->dn);
      51             : }
      52             : 
      53             : struct search_context {
      54             :         struct ldb_context *ldb;
      55             :         struct ldb_control **req_ctrls;
      56             : 
      57             :         int sort;
      58             :         unsigned int num_stored;
      59             :         struct ldb_message **store;
      60             :         unsigned int refs_stored;
      61             :         char **refs_store;
      62             : 
      63             :         unsigned int entries;
      64             :         unsigned int refs;
      65             : 
      66             :         unsigned int pending;
      67             :         int status;
      68             : };
      69             : 
      70         626 : static int store_message(struct ldb_message *msg, struct search_context *sctx) {
      71             : 
      72         626 :         sctx->store = talloc_realloc(sctx, sctx->store, struct ldb_message *, sctx->num_stored + 2);
      73         626 :         if (!sctx->store) {
      74           0 :                 fprintf(stderr, "talloc_realloc failed while storing messages\n");
      75           0 :                 return -1;
      76             :         }
      77             : 
      78         626 :         sctx->store[sctx->num_stored] = talloc_move(sctx->store, &msg);
      79         626 :         sctx->num_stored++;
      80         626 :         sctx->store[sctx->num_stored] = NULL;
      81             : 
      82         626 :         return 0;
      83             : }
      84             : 
      85          90 : static int store_referral(char *referral, struct search_context *sctx) {
      86             : 
      87          90 :         sctx->refs_store = talloc_realloc(sctx, sctx->refs_store, char *, sctx->refs_stored + 2);
      88          90 :         if (!sctx->refs_store) {
      89           0 :                 fprintf(stderr, "talloc_realloc failed while storing referrals\n");
      90           0 :                 return -1;
      91             :         }
      92             : 
      93          90 :         sctx->refs_store[sctx->refs_stored] = talloc_move(sctx->refs_store, &referral);
      94          90 :         sctx->refs_stored++;
      95          90 :         sctx->refs_store[sctx->refs_stored] = NULL;
      96             : 
      97          90 :         return 0;
      98             : }
      99             : 
     100        7821 : static int display_message(struct ldb_message *msg, struct search_context *sctx) {
     101         593 :         struct ldb_ldif ldif;
     102             : 
     103        7821 :         sctx->entries++;
     104        7821 :         printf("# record %d\n", sctx->entries);
     105             : 
     106        7821 :         ldif.changetype = LDB_CHANGETYPE_NONE;
     107        7821 :         ldif.msg = msg;
     108             : 
     109        7821 :         if (sctx->sort) {
     110             :         /*
     111             :          * Ensure attributes are always returned in the same
     112             :          * order.  For testing, this makes comparison of old
     113             :          * vs. new much easier.
     114             :          */
     115         626 :                 ldb_msg_sort_elements(ldif.msg);
     116             :         }
     117             : 
     118        7821 :         ldb_ldif_write_file(sctx->ldb, stdout, &ldif);
     119             : 
     120        7821 :         return 0;
     121             : }
     122             : 
     123         628 : static int display_referral(char *referral, struct search_context *sctx)
     124             : {
     125             : 
     126         628 :         sctx->refs++;
     127         649 :         printf("# Referral\nref: %s\n\n", referral);
     128             : 
     129         628 :         return 0;
     130             : }
     131             : 
     132        9459 : static int search_callback(struct ldb_request *req, struct ldb_reply *ares)
     133             : {
     134         721 :         struct search_context *sctx;
     135        9459 :         int ret = LDB_SUCCESS;
     136             : 
     137        9459 :         sctx = talloc_get_type(req->context, struct search_context);
     138             : 
     139        9459 :         if (!ares) {
     140           0 :                 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
     141             :         }
     142        9459 :         if (ares->error != LDB_SUCCESS) {
     143          10 :                 return ldb_request_done(req, ares->error);
     144             :         }
     145             :         
     146        9449 :         switch (ares->type) {
     147        7821 :         case LDB_REPLY_ENTRY:
     148        7821 :                 if (sctx->sort) {
     149         626 :                         ret = store_message(ares->message, sctx);
     150             :                 } else {
     151        7195 :                         ret = display_message(ares->message, sctx);
     152             :                 }
     153        7228 :                 break;
     154             : 
     155         628 :         case LDB_REPLY_REFERRAL:
     156         628 :                 if (sctx->sort) {
     157          90 :                         ret = store_referral(ares->referral, sctx);
     158             :                 } else {
     159         538 :                         ret = display_referral(ares->referral, sctx);
     160             :                 }
     161         628 :                 if (ret) {
     162           0 :                         return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
     163             :                 }
     164         607 :                 break;
     165             : 
     166        1000 :         case LDB_REPLY_DONE:
     167        1000 :                 if (ares->controls) {
     168          44 :                         if (handle_controls_reply(ares->controls, sctx->req_ctrls) == 1)
     169          22 :                                 sctx->pending = 1;
     170             :                 }
     171        1000 :                 talloc_free(ares);
     172        1000 :                 return ldb_request_done(req, LDB_SUCCESS);
     173             :         }
     174             : 
     175        8449 :         talloc_free(ares);
     176        8449 :         if (ret != LDB_SUCCESS) {
     177           0 :                 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
     178             :         }
     179             : 
     180        7835 :         return LDB_SUCCESS;
     181             : }
     182             : 
     183         991 : static int do_search(struct ldb_context *ldb,
     184             :                      struct ldb_dn *basedn,
     185             :                      struct ldb_cmdline *options,
     186             :                      const char *expression,
     187             :                      const char * const *attrs)
     188             : {
     189         110 :         struct ldb_request *req;
     190         110 :         struct search_context *sctx;
     191         110 :         int ret;
     192             : 
     193         991 :         req = NULL;
     194             :         
     195         991 :         sctx = talloc_zero(ldb, struct search_context);
     196         991 :         if (!sctx) return LDB_ERR_OPERATIONS_ERROR;
     197             : 
     198         991 :         sctx->ldb = ldb;
     199         991 :         sctx->sort = options->sorted;
     200         991 :         sctx->req_ctrls = ldb_parse_control_strings(ldb, sctx, (const char **)options->controls);
     201         991 :         if (options->controls != NULL &&  sctx->req_ctrls== NULL) {
     202           0 :                 printf("parsing controls failed: %s\n", ldb_errstring(ldb));
     203           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     204             :         }
     205             : 
     206         991 : again:
     207             :         /* free any previous requests */
     208        1013 :         if (req) talloc_free(req);
     209             : 
     210        1013 :         ret = ldb_build_search_req(&req, ldb, ldb,
     211             :                                    basedn, options->scope,
     212             :                                    expression, attrs,
     213             :                                    sctx->req_ctrls,
     214             :                                    sctx, search_callback,
     215             :                                    NULL);
     216        1013 :         if (ret != LDB_SUCCESS) {
     217           3 :                 talloc_free(sctx);
     218           3 :                 printf("allocating request failed: %s\n", ldb_errstring(ldb));
     219           3 :                 return ret;
     220             :         }
     221             : 
     222        1010 :         if (basedn == NULL) {
     223             :                 /*
     224             :                   we need to use a NULL base DN when doing a cross-ncs
     225             :                   search so we find results on all partitions in a
     226             :                   forest. When doing a domain-local search, default to
     227             :                   the default basedn
     228             :                  */
     229          67 :                 struct ldb_control *ctrl;
     230         332 :                 struct ldb_search_options_control *search_options = NULL;
     231             : 
     232         332 :                 ctrl = ldb_request_get_control(req, LDB_CONTROL_SEARCH_OPTIONS_OID);
     233         332 :                 if (ctrl) {
     234          22 :                         search_options = talloc_get_type(ctrl->data, struct ldb_search_options_control);
     235             :                 }
     236             : 
     237         332 :                 if (ctrl == NULL || search_options == NULL ||
     238          22 :                     !(search_options->search_options & LDB_SEARCH_OPTION_PHANTOM_ROOT)) {
     239         310 :                         struct ldb_dn *base = ldb_get_default_basedn(ldb);
     240         310 :                         if (base != NULL) {
     241         245 :                                 req->op.search.base = base;
     242             :                         }
     243             :                 }
     244             :         }
     245             : 
     246        1010 :         sctx->pending = 0;
     247             : 
     248        1010 :         ret = ldb_request(ldb, req);
     249        1010 :         if (ret != LDB_SUCCESS) {
     250           0 :                 talloc_free(sctx);
     251           0 :                 talloc_free(req);
     252           0 :                 printf("search failed - %s\n", ldb_errstring(ldb));
     253           0 :                 return ret;
     254             :         }
     255             : 
     256        1010 :         ret = ldb_wait(req->handle, LDB_WAIT_ALL);
     257        1010 :         if (ret != LDB_SUCCESS) {
     258          10 :                 talloc_free(sctx);
     259          10 :                 talloc_free(req);
     260          10 :                 printf("search error - %s\n", ldb_errstring(ldb));
     261          10 :                 return ret;
     262             :         }
     263             : 
     264        1000 :         if (sctx->pending)
     265          22 :                 goto again;
     266             : 
     267         978 :         if (sctx->sort && (sctx->num_stored != 0 || sctx->refs != 0)) {
     268           7 :                 unsigned int i;
     269             : 
     270          46 :                 if (sctx->num_stored) {
     271          46 :                         TYPESAFE_QSORT(sctx->store, sctx->num_stored, do_compare_msg);
     272             :                 }
     273         672 :                 for (i = 0; i < sctx->num_stored; i++) {
     274         626 :                         display_message(sctx->store[i], sctx);
     275             :                 }
     276             : 
     277         136 :                 for (i = 0; i < sctx->refs_stored; i++) {
     278          90 :                         display_referral(sctx->refs_store[i], sctx);
     279             :                 }
     280             :         }
     281             : 
     282         978 :         printf("# returned %u records\n# %u entries\n# %u referrals\n",
     283         881 :                 sctx->entries + sctx->refs, sctx->entries, sctx->refs);
     284             : 
     285         978 :         talloc_free(sctx);
     286         978 :         talloc_free(req);
     287             : 
     288         978 :         return LDB_SUCCESS;
     289             : }
     290             : 
     291        1081 : int main(int argc, const char **argv)
     292             : {
     293         111 :         struct ldb_context *ldb;
     294        1081 :         struct ldb_dn *basedn = NULL;
     295        1081 :         const char * const * attrs = NULL;
     296         111 :         struct ldb_cmdline *options;
     297        1081 :         int ret = -1;
     298        1081 :         const char *expression = "(|(objectClass=*)(distinguishedName=*))";
     299        1081 :         TALLOC_CTX *mem_ctx = talloc_new(NULL);
     300             : 
     301        1081 :         ldb = ldb_init(mem_ctx, NULL);
     302        1081 :         if (ldb == NULL) {
     303           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     304             :         }
     305             : 
     306        1081 :         options = ldb_cmdline_process_search(ldb, argc, argv, usage);
     307             : 
     308             :         /* the check for '=' is for compatibility with ldapsearch */
     309         991 :         if (!options->interactive &&
     310         991 :             options->argc > 0 && 
     311         860 :             strpbrk(options->argv[0], "=<>~:")) {
     312         613 :                 expression = options->argv[0];
     313         613 :                 options->argv++;
     314         613 :                 options->argc--;
     315             :         }
     316             : 
     317         991 :         if (options->argc > 0) {
     318         498 :                 attrs = (const char * const *)(options->argv);
     319             :         }
     320             : 
     321         991 :         if (options->basedn != NULL) {
     322         678 :                 basedn = ldb_dn_new(ldb, ldb, options->basedn);
     323         678 :                 if (basedn == NULL) {
     324           0 :                         talloc_free(mem_ctx);
     325           0 :                         return LDB_ERR_OPERATIONS_ERROR;
     326             :                 }
     327             :         }
     328             : 
     329         991 :         if (options->interactive) {
     330             :                 char line[1024];
     331           0 :                 while (fgets(line, sizeof(line), stdin)) {
     332           0 :                         ret = do_search(ldb, basedn, options, line, attrs);
     333             :                 }
     334             :         } else {
     335         991 :                 ret = do_search(ldb, basedn, options, expression, attrs);
     336             :         }
     337             : 
     338         991 :         talloc_free(mem_ctx);
     339             : 
     340         991 :         return ret;
     341             : }

Generated by: LCOV version 1.14