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
*/
2007-05-05 18:50:56 +00:00
# include "ldb_includes.h"
# include "tools/cmdline.h"
2004-04-10 20:18:22 +00:00
static void usage ( void )
{
printf ( " Usage: ldbsearch <options> <expression> <attrs...> \n " ) ;
printf ( " Options: \n " ) ;
printf ( " -H ldb_url choose the database (or $LDB_URL) \n " ) ;
printf ( " -s base|sub|one choose search scope \n " ) ;
printf ( " -b basedn choose baseDN \n " ) ;
2004-05-03 14:51:26 +00:00
printf ( " -i read search expressions from stdin \n " ) ;
2005-06-04 17:13:43 +00:00
printf ( " -S sort returned attributes \n " ) ;
2004-11-15 14:16:10 +00:00
printf ( " -o options pass options like modules to activate \n " ) ;
printf ( " e.g: -o modules:timestamps \n " ) ;
2004-04-10 20:18:22 +00:00
exit ( 1 ) ;
}
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 {
2006-05-23 23:52:05 +00:00
struct ldb_control * * req_ctrls ;
int sort ;
int num_stored ;
struct ldb_message * * store ;
char * * refs_store ;
int entries ;
int refs ;
int pending ;
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
2006-07-22 16:56:33 +00:00
sctx - > refs_store = talloc_realloc ( sctx , sctx - > refs_store , char * , sctx - > refs + 2 ) ;
if ( ! sctx - > refs_store ) {
2006-05-23 23:52:05 +00:00
fprintf ( stderr , " talloc_realloc failed while storing referrals \n " ) ;
return - 1 ;
}
2006-09-13 02:33:51 +00:00
sctx - > refs_store [ sctx - > refs ] = talloc_move ( sctx - > refs_store , & referral ) ;
2006-07-22 16:56:33 +00:00
sctx - > refs + + ;
sctx - > refs_store [ sctx - > refs ] = NULL ;
2006-05-23 23:52:05 +00:00
return 0 ;
}
2006-07-22 16:56:33 +00:00
static int display_message ( struct ldb_context * ldb , 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 ) ;
}
ldb_ldif_write_file ( ldb , stdout , & ldif ) ;
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 ;
}
2006-07-22 16:56:33 +00:00
static int search_callback ( struct ldb_context * ldb , void * context , struct ldb_reply * ares )
2006-05-23 23:52:05 +00:00
{
2006-07-22 16:56:33 +00:00
struct search_context * sctx = talloc_get_type ( context , struct search_context ) ;
2006-05-23 23:52:05 +00:00
int ret ;
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 {
2006-07-22 16:56:33 +00:00
ret = display_message ( ldb , 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
}
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
}
ret = 0 ;
break ;
default :
fprintf ( stderr , " unknown Reply Type \n " ) ;
return LDB_ERR_OTHER ;
}
if ( talloc_free ( ares ) = = - 1 ) {
fprintf ( stderr , " talloc_free failed \n " ) ;
2006-07-22 16:56:33 +00:00
sctx - > pending = 0 ;
2006-05-23 23:52:05 +00:00
return LDB_ERR_OPERATIONS_ERROR ;
}
if ( ret ) {
return LDB_ERR_OPERATIONS_ERROR ;
}
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
2006-03-08 01:01:14 +00:00
req = talloc ( ldb , struct ldb_request ) ;
2006-05-23 23:52:05 +00:00
if ( ! req ) return - 1 ;
2006-07-22 16:56:33 +00:00
sctx = talloc ( req , struct search_context ) ;
if ( ! sctx ) return - 1 ;
2006-05-23 23:52:05 +00:00
2006-07-22 16:56:33 +00:00
sctx - > sort = options - > sorted ;
sctx - > num_stored = 0 ;
sctx - > store = NULL ;
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 ) ) ;
return - 1 ;
}
2006-07-22 16:56:33 +00:00
sctx - > entries = 0 ;
sctx - > refs = 0 ;
2006-05-23 23:52:05 +00:00
2006-08-25 06:41:37 +00:00
if ( basedn = = NULL ) {
2006-08-25 12:59:03 +00:00
basedn = ldb_get_default_basedn ( ldb ) ;
2006-08-25 06:41:37 +00:00
}
2006-05-30 00:33:52 +00:00
req - > operation = LDB_SEARCH ;
2006-03-08 01:01:14 +00:00
req - > op . search . base = basedn ;
req - > op . search . scope = options - > scope ;
2006-10-16 12:03:55 +00:00
req - > op . search . tree = ldb_parse_tree ( req , expression ) ;
2006-03-08 01:01:14 +00:00
if ( req - > op . search . tree = = NULL ) return - 1 ;
req - > op . search . attrs = attrs ;
2006-07-22 16:56:33 +00:00
req - > controls = sctx - > req_ctrls ;
2006-07-22 17:21:59 +00:00
req - > context = sctx ;
req - > callback = & search_callback ;
2006-06-04 05:28:13 +00:00
ldb_set_timeout ( ldb , req , 0 ) ; /* TODO: make this settable by command line */
2006-01-06 19:42:08 +00:00
2006-05-23 23:52:05 +00:00
again :
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 ) {
printf ( " search failed - %s \n " , ldb_errstring ( ldb ) ) ;
return - 1 ;
}
2004-05-03 14:51:26 +00:00
2006-07-22 17:21:59 +00:00
ret = ldb_wait ( req - > handle , LDB_WAIT_ALL ) ;
2006-05-23 23:52:05 +00:00
if ( ret ! = LDB_SUCCESS ) {
printf ( " search error - %s \n " , ldb_errstring ( ldb ) ) ;
return - 1 ;
}
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 ) ) {
2006-05-23 23:52:05 +00:00
int i ;
2006-01-10 17:19:32 +00:00
2008-01-11 12:47:51 +11:00
ldb_qsort ( sctx - > store , sctx - > num_stored , sizeof ( struct ldb_message * ) ,
2006-05-23 23:52:05 +00:00
ldb , ( ldb_qsort_cmp_fn_t ) do_compare_msg ) ;
if ( ret ! = 0 ) {
fprintf ( stderr , " An error occurred while sorting messages \n " ) ;
exit ( 1 ) ;
2006-02-22 01:31:35 +00:00
}
2006-05-23 23:52:05 +00:00
2006-07-22 16:56:33 +00:00
for ( i = 0 ; i < sctx - > num_stored ; i + + ) {
display_message ( ldb , sctx - > store [ i ] , sctx ) ;
2006-01-10 17:19:32 +00:00
}
2006-07-22 16:56:33 +00:00
for ( i = 0 ; i < sctx - > refs ; i + + ) {
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
2006-05-23 23:52:05 +00:00
printf ( " # returned %d records \n # %d entries \n # %d 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
2006-05-23 23:52:05 +00:00
talloc_free ( req ) ;
2006-02-22 01:31:35 +00:00
2004-05-06 04:40:15 +00:00
return 0 ;
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=*)) " ;
2005-06-04 17:13:43 +00:00
2006-05-23 23:59:26 +00:00
ldb_global_init ( ) ;
2005-06-18 07:42:21 +00:00
ldb = ldb_init ( NULL ) ;
2004-03-31 06:45:39 +00:00
2005-06-18 07:42:21 +00:00
options = ldb_cmdline_process ( 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 & &
strchr ( options - > argv [ 0 ] , ' = ' ) ) {
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 ) ;
if ( ! ldb_dn_validate ( basedn ) ) {
2005-08-18 15:02:01 +00:00
fprintf ( stderr , " Invalid Base DN format \n " ) ;
exit ( 1 ) ;
}
}
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 ) ) {
2006-01-06 19:42:08 +00:00
if ( do_search ( ldb , basedn , options , line , attrs ) = = - 1 ) {
2004-05-06 04:40:15 +00:00
ret = - 1 ;
}
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
}
2005-02-27 11:35:47 +00:00
talloc_free ( ldb ) ;
2004-05-06 04:40:15 +00:00
return ret ;
2004-03-31 06:45:39 +00:00
}