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"
extern int DEBUGLEVEL ;
extern int Protocol ;
extern int smb_read_error ;
extern int global_oplock_break ;
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-05-08 20:59:30 +04:00
static char * known_nt_pipes [ ] = {
" \\ LANMAN " ,
" \\ srvsvc " ,
" \\ samr " ,
" \\ wkssvc " ,
" \\ NETLOGON " ,
" \\ ntlsa " ,
" \\ ntsvcs " ,
" \\ lsass " ,
" \\ lsarpc " ,
1998-09-24 01:49:09 +04:00
" \\ winreg " ,
2000-02-07 19:22:16 +03:00
" \\ spoolss " ,
2000-05-26 21:10:40 +04:00
# ifdef WITH_MSDFS
2000-05-18 22:43:53 +04:00
" \\ netdfs " ,
# endif
1998-05-08 20:59:30 +04:00
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
1999-12-13 16:27:58 +03:00
static int send_nt_replies ( char * inbuf , char * outbuf , int bufsize , uint32 nt_error , char * params ,
1998-07-09 04:41:32 +04:00
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 ) ;
1999-12-13 16:27:58 +03:00
if ( nt_error ! = 0 ) {
/* NT Error. */
SSVAL ( outbuf , smb_flg2 , SVAL ( outbuf , smb_flg2 ) | FLAGS2_32_BIT_ERROR_CODES ) ;
ERROR ( 0 , nt_error ) ;
}
1998-07-09 04:41:32 +04:00
/*
* If there genuinely are no parameters or data to send just send
* the empty packet .
*/
if ( params_to_send = = 0 & & data_to_send = = 0 ) {
2000-04-11 17:55:53 +04:00
send_smb ( smbd_server_fd ( ) , outbuf ) ;
1998-07-09 04:41:32 +04:00
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 */
2000-04-11 17:55:53 +04:00
send_smb ( smbd_server_fd ( ) , outbuf ) ;
1998-07-09 04:41:32 +04:00
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-10-22 20:55:03 +04:00
int ret ;
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-10-23 04:58:28 +04:00
ret = ( FILE_CREATE_IF_NOT_EXIST | FILE_EXISTS_FAIL ) ;
1998-10-22 20:55:03 +04:00
break ;
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-10-23 04:58:28 +04:00
ret = ( FILE_CREATE_IF_NOT_EXIST | FILE_EXISTS_TRUNCATE ) ;
1998-10-22 20:55:03 +04:00
break ;
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-10-23 04:58:28 +04:00
ret = ( FILE_FAIL_IF_NOT_EXIST | FILE_EXISTS_OPEN ) ;
1998-10-22 20:55:03 +04:00
break ;
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-10-23 04:58:28 +04:00
ret = ( FILE_CREATE_IF_NOT_EXIST | FILE_EXISTS_OPEN ) ;
1998-10-22 20:55:03 +04:00
break ;
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-10-23 04:58:28 +04:00
ret = ( FILE_FAIL_IF_NOT_EXIST | FILE_EXISTS_TRUNCATE ) ;
1998-10-22 20:55:03 +04:00
break ;
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-10-22 20:55:03 +04:00
DEBUG ( 10 , ( " map_create_disposition: Mapped create_disposition %lx to %x \n " ,
( unsigned long ) create_disposition , ret ) ) ;
return ret ;
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 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
static int map_share_mode ( BOOL * pstat_open_only , char * fname ,
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
1999-12-13 16:27:58 +03:00
* pstat_open_only = False ;
switch ( desired_access & ( FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA ) ) {
1998-07-01 01:19:40 +04:00
case FILE_READ_DATA :
1998-10-23 04:58:28 +04:00
smb_open_mode = DOS_OPEN_RDONLY ;
1998-07-01 01:19:40 +04:00
break ;
case FILE_WRITE_DATA :
1999-12-13 16:27:58 +03:00
case FILE_APPEND_DATA :
case FILE_WRITE_DATA | FILE_APPEND_DATA :
1998-10-23 04:58:28 +04:00
smb_open_mode = DOS_OPEN_WRONLY ;
1998-07-01 01:19:40 +04:00
break ;
case FILE_READ_DATA | FILE_WRITE_DATA :
1999-12-13 16:27:58 +03:00
case FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA :
case FILE_READ_DATA | FILE_APPEND_DATA :
1998-10-23 04:58:28 +04:00
smb_open_mode = DOS_OPEN_RDWR ;
1998-07-01 01:19:40 +04:00
break ;
1998-07-17 04:47:16 +04:00
}
1998-10-22 20:55:03 +04:00
/*
* NB . For DELETE_ACCESS we should really check the
* directory permissions , as that is what controls
* delete , and for WRITE_DAC_ACCESS we should really
* check the ownership , as that is what controls the
* chmod . Note that this is * NOT * a security hole ( this
* note is for you , Andrew ) as we are not * allowing *
* the access at this point , the actual unlink or
* chown or chmod call would do this . We are just helping
* clients out by telling them if they have a hope
* of any of this succeeding . POSIX acls may still
* deny the real call . JRA .
*/
1998-07-17 04:47:16 +04:00
if ( smb_open_mode = = - 1 ) {
2000-06-09 01:54:50 +04:00
1999-12-13 16:27:58 +03:00
if ( desired_access = = WRITE_DAC_ACCESS | | desired_access = = READ_CONTROL_ACCESS )
* pstat_open_only = True ;
1998-10-22 20:55:03 +04:00
if ( desired_access & ( DELETE_ACCESS | WRITE_DAC_ACCESS | WRITE_OWNER_ACCESS |
FILE_EXECUTE | FILE_READ_ATTRIBUTES |
1999-12-13 16:27:58 +03:00
FILE_READ_EA | FILE_WRITE_EA | SYSTEM_SECURITY_ACCESS |
2000-06-09 23:41:48 +04:00
FILE_WRITE_ATTRIBUTES | READ_CONTROL_ACCESS ) ) {
1998-10-23 04:58:28 +04:00
smb_open_mode = DOS_OPEN_RDONLY ;
2000-06-09 23:41:48 +04:00
} else if ( desired_access = = 0 ) {
/*
* JRA - NT seems to sometimes send desired_access as zero . play it safe
* and map to a stat open .
*/
* pstat_open_only = True ;
smb_open_mode = DOS_OPEN_RDONLY ;
} else {
1998-10-22 20:55:03 +04:00
DEBUG ( 0 , ( " map_share_mode: Incorrect value %lx for desired_access to file %s \n " ,
( unsigned long ) desired_access , fname ) ) ;
1998-07-17 04:47:16 +04:00
return - 1 ;
}
1998-07-01 01:19:40 +04:00
}
1998-10-23 04:58:28 +04:00
/*
* Set the special bit that means allow share delete .
* This is held outside the normal share mode bits at 1 < < 15.
* JRA .
*/
if ( share_access & FILE_SHARE_DELETE )
smb_open_mode | = ALLOW_SHARE_DELETE ;
/* Add in the requested share mode. */
1998-07-01 01:19:40 +04:00
switch ( share_access & ( FILE_SHARE_READ | FILE_SHARE_WRITE ) ) {
case FILE_SHARE_READ :
1998-10-23 04:58:28 +04:00
smb_open_mode | = SET_DENY_MODE ( DENY_WRITE ) ;
1998-07-01 01:19:40 +04:00
break ;
case FILE_SHARE_WRITE :
1998-10-23 04:58:28 +04:00
smb_open_mode | = SET_DENY_MODE ( DENY_READ ) ;
1998-07-01 01:19:40 +04:00
break ;
case ( FILE_SHARE_READ | FILE_SHARE_WRITE ) :
1998-10-23 04:58:28 +04:00
smb_open_mode | = SET_DENY_MODE ( DENY_NONE ) ;
1998-07-01 01:19:40 +04:00
break ;
case FILE_SHARE_NONE :
1998-10-23 04:58:28 +04:00
smb_open_mode | = SET_DENY_MODE ( DENY_ALL ) ;
1998-07-01 01:19:40 +04:00
break ;
}
/*
1998-10-23 04:58:28 +04:00
* Handle an O_SYNC request .
1998-07-01 01:19:40 +04:00
*/
1998-10-23 04:58:28 +04:00
1998-07-01 01:19:40 +04:00
if ( file_attributes & FILE_FLAG_WRITE_THROUGH )
1998-10-23 04:58:28 +04:00
smb_open_mode | = FILE_SYNC_OPENMODE ;
1998-07-01 01:19:40 +04:00
1998-10-22 20:55:03 +04:00
DEBUG ( 10 , ( " map_share_mode: Mapped desired access %lx, share access %lx, file attributes %lx \
to open_mode % x \ n " , (unsigned long)desired_access, (unsigned long)share_access,
( unsigned long ) file_attributes , smb_open_mode ) ) ;
1998-07-08 05:42:05 +04:00
return smb_open_mode ;
}
2000-06-07 05:49:23 +04:00
#if 0
1998-11-20 01:37:33 +03:00
/*
* This is a * disgusting * hack .
* This is * so * bad that even I ' m embarrassed ( and I
* have no shame ) . Here ' s the deal :
* Until we get the correct SPOOLSS code into smbd
* then when we ' re running with NT SMB support then
* NT makes this call with a level of zero , and then
* immediately follows it with an open request to
* the \ \ SRVSVC pipe . If we allow that open to
* succeed then NT barfs when it cannot open the
* \ \ SPOOLSS pipe immediately after and continually
* whines saying " Printer name is invalid " forever
* after . If we cause * JUST THIS NEXT OPEN * of \ \ SRVSVC
* to fail , then NT downgrades to using the downlevel code
* and everything works as well as before . I hate
* myself for adding this code . . . . JRA .
*
* The HACK_FAIL_TIME define allows only a 2
* second window for this to occur , just in
* case . . .
*/
static BOOL fail_next_srvsvc = False ;
static time_t fail_time ;
# define HACK_FAIL_TIME 2 /* In seconds. */
void fail_next_srvsvc_open ( void )
{
1999-12-13 16:27:58 +03:00
/* Check client is WinNT proper; Win2K doesn't like Jeremy's hack - matty */
if ( get_remote_arch ( ) ! = RA_WINNT )
return ;
1998-11-20 01:37:33 +03:00
fail_next_srvsvc = True ;
fail_time = time ( NULL ) ;
1998-11-21 02:22:43 +03:00
DEBUG ( 10 , ( " fail_next_srvsvc_open: setting up timeout close of \\ srvsvc pipe for print fix. \n " ) ) ;
1998-11-20 01:37:33 +03:00
}
1999-12-13 16:27:58 +03:00
/*
* HACK alert . . . . see above - JRA .
*/
BOOL should_fail_next_srvsvc_open ( const char * pipename )
{
DEBUG ( 10 , ( " should_fail_next_srvsvc_open: fail = %d, pipe = %s \n " ,
( int ) fail_next_srvsvc , pipename ) ) ;
if ( fail_next_srvsvc & & ( time ( NULL ) > fail_time + HACK_FAIL_TIME ) ) {
fail_next_srvsvc = False ;
fail_time = ( time_t ) 0 ;
DEBUG ( 10 , ( " should_fail_next_srvsvc_open: End of timeout close of \\ srvsvc pipe for print fix. \n " ) ) ;
}
if ( fail_next_srvsvc & & strequal ( pipename , " srvsvc " ) ) {
fail_next_srvsvc = False ;
DEBUG ( 10 , ( " should_fail_next_srvsvc_open: Deliberately failing open of \\ srvsvc pipe for print fix. \n " ) ) ;
return True ;
}
return False ;
}
2000-06-07 05:49:23 +04:00
# endif
1999-12-13 16:27:58 +03:00
1998-07-08 05:42:05 +04:00
/****************************************************************************
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
2000-06-07 05:49:23 +04:00
#if 0
1999-12-13 16:27:58 +03:00
if ( should_fail_next_srvsvc_open ( fname ) )
return ( ERROR ( ERRSRV , ERRaccess ) ) ;
2000-06-07 05:49:23 +04:00
# endif
1999-12-13 16:27:58 +03: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
}
2000-05-23 21:57:51 +04:00
/****************************************************************************
Reply to an NT create and X call for pipes .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int do_ntcreate_pipe_open ( connection_struct * conn ,
char * inbuf , char * outbuf , int length , int bufsize )
{
pstring fname ;
int ret ;
int pnum = - 1 ;
char * p = NULL ;
2001-03-16 06:53:59 +03:00
srvstr_pull ( inbuf , fname , smb_buf ( inbuf ) , sizeof ( fname ) , - 1 , STR_TERMINATE | STR_CONVERT ) ;
2000-05-23 21:57:51 +04:00
if ( ( ret = nt_open_pipe ( fname , conn , inbuf , outbuf , & pnum ) ) ! = 0 )
return ret ;
/*
* 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 ) ; /* ? */
DEBUG ( 5 , ( " do_ntcreate_pipe_open: open pipe = %s \n " , fname ) ) ;
return chain_reply ( inbuf , outbuf , length , bufsize ) ;
}
1998-07-08 05:42:05 +04:00
/****************************************************************************
Reply to an NT create and X call .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-09-30 23:27:04 +04:00
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
{
2000-10-11 09:31:39 +04:00
int result ;
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-10-09 23:34:57 +04:00
uint16 root_dir_fid = ( uint16 ) IVAL ( inbuf , smb_ntcreate_RootDirectoryFid ) ;
1998-08-14 21:38:29 +04:00
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 ;
1999-12-13 16:27:58 +03:00
mode_t unixmode ;
1998-09-17 23:16:12 +04:00
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 ;
1999-12-13 16:27:58 +03:00
BOOL stat_open_only = False ;
2000-10-11 09:31:39 +04:00
START_PROFILE ( SMBntcreateX ) ;
1998-08-14 21:38:29 +04:00
2000-05-23 21:57:51 +04:00
/* If it's an IPC, use the pipe handler. */
if ( IS_IPC ( conn ) ) {
2000-10-11 09:31:39 +04:00
if ( lp_nt_pipe_support ( ) ) {
END_PROFILE ( SMBntcreateX ) ;
2000-05-23 21:57:51 +04:00
return do_ntcreate_pipe_open ( conn , inbuf , outbuf , length , bufsize ) ;
2000-10-11 09:31:39 +04:00
} else {
END_PROFILE ( SMBntcreateX ) ;
2000-05-23 21:57:51 +04:00
return ( ERROR ( ERRDOS , ERRbadaccess ) ) ;
2000-10-11 09:31:39 +04:00
}
2000-05-23 21:57:51 +04:00
}
1998-08-14 21:38:29 +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 .
*/
2000-10-11 09:31:39 +04:00
if ( ( smb_ofun = map_create_disposition ( create_disposition ) ) = = - 1 ) {
END_PROFILE ( SMBntcreateX ) ;
1998-08-14 21:38:29 +04:00
return ( ERROR ( ERRDOS , ERRbadaccess ) ) ;
2000-10-11 09:31:39 +04:00
}
1998-08-14 21:38:29 +04:00
/*
* Get the file name .
*/
1998-09-30 23:27:04 +04:00
if ( root_dir_fid ! = 0 ) {
/*
* This filename is relative to a directory fid .
*/
files_struct * dir_fsp = file_fsp ( inbuf , smb_ntcreate_RootDirectoryFid ) ;
size_t dir_name_len ;
2000-10-11 09:31:39 +04:00
if ( ! dir_fsp ) {
END_PROFILE ( SMBntcreateX ) ;
1998-09-30 23:27:04 +04:00
return ( ERROR ( ERRDOS , ERRbadfid ) ) ;
2000-10-11 09:31:39 +04:00
}
1998-09-30 23:27:04 +04:00
1999-12-13 16:27:58 +03:00
if ( ! dir_fsp - > is_directory ) {
/*
* Check to see if this is a mac fork of some kind .
*/
2001-03-16 06:53:59 +03:00
srvstr_pull ( inbuf , fname , smb_buf ( inbuf ) , sizeof ( fname ) , - 1 , STR_TERMINATE | STR_CONVERT ) ;
1999-12-13 16:27:58 +03:00
2000-11-24 22:53:38 +03:00
if ( strchr ( fname , ' : ' ) ) {
2001-03-13 03:55:19 +03:00
SSVAL ( outbuf , smb_flg2 , SVAL ( outbuf , smb_flg2 ) | FLAGS2_32_BIT_ERROR_CODES ) ;
2000-11-24 22:53:38 +03:00
END_PROFILE ( SMBntcreateX ) ;
2000-08-01 22:32:34 +04:00
return ( ERROR ( 0 , NT_STATUS_OBJECT_PATH_NOT_FOUND ) ) ;
1999-12-13 16:27:58 +03:00
}
2000-10-11 09:31:39 +04:00
END_PROFILE ( SMBntcreateX ) ;
1999-12-13 16:27:58 +03:00
return ( ERROR ( ERRDOS , ERRbadfid ) ) ;
}
1998-09-30 23:27:04 +04:00
/*
* Copy in the base directory name .
*/
pstrcpy ( fname , dir_fsp - > fsp_name ) ;
dir_name_len = strlen ( fname ) ;
/*
* Ensure it ends in a ' \ ' .
*/
if ( fname [ dir_name_len - 1 ] ! = ' \\ ' & & fname [ dir_name_len - 1 ] ! = ' / ' ) {
pstrcat ( fname , " \\ " ) ;
dir_name_len + + ;
}
2001-03-16 06:53:59 +03:00
srvstr_pull ( inbuf , & fname [ dir_name_len ] , smb_buf ( inbuf ) , sizeof ( fname ) - dir_name_len ,
- 1 , STR_TERMINATE | STR_CONVERT ) ;
1998-09-30 23:27:04 +04:00
} else {
2001-03-16 06:53:59 +03:00
srvstr_pull ( inbuf , fname , smb_buf ( inbuf ) , sizeof ( fname ) ,
- 1 , STR_TERMINATE | STR_CONVERT ) ;
1998-09-30 23:27:04 +04:00
}
1998-08-14 21:38:29 +04:00
1998-10-22 20:55:03 +04:00
/*
* Now contruct the smb_open_mode value from the filename ,
* desired access and the share access .
*/
2000-03-09 01:14:30 +03:00
RESOLVE_DFSPATH ( fname , conn , inbuf , outbuf ) ;
1999-12-13 16:27:58 +03:00
if ( ( smb_open_mode = map_share_mode ( & stat_open_only , fname , desired_access ,
1998-10-22 20:55:03 +04:00
share_access ,
2000-10-11 09:31:39 +04:00
file_attributes ) ) = = - 1 ) {
END_PROFILE ( SMBntcreateX ) ;
1998-10-22 20:55:03 +04:00
return ( ERROR ( ERRDOS , ERRbadaccess ) ) ;
2000-10-11 09:31:39 +04:00
}
1999-12-13 16:27:58 +03:00
oplock_request = ( flags & REQUEST_OPLOCK ) ? EXCLUSIVE_OPLOCK : 0 ;
oplock_request | = ( flags & REQUEST_BATCH_OPLOCK ) ? BATCH_OPLOCK : 0 ;
1998-10-22 20:55:03 +04:00
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
2000-10-19 06:58:24 +04:00
unix_convert ( fname , conn , 0 , & bad_path , & sbuf ) ;
1998-08-14 21:38:29 +04:00
2000-01-14 04:41:04 +03:00
unixmode = unix_mode ( conn , smb_attr | aARCH , fname ) ;
1998-05-19 01:30:57 +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 ;
2000-10-19 06:58:24 +04:00
fsp = open_directory ( conn , fname , & sbuf , 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
2000-04-22 04:33:16 +04:00
if ( ! fsp ) {
2000-10-07 00:34:14 +04:00
if ( ( errno = = ENOENT ) & & bad_path ) {
unix_ERR_class = ERRDOS ;
unix_ERR_code = ERRbadpath ;
}
2000-10-11 09:31:39 +04:00
END_PROFILE ( SMBntcreateX ) ;
1998-08-18 02:59:53 +04:00
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 . */
2000-10-19 06:58:24 +04:00
fsp = open_file_shared ( conn , fname , & sbuf , smb_open_mode ,
1999-12-13 16:27:58 +03:00
smb_ofun , unixmode , oplock_request , & rmode , & smb_action ) ;
1998-08-18 02:59:53 +04:00
2000-04-22 04:33:16 +04:00
if ( ! fsp ) {
1999-12-13 16:27:58 +03:00
/* We cheat here. There are two cases we
* care about . One is a directory rename ,
1998-08-18 02:59:53 +04:00
* 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
1999-12-13 16:27:58 +03:00
* directory . The second is an open
* for a permissions read only , which
* we handle in the open_file_stat case . JRA .
*/
1998-08-18 02:59:53 +04:00
if ( errno = = EISDIR ) {
1999-12-13 16:27:58 +03:00
/*
* Fail the open if it was explicitly a non - directory file .
*/
if ( create_options & FILE_NON_DIRECTORY_FILE ) {
restore_case_semantics ( file_attributes ) ;
2001-03-13 03:55:19 +03:00
SSVAL ( outbuf , smb_flg2 ,
SVAL ( outbuf , smb_flg2 ) | FLAGS2_32_BIT_ERROR_CODES ) ;
2000-10-11 09:31:39 +04:00
END_PROFILE ( SMBntcreateX ) ;
2000-08-01 22:32:34 +04:00
return ( ERROR ( 0 , NT_STATUS_FILE_IS_A_DIRECTORY ) ) ;
1999-12-13 16:27:58 +03:00
}
1998-08-18 02:59:53 +04:00
oplock_request = 0 ;
2000-10-19 06:58:24 +04:00
fsp = open_directory ( conn , fname , & sbuf , smb_ofun , unixmode , & smb_action ) ;
1998-08-18 02:59:53 +04:00
2000-04-22 04:33:16 +04:00
if ( ! fsp ) {
1998-08-14 21:38:29 +04:00
restore_case_semantics ( file_attributes ) ;
2000-10-07 00:34:14 +04:00
if ( ( errno = = ENOENT ) & & bad_path ) {
unix_ERR_class = ERRDOS ;
unix_ERR_code = ERRbadpath ;
}
2000-10-11 09:31:39 +04:00
END_PROFILE ( SMBntcreateX ) ;
1998-08-14 21:38:29 +04:00
return ( UNIXERROR ( ERRDOS , ERRnoaccess ) ) ;
}
1999-12-13 16:27:58 +03:00
# ifdef EROFS
} else if ( ( ( errno = = EACCES ) | | ( errno = = EROFS ) ) & & stat_open_only ) {
# else /* !EROFS */
} else if ( errno = = EACCES & & stat_open_only ) {
# endif
/*
* We couldn ' t open normally and all we want
* are the permissions . Try and do a stat open .
*/
oplock_request = 0 ;
2000-10-19 06:58:24 +04:00
fsp = open_file_stat ( conn , fname , & sbuf , smb_open_mode , & smb_action ) ;
1999-12-13 16:27:58 +03:00
2000-04-22 04:33:16 +04:00
if ( ! fsp ) {
1999-12-13 16:27:58 +03:00
restore_case_semantics ( file_attributes ) ;
2000-10-11 09:31:39 +04:00
END_PROFILE ( SMBntcreateX ) ;
1999-12-13 16:27:58 +03:00
return ( UNIXERROR ( ERRDOS , ERRnoaccess ) ) ;
}
1998-08-18 02:59:53 +04:00
} else {
1999-12-13 16:27:58 +03:00
1998-08-18 02:59:53 +04:00
if ( ( errno = = ENOENT ) & & bad_path ) {
unix_ERR_class = ERRDOS ;
unix_ERR_code = ERRbadpath ;
}
1998-08-14 21:38:29 +04:00
restore_case_semantics ( file_attributes ) ;
1998-08-18 02:59:53 +04:00
2000-10-11 09:31:39 +04:00
END_PROFILE ( SMBntcreateX ) ;
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
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 ) ;
2000-10-11 09:31:39 +04:00
END_PROFILE ( SMBntcreateX ) ;
1998-08-18 02:59:53 +04:00
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 ;
1999-12-13 16:27:58 +03:00
if ( oplock_request & & EXCLUSIVE_OPLOCK_TYPE ( fsp - > oplock_type ) )
1998-08-18 02:59:53 +04:00
smb_action | = EXTENDED_OPLOCK_GRANTED ;
1999-12-13 16:27:58 +03:00
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 .
*/
1999-12-13 16:27:58 +03:00
if ( smb_action & EXTENDED_OPLOCK_GRANTED )
SCVAL ( p , 0 , BATCH_OPLOCK_RETURN ) ;
else if ( LEVEL_II_OPLOCK_TYPE ( fsp - > oplock_type ) )
SCVAL ( p , 0 , LEVEL_II_OPLOCK_RETURN ) ;
else
SCVAL ( p , 0 , NO_OPLOCK_RETURN ) ;
1998-08-14 21:38:29 +04:00
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-18 07:00:20 +04:00
p + = 4 ;
SOFF_T ( p , 0 , file_len ) ;
1998-09-12 01:42:18 +04:00
p + = 8 ;
1998-09-18 07:00:20 +04:00
SOFF_T ( p , 0 , file_len ) ;
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
2000-10-11 09:31:39 +04:00
result = chain_reply ( inbuf , outbuf , length , bufsize ) ;
END_PROFILE ( SMBntcreateX ) ;
return result ;
1998-07-02 01:49:49 +04:00
}
1998-05-08 20:59:30 +04:00
2000-05-23 21:57:51 +04:00
/****************************************************************************
Reply to a NT_TRANSACT_CREATE call to open a pipe .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int do_nt_transact_create_pipe ( connection_struct * conn ,
char * inbuf , char * outbuf , int length ,
int bufsize , char * * ppsetup , char * * ppparams ,
char * * ppdata )
{
pstring fname ;
int total_parameter_count = ( int ) IVAL ( inbuf , smb_nt_TotalParameterCount ) ;
char * params = * ppparams ;
int ret ;
int pnum = - 1 ;
char * p = NULL ;
/*
* Ensure minimum number of parameters sent .
*/
if ( total_parameter_count < 54 ) {
DEBUG ( 0 , ( " do_nt_transact_create_pipe - insufficient parameters (%u) \n " , ( unsigned int ) total_parameter_count ) ) ;
return ( ERROR ( ERRDOS , ERRbadaccess ) ) ;
}
2001-03-16 06:53:59 +03:00
srvstr_pull ( inbuf , fname , params + 53 , sizeof ( fname ) , - 1 , STR_TERMINATE | STR_CONVERT ) ;
2000-05-23 21:57:51 +04:00
if ( ( ret = nt_open_pipe ( fname , conn , inbuf , outbuf , & pnum ) ) ! = 0 )
return ret ;
/* Realloc the size of parameters and data we will return */
2001-01-24 22:04:56 +03:00
params = Realloc ( * ppparams , 69 ) ;
2000-05-23 21:57:51 +04:00
if ( params = = NULL )
return ( ERROR ( ERRDOS , ERRnomem ) ) ;
2001-01-24 22:04:56 +03:00
* ppparams = params ;
2000-05-23 21:57:51 +04:00
memset ( ( char * ) params , ' \0 ' , 69 ) ;
p = params ;
SCVAL ( p , 0 , NO_OPLOCK_RETURN ) ;
p + = 2 ;
SSVAL ( p , 0 , pnum ) ;
p + = 2 ;
SIVAL ( p , 0 , FILE_WAS_OPENED ) ;
p + = 8 ;
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 ) ; /* ? */
DEBUG ( 5 , ( " do_nt_transact_create_pipe: open name = %s \n " , fname ) ) ;
/* Send the required number of replies */
send_nt_replies ( inbuf , outbuf , bufsize , 0 , params , 69 , * ppdata , 0 ) ;
return - 1 ;
}
2001-01-31 08:14:31 +03:00
/****************************************************************************
Internal fn to set security descriptors .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL set_sd ( files_struct * fsp , char * data , uint32 sd_len , uint security_info_sent , int * pdef_class , uint32 * pdef_code )
{
prs_struct pd ;
SEC_DESC * psd = NULL ;
TALLOC_CTX * mem_ctx ;
BOOL ret ;
if ( sd_len = = 0 ) {
* pdef_class = ERRDOS ;
* pdef_code = ERRbadaccess ;
return False ;
}
/*
* Init the parse struct we will unmarshall from .
*/
if ( ( mem_ctx = talloc_init ( ) ) = = NULL ) {
DEBUG ( 0 , ( " set_sd: talloc_init failed. \n " ) ) ;
* pdef_class = ERRDOS ;
* pdef_code = ERRnomem ;
return False ;
}
2001-03-10 02:48:58 +03:00
prs_init ( & pd , 0 , mem_ctx , UNMARSHALL ) ;
2001-01-31 08:14:31 +03:00
/*
* Setup the prs_struct to point at the memory we just
* allocated .
*/
prs_give_memory ( & pd , data , sd_len , False ) ;
/*
* Finally , unmarshall from the data buffer .
*/
if ( ! sec_io_desc ( " sd data " , & psd , & pd , 1 ) ) {
DEBUG ( 0 , ( " set_sd: Error in unmarshalling security descriptor. \n " ) ) ;
/*
* Return access denied for want of a better error message . .
*/
talloc_destroy ( mem_ctx ) ;
* pdef_class = ERRDOS ;
* pdef_code = ERRnomem ;
return False ;
}
2001-02-12 19:18:02 +03:00
if ( psd - > off_owner_sid = = 0 )
security_info_sent & = ~ OWNER_SECURITY_INFORMATION ;
if ( psd - > off_grp_sid = = 0 )
security_info_sent & = ~ GROUP_SECURITY_INFORMATION ;
if ( psd - > off_sacl = = 0 )
security_info_sent & = ~ SACL_SECURITY_INFORMATION ;
2001-02-13 01:37:40 +03:00
if ( psd - > off_dacl = = 0 )
security_info_sent & = ~ DACL_SECURITY_INFORMATION ;
2001-02-12 19:18:02 +03:00
2001-03-26 21:58:05 +04:00
ret = fsp - > conn - > vfs_ops . fset_nt_acl ( fsp , fsp - > fd , security_info_sent , psd ) ;
2001-01-31 08:14:31 +03:00
if ( ! ret ) {
talloc_destroy ( mem_ctx ) ;
* pdef_class = ERRDOS ;
* pdef_code = ERRnoaccess ;
return False ;
}
talloc_destroy ( mem_ctx ) ;
* pdef_class = 0 ;
* pdef_code = 0 ;
return True ;
}
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
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
1998-08-14 21:38:29 +04:00
static int call_nt_transact_create ( connection_struct * conn ,
2000-03-01 05:42:06 +03:00
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 ;
2001-01-31 08:14:31 +03:00
char * data = * ppdata ;
2000-03-01 05:42:06 +03:00
int total_parameter_count = ( int ) IVAL ( inbuf , smb_nt_TotalParameterCount ) ;
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 ;
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 ;
1999-12-13 16:27:58 +03:00
BOOL stat_open_only = False ;
2000-03-13 23:05:18 +03:00
uint32 flags ;
uint32 desired_access ;
uint32 file_attributes ;
uint32 share_access ;
uint32 create_disposition ;
uint32 create_options ;
2001-01-31 08:14:31 +03:00
uint32 sd_len ;
2000-03-13 23:05:18 +03:00
uint16 root_dir_fid ;
int smb_ofun ;
int smb_open_mode ;
int smb_attr ;
2001-01-31 08:14:31 +03:00
int error_class ;
uint32 error_code ;
2000-03-13 23:05:18 +03:00
DEBUG ( 5 , ( " call_nt_transact_create \n " ) ) ;
2000-05-23 21:57:51 +04:00
/*
* If it ' s an IPC , use the pipe handler .
*/
if ( IS_IPC ( conn ) ) {
if ( lp_nt_pipe_support ( ) )
return do_nt_transact_create_pipe ( conn , inbuf , outbuf , length ,
bufsize , ppsetup , ppparams , ppdata ) ;
else
return ( ERROR ( ERRDOS , ERRbadaccess ) ) ;
}
2000-03-13 23:05:18 +03:00
/*
* Ensure minimum number of parameters sent .
*/
if ( total_parameter_count < 54 ) {
DEBUG ( 0 , ( " call_nt_transact_create - insufficient parameters (%u) \n " , ( unsigned int ) total_parameter_count ) ) ;
return ( ERROR ( ERRDOS , ERRbadaccess ) ) ;
}
flags = IVAL ( params , 0 ) ;
desired_access = IVAL ( params , 8 ) ;
file_attributes = IVAL ( params , 20 ) ;
share_access = IVAL ( params , 24 ) ;
create_disposition = IVAL ( params , 28 ) ;
create_options = IVAL ( params , 32 ) ;
2001-01-31 08:14:31 +03:00
sd_len = IVAL ( params , 36 ) ;
2000-03-13 23:05:18 +03:00
root_dir_fid = ( uint16 ) IVAL ( params , 4 ) ;
smb_attr = ( file_attributes & SAMBA_ATTRIBUTES_MASK ) ;
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 )
2000-03-13 23:05:18 +03:00
return ( ERROR ( ERRDOS , ERRbadmem ) ) ;
1998-07-08 05:42:05 +04:00
/*
1998-07-17 02:46:06 +04:00
* Get the file name .
1998-07-08 05:42:05 +04:00
*/
1998-09-30 23:27:04 +04:00
if ( root_dir_fid ! = 0 ) {
/*
* This filename is relative to a directory fid .
*/
files_struct * dir_fsp = file_fsp ( params , 4 ) ;
size_t dir_name_len ;
1999-12-13 16:27:58 +03:00
if ( ! dir_fsp )
return ( ERROR ( ERRDOS , ERRbadfid ) ) ;
if ( ! dir_fsp - > is_directory ) {
/*
* Check to see if this is a mac fork of some kind .
*/
2001-03-16 06:53:59 +03:00
srvstr_pull ( inbuf , fname , params + 53 , sizeof ( fname ) , - 1 , STR_TERMINATE | STR_CONVERT ) ;
1999-12-13 16:27:58 +03:00
2000-11-24 22:53:38 +03:00
if ( strchr ( fname , ' : ' ) ) {
2001-03-13 03:55:19 +03:00
SSVAL ( outbuf , smb_flg2 , SVAL ( outbuf , smb_flg2 ) | FLAGS2_32_BIT_ERROR_CODES ) ;
2000-08-01 22:32:34 +04:00
return ( ERROR ( 0 , NT_STATUS_OBJECT_PATH_NOT_FOUND ) ) ;
1999-12-13 16:27:58 +03:00
}
1998-09-30 23:27:04 +04:00
return ( ERROR ( ERRDOS , ERRbadfid ) ) ;
1999-12-13 16:27:58 +03:00
}
1998-09-30 23:27:04 +04:00
/*
* Copy in the base directory name .
*/
pstrcpy ( fname , dir_fsp - > fsp_name ) ;
dir_name_len = strlen ( fname ) ;
/*
* Ensure it ends in a ' \ ' .
*/
if ( ( fname [ dir_name_len - 1 ] ! = ' \\ ' ) & & ( fname [ dir_name_len - 1 ] ! = ' / ' ) ) {
pstrcat ( fname , " \\ " ) ;
dir_name_len + + ;
}
2001-03-16 06:53:59 +03:00
srvstr_pull ( inbuf , & fname [ dir_name_len ] , params + 53 , sizeof ( fname ) - dir_name_len ,
- 1 , STR_TERMINATE | STR_CONVERT ) ;
1998-09-30 23:27:04 +04:00
} else {
2001-03-16 06:53:59 +03:00
srvstr_pull ( inbuf , fname , params + 53 , sizeof ( fname ) , - 1 , STR_TERMINATE | STR_CONVERT ) ;
1998-09-30 23:27:04 +04:00
}
1998-07-08 05:42:05 +04:00
2000-05-23 21:57:51 +04:00
/*
* Now contruct the smb_open_mode value from the desired access
* and the share access .
*/
1999-12-13 16:27:58 +03:00
2000-05-23 21:57:51 +04:00
if ( ( smb_open_mode = map_share_mode ( & stat_open_only , fname , desired_access ,
share_access , file_attributes ) ) = = - 1 )
return ( ERROR ( ERRDOS , ERRbadaccess ) ) ;
1999-12-13 16:27:58 +03:00
2000-05-23 21:57:51 +04:00
oplock_request = ( flags & REQUEST_OPLOCK ) ? EXCLUSIVE_OPLOCK : 0 ;
oplock_request | = ( flags & REQUEST_BATCH_OPLOCK ) ? BATCH_OPLOCK : 0 ;
1999-12-13 16:27:58 +03:00
2000-05-23 21:57:51 +04:00
/*
* Check if POSIX semantics are wanted .
*/
1998-07-17 02:46:06 +04:00
2000-05-23 21:57:51 +04:00
set_posix_case_semantics ( file_attributes ) ;
2000-03-09 01:14:30 +03:00
2000-05-23 21:57:51 +04:00
RESOLVE_DFSPATH ( fname , conn , inbuf , outbuf ) ;
1998-07-17 02:46:06 +04:00
2000-10-19 06:58:24 +04:00
unix_convert ( fname , conn , 0 , & bad_path , & sbuf ) ;
1998-07-08 05:42:05 +04:00
2000-05-23 21:57:51 +04:00
unixmode = unix_mode ( conn , smb_attr | aARCH , fname ) ;
/*
* If it ' s a request for a directory open , deal with it separately .
*/
1998-07-08 05:42:05 +04:00
2000-05-23 21:57:51 +04:00
if ( create_options & FILE_DIRECTORY_FILE ) {
1998-07-31 01:18:57 +04:00
2000-05-23 21:57:51 +04:00
oplock_request = 0 ;
1998-07-31 01:18:57 +04:00
2000-05-23 21:57:51 +04:00
/*
* We will get a create directory here if the Win32
* app specified a security descriptor in the
* CreateDirectory ( ) call .
*/
1998-07-31 01:18:57 +04:00
2000-10-19 06:58:24 +04:00
fsp = open_directory ( conn , fname , & sbuf , smb_ofun , unixmode , & smb_action ) ;
1998-07-31 01:18:57 +04:00
2000-05-23 21:57:51 +04:00
if ( ! fsp ) {
restore_case_semantics ( file_attributes ) ;
2000-10-07 00:34:14 +04:00
if ( ( errno = = ENOENT ) & & bad_path ) {
unix_ERR_class = ERRDOS ;
unix_ERR_code = ERRbadpath ;
}
2000-05-23 21:57:51 +04:00
return ( UNIXERROR ( ERRDOS , ERRnoaccess ) ) ;
}
1999-12-13 16:27:58 +03:00
2000-05-23 21:57:51 +04:00
} else {
1998-07-08 05:42:05 +04:00
2000-05-23 21:57:51 +04:00
/*
* Ordinary file case .
*/
1998-07-08 05:42:05 +04:00
2000-10-19 06:58:24 +04:00
fsp = open_file_shared ( conn , fname , & sbuf , smb_open_mode , smb_ofun , unixmode ,
2000-05-23 21:57:51 +04:00
oplock_request , & rmode , & smb_action ) ;
1998-07-08 05:42:05 +04:00
2000-05-23 21:57:51 +04:00
if ( ! fsp ) {
1998-07-08 05:42:05 +04:00
1999-12-13 16:27:58 +03:00
if ( errno = = EISDIR ) {
1998-07-31 01:18:57 +04:00
1999-12-13 16:27:58 +03:00
/*
* Fail the open if it was explicitly a non - directory file .
*/
1998-07-08 05:42:05 +04:00
1999-12-13 16:27:58 +03:00
if ( create_options & FILE_NON_DIRECTORY_FILE ) {
restore_case_semantics ( file_attributes ) ;
2001-03-13 03:55:19 +03:00
SSVAL ( outbuf , smb_flg2 ,
SVAL ( outbuf , smb_flg2 ) | FLAGS2_32_BIT_ERROR_CODES ) ;
2000-08-01 22:32:34 +04:00
return ( ERROR ( 0 , NT_STATUS_FILE_IS_A_DIRECTORY ) ) ;
1999-12-13 16:27:58 +03:00
}
oplock_request = 0 ;
2000-10-19 06:58:24 +04:00
fsp = open_directory ( conn , fname , & sbuf , smb_ofun , unixmode , & smb_action ) ;
1999-12-13 16:27:58 +03:00
2000-04-22 04:33:16 +04:00
if ( ! fsp ) {
1999-12-13 16:27:58 +03:00
restore_case_semantics ( file_attributes ) ;
2000-10-07 00:34:14 +04:00
if ( ( errno = = ENOENT ) & & bad_path ) {
unix_ERR_class = ERRDOS ;
unix_ERR_code = ERRbadpath ;
}
1999-12-13 16:27:58 +03:00
return ( UNIXERROR ( ERRDOS , ERRnoaccess ) ) ;
}
# ifdef EROFS
} else if ( ( ( errno = = EACCES ) | | ( errno = = EROFS ) ) & & stat_open_only ) {
# else /* !EROFS */
} else if ( errno = = EACCES & & stat_open_only ) {
# endif
1998-07-31 01:18:57 +04:00
1999-12-13 16:27:58 +03:00
/*
* We couldn ' t open normally and all we want
* are the permissions . Try and do a stat open .
*/
oplock_request = 0 ;
2000-10-19 06:58:24 +04:00
fsp = open_file_stat ( conn , fname , & sbuf , smb_open_mode , & smb_action ) ;
1999-12-13 16:27:58 +03:00
2000-04-22 04:33:16 +04:00
if ( ! fsp ) {
1999-12-13 16:27:58 +03:00
restore_case_semantics ( file_attributes ) ;
return ( UNIXERROR ( ERRDOS , ERRnoaccess ) ) ;
}
} else {
if ( ( errno = = ENOENT ) & & bad_path ) {
unix_ERR_class = ERRDOS ;
unix_ERR_code = ERRbadpath ;
}
restore_case_semantics ( file_attributes ) ;
return ( UNIXERROR ( ERRDOS , ERRnoaccess ) ) ;
}
1998-07-31 01:18:57 +04:00
}
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
1999-12-13 16:27:58 +03:00
if ( oplock_request & & EXCLUSIVE_OPLOCK_TYPE ( fsp - > oplock_type ) )
1998-07-31 01:18:57 +04:00
smb_action | = EXTENDED_OPLOCK_GRANTED ;
1998-07-17 02:46:06 +04:00
}
1998-07-08 05:42:05 +04:00
2001-01-31 08:14:31 +03:00
/*
* Now try and apply the desired SD .
*/
if ( ! set_sd ( fsp , data , sd_len , ALL_SECURITY_INFORMATION , & error_class , & error_code ) ) {
close_file ( fsp , False ) ;
restore_case_semantics ( file_attributes ) ;
return ( ERROR ( error_class , error_code ) ) ;
}
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 */
2001-01-24 22:04:56 +03:00
params = Realloc ( * ppparams , 69 ) ;
1998-07-09 04:41:32 +04:00
if ( params = = NULL )
return ( ERROR ( ERRDOS , ERRnomem ) ) ;
2001-01-24 22:04:56 +03:00
* ppparams = params ;
1999-12-13 16:27:58 +03:00
memset ( ( char * ) params , ' \0 ' , 69 ) ;
1998-07-09 04:41:32 +04:00
p = params ;
1999-12-13 16:27:58 +03:00
if ( smb_action & EXTENDED_OPLOCK_GRANTED )
SCVAL ( p , 0 , BATCH_OPLOCK_RETURN ) ;
else if ( LEVEL_II_OPLOCK_TYPE ( fsp - > oplock_type ) )
SCVAL ( p , 0 , LEVEL_II_OPLOCK_RETURN ) ;
else
SCVAL ( p , 0 , NO_OPLOCK_RETURN ) ;
1998-07-09 04:41:32 +04:00
p + = 2 ;
2000-05-23 21:57:51 +04:00
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
2000-05-23 21:57:51 +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. */
p + = 4 ;
SOFF_T ( p , 0 , file_len ) ;
p + = 8 ;
SOFF_T ( p , 0 , file_len ) ;
1998-07-09 04:41:32 +04:00
2000-03-01 05:42:06 +03:00
DEBUG ( 5 , ( " call_nt_transact_create: open name = %s \n " , fname ) ) ;
1998-07-09 04:41:32 +04:00
/* Send the required number of replies */
1999-12-13 16:27:58 +03:00
send_nt_replies ( inbuf , outbuf , bufsize , 0 , params , 69 , * ppdata , 0 ) ;
1998-07-09 04:41:32 +04:00
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 ) ;
2000-10-11 09:31:39 +04:00
START_PROFILE ( SMBntcancel ) ;
1998-08-14 21:38:29 +04:00
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 ) ) ;
2000-10-11 09:31:39 +04:00
END_PROFILE ( SMBntcancel ) ;
1998-08-14 21:38:29 +04:00
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
{
2000-10-11 09:31:39 +04:00
START_PROFILE ( SMBnttranss ) ;
1998-08-14 21:38:29 +04:00
DEBUG ( 4 , ( " Ignoring nttranss of length %d \n " , length ) ) ;
2000-10-11 09:31:39 +04:00
END_PROFILE ( SMBnttranss ) ;
1998-08-14 21:38:29 +04:00
return ( - 1 ) ;
1998-05-08 05:22:16 +04:00
}
2000-06-12 09:32:28 +04:00
/****************************************************************************
Reply to a notify change - queue the request and
don ' t allow a directory to be opened .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int call_nt_transact_notify_change ( connection_struct * conn ,
char * inbuf , char * outbuf , int length ,
int bufsize ,
char * * ppsetup ,
char * * ppparams , char * * ppdata )
{
char * setup = * ppsetup ;
files_struct * fsp ;
uint32 flags ;
fsp = file_fsp ( setup , 4 ) ;
flags = IVAL ( setup , 0 ) ;
DEBUG ( 3 , ( " call_nt_transact_notify_change \n " ) ) ;
if ( ! fsp )
return ( ERROR ( ERRDOS , ERRbadfid ) ) ;
if ( ( ! fsp - > is_directory ) | | ( conn ! = fsp - > conn ) )
return ( ERROR ( ERRDOS , ERRbadfid ) ) ;
if ( ! change_notify_set ( inbuf , fsp , conn , flags ) ) {
return ( UNIXERROR ( ERRDOS , ERRbadfid ) ) ;
}
DEBUG ( 3 , ( " call_nt_transact_notify_change: notify change called on directory \
name = % s \ n " , fsp->fsp_name ));
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 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
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 ;
int outsize = 0 ;
1998-07-08 05:42:05 +04:00
1998-08-15 11:27:34 +04:00
CHECK_FSP ( fsp , conn ) ;
2001-03-16 06:53:59 +03:00
srvstr_pull ( inbuf , new_name , params + 4 , sizeof ( new_name ) , - 1 , STR_TERMINATE | STR_CONVERT ) ;
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 .
*/
1999-12-13 16:27:58 +03:00
send_nt_replies ( inbuf , outbuf , bufsize , 0 , 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 ;
2000-09-20 23:00:21 +04:00
/*
* Win2k needs a changenotify request response before it will
* update after a rename . .
*/
process_pending_change_notify_queue ( ( time_t ) 0 ) ;
1998-07-11 05:25:02 +04:00
}
return ( outsize ) ;
1998-07-08 05:42:05 +04:00
}
2000-09-20 23:00:21 +04:00
1998-08-03 23:07:55 +04:00
1998-07-08 05:42:05 +04:00
/****************************************************************************
1999-12-13 16:27:58 +03:00
Reply to query a security descriptor - currently this is not implemented ( it
is planned to be though ) . Right now it just returns the same thing NT would
when queried on a FAT filesystem . JRA .
1998-07-08 05:42:05 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
static int call_nt_transact_query_security_desc ( connection_struct * conn ,
char * inbuf , char * outbuf ,
int length , int bufsize ,
char * * ppsetup , char * * ppparams , char * * ppdata )
{
uint32 max_data_count = IVAL ( inbuf , smb_nt_MaxDataCount ) ;
char * params = * ppparams ;
char * data = * ppdata ;
prs_struct pd ;
2000-05-27 05:56:26 +04:00
SEC_DESC * psd = NULL ;
2000-06-03 04:53:07 +04:00
size_t sd_size ;
2000-07-27 04:47:19 +04:00
TALLOC_CTX * mem_ctx ;
1999-12-13 16:27:58 +03:00
files_struct * fsp = file_fsp ( params , 0 ) ;
if ( ! fsp )
return ( ERROR ( ERRDOS , ERRbadfid ) ) ;
DEBUG ( 3 , ( " call_nt_transact_query_security_desc: file = %s \n " , fsp - > fsp_name ) ) ;
2001-01-24 22:04:56 +03:00
params = Realloc ( * ppparams , 4 ) ;
1999-12-13 16:27:58 +03:00
if ( params = = NULL )
return ( ERROR ( ERRDOS , ERRnomem ) ) ;
2001-01-24 22:04:56 +03:00
* ppparams = params ;
1999-12-13 16:27:58 +03:00
/*
* Get the permissions to return .
*/
2001-03-26 21:58:05 +04:00
if ( ( sd_size = conn - > vfs_ops . fget_nt_acl ( fsp , fsp - > fd , & psd ) ) = = 0 )
1999-12-13 16:27:58 +03:00
return ( UNIXERROR ( ERRDOS , ERRnoaccess ) ) ;
2000-06-03 04:53:07 +04:00
DEBUG ( 3 , ( " call_nt_transact_query_security_desc: sd_size = %d. \n " , ( int ) sd_size ) ) ;
1999-12-13 16:27:58 +03:00
2000-06-03 04:53:07 +04:00
SIVAL ( params , 0 , ( uint32 ) sd_size ) ;
1999-12-13 16:27:58 +03:00
2000-06-03 04:53:07 +04:00
if ( max_data_count < sd_size ) {
1999-12-13 16:27:58 +03:00
2000-08-01 22:32:34 +04:00
send_nt_replies ( inbuf , outbuf , bufsize , NT_STATUS_BUFFER_TOO_SMALL ,
1999-12-13 16:27:58 +03:00
params , 4 , * ppdata , 0 ) ;
return - 1 ;
}
/*
* Allocate the data we will point this at .
*/
2001-01-24 22:04:56 +03:00
data = Realloc ( * ppdata , sd_size ) ;
1999-12-13 16:27:58 +03:00
if ( data = = NULL ) {
return ( ERROR ( ERRDOS , ERRnomem ) ) ;
}
2001-01-24 22:04:56 +03:00
* ppdata = data ;
2000-06-03 04:53:07 +04:00
memset ( data , ' \0 ' , sd_size ) ;
1999-12-13 16:27:58 +03:00
/*
* Init the parse struct we will marshall into .
*/
2000-07-27 04:47:19 +04:00
if ( ( mem_ctx = talloc_init ( ) ) = = NULL ) {
DEBUG ( 0 , ( " call_nt_transact_query_security_desc: talloc_init failed. \n " ) ) ;
return ( ERROR ( ERRDOS , ERRnomem ) ) ;
}
2001-03-10 02:48:58 +03:00
prs_init ( & pd , 0 , mem_ctx , MARSHALL ) ;
2000-05-27 13:19:57 +04:00
/*
2000-05-31 21:51:28 +04:00
* Setup the prs_struct to point at the memory we just
* allocated .
2000-05-27 13:19:57 +04:00
*/
2000-06-03 04:53:07 +04:00
prs_give_memory ( & pd , data , ( uint32 ) sd_size , False ) ;
1999-12-13 16:27:58 +03:00
/*
* Finally , linearize into the outgoing buffer .
*/
2000-05-31 21:51:28 +04:00
if ( ! sec_io_desc ( " sd data " , & psd , & pd , 1 ) ) {
1999-12-13 16:27:58 +03:00
DEBUG ( 0 , ( " call_nt_transact_query_security_desc: Error in marshalling \
security descriptor . \ n " ));
/*
* Return access denied for want of a better error message . .
*/
2000-07-27 04:47:19 +04:00
talloc_destroy ( mem_ctx ) ;
1999-12-13 16:27:58 +03:00
return ( UNIXERROR ( ERRDOS , ERRnoaccess ) ) ;
}
/*
2000-05-27 05:56:26 +04:00
* Now we can delete the security descriptor .
1999-12-13 16:27:58 +03:00
*/
2000-07-27 04:47:19 +04:00
talloc_destroy ( mem_ctx ) ;
1999-12-13 16:27:58 +03:00
2000-06-03 04:53:07 +04:00
send_nt_replies ( inbuf , outbuf , bufsize , 0 , params , 4 , data , ( int ) sd_size ) ;
2000-05-27 05:56:26 +04:00
return - 1 ;
1999-12-13 16:27:58 +03:00
}
/****************************************************************************
Reply to set a security descriptor . Map to UNIX perms .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-08-14 21:38:29 +04:00
static int call_nt_transact_set_security_desc ( connection_struct * conn ,
1999-12-13 16:27:58 +03:00
char * inbuf , char * outbuf , int length ,
int bufsize , char * * ppsetup ,
char * * ppparams , char * * ppdata )
1998-07-08 05:42:05 +04:00
{
1999-12-13 16:27:58 +03:00
uint32 total_parameter_count = IVAL ( inbuf , smb_nts_TotalParameterCount ) ;
char * params = * ppparams ;
char * data = * ppdata ;
uint32 total_data_count = ( uint32 ) IVAL ( inbuf , smb_nts_TotalDataCount ) ;
files_struct * fsp = NULL ;
uint32 security_info_sent = 0 ;
2001-01-31 08:14:31 +03:00
int error_class ;
uint32 error_code ;
1998-11-20 01:37:33 +03:00
1999-12-13 16:27:58 +03:00
if ( ! lp_nt_acl_support ( ) )
return ( UNIXERROR ( ERRDOS , ERRnoaccess ) ) ;
if ( total_parameter_count < 8 )
return ( ERROR ( ERRDOS , ERRbadfunc ) ) ;
if ( ( fsp = file_fsp ( params , 0 ) ) = = NULL )
return ( ERROR ( ERRDOS , ERRbadfid ) ) ;
security_info_sent = IVAL ( params , 4 ) ;
DEBUG ( 3 , ( " call_nt_transact_set_security_desc: file = %s, sent 0x%x \n " , fsp - > fsp_name ,
( unsigned int ) security_info_sent ) ) ;
2001-01-31 08:14:31 +03:00
if ( ! set_sd ( fsp , data , total_data_count , security_info_sent , & error_class , & error_code ) )
return ( ERROR ( error_class , error_code ) ) ;
2000-10-05 23:04:41 +04:00
1999-12-13 16:27:58 +03:00
send_nt_replies ( inbuf , outbuf , bufsize , 0 , NULL , 0 , NULL , 0 ) ;
return - 1 ;
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-11-20 01:37:33 +03:00
static BOOL logged_message = False ;
if ( ! logged_message ) {
DEBUG ( 0 , ( " call_nt_transact_ioctl: Currently not implemented. \n " ) ) ;
logged_message = True ; /* Only print this once... */
}
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 ;
2000-10-11 09:31:39 +04:00
START_PROFILE ( SMBnttrans ) ;
1998-05-08 05:22:16 +04:00
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 ) ;
2000-10-11 09:31:39 +04:00
END_PROFILE ( SMBnttrans ) ;
1998-05-08 05:22:16 +04:00
return - 1 ;
}
2000-10-11 09:31:39 +04:00
if ( IS_IPC ( conn ) & & ( function_code ! = NT_TRANSACT_CREATE ) ) {
END_PROFILE ( SMBnttrans ) ;
2000-05-23 05:27:19 +04:00
return ( ERROR ( ERRSRV , ERRaccess ) ) ;
2000-10-11 09:31:39 +04:00
}
2000-05-23 05:27:19 +04:00
1998-05-08 05:22:16 +04:00
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 ) ) ) ;
2000-10-11 09:31:39 +04:00
END_PROFILE ( SMBnttrans ) ;
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 ) ) {
2001-01-31 08:14:31 +03:00
safe_free ( setup ) ;
safe_free ( params ) ;
safe_free ( data ) ;
1998-05-08 05:22:16 +04:00
DEBUG ( 0 , ( " reply_nttrans : Out of memory \n " ) ) ;
2000-10-11 09:31:39 +04:00
END_PROFILE ( SMBnttrans ) ;
1998-05-08 05:22:16 +04:00
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 ) ;
2000-04-11 17:55:53 +04:00
send_smb ( smbd_server_fd ( ) , outbuf ) ;
1998-05-08 05:22:16 +04:00
while ( num_data_sofar < total_data_count | | num_params_sofar < total_parameter_count ) {
BOOL ret ;
1998-09-23 05:48:45 +04:00
ret = receive_next_smb ( inbuf , bufsize , SMB_SECONDARY_WAIT ) ;
1998-05-08 05:22:16 +04:00
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 ) ;
2000-10-11 09:31:39 +04:00
END_PROFILE ( SMBnttrans ) ;
1998-05-08 05:22:16 +04:00
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 ) {
2001-03-13 03:55:19 +03:00
SSVAL ( outbuf , smb_flg2 , SVAL ( outbuf , smb_flg2 ) | 0x40 ) ; /* IS_LONG_NAME */
1998-05-08 05:22:16 +04:00
}
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 :
2000-10-11 09:31:39 +04:00
START_PROFILE_NESTED ( 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 ) ;
2000-10-11 09:31:39 +04:00
END_PROFILE_NESTED ( NT_transact_create ) ;
1998-05-08 05:22:16 +04:00
break ;
case NT_TRANSACT_IOCTL :
2000-10-11 09:31:39 +04:00
START_PROFILE_NESTED ( 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 ) ;
2000-10-11 09:31:39 +04:00
END_PROFILE_NESTED ( NT_transact_ioctl ) ;
1998-05-08 05:22:16 +04:00
break ;
case NT_TRANSACT_SET_SECURITY_DESC :
2000-10-11 09:31:39 +04:00
START_PROFILE_NESTED ( 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 ) ;
2000-10-11 09:31:39 +04:00
END_PROFILE_NESTED ( NT_transact_set_security_desc ) ;
1998-05-08 05:22:16 +04:00
break ;
case NT_TRANSACT_NOTIFY_CHANGE :
2000-10-11 09:31:39 +04:00
START_PROFILE_NESTED ( 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 ) ;
2000-10-11 09:31:39 +04:00
END_PROFILE_NESTED ( NT_transact_notify_change ) ;
1998-05-08 05:22:16 +04:00
break ;
case NT_TRANSACT_RENAME :
2000-10-11 09:31:39 +04:00
START_PROFILE_NESTED ( 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 ) ;
2000-10-11 09:31:39 +04:00
END_PROFILE_NESTED ( NT_transact_rename ) ;
1998-05-08 05:22:16 +04:00
break ;
1998-08-14 21:38:29 +04:00
1998-05-08 05:22:16 +04:00
case NT_TRANSACT_QUERY_SECURITY_DESC :
2000-10-11 09:31:39 +04:00
START_PROFILE_NESTED ( 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 ) ;
2000-10-11 09:31:39 +04:00
END_PROFILE_NESTED ( NT_transact_query_security_desc ) ;
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 ) ;
2000-10-11 09:31:39 +04:00
END_PROFILE ( SMBnttrans ) ;
1998-08-14 21:38:29 +04:00
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 ) ;
2000-10-11 09:31:39 +04:00
END_PROFILE ( SMBnttrans ) ;
1998-05-08 05:22:16 +04:00
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 . */
}