1996-08-15 19:11:34 +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.
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 .
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 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"
# define PIPE "\\PIPE\\"
# define PIPELEN strlen(PIPE)
2006-07-11 22:01:26 +04:00
# define MAX_PIPE_NAME_LEN 24
/* PIPE/<name>/<pid>/<pnum> */
# define PIPEDB_KEY_FORMAT "PIPE / %s / %u / %d"
struct pipe_dbrec {
2007-05-07 13:35:35 +04:00
struct server_id pid ;
2006-07-11 22:01:26 +04:00
int pnum ;
uid_t uid ;
char name [ MAX_PIPE_NAME_LEN ] ;
fstring user ;
} ;
1998-03-12 00:11:04 +03:00
extern struct pipe_id_info pipe_names [ ] ;
1996-08-15 19:11:34 +04:00
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
{
1998-08-17 07:06:20 +04:00
pstring fname ;
2001-07-05 01:57:03 +04:00
pstring pipe_name ;
2002-01-20 05:40:05 +03:00
smb_np_struct * p ;
1998-08-17 07:06:20 +04:00
int size = 0 , fmode = 0 , mtime = 0 , rmode = 0 ;
int i ;
/* XXXX we need to handle passed times, sattr and flags */
2007-07-23 13:54:36 +04:00
srvstr_pull_buf ( req - > inbuf , req - > flags2 , pipe_name ,
smb_buf ( req - > inbuf ) , sizeof ( pipe_name ) , STR_TERMINATE ) ;
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. */
2005-07-08 08:51:27 +04:00
if ( strncmp ( pipe_name , PIPE , PIPELEN ) ! = 0 ) {
2007-07-23 13:54:36 +04:00
reply_doserror ( req , ERRSRV , ERRaccess ) ;
return ;
2005-07-08 08:51:27 +04:00
}
1998-08-17 07:06:20 +04:00
2001-07-05 01:57:03 +04:00
DEBUG ( 4 , ( " Opening pipe %s. \n " , pipe_name ) ) ;
1998-08-17 07:06:20 +04:00
/* See if it is one we want to handle. */
2005-07-08 08:51:27 +04:00
for ( i = 0 ; pipe_names [ i ] . client_pipe ; i + + ) {
if ( strequal ( pipe_name , pipe_names [ i ] . client_pipe ) ) {
1998-08-17 07:06:20 +04:00
break ;
2005-07-08 08:51:27 +04:00
}
}
1998-08-17 07:06:20 +04:00
2005-07-08 08:51:27 +04:00
if ( pipe_names [ i ] . client_pipe = = NULL ) {
2007-07-23 13:54:36 +04:00
reply_botherror ( req , NT_STATUS_OBJECT_NAME_NOT_FOUND ,
ERRDOS , ERRbadpipe ) ;
return ;
2005-07-08 08:51:27 +04:00
}
1998-08-17 07:06:20 +04:00
/* Strip \PIPE\ off the name. */
2001-07-05 01:57:03 +04:00
pstrcpy ( fname , pipe_name + PIPELEN ) ;
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 ) ) {
reply_doserror ( req , ERRSRV , ERRaccess ) ;
return ;
}
2000-06-07 05:49:23 +04:00
# endif
1999-12-13 16:27:58 +03:00
1998-08-17 07:06:20 +04:00
/* Known pipes arrive with DIR attribs. Remove it so a regular file */
/* can be opened and add it in after the open. */
DEBUG ( 3 , ( " Known pipe %s opening. \n " , fname ) ) ;
2007-07-23 13:54:36 +04:00
p = open_rpc_pipe_p ( fname , conn , req - > vuid ) ;
2005-07-08 08:51:27 +04:00
if ( ! p ) {
2007-07-23 13:54:36 +04:00
reply_doserror ( req , ERRSRV , ERRnofids ) ;
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
/* 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
if ( rmode = = 2 ) {
DEBUG ( 4 , ( " Resetting open result to open from create. \n " ) ) ;
rmode = 1 ;
}
2007-07-23 13:54:36 +04:00
SSVAL ( req - > outbuf , smb_vwv2 , p - > pnum ) ;
SSVAL ( req - > outbuf , smb_vwv3 , fmode ) ;
srv_put_dos_date3 ( ( char * ) req - > outbuf , smb_vwv4 , mtime ) ;
SIVAL ( req - > outbuf , smb_vwv6 , size ) ;
SSVAL ( req - > outbuf , smb_vwv8 , rmode ) ;
SSVAL ( req - > outbuf , smb_vwv11 , 0x0001 ) ;
1998-08-17 07:06:20 +04:00
2007-08-27 16:04:09 +04:00
chain_reply ( req ) ;
2007-07-23 13:54:36 +04:00
return ;
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
2007-08-14 22:16:04 +04:00
void reply_pipe_write ( struct smb_request * req )
1999-11-16 01:11:10 +03:00
{
2007-08-14 22:16:04 +04:00
smb_np_struct * p = get_rpc_pipe_p ( SVAL ( req - > inbuf , smb_vwv0 ) ) ;
size_t numtowrite = SVAL ( req - > inbuf , smb_vwv1 ) ;
1999-12-13 16:27:58 +03:00
int nwritten ;
1999-11-16 01:11:10 +03:00
char * data ;
2005-07-08 08:51:27 +04:00
if ( ! p ) {
2007-08-14 22:16:04 +04:00
reply_doserror ( req , ERRDOS , ERRbadfid ) ;
return ;
2005-07-08 08:51:27 +04:00
}
1999-11-16 01:11:10 +03:00
2007-08-14 22:16:04 +04:00
if ( p - > vuid ! = req - > vuid ) {
reply_nterror ( req , NT_STATUS_INVALID_HANDLE ) ;
return ;
2006-05-28 01:38:54 +04:00
}
2007-08-14 22:16:04 +04:00
data = smb_buf ( req - > inbuf ) + 3 ;
1999-11-16 01:11:10 +03:00
2005-07-08 08:51:27 +04:00
if ( numtowrite = = 0 ) {
1999-11-16 01:11:10 +03:00
nwritten = 0 ;
2005-07-08 08:51:27 +04:00
} else {
2000-03-10 00:45:16 +03:00
nwritten = write_to_pipe ( p , data , numtowrite ) ;
2005-07-08 08:51:27 +04:00
}
1999-11-16 01:11:10 +03:00
2005-07-08 08:51:27 +04:00
if ( ( nwritten = = 0 & & numtowrite ! = 0 ) | | ( nwritten < 0 ) ) {
2007-08-14 22:16:04 +04:00
reply_unixerror ( req , ERRDOS , ERRnoaccess ) ;
return ;
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-12-13 16:27:58 +03:00
2005-07-08 08:51:27 +04:00
DEBUG ( 3 , ( " write-IPC pnum=%04x nwritten=%d \n " , p - > pnum , nwritten ) ) ;
1999-11-16 01:11:10 +03:00
2007-08-14 22:16:04 +04:00
return ;
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
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
{
2007-08-08 22:40:26 +04:00
smb_np_struct * p = get_rpc_pipe_p ( SVAL ( req - > inbuf , smb_vwv2 ) ) ;
size_t numtowrite = SVAL ( req - > inbuf , smb_vwv10 ) ;
1998-10-07 19:22:49 +04:00
int nwritten = - 1 ;
2007-08-08 22:40:26 +04:00
int smb_doff = SVAL ( req - > inbuf , smb_vwv11 ) ;
BOOL pipe_start_message_raw =
( ( SVAL ( req - > inbuf , smb_vwv7 )
& ( PIPE_START_MESSAGE | PIPE_RAW_MODE ) )
= = ( PIPE_START_MESSAGE | PIPE_RAW_MODE ) ) ;
1998-10-07 19:22:49 +04:00
char * data ;
2005-07-08 08:51:27 +04:00
if ( ! p ) {
2007-08-08 22:40:26 +04:00
reply_doserror ( req , ERRDOS , ERRbadfid ) ;
return ;
2005-07-08 08:51:27 +04:00
}
1998-10-07 19:22:49 +04:00
2007-08-08 22:40:26 +04:00
if ( p - > vuid ! = req - > vuid ) {
reply_nterror ( req , NT_STATUS_INVALID_HANDLE ) ;
return ;
2006-05-28 01:38:54 +04:00
}
2007-08-08 22:40:26 +04:00
data = smb_base ( req - > inbuf ) + smb_doff ;
1998-10-07 19:22:49 +04:00
2005-07-08 08:51:27 +04:00
if ( numtowrite = = 0 ) {
1998-10-07 19:22:49 +04:00
nwritten = 0 ;
2005-07-08 08:51:27 +04:00
} else {
2000-03-10 00:45:16 +03:00
if ( pipe_start_message_raw ) {
/*
* For the start of a message in named pipe byte mode ,
* the first two bytes are a length - of - pdu field . Ignore
2005-07-08 08:51:27 +04:00
* them ( we don ' t trust the client ) . JRA .
2000-03-10 00:45:16 +03:00
*/
2005-07-08 08:51:27 +04:00
if ( numtowrite < 2 ) {
2007-08-08 22:40:26 +04:00
DEBUG ( 0 , ( " reply_pipe_write_and_X: start of "
" message set and not enough data "
" sent.(%u) \n " ,
( unsigned int ) numtowrite ) ) ;
reply_unixerror ( req , ERRDOS , ERRnoaccess ) ;
return ;
2000-03-10 00:45:16 +03:00
}
data + = 2 ;
numtowrite - = 2 ;
2005-07-08 08:51:27 +04:00
}
1999-12-13 16:27:58 +03:00
nwritten = write_to_pipe ( p , data , numtowrite ) ;
2000-03-10 00:45:16 +03:00
}
1998-10-07 19:22:49 +04:00
2005-07-08 08:51:27 +04:00
if ( ( nwritten = = 0 & & numtowrite ! = 0 ) | | ( nwritten < 0 ) ) {
2007-08-08 22:40:26 +04:00
reply_unixerror ( req , ERRDOS , ERRnoaccess ) ;
return ;
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
2000-03-10 00:45:16 +03:00
nwritten = ( 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
2005-07-08 08:51:27 +04:00
DEBUG ( 3 , ( " writeX-IPC pnum=%04x nwritten=%d \n " , p - > pnum , nwritten ) ) ;
1998-10-07 19:22:49 +04:00
2007-08-27 16:04:09 +04:00
chain_reply ( 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
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
{
2007-08-11 14:53:36 +04:00
smb_np_struct * p = get_rpc_pipe_p ( SVAL ( req - > inbuf , smb_vwv2 ) ) ;
int smb_maxcnt = SVAL ( req - > inbuf , smb_vwv5 ) ;
int smb_mincnt = SVAL ( req - > inbuf , smb_vwv6 ) ;
1998-08-17 07:06:20 +04:00
int nread = - 1 ;
char * data ;
2002-01-20 05:40:05 +03:00
BOOL unused ;
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
2007-08-11 14:53:36 +04:00
uint32 smb_offs = IVAL ( req - > inbuf , smb_vwv3 ) ;
1999-12-13 16:27:58 +03:00
# endif
1996-08-15 19:11:34 +04:00
2005-07-08 08:51:27 +04:00
if ( ! p ) {
2007-08-11 14:53:36 +04:00
reply_doserror ( req , ERRDOS , ERRbadfid ) ;
return ;
2005-07-08 08:51:27 +04:00
}
1998-09-01 05:10:01 +04:00
2007-08-11 14:53:36 +04:00
reply_outbuf ( req , 12 , smb_maxcnt ) ;
data = smb_buf ( req - > outbuf ) ;
1996-08-15 19:11:34 +04:00
2002-01-20 05:40:05 +03:00
nread = read_from_pipe ( p , data , smb_maxcnt , & unused ) ;
1996-08-15 19:11:34 +04:00
2005-07-08 08:51:27 +04:00
if ( nread < 0 ) {
2007-08-11 14:53:36 +04:00
reply_doserror ( req , ERRDOS , ERRnoaccess ) ;
return ;
2005-07-08 08:51:27 +04:00
}
2007-08-11 14:53:36 +04:00
set_message ( NULL , ( char * ) req - > outbuf , 12 , nread , False ) ;
1998-03-12 00:11:04 +03:00
2007-08-11 14:53:36 +04:00
SSVAL ( req - > outbuf , smb_vwv5 , nread ) ;
SSVAL ( req - > outbuf , smb_vwv6 , smb_offset ( data , req - > outbuf ) ) ;
SSVAL ( smb_buf ( req - > outbuf ) , - 2 , nread ) ;
1998-03-12 00:11:04 +03:00
1998-10-07 19:22:49 +04:00
DEBUG ( 3 , ( " readX-IPC pnum=%04x min=%d max=%d nread=%d \n " ,
1998-08-17 07:06:20 +04:00
p - > pnum , smb_mincnt , smb_maxcnt , nread ) ) ;
1996-08-15 19:11:34 +04:00
2007-08-27 16:04:09 +04:00
chain_reply ( req ) ;
1996-08-15 19:11:34 +04:00
}
1998-10-07 19:22:49 +04:00
1998-03-12 00:11:04 +03:00
/****************************************************************************
2005-07-08 08:51:27 +04:00
Reply to a close .
1998-03-12 00:11:04 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-07-08 08:51:27 +04:00
2007-07-23 13:53:06 +04:00
void reply_pipe_close ( connection_struct * conn , struct smb_request * req )
1996-08-15 19:11:34 +04:00
{
2007-07-31 17:14:07 +04:00
smb_np_struct * p = get_rpc_pipe_p ( SVAL ( req - > inbuf , smb_vwv0 ) ) ;
1996-08-15 19:11:34 +04:00
2005-07-08 08:51:27 +04:00
if ( ! p ) {
2007-07-23 13:53:06 +04:00
reply_doserror ( req , ERRDOS , ERRbadfid ) ;
return ;
2005-07-08 08:51:27 +04:00
}
1998-09-01 05:10:01 +04:00
1998-08-17 07:06:20 +04:00
DEBUG ( 5 , ( " reply_pipe_close: pnum:%x \n " , p - > pnum ) ) ;
1996-08-15 19:11:34 +04:00
2005-07-08 08:51:27 +04:00
if ( ! close_rpc_pipe_hnd ( p ) ) {
2007-07-23 13:53:06 +04:00
reply_doserror ( req , ERRDOS , ERRbadfid ) ;
return ;
2005-07-08 08:51:27 +04:00
}
2006-07-11 22:01:26 +04:00
/* TODO: REMOVE PIPE FROM DB */
1996-08-15 19:11:34 +04:00
2007-07-23 13:53:06 +04:00
reply_outbuf ( req , 0 , 0 ) ;
return ;
1996-08-15 19:11:34 +04:00
}