1996-08-15 15:11:34 +00:00
/*
2002-01-30 06:08:46 +00:00
Unix SMB / CIFS implementation .
1996-08-15 15:11:34 +00:00
Pipe SMB reply routines
1998-01-22 13:27:43 +00:00
Copyright ( C ) Andrew Tridgell 1992 - 1998
Copyright ( C ) Luke Kenneth Casson Leighton 1996 - 1998
Copyright ( C ) Paul Ashton 1997 - 1998.
2005-07-08 04:51:27 +00:00
Copyright ( C ) Jeremy Allison 2005.
1996-08-15 15:11:34 +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
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"
# define PIPE "\\PIPE\\"
# define PIPELEN strlen(PIPE)
2006-07-11 18:01:26 +00:00
# define MAX_PIPE_NAME_LEN 24
/* PIPE/<name>/<pid>/<pnum> */
# define PIPEDB_KEY_FORMAT "PIPE / %s / %u / %d"
struct pipe_dbrec {
struct process_id pid ;
int pnum ;
uid_t uid ;
char name [ MAX_PIPE_NAME_LEN ] ;
fstring user ;
} ;
1998-03-11 21:11:04 +00:00
extern struct pipe_id_info pipe_names [ ] ;
1996-08-15 15:11:34 +00:00
1997-10-30 01:05:13 +00:00
/****************************************************************************
2005-07-08 04:51:27 +00: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 15:11:34 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-07-08 04:51:27 +00:00
1998-08-14 17:38:29 +00:00
int reply_open_pipe_and_X ( connection_struct * conn ,
char * inbuf , char * outbuf , int length , int bufsize )
1996-08-15 15:11:34 +00:00
{
1998-08-17 03:06:20 +00:00
pstring fname ;
2001-07-04 21:57:03 +00:00
pstring pipe_name ;
1998-08-17 03:06:20 +00:00
uint16 vuid = SVAL ( inbuf , smb_uid ) ;
2002-01-20 02:40:05 +00:00
smb_np_struct * p ;
1998-08-17 03:06:20 +00:00
int size = 0 , fmode = 0 , mtime = 0 , rmode = 0 ;
int i ;
/* XXXX we need to handle passed times, sattr and flags */
2002-07-15 10:35:28 +00:00
srvstr_pull_buf ( inbuf , pipe_name , smb_buf ( inbuf ) , sizeof ( pipe_name ) , STR_TERMINATE ) ;
1998-08-17 03:06:20 +00: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 04:51:27 +00:00
if ( strncmp ( pipe_name , PIPE , PIPELEN ) ! = 0 ) {
2001-08-27 08:19:43 +00:00
return ( ERROR_DOS ( ERRSRV , ERRaccess ) ) ;
2005-07-08 04:51:27 +00:00
}
1998-08-17 03:06:20 +00:00
2001-07-04 21:57:03 +00:00
DEBUG ( 4 , ( " Opening pipe %s. \n " , pipe_name ) ) ;
1998-08-17 03:06:20 +00:00
/* See if it is one we want to handle. */
2005-07-08 04:51:27 +00:00
for ( i = 0 ; pipe_names [ i ] . client_pipe ; i + + ) {
if ( strequal ( pipe_name , pipe_names [ i ] . client_pipe ) ) {
1998-08-17 03:06:20 +00:00
break ;
2005-07-08 04:51:27 +00:00
}
}
1998-08-17 03:06:20 +00:00
2005-07-08 04:51:27 +00:00
if ( pipe_names [ i ] . client_pipe = = NULL ) {
2001-12-18 02:09:57 +00:00
return ( ERROR_BOTH ( NT_STATUS_OBJECT_NAME_NOT_FOUND , ERRDOS , ERRbadpipe ) ) ;
2005-07-08 04:51:27 +00:00
}
1998-08-17 03:06:20 +00:00
/* Strip \PIPE\ off the name. */
2001-07-04 21:57:03 +00:00
pstrcpy ( fname , pipe_name + PIPELEN ) ;
2000-06-07 01:49:23 +00:00
#if 0
1999-12-13 13:27:58 +00:00
/*
* Hack for NT printers . . . JRA .
*/
if ( should_fail_next_srvsvc_open ( fname ) )
return ( ERROR ( ERRSRV , ERRaccess ) ) ;
2000-06-07 01:49:23 +00:00
# endif
1999-12-13 13:27:58 +00:00
1998-08-17 03:06:20 +00: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 ) ) ;
p = open_rpc_pipe_p ( fname , conn , vuid ) ;
2005-07-08 04:51:27 +00:00
if ( ! p ) {
return ( ERROR_DOS ( ERRSRV , ERRnofids ) ) ;
}
1998-08-17 03:06:20 +00:00
/* 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 ) ;
2005-11-05 04:21:55 +00:00
srv_put_dos_date3 ( outbuf , smb_vwv4 , mtime ) ;
1998-08-17 03:06:20 +00:00
SIVAL ( outbuf , smb_vwv6 , size ) ;
SSVAL ( outbuf , smb_vwv8 , rmode ) ;
1998-10-09 19:05:19 +00:00
SSVAL ( outbuf , smb_vwv11 , 0x0001 ) ;
1998-08-17 03:06:20 +00:00
return chain_reply ( inbuf , outbuf , length , bufsize ) ;
1996-08-15 15:11:34 +00:00
}
1999-11-15 22:11:10 +00:00
/****************************************************************************
2005-07-08 04:51:27 +00:00
Reply to a write on a pipe .
1999-11-15 22:11:10 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-07-08 04:51:27 +00:00
1999-12-13 13:27:58 +00:00
int reply_pipe_write ( char * inbuf , char * outbuf , int length , int dum_bufsize )
1999-11-15 22:11:10 +00:00
{
2002-01-20 02:40:05 +00:00
smb_np_struct * p = get_rpc_pipe_p ( inbuf , smb_vwv0 ) ;
2006-05-27 21:38:54 +00:00
uint16 vuid = SVAL ( inbuf , smb_uid ) ;
1999-11-15 22:11:10 +00:00
size_t numtowrite = SVAL ( inbuf , smb_vwv1 ) ;
1999-12-13 13:27:58 +00:00
int nwritten ;
int outsize ;
1999-11-15 22:11:10 +00:00
char * data ;
2005-07-08 04:51:27 +00:00
if ( ! p ) {
2001-08-27 08:19:43 +00:00
return ( ERROR_DOS ( ERRDOS , ERRbadfid ) ) ;
2005-07-08 04:51:27 +00:00
}
1999-11-15 22:11:10 +00:00
2006-05-27 21:38:54 +00:00
if ( p - > vuid ! = vuid ) {
return ERROR_NT ( NT_STATUS_INVALID_HANDLE ) ;
}
1999-11-15 22:11:10 +00:00
data = smb_buf ( inbuf ) + 3 ;
2005-07-08 04:51:27 +00:00
if ( numtowrite = = 0 ) {
1999-11-15 22:11:10 +00:00
nwritten = 0 ;
2005-07-08 04:51:27 +00:00
} else {
2000-03-09 21:45:16 +00:00
nwritten = write_to_pipe ( p , data , numtowrite ) ;
2005-07-08 04:51:27 +00:00
}
1999-11-15 22:11:10 +00:00
2005-07-08 04:51:27 +00:00
if ( ( nwritten = = 0 & & numtowrite ! = 0 ) | | ( nwritten < 0 ) ) {
1999-11-15 22:11:10 +00:00
return ( UNIXERROR ( ERRDOS , ERRnoaccess ) ) ;
2005-07-08 04:51:27 +00:00
}
1999-11-15 22:11:10 +00:00
outsize = set_message ( outbuf , 1 , 0 , True ) ;
SSVAL ( outbuf , smb_vwv0 , nwritten ) ;
1999-12-13 13:27:58 +00:00
2005-07-08 04:51:27 +00:00
DEBUG ( 3 , ( " write-IPC pnum=%04x nwritten=%d \n " , p - > pnum , nwritten ) ) ;
1999-11-15 22:11:10 +00:00
1999-12-13 13:27:58 +00:00
return ( outsize ) ;
1999-11-15 22:11:10 +00:00
}
1996-08-15 15:11:34 +00:00
1998-10-07 15:22:49 +00:00
/****************************************************************************
2000-03-09 21:45:16 +00:00
Reply to a write and X .
1998-10-07 15:22:49 +00:00
2000-03-09 21:45:16 +00:00
This code is basically stolen from reply_write_and_X with some
wrinkles to handle pipes .
1998-10-07 15:22:49 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-03-09 21:45:16 +00:00
1998-10-07 15:22:49 +00:00
int reply_pipe_write_and_X ( char * inbuf , char * outbuf , int length , int bufsize )
{
2002-01-20 02:40:05 +00:00
smb_np_struct * p = get_rpc_pipe_p ( inbuf , smb_vwv2 ) ;
2006-05-27 21:38:54 +00:00
uint16 vuid = SVAL ( inbuf , smb_uid ) ;
1998-10-07 15:22:49 +00:00
size_t numtowrite = SVAL ( inbuf , smb_vwv10 ) ;
int nwritten = - 1 ;
int smb_doff = SVAL ( inbuf , smb_vwv11 ) ;
2000-03-11 01:28:57 +00:00
BOOL pipe_start_message_raw = ( ( SVAL ( inbuf , smb_vwv7 ) & ( PIPE_START_MESSAGE | PIPE_RAW_MODE ) ) = =
2005-07-08 04:51:27 +00:00
( PIPE_START_MESSAGE | PIPE_RAW_MODE ) ) ;
1998-10-07 15:22:49 +00:00
char * data ;
2005-07-08 04:51:27 +00:00
if ( ! p ) {
2001-08-27 08:19:43 +00:00
return ( ERROR_DOS ( ERRDOS , ERRbadfid ) ) ;
2005-07-08 04:51:27 +00:00
}
1998-10-07 15:22:49 +00:00
2006-05-27 21:38:54 +00:00
if ( p - > vuid ! = vuid ) {
return ERROR_NT ( NT_STATUS_INVALID_HANDLE ) ;
}
1998-10-07 21:42:24 +00:00
data = smb_base ( inbuf ) + smb_doff ;
1998-10-07 15:22:49 +00:00
2005-07-08 04:51:27 +00:00
if ( numtowrite = = 0 ) {
1998-10-07 15:22:49 +00:00
nwritten = 0 ;
2005-07-08 04:51:27 +00:00
} else {
2000-03-09 21:45:16 +00: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 04:51:27 +00:00
* them ( we don ' t trust the client ) . JRA .
2000-03-09 21:45:16 +00:00
*/
2005-07-08 04:51:27 +00:00
if ( numtowrite < 2 ) {
2000-03-09 21:45:16 +00:00
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 ;
2005-07-08 04:51:27 +00:00
}
1999-12-13 13:27:58 +00:00
nwritten = write_to_pipe ( p , data , numtowrite ) ;
2000-03-09 21:45:16 +00:00
}
1998-10-07 15:22:49 +00:00
2005-07-08 04:51:27 +00:00
if ( ( nwritten = = 0 & & numtowrite ! = 0 ) | | ( nwritten < 0 ) ) {
1998-10-07 15:22:49 +00:00
return ( UNIXERROR ( ERRDOS , ERRnoaccess ) ) ;
2005-07-08 04:51:27 +00:00
}
1998-10-07 15:22:49 +00:00
set_message ( outbuf , 6 , 0 , True ) ;
2000-03-09 21:45:16 +00:00
nwritten = ( pipe_start_message_raw ? nwritten + 2 : nwritten ) ;
1998-10-07 15:22:49 +00:00
SSVAL ( outbuf , smb_vwv2 , nwritten ) ;
2005-07-08 04:51:27 +00:00
DEBUG ( 3 , ( " writeX-IPC pnum=%04x nwritten=%d \n " , p - > pnum , nwritten ) ) ;
1998-10-07 15:22:49 +00:00
return chain_reply ( inbuf , outbuf , length , bufsize ) ;
}
1997-10-30 01:05:13 +00:00
/****************************************************************************
2005-07-08 04:51:27 +00: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 15:11:34 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-07-08 04:51:27 +00:00
1998-03-11 21:11:04 +00:00
int reply_pipe_read_and_X ( char * inbuf , char * outbuf , int length , int bufsize )
1996-08-15 15:11:34 +00:00
{
2002-01-20 02:40:05 +00:00
smb_np_struct * p = get_rpc_pipe_p ( inbuf , smb_vwv2 ) ;
1998-08-17 03:06:20 +00:00
int smb_maxcnt = SVAL ( inbuf , smb_vwv5 ) ;
int smb_mincnt = SVAL ( inbuf , smb_vwv6 ) ;
int nread = - 1 ;
char * data ;
2002-01-20 02:40:05 +00:00
BOOL unused ;
1999-12-13 13:27:58 +00: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 15:11:34 +00:00
2005-07-08 04:51:27 +00:00
if ( ! p ) {
2001-08-27 08:19:43 +00:00
return ( ERROR_DOS ( ERRDOS , ERRbadfid ) ) ;
2005-07-08 04:51:27 +00:00
}
1998-09-01 01:10:01 +00:00
1998-08-17 03:06:20 +00:00
set_message ( outbuf , 12 , 0 , True ) ;
data = smb_buf ( outbuf ) ;
1996-08-15 15:11:34 +00:00
2002-01-20 02:40:05 +00:00
nread = read_from_pipe ( p , data , smb_maxcnt , & unused ) ;
1996-08-15 15:11:34 +00:00
2005-07-08 04:51:27 +00:00
if ( nread < 0 ) {
1998-08-17 03:06:20 +00:00
return ( UNIXERROR ( ERRDOS , ERRnoaccess ) ) ;
2005-07-08 04:51:27 +00:00
}
1998-03-11 21:11:04 +00:00
1998-08-17 03:06:20 +00:00
SSVAL ( outbuf , smb_vwv5 , nread ) ;
SSVAL ( outbuf , smb_vwv6 , smb_offset ( data , outbuf ) ) ;
SSVAL ( smb_buf ( outbuf ) , - 2 , nread ) ;
1998-03-11 21:11:04 +00:00
1998-10-07 15:22:49 +00:00
DEBUG ( 3 , ( " readX-IPC pnum=%04x min=%d max=%d nread=%d \n " ,
1998-08-17 03:06:20 +00:00
p - > pnum , smb_mincnt , smb_maxcnt , nread ) ) ;
1996-08-15 15:11:34 +00:00
2004-12-21 23:14:20 +00:00
/* Ensure we set up the message length to include the data length read. */
set_message_bcc ( outbuf , nread ) ;
1998-08-17 03:06:20 +00:00
return chain_reply ( inbuf , outbuf , length , bufsize ) ;
1996-08-15 15:11:34 +00:00
}
1998-10-07 15:22:49 +00:00
1998-03-11 21:11:04 +00:00
/****************************************************************************
2005-07-08 04:51:27 +00:00
Reply to a close .
1998-03-11 21:11:04 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-07-08 04:51:27 +00:00
1998-08-14 17:38:29 +00:00
int reply_pipe_close ( connection_struct * conn , char * inbuf , char * outbuf )
1996-08-15 15:11:34 +00:00
{
2002-01-20 02:40:05 +00:00
smb_np_struct * p = get_rpc_pipe_p ( inbuf , smb_vwv0 ) ;
1998-08-17 03:06:20 +00:00
int outsize = set_message ( outbuf , 0 , 0 , True ) ;
1996-08-15 15:11:34 +00:00
2005-07-08 04:51:27 +00:00
if ( ! p ) {
2001-08-27 08:19:43 +00:00
return ( ERROR_DOS ( ERRDOS , ERRbadfid ) ) ;
2005-07-08 04:51:27 +00:00
}
1998-09-01 01:10:01 +00:00
1998-08-17 03:06:20 +00:00
DEBUG ( 5 , ( " reply_pipe_close: pnum:%x \n " , p - > pnum ) ) ;
1996-08-15 15:11:34 +00:00
2005-07-08 04:51:27 +00:00
if ( ! close_rpc_pipe_hnd ( p ) ) {
2001-08-27 08:19:43 +00:00
return ERROR_DOS ( ERRDOS , ERRbadfid ) ;
2005-07-08 04:51:27 +00:00
}
2006-07-11 18:01:26 +00:00
/* TODO: REMOVE PIPE FROM DB */
1996-08-15 15:11:34 +00:00
1998-08-17 03:06:20 +00:00
return ( outsize ) ;
1996-08-15 15:11:34 +00:00
}