1996-06-04 06:42:03 +00:00
/*
Unix SMB / Netbios implementation .
Version 1.9 .
SMB client
1998-01-22 13:27:43 +00:00
Copyright ( C ) Andrew Tridgell 1994 - 1998
1996-06-04 06:42:03 +00: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 .
*/
1998-07-29 03:08:05 +00:00
# define NO_SYSLOG
1996-06-04 06:42:03 +00:00
# include "includes.h"
# ifndef REGISTER
# define REGISTER 0
# endif
pstring service = " " ;
pstring desthost = " " ;
1998-04-25 01:12:08 +00:00
extern pstring global_myname ;
1996-06-04 06:42:03 +00:00
pstring password = " " ;
1997-11-03 15:47:03 +00:00
pstring smb_login_passwd = " " ;
1996-06-04 06:42:03 +00:00
pstring username = " " ;
pstring workgroup = WORKGROUP ;
BOOL got_pass = False ;
1998-02-26 20:41:05 +00:00
BOOL no_pass = False ;
1996-06-04 06:42:03 +00:00
BOOL connect_as_printer = False ;
BOOL connect_as_ipc = False ;
char cryptkey [ 8 ] ;
BOOL doencrypt = False ;
extern pstring user_socket_options ;
/* 30 second timeout on most commands */
# define CLIENT_TIMEOUT (30*1000)
# define SHORT_TIMEOUT (5*1000)
int name_type = 0x20 ;
int max_protocol = PROTOCOL_NT1 ;
BOOL readbraw_supported = False ;
BOOL writebraw_supported = False ;
extern int DEBUGLEVEL ;
1998-09-29 20:24:17 +00:00
uint16 cnum = 0 ;
uint16 pid = 0 ;
uint16 vuid = 0 ;
uint16 mid = 0 ;
1996-06-04 06:42:03 +00:00
int max_xmit = BUFFER_SIZE ;
BOOL have_ip = False ;
1997-10-26 07:45:36 +00:00
extern struct in_addr dest_ip ;
1996-06-04 06:42:03 +00:00
extern int Protocol ;
extern int Client ;
/****************************************************************************
setup basics in a outgoing packet
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1997-10-22 14:28:19 +00:00
void cli_setup_pkt ( char * outbuf )
1996-06-04 06:42:03 +00:00
{
SSVAL ( outbuf , smb_pid , pid ) ;
1998-09-29 20:24:17 +00:00
SSVAL ( outbuf , smb_uid , vuid ) ;
1996-06-04 06:42:03 +00:00
SSVAL ( outbuf , smb_mid , mid ) ;
1997-10-22 14:28:19 +00:00
if ( Protocol > PROTOCOL_COREPLUS )
1996-06-04 06:42:03 +00:00
{
SCVAL ( outbuf , smb_flg , 0x8 ) ;
SSVAL ( outbuf , smb_flg2 , 0x1 ) ;
}
}
1997-10-22 14:28:19 +00:00
/****************************************************************************
call a remote api
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1997-11-01 19:20:29 +00:00
BOOL cli_call_api ( char * pipe_name , int pipe_name_len ,
int prcnt , int drcnt , int srcnt ,
1997-10-22 14:28:19 +00:00
int mprcnt , int mdrcnt ,
int * rprcnt , int * rdrcnt ,
1997-10-23 13:38:46 +00:00
char * param , char * data , uint16 * setup ,
1997-10-22 14:28:19 +00:00
char * * rparam , char * * rdata )
{
static char * inbuf = NULL ;
static char * outbuf = NULL ;
if ( ! inbuf ) inbuf = ( char * ) malloc ( BUFFER_SIZE + SAFETY_MARGIN ) ;
if ( ! outbuf ) outbuf = ( char * ) malloc ( BUFFER_SIZE + SAFETY_MARGIN ) ;
1998-09-28 23:55:09 +00:00
if ( ! inbuf | | ! outbuf ) {
DEBUG ( 0 , ( " cli_call_api: malloc fail. \n " ) ) ;
return False ;
}
1997-11-01 19:20:29 +00:00
if ( pipe_name_len = = 0 ) pipe_name_len = strlen ( pipe_name ) ;
cli_send_trans_request ( outbuf , SMBtrans , pipe_name , pipe_name_len , 0 , 0 ,
1997-10-23 13:38:46 +00:00
data , param , setup ,
drcnt , prcnt , srcnt ,
mdrcnt , mprcnt , 0 ) ;
1997-10-22 14:28:19 +00:00
return ( cli_receive_trans_response ( inbuf , SMBtrans ,
rdrcnt , rprcnt ,
rdata , rparam ) ) ;
}
1997-10-21 09:39:08 +00:00
1996-06-04 06:42:03 +00:00
/****************************************************************************
receive a SMB trans or trans2 response allocating the necessary memory
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1997-10-22 14:28:19 +00:00
BOOL cli_receive_trans_response ( char * inbuf , int trans ,
int * data_len , int * param_len ,
char * * data , char * * param )
1996-06-04 06:42:03 +00:00
{
int total_data = 0 ;
int total_param = 0 ;
int this_data , this_param ;
* data_len = * param_len = 0 ;
1997-12-20 14:36:11 +00:00
client_receive_smb ( Client , inbuf , CLIENT_TIMEOUT ) ;
1996-06-04 06:42:03 +00:00
show_msg ( inbuf ) ;
/* sanity check */
if ( CVAL ( inbuf , smb_com ) ! = trans )
{
DEBUG ( 0 , ( " Expected %s response, got command 0x%02x \n " ,
trans = = SMBtrans ? " SMBtrans " : " SMBtrans2 " , CVAL ( inbuf , smb_com ) ) ) ;
return ( False ) ;
}
if ( CVAL ( inbuf , smb_rcls ) ! = 0 )
return ( False ) ;
/* parse out the lengths */
total_data = SVAL ( inbuf , smb_tdrcnt ) ;
total_param = SVAL ( inbuf , smb_tprcnt ) ;
/* allocate it */
* data = Realloc ( * data , total_data ) ;
* param = Realloc ( * param , total_param ) ;
1998-09-28 23:55:09 +00:00
if ( ( total_data & & ! data ) | | ( total_param & & ! param ) ) {
DEBUG ( 0 , ( " cli_receive_trans_response: Realloc fail ! \n " ) ) ;
return ( False ) ;
}
1996-06-04 06:42:03 +00:00
while ( 1 )
{
this_data = SVAL ( inbuf , smb_drcnt ) ;
this_param = SVAL ( inbuf , smb_prcnt ) ;
if ( this_data )
memcpy ( * data + SVAL ( inbuf , smb_drdisp ) ,
smb_base ( inbuf ) + SVAL ( inbuf , smb_droff ) ,
this_data ) ;
if ( this_param )
memcpy ( * param + SVAL ( inbuf , smb_prdisp ) ,
smb_base ( inbuf ) + SVAL ( inbuf , smb_proff ) ,
this_param ) ;
* data_len + = this_data ;
* param_len + = this_param ;
/* parse out the total lengths again - they can shrink! */
total_data = SVAL ( inbuf , smb_tdrcnt ) ;
total_param = SVAL ( inbuf , smb_tprcnt ) ;
if ( total_data < = * data_len & & total_param < = * param_len )
break ;
1997-12-20 14:36:11 +00:00
client_receive_smb ( Client , inbuf , CLIENT_TIMEOUT ) ;
1996-06-04 06:42:03 +00:00
show_msg ( inbuf ) ;
/* sanity check */
if ( CVAL ( inbuf , smb_com ) ! = trans )
{
DEBUG ( 0 , ( " Expected %s response, got command 0x%02x \n " ,
trans = = SMBtrans ? " SMBtrans " : " SMBtrans2 " , CVAL ( inbuf , smb_com ) ) ) ;
return ( False ) ;
}
if ( CVAL ( inbuf , smb_rcls ) ! = 0 )
return ( False ) ;
}
return ( True ) ;
}
1997-10-22 14:28:19 +00:00
/****************************************************************************
send a SMB trans or trans2 request
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL cli_send_trans_request ( char * outbuf , int trans ,
1997-11-02 04:01:57 +00:00
char * name , int namelen , int fid , int flags ,
1997-10-22 14:28:19 +00:00
char * data , char * param , uint16 * setup ,
int ldata , int lparam , int lsetup ,
int mdata , int mparam , int msetup )
{
int i ;
int this_ldata , this_lparam ;
int tot_data = 0 , tot_param = 0 ;
char * outdata , * outparam ;
pstring inbuf ;
char * p ;
this_lparam = MIN ( lparam , max_xmit - ( 500 + lsetup * SIZEOFWORD ) ) ; /* hack */
this_ldata = MIN ( ldata , max_xmit - ( 500 + lsetup * SIZEOFWORD + this_lparam ) ) ;
bzero ( outbuf , smb_size ) ;
set_message ( outbuf , 14 + lsetup , 0 , True ) ;
CVAL ( outbuf , smb_com ) = trans ;
SSVAL ( outbuf , smb_tid , cnum ) ;
cli_setup_pkt ( outbuf ) ;
1997-11-02 04:01:57 +00:00
outparam = smb_buf ( outbuf ) + ( trans = = SMBtrans ? namelen + 1 : 3 ) ;
1997-10-22 14:28:19 +00:00
outdata = outparam + this_lparam ;
/* primary request */
SSVAL ( outbuf , smb_tpscnt , lparam ) ; /* tpscnt */
SSVAL ( outbuf , smb_tdscnt , ldata ) ; /* tdscnt */
SSVAL ( outbuf , smb_mprcnt , mparam ) ; /* mprcnt */
SSVAL ( outbuf , smb_mdrcnt , mdata ) ; /* mdrcnt */
SCVAL ( outbuf , smb_msrcnt , msetup ) ; /* msrcnt */
SSVAL ( outbuf , smb_flags , flags ) ; /* flags */
SIVAL ( outbuf , smb_timeout , 0 ) ; /* timeout */
SSVAL ( outbuf , smb_pscnt , this_lparam ) ; /* pscnt */
SSVAL ( outbuf , smb_psoff , smb_offset ( outparam , outbuf ) ) ; /* psoff */
SSVAL ( outbuf , smb_dscnt , this_ldata ) ; /* dscnt */
SSVAL ( outbuf , smb_dsoff , smb_offset ( outdata , outbuf ) ) ; /* dsoff */
SCVAL ( outbuf , smb_suwcnt , lsetup ) ; /* suwcnt */
for ( i = 0 ; i < lsetup ; i + + ) /* setup[] */
SSVAL ( outbuf , smb_setup + i * SIZEOFWORD , setup [ i ] ) ;
p = smb_buf ( outbuf ) ;
if ( trans = = SMBtrans )
1997-11-02 04:01:57 +00:00
memcpy ( p , name , namelen + 1 ) ; /* name[] */
1997-10-22 14:28:19 +00:00
else
{
* p + + = 0 ; /* put in a null smb_name */
* p + + = ' D ' ; * p + + = ' ' ; /* this was added because OS/2 does it */
}
if ( this_lparam ) /* param[] */
memcpy ( outparam , param , this_lparam ) ;
if ( this_ldata ) /* data[] */
memcpy ( outdata , data , this_ldata ) ;
set_message ( outbuf , 14 + lsetup , /* wcnt, bcc */
PTR_DIFF ( outdata + this_ldata , smb_buf ( outbuf ) ) , False ) ;
show_msg ( outbuf ) ;
send_smb ( Client , outbuf ) ;
if ( this_ldata < ldata | | this_lparam < lparam )
{
/* receive interim response */
1997-12-20 14:36:11 +00:00
if ( ! client_receive_smb ( Client , inbuf , SHORT_TIMEOUT ) | | CVAL ( inbuf , smb_rcls ) ! = 0 )
1997-10-22 14:28:19 +00:00
{
DEBUG ( 0 , ( " %s request failed (%s) \n " ,
trans = = SMBtrans ? " SMBtrans " : " SMBtrans2 " , smb_errstr ( inbuf ) ) ) ;
return ( False ) ;
}
tot_data = this_ldata ;
tot_param = this_lparam ;
while ( tot_data < ldata | | tot_param < lparam )
{
this_lparam = MIN ( lparam - tot_param , max_xmit - 500 ) ; /* hack */
this_ldata = MIN ( ldata - tot_data , max_xmit - ( 500 + this_lparam ) ) ;
set_message ( outbuf , trans = = SMBtrans ? 8 : 9 , 0 , True ) ;
CVAL ( outbuf , smb_com ) = trans = = SMBtrans ? SMBtranss : SMBtranss2 ;
outparam = smb_buf ( outbuf ) ;
outdata = outparam + this_lparam ;
/* secondary request */
SSVAL ( outbuf , smb_tpscnt , lparam ) ; /* tpscnt */
SSVAL ( outbuf , smb_tdscnt , ldata ) ; /* tdscnt */
SSVAL ( outbuf , smb_spscnt , this_lparam ) ; /* pscnt */
SSVAL ( outbuf , smb_spsoff , smb_offset ( outparam , outbuf ) ) ; /* psoff */
SSVAL ( outbuf , smb_spsdisp , tot_param ) ; /* psdisp */
SSVAL ( outbuf , smb_sdscnt , this_ldata ) ; /* dscnt */
SSVAL ( outbuf , smb_sdsoff , smb_offset ( outdata , outbuf ) ) ; /* dsoff */
SSVAL ( outbuf , smb_sdsdisp , tot_data ) ; /* dsdisp */
if ( trans = = SMBtrans2 )
SSVAL ( outbuf , smb_sfid , fid ) ; /* fid */
if ( this_lparam ) /* param[] */
memcpy ( outparam , param , this_lparam ) ;
if ( this_ldata ) /* data[] */
memcpy ( outdata , data , this_ldata ) ;
set_message ( outbuf , trans = = SMBtrans ? 8 : 9 , /* wcnt, bcc */
PTR_DIFF ( outdata + this_ldata , smb_buf ( outbuf ) ) , False ) ;
show_msg ( outbuf ) ;
send_smb ( Client , outbuf ) ;
tot_data + = this_ldata ;
tot_param + = this_lparam ;
}
}
return ( True ) ;
}
1996-06-04 06:42:03 +00:00
/****************************************************************************
send a session request
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1997-10-22 14:28:19 +00:00
BOOL cli_send_session_request ( char * inbuf , char * outbuf )
1996-06-04 06:42:03 +00:00
{
fstring dest ;
char * p ;
int len = 4 ;
/* send a session request (RFC 8002) */
1998-05-12 00:55:32 +00:00
fstrcpy ( dest , desthost ) ;
1996-06-04 06:42:03 +00:00
p = strchr ( dest , ' . ' ) ;
if ( p ) * p = 0 ;
/* put in the destination name */
p = outbuf + len ;
1997-10-22 14:28:19 +00:00
name_mangle ( dest , p , name_type ) ; /* 0x20 is the SMB server NetBIOS type. */
1996-06-04 06:42:03 +00:00
len + = name_len ( p ) ;
/* and my name */
p = outbuf + len ;
1998-04-25 01:12:08 +00:00
name_mangle ( global_myname , p , 0 ) ;
1996-06-04 06:42:03 +00:00
len + = name_len ( p ) ;
/* setup the packet length */
_smb_setlen ( outbuf , len ) ;
CVAL ( outbuf , 0 ) = 0x81 ;
1998-07-29 03:08:05 +00:00
# ifdef WITH_SSL
1998-06-16 01:35:52 +00:00
retry :
1998-07-29 03:08:05 +00:00
# endif /* WITH_SSL */
1998-06-16 01:35:52 +00:00
1996-06-04 06:42:03 +00:00
send_smb ( Client , outbuf ) ;
DEBUG ( 5 , ( " Sent session request \n " ) ) ;
1997-12-20 14:36:11 +00:00
client_receive_smb ( Client , inbuf , CLIENT_TIMEOUT ) ;
1996-06-04 06:42:03 +00:00
if ( CVAL ( inbuf , 0 ) = = 0x84 ) /* C. Hoch 9/14/95 Start */
{
/* For information, here is the response structure.
* We do the byte - twiddling to for portability .
struct RetargetResponse {
unsigned char type ;
unsigned char flags ;
int16 length ;
int32 ip_addr ;
int16 port ;
} ;
*/
extern int Client ;
int port = ( CVAL ( inbuf , 8 ) < < 8 ) + CVAL ( inbuf , 9 ) ;
/* SESSION RETARGET */
putip ( ( char * ) & dest_ip , inbuf + 4 ) ;
close_sockets ( ) ;
1997-10-22 14:28:19 +00:00
Client = open_socket_out ( SOCK_STREAM , & dest_ip , port , LONG_CONNECT_TIMEOUT ) ;
1996-06-04 06:42:03 +00:00
if ( Client = = - 1 )
return False ;
1997-10-22 14:28:19 +00:00
DEBUG ( 3 , ( " Retargeted \n " ) ) ;
1996-06-04 06:42:03 +00:00
set_socket_options ( Client , user_socket_options ) ;
/* Try again */
return cli_send_session_request ( inbuf , outbuf ) ;
} /* C. Hoch 9/14/95 End */
1998-07-29 03:08:05 +00:00
# ifdef WITH_SSL
1998-06-16 01:35:52 +00:00
if ( CVAL ( inbuf , 0 ) = = 0x83 & & CVAL ( inbuf , 4 ) = = 0x8e ) { /* use ssl */
fprintf ( stderr , " Making secure connection \n " ) ;
if ( ! sslutil_fd_is_ssl ( Client ) ) {
if ( sslutil_connect ( Client ) = = 0 )
goto retry ;
}
}
# endif
1996-06-04 06:42:03 +00:00
if ( CVAL ( inbuf , 0 ) ! = 0x82 )
{
int ecode = CVAL ( inbuf , 4 ) ;
DEBUG ( 0 , ( " Session request failed (%d,%d) with myname=%s destname=%s \n " ,
1998-04-25 01:12:08 +00:00
CVAL ( inbuf , 0 ) , ecode , global_myname , desthost ) ) ;
1996-06-04 06:42:03 +00:00
switch ( ecode )
{
case 0x80 :
DEBUG ( 0 , ( " Not listening on called name \n " ) ) ;
DEBUG ( 0 , ( " Try to connect to another name (instead of %s) \n " , desthost ) ) ;
DEBUG ( 0 , ( " You may find the -I option useful for this \n " ) ) ;
break ;
case 0x81 :
DEBUG ( 0 , ( " Not listening for calling name \n " ) ) ;
1998-04-25 01:12:08 +00:00
DEBUG ( 0 , ( " Try to connect as another name (instead of %s) \n " , global_myname ) ) ;
1996-06-04 06:42:03 +00:00
DEBUG ( 0 , ( " You may find the -n option useful for this \n " ) ) ;
break ;
case 0x82 :
DEBUG ( 0 , ( " Called name not present \n " ) ) ;
DEBUG ( 0 , ( " Try to connect to another name (instead of %s) \n " , desthost ) ) ;
DEBUG ( 0 , ( " You may find the -I option useful for this \n " ) ) ;
break ;
case 0x83 :
DEBUG ( 0 , ( " Called name present, but insufficient resources \n " ) ) ;
DEBUG ( 0 , ( " Perhaps you should try again later? \n " ) ) ;
break ;
default :
DEBUG ( 0 , ( " Unspecified error 0x%X \n " , ecode ) ) ;
DEBUG ( 0 , ( " Your server software is being unfriendly \n " ) ) ;
break ;
}
return ( False ) ;
}
return ( True ) ;
}
1997-10-22 14:28:19 +00:00
static struct {
int prot ;
char * name ;
} prots [ ] = {
{ PROTOCOL_CORE , " PC NETWORK PROGRAM 1.0 " } ,
{ PROTOCOL_COREPLUS , " MICROSOFT NETWORKS 1.03 " } ,
{ PROTOCOL_LANMAN1 , " MICROSOFT NETWORKS 3.0 " } ,
{ PROTOCOL_LANMAN1 , " LANMAN1.0 " } ,
{ PROTOCOL_LANMAN2 , " LM1.2X002 " } ,
{ PROTOCOL_LANMAN2 , " Samba " } ,
{ PROTOCOL_NT1 , " NT LM 0.12 " } ,
{ PROTOCOL_NT1 , " NT LANMAN 1.0 " } ,
{ - 1 , NULL }
} ;
1996-06-04 06:42:03 +00:00
/****************************************************************************
1997-11-03 15:47:03 +00:00
send a login command .
1996-06-04 06:42:03 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-01-05 22:54:32 +00:00
BOOL cli_send_login ( char * inbuf , char * outbuf , BOOL start_session , BOOL use_setup , struct connection_options * options )
1996-06-04 06:42:03 +00:00
{
BOOL was_null = ( ! inbuf & & ! outbuf ) ;
time_t servertime = 0 ;
extern int serverzone ;
1998-01-05 22:54:32 +00:00
int crypt_len = 0 ;
1996-06-04 06:42:03 +00:00
char * pass = NULL ;
1998-06-15 22:02:14 +00:00
uchar enc_ntpass [ 24 ] ;
int ntpasslen = 0 ;
1996-06-04 06:42:03 +00:00
pstring dev ;
char * p ;
int numprots ;
1997-10-22 14:28:19 +00:00
int tries = 0 ;
1998-01-05 22:54:32 +00:00
struct connection_options opt ;
bzero ( & opt , sizeof ( opt ) ) ;
1996-06-04 06:42:03 +00:00
if ( was_null )
1998-09-28 23:55:09 +00:00
{
inbuf = ( char * ) malloc ( BUFFER_SIZE + SAFETY_MARGIN ) ;
outbuf = ( char * ) malloc ( BUFFER_SIZE + SAFETY_MARGIN ) ;
if ( ! inbuf | | ! outbuf ) {
DEBUG ( 0 , ( " cli_send_login: malloc fail ! \n " ) ) ;
return False ;
1996-06-04 06:42:03 +00:00
}
1998-09-28 23:55:09 +00:00
}
1996-06-04 06:42:03 +00:00
1997-10-22 14:28:19 +00:00
if ( strstr ( service , " IPC$ " ) ) connect_as_ipc = True ;
1998-05-12 00:55:32 +00:00
pstrcpy ( dev , " A: " ) ;
1996-06-04 06:42:03 +00:00
if ( connect_as_printer )
1998-05-12 00:55:32 +00:00
pstrcpy ( dev , " LPT1: " ) ;
1996-06-04 06:42:03 +00:00
if ( connect_as_ipc )
1998-05-12 00:55:32 +00:00
pstrcpy ( dev , " IPC " ) ;
1996-06-04 06:42:03 +00:00
if ( start_session & & ! cli_send_session_request ( inbuf , outbuf ) )
{
if ( was_null )
{
free ( inbuf ) ;
free ( outbuf ) ;
}
return ( False ) ;
}
bzero ( outbuf , smb_size ) ;
/* setup the protocol strings */
{
int plength ;
for ( plength = 0 , numprots = 0 ;
prots [ numprots ] . name & & prots [ numprots ] . prot < = max_protocol ;
numprots + + )
plength + = strlen ( prots [ numprots ] . name ) + 2 ;
set_message ( outbuf , 0 , plength , True ) ;
p = smb_buf ( outbuf ) ;
for ( numprots = 0 ;
prots [ numprots ] . name & & prots [ numprots ] . prot < = max_protocol ;
numprots + + )
{
* p + + = 2 ;
1998-05-12 00:55:32 +00:00
pstrcpy ( p , prots [ numprots ] . name ) ;
1996-06-04 06:42:03 +00:00
p + = strlen ( p ) + 1 ;
}
}
CVAL ( outbuf , smb_com ) = SMBnegprot ;
cli_setup_pkt ( outbuf ) ;
CVAL ( smb_buf ( outbuf ) , 0 ) = 2 ;
send_smb ( Client , outbuf ) ;
1997-12-20 14:36:11 +00:00
client_receive_smb ( Client , inbuf , CLIENT_TIMEOUT ) ;
1996-06-04 06:42:03 +00:00
show_msg ( inbuf ) ;
if ( CVAL ( inbuf , smb_rcls ) ! = 0 | | ( ( int ) SVAL ( inbuf , smb_vwv0 ) > = numprots ) )
{
DEBUG ( 0 , ( " SMBnegprot failed. myname=%s destname=%s - %s \n " ,
1998-04-25 01:12:08 +00:00
global_myname , desthost , smb_errstr ( inbuf ) ) ) ;
1996-06-04 06:42:03 +00:00
if ( was_null )
{
free ( inbuf ) ;
free ( outbuf ) ;
}
return ( False ) ;
}
1998-01-05 22:54:32 +00:00
opt . protocol = Protocol = prots [ SVAL ( inbuf , smb_vwv0 ) ] . prot ;
1996-06-04 06:42:03 +00:00
1997-12-14 17:48:55 +00:00
if ( Protocol < PROTOCOL_LANMAN1 ) {
/* no extra params */
} else if ( Protocol < PROTOCOL_NT1 ) {
1998-01-05 22:54:32 +00:00
opt . sec_mode = SVAL ( inbuf , smb_vwv1 ) ;
opt . max_xmit = max_xmit = SVAL ( inbuf , smb_vwv2 ) ;
opt . sesskey = IVAL ( inbuf , smb_vwv6 ) ;
opt . serverzone = serverzone = SVALS ( inbuf , smb_vwv10 ) * 60 ;
1996-06-04 06:42:03 +00:00
/* this time is converted to GMT by make_unix_date */
servertime = make_unix_date ( inbuf + smb_vwv8 ) ;
if ( Protocol > = PROTOCOL_COREPLUS ) {
1998-01-05 22:54:32 +00:00
opt . rawmode = SVAL ( inbuf , smb_vwv5 ) ;
1996-06-04 06:42:03 +00:00
readbraw_supported = ( ( SVAL ( inbuf , smb_vwv5 ) & 0x1 ) ! = 0 ) ;
writebraw_supported = ( ( SVAL ( inbuf , smb_vwv5 ) & 0x2 ) ! = 0 ) ;
}
crypt_len = smb_buflen ( inbuf ) ;
memcpy ( cryptkey , smb_buf ( inbuf ) , 8 ) ;
1997-10-22 14:28:19 +00:00
DEBUG ( 3 , ( " max mux %d \n " , SVAL ( inbuf , smb_vwv3 ) ) ) ;
1998-01-05 22:54:32 +00:00
opt . max_vcs = SVAL ( inbuf , smb_vwv4 ) ;
DEBUG ( 3 , ( " max vcs %d \n " , opt . max_vcs ) ) ;
1997-10-22 14:28:19 +00:00
DEBUG ( 3 , ( " max blk %d \n " , SVAL ( inbuf , smb_vwv5 ) ) ) ;
1996-06-04 06:42:03 +00:00
} else {
/* NT protocol */
1998-01-05 22:54:32 +00:00
opt . sec_mode = CVAL ( inbuf , smb_vwv1 ) ;
opt . max_xmit = max_xmit = IVAL ( inbuf , smb_vwv3 + 1 ) ;
opt . sesskey = IVAL ( inbuf , smb_vwv7 + 1 ) ;
opt . serverzone = SVALS ( inbuf , smb_vwv15 + 1 ) * 60 ;
1996-06-04 06:42:03 +00:00
/* this time arrives in real GMT */
servertime = interpret_long_date ( inbuf + smb_vwv11 + 1 ) ;
crypt_len = CVAL ( inbuf , smb_vwv16 + 1 ) ;
memcpy ( cryptkey , smb_buf ( inbuf ) , 8 ) ;
if ( IVAL ( inbuf , smb_vwv9 + 1 ) & 1 )
readbraw_supported = writebraw_supported = True ;
1997-10-22 14:28:19 +00:00
DEBUG ( 3 , ( " max mux %d \n " , SVAL ( inbuf , smb_vwv1 + 1 ) ) ) ;
1998-01-05 22:54:32 +00:00
opt . max_vcs = SVAL ( inbuf , smb_vwv2 + 1 ) ;
DEBUG ( 3 , ( " max vcs %d \n " , opt . max_vcs ) ) ;
1997-10-22 14:28:19 +00:00
DEBUG ( 3 , ( " max raw %d \n " , IVAL ( inbuf , smb_vwv5 + 1 ) ) ) ;
DEBUG ( 3 , ( " capabilities 0x%x \n " , IVAL ( inbuf , smb_vwv9 + 1 ) ) ) ;
1996-06-04 06:42:03 +00:00
}
1997-10-22 14:28:19 +00:00
DEBUG ( 3 , ( " Sec mode %d \n " , SVAL ( inbuf , smb_vwv1 ) ) ) ;
DEBUG ( 3 , ( " max xmt %d \n " , max_xmit ) ) ;
DEBUG ( 3 , ( " Got %d byte crypt key \n " , crypt_len ) ) ;
DEBUG ( 3 , ( " Chose protocol [%s] \n " , prots [ SVAL ( inbuf , smb_vwv0 ) ] . name ) ) ;
1996-06-04 06:42:03 +00:00
1998-01-05 22:54:32 +00:00
doencrypt = ( ( opt . sec_mode & 2 ) ! = 0 ) ;
1996-06-04 06:42:03 +00:00
if ( servertime ) {
static BOOL done_time = False ;
if ( ! done_time ) {
DEBUG ( 1 , ( " Server time is %sTimezone is UTC%+02.1f \n " ,
asctime ( LocalTime ( & servertime ) ) ,
- ( double ) ( serverzone / 3600.0 ) ) ) ;
done_time = True ;
}
}
get_pass :
if ( got_pass )
pass = password ;
else
pass = ( char * ) getpass ( " Password: " ) ;
1998-06-01 18:50:27 +00:00
if ( ! pass )
pass = " " ;
1997-11-03 15:47:03 +00:00
pstrcpy ( smb_login_passwd , pass ) ;
1997-10-22 14:28:19 +00:00
/* use a blank username for the 2nd try with a blank password */
if ( tries + + & & ! * pass )
* username = 0 ;
1997-08-28 20:59:51 +00:00
1996-06-04 06:42:03 +00:00
if ( Protocol > = PROTOCOL_LANMAN1 & & use_setup )
1998-06-15 22:02:14 +00:00
{
fstring pword ;
int passlen = strlen ( pass ) + 1 ;
fstrcpy ( pword , pass ) ;
if ( doencrypt & & * pass )
1996-06-04 06:42:03 +00:00
{
1998-06-15 22:02:14 +00:00
DEBUG ( 3 , ( " Using encrypted passwords \n " ) ) ;
passlen = 24 ;
SMBencrypt ( ( uchar * ) pass , ( uchar * ) cryptkey , ( uchar * ) pword ) ;
ntpasslen = 24 ;
SMBNTencrypt ( ( uchar * ) pass , ( uchar * ) cryptkey , enc_ntpass ) ;
}
1996-06-04 06:42:03 +00:00
1998-06-15 22:02:14 +00:00
/* if in share level security then don't send a password now */
if ( ! ( opt . sec_mode & 1 ) ) { fstrcpy ( pword , " " ) ; passlen = 1 ; }
1996-06-04 06:42:03 +00:00
1998-06-15 22:02:14 +00:00
/* send a session setup command */
bzero ( outbuf , smb_size ) ;
1996-06-04 06:42:03 +00:00
1998-06-15 22:02:14 +00:00
if ( Protocol < PROTOCOL_NT1 )
{
set_message ( outbuf , 10 , 1 + strlen ( username ) + passlen , True ) ;
CVAL ( outbuf , smb_com ) = SMBsesssetupX ;
cli_setup_pkt ( outbuf ) ;
CVAL ( outbuf , smb_vwv0 ) = 0xFF ;
SSVAL ( outbuf , smb_vwv2 , max_xmit ) ;
SSVAL ( outbuf , smb_vwv3 , 2 ) ;
SSVAL ( outbuf , smb_vwv4 , opt . max_vcs - 1 ) ;
SIVAL ( outbuf , smb_vwv5 , opt . sesskey ) ;
SSVAL ( outbuf , smb_vwv7 , passlen ) ;
p = smb_buf ( outbuf ) ;
memcpy ( p , pword , passlen ) ;
p + = passlen ;
pstrcpy ( p , username ) ;
}
else
{
if ( ! doencrypt ) passlen - - ;
/* for Win95 */
set_message ( outbuf , 13 , 0 , True ) ;
CVAL ( outbuf , smb_com ) = SMBsesssetupX ;
cli_setup_pkt ( outbuf ) ;
CVAL ( outbuf , smb_vwv0 ) = 0xFF ;
SSVAL ( outbuf , smb_vwv2 , BUFFER_SIZE ) ;
SSVAL ( outbuf , smb_vwv3 , 2 ) ;
SSVAL ( outbuf , smb_vwv4 , getpid ( ) ) ;
SIVAL ( outbuf , smb_vwv5 , opt . sesskey ) ;
SSVAL ( outbuf , smb_vwv7 , passlen ) ;
SSVAL ( outbuf , smb_vwv8 , doencrypt ? ntpasslen : 0 ) ;
p = smb_buf ( outbuf ) ;
memcpy ( p , pword , passlen ) ; p + = SVAL ( outbuf , smb_vwv7 ) ;
if ( doencrypt )
memcpy ( p , enc_ntpass , ntpasslen ) ; p + = SVAL ( outbuf , smb_vwv8 ) ;
pstrcpy ( p , username ) ; p = skip_string ( p , 1 ) ;
pstrcpy ( p , workgroup ) ; p = skip_string ( p , 1 ) ;
pstrcpy ( p , " Unix " ) ; p = skip_string ( p , 1 ) ;
pstrcpy ( p , " Samba " ) ; p = skip_string ( p , 1 ) ;
set_message ( outbuf , 13 , PTR_DIFF ( p , smb_buf ( outbuf ) ) , False ) ;
}
1996-06-04 06:42:03 +00:00
1998-06-15 22:02:14 +00:00
send_smb ( Client , outbuf ) ;
client_receive_smb ( Client , inbuf , CLIENT_TIMEOUT ) ;
1996-06-04 06:42:03 +00:00
1998-06-15 22:02:14 +00:00
show_msg ( inbuf ) ;
if ( CVAL ( inbuf , smb_rcls ) ! = 0 )
{
if ( ! * pass & &
( ( CVAL ( inbuf , smb_rcls ) = = ERRDOS & &
SVAL ( inbuf , smb_err ) = = ERRnoaccess ) | |
( CVAL ( inbuf , smb_rcls ) = = ERRSRV & &
SVAL ( inbuf , smb_err ) = = ERRbadpw ) ) )
{
got_pass = False ;
DEBUG ( 3 , ( " resending login \n " ) ) ;
if ( ! no_pass )
goto get_pass ;
1996-06-04 06:42:03 +00:00
}
1998-06-15 22:02:14 +00:00
DEBUG ( 0 , ( " Session setup failed for username=%s myname=%s destname=%s %s \n " ,
username , global_myname , desthost , smb_errstr ( inbuf ) ) ) ;
DEBUG ( 0 , ( " You might find the -U, -W or -n options useful \n " ) ) ;
DEBUG ( 0 , ( " Sometimes you have to use `-n USERNAME' (particularly with OS/2) \n " ) ) ;
DEBUG ( 0 , ( " Some servers also insist on uppercase-only passwords \n " ) ) ;
if ( was_null )
{
free ( inbuf ) ;
free ( outbuf ) ;
}
return ( False ) ;
}
1996-06-04 06:42:03 +00:00
1998-06-15 22:02:14 +00:00
if ( Protocol > = PROTOCOL_NT1 )
{
char * domain , * os , * lanman ;
p = smb_buf ( inbuf ) ;
os = p ;
lanman = skip_string ( os , 1 ) ;
domain = skip_string ( lanman , 1 ) ;
if ( * domain | | * os | | * lanman )
DEBUG ( 1 , ( " Domain=[%s] OS=[%s] Server=[%s] \n " , domain , os , lanman ) ) ;
1996-06-04 06:42:03 +00:00
}
1998-06-15 22:02:14 +00:00
/* use the returned uid from now on */
1998-09-29 20:24:17 +00:00
if ( SVAL ( inbuf , smb_uid ) ! = vuid )
1998-06-15 22:02:14 +00:00
DEBUG ( 3 , ( " Server gave us a UID of %d. We gave %d \n " ,
1998-09-29 20:24:17 +00:00
SVAL ( inbuf , smb_uid ) , ( int ) vuid ) ) ;
opt . server_vuid = vuid = SVAL ( inbuf , smb_uid ) ;
1998-06-15 22:02:14 +00:00
}
1998-01-05 22:54:32 +00:00
if ( opt . sec_mode & 1 ) {
1997-10-26 07:32:02 +00:00
if ( SVAL ( inbuf , smb_vwv2 ) & 1 )
DEBUG ( 1 , ( " connected as guest " ) ) ;
1997-10-22 14:28:19 +00:00
DEBUG ( 1 , ( " security=user \n " ) ) ;
1997-10-26 07:32:02 +00:00
} else {
1997-10-22 14:28:19 +00:00
DEBUG ( 1 , ( " security=share \n " ) ) ;
1997-10-26 07:32:02 +00:00
}
1997-10-22 14:28:19 +00:00
1996-06-04 06:42:03 +00:00
/* now we've got a connection - send a tcon message */
bzero ( outbuf , smb_size ) ;
if ( strncmp ( service , " \\ \\ " , 2 ) ! = 0 )
{
DEBUG ( 0 , ( " \n Warning: Your service name doesn't start with \\ \\ . This is probably incorrect. \n " ) ) ;
DEBUG ( 0 , ( " Perhaps try replacing each \\ with \\ \\ on the command line? \n \n " ) ) ;
}
again2 :
{
int passlen = strlen ( pass ) + 1 ;
fstring pword ;
1998-05-12 00:55:32 +00:00
fstrcpy ( pword , pass ) ;
1996-06-04 06:42:03 +00:00
if ( doencrypt & & * pass ) {
passlen = 24 ;
1997-07-30 19:17:51 +00:00
SMBencrypt ( ( uchar * ) pass , ( uchar * ) cryptkey , ( uchar * ) pword ) ;
1996-06-04 06:42:03 +00:00
}
/* if in user level security then don't send a password now */
1998-01-05 22:54:32 +00:00
if ( ( opt . sec_mode & 1 ) ) {
1998-05-12 00:55:32 +00:00
fstrcpy ( pword , " " ) ; passlen = 1 ;
1996-06-04 06:42:03 +00:00
}
1997-10-22 14:28:19 +00:00
if ( Protocol < = PROTOCOL_COREPLUS ) {
set_message ( outbuf , 0 , 6 + strlen ( service ) + passlen + strlen ( dev ) , True ) ;
CVAL ( outbuf , smb_com ) = SMBtcon ;
cli_setup_pkt ( outbuf ) ;
p = smb_buf ( outbuf ) ;
* p + + = 0x04 ;
1998-05-12 00:55:32 +00:00
pstrcpy ( p , service ) ;
1997-10-22 14:28:19 +00:00
p = skip_string ( p , 1 ) ;
* p + + = 0x04 ;
memcpy ( p , pword , passlen ) ;
p + = passlen ;
* p + + = 0x04 ;
1998-05-12 00:55:32 +00:00
pstrcpy ( p , dev ) ;
1997-10-22 14:28:19 +00:00
}
else {
set_message ( outbuf , 4 , 2 + strlen ( service ) + passlen + strlen ( dev ) , True ) ;
CVAL ( outbuf , smb_com ) = SMBtconX ;
cli_setup_pkt ( outbuf ) ;
SSVAL ( outbuf , smb_vwv0 , 0xFF ) ;
SSVAL ( outbuf , smb_vwv3 , passlen ) ;
p = smb_buf ( outbuf ) ;
memcpy ( p , pword , passlen ) ;
p + = passlen ;
1998-05-12 00:55:32 +00:00
pstrcpy ( p , service ) ;
1997-10-22 14:28:19 +00:00
p = skip_string ( p , 1 ) ;
1998-05-12 00:55:32 +00:00
pstrcpy ( p , dev ) ;
1997-10-22 14:28:19 +00:00
}
1996-06-04 06:42:03 +00:00
}
send_smb ( Client , outbuf ) ;
1997-12-20 14:36:11 +00:00
client_receive_smb ( Client , inbuf , CLIENT_TIMEOUT ) ;
1996-06-04 06:42:03 +00:00
/* trying again with a blank password */
if ( CVAL ( inbuf , smb_rcls ) ! = 0 & &
( int ) strlen ( pass ) > 0 & &
! doencrypt & &
Protocol > = PROTOCOL_LANMAN1 )
{
DEBUG ( 2 , ( " first SMBtconX failed, trying again. %s \n " , smb_errstr ( inbuf ) ) ) ;
1998-05-12 00:55:32 +00:00
pstrcpy ( pass , " " ) ;
1996-06-04 06:42:03 +00:00
goto again2 ;
}
if ( CVAL ( inbuf , smb_rcls ) ! = 0 )
{
DEBUG ( 0 , ( " SMBtconX failed. %s \n " , smb_errstr ( inbuf ) ) ) ;
DEBUG ( 0 , ( " Perhaps you are using the wrong sharename, username or password? \n " ) ) ;
DEBUG ( 0 , ( " Some servers insist that these be in uppercase \n " ) ) ;
if ( was_null )
{
free ( inbuf ) ;
free ( outbuf ) ;
}
return ( False ) ;
}
1997-10-22 14:28:19 +00:00
if ( Protocol < = PROTOCOL_COREPLUS ) {
max_xmit = SVAL ( inbuf , smb_vwv0 ) ;
1996-06-04 06:42:03 +00:00
1997-10-22 14:28:19 +00:00
cnum = SVAL ( inbuf , smb_vwv1 ) ;
}
else {
max_xmit = MIN ( max_xmit , BUFFER_SIZE - 4 ) ;
if ( max_xmit < = 0 )
max_xmit = BUFFER_SIZE - 4 ;
1996-06-04 06:42:03 +00:00
1997-10-22 14:28:19 +00:00
cnum = SVAL ( inbuf , smb_tid ) ;
}
1998-01-05 22:54:32 +00:00
opt . max_xmit = max_xmit ;
opt . tid = cnum ;
1997-10-22 14:28:19 +00:00
DEBUG ( 3 , ( " Connected with cnum=%d max_xmit=%d \n " , cnum , max_xmit ) ) ;
1996-06-04 06:42:03 +00:00
if ( was_null )
{
free ( inbuf ) ;
free ( outbuf ) ;
}
1997-10-22 14:28:19 +00:00
1998-01-05 22:54:32 +00:00
if ( options ! = NULL )
{
* options = opt ;
}
1996-06-04 06:42:03 +00:00
return True ;
}
/****************************************************************************
send a logout command
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-04-13 19:24:06 +00:00
void cli_send_logout ( char * dum_in , char * dum_out )
1996-06-04 06:42:03 +00:00
{
pstring inbuf , outbuf ;
1997-10-23 13:38:46 +00:00
DEBUG ( 5 , ( " cli_send_logout \n " ) ) ;
1996-06-04 06:42:03 +00:00
bzero ( outbuf , smb_size ) ;
set_message ( outbuf , 0 , 0 , True ) ;
CVAL ( outbuf , smb_com ) = SMBtdis ;
SSVAL ( outbuf , smb_tid , cnum ) ;
cli_setup_pkt ( outbuf ) ;
send_smb ( Client , outbuf ) ;
1997-12-20 14:36:11 +00:00
client_receive_smb ( Client , inbuf , SHORT_TIMEOUT ) ;
1996-06-04 06:42:03 +00:00
if ( CVAL ( inbuf , smb_rcls ) ! = 0 )
{
DEBUG ( 0 , ( " SMBtdis failed %s \n " , smb_errstr ( inbuf ) ) ) ;
}
# ifdef STATS
stats_report ( ) ;
# endif
exit ( 0 ) ;
}
/****************************************************************************
open the client sockets
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1997-10-22 14:28:19 +00:00
BOOL cli_open_sockets ( int port )
1996-06-04 06:42:03 +00:00
{
static int last_port ;
char * host ;
pstring service2 ;
extern int Client ;
if ( port = = 0 ) port = last_port ;
last_port = port ;
strupper ( service ) ;
if ( * desthost )
{
host = desthost ;
}
else
{
1998-05-12 00:55:32 +00:00
pstrcpy ( service2 , service ) ;
1996-06-04 06:42:03 +00:00
host = strtok ( service2 , " \\ / " ) ;
1997-10-22 14:28:19 +00:00
if ( ! host ) {
DEBUG ( 0 , ( " Badly formed host name \n " ) ) ;
return ( False ) ;
}
1998-05-12 00:55:32 +00:00
pstrcpy ( desthost , host ) ;
1996-06-04 06:42:03 +00:00
}
1998-04-25 01:12:08 +00:00
if ( ! ( * global_myname ) ) {
get_myname ( global_myname , NULL ) ;
1997-10-22 14:28:19 +00:00
}
1998-04-25 01:12:08 +00:00
strupper ( global_myname ) ;
1996-06-04 06:42:03 +00:00
1997-10-22 14:28:19 +00:00
DEBUG ( 3 , ( " Opening sockets \n " ) ) ;
1996-06-04 06:42:03 +00:00
if ( ! have_ip )
{
1998-10-04 12:00:40 +00:00
if ( ! resolve_name ( host , & dest_ip , 0x20 ) )
1997-10-22 14:28:19 +00:00
{
1998-03-16 20:59:47 +00:00
DEBUG ( 0 , ( " cli_open_sockets: Unknown host %s. \n " , host ) ) ;
1996-06-04 06:42:03 +00:00
return False ;
1997-10-22 14:28:19 +00:00
}
1996-06-04 06:42:03 +00:00
}
1997-10-22 14:28:19 +00:00
Client = open_socket_out ( SOCK_STREAM , & dest_ip , port , LONG_CONNECT_TIMEOUT ) ;
1996-06-04 06:42:03 +00:00
if ( Client = = - 1 )
return False ;
1997-10-22 14:28:19 +00:00
DEBUG ( 3 , ( " Connected \n " ) ) ;
1996-06-04 06:42:03 +00:00
set_socket_options ( Client , user_socket_options ) ;
1997-10-22 14:28:19 +00:00
1996-06-04 06:42:03 +00:00
return True ;
}
/****************************************************************************
close and open the connection again
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL cli_reopen_connection ( char * inbuf , char * outbuf )
{
static int open_count = 0 ;
open_count + + ;
if ( open_count > 5 ) return ( False ) ;
DEBUG ( 1 , ( " Trying to re-open connection \n " ) ) ;
set_message ( outbuf , 0 , 0 , True ) ;
SCVAL ( outbuf , smb_com , SMBtdis ) ;
SSVAL ( outbuf , smb_tid , cnum ) ;
cli_setup_pkt ( outbuf ) ;
send_smb ( Client , outbuf ) ;
1997-12-20 14:36:11 +00:00
client_receive_smb ( Client , inbuf , SHORT_TIMEOUT ) ;
1996-06-04 06:42:03 +00:00
close_sockets ( ) ;
if ( ! cli_open_sockets ( 0 ) ) return ( False ) ;
1998-01-05 22:54:32 +00:00
return ( cli_send_login ( inbuf , outbuf , True , True , NULL ) ) ;
1996-06-04 06:42:03 +00:00
}