2001-07-06 14:49:34 +04:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
2001-07-06 14:49:34 +04:00
Network neighbourhood browser .
Copyright ( C ) Tim Potter 2000
2003-04-14 07:30:20 +04:00
Copyright ( C ) Jelmer Vernooij 2003
2001-07-06 14:49:34 +04:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
2001-07-06 14:49:34 +04:00
( at your option ) any later version .
This program 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 General Public License for more details .
You should have received a copy of the GNU General Public License
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2001-07-06 14:49:34 +04:00
*/
# include "includes.h"
2010-08-05 12:49:53 +04:00
# include "popt_common.h"
2011-02-28 12:19:44 +03:00
# include "rpc_client/cli_pipe.h"
2011-01-12 15:01:57 +03:00
# include "../librpc/gen_ndr/ndr_srvsvc_c.h"
2011-05-06 13:47:43 +04:00
# include "libsmb/libsmb.h"
2011-02-24 12:46:55 +03:00
# include "libsmb/clirap.h"
2001-07-06 14:49:34 +04:00
2007-10-19 22:38:36 +04:00
static int use_bcast ;
2001-08-20 21:38:37 +04:00
2001-07-06 14:49:34 +04:00
/* How low can we go? */
enum tree_level { LEV_WORKGROUP , LEV_SERVER , LEV_SHARE } ;
2002-08-17 18:45:04 +04:00
static enum tree_level level = LEV_SHARE ;
2001-07-06 14:49:34 +04:00
/* Holds a list of workgroups or servers */
2008-11-26 02:53:56 +03:00
struct smb_name_list {
struct smb_name_list * prev , * next ;
2007-12-04 05:48:41 +03:00
char * name , * comment ;
2001-07-06 14:49:34 +04:00
uint32 server_type ;
} ;
2008-11-26 02:53:56 +03:00
static struct smb_name_list * workgroups , * servers , * shares ;
2001-07-06 14:49:34 +04:00
2008-11-26 02:53:56 +03:00
static void free_name_list ( struct smb_name_list * list )
2001-07-06 14:49:34 +04:00
{
while ( list )
DLIST_REMOVE ( list , list ) ;
}
static void add_name ( const char * machine_name , uint32 server_type ,
const char * comment , void * state )
{
2008-11-26 02:53:56 +03:00
struct smb_name_list * * name_list = ( struct smb_name_list * * ) state ;
struct smb_name_list * new_name ;
2001-07-06 14:49:34 +04:00
2008-11-26 02:53:56 +03:00
new_name = SMB_MALLOC_P ( struct smb_name_list ) ;
2001-07-06 14:49:34 +04:00
if ( ! new_name )
return ;
ZERO_STRUCTP ( new_name ) ;
2007-12-04 05:48:41 +03:00
new_name - > name = SMB_STRDUP ( machine_name ) ;
new_name - > comment = SMB_STRDUP ( comment ) ;
2001-07-06 14:49:34 +04:00
new_name - > server_type = server_type ;
2007-12-04 05:48:41 +03:00
if ( ! new_name - > name | | ! new_name - > comment ) {
SAFE_FREE ( new_name - > name ) ;
SAFE_FREE ( new_name - > comment ) ;
SAFE_FREE ( new_name ) ;
return ;
}
2001-07-06 14:49:34 +04:00
DLIST_ADD ( * name_list , new_name ) ;
}
/****************************************************************************
display tree of smb workgroups , servers and shares
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
static bool get_workgroups ( struct user_auth_info * user_info )
2001-07-06 14:49:34 +04:00
{
struct cli_state * cli ;
2007-10-26 05:11:29 +04:00
struct sockaddr_storage server_ss ;
2007-11-30 00:24:54 +03:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
char * master_workgroup = NULL ;
2001-07-06 14:49:34 +04:00
/* Try to connect to a #1d name of our current workgroup. If that
doesn ' t work broadcast for a master browser and then jump off
that workgroup . */
2007-11-30 00:24:54 +03:00
master_workgroup = talloc_strdup ( ctx , lp_workgroup ( ) ) ;
if ( ! master_workgroup ) {
return false ;
}
2001-07-06 14:49:34 +04:00
2011-07-22 14:48:09 +04:00
if ( ! use_bcast & & ! find_master_ip ( lp_workgroup ( ) , & server_ss ) ) {
DEBUG ( 4 , ( " Unable to find master browser for workgroup %s, "
" falling back to broadcast \n " ,
master_workgroup ) ) ;
use_bcast = true ;
}
if ( ! use_bcast ) {
char addr [ INET6_ADDRSTRLEN ] ;
print_sockaddr ( addr , sizeof ( addr ) , & server_ss ) ;
2007-10-26 05:11:29 +04:00
2011-07-22 14:48:09 +04:00
cli = get_ipc_connect ( addr , & server_ss , user_info ) ;
if ( cli = = NULL ) {
return false ;
}
} else {
cli = get_ipc_connect_master_ip_bcast ( talloc_tos ( ) ,
user_info ,
& master_workgroup ) ;
if ( cli = = NULL ) {
2001-07-06 14:49:34 +04:00
DEBUG ( 4 , ( " Unable to find master browser by "
" broadcast \n " ) ) ;
2011-07-22 14:48:09 +04:00
return false ;
}
}
2001-07-06 14:49:34 +04:00
2007-10-26 05:11:29 +04:00
if ( ! cli_NetServerEnum ( cli , master_workgroup ,
2001-07-06 14:49:34 +04:00
SV_TYPE_DOMAIN_ENUM , add_name , & workgroups ) )
return False ;
return True ;
}
/* Retrieve the list of servers for a given workgroup */
2007-10-19 04:40:25 +04:00
static bool get_servers ( char * workgroup , struct user_auth_info * user_info )
2001-07-06 14:49:34 +04:00
{
struct cli_state * cli ;
2007-10-26 05:11:29 +04:00
struct sockaddr_storage server_ss ;
char addr [ INET6_ADDRSTRLEN ] ;
2001-07-06 14:49:34 +04:00
/* Open an IPC$ connection to the master browser for the workgroup */
2007-10-26 05:11:29 +04:00
if ( ! find_master_ip ( workgroup , & server_ss ) ) {
2001-07-06 14:49:34 +04:00
DEBUG ( 4 , ( " Cannot find master browser for workgroup %s \n " ,
workgroup ) ) ;
return False ;
}
2007-10-26 05:11:29 +04:00
print_sockaddr ( addr , sizeof ( addr ) , & server_ss ) ;
if ( ! ( cli = get_ipc_connect ( addr , & server_ss , user_info ) ) )
2001-07-06 14:49:34 +04:00
return False ;
2007-10-26 05:11:29 +04:00
if ( ! cli_NetServerEnum ( cli , workgroup , SV_TYPE_ALL , add_name ,
2001-07-06 14:49:34 +04:00
& servers ) )
return False ;
return True ;
}
2007-10-26 05:11:29 +04:00
static bool get_rpc_shares ( struct cli_state * cli ,
2006-05-16 05:21:16 +04:00
void ( * fn ) ( const char * , uint32 , const char * , void * ) ,
void * state )
{
NTSTATUS status ;
2009-11-13 00:56:33 +03:00
struct rpc_pipe_client * pipe_hnd = NULL ;
2006-05-16 05:21:16 +04:00
TALLOC_CTX * mem_ctx ;
2007-10-11 00:34:30 +04:00
WERROR werr ;
2008-03-10 07:05:37 +03:00
struct srvsvc_NetShareInfoCtr info_ctr ;
struct srvsvc_NetShareCtr1 ctr1 ;
2006-05-16 05:21:16 +04:00
int i ;
2008-03-10 07:05:37 +03:00
uint32_t resume_handle = 0 ;
uint32_t total_entries = 0 ;
2011-01-12 15:01:57 +03:00
struct dcerpc_binding_handle * b ;
2006-05-16 05:21:16 +04:00
mem_ctx = talloc_new ( NULL ) ;
if ( mem_ctx = = NULL ) {
DEBUG ( 0 , ( " talloc_new failed \n " ) ) ;
return False ;
}
2008-07-20 13:04:31 +04:00
status = cli_rpc_pipe_open_noauth ( cli , & ndr_table_srvsvc . syntax_id ,
& pipe_hnd ) ;
2006-05-16 05:21:16 +04:00
2008-07-20 13:04:31 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2006-05-16 05:21:16 +04:00
DEBUG ( 10 , ( " Could not connect to srvsvc pipe: %s \n " ,
nt_errstr ( status ) ) ) ;
TALLOC_FREE ( mem_ctx ) ;
return False ;
}
2011-01-12 15:01:57 +03:00
b = pipe_hnd - > binding_handle ;
2008-03-10 07:05:37 +03:00
ZERO_STRUCT ( info_ctr ) ;
ZERO_STRUCT ( ctr1 ) ;
info_ctr . level = 1 ;
info_ctr . ctr . ctr1 = & ctr1 ;
2011-01-12 15:01:57 +03:00
status = dcerpc_srvsvc_NetShareEnumAll ( b , mem_ctx ,
2008-04-19 23:56:43 +04:00
pipe_hnd - > desthost ,
2008-03-10 07:05:37 +03:00
& info_ctr ,
0xffffffff ,
& total_entries ,
& resume_handle ,
& werr ) ;
2006-05-16 05:21:16 +04:00
2008-03-10 07:05:37 +03:00
if ( ! NT_STATUS_IS_OK ( status ) | | ! W_ERROR_IS_OK ( werr ) ) {
2006-05-16 05:21:16 +04:00
TALLOC_FREE ( mem_ctx ) ;
2008-04-20 15:51:46 +04:00
TALLOC_FREE ( pipe_hnd ) ;
2006-05-16 05:21:16 +04:00
return False ;
}
2008-03-10 07:05:37 +03:00
for ( i = 0 ; i < total_entries ; i + + ) {
struct srvsvc_NetShareInfo1 info = info_ctr . ctr . ctr1 - > array [ i ] ;
fn ( info . name , info . type , info . comment , state ) ;
2006-05-16 05:21:16 +04:00
}
TALLOC_FREE ( mem_ctx ) ;
2008-04-20 15:51:46 +04:00
TALLOC_FREE ( pipe_hnd ) ;
2006-05-16 05:21:16 +04:00
return True ;
}
2007-10-19 04:40:25 +04:00
static bool get_shares ( char * server_name , struct user_auth_info * user_info )
2001-07-06 14:49:34 +04:00
{
struct cli_state * cli ;
2002-07-15 14:35:28 +04:00
if ( ! ( cli = get_ipc_connect ( server_name , NULL , user_info ) ) )
2001-07-06 14:49:34 +04:00
return False ;
2006-05-16 05:21:16 +04:00
if ( get_rpc_shares ( cli , add_name , & shares ) )
return True ;
2007-12-04 05:48:41 +03:00
2001-07-06 14:49:34 +04:00
if ( ! cli_RNetShareEnum ( cli , add_name , & shares ) )
return False ;
return True ;
}
2007-10-19 04:40:25 +04:00
static bool print_tree ( struct user_auth_info * user_info )
2001-07-06 14:49:34 +04:00
{
2008-11-26 02:53:56 +03:00
struct smb_name_list * wg , * sv , * sh ;
2001-07-06 14:49:34 +04:00
/* List workgroups */
if ( ! get_workgroups ( user_info ) )
return False ;
for ( wg = workgroups ; wg ; wg = wg - > next ) {
printf ( " %s \n " , wg - > name ) ;
/* List servers */
free_name_list ( servers ) ;
servers = NULL ;
if ( level = = LEV_WORKGROUP | |
! get_servers ( wg - > name , user_info ) )
continue ;
for ( sv = servers ; sv ; sv = sv - > next ) {
2001-07-25 08:09:44 +04:00
printf ( " \t \\ \\ %-15s \t \t %s \n " ,
sv - > name , sv - > comment ) ;
2001-07-06 14:49:34 +04:00
/* List shares */
free_name_list ( shares ) ;
shares = NULL ;
if ( level = = LEV_SERVER | |
! get_shares ( sv - > name , user_info ) )
continue ;
for ( sh = shares ; sh ; sh = sh - > next ) {
2001-07-25 08:09:44 +04:00
printf ( " \t \t \\ \\ %s \\ %-15s \t %s \n " ,
sv - > name , sh - > name , sh - > comment ) ;
2001-07-06 14:49:34 +04:00
}
}
}
return True ;
}
/****************************************************************************
main program
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int main ( int argc , char * argv [ ] )
{
2007-09-04 09:39:06 +04:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2008-12-14 15:06:19 +03:00
struct user_auth_info * auth_info ;
2003-04-14 07:30:20 +04:00
struct poptOption long_options [ ] = {
POPT_AUTOHELP
{ " broadcast " , ' b ' , POPT_ARG_VAL , & use_bcast , True , " Use broadcast instead of using the master browser " } ,
{ " domains " , ' D ' , POPT_ARG_VAL , & level , LEV_WORKGROUP , " List only domains (workgroups) of tree " } ,
{ " servers " , ' S ' , POPT_ARG_VAL , & level , LEV_SERVER , " List domains(workgroups) and servers of tree " } ,
POPT_COMMON_SAMBA
POPT_COMMON_CREDENTIALS
POPT_TABLEEND
} ;
poptContext pc ;
2007-12-04 05:48:41 +03:00
2001-07-06 14:49:34 +04:00
/* Initialise samba stuff */
2005-12-29 01:48:54 +03:00
load_case_tables ( ) ;
2001-07-06 14:49:34 +04:00
setlinebuf ( stdout ) ;
2010-10-29 07:19:32 +04:00
setup_logging ( argv [ 0 ] , DEBUG_STDERR ) ;
2001-07-06 14:49:34 +04:00
2008-12-14 15:06:19 +03:00
auth_info = user_auth_info_init ( frame ) ;
if ( auth_info = = NULL ) {
exit ( 1 ) ;
}
popt_common_set_auth_info ( auth_info ) ;
2007-12-04 05:48:41 +03:00
pc = poptGetContext ( " smbtree " , argc , ( const char * * ) argv , long_options ,
2003-04-14 07:30:20 +04:00
POPT_CONTEXT_KEEP_FIRST ) ;
while ( poptGetNextOpt ( pc ) ! = - 1 ) ;
poptFreeContext ( pc ) ;
2012-11-06 12:27:43 +04:00
popt_burn_cmdline_password ( argc , argv ) ;
2003-04-14 07:30:20 +04:00
2011-07-28 12:28:40 +04:00
lp_load_global ( get_dyn_CONFIGFILE ( ) ) ;
2001-07-06 14:49:34 +04:00
load_interfaces ( ) ;
/* Parse command line args */
2008-12-14 15:06:19 +03:00
if ( get_cmdline_auth_info_use_machine_account ( auth_info ) & &
! set_cmdline_auth_info_machine_account_creds ( auth_info ) ) {
2008-05-05 18:58:24 +04:00
TALLOC_FREE ( frame ) ;
return 1 ;
}
2009-03-18 00:53:06 +03:00
set_cmdline_auth_info_getpass ( auth_info ) ;
2001-07-06 14:49:34 +04:00
/* Now do our stuff */
2008-12-14 15:06:19 +03:00
if ( ! print_tree ( auth_info ) ) {
2007-09-04 09:39:06 +04:00
TALLOC_FREE ( frame ) ;
2001-07-06 14:49:34 +04:00
return 1 ;
2007-09-04 09:39:06 +04:00
}
2001-07-06 14:49:34 +04:00
2007-09-04 09:39:06 +04:00
TALLOC_FREE ( frame ) ;
2001-07-06 14:49:34 +04:00
return 0 ;
}