1996-05-04 07:50:46 +00:00
/*
2002-01-30 06:08:46 +00:00
Unix SMB / CIFS implementation .
1996-05-04 07:50:46 +00:00
Inter - process communication and named pipe handling
1998-01-22 13:27:43 +00:00
Copyright ( C ) Andrew Tridgell 1992 - 1998
1997-07-09 11:04:45 +00:00
SMB Version handling
1998-01-22 13:27:43 +00:00
Copyright ( C ) John H Terpstra 1995 - 1998
1996-05-04 07:50:46 +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
2007-07-09 19:25:36 +00:00
the Free Software Foundation ; either version 3 of the License , or
1996-05-04 07:50:46 +00:00
( 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
2007-07-10 00:52:41 +00:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
1996-05-04 07:50:46 +00:00
*/
/*
This file handles the named pipe and mailslot calls
in the SMBtrans protocol
*/
# include "includes.h"
1997-02-28 20:39:36 +00:00
extern int max_send ;
1996-05-04 07:50:46 +00:00
# define NERR_notsupported 50
1997-11-18 23:30:49 +00:00
extern int smb_read_error ;
1996-05-04 07:50:46 +00:00
1998-03-11 21:11:04 +00:00
/*******************************************************************
copies parameters and data , as needed , into the smb buffer
* both * the data and params sections should be aligned . this
is fudged in the rpc pipes by
at present , only the data section is . this may be a possible
cause of some of the ipc problems being experienced . lkcl26dec97
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 13:27:58 +00:00
1998-03-11 21:11:04 +00:00
static void copy_trans_params_and_data ( char * outbuf , int align ,
1999-12-13 13:27:58 +00:00
char * rparam , int param_offset , int param_len ,
char * rdata , int data_offset , int data_len )
1998-03-11 21:11:04 +00:00
{
1998-09-03 05:37:15 +00:00
char * copy_into = smb_buf ( outbuf ) + 1 ;
1998-03-11 21:11:04 +00:00
1999-12-13 13:27:58 +00:00
if ( param_len < 0 )
param_len = 0 ;
if ( data_len < 0 )
data_len = 0 ;
1998-03-11 21:11:04 +00:00
DEBUG ( 5 , ( " copy_trans_params_and_data: params[%d..%d] data[%d..%d] \n " ,
param_offset , param_offset + param_len ,
data_offset , data_offset + data_len ) ) ;
1999-12-13 13:27:58 +00:00
if ( param_len )
memcpy ( copy_into , & rparam [ param_offset ] , param_len ) ;
1998-03-11 21:11:04 +00:00
copy_into + = param_len + align ;
1999-12-13 13:27:58 +00:00
if ( data_len )
memcpy ( copy_into , & rdata [ data_offset ] , data_len ) ;
1998-03-11 21:11:04 +00:00
}
1996-05-04 07:50:46 +00:00
/****************************************************************************
1999-12-13 13:27:58 +00:00
Send a trans reply .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-04-19 22:40:32 +00:00
void send_trans_reply ( const char * inbuf ,
char * outbuf ,
char * rparam ,
int rparam_len ,
char * rdata ,
int rdata_len ,
BOOL buffer_too_large )
1996-05-04 07:50:46 +00:00
{
1998-03-11 21:11:04 +00:00
int this_ldata , this_lparam ;
1999-12-13 13:27:58 +00:00
int tot_data_sent = 0 ;
int tot_param_sent = 0 ;
1998-03-11 21:11:04 +00:00
int align ;
1999-12-13 13:27:58 +00:00
int ldata = rdata ? rdata_len : 0 ;
int lparam = rparam ? rparam_len : 0 ;
1998-03-11 21:11:04 +00:00
if ( buffer_too_large )
1999-12-13 13:27:58 +00:00
DEBUG ( 5 , ( " send_trans_reply: buffer %d too large \n " , ldata ) ) ;
1998-03-11 21:11:04 +00:00
1999-12-13 13:27:58 +00:00
this_lparam = MIN ( lparam , max_send - 500 ) ; /* hack */
this_ldata = MIN ( ldata , max_send - ( 500 + this_lparam ) ) ;
1996-05-04 07:50:46 +00:00
1998-09-03 05:37:15 +00:00
align = ( ( this_lparam ) % 4 ) ;
1996-05-04 07:50:46 +00:00
2001-08-27 08:19:43 +00:00
if ( buffer_too_large ) {
2003-10-21 23:14:41 +00:00
ERROR_BOTH ( STATUS_BUFFER_OVERFLOW , ERRDOS , ERRmoredata ) ;
1998-03-11 21:11:04 +00:00
}
2007-04-19 22:40:32 +00:00
set_message ( inbuf , outbuf , 10 , 1 + align + this_ldata + this_lparam , True ) ;
2001-08-27 08:19:43 +00:00
1998-03-11 21:11:04 +00:00
copy_trans_params_and_data ( outbuf , align ,
2007-04-19 22:40:32 +00:00
rparam , tot_param_sent , this_lparam ,
rdata , tot_data_sent , this_ldata ) ;
1998-03-11 21:11:04 +00:00
SSVAL ( outbuf , smb_vwv0 , lparam ) ;
SSVAL ( outbuf , smb_vwv1 , ldata ) ;
SSVAL ( outbuf , smb_vwv3 , this_lparam ) ;
1998-09-03 05:37:15 +00:00
SSVAL ( outbuf , smb_vwv4 , smb_offset ( smb_buf ( outbuf ) + 1 , outbuf ) ) ;
1998-03-11 21:11:04 +00:00
SSVAL ( outbuf , smb_vwv5 , 0 ) ;
SSVAL ( outbuf , smb_vwv6 , this_ldata ) ;
1998-09-03 05:37:15 +00:00
SSVAL ( outbuf , smb_vwv7 , smb_offset ( smb_buf ( outbuf ) + 1 + this_lparam + align , outbuf ) ) ;
1998-03-11 21:11:04 +00:00
SSVAL ( outbuf , smb_vwv8 , 0 ) ;
1999-12-13 13:27:58 +00:00
SSVAL ( outbuf , smb_vwv9 , 0 ) ;
1998-03-11 21:11:04 +00:00
show_msg ( outbuf ) ;
2001-06-09 01:38:54 +00:00
if ( ! send_smb ( smbd_server_fd ( ) , outbuf ) )
2006-12-18 04:25:21 +00:00
exit_server_cleanly ( " send_trans_reply: send_smb failed. " ) ;
1998-03-11 21:11:04 +00:00
1999-12-13 13:27:58 +00:00
tot_data_sent = this_ldata ;
tot_param_sent = this_lparam ;
1998-03-11 21:11:04 +00:00
1999-12-13 13:27:58 +00:00
while ( tot_data_sent < ldata | | tot_param_sent < lparam )
1998-03-11 21:11:04 +00:00
{
1999-12-13 13:27:58 +00:00
this_lparam = MIN ( lparam - tot_param_sent , max_send - 500 ) ; /* hack */
this_ldata = MIN ( ldata - tot_data_sent , max_send - ( 500 + this_lparam ) ) ;
if ( this_lparam < 0 )
this_lparam = 0 ;
if ( this_ldata < 0 )
this_ldata = 0 ;
1998-03-11 21:11:04 +00:00
align = ( this_lparam % 4 ) ;
2007-04-19 22:40:32 +00:00
set_message ( inbuf , outbuf , 10 , 1 + this_ldata + this_lparam + align , False ) ;
1998-03-11 21:11:04 +00:00
copy_trans_params_and_data ( outbuf , align ,
2003-04-14 03:48:26 +00:00
rparam , tot_param_sent , this_lparam ,
rdata , tot_data_sent , this_ldata ) ;
1998-03-11 21:11:04 +00:00
SSVAL ( outbuf , smb_vwv3 , this_lparam ) ;
1998-09-03 05:37:15 +00:00
SSVAL ( outbuf , smb_vwv4 , smb_offset ( smb_buf ( outbuf ) + 1 , outbuf ) ) ;
1999-12-13 13:27:58 +00:00
SSVAL ( outbuf , smb_vwv5 , tot_param_sent ) ;
1998-03-11 21:11:04 +00:00
SSVAL ( outbuf , smb_vwv6 , this_ldata ) ;
1998-09-03 05:37:15 +00:00
SSVAL ( outbuf , smb_vwv7 , smb_offset ( smb_buf ( outbuf ) + 1 + this_lparam + align , outbuf ) ) ;
1999-12-13 13:27:58 +00:00
SSVAL ( outbuf , smb_vwv8 , tot_data_sent ) ;
1998-03-11 21:11:04 +00:00
SSVAL ( outbuf , smb_vwv9 , 0 ) ;
show_msg ( outbuf ) ;
2001-06-09 01:38:54 +00:00
if ( ! send_smb ( smbd_server_fd ( ) , outbuf ) )
2006-12-18 04:25:21 +00:00
exit_server_cleanly ( " send_trans_reply: send_smb failed. " ) ;
1998-03-11 21:11:04 +00:00
1999-12-13 13:27:58 +00:00
tot_data_sent + = this_ldata ;
tot_param_sent + = this_lparam ;
1998-03-11 21:11:04 +00:00
}
1996-05-04 07:50:46 +00:00
}
1999-12-13 13:27:58 +00:00
/****************************************************************************
Start the first part of an RPC reply which began with an SMBtrans request .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-04-19 22:40:32 +00:00
static BOOL api_rpc_trans_reply ( const char * inbuf ,
char * outbuf ,
smb_np_struct * p )
1998-03-11 21:11:04 +00:00
{
2002-01-20 02:40:05 +00:00
BOOL is_data_outstanding ;
2005-06-24 20:25:18 +00:00
char * rdata = ( char * ) SMB_MALLOC ( p - > max_trans_reply ) ;
1999-12-13 13:27:58 +00:00
int data_len ;
1998-03-11 21:11:04 +00:00
1999-12-13 13:27:58 +00:00
if ( rdata = = NULL ) {
DEBUG ( 0 , ( " api_rpc_trans_reply: malloc fail. \n " ) ) ;
return False ;
1998-03-11 21:11:04 +00:00
}
1999-12-13 13:27:58 +00:00
2002-01-20 02:40:05 +00:00
if ( ( data_len = read_from_pipe ( p , rdata , p - > max_trans_reply ,
& is_data_outstanding ) ) < 0 ) {
2001-09-17 11:25:41 +00:00
SAFE_FREE ( rdata ) ;
1999-12-13 13:27:58 +00:00
return False ;
}
2007-04-19 22:40:32 +00:00
send_trans_reply ( inbuf , outbuf , NULL , 0 , rdata , data_len , is_data_outstanding ) ;
1999-12-13 13:27:58 +00:00
2001-09-17 11:25:41 +00:00
SAFE_FREE ( rdata ) ;
1999-12-13 13:27:58 +00:00
return True ;
1998-03-11 21:11:04 +00:00
}
1998-10-15 05:47:29 +00:00
/****************************************************************************
WaitNamedPipeHandleState
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 13:27:58 +00:00
2007-04-19 22:40:32 +00:00
static BOOL api_WNPHS ( const char * inbuf ,
char * outbuf ,
smb_np_struct * p ,
char * param ,
int param_len )
1998-10-15 05:47:29 +00:00
{
uint16 priority ;
1999-12-13 13:27:58 +00:00
if ( ! param | | param_len < 2 )
return False ;
1998-10-15 05:47:29 +00:00
1999-12-13 13:27:58 +00:00
priority = SVAL ( param , 0 ) ;
1998-10-15 05:47:29 +00:00
DEBUG ( 4 , ( " WaitNamedPipeHandleState priority %x \n " , priority ) ) ;
1999-12-13 13:27:58 +00:00
if ( wait_rpc_pipe_hnd_state ( p , priority ) ) {
1998-10-15 05:47:29 +00:00
/* now send the reply */
2007-04-19 22:40:32 +00:00
send_trans_reply ( inbuf , outbuf , NULL , 0 , NULL , 0 , False ) ;
1998-10-15 05:47:29 +00:00
return True ;
}
return False ;
}
1998-03-11 21:11:04 +00:00
/****************************************************************************
SetNamedPipeHandleState
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 13:27:58 +00:00
2007-04-19 22:40:32 +00:00
static BOOL api_SNPHS ( const char * inbuf ,
char * outbuf ,
smb_np_struct * p ,
char * param ,
int param_len )
1998-03-11 21:11:04 +00:00
{
uint16 id ;
1999-12-13 13:27:58 +00:00
if ( ! param | | param_len < 2 )
return False ;
1998-03-11 21:11:04 +00:00
1999-12-13 13:27:58 +00:00
id = SVAL ( param , 0 ) ;
1998-10-15 05:47:29 +00:00
DEBUG ( 4 , ( " SetNamedPipeHandleState to code %x \n " , id ) ) ;
1998-03-11 21:11:04 +00:00
1999-12-13 13:27:58 +00:00
if ( set_rpc_pipe_hnd_state ( p , id ) ) {
1998-03-11 21:11:04 +00:00
/* now send the reply */
2007-04-19 22:40:32 +00:00
send_trans_reply ( inbuf , outbuf , NULL , 0 , NULL , 0 , False ) ;
1998-03-11 21:11:04 +00:00
return True ;
}
return False ;
1996-08-15 15:11:34 +00:00
}
1998-03-11 21:11:04 +00:00
/****************************************************************************
1999-12-13 13:27:58 +00:00
When no reply is generated , indicate unsupported .
1998-03-11 21:11:04 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 13:27:58 +00:00
2007-04-19 22:40:32 +00:00
static BOOL api_no_reply ( const char * inbuf , char * outbuf , int max_rdata_len )
1998-03-11 21:11:04 +00:00
{
1999-12-13 13:27:58 +00:00
char rparam [ 4 ] ;
1998-03-11 21:11:04 +00:00
/* unsupported */
1999-12-13 13:27:58 +00:00
SSVAL ( rparam , 0 , NERR_notsupported ) ;
SSVAL ( rparam , 2 , 0 ) ; /* converter word */
1998-03-11 21:11:04 +00:00
DEBUG ( 3 , ( " Unsupported API fd command \n " ) ) ;
/* now send the reply */
2007-04-19 22:40:32 +00:00
send_trans_reply ( inbuf , outbuf , rparam , 4 , NULL , 0 , False ) ;
1998-03-11 21:11:04 +00:00
1999-12-13 13:27:58 +00:00
return - 1 ;
1998-03-11 21:11:04 +00:00
}
/****************************************************************************
1999-12-13 13:27:58 +00:00
Handle remote api calls delivered to a named pipe already opened .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-04-19 22:40:32 +00:00
static int api_fd_reply ( connection_struct * conn ,
uint16 vuid ,
const char * inbuf ,
char * outbuf ,
uint16 * setup ,
char * data ,
char * params ,
int suwcnt ,
int tdscnt ,
int tpscnt ,
int mdrcnt ,
int mprcnt )
1998-03-11 21:11:04 +00:00
{
1999-12-13 13:27:58 +00:00
BOOL reply = False ;
2002-01-20 02:40:05 +00:00
smb_np_struct * p = NULL ;
1999-12-13 13:27:58 +00:00
int pnum ;
int subcommand ;
1998-03-11 21:11:04 +00:00
DEBUG ( 5 , ( " api_fd_reply \n " ) ) ;
/* First find out the name of this file. */
1999-12-13 13:27:58 +00:00
if ( suwcnt ! = 2 ) {
1998-03-11 21:11:04 +00:00
DEBUG ( 0 , ( " Unexpected named pipe transaction. \n " ) ) ;
2005-01-18 22:40:49 +00:00
return ERROR_NT ( NT_STATUS_INVALID_PARAMETER ) ;
1998-03-11 21:11:04 +00:00
}
/* Get the file handle and hence the file name. */
1999-12-13 13:27:58 +00:00
/*
* NB . The setup array has already been transformed
* via SVAL and so is in gost byte order .
*/
pnum = ( ( int ) setup [ 1 ] ) & 0xFFFF ;
subcommand = ( ( int ) setup [ 0 ] ) & 0xFFFF ;
1998-03-11 21:11:04 +00:00
1999-12-13 13:27:58 +00:00
if ( ! ( p = get_rpc_pipe ( pnum ) ) ) {
2003-10-21 23:14:41 +00:00
if ( subcommand = = TRANSACT_WAITNAMEDPIPEHANDLESTATE ) {
/* Win9x does this call with a unicode pipe name, not a pnum. */
/* Just return success for now... */
DEBUG ( 3 , ( " Got TRANSACT_WAITNAMEDPIPEHANDLESTATE on text pipe name \n " ) ) ;
2007-04-19 22:40:32 +00:00
send_trans_reply ( inbuf , outbuf , NULL , 0 , NULL , 0 , False ) ;
2003-10-21 23:14:41 +00:00
return - 1 ;
}
1999-12-13 13:27:58 +00:00
DEBUG ( 1 , ( " api_fd_reply: INVALID PIPE HANDLE: %x \n " , pnum ) ) ;
2005-01-18 22:40:49 +00:00
return ERROR_NT ( NT_STATUS_INVALID_HANDLE ) ;
1999-12-13 13:27:58 +00:00
}
1998-03-11 21:11:04 +00:00
2006-05-27 21:38:54 +00:00
if ( vuid ! = p - > vuid ) {
DEBUG ( 1 , ( " Got pipe request (pnum %x) using invalid VUID %d, "
" expected %d \n " , pnum , vuid , p - > vuid ) ) ;
return ERROR_NT ( NT_STATUS_INVALID_HANDLE ) ;
}
2004-03-09 21:47:49 +00:00
DEBUG ( 3 , ( " Got API command 0x%x on pipe \" %s \" (pnum %x) \n " , subcommand , p - > name , pnum ) ) ;
1998-03-11 21:11:04 +00:00
1999-12-13 13:27:58 +00:00
/* record maximum data length that can be transmitted in an SMBtrans */
p - > max_trans_reply = mdrcnt ;
1998-04-10 18:21:16 +00:00
1999-12-13 13:27:58 +00:00
DEBUG ( 10 , ( " api_fd_reply: p:%p max_trans_reply: %d \n " , p , p - > max_trans_reply ) ) ;
switch ( subcommand ) {
2002-11-07 14:46:24 +00:00
case TRANSACT_DCERPCCMD :
2000-03-09 21:45:16 +00:00
/* dce/rpc command */
reply = write_to_pipe ( p , data , tdscnt ) ;
1999-12-13 13:27:58 +00:00
if ( reply )
2007-04-19 22:40:32 +00:00
reply = api_rpc_trans_reply ( inbuf , outbuf , p ) ;
1999-12-13 13:27:58 +00:00
break ;
2002-11-07 14:46:24 +00:00
case TRANSACT_WAITNAMEDPIPEHANDLESTATE :
1999-12-13 13:27:58 +00:00
/* Wait Named Pipe Handle state */
2007-04-19 22:40:32 +00:00
reply = api_WNPHS ( inbuf , outbuf , p , params , tpscnt ) ;
1999-12-13 13:27:58 +00:00
break ;
2002-11-07 14:46:24 +00:00
case TRANSACT_SETNAMEDPIPEHANDLESTATE :
1999-12-13 13:27:58 +00:00
/* Set Named Pipe Handle state */
2007-04-19 22:40:32 +00:00
reply = api_SNPHS ( inbuf , outbuf , p , params , tpscnt ) ;
1999-12-13 13:27:58 +00:00
break ;
2005-01-18 22:40:49 +00:00
default :
return ERROR_NT ( NT_STATUS_INVALID_PARAMETER ) ;
1998-03-11 21:11:04 +00:00
}
if ( ! reply )
2007-04-19 22:40:32 +00:00
return api_no_reply ( inbuf , outbuf , mdrcnt ) ;
1999-12-13 13:27:58 +00:00
1998-03-11 21:11:04 +00:00
return - 1 ;
}
1996-08-15 15:11:34 +00:00
1996-05-04 07:50:46 +00:00
/****************************************************************************
2007-04-19 22:40:32 +00:00
Handle named pipe commands .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int named_pipe ( connection_struct * conn ,
uint16 vuid ,
const char * inbuf ,
char * outbuf ,
char * name ,
uint16 * setup ,
char * data ,
char * params ,
int suwcnt ,
int tdscnt ,
int tpscnt ,
int msrcnt ,
int mdrcnt ,
int mprcnt )
1996-05-04 07:50:46 +00:00
{
1997-10-24 13:15:34 +00:00
DEBUG ( 3 , ( " named pipe command on <%s> name \n " , name ) ) ;
1996-05-04 07:50:46 +00:00
2007-04-19 22:40:32 +00:00
if ( strequal ( name , " LANMAN " ) ) {
return api_reply ( conn ,
vuid ,
inbuf ,
outbuf ,
data ,
params ,
tdscnt ,
tpscnt ,
mdrcnt ,
mprcnt ) ;
}
1996-05-04 07:50:46 +00:00
1998-10-15 05:47:29 +00:00
if ( strequal ( name , " WKSSVC " ) | |
strequal ( name , " SRVSVC " ) | |
strequal ( name , " WINREG " ) | |
strequal ( name , " SAMR " ) | |
2007-04-19 22:40:32 +00:00
strequal ( name , " LSARPC " ) ) {
1998-10-15 05:47:29 +00:00
DEBUG ( 4 , ( " named pipe command from Win95 (wow!) \n " ) ) ;
2007-04-19 22:40:32 +00:00
return api_fd_reply ( conn ,
vuid ,
inbuf ,
outbuf ,
setup ,
data ,
params ,
suwcnt ,
tdscnt ,
tpscnt ,
mdrcnt ,
mprcnt ) ;
1998-10-15 05:47:29 +00:00
}
2007-04-19 22:40:32 +00:00
if ( strlen ( name ) < 1 ) {
return api_fd_reply ( conn ,
vuid ,
inbuf ,
outbuf ,
setup ,
data ,
params ,
suwcnt ,
tdscnt ,
tpscnt ,
mdrcnt ,
mprcnt ) ;
}
1996-08-15 15:11:34 +00:00
1997-10-22 18:37:43 +00:00
if ( setup )
DEBUG ( 3 , ( " unknown named pipe: setup 0x%X setup1=%d \n " , ( int ) setup [ 0 ] , ( int ) setup [ 1 ] ) ) ;
1996-08-15 15:11:34 +00:00
1997-10-22 18:37:43 +00:00
return 0 ;
1996-05-04 07:50:46 +00:00
}
2006-04-10 15:33:04 +00:00
static NTSTATUS handle_trans ( connection_struct * conn ,
2007-04-19 22:40:32 +00:00
struct trans_state * state ,
const char * inbuf ,
char * outbuf ,
int * outsize )
2006-04-10 15:33:04 +00:00
{
char * local_machine_name ;
int name_offset = 0 ;
DEBUG ( 3 , ( " trans <%s> data=%u params=%u setup=%u \n " ,
2006-06-16 01:30:42 +00:00
state - > name , ( unsigned int ) state - > total_data , ( unsigned int ) state - > total_param ,
( unsigned int ) state - > setup_count ) ) ;
2006-04-10 15:33:04 +00:00
/*
* WinCE wierdness . . . .
*/
local_machine_name = talloc_asprintf ( state , " \\ %s \\ " ,
get_local_machine_name ( ) ) ;
if ( local_machine_name = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
if ( strnequal ( state - > name , local_machine_name ,
strlen ( local_machine_name ) ) ) {
name_offset = strlen ( local_machine_name ) - 1 ;
}
if ( ! strnequal ( & state - > name [ name_offset ] , " \\ PIPE " ,
strlen ( " \\ PIPE " ) ) ) {
return NT_STATUS_NOT_SUPPORTED ;
}
name_offset + = strlen ( " \\ PIPE " ) ;
/* Win9x weirdness. When talking to a unicode server Win9x
only sends \ PIPE instead of \ PIPE \ */
if ( state - > name [ name_offset ] = = ' \\ ' )
name_offset + + ;
DEBUG ( 5 , ( " calling named_pipe \n " ) ) ;
2007-04-19 22:40:32 +00:00
* outsize = named_pipe ( conn ,
state - > vuid ,
inbuf ,
outbuf ,
state - > name + name_offset ,
state - > setup , state - > data ,
state - > param ,
state - > setup_count , state - > total_data ,
state - > total_param ,
state - > max_setup_return ,
state - > max_data_return ,
state - > max_param_return ) ;
2006-04-10 15:33:04 +00:00
if ( * outsize = = 0 ) {
return NT_STATUS_NOT_SUPPORTED ;
}
if ( state - > close_on_completion )
close_cnum ( conn , state - > vuid ) ;
return NT_STATUS_OK ;
}
1996-05-04 07:50:46 +00:00
/****************************************************************************
1999-12-13 13:27:58 +00:00
Reply to a SMBtrans .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-08-05 08:04:11 +00:00
void reply_trans ( connection_struct * conn , struct smb_request * req )
1998-08-14 17:38:29 +00:00
{
int outsize = 0 ;
2007-08-04 20:28:46 +00:00
unsigned int dsoff ;
unsigned int dscnt ;
unsigned int psoff ;
unsigned int pscnt ;
2006-04-10 15:33:04 +00:00
struct trans_state * state ;
NTSTATUS result ;
2007-08-05 08:04:11 +00:00
char * inbuf , * outbuf ;
int size , bufsize ;
2006-04-10 15:33:04 +00:00
2000-10-11 05:31:39 +00:00
START_PROFILE ( SMBtrans ) ;
1998-08-14 17:38:29 +00:00
2007-08-05 08:31:41 +00:00
if ( SVAL ( req - > inbuf , smb_wct ) < 10 ) {
2007-08-05 08:04:11 +00:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2007-08-04 20:28:46 +00:00
END_PROFILE ( SMBtrans ) ;
2007-08-05 08:04:11 +00:00
return ;
2007-08-04 20:28:46 +00:00
}
2007-08-05 08:31:41 +00:00
size = smb_len ( req - > inbuf ) + 4 ;
dsoff = SVAL ( req - > inbuf , smb_dsoff ) ;
dscnt = SVAL ( req - > inbuf , smb_dscnt ) ;
psoff = SVAL ( req - > inbuf , smb_psoff ) ;
pscnt = SVAL ( req - > inbuf , smb_pscnt ) ;
2007-08-04 20:28:46 +00:00
2007-08-05 08:31:41 +00:00
result = allow_new_trans ( conn - > pending_trans , req - > mid ) ;
2006-04-26 09:43:39 +00:00
if ( ! NT_STATUS_IS_OK ( result ) ) {
2006-04-10 15:33:04 +00:00
DEBUG ( 2 , ( " Got invalid trans request: %s \n " ,
nt_errstr ( result ) ) ) ;
2007-08-05 08:04:11 +00:00
reply_nterror ( req , result ) ;
2006-04-10 15:33:04 +00:00
END_PROFILE ( SMBtrans ) ;
2007-08-05 08:04:11 +00:00
return ;
2006-04-10 15:33:04 +00:00
}
1998-08-14 17:38:29 +00:00
2006-12-15 00:49:12 +00:00
if ( ( state = TALLOC_P ( conn - > mem_ctx , struct trans_state ) ) = = NULL ) {
2006-04-10 15:33:04 +00:00
DEBUG ( 0 , ( " talloc failed \n " ) ) ;
2007-08-05 08:04:11 +00:00
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
2006-04-10 15:33:04 +00:00
END_PROFILE ( SMBtrans ) ;
2007-08-05 08:04:11 +00:00
return ;
2006-04-10 15:33:04 +00:00
}
state - > cmd = SMBtrans ;
2007-08-05 08:31:41 +00:00
state - > mid = req - > mid ;
state - > vuid = req - > vuid ;
state - > setup_count = CVAL ( req - > inbuf , smb_suwcnt ) ;
2006-12-15 00:49:12 +00:00
state - > setup = NULL ;
2007-08-05 08:31:41 +00:00
state - > total_param = SVAL ( req - > inbuf , smb_tpscnt ) ;
2006-04-10 15:33:04 +00:00
state - > param = NULL ;
2007-08-05 08:31:41 +00:00
state - > total_data = SVAL ( req - > inbuf , smb_tdscnt ) ;
2006-04-10 15:33:04 +00:00
state - > data = NULL ;
2007-08-05 08:31:41 +00:00
state - > max_param_return = SVAL ( req - > inbuf , smb_mprcnt ) ;
state - > max_data_return = SVAL ( req - > inbuf , smb_mdrcnt ) ;
state - > max_setup_return = CVAL ( req - > inbuf , smb_msrcnt ) ;
state - > close_on_completion = BITSETW ( req - > inbuf + smb_vwv5 , 0 ) ;
state - > one_way = BITSETW ( req - > inbuf + smb_vwv5 , 1 ) ;
2006-04-10 15:33:04 +00:00
memset ( state - > name , ' \0 ' , sizeof ( state - > name ) ) ;
2007-08-05 08:31:41 +00:00
srvstr_pull_buf ( req - > inbuf , req - > flags2 , state - > name ,
smb_buf ( req - > inbuf ) , sizeof ( state - > name ) ,
STR_TERMINATE ) ;
2006-04-10 15:33:04 +00:00
if ( ( dscnt > state - > total_data ) | | ( pscnt > state - > total_param ) )
2003-03-07 00:30:47 +00:00
goto bad_param ;
2006-04-10 15:33:04 +00:00
if ( state - > total_data ) {
/* Can't use talloc here, the core routines do realloc on the
2007-04-03 14:16:56 +00:00
* params and data . Out of paranoia , 100 bytes too many . */
state - > data = ( char * ) SMB_MALLOC ( state - > total_data + 100 ) ;
2006-04-10 15:33:04 +00:00
if ( state - > data = = NULL ) {
DEBUG ( 0 , ( " reply_trans: data malloc fail for %u "
2006-06-16 01:30:42 +00:00
" bytes ! \n " , ( unsigned int ) state - > total_data ) ) ;
2006-04-10 15:33:04 +00:00
TALLOC_FREE ( state ) ;
2007-08-05 08:04:11 +00:00
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
2000-10-11 05:31:39 +00:00
END_PROFILE ( SMBtrans ) ;
2007-08-05 08:04:11 +00:00
return ;
1998-10-08 06:49:00 +00:00
}
2007-04-03 14:16:56 +00:00
/* null-terminate the slack space */
memset ( & state - > data [ state - > total_data ] , 0 , 100 ) ;
2003-03-07 00:30:47 +00:00
if ( ( dsoff + dscnt < dsoff ) | | ( dsoff + dscnt < dscnt ) )
goto bad_param ;
2007-08-05 08:31:41 +00:00
if ( ( smb_base ( req - > inbuf ) + dsoff + dscnt
> ( char * ) req - > inbuf + size ) | |
( smb_base ( req - > inbuf ) + dsoff + dscnt < smb_base ( req - > inbuf ) ) )
2003-03-07 00:30:47 +00:00
goto bad_param ;
2007-08-05 08:31:41 +00:00
memcpy ( state - > data , smb_base ( req - > inbuf ) + dsoff , dscnt ) ;
1998-08-14 17:38:29 +00:00
}
1996-05-04 07:50:46 +00:00
2006-04-10 15:33:04 +00:00
if ( state - > total_param ) {
/* Can't use talloc here, the core routines do realloc on the
2007-04-03 14:16:56 +00:00
* params and data . Out of paranoia , 100 bytes too many */
state - > param = ( char * ) SMB_MALLOC ( state - > total_param + 100 ) ;
2006-04-10 15:33:04 +00:00
if ( state - > param = = NULL ) {
DEBUG ( 0 , ( " reply_trans: param malloc fail for %u "
2006-06-16 01:30:42 +00:00
" bytes ! \n " , ( unsigned int ) state - > total_param ) ) ;
2006-04-10 15:33:04 +00:00
SAFE_FREE ( state - > data ) ;
TALLOC_FREE ( state ) ;
2007-08-05 08:04:11 +00:00
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
2000-10-11 05:31:39 +00:00
END_PROFILE ( SMBtrans ) ;
2007-08-05 08:04:11 +00:00
return ;
1998-10-08 06:49:00 +00:00
}
2007-04-03 14:16:56 +00:00
/* null-terminate the slack space */
memset ( & state - > param [ state - > total_param ] , 0 , 100 ) ;
2003-03-07 00:30:47 +00:00
if ( ( psoff + pscnt < psoff ) | | ( psoff + pscnt < pscnt ) )
2003-10-16 20:44:43 +00:00
goto bad_param ;
2007-08-05 08:31:41 +00:00
if ( ( smb_base ( req - > inbuf ) + psoff + pscnt
> ( char * ) req - > inbuf + size ) | |
( smb_base ( req - > inbuf ) + psoff + pscnt < smb_base ( req - > inbuf ) ) )
2003-03-07 00:30:47 +00:00
goto bad_param ;
2007-08-05 08:31:41 +00:00
memcpy ( state - > param , smb_base ( req - > inbuf ) + psoff , pscnt ) ;
1998-08-14 17:38:29 +00:00
}
1996-05-04 07:50:46 +00:00
2006-04-10 15:33:04 +00:00
state - > received_data = dscnt ;
state - > received_param = pscnt ;
if ( state - > setup_count ) {
2003-03-18 11:18:27 +00:00
unsigned int i ;
2006-04-10 15:33:04 +00:00
if ( ( state - > setup = TALLOC_ARRAY (
state , uint16 , state - > setup_count ) ) = = NULL ) {
DEBUG ( 0 , ( " reply_trans: setup malloc fail for %u "
" bytes ! \n " , ( unsigned int )
( state - > setup_count * sizeof ( uint16 ) ) ) ) ;
2007-07-11 06:18:32 +00:00
SAFE_FREE ( state - > data ) ;
SAFE_FREE ( state - > param ) ;
2006-04-10 15:33:04 +00:00
TALLOC_FREE ( state ) ;
2007-08-05 08:04:11 +00:00
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
2003-03-07 00:30:47 +00:00
END_PROFILE ( SMBtrans ) ;
2007-08-05 08:04:11 +00:00
return ;
2003-03-07 00:30:47 +00:00
}
2007-08-05 08:31:41 +00:00
if ( req - > inbuf + smb_vwv14 + ( state - > setup_count * SIZEOFWORD ) >
req - > inbuf + size )
2003-03-07 00:30:47 +00:00
goto bad_param ;
2006-04-10 15:33:04 +00:00
if ( ( smb_vwv14 + ( state - > setup_count * SIZEOFWORD ) < smb_vwv14 ) | |
( smb_vwv14 + ( state - > setup_count * SIZEOFWORD ) <
( state - > setup_count * SIZEOFWORD ) ) )
2003-03-07 00:30:47 +00:00
goto bad_param ;
2006-04-10 15:33:04 +00:00
for ( i = 0 ; i < state - > setup_count ; i + + )
2007-08-05 08:31:41 +00:00
state - > setup [ i ] = SVAL ( req - > inbuf ,
smb_vwv14 + i * SIZEOFWORD ) ;
1998-08-14 17:38:29 +00:00
}
1996-05-04 07:50:46 +00:00
2006-04-10 15:33:04 +00:00
state - > received_param = pscnt ;
1996-05-04 07:50:46 +00:00
2007-08-05 08:31:41 +00:00
if ( ( state - > received_param ! = state - > total_param ) | |
( state - > received_data ! = state - > total_data ) ) {
DLIST_ADD ( conn - > pending_trans , state ) ;
2003-08-02 03:06:07 +00:00
2007-08-05 08:31:41 +00:00
/* We need to send an interim response then receive the rest
of the parameter / data bytes */
reply_outbuf ( req , 0 , 0 ) ;
show_msg ( ( char * ) req - > outbuf ) ;
END_PROFILE ( SMBtrans ) ;
return ;
}
2006-04-10 15:33:04 +00:00
2007-08-05 08:31:41 +00:00
if ( ! ( reply_prep_legacy ( req , & inbuf , & outbuf , & size , & bufsize ) ) ) {
2006-04-10 15:33:04 +00:00
SAFE_FREE ( state - > data ) ;
SAFE_FREE ( state - > param ) ;
TALLOC_FREE ( state ) ;
2007-08-05 08:31:41 +00:00
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
END_PROFILE ( SMBtrans ) ;
return ;
}
1996-06-10 05:16:19 +00:00
2007-08-05 08:31:41 +00:00
result = handle_trans ( conn , state , inbuf , outbuf , & outsize ) ;
1996-05-04 07:50:46 +00:00
2007-08-05 08:31:41 +00:00
if ( NT_STATUS_IS_OK ( result ) ) {
reply_post_legacy ( req , outsize ) ;
}
SAFE_FREE ( state - > data ) ;
SAFE_FREE ( state - > param ) ;
TALLOC_FREE ( state ) ;
2003-03-07 00:30:47 +00:00
2007-08-05 08:31:41 +00:00
if ( ! NT_STATUS_IS_OK ( result ) ) {
reply_nterror ( req , result ) ;
2006-04-10 15:33:04 +00:00
END_PROFILE ( SMBtrans ) ;
2007-08-05 08:04:11 +00:00
return ;
1998-08-14 17:38:29 +00:00
}
2003-08-02 07:07:38 +00:00
2007-08-05 08:31:41 +00:00
if ( outsize = = 0 ) {
reply_nterror ( req , NT_STATUS_INTERNAL_ERROR ) ;
END_PROFILE ( SMBtrans ) ;
return ;
}
2003-08-02 07:07:38 +00:00
2006-04-10 15:33:04 +00:00
END_PROFILE ( SMBtrans ) ;
2007-08-05 08:04:11 +00:00
return ;
1998-10-15 00:55:17 +00:00
2006-04-10 15:33:04 +00:00
bad_param :
2005-02-01 20:43:14 +00:00
2006-04-10 15:33:04 +00:00
DEBUG ( 0 , ( " reply_trans: invalid trans parameters \n " ) ) ;
SAFE_FREE ( state - > data ) ;
SAFE_FREE ( state - > param ) ;
TALLOC_FREE ( state ) ;
END_PROFILE ( SMBtrans ) ;
2007-08-05 08:04:11 +00:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
return ;
2006-04-10 15:33:04 +00:00
}
/****************************************************************************
Reply to a secondary SMBtrans .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-08-05 08:47:09 +00:00
void reply_transs ( connection_struct * conn , struct smb_request * req )
2006-04-10 15:33:04 +00:00
{
int outsize = 0 ;
unsigned int pcnt , poff , dcnt , doff , pdisp , ddisp ;
struct trans_state * state ;
NTSTATUS result ;
2007-08-05 08:47:09 +00:00
char * inbuf , * outbuf ;
int size , bufsize ;
2006-04-10 15:33:04 +00:00
START_PROFILE ( SMBtranss ) ;
2007-08-05 09:01:15 +00:00
show_msg ( ( char * ) req - > inbuf ) ;
2006-04-10 15:33:04 +00:00
2007-08-05 08:47:09 +00:00
if ( req - > wct < 10 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2007-08-04 20:28:46 +00:00
END_PROFILE ( SMBtranss ) ;
2007-08-05 08:47:09 +00:00
return ;
2007-08-04 20:28:46 +00:00
}
2006-04-10 15:33:04 +00:00
for ( state = conn - > pending_trans ; state ! = NULL ;
state = state - > next ) {
2007-08-05 09:01:15 +00:00
if ( state - > mid = = req - > mid ) {
2006-04-10 15:33:04 +00:00
break ;
}
2006-03-07 19:52:26 +00:00
}
2006-04-10 15:33:04 +00:00
if ( ( state = = NULL ) | | ( state - > cmd ! = SMBtrans ) ) {
2007-08-05 08:47:09 +00:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2006-04-10 15:33:04 +00:00
END_PROFILE ( SMBtranss ) ;
2007-08-05 08:47:09 +00:00
return ;
2006-03-07 19:52:26 +00:00
}
2006-04-10 15:33:04 +00:00
/* Revise total_params and total_data in case they have changed
* downwards */
1998-10-15 00:55:17 +00:00
2007-08-05 09:01:15 +00:00
if ( SVAL ( req - > inbuf , smb_vwv0 ) < state - > total_param )
state - > total_param = SVAL ( req - > inbuf , smb_vwv0 ) ;
if ( SVAL ( req - > inbuf , smb_vwv1 ) < state - > total_data )
state - > total_data = SVAL ( req - > inbuf , smb_vwv1 ) ;
size = smb_len ( req - > inbuf ) + 4 ;
2001-06-29 01:58:48 +00:00
2007-08-05 09:01:15 +00:00
pcnt = SVAL ( req - > inbuf , smb_spscnt ) ;
poff = SVAL ( req - > inbuf , smb_spsoff ) ;
pdisp = SVAL ( req - > inbuf , smb_spsdisp ) ;
2001-06-29 01:58:48 +00:00
2007-08-05 09:01:15 +00:00
dcnt = SVAL ( req - > inbuf , smb_sdscnt ) ;
doff = SVAL ( req - > inbuf , smb_sdsoff ) ;
ddisp = SVAL ( req - > inbuf , smb_sdsdisp ) ;
2001-06-29 01:58:48 +00:00
2006-04-10 15:33:04 +00:00
state - > received_param + = pcnt ;
state - > received_data + = dcnt ;
if ( ( state - > received_data > state - > total_data ) | |
( state - > received_param > state - > total_param ) )
goto bad_param ;
if ( pcnt ) {
if ( pdisp + pcnt > state - > total_param )
goto bad_param ;
if ( ( pdisp + pcnt < pdisp ) | | ( pdisp + pcnt < pcnt ) )
goto bad_param ;
if ( pdisp > state - > total_param )
goto bad_param ;
2007-08-05 09:01:15 +00:00
if ( ( smb_base ( req - > inbuf ) + poff + pcnt
> ( char * ) req - > inbuf + size ) | |
( smb_base ( req - > inbuf ) + poff + pcnt
< smb_base ( req - > inbuf ) ) )
2006-04-10 15:33:04 +00:00
goto bad_param ;
if ( state - > param + pdisp < state - > param )
goto bad_param ;
2007-08-05 09:01:15 +00:00
memcpy ( state - > param + pdisp , smb_base ( req - > inbuf ) + poff ,
2006-04-10 15:33:04 +00:00
pcnt ) ;
1998-08-14 17:38:29 +00:00
}
1996-05-04 07:50:46 +00:00
2006-04-10 15:33:04 +00:00
if ( dcnt ) {
if ( ddisp + dcnt > state - > total_data )
goto bad_param ;
if ( ( ddisp + dcnt < ddisp ) | | ( ddisp + dcnt < dcnt ) )
goto bad_param ;
if ( ddisp > state - > total_data )
goto bad_param ;
2007-08-05 09:01:15 +00:00
if ( ( smb_base ( req - > inbuf ) + doff + dcnt
> ( char * ) inbuf + size ) | |
( smb_base ( req - > inbuf ) + doff + dcnt
< smb_base ( req - > inbuf ) ) )
2006-04-10 15:33:04 +00:00
goto bad_param ;
if ( state - > data + ddisp < state - > data )
goto bad_param ;
2003-08-02 03:06:07 +00:00
2007-08-05 09:01:15 +00:00
memcpy ( state - > data + ddisp , smb_base ( req - > inbuf ) + doff ,
2006-04-10 15:33:04 +00:00
dcnt ) ;
}
1996-05-04 07:50:46 +00:00
2006-04-10 15:33:04 +00:00
if ( ( state - > received_param < state - > total_param ) | |
( state - > received_data < state - > total_data ) ) {
END_PROFILE ( SMBtranss ) ;
2007-08-05 08:47:09 +00:00
return ;
2000-10-11 05:31:39 +00:00
}
2006-04-10 15:33:04 +00:00
2007-08-05 09:01:15 +00:00
if ( ! reply_prep_legacy ( req , & inbuf , & outbuf , & size , & bufsize ) ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
END_PROFILE ( SMBtranss ) ;
return ;
}
2006-04-10 15:33:04 +00:00
/* construct_reply_common has done us the favor to pre-fill the
* command field with SMBtranss which is wrong : - )
*/
2007-08-05 09:01:15 +00:00
SCVAL ( req - > outbuf , smb_com , SMBtrans ) ;
2006-04-10 15:33:04 +00:00
2007-04-19 22:40:32 +00:00
result = handle_trans ( conn , state , inbuf , outbuf , & outsize ) ;
2006-04-10 15:33:04 +00:00
2007-08-05 09:01:15 +00:00
if ( NT_STATUS_IS_OK ( result ) ) {
reply_post_legacy ( req , outsize ) ;
}
2006-04-10 15:33:04 +00:00
DLIST_REMOVE ( conn - > pending_trans , state ) ;
SAFE_FREE ( state - > data ) ;
SAFE_FREE ( state - > param ) ;
TALLOC_FREE ( state ) ;
if ( ( outsize = = 0 ) | | ! NT_STATUS_IS_OK ( result ) ) {
2007-08-05 08:47:09 +00:00
reply_doserror ( req , ERRSRV , ERRnosupport ) ;
2006-04-10 15:33:04 +00:00
END_PROFILE ( SMBtranss ) ;
2007-08-05 08:47:09 +00:00
return ;
2000-10-11 05:31:39 +00:00
}
1998-08-14 17:38:29 +00:00
2006-04-10 15:33:04 +00:00
END_PROFILE ( SMBtranss ) ;
2007-08-05 08:47:09 +00:00
return ;
2003-03-07 00:30:47 +00:00
bad_param :
2006-04-10 15:33:04 +00:00
DEBUG ( 0 , ( " reply_transs: invalid trans parameters \n " ) ) ;
DLIST_REMOVE ( conn - > pending_trans , state ) ;
SAFE_FREE ( state - > data ) ;
SAFE_FREE ( state - > param ) ;
TALLOC_FREE ( state ) ;
2007-08-05 08:47:09 +00:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2006-04-10 15:33:04 +00:00
END_PROFILE ( SMBtranss ) ;
2007-08-05 08:47:09 +00:00
return ;
1996-05-04 07:50:46 +00:00
}