0001-01-01 02:30:17 +02:30
/*
Samba Unix / Linux SMB client library
Version 3.0
Distributed SMB / CIFS Server Management Utility
Copyright ( C ) 2001 Andrew Bartlett ( abartlet @ samba . org )
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
/**
* @ 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
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 ) ) ) ) {
DEBUG ( 0 , ( " fetch_domain_sid: malloc returned NULL! \n " ) ) ;
goto error ;
}
if ( ! ( mem_ctx = talloc_init ( ) ) )
{
DEBUG ( 0 , ( " fetch_domain_sid: talloc_init returned NULL! \n " ) ) ;
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 ) ) {
fprintf ( stderr , " error: %s \n " , get_nt_error_msg ( result ) ) ;
}
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
DEBUG ( 5 , ( " rpc command function returned %s \n " , get_nt_error_msg ( nt_status ) ) ) ;
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 ) ;
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 rpc_join_oldstyle ( int argc , const char * * argv )
{
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 )
{
d_printf ( " net rpc join \t to join a domain with admin username & password \n " ) ;
d_printf ( " net rpc join oldstyle \t to join a domain created in server manager \n " ) ;
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
static int rpc_join ( int argc , const char * * argv )
{
struct functable func [ ] = {
{ " oldstyle " , rpc_join_oldstyle } ,
{ NULL , NULL }
} ;
if ( argc = = 0 ) {
return net_rpc_join ( argc , argv ) ;
}
return net_run_function ( argc , argv , func , rpc_join_usage ) ;
}
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 .
*
* @ 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_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 ) {
d_printf ( " Usage: net rpc user add username \n " ) ;
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 :
return result ;
}
/**
* Add a new user to 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 )
* */
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
/**
* 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_user_usage ( int argc , const char * * argv )
{
d_printf ( " net rpc user add \t to add a user \n " ) ;
return - 1 ;
}
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
static int rpc_user ( int argc , const char * * argv )
{
struct functable func [ ] = {
{ " add " , rpc_user_add } ,
{ NULL , NULL }
} ;
if ( argc = = 0 ) {
rpc_user_usage ( argc , argv ) ;
}
return net_run_function ( argc , argv , func , rpc_user_usage ) ;
}
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
int net_rpc_usage ( int argc , const char * * argv )
{
0001-01-01 02:30:17 +02:30
d_printf ( " net rpc join \t to join a domain \n " ) ;
d_printf ( " net rpc user \t to add, delete and list users \n " ) ;
d_printf ( " net rpc changetrustpw \t to change the trust account password \n " ) ;
0001-01-01 02:30:17 +02:30
return - 1 ;
}
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 ( int argc , const char * * argv )
{
struct functable func [ ] = {
0001-01-01 02:30:17 +02:30
{ " join " , rpc_join } ,
0001-01-01 02:30:17 +02:30
{ " user " , rpc_user } ,
0001-01-01 02:30:17 +02:30
{ " changetrustpw " , rpc_changetrustpw } ,
0001-01-01 02:30:17 +02:30
{ NULL , NULL }
} ;
return net_run_function ( argc , argv , func , net_rpc_usage ) ;
}