1996-08-15 19:11:34 +04:00
/*
Unix SMB / Netbios implementation .
Version 1.9 .
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.
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
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
/*
This file handles reply_ calls on named pipes that the server
makes to handle specific protocols
*/
# include "includes.h"
# include "trans2.h"
# define PIPE "\\PIPE\\"
# define PIPELEN strlen(PIPE)
extern int DEBUGLEVEL ;
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
/****************************************************************************
reply to an open and X on a named pipe
1996-08-15 19:11:34 +04:00
This code is basically stolen from reply_open_and_X with some
wrinkles to handle pipes .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-14 21:38:29 +04:00
int reply_open_pipe_and_X ( connection_struct * conn ,
char * inbuf , char * outbuf , int length , int bufsize )
1996-08-15 19:11:34 +04:00
{
1998-08-17 07:06:20 +04:00
pstring fname ;
uint16 vuid = SVAL ( inbuf , smb_uid ) ;
pipes_struct * p ;
int smb_ofun = SVAL ( inbuf , smb_vwv8 ) ;
int size = 0 , fmode = 0 , mtime = 0 , rmode = 0 ;
int i ;
/* XXXX we need to handle passed times, sattr and flags */
pstrcpy ( fname , smb_buf ( inbuf ) ) ;
/* 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. */
if ( strncmp ( fname , PIPE , PIPELEN ) ! = 0 )
return ( ERROR ( ERRSRV , ERRaccess ) ) ;
DEBUG ( 4 , ( " Opening pipe %s. \n " , fname ) ) ;
/* See if it is one we want to handle. */
for ( i = 0 ; pipe_names [ i ] . client_pipe ; i + + )
if ( strequal ( fname , pipe_names [ i ] . client_pipe ) )
break ;
if ( pipe_names [ i ] . client_pipe = = NULL )
return ( ERROR ( ERRSRV , ERRaccess ) ) ;
/* Strip \PIPE\ off the name. */
pstrcpy ( fname , smb_buf ( inbuf ) + PIPELEN ) ;
1999-12-13 16:27:58 +03:00
/*
* Hack for NT printers . . . JRA .
*/
if ( should_fail_next_srvsvc_open ( fname ) )
return ( ERROR ( ERRSRV , ERRaccess ) ) ;
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 ) ) ;
1999-12-13 16:27:58 +03:00
smb_ofun | = FILE_CREATE_IF_NOT_EXIST ;
1998-08-17 07:06:20 +04:00
p = open_rpc_pipe_p ( fname , conn , vuid ) ;
if ( ! p ) return ( ERROR ( ERRSRV , ERRnofids ) ) ;
/* Prepare the reply */
set_message ( outbuf , 15 , 0 , True ) ;
/* Mark the opened file as an existing named pipe in message mode. */
SSVAL ( outbuf , smb_vwv9 , 2 ) ;
SSVAL ( outbuf , smb_vwv10 , 0xc700 ) ;
if ( rmode = = 2 ) {
DEBUG ( 4 , ( " Resetting open result to open from create. \n " ) ) ;
rmode = 1 ;
}
SSVAL ( outbuf , smb_vwv2 , p - > pnum ) ;
SSVAL ( outbuf , smb_vwv3 , fmode ) ;
put_dos_date3 ( outbuf , smb_vwv4 , mtime ) ;
SIVAL ( outbuf , smb_vwv6 , size ) ;
SSVAL ( outbuf , smb_vwv8 , rmode ) ;
1998-10-09 23:05:19 +04:00
SSVAL ( outbuf , smb_vwv11 , 0x0001 ) ;
1998-08-17 07:06:20 +04:00
return chain_reply ( inbuf , outbuf , length , bufsize ) ;
1996-08-15 19:11:34 +04:00
}
1999-11-16 01:11:10 +03:00
/****************************************************************************
1999-12-13 16:27:58 +03:00
reply to a write on a pipe
1999-11-16 01:11:10 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
int reply_pipe_write ( char * inbuf , char * outbuf , int length , int dum_bufsize )
1999-11-16 01:11:10 +03:00
{
pipes_struct * p = get_rpc_pipe_p ( inbuf , smb_vwv0 ) ;
size_t numtowrite = SVAL ( inbuf , smb_vwv1 ) ;
1999-12-13 16:27:58 +03:00
int nwritten ;
int outsize ;
1999-11-16 01:11:10 +03:00
char * data ;
1999-12-13 16:27:58 +03:00
if ( ! p )
return ( ERROR ( ERRDOS , ERRbadfid ) ) ;
1999-11-16 01:11:10 +03:00
data = smb_buf ( inbuf ) + 3 ;
if ( numtowrite = = 0 )
nwritten = 0 ;
else
2000-03-10 00:45:16 +03:00
nwritten = write_to_pipe ( p , data , numtowrite ) ;
1999-11-16 01:11:10 +03:00
if ( ( nwritten = = 0 & & numtowrite ! = 0 ) | | ( nwritten < 0 ) )
return ( UNIXERROR ( ERRDOS , ERRnoaccess ) ) ;
outsize = set_message ( outbuf , 1 , 0 , True ) ;
SSVAL ( outbuf , smb_vwv0 , nwritten ) ;
1999-12-13 16:27:58 +03:00
1999-11-16 01:11:10 +03:00
DEBUG ( 3 , ( " write-IPC pnum=%04x nwritten=%d \n " ,
p - > pnum , nwritten ) ) ;
1999-12-13 16:27:58 +03:00
return ( outsize ) ;
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
1998-10-07 19:22:49 +04:00
int reply_pipe_write_and_X ( char * inbuf , char * outbuf , int length , int bufsize )
{
pipes_struct * p = get_rpc_pipe_p ( inbuf , smb_vwv2 ) ;
size_t numtowrite = SVAL ( inbuf , smb_vwv10 ) ;
int nwritten = - 1 ;
int smb_doff = SVAL ( inbuf , smb_vwv11 ) ;
2000-03-11 04:28:57 +03:00
BOOL pipe_start_message_raw = ( ( SVAL ( 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 ;
1999-12-13 16:27:58 +03:00
if ( ! p )
return ( ERROR ( ERRDOS , ERRbadfid ) ) ;
1998-10-07 19:22:49 +04:00
1998-10-08 01:42:24 +04:00
data = smb_base ( inbuf ) + smb_doff ;
1998-10-07 19:22:49 +04:00
if ( numtowrite = = 0 )
nwritten = 0 ;
2000-03-10 00:45:16 +03:00
else {
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
* them ( we don ' t trust the client . JRA .
*/
if ( numtowrite < 2 ) {
DEBUG ( 0 , ( " reply_pipe_write_and_X: start of message set and not enough data sent.(%u) \n " ,
( unsigned int ) numtowrite ) ) ;
return ( UNIXERROR ( ERRDOS , ERRnoaccess ) ) ;
}
data + = 2 ;
numtowrite - = 2 ;
}
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
if ( ( nwritten = = 0 & & numtowrite ! = 0 ) | | ( nwritten < 0 ) )
return ( UNIXERROR ( ERRDOS , ERRnoaccess ) ) ;
set_message ( outbuf , 6 , 0 , True ) ;
2000-03-10 00:45:16 +03:00
nwritten = ( pipe_start_message_raw ? nwritten + 2 : nwritten ) ;
1998-10-07 19:22:49 +04:00
SSVAL ( outbuf , smb_vwv2 , nwritten ) ;
DEBUG ( 3 , ( " writeX-IPC pnum=%04x nwritten=%d \n " ,
p - > pnum , nwritten ) ) ;
return chain_reply ( inbuf , outbuf , length , bufsize ) ;
}
1997-10-30 04:05:13 +03:00
/****************************************************************************
1998-03-12 00:11:04 +03:00
reply to a read and X
1996-08-15 19:11:34 +04:00
1998-03-12 00:11:04 +03:00
This code is basically stolen from reply_read_and_X with some
wrinkles to handle pipes .
1996-08-15 19:11:34 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-03-12 00:11:04 +03:00
int reply_pipe_read_and_X ( char * inbuf , char * outbuf , int length , int bufsize )
1996-08-15 19:11:34 +04:00
{
1998-08-17 07:06:20 +04:00
pipes_struct * p = get_rpc_pipe_p ( inbuf , smb_vwv2 ) ;
int smb_maxcnt = SVAL ( inbuf , smb_vwv5 ) ;
int smb_mincnt = SVAL ( inbuf , smb_vwv6 ) ;
int nread = - 1 ;
char * data ;
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
uint32 smb_offs = IVAL ( inbuf , smb_vwv3 ) ;
# endif
1996-08-15 19:11:34 +04:00
1999-12-13 16:27:58 +03:00
if ( ! p )
return ( ERROR ( ERRDOS , ERRbadfid ) ) ;
1998-09-01 05:10:01 +04:00
1998-08-17 07:06:20 +04:00
set_message ( outbuf , 12 , 0 , True ) ;
data = smb_buf ( outbuf ) ;
1996-08-15 19:11:34 +04:00
2000-03-10 00:45:16 +03:00
nread = read_from_pipe ( p , data , smb_maxcnt ) ;
1996-08-15 19:11:34 +04:00
1998-08-17 07:06:20 +04:00
if ( nread < 0 )
return ( UNIXERROR ( ERRDOS , ERRnoaccess ) ) ;
1998-03-12 00:11:04 +03:00
1998-08-17 07:06:20 +04:00
SSVAL ( outbuf , smb_vwv5 , nread ) ;
SSVAL ( outbuf , smb_vwv6 , smb_offset ( data , outbuf ) ) ;
SSVAL ( smb_buf ( 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
1998-08-17 07:06:20 +04:00
return chain_reply ( inbuf , outbuf , length , bufsize ) ;
1996-08-15 19:11:34 +04:00
}
1998-10-07 19:22:49 +04:00
1998-03-12 00:11:04 +03:00
/****************************************************************************
reply to a close
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-14 21:38:29 +04:00
int reply_pipe_close ( connection_struct * conn , char * inbuf , char * outbuf )
1996-08-15 19:11:34 +04:00
{
1998-08-17 07:06:20 +04:00
pipes_struct * p = get_rpc_pipe_p ( inbuf , smb_vwv0 ) ;
int outsize = set_message ( outbuf , 0 , 0 , True ) ;
1996-08-15 19:11:34 +04:00
1999-12-13 16:27:58 +03:00
if ( ! p )
return ( ERROR ( ERRDOS , ERRbadfid ) ) ;
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
1999-12-13 16:27:58 +03:00
if ( ! close_rpc_pipe_hnd ( p , conn ) )
return ( ERROR ( ERRDOS , ERRbadfid ) ) ;
1996-08-15 19:11:34 +04:00
1998-08-17 07:06:20 +04:00
return ( outsize ) ;
1996-08-15 19:11:34 +04:00
}