1998-05-08 05:22:16 +04:00
/*
Unix SMB / Netbios implementation .
Version 1.9 .
SMB NT transaction handling
Copyright ( C ) Jeremy Allison 1994 - 1998
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"
1998-08-11 06:13:01 +04:00
# include "nterr.h"
1998-05-08 05:22:16 +04:00
extern int DEBUGLEVEL ;
extern int Protocol ;
extern int Client ;
extern int oplock_sock ;
extern int smb_read_error ;
extern int global_oplock_break ;
1998-08-21 05:30:29 +04:00
extern int chain_size ;
1998-07-02 01:49:49 +04:00
extern BOOL case_sensitive ;
extern BOOL case_preserve ;
extern BOOL short_case_preserve ;
1998-05-08 05:22:16 +04:00
1998-09-05 09:07:05 +04:00
static void remove_pending_change_notify_requests_by_mid ( int mid ) ;
1998-05-08 20:59:30 +04:00
static char * known_nt_pipes [ ] = {
" \\ LANMAN " ,
" \\ srvsvc " ,
" \\ samr " ,
" \\ wkssvc " ,
" \\ NETLOGON " ,
" \\ ntlsa " ,
" \\ ntsvcs " ,
" \\ lsass " ,
" \\ lsarpc " ,
NULL
} ;
1998-07-09 04:41:32 +04:00
/****************************************************************************
1998-07-11 04:28:34 +04:00
Send the required number of replies back .
We assume all fields other than the data fields are
set correctly for the type of call .
HACK ! Always assumes smb_setup field is zero .
1998-07-09 04:41:32 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-07-11 04:28:34 +04:00
1998-07-09 04:41:32 +04:00
static int send_nt_replies ( char * outbuf , int bufsize , char * params ,
int paramsize , char * pdata , int datasize )
{
extern int max_send ;
int data_to_send = datasize ;
int params_to_send = paramsize ;
int useable_space ;
char * pp = params ;
char * pd = pdata ;
int params_sent_thistime , data_sent_thistime , total_sent_thistime ;
int alignment_offset = 3 ;
int data_alignment_offset = 0 ;
/*
* Initially set the wcnt area to be 18 - this is true for all
* transNT replies .
*/
set_message ( outbuf , 18 , 0 , True ) ;
/*
* If there genuinely are no parameters or data to send just send
* the empty packet .
*/
if ( params_to_send = = 0 & & data_to_send = = 0 ) {
send_smb ( Client , outbuf ) ;
return 0 ;
}
/*
* When sending params and data ensure that both are nicely aligned .
* Only do this alignment when there is also data to send - else
* can cause NT redirector problems .
*/
if ( ( ( params_to_send % 4 ) ! = 0 ) & & ( data_to_send ! = 0 ) )
data_alignment_offset = 4 - ( params_to_send % 4 ) ;
/*
* Space is bufsize minus Netbios over TCP header minus SMB header .
* The alignment_offset is to align the param bytes on a four byte
* boundary ( 2 bytes for data len , one byte pad ) .
* NT needs this to work correctly .
*/
useable_space = bufsize - ( ( smb_buf ( outbuf ) +
alignment_offset + data_alignment_offset ) -
outbuf ) ;
/*
* useable_space can never be more than max_send minus the
* alignment offset .
*/
useable_space = MIN ( useable_space ,
max_send - ( alignment_offset + data_alignment_offset ) ) ;
while ( params_to_send | | data_to_send ) {
/*
* Calculate whether we will totally or partially fill this packet .
*/
total_sent_thistime = params_to_send + data_to_send +
alignment_offset + data_alignment_offset ;
/*
* We can never send more than useable_space .
*/
total_sent_thistime = MIN ( total_sent_thistime , useable_space ) ;
set_message ( outbuf , 18 , total_sent_thistime , True ) ;
/*
* Set total params and data to be sent .
*/
SIVAL ( outbuf , smb_ntr_TotalParameterCount , paramsize ) ;
SIVAL ( outbuf , smb_ntr_TotalDataCount , datasize ) ;
/*
* Calculate how many parameters and data we can fit into
* this packet . Parameters get precedence .
*/
params_sent_thistime = MIN ( params_to_send , useable_space ) ;
data_sent_thistime = useable_space - params_sent_thistime ;
data_sent_thistime = MIN ( data_sent_thistime , data_to_send ) ;
SIVAL ( outbuf , smb_ntr_ParameterCount , params_sent_thistime ) ;
if ( params_sent_thistime = = 0 ) {
SIVAL ( outbuf , smb_ntr_ParameterOffset , 0 ) ;
SIVAL ( outbuf , smb_ntr_ParameterDisplacement , 0 ) ;
} else {
/*
* smb_ntr_ParameterOffset is the offset from the start of the SMB header to the
* parameter bytes , however the first 4 bytes of outbuf are
* the Netbios over TCP header . Thus use smb_base ( ) to subtract
* them from the calculation .
*/
SIVAL ( outbuf , smb_ntr_ParameterOffset ,
( ( smb_buf ( outbuf ) + alignment_offset ) - smb_base ( outbuf ) ) ) ;
/*
* Absolute displacement of param bytes sent in this packet .
*/
SIVAL ( outbuf , smb_ntr_ParameterDisplacement , pp - params ) ;
}
/*
* Deal with the data portion .
*/
SIVAL ( outbuf , smb_ntr_DataCount , data_sent_thistime ) ;
if ( data_sent_thistime = = 0 ) {
SIVAL ( outbuf , smb_ntr_DataOffset , 0 ) ;
SIVAL ( outbuf , smb_ntr_DataDisplacement , 0 ) ;
} else {
/*
* The offset of the data bytes is the offset of the
* parameter bytes plus the number of parameters being sent this time .
*/
SIVAL ( outbuf , smb_ntr_DataOffset , ( ( smb_buf ( outbuf ) + alignment_offset ) -
smb_base ( outbuf ) ) + params_sent_thistime + data_alignment_offset ) ;
SIVAL ( outbuf , smb_ntr_DataDisplacement , pd - pdata ) ;
}
/*
* Copy the param bytes into the packet .
*/
if ( params_sent_thistime )
memcpy ( ( smb_buf ( outbuf ) + alignment_offset ) , pp , params_sent_thistime ) ;
/*
* Copy in the data bytes
*/
if ( data_sent_thistime )
memcpy ( smb_buf ( outbuf ) + alignment_offset + params_sent_thistime +
data_alignment_offset , pd , data_sent_thistime ) ;
DEBUG ( 9 , ( " nt_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d \n " ,
params_sent_thistime , data_sent_thistime , useable_space ) ) ;
DEBUG ( 9 , ( " nt_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d \n " ,
params_to_send , data_to_send , paramsize , datasize ) ) ;
/* Send the packet */
send_smb ( Client , outbuf ) ;
pp + = params_sent_thistime ;
pd + = data_sent_thistime ;
params_to_send - = params_sent_thistime ;
data_to_send - = data_sent_thistime ;
/*
* Sanity check
*/
if ( params_to_send < 0 | | data_to_send < 0 ) {
DEBUG ( 0 , ( " send_nt_replies failed sanity check pts = %d, dts = %d \n !!! " ,
params_to_send , data_to_send ) ) ;
return - 1 ;
}
}
return 0 ;
}
1998-07-02 22:49:08 +04:00
/****************************************************************************
Save case statics .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-07-02 01:49:49 +04:00
static BOOL saved_case_sensitive ;
static BOOL saved_case_preserve ;
static BOOL saved_short_case_preserve ;
1998-05-19 01:30:57 +04:00
/****************************************************************************
1998-07-02 01:49:49 +04:00
Save case semantics .
1998-05-19 01:30:57 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-07-02 01:49:49 +04:00
static void set_posix_case_semantics ( uint32 file_attributes )
{
if ( ! ( file_attributes & FILE_FLAG_POSIX_SEMANTICS ) )
return ;
saved_case_sensitive = case_sensitive ;
saved_case_preserve = case_preserve ;
saved_short_case_preserve = short_case_preserve ;
/* Set to POSIX. */
case_sensitive = True ;
case_preserve = True ;
short_case_preserve = True ;
}
/****************************************************************************
Restore case semantics .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void restore_case_semantics ( uint32 file_attributes )
{
if ( ! ( file_attributes & FILE_FLAG_POSIX_SEMANTICS ) )
return ;
case_sensitive = saved_case_sensitive ;
case_preserve = saved_case_preserve ;
short_case_preserve = saved_short_case_preserve ;
}
/****************************************************************************
1998-07-08 05:42:05 +04:00
Utility function to map create disposition .
1998-07-02 01:49:49 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-05-19 01:30:57 +04:00
1998-07-08 05:42:05 +04:00
static int map_create_disposition ( uint32 create_disposition )
{
1998-07-01 01:19:40 +04:00
switch ( create_disposition ) {
1998-07-17 02:46:06 +04:00
case FILE_CREATE :
1998-07-01 01:19:40 +04:00
/* create if not exist, fail if exist */
1998-07-08 05:42:05 +04:00
return 0x10 ;
1998-07-17 02:46:06 +04:00
case FILE_SUPERSEDE :
case FILE_OVERWRITE_IF :
1998-07-01 01:19:40 +04:00
/* create if not exist, trunc if exist */
1998-07-08 05:42:05 +04:00
return 0x12 ;
1998-07-17 02:46:06 +04:00
case FILE_OPEN :
1998-07-01 01:19:40 +04:00
/* fail if not exist, open if exists */
1998-07-08 05:42:05 +04:00
return 0x1 ;
1998-07-17 02:46:06 +04:00
case FILE_OPEN_IF :
1998-07-01 01:19:40 +04:00
/* create if not exist, open if exists */
1998-07-08 05:42:05 +04:00
return 0x11 ;
1998-07-17 02:46:06 +04:00
case FILE_OVERWRITE :
1998-07-01 01:19:40 +04:00
/* fail if not exist, truncate if exists */
1998-07-08 05:42:05 +04:00
return 0x2 ;
1998-07-01 01:19:40 +04:00
default :
1998-07-08 05:42:05 +04:00
DEBUG ( 0 , ( " map_create_disposition: Incorrect value for create_disposition = %d \n " ,
1998-07-01 01:19:40 +04:00
create_disposition ) ) ;
1998-07-08 05:42:05 +04:00
return - 1 ;
1998-07-01 01:19:40 +04:00
}
1998-07-08 05:42:05 +04:00
}
1998-07-01 01:19:40 +04:00
1998-07-08 05:42:05 +04:00
/****************************************************************************
Utility function to map share modes .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-07-17 02:46:06 +04:00
static int map_share_mode ( uint32 desired_access , uint32 share_access , uint32 file_attributes )
1998-07-08 05:42:05 +04:00
{
1998-07-17 04:47:16 +04:00
int smb_open_mode = - 1 ;
1998-07-01 01:19:40 +04:00
switch ( desired_access & ( FILE_READ_DATA | FILE_WRITE_DATA ) ) {
case FILE_READ_DATA :
smb_open_mode = 0 ;
break ;
case FILE_WRITE_DATA :
smb_open_mode = 1 ;
break ;
case FILE_READ_DATA | FILE_WRITE_DATA :
smb_open_mode = 2 ;
break ;
1998-07-17 04:47:16 +04:00
}
if ( smb_open_mode = = - 1 ) {
1998-09-15 00:43:50 +04:00
if ( desired_access & ( DELETE_ACCESS | FILE_WRITE_ATTRIBUTES |
WRITE_DAC_ACCESS | WRITE_OWNER_ACCESS ) )
1998-07-17 04:47:16 +04:00
smb_open_mode = 2 ;
1998-09-15 00:43:50 +04:00
else if ( desired_access & ( FILE_EXECUTE | READ_CONTROL_ACCESS ) )
1998-07-17 05:38:08 +04:00
smb_open_mode = 0 ;
1998-07-17 04:47:16 +04:00
else {
DEBUG ( 0 , ( " map_share_mode: Incorrect value for desired_access = %x \n " ,
1998-07-01 01:19:40 +04:00
desired_access ) ) ;
1998-07-17 04:47:16 +04:00
return - 1 ;
}
1998-07-01 01:19:40 +04:00
}
/* Add in the requested share mode - ignore FILE_SHARE_DELETE for now. */
switch ( share_access & ( FILE_SHARE_READ | FILE_SHARE_WRITE ) ) {
case FILE_SHARE_READ :
smb_open_mode | = ( DENY_WRITE < < 4 ) ;
break ;
case FILE_SHARE_WRITE :
smb_open_mode | = ( DENY_READ < < 4 ) ;
break ;
case ( FILE_SHARE_READ | FILE_SHARE_WRITE ) :
smb_open_mode | = ( DENY_NONE < < 4 ) ;
break ;
case FILE_SHARE_NONE :
smb_open_mode | = ( DENY_ALL < < 4 ) ;
break ;
}
/*
* Handle a O_SYNC request .
*/
if ( file_attributes & FILE_FLAG_WRITE_THROUGH )
smb_open_mode | = ( 1 < < 14 ) ;
1998-07-08 05:42:05 +04:00
return smb_open_mode ;
}
/****************************************************************************
Reply to an NT create and X call on a pipe .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-14 21:38:29 +04:00
static int nt_open_pipe ( char * fname , connection_struct * conn ,
char * inbuf , char * outbuf , int * ppnum )
1998-07-08 05:42:05 +04:00
{
1998-08-17 07:06:20 +04:00
pipes_struct * p = NULL ;
1998-07-08 05:42:05 +04:00
1998-08-17 07:06:20 +04:00
uint16 vuid = SVAL ( inbuf , smb_uid ) ;
int i ;
DEBUG ( 4 , ( " nt_open_pipe: Opening pipe %s. \n " , fname ) ) ;
1998-07-08 05:42:05 +04:00
1998-08-17 07:06:20 +04:00
/* See if it is one we want to handle. */
for ( i = 0 ; known_nt_pipes [ i ] ; i + + )
if ( strequal ( fname , known_nt_pipes [ i ] ) )
break ;
1998-07-08 05:42:05 +04:00
1998-08-17 07:06:20 +04:00
if ( known_nt_pipes [ i ] = = NULL )
return ( ERROR ( ERRSRV , ERRaccess ) ) ;
1998-07-08 05:42:05 +04:00
1998-08-17 07:06:20 +04:00
/* Strip \\ off the name. */
fname + + ;
1998-07-08 05:42:05 +04:00
1998-08-17 07:06:20 +04:00
DEBUG ( 3 , ( " nt_open_pipe: Known pipe %s opening. \n " , fname ) ) ;
1998-07-08 05:42:05 +04:00
1998-08-17 07:06:20 +04:00
p = open_rpc_pipe_p ( fname , conn , vuid ) ;
if ( ! p )
return ( ERROR ( ERRSRV , ERRnofids ) ) ;
1998-07-17 02:46:06 +04:00
1998-08-17 07:06:20 +04:00
* ppnum = p - > pnum ;
return 0 ;
1998-07-08 05:42:05 +04:00
}
/****************************************************************************
Reply to an NT create and X call .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-14 21:38:29 +04:00
int reply_ntcreate_and_X ( connection_struct * conn ,
char * inbuf , char * outbuf , int length , int bufsize )
1998-07-08 05:42:05 +04:00
{
1998-08-14 21:38:29 +04:00
pstring fname ;
uint32 flags = IVAL ( inbuf , smb_ntcreate_Flags ) ;
uint32 desired_access = IVAL ( inbuf , smb_ntcreate_DesiredAccess ) ;
uint32 file_attributes = IVAL ( inbuf , smb_ntcreate_FileAttributes ) ;
uint32 share_access = IVAL ( inbuf , smb_ntcreate_ShareAccess ) ;
uint32 create_disposition = IVAL ( inbuf , smb_ntcreate_CreateDisposition ) ;
1998-09-14 23:49:55 +04:00
uint32 create_options = IVAL ( inbuf , smb_ntcreate_CreateOptions ) ;
1998-08-14 21:38:29 +04:00
uint32 fname_len = MIN ( ( ( uint32 ) SVAL ( inbuf , smb_ntcreate_NameLength ) ) ,
( ( uint32 ) sizeof ( fname ) - 1 ) ) ;
int smb_ofun ;
int smb_open_mode ;
int smb_attr = ( file_attributes & SAMBA_ATTRIBUTES_MASK ) ;
/* Breakout the oplock request bits so we can set the
reply bits separately . */
int oplock_request = 0 ;
1998-09-17 23:16:12 +04:00
mode_t unixmode ;
int pnum = - 1 ;
int fmode = 0 , rmode = 0 ;
1998-09-03 22:40:31 +04:00
SMB_OFF_T file_len = 0 ;
1998-09-02 00:11:54 +04:00
SMB_STRUCT_STAT sbuf ;
1998-08-14 21:38:29 +04:00
int smb_action = 0 ;
BOOL bad_path = False ;
files_struct * fsp = NULL ;
char * p = NULL ;
/*
* We need to construct the open_and_X ofun value from the
* NT values , as that ' s what our code is structured to accept .
*/
if ( ( smb_ofun = map_create_disposition ( create_disposition ) ) = = - 1 )
return ( ERROR ( ERRDOS , ERRbadaccess ) ) ;
/*
* Now contruct the smb_open_mode value from the desired access
* and the share access .
*/
if ( ( smb_open_mode = map_share_mode ( desired_access ,
share_access ,
file_attributes ) ) = = - 1 ) {
return ( ERROR ( ERRDOS , ERRbadaccess ) ) ;
}
1998-07-31 01:18:57 +04:00
1998-08-14 21:38:29 +04:00
/*
* Get the file name .
*/
StrnCpy ( fname , smb_buf ( inbuf ) , fname_len ) ;
fname [ fname_len ] = ' \0 ' ;
/* If it's an IPC, use the pipe handler. */
1998-08-18 02:59:53 +04:00
1998-08-14 21:38:29 +04:00
if ( IS_IPC ( conn ) ) {
1998-08-18 02:59:53 +04:00
1998-08-15 11:27:34 +04:00
int ret = nt_open_pipe ( fname , conn , inbuf , outbuf , & pnum ) ;
1998-08-14 21:38:29 +04:00
if ( ret ! = 0 )
return ret ;
/*
1998-08-18 02:59:53 +04:00
* Deal with pipe return .
*/
set_message ( outbuf , 34 , 0 , True ) ;
p = outbuf + smb_vwv2 ;
p + + ;
SSVAL ( p , 0 , pnum ) ;
p + = 2 ;
SIVAL ( p , 0 , FILE_WAS_OPENED ) ;
p + = 4 ;
p + = 32 ;
SIVAL ( p , 0 , FILE_ATTRIBUTE_NORMAL ) ; /* File Attributes. */
p + = 20 ;
/* File type. */
SSVAL ( p , 0 , FILE_TYPE_MESSAGE_MODE_PIPE ) ;
/* Device state. */
SSVAL ( p , 2 , 0x5FF ) ; /* ? */
1998-08-18 03:39:59 +04:00
DEBUG ( 5 , ( " reply_ntcreate_and_X: open pipe = %s \n " , fname ) ) ;
return chain_reply ( inbuf , outbuf , length , bufsize ) ;
1998-08-18 02:59:53 +04:00
}
/*
* Ordinary file or directory .
*/
1998-08-14 21:38:29 +04:00
1998-08-18 02:59:53 +04:00
/*
* Check if POSIX semantics are wanted .
*/
1998-08-14 21:38:29 +04:00
1998-08-18 02:59:53 +04:00
set_posix_case_semantics ( file_attributes ) ;
1998-08-14 21:38:29 +04:00
1998-08-28 00:38:53 +04:00
unix_convert ( fname , conn , 0 , & bad_path , NULL ) ;
1998-08-14 21:38:29 +04:00
1998-08-18 02:59:53 +04:00
fsp = file_new ( ) ;
if ( ! fsp ) {
restore_case_semantics ( file_attributes ) ;
return ( ERROR ( ERRSRV , ERRnofids ) ) ;
}
if ( ! check_name ( fname , conn ) ) {
if ( ( errno = = ENOENT ) & & bad_path ) {
unix_ERR_class = ERRDOS ;
unix_ERR_code = ERRbadpath ;
1998-08-14 21:38:29 +04:00
}
1998-08-18 02:59:53 +04:00
file_free ( fsp ) ;
1998-08-14 21:38:29 +04:00
1998-08-18 02:59:53 +04:00
restore_case_semantics ( file_attributes ) ;
return ( UNIXERROR ( ERRDOS , ERRnoaccess ) ) ;
}
1998-08-14 21:38:29 +04:00
1998-08-18 02:59:53 +04:00
unixmode = unix_mode ( conn , smb_attr | aARCH ) ;
1998-05-19 01:30:57 +04:00
1998-08-18 02:59:53 +04:00
oplock_request = ( flags & REQUEST_OPLOCK ) ? EXCLUSIVE_OPLOCK : 0 ;
oplock_request | = ( flags & REQUEST_BATCH_OPLOCK ) ? BATCH_OPLOCK : 0 ;
1998-08-14 21:38:29 +04:00
1998-08-18 02:59:53 +04:00
/*
* If it ' s a request for a directory open , deal with it separately .
*/
1998-08-14 21:38:29 +04:00
1998-09-14 23:49:55 +04:00
if ( create_options & FILE_DIRECTORY_FILE ) {
1998-08-18 02:59:53 +04:00
oplock_request = 0 ;
open_directory ( fsp , conn , fname , smb_ofun ,
unixmode , & smb_action ) ;
1998-08-14 21:38:29 +04:00
1998-08-18 02:59:53 +04:00
restore_case_semantics ( file_attributes ) ;
1998-08-14 21:38:29 +04:00
1998-08-18 02:59:53 +04:00
if ( ! fsp - > open ) {
file_free ( fsp ) ;
return ( UNIXERROR ( ERRDOS , ERRnoaccess ) ) ;
}
} else {
/*
* Ordinary file case .
*/
/* NB. We have a potential bug here. If we
* cause an oplock break to ourselves , then we
* could end up processing filename related
* SMB requests whilst we await the oplock
* break response . As we may have changed the
* filename case semantics to be POSIX - like ,
* this could mean a filename request could
* fail when it should succeed . This is a rare
* condition , but eventually we must arrange
* to restore the correct case semantics
* before issuing an oplock break request to
* our client . JRA . */
open_file_shared ( fsp , conn , fname , smb_open_mode ,
smb_ofun , unixmode ,
oplock_request , & rmode , & smb_action ) ;
if ( ! fsp - > open ) {
/* We cheat here. The only case we
* care about is a directory rename ,
* where the NT client will attempt to
* open the source directory for
* DELETE access . Note that when the
* NT client does this it does * not *
* set the directory bit in the
* request packet . This is translated
* into a read / write open
* request . POSIX states that any open
* for write request on a directory
* will generate an EISDIR error , so
* we can catch this here and open a
* pseudo handle that is flagged as a
* directory . JRA . */
if ( errno = = EISDIR ) {
oplock_request = 0 ;
open_directory ( fsp , conn , fname , smb_ofun , unixmode , & smb_action ) ;
if ( ! fsp - > open ) {
1998-08-15 11:27:34 +04:00
file_free ( fsp ) ;
1998-08-14 21:38:29 +04:00
restore_case_semantics ( file_attributes ) ;
return ( UNIXERROR ( ERRDOS , ERRnoaccess ) ) ;
}
1998-08-18 02:59:53 +04:00
} else {
if ( ( errno = = ENOENT ) & & bad_path ) {
unix_ERR_class = ERRDOS ;
unix_ERR_code = ERRbadpath ;
}
file_free ( fsp ) ;
1998-08-14 21:38:29 +04:00
restore_case_semantics ( file_attributes ) ;
1998-08-18 02:59:53 +04:00
return ( UNIXERROR ( ERRDOS , ERRnoaccess ) ) ;
1998-08-14 21:38:29 +04:00
}
1998-08-18 02:59:53 +04:00
}
}
1998-08-14 21:38:29 +04:00
1998-08-18 02:59:53 +04:00
if ( fsp - > is_directory ) {
1998-09-02 00:11:54 +04:00
if ( dos_stat ( fsp - > fsp_name , & sbuf ) ! = 0 ) {
1998-08-18 02:59:53 +04:00
close_directory ( fsp ) ;
restore_case_semantics ( file_attributes ) ;
return ( ERROR ( ERRDOS , ERRnoaccess ) ) ;
}
} else {
1998-09-03 22:40:31 +04:00
if ( sys_fstat ( fsp - > fd_ptr - > fd , & sbuf ) ! = 0 ) {
1998-08-15 11:27:34 +04:00
close_file ( fsp , False ) ;
1998-08-18 02:59:53 +04:00
restore_case_semantics ( file_attributes ) ;
1998-08-14 21:38:29 +04:00
return ( ERROR ( ERRDOS , ERRnoaccess ) ) ;
}
1998-08-18 02:59:53 +04:00
}
1998-08-14 21:38:29 +04:00
1998-08-18 02:59:53 +04:00
restore_case_semantics ( file_attributes ) ;
1998-08-14 21:38:29 +04:00
1998-08-18 02:59:53 +04:00
file_len = sbuf . st_size ;
fmode = dos_mode ( conn , fname , & sbuf ) ;
if ( fmode = = 0 )
fmode = FILE_ATTRIBUTE_NORMAL ;
if ( ! fsp - > is_directory & & ( fmode & aDIR ) ) {
close_file ( fsp , False ) ;
return ( ERROR ( ERRDOS , ERRnoaccess ) ) ;
}
/*
* If the caller set the extended oplock request bit
* and we granted one ( by whatever means ) - set the
* correct bit for extended oplock reply .
*/
if ( oplock_request & & lp_fake_oplocks ( SNUM ( conn ) ) )
smb_action | = EXTENDED_OPLOCK_GRANTED ;
if ( oplock_request & & fsp - > granted_oplock )
smb_action | = EXTENDED_OPLOCK_GRANTED ;
1998-08-14 21:38:29 +04:00
set_message ( outbuf , 34 , 0 , True ) ;
p = outbuf + smb_vwv2 ;
/*
* Currently as we don ' t support level II oplocks we just report
* exclusive & batch here .
*/
SCVAL ( p , 0 , ( smb_action & EXTENDED_OPLOCK_GRANTED ? 1 : 0 ) ) ;
p + + ;
1998-08-18 02:59:53 +04:00
SSVAL ( p , 0 , fsp - > fnum ) ;
1998-08-14 21:38:29 +04:00
p + = 2 ;
SIVAL ( p , 0 , smb_action ) ;
p + = 4 ;
1998-08-18 02:59:53 +04:00
/* Create time. */
put_long_date ( p , get_create_time ( & sbuf , lp_fake_dir_create_times ( SNUM ( conn ) ) ) ) ;
p + = 8 ;
put_long_date ( p , sbuf . st_atime ) ; /* access time */
p + = 8 ;
put_long_date ( p , sbuf . st_mtime ) ; /* write time */
p + = 8 ;
put_long_date ( p , sbuf . st_mtime ) ; /* change time */
p + = 8 ;
SIVAL ( p , 0 , fmode ) ; /* File Attributes. */
1998-09-12 01:42:18 +04:00
p + = 4 ;
# ifdef LARGE_SMB_OFF_T
SIVAL ( p , 0 , file_len ) ;
SIVAL ( p , 4 , file_len > > 32 ) ;
# else /* LARGE_SMB_OFF_T */
SIVAL ( p , 0 , file_len ) ;
# endif /* LARGE_SMB_OFF_T */
p + = 8 ;
1998-09-03 22:40:31 +04:00
# ifdef LARGE_SMB_OFF_T
1998-09-12 01:42:18 +04:00
SIVAL ( p , 0 , file_len ) ;
1998-08-18 02:59:53 +04:00
SIVAL ( p , 4 , file_len > > 32 ) ;
1998-09-03 22:40:31 +04:00
# else /* LARGE_SMB_OFF_T */
1998-08-18 02:59:53 +04:00
SIVAL ( p , 0 , file_len ) ;
1998-09-03 22:40:31 +04:00
# endif /* LARGE_SMB_OFF_T */
1998-08-18 02:59:53 +04:00
p + = 12 ;
SCVAL ( p , 0 , fsp - > is_directory ? 1 : 0 ) ;
1998-08-14 21:38:29 +04:00
1998-08-20 23:28:37 +04:00
DEBUG ( 5 , ( " reply_ntcreate_and_X: fnum = %d, open name = %s \n " , fsp - > fnum , fsp - > fsp_name ) ) ;
1998-08-03 23:07:55 +04:00
1998-08-14 21:38:29 +04:00
return chain_reply ( inbuf , outbuf , length , bufsize ) ;
1998-07-02 01:49:49 +04:00
}
1998-05-08 20:59:30 +04:00
1998-07-02 22:49:08 +04:00
/****************************************************************************
1998-07-08 05:42:05 +04:00
Reply to a NT_TRANSACT_CREATE call ( needs to process SD ' s ) .
1998-07-02 22:49:08 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-14 21:38:29 +04:00
static int call_nt_transact_create ( connection_struct * conn ,
char * inbuf , char * outbuf , int length ,
int bufsize ,
char * * ppsetup , char * * ppparams ,
char * * ppdata )
1998-07-02 22:49:08 +04:00
{
1998-07-08 05:42:05 +04:00
pstring fname ;
1998-07-17 02:46:06 +04:00
char * params = * ppparams ;
1998-07-08 05:42:05 +04:00
uint32 flags = IVAL ( params , 0 ) ;
uint32 desired_access = IVAL ( params , 8 ) ;
uint32 file_attributes = IVAL ( params , 20 ) ;
uint32 share_access = IVAL ( params , 24 ) ;
uint32 create_disposition = IVAL ( params , 28 ) ;
1998-09-14 23:49:55 +04:00
uint32 create_options = IVAL ( params , 32 ) ;
1998-07-08 05:42:05 +04:00
uint32 fname_len = MIN ( ( ( uint32 ) IVAL ( params , 44 ) ) ,
1998-07-02 22:49:08 +04:00
( ( uint32 ) sizeof ( fname ) - 1 ) ) ;
int smb_ofun ;
int smb_open_mode ;
1998-07-03 02:23:56 +04:00
int smb_attr = ( file_attributes & SAMBA_ATTRIBUTES_MASK ) ;
1998-07-17 02:46:06 +04:00
/* Breakout the oplock request bits so we can set the
reply bits separately . */
int oplock_request = 0 ;
1998-09-17 23:16:12 +04:00
mode_t unixmode ;
int pnum = - 1 ;
1998-09-18 03:06:57 +04:00
int fmode = 0 , rmode = 0 ;
1998-09-18 06:26:36 +04:00
SMB_OFF_T file_len = 0 ;
1998-09-02 00:11:54 +04:00
SMB_STRUCT_STAT sbuf ;
1998-07-17 02:46:06 +04:00
int smb_action = 0 ;
BOOL bad_path = False ;
1998-08-18 02:59:53 +04:00
files_struct * fsp = NULL ;
1998-07-17 02:46:06 +04:00
char * p = NULL ;
1998-07-08 05:42:05 +04:00
/*
* We need to construct the open_and_X ofun value from the
* NT values , as that ' s what our code is structured to accept .
*/
if ( ( smb_ofun = map_create_disposition ( create_disposition ) ) = = - 1 )
return ( ERROR ( ERRDOS , ERRbadaccess ) ) ;
/*
* Now contruct the smb_open_mode value from the desired access
* and the share access .
*/
1998-07-17 02:46:06 +04:00
if ( ( smb_open_mode = map_share_mode ( desired_access , share_access , file_attributes ) ) = = - 1 )
1998-07-08 05:42:05 +04:00
return ( ERROR ( ERRDOS , ERRbadaccess ) ) ;
/*
1998-07-17 02:46:06 +04:00
* Get the file name .
1998-07-08 05:42:05 +04:00
*/
StrnCpy ( fname , params + 53 , fname_len ) ;
1998-07-11 05:25:02 +04:00
fname [ fname_len ] = ' \0 ' ;
1998-07-08 05:42:05 +04:00
1998-07-17 02:46:06 +04:00
/* If it's an IPC, use the pipe handler. */
1998-08-14 21:38:29 +04:00
if ( IS_IPC ( conn ) ) {
1998-08-15 11:27:34 +04:00
int ret = nt_open_pipe ( fname , conn , inbuf , outbuf , & pnum ) ;
1998-07-17 02:46:06 +04:00
if ( ret ! = 0 )
return ret ;
smb_action = FILE_WAS_OPENED ;
} else {
/*
* Check if POSIX semantics are wanted .
*/
set_posix_case_semantics ( file_attributes ) ;
1998-08-28 00:38:53 +04:00
unix_convert ( fname , conn , 0 , & bad_path , NULL ) ;
1998-07-17 02:46:06 +04:00
1998-08-16 06:32:55 +04:00
fsp = file_new ( ) ;
1998-08-15 11:27:34 +04:00
if ( ! fsp ) {
restore_case_semantics ( file_attributes ) ;
return ( ERROR ( ERRSRV , ERRnofids ) ) ;
1998-07-08 05:42:05 +04:00
}
1998-08-14 21:38:29 +04:00
if ( ! check_name ( fname , conn ) ) {
1998-07-17 02:46:06 +04:00
if ( ( errno = = ENOENT ) & & bad_path ) {
unix_ERR_class = ERRDOS ;
unix_ERR_code = ERRbadpath ;
}
1998-08-16 08:08:47 +04:00
file_free ( fsp ) ;
1998-07-08 05:42:05 +04:00
1998-07-17 02:46:06 +04:00
restore_case_semantics ( file_attributes ) ;
return ( UNIXERROR ( ERRDOS , ERRnoaccess ) ) ;
}
1998-07-08 05:42:05 +04:00
1998-08-14 21:38:29 +04:00
unixmode = unix_mode ( conn , smb_attr | aARCH ) ;
1998-07-08 05:42:05 +04:00
1998-07-17 02:46:06 +04:00
oplock_request = ( flags & REQUEST_OPLOCK ) ? EXCLUSIVE_OPLOCK : 0 ;
oplock_request | = ( flags & REQUEST_BATCH_OPLOCK ) ? BATCH_OPLOCK : 0 ;
1998-07-31 01:18:57 +04:00
/*
* If it ' s a request for a directory open , deal with it separately .
*/
1998-07-08 05:42:05 +04:00
1998-09-14 23:49:55 +04:00
if ( create_options & FILE_DIRECTORY_FILE ) {
1998-07-31 01:18:57 +04:00
oplock_request = 0 ;
/*
* We will get a create directory here if the Win32
* app specified a security descriptor in the
* CreateDirectory ( ) call .
*/
1998-08-15 11:27:34 +04:00
open_directory ( fsp , conn , fname , smb_ofun , unixmode , & smb_action ) ;
1998-07-31 01:18:57 +04:00
if ( ! fsp - > open ) {
1998-08-15 11:27:34 +04:00
file_free ( fsp ) ;
1998-07-31 01:18:57 +04:00
return ( UNIXERROR ( ERRDOS , ERRnoaccess ) ) ;
1998-07-17 02:46:06 +04:00
}
1998-07-31 01:18:57 +04:00
} else {
1998-07-08 05:42:05 +04:00
1998-07-31 01:18:57 +04:00
/*
* Ordinary file case .
*/
1998-07-08 05:42:05 +04:00
1998-08-15 11:27:34 +04:00
open_file_shared ( fsp , conn , fname , smb_open_mode , smb_ofun , unixmode ,
1998-07-31 01:18:57 +04:00
oplock_request , & rmode , & smb_action ) ;
1998-07-08 05:42:05 +04:00
1998-07-31 01:18:57 +04:00
if ( ! fsp - > open ) {
if ( ( errno = = ENOENT ) & & bad_path ) {
unix_ERR_class = ERRDOS ;
unix_ERR_code = ERRbadpath ;
}
1998-08-15 11:27:34 +04:00
file_free ( fsp ) ;
1998-07-08 05:42:05 +04:00
1998-07-31 01:18:57 +04:00
restore_case_semantics ( file_attributes ) ;
return ( UNIXERROR ( ERRDOS , ERRnoaccess ) ) ;
}
1998-07-08 05:42:05 +04:00
1998-09-03 22:40:31 +04:00
if ( sys_fstat ( fsp - > fd_ptr - > fd , & sbuf ) ! = 0 ) {
1998-08-15 11:27:34 +04:00
close_file ( fsp , False ) ;
1998-07-08 05:42:05 +04:00
1998-07-31 01:18:57 +04:00
restore_case_semantics ( file_attributes ) ;
return ( ERROR ( ERRDOS , ERRnoaccess ) ) ;
}
1998-07-08 05:42:05 +04:00
1998-07-31 01:18:57 +04:00
file_len = sbuf . st_size ;
1998-08-14 21:38:29 +04:00
fmode = dos_mode ( conn , fname , & sbuf ) ;
1998-07-31 01:18:57 +04:00
if ( fmode = = 0 )
fmode = FILE_ATTRIBUTE_NORMAL ;
if ( fmode & aDIR ) {
1998-08-15 11:27:34 +04:00
close_file ( fsp , False ) ;
1998-07-31 01:18:57 +04:00
restore_case_semantics ( file_attributes ) ;
return ( ERROR ( ERRDOS , ERRnoaccess ) ) ;
}
/*
* If the caller set the extended oplock request bit
* and we granted one ( by whatever means ) - set the
* correct bit for extended oplock reply .
*/
1998-07-08 05:42:05 +04:00
1998-08-14 21:38:29 +04:00
if ( oplock_request & & lp_fake_oplocks ( SNUM ( conn ) ) )
1998-07-31 01:18:57 +04:00
smb_action | = EXTENDED_OPLOCK_GRANTED ;
1998-07-08 05:42:05 +04:00
1998-07-31 01:18:57 +04:00
if ( oplock_request & & fsp - > granted_oplock )
smb_action | = EXTENDED_OPLOCK_GRANTED ;
}
1998-07-17 02:46:06 +04:00
}
1998-07-08 05:42:05 +04:00
1998-07-31 01:18:57 +04:00
restore_case_semantics ( file_attributes ) ;
1998-07-09 04:41:32 +04:00
/* Realloc the size of parameters and data we will return */
1998-07-17 02:46:06 +04:00
params = * ppparams = Realloc ( * ppparams , 69 ) ;
1998-07-09 04:41:32 +04:00
if ( params = = NULL )
return ( ERROR ( ERRDOS , ERRnomem ) ) ;
p = params ;
1998-07-17 02:46:06 +04:00
SCVAL ( p , 0 , ( smb_action & EXTENDED_OPLOCK_GRANTED ? 1 : 0 ) ) ;
1998-07-09 04:41:32 +04:00
p + = 2 ;
1998-08-15 11:27:34 +04:00
if ( IS_IPC ( conn ) ) {
SSVAL ( p , 0 , pnum ) ;
} else {
SSVAL ( p , 0 , fsp - > fnum ) ;
}
1998-07-09 04:41:32 +04:00
p + = 2 ;
SIVAL ( p , 0 , smb_action ) ;
p + = 8 ;
1998-07-17 02:46:06 +04:00
1998-08-14 21:38:29 +04:00
if ( IS_IPC ( conn ) ) {
1998-07-17 02:46:06 +04:00
/*
* Deal with pipe return .
*/
p + = 32 ;
SIVAL ( p , 0 , FILE_ATTRIBUTE_NORMAL ) ; /* File Attributes. */
p + = 20 ;
/* File type. */
SSVAL ( p , 0 , FILE_TYPE_MESSAGE_MODE_PIPE ) ;
/* Device state. */
SSVAL ( p , 2 , 0x5FF ) ; /* ? */
} else {
/*
* Deal with file return .
*/
/* Create time. */
1998-08-14 21:38:29 +04:00
put_long_date ( p , get_create_time ( & sbuf , lp_fake_dir_create_times ( SNUM ( conn ) ) ) ) ;
1998-07-17 02:46:06 +04:00
p + = 8 ;
put_long_date ( p , sbuf . st_atime ) ; /* access time */
p + = 8 ;
put_long_date ( p , sbuf . st_mtime ) ; /* write time */
p + = 8 ;
put_long_date ( p , sbuf . st_mtime ) ; /* change time */
p + = 8 ;
SIVAL ( p , 0 , fmode ) ; /* File Attributes. */
1998-09-12 01:42:18 +04:00
p + = 4 ;
# ifdef LARGE_SMB_OFF_T
SIVAL ( p , 0 , file_len ) ;
SIVAL ( p , 4 , ( file_len > > 32 ) ) ;
# else /* LARGE_SMB_OFF_T */
SIVAL ( p , 0 , file_len ) ;
# endif /* LARGE_SMB_OFF_T */
p + = 8 ;
1998-09-11 05:24:30 +04:00
# ifdef LARGE_SMB_OFF_T
1998-09-12 01:42:18 +04:00
SIVAL ( p , 0 , file_len ) ;
1998-09-11 05:24:30 +04:00
SIVAL ( p , 4 , ( file_len > > 32 ) ) ;
# else /* LARGE_SMB_OFF_T */
SIVAL ( p , 0 , file_len ) ;
# endif /* LARGE_SMB_OFF_T */
1998-07-17 02:46:06 +04:00
}
1998-07-09 04:41:32 +04:00
/* Send the required number of replies */
send_nt_replies ( outbuf , bufsize , params , 69 , * ppdata , 0 ) ;
return - 1 ;
1998-07-02 22:49:08 +04:00
}
1998-05-08 05:22:16 +04:00
/****************************************************************************
1998-08-03 23:07:55 +04:00
Reply to a NT CANCEL request .
1998-07-08 05:42:05 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-14 21:38:29 +04:00
int reply_ntcancel ( connection_struct * conn ,
char * inbuf , char * outbuf , int length , int bufsize )
1998-07-08 05:42:05 +04:00
{
1998-08-14 21:38:29 +04:00
/*
* Go through and cancel any pending change notifies .
*/
int mid = SVAL ( inbuf , smb_mid ) ;
remove_pending_change_notify_requests_by_mid ( mid ) ;
1998-08-19 05:49:34 +04:00
remove_pending_lock_requests_by_mid ( mid ) ;
1998-08-14 21:38:29 +04:00
DEBUG ( 3 , ( " reply_ntcancel: cancel called on mid = %d. \n " , mid ) ) ;
return ( - 1 ) ;
1998-07-08 05:42:05 +04:00
}
/****************************************************************************
Reply to an unsolicited SMBNTtranss - just ignore it !
1998-05-08 05:22:16 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-14 21:38:29 +04:00
int reply_nttranss ( connection_struct * conn ,
char * inbuf , char * outbuf , int length , int bufsize )
1998-05-08 05:22:16 +04:00
{
1998-08-14 21:38:29 +04:00
DEBUG ( 4 , ( " Ignoring nttranss of length %d \n " , length ) ) ;
return ( - 1 ) ;
1998-05-08 05:22:16 +04:00
}
/****************************************************************************
1998-07-08 05:42:05 +04:00
Reply to an NT transact rename command .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-14 21:38:29 +04:00
static int call_nt_transact_rename ( connection_struct * conn ,
char * inbuf , char * outbuf , int length ,
int bufsize ,
1998-07-17 02:46:06 +04:00
char * * ppsetup , char * * ppparams , char * * ppdata )
1998-07-08 05:42:05 +04:00
{
1998-07-17 02:46:06 +04:00
char * params = * ppparams ;
1998-07-11 04:28:34 +04:00
pstring new_name ;
1998-08-17 07:52:05 +04:00
files_struct * fsp = file_fsp ( params , 0 ) ;
1998-07-11 05:25:02 +04:00
BOOL replace_if_exists = ( SVAL ( params , 2 ) & RENAME_REPLACE_IF_EXISTS ) ? True : False ;
1998-07-08 05:42:05 +04:00
uint32 fname_len = MIN ( ( ( ( uint32 ) IVAL ( inbuf , smb_nt_TotalParameterCount ) - 4 ) ) ,
1998-07-17 02:46:06 +04:00
( ( uint32 ) sizeof ( new_name ) - 1 ) ) ;
1998-07-11 05:25:02 +04:00
int outsize = 0 ;
1998-07-08 05:42:05 +04:00
1998-08-15 11:27:34 +04:00
CHECK_FSP ( fsp , conn ) ;
1998-07-11 04:28:34 +04:00
StrnCpy ( new_name , params + 4 , fname_len ) ;
1998-07-11 05:25:02 +04:00
new_name [ fname_len ] = ' \0 ' ;
1998-07-11 04:28:34 +04:00
1998-08-15 11:27:34 +04:00
outsize = rename_internals ( conn , inbuf , outbuf , fsp - > fsp_name ,
1998-07-17 02:46:06 +04:00
new_name , replace_if_exists ) ;
1998-07-11 05:25:02 +04:00
if ( outsize = = 0 ) {
/*
* Rename was successful .
*/
send_nt_replies ( outbuf , bufsize , NULL , 0 , NULL , 0 ) ;
1998-08-03 23:07:55 +04:00
DEBUG ( 3 , ( " nt transact rename from = %s, to = %s succeeded. \n " ,
1998-08-15 11:27:34 +04:00
fsp - > fsp_name , new_name ) ) ;
1998-08-03 23:07:55 +04:00
1998-07-11 05:25:02 +04:00
outsize = - 1 ;
}
return ( outsize ) ;
1998-07-08 05:42:05 +04:00
}
/****************************************************************************
1998-08-03 23:07:55 +04:00
This is the structure to queue to implement NT change
notify . It consists of smb_size bytes stored from the
transact command ( to keep the mid , tid etc around ) .
Plus the fid to examine and the time to check next .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
typedef struct {
ubi_slNode msg_next ;
1998-08-15 11:27:34 +04:00
files_struct * fsp ;
1998-08-14 21:38:29 +04:00
connection_struct * conn ;
1998-08-03 23:07:55 +04:00
time_t next_check_time ;
1998-08-12 03:28:35 +04:00
time_t modify_time ; /* Info from the directory we're monitoring. */
time_t status_time ; /* Info from the directory we're monitoring. */
1998-08-03 23:07:55 +04:00
char request_buf [ smb_size ] ;
} change_notify_buf ;
static ubi_slList change_notify_queue = { NULL , ( ubi_slNodePtr ) & change_notify_queue , 0 } ;
/****************************************************************************
Setup the common parts of the return packet and send it .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void change_notify_reply_packet ( char * inbuf , int error_class , uint32 error_code )
{
extern int Client ;
1998-08-12 03:28:35 +04:00
char outbuf [ smb_size + 38 ] ;
1998-08-03 23:07:55 +04:00
1998-08-12 03:28:35 +04:00
memset ( outbuf , ' \0 ' , sizeof ( outbuf ) ) ;
1998-08-04 05:01:26 +04:00
construct_reply_common ( inbuf , outbuf ) ;
1998-08-03 23:07:55 +04:00
1998-08-11 06:13:01 +04:00
/*
* If we ' re returning a ' too much in the directory changed ' we need to
* set this is an NT error status flags . If we don ' t then the ( probably
* untested ) code in the NT redirector has a bug in that it doesn ' t re - issue
* the change notify . . . . Ah - I * love * it when I get so deeply into this I
* can even determine how MS failed to test stuff and why . . . . : - ) . JRA .
*/
1998-08-12 03:28:35 +04:00
if ( error_class = = 0 ) /* NT Error. */
1998-08-11 06:13:01 +04:00
SSVAL ( outbuf , smb_flg2 , SVAL ( outbuf , smb_flg2 ) | FLAGS2_32_BIT_ERROR_CODES ) ;
1998-08-03 23:07:55 +04:00
ERROR ( error_class , error_code ) ;
1998-08-12 03:28:35 +04:00
/*
* Seems NT needs a transact command with an error code
* in it . This is a longer packet than a simple error .
*/
set_message ( outbuf , 18 , 0 , False ) ;
1998-08-03 23:07:55 +04:00
send_smb ( Client , outbuf ) ;
}
/****************************************************************************
Delete entries by fnum from the change notify pending queue .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-15 11:27:34 +04:00
void remove_pending_change_notify_requests_by_fid ( files_struct * fsp )
1998-08-03 23:07:55 +04:00
{
change_notify_buf * cnbp = ( change_notify_buf * ) ubi_slFirst ( & change_notify_queue ) ;
change_notify_buf * prev = NULL ;
while ( cnbp ! = NULL ) {
1998-08-21 05:30:29 +04:00
if ( cnbp - > fsp - > fnum = = fsp - > fnum ) {
1998-08-06 02:17:51 +04:00
free ( ( char * ) ubi_slRemNext ( & change_notify_queue , prev ) ) ;
1998-08-03 23:07:55 +04:00
cnbp = ( change_notify_buf * ) ( prev ? ubi_slNext ( prev ) : ubi_slFirst ( & change_notify_queue ) ) ;
continue ;
}
prev = cnbp ;
cnbp = ( change_notify_buf * ) ubi_slNext ( cnbp ) ;
}
}
/****************************************************************************
Delete entries by mid from the change notify pending queue . Always send reply .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-09-05 09:07:05 +04:00
static void remove_pending_change_notify_requests_by_mid ( int mid )
1998-08-03 23:07:55 +04:00
{
change_notify_buf * cnbp = ( change_notify_buf * ) ubi_slFirst ( & change_notify_queue ) ;
change_notify_buf * prev = NULL ;
while ( cnbp ! = NULL ) {
if ( SVAL ( cnbp - > request_buf , smb_mid ) = = mid ) {
1998-08-12 03:28:35 +04:00
change_notify_reply_packet ( cnbp - > request_buf , 0 , NT_STATUS_CANCELLED ) ;
1998-08-06 02:17:51 +04:00
free ( ( char * ) ubi_slRemNext ( & change_notify_queue , prev ) ) ;
1998-08-03 23:07:55 +04:00
cnbp = ( change_notify_buf * ) ( prev ? ubi_slNext ( prev ) : ubi_slFirst ( & change_notify_queue ) ) ;
continue ;
}
prev = cnbp ;
cnbp = ( change_notify_buf * ) ubi_slNext ( cnbp ) ;
}
}
/****************************************************************************
Process the change notify queue . Note that this is only called as root .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void process_pending_change_notify_queue ( time_t t )
{
change_notify_buf * cnbp = ( change_notify_buf * ) ubi_slFirst ( & change_notify_queue ) ;
change_notify_buf * prev = NULL ;
if ( cnbp = = NULL )
return ;
if ( cnbp - > next_check_time > = t )
return ;
/*
* It ' s time to check . Go through the queue and see if
* the timestamps changed .
*/
while ( ( cnbp ! = NULL ) & & ( cnbp - > next_check_time < = t ) ) {
1998-09-02 00:11:54 +04:00
SMB_STRUCT_STAT st ;
1998-08-15 11:27:34 +04:00
files_struct * fsp = cnbp - > fsp ;
1998-08-14 21:38:29 +04:00
connection_struct * conn = cnbp - > conn ;
1998-08-03 23:07:55 +04:00
uint16 vuid = ( lp_security ( ) = = SEC_SHARE ) ? UID_FIELD_INVALID :
SVAL ( cnbp - > request_buf , smb_uid ) ;
1998-08-21 05:30:29 +04:00
/*
* Ensure we don ' t have any old chain_fsp values
* sitting around . . . .
*/
chain_size = 0 ;
file_chain_reset ( ) ;
1998-08-14 21:38:29 +04:00
if ( ! become_user ( conn , vuid ) ) {
1998-08-03 23:07:55 +04:00
DEBUG ( 0 , ( " process_pending_change_notify_queue: Unable to become user vuid=%d. \n " ,
vuid ) ) ;
/*
* Remove the entry and return an error to the client .
*/
change_notify_reply_packet ( cnbp - > request_buf , ERRSRV , ERRaccess ) ;
1998-08-06 02:17:51 +04:00
free ( ( char * ) ubi_slRemNext ( & change_notify_queue , prev ) ) ;
1998-08-03 23:07:55 +04:00
cnbp = ( change_notify_buf * ) ( prev ? ubi_slNext ( prev ) : ubi_slFirst ( & change_notify_queue ) ) ;
continue ;
}
1998-08-14 21:38:29 +04:00
if ( ! become_service ( conn , True ) ) {
DEBUG ( 0 , ( " process_pending_change_notify_queue: Unable to become service Error was %s. \n " , strerror ( errno ) ) ) ;
1998-08-05 03:45:34 +04:00
/*
* Remove the entry and return an error to the client .
*/
change_notify_reply_packet ( cnbp - > request_buf , ERRSRV , ERRaccess ) ;
1998-08-06 02:17:51 +04:00
free ( ( char * ) ubi_slRemNext ( & change_notify_queue , prev ) ) ;
1998-08-05 03:45:34 +04:00
cnbp = ( change_notify_buf * ) ( prev ? ubi_slNext ( prev ) : ubi_slFirst ( & change_notify_queue ) ) ;
unbecome_user ( ) ;
continue ;
}
1998-09-02 00:11:54 +04:00
if ( dos_stat ( fsp - > fsp_name , & st ) < 0 ) {
1998-08-03 23:07:55 +04:00
DEBUG ( 0 , ( " process_pending_change_notify_queue: Unable to stat directory %s. \
1998-08-14 21:38:29 +04:00
Error was % s . \ n " , fsp->fsp_name, strerror(errno) ));
1998-08-03 23:07:55 +04:00
/*
* Remove the entry and return an error to the client .
*/
change_notify_reply_packet ( cnbp - > request_buf , ERRSRV , ERRaccess ) ;
1998-08-06 02:17:51 +04:00
free ( ( char * ) ubi_slRemNext ( & change_notify_queue , prev ) ) ;
1998-08-03 23:07:55 +04:00
cnbp = ( change_notify_buf * ) ( prev ? ubi_slNext ( prev ) : ubi_slFirst ( & change_notify_queue ) ) ;
unbecome_user ( ) ;
continue ;
}
1998-08-12 03:28:35 +04:00
if ( cnbp - > modify_time ! = st . st_mtime | |
cnbp - > status_time ! = st . st_ctime ) {
1998-08-03 23:07:55 +04:00
/*
* Remove the entry and return a change notify to the client .
*/
1998-08-15 11:27:34 +04:00
DEBUG ( 5 , ( " process_pending_change_notify_queue: directory name = %s changed \n " ,
fsp - > fsp_name ) ) ;
1998-08-11 06:13:01 +04:00
change_notify_reply_packet ( cnbp - > request_buf , 0 , NT_STATUS_NOTIFY_ENUM_DIR ) ;
1998-08-06 02:17:51 +04:00
free ( ( char * ) ubi_slRemNext ( & change_notify_queue , prev ) ) ;
1998-08-03 23:07:55 +04:00
cnbp = ( change_notify_buf * ) ( prev ? ubi_slNext ( prev ) : ubi_slFirst ( & change_notify_queue ) ) ;
unbecome_user ( ) ;
continue ;
}
unbecome_user ( ) ;
/*
* Move to the next in the list .
*/
prev = cnbp ;
cnbp = ( change_notify_buf * ) ubi_slNext ( cnbp ) ;
}
}
/****************************************************************************
Reply to a notify change - queue the request and
1998-07-08 05:42:05 +04:00
don ' t allow a directory to be opened .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-14 21:38:29 +04:00
static int call_nt_transact_notify_change ( connection_struct * conn ,
char * inbuf , char * outbuf , int length ,
int bufsize ,
char * * ppsetup ,
char * * ppparams , char * * ppdata )
1998-07-08 05:42:05 +04:00
{
1998-08-03 23:07:55 +04:00
char * setup = * ppsetup ;
files_struct * fsp ;
change_notify_buf * cnbp ;
1998-09-02 00:11:54 +04:00
SMB_STRUCT_STAT st ;
1998-08-03 23:07:55 +04:00
1998-08-17 07:52:05 +04:00
fsp = file_fsp ( setup , 4 ) ;
1998-08-03 23:07:55 +04:00
1998-08-15 11:27:34 +04:00
DEBUG ( 3 , ( " call_nt_transact_notify_change \n " ) ) ;
1998-08-03 23:07:55 +04:00
1998-08-15 11:27:34 +04:00
if ( ! fsp )
1998-08-03 23:07:55 +04:00
return ( ERROR ( ERRDOS , ERRbadfid ) ) ;
1998-08-14 21:38:29 +04:00
if ( ( ! fsp - > open ) | | ( ! fsp - > is_directory ) | | ( conn ! = fsp - > conn ) )
1998-08-03 23:07:55 +04:00
return ( ERROR ( ERRDOS , ERRbadfid ) ) ;
/*
* Now queue an entry on the notify change stack . We timestamp
* the entry we are adding so that we know when to scan next .
* We only need to save smb_size bytes from this incoming packet
* as we will always by returning a ' read the directory yourself '
* error .
*/
if ( ( cnbp = ( change_notify_buf * ) malloc ( sizeof ( change_notify_buf ) ) ) = = NULL ) {
DEBUG ( 0 , ( " call_nt_transact_notify_change: Malloc fail (2) ! \n " ) ) ;
return - 1 ;
}
1998-08-12 03:28:35 +04:00
/*
* Store the current timestamp on the directory we are monitoring .
*/
1998-09-02 00:11:54 +04:00
if ( dos_stat ( fsp - > fsp_name , & st ) < 0 ) {
1998-08-15 11:27:34 +04:00
DEBUG ( 0 , ( " call_nt_transact_notify_change: Unable to stat name = %s. \
Error was % s \ n " , fsp->fsp_name, strerror(errno) ));
1998-08-12 03:28:35 +04:00
free ( ( char * ) cnbp ) ;
return ( UNIXERROR ( ERRDOS , ERRbadfid ) ) ;
}
1998-08-03 23:07:55 +04:00
memcpy ( cnbp - > request_buf , inbuf , smb_size ) ;
1998-08-15 11:27:34 +04:00
cnbp - > fsp = fsp ;
1998-08-14 21:38:29 +04:00
cnbp - > conn = conn ;
1998-08-12 03:28:35 +04:00
cnbp - > modify_time = st . st_mtime ;
cnbp - > status_time = st . st_ctime ;
1998-08-03 23:07:55 +04:00
cnbp - > next_check_time = time ( NULL ) + lp_change_notify_timeout ( ) ;
/*
* Adding to the tail enables us to check only
* the head when scanning for change , as this entry
* is forced to have the first timeout expiration .
*/
ubi_slAddTail ( & change_notify_queue , cnbp ) ;
1998-08-05 03:45:34 +04:00
DEBUG ( 3 , ( " call_nt_transact_notify_change: notify change called on directory \
1998-08-15 11:27:34 +04:00
name = % s \ n " , fsp->fsp_name ));
1998-08-03 23:07:55 +04:00
return - 1 ;
1998-07-08 05:42:05 +04:00
}
1998-08-03 23:07:55 +04:00
1998-07-08 05:42:05 +04:00
/****************************************************************************
Reply to query a security descriptor - currently this is not implemented ( it
is planned to be though ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-14 21:38:29 +04:00
static int call_nt_transact_query_security_desc ( connection_struct * conn ,
char * inbuf , char * outbuf ,
int length ,
int bufsize ,
1998-07-17 02:46:06 +04:00
char * * ppsetup , char * * ppparams , char * * ppdata )
1998-07-08 05:42:05 +04:00
{
DEBUG ( 0 , ( " call_nt_transact_query_security_desc: Currently not implemented. \n " ) ) ;
return ( ERROR ( ERRSRV , ERRnosupport ) ) ;
}
/****************************************************************************
Reply to set a security descriptor - currently this is not implemented ( it
is planned to be though ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-14 21:38:29 +04:00
static int call_nt_transact_set_security_desc ( connection_struct * conn ,
char * inbuf , char * outbuf ,
int length ,
int bufsize ,
char * * ppsetup ,
char * * ppparams , char * * ppdata )
1998-07-08 05:42:05 +04:00
{
1998-08-14 21:38:29 +04:00
DEBUG ( 0 , ( " call_nt_transact_set_security_desc: Currently not implemented. \n " ) ) ;
return ( ERROR ( ERRSRV , ERRnosupport ) ) ;
1998-07-08 05:42:05 +04:00
}
/****************************************************************************
Reply to IOCTL - not implemented - no plans .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-14 21:38:29 +04:00
static int call_nt_transact_ioctl ( connection_struct * conn ,
char * inbuf , char * outbuf , int length ,
int bufsize ,
1998-07-17 02:46:06 +04:00
char * * ppsetup , char * * ppparams , char * * ppdata )
1998-07-08 05:42:05 +04:00
{
1998-08-17 07:06:20 +04:00
DEBUG ( 0 , ( " call_nt_transact_ioctl: Currently not implemented. \n " ) ) ;
return ( ERROR ( ERRSRV , ERRnosupport ) ) ;
1998-07-08 05:42:05 +04:00
}
/****************************************************************************
Reply to a SMBNTtrans .
1998-05-08 05:22:16 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-14 21:38:29 +04:00
int reply_nttrans ( connection_struct * conn ,
char * inbuf , char * outbuf , int length , int bufsize )
1998-05-08 05:22:16 +04:00
{
1998-08-03 23:07:55 +04:00
int outsize = 0 ;
1998-07-02 22:49:08 +04:00
#if 0 /* Not used. */
1998-05-08 05:22:16 +04:00
uint16 max_setup_count = CVAL ( inbuf , smb_nt_MaxSetupCount ) ;
uint32 max_parameter_count = IVAL ( inbuf , smb_nt_MaxParameterCount ) ;
uint32 max_data_count = IVAL ( inbuf , smb_nt_MaxDataCount ) ;
1998-07-02 22:49:08 +04:00
# endif /* Not used. */
1998-05-08 05:22:16 +04:00
uint32 total_parameter_count = IVAL ( inbuf , smb_nt_TotalParameterCount ) ;
uint32 total_data_count = IVAL ( inbuf , smb_nt_TotalDataCount ) ;
uint32 parameter_count = IVAL ( inbuf , smb_nt_ParameterCount ) ;
uint32 parameter_offset = IVAL ( inbuf , smb_nt_ParameterOffset ) ;
uint32 data_count = IVAL ( inbuf , smb_nt_DataCount ) ;
uint32 data_offset = IVAL ( inbuf , smb_nt_DataOffset ) ;
1998-08-03 23:07:55 +04:00
uint16 setup_count = 2 * CVAL ( inbuf , smb_nt_SetupCount ) ; /* setup count is in *words* */
1998-05-08 05:22:16 +04:00
uint16 function_code = SVAL ( inbuf , smb_nt_Function ) ;
char * params = NULL , * data = NULL , * setup = NULL ;
uint32 num_params_sofar , num_data_sofar ;
if ( global_oplock_break & & ( function_code = = NT_TRANSACT_CREATE ) ) {
/*
* Queue this open message as we are the process of an oplock break .
*/
1998-08-03 23:07:55 +04:00
DEBUG ( 2 , ( " reply_nttrans: queueing message NT_TRANSACT_CREATE \
due to being in oplock break state . \ n " ));
1998-05-08 05:22:16 +04:00
1998-07-31 01:18:57 +04:00
push_oplock_pending_smb_message ( inbuf , length ) ;
1998-05-08 05:22:16 +04:00
return - 1 ;
}
outsize = set_message ( outbuf , 0 , 0 , True ) ;
/*
1998-07-17 02:46:06 +04:00
* All nttrans messages we handle have smb_wct = = 19 + setup_count .
1998-05-08 05:22:16 +04:00
* Ensure this is so as a sanity check .
*/
1998-08-03 23:07:55 +04:00
if ( CVAL ( inbuf , smb_wct ) ! = 19 + ( setup_count / 2 ) ) {
1998-07-17 02:46:06 +04:00
DEBUG ( 2 , ( " Invalid smb_wct %d in nttrans call (should be %d) \n " ,
1998-08-03 23:07:55 +04:00
CVAL ( inbuf , smb_wct ) , 19 + ( setup_count / 2 ) ) ) ;
1998-05-08 05:22:16 +04:00
return ( ERROR ( ERRSRV , ERRerror ) ) ;
}
/* Allocate the space for the setup, the maximum needed parameters and data */
if ( setup_count > 0 )
setup = ( char * ) malloc ( setup_count ) ;
if ( total_parameter_count > 0 )
params = ( char * ) malloc ( total_parameter_count ) ;
if ( total_data_count > 0 )
data = ( char * ) malloc ( total_data_count ) ;
if ( ( total_parameter_count & & ! params ) | | ( total_data_count & & ! data ) | |
( setup_count & & ! setup ) ) {
DEBUG ( 0 , ( " reply_nttrans : Out of memory \n " ) ) ;
return ( ERROR ( ERRDOS , ERRnomem ) ) ;
}
/* Copy the param and data bytes sent with this request into
the params buffer */
num_params_sofar = parameter_count ;
num_data_sofar = data_count ;
if ( parameter_count > total_parameter_count | | data_count > total_data_count )
exit_server ( " reply_nttrans: invalid sizes in packet. \n " ) ;
1998-08-03 23:07:55 +04:00
if ( setup ) {
1998-05-08 05:22:16 +04:00
memcpy ( setup , & inbuf [ smb_nt_SetupStart ] , setup_count ) ;
1998-08-03 23:07:55 +04:00
DEBUG ( 10 , ( " reply_nttrans: setup_count = %d \n " , setup_count ) ) ;
dump_data ( 10 , setup , setup_count ) ;
}
if ( params ) {
1998-05-08 05:22:16 +04:00
memcpy ( params , smb_base ( inbuf ) + parameter_offset , parameter_count ) ;
1998-08-03 23:07:55 +04:00
DEBUG ( 10 , ( " reply_nttrans: parameter_count = %d \n " , parameter_count ) ) ;
dump_data ( 10 , params , parameter_count ) ;
}
if ( data ) {
1998-05-08 05:22:16 +04:00
memcpy ( data , smb_base ( inbuf ) + data_offset , data_count ) ;
1998-08-03 23:07:55 +04:00
DEBUG ( 10 , ( " reply_nttrans: data_count = %d \n " , data_count ) ) ;
dump_data ( 10 , data , data_count ) ;
}
1998-05-08 05:22:16 +04:00
if ( num_data_sofar < total_data_count | | num_params_sofar < total_parameter_count ) {
/* We need to send an interim response then receive the rest
of the parameter / data bytes */
outsize = set_message ( outbuf , 0 , 0 , True ) ;
send_smb ( Client , outbuf ) ;
while ( num_data_sofar < total_data_count | | num_params_sofar < total_parameter_count ) {
BOOL ret ;
ret = receive_next_smb ( Client , oplock_sock , inbuf , bufsize ,
SMB_SECONDARY_WAIT ) ;
if ( ( ret & & ( CVAL ( inbuf , smb_com ) ! = SMBnttranss ) ) | | ! ret ) {
outsize = set_message ( outbuf , 0 , 0 , True ) ;
1998-08-09 17:25:34 +04:00
if ( ret ) {
DEBUG ( 0 , ( " reply_nttrans: Invalid secondary nttrans packet \n " ) ) ;
} else {
DEBUG ( 0 , ( " reply_nttrans: %s in getting secondary nttrans response. \n " ,
( smb_read_error = = READ_ERROR ) ? " error " : " timeout " ) ) ;
}
1998-05-08 05:22:16 +04:00
if ( params )
free ( params ) ;
if ( data )
free ( data ) ;
if ( setup )
free ( setup ) ;
return ( ERROR ( ERRSRV , ERRerror ) ) ;
}
/* Revise total_params and total_data in case they have changed downwards */
1998-07-08 05:42:05 +04:00
total_parameter_count = IVAL ( inbuf , smb_nts_TotalParameterCount ) ;
total_data_count = IVAL ( inbuf , smb_nts_TotalDataCount ) ;
num_params_sofar + = ( parameter_count = IVAL ( inbuf , smb_nts_ParameterCount ) ) ;
num_data_sofar + = ( data_count = IVAL ( inbuf , smb_nts_DataCount ) ) ;
1998-05-08 05:22:16 +04:00
if ( num_params_sofar > total_parameter_count | | num_data_sofar > total_data_count )
exit_server ( " reply_nttrans2: data overflow in secondary nttrans packet \n " ) ;
1998-07-08 05:42:05 +04:00
memcpy ( & params [ IVAL ( inbuf , smb_nts_ParameterDisplacement ) ] ,
smb_base ( inbuf ) + IVAL ( inbuf , smb_nts_ParameterOffset ) , parameter_count ) ;
memcpy ( & data [ IVAL ( inbuf , smb_nts_DataDisplacement ) ] ,
smb_base ( inbuf ) + IVAL ( inbuf , smb_nts_DataOffset ) , data_count ) ;
1998-05-08 05:22:16 +04:00
}
}
if ( Protocol > = PROTOCOL_NT1 ) {
uint16 flg2 = SVAL ( outbuf , smb_flg2 ) ;
SSVAL ( outbuf , smb_flg2 , flg2 | 0x40 ) ; /* IS_LONG_NAME */
}
1998-05-08 20:59:30 +04:00
/* Now we must call the relevant NT_TRANS function */
switch ( function_code ) {
1998-05-08 05:22:16 +04:00
case NT_TRANSACT_CREATE :
1998-08-14 21:38:29 +04:00
outsize = call_nt_transact_create ( conn , inbuf , outbuf , length , bufsize ,
1998-05-08 05:22:16 +04:00
& setup , & params , & data ) ;
break ;
case NT_TRANSACT_IOCTL :
1998-08-14 21:38:29 +04:00
outsize = call_nt_transact_ioctl ( conn ,
inbuf , outbuf , length , bufsize ,
1998-05-08 05:22:16 +04:00
& setup , & params , & data ) ;
break ;
case NT_TRANSACT_SET_SECURITY_DESC :
1998-08-14 21:38:29 +04:00
outsize = call_nt_transact_set_security_desc ( conn , inbuf , outbuf ,
length , bufsize ,
1998-05-08 05:22:16 +04:00
& setup , & params , & data ) ;
break ;
case NT_TRANSACT_NOTIFY_CHANGE :
1998-08-14 21:38:29 +04:00
outsize = call_nt_transact_notify_change ( conn , inbuf , outbuf ,
length , bufsize ,
1998-05-08 05:22:16 +04:00
& setup , & params , & data ) ;
break ;
case NT_TRANSACT_RENAME :
1998-08-14 21:38:29 +04:00
outsize = call_nt_transact_rename ( conn , inbuf , outbuf , length ,
bufsize ,
1998-05-08 05:22:16 +04:00
& setup , & params , & data ) ;
break ;
1998-08-14 21:38:29 +04:00
1998-05-08 05:22:16 +04:00
case NT_TRANSACT_QUERY_SECURITY_DESC :
1998-08-14 21:38:29 +04:00
outsize = call_nt_transact_query_security_desc ( conn , inbuf , outbuf ,
length , bufsize ,
1998-07-17 02:46:06 +04:00
& setup , & params , & data ) ;
1998-05-08 05:22:16 +04:00
break ;
1998-08-14 21:38:29 +04:00
default :
/* Error in request */
DEBUG ( 0 , ( " reply_nttrans: Unknown request %d in nttrans call \n " , function_code ) ) ;
if ( setup )
free ( setup ) ;
if ( params )
free ( params ) ;
if ( data )
free ( data ) ;
return ( ERROR ( ERRSRV , ERRerror ) ) ;
1998-05-08 20:59:30 +04:00
}
1998-05-08 05:22:16 +04:00
/* As we do not know how many data packets will need to be
returned here the various call_nt_transact_xxxx calls
must send their own . Thus a call_nt_transact_xxxx routine only
returns a value other than - 1 when it wants to send
an error packet .
*/
if ( setup )
free ( setup ) ;
if ( params )
free ( params ) ;
if ( data )
free ( data ) ;
return outsize ; /* If a correct response was needed the call_nt_transact_xxxx
calls have already sent it . If outsize ! = - 1 then it is
returning an error packet . */
}