LCOV - code coverage report
Current view: top level - lib/ldb/tools - ldbsearch.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 132 150 88.0 %
Date: 2021-09-23 10: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: 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        4287 : static int do_compare_msg(struct ldb_message **el1,
      48             :                           struct ldb_message **el2,
      49             :                           void *opaque)
      50             : {
      51        4293 :         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        7578 : static int display_message(struct ldb_message *msg, struct search_context *sctx) {
     102             :         struct ldb_ldif ldif;
     103             : 
     104        7578 :         sctx->entries++;
     105        8171 :         printf("# record %d\n", sctx->entries);
     106             : 
     107        7578 :         ldif.changetype = LDB_CHANGETYPE_NONE;
     108        7578 :         ldif.msg = msg;
     109             : 
     110        7578 :         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        7578 :         ldb_ldif_write_file(sctx->ldb, stdout, &ldif);
     120             : 
     121        7578 :         return 0;
     122             : }
     123             : 
     124         607 : static int display_referral(char *referral, struct search_context *sctx)
     125             : {
     126             : 
     127         628 :         sctx->refs++;
     128         628 :         printf("# Referral\nref: %s\n\n", referral);
     129             : 
     130         607 :         return 0;
     131             : }
     132             : 
     133        9183 : static int search_callback(struct ldb_request *req, struct ldb_reply *ares)
     134             : {
     135             :         struct search_context *sctx;
     136        9183 :         int ret = LDB_SUCCESS;
     137             : 
     138        9183 :         sctx = talloc_get_type(req->context, struct search_context);
     139             : 
     140        9183 :         if (!ares) {
     141           0 :                 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
     142             :         }
     143        9183 :         if (ares->error != LDB_SUCCESS) {
     144          12 :                 return ldb_request_done(req, ares->error);
     145             :         }
     146             :         
     147        9171 :         switch (ares->type) {
     148        7578 :         case LDB_REPLY_ENTRY:
     149        7578 :                 if (sctx->sort) {
     150         626 :                         ret = store_message(ares->message, sctx);
     151             :                 } else {
     152        6952 :                         ret = display_message(ares->message, sctx);
     153             :                 }
     154        6985 :                 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         965 :         case LDB_REPLY_DONE:
     168         965 :                 if (ares->controls) {
     169          44 :                         if (handle_controls_reply(ares->controls, sctx->req_ctrls) == 1)
     170          22 :                                 sctx->pending = 1;
     171             :                 }
     172         965 :                 talloc_free(ares);
     173         965 :                 return ldb_request_done(req, LDB_SUCCESS);
     174             :         }
     175             : 
     176        8206 :         talloc_free(ares);
     177        8206 :         if (ret != LDB_SUCCESS) {
     178           0 :                 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
     179             :         }
     180             : 
     181        7592 :         return LDB_SUCCESS;
     182             : }
     183             : 
     184         961 : 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             :         struct ldb_request *req;
     191             :         struct search_context *sctx;
     192             :         int ret;
     193             : 
     194         961 :         req = NULL;
     195             :         
     196         961 :         sctx = talloc_zero(ldb, struct search_context);
     197         961 :         if (!sctx) return LDB_ERR_OPERATIONS_ERROR;
     198             : 
     199         961 :         sctx->ldb = ldb;
     200         961 :         sctx->sort = options->sorted;
     201         961 :         sctx->req_ctrls = ldb_parse_control_strings(ldb, sctx, (const char **)options->controls);
     202         961 :         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         961 : again:
     208             :         /* free any previous requests */
     209         983 :         if (req) talloc_free(req);
     210             : 
     211         983 :         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         983 :         if (ret != LDB_SUCCESS) {
     218           6 :                 talloc_free(sctx);
     219           9 :                 printf("allocating request failed: %s\n", ldb_errstring(ldb));
     220           6 :                 return ret;
     221             :         }
     222             : 
     223         977 :         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             :                 struct ldb_control *ctrl;
     231         393 :                 struct ldb_search_options_control *search_options = NULL;
     232             : 
     233         393 :                 ctrl = ldb_request_get_control(req, LDB_CONTROL_SEARCH_OPTIONS_OID);
     234         393 :                 if (ctrl) {
     235          22 :                         search_options = talloc_get_type(ctrl->data, struct ldb_search_options_control);
     236             :                 }
     237             : 
     238         415 :                 if (ctrl == NULL || search_options == NULL ||
     239          22 :                     !(search_options->search_options & LDB_SEARCH_OPTION_PHANTOM_ROOT)) {
     240         371 :                         struct ldb_dn *base = ldb_get_default_basedn(ldb);
     241         371 :                         if (base != NULL) {
     242         241 :                                 req->op.search.base = base;
     243             :                         }
     244             :                 }
     245             :         }
     246             : 
     247         977 :         sctx->pending = 0;
     248             : 
     249         977 :         ret = ldb_request(ldb, req);
     250         977 :         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         977 :         ret = ldb_wait(req->handle, LDB_WAIT_ALL);
     258         977 :         if (ret != LDB_SUCCESS) {
     259          12 :                 talloc_free(sctx);
     260          12 :                 talloc_free(req);
     261          22 :                 printf("search error - %s\n", ldb_errstring(ldb));
     262          12 :                 return ret;
     263             :         }
     264             : 
     265         965 :         if (sctx->pending)
     266          22 :                 goto again;
     267             : 
     268         943 :         if (sctx->sort && (sctx->num_stored != 0 || sctx->refs != 0)) {
     269             :                 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         665 :                 for (i = 0; i < sctx->num_stored; i++) {
     275         626 :                         display_message(sctx->store[i], sctx);
     276             :                 }
     277             : 
     278         129 :                 for (i = 0; i < sctx->refs_stored; i++) {
     279         111 :                         display_referral(sctx->refs_store[i], sctx);
     280             :                 }
     281             :         }
     282             : 
     283        1781 :         printf("# returned %u records\n# %u entries\n# %u referrals\n",
     284         846 :                 sctx->entries + sctx->refs, sctx->entries, sctx->refs);
     285             : 
     286         943 :         talloc_free(sctx);
     287         943 :         talloc_free(req);
     288             : 
     289         943 :         return LDB_SUCCESS;
     290             : }
     291             : 
     292         991 : int main(int argc, const char **argv)
     293             : {
     294             :         struct ldb_context *ldb;
     295         991 :         struct ldb_dn *basedn = NULL;
     296         991 :         const char * const * attrs = NULL;
     297             :         struct ldb_cmdline *options;
     298         991 :         int ret = -1;
     299         991 :         const char *expression = "(|(objectClass=*)(distinguishedName=*))";
     300         991 :         TALLOC_CTX *mem_ctx = talloc_new(NULL);
     301             : 
     302         991 :         ldb = ldb_init(mem_ctx, NULL);
     303         991 :         if (ldb == NULL) {
     304           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     305             :         }
     306             : 
     307         991 :         options = ldb_cmdline_process_search(ldb, argc, argv, usage);
     308             : 
     309             :         /* the check for '=' is for compatibility with ldapsearch */
     310        1817 :         if (!options->interactive &&
     311        1707 :             options->argc > 0 && 
     312         831 :             strpbrk(options->argv[0], "=<>~:")) {
     313         687 :                 expression = options->argv[0];
     314         687 :                 options->argv++;
     315         687 :                 options->argc--;
     316             :         }
     317             : 
     318         961 :         if (options->argc > 0) {
     319         404 :                 attrs = (const char * const *)(options->argv);
     320             :         }
     321             : 
     322         961 :         if (options->basedn != NULL) {
     323         584 :                 basedn = ldb_dn_new(ldb, ldb, options->basedn);
     324         584 :                 if (basedn == NULL) {
     325           0 :                         talloc_free(mem_ctx);
     326           0 :                         return LDB_ERR_OPERATIONS_ERROR;
     327             :                 }
     328             :         }
     329             : 
     330         961 :         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         961 :                 ret = do_search(ldb, basedn, options, expression, attrs);
     337             :         }
     338             : 
     339         961 :         talloc_free(mem_ctx);
     340             : 
     341         961 :         return ret;
     342             : }

Generated by: LCOV version 1.13