1996-08-15 19:11:34 +04:00
/*
Unix SMB / Netbios implementation .
Version 1.9 .
Pipe SMB reply routines
1997-10-07 18:58:07 +04:00
Copyright ( C ) Andrew Tridgell 1992 - 1997 ,
1997-10-09 19:48:40 +04:00
Copyright ( C ) Luke Kenneth Casson Leighton 1996 - 1997.
Copyright ( C ) Paul Ashton 1997.
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)
# define REALLOC(ptr,size) Realloc(ptr,MAX((size),4*1024))
/* look in server.c for some explanation of these variables */
extern int Protocol ;
extern int DEBUGLEVEL ;
extern char magic_char ;
1997-10-30 04:05:13 +03:00
static int chain_pnum = - 1 ;
1996-08-15 19:11:34 +04:00
extern BOOL case_sensitive ;
extern pstring sesssetup_user ;
extern int Client ;
1997-05-20 04:32:51 +04:00
extern fstring myworkgroup ;
1996-08-15 19:11:34 +04:00
1997-10-30 04:05:13 +03:00
# ifndef MAX_OPEN_PIPES
# define MAX_OPEN_PIPES 50
# endif
static struct
{
int cnum ;
BOOL open ;
fstring name ;
} Pipes [ MAX_OPEN_PIPES ] ;
# define VALID_PNUM(pnum) (((pnum) >= 0) && ((pnum) < MAX_OPEN_PIPES))
# define OPEN_PNUM(pnum) (VALID_PNUM(pnum) && Pipes[pnum].open)
# define PNUM_OK(pnum,c) (OPEN_PNUM(pnum) && (c)==Pipes[pnum].cnum)
# define CHECK_PNUM(pnum,c) if (!PNUM_OK(pnum,c)) \
return ( ERROR ( ERRDOS , ERRbadfid ) )
/* this macro should always be used to extract an pnum (smb_fid) from
a packet to ensure chaining works correctly */
# define GETPNUM(buf,where) (chain_pnum!= -1?chain_pnum:SVAL(buf,where))
1996-08-15 19:11:34 +04:00
char * known_pipes [ ] =
{
1997-10-12 23:02:55 +04:00
" lsarpc " ,
1997-10-09 20:14:53 +04:00
# if NTDOMAIN
1997-10-07 18:58:07 +04:00
" NETLOGON " ,
1997-10-15 20:51:03 +04:00
" srvsvc " ,
1997-10-07 18:58:07 +04:00
# endif
1996-08-15 19:11:34 +04:00
NULL
} ;
/****************************************************************************
1997-10-30 04:05:13 +03:00
find first available file slot
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int find_free_pipe ( void )
{
int i ;
/* we start at 1 here for an obscure reason I can't now remember,
but I think is important : - ) */
for ( i = 1 ; i < MAX_OPEN_PIPES ; i + + )
if ( ! Pipes [ i ] . open )
return ( i ) ;
1996-08-15 19:11:34 +04:00
1997-10-30 04:05:13 +03:00
DEBUG ( 1 , ( " ERROR! Out of pipe structures - perhaps increase MAX_OPEN_PIPES? \n " ) ) ;
return ( - 1 ) ;
}
/****************************************************************************
gets the name of a pipe
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
char * get_pipe_name ( int pnum )
{
DEBUG ( 6 , ( " get_pipe_name: " ) ) ;
if ( VALID_PNUM ( pnum - 0x800 ) )
{
DEBUG ( 6 , ( " name: %s cnum: %d open: %s " ,
Pipes [ pnum - 0x800 ] . name ,
Pipes [ pnum - 0x800 ] . cnum ,
BOOLSTR ( Pipes [ pnum - 0x800 ] . open ) ) ) ;
}
if ( OPEN_PNUM ( pnum - 0x800 ) )
{
DEBUG ( 6 , ( " OK \n " ) ) ;
return Pipes [ pnum - 0x800 ] . name ;
}
else
{
DEBUG ( 6 , ( " NOT \n " ) ) ;
return NULL ;
}
}
/****************************************************************************
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 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int reply_open_pipe_and_X ( char * inbuf , char * outbuf , int length , int bufsize )
{
pstring fname ;
int cnum = SVAL ( inbuf , smb_tid ) ;
1997-10-30 04:05:13 +03:00
int pnum = - 1 ;
1996-08-15 19:11:34 +04:00
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 */
1997-09-26 22:55:29 +04:00
pstrcpy ( fname , smb_buf ( inbuf ) ) ;
1996-08-15 19:11:34 +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. */
if ( strncmp ( fname , PIPE , PIPELEN ) ! = 0 )
return ( ERROR ( ERRSRV , ERRaccess ) ) ;
DEBUG ( 4 , ( " Opening pipe %s. \n " , fname ) ) ;
/* Strip \PIPE\ off the name. */
1997-09-26 22:55:29 +04:00
pstrcpy ( fname , smb_buf ( inbuf ) + PIPELEN ) ;
1996-08-15 19:11:34 +04:00
/* See if it is one we want to handle. */
for ( i = 0 ; known_pipes [ i ] ; i + + )
if ( strcmp ( fname , known_pipes [ i ] ) = = 0 )
break ;
if ( known_pipes [ i ] = = NULL )
return ( ERROR ( ERRSRV , ERRaccess ) ) ;
/* 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 ) ) ;
smb_ofun | = 0x10 ; /* Add Create it not exists flag */
1997-10-30 04:05:13 +03:00
pnum = find_free_pipe ( ) ;
if ( pnum < 0 ) return ( ERROR ( ERRSRV , ERRnofids ) ) ;
1996-08-15 19:11:34 +04:00
1997-10-30 04:05:13 +03:00
Pipes [ pnum ] . open = True ;
Pipes [ pnum ] . cnum = cnum ;
fstrcpy ( Pipes [ pnum ] . name , fname ) ;
1996-08-15 19:11:34 +04:00
/* Prepare the reply */
1996-08-19 15:17:29 +04:00
set_message ( outbuf , 15 , 0 , True ) ;
1996-08-15 19:11:34 +04:00
/* Mark the opened file as an existing named pipe in message mode. */
SSVAL ( outbuf , smb_vwv9 , 2 ) ;
SSVAL ( outbuf , smb_vwv10 , 0xc700 ) ;
1997-10-30 04:05:13 +03:00
1996-08-15 19:11:34 +04:00
if ( rmode = = 2 )
{
DEBUG ( 4 , ( " Resetting open result to open from create. \n " ) ) ;
rmode = 1 ;
}
1997-10-30 04:05:13 +03:00
SSVAL ( outbuf , smb_vwv2 , pnum + 0x800 ) ; /* mark file handle up into high range */
1996-08-15 19:11:34 +04:00
SSVAL ( outbuf , smb_vwv3 , fmode ) ;
put_dos_date3 ( outbuf , smb_vwv4 , mtime ) ;
SIVAL ( outbuf , smb_vwv6 , size ) ;
SSVAL ( outbuf , smb_vwv8 , rmode ) ;
1997-10-30 04:05:13 +03:00
SSVAL ( outbuf , smb_vwv11 , 0 ) ;
1996-08-15 19:11:34 +04:00
1997-10-30 04:05:13 +03:00
DEBUG ( 4 , ( " Opened pipe %s with handle %x name %s. \n " ,
fname , pnum + 0x800 , Pipes [ pnum ] . name ) ) ;
1996-08-15 19:11:34 +04:00
1997-10-30 04:05:13 +03:00
chain_pnum = pnum ;
1996-08-19 15:17:29 +04:00
return chain_reply ( inbuf , outbuf , length , bufsize ) ;
1996-08-15 19:11:34 +04:00
}
1997-10-30 04:05:13 +03:00
/****************************************************************************
reply to a close
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int reply_pipe_close ( char * inbuf , char * outbuf )
{
int pnum = GETPNUM ( inbuf , smb_vwv0 ) ;
int cnum = SVAL ( inbuf , smb_tid ) ;
int outsize = set_message ( outbuf , 0 , 0 , True ) ;
/* mapping is 0x800 up... */
CHECK_PNUM ( pnum - 0x800 , cnum ) ;
DEBUG ( 3 , ( " %s Closed pipe name %s pnum=%d cnum=%d \n " ,
timestring ( ) , Pipes [ pnum - 0x800 ] . name , pnum , cnum ) ) ;
Pipes [ pnum - 0x800 ] . open = False ;
return ( outsize ) ;
}
1996-08-15 19:11:34 +04:00
/****************************************************************************
api_LsarpcSNPHS
SetNamedPipeHandleState on \ PIPE \ lsarpc . We can ' t really do much here ,
so just blithely return True . This is really only for NT domain stuff ,
we we ' re only handling that - don ' t assume Samba now does complete
named pipe handling .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL api_LsarpcSNPHS ( int cnum , int uid , char * param , char * data ,
int mdrcnt , int mprcnt ,
char * * rdata , char * * rparam ,
int * rdata_len , int * rparam_len )
{
uint16 id ;
id = param [ 0 ] + ( param [ 1 ] < < 8 ) ;
DEBUG ( 4 , ( " lsarpc SetNamedPipeHandleState to code %x \n " , id ) ) ;
return ( True ) ;
}
/****************************************************************************
api_LsarpcTNP
TransactNamedPipe on \ PIPE \ lsarpc .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1997-10-29 03:04:14 +03:00
static void LsarpcTNP1 ( char * data , char * * rdata , int * rdata_len )
1996-08-15 19:11:34 +04:00
{
uint32 dword1 , dword2 ;
char pname [ ] = " \\ PIPE \\ lsass " ;
/* All kinds of mysterious numbers here */
* rdata_len = 68 ;
* rdata = REALLOC ( * rdata , * rdata_len ) ;
dword1 = IVAL ( data , 0xC ) ;
dword2 = IVAL ( data , 0x10 ) ;
SIVAL ( * rdata , 0 , 0xc0005 ) ;
SIVAL ( * rdata , 4 , 0x10 ) ;
SIVAL ( * rdata , 8 , 0x44 ) ;
SIVAL ( * rdata , 0xC , dword1 ) ;
SIVAL ( * rdata , 0x10 , dword2 ) ;
SIVAL ( * rdata , 0x14 , 0x15 ) ;
SSVAL ( * rdata , 0x18 , sizeof ( pname ) ) ;
strcpy ( * rdata + 0x1a , pname ) ;
SIVAL ( * rdata , 0x28 , 1 ) ;
memcpy ( * rdata + 0x30 , data + 0x34 , 0x14 ) ;
}
static void LsarpcTNP2 ( char * data , char * * rdata , int * rdata_len )
{
uint32 dword1 ;
/* All kinds of mysterious numbers here */
* rdata_len = 48 ;
* rdata = REALLOC ( * rdata , * rdata_len ) ;
dword1 = IVAL ( data , 0xC ) ;
SIVAL ( * rdata , 0 , 0x03020005 ) ;
SIVAL ( * rdata , 4 , 0x10 ) ;
SIVAL ( * rdata , 8 , 0x30 ) ;
SIVAL ( * rdata , 0xC , dword1 ) ;
SIVAL ( * rdata , 0x10 , 0x18 ) ;
SIVAL ( * rdata , 0x1c , 0x44332211 ) ;
SIVAL ( * rdata , 0x20 , 0x88776655 ) ;
SIVAL ( * rdata , 0x24 , 0xCCBBAA99 ) ;
SIVAL ( * rdata , 0x28 , 0x11FFEEDD ) ;
}
static void LsarpcTNP3 ( char * data , char * * rdata , int * rdata_len )
{
uint32 dword1 ;
uint16 word1 ;
1997-05-20 04:32:51 +04:00
char * workgroup = myworkgroup ;
1996-10-02 19:41:30 +04:00
int wglen = strlen ( workgroup ) ;
1996-08-15 19:11:34 +04:00
int i ;
/* All kinds of mysterious numbers here */
* rdata_len = 90 + 2 * wglen ;
* rdata = REALLOC ( * rdata , * rdata_len ) ;
dword1 = IVAL ( data , 0xC ) ;
word1 = SVAL ( data , 0x2C ) ;
SIVAL ( * rdata , 0 , 0x03020005 ) ;
SIVAL ( * rdata , 4 , 0x10 ) ;
SIVAL ( * rdata , 8 , 0x60 ) ;
SIVAL ( * rdata , 0xC , dword1 ) ;
SIVAL ( * rdata , 0x10 , 0x48 ) ;
SSVAL ( * rdata , 0x18 , 0x5988 ) ; /* This changes */
SSVAL ( * rdata , 0x1A , 0x15 ) ;
SSVAL ( * rdata , 0x1C , word1 ) ;
SSVAL ( * rdata , 0x20 , 6 ) ;
SSVAL ( * rdata , 0x22 , 8 ) ;
SSVAL ( * rdata , 0x24 , 0x8E8 ) ; /* So does this */
SSVAL ( * rdata , 0x26 , 0x15 ) ;
SSVAL ( * rdata , 0x28 , 0x4D48 ) ; /* And this */
SSVAL ( * rdata , 0x2A , 0x15 ) ;
SIVAL ( * rdata , 0x2C , 4 ) ;
SIVAL ( * rdata , 0x34 , wglen ) ;
for ( i = 0 ; i < wglen ; i + + )
1996-10-02 19:41:30 +04:00
( * rdata ) [ 0x38 + i * 2 ] = workgroup [ i ] ;
1996-08-15 19:11:34 +04:00
/* Now fill in the rest */
i = 0x38 + wglen * 2 ;
SSVAL ( * rdata , i , 0x648 ) ;
SIVAL ( * rdata , i + 2 , 4 ) ;
SIVAL ( * rdata , i + 6 , 0x401 ) ;
SSVAL ( * rdata , i + 0xC , 0x500 ) ;
SIVAL ( * rdata , i + 0xE , 0x15 ) ;
SIVAL ( * rdata , i + 0x12 , 0x2372FE1 ) ;
SIVAL ( * rdata , i + 0x16 , 0x7E831BEF ) ;
SIVAL ( * rdata , i + 0x1A , 0x4B454B2 ) ;
}
static void LsarpcTNP4 ( char * data , char * * rdata , int * rdata_len )
{
uint32 dword1 ;
/* All kinds of mysterious numbers here */
* rdata_len = 48 ;
* rdata = REALLOC ( * rdata , * rdata_len ) ;
dword1 = IVAL ( data , 0xC ) ;
SIVAL ( * rdata , 0 , 0x03020005 ) ;
SIVAL ( * rdata , 4 , 0x10 ) ;
SIVAL ( * rdata , 8 , 0x30 ) ;
SIVAL ( * rdata , 0xC , dword1 ) ;
SIVAL ( * rdata , 0x10 , 0x18 ) ;
}
BOOL api_LsarpcTNP ( int cnum , int uid , char * param , char * data ,
int mdrcnt , int mprcnt ,
char * * rdata , char * * rparam ,
int * rdata_len , int * rparam_len )
{
uint32 id , id2 ;
id = IVAL ( data , 0 ) ;
DEBUG ( 4 , ( " lsarpc TransactNamedPipe id %lx \n " , id ) ) ;
switch ( id )
{
case 0xb0005 :
LsarpcTNP1 ( data , rdata , rdata_len ) ;
break ;
case 0x03000005 :
id2 = IVAL ( data , 8 ) ;
DEBUG ( 4 , ( " \t - Suboperation %lx \n " , id2 ) ) ;
switch ( id2 & 0xF )
{
case 8 :
LsarpcTNP2 ( data , rdata , rdata_len ) ;
break ;
case 0xC :
LsarpcTNP4 ( data , rdata , rdata_len ) ;
break ;
case 0xE :
LsarpcTNP3 ( data , rdata , rdata_len ) ;
break ;
}
break ;
}
return ( True ) ;
}
1997-10-15 20:51:03 +04:00