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

Generated by: LCOV version 1.14