1996-05-04 11:50:46 +04:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
1996-05-04 11:50:46 +04:00
Inter - process communication and named pipe handling
1998-01-22 16:27:43 +03:00
Copyright ( C ) Andrew Tridgell 1992 - 1998
1997-07-09 15:04:45 +04:00
SMB Version handling
1998-01-22 16:27:43 +03:00
Copyright ( C ) John H Terpstra 1995 - 1998
2008-10-10 19:50:09 +04:00
1996-05-04 11:50:46 +04:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
1996-05-04 11:50:46 +04:00
( at your option ) any later version .
2008-10-10 19:50:09 +04:00
1996-05-04 11:50:46 +04:00
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 .
2008-10-10 19:50:09 +04:00
1996-05-04 11:50:46 +04:00
You should have received a copy of the GNU General Public License
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
1996-05-04 11:50:46 +04:00
*/
/*
This file handles the named pipe and mailslot calls
in the SMBtrans protocol
*/
# include "includes.h"
1997-02-28 23:39:36 +03:00
extern int max_send ;
1996-05-04 11:50:46 +04:00
# define NERR_notsupported 50
2008-01-04 23:56:23 +03:00
static void api_no_reply ( connection_struct * conn , struct smb_request * req ) ;
1996-05-04 11:50:46 +04:00
1998-03-12 00:11:04 +03: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 16:27:58 +03:00
1998-03-12 00:11:04 +03:00
static void copy_trans_params_and_data ( char * outbuf , int align ,
1999-12-13 16:27:58 +03:00
char * rparam , int param_offset , int param_len ,
char * rdata , int data_offset , int data_len )
1998-03-12 00:11:04 +03:00
{
2007-08-05 15:34:57 +04:00
char * copy_into = smb_buf ( outbuf ) ;
1998-03-12 00:11:04 +03:00
1999-12-13 16:27:58 +03:00
if ( param_len < 0 )
param_len = 0 ;
if ( data_len < 0 )
data_len = 0 ;
2007-09-11 23:27:34 +04:00
DEBUG ( 5 , ( " copy_trans_params_and_data: params[%d..%d] data[%d..%d] (align %d) \n " ,
1998-03-12 00:11:04 +03:00
param_offset , param_offset + param_len ,
2007-09-11 23:27:34 +04:00
data_offset , data_offset + data_len ,
align ) ) ;
1998-03-12 00:11:04 +03:00
2007-08-05 15:34:57 +04:00
* copy_into = ' \0 ' ;
copy_into + = 1 ;
1999-12-13 16:27:58 +03:00
if ( param_len )
memcpy ( copy_into , & rparam [ param_offset ] , param_len ) ;
2007-09-11 23:27:34 +04:00
copy_into + = param_len ;
if ( align ) {
memset ( copy_into , ' \0 ' , align ) ;
}
copy_into + = align ;
1999-12-13 16:27:58 +03:00
if ( data_len )
memcpy ( copy_into , & rdata [ data_offset ] , data_len ) ;
1998-03-12 00:11:04 +03:00
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
1999-12-13 16:27:58 +03:00
Send a trans reply .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-11-02 23:24:28 +03:00
void send_trans_reply ( connection_struct * conn ,
struct smb_request * req ,
2007-08-05 15:34:57 +04:00
char * rparam , int rparam_len ,
char * rdata , int rdata_len ,
2007-10-19 04:40:25 +04:00
bool buffer_too_large )
1996-05-04 11:50:46 +04:00
{
1998-03-12 00:11:04 +03:00
int this_ldata , this_lparam ;
1999-12-13 16:27:58 +03:00
int tot_data_sent = 0 ;
int tot_param_sent = 0 ;
1998-03-12 00:11:04 +03:00
int align ;
1999-12-13 16:27:58 +03:00
int ldata = rdata ? rdata_len : 0 ;
int lparam = rparam ? rparam_len : 0 ;
1998-03-12 00:11:04 +03:00
if ( buffer_too_large )
1999-12-13 16:27:58 +03:00
DEBUG ( 5 , ( " send_trans_reply: buffer %d too large \n " , ldata ) ) ;
1998-03-12 00:11:04 +03:00
1999-12-13 16:27:58 +03:00
this_lparam = MIN ( lparam , max_send - 500 ) ; /* hack */
this_ldata = MIN ( ldata , max_send - ( 500 + this_lparam ) ) ;
1996-05-04 11:50:46 +04:00
1998-09-03 09:37:15 +04:00
align = ( ( this_lparam ) % 4 ) ;
1996-05-04 11:50:46 +04:00
2008-11-07 14:29:24 +03:00
reply_outbuf ( req , 10 , 1 + align + this_ldata + this_lparam ) ;
2001-08-27 12:19:43 +04:00
2008-11-07 22:38:05 +03:00
/*
* We might have SMBtranss in req which was transferred to the outbuf ,
* fix that .
*/
SCVAL ( req - > outbuf , smb_com , SMBtrans ) ;
2008-11-07 14:29:24 +03:00
copy_trans_params_and_data ( ( char * ) req - > outbuf , align ,
2007-04-20 02:40:32 +04:00
rparam , tot_param_sent , this_lparam ,
rdata , tot_data_sent , this_ldata ) ;
1998-03-12 00:11:04 +03:00
2008-11-07 14:29:24 +03:00
SSVAL ( req - > outbuf , smb_vwv0 , lparam ) ;
SSVAL ( req - > outbuf , smb_vwv1 , ldata ) ;
SSVAL ( req - > outbuf , smb_vwv3 , this_lparam ) ;
SSVAL ( req - > outbuf , smb_vwv4 ,
smb_offset ( smb_buf ( req - > outbuf ) + 1 , req - > outbuf ) ) ;
SSVAL ( req - > outbuf , smb_vwv5 , 0 ) ;
SSVAL ( req - > outbuf , smb_vwv6 , this_ldata ) ;
SSVAL ( req - > outbuf , smb_vwv7 ,
smb_offset ( smb_buf ( req - > outbuf ) + 1 + this_lparam + align ,
req - > outbuf ) ) ;
SSVAL ( req - > outbuf , smb_vwv8 , 0 ) ;
SSVAL ( req - > outbuf , smb_vwv9 , 0 ) ;
2007-08-05 15:34:57 +04:00
if ( buffer_too_large ) {
2008-11-07 14:29:24 +03:00
error_packet_set ( ( char * ) req - > outbuf , ERRDOS , ERRmoredata ,
2008-04-02 17:55:10 +04:00
STATUS_BUFFER_OVERFLOW , __LINE__ , __FILE__ ) ;
2007-08-05 15:34:57 +04:00
}
2008-11-07 14:29:24 +03:00
show_msg ( ( char * ) req - > outbuf ) ;
if ( ! srv_send_smb ( smbd_server_fd ( ) , ( char * ) req - > outbuf ,
2008-04-02 17:55:10 +04:00
IS_CONN_ENCRYPTED ( conn ) ) ) {
2008-01-04 23:56:23 +03:00
exit_server_cleanly ( " send_trans_reply: srv_send_smb failed. " ) ;
2008-04-02 17:55:10 +04:00
}
1998-03-12 00:11:04 +03:00
2008-11-07 14:29:24 +03:00
TALLOC_FREE ( req - > outbuf ) ;
2007-08-05 15:34:57 +04:00
1999-12-13 16:27:58 +03:00
tot_data_sent = this_ldata ;
tot_param_sent = this_lparam ;
1998-03-12 00:11:04 +03:00
1999-12-13 16:27:58 +03:00
while ( tot_data_sent < ldata | | tot_param_sent < lparam )
1998-03-12 00:11:04 +03:00
{
2008-04-02 17:55:10 +04:00
this_lparam = MIN ( lparam - tot_param_sent ,
max_send - 500 ) ; /* hack */
this_ldata = MIN ( ldata - tot_data_sent ,
max_send - ( 500 + this_lparam ) ) ;
1999-12-13 16:27:58 +03:00
if ( this_lparam < 0 )
this_lparam = 0 ;
if ( this_ldata < 0 )
this_ldata = 0 ;
1998-03-12 00:11:04 +03:00
align = ( this_lparam % 4 ) ;
2008-11-07 14:29:24 +03:00
reply_outbuf ( req , 10 , 1 + align + this_ldata + this_lparam ) ;
1998-03-12 00:11:04 +03:00
2008-11-07 22:38:05 +03:00
/*
* We might have SMBtranss in req which was transferred to the
* outbuf , fix that .
*/
SCVAL ( req - > outbuf , smb_com , SMBtrans ) ;
2008-11-07 14:29:24 +03:00
copy_trans_params_and_data ( ( char * ) req - > outbuf , align ,
2003-04-14 07:48:26 +04:00
rparam , tot_param_sent , this_lparam ,
rdata , tot_data_sent , this_ldata ) ;
2008-10-10 19:50:09 +04:00
2008-11-07 14:29:24 +03:00
SSVAL ( req - > outbuf , smb_vwv3 , this_lparam ) ;
SSVAL ( req - > outbuf , smb_vwv4 ,
smb_offset ( smb_buf ( req - > outbuf ) + 1 , req - > outbuf ) ) ;
SSVAL ( req - > outbuf , smb_vwv5 , tot_param_sent ) ;
SSVAL ( req - > outbuf , smb_vwv6 , this_ldata ) ;
SSVAL ( req - > outbuf , smb_vwv7 ,
smb_offset ( smb_buf ( req - > outbuf ) + 1 + this_lparam + align ,
req - > outbuf ) ) ;
SSVAL ( req - > outbuf , smb_vwv8 , tot_data_sent ) ;
SSVAL ( req - > outbuf , smb_vwv9 , 0 ) ;
2007-08-05 15:34:57 +04:00
if ( buffer_too_large ) {
2008-11-07 14:29:24 +03:00
error_packet_set ( ( char * ) req - > outbuf ,
ERRDOS , ERRmoredata ,
2007-08-05 15:34:57 +04:00
STATUS_BUFFER_OVERFLOW ,
__LINE__ , __FILE__ ) ;
}
2008-11-07 14:29:24 +03:00
show_msg ( ( char * ) req - > outbuf ) ;
if ( ! srv_send_smb ( smbd_server_fd ( ) , ( char * ) req - > outbuf ,
2008-04-02 17:55:10 +04:00
IS_CONN_ENCRYPTED ( conn ) ) )
exit_server_cleanly ( " send_trans_reply: srv_send_smb "
" failed. " ) ;
1998-03-12 00:11:04 +03:00
1999-12-13 16:27:58 +03:00
tot_data_sent + = this_ldata ;
tot_param_sent + = this_lparam ;
2008-11-07 14:29:24 +03:00
TALLOC_FREE ( req - > outbuf ) ;
1998-03-12 00:11:04 +03:00
}
1996-05-04 11:50:46 +04:00
}
1999-12-13 16:27:58 +03:00
/****************************************************************************
Start the first part of an RPC reply which began with an SMBtrans request .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-10-13 01:01:38 +04:00
static void api_rpc_trans_reply ( connection_struct * conn ,
struct smb_request * req ,
files_struct * fsp ,
int max_trans_reply )
1998-03-12 00:11:04 +03:00
{
2007-10-19 04:40:25 +04:00
bool is_data_outstanding ;
2008-10-13 01:01:38 +04:00
uint8_t * rdata = SMB_MALLOC_ARRAY ( uint8_t , max_trans_reply ) ;
ssize_t data_len ;
NTSTATUS status ;
1998-03-12 00:11:04 +03:00
1999-12-13 16:27:58 +03:00
if ( rdata = = NULL ) {
DEBUG ( 0 , ( " api_rpc_trans_reply: malloc fail. \n " ) ) ;
2007-08-05 14:57:04 +04:00
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
return ;
1998-03-12 00:11:04 +03:00
}
1999-12-13 16:27:58 +03:00
2008-10-13 01:01:38 +04:00
status = np_read ( fsp , rdata , max_trans_reply , & data_len ,
& is_data_outstanding ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2001-09-17 15:25:41 +04:00
SAFE_FREE ( rdata ) ;
2008-01-04 23:56:23 +03:00
api_no_reply ( conn , req ) ;
2007-08-05 14:57:04 +04:00
return ;
1999-12-13 16:27:58 +03:00
}
2008-11-02 23:24:28 +03:00
send_trans_reply ( conn , req , NULL , 0 , ( char * ) rdata , data_len ,
2008-04-02 17:55:10 +04:00
is_data_outstanding ) ;
2001-09-17 15:25:41 +04:00
SAFE_FREE ( rdata ) ;
2007-08-05 14:57:04 +04:00
return ;
1998-03-12 00:11:04 +03:00
}
1998-10-15 09:47:29 +04:00
/****************************************************************************
WaitNamedPipeHandleState
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2008-10-13 01:01:38 +04:00
static void api_WNPHS ( connection_struct * conn , struct smb_request * req ,
struct files_struct * fsp , char * param , int param_len )
1998-10-15 09:47:29 +04:00
{
2007-08-05 14:48:35 +04:00
if ( ! param | | param_len < 2 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
return ;
}
1998-10-15 09:47:29 +04:00
2008-10-13 01:01:38 +04:00
DEBUG ( 4 , ( " WaitNamedPipeHandleState priority %x \n " ,
( int ) SVAL ( param , 0 ) ) ) ;
1998-10-15 09:47:29 +04:00
2008-11-02 23:24:28 +03:00
send_trans_reply ( conn , req , NULL , 0 , NULL , 0 , False ) ;
1998-10-15 09:47:29 +04:00
}
1998-03-12 00:11:04 +03:00
/****************************************************************************
SetNamedPipeHandleState
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2008-10-13 01:01:38 +04:00
static void api_SNPHS ( connection_struct * conn , struct smb_request * req ,
struct files_struct * fsp , char * param , int param_len )
1998-03-12 00:11:04 +03:00
{
2007-08-05 14:48:35 +04:00
if ( ! param | | param_len < 2 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
return ;
}
1998-03-12 00:11:04 +03:00
2008-10-13 01:01:38 +04:00
DEBUG ( 4 , ( " SetNamedPipeHandleState to code %x \n " , ( int ) SVAL ( param , 0 ) ) ) ;
1998-03-12 00:11:04 +03:00
2008-11-02 23:24:28 +03:00
send_trans_reply ( conn , req , NULL , 0 , NULL , 0 , False ) ;
1996-08-15 19:11:34 +04:00
}
1998-03-12 00:11:04 +03:00
/****************************************************************************
1999-12-13 16:27:58 +03:00
When no reply is generated , indicate unsupported .
1998-03-12 00:11:04 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2008-01-04 23:56:23 +03:00
static void api_no_reply ( connection_struct * conn , struct smb_request * req )
1998-03-12 00:11:04 +03:00
{
1999-12-13 16:27:58 +03:00
char rparam [ 4 ] ;
1998-03-12 00:11:04 +03:00
/* unsupported */
1999-12-13 16:27:58 +03:00
SSVAL ( rparam , 0 , NERR_notsupported ) ;
SSVAL ( rparam , 2 , 0 ) ; /* converter word */
1998-03-12 00:11:04 +03:00
DEBUG ( 3 , ( " Unsupported API fd command \n " ) ) ;
/* now send the reply */
2008-11-02 23:24:28 +03:00
send_trans_reply ( conn , req , rparam , 4 , NULL , 0 , False ) ;
1998-03-12 00:11:04 +03:00
2007-08-05 14:28:12 +04:00
return ;
1998-03-12 00:11:04 +03:00
}
/****************************************************************************
1999-12-13 16:27:58 +03:00
Handle remote api calls delivered to a named pipe already opened .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-08-05 14:28:12 +04:00
static void api_fd_reply ( connection_struct * conn , uint16 vuid ,
struct smb_request * req ,
2008-10-13 01:01:38 +04:00
uint16 * setup , uint8_t * data , char * params ,
2007-08-05 14:28:12 +04:00
int suwcnt , int tdscnt , int tpscnt ,
int mdrcnt , int mprcnt )
1998-03-12 00:11:04 +03:00
{
2008-10-13 01:01:38 +04:00
struct files_struct * fsp ;
1999-12-13 16:27:58 +03:00
int pnum ;
int subcommand ;
2008-10-13 01:01:38 +04:00
NTSTATUS status ;
1998-03-12 00:11:04 +03:00
DEBUG ( 5 , ( " api_fd_reply \n " ) ) ;
/* First find out the name of this file. */
1999-12-13 16:27:58 +03:00
if ( suwcnt ! = 2 ) {
1998-03-12 00:11:04 +03:00
DEBUG ( 0 , ( " Unexpected named pipe transaction. \n " ) ) ;
2007-08-05 14:28:12 +04:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
return ;
1998-03-12 00:11:04 +03:00
}
/* Get the file handle and hence the file name. */
1999-12-13 16:27:58 +03:00
/*
* NB . The setup array has already been transformed
2008-10-08 19:24:24 +04:00
* via SVAL and so is in host byte order .
1999-12-13 16:27:58 +03:00
*/
pnum = ( ( int ) setup [ 1 ] ) & 0xFFFF ;
subcommand = ( ( int ) setup [ 0 ] ) & 0xFFFF ;
1998-03-12 00:11:04 +03:00
2008-10-13 01:01:38 +04:00
fsp = file_fsp ( req , pnum ) ;
if ( ! fsp_is_np ( fsp ) ) {
2003-10-22 03:14:41 +04: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 " ) ) ;
2008-11-02 23:24:28 +03:00
send_trans_reply ( conn , req , NULL , 0 , NULL , 0 , False ) ;
2007-08-05 14:28:12 +04:00
return ;
2003-10-22 03:14:41 +04:00
}
1999-12-13 16:27:58 +03:00
DEBUG ( 1 , ( " api_fd_reply: INVALID PIPE HANDLE: %x \n " , pnum ) ) ;
2007-08-05 14:28:12 +04:00
reply_nterror ( req , NT_STATUS_INVALID_HANDLE ) ;
return ;
1999-12-13 16:27:58 +03:00
}
1998-03-12 00:11:04 +03:00
2008-10-13 01:01:38 +04:00
if ( vuid ! = fsp - > vuid ) {
2006-05-28 01:38:54 +04:00
DEBUG ( 1 , ( " Got pipe request (pnum %x) using invalid VUID %d, "
2008-10-13 01:01:38 +04:00
" expected %d \n " , pnum , vuid , fsp - > vuid ) ) ;
2007-08-05 14:28:12 +04:00
reply_nterror ( req , NT_STATUS_INVALID_HANDLE ) ;
return ;
2006-05-28 01:38:54 +04:00
}
2008-10-13 01:01:38 +04:00
DEBUG ( 3 , ( " Got API command 0x%x on pipe \" %s \" (pnum %x) \n " ,
subcommand , fsp - > fsp_name , pnum ) ) ;
1998-03-12 00:11:04 +03:00
2008-10-13 01:01:38 +04:00
DEBUG ( 10 , ( " api_fd_reply: p:%p max_trans_reply: %d \n " , fsp , mdrcnt ) ) ;
1999-12-13 16:27:58 +03:00
switch ( subcommand ) {
2008-10-13 01:01:38 +04:00
case TRANSACT_DCERPCCMD : {
2000-03-10 00:45:16 +03:00
/* dce/rpc command */
2008-10-13 01:01:38 +04:00
ssize_t nwritten ;
status = np_write ( fsp , data , tdscnt , & nwritten ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2008-01-04 23:56:23 +03:00
api_no_reply ( conn , req ) ;
2007-08-05 14:37:08 +04:00
return ;
}
2008-10-13 01:01:38 +04:00
api_rpc_trans_reply ( conn , req , fsp , mdrcnt ) ;
1999-12-13 16:27:58 +03:00
break ;
2008-10-13 01:01:38 +04:00
}
2007-08-05 14:48:35 +04:00
case TRANSACT_WAITNAMEDPIPEHANDLESTATE :
1999-12-13 16:27:58 +03:00
/* Wait Named Pipe Handle state */
2008-10-13 01:01:38 +04:00
api_WNPHS ( conn , req , fsp , params , tpscnt ) ;
1999-12-13 16:27:58 +03:00
break ;
2007-08-05 14:48:35 +04:00
case TRANSACT_SETNAMEDPIPEHANDLESTATE :
1999-12-13 16:27:58 +03:00
/* Set Named Pipe Handle state */
2008-10-13 01:01:38 +04:00
api_SNPHS ( conn , req , fsp , params , tpscnt ) ;
1999-12-13 16:27:58 +03:00
break ;
2005-01-19 01:40:49 +03:00
default :
2007-08-05 14:28:12 +04:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
return ;
1998-03-12 00:11:04 +03:00
}
}
1996-08-15 19:11:34 +04:00
1996-05-04 11:50:46 +04:00
/****************************************************************************
2007-04-20 02:40:32 +04:00
Handle named pipe commands .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-08-05 14:01:58 +04:00
static void named_pipe ( connection_struct * conn , uint16 vuid ,
struct smb_request * req ,
2007-12-11 02:31:05 +03:00
const char * name , uint16 * setup ,
2007-08-05 14:01:58 +04:00
char * data , char * params ,
int suwcnt , int tdscnt , int tpscnt ,
int msrcnt , int mdrcnt , int mprcnt )
1996-05-04 11:50:46 +04:00
{
1997-10-24 17:15:34 +04:00
DEBUG ( 3 , ( " named pipe command on <%s> name \n " , name ) ) ;
1996-05-04 11:50:46 +04:00
2007-04-20 02:40:32 +04:00
if ( strequal ( name , " LANMAN " ) ) {
2007-08-05 15:19:24 +04:00
api_reply ( conn , vuid , req ,
data , params ,
tdscnt , tpscnt ,
mdrcnt , mprcnt ) ;
2007-08-05 14:01:58 +04:00
return ;
2007-04-20 02:40:32 +04:00
}
1996-05-04 11:50:46 +04:00
1998-10-15 09:47:29 +04:00
if ( strequal ( name , " WKSSVC " ) | |
strequal ( name , " SRVSVC " ) | |
strequal ( name , " WINREG " ) | |
strequal ( name , " SAMR " ) | |
2007-04-20 02:40:32 +04:00
strequal ( name , " LSARPC " ) ) {
2007-08-05 14:17:58 +04:00
1998-10-15 09:47:29 +04:00
DEBUG ( 4 , ( " named pipe command from Win95 (wow!) \n " ) ) ;
2007-08-05 14:17:58 +04:00
2007-08-05 14:28:12 +04:00
api_fd_reply ( conn , vuid , req ,
2008-10-13 01:01:38 +04:00
setup , ( uint8_t * ) data , params ,
2007-08-05 14:28:12 +04:00
suwcnt , tdscnt , tpscnt ,
mdrcnt , mprcnt ) ;
2007-08-05 14:01:58 +04:00
return ;
1998-10-15 09:47:29 +04:00
}
2007-04-20 02:40:32 +04:00
if ( strlen ( name ) < 1 ) {
2007-08-05 14:28:12 +04:00
api_fd_reply ( conn , vuid , req ,
2008-10-13 01:01:38 +04:00
setup , ( uint8_t * ) data ,
2007-08-05 14:28:12 +04:00
params , suwcnt , tdscnt ,
tpscnt , mdrcnt , mprcnt ) ;
2007-08-05 14:01:58 +04:00
return ;
2007-04-20 02:40:32 +04:00
}
1996-08-15 19:11:34 +04:00
1997-10-22 22:37:43 +04:00
if ( setup )
2007-08-05 13:19:21 +04:00
DEBUG ( 3 , ( " unknown named pipe: setup 0x%X setup1=%d \n " ,
( int ) setup [ 0 ] , ( int ) setup [ 1 ] ) ) ;
1996-08-15 19:11:34 +04:00
2007-08-05 14:01:58 +04:00
reply_nterror ( req , NT_STATUS_NOT_SUPPORTED ) ;
return ;
1996-05-04 11:50:46 +04:00
}
2007-08-05 13:46:17 +04:00
static void handle_trans ( connection_struct * conn , struct smb_request * req ,
struct trans_state * state )
2006-04-10 19:33:04 +04:00
{
char * local_machine_name ;
int name_offset = 0 ;
DEBUG ( 3 , ( " trans <%s> data=%u params=%u setup=%u \n " ,
2006-06-16 05:30:42 +04:00
state - > name , ( unsigned int ) state - > total_data , ( unsigned int ) state - > total_param ,
( unsigned int ) state - > setup_count ) ) ;
2006-04-10 19:33:04 +04:00
/*
* WinCE wierdness . . . .
*/
local_machine_name = talloc_asprintf ( state , " \\ %s \\ " ,
get_local_machine_name ( ) ) ;
if ( local_machine_name = = NULL ) {
2007-08-05 13:46:17 +04:00
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
return ;
2006-04-10 19:33:04 +04:00
}
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 " ) ) ) {
2007-08-05 13:46:17 +04:00
reply_nterror ( req , NT_STATUS_NOT_SUPPORTED ) ;
return ;
2006-04-10 19:33:04 +04:00
}
2007-12-11 02:31:05 +03:00
2006-04-10 19:33:04 +04:00
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-08-05 14:01:58 +04:00
named_pipe ( conn , state - > vuid , req ,
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 19:33:04 +04:00
2008-01-04 23:56:23 +03:00
if ( state - > close_on_completion ) {
2006-04-10 19:33:04 +04:00
close_cnum ( conn , state - > vuid ) ;
2008-01-04 23:56:23 +03:00
req - > conn = NULL ;
}
2006-04-10 19:33:04 +04:00
2007-08-05 13:46:17 +04:00
return ;
2006-04-10 19:33:04 +04:00
}
1996-05-04 11:50:46 +04:00
/****************************************************************************
1999-12-13 16:27:58 +03:00
Reply to a SMBtrans .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-05 02:37:24 +03:00
void reply_trans ( struct smb_request * req )
1998-08-14 21:38:29 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2007-08-05 00:28:46 +04:00
unsigned int dsoff ;
unsigned int dscnt ;
unsigned int psoff ;
unsigned int pscnt ;
2006-04-10 19:33:04 +04:00
struct trans_state * state ;
NTSTATUS result ;
2000-10-11 09:31:39 +04:00
START_PROFILE ( SMBtrans ) ;
1998-08-14 21:38:29 +04:00
2007-08-11 01:34:55 +04:00
if ( req - > wct < 14 ) {
2007-08-05 12:04:11 +04:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2007-08-05 00:28:46 +04:00
END_PROFILE ( SMBtrans ) ;
2007-08-05 12:04:11 +04:00
return ;
2007-08-05 00:28:46 +04:00
}
2008-11-02 19:38:41 +03:00
dsoff = SVAL ( req - > vwv + 12 , 0 ) ;
dscnt = SVAL ( req - > vwv + 11 , 0 ) ;
psoff = SVAL ( req - > vwv + 10 , 0 ) ;
pscnt = SVAL ( req - > vwv + 9 , 0 ) ;
2007-08-05 00:28:46 +04:00
2007-08-05 12:31:41 +04:00
result = allow_new_trans ( conn - > pending_trans , req - > mid ) ;
2006-04-26 13:43:39 +04:00
if ( ! NT_STATUS_IS_OK ( result ) ) {
2006-04-10 19:33:04 +04:00
DEBUG ( 2 , ( " Got invalid trans request: %s \n " ,
nt_errstr ( result ) ) ) ;
2007-08-05 12:04:11 +04:00
reply_nterror ( req , result ) ;
2006-04-10 19:33:04 +04:00
END_PROFILE ( SMBtrans ) ;
2007-08-05 12:04:11 +04:00
return ;
2006-04-10 19:33:04 +04:00
}
1998-08-14 21:38:29 +04:00
2008-04-28 12:31:49 +04:00
if ( ( state = TALLOC_P ( conn , struct trans_state ) ) = = NULL ) {
2006-04-10 19:33:04 +04:00
DEBUG ( 0 , ( " talloc failed \n " ) ) ;
2007-08-05 12:04:11 +04:00
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
2006-04-10 19:33:04 +04:00
END_PROFILE ( SMBtrans ) ;
2007-08-05 12:04:11 +04:00
return ;
2006-04-10 19:33:04 +04:00
}
state - > cmd = SMBtrans ;
2007-08-05 12:31:41 +04:00
state - > mid = req - > mid ;
state - > vuid = req - > vuid ;
2008-11-02 19:38:41 +03:00
state - > setup_count = CVAL ( req - > vwv + 13 , 0 ) ;
2006-12-15 03:49:12 +03:00
state - > setup = NULL ;
2008-11-02 19:38:41 +03:00
state - > total_param = SVAL ( req - > vwv + 0 , 0 ) ;
2006-04-10 19:33:04 +04:00
state - > param = NULL ;
2008-11-02 19:38:41 +03:00
state - > total_data = SVAL ( req - > vwv + 1 , 0 ) ;
2006-04-10 19:33:04 +04:00
state - > data = NULL ;
2008-11-02 19:38:41 +03:00
state - > max_param_return = SVAL ( req - > vwv + 2 , 0 ) ;
state - > max_data_return = SVAL ( req - > vwv + 3 , 0 ) ;
state - > max_setup_return = CVAL ( req - > vwv + 4 , 0 ) ;
2008-11-02 14:20:47 +03:00
state - > close_on_completion = BITSETW ( req - > vwv + 5 , 0 ) ;
state - > one_way = BITSETW ( req - > vwv + 5 , 1 ) ;
2006-04-10 19:33:04 +04:00
2008-11-02 03:07:46 +03:00
srvstr_pull_req_talloc ( state , req , & state - > name , req - > buf ,
STR_TERMINATE ) ;
2007-12-11 02:31:05 +03:00
if ( ( dscnt > state - > total_data ) | | ( pscnt > state - > total_param ) | |
! state - > name )
2003-03-07 03:30:47 +03:00
goto bad_param ;
2006-04-10 19:33:04 +04:00
if ( state - > total_data ) {
2008-11-08 19:08:57 +03:00
if ( trans_oob ( state - > total_data , 0 , dscnt )
| | trans_oob ( smb_len ( req - > inbuf ) , dsoff , dscnt ) ) {
goto bad_param ;
}
2006-04-10 19:33:04 +04:00
/* Can't use talloc here, the core routines do realloc on the
2007-04-03 18:16:56 +04:00
* params and data . Out of paranoia , 100 bytes too many . */
state - > data = ( char * ) SMB_MALLOC ( state - > total_data + 100 ) ;
2006-04-10 19:33:04 +04:00
if ( state - > data = = NULL ) {
DEBUG ( 0 , ( " reply_trans: data malloc fail for %u "
2006-06-16 05:30:42 +04:00
" bytes ! \n " , ( unsigned int ) state - > total_data ) ) ;
2006-04-10 19:33:04 +04:00
TALLOC_FREE ( state ) ;
2007-08-05 12:04:11 +04:00
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
2000-10-11 09:31:39 +04:00
END_PROFILE ( SMBtrans ) ;
2007-08-05 12:04:11 +04:00
return ;
2007-12-11 02:31:05 +03:00
}
2007-04-03 18:16:56 +04:00
/* null-terminate the slack space */
memset ( & state - > data [ state - > total_data ] , 0 , 100 ) ;
2008-04-08 08:11:16 +04:00
2007-08-05 12:31:41 +04:00
memcpy ( state - > data , smb_base ( req - > inbuf ) + dsoff , dscnt ) ;
1998-08-14 21:38:29 +04:00
}
1996-05-04 11:50:46 +04:00
2006-04-10 19:33:04 +04:00
if ( state - > total_param ) {
2008-11-08 19:08:57 +03:00
if ( trans_oob ( state - > total_param , 0 , pscnt )
| | trans_oob ( smb_len ( req - > inbuf ) , psoff , pscnt ) ) {
goto bad_param ;
}
2006-04-10 19:33:04 +04:00
/* Can't use talloc here, the core routines do realloc on the
2007-04-03 18:16:56 +04:00
* params and data . Out of paranoia , 100 bytes too many */
state - > param = ( char * ) SMB_MALLOC ( state - > total_param + 100 ) ;
2006-04-10 19:33:04 +04:00
if ( state - > param = = NULL ) {
DEBUG ( 0 , ( " reply_trans: param malloc fail for %u "
2006-06-16 05:30:42 +04:00
" bytes ! \n " , ( unsigned int ) state - > total_param ) ) ;
2006-04-10 19:33:04 +04:00
SAFE_FREE ( state - > data ) ;
TALLOC_FREE ( state ) ;
2007-08-05 12:04:11 +04:00
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
2000-10-11 09:31:39 +04:00
END_PROFILE ( SMBtrans ) ;
2007-08-05 12:04:11 +04:00
return ;
1998-10-08 10:49:00 +04:00
}
2007-04-03 18:16:56 +04:00
/* null-terminate the slack space */
memset ( & state - > param [ state - > total_param ] , 0 , 100 ) ;
2008-04-08 08:11:16 +04:00
2007-08-05 12:31:41 +04:00
memcpy ( state - > param , smb_base ( req - > inbuf ) + psoff , pscnt ) ;
1998-08-14 21:38:29 +04:00
}
1996-05-04 11:50:46 +04:00
2006-04-10 19:33:04 +04:00
state - > received_data = dscnt ;
state - > received_param = pscnt ;
if ( state - > setup_count ) {
2003-03-18 14:18:27 +03:00
unsigned int i ;
2008-11-08 18:14:12 +03:00
/*
* No overflow possible here , state - > setup_count is an
* unsigned int , being filled by a single byte from
* CVAL ( req - > vwv + 13 , 0 ) above . The cast in the comparison
* below is not necessary , it ' s here to clarify things . The
* validity of req - > vwv and req - > wct has been checked in
* init_smb_request already .
*/
if ( state - > setup_count + 14 > ( unsigned int ) req - > wct ) {
goto bad_param ;
}
2006-04-10 19:33:04 +04: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 10:18:32 +04:00
SAFE_FREE ( state - > data ) ;
SAFE_FREE ( state - > param ) ;
2006-04-10 19:33:04 +04:00
TALLOC_FREE ( state ) ;
2007-08-05 12:04:11 +04:00
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
2003-03-07 03:30:47 +03:00
END_PROFILE ( SMBtrans ) ;
2007-08-05 12:04:11 +04:00
return ;
2003-03-07 03:30:47 +03:00
}
2008-11-08 18:14:12 +03:00
for ( i = 0 ; i < state - > setup_count ; i + + ) {
state - > setup [ i ] = SVAL ( req - > vwv + 14 + i , 0 ) ;
}
1998-08-14 21:38:29 +04:00
}
1996-05-04 11:50:46 +04:00
2006-04-10 19:33:04 +04:00
state - > received_param = pscnt ;
1996-05-04 11:50:46 +04:00
2007-08-05 12:31:41 +04:00
if ( ( state - > received_param ! = state - > total_param ) | |
( state - > received_data ! = state - > total_data ) ) {
DLIST_ADD ( conn - > pending_trans , state ) ;
2003-08-02 07:06:07 +04:00
2007-08-05 12:31:41 +04: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 19:33:04 +04:00
2007-08-05 13:46:17 +04:00
handle_trans ( conn , req , state ) ;
2007-08-05 12:31:41 +04:00
SAFE_FREE ( state - > data ) ;
SAFE_FREE ( state - > param ) ;
TALLOC_FREE ( state ) ;
2003-03-07 03:30:47 +03:00
2006-04-10 19:33:04 +04:00
END_PROFILE ( SMBtrans ) ;
2007-08-05 12:04:11 +04:00
return ;
1998-10-15 04:55:17 +04:00
2006-04-10 19:33:04 +04:00
bad_param :
2005-02-01 23:43:14 +03:00
2006-04-10 19:33:04 +04: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 12:04:11 +04:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
return ;
2006-04-10 19:33:04 +04:00
}
/****************************************************************************
Reply to a secondary SMBtrans .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-05 02:37:24 +03:00
void reply_transs ( struct smb_request * req )
2006-04-10 19:33:04 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2006-04-10 19:33:04 +04:00
unsigned int pcnt , poff , dcnt , doff , pdisp , ddisp ;
struct trans_state * state ;
START_PROFILE ( SMBtranss ) ;
2007-08-05 13:01:15 +04:00
show_msg ( ( char * ) req - > inbuf ) ;
2006-04-10 19:33:04 +04:00
2007-08-11 01:34:55 +04:00
if ( req - > wct < 8 ) {
2007-08-05 12:47:09 +04:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2007-08-05 00:28:46 +04:00
END_PROFILE ( SMBtranss ) ;
2007-08-05 12:47:09 +04:00
return ;
2007-08-05 00:28:46 +04:00
}
2006-04-10 19:33:04 +04:00
for ( state = conn - > pending_trans ; state ! = NULL ;
state = state - > next ) {
2007-08-05 13:01:15 +04:00
if ( state - > mid = = req - > mid ) {
2006-04-10 19:33:04 +04:00
break ;
}
2006-03-07 22:52:26 +03:00
}
2006-04-10 19:33:04 +04:00
if ( ( state = = NULL ) | | ( state - > cmd ! = SMBtrans ) ) {
2007-08-05 12:47:09 +04:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2006-04-10 19:33:04 +04:00
END_PROFILE ( SMBtranss ) ;
2007-08-05 12:47:09 +04:00
return ;
2006-03-07 22:52:26 +03:00
}
2006-04-10 19:33:04 +04:00
/* Revise total_params and total_data in case they have changed
* downwards */
1998-10-15 04:55:17 +04:00
2008-11-02 14:20:47 +03:00
if ( SVAL ( req - > vwv + 0 , 0 ) < state - > total_param )
state - > total_param = SVAL ( req - > vwv + 0 , 0 ) ;
if ( SVAL ( req - > vwv + 1 , 0 ) < state - > total_data )
state - > total_data = SVAL ( req - > vwv + 1 , 0 ) ;
2007-08-05 13:01:15 +04:00
2008-11-02 19:38:41 +03:00
pcnt = SVAL ( req - > vwv + 2 , 0 ) ;
poff = SVAL ( req - > vwv + 3 , 0 ) ;
pdisp = SVAL ( req - > vwv + 4 , 0 ) ;
2001-06-29 05:58:48 +04:00
2008-11-02 19:38:41 +03:00
dcnt = SVAL ( req - > vwv + 5 , 0 ) ;
doff = SVAL ( req - > vwv + 6 , 0 ) ;
ddisp = SVAL ( req - > vwv + 7 , 0 ) ;
2001-06-29 05:58:48 +04:00
2006-04-10 19:33:04 +04:00
state - > received_param + = pcnt ;
state - > received_data + = dcnt ;
2008-10-10 19:50:09 +04:00
2006-04-10 19:33:04 +04:00
if ( ( state - > received_data > state - > total_data ) | |
( state - > received_param > state - > total_param ) )
goto bad_param ;
2008-10-10 19:50:09 +04:00
2006-04-10 19:33:04 +04:00
if ( pcnt ) {
2008-11-08 19:08:57 +03:00
if ( trans_oob ( state - > total_param , pdisp , pcnt )
| | trans_oob ( smb_len ( req - > inbuf ) , poff , pcnt ) ) {
2006-04-10 19:33:04 +04:00
goto bad_param ;
2008-04-08 08:11:16 +04:00
}
2008-11-08 19:08:57 +03:00
memcpy ( state - > param + pdisp , smb_base ( req - > inbuf ) + poff , pcnt ) ;
1998-08-14 21:38:29 +04:00
}
1996-05-04 11:50:46 +04:00
2006-04-10 19:33:04 +04:00
if ( dcnt ) {
2008-11-08 19:08:57 +03:00
if ( trans_oob ( state - > total_data , ddisp , dcnt )
| | trans_oob ( smb_len ( req - > inbuf ) , doff , dcnt ) ) {
2006-04-10 19:33:04 +04:00
goto bad_param ;
2008-04-08 08:11:16 +04:00
}
2008-11-08 19:08:57 +03:00
memcpy ( state - > data + ddisp , smb_base ( req - > inbuf ) + doff , dcnt ) ;
2006-04-10 19:33:04 +04:00
}
1996-05-04 11:50:46 +04:00
2006-04-10 19:33:04 +04:00
if ( ( state - > received_param < state - > total_param ) | |
( state - > received_data < state - > total_data ) ) {
END_PROFILE ( SMBtranss ) ;
2007-08-05 12:47:09 +04:00
return ;
2000-10-11 09:31:39 +04:00
}
2006-04-10 19:33:04 +04:00
2007-08-05 13:46:17 +04:00
handle_trans ( conn , req , state ) ;
2007-08-05 13:01:15 +04:00
2006-04-10 19:33:04 +04:00
DLIST_REMOVE ( conn - > pending_trans , state ) ;
SAFE_FREE ( state - > data ) ;
SAFE_FREE ( state - > param ) ;
TALLOC_FREE ( state ) ;
END_PROFILE ( SMBtranss ) ;
2007-08-05 12:47:09 +04:00
return ;
2003-03-07 03:30:47 +03:00
bad_param :
2006-04-10 19:33:04 +04: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 12:47:09 +04:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2006-04-10 19:33:04 +04:00
END_PROFILE ( SMBtranss ) ;
2007-08-05 12:47:09 +04:00
return ;
1996-05-04 11:50:46 +04:00
}