2012-03-03 04:23:44 +04:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
1996-08-15 19:11:34 +04:00
Pipe SMB reply routines
1998-01-22 16:27:43 +03:00
Copyright ( C ) Andrew Tridgell 1992 - 1998
Copyright ( C ) Luke Kenneth Casson Leighton 1996 - 1998
Copyright ( C ) Paul Ashton 1997 - 1998.
2005-07-08 08:51:27 +04:00
Copyright ( C ) Jeremy Allison 2005.
2012-03-03 04:23:44 +04:00
1996-08-15 19:11:34 +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-08-15 19:11:34 +04:00
( at your option ) any later version .
2012-03-03 04:23:44 +04:00
1996-08-15 19:11:34 +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 .
2012-03-03 04:23:44 +04:00
1996-08-15 19:11:34 +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-08-15 19:11:34 +04:00
*/
/*
This file handles reply_ calls on named pipes that the server
makes to handle specific protocols
*/
# include "includes.h"
2011-03-22 18:57:01 +03:00
# include "smbd/smbd.h"
2010-04-27 17:12:32 +04:00
# include "smbd/globals.h"
2010-10-12 08:27:50 +04:00
# include "libcli/security/security.h"
2011-04-30 01:32:28 +04:00
# include "rpc_server/srv_pipe_hnd.h"
1996-08-15 19:11:34 +04:00
2009-01-20 17:21:04 +03:00
NTSTATUS open_np_file ( struct smb_request * smb_req , const char * name ,
struct files_struct * * pfsp )
{
struct connection_struct * conn = smb_req - > conn ;
struct files_struct * fsp ;
2009-07-11 01:50:37 +04:00
struct smb_filename * smb_fname = NULL ;
2009-01-20 17:21:04 +03:00
NTSTATUS status ;
status = file_new ( smb_req , conn , & fsp ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " file_new failed: %s \n " , nt_errstr ( status ) ) ) ;
return status ;
}
fsp - > conn = conn ;
fsp - > fh - > fd = - 1 ;
fsp - > vuid = smb_req - > vuid ;
fsp - > can_lock = false ;
fsp - > access_mask = FILE_READ_DATA | FILE_WRITE_DATA ;
2009-07-11 01:50:37 +04:00
2016-03-19 07:19:38 +03:00
smb_fname = synthetic_smb_fname ( talloc_tos ( ) , name , NULL , NULL , 0 ) ;
2013-04-15 13:00:14 +04:00
if ( smb_fname = = NULL ) {
2009-07-11 01:50:37 +04:00
file_free ( smb_req , fsp ) ;
2013-04-15 13:00:14 +04:00
return NT_STATUS_NO_MEMORY ;
2009-07-11 01:50:37 +04:00
}
status = fsp_set_smb_fname ( fsp , smb_fname ) ;
TALLOC_FREE ( smb_fname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
file_free ( smb_req , fsp ) ;
return status ;
}
2009-01-20 17:21:04 +03:00
2010-04-27 17:12:32 +04:00
status = np_open ( fsp , name ,
conn - > sconn - > remote_address ,
2017-03-23 04:05:56 +03:00
conn - > sconn - > local_address ,
2011-02-21 12:25:52 +03:00
conn - > session_info ,
2018-03-22 12:54:41 +03:00
smb_req - > ev_ctx ,
2010-08-08 11:11:45 +04:00
conn - > sconn - > msg_ctx ,
& fsp - > fake_file_handle ) ;
2009-01-20 17:21:04 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 10 , ( " np_open(%s) returned %s \n " , name ,
nt_errstr ( status ) ) ) ;
file_free ( smb_req , fsp ) ;
return status ;
}
* pfsp = fsp ;
return NT_STATUS_OK ;
}
1997-10-30 04:05:13 +03:00
/****************************************************************************
2005-07-08 08:51:27 +04:00
Reply to an open and X on a named pipe .
This code is basically stolen from reply_open_and_X with some
wrinkles to handle pipes .
1996-08-15 19:11:34 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-07-08 08:51:27 +04:00
2007-07-23 13:54:36 +04:00
void reply_open_pipe_and_X ( connection_struct * conn , struct smb_request * req )
1996-08-15 19:11:34 +04:00
{
2007-09-13 03:50:21 +04:00
const char * fname = NULL ;
char * pipe_name = NULL ;
2008-10-13 01:01:38 +04:00
files_struct * fsp ;
2007-09-13 03:50:21 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2008-10-13 01:01:38 +04:00
NTSTATUS status ;
1998-08-17 07:06:20 +04:00
/* XXXX we need to handle passed times, sattr and flags */
2008-11-02 03:07:46 +03:00
srvstr_pull_req_talloc ( ctx , req , & pipe_name , req - > buf , STR_TERMINATE ) ;
2007-09-13 03:50:21 +04:00
if ( ! pipe_name ) {
reply_botherror ( req , NT_STATUS_OBJECT_NAME_NOT_FOUND ,
ERRDOS , ERRbadpipe ) ;
return ;
}
1998-08-17 07:06:20 +04:00
/* If the name doesn't start \PIPE\ then this is directed */
/* at a mailslot or something we really, really don't understand, */
/* not just something we really don't understand. */
2012-05-28 20:23:50 +04:00
# define PIPE "PIPE\\"
# define PIPELEN strlen(PIPE)
fname = pipe_name ;
while ( fname [ 0 ] = = ' \\ ' ) {
fname + + ;
}
if ( ! strnequal ( fname , PIPE , PIPELEN ) ) {
reply_nterror ( req , NT_STATUS_OBJECT_PATH_SYNTAX_BAD ) ;
2007-07-23 13:54:36 +04:00
return ;
2005-07-08 08:51:27 +04:00
}
2012-05-28 20:23:50 +04:00
fname + = PIPELEN ;
while ( fname [ 0 ] = = ' \\ ' ) {
fname + + ;
}
1998-08-17 07:06:20 +04:00
2012-05-28 20:23:50 +04:00
DEBUG ( 4 , ( " Opening pipe %s => %s. \n " , pipe_name , fname ) ) ;
2001-07-05 01:57:03 +04:00
2000-06-07 05:49:23 +04:00
#if 0
1999-12-13 16:27:58 +03:00
/*
* Hack for NT printers . . . JRA .
*/
2007-07-23 13:54:36 +04:00
if ( should_fail_next_srvsvc_open ( fname ) ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
2007-07-23 13:54:36 +04:00
return ;
}
2000-06-07 05:49:23 +04:00
# endif
1999-12-13 16:27:58 +03:00
2009-01-20 17:21:04 +03:00
status = open_np_file ( req , fname , & fsp ) ;
2008-10-13 01:01:38 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2008-10-25 17:23:36 +04:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_OBJECT_NAME_NOT_FOUND ) ) {
reply_botherror ( req , NT_STATUS_OBJECT_NAME_NOT_FOUND ,
ERRDOS , ERRbadpipe ) ;
return ;
}
2008-10-13 01:01:38 +04:00
reply_nterror ( req , status ) ;
2007-07-23 13:54:36 +04:00
return ;
2005-07-08 08:51:27 +04:00
}
1998-08-17 07:06:20 +04:00
/* Prepare the reply */
2007-07-23 13:54:36 +04:00
reply_outbuf ( req , 15 , 0 ) ;
1998-08-17 07:06:20 +04:00
2012-02-26 19:49:09 +04:00
SSVAL ( req - > outbuf , smb_vwv0 , 0xff ) ; /* andx chain ends */
SSVAL ( req - > outbuf , smb_vwv1 , 0 ) ; /* no andx offset */
1998-08-17 07:06:20 +04:00
/* Mark the opened file as an existing named pipe in message mode. */
2007-07-23 13:54:36 +04:00
SSVAL ( req - > outbuf , smb_vwv9 , 2 ) ;
SSVAL ( req - > outbuf , smb_vwv10 , 0xc700 ) ;
1998-08-17 07:06:20 +04:00
2008-11-09 21:57:10 +03:00
SSVAL ( req - > outbuf , smb_vwv2 , fsp - > fnum ) ;
SSVAL ( req - > outbuf , smb_vwv3 , 0 ) ; /* fmode */
srv_put_dos_date3 ( ( char * ) req - > outbuf , smb_vwv4 , 0 ) ; /* mtime */
SIVAL ( req - > outbuf , smb_vwv6 , 0 ) ; /* size */
SSVAL ( req - > outbuf , smb_vwv8 , 0 ) ; /* rmode */
SSVAL ( req - > outbuf , smb_vwv11 , 0x0001 ) ;
1996-08-15 19:11:34 +04:00
}
1999-11-16 01:11:10 +03:00
/****************************************************************************
2005-07-08 08:51:27 +04:00
Reply to a write on a pipe .
1999-11-16 01:11:10 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-07-08 08:51:27 +04:00
2009-01-31 16:43:06 +03:00
struct pipe_write_state {
size_t numtowrite ;
} ;
2009-03-17 11:17:16 +03:00
static void pipe_write_done ( struct tevent_req * subreq ) ;
2009-01-31 16:43:06 +03:00
2007-08-14 22:16:04 +04:00
void reply_pipe_write ( struct smb_request * req )
1999-11-16 01:11:10 +03:00
{
2008-11-02 14:20:47 +03:00
files_struct * fsp = file_fsp ( req , SVAL ( req - > vwv + 0 , 0 ) ) ;
2008-11-01 19:35:48 +03:00
const uint8_t * data ;
2009-01-31 16:43:06 +03:00
struct pipe_write_state * state ;
2009-03-17 11:17:16 +03:00
struct tevent_req * subreq ;
1999-11-16 01:11:10 +03:00
2008-10-13 01:01:38 +04:00
if ( ! fsp_is_np ( fsp ) ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_INVALID_HANDLE ) ;
2007-08-14 22:16:04 +04:00
return ;
2005-07-08 08:51:27 +04:00
}
1999-11-16 01:11:10 +03:00
2008-10-13 01:01:38 +04:00
if ( fsp - > vuid ! = req - > vuid ) {
2007-08-14 22:16:04 +04:00
reply_nterror ( req , NT_STATUS_INVALID_HANDLE ) ;
return ;
2006-05-28 01:38:54 +04:00
}
2009-01-31 16:43:06 +03:00
state = talloc ( req , struct pipe_write_state ) ;
if ( state = = NULL ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
return ;
}
req - > async_priv = state ;
state - > numtowrite = SVAL ( req - > vwv + 1 , 0 ) ;
2008-11-01 19:35:48 +03:00
data = req - > buf + 3 ;
1999-11-16 01:11:10 +03:00
2012-06-14 14:57:25 +04:00
DEBUG ( 6 , ( " reply_pipe_write: %s, name: %s len: %d \n " , fsp_fnum_dbg ( fsp ) ,
2009-07-11 01:50:37 +04:00
fsp_str_dbg ( fsp ) , ( int ) state - > numtowrite ) ) ;
2009-01-31 16:43:06 +03:00
2018-03-22 12:54:41 +03:00
subreq = np_write_send ( state , req - > ev_ctx ,
2009-01-31 16:43:06 +03:00
fsp - > fake_file_handle , data , state - > numtowrite ) ;
if ( subreq = = NULL ) {
TALLOC_FREE ( state ) ;
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
2009-01-31 16:33:38 +03:00
return ;
2005-07-08 08:51:27 +04:00
}
2009-03-17 11:17:16 +03:00
tevent_req_set_callback ( subreq , pipe_write_done ,
talloc_move ( req - > conn , & req ) ) ;
2009-01-31 16:43:06 +03:00
}
2009-03-17 11:17:16 +03:00
static void pipe_write_done ( struct tevent_req * subreq )
2009-01-31 16:43:06 +03:00
{
2009-03-17 11:17:16 +03:00
struct smb_request * req = tevent_req_callback_data (
subreq , struct smb_request ) ;
2009-01-31 16:43:06 +03:00
struct pipe_write_state * state = talloc_get_type_abort (
req - > async_priv , struct pipe_write_state ) ;
NTSTATUS status ;
ssize_t nwritten = - 1 ;
1999-11-16 01:11:10 +03:00
2009-01-31 16:43:06 +03:00
status = np_write_recv ( subreq , & nwritten ) ;
TALLOC_FREE ( subreq ) ;
2009-07-11 05:23:00 +04:00
if ( nwritten < 0 ) {
reply_nterror ( req , status ) ;
goto send ;
}
/* Looks bogus to me now. Needs to be removed ? JRA. */
if ( ( nwritten = = 0 & & state - > numtowrite ! = 0 ) ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
2009-01-31 16:43:06 +03:00
goto send ;
2005-07-08 08:51:27 +04:00
}
1999-11-16 01:11:10 +03:00
2007-08-14 22:16:04 +04:00
reply_outbuf ( req , 1 , 0 ) ;
SSVAL ( req - > outbuf , smb_vwv0 , nwritten ) ;
1999-11-16 01:11:10 +03:00
2009-01-31 16:43:06 +03:00
DEBUG ( 3 , ( " write-IPC nwritten=%d \n " , ( int ) nwritten ) ) ;
send :
2014-06-11 14:55:24 +04:00
if ( ! srv_send_smb ( req - > xconn , ( char * ) req - > outbuf ,
2009-03-09 11:47:59 +03:00
true , req - > seqnum + 1 ,
2009-02-09 10:10:34 +03:00
IS_CONN_ENCRYPTED ( req - > conn ) | | req - > encrypted ,
& req - > pcd ) ) {
2009-01-31 16:43:06 +03:00
exit_server_cleanly ( " construct_reply: srv_send_smb failed. " ) ;
}
TALLOC_FREE ( req ) ;
1999-11-16 01:11:10 +03:00
}
1996-08-15 19:11:34 +04:00
1998-10-07 19:22:49 +04:00
/****************************************************************************
2000-03-10 00:45:16 +03:00
Reply to a write and X .
1998-10-07 19:22:49 +04:00
2000-03-10 00:45:16 +03:00
This code is basically stolen from reply_write_and_X with some
wrinkles to handle pipes .
1998-10-07 19:22:49 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-03-10 00:45:16 +03:00
2009-01-31 16:31:31 +03:00
struct pipe_write_andx_state {
bool pipe_start_message_raw ;
size_t numtowrite ;
} ;
2009-03-17 11:17:16 +03:00
static void pipe_write_andx_done ( struct tevent_req * subreq ) ;
2009-01-31 16:31:31 +03:00
2007-08-08 22:40:26 +04:00
void reply_pipe_write_and_X ( struct smb_request * req )
1998-10-07 19:22:49 +04:00
{
2008-11-02 14:20:47 +03:00
files_struct * fsp = file_fsp ( req , SVAL ( req - > vwv + 2 , 0 ) ) ;
int smb_doff = SVAL ( req - > vwv + 11 , 0 ) ;
2011-05-05 21:41:59 +04:00
const uint8_t * data ;
2009-01-31 16:31:31 +03:00
struct pipe_write_andx_state * state ;
2009-03-17 11:17:16 +03:00
struct tevent_req * subreq ;
1998-10-07 19:22:49 +04:00
2008-10-13 01:01:38 +04:00
if ( ! fsp_is_np ( fsp ) ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_INVALID_HANDLE ) ;
2007-08-08 22:40:26 +04:00
return ;
2005-07-08 08:51:27 +04:00
}
1998-10-07 19:22:49 +04:00
2008-10-13 01:01:38 +04:00
if ( fsp - > vuid ! = req - > vuid ) {
2007-08-08 22:40:26 +04:00
reply_nterror ( req , NT_STATUS_INVALID_HANDLE ) ;
return ;
2006-05-28 01:38:54 +04:00
}
2009-01-31 16:31:31 +03:00
state = talloc ( req , struct pipe_write_andx_state ) ;
if ( state = = NULL ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
return ;
}
req - > async_priv = state ;
state - > numtowrite = SVAL ( req - > vwv + 10 , 0 ) ;
state - > pipe_start_message_raw =
( ( SVAL ( req - > vwv + 7 , 0 ) & ( PIPE_START_MESSAGE | PIPE_RAW_MODE ) )
= = ( PIPE_START_MESSAGE | PIPE_RAW_MODE ) ) ;
2012-06-14 14:57:25 +04:00
DEBUG ( 6 , ( " reply_pipe_write_and_X: %s, name: %s len: %d \n " ,
fsp_fnum_dbg ( fsp ) , fsp_str_dbg ( fsp ) , ( int ) state - > numtowrite ) ) ;
2009-01-20 17:21:04 +03:00
2011-05-05 21:41:59 +04:00
data = ( const uint8_t * ) smb_base ( req - > inbuf ) + smb_doff ;
1998-10-07 19:22:49 +04:00
2009-01-31 16:31:31 +03:00
if ( state - > pipe_start_message_raw ) {
2009-01-31 16:33:38 +03:00
/*
* For the start of a message in named pipe byte mode ,
* the first two bytes are a length - of - pdu field . Ignore
* them ( we don ' t trust the client ) . JRA .
*/
2009-01-31 16:31:31 +03:00
if ( state - > numtowrite < 2 ) {
2009-01-31 16:33:38 +03:00
DEBUG ( 0 , ( " reply_pipe_write_and_X: start of message "
" set and not enough data sent.(%u) \n " ,
2009-01-31 16:31:31 +03:00
( unsigned int ) state - > numtowrite ) ) ;
2009-07-11 05:23:00 +04:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2008-10-13 01:01:38 +04:00
return ;
}
2009-01-31 16:33:38 +03:00
data + = 2 ;
2009-01-31 16:31:31 +03:00
state - > numtowrite - = 2 ;
2009-01-31 16:33:38 +03:00
}
2009-01-31 16:31:31 +03:00
2018-03-22 12:54:41 +03:00
subreq = np_write_send ( state , req - > ev_ctx ,
2009-01-31 16:31:31 +03:00
fsp - > fake_file_handle , data , state - > numtowrite ) ;
if ( subreq = = NULL ) {
TALLOC_FREE ( state ) ;
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
2009-01-31 16:33:38 +03:00
return ;
2000-03-10 00:45:16 +03:00
}
2009-03-17 11:17:16 +03:00
tevent_req_set_callback ( subreq , pipe_write_andx_done ,
talloc_move ( req - > conn , & req ) ) ;
2009-01-31 16:31:31 +03:00
}
1998-10-07 19:22:49 +04:00
2009-03-17 11:17:16 +03:00
static void pipe_write_andx_done ( struct tevent_req * subreq )
2009-01-31 16:31:31 +03:00
{
2009-03-17 11:17:16 +03:00
struct smb_request * req = tevent_req_callback_data (
subreq , struct smb_request ) ;
2009-01-31 16:31:31 +03:00
struct pipe_write_andx_state * state = talloc_get_type_abort (
req - > async_priv , struct pipe_write_andx_state ) ;
NTSTATUS status ;
ssize_t nwritten = - 1 ;
status = np_write_recv ( subreq , & nwritten ) ;
TALLOC_FREE ( subreq ) ;
2009-07-11 05:23:00 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
reply_nterror ( req , status ) ;
goto done ;
}
/* Looks bogus to me now. Is this error message correct ? JRA. */
if ( nwritten ! = state - > numtowrite ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
2009-01-31 16:31:31 +03:00
goto done ;
2005-07-08 08:51:27 +04:00
}
2007-08-08 22:40:26 +04:00
reply_outbuf ( req , 6 , 0 ) ;
1998-10-07 19:22:49 +04:00
2012-02-26 19:49:09 +04:00
SSVAL ( req - > outbuf , smb_vwv0 , 0xff ) ; /* andx chain ends */
SSVAL ( req - > outbuf , smb_vwv1 , 0 ) ; /* no andx offset */
2009-01-31 16:31:31 +03:00
nwritten = ( state - > pipe_start_message_raw ? nwritten + 2 : nwritten ) ;
2007-08-08 22:40:26 +04:00
SSVAL ( req - > outbuf , smb_vwv2 , nwritten ) ;
1998-10-07 19:22:49 +04:00
2009-01-31 16:31:31 +03:00
DEBUG ( 3 , ( " writeX-IPC nwritten=%d \n " , ( int ) nwritten ) ) ;
done :
2010-01-06 01:34:00 +03:00
/*
* We must free here as the ownership of req was
* moved to the connection struct in reply_pipe_write_and_X ( ) .
*/
2012-03-04 15:10:04 +04:00
smb_request_done ( req ) ;
1998-10-07 19:22:49 +04:00
}
1997-10-30 04:05:13 +03:00
/****************************************************************************
2005-07-08 08:51:27 +04:00
Reply to a read and X .
This code is basically stolen from reply_read_and_X with some
wrinkles to handle pipes .
1996-08-15 19:11:34 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-07-08 08:51:27 +04:00
2009-01-31 16:57:52 +03:00
struct pipe_read_andx_state {
uint8_t * outbuf ;
int smb_mincnt ;
int smb_maxcnt ;
} ;
2009-03-17 11:34:17 +03:00
static void pipe_read_andx_done ( struct tevent_req * subreq ) ;
2009-01-31 16:57:52 +03:00
2007-08-11 14:53:36 +04:00
void reply_pipe_read_and_X ( struct smb_request * req )
1996-08-15 19:11:34 +04:00
{
2008-11-02 14:20:47 +03:00
files_struct * fsp = file_fsp ( req , SVAL ( req - > vwv + 0 , 0 ) ) ;
2008-10-13 01:01:38 +04:00
uint8_t * data ;
2009-01-31 16:57:52 +03:00
struct pipe_read_andx_state * state ;
2009-03-17 11:34:17 +03:00
struct tevent_req * subreq ;
2002-01-20 05:40:05 +03:00
1999-12-13 16:27:58 +03:00
/* we don't use the offset given to use for pipe reads. This
is deliberate , instead we always return the next lump of
data on the pipe */
#if 0
2015-05-03 07:01:14 +03:00
uint32_t smb_offs = IVAL ( req - > vwv + 3 , 0 ) ;
1999-12-13 16:27:58 +03:00
# endif
1996-08-15 19:11:34 +04:00
2008-10-13 01:01:38 +04:00
if ( ! fsp_is_np ( fsp ) ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_INVALID_HANDLE ) ;
2007-08-11 14:53:36 +04:00
return ;
2005-07-08 08:51:27 +04:00
}
1998-09-01 05:10:01 +04:00
2008-10-13 01:01:38 +04:00
if ( fsp - > vuid ! = req - > vuid ) {
reply_nterror ( req , NT_STATUS_INVALID_HANDLE ) ;
return ;
}
2009-01-31 16:57:52 +03:00
state = talloc ( req , struct pipe_read_andx_state ) ;
if ( state = = NULL ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
return ;
}
req - > async_priv = state ;
2007-08-11 14:53:36 +04:00
2009-01-31 16:57:52 +03:00
state - > smb_maxcnt = SVAL ( req - > vwv + 5 , 0 ) ;
state - > smb_mincnt = SVAL ( req - > vwv + 6 , 0 ) ;
2014-08-15 09:04:33 +04:00
reply_outbuf ( req , 12 , state - > smb_maxcnt + 1 /* padding byte */ ) ;
2012-02-26 19:49:09 +04:00
SSVAL ( req - > outbuf , smb_vwv0 , 0xff ) ; /* andx chain ends */
SSVAL ( req - > outbuf , smb_vwv1 , 0 ) ; /* no andx offset */
2014-08-15 09:04:33 +04:00
SCVAL ( smb_buf ( req - > outbuf ) , 0 , 0 ) ; /* padding byte */
2012-02-26 19:49:09 +04:00
2014-08-15 09:04:33 +04:00
data = ( uint8_t * ) smb_buf ( req - > outbuf ) + 1 /* padding byte */ ;
1996-08-15 19:11:34 +04:00
2009-01-31 16:57:52 +03:00
/*
* We have to tell the upper layers that we ' re async .
*/
state - > outbuf = req - > outbuf ;
req - > outbuf = NULL ;
1996-08-15 19:11:34 +04:00
2018-03-22 12:54:41 +03:00
subreq = np_read_send ( state , req - > ev_ctx ,
2009-01-31 16:57:52 +03:00
fsp - > fake_file_handle , data ,
state - > smb_maxcnt ) ;
if ( subreq = = NULL ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
2007-08-11 14:53:36 +04:00
return ;
2005-07-08 08:51:27 +04:00
}
2009-03-17 11:34:17 +03:00
tevent_req_set_callback ( subreq , pipe_read_andx_done ,
talloc_move ( req - > conn , & req ) ) ;
2009-01-31 16:57:52 +03:00
}
2009-03-17 11:34:17 +03:00
static void pipe_read_andx_done ( struct tevent_req * subreq )
2009-01-31 16:57:52 +03:00
{
2009-03-17 11:34:17 +03:00
struct smb_request * req = tevent_req_callback_data (
subreq , struct smb_request ) ;
2009-01-31 16:57:52 +03:00
struct pipe_read_andx_state * state = talloc_get_type_abort (
req - > async_priv , struct pipe_read_andx_state ) ;
NTSTATUS status ;
ssize_t nread ;
bool is_data_outstanding ;
status = np_read_recv ( subreq , & nread , & is_data_outstanding ) ;
TALLOC_FREE ( subreq ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2012-05-23 17:23:23 +04:00
NTSTATUS old = status ;
status = nt_status_np_pipe ( old ) ;
2009-01-31 16:57:52 +03:00
reply_nterror ( req , status ) ;
goto done ;
}
req - > outbuf = state - > outbuf ;
state - > outbuf = NULL ;
2007-08-11 14:53:36 +04:00
2014-08-15 09:04:33 +04:00
srv_set_message ( ( char * ) req - > outbuf , 12 , nread + 1 /* padding byte */ ,
false ) ;
2010-04-28 16:36:10 +04:00
#if 0
/*
* we should return STATUS_BUFFER_OVERFLOW if there ' s
* out standing data .
*
* But we can ' t enable it yet , as it has bad interactions
* with fixup_chain_error_packet ( ) in chain_reply ( ) .
*/
if ( is_data_outstanding ) {
error_packet_set ( ( char * ) req - > outbuf , ERRDOS , ERRmoredata ,
STATUS_BUFFER_OVERFLOW , __LINE__ , __FILE__ ) ;
}
# endif
2007-08-11 14:53:36 +04:00
SSVAL ( req - > outbuf , smb_vwv5 , nread ) ;
2008-11-22 01:17:31 +03:00
SSVAL ( req - > outbuf , smb_vwv6 ,
2012-03-03 03:33:15 +04:00
( smb_wct - 4 ) /* offset from smb header to wct */
2008-11-22 01:17:31 +03:00
+ 1 /* the wct field */
+ 12 * sizeof ( uint16_t ) /* vwv */
2014-08-15 09:04:33 +04:00
+ 2 /* the buflen field */
+ 1 ) ; /* padding byte */
2012-03-03 04:23:44 +04:00
2009-01-31 16:57:52 +03:00
DEBUG ( 3 , ( " readX-IPC min=%d max=%d nread=%d \n " ,
state - > smb_mincnt , state - > smb_maxcnt , ( int ) nread ) ) ;
1996-08-15 19:11:34 +04:00
2009-01-31 16:57:52 +03:00
done :
2010-01-06 01:34:00 +03:00
/*
* We must free here as the ownership of req was
* moved to the connection struct in reply_pipe_read_and_X ( ) .
*/
2012-03-04 15:10:04 +04:00
smb_request_done ( req ) ;
1996-08-15 19:11:34 +04:00
}