2004-03-31 06:45:39 +00:00
/*
ldb database library
Copyright ( C ) Andrew Tridgell 2004
* * NOTE ! The following LGPL license applies to the ldb
* * library . This does NOT imply that all of Samba is released
* * under the LGPL
This library is free software ; you can redistribute it and / or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation ; either
2007-07-10 02:46:15 +00:00
version 3 of the License , or ( at your option ) any later version .
2004-03-31 06:45:39 +00:00
This library is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
Lesser General Public License for more details .
You should have received a copy of the GNU Lesser General Public
2007-07-10 03:42:26 +00:00
License along with this library ; if not , see < http : //www.gnu.org/licenses/>.
2004-03-31 06:45:39 +00:00
*/
/*
* Name : ldb
*
* Component : ldbsearch
*
* Description : utility for ldb search - modelled on ldapsearch
*
* Author : Andrew Tridgell
*/
2010-11-01 23:36:42 +11:00
# include "replace.h"
# include "system/filesys.h"
# include "system/time.h"
2009-01-29 18:39:30 -05:00
# include "ldb.h"
2007-05-05 18:50:56 +00:00
# include "tools/cmdline.h"
2004-04-10 20:18:22 +00:00
2010-11-01 18:45:25 +11:00
static void usage ( struct ldb_context * ldb )
2004-04-10 20:18:22 +00:00
{
printf ( " Usage: ldbsearch <options> <expression> <attrs...> \n " ) ;
2010-11-01 18:45:25 +11:00
ldb_cmdline_help ( ldb , " ldbsearch " , stdout ) ;
2011-02-01 20:34:44 +01:00
exit ( LDB_ERR_OPERATIONS_ERROR ) ;
2004-04-10 20:18:22 +00:00
}
2004-03-31 06:45:39 +00:00
2005-06-09 14:50:32 +00:00
static int do_compare_msg ( struct ldb_message * * el1 ,
2006-01-06 04:01:23 +00:00
struct ldb_message * * el2 ,
void * opaque )
2005-06-09 14:50:32 +00:00
{
2006-11-22 00:59:34 +00:00
return ldb_dn_compare ( ( * el1 ) - > dn , ( * el2 ) - > dn ) ;
2005-06-09 14:50:32 +00:00
}
2006-07-22 16:56:33 +00:00
struct search_context {
2008-09-12 13:27:15 -04:00
struct ldb_context * ldb ;
2006-05-23 23:52:05 +00:00
struct ldb_control * * req_ctrls ;
int sort ;
2009-11-06 18:35:17 +01:00
unsigned int num_stored ;
2006-05-23 23:52:05 +00:00
struct ldb_message * * store ;
2009-11-06 18:35:17 +01:00
unsigned int refs_stored ;
2006-05-23 23:52:05 +00:00
char * * refs_store ;
2009-11-06 18:35:17 +01:00
unsigned int entries ;
unsigned int refs ;
2006-05-23 23:52:05 +00:00
2009-11-06 18:35:17 +01:00
unsigned int pending ;
2006-05-23 23:52:05 +00:00
int status ;
} ;
2006-07-22 16:56:33 +00:00
static int store_message ( struct ldb_message * msg , struct search_context * sctx ) {
2006-05-23 23:52:05 +00:00
2006-07-22 16:56:33 +00:00
sctx - > store = talloc_realloc ( sctx , sctx - > store , struct ldb_message * , sctx - > num_stored + 2 ) ;
if ( ! sctx - > store ) {
2006-05-23 23:52:05 +00:00
fprintf ( stderr , " talloc_realloc failed while storing messages \n " ) ;
return - 1 ;
}
2006-09-13 02:33:51 +00:00
sctx - > store [ sctx - > num_stored ] = talloc_move ( sctx - > store , & msg ) ;
2006-07-22 16:56:33 +00:00
sctx - > num_stored + + ;
sctx - > store [ sctx - > num_stored ] = NULL ;
2006-05-23 23:52:05 +00:00
return 0 ;
}
2006-07-22 16:56:33 +00:00
static int store_referral ( char * referral , struct search_context * sctx ) {
2006-05-23 23:52:05 +00:00
2008-01-11 13:15:49 +11:00
sctx - > refs_store = talloc_realloc ( sctx , sctx - > refs_store , char * , sctx - > refs_stored + 2 ) ;
2006-07-22 16:56:33 +00:00
if ( ! sctx - > refs_store ) {
2006-05-23 23:52:05 +00:00
fprintf ( stderr , " talloc_realloc failed while storing referrals \n " ) ;
return - 1 ;
}
2008-01-11 13:15:49 +11:00
sctx - > refs_store [ sctx - > refs_stored ] = talloc_move ( sctx - > refs_store , & referral ) ;
sctx - > refs_stored + + ;
sctx - > refs_store [ sctx - > refs_stored ] = NULL ;
2006-05-23 23:52:05 +00:00
return 0 ;
}
2008-09-12 13:27:15 -04:00
static int display_message ( struct ldb_message * msg , struct search_context * sctx ) {
2006-05-23 23:52:05 +00:00
struct ldb_ldif ldif ;
2006-07-22 16:56:33 +00:00
sctx - > entries + + ;
printf ( " # record %d \n " , sctx - > entries ) ;
2006-05-23 23:52:05 +00:00
ldif . changetype = LDB_CHANGETYPE_NONE ;
ldif . msg = msg ;
2006-07-22 16:56:33 +00:00
if ( sctx - > sort ) {
2006-05-23 23:52:05 +00:00
/*
* Ensure attributes are always returned in the same
* order . For testing , this makes comparison of old
* vs . new much easier .
*/
ldb_msg_sort_elements ( ldif . msg ) ;
}
2008-09-12 13:27:15 -04:00
ldb_ldif_write_file ( sctx - > ldb , stdout , & ldif ) ;
2006-05-23 23:52:05 +00:00
return 0 ;
}
2006-08-19 20:44:41 +00:00
static int display_referral ( char * referral , struct search_context * sctx )
{
2006-05-23 23:52:05 +00:00
2006-07-22 16:56:33 +00:00
sctx - > refs + + ;
2006-05-23 23:52:05 +00:00
printf ( " # Referral \n ref: %s \n \n " , referral ) ;
return 0 ;
}
2008-09-12 13:27:15 -04:00
static int search_callback ( struct ldb_request * req , struct ldb_reply * ares )
2006-05-23 23:52:05 +00:00
{
2008-09-12 13:27:15 -04:00
struct search_context * sctx ;
2011-01-08 22:08:40 +01:00
int ret = LDB_SUCCESS ;
2008-09-12 13:27:15 -04:00
sctx = talloc_get_type ( req - > context , struct search_context ) ;
if ( ! ares ) {
return ldb_request_done ( req , LDB_ERR_OPERATIONS_ERROR ) ;
}
if ( ares - > error ! = LDB_SUCCESS ) {
return ldb_request_done ( req , ares - > error ) ;
}
2006-05-23 23:52:05 +00:00
switch ( ares - > type ) {
case LDB_REPLY_ENTRY :
2006-07-22 16:56:33 +00:00
if ( sctx - > sort ) {
ret = store_message ( ares - > message , sctx ) ;
2006-05-23 23:52:05 +00:00
} else {
2008-09-12 13:27:15 -04:00
ret = display_message ( ares - > message , sctx ) ;
2006-05-23 23:52:05 +00:00
}
break ;
case LDB_REPLY_REFERRAL :
2006-07-22 16:56:33 +00:00
if ( sctx - > sort ) {
ret = store_referral ( ares - > referral , sctx ) ;
2006-05-23 23:52:05 +00:00
} else {
2006-07-22 16:56:33 +00:00
ret = display_referral ( ares - > referral , sctx ) ;
2006-05-23 23:52:05 +00:00
}
2008-09-12 13:27:15 -04:00
if ( ret ) {
return ldb_request_done ( req , LDB_ERR_OPERATIONS_ERROR ) ;
}
2006-05-23 23:52:05 +00:00
break ;
case LDB_REPLY_DONE :
if ( ares - > controls ) {
2006-07-22 16:56:33 +00:00
if ( handle_controls_reply ( ares - > controls , sctx - > req_ctrls ) = = 1 )
sctx - > pending = 1 ;
2006-05-23 23:52:05 +00:00
}
2008-09-12 13:27:15 -04:00
talloc_free ( ares ) ;
return ldb_request_done ( req , LDB_SUCCESS ) ;
2006-05-23 23:52:05 +00:00
}
2008-09-12 13:27:15 -04:00
talloc_free ( ares ) ;
2011-01-08 22:08:40 +01:00
if ( ret ! = LDB_SUCCESS ) {
2008-09-12 13:27:15 -04:00
return ldb_request_done ( req , LDB_ERR_OPERATIONS_ERROR ) ;
2006-05-23 23:52:05 +00:00
}
return LDB_SUCCESS ;
}
2004-05-06 04:40:15 +00:00
static int do_search ( struct ldb_context * ldb ,
2006-11-22 00:59:34 +00:00
struct ldb_dn * basedn ,
2006-01-06 19:42:08 +00:00
struct ldb_cmdline * options ,
2004-05-06 04:40:15 +00:00
const char * expression ,
2004-05-07 23:54:41 +00:00
const char * const * attrs )
2004-05-03 14:51:26 +00:00
{
2006-03-08 01:01:14 +00:00
struct ldb_request * req ;
2006-07-22 16:56:33 +00:00
struct search_context * sctx ;
2006-05-23 23:52:05 +00:00
int ret ;
2004-05-03 14:51:26 +00:00
2008-09-12 13:27:15 -04:00
req = NULL ;
2006-05-23 23:52:05 +00:00
2010-02-25 11:46:41 +11:00
sctx = talloc_zero ( ldb , struct search_context ) ;
2011-02-01 20:48:52 +01:00
if ( ! sctx ) return LDB_ERR_OPERATIONS_ERROR ;
2006-05-23 23:52:05 +00:00
2008-09-12 13:27:15 -04:00
sctx - > ldb = ldb ;
2006-07-22 16:56:33 +00:00
sctx - > sort = options - > sorted ;
2007-02-22 01:54:40 +00:00
sctx - > req_ctrls = ldb_parse_control_strings ( ldb , sctx , ( const char * * ) options - > controls ) ;
if ( options - > controls ! = NULL & & sctx - > req_ctrls = = NULL ) {
printf ( " parsing controls failed: %s \n " , ldb_errstring ( ldb ) ) ;
2011-02-01 20:48:52 +01:00
return LDB_ERR_OPERATIONS_ERROR ;
2007-02-22 01:54:40 +00:00
}
2006-05-23 23:52:05 +00:00
again :
2008-09-12 13:27:15 -04:00
/* free any previous requests */
if ( req ) talloc_free ( req ) ;
ret = ldb_build_search_req ( & req , ldb , ldb ,
basedn , options - > scope ,
expression , attrs ,
sctx - > req_ctrls ,
sctx , search_callback ,
NULL ) ;
if ( ret ! = LDB_SUCCESS ) {
talloc_free ( sctx ) ;
printf ( " allocating request failed: %s \n " , ldb_errstring ( ldb ) ) ;
2011-02-01 20:48:52 +01:00
return ret ;
2008-09-12 13:27:15 -04:00
}
2011-08-31 16:17:54 +10:00
if ( basedn = = NULL ) {
/*
we need to use a NULL base DN when doing a cross - ncs
search so we find results on all partitions in a
forest . When doing a domain - local search , default to
the default basedn
*/
struct ldb_control * ctrl ;
struct ldb_search_options_control * search_options = NULL ;
ctrl = ldb_request_get_control ( req , LDB_CONTROL_SEARCH_OPTIONS_OID ) ;
if ( ctrl ) {
search_options = talloc_get_type ( ctrl - > data , struct ldb_search_options_control ) ;
}
if ( ctrl = = NULL | | search_options = = NULL | |
! ( search_options - > search_options & LDB_SEARCH_OPTION_PHANTOM_ROOT ) ) {
struct ldb_dn * base = ldb_get_default_basedn ( ldb ) ;
if ( base ! = NULL ) {
req - > op . search . base = base ;
}
}
}
2006-07-22 16:56:33 +00:00
sctx - > pending = 0 ;
2004-05-03 14:51:26 +00:00
2006-05-23 23:52:05 +00:00
ret = ldb_request ( ldb , req ) ;
if ( ret ! = LDB_SUCCESS ) {
2018-07-16 11:43:22 +02:00
talloc_free ( sctx ) ;
talloc_free ( req ) ;
2006-05-23 23:52:05 +00:00
printf ( " search failed - %s \n " , ldb_errstring ( ldb ) ) ;
2011-02-01 20:48:52 +01:00
return ret ;
2006-05-23 23:52:05 +00:00
}
2004-05-03 14:51:26 +00:00
2006-07-22 17:21:59 +00:00
ret = ldb_wait ( req - > handle , LDB_WAIT_ALL ) ;
2011-02-01 20:48:52 +01:00
if ( ret ! = LDB_SUCCESS ) {
2018-07-16 11:43:22 +02:00
talloc_free ( sctx ) ;
talloc_free ( req ) ;
2006-05-23 23:52:05 +00:00
printf ( " search error - %s \n " , ldb_errstring ( ldb ) ) ;
2011-02-01 20:48:52 +01:00
return ret ;
2006-05-23 23:52:05 +00:00
}
2005-06-09 14:50:32 +00:00
2006-07-22 16:56:33 +00:00
if ( sctx - > pending )
2006-05-23 23:52:05 +00:00
goto again ;
2004-05-03 14:51:26 +00:00
2008-01-11 12:47:51 +11:00
if ( sctx - > sort & & ( sctx - > num_stored ! = 0 | | sctx - > refs ! = 0 ) ) {
2009-11-06 18:35:17 +01:00
unsigned int i ;
2006-01-10 17:19:32 +00:00
2008-01-11 13:15:49 +11:00
if ( sctx - > num_stored ) {
2010-02-13 13:26:51 +11:00
LDB_TYPESAFE_QSORT ( sctx - > store , sctx - > num_stored , ldb , do_compare_msg ) ;
2006-02-22 01:31:35 +00:00
}
2006-07-22 16:56:33 +00:00
for ( i = 0 ; i < sctx - > num_stored ; i + + ) {
2008-09-12 13:27:15 -04:00
display_message ( sctx - > store [ i ] , sctx ) ;
2006-01-10 17:19:32 +00:00
}
2008-01-11 13:15:49 +11:00
for ( i = 0 ; i < sctx - > refs_stored ; i + + ) {
2006-07-22 16:56:33 +00:00
display_referral ( sctx - > refs_store [ i ] , sctx ) ;
2006-01-10 17:19:32 +00:00
}
2006-05-23 23:52:05 +00:00
}
2006-01-10 17:19:32 +00:00
2011-02-01 20:51:26 +01:00
printf ( " # returned %u records \n # %u entries \n # %u referrals \n " ,
2006-07-22 16:56:33 +00:00
sctx - > entries + sctx - > refs , sctx - > entries , sctx - > refs ) ;
2004-05-06 04:40:15 +00:00
2008-09-12 13:27:15 -04:00
talloc_free ( sctx ) ;
2006-05-23 23:52:05 +00:00
talloc_free ( req ) ;
2006-02-22 01:31:35 +00:00
2011-02-01 20:48:52 +01:00
return LDB_SUCCESS ;
2004-05-03 14:51:26 +00:00
}
2006-03-02 16:32:53 +00:00
int main ( int argc , const char * * argv )
2004-03-31 06:45:39 +00:00
{
2004-04-10 20:18:22 +00:00
struct ldb_context * ldb ;
2005-08-18 15:02:01 +00:00
struct ldb_dn * basedn = NULL ;
2004-05-07 23:54:41 +00:00
const char * const * attrs = NULL ;
2005-06-18 07:42:21 +00:00
struct ldb_cmdline * options ;
2005-06-18 09:01:09 +00:00
int ret = - 1 ;
2006-01-11 15:03:20 +00:00
const char * expression = " (|(objectClass=*)(distinguishedName=*)) " ;
2010-05-02 15:53:14 +02:00
TALLOC_CTX * mem_ctx = talloc_new ( NULL ) ;
2005-06-04 17:13:43 +00:00
2010-05-02 15:53:14 +02:00
ldb = ldb_init ( mem_ctx , NULL ) ;
2008-06-14 11:24:17 -04:00
if ( ldb = = NULL ) {
2011-02-01 20:26:12 +01:00
return LDB_ERR_OPERATIONS_ERROR ;
2008-06-14 11:24:17 -04:00
}
2004-03-31 06:45:39 +00:00
2017-01-19 04:29:13 +01:00
options = ldb_cmdline_process_search ( ldb , argc , argv , usage ) ;
2005-06-22 03:10:40 +00:00
/* the check for '=' is for compatibility with ldapsearch */
if ( ! options - > interactive & &
options - > argc > 0 & &
2012-05-04 11:59:22 +02:00
strpbrk ( options - > argv [ 0 ] , " =<>~: " ) ) {
2005-06-22 03:10:40 +00:00
expression = options - > argv [ 0 ] ;
options - > argv + + ;
options - > argc - - ;
2004-03-31 06:45:39 +00:00
}
2005-06-22 03:10:40 +00:00
if ( options - > argc > 0 ) {
attrs = ( const char * const * ) ( options - > argv ) ;
2004-03-31 06:45:39 +00:00
}
2005-08-18 15:02:01 +00:00
if ( options - > basedn ! = NULL ) {
2006-11-22 00:59:34 +00:00
basedn = ldb_dn_new ( ldb , ldb , options - > basedn ) ;
2011-03-04 10:49:47 +01:00
if ( basedn = = NULL ) {
2018-07-16 11:43:22 +02:00
talloc_free ( mem_ctx ) ;
2011-03-04 10:49:47 +01:00
return LDB_ERR_OPERATIONS_ERROR ;
2005-08-18 15:02:01 +00:00
}
}
2005-06-18 07:42:21 +00:00
if ( options - > interactive ) {
2004-05-03 14:51:26 +00:00
char line [ 1024 ] ;
while ( fgets ( line , sizeof ( line ) , stdin ) ) {
2011-02-01 20:40:27 +01:00
ret = do_search ( ldb , basedn , options , line , attrs ) ;
2004-03-31 06:45:39 +00:00
}
2004-05-03 14:51:26 +00:00
} else {
2006-01-06 19:42:08 +00:00
ret = do_search ( ldb , basedn , options , expression , attrs ) ;
2004-03-31 06:45:39 +00:00
}
2010-05-02 15:53:14 +02:00
talloc_free ( mem_ctx ) ;
2004-05-06 04:40:15 +00:00
return ret ;
2004-03-31 06:45:39 +00:00
}