2001-10-19 20:51:26 +04:00
/*
Samba Unix / Linux SMB client library
Distributed SMB / CIFS Server Management Utility
Copyright ( C ) 2001 Steve French ( sfrench @ us . ibm . com )
Copyright ( C ) 2001 Jim McDonough ( jmcd @ us . ibm . com )
2001-11-24 16:26:01 +03:00
Copyright ( C ) 2001 Andrew Tridgell ( tridge @ samba . org )
2001-12-03 07:39:23 +03:00
Copyright ( C ) 2001 Andrew Bartlett ( abartlet @ samba . org )
2001-10-19 20:51:26 +04:00
2001-11-24 16:26:01 +03:00
Originally written by Steve and Jim . Largely rewritten by tridge in
November 2001.
2001-10-19 20:51:26 +04:00
2001-12-03 07:39:23 +03:00
Reworked again by abartlet in December 2001
2001-10-19 20:51:26 +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
the Free Software Foundation ; either version 2 of the License , or
( 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
along with this program ; if not , write to the Free Software
2001-11-24 16:26:01 +03:00
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA . */
2001-10-19 20:51:26 +04:00
/*****************************************************/
/* */
/* Distributed SMB/CIFS Server Management Utility */
/* */
/* The intent was to make the syntax similar */
/* to the NET utility (first developed in DOS */
/* with additional interesting & useful functions */
/* added in later SMB server network operating */
/* systems). */
/* */
/*****************************************************/
2001-11-25 03:18:11 +03:00
# include "includes.h"
2001-12-03 07:39:23 +03:00
# include "../utils/net.h"
2001-10-19 20:51:26 +04:00
/***********************************************************************/
/* Beginning of internationalization section. Translatable constants */
/* should be kept in this area and referenced in the rest of the code. */
/* */
/* No functions, outside of Samba or LSB (Linux Standards Base) should */
/* be used (if possible). */
/***********************************************************************/
# define YES_STRING "Yes"
# define NO_STRING "No"
/************************************************************************************/
/* end of internationalization section */
/************************************************************************************/
2001-12-03 07:39:23 +03:00
/* Yes, these buggers are globals.... */
char * opt_requester_name = NULL ;
char * opt_host = NULL ;
char * opt_password = NULL ;
char * opt_user_name = NULL ;
2002-01-26 01:07:46 +03:00
BOOL opt_user_specified = False ;
2001-12-03 07:39:23 +03:00
char * opt_workgroup = NULL ;
int opt_long_list_entries = 0 ;
2001-12-31 16:00:59 +03:00
int opt_reboot = 0 ;
int opt_force = 0 ;
2001-12-03 07:39:23 +03:00
int opt_port = 0 ;
int opt_maxusers = - 1 ;
char * opt_comment = " " ;
int opt_flags = - 1 ;
int opt_jobid = 0 ;
2001-12-31 16:00:59 +03:00
int opt_timeout = 0 ;
2001-12-03 07:39:23 +03:00
char * opt_target_workgroup = NULL ;
2001-11-24 16:26:01 +03:00
2001-12-11 08:21:50 +03:00
BOOL opt_have_ip = False ;
struct in_addr opt_dest_ip ;
2001-10-19 20:51:26 +04:00
2001-12-04 07:48:01 +03:00
extern pstring global_myname ;
2001-11-24 16:26:01 +03:00
/*
run a function from a function table . If not found then
call the specified usage function
*/
2001-11-24 17:16:41 +03:00
int net_run_function ( int argc , const char * * argv , struct functable * table ,
2001-11-26 07:53:08 +03:00
int ( * usage_fn ) ( int argc , const char * * argv ) )
2001-10-19 20:51:26 +04:00
{
2001-11-24 16:26:01 +03:00
int i ;
2001-12-03 07:39:23 +03:00
if ( argc < 1 ) {
d_printf ( " \n Usage: \n " ) ;
2001-11-26 07:53:08 +03:00
return usage_fn ( argc , argv ) ;
2001-12-03 07:39:23 +03:00
}
2001-11-24 16:26:01 +03:00
for ( i = 0 ; table [ i ] . funcname ; i + + ) {
2001-11-26 07:53:08 +03:00
if ( StrCaseCmp ( argv [ 0 ] , table [ i ] . funcname ) = = 0 )
2001-11-24 16:26:01 +03:00
return table [ i ] . fn ( argc - 1 , argv + 1 ) ;
}
d_printf ( " No command: %s \n " , argv [ 0 ] ) ;
2001-11-26 07:53:08 +03:00
return usage_fn ( argc , argv ) ;
2001-10-19 20:51:26 +04:00
}
/****************************************************************************
2001-11-24 16:26:01 +03:00
connect to \ \ server \ ipc $
2001-10-19 20:51:26 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-03-01 05:56:35 +03:00
NTSTATUS connect_to_ipc ( struct cli_state * * c , struct in_addr * server_ip ,
const char * server_name )
2001-11-24 16:26:01 +03:00
{
2001-12-03 10:42:18 +03:00
NTSTATUS nt_status ;
2001-11-24 16:26:01 +03:00
2002-04-04 20:53:07 +04:00
if ( ! opt_password ) {
2001-12-03 10:42:18 +03:00
char * pass = getpass ( " Password: " ) ;
2001-11-24 16:26:01 +03:00
if ( pass ) {
opt_password = strdup ( pass ) ;
}
}
2001-10-19 20:51:26 +04:00
2002-03-01 05:56:35 +03:00
nt_status = cli_full_connection ( c , opt_requester_name , server_name ,
2001-12-03 10:42:18 +03:00
server_ip , opt_port ,
" IPC$ " , " IPC " ,
opt_user_name , opt_workgroup ,
opt_password , strlen ( opt_password ) ) ;
2001-11-24 16:26:01 +03:00
2001-12-03 10:42:18 +03:00
if ( NT_STATUS_IS_OK ( nt_status ) ) {
2002-03-01 05:56:35 +03:00
return nt_status ;
2001-12-03 10:42:18 +03:00
} else {
2002-04-04 20:53:07 +04:00
DEBUG ( 1 , ( " Cannot connect to server. Error was %s \n " ,
2002-03-17 07:36:35 +03:00
nt_errstr ( nt_status ) ) ) ;
2001-12-14 06:55:09 +03:00
/* Display a nicer message depending on the result */
if ( NT_STATUS_V ( nt_status ) = =
NT_STATUS_V ( NT_STATUS_LOGON_FAILURE ) )
d_printf ( " The username or password was not correct. \n " ) ;
2002-03-01 05:56:35 +03:00
return nt_status ;
2001-11-24 16:26:01 +03:00
}
}
2001-10-19 20:51:26 +04:00
2001-12-05 06:14:21 +03:00
/****************************************************************************
connect to \ \ server \ ipc $ anonymously
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-03-01 05:56:35 +03:00
NTSTATUS connect_to_ipc_anonymous ( struct cli_state * * c ,
struct in_addr * server_ip , const char * server_name )
2001-12-05 06:14:21 +03:00
{
NTSTATUS nt_status ;
2002-03-01 05:56:35 +03:00
nt_status = cli_full_connection ( c , opt_requester_name , server_name ,
2001-12-05 06:14:21 +03:00
server_ip , opt_port ,
" IPC$ " , " IPC " ,
" " , " " ,
" " , 0 ) ;
if ( NT_STATUS_IS_OK ( nt_status ) ) {
2002-03-01 05:56:35 +03:00
return nt_status ;
2001-12-05 06:14:21 +03:00
} else {
2002-04-04 20:53:07 +04:00
DEBUG ( 1 , ( " Cannot connect to server (anonymously). Error was %s \n " , nt_errstr ( nt_status ) ) ) ;
2002-03-01 05:56:35 +03:00
return nt_status ;
2001-12-05 06:14:21 +03:00
}
}
2002-04-05 05:36:28 +04:00
BOOL net_find_server ( unsigned flags , struct in_addr * server_ip , char * * server_name )
2001-11-24 16:26:01 +03:00
{
2001-12-04 07:48:01 +03:00
if ( opt_host ) {
2001-12-05 05:58:40 +03:00
* server_name = strdup ( opt_host ) ;
2001-12-04 07:48:01 +03:00
}
2001-12-11 08:21:50 +03:00
if ( opt_have_ip ) {
* server_ip = opt_dest_ip ;
2001-12-05 05:58:40 +03:00
if ( ! * server_name ) {
2001-12-11 08:21:50 +03:00
* server_name = strdup ( inet_ntoa ( opt_dest_ip ) ) ;
2001-12-03 07:39:23 +03:00
}
2001-12-05 14:00:26 +03:00
} else if ( * server_name ) {
2001-12-03 07:39:23 +03:00
/* resolve the IP address */
2001-12-05 05:58:40 +03:00
if ( ! resolve_name ( * server_name , server_ip , 0x20 ) ) {
2001-12-03 10:42:18 +03:00
DEBUG ( 1 , ( " Unable to resolve server name \n " ) ) ;
2001-12-05 05:58:40 +03:00
return False ;
2001-12-03 07:39:23 +03:00
}
2001-12-04 07:48:01 +03:00
} else if ( flags & NET_FLAGS_PDC ) {
2001-11-24 16:26:01 +03:00
struct in_addr * ip_list ;
int addr_count ;
2001-12-04 07:48:01 +03:00
if ( get_dc_list ( True /* PDC only*/ , opt_target_workgroup , & ip_list , & addr_count ) ) {
fstring dc_name ;
if ( addr_count < 1 ) {
2001-12-05 05:58:40 +03:00
return False ;
2001-11-24 16:26:01 +03:00
}
2001-12-04 07:48:01 +03:00
2001-12-05 05:58:40 +03:00
* server_ip = * ip_list ;
2001-12-04 07:48:01 +03:00
2001-12-05 05:58:40 +03:00
if ( is_zero_ip ( * server_ip ) )
return False ;
2001-12-04 07:48:01 +03:00
2001-12-05 05:58:40 +03:00
if ( ! lookup_dc_name ( global_myname , opt_target_workgroup , server_ip , dc_name ) )
return False ;
2001-12-04 07:48:01 +03:00
2001-12-05 05:58:40 +03:00
* server_name = strdup ( dc_name ) ;
2001-11-24 16:26:01 +03:00
}
2001-12-04 07:48:01 +03:00
} else if ( flags & NET_FLAGS_DMB ) {
struct in_addr msbrow_ip ;
/* if (!resolve_name(MSBROWSE, &msbrow_ip, 1)) */
if ( ! resolve_name ( opt_target_workgroup , & msbrow_ip , 0x1B ) ) {
DEBUG ( 1 , ( " Unable to resolve domain browser via name lookup \n " ) ) ;
2001-12-05 05:58:40 +03:00
return False ;
2001-12-04 07:48:01 +03:00
} else {
2001-12-05 05:58:40 +03:00
* server_ip = msbrow_ip ;
2001-12-04 07:48:01 +03:00
}
2001-12-11 08:21:50 +03:00
* server_name = strdup ( inet_ntoa ( opt_dest_ip ) ) ;
2001-12-03 07:39:23 +03:00
} else if ( flags & NET_FLAGS_MASTER ) {
2001-11-24 16:26:01 +03:00
struct in_addr brow_ips ;
2001-12-04 07:48:01 +03:00
if ( ! resolve_name ( opt_target_workgroup , & brow_ips , 0x1D ) ) {
2001-11-24 16:26:01 +03:00
/* go looking for workgroups */
DEBUG ( 1 , ( " Unable to resolve master browser via name lookup \n " ) ) ;
2001-12-05 05:58:40 +03:00
return False ;
2001-11-24 16:26:01 +03:00
} else {
2001-12-05 05:58:40 +03:00
* server_ip = brow_ips ;
2001-11-24 16:26:01 +03:00
}
2001-12-11 08:21:50 +03:00
* server_name = strdup ( inet_ntoa ( opt_dest_ip ) ) ;
2001-12-03 07:39:23 +03:00
} else if ( ! ( flags & NET_FLAGS_LOCALHOST_DEFAULT_INSANE ) ) {
2001-11-24 16:26:01 +03:00
extern struct in_addr loopback_ip ;
2001-12-05 05:58:40 +03:00
* server_ip = loopback_ip ;
* server_name = strdup ( " 127.0.0.1 " ) ;
2001-11-24 16:26:01 +03:00
}
2001-10-19 20:51:26 +04:00
2001-12-05 05:58:40 +03:00
if ( ! server_name | | ! * server_name ) {
2001-11-24 16:26:01 +03:00
DEBUG ( 1 , ( " no server to connect to \n " ) ) ;
2001-12-05 05:58:40 +03:00
return False ;
2001-11-24 16:26:01 +03:00
}
2001-12-03 07:39:23 +03:00
2001-12-05 05:58:40 +03:00
return True ;
}
2002-03-01 05:56:35 +03:00
BOOL net_find_dc ( struct in_addr * server_ip , fstring server_name , char * domain_name )
{
struct in_addr * ip_list ;
int addr_count ;
if ( get_dc_list ( True /* PDC only*/ , domain_name , & ip_list , & addr_count ) ) {
fstring dc_name ;
if ( addr_count < 1 ) {
return False ;
}
* server_ip = * ip_list ;
if ( is_zero_ip ( * server_ip ) )
return False ;
if ( ! lookup_dc_name ( global_myname , domain_name , server_ip , dc_name ) )
return False ;
safe_strcpy ( server_name , dc_name , FSTRING_LEN ) ;
return True ;
} else
return False ;
}
2001-12-05 05:58:40 +03:00
struct cli_state * net_make_ipc_connection ( unsigned flags )
{
char * server_name = NULL ;
struct in_addr server_ip ;
2002-03-01 05:56:35 +03:00
struct cli_state * cli = NULL ;
NTSTATUS nt_status ;
2001-12-05 05:58:40 +03:00
if ( ! net_find_server ( flags , & server_ip , & server_name ) ) {
d_printf ( " \n Unable to find a suitable server \n " ) ;
return NULL ;
}
2001-12-05 06:14:21 +03:00
if ( flags & NET_FLAGS_ANONYMOUS ) {
2002-03-01 05:56:35 +03:00
nt_status = connect_to_ipc_anonymous ( & cli , & server_ip , server_name ) ;
2001-12-05 06:14:21 +03:00
} else {
2002-03-01 05:56:35 +03:00
nt_status = connect_to_ipc ( & cli , & server_ip , server_name ) ;
2001-12-05 06:14:21 +03:00
}
2001-12-04 07:48:01 +03:00
SAFE_FREE ( server_name ) ;
2001-12-03 07:39:23 +03:00
return cli ;
2001-10-19 20:51:26 +04:00
}
2002-04-05 05:36:28 +04:00
2002-04-04 20:53:07 +04:00
static int net_user ( int argc , const char * * argv )
{
if ( net_ads_check ( ) = = 0 )
return net_ads_user ( argc , argv ) ;
2002-04-05 05:36:28 +04:00
/* if server is not specified, default to PDC? */
if ( net_rpc_check ( NET_FLAGS_PDC ) )
return net_rpc_user ( argc , argv ) ;
2002-04-04 20:53:07 +04:00
return net_rap_user ( argc , argv ) ;
}
2001-10-19 20:51:26 +04:00
2002-03-16 01:04:53 +03:00
static int net_join ( int argc , const char * * argv )
{
2002-04-04 20:53:07 +04:00
if ( net_ads_check ( ) = = 0 ) {
2002-03-16 01:04:53 +03:00
if ( net_ads_join ( argc , argv ) = = 0 )
return 0 ;
else
d_printf ( " ADS join did not work, trying RPC... \n " ) ;
}
return net_rpc_join ( argc , argv ) ;
}
2001-11-24 16:26:01 +03:00
/* main function table */
static struct functable net_func [ ] = {
2001-12-03 07:39:23 +03:00
{ " RPC " , net_rpc } ,
{ " RAP " , net_rap } ,
2001-11-25 03:18:11 +03:00
{ " ADS " , net_ads } ,
2001-12-11 01:25:21 +03:00
/* eventually these should auto-choose the transport ... */
{ " FILE " , net_rap_file } ,
{ " SHARE " , net_rap_share } ,
{ " SESSION " , net_rap_session } ,
{ " SERVER " , net_rap_server } ,
{ " DOMAIN " , net_rap_domain } ,
{ " PRINTQ " , net_rap_printq } ,
2002-04-04 20:53:07 +04:00
{ " USER " , net_user } ,
2001-12-11 01:25:21 +03:00
{ " GROUP " , net_rap_group } ,
{ " VALIDATE " , net_rap_validate } ,
{ " GROUPMEMBER " , net_rap_groupmember } ,
{ " ADMIN " , net_rap_admin } ,
{ " SERVICE " , net_rap_service } ,
{ " PASSWORD " , net_rap_password } ,
2001-12-11 08:21:50 +03:00
{ " TIME " , net_time } ,
2001-12-20 10:42:00 +03:00
{ " LOOKUP " , net_lookup } ,
2002-03-16 01:04:53 +03:00
{ " JOIN " , net_join } ,
2001-12-11 01:25:21 +03:00
2001-11-24 16:26:01 +03:00
{ " HELP " , net_help } ,
{ NULL , NULL }
} ;
2001-11-13 01:50:48 +03:00
2001-10-19 20:51:26 +04:00
/****************************************************************************
main program
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-11-26 08:59:43 +03:00
int main ( int argc , const char * * argv )
2001-10-19 20:51:26 +04:00
{
2001-11-24 16:26:01 +03:00
int opt , i ;
char * p ;
int rc = 0 ;
int argc_new = 0 ;
const char * * argv_new ;
poptContext pc ;
2001-11-25 16:36:02 +03:00
static char * servicesf = dyn_CONFIGFILE ;
2002-04-04 20:53:07 +04:00
static int debuglevel = 0 ;
2001-11-24 16:26:01 +03:00
struct poptOption long_options [ ] = {
2002-03-15 23:03:07 +03:00
{ " help " , ' h ' , POPT_ARG_NONE , 0 , ' h ' } ,
{ " workgroup " , ' w ' , POPT_ARG_STRING , & opt_target_workgroup } ,
{ " myworkgroup " , ' W ' , POPT_ARG_STRING , & opt_workgroup } ,
{ " user " , ' U ' , POPT_ARG_STRING , & opt_user_name , ' U ' } ,
{ " ipaddress " , ' I ' , POPT_ARG_STRING , 0 , ' I ' } ,
{ " port " , ' p ' , POPT_ARG_INT , & opt_port } ,
{ " myname " , ' n ' , POPT_ARG_STRING , & opt_requester_name } ,
{ " conf " , ' s ' , POPT_ARG_STRING , & servicesf } ,
2002-04-04 20:53:07 +04:00
{ " debug " , ' d ' , POPT_ARG_INT , & debuglevel } ,
{ " debuglevel " , ' d ' , POPT_ARG_INT , & debuglevel } ,
2002-03-15 23:03:07 +03:00
{ " server " , ' S ' , POPT_ARG_STRING , & opt_host } ,
{ " comment " , ' C ' , POPT_ARG_STRING , & opt_comment } ,
{ " maxusers " , ' M ' , POPT_ARG_INT , & opt_maxusers } ,
{ " flags " , ' F ' , POPT_ARG_INT , & opt_flags } ,
{ " jobid " , ' j ' , POPT_ARG_INT , & opt_jobid } ,
{ " long " , ' l ' , POPT_ARG_NONE , & opt_long_list_entries } ,
{ " reboot " , ' r ' , POPT_ARG_NONE , & opt_reboot } ,
{ " force " , ' f ' , POPT_ARG_NONE , & opt_force } ,
{ " timeout " , ' t ' , POPT_ARG_INT , & opt_timeout } ,
2001-11-24 16:26:01 +03:00
{ 0 , 0 , 0 , 0 }
} ;
2001-12-11 08:21:50 +03:00
zero_ip ( & opt_dest_ip ) ;
2001-11-24 16:26:01 +03:00
2001-12-20 10:13:47 +03:00
dbf = x_stderr ;
2001-11-24 16:26:01 +03:00
pc = poptGetContext ( NULL , argc , ( const char * * ) argv , long_options ,
POPT_CONTEXT_KEEP_FIRST ) ;
while ( ( opt = poptGetNextOpt ( pc ) ) ! = - 1 ) {
switch ( opt ) {
case ' h ' :
2002-04-05 05:36:28 +04:00
net_help ( argc , argv ) ;
2001-11-24 16:26:01 +03:00
exit ( 0 ) ;
break ;
case ' I ' :
2001-12-11 08:21:50 +03:00
opt_dest_ip = * interpret_addr2 ( poptGetOptArg ( pc ) ) ;
if ( is_zero_ip ( opt_dest_ip ) )
2001-12-03 07:39:23 +03:00
d_printf ( " \n Invalid ip address specified \n " ) ;
2001-11-24 16:26:01 +03:00
else
2001-12-11 08:21:50 +03:00
opt_have_ip = True ;
2001-11-24 16:26:01 +03:00
break ;
case ' U ' :
2002-01-26 01:07:46 +03:00
opt_user_specified = True ;
2001-11-24 16:26:01 +03:00
opt_user_name = strdup ( opt_user_name ) ;
p = strchr ( opt_user_name , ' % ' ) ;
if ( p ) {
* p = 0 ;
opt_password = p + 1 ;
}
break ;
default :
2001-12-03 07:39:23 +03:00
d_printf ( " \n Invalid option %c (%d) \n " , ( char ) opt , opt ) ;
2002-04-05 05:36:28 +04:00
net_help ( argc , argv ) ;
2001-11-24 16:26:01 +03:00
}
2001-10-23 18:16:59 +04:00
}
2001-10-19 20:51:26 +04:00
2001-11-24 16:26:01 +03:00
lp_load ( servicesf , True , False , False ) ;
2001-10-19 20:51:26 +04:00
2001-12-14 05:14:59 +03:00
DEBUGLEVEL = debuglevel ;
2001-11-24 16:26:01 +03:00
argv_new = ( const char * * ) poptGetArgs ( pc ) ;
2001-10-19 20:51:26 +04:00
2001-11-24 16:26:01 +03:00
argc_new = argc ;
for ( i = 0 ; i < argc ; i + + ) {
if ( argv_new [ i ] = = NULL ) {
argc_new = i ;
break ;
}
}
if ( ! opt_requester_name ) {
static fstring myname ;
get_myname ( myname ) ;
opt_requester_name = myname ;
}
if ( ! opt_user_name & & getenv ( " LOGNAME " ) ) {
opt_user_name = getenv ( " LOGNAME " ) ;
}
if ( ! opt_workgroup ) {
opt_workgroup = lp_workgroup ( ) ;
}
2001-12-04 07:48:01 +03:00
if ( ! opt_target_workgroup ) {
opt_target_workgroup = lp_workgroup ( ) ;
}
2001-11-24 17:16:41 +03:00
if ( ! * global_myname ) {
2001-11-26 07:53:08 +03:00
char * p2 ;
2001-11-24 17:16:41 +03:00
fstrcpy ( global_myname , myhostname ( ) ) ;
2001-11-26 07:53:08 +03:00
p2 = strchr_m ( global_myname , ' . ' ) ;
if ( p2 )
* p2 = 0 ;
2001-11-24 17:16:41 +03:00
}
2001-11-24 16:26:01 +03:00
2001-12-05 14:00:26 +03:00
strupper ( global_myname ) ;
2001-11-24 16:26:01 +03:00
load_interfaces ( ) ;
2001-10-19 20:51:26 +04:00
2002-04-05 05:36:28 +04:00
rc = net_run_function ( argc_new - 1 , argv_new + 1 , net_func , net_help ) ;
2001-11-24 16:26:01 +03:00
DEBUG ( 2 , ( " return code = %d \n " , rc ) ) ;
return rc ;
}