2000-04-25 18:04:06 +04:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
2000-04-25 18:04:06 +04:00
client transaction calls
Copyright ( C ) Andrew Tridgell 1994 - 1998
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 .
*/
# define NO_SYSLOG
# include "includes.h"
/****************************************************************************
2003-03-13 03:51:05 +03:00
Send a SMB trans or trans2 request .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-04-25 18:04:06 +04:00
BOOL cli_send_trans ( struct cli_state * cli , int trans ,
2001-07-04 11:15:53 +04:00
const char * pipe_name ,
2000-04-25 18:04:06 +04:00
int fid , int flags ,
2003-03-13 03:51:05 +03:00
uint16 * setup , unsigned int lsetup , unsigned int msetup ,
2003-03-18 02:04:03 +03:00
const char * param , unsigned int lparam , unsigned int mparam ,
const char * data , unsigned int ldata , unsigned int mdata )
2000-04-25 18:04:06 +04:00
{
2003-03-18 02:04:03 +03:00
unsigned int i ;
2003-03-13 03:51:05 +03:00
unsigned int this_ldata , this_lparam ;
unsigned int tot_data = 0 , tot_param = 0 ;
2000-04-25 18:04:06 +04:00
char * outdata , * outparam ;
char * p ;
2001-02-20 13:11:40 +03:00
int pipe_name_len = 0 ;
2003-08-02 04:29:45 +04:00
uint16 mid ;
2000-04-25 18:04:06 +04:00
this_lparam = MIN ( lparam , cli - > max_xmit - ( 500 + lsetup * 2 ) ) ; /* hack */
this_ldata = MIN ( ldata , cli - > max_xmit - ( 500 + lsetup * 2 + this_lparam ) ) ;
memset ( cli - > outbuf , ' \0 ' , smb_size ) ;
set_message ( cli - > outbuf , 14 + lsetup , 0 , True ) ;
2002-01-11 22:10:25 +03:00
SCVAL ( cli - > outbuf , smb_com , trans ) ;
2000-04-25 18:04:06 +04:00
SSVAL ( cli - > outbuf , smb_tid , cli - > cnum ) ;
cli_setup_packet ( cli ) ;
2003-12-01 04:04:04 +03:00
/*
* Save the mid we ' re using . We need this for finding
* signing replies .
*/
2003-08-02 04:29:45 +04:00
mid = cli - > mid ;
2000-04-25 18:04:06 +04:00
2001-02-20 13:11:40 +03:00
if ( pipe_name ) {
2001-03-14 15:42:43 +03:00
pipe_name_len = clistr_push ( cli , smb_buf ( cli - > outbuf ) , pipe_name , - 1 , STR_TERMINATE ) ;
2001-02-20 13:11:40 +03:00
}
outparam = smb_buf ( cli - > outbuf ) + ( trans = = SMBtrans ? pipe_name_len : 3 ) ;
2000-04-25 18:04:06 +04:00
outdata = outparam + this_lparam ;
/* primary request */
SSVAL ( cli - > outbuf , smb_tpscnt , lparam ) ; /* tpscnt */
SSVAL ( cli - > outbuf , smb_tdscnt , ldata ) ; /* tdscnt */
SSVAL ( cli - > outbuf , smb_mprcnt , mparam ) ; /* mprcnt */
SSVAL ( cli - > outbuf , smb_mdrcnt , mdata ) ; /* mdrcnt */
SCVAL ( cli - > outbuf , smb_msrcnt , msetup ) ; /* msrcnt */
SSVAL ( cli - > outbuf , smb_flags , flags ) ; /* flags */
SIVAL ( cli - > outbuf , smb_timeout , 0 ) ; /* timeout */
SSVAL ( cli - > outbuf , smb_pscnt , this_lparam ) ; /* pscnt */
SSVAL ( cli - > outbuf , smb_psoff , smb_offset ( outparam , cli - > outbuf ) ) ; /* psoff */
SSVAL ( cli - > outbuf , smb_dscnt , this_ldata ) ; /* dscnt */
SSVAL ( cli - > outbuf , smb_dsoff , smb_offset ( outdata , cli - > outbuf ) ) ; /* dsoff */
SCVAL ( cli - > outbuf , smb_suwcnt , lsetup ) ; /* suwcnt */
for ( i = 0 ; i < lsetup ; i + + ) /* setup[] */
SSVAL ( cli - > outbuf , smb_setup + i * 2 , setup [ i ] ) ;
p = smb_buf ( cli - > outbuf ) ;
2001-03-14 15:42:43 +03:00
if ( trans ! = SMBtrans ) {
2000-04-25 18:04:06 +04:00
* p + + = 0 ; /* put in a null smb_name */
* p + + = ' D ' ; * p + + = ' ' ; /* observed in OS/2 */
}
if ( this_lparam ) /* param[] */
memcpy ( outparam , param , this_lparam ) ;
if ( this_ldata ) /* data[] */
memcpy ( outdata , data , this_ldata ) ;
2001-02-20 15:45:50 +03:00
cli_setup_bcc ( cli , outdata + this_ldata ) ;
2000-04-25 18:04:06 +04:00
show_msg ( cli - > outbuf ) ;
2003-08-02 04:29:45 +04:00
2003-08-02 11:07:38 +04:00
if ( ! cli_send_smb ( cli ) ) {
2003-03-13 03:51:05 +03:00
return False ;
2003-08-02 11:07:38 +04:00
}
2000-04-25 18:04:06 +04:00
if ( this_ldata < ldata | | this_lparam < lparam ) {
/* receive interim response */
2003-08-02 11:07:38 +04:00
if ( ! cli_receive_smb ( cli ) | | cli_is_error ( cli ) ) {
2000-04-25 18:04:06 +04:00
return ( False ) ;
2003-08-02 11:07:38 +04:00
}
2000-04-25 18:04:06 +04:00
tot_data = this_ldata ;
tot_param = this_lparam ;
while ( tot_data < ldata | | tot_param < lparam ) {
this_lparam = MIN ( lparam - tot_param , cli - > max_xmit - 500 ) ; /* hack */
this_ldata = MIN ( ldata - tot_data , cli - > max_xmit - ( 500 + this_lparam ) ) ;
set_message ( cli - > outbuf , trans = = SMBtrans ? 8 : 9 , 0 , True ) ;
2002-01-11 22:10:25 +03:00
SCVAL ( cli - > outbuf , smb_com , ( trans = = SMBtrans ? SMBtranss : SMBtranss2 ) ) ;
2000-04-25 18:04:06 +04:00
outparam = smb_buf ( cli - > outbuf ) ;
outdata = outparam + this_lparam ;
/* secondary request */
SSVAL ( cli - > outbuf , smb_tpscnt , lparam ) ; /* tpscnt */
SSVAL ( cli - > outbuf , smb_tdscnt , ldata ) ; /* tdscnt */
SSVAL ( cli - > outbuf , smb_spscnt , this_lparam ) ; /* pscnt */
SSVAL ( cli - > outbuf , smb_spsoff , smb_offset ( outparam , cli - > outbuf ) ) ; /* psoff */
SSVAL ( cli - > outbuf , smb_spsdisp , tot_param ) ; /* psdisp */
SSVAL ( cli - > outbuf , smb_sdscnt , this_ldata ) ; /* dscnt */
SSVAL ( cli - > outbuf , smb_sdsoff , smb_offset ( outdata , cli - > outbuf ) ) ; /* dsoff */
SSVAL ( cli - > outbuf , smb_sdsdisp , tot_data ) ; /* dsdisp */
if ( trans = = SMBtrans2 )
SSVALS ( cli - > outbuf , smb_sfid , fid ) ; /* fid */
if ( this_lparam ) /* param[] */
memcpy ( outparam , param + tot_param , this_lparam ) ;
if ( this_ldata ) /* data[] */
memcpy ( outdata , data + tot_data , this_ldata ) ;
2001-02-20 15:45:50 +03:00
cli_setup_bcc ( cli , outdata + this_ldata ) ;
2000-04-25 18:04:06 +04:00
2003-11-30 22:40:57 +03:00
/*
2003-12-01 04:04:04 +03:00
* Save the mid we ' re using . We need this for finding
* signing replies .
2003-11-30 22:40:57 +03:00
*/
2003-12-01 04:04:04 +03:00
mid = cli - > mid ;
2003-11-30 22:40:57 +03:00
2000-04-25 18:04:06 +04:00
show_msg ( cli - > outbuf ) ;
2003-08-02 11:07:38 +04:00
if ( ! cli_send_smb ( cli ) ) {
2003-03-13 03:51:05 +03:00
return False ;
2003-08-02 11:07:38 +04:00
}
2003-12-01 06:24:50 +03:00
/* Ensure we use the same mid for the secondaries. */
cli - > mid = mid ;
2000-04-25 18:04:06 +04:00
tot_data + = this_ldata ;
tot_param + = this_lparam ;
}
}
2003-12-01 04:04:04 +03:00
/* Note we're in a trans state. Save the sequence
* numbers for replies . */
cli_signing_trans_start ( cli , mid ) ;
2000-04-25 18:04:06 +04:00
return ( True ) ;
}
/****************************************************************************
2003-03-13 03:51:05 +03:00
Receive a SMB trans or trans2 response allocating the necessary memory .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-04-25 18:04:06 +04:00
BOOL cli_receive_trans ( struct cli_state * cli , int trans ,
2003-03-13 03:51:05 +03:00
char * * param , unsigned int * param_len ,
char * * data , unsigned int * data_len )
2000-04-25 18:04:06 +04:00
{
2003-03-13 03:51:05 +03:00
unsigned int total_data = 0 ;
unsigned int total_param = 0 ;
unsigned int this_data , this_param ;
2001-08-27 21:52:23 +04:00
NTSTATUS status ;
2001-08-12 21:30:01 +04:00
char * tdata ;
2001-08-17 22:16:42 +04:00
char * tparam ;
2000-04-25 18:04:06 +04:00
* data_len = * param_len = 0 ;
2003-08-02 11:07:38 +04:00
if ( ! cli_receive_smb ( cli ) ) {
cli_signing_trans_stop ( cli ) ;
2000-04-25 18:04:06 +04:00
return False ;
2003-08-02 11:07:38 +04:00
}
2000-04-25 18:04:06 +04:00
show_msg ( cli - > inbuf ) ;
/* sanity check */
if ( CVAL ( cli - > inbuf , smb_com ) ! = trans ) {
DEBUG ( 0 , ( " Expected %s response, got command 0x%02x \n " ,
trans = = SMBtrans ? " SMBtrans " : " SMBtrans2 " ,
CVAL ( cli - > inbuf , smb_com ) ) ) ;
2003-08-02 11:07:38 +04:00
cli_signing_trans_stop ( cli ) ;
2000-04-25 18:04:06 +04:00
return ( False ) ;
}
/*
* An NT RPC pipe call can return ERRDOS , ERRmoredata
* to a trans call . This is not an error and should not
* be treated as such .
*/
2001-08-27 21:52:23 +04:00
status = cli_nt_error ( cli ) ;
2003-08-02 11:07:38 +04:00
if ( NT_STATUS_IS_ERR ( status ) ) {
cli_signing_trans_stop ( cli ) ;
2001-08-20 09:15:26 +04:00
return False ;
2003-08-02 11:07:38 +04:00
}
2000-04-25 18:04:06 +04:00
/* parse out the lengths */
total_data = SVAL ( cli - > inbuf , smb_tdrcnt ) ;
total_param = SVAL ( cli - > inbuf , smb_tprcnt ) ;
/* allocate it */
2001-08-17 21:07:40 +04:00
if ( total_data ! = 0 ) {
tdata = Realloc ( * data , total_data ) ;
if ( ! tdata ) {
DEBUG ( 0 , ( " cli_receive_trans: failed to enlarge data buffer \n " ) ) ;
2003-08-02 11:07:38 +04:00
cli_signing_trans_stop ( cli ) ;
2001-08-17 21:07:40 +04:00
return False ;
}
else
* data = tdata ;
2001-08-12 21:30:01 +04:00
}
2001-08-17 21:07:40 +04:00
if ( total_param ! = 0 ) {
2001-08-17 22:16:42 +04:00
tparam = Realloc ( * param , total_param ) ;
if ( ! tparam ) {
2001-08-17 21:07:40 +04:00
DEBUG ( 0 , ( " cli_receive_trans: failed to enlarge param buffer \n " ) ) ;
2003-08-02 11:07:38 +04:00
cli_signing_trans_stop ( cli ) ;
2001-08-17 21:07:40 +04:00
return False ;
}
else
2001-08-17 22:16:42 +04:00
* param = tparam ;
2001-08-12 21:30:01 +04:00
}
2000-04-25 18:04:06 +04:00
2003-03-13 03:51:05 +03:00
for ( ; ; ) {
2000-04-25 18:04:06 +04:00
this_data = SVAL ( cli - > inbuf , smb_drcnt ) ;
this_param = SVAL ( cli - > inbuf , smb_prcnt ) ;
if ( this_data + * data_len > total_data | |
this_param + * param_len > total_param ) {
DEBUG ( 1 , ( " Data overflow in cli_receive_trans \n " ) ) ;
2003-08-02 11:07:38 +04:00
cli_signing_trans_stop ( cli ) ;
2000-04-25 18:04:06 +04:00
return False ;
}
2003-03-13 03:51:05 +03:00
if ( this_data + * data_len < this_data | |
this_data + * data_len < * data_len | |
this_param + * param_len < this_param | |
this_param + * param_len < * param_len ) {
DEBUG ( 1 , ( " Data overflow in cli_receive_trans \n " ) ) ;
2003-08-02 11:07:38 +04:00
cli_signing_trans_stop ( cli ) ;
2003-03-13 03:51:05 +03:00
return False ;
}
if ( this_data ) {
unsigned int data_offset_out = SVAL ( cli - > inbuf , smb_drdisp ) ;
unsigned int data_offset_in = SVAL ( cli - > inbuf , smb_droff ) ;
if ( data_offset_out > total_data | |
data_offset_out + this_data > total_data | |
data_offset_out + this_data < data_offset_out | |
data_offset_out + this_data < this_data ) {
DEBUG ( 1 , ( " Data overflow in cli_receive_trans \n " ) ) ;
2003-08-02 11:07:38 +04:00
cli_signing_trans_stop ( cli ) ;
2003-03-13 03:51:05 +03:00
return False ;
}
if ( data_offset_in > cli - > bufsize | |
data_offset_in + this_data > cli - > bufsize | |
data_offset_in + this_data < data_offset_in | |
data_offset_in + this_data < this_data ) {
DEBUG ( 1 , ( " Data overflow in cli_receive_trans \n " ) ) ;
2003-08-02 11:07:38 +04:00
cli_signing_trans_stop ( cli ) ;
2003-03-13 03:51:05 +03:00
return False ;
}
memcpy ( * data + data_offset_out , smb_base ( cli - > inbuf ) + data_offset_in , this_data ) ;
}
if ( this_param ) {
unsigned int param_offset_out = SVAL ( cli - > inbuf , smb_prdisp ) ;
unsigned int param_offset_in = SVAL ( cli - > inbuf , smb_proff ) ;
if ( param_offset_out > total_param | |
param_offset_out + this_param > total_param | |
param_offset_out + this_param < param_offset_out | |
param_offset_out + this_param < this_param ) {
DEBUG ( 1 , ( " Param overflow in cli_receive_trans \n " ) ) ;
2003-08-02 11:07:38 +04:00
cli_signing_trans_stop ( cli ) ;
2003-03-13 03:51:05 +03:00
return False ;
}
if ( param_offset_in > cli - > bufsize | |
param_offset_in + this_param > cli - > bufsize | |
param_offset_in + this_param < param_offset_in | |
param_offset_in + this_param < this_param ) {
DEBUG ( 1 , ( " Param overflow in cli_receive_trans \n " ) ) ;
2003-08-02 11:07:38 +04:00
cli_signing_trans_stop ( cli ) ;
2003-03-13 03:51:05 +03:00
return False ;
}
memcpy ( * param + param_offset_out , smb_base ( cli - > inbuf ) + param_offset_in , this_param ) ;
}
2000-04-25 18:04:06 +04:00
* data_len + = this_data ;
* param_len + = this_param ;
if ( total_data < = * data_len & & total_param < = * param_len )
break ;
2003-08-02 11:07:38 +04:00
if ( ! cli_receive_smb ( cli ) ) {
cli_signing_trans_stop ( cli ) ;
return False ;
}
2000-04-25 18:04:06 +04:00
show_msg ( cli - > inbuf ) ;
/* sanity check */
if ( CVAL ( cli - > inbuf , smb_com ) ! = trans ) {
DEBUG ( 0 , ( " Expected %s response, got command 0x%02x \n " ,
trans = = SMBtrans ? " SMBtrans " : " SMBtrans2 " ,
CVAL ( cli - > inbuf , smb_com ) ) ) ;
2003-08-02 11:07:38 +04:00
cli_signing_trans_stop ( cli ) ;
2000-04-25 18:04:06 +04:00
return ( False ) ;
}
2001-08-27 21:52:23 +04:00
if ( NT_STATUS_IS_ERR ( cli_nt_error ( cli ) ) ) {
2003-08-02 11:07:38 +04:00
cli_signing_trans_stop ( cli ) ;
2001-08-27 21:52:23 +04:00
return ( False ) ;
2000-04-25 18:04:06 +04:00
}
2003-03-13 03:51:05 +03:00
/* parse out the total lengths again - they can shrink! */
if ( SVAL ( cli - > inbuf , smb_tdrcnt ) < total_data )
total_data = SVAL ( cli - > inbuf , smb_tdrcnt ) ;
if ( SVAL ( cli - > inbuf , smb_tprcnt ) < total_param )
total_param = SVAL ( cli - > inbuf , smb_tprcnt ) ;
if ( total_data < = * data_len & & total_param < = * param_len )
break ;
2000-04-25 18:04:06 +04:00
}
2003-08-02 04:29:45 +04:00
cli_signing_trans_stop ( cli ) ;
2000-04-25 18:04:06 +04:00
return ( True ) ;
}
2000-12-03 05:18:14 +03:00
/****************************************************************************
2003-03-13 03:51:05 +03:00
Send a SMB nttrans request .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-12-03 05:18:14 +03:00
BOOL cli_send_nt_trans ( struct cli_state * cli ,
int function ,
int flags ,
2003-03-13 03:51:05 +03:00
uint16 * setup , unsigned int lsetup , unsigned int msetup ,
char * param , unsigned int lparam , unsigned int mparam ,
char * data , unsigned int ldata , unsigned int mdata )
2000-12-03 05:18:14 +03:00
{
2003-03-13 03:51:05 +03:00
unsigned int i ;
unsigned int this_ldata , this_lparam ;
unsigned int tot_data = 0 , tot_param = 0 ;
2003-08-02 04:29:45 +04:00
uint16 mid ;
2000-12-03 05:18:14 +03:00
char * outdata , * outparam ;
this_lparam = MIN ( lparam , cli - > max_xmit - ( 500 + lsetup * 2 ) ) ; /* hack */
this_ldata = MIN ( ldata , cli - > max_xmit - ( 500 + lsetup * 2 + this_lparam ) ) ;
memset ( cli - > outbuf , ' \0 ' , smb_size ) ;
set_message ( cli - > outbuf , 19 + lsetup , 0 , True ) ;
2002-01-11 22:10:25 +03:00
SCVAL ( cli - > outbuf , smb_com , SMBnttrans ) ;
2000-12-03 05:18:14 +03:00
SSVAL ( cli - > outbuf , smb_tid , cli - > cnum ) ;
cli_setup_packet ( cli ) ;
2003-12-01 04:04:04 +03:00
/*
* Save the mid we ' re using . We need this for finding
* signing replies .
*/
2003-08-02 04:29:45 +04:00
mid = cli - > mid ;
2000-12-03 05:18:14 +03:00
outparam = smb_buf ( cli - > outbuf ) + 3 ;
outdata = outparam + this_lparam ;
/* primary request */
SCVAL ( cli - > outbuf , smb_nt_MaxSetupCount , msetup ) ;
SCVAL ( cli - > outbuf , smb_nt_Flags , flags ) ;
SIVAL ( cli - > outbuf , smb_nt_TotalParameterCount , lparam ) ;
SIVAL ( cli - > outbuf , smb_nt_TotalDataCount , ldata ) ;
SIVAL ( cli - > outbuf , smb_nt_MaxParameterCount , mparam ) ;
SIVAL ( cli - > outbuf , smb_nt_MaxDataCount , mdata ) ;
SIVAL ( cli - > outbuf , smb_nt_ParameterCount , this_lparam ) ;
SIVAL ( cli - > outbuf , smb_nt_ParameterOffset , smb_offset ( outparam , cli - > outbuf ) ) ;
SIVAL ( cli - > outbuf , smb_nt_DataCount , this_ldata ) ;
SIVAL ( cli - > outbuf , smb_nt_DataOffset , smb_offset ( outdata , cli - > outbuf ) ) ;
SIVAL ( cli - > outbuf , smb_nt_SetupCount , lsetup ) ;
SIVAL ( cli - > outbuf , smb_nt_Function , function ) ;
for ( i = 0 ; i < lsetup ; i + + ) /* setup[] */
SSVAL ( cli - > outbuf , smb_nt_SetupStart + i * 2 , setup [ i ] ) ;
if ( this_lparam ) /* param[] */
memcpy ( outparam , param , this_lparam ) ;
if ( this_ldata ) /* data[] */
memcpy ( outdata , data , this_ldata ) ;
2001-02-20 15:45:50 +03:00
cli_setup_bcc ( cli , outdata + this_ldata ) ;
2000-12-03 05:18:14 +03:00
show_msg ( cli - > outbuf ) ;
2003-08-02 11:07:38 +04:00
if ( ! cli_send_smb ( cli ) ) {
2003-03-13 03:51:05 +03:00
return False ;
2003-08-02 11:07:38 +04:00
}
2000-12-03 05:18:14 +03:00
if ( this_ldata < ldata | | this_lparam < lparam ) {
/* receive interim response */
2003-08-02 11:07:38 +04:00
if ( ! cli_receive_smb ( cli ) | | cli_is_error ( cli ) ) {
2000-12-03 05:18:14 +03:00
return ( False ) ;
2003-08-02 11:07:38 +04:00
}
2000-12-03 05:18:14 +03:00
tot_data = this_ldata ;
tot_param = this_lparam ;
while ( tot_data < ldata | | tot_param < lparam ) {
this_lparam = MIN ( lparam - tot_param , cli - > max_xmit - 500 ) ; /* hack */
this_ldata = MIN ( ldata - tot_data , cli - > max_xmit - ( 500 + this_lparam ) ) ;
set_message ( cli - > outbuf , 18 , 0 , True ) ;
2002-01-11 22:10:25 +03:00
SCVAL ( cli - > outbuf , smb_com , SMBnttranss ) ;
2000-12-03 05:18:14 +03:00
/* XXX - these should probably be aligned */
outparam = smb_buf ( cli - > outbuf ) ;
outdata = outparam + this_lparam ;
/* secondary request */
SIVAL ( cli - > outbuf , smb_nts_TotalParameterCount , lparam ) ;
SIVAL ( cli - > outbuf , smb_nts_TotalDataCount , ldata ) ;
SIVAL ( cli - > outbuf , smb_nts_ParameterCount , this_lparam ) ;
SIVAL ( cli - > outbuf , smb_nts_ParameterOffset , smb_offset ( outparam , cli - > outbuf ) ) ;
SIVAL ( cli - > outbuf , smb_nts_ParameterDisplacement , tot_param ) ;
SIVAL ( cli - > outbuf , smb_nts_DataCount , this_ldata ) ;
SIVAL ( cli - > outbuf , smb_nts_DataOffset , smb_offset ( outdata , cli - > outbuf ) ) ;
SIVAL ( cli - > outbuf , smb_nts_DataDisplacement , tot_data ) ;
if ( this_lparam ) /* param[] */
memcpy ( outparam , param + tot_param , this_lparam ) ;
if ( this_ldata ) /* data[] */
memcpy ( outdata , data + tot_data , this_ldata ) ;
2001-02-20 15:45:50 +03:00
cli_setup_bcc ( cli , outdata + this_ldata ) ;
2000-12-03 05:18:14 +03:00
2003-11-30 22:40:57 +03:00
/*
2003-12-01 04:04:04 +03:00
* Save the mid we ' re using . We need this for finding
* signing replies .
2003-11-30 22:40:57 +03:00
*/
2003-12-01 04:04:04 +03:00
mid = cli - > mid ;
2003-11-30 22:40:57 +03:00
2000-12-03 05:18:14 +03:00
show_msg ( cli - > outbuf ) ;
2003-08-02 04:29:45 +04:00
2003-08-02 11:07:38 +04:00
if ( ! cli_send_smb ( cli ) ) {
2003-03-13 03:51:05 +03:00
return False ;
2003-08-02 11:07:38 +04:00
}
2000-12-03 05:18:14 +03:00
2003-12-01 06:24:50 +03:00
/* Ensure we use the same mid for the secondaries. */
cli - > mid = mid ;
2000-12-03 05:18:14 +03:00
tot_data + = this_ldata ;
tot_param + = this_lparam ;
}
}
2003-12-01 04:04:04 +03:00
/* Note we're in a trans state. Save the sequence
* numbers for replies . */
cli_signing_trans_start ( cli , mid ) ;
2000-12-03 05:18:14 +03:00
return ( True ) ;
}
/****************************************************************************
receive a SMB nttrans response allocating the necessary memory
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-03-13 03:51:05 +03:00
2000-12-03 05:18:14 +03:00
BOOL cli_receive_nt_trans ( struct cli_state * cli ,
2003-03-13 03:51:05 +03:00
char * * param , unsigned int * param_len ,
char * * data , unsigned int * data_len )
2000-12-03 05:18:14 +03:00
{
2003-03-13 03:51:05 +03:00
unsigned int total_data = 0 ;
unsigned int total_param = 0 ;
unsigned int this_data , this_param ;
2000-12-03 05:18:14 +03:00
uint8 eclass ;
uint32 ecode ;
2001-08-12 21:30:01 +04:00
char * tdata ;
2001-08-17 22:16:42 +04:00
char * tparam ;
2000-12-03 05:18:14 +03:00
* data_len = * param_len = 0 ;
2003-08-02 11:07:38 +04:00
if ( ! cli_receive_smb ( cli ) ) {
cli_signing_trans_stop ( cli ) ;
2000-12-03 05:18:14 +03:00
return False ;
2003-08-02 11:07:38 +04:00
}
2000-12-03 05:18:14 +03:00
show_msg ( cli - > inbuf ) ;
/* sanity check */
if ( CVAL ( cli - > inbuf , smb_com ) ! = SMBnttrans ) {
DEBUG ( 0 , ( " Expected SMBnttrans response, got command 0x%02x \n " ,
CVAL ( cli - > inbuf , smb_com ) ) ) ;
2003-08-02 11:07:38 +04:00
cli_signing_trans_stop ( cli ) ;
2000-12-03 05:18:14 +03:00
return ( False ) ;
}
/*
* An NT RPC pipe call can return ERRDOS , ERRmoredata
* to a trans call . This is not an error and should not
* be treated as such .
*/
2001-08-10 10:00:33 +04:00
if ( cli_is_dos_error ( cli ) ) {
cli_dos_error ( cli , & eclass , & ecode ) ;
2003-08-02 11:07:38 +04:00
if ( cli - > nt_pipe_fnum = = 0 | | ! ( eclass = = ERRDOS & & ecode = = ERRmoredata ) ) {
cli_signing_trans_stop ( cli ) ;
2000-12-03 05:18:14 +03:00
return ( False ) ;
2003-08-02 11:07:38 +04:00
}
2000-12-03 05:18:14 +03:00
}
2003-10-20 12:41:32 +04:00
/*
* Likewise for NT_STATUS_BUFFER_TOO_SMALL
*/
if ( cli_is_nt_error ( cli ) ) {
if ( ! NT_STATUS_EQUAL ( cli_nt_error ( cli ) ,
NT_STATUS_BUFFER_TOO_SMALL ) ) {
cli_signing_trans_stop ( cli ) ;
return ( False ) ;
}
}
2000-12-03 05:18:14 +03:00
/* parse out the lengths */
total_data = SVAL ( cli - > inbuf , smb_ntr_TotalDataCount ) ;
total_param = SVAL ( cli - > inbuf , smb_ntr_TotalParameterCount ) ;
/* allocate it */
2001-08-27 12:19:43 +04:00
if ( total_data ) {
tdata = Realloc ( * data , total_data ) ;
if ( ! tdata ) {
DEBUG ( 0 , ( " cli_receive_nt_trans: failed to enlarge data buffer to %d \n " , total_data ) ) ;
2003-08-02 11:07:38 +04:00
cli_signing_trans_stop ( cli ) ;
2001-08-27 12:19:43 +04:00
return False ;
} else {
* data = tdata ;
}
2001-08-12 21:30:01 +04:00
}
2001-08-27 12:19:43 +04:00
if ( total_param ) {
tparam = Realloc ( * param , total_param ) ;
if ( ! tparam ) {
DEBUG ( 0 , ( " cli_receive_nt_trans: failed to enlarge param buffer to %d \n " , total_param ) ) ;
2003-08-02 11:07:38 +04:00
cli_signing_trans_stop ( cli ) ;
2001-08-27 12:19:43 +04:00
return False ;
} else {
* param = tparam ;
}
2001-08-12 21:30:01 +04:00
}
2000-12-03 05:18:14 +03:00
while ( 1 ) {
this_data = SVAL ( cli - > inbuf , smb_ntr_DataCount ) ;
this_param = SVAL ( cli - > inbuf , smb_ntr_ParameterCount ) ;
if ( this_data + * data_len > total_data | |
this_param + * param_len > total_param ) {
2003-03-13 03:51:05 +03:00
DEBUG ( 1 , ( " Data overflow in cli_receive_nt_trans \n " ) ) ;
2003-08-02 11:07:38 +04:00
cli_signing_trans_stop ( cli ) ;
2003-03-13 03:51:05 +03:00
return False ;
}
if ( this_data + * data_len < this_data | |
this_data + * data_len < * data_len | |
this_param + * param_len < this_param | |
this_param + * param_len < * param_len ) {
DEBUG ( 1 , ( " Data overflow in cli_receive_nt_trans \n " ) ) ;
2003-08-02 11:07:38 +04:00
cli_signing_trans_stop ( cli ) ;
2000-12-03 05:18:14 +03:00
return False ;
}
2003-03-13 03:51:05 +03:00
if ( this_data ) {
unsigned int data_offset_out = SVAL ( cli - > inbuf , smb_ntr_DataDisplacement ) ;
unsigned int data_offset_in = SVAL ( cli - > inbuf , smb_ntr_DataOffset ) ;
if ( data_offset_out > total_data | |
data_offset_out + this_data > total_data | |
data_offset_out + this_data < data_offset_out | |
data_offset_out + this_data < this_data ) {
DEBUG ( 1 , ( " Data overflow in cli_receive_nt_trans \n " ) ) ;
2003-08-02 11:07:38 +04:00
cli_signing_trans_stop ( cli ) ;
2003-03-13 03:51:05 +03:00
return False ;
}
if ( data_offset_in > cli - > bufsize | |
data_offset_in + this_data > cli - > bufsize | |
data_offset_in + this_data < data_offset_in | |
data_offset_in + this_data < this_data ) {
DEBUG ( 1 , ( " Data overflow in cli_receive_nt_trans \n " ) ) ;
2003-08-02 11:07:38 +04:00
cli_signing_trans_stop ( cli ) ;
2003-03-13 03:51:05 +03:00
return False ;
}
memcpy ( * data + data_offset_out , smb_base ( cli - > inbuf ) + data_offset_in , this_data ) ;
}
if ( this_param ) {
unsigned int param_offset_out = SVAL ( cli - > inbuf , smb_ntr_ParameterDisplacement ) ;
unsigned int param_offset_in = SVAL ( cli - > inbuf , smb_ntr_ParameterOffset ) ;
if ( param_offset_out > total_param | |
param_offset_out + this_param > total_param | |
param_offset_out + this_param < param_offset_out | |
param_offset_out + this_param < this_param ) {
DEBUG ( 1 , ( " Param overflow in cli_receive_nt_trans \n " ) ) ;
2003-08-02 11:07:38 +04:00
cli_signing_trans_stop ( cli ) ;
2003-03-13 03:51:05 +03:00
return False ;
}
if ( param_offset_in > cli - > bufsize | |
param_offset_in + this_param > cli - > bufsize | |
param_offset_in + this_param < param_offset_in | |
param_offset_in + this_param < this_param ) {
DEBUG ( 1 , ( " Param overflow in cli_receive_nt_trans \n " ) ) ;
2003-08-02 11:07:38 +04:00
cli_signing_trans_stop ( cli ) ;
2003-03-13 03:51:05 +03:00
return False ;
}
memcpy ( * param + param_offset_out , smb_base ( cli - > inbuf ) + param_offset_in , this_param ) ;
}
2000-12-03 05:18:14 +03:00
* data_len + = this_data ;
* param_len + = this_param ;
if ( total_data < = * data_len & & total_param < = * param_len )
break ;
2003-08-02 11:07:38 +04:00
if ( ! cli_receive_smb ( cli ) ) {
cli_signing_trans_stop ( cli ) ;
2000-12-03 05:18:14 +03:00
return False ;
2003-08-02 11:07:38 +04:00
}
2000-12-03 05:18:14 +03:00
show_msg ( cli - > inbuf ) ;
/* sanity check */
if ( CVAL ( cli - > inbuf , smb_com ) ! = SMBnttrans ) {
DEBUG ( 0 , ( " Expected SMBnttrans response, got command 0x%02x \n " ,
CVAL ( cli - > inbuf , smb_com ) ) ) ;
2003-08-02 11:07:38 +04:00
cli_signing_trans_stop ( cli ) ;
2000-12-03 05:18:14 +03:00
return ( False ) ;
}
2001-08-10 10:00:33 +04:00
if ( cli_is_dos_error ( cli ) ) {
cli_dos_error ( cli , & eclass , & ecode ) ;
2003-08-02 11:07:38 +04:00
if ( cli - > nt_pipe_fnum = = 0 | | ! ( eclass = = ERRDOS & & ecode = = ERRmoredata ) ) {
cli_signing_trans_stop ( cli ) ;
2000-12-03 05:18:14 +03:00
return ( False ) ;
2003-08-02 11:07:38 +04:00
}
2000-12-03 05:18:14 +03:00
}
2003-03-13 03:51:05 +03:00
/* parse out the total lengths again - they can shrink! */
if ( SVAL ( cli - > inbuf , smb_ntr_TotalDataCount ) < total_data )
total_data = SVAL ( cli - > inbuf , smb_ntr_TotalDataCount ) ;
if ( SVAL ( cli - > inbuf , smb_ntr_TotalParameterCount ) < total_param )
total_param = SVAL ( cli - > inbuf , smb_ntr_TotalParameterCount ) ;
if ( total_data < = * data_len & & total_param < = * param_len )
break ;
2000-12-03 05:18:14 +03:00
}
2003-08-02 04:29:45 +04:00
cli_signing_trans_stop ( cli ) ;
2000-12-03 05:18:14 +03:00
return ( True ) ;
}