0001-01-01 02:30:17 +02:30
/*
Samba Unix / Linux SMB client library
Distributed SMB / CIFS Server Management Utility
Copyright ( C ) 2001 Andrew Bartlett ( abartlet @ samba . org )
0001-01-01 02:30:17 +02:30
Copyright ( C ) 2002 Jim McDonough ( jmcd @ us . ibm . com )
0001-01-01 02:30:17 +02:30
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
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA . */
# include "includes.h"
# include "../utils/net.h"
0001-01-01 02:30:17 +02:30
extern pstring global_myname ;
0001-01-01 02:30:17 +02:30
/**
* @ file net_rpc . c
*
* @ brief RPC based subcommands for the ' net ' utility .
*
* This file should contain much of the functionality that used to
* be found in rpcclient , execpt that the commands should change
* less often , and the fucntionality should be sane ( the user is not
* expected to know a rid / sid before they conduct an operation etc . )
*
* @ todo Perhaps eventually these should be split out into a number
* of files , as this could get quite big .
* */
/* A function of this type is passed to the 'run_rpc_command' wrapper */
0001-01-01 02:30:17 +02:30
typedef NTSTATUS ( * rpc_command_fn ) ( const DOM_SID * , struct cli_state * , TALLOC_CTX * , int , const char * * ) ;
0001-01-01 02:30:17 +02:30
/**
* Many of the RPC functions need the domain sid . This function gets
* it at the start of every run
*
* @ param cli A cli_state already connected to the remote machine
*
* @ return The Domain SID of the remote machine .
0001-01-01 02:30:17 +02:30
* */
0001-01-01 02:30:17 +02:30
static DOM_SID * net_get_remote_domain_sid ( struct cli_state * cli )
{
DOM_SID * domain_sid ;
POLICY_HND pol ;
NTSTATUS result = NT_STATUS_OK ;
uint32 info_class = 5 ;
fstring domain_name ;
TALLOC_CTX * mem_ctx ;
if ( ! ( domain_sid = malloc ( sizeof ( DOM_SID ) ) ) ) {
0001-01-01 02:30:17 +02:30
DEBUG ( 0 , ( " net_get_remote_domain_sid: malloc returned NULL! \n " ) ) ;
0001-01-01 02:30:17 +02:30
goto error ;
}
if ( ! ( mem_ctx = talloc_init ( ) ) )
{
0001-01-01 02:30:17 +02:30
DEBUG ( 0 , ( " net_get_remote_domain_sid: talloc_init returned NULL! \n " ) ) ;
0001-01-01 02:30:17 +02:30
goto error ;
}
if ( ! cli_nt_session_open ( cli , PIPE_LSARPC ) ) {
fprintf ( stderr , " could not initialise lsa pipe \n " ) ;
goto error ;
}
result = cli_lsa_open_policy ( cli , mem_ctx , True ,
SEC_RIGHTS_MAXIMUM_ALLOWED ,
& pol ) ;
if ( ! NT_STATUS_IS_OK ( result ) ) {
goto error ;
}
result = cli_lsa_query_info_policy ( cli , mem_ctx , & pol , info_class ,
domain_name , domain_sid ) ;
if ( ! NT_STATUS_IS_OK ( result ) ) {
goto error ;
}
cli_lsa_close ( cli , mem_ctx , & pol ) ;
cli_nt_session_close ( cli ) ;
talloc_destroy ( mem_ctx ) ;
return domain_sid ;
error :
fprintf ( stderr , " could not obtain sid for domain %s \n " , cli - > domain ) ;
if ( ! NT_STATUS_IS_OK ( result ) ) {
0001-01-01 02:30:17 +02:30
fprintf ( stderr , " error: %s \n " , nt_errstr ( result ) ) ;
0001-01-01 02:30:17 +02:30
}
exit ( 1 ) ;
}
0001-01-01 02:30:17 +02:30
/**
* Run a single RPC command , from start to finish .
*
* @ param pipe_name the pipe to connect to ( usually a PIPE_ constant )
* @ param conn_flag a NET_FLAG_ combination . Passed to
* net_make_ipc_connection .
* @ param argc Standard main ( ) style argc
* @ param argc Standard main ( ) style argv . Initial components are already
* stripped
* @ return A shell status integer ( 0 for success )
*/
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
static int run_rpc_command ( const char * pipe_name , int conn_flags ,
0001-01-01 02:30:17 +02:30
rpc_command_fn fn ,
int argc , const char * * argv )
{
0001-01-01 02:30:17 +02:30
struct cli_state * cli = net_make_ipc_connection ( conn_flags ) ;
0001-01-01 02:30:17 +02:30
TALLOC_CTX * mem_ctx ;
NTSTATUS nt_status ;
0001-01-01 02:30:17 +02:30
DOM_SID * domain_sid ;
if ( ! cli ) {
return - 1 ;
}
domain_sid = net_get_remote_domain_sid ( cli ) ;
0001-01-01 02:30:17 +02:30
/* Create mem_ctx */
if ( ! ( mem_ctx = talloc_init ( ) ) ) {
DEBUG ( 0 , ( " talloc_init() failed \n " ) ) ;
cli_shutdown ( cli ) ;
return - 1 ;
}
if ( ! cli_nt_session_open ( cli , pipe_name ) ) {
DEBUG ( 0 , ( " Could not initialise samr pipe \n " ) ) ;
}
nt_status = fn ( domain_sid , cli , mem_ctx , argc , argv ) ;
0001-01-01 02:30:17 +02:30
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
0001-01-01 02:30:17 +02:30
DEBUG ( 1 , ( " rpc command function failed! (%s) \n " , nt_errstr ( nt_status ) ) ) ;
0001-01-01 02:30:17 +02:30
} else {
DEBUG ( 5 , ( " rpc command function succedded \n " ) ) ;
}
0001-01-01 02:30:17 +02:30
if ( cli - > nt_pipe_fnum )
cli_nt_session_close ( cli ) ;
talloc_destroy ( mem_ctx ) ;
return ( ! NT_STATUS_IS_OK ( nt_status ) ) ;
}
0001-01-01 02:30:17 +02:30
/****************************************************************************/
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
/**
* Force a change of the trust acccount password .
*
* All paramaters are provided by the run_rpc_command funcion , except for
* argc , argv which are passes through .
*
* @ param domain_sid The domain sid aquired from the remote server
* @ param cli A cli_state connected to the server .
* @ param mem_ctx Talloc context , destoyed on compleation of the function .
* @ param argc Standard main ( ) style argc
* @ param argc Standard main ( ) style argv . Initial components are already
* stripped
*
* @ return Normal NTSTATUS return .
* */
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
static NTSTATUS rpc_changetrustpw_internals ( const DOM_SID * domain_sid , struct cli_state * cli , TALLOC_CTX * mem_ctx ,
int argc , const char * * argv ) {
return trust_pw_find_change_and_store_it ( cli , mem_ctx , opt_target_workgroup ) ;
}
0001-01-01 02:30:17 +02:30
/**
* Force a change of the trust acccount password .
*
* @ param argc Standard main ( ) style argc
* @ param argc Standard main ( ) style argv . Initial components are already
* stripped
*
* @ return A shell status integer ( 0 for success )
* */
0001-01-01 02:30:17 +02:30
static int rpc_changetrustpw ( int argc , const char * * argv )
{
return run_rpc_command ( PIPE_NETLOGON , NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC , rpc_changetrustpw_internals ,
argc , argv ) ;
}
0001-01-01 02:30:17 +02:30
/****************************************************************************/
/**
* Join a domain , the old way .
*
* This uses ' machinename ' as the inital password , and changes it .
*
* The password should be created with ' server manager ' or eqiv first .
*
* All paramaters are provided by the run_rpc_command funcion , except for
* argc , argv which are passes through .
*
* @ param domain_sid The domain sid aquired from the remote server
* @ param cli A cli_state connected to the server .
* @ param mem_ctx Talloc context , destoyed on compleation of the function .
* @ param argc Standard main ( ) style argc
* @ param argc Standard main ( ) style argv . Initial components are already
* stripped
*
* @ return Normal NTSTATUS return .
* */
0001-01-01 02:30:17 +02:30
static NTSTATUS rpc_join_oldstyle_internals ( const DOM_SID * domain_sid , struct cli_state * cli , TALLOC_CTX * mem_ctx ,
int argc , const char * * argv ) {
extern pstring global_myname ;
fstring trust_passwd ;
unsigned char orig_trust_passwd_hash [ 16 ] ;
fstrcpy ( trust_passwd , global_myname ) ;
strlower ( trust_passwd ) ;
0001-01-01 02:30:17 +02:30
/*
* Machine names can be 15 characters , but the max length on
* a password is 14. - - jerry
*/
trust_passwd [ 14 ] = ' \0 ' ;
0001-01-01 02:30:17 +02:30
E_md4hash ( ( uchar * ) trust_passwd , orig_trust_passwd_hash ) ;
return trust_pw_change_and_store_it ( cli , mem_ctx , orig_trust_passwd_hash ) ;
}
0001-01-01 02:30:17 +02:30
/**
* Join a domain , the old way .
*
* @ param argc Standard main ( ) style argc
* @ param argc Standard main ( ) style argv . Initial components are already
* stripped
*
* @ return A shell status integer ( 0 for success )
* */
0001-01-01 02:30:17 +02:30
static int net_rpc_join_oldstyle ( int argc , const char * * argv )
0001-01-01 02:30:17 +02:30
{
return run_rpc_command ( PIPE_NETLOGON , NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC , rpc_join_oldstyle_internals ,
argc , argv ) ;
}
0001-01-01 02:30:17 +02:30
/**
* Basic usage function for ' net rpc join '
* @ param argc Standard main ( ) style argc
* @ param argc Standard main ( ) style argv . Initial components are already
* stripped
* */
0001-01-01 02:30:17 +02:30
static int rpc_join_usage ( int argc , const char * * argv )
{
0001-01-01 02:30:17 +02:30
d_printf ( " net rpc join -U <username>[%%password] [options] \n " \
" \t to join a domain with admin username & password \n " \
" \t \t password will be prompted if none is specified \n " ) ;
d_printf ( " net rpc join [options except -U] \n " \
" \t to join a domain created in server manager \n \n \n " ) ;
net_common_flags_usage ( argc , argv ) ;
0001-01-01 02:30:17 +02:30
return - 1 ;
}
0001-01-01 02:30:17 +02:30
/**
* ' net rpc join ' entrypoint .
* @ param argc Standard main ( ) style argc
* @ param argc Standard main ( ) style argv . Initial components are already
* stripped
*
* Main ' net_rpc_join ( ) ' ( where the admain username / password is used ) is
* in net_rpc_join . c
0001-01-01 02:30:17 +02:30
* Assume if a - U is specified , it ' s the new style , otherwise it ' s the
* old style
0001-01-01 02:30:17 +02:30
* */
0001-01-01 02:30:17 +02:30
int net_rpc_join ( int argc , const char * * argv )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
if ( ( net_rpc_join_oldstyle ( argc , argv ) = = 0 ) )
return 0 ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
return net_rpc_join_newstyle ( argc , argv ) ;
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
/**
* display info about a rpc domain
*
* All paramaters are provided by the run_rpc_command function , except for
* argc , argv which are passes through .
*
* @ param domain_sid The domain sid acquired from the remote server
* @ param cli A cli_state connected to the server .
* @ param mem_ctx Talloc context , destoyed on completion of the function .
* @ param argc Standard main ( ) style argc
* @ param argv Standard main ( ) style argv . Initial components are already
* stripped
*
* @ return Normal NTSTATUS return .
* */
static NTSTATUS
rpc_info_internals ( const DOM_SID * domain_sid , struct cli_state * cli ,
TALLOC_CTX * mem_ctx , int argc , const char * * argv )
{
POLICY_HND connect_pol , domain_pol ;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL ;
SAM_UNK_CTR ctr ;
/* Get sam policy handle */
result = cli_samr_connect ( cli , mem_ctx , MAXIMUM_ALLOWED_ACCESS ,
& connect_pol ) ;
if ( ! NT_STATUS_IS_OK ( result ) ) {
goto done ;
}
/* Get domain policy handle */
result = cli_samr_open_domain ( cli , mem_ctx , & connect_pol ,
MAXIMUM_ALLOWED_ACCESS ,
domain_sid , & domain_pol ) ;
if ( ! NT_STATUS_IS_OK ( result ) ) {
goto done ;
}
ZERO_STRUCT ( ctr ) ;
result = cli_samr_query_dom_info ( cli , mem_ctx , & domain_pol ,
2 , & ctr ) ;
if ( NT_STATUS_IS_OK ( result ) ) {
TALLOC_CTX * ctx = talloc_init ( ) ;
d_printf ( " Domain Name: %s \n " , unistr2_tdup ( ctx , & ctr . info . inf2 . uni_domain ) ) ;
d_printf ( " Sequence number: %u \n " , ctr . info . inf2 . seq_num ) ;
d_printf ( " Num users: %u \n " , ctr . info . inf2 . num_domain_usrs ) ;
d_printf ( " Num domain groups: %u \n " , ctr . info . inf2 . num_domain_grps ) ;
d_printf ( " Num local groups: %u \n " , ctr . info . inf2 . num_local_grps ) ;
talloc_destroy ( ctx ) ;
}
done :
return result ;
}
/**
* ' net rpc info ' entrypoint .
* @ param argc Standard main ( ) style argc
* @ param argc Standard main ( ) style argv . Initial components are already
* stripped
* */
int net_rpc_info ( int argc , const char * * argv )
{
return run_rpc_command ( PIPE_SAMR , NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC ,
rpc_info_internals ,
argc , argv ) ;
}
0001-01-01 02:30:17 +02:30
/****************************************************************************/
0001-01-01 02:30:17 +02:30
/**
* Basic usage function for ' net rpc user '
* @ param argc Standard main ( ) style argc .
* @ param argv Standard main ( ) style argv . Initial components are already
* stripped .
* */
static int rpc_user_usage ( int argc , const char * * argv )
{
return net_help_user ( argc , argv ) ;
}
0001-01-01 02:30:17 +02:30
/**
* Add a new user to a remote RPC server
*
* All paramaters are provided by the run_rpc_command funcion , except for
* argc , argv which are passes through .
*
0001-01-01 02:30:17 +02:30
* @ param domain_sid The domain sid acquired from the remote server
0001-01-01 02:30:17 +02:30
* @ param cli A cli_state connected to the server .
0001-01-01 02:30:17 +02:30
* @ param mem_ctx Talloc context , destoyed on completion of the function .
0001-01-01 02:30:17 +02:30
* @ param argc Standard main ( ) style argc
0001-01-01 02:30:17 +02:30
* @ param argv Standard main ( ) style argv . Initial components are already
0001-01-01 02:30:17 +02:30
* stripped
*
* @ return Normal NTSTATUS return .
* */
static NTSTATUS rpc_user_add_internals ( const DOM_SID * domain_sid , struct cli_state * cli , TALLOC_CTX * mem_ctx ,
int argc , const char * * argv ) {
POLICY_HND connect_pol , domain_pol , user_pol ;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL ;
const char * acct_name ;
uint16 acb_info ;
uint32 unknown , user_rid ;
if ( argc ! = 1 ) {
0001-01-01 02:30:17 +02:30
d_printf ( " User must be specified \n " ) ;
rpc_user_usage ( argc , argv ) ;
0001-01-01 02:30:17 +02:30
return NT_STATUS_OK ;
}
acct_name = argv [ 0 ] ;
/* Get sam policy handle */
result = cli_samr_connect ( cli , mem_ctx , MAXIMUM_ALLOWED_ACCESS ,
& connect_pol ) ;
if ( ! NT_STATUS_IS_OK ( result ) ) {
goto done ;
}
/* Get domain policy handle */
result = cli_samr_open_domain ( cli , mem_ctx , & connect_pol ,
MAXIMUM_ALLOWED_ACCESS ,
domain_sid , & domain_pol ) ;
if ( ! NT_STATUS_IS_OK ( result ) ) {
goto done ;
}
/* Create domain user */
acb_info = ACB_NORMAL ;
unknown = 0xe005000b ; /* No idea what this is - a permission mask? */
result = cli_samr_create_dom_user ( cli , mem_ctx , & domain_pol ,
acct_name , acb_info , unknown ,
& user_pol , & user_rid ) ;
if ( ! NT_STATUS_IS_OK ( result ) ) {
goto done ;
}
done :
0001-01-01 02:30:17 +02:30
if ( ! NT_STATUS_IS_OK ( result ) ) {
d_printf ( " Failed to add user %s - %s \n " , acct_name ,
0001-01-01 02:30:17 +02:30
nt_errstr ( result ) ) ;
0001-01-01 02:30:17 +02:30
} else {
d_printf ( " Added user %s \n " , acct_name ) ;
}
0001-01-01 02:30:17 +02:30
return result ;
}
/**
* Add a new user to a remote RPC server
*
* @ param argc Standard main ( ) style argc
0001-01-01 02:30:17 +02:30
* @ param argv Standard main ( ) style argv . Initial components are already
0001-01-01 02:30:17 +02:30
* stripped
*
* @ return A shell status integer ( 0 for success )
* */
0001-01-01 02:30:17 +02:30
static int rpc_user_add ( int argc , const char * * argv )
{
0001-01-01 02:30:17 +02:30
return run_rpc_command ( PIPE_SAMR , 0 , rpc_user_add_internals ,
0001-01-01 02:30:17 +02:30
argc , argv ) ;
}
0001-01-01 02:30:17 +02:30
/**
0001-01-01 02:30:17 +02:30
* Delete a user from a remote RPC server
*
* All paramaters are provided by the run_rpc_command funcion , except for
* argc , argv which are passes through .
*
* @ param domain_sid The domain sid acquired from the remote server
* @ param cli A cli_state connected to the server .
* @ param mem_ctx Talloc context , destoyed on completion of the function .
0001-01-01 02:30:17 +02:30
* @ param argc Standard main ( ) style argc
0001-01-01 02:30:17 +02:30
* @ param argv Standard main ( ) style argv . Initial components are already
0001-01-01 02:30:17 +02:30
* stripped
0001-01-01 02:30:17 +02:30
*
* @ return Normal NTSTATUS return .
0001-01-01 02:30:17 +02:30
* */
0001-01-01 02:30:17 +02:30
static NTSTATUS rpc_user_del_internals ( const DOM_SID * domain_sid ,
struct cli_state * cli ,
TALLOC_CTX * mem_ctx ,
int argc , const char * * argv )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
NTSTATUS result = NT_STATUS_UNSUCCESSFUL ;
POLICY_HND connect_pol , domain_pol , user_pol ;
if ( argc < 1 ) {
d_printf ( " User must be specified \n " ) ;
rpc_user_usage ( argc , argv ) ;
return NT_STATUS_OK ;
}
/* Get sam policy and domain handles */
result = cli_samr_connect ( cli , mem_ctx , MAXIMUM_ALLOWED_ACCESS ,
& connect_pol ) ;
if ( ! NT_STATUS_IS_OK ( result ) ) {
goto done ;
}
result = cli_samr_open_domain ( cli , mem_ctx , & connect_pol ,
MAXIMUM_ALLOWED_ACCESS ,
domain_sid , & domain_pol ) ;
if ( ! NT_STATUS_IS_OK ( result ) ) {
goto done ;
}
/* Get handle on user */
{
uint32 * user_rids , num_rids , * name_types ;
uint32 flags = 0x000003e8 ; /* Unknown */
result = cli_samr_lookup_names ( cli , mem_ctx , & domain_pol ,
0001-01-01 02:30:17 +02:30
flags , 1 , & argv [ 0 ] ,
0001-01-01 02:30:17 +02:30
& num_rids , & user_rids ,
& name_types ) ;
if ( ! NT_STATUS_IS_OK ( result ) ) {
goto done ;
}
result = cli_samr_open_user ( cli , mem_ctx , & domain_pol ,
MAXIMUM_ALLOWED_ACCESS ,
user_rids [ 0 ] , & user_pol ) ;
if ( ! NT_STATUS_IS_OK ( result ) ) {
goto done ;
}
}
/* Delete user */
result = cli_samr_delete_dom_user ( cli , mem_ctx , & user_pol ) ;
if ( ! NT_STATUS_IS_OK ( result ) ) {
goto done ;
}
/* Display results */
done :
return result ;
}
/**
* Delete a user from a remote RPC server
*
* @ param argc Standard main ( ) style argc
* @ param argv Standard main ( ) style argv . Initial components are already
* stripped
*
* @ return A shell status integer ( 0 for success )
* */
static int rpc_user_delete ( int argc , const char * * argv )
{
return run_rpc_command ( PIPE_SAMR , 0 , rpc_user_del_internals ,
argc , argv ) ;
}
/**
* List user ' s groups on a remote RPC server
*
* All paramaters are provided by the run_rpc_command funcion , except for
* argc , argv which are passes through .
*
* @ param domain_sid The domain sid acquired from the remote server
* @ param cli A cli_state connected to the server .
* @ param mem_ctx Talloc context , destoyed on completion of the function .
* @ param argc Standard main ( ) style argc
* @ param argv Standard main ( ) style argv . Initial components are already
* stripped
*
* @ return Normal NTSTATUS return .
* */
static NTSTATUS
rpc_user_info_internals ( const DOM_SID * domain_sid , struct cli_state * cli ,
TALLOC_CTX * mem_ctx , int argc , const char * * argv )
{
POLICY_HND connect_pol , domain_pol , user_pol ;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL ;
uint32 * rids , num_rids , * name_types , num_names ;
uint32 flags = 0x000003e8 ; /* Unknown */
int i ;
char * * names ;
DOM_GID * user_gids ;
if ( argc < 1 ) {
d_printf ( " User must be specified \n " ) ;
rpc_user_usage ( argc , argv ) ;
return NT_STATUS_OK ;
}
/* Get sam policy handle */
result = cli_samr_connect ( cli , mem_ctx , MAXIMUM_ALLOWED_ACCESS ,
& connect_pol ) ;
if ( ! NT_STATUS_IS_OK ( result ) ) goto done ;
/* Get domain policy handle */
result = cli_samr_open_domain ( cli , mem_ctx , & connect_pol ,
MAXIMUM_ALLOWED_ACCESS ,
domain_sid , & domain_pol ) ;
if ( ! NT_STATUS_IS_OK ( result ) ) goto done ;
/* Get handle on user */
result = cli_samr_lookup_names ( cli , mem_ctx , & domain_pol ,
0001-01-01 02:30:17 +02:30
flags , 1 , & argv [ 0 ] ,
0001-01-01 02:30:17 +02:30
& num_rids , & rids , & name_types ) ;
if ( ! NT_STATUS_IS_OK ( result ) ) goto done ;
result = cli_samr_open_user ( cli , mem_ctx , & domain_pol ,
MAXIMUM_ALLOWED_ACCESS ,
rids [ 0 ] , & user_pol ) ;
if ( ! NT_STATUS_IS_OK ( result ) ) goto done ;
result = cli_samr_query_usergroups ( cli , mem_ctx , & user_pol ,
& num_rids , & user_gids ) ;
/* Look up rids */
rids = ( uint32 * ) talloc ( mem_ctx , sizeof ( uint32 ) * num_rids ) ;
for ( i = 0 ; i < num_rids ; i + + )
rids [ i ] = user_gids [ i ] . g_rid ;
result = cli_samr_lookup_rids ( cli , mem_ctx , & domain_pol ,
flags , num_rids , rids ,
& num_names , & names , & name_types ) ;
if ( ! NT_STATUS_IS_OK ( result ) ) {
goto done ;
}
/* Display results */
for ( i = 0 ; i < num_names ; i + + )
printf ( " %s \n " , names [ i ] ) ;
done :
return result ;
}
/**
* List a user ' s groups from a remote RPC server
*
* @ param argc Standard main ( ) style argc
* @ param argv Standard main ( ) style argv . Initial components are already
* stripped
*
* @ return A shell status integer ( 0 for success )
* */
static int rpc_user_info ( int argc , const char * * argv )
{
return run_rpc_command ( PIPE_SAMR , 0 , rpc_user_info_internals ,
argc , argv ) ;
}
/**
* List users on a remote RPC server
*
0001-01-01 02:30:17 +02:30
* All paramaters are provided by the run_rpc_command function , except for
0001-01-01 02:30:17 +02:30
* argc , argv which are passes through .
*
* @ param domain_sid The domain sid acquired from the remote server
* @ param cli A cli_state connected to the server .
* @ param mem_ctx Talloc context , destoyed on completion of the function .
* @ param argc Standard main ( ) style argc
* @ param argv Standard main ( ) style argv . Initial components are already
* stripped
*
* @ return Normal NTSTATUS return .
* */
static NTSTATUS
rpc_user_list_internals ( const DOM_SID * domain_sid , struct cli_state * cli ,
TALLOC_CTX * mem_ctx , int argc , const char * * argv )
{
POLICY_HND connect_pol , domain_pol ;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL ;
uint32 start_idx = 0 , max_entries = 250 , num_entries , i ;
SAM_DISPINFO_CTR ctr ;
SAM_DISPINFO_1 info1 ;
/* Get sam policy handle */
result = cli_samr_connect ( cli , mem_ctx , MAXIMUM_ALLOWED_ACCESS ,
& connect_pol ) ;
if ( ! NT_STATUS_IS_OK ( result ) ) {
goto done ;
}
/* Get domain policy handle */
result = cli_samr_open_domain ( cli , mem_ctx , & connect_pol ,
MAXIMUM_ALLOWED_ACCESS ,
domain_sid , & domain_pol ) ;
if ( ! NT_STATUS_IS_OK ( result ) ) {
goto done ;
}
/* Query domain users */
ZERO_STRUCT ( ctr ) ;
ZERO_STRUCT ( info1 ) ;
ctr . sam . info1 = & info1 ;
if ( opt_long_list_entries )
d_printf ( " \n User name Comment " \
" \n ----------------------------- \n " ) ;
do {
fstring user , desc ;
result = cli_samr_query_dispinfo ( cli , mem_ctx , & domain_pol ,
& start_idx , 1 , & num_entries ,
max_entries , & ctr ) ;
for ( i = 0 ; i < num_entries ; i + + ) {
unistr2_to_ascii ( user , & ( & ctr . sam . info1 - > str [ i ] ) - > uni_acct_name , sizeof ( user ) - 1 ) ;
if ( opt_long_list_entries )
unistr2_to_ascii ( desc , & ( & ctr . sam . info1 - > str [ i ] ) - > uni_acct_desc , sizeof ( desc ) - 1 ) ;
if ( opt_long_list_entries )
printf ( " %-21.21s %-50.50s \n " , user , desc ) ;
else
0001-01-01 02:30:17 +02:30
printf ( " %s \n " , user ) ;
0001-01-01 02:30:17 +02:30
}
} while ( ! NT_STATUS_IS_OK ( result ) ) ;
done :
return result ;
0001-01-01 02:30:17 +02:30
}
0001-01-01 02:30:17 +02:30
/**
* ' net rpc user ' entrypoint .
* @ param argc Standard main ( ) style argc
* @ param argc Standard main ( ) style argv . Initial components are already
* stripped
* */
0001-01-01 02:30:17 +02:30
int net_rpc_user ( int argc , const char * * argv )
0001-01-01 02:30:17 +02:30
{
struct functable func [ ] = {
{ " add " , rpc_user_add } ,
0001-01-01 02:30:17 +02:30
{ " info " , rpc_user_info } ,
{ " delete " , rpc_user_delete } ,
0001-01-01 02:30:17 +02:30
{ NULL , NULL }
} ;
if ( argc = = 0 ) {
0001-01-01 02:30:17 +02:30
if ( opt_long_list_entries ) {
} else {
}
return run_rpc_command ( PIPE_SAMR , 0 ,
rpc_user_list_internals ,
argc , argv ) ;
0001-01-01 02:30:17 +02:30
}
return net_run_function ( argc , argv , func , rpc_user_usage ) ;
}
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
/****************************************************************************/
/**
* Basic usage function for ' net rpc group '
* @ param argc Standard main ( ) style argc .
* @ param argv Standard main ( ) style argv . Initial components are already
* stripped .
* */
static int rpc_group_usage ( int argc , const char * * argv )
{
return net_help_group ( argc , argv ) ;
}
/**
* List groups on a remote RPC server
*
* All paramaters are provided by the run_rpc_command funcion , except for
* argc , argv which are passes through .
*
* @ param domain_sid The domain sid acquired from the remote server
* @ param cli A cli_state connected to the server .
* @ param mem_ctx Talloc context , destoyed on completion of the function .
* @ param argc Standard main ( ) style argc
* @ param argv Standard main ( ) style argv . Initial components are already
* stripped
*
* @ return Normal NTSTATUS return .
* */
static NTSTATUS
rpc_group_list_internals ( const DOM_SID * domain_sid , struct cli_state * cli ,
TALLOC_CTX * mem_ctx , int argc , const char * * argv )
{
POLICY_HND connect_pol , domain_pol ;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL ;
uint32 start_idx = 0 , max_entries = 250 , num_entries , i ;
struct acct_info * groups ;
DOM_SID global_sid_Builtin ;
string_to_sid ( & global_sid_Builtin , " S-1-5-32 " ) ;
/* Get sam policy handle */
result = cli_samr_connect ( cli , mem_ctx , MAXIMUM_ALLOWED_ACCESS ,
& connect_pol ) ;
if ( ! NT_STATUS_IS_OK ( result ) ) {
goto done ;
}
/* Get domain policy handle */
result = cli_samr_open_domain ( cli , mem_ctx , & connect_pol ,
MAXIMUM_ALLOWED_ACCESS ,
domain_sid , & domain_pol ) ;
if ( ! NT_STATUS_IS_OK ( result ) ) {
goto done ;
}
/* Query domain groups */
if ( opt_long_list_entries )
d_printf ( " \n Group name Comment " \
" \n ----------------------------- \n " ) ;
do {
result = cli_samr_enum_dom_groups ( cli , mem_ctx , & domain_pol ,
& start_idx , max_entries ,
& groups , & num_entries ) ;
for ( i = 0 ; i < num_entries ; i + + ) {
if ( opt_long_list_entries )
printf ( " %-21.21s %-50.50s \n " ,
groups [ i ] . acct_name ,
groups [ i ] . acct_desc ) ;
else
printf ( " %-21.21s \n " , groups [ i ] . acct_name ) ;
}
} while ( ! NT_STATUS_IS_OK ( result ) ) ;
/* query domain aliases */
do {
result = cli_samr_enum_als_groups ( cli , mem_ctx , & domain_pol ,
& start_idx , max_entries ,
& groups , & num_entries ) ;
for ( i = 0 ; i < num_entries ; i + + ) {
if ( opt_long_list_entries )
printf ( " %-21.21s %-50.50s \n " ,
groups [ i ] . acct_name ,
groups [ i ] . acct_desc ) ;
else
printf ( " %-21.21s \n " , groups [ i ] . acct_name ) ;
}
} while ( ! NT_STATUS_IS_OK ( result ) ) ;
cli_samr_close ( cli , mem_ctx , & domain_pol ) ;
/* Get builtin policy handle */
result = cli_samr_open_domain ( cli , mem_ctx , & connect_pol ,
MAXIMUM_ALLOWED_ACCESS ,
& global_sid_Builtin , & domain_pol ) ;
if ( ! NT_STATUS_IS_OK ( result ) ) {
goto done ;
}
/* query builtin aliases */
do {
result = cli_samr_enum_als_groups ( cli , mem_ctx , & domain_pol ,
& start_idx , max_entries ,
& groups , & num_entries ) ;
for ( i = 0 ; i < num_entries ; i + + ) {
if ( opt_long_list_entries )
printf ( " %-21.21s %-50.50s \n " ,
groups [ i ] . acct_name ,
groups [ i ] . acct_desc ) ;
else
printf ( " %s \n " , groups [ i ] . acct_name ) ;
}
} while ( ! NT_STATUS_IS_OK ( result ) ) ;
done :
return result ;
}
/**
* ' net rpc group ' entrypoint .
* @ param argc Standard main ( ) style argc
* @ param argc Standard main ( ) style argv . Initial components are already
* stripped
* */
int net_rpc_group ( int argc , const char * * argv )
{
struct functable func [ ] = {
#if 0
{ " add " , rpc_group_add } ,
{ " delete " , rpc_group_delete } ,
# endif
{ NULL , NULL }
} ;
if ( argc = = 0 ) {
if ( opt_long_list_entries ) {
} else {
}
return run_rpc_command ( PIPE_SAMR , 0 ,
rpc_group_list_internals ,
argc , argv ) ;
}
return net_run_function ( argc , argv , func , rpc_group_usage ) ;
}
0001-01-01 02:30:17 +02:30
/****************************************************************************/
static int rpc_share_usage ( int argc , const char * * argv )
{
return net_help_share ( argc , argv ) ;
}
0001-01-01 02:30:17 +02:30
/**
* Add a share on a remote RPC server
*
* All paramaters are provided by the run_rpc_command function , except for
* argc , argv which are passes through .
*
* @ param domain_sid The domain sid acquired from the remote server
* @ param cli A cli_state connected to the server .
* @ param mem_ctx Talloc context , destoyed on completion of the function .
* @ param argc Standard main ( ) style argc
* @ param argv Standard main ( ) style argv . Initial components are already
* stripped
*
* @ return Normal NTSTATUS return .
* */
0001-01-01 02:30:17 +02:30
static NTSTATUS
rpc_share_add_internals ( const DOM_SID * domain_sid , struct cli_state * cli ,
TALLOC_CTX * mem_ctx , int argc , const char * * argv )
{
WERROR result ;
char * sharename = talloc_strdup ( mem_ctx , argv [ 0 ] ) ;
char * path ;
uint32 type = 0 ; /* only allow disk shares to be added */
uint32 num_users = 0 , perms = 0 ;
char * password = NULL ; /* don't allow a share password */
path = strchr ( sharename , ' = ' ) ;
if ( ! path )
return NT_STATUS_UNSUCCESSFUL ;
* path + + = ' \0 ' ;
result = cli_srvsvc_net_share_add ( cli , mem_ctx , sharename , type ,
opt_comment , perms , opt_maxusers ,
num_users , path , password ) ;
return W_ERROR_IS_OK ( result ) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL ;
}
static int rpc_share_add ( int argc , const char * * argv )
{
if ( ( argc < 1 ) | | ! strchr ( argv [ 0 ] , ' = ' ) ) {
DEBUG ( 1 , ( " Sharename or path not specified on add \n " ) ) ;
return rpc_share_usage ( argc , argv ) ;
}
return run_rpc_command ( PIPE_SRVSVC , 0 ,
rpc_share_add_internals ,
argc , argv ) ;
}
0001-01-01 02:30:17 +02:30
/**
* Delete a share on a remote RPC server
*
* All paramaters are provided by the run_rpc_command function , except for
* argc , argv which are passes through .
*
* @ param domain_sid The domain sid acquired from the remote server
* @ param cli A cli_state connected to the server .
* @ param mem_ctx Talloc context , destoyed on completion of the function .
* @ param argc Standard main ( ) style argc
* @ param argv Standard main ( ) style argv . Initial components are already
* stripped
*
* @ return Normal NTSTATUS return .
* */
0001-01-01 02:30:17 +02:30
static NTSTATUS
rpc_share_del_internals ( const DOM_SID * domain_sid , struct cli_state * cli ,
TALLOC_CTX * mem_ctx , int argc , const char * * argv )
{
WERROR result ;
result = cli_srvsvc_net_share_del ( cli , mem_ctx , argv [ 0 ] ) ;
return W_ERROR_IS_OK ( result ) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL ;
}
0001-01-01 02:30:17 +02:30
/**
* Delete a share on a remote RPC server
*
* @ param domain_sid The domain sid acquired from the remote server
* @ param argc Standard main ( ) style argc
* @ param argv Standard main ( ) style argv . Initial components are already
* stripped
*
* @ return A shell status integer ( 0 for success )
* */
0001-01-01 02:30:17 +02:30
static int rpc_share_delete ( int argc , const char * * argv )
{
if ( argc < 1 ) {
DEBUG ( 1 , ( " Sharename not specified on delete \n " ) ) ;
return rpc_share_usage ( argc , argv ) ;
}
return run_rpc_command ( PIPE_SRVSVC , 0 ,
rpc_share_del_internals ,
argc , argv ) ;
}
0001-01-01 02:30:17 +02:30
/**
* Formatted print of share info
*
* @ param info1 pointer to SRV_SHARE_INFO_1 to format
* */
0001-01-01 02:30:17 +02:30
static void display_share_info_1 ( SRV_SHARE_INFO_1 * info1 )
{
fstring netname = " " , remark = " " ;
rpcstr_pull_unistr2_fstring ( netname , & info1 - > info_1_str . uni_netname ) ;
rpcstr_pull_unistr2_fstring ( remark , & info1 - > info_1_str . uni_remark ) ;
if ( opt_long_list_entries ) {
d_printf ( " %-12.12s %-8.8s %-50.50s \n " ,
netname , share_type [ info1 - > info_1 . type ] , remark ) ;
} else {
d_printf ( " %-12.12s \n " , netname ) ;
}
}
/**
* List shares on a remote RPC server
*
0001-01-01 02:30:17 +02:30
* All paramaters are provided by the run_rpc_command function , except for
0001-01-01 02:30:17 +02:30
* argc , argv which are passes through .
*
* @ param domain_sid The domain sid acquired from the remote server
* @ param cli A cli_state connected to the server .
* @ param mem_ctx Talloc context , destoyed on completion of the function .
* @ param argc Standard main ( ) style argc
* @ param argv Standard main ( ) style argv . Initial components are already
* stripped
*
* @ return Normal NTSTATUS return .
* */
static NTSTATUS
rpc_share_list_internals ( const DOM_SID * domain_sid , struct cli_state * cli ,
TALLOC_CTX * mem_ctx , int argc , const char * * argv )
{
SRV_SHARE_INFO_CTR ctr ;
WERROR result ;
ENUM_HND hnd ;
uint32 preferred_len = 0xffffffff , i ;
init_enum_hnd ( & hnd , 0 ) ;
result = cli_srvsvc_net_share_enum (
cli , mem_ctx , 1 , & ctr , preferred_len , & hnd ) ;
if ( ! W_ERROR_IS_OK ( result ) )
goto done ;
/* Display results */
if ( opt_long_list_entries ) {
d_printf (
" \n Enumerating shared resources (exports) on remote server: \n \n " \
" \n Share name Type Description \n " \
" ---------- ---- ----------- \n " ) ;
}
for ( i = 0 ; i < ctr . num_entries ; i + + )
display_share_info_1 ( & ctr . share . info1 [ i ] ) ;
done :
return W_ERROR_IS_OK ( result ) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL ;
}
/**
* ' net rpc share ' entrypoint .
* @ param argc Standard main ( ) style argc
* @ param argv Standard main ( ) style argv . Initial components are already
* stripped
* */
int net_rpc_share ( int argc , const char * * argv )
{
struct functable func [ ] = {
{ " add " , rpc_share_add } ,
{ " delete " , rpc_share_delete } ,
{ NULL , NULL }
} ;
if ( argc = = 0 )
return run_rpc_command ( PIPE_SRVSVC , 0 ,
rpc_share_list_internals ,
argc , argv ) ;
return net_run_function ( argc , argv , func , rpc_share_usage ) ;
}
/****************************************************************************/
static int rpc_file_usage ( int argc , const char * * argv )
{
return net_help_file ( argc , argv ) ;
}
0001-01-01 02:30:17 +02:30
/**
* Close a file on a remote RPC server
*
* All paramaters are provided by the run_rpc_command function , except for
* argc , argv which are passes through .
*
* @ param domain_sid The domain sid acquired from the remote server
* @ param cli A cli_state connected to the server .
* @ param mem_ctx Talloc context , destoyed on completion of the function .
* @ param argc Standard main ( ) style argc
* @ param argv Standard main ( ) style argv . Initial components are already
* stripped
*
* @ return Normal NTSTATUS return .
* */
static NTSTATUS
rpc_file_close_internals ( const DOM_SID * domain_sid , struct cli_state * cli ,
TALLOC_CTX * mem_ctx , int argc , const char * * argv )
{
WERROR result ;
result = cli_srvsvc_net_file_close ( cli , mem_ctx , atoi ( argv [ 0 ] ) ) ;
return W_ERROR_IS_OK ( result ) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL ;
}
/**
* Close a file on a remote RPC server
*
* @ param argc Standard main ( ) style argc
* @ param argv Standard main ( ) style argv . Initial components are already
* stripped
*
* @ return A shell status integer ( 0 for success )
* */
static int rpc_file_close ( int argc , const char * * argv )
{
if ( argc < 1 ) {
DEBUG ( 1 , ( " No fileid given on close \n " ) ) ;
return ( rpc_file_usage ( argc , argv ) ) ;
}
return run_rpc_command ( PIPE_SRVSVC , 0 ,
rpc_file_close_internals ,
argc , argv ) ;
}
/**
* Formatted print of open file info
*
* @ param info3 FILE_INFO_3 contents
* @ param str3 strings for FILE_INFO_3
* */
0001-01-01 02:30:17 +02:30
static void display_file_info_3 ( FILE_INFO_3 * info3 , FILE_INFO_3_STR * str3 )
{
fstring user = " " , path = " " ;
rpcstr_pull_unistr2_fstring ( user , & str3 - > uni_user_name ) ;
rpcstr_pull_unistr2_fstring ( path , & str3 - > uni_path_name ) ;
d_printf ( " %-7.1d %-20.20s 0x%-4.2x %-6.1d %s \n " ,
info3 - > id , user , info3 - > perms , info3 - > num_locks , path ) ;
}
/**
* List open files on a remote RPC server
*
* All paramaters are provided by the run_rpc_command funcion , except for
* argc , argv which are passes through .
*
* @ param domain_sid The domain sid acquired from the remote server
* @ param cli A cli_state connected to the server .
* @ param mem_ctx Talloc context , destoyed on completion of the function .
* @ param argc Standard main ( ) style argc
* @ param argv Standard main ( ) style argv . Initial components are already
* stripped
*
* @ return Normal NTSTATUS return .
* */
static NTSTATUS
rpc_file_list_internals ( const DOM_SID * domain_sid , struct cli_state * cli ,
TALLOC_CTX * mem_ctx , int argc , const char * * argv )
{
SRV_FILE_INFO_CTR ctr ;
WERROR result ;
ENUM_HND hnd ;
uint32 preferred_len = 0xffffffff , i ;
0001-01-01 02:30:17 +02:30
char * username = NULL ;
0001-01-01 02:30:17 +02:30
init_enum_hnd ( & hnd , 0 ) ;
0001-01-01 02:30:17 +02:30
/* if argc > 0, must be user command */
if ( argc > 0 )
username = argv [ 0 ] ;
0001-01-01 02:30:17 +02:30
result = cli_srvsvc_net_file_enum (
0001-01-01 02:30:17 +02:30
cli , mem_ctx , 3 , username , & ctr , preferred_len , & hnd ) ;
0001-01-01 02:30:17 +02:30
if ( ! W_ERROR_IS_OK ( result ) )
goto done ;
/* Display results */
d_printf (
" \n Enumerating open files on remote server: \n \n " \
" \n FileId Opened by Perms Locks Path " \
" \n ------ --------- ----- ----- ---- \n " ) ;
for ( i = 0 ; i < ctr . num_entries ; i + + )
display_file_info_3 ( & ctr . file . info3 [ i ] . info_3 ,
& ctr . file . info3 [ i ] . info_3_str ) ;
done :
return W_ERROR_IS_OK ( result ) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL ;
}
0001-01-01 02:30:17 +02:30
/**
* List files for a user on a remote RPC server
*
* @ param argc Standard main ( ) style argc
* @ param argv Standard main ( ) style argv . Initial components are already
* stripped
*
* @ return A shell status integer ( 0 for success )
* */
static int rpc_file_user ( int argc , const char * * argv )
{
if ( argc < 1 ) {
DEBUG ( 1 , ( " No username given \n " ) ) ;
return ( rpc_file_usage ( argc , argv ) ) ;
}
return run_rpc_command ( PIPE_SRVSVC , 0 ,
rpc_file_list_internals ,
argc , argv ) ;
}
0001-01-01 02:30:17 +02:30
/**
* ' net rpc file ' entrypoint .
* @ param argc Standard main ( ) style argc
* @ param argv Standard main ( ) style argv . Initial components are already
* stripped
* */
int net_rpc_file ( int argc , const char * * argv )
{
struct functable func [ ] = {
{ " close " , rpc_file_close } ,
0001-01-01 02:30:17 +02:30
{ " user " , rpc_file_user } ,
#if 0
{ " info " , rpc_file_info } ,
0001-01-01 02:30:17 +02:30
# endif
{ NULL , NULL }
} ;
if ( argc = = 0 )
return run_rpc_command ( PIPE_SRVSVC , 0 ,
rpc_file_list_internals ,
argc , argv ) ;
return net_run_function ( argc , argv , func , rpc_file_usage ) ;
}
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
/****************************************************************************/
0001-01-01 02:30:17 +02:30
/**
0001-01-01 02:30:17 +02:30
* ABORT the shutdown of a remote RPC Server
*
0001-01-01 02:30:17 +02:30
* All paramaters are provided by the run_rpc_command function , except for
0001-01-01 02:30:17 +02:30
* argc , argv which are passed through .
*
* @ param domain_sid The domain sid aquired from the remote server
* @ param cli A cli_state connected to the server .
* @ param mem_ctx Talloc context , destoyed on compleation of the function .
* @ param argc Standard main ( ) style argc
0001-01-01 02:30:17 +02:30
* @ param argv Standard main ( ) style argv . Initial components are already
0001-01-01 02:30:17 +02:30
* stripped
*
* @ return Normal NTSTATUS return .
* */
static NTSTATUS rpc_shutdown_abort_internals ( const DOM_SID * domain_sid , struct cli_state * cli , TALLOC_CTX * mem_ctx ,
int argc , const char * * argv )
{
NTSTATUS result = NT_STATUS_UNSUCCESSFUL ;
result = cli_reg_abort_shutdown ( cli , mem_ctx ) ;
if ( NT_STATUS_IS_OK ( result ) )
DEBUG ( 5 , ( " cmd_reg_abort_shutdown: query succeeded \n " ) ) ;
else
DEBUG ( 5 , ( " cmd_reg_abort_shutdown: query failed \n " ) ) ;
return result ;
}
/**
* ABORT the Shut down of a remote RPC server
*
* @ param argc Standard main ( ) style argc
0001-01-01 02:30:17 +02:30
* @ param argv Standard main ( ) style argv . Initial components are already
0001-01-01 02:30:17 +02:30
* stripped
*
* @ return A shell status integer ( 0 for success )
* */
static int rpc_shutdown_abort ( int argc , const char * * argv )
{
return run_rpc_command ( PIPE_WINREG , 0 , rpc_shutdown_abort_internals ,
argc , argv ) ;
}
/**
* Shut down a remote RPC Server
*
* All paramaters are provided by the run_rpc_command funcion , except for
* argc , argv which are passes through .
*
* @ param domain_sid The domain sid aquired from the remote server
* @ param cli A cli_state connected to the server .
* @ param mem_ctx Talloc context , destoyed on compleation of the function .
* @ param argc Standard main ( ) style argc
* @ param argc Standard main ( ) style argv . Initial components are already
* stripped
*
* @ return Normal NTSTATUS return .
* */
static NTSTATUS rpc_shutdown_internals ( const DOM_SID * domain_sid , struct cli_state * cli , TALLOC_CTX * mem_ctx ,
int argc , const char * * argv )
{
NTSTATUS result = NT_STATUS_UNSUCCESSFUL ;
char * msg = " This machine will be shutdown shortly " ;
uint32 timeout = 20 ;
uint16 flgs = 0 ;
BOOL reboot = opt_reboot ;
BOOL force = opt_force ;
#if 0
poptContext pc ;
int rc ;
struct poptOption long_options [ ] = {
{ " message " , ' m ' , POPT_ARG_STRING , & msg } ,
{ " timeout " , ' t ' , POPT_ARG_INT , & timeout } ,
{ " reboot " , ' r ' , POPT_ARG_NONE , & reboot } ,
{ " force " , ' f ' , POPT_ARG_NONE , & force } ,
{ 0 , 0 , 0 , 0 }
} ;
pc = poptGetContext ( NULL , argc , ( const char * * ) argv , long_options ,
POPT_CONTEXT_KEEP_FIRST ) ;
rc = poptGetNextOpt ( pc ) ;
if ( rc < - 1 ) {
/* an error occurred during option processing */
DEBUG ( 0 , ( " %s: %s \n " ,
poptBadOption ( pc , POPT_BADOPTION_NOALIAS ) ,
poptStrerror ( rc ) ) ) ;
return NT_STATUS_INVALID_PARAMETER ;
}
# endif
if ( reboot ) {
flgs | = REG_REBOOT_ON_SHUTDOWN ;
}
if ( force ) {
flgs | = REG_FORCE_SHUTDOWN ;
}
if ( opt_comment ) {
msg = opt_comment ;
}
if ( opt_timeout ) {
timeout = opt_timeout ;
}
/* create an entry */
result = cli_reg_shutdown ( cli , mem_ctx , msg , timeout , flgs ) ;
if ( NT_STATUS_IS_OK ( result ) )
DEBUG ( 5 , ( " Shutdown of remote machine succeeded \n " ) ) ;
else
DEBUG ( 0 , ( " Shutdown of remote machine failed! \n " ) ) ;
return result ;
}
/**
* Shut down a remote RPC server
*
* @ param argc Standard main ( ) style argc
* @ param argc Standard main ( ) style argv . Initial components are already
* stripped
*
* @ return A shell status integer ( 0 for success )
* */
static int rpc_shutdown ( int argc , const char * * argv )
{
return run_rpc_command ( PIPE_WINREG , 0 , rpc_shutdown_internals ,
argc , argv ) ;
}
0001-01-01 02:30:17 +02:30
/***************************************************************************
NT Domain trusts code ( i . e . ' net rpc trustdom ' functionality )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
* Add interdomain trust account to the RPC server .
* All parameters ( except for argc and argv ) are passed by run_rpc_command
* function .
*
* @ param domain_sid The domain sid acquired from the server
* @ param cli A cli_state connected to the server .
* @ param mem_ctx Talloc context , destoyed on completion of the function .
* @ param argc Standard main ( ) style argc
* @ param argc Standard main ( ) style argv . Initial components are already
* stripped
*
* @ return normal NTSTATUS return code
*/
static NTSTATUS rpc_trustdom_add_internals ( const DOM_SID * domain_sid , struct cli_state * cli , TALLOC_CTX * mem_ctx ,
int argc , const char * * argv ) {
POLICY_HND connect_pol , domain_pol , user_pol ;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL ;
char * acct_name ;
uint16 acb_info ;
uint32 unknown , user_rid ;
if ( argc ! = 1 ) {
d_printf ( " Usage: net rpc trustdom add <domain_name> \n " ) ;
0001-01-01 02:30:17 +02:30
return NT_STATUS_INVALID_PARAMETER ;
0001-01-01 02:30:17 +02:30
}
/*
* Make valid trusting domain account ( ie . uppercased and with ' $ ' appended )
*/
if ( asprintf ( & acct_name , " %s$ " , argv [ 0 ] ) < 0 ) {
return NT_STATUS_NO_MEMORY ;
}
strupper ( acct_name ) ;
/* Get sam policy handle */
result = cli_samr_connect ( cli , mem_ctx , MAXIMUM_ALLOWED_ACCESS ,
& connect_pol ) ;
if ( ! NT_STATUS_IS_OK ( result ) ) {
goto done ;
}
/* Get domain policy handle */
result = cli_samr_open_domain ( cli , mem_ctx , & connect_pol ,
MAXIMUM_ALLOWED_ACCESS ,
domain_sid , & domain_pol ) ;
if ( ! NT_STATUS_IS_OK ( result ) ) {
goto done ;
}
/* Create trusting domain's account */
acb_info = ACB_DOMTRUST ;
unknown = 0xe005000b ; /* No idea what this is - a permission mask?
Is it needed for interdomain account also ? */
result = cli_samr_create_dom_user ( cli , mem_ctx , & domain_pol ,
acct_name , acb_info , unknown ,
& user_pol , & user_rid ) ;
if ( ! NT_STATUS_IS_OK ( result ) ) {
goto done ;
}
done :
SAFE_FREE ( acct_name ) ;
return result ;
}
/**
* Create interdomain trust account for a remote domain .
*
* @ param argc standard argc
* @ param argv standard argv without initial components
*
* @ return Integer status ( 0 means success )
* */
static int rpc_trustdom_add ( int argc , const char * * argv )
{
return run_rpc_command ( PIPE_SAMR , 0 , rpc_trustdom_add_internals ,
argc , argv ) ;
}
/**
* Delete interdomain trust account for a remote domain .
*
* @ param argc standard argc
* @ param argv standard argv without initial components
*
* @ return Integer status ( 0 means success )
* */
static int rpc_trustdom_del ( int argc , const char * * argv )
{
d_printf ( " Sorry, not yet implemented. \n " ) ;
return - 1 ;
}
/**
* Establish trust relationship to a trusting domain .
* Interdomain account must already be created on remote PDC .
*
* @ param argc standard argc
* @ param argv standard argv without initial components
*
* @ return Integer status ( 0 means success )
* */
extern char * opt_user_name ;
extern char * opt_password ;
static int rpc_trustdom_establish ( int argc , const char * * argv ) {
struct cli_state * cli ;
struct in_addr server_ip ;
POLICY_HND connect_hnd ;
TALLOC_CTX * mem_ctx ;
NTSTATUS nt_status ;
DOM_SID domain_sid ;
WKS_INFO_100 wks_info ;
char * domain_name ;
char * acct_name ;
fstring pdc_name ;
/*
* Connect to \ \ server \ ipc $ as ' our domain ' account with password
*/
0001-01-01 02:30:17 +02:30
if ( argc ! = 1 ) {
d_printf ( " Usage: net rpc trustdom add <domain_name> \n " ) ;
return - 1 ;
}
0001-01-01 02:30:17 +02:30
domain_name = smb_xstrdup ( argv [ 0 ] ) ;
strupper ( domain_name ) ;
asprintf ( & acct_name , " %s$ " , lp_workgroup ( ) ) ;
strupper ( acct_name ) ;
opt_user_name = ( char * ) malloc ( strlen ( acct_name ) + 1 ) ;
safe_strcpy ( opt_user_name , acct_name , strlen ( acct_name ) + 1 ) ;
/* find the domain controller */
if ( ! net_find_dc ( & server_ip , pdc_name , domain_name ) ) {
DEBUG ( 0 , ( " Coulnd find domain controller for domain %s \n " , domain_name ) ) ;
return - 1 ;
}
/* connect to ipc$ as username/password */
nt_status = connect_to_ipc ( & cli , & server_ip , pdc_name ) ;
if ( ! NT_STATUS_EQUAL ( nt_status , NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT ) ) {
/* Is it trusting domain account for sure ? */
DEBUG ( 0 , ( " Couldn't verify trusting domain account. Error was %s \n " ,
0001-01-01 02:30:17 +02:30
nt_errstr ( nt_status ) ) ) ;
0001-01-01 02:30:17 +02:30
return - 1 ;
}
/*
* Connect to \ \ server \ ipc $ again ( this time anonymously )
*/
nt_status = connect_to_ipc_anonymous ( & cli , & server_ip , ( char * ) pdc_name ) ;
if ( NT_STATUS_IS_ERR ( nt_status ) ) {
DEBUG ( 0 , ( " Couldn't connect to domain %s controller. Error was %s. \n " ,
0001-01-01 02:30:17 +02:30
domain_name , nt_errstr ( nt_status ) ) ) ;
0001-01-01 02:30:17 +02:30
}
/*
* Use NetServerEnum2 to make sure we ' re talking to a proper server
*/
if ( ! cli_get_pdc_name ( cli , domain_name , ( char * ) pdc_name ) ) {
DEBUG ( 0 , ( " NetServerEnum2 error: Couldn't find primary domain controller \
for domain % s \ n " , domain_name));
}
/*
* Call WksQueryInfo to check remote server ' s capabilities
* FIXME : Is really necessary ? nt serv does this , but from samba ' s
* point of view it doesn ' t seem to make the difference
* IDEA : It may be used to get info about type of pdc we ' re talking to
* ( e . g . WinNT or Win2k )
*/
if ( ! cli_nt_session_open ( cli , PIPE_WKSSVC ) ) {
DEBUG ( 0 , ( " Couldn't not initialise wkssvc pipe \n " ) ) ;
return - 1 ;
}
/* TODO: convert this call from rpc_client/cli_wkssvc.c
to cli_wks_query_info ( ) in libsmb / cli_wkssvc . c
UPDATE : already done : )
*/
if ( ! ( mem_ctx = talloc_init ( ) ) ) {
DEBUG ( 0 , ( " talloc_init() failed \n " ) ) ;
cli_shutdown ( cli ) ;
return - 1 ;
}
nt_status = cli_wks_query_info ( cli , mem_ctx , & wks_info ) ;
if ( NT_STATUS_IS_ERR ( nt_status ) ) {
DEBUG ( 0 , ( " WksQueryInfo call failed. \n " ) ) ;
return - 1 ;
}
0001-01-01 02:30:17 +02:30
if ( cli - > nt_pipe_fnum )
0001-01-01 02:30:17 +02:30
cli_nt_session_close ( cli ) ;
/*
* Call LsaOpenPolicy and LsaQueryInfo
*/
if ( ! ( mem_ctx = talloc_init ( ) ) ) {
DEBUG ( 0 , ( " talloc_init() failed \n " ) ) ;
cli_shutdown ( cli ) ;
return - 1 ;
}
if ( ! cli_nt_session_open ( cli , PIPE_LSARPC ) ) {
DEBUG ( 0 , ( " Could not initialise lsa pipe \n " ) ) ;
}
nt_status = cli_lsa_open_policy2 ( cli , mem_ctx , True , SEC_RIGHTS_QUERY_VALUE ,
& connect_hnd ) ;
if ( NT_STATUS_IS_ERR ( nt_status ) ) {
DEBUG ( 0 , ( " Couldn't open policy handle. Error was %s \n " ,
0001-01-01 02:30:17 +02:30
nt_errstr ( nt_status ) ) ) ;
0001-01-01 02:30:17 +02:30
return - 1 ;
}
/* Querying info level 5 */
nt_status = cli_lsa_query_info_policy ( cli , mem_ctx , & connect_hnd ,
5 /* info level */ , domain_name , & domain_sid ) ;
if ( NT_STATUS_IS_ERR ( nt_status ) ) {
DEBUG ( 0 , ( " LSA Query Info failed. Returned error was %s \n " ,
0001-01-01 02:30:17 +02:30
nt_errstr ( nt_status ) ) ) ;
0001-01-01 02:30:17 +02:30
return - 1 ;
}
/* There should be actually query info level 3 (following nt serv behaviour),
but I still don ' t know if it ' s _really_ necessary */
0001-01-01 02:30:17 +02:30
/*
* Store the password in secrets db
*/
if ( ! secrets_store_trusted_domain_password ( domain_name , wks_info . uni_lan_grp . buffer ,
wks_info . uni_lan_grp . uni_str_len , opt_password ,
domain_sid ) ) {
DEBUG ( 0 , ( " Storing password for trusted domain failed. \n " ) ) ;
return - 1 ;
}
0001-01-01 02:30:17 +02:30
/*
* Close the pipes and clean up
*/
nt_status = cli_lsa_close ( cli , mem_ctx , & connect_hnd ) ;
if ( NT_STATUS_IS_ERR ( nt_status ) ) {
DEBUG ( 0 , ( " Couldn't close LSA pipe. Error was %s \n " ,
0001-01-01 02:30:17 +02:30
nt_errstr ( nt_status ) ) ) ;
0001-01-01 02:30:17 +02:30
return - 1 ;
}
if ( cli - > nt_pipe_fnum )
cli_nt_session_close ( cli ) ;
0001-01-01 02:30:17 +02:30
talloc_destroy ( mem_ctx ) ;
0001-01-01 02:30:17 +02:30
DEBUG ( 0 , ( " Success! \n " ) ) ;
return 0 ;
}
/**
* Revoke trust relationship to the remote domain
*
* @ param argc standard argc
* @ param argv standard argv without initial components
*
* @ return Integer status ( 0 means success )
* */
static int rpc_trustdom_revoke ( int argc , const char * * argv ) {
char * domain_name ;
if ( argc < 1 ) return - 1 ;
/* generate upper cased domain name */
domain_name = smb_xstrdup ( argv [ 0 ] ) ;
strupper ( domain_name ) ;
/* delete password of the trust */
if ( ! trusted_domain_password_delete ( domain_name ) ) {
DEBUG ( 0 , ( " Failed to revoke relationship to the trusted domain %s \n " ,
domain_name ) ) ;
return - 1 ;
} ;
return 0 ;
}
/**
* Usage for ' net rpc trustdom ' command
*
* @ param argc standard argc
* @ param argv standard argv without inital components
*
* @ return Integer status returned to shell
* */
static int rpc_trustdom_usage ( int argc , const char * * argv ) {
d_printf ( " net rpc trustdom add \t \t add trusting domain's account \n " ) ;
d_printf ( " net rpc trustdom del \t \t delete trusting domain's account \n " ) ;
d_printf ( " net rpc trustdom establish \t establish relationship to trusted domain \n " ) ;
d_printf ( " net rpc trustdom revoke \t abandon relationship to trusted domain \n " ) ;
d_printf ( " net rpc trustdom list \t show current interdomain trust relationships \n " ) ;
return - 1 ;
}
/**
* Entrypoint for ' net rpc trustdom ' code
*
* @ param argc standard argc
* @ param argv standard argv without initial components
*
* @ return Integer status ( 0 means success )
*/
static int rpc_trustdom ( int argc , const char * * argv )
{
struct functable func [ ] = {
{ " add " , rpc_trustdom_add } ,
{ " del " , rpc_trustdom_del } ,
{ " establish " , rpc_trustdom_establish } ,
{ " revoke " , rpc_trustdom_revoke } ,
0001-01-01 02:30:17 +02:30
{ " help " , rpc_trustdom_usage } ,
0001-01-01 02:30:17 +02:30
{ NULL , NULL }
} ;
if ( argc = = 0 ) {
rpc_trustdom_usage ( argc , argv ) ;
return - 1 ;
}
return ( net_run_function ( argc , argv , func , rpc_user_usage ) ) ;
}
0001-01-01 02:30:17 +02:30
/**
* Check if a server will take rpc commands
* @ param flags Type of server to connect to ( PDC , DMB , localhost )
* if the host is not explicitly specified
* @ return BOOL ( true means rpc supported )
*/
BOOL net_rpc_check ( unsigned flags )
{
struct cli_state cli ;
BOOL ret = False ;
struct in_addr server_ip ;
char * server_name = NULL ;
/* flags (i.e. server type) may depend on command */
if ( ! net_find_server ( flags , & server_ip , & server_name ) )
goto done ;
ZERO_STRUCT ( cli ) ;
if ( cli_initialise ( & cli ) = = False )
return False ;
if ( ! cli_connect ( & cli , server_name , & server_ip ) )
goto done ;
if ( ! attempt_netbios_session_request ( & cli , global_myname ,
server_name , & server_ip ) )
goto done ;
if ( ! cli_negprot ( & cli ) )
goto done ;
if ( cli . protocol < PROTOCOL_NT1 )
goto done ;
ret = True ;
done :
cli_shutdown ( & cli ) ;
return ret ;
}
0001-01-01 02:30:17 +02:30
/****************************************************************************/
/**
* Basic usage function for ' net rpc '
0001-01-01 02:30:17 +02:30
* @ param argc Standard main ( ) style argc
0001-01-01 02:30:17 +02:30
* @ param argv Standard main ( ) style argv . Initial components are already
0001-01-01 02:30:17 +02:30
* stripped
* */
0001-01-01 02:30:17 +02:30
int net_rpc_usage ( int argc , const char * * argv )
{
0001-01-01 02:30:17 +02:30
d_printf ( " net rpc info \t \t \t show basic info about a domain \n " ) ;
0001-01-01 02:30:17 +02:30
d_printf ( " net rpc join \t \t \t to join a domain \n " ) ;
d_printf ( " net rpc user \t \t \t to add, delete and list users \n " ) ;
0001-01-01 02:30:17 +02:30
d_printf ( " net rpc group \t \t to list groups \n " ) ;
0001-01-01 02:30:17 +02:30
d_printf ( " net rpc share \t \t to add, delete, and list shares \n " ) ;
0001-01-01 02:30:17 +02:30
d_printf ( " net rpc file \t \t \t to list open files \n " ) ;
0001-01-01 02:30:17 +02:30
d_printf ( " net rpc changetrustpw \t to change the trust account password \n " ) ;
0001-01-01 02:30:17 +02:30
d_printf ( " net rpc trustdom \t \t to create trusting domain's account \n "
" \t \t \t \t \t or establish trust \n " ) ;
d_printf ( " net rpc abortshutdown \t to abort the shutdown of a remote server \n " ) ;
d_printf ( " net rpc shutdown \t \t to shutdown a remote server \n " ) ;
0001-01-01 02:30:17 +02:30
d_printf ( " \n " ) ;
d_printf ( " 'net rpc shutdown' also accepts the following miscellaneous options: \n " ) ; /* misc options */
d_printf ( " \t -r or --reboot \t request remote server reboot on shutdown \n " ) ;
d_printf ( " \t -f or --force \t request the remote server force its shutdown \n " ) ;
d_printf ( " \t -t or --timeout=<timeout> \t number of seconds before shutdown \n " ) ;
d_printf ( " \t -c or --comment=<message> \t text message to display on impending shutdown \n " ) ;
0001-01-01 02:30:17 +02:30
return - 1 ;
}
0001-01-01 02:30:17 +02:30
/**
* Help function for ' net rpc ' . Calls command specific help if requested
* or displays usage of net rpc
* @ param argc Standard main ( ) style argc
* @ param argv Standard main ( ) style argv . Initial components are already
* stripped
* */
0001-01-01 02:30:17 +02:30
int net_rpc_help ( int argc , const char * * argv )
0001-01-01 02:30:17 +02:30
{
struct functable func [ ] = {
{ " join " , rpc_join_usage } ,
0001-01-01 02:30:17 +02:30
{ " user " , rpc_user_usage } ,
{ " group " , rpc_group_usage } ,
{ " share " , rpc_share_usage } ,
0001-01-01 02:30:17 +02:30
/*{"changetrustpw", rpc_changetrustpw_usage}, */
0001-01-01 02:30:17 +02:30
{ " trustdom " , rpc_trustdom_usage } ,
0001-01-01 02:30:17 +02:30
/*{"abortshutdown", rpc_shutdown_abort_usage},*/
/*{"shutdown", rpc_shutdown_usage}, */
0001-01-01 02:30:17 +02:30
{ NULL , NULL }
} ;
if ( argc = = 0 ) {
net_rpc_usage ( argc , argv ) ;
return - 1 ;
}
return ( net_run_function ( argc , argv , func , rpc_user_usage ) ) ;
}
0001-01-01 02:30:17 +02:30
/**
0001-01-01 02:30:17 +02:30
* ' net rpc ' entrypoint .
0001-01-01 02:30:17 +02:30
* @ param argc Standard main ( ) style argc
0001-01-01 02:30:17 +02:30
* @ param argv Standard main ( ) style argv . Initial components are already
0001-01-01 02:30:17 +02:30
* stripped
* */
0001-01-01 02:30:17 +02:30
int net_rpc ( int argc , const char * * argv )
{
struct functable func [ ] = {
0001-01-01 02:30:17 +02:30
{ " info " , net_rpc_info } ,
0001-01-01 02:30:17 +02:30
{ " join " , net_rpc_join } ,
0001-01-01 02:30:17 +02:30
{ " user " , net_rpc_user } ,
0001-01-01 02:30:17 +02:30
{ " group " , net_rpc_group } ,
0001-01-01 02:30:17 +02:30
{ " share " , net_rpc_share } ,
{ " file " , net_rpc_file } ,
0001-01-01 02:30:17 +02:30
{ " changetrustpw " , rpc_changetrustpw } ,
0001-01-01 02:30:17 +02:30
{ " trustdom " , rpc_trustdom } ,
0001-01-01 02:30:17 +02:30
{ " abortshutdown " , rpc_shutdown_abort } ,
{ " shutdown " , rpc_shutdown } ,
0001-01-01 02:30:17 +02:30
{ " help " , net_rpc_help } ,
0001-01-01 02:30:17 +02:30
{ NULL , NULL }
} ;
return net_run_function ( argc , argv , func , net_rpc_usage ) ;
}