1998-03-12 00:11:04 +03:00
/*
* Unix SMB / Netbios implementation .
* Version 1.9 .
* RPC Pipe client / server routines
1998-10-20 22:27:49 +04:00
* Copyright ( C ) Andrew Tridgell 1992 - 1998 ,
* Copyright ( C ) Luke Kenneth Casson Leighton 1996 - 1998 ,
1998-03-12 00:11:04 +03: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 .
*/
# include "includes.h"
# define PIPE "\\PIPE\\"
# define PIPELEN strlen(PIPE)
extern int DEBUGLEVEL ;
1998-08-17 07:06:20 +04:00
static pipes_struct * chain_p ;
static int pipes_open ;
1998-03-12 00:11:04 +03:00
# ifndef MAX_OPEN_PIPES
1998-08-17 07:06:20 +04:00
# define MAX_OPEN_PIPES 64
1998-03-12 00:11:04 +03:00
# endif
1998-08-17 07:06:20 +04:00
static pipes_struct * Pipes ;
static struct bitmap * bmap ;
1998-03-12 00:11:04 +03:00
1998-09-30 05:49:24 +04:00
/* this must be larger than the sum of the open files and directories */
static int pipe_handle_offset ;
/****************************************************************************
Set the pipe_handle_offset . Called from smbd / files . c
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void set_pipe_handle_offset ( int max_open_files )
{
if ( max_open_files < 0x7000 )
pipe_handle_offset = 0x7000 ;
else
pipe_handle_offset = max_open_files + 10 ; /* For safety. :-) */
}
1998-03-12 00:11:04 +03:00
/****************************************************************************
reset pipe chain handle number
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-17 07:06:20 +04:00
void reset_chain_p ( void )
1998-03-12 00:11:04 +03:00
{
1998-08-17 07:06:20 +04:00
chain_p = NULL ;
1998-03-12 00:11:04 +03:00
}
/****************************************************************************
initialise pipe handle states . . .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void init_rpc_pipe_hnd ( void )
{
1998-08-17 07:06:20 +04:00
bmap = bitmap_allocate ( MAX_OPEN_PIPES ) ;
if ( ! bmap ) {
exit_server ( " out of memory in init_rpc_pipe_hnd \n " ) ;
1998-03-12 00:11:04 +03:00
}
}
1998-08-17 07:06:20 +04:00
1998-03-12 00:11:04 +03:00
/****************************************************************************
find first available file slot
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-17 07:06:20 +04:00
pipes_struct * open_rpc_pipe_p ( char * pipe_name ,
connection_struct * conn , uint16 vuid )
1998-03-12 00:11:04 +03:00
{
int i ;
1998-08-17 07:06:20 +04:00
pipes_struct * p ;
static int next_pipe ;
1998-09-24 01:49:09 +04:00
DEBUG ( 4 , ( " Open pipe requested %s (pipes_open=%d) \n " ,
pipe_name , pipes_open ) ) ;
1998-08-17 07:06:20 +04:00
/* not repeating pipe numbers makes it easier to track things in
log files and prevents client bugs where pipe numbers are reused
over connection restarts */
if ( next_pipe = = 0 ) {
next_pipe = ( getpid ( ) ^ time ( NULL ) ) % MAX_OPEN_PIPES ;
1998-03-12 00:11:04 +03:00
}
1998-08-17 07:06:20 +04:00
i = bitmap_find ( bmap , next_pipe ) ;
if ( i = = - 1 ) {
DEBUG ( 0 , ( " ERROR! Out of pipe structures \n " ) ) ;
return NULL ;
}
next_pipe = ( i + 1 ) % MAX_OPEN_PIPES ;
1998-09-24 01:49:09 +04:00
for ( p = Pipes ; p ; p = p - > next )
{
DEBUG ( 5 , ( " open pipes: name %s pnum=%x \n " , p - > name , p - > pnum ) ) ;
}
1998-08-17 07:06:20 +04:00
p = ( pipes_struct * ) malloc ( sizeof ( * p ) ) ;
if ( ! p ) return NULL ;
1998-09-24 01:49:09 +04:00
ZERO_STRUCTP ( p ) ;
1998-08-17 10:47:53 +04:00
DLIST_ADD ( Pipes , p ) ;
1998-03-12 00:11:04 +03:00
1998-08-17 07:06:20 +04:00
bitmap_set ( bmap , i ) ;
1998-09-30 05:49:24 +04:00
i + = pipe_handle_offset ;
1998-08-17 07:06:20 +04:00
pipes_open + + ;
p - > pnum = i ;
p - > open = True ;
p - > device_state = 0 ;
1998-10-15 09:47:29 +04:00
p - > priority = 0 ;
1998-08-17 07:06:20 +04:00
p - > conn = conn ;
1998-09-30 00:24:17 +04:00
p - > vuid = vuid ;
1998-08-14 21:38:29 +04:00
1998-08-17 07:06:20 +04:00
p - > rhdr . data = NULL ;
p - > rdata . data = NULL ;
p - > rhdr . offset = 0 ;
p - > rdata . offset = 0 ;
1998-08-14 21:38:29 +04:00
1998-08-17 07:06:20 +04:00
p - > file_offset = 0 ;
1999-02-03 03:48:27 +03:00
p - > prev_pdu_file_offset = 0 ;
1998-08-17 07:06:20 +04:00
p - > hdr_offsets = 0 ;
p - > next_frag_start = 0 ;
1998-08-14 21:38:29 +04:00
1998-10-17 03:40:59 +04:00
p - > ntlmssp_validated = False ;
p - > ntlmssp_auth = False ;
1998-08-17 07:06:20 +04:00
fstrcpy ( p - > name , pipe_name ) ;
1998-08-14 21:38:29 +04:00
1998-08-17 07:06:20 +04:00
DEBUG ( 4 , ( " Opened pipe %s with handle %x (pipes_open=%d) \n " ,
pipe_name , i , pipes_open ) ) ;
1998-08-14 21:38:29 +04:00
1998-08-17 07:52:05 +04:00
chain_p = p ;
1998-08-14 21:38:29 +04:00
1998-09-24 01:49:09 +04:00
/* OVERWRITE p as a temp variable, to display all open pipes */
for ( p = Pipes ; p ; p = p - > next )
{
DEBUG ( 5 , ( " open pipes: name %s pnum=%x \n " , p - > name , p - > pnum ) ) ;
}
return chain_p ;
1998-03-12 00:11:04 +03:00
}
1998-08-17 07:06:20 +04:00
1998-10-07 19:22:49 +04:00
/****************************************************************************
writes data to a pipe .
1998-10-08 01:42:24 +04:00
SERIOUSLY ALPHA CODE !
1998-10-07 19:22:49 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-10-17 00:07:02 +04:00
ssize_t write_pipe ( pipes_struct * p , char * data , size_t n )
1998-10-07 19:22:49 +04:00
{
1998-10-08 01:42:24 +04:00
prs_struct pd ;
struct mem_buf data_buf ;
1998-10-07 19:22:49 +04:00
DEBUG ( 6 , ( " write_pipe: %x " , p - > pnum ) ) ;
DEBUG ( 6 , ( " name: %s open: %s len: %d " ,
p - > name , BOOLSTR ( p - > open ) , n ) ) ;
1998-10-08 01:42:24 +04:00
dump_data ( 50 , data , n ) ;
/* fake up a data buffer from the write_pipe data parameters */
1998-10-20 22:27:49 +04:00
mem_create ( & data_buf , data , 0 , n , 0 , False ) ;
1998-10-08 01:42:24 +04:00
data_buf . offset . start = 0 ;
data_buf . offset . end = n ;
/* fake up a parsing structure */
pd . data = & data_buf ;
pd . align = 4 ;
pd . io = True ;
pd . offset = 0 ;
1998-10-17 00:07:02 +04:00
return rpc_command ( p , & pd ) ? ( ( ssize_t ) n ) : - 1 ;
1998-10-07 19:22:49 +04:00
}
1998-03-12 00:11:04 +03:00
/****************************************************************************
reads data from a pipe .
headers are interspersed with the data at regular intervals . by the time
this function is called , the start of the data could possibly have been
1998-04-21 06:36:37 +04:00
read by an SMBtrans ( file_offset ! = 0 ) .
1998-03-12 00:11:04 +03:00
1998-10-20 22:27:49 +04:00
calling create_rpc_reply ( ) here is a fudge . the data should already
1998-03-12 00:11:04 +03:00
have been prepared into arrays of headers + data stream sections .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-17 07:06:20 +04:00
int read_pipe ( pipes_struct * p , char * data , uint32 pos , int n )
1998-03-12 00:11:04 +03:00
{
1998-08-17 07:06:20 +04:00
int num = 0 ;
int len = 0 ;
uint32 hdr_num = 0 ;
int data_hdr_pos ;
int data_pos ;
DEBUG ( 6 , ( " read_pipe: %x " , p - > pnum ) ) ;
DEBUG ( 6 , ( " name: %s open: %s pos: %d len: %d " ,
p - > name ,
BOOLSTR ( p - > open ) ,
pos , n ) ) ;
1998-10-09 03:57:46 +04:00
if ( ! p | | ! p - > open )
{
1998-08-17 07:06:20 +04:00
DEBUG ( 6 , ( " pipe not open \n " ) ) ;
return - 1 ;
1998-03-12 00:11:04 +03:00
}
1998-04-21 06:36:37 +04:00
1998-08-17 07:06:20 +04:00
if ( p - > rhdr . data = = NULL | | p - > rhdr . data - > data = = NULL | |
1998-10-09 03:57:46 +04:00
p - > rhdr . data - > data_used = = 0 )
{
1998-08-17 07:06:20 +04:00
return 0 ;
}
1998-04-10 22:21:16 +04:00
1998-08-17 07:06:20 +04:00
DEBUG ( 6 , ( " read_pipe: p: %p file_offset: %d file_pos: %d \n " ,
p , p - > file_offset , n ) ) ;
1999-02-03 03:48:27 +03:00
DEBUG ( 6 , ( " read_pipe: next_frag_start: %d \n " ,
p - > next_frag_start ) ) ;
1998-04-21 06:36:37 +04:00
1998-08-17 07:06:20 +04:00
/* the read request starts from where the SMBtrans2 left off. */
1999-02-03 03:48:27 +03:00
data_hdr_pos = p - > file_offset - p - > prev_pdu_file_offset ;
data_pos = data_hdr_pos - p - > hdr_offsets ;
1998-03-12 00:11:04 +03:00
1998-10-09 03:57:46 +04:00
if ( ! IS_BITS_SET_ALL ( p - > hdr . flags , RPC_FLG_LAST ) )
{
1998-08-17 07:06:20 +04:00
/* intermediate fragment - possibility of another header */
DEBUG ( 5 , ( " read_pipe: frag_len: %d data_pos: %d data_hdr_pos: %d \n " ,
p - > hdr . frag_len , data_pos , data_hdr_pos ) ) ;
1999-02-03 03:48:27 +03:00
if ( data_hdr_pos = = 0 )
1998-10-09 03:57:46 +04:00
{
1998-08-17 07:06:20 +04:00
DEBUG ( 6 , ( " read_pipe: next fragment header \n " ) ) ;
/* this is subtracted from the total data bytes, later */
hdr_num = 0x18 ;
1999-02-03 03:48:27 +03:00
p - > hdr_offsets + = 0x18 ;
1998-08-17 07:06:20 +04:00
/* create and copy in a new header. */
1999-02-03 03:48:27 +03:00
create_rpc_reply ( p , p - > file_offset - p - > hdr_offsets , p - > rdata . offset ) ;
1998-08-17 07:06:20 +04:00
}
1998-03-12 00:11:04 +03:00
}
1998-08-17 07:06:20 +04:00
1999-02-03 03:48:27 +03:00
len = mem_buf_len ( p - > rhdr . data ) ;
num = len - ( int ) data_pos ;
DEBUG ( 6 , ( " read_pipe: len: %d num: %d n: %d \n " , len , num , n ) ) ;
if ( num > n ) num = n ;
if ( num < = 0 )
{
DEBUG ( 5 , ( " read_pipe: 0 or -ve data length \n " ) ) ;
return 0 ;
}
1998-10-09 03:57:46 +04:00
if ( num < hdr_num )
{
1998-08-17 07:06:20 +04:00
DEBUG ( 5 , ( " read_pipe: warning - data read only part of a header \n " ) ) ;
1998-03-12 00:11:04 +03:00
}
1999-02-03 03:48:27 +03:00
mem_buf_copy ( data , p - > rhdr . data , data_pos , num ) ;
1998-08-17 07:06:20 +04:00
data_pos + = num ;
data_hdr_pos + = num ;
1999-02-03 03:48:27 +03:00
p - > file_offset + = num ;
1998-08-17 07:06:20 +04:00
1998-10-09 03:57:46 +04:00
if ( hdr_num = = 0x18 & & num = = 0x18 )
{
1998-08-17 07:06:20 +04:00
DEBUG ( 6 , ( " read_pipe: just header read \n " ) ) ;
1998-10-09 03:57:46 +04:00
}
else if ( data_hdr_pos = = p - > next_frag_start )
{
1998-08-17 07:06:20 +04:00
DEBUG ( 6 , ( " read_pipe: next fragment expected \n " ) ) ;
1999-02-03 03:48:27 +03:00
p - > prev_pdu_file_offset = p - > file_offset ;
1998-03-12 00:11:04 +03:00
}
1998-08-17 07:06:20 +04:00
return num ;
1998-03-12 00:11:04 +03:00
}
1998-08-17 07:06:20 +04:00
1998-10-15 09:47:29 +04:00
/****************************************************************************
wait device state on a pipe . exactly what this is for is unknown . . .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL wait_rpc_pipe_hnd_state ( pipes_struct * p , uint16 priority )
{
if ( p = = NULL ) return False ;
if ( p - > open )
{
DEBUG ( 3 , ( " %s Setting pipe wait state priority=%x on pipe (name=%s) \n " ,
timestring ( ) , priority , p - > name ) ) ;
p - > priority = priority ;
return True ;
}
DEBUG ( 3 , ( " %s Error setting pipe wait state priority=%x (name=%s) \n " ,
timestring ( ) , priority , p - > name ) ) ;
return False ;
}
1998-03-12 00:11:04 +03:00
/****************************************************************************
set device state on a pipe . exactly what this is for is unknown . . .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL set_rpc_pipe_hnd_state ( pipes_struct * p , uint16 device_state )
{
if ( p = = NULL ) return False ;
1998-08-17 07:06:20 +04:00
if ( p - > open ) {
1998-08-14 21:38:29 +04:00
DEBUG ( 3 , ( " %s Setting pipe device state=%x on pipe (name=%s) \n " ,
timestring ( ) , device_state , p - > name ) ) ;
1998-03-12 00:11:04 +03:00
p - > device_state = device_state ;
1998-08-17 07:06:20 +04:00
1998-03-12 00:11:04 +03:00
return True ;
1998-08-17 07:06:20 +04:00
}
DEBUG ( 3 , ( " %s Error setting pipe device state=%x (name=%s) \n " ,
timestring ( ) , device_state , p - > name ) ) ;
return False ;
1998-03-12 00:11:04 +03:00
}
1998-08-17 07:06:20 +04:00
1998-03-12 00:11:04 +03:00
/****************************************************************************
close an rpc pipe
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-17 07:06:20 +04:00
BOOL close_rpc_pipe_hnd ( pipes_struct * p , connection_struct * conn )
1998-03-12 00:11:04 +03:00
{
1998-08-17 07:06:20 +04:00
if ( ! p ) {
DEBUG ( 0 , ( " Invalid pipe in close_rpc_pipe_hnd \n " ) ) ;
1998-08-14 21:38:29 +04:00
return False ;
}
1998-08-17 07:06:20 +04:00
mem_buf_free ( & ( p - > rdata . data ) ) ;
mem_buf_free ( & ( p - > rhdr . data ) ) ;
1998-09-30 05:49:24 +04:00
bitmap_clear ( bmap , p - > pnum - pipe_handle_offset ) ;
1998-08-17 07:06:20 +04:00
pipes_open - - ;
DEBUG ( 4 , ( " closed pipe name %s pnum=%x (pipes_open=%d) \n " ,
p - > name , p - > pnum , pipes_open ) ) ;
1998-08-17 10:47:53 +04:00
DLIST_REMOVE ( Pipes , p ) ;
1998-08-17 07:06:20 +04:00
1998-09-05 17:24:20 +04:00
ZERO_STRUCTP ( p ) ;
1998-08-17 07:06:20 +04:00
free ( p ) ;
return True ;
1998-03-12 00:11:04 +03:00
}
/****************************************************************************
close an rpc pipe
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-17 07:06:20 +04:00
pipes_struct * get_rpc_pipe_p ( char * buf , int where )
1998-03-12 00:11:04 +03:00
{
1998-08-17 07:06:20 +04:00
int pnum = SVAL ( buf , where ) ;
if ( chain_p ) return chain_p ;
return get_rpc_pipe ( pnum ) ;
}
/****************************************************************************
close an rpc pipe
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
pipes_struct * get_rpc_pipe ( int pnum )
{
pipes_struct * p ;
1998-09-24 01:49:09 +04:00
DEBUG ( 4 , ( " search for pipe pnum=%x \n " , pnum ) ) ;
for ( p = Pipes ; p ; p = p - > next )
{
DEBUG ( 5 , ( " pipe name %s pnum=%x (pipes_open=%d) \n " ,
p - > name , p - > pnum , pipes_open ) ) ;
}
for ( p = Pipes ; p ; p = p - > next )
{
if ( p - > pnum = = pnum )
{
1998-08-17 07:52:05 +04:00
chain_p = p ;
return p ;
}
1998-08-17 07:06:20 +04:00
}
return NULL ;
1998-03-12 00:11:04 +03:00
}