0001-01-01 02:30:17 +02:30
/*
Unix SMB / Netbios implementation .
Version 2.2
RPC pipe client
Copyright ( C ) Tim Potter 2001
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"
/* Synchronise sam database */
0001-01-01 02:30:17 +02:30
static NTSTATUS sam_sync ( struct cli_state * cli , unsigned char trust_passwd [ 16 ] ,
BOOL do_smbpasswd_output )
0001-01-01 02:30:17 +02:30
{
TALLOC_CTX * mem_ctx ;
SAM_DELTA_HDR * hdr_deltas ;
SAM_DELTA_CTR * deltas ;
0001-01-01 02:30:17 +02:30
uint32 database_id = 0 , num_deltas ;
NTSTATUS result = NT_STATUS_UNSUCCESSFUL ;
/* Initialise */
0001-01-01 02:30:17 +02:30
if ( ! ( mem_ctx = talloc_init ( ) ) ) {
DEBUG ( 0 , ( " talloc_init failed \n " ) ) ;
return result ;
}
if ( ! cli_nt_session_open ( cli , PIPE_NETLOGON ) ) {
DEBUG ( 0 , ( " Could not initialize netlogon pipe! \n " ) ) ;
goto done ;
}
0001-01-01 02:30:17 +02:30
/* Request a challenge */
if ( ! NT_STATUS_IS_OK ( new_cli_nt_setup_creds ( cli , trust_passwd ) ) ) {
DEBUG ( 0 , ( " Error initialising session creds \n " ) ) ;
goto done ;
}
/* Do sam synchronisation */
result = cli_netlogon_sam_sync ( cli , mem_ctx , database_id ,
& num_deltas , & hdr_deltas , & deltas ) ;
if ( ! NT_STATUS_IS_OK ( result ) ) {
0001-01-01 02:30:17 +02:30
goto done ;
}
0001-01-01 02:30:17 +02:30
/* Produce smbpasswd output - good for migrating from NT! */
if ( do_smbpasswd_output ) {
int i ;
for ( i = 0 ; i < num_deltas ; i + + ) {
0001-01-01 02:30:17 +02:30
SAM_ACCOUNT_INFO * a ;
0001-01-01 02:30:17 +02:30
fstring acct_name , hex_nt_passwd , hex_lm_passwd ;
uchar lm_passwd [ 16 ] , nt_passwd [ 16 ] ;
0001-01-01 02:30:17 +02:30
/* Skip non-user accounts */
if ( hdr_deltas [ i ] . type ! = SAM_DELTA_ACCOUNT_INFO )
continue ;
0001-01-01 02:30:17 +02:30
a = & deltas [ i ] . account_info ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
unistr2_to_ascii ( acct_name , & a - > uni_acct_name ,
0001-01-01 02:30:17 +02:30
sizeof ( acct_name ) - 1 ) ;
0001-01-01 02:30:17 +02:30
/* Decode hashes from password hash */
0001-01-01 02:30:17 +02:30
sam_pwd_hash ( a - > user_rid , a - > pass . buf_lm_pwd ,
0001-01-01 02:30:17 +02:30
lm_passwd , 0 ) ;
0001-01-01 02:30:17 +02:30
sam_pwd_hash ( a - > user_rid , a - > pass . buf_nt_pwd ,
0001-01-01 02:30:17 +02:30
nt_passwd , 0 ) ;
/* Encode as strings */
smbpasswd_sethexpwd ( hex_lm_passwd , lm_passwd ,
0001-01-01 02:30:17 +02:30
a - > acb_info ) ;
0001-01-01 02:30:17 +02:30
smbpasswd_sethexpwd ( hex_nt_passwd , nt_passwd ,
0001-01-01 02:30:17 +02:30
a - > acb_info ) ;
0001-01-01 02:30:17 +02:30
/* Display user info */
printf ( " %s:%d:%s:%s:%s:LCT-0 \n " , acct_name ,
0001-01-01 02:30:17 +02:30
a - > user_rid , hex_lm_passwd , hex_nt_passwd ,
0001-01-01 02:30:17 +02:30
smbpasswd_encode_acb_info (
deltas [ i ] . account_info . acb_info ) ) ;
}
goto done ;
}
/* Update sam tdb */
0001-01-01 02:30:17 +02:30
done :
cli_nt_session_close ( cli ) ;
talloc_destroy ( mem_ctx ) ;
return result ;
}
/* Replicate sam deltas */
0001-01-01 02:30:17 +02:30
static NTSTATUS sam_repl ( struct cli_state * cli , unsigned char trust_passwde [ 16 ] ,
uint32 low_serial )
0001-01-01 02:30:17 +02:30
{
0001-01-01 02:30:17 +02:30
NTSTATUS result = NT_STATUS_UNSUCCESSFUL ;
0001-01-01 02:30:17 +02:30
0001-01-01 02:30:17 +02:30
return result ;
0001-01-01 02:30:17 +02:30
}
/* Print usage information */
static void usage ( void )
{
printf ( " Usage: samsync [options] \n " ) ;
printf ( " \t -d debuglevel set the debuglevel \n " ) ;
printf ( " \t -h Print this help message. \n " ) ;
printf ( " \t -s configfile specify an alternative config file \n " ) ;
printf ( " \t -S synchronise sam database \n " ) ;
printf ( " \t -R replicate sam deltas \n " ) ;
0001-01-01 02:30:17 +02:30
printf ( " \t -U username username and password \n " ) ;
printf ( " \t -p produce smbpasswd output \n " ) ;
0001-01-01 02:30:17 +02:30
printf ( " \n " ) ;
}
/* Initialise client credentials for authenticated pipe access */
void init_rpcclient_creds ( struct ntuser_creds * creds , char * username ,
char * domain , char * password )
{
ZERO_STRUCTP ( creds ) ;
if ( lp_encrypted_passwords ( ) ) {
pwd_make_lm_nt_16 ( & creds - > pwd , password ) ;
} else {
pwd_set_cleartext ( & creds - > pwd , password ) ;
}
fstrcpy ( creds - > user_name , username ) ;
fstrcpy ( creds - > domain , domain ) ;
if ( ! * username ) {
creds - > pwd . null_pwd = True ;
}
}
/* Connect to primary domain controller */
0001-01-01 02:30:17 +02:30
static struct cli_state * init_connection ( struct cli_state * cli ,
char * username , char * domain ,
char * password )
0001-01-01 02:30:17 +02:30
{
struct ntuser_creds creds ;
extern pstring global_myname ;
struct in_addr * dest_ip ;
struct nmb_name calling , called ;
int count ;
fstring dest_host ;
/* Initialise cli_state information */
ZERO_STRUCTP ( cli ) ;
if ( ! cli_initialise ( cli ) ) {
return NULL ;
}
0001-01-01 02:30:17 +02:30
init_rpcclient_creds ( & creds , username , domain , password ) ;
0001-01-01 02:30:17 +02:30
cli_init_creds ( cli , & creds ) ;
/* Look up name of PDC controller */
if ( ! get_dc_list ( True , lp_workgroup ( ) , & dest_ip , & count ) ) {
DEBUG ( 0 , ( " Cannot find domain controller for domain %s \n " ,
lp_workgroup ( ) ) ) ;
return NULL ;
}
0001-01-01 02:30:17 +02:30
if ( ! lookup_dc_name ( global_myname , lp_workgroup ( ) , dest_ip ,
dest_host ) ) {
0001-01-01 02:30:17 +02:30
DEBUG ( 0 , ( " Could not lookup up PDC name for domain %s \n " ,
lp_workgroup ( ) ) ) ;
return NULL ;
}
get_myname ( ( * global_myname ) ? NULL : global_myname ) ;
strupper ( global_myname ) ;
make_nmb_name ( & called , dns_to_netbios_name ( dest_host ) , 0x20 ) ;
make_nmb_name ( & calling , dns_to_netbios_name ( global_myname ) , 0 ) ;
/* Establish a SMB connection */
if ( ! cli_establish_connection ( cli , dest_host , dest_ip , & calling ,
& called , " IPC$ " , " IPC " , False , True ) ) {
return NULL ;
}
return cli ;
}
/* Main function */
int main ( int argc , char * * argv )
{
BOOL do_sam_sync = False , do_sam_repl = False ;
struct cli_state cli ;
0001-01-01 02:30:17 +02:30
NTSTATUS result ;
int opt ;
0001-01-01 02:30:17 +02:30
extern pstring debugf ;
0001-01-01 02:30:17 +02:30
BOOL interactive = False , do_smbpasswd_output = False ;
0001-01-01 02:30:17 +02:30
uint32 low_serial = 0 ;
unsigned char trust_passwd [ 16 ] ;
0001-01-01 02:30:17 +02:30
fstring username , domain , password ;
0001-01-01 02:30:17 +02:30
if ( argc = = 1 ) {
usage ( ) ;
return 1 ;
}
0001-01-01 02:30:17 +02:30
ZERO_STRUCT ( username ) ;
ZERO_STRUCT ( domain ) ;
ZERO_STRUCT ( password ) ;
0001-01-01 02:30:17 +02:30
/* Parse command line options */
0001-01-01 02:30:17 +02:30
while ( ( opt = getopt ( argc , argv , " s:d:SR:hiU:W:p " ) ) ! = EOF ) {
0001-01-01 02:30:17 +02:30
switch ( opt ) {
case ' s ' :
0001-01-01 02:30:17 +02:30
pstrcpy ( dyn_CONFIGFILE , optarg ) ;
0001-01-01 02:30:17 +02:30
break ;
case ' d ' :
DEBUGLEVEL = atoi ( optarg ) ;
break ;
case ' S ' :
do_sam_sync = 1 ;
break ;
case ' R ' :
do_sam_repl = 1 ;
low_serial = atoi ( optarg ) ;
break ;
case ' i ' :
interactive = True ;
break ;
0001-01-01 02:30:17 +02:30
case ' U ' : {
char * lp ;
fstrcpy ( username , optarg ) ;
if ( ( lp = strchr_m ( username , ' % ' ) ) ) {
* lp = 0 ;
fstrcpy ( password , lp + 1 ) ;
memset ( strchr_m ( optarg , ' % ' ) + 1 , ' X ' ,
strlen ( password ) ) ;
}
break ;
}
case ' W ' :
pstrcpy ( domain , optarg ) ;
break ;
case ' p ' :
do_smbpasswd_output = True ;
break ;
0001-01-01 02:30:17 +02:30
case ' h ' :
default :
usage ( ) ;
exit ( 1 ) ;
}
}
argc - = optind ;
if ( argc > 0 ) {
usage ( ) ;
return 1 ;
}
/* Initialise samba */
0001-01-01 02:30:17 +02:30
slprintf ( debugf , sizeof ( debugf ) - 1 , " %s/log.%s " , dyn_LOGFILEBASE ,
0001-01-01 02:30:17 +02:30
" samsync " ) ;
setup_logging ( " samsync " , interactive ) ;
if ( ! interactive )
reopen_logs ( ) ;
0001-01-01 02:30:17 +02:30
if ( ! lp_load ( dyn_CONFIGFILE , True , False , False ) ) {
fprintf ( stderr , " Can't load %s \n " , dyn_CONFIGFILE ) ;
0001-01-01 02:30:17 +02:30
}
load_interfaces ( ) ;
/* Check arguments make sense */
if ( do_sam_sync & & do_sam_repl ) {
fprintf ( stderr , " cannot specify both -S and -R \n " ) ;
return 1 ;
}
if ( ! do_sam_sync & & ! do_sam_repl ) {
fprintf ( stderr , " must specify either -S or -R \n " ) ;
return 1 ;
}
if ( do_sam_repl & & low_serial = = 0 ) {
fprintf ( stderr , " serial number must be positive \n " ) ;
return 1 ;
}
/* BDC operations require the machine account password */
if ( ! secrets_init ( ) ) {
DEBUG ( 0 , ( " Unable to initialise secrets database \n " ) ) ;
return 1 ;
}
if ( ! secrets_fetch_trust_account_password ( lp_workgroup ( ) ,
trust_passwd , NULL ) ) {
DEBUG ( 0 , ( " could not fetch trust account password \n " ) ) ;
return 1 ;
}
/* Perform sync or replication */
0001-01-01 02:30:17 +02:30
if ( ! init_connection ( & cli , username , domain , password ) )
0001-01-01 02:30:17 +02:30
return 1 ;
if ( do_sam_sync )
0001-01-01 02:30:17 +02:30
result = sam_sync ( & cli , trust_passwd , do_smbpasswd_output ) ;
0001-01-01 02:30:17 +02:30
if ( do_sam_repl )
result = sam_repl ( & cli , trust_passwd , low_serial ) ;
0001-01-01 02:30:17 +02:30
if ( ! NT_STATUS_IS_OK ( result ) ) {
DEBUG ( 0 , ( " %s \n " , get_nt_error_msg ( result ) ) ) ;
return 1 ;
}
return 0 ;
0001-01-01 02:30:17 +02:30
}