2002-08-23 02:48:54 +04:00
/*
Unix SMB / CIFS implementation .
dump the remote SAM using rpc samsync operations
Copyright ( C ) Andrew Tridgell 2002
Copyright ( C ) Tim Potter 2001 , 2002
2002-10-01 22:26:00 +04:00
Modified by Volker Lendecke 2002
2002-08-23 02:48:54 +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
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include "includes.h"
# include "../utils/net.h"
2002-09-24 10:50:11 +04:00
extern DOM_SID global_sid_Builtin ;
2002-08-23 02:48:54 +04:00
static void display_group_mem_info ( uint32 rid , SAM_GROUP_MEM_INFO * g )
{
int i ;
d_printf ( " Group mem %u: " , rid ) ;
for ( i = 0 ; i < g - > num_members ; i + + ) {
d_printf ( " %u " , g - > rids [ i ] ) ;
}
d_printf ( " \n " ) ;
}
static void display_alias_info ( uint32 rid , SAM_ALIAS_INFO * a )
{
d_printf ( " Alias '%s' " , unistr2_static ( & a - > uni_als_name ) ) ;
d_printf ( " desc='%s' rid=%u \n " , unistr2_static ( & a - > uni_als_desc ) , a - > als_rid ) ;
}
static void display_alias_mem ( uint32 rid , SAM_ALIAS_MEM_INFO * a )
{
int i ;
d_printf ( " Alias rid %u: " , rid ) ;
2002-08-29 12:00:15 +04:00
for ( i = 0 ; i < a - > num_members ; i + + ) {
2002-08-23 02:48:54 +04:00
d_printf ( " %s " , sid_string_static ( & a - > sids [ i ] . sid ) ) ;
}
d_printf ( " \n " ) ;
}
static void display_account_info ( uint32 rid , SAM_ACCOUNT_INFO * a )
{
fstring hex_nt_passwd , hex_lm_passwd ;
uchar lm_passwd [ 16 ] , nt_passwd [ 16 ] ;
2002-11-10 06:07:19 +03:00
static uchar zero_buf [ 16 ] ;
2002-08-23 02:48:54 +04:00
2002-11-10 06:07:19 +03:00
/* Decode hashes from password hash (if they are not NULL) */
2002-08-23 02:48:54 +04:00
2002-11-10 06:07:19 +03:00
if ( memcmp ( a - > pass . buf_lm_pwd , zero_buf , 16 ) ! = 0 ) {
sam_pwd_hash ( a - > user_rid , a - > pass . buf_lm_pwd , lm_passwd , 0 ) ;
smbpasswd_sethexpwd ( hex_lm_passwd , lm_passwd , a - > acb_info ) ;
} else {
smbpasswd_sethexpwd ( hex_lm_passwd , NULL , 0 ) ;
}
if ( memcmp ( a - > pass . buf_nt_pwd , zero_buf , 16 ) ! = 0 ) {
sam_pwd_hash ( a - > user_rid , a - > pass . buf_nt_pwd , nt_passwd , 0 ) ;
smbpasswd_sethexpwd ( hex_nt_passwd , nt_passwd , a - > acb_info ) ;
} else {
smbpasswd_sethexpwd ( hex_nt_passwd , NULL , 0 ) ;
}
2002-08-23 02:48:54 +04:00
printf ( " %s:%d:%s:%s:%s:LCT-0 \n " , unistr2_static ( & a - > uni_acct_name ) ,
a - > user_rid , hex_lm_passwd , hex_nt_passwd ,
smbpasswd_encode_acb_info ( a - > acb_info ) ) ;
}
2002-08-29 14:36:05 +04:00
static void display_domain_info ( SAM_DOMAIN_INFO * a )
{
d_printf ( " Domain name: %s \n " , unistr2_static ( & a - > uni_dom_name ) ) ;
}
static void display_group_info ( uint32 rid , SAM_GROUP_INFO * a )
{
d_printf ( " Group '%s' " , unistr2_static ( & a - > uni_grp_name ) ) ;
d_printf ( " desc='%s', rid=%u \n " , unistr2_static ( & a - > uni_grp_desc ) , rid ) ;
}
2002-08-23 02:48:54 +04:00
static void display_sam_entry ( SAM_DELTA_HDR * hdr_delta , SAM_DELTA_CTR * delta )
{
switch ( hdr_delta - > type ) {
case SAM_DELTA_ACCOUNT_INFO :
display_account_info ( hdr_delta - > target_rid , & delta - > account_info ) ;
break ;
case SAM_DELTA_GROUP_MEM :
display_group_mem_info ( hdr_delta - > target_rid , & delta - > grp_mem_info ) ;
break ;
case SAM_DELTA_ALIAS_INFO :
display_alias_info ( hdr_delta - > target_rid , & delta - > alias_info ) ;
break ;
case SAM_DELTA_ALIAS_MEM :
display_alias_mem ( hdr_delta - > target_rid , & delta - > als_mem_info ) ;
break ;
2002-08-29 14:36:05 +04:00
case SAM_DELTA_DOMAIN_INFO :
display_domain_info ( & delta - > domain_info ) ;
break ;
case SAM_DELTA_GROUP_INFO :
display_group_info ( hdr_delta - > target_rid , & delta - > group_info ) ;
break ;
2003-03-23 05:22:41 +03:00
/* The following types are recognised but not handled */
case SAM_DELTA_RENAME_GROUP :
d_printf ( " SAM_DELTA_RENAME_GROUP not handled \n " ) ;
break ;
case SAM_DELTA_RENAME_USER :
d_printf ( " SAM_DELTA_RENAME_USER not handled \n " ) ;
break ;
case SAM_DELTA_RENAME_ALIAS :
d_printf ( " SAM_DELTA_RENAME_ALIAS not handled \n " ) ;
break ;
case SAM_DELTA_POLICY_INFO :
d_printf ( " SAM_DELTA_POLICY_INFO not handled \n " ) ;
break ;
case SAM_DELTA_TRUST_DOMS :
d_printf ( " SAM_DELTA_TRUST_DOMS not handled \n " ) ;
break ;
case SAM_DELTA_PRIVS_INFO :
d_printf ( " SAM_DELTA_PRIVS_INFO not handled \n " ) ;
break ;
case SAM_DELTA_SECRET_INFO :
d_printf ( " SAM_DELTA_SECRET_INFO not handled \n " ) ;
break ;
case SAM_DELTA_DELETE_GROUP :
d_printf ( " SAM_DELTA_DELETE_GROUP not handled \n " ) ;
break ;
case SAM_DELTA_DELETE_USER :
d_printf ( " SAM_DELTA_DELETE_USER not handled \n " ) ;
break ;
case SAM_DELTA_MODIFIED_COUNT :
d_printf ( " SAM_DELTA_MODIFIED_COUNT not handled \n " ) ;
break ;
2002-08-23 02:48:54 +04:00
default :
d_printf ( " Unknown delta record type %d \n " , hdr_delta - > type ) ;
break ;
}
}
2002-08-29 12:00:15 +04:00
static void dump_database ( struct cli_state * cli , unsigned db_type , DOM_CRED * ret_creds )
2002-08-23 02:48:54 +04:00
{
2002-11-02 06:47:48 +03:00
unsigned sync_context = 0 ;
2002-08-29 12:00:15 +04:00
NTSTATUS result ;
int i ;
TALLOC_CTX * mem_ctx ;
2002-08-23 02:48:54 +04:00
SAM_DELTA_HDR * hdr_deltas ;
SAM_DELTA_CTR * deltas ;
uint32 num_deltas ;
2002-08-29 12:00:15 +04:00
2002-12-20 23:21:31 +03:00
if ( ! ( mem_ctx = talloc_init ( " dump_database " ) ) ) {
2002-08-29 12:00:15 +04:00
return ;
}
2003-03-23 05:22:41 +03:00
switch ( db_type ) {
case SAM_DATABASE_DOMAIN :
d_printf ( " Dumping DOMAIN database \n " ) ;
break ;
case SAM_DATABASE_BUILTIN :
d_printf ( " Dumping BUILTIN database \n " ) ;
break ;
case SAM_DATABASE_PRIVS :
d_printf ( " Dumping PRIVS databases \n " ) ;
break ;
default :
d_printf ( " Dumping unknown database type %u \n " , db_type ) ;
break ;
}
2002-08-29 12:00:15 +04:00
do {
2002-11-02 06:47:48 +03:00
result = cli_netlogon_sam_sync ( cli , mem_ctx , ret_creds , db_type ,
sync_context ,
2002-08-29 12:00:15 +04:00
& num_deltas , & hdr_deltas , & deltas ) ;
clnt_deal_with_creds ( cli - > sess_key , & ( cli - > clnt_cred ) , ret_creds ) ;
for ( i = 0 ; i < num_deltas ; i + + ) {
display_sam_entry ( & hdr_deltas [ i ] , & deltas [ i ] ) ;
}
2002-11-02 06:47:48 +03:00
sync_context + = 1 ;
} while ( NT_STATUS_EQUAL ( result , STATUS_MORE_ENTRIES ) ) ;
2002-08-29 12:00:15 +04:00
talloc_destroy ( mem_ctx ) ;
}
/* dump sam database via samsync rpc calls */
int rpc_samdump ( int argc , const char * * argv )
{
2002-08-23 02:48:54 +04:00
struct cli_state * cli = NULL ;
uchar trust_password [ 16 ] ;
2002-08-29 12:00:15 +04:00
DOM_CRED ret_creds ;
2003-04-21 18:09:03 +04:00
uint32 sec_channel ;
2002-08-29 12:00:15 +04:00
ZERO_STRUCT ( ret_creds ) ;
2002-08-23 02:48:54 +04:00
/* Connect to remote machine */
if ( ! ( cli = net_make_ipc_connection ( NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC ) ) ) {
return 1 ;
}
2003-04-09 19:54:17 +04:00
fstrcpy ( cli - > domain , lp_workgroup ( ) ) ;
2002-08-23 02:48:54 +04:00
2003-05-08 12:02:52 +04:00
if ( ! cli_nt_session_open ( cli , PI_NETLOGON ) ) {
DEBUG ( 0 , ( " Could not open connection to NETLOGON pipe \n " ) ) ;
goto fail ;
}
2003-04-09 19:54:17 +04:00
if ( ! secrets_fetch_trust_account_password ( lp_workgroup ( ) ,
trust_password ,
2003-04-21 18:09:03 +04:00
NULL , & sec_channel ) ) {
2003-04-09 19:54:17 +04:00
DEBUG ( 0 , ( " Could not fetch trust account password \n " ) ) ;
2002-08-23 02:48:54 +04:00
goto fail ;
}
2003-04-09 19:54:17 +04:00
2003-05-08 12:02:52 +04:00
if ( ! NT_STATUS_IS_OK ( cli_nt_establish_netlogon ( cli , sec_channel ,
trust_password ) ) ) {
2003-04-09 19:54:17 +04:00
DEBUG ( 0 , ( " Error connecting to NETLOGON pipe \n " ) ) ;
2002-08-23 02:48:54 +04:00
goto fail ;
}
2002-08-29 12:00:15 +04:00
dump_database ( cli , SAM_DATABASE_DOMAIN , & ret_creds ) ;
dump_database ( cli , SAM_DATABASE_BUILTIN , & ret_creds ) ;
2002-09-22 14:30:00 +04:00
dump_database ( cli , SAM_DATABASE_PRIVS , & ret_creds ) ;
2002-08-23 02:48:54 +04:00
cli_nt_session_close ( cli ) ;
return 0 ;
fail :
if ( cli ) {
cli_nt_session_close ( cli ) ;
}
return - 1 ;
}
2002-09-18 10:34:10 +04:00
/* Convert a SAM_ACCOUNT_DELTA to a SAM_ACCOUNT. */
2003-03-23 05:22:41 +03:00
# define STRING_CHANGED (old_string && !new_string) ||\
( ! old_string & & new_string ) | | \
( old_string & & new_string & & ( strcmp ( old_string , new_string ) ! = 0 ) )
2002-09-18 10:34:10 +04:00
static NTSTATUS
sam_account_from_delta ( SAM_ACCOUNT * account , SAM_ACCOUNT_INFO * delta )
{
2003-03-23 05:22:41 +03:00
const char * old_string , * new_string ;
time_t unix_time , stored_time ;
2002-09-24 10:50:11 +04:00
uchar lm_passwd [ 16 ] , nt_passwd [ 16 ] ;
2002-11-10 06:07:19 +03:00
static uchar zero_buf [ 16 ] ;
2002-09-18 10:34:10 +04:00
/* Username, fullname, home dir, dir drive, logon script, acct
desc , workstations , profile . */
2003-03-23 05:22:41 +03:00
if ( delta - > hdr_acct_name . buffer ) {
old_string = pdb_get_nt_username ( account ) ;
new_string = unistr2_static ( & delta - > uni_acct_name ) ;
if ( STRING_CHANGED ) {
pdb_set_nt_username ( account , new_string , PDB_CHANGED ) ;
}
/* Unix username is the same - for sanity */
old_string = pdb_get_username ( account ) ;
if ( STRING_CHANGED ) {
pdb_set_username ( account , new_string , PDB_CHANGED ) ;
}
}
if ( delta - > hdr_full_name . buffer ) {
old_string = pdb_get_fullname ( account ) ;
new_string = unistr2_static ( & delta - > uni_full_name ) ;
if ( STRING_CHANGED )
pdb_set_fullname ( account , new_string , PDB_CHANGED ) ;
}
2002-09-18 10:34:10 +04:00
2003-03-23 05:22:41 +03:00
if ( delta - > hdr_home_dir . buffer ) {
old_string = pdb_get_homedir ( account ) ;
new_string = unistr2_static ( & delta - > uni_home_dir ) ;
if ( STRING_CHANGED )
pdb_set_homedir ( account , new_string , PDB_CHANGED ) ;
}
2002-09-18 10:34:10 +04:00
2003-03-23 05:22:41 +03:00
if ( delta - > hdr_dir_drive . buffer ) {
old_string = pdb_get_dir_drive ( account ) ;
new_string = unistr2_static ( & delta - > uni_dir_drive ) ;
2002-09-18 10:34:10 +04:00
2003-03-23 05:22:41 +03:00
if ( STRING_CHANGED )
pdb_set_dir_drive ( account , new_string , PDB_CHANGED ) ;
}
2002-09-18 10:34:10 +04:00
2003-03-23 05:22:41 +03:00
if ( delta - > hdr_logon_script . buffer ) {
old_string = pdb_get_logon_script ( account ) ;
new_string = unistr2_static ( & delta - > uni_logon_script ) ;
2002-09-18 10:34:10 +04:00
2003-03-23 05:22:41 +03:00
if ( STRING_CHANGED )
pdb_set_logon_script ( account , new_string , PDB_CHANGED ) ;
}
2002-09-18 10:34:10 +04:00
2003-03-23 05:22:41 +03:00
if ( delta - > hdr_acct_desc . buffer ) {
old_string = pdb_get_acct_desc ( account ) ;
new_string = unistr2_static ( & delta - > uni_acct_desc ) ;
2002-09-18 10:34:10 +04:00
2003-03-23 05:22:41 +03:00
if ( STRING_CHANGED )
pdb_set_acct_desc ( account , new_string , PDB_CHANGED ) ;
}
2002-09-18 10:34:10 +04:00
2003-03-23 05:22:41 +03:00
if ( delta - > hdr_workstations . buffer ) {
old_string = pdb_get_workstations ( account ) ;
new_string = unistr2_static ( & delta - > uni_workstations ) ;
2002-09-18 10:34:10 +04:00
2003-03-23 05:22:41 +03:00
if ( STRING_CHANGED )
pdb_set_workstations ( account , new_string , PDB_CHANGED ) ;
}
2002-09-18 10:34:10 +04:00
2003-03-23 05:22:41 +03:00
if ( delta - > hdr_profile . buffer ) {
old_string = pdb_get_profile_path ( account ) ;
new_string = unistr2_static ( & delta - > uni_profile ) ;
if ( STRING_CHANGED )
pdb_set_profile_path ( account , new_string , PDB_CHANGED ) ;
}
/* User and group sid */
if ( pdb_get_user_rid ( account ) ! = delta - > user_rid )
pdb_set_user_sid_from_rid ( account , delta - > user_rid , PDB_CHANGED ) ;
if ( pdb_get_group_rid ( account ) ! = delta - > group_rid )
pdb_set_group_sid_from_rid ( account , delta - > group_rid , PDB_CHANGED ) ;
2002-09-18 10:34:10 +04:00
/* Logon and password information */
2003-03-23 05:22:41 +03:00
if ( ! nt_time_is_zero ( & delta - > logon_time ) ) {
unix_time = nt_time_to_unix ( & delta - > logon_time ) ;
stored_time = pdb_get_logon_time ( account ) ;
if ( stored_time ! = unix_time )
pdb_set_logon_time ( account , unix_time , PDB_CHANGED ) ;
}
2002-09-18 10:34:10 +04:00
2003-03-23 05:22:41 +03:00
if ( ! nt_time_is_zero ( & delta - > logoff_time ) ) {
unix_time = nt_time_to_unix ( & delta - > logoff_time ) ;
stored_time = pdb_get_logoff_time ( account ) ;
if ( stored_time ! = unix_time )
pdb_set_logoff_time ( account , unix_time , PDB_CHANGED ) ;
}
if ( pdb_get_logon_divs ( account ) ! = delta - > logon_divs )
pdb_set_logon_divs ( account , delta - > logon_divs , PDB_CHANGED ) ;
2002-09-18 10:34:10 +04:00
/* TODO: logon hours */
/* TODO: bad password count */
/* TODO: logon count */
2003-03-23 05:22:41 +03:00
if ( ! nt_time_is_zero ( & delta - > pwd_last_set_time ) ) {
unix_time = nt_time_to_unix ( & delta - > pwd_last_set_time ) ;
stored_time = pdb_get_pass_last_set_time ( account ) ;
if ( stored_time ! = unix_time )
pdb_set_pass_last_set_time ( account , unix_time , PDB_CHANGED ) ;
}
2002-09-18 10:34:10 +04:00
2003-03-23 05:22:41 +03:00
#if 0
2003-04-14 08:00:37 +04:00
/* No kickoff time in the delta? */
2003-03-23 05:22:41 +03:00
if ( ! nt_time_is_zero ( & delta - > kickoff_time ) ) {
unix_time = nt_time_to_unix ( & delta - > kickoff_time ) ;
stored_time = pdb_get_kickoff_time ( account ) ;
if ( stored_time ! = unix_time )
pdb_set_kickoff_time ( account , unix_time , PDB_CHANGED ) ;
}
# endif
2002-09-24 10:50:11 +04:00
2002-11-10 06:07:19 +03:00
/* Decode hashes from password hash
Note that win2000 may send us all zeros for the hashes if it doesn ' t
think this channel is secure enough - don ' t set the passwords at all
in that case
2003-03-23 05:22:41 +03:00
*/
2002-11-10 06:07:19 +03:00
if ( memcmp ( delta - > pass . buf_lm_pwd , zero_buf , 16 ) ! = 0 ) {
sam_pwd_hash ( delta - > user_rid , delta - > pass . buf_lm_pwd , lm_passwd , 0 ) ;
pdb_set_lanman_passwd ( account , lm_passwd , PDB_CHANGED ) ;
}
if ( memcmp ( delta - > pass . buf_nt_pwd , zero_buf , 16 ) ! = 0 ) {
sam_pwd_hash ( delta - > user_rid , delta - > pass . buf_nt_pwd , nt_passwd , 0 ) ;
pdb_set_nt_passwd ( account , nt_passwd , PDB_CHANGED ) ;
}
2002-09-24 10:50:11 +04:00
2002-09-18 10:34:10 +04:00
/* TODO: account expiry time */
2003-03-23 05:22:41 +03:00
if ( pdb_get_acct_ctrl ( account ) ! = delta - > acb_info )
pdb_set_acct_ctrl ( account , delta - > acb_info , PDB_CHANGED ) ;
2003-03-30 20:46:04 +04:00
pdb_set_domain ( account , lp_workgroup ( ) , PDB_CHANGED ) ;
2002-09-18 10:34:10 +04:00
return NT_STATUS_OK ;
}
static NTSTATUS
fetch_account_info ( uint32 rid , SAM_ACCOUNT_INFO * delta )
{
NTSTATUS nt_ret ;
fstring account ;
pstring add_script ;
SAM_ACCOUNT * sam_account = NULL ;
2002-09-24 10:50:11 +04:00
GROUP_MAP map ;
struct group * grp ;
2003-07-05 13:46:12 +04:00
DOM_SID user_sid ;
DOM_SID group_sid ;
2003-06-14 04:49:02 +04:00
struct passwd * passwd ;
unid_t id ;
2003-07-05 13:46:12 +04:00
int u_type = ID_USERID | ID_QUERY_ONLY ;
2003-07-05 14:39:41 +04:00
fstring sid_string ;
2002-09-18 10:34:10 +04:00
fstrcpy ( account , unistr2_static ( & delta - > uni_acct_name ) ) ;
d_printf ( " Creating account: %s \n " , account ) ;
if ( ! NT_STATUS_IS_OK ( nt_ret = pdb_init_sam ( & sam_account ) ) )
return nt_ret ;
2003-06-14 04:49:02 +04:00
if ( ! ( passwd = Get_Pwnam ( account ) ) ) {
2002-09-18 10:34:10 +04:00
/* Create appropriate user */
if ( delta - > acb_info & ACB_NORMAL ) {
pstrcpy ( add_script , lp_adduser_script ( ) ) ;
} else if ( ( delta - > acb_info & ACB_WSTRUST ) | |
2003-03-23 05:22:41 +03:00
( delta - > acb_info & ACB_SVRTRUST ) | |
( delta - > acb_info & ACB_DOMTRUST ) ) {
2002-09-18 10:34:10 +04:00
pstrcpy ( add_script , lp_addmachine_script ( ) ) ;
} else {
DEBUG ( 1 , ( " Unknown user type: %s \n " ,
smbpasswd_encode_acb_info ( delta - > acb_info ) ) ) ;
}
if ( * add_script ) {
int add_ret ;
all_string_sub ( add_script , " %u " , account ,
sizeof ( account ) ) ;
add_ret = smbrun ( add_script , NULL ) ;
DEBUG ( 1 , ( " fetch_account: Running the command `%s' "
" gave %d \n " , add_script , add_ret ) ) ;
2003-06-14 04:49:02 +04:00
}
2003-07-09 20:44:47 +04:00
else {
DEBUG ( 8 , ( " fetch_account_info: no add user/machine script. Asking winbindd \n " ) ) ;
if ( ! winbind_create_user ( account ) )
DEBUG ( 4 , ( " fetch_account_info: winbind_create_user() failed \n " ) ) ;
}
/* try and find the possible unix account again */
if ( ! ( passwd = Get_Pwnam ( account ) ) )
return NT_STATUS_NO_SUCH_USER ;
2002-09-18 10:34:10 +04:00
}
2003-07-05 13:46:12 +04:00
sid_copy ( & user_sid , get_global_sam_sid ( ) ) ;
sid_append_rid ( & user_sid , delta - > user_rid ) ;
2002-09-18 10:34:10 +04:00
2003-07-05 14:39:41 +04:00
DEBUG ( 3 , ( " Attempting to find SID %s for user %s in the passdb \n " , sid_to_string ( sid_string , & user_sid ) , account ) ) ;
2003-07-05 13:46:12 +04:00
if ( ! pdb_getsampwsid ( sam_account , & user_sid ) ) {
sam_account_from_delta ( sam_account , delta ) ;
2003-07-05 14:39:41 +04:00
DEBUG ( 3 , ( " Attempting to add user SID %s for user %s in the passdb \n " ,
sid_to_string ( sid_string , & user_sid ) , pdb_get_username ( sam_account ) ) ) ;
2003-07-05 13:46:12 +04:00
if ( ! pdb_add_sam_account ( sam_account ) ) {
DEBUG ( 1 , ( " SAM Account for %s failed to be added to the passdb! \n " ,
account ) ) ;
return NT_STATUS_ACCESS_DENIED ;
}
} else {
sam_account_from_delta ( sam_account , delta ) ;
2003-07-05 14:39:41 +04:00
DEBUG ( 3 , ( " Attempting to update user SID %s for user %s in the passdb \n " ,
sid_to_string ( sid_string , & user_sid ) , pdb_get_username ( sam_account ) ) ) ;
2003-01-29 21:47:57 +03:00
if ( ! pdb_update_sam_account ( sam_account ) ) {
DEBUG ( 1 , ( " SAM Account for %s failed to be updated in the passdb! \n " ,
account ) ) ;
2003-06-14 04:49:02 +04:00
pdb_free_sam ( & sam_account ) ;
2003-07-05 13:46:12 +04:00
return NT_STATUS_ACCESS_DENIED ;
2003-01-29 21:47:57 +03:00
}
2002-09-24 10:50:11 +04:00
}
2003-07-05 13:46:12 +04:00
group_sid = * pdb_get_group_sid ( sam_account ) ;
2002-11-07 10:20:33 +03:00
2003-07-05 13:46:12 +04:00
if ( ! pdb_getgrsid ( & map , group_sid ) ) {
2002-09-24 10:50:11 +04:00
DEBUG ( 0 , ( " Primary group of %s has no mapping! \n " ,
pdb_get_username ( sam_account ) ) ) ;
2003-07-05 13:46:12 +04:00
} else {
if ( map . gid ! = passwd - > pw_gid ) {
if ( ! ( grp = getgrgid ( map . gid ) ) ) {
DEBUG ( 0 , ( " Could not find unix group %d for user %s (group SID=%s) \n " ,
map . gid , pdb_get_username ( sam_account ) , sid_string_static ( & group_sid ) ) ) ;
} else {
smb_set_primary_group ( grp - > gr_name , pdb_get_username ( sam_account ) ) ;
}
}
}
2003-06-14 04:49:02 +04:00
if ( ! passwd ) {
2003-07-05 13:46:12 +04:00
DEBUG ( 1 , ( " No unix user for this account (%s), cannot adjust mappings \n " , pdb_get_username ( sam_account ) ) ) ;
2003-06-14 04:49:02 +04:00
/* if no unix user, changing the mapping won't help */
2003-07-05 13:46:12 +04:00
} else {
nt_ret = idmap_get_id_from_sid ( & id , & u_type , pdb_get_user_sid ( sam_account ) ) ;
if ( NT_STATUS_IS_OK ( nt_ret ) & & ( u_type = = ID_USERID ) & & ( id . uid = = passwd - > pw_uid ) ) {
} else {
/* set mapping */
id . uid = passwd - > pw_uid ;
nt_ret = idmap_set_mapping ( pdb_get_user_sid ( sam_account ) , id , ID_USERID ) ;
2003-06-14 04:49:02 +04:00
}
}
2002-09-24 10:50:11 +04:00
2002-09-18 10:34:10 +04:00
pdb_free_sam ( & sam_account ) ;
2003-06-14 04:49:02 +04:00
return nt_ret ;
2002-09-18 10:34:10 +04:00
}
static NTSTATUS
fetch_group_info ( uint32 rid , SAM_GROUP_INFO * delta )
{
fstring name ;
fstring comment ;
2002-09-24 10:50:11 +04:00
struct group * grp = NULL ;
2002-09-18 10:34:10 +04:00
DOM_SID group_sid ;
fstring sid_string ;
GROUP_MAP map ;
2002-11-02 06:47:48 +03:00
BOOL insert = True ;
2002-09-18 10:34:10 +04:00
unistr2_to_ascii ( name , & delta - > uni_grp_name , sizeof ( name ) - 1 ) ;
unistr2_to_ascii ( comment , & delta - > uni_grp_desc , sizeof ( comment ) - 1 ) ;
/* add the group to the mapping table */
sid_copy ( & group_sid , get_global_sam_sid ( ) ) ;
sid_append_rid ( & group_sid , rid ) ;
sid_to_string ( sid_string , & group_sid ) ;
2003-06-18 19:24:10 +04:00
if ( pdb_getgrsid ( & map , group_sid ) ) {
2002-09-24 10:50:11 +04:00
grp = getgrgid ( map . gid ) ;
2002-11-02 06:47:48 +03:00
insert = False ;
2002-09-24 10:50:11 +04:00
}
if ( grp = = NULL )
{
2002-10-01 22:26:00 +04:00
gid_t gid ;
2002-09-24 10:50:11 +04:00
/* No group found from mapping, find it from its name. */
if ( ( grp = getgrnam ( name ) ) = = NULL ) {
2003-03-23 05:22:41 +03:00
/* No appropriate group found, create one */
2002-09-24 10:50:11 +04:00
d_printf ( " Creating unix group: '%s' \n " , name ) ;
2002-10-01 22:26:00 +04:00
if ( smb_create_group ( name , & gid ) ! = 0 )
return NT_STATUS_ACCESS_DENIED ;
if ( ( grp = getgrgid ( gid ) ) = = NULL )
2002-09-24 10:50:11 +04:00
return NT_STATUS_ACCESS_DENIED ;
}
2002-09-18 10:34:10 +04:00
}
map . gid = grp - > gr_gid ;
map . sid = group_sid ;
map . sid_name_use = SID_NAME_DOM_GRP ;
fstrcpy ( map . nt_name , name ) ;
fstrcpy ( map . comment , comment ) ;
2002-11-02 06:47:48 +03:00
if ( insert )
pdb_add_group_mapping_entry ( & map ) ;
else
pdb_update_group_mapping_entry ( & map ) ;
2002-09-18 10:34:10 +04:00
return NT_STATUS_OK ;
}
2002-09-24 10:50:11 +04:00
static NTSTATUS
fetch_group_mem_info ( uint32 rid , SAM_GROUP_MEM_INFO * delta )
{
int i ;
TALLOC_CTX * t = NULL ;
char * * nt_members = NULL ;
char * * unix_members ;
DOM_SID group_sid ;
GROUP_MAP map ;
struct group * grp ;
if ( delta - > num_members = = 0 ) {
return NT_STATUS_OK ;
}
sid_copy ( & group_sid , get_global_sam_sid ( ) ) ;
sid_append_rid ( & group_sid , rid ) ;
2003-06-18 19:24:10 +04:00
if ( ! get_domain_group_from_sid ( group_sid , & map ) ) {
2002-09-24 10:50:11 +04:00
DEBUG ( 0 , ( " Could not find global group %d \n " , rid ) ) ;
return NT_STATUS_NO_SUCH_GROUP ;
}
if ( ! ( grp = getgrgid ( map . gid ) ) ) {
DEBUG ( 0 , ( " Could not find unix group %d \n " , map . gid ) ) ;
return NT_STATUS_NO_SUCH_GROUP ;
}
d_printf ( " Group members of %s: " , grp - > gr_name ) ;
2002-12-20 23:21:31 +03:00
if ( ! ( t = talloc_init ( " fetch_group_mem_info " ) ) ) {
2002-09-24 10:50:11 +04:00
DEBUG ( 0 , ( " could not talloc_init \n " ) ) ;
return NT_STATUS_NO_MEMORY ;
}
nt_members = talloc_zero ( t , sizeof ( char * ) * delta - > num_members ) ;
for ( i = 0 ; i < delta - > num_members ; i + + ) {
NTSTATUS nt_status ;
SAM_ACCOUNT * member = NULL ;
DOM_SID member_sid ;
if ( ! NT_STATUS_IS_OK ( nt_status = pdb_init_sam_talloc ( t , & member ) ) ) {
talloc_destroy ( t ) ;
return nt_status ;
}
sid_copy ( & member_sid , get_global_sam_sid ( ) ) ;
sid_append_rid ( & member_sid , delta - > rids [ i ] ) ;
if ( ! pdb_getsampwsid ( member , & member_sid ) ) {
2002-11-07 10:20:33 +03:00
DEBUG ( 1 , ( " Found bogus group member: %d (member_sid=%s group=%s) \n " ,
delta - > rids [ i ] , sid_string_static ( & member_sid ) , grp - > gr_name ) ) ;
2002-09-24 10:50:11 +04:00
pdb_free_sam ( & member ) ;
continue ;
}
if ( pdb_get_group_rid ( member ) = = rid ) {
d_printf ( " %s(primary), " , pdb_get_username ( member ) ) ;
pdb_free_sam ( & member ) ;
continue ;
}
d_printf ( " %s, " , pdb_get_username ( member ) ) ;
nt_members [ i ] = talloc_strdup ( t , pdb_get_username ( member ) ) ;
pdb_free_sam ( & member ) ;
}
d_printf ( " \n " ) ;
unix_members = grp - > gr_mem ;
while ( * unix_members ) {
BOOL is_nt_member = False ;
for ( i = 0 ; i < delta - > num_members ; i + + ) {
if ( nt_members [ i ] = = NULL ) {
/* This was a primary group */
continue ;
}
if ( strcmp ( * unix_members , nt_members [ i ] ) = = 0 ) {
is_nt_member = True ;
break ;
}
}
if ( ! is_nt_member ) {
/* We look at a unix group member that is not
an nt group member . So , remove it . NT is
boss here . */
smb_delete_user_group ( grp - > gr_name , * unix_members ) ;
}
unix_members + = 1 ;
}
for ( i = 0 ; i < delta - > num_members ; i + + ) {
BOOL is_unix_member = False ;
if ( nt_members [ i ] = = NULL ) {
/* This was the primary group */
continue ;
}
unix_members = grp - > gr_mem ;
while ( * unix_members ) {
if ( strcmp ( * unix_members , nt_members [ i ] ) = = 0 ) {
is_unix_member = True ;
break ;
}
unix_members + = 1 ;
}
if ( ! is_unix_member ) {
/* We look at a nt group member that is not a
unix group member currently . So , add the nt
group member . */
smb_add_user_group ( grp - > gr_name , nt_members [ i ] ) ;
}
}
talloc_destroy ( t ) ;
return NT_STATUS_OK ;
}
static NTSTATUS fetch_alias_info ( uint32 rid , SAM_ALIAS_INFO * delta ,
DOM_SID dom_sid )
{
fstring name ;
fstring comment ;
struct group * grp = NULL ;
DOM_SID alias_sid ;
fstring sid_string ;
GROUP_MAP map ;
2002-11-02 06:47:48 +03:00
BOOL insert = True ;
2002-09-24 10:50:11 +04:00
unistr2_to_ascii ( name , & delta - > uni_als_name , sizeof ( name ) - 1 ) ;
unistr2_to_ascii ( comment , & delta - > uni_als_desc , sizeof ( comment ) - 1 ) ;
/* Find out whether the group is already mapped */
sid_copy ( & alias_sid , & dom_sid ) ;
sid_append_rid ( & alias_sid , rid ) ;
sid_to_string ( sid_string , & alias_sid ) ;
2003-06-18 19:24:10 +04:00
if ( pdb_getgrsid ( & map , alias_sid ) ) {
2002-09-24 10:50:11 +04:00
grp = getgrgid ( map . gid ) ;
2002-11-02 06:47:48 +03:00
insert = False ;
2002-09-24 10:50:11 +04:00
}
if ( grp = = NULL ) {
2002-10-01 22:26:00 +04:00
gid_t gid ;
2002-09-24 10:50:11 +04:00
/* No group found from mapping, find it from its name. */
if ( ( grp = getgrnam ( name ) ) = = NULL ) {
2003-03-23 05:22:41 +03:00
/* No appropriate group found, create one */
2002-09-24 10:50:11 +04:00
d_printf ( " Creating unix group: '%s' \n " , name ) ;
2002-10-01 22:26:00 +04:00
if ( smb_create_group ( name , & gid ) ! = 0 )
return NT_STATUS_ACCESS_DENIED ;
if ( ( grp = getgrgid ( gid ) ) = = NULL )
2002-09-24 10:50:11 +04:00
return NT_STATUS_ACCESS_DENIED ;
}
}
map . gid = grp - > gr_gid ;
map . sid = alias_sid ;
2002-10-01 22:26:00 +04:00
if ( sid_equal ( & dom_sid , & global_sid_Builtin ) )
map . sid_name_use = SID_NAME_WKN_GRP ;
else
map . sid_name_use = SID_NAME_ALIAS ;
2002-09-24 10:50:11 +04:00
fstrcpy ( map . nt_name , name ) ;
fstrcpy ( map . comment , comment ) ;
2002-11-02 06:47:48 +03:00
if ( insert )
pdb_add_group_mapping_entry ( & map ) ;
else
pdb_update_group_mapping_entry ( & map ) ;
2002-09-24 10:50:11 +04:00
return NT_STATUS_OK ;
}
static NTSTATUS
fetch_alias_mem ( uint32 rid , SAM_ALIAS_MEM_INFO * delta , DOM_SID dom_sid )
{
2003-04-29 18:42:49 +04:00
#if 0 /*
* commented out right now after talking to Volker . Can ' t
* do much with the membership but seemed a shame to waste
* somewhat working code . Needs testing because the membership
* that shows up surprises me . Also can ' t do much with groups
* in groups ( e . g . Domain Admins being a member of Adminsitrators ) .
* - - jerry
*/
2002-09-24 10:50:11 +04:00
2003-04-29 18:42:49 +04:00
int i ;
TALLOC_CTX * t = NULL ;
char * * nt_members = NULL ;
char * * unix_members ;
DOM_SID group_sid ;
GROUP_MAP map ;
struct group * grp ;
enum SID_NAME_USE sid_type ;
if ( delta - > num_members = = 0 ) {
return NT_STATUS_OK ;
}
sid_copy ( & group_sid , & dom_sid ) ;
sid_append_rid ( & group_sid , rid ) ;
if ( sid_equal ( & dom_sid , & global_sid_Builtin ) ) {
sid_type = SID_NAME_WKN_GRP ;
if ( ! get_builtin_group_from_sid ( group_sid , & map , False ) ) {
DEBUG ( 0 , ( " Could not find builtin group %s \n " , sid_string_static ( & group_sid ) ) ) ;
return NT_STATUS_NO_SUCH_GROUP ;
}
} else {
sid_type = SID_NAME_ALIAS ;
if ( ! get_local_group_from_sid ( group_sid , & map , False ) ) {
DEBUG ( 0 , ( " Could not find local group %s \n " , sid_string_static ( & group_sid ) ) ) ;
return NT_STATUS_NO_SUCH_GROUP ;
}
}
if ( ! ( grp = getgrgid ( map . gid ) ) ) {
DEBUG ( 0 , ( " Could not find unix group %d \n " , map . gid ) ) ;
return NT_STATUS_NO_SUCH_GROUP ;
}
d_printf ( " Group members of %s: " , grp - > gr_name ) ;
if ( ! ( t = talloc_init ( " fetch_group_mem_info " ) ) ) {
DEBUG ( 0 , ( " could not talloc_init \n " ) ) ;
return NT_STATUS_NO_MEMORY ;
}
nt_members = talloc_zero ( t , sizeof ( char * ) * delta - > num_members ) ;
for ( i = 0 ; i < delta - > num_members ; i + + ) {
NTSTATUS nt_status ;
SAM_ACCOUNT * member = NULL ;
DOM_SID member_sid ;
if ( ! NT_STATUS_IS_OK ( nt_status = pdb_init_sam_talloc ( t , & member ) ) ) {
talloc_destroy ( t ) ;
return nt_status ;
}
sid_copy ( & member_sid , & delta - > sids [ i ] . sid ) ;
if ( ! pdb_getsampwsid ( member , & member_sid ) ) {
DEBUG ( 1 , ( " Found bogus group member: (member_sid=%s group=%s) \n " ,
sid_string_static ( & member_sid ) , grp - > gr_name ) ) ;
pdb_free_sam ( & member ) ;
continue ;
}
if ( pdb_get_group_rid ( member ) = = rid ) {
d_printf ( " %s(primary), " , pdb_get_username ( member ) ) ;
pdb_free_sam ( & member ) ;
continue ;
}
d_printf ( " %s, " , pdb_get_username ( member ) ) ;
nt_members [ i ] = talloc_strdup ( t , pdb_get_username ( member ) ) ;
pdb_free_sam ( & member ) ;
}
d_printf ( " \n " ) ;
unix_members = grp - > gr_mem ;
while ( * unix_members ) {
BOOL is_nt_member = False ;
for ( i = 0 ; i < delta - > num_members ; i + + ) {
if ( nt_members [ i ] = = NULL ) {
/* This was a primary group */
continue ;
}
if ( strcmp ( * unix_members , nt_members [ i ] ) = = 0 ) {
is_nt_member = True ;
break ;
}
}
if ( ! is_nt_member ) {
/* We look at a unix group member that is not
an nt group member . So , remove it . NT is
boss here . */
smb_delete_user_group ( grp - > gr_name , * unix_members ) ;
}
unix_members + = 1 ;
}
for ( i = 0 ; i < delta - > num_members ; i + + ) {
BOOL is_unix_member = False ;
if ( nt_members [ i ] = = NULL ) {
/* This was the primary group */
continue ;
}
unix_members = grp - > gr_mem ;
while ( * unix_members ) {
if ( strcmp ( * unix_members , nt_members [ i ] ) = = 0 ) {
is_unix_member = True ;
break ;
}
unix_members + = 1 ;
}
if ( ! is_unix_member ) {
/* We look at a nt group member that is not a
unix group member currently . So , add the nt
group member . */
smb_add_user_group ( grp - > gr_name , nt_members [ i ] ) ;
}
}
talloc_destroy ( t ) ;
# endif /* end of fetch_alias_mem() */
2002-09-24 10:50:11 +04:00
return NT_STATUS_OK ;
}
2002-09-18 10:34:10 +04:00
static void
2002-09-24 10:50:11 +04:00
fetch_sam_entry ( SAM_DELTA_HDR * hdr_delta , SAM_DELTA_CTR * delta ,
DOM_SID dom_sid )
2002-09-18 10:34:10 +04:00
{
switch ( hdr_delta - > type ) {
case SAM_DELTA_ACCOUNT_INFO :
fetch_account_info ( hdr_delta - > target_rid ,
& delta - > account_info ) ;
break ;
case SAM_DELTA_GROUP_INFO :
fetch_group_info ( hdr_delta - > target_rid ,
& delta - > group_info ) ;
break ;
2002-09-24 10:50:11 +04:00
case SAM_DELTA_GROUP_MEM :
fetch_group_mem_info ( hdr_delta - > target_rid ,
& delta - > grp_mem_info ) ;
break ;
case SAM_DELTA_ALIAS_INFO :
fetch_alias_info ( hdr_delta - > target_rid ,
& delta - > alias_info , dom_sid ) ;
break ;
case SAM_DELTA_ALIAS_MEM :
fetch_alias_mem ( hdr_delta - > target_rid ,
& delta - > als_mem_info , dom_sid ) ;
break ;
2003-03-31 14:47:26 +04:00
case SAM_DELTA_DOMAIN_INFO :
2003-07-09 20:44:47 +04:00
d_printf ( " SAM_DELTA_DOMAIN_INFO not handled \n " ) ;
2003-03-31 14:47:26 +04:00
break ;
2002-09-18 10:34:10 +04:00
default :
d_printf ( " Unknown delta record type %d \n " , hdr_delta - > type ) ;
break ;
}
}
2003-06-16 09:39:26 +04:00
static NTSTATUS
2002-09-24 10:50:11 +04:00
fetch_database ( struct cli_state * cli , unsigned db_type , DOM_CRED * ret_creds ,
DOM_SID dom_sid )
2002-09-18 10:34:10 +04:00
{
2002-11-02 06:47:48 +03:00
unsigned sync_context = 0 ;
2002-09-18 10:34:10 +04:00
NTSTATUS result ;
int i ;
TALLOC_CTX * mem_ctx ;
SAM_DELTA_HDR * hdr_deltas ;
SAM_DELTA_CTR * deltas ;
uint32 num_deltas ;
2003-06-16 09:39:26 +04:00
if ( ! ( mem_ctx = talloc_init ( " fetch_database " ) ) )
return NT_STATUS_NO_MEMORY ;
2002-09-18 10:34:10 +04:00
2003-03-31 14:47:26 +04:00
switch ( db_type ) {
case SAM_DATABASE_DOMAIN :
d_printf ( " Fetching DOMAIN database \n " ) ;
break ;
case SAM_DATABASE_BUILTIN :
d_printf ( " Fetching BUILTIN database \n " ) ;
break ;
case SAM_DATABASE_PRIVS :
d_printf ( " Fetching PRIVS databases \n " ) ;
break ;
default :
d_printf ( " Fetching unknown database type %u \n " , db_type ) ;
break ;
}
2002-09-18 10:34:10 +04:00
do {
result = cli_netlogon_sam_sync ( cli , mem_ctx , ret_creds ,
2002-11-02 06:47:48 +03:00
db_type , sync_context ,
2002-09-18 10:34:10 +04:00
& num_deltas ,
& hdr_deltas , & deltas ) ;
2003-05-12 11:18:36 +04:00
if ( NT_STATUS_IS_OK ( result ) | |
NT_STATUS_EQUAL ( result , STATUS_MORE_ENTRIES ) ) {
clnt_deal_with_creds ( cli - > sess_key , & ( cli - > clnt_cred ) ,
ret_creds ) ;
for ( i = 0 ; i < num_deltas ; i + + ) {
fetch_sam_entry ( & hdr_deltas [ i ] , & deltas [ i ] , dom_sid ) ;
}
2003-06-16 09:39:26 +04:00
} else
return result ;
2002-11-02 06:47:48 +03:00
sync_context + = 1 ;
} while ( NT_STATUS_EQUAL ( result , STATUS_MORE_ENTRIES ) ) ;
2002-09-18 10:34:10 +04:00
talloc_destroy ( mem_ctx ) ;
2003-06-16 09:39:26 +04:00
return result ;
2002-09-18 10:34:10 +04:00
}
/* dump sam database via samsync rpc calls */
int rpc_vampire ( int argc , const char * * argv )
{
NTSTATUS result ;
struct cli_state * cli = NULL ;
uchar trust_password [ 16 ] ;
DOM_CRED ret_creds ;
2002-09-24 10:50:11 +04:00
DOM_SID dom_sid ;
2003-04-21 18:09:03 +04:00
uint32 sec_channel ;
2002-09-18 10:34:10 +04:00
ZERO_STRUCT ( ret_creds ) ;
2003-07-05 13:46:12 +04:00
if ( ! idmap_init ( lp_idmap_backend ( ) ) ) {
d_printf ( " Could not init idmap \n " ) ;
return - 1 ;
}
2002-09-18 10:34:10 +04:00
/* Connect to remote machine */
if ( ! ( cli = net_make_ipc_connection ( NET_FLAGS_ANONYMOUS |
NET_FLAGS_PDC ) ) ) {
return 1 ;
}
2002-10-04 08:10:23 +04:00
if ( ! cli_nt_session_open ( cli , PI_NETLOGON ) ) {
2002-09-18 10:34:10 +04:00
DEBUG ( 0 , ( " Error connecting to NETLOGON pipe \n " ) ) ;
goto fail ;
}
if ( ! secrets_fetch_trust_account_password ( lp_workgroup ( ) ,
2003-04-21 18:09:03 +04:00
trust_password , NULL ,
& sec_channel ) ) {
2002-11-07 10:20:33 +03:00
d_printf ( " Could not retrieve domain trust secret \n " ) ;
2002-09-18 10:34:10 +04:00
goto fail ;
}
2003-05-12 11:18:36 +04:00
result = cli_nt_establish_netlogon ( cli , sec_channel , trust_password ) ;
2002-09-18 10:34:10 +04:00
if ( ! NT_STATUS_IS_OK ( result ) ) {
d_printf ( " Failed to setup BDC creds \n " ) ;
goto fail ;
}
2002-09-24 10:50:11 +04:00
dom_sid = * get_global_sam_sid ( ) ;
2003-06-16 09:39:26 +04:00
result = fetch_database ( cli , SAM_DATABASE_DOMAIN , & ret_creds , dom_sid ) ;
if ( ! NT_STATUS_IS_OK ( result ) ) {
d_printf ( " Failed to fetch domain database: %s \n " ,
nt_errstr ( result ) ) ;
if ( NT_STATUS_EQUAL ( result , NT_STATUS_NOT_SUPPORTED ) )
d_printf ( " Perhaps %s is a Windows 2000 native mode "
" domain? \n " , lp_workgroup ( ) ) ;
goto fail ;
}
2002-09-24 10:50:11 +04:00
sid_copy ( & dom_sid , & global_sid_Builtin ) ;
2003-06-16 09:39:26 +04:00
result = fetch_database ( cli , SAM_DATABASE_BUILTIN , & ret_creds ,
dom_sid ) ;
if ( ! NT_STATUS_IS_OK ( result ) ) {
d_printf ( " Failed to fetch builtin database: %s \n " ,
nt_errstr ( result ) ) ;
goto fail ;
}
2002-09-18 10:34:10 +04:00
/* Currently we crash on PRIVS somewhere in unmarshalling */
/* Dump_database(cli, SAM_DATABASE_PRIVS, &ret_creds); */
cli_nt_session_close ( cli ) ;
return 0 ;
fail :
2003-06-16 09:39:26 +04:00
if ( cli )
2002-09-18 10:34:10 +04:00
cli_nt_session_close ( cli ) ;
2003-06-16 09:39:26 +04:00
2002-09-18 10:34:10 +04:00
return - 1 ;
}