1998-05-08 05:22:16 +04:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
1998-05-08 05:22:16 +04:00
SMB NT transaction handling
2007-09-12 03:57:59 +04:00
Copyright ( C ) Jeremy Allison 1994 - 2007
2003-05-12 05:20:17 +04:00
Copyright ( C ) Stefan ( metze ) Metzmacher 2003
1998-05-08 05:22:16 +04:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
1998-05-08 05:22:16 +04:00
( 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
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
1998-05-08 05:22:16 +04:00
*/
# include "includes.h"
2005-04-06 20:28:04 +04:00
extern int max_send ;
2004-11-25 03:07:01 +03:00
extern enum protocol_types Protocol ;
1998-05-08 05:22:16 +04:00
extern int smb_read_error ;
2003-05-12 05:20:17 +04:00
extern struct current_user current_user ;
1998-05-08 05:22:16 +04:00
2003-01-03 11:28:12 +03:00
static const char * known_nt_pipes [ ] = {
2002-08-17 19:27:10 +04:00
" \\ LANMAN " ,
" \\ srvsvc " ,
" \\ samr " ,
" \\ wkssvc " ,
" \\ NETLOGON " ,
" \\ ntlsa " ,
" \\ ntsvcs " ,
" \\ lsass " ,
" \\ lsarpc " ,
" \\ winreg " ,
2006-09-21 21:51:06 +04:00
" \\ initshutdown " ,
2002-08-17 19:27:10 +04:00
" \\ spoolss " ,
" \\ netdfs " ,
2003-04-14 06:08:03 +04:00
" \\ rpcecho " ,
2005-03-24 02:26:33 +03:00
" \\ svcctl " ,
" \\ eventlog " ,
2005-09-30 21:13:37 +04:00
" \\ unixinfo " ,
2002-08-17 19:27:10 +04:00
NULL
1998-05-08 20:59:30 +04:00
} ;
2004-02-08 11:38:42 +03:00
static char * nttrans_realloc ( char * * ptr , size_t size )
2003-05-12 05:20:17 +04:00
{
2005-07-08 08:51:27 +04:00
if ( ptr = = NULL ) {
2007-06-16 01:58:49 +04:00
smb_panic ( " nttrans_realloc() called with NULL ptr " ) ;
2005-07-08 08:51:27 +04:00
}
2007-09-12 03:57:59 +04:00
2006-07-30 20:36:56 +04:00
* ptr = ( char * ) SMB_REALLOC ( * ptr , size ) ;
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
if ( * ptr = = NULL ) {
2003-05-12 05:20:17 +04:00
return NULL ;
}
r13915: Fixed a very interesting class of realloc() bugs found by Coverity.
realloc can return NULL in one of two cases - (1) the realloc failed,
(2) realloc succeeded but the new size requested was zero, in which
case this is identical to a free() call.
The error paths dealing with these two cases should be different,
but mostly weren't. Secondly the standard idiom for dealing with
realloc when you know the new size is non-zero is the following :
tmp = realloc(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
However, there were *many* *many* places in Samba where we were
using the old (broken) idiom of :
p = realloc(p, size)
if (!p) {
return error;
}
which will leak the memory pointed to by p on realloc fail.
This commit (hopefully) fixes all these cases by moving to
a standard idiom of :
p = SMB_REALLOC(p, size)
if (!p) {
return error;
}
Where if the realloc returns null due to the realloc failing
or size == 0 we *guarentee* that the storage pointed to by p
has been freed. This allows me to remove a lot of code that
was dealing with the standard (more verbose) method that required
a tmp pointer. This is almost always what you want. When a
realloc fails you never usually want the old memory, you
want to free it and get into your error processing asap.
For the 11 remaining cases where we really do need to keep the
old pointer I have invented the new macro SMB_REALLOC_KEEP_OLD_ON_ERROR,
which can be used as follows :
tmp = SMB_REALLOC_KEEP_OLD_ON_ERROR(p, size);
if (!tmp) {
SAFE_FREE(p);
return error;
} else {
p = tmp;
}
SMB_REALLOC_KEEP_OLD_ON_ERROR guarentees never to free the
pointer p, even on size == 0 or realloc fail. All this is
done by a hidden extra argument to Realloc(), BOOL free_old_on_error
which is set appropriately by the SMB_REALLOC and SMB_REALLOC_KEEP_OLD_ON_ERROR
macros (and their array counterparts).
It remains to be seen what this will do to our Coverity bug count :-).
Jeremy.
(This used to be commit 1d710d06a214f3f1740e80e0bffd6aab44aac2b0)
2006-03-07 09:31:04 +03:00
memset ( * ptr , ' \0 ' , size ) ;
return * ptr ;
2003-05-12 05:20:17 +04:00
}
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
2007-08-14 12:24:02 +04:00
void send_nt_replies ( struct smb_request * req , NTSTATUS nt_error ,
char * params , int paramsize ,
char * pdata , int datasize )
1998-07-09 04:41:32 +04:00
{
2002-08-17 19:27:10 +04:00
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 ;
1998-07-09 04:41:32 +04:00
2007-09-12 03:57:59 +04:00
/*
2002-08-17 19:27:10 +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 ) {
2007-08-14 12:44:00 +04:00
reply_outbuf ( req , 18 , 0 ) ;
show_msg ( ( char * ) req - > outbuf ) ;
2007-08-14 12:24:02 +04:00
return ;
2002-08-17 19:27:10 +04:00
}
/*
* 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 .
*/
2005-07-08 08:51:27 +04:00
if ( ( ( params_to_send % 4 ) ! = 0 ) & & ( data_to_send ! = 0 ) ) {
2002-08-17 19:27:10 +04:00
data_alignment_offset = 4 - ( params_to_send % 4 ) ;
2005-07-08 08:51:27 +04:00
}
2002-08-17 19:27:10 +04:00
2007-09-12 03:57:59 +04:00
/*
2002-08-17 19:27:10 +04:00
* Space is bufsize minus Netbios over TCP header minus SMB header .
* The alignment_offset is to align the param bytes on a four byte
2007-09-12 03:57:59 +04:00
* boundary ( 2 bytes for data len , one byte pad ) .
2002-08-17 19:27:10 +04:00
* NT needs this to work correctly .
*/
2007-08-14 12:44:00 +04:00
useable_space = max_send - ( smb_size
+ 2 * 18 /* wct */
+ alignment_offset
+ data_alignment_offset ) ;
2002-08-17 19:27:10 +04:00
/*
* 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 ) ) ;
1998-07-09 04:41:32 +04:00
2002-08-17 19:27:10 +04:00
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 ;
2007-09-12 03:57:59 +04:00
/*
2002-08-17 19:27:10 +04:00
* We can never send more than useable_space .
*/
total_sent_thistime = MIN ( total_sent_thistime , useable_space ) ;
2007-08-14 12:44:00 +04:00
reply_outbuf ( req , 18 , total_sent_thistime ) ;
2002-08-17 19:27:10 +04:00
/*
* Set total params and data to be sent .
*/
2007-08-14 12:44:00 +04:00
SIVAL ( req - > outbuf , smb_ntr_TotalParameterCount , paramsize ) ;
SIVAL ( req - > outbuf , smb_ntr_TotalDataCount , datasize ) ;
2002-08-17 19:27:10 +04:00
2007-09-12 03:57:59 +04:00
/*
2002-08-17 19:27:10 +04:00
* 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 ) ;
2007-08-14 12:44:00 +04:00
SIVAL ( req - > outbuf , smb_ntr_ParameterCount ,
params_sent_thistime ) ;
2002-08-17 19:27:10 +04:00
if ( params_sent_thistime = = 0 ) {
2007-08-14 12:44:00 +04:00
SIVAL ( req - > outbuf , smb_ntr_ParameterOffset , 0 ) ;
SIVAL ( req - > outbuf , smb_ntr_ParameterDisplacement , 0 ) ;
2002-08-17 19:27:10 +04:00
} 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 .
*/
2007-08-14 12:44:00 +04:00
SIVAL ( req - > outbuf , smb_ntr_ParameterOffset ,
( ( smb_buf ( req - > outbuf ) + alignment_offset )
- smb_base ( req - > outbuf ) ) ) ;
2007-09-12 03:57:59 +04:00
/*
2002-08-17 19:27:10 +04:00
* Absolute displacement of param bytes sent in this packet .
*/
2007-08-14 12:44:00 +04:00
SIVAL ( req - > outbuf , smb_ntr_ParameterDisplacement ,
pp - params ) ;
2002-08-17 19:27:10 +04:00
}
/*
* Deal with the data portion .
*/
2007-08-14 12:44:00 +04:00
SIVAL ( req - > outbuf , smb_ntr_DataCount , data_sent_thistime ) ;
2002-08-17 19:27:10 +04:00
if ( data_sent_thistime = = 0 ) {
2007-08-14 12:44:00 +04:00
SIVAL ( req - > outbuf , smb_ntr_DataOffset , 0 ) ;
SIVAL ( req - > outbuf , smb_ntr_DataDisplacement , 0 ) ;
2002-08-17 19:27:10 +04:00
} else {
/*
* The offset of the data bytes is the offset of the
* parameter bytes plus the number of parameters being sent this time .
*/
2007-08-14 12:44:00 +04:00
SIVAL ( req - > outbuf , smb_ntr_DataOffset ,
( ( smb_buf ( req - > outbuf ) + alignment_offset ) -
smb_base ( req - > outbuf ) )
+ params_sent_thistime + data_alignment_offset ) ;
SIVAL ( req - > outbuf , smb_ntr_DataDisplacement , pd - pdata ) ;
2002-08-17 19:27:10 +04:00
}
2007-09-12 03:57:59 +04:00
/*
2002-08-17 19:27:10 +04:00
* Copy the param bytes into the packet .
*/
2005-07-08 08:51:27 +04:00
if ( params_sent_thistime ) {
2007-08-14 12:44:00 +04:00
if ( alignment_offset ! = 0 ) {
memset ( smb_buf ( req - > outbuf ) , 0 ,
alignment_offset ) ;
}
memcpy ( ( smb_buf ( req - > outbuf ) + alignment_offset ) , pp ,
params_sent_thistime ) ;
2005-07-08 08:51:27 +04:00
}
2002-08-17 19:27:10 +04:00
/*
* Copy in the data bytes
*/
2005-07-08 08:51:27 +04:00
if ( data_sent_thistime ) {
2007-08-14 12:44:00 +04:00
if ( data_alignment_offset ! = 0 ) {
memset ( ( smb_buf ( req - > outbuf ) + alignment_offset +
params_sent_thistime ) , 0 ,
data_alignment_offset ) ;
}
memcpy ( smb_buf ( req - > outbuf ) + alignment_offset
+ params_sent_thistime + data_alignment_offset ,
pd , data_sent_thistime ) ;
2005-07-08 08:51:27 +04:00
}
2007-09-12 03:57:59 +04:00
2002-08-17 19:27:10 +04:00
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 ) ) ;
2007-08-14 12:44:00 +04:00
if ( NT_STATUS_V ( nt_error ) ) {
error_packet_set ( ( char * ) req - > outbuf ,
0 , 0 , nt_error ,
__LINE__ , __FILE__ ) ;
}
2007-09-12 03:57:59 +04:00
2002-08-17 19:27:10 +04:00
/* Send the packet */
2007-08-14 12:44:00 +04:00
show_msg ( ( char * ) req - > outbuf ) ;
if ( ! send_smb ( smbd_server_fd ( ) , ( char * ) req - > outbuf ) ) {
2006-12-18 07:25:21 +03:00
exit_server_cleanly ( " send_nt_replies: send_smb failed. " ) ;
2005-07-08 08:51:27 +04:00
}
2007-08-14 12:44:00 +04:00
TALLOC_FREE ( req - > outbuf ) ;
2007-09-12 03:57:59 +04:00
2002-08-17 19:27:10 +04:00
pp + = params_sent_thistime ;
pd + = data_sent_thistime ;
2007-09-12 03:57:59 +04:00
2002-08-17 19:27:10 +04:00
params_to_send - = params_sent_thistime ;
data_to_send - = data_sent_thistime ;
1998-07-09 04:41:32 +04:00
2002-08-17 19:27:10 +04:00
/*
* Sanity check
*/
1998-07-09 04:41:32 +04:00
2002-08-17 19:27:10 +04:00
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 ) ) ;
2007-08-14 12:24:02 +04:00
return ;
2002-08-17 19:27:10 +04:00
}
2007-09-12 03:57:59 +04:00
}
2007-08-13 12:33:01 +04:00
}
2005-05-06 17:26:54 +04:00
/****************************************************************************
Is it an NTFS stream name ?
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
bool is_ntfs_stream_name ( const char * fname )
2005-05-06 17:26:54 +04:00
{
2005-06-23 01:20:41 +04:00
if ( lp_posix_pathnames ( ) ) {
return False ;
}
2005-05-06 17:26:54 +04:00
return ( strchr_m ( fname , ' : ' ) ! = NULL ) ? True : False ;
}
2007-07-09 18:43:36 +04:00
struct case_semantics_state {
connection_struct * conn ;
2007-10-19 04:40:25 +04:00
bool case_sensitive ;
bool case_preserve ;
bool short_case_preserve ;
2007-07-09 18:43:36 +04:00
} ;
1998-07-02 22:49:08 +04:00
/****************************************************************************
2007-07-09 18:43:36 +04:00
Restore case semantics .
1998-07-02 22:49:08 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-07-09 18:43:36 +04:00
static int restore_case_semantics ( struct case_semantics_state * state )
{
state - > conn - > case_sensitive = state - > case_sensitive ;
state - > conn - > case_preserve = state - > case_preserve ;
state - > conn - > short_case_preserve = state - > short_case_preserve ;
return 0 ;
}
1998-07-02 01:49:49 +04:00
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
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-07-09 18:43:36 +04:00
static struct case_semantics_state * set_posix_case_semantics ( TALLOC_CTX * mem_ctx ,
connection_struct * conn )
1998-07-02 01:49:49 +04:00
{
2007-07-09 18:43:36 +04:00
struct case_semantics_state * result ;
if ( ! ( result = talloc ( mem_ctx , struct case_semantics_state ) ) ) {
DEBUG ( 0 , ( " talloc failed \n " ) ) ;
return NULL ;
2005-07-08 08:51:27 +04:00
}
1998-07-02 01:49:49 +04:00
2007-07-16 23:36:46 +04:00
result - > conn = conn ;
2007-07-09 18:43:36 +04:00
result - > case_sensitive = conn - > case_sensitive ;
result - > case_preserve = conn - > case_preserve ;
result - > short_case_preserve = conn - > short_case_preserve ;
1998-07-02 01:49:49 +04:00
2002-03-06 06:50:09 +03:00
/* Set to POSIX. */
2004-05-07 22:37:47 +04:00
conn - > case_sensitive = True ;
conn - > case_preserve = True ;
conn - > short_case_preserve = True ;
2007-02-07 00:05:34 +03:00
2007-07-09 18:43:36 +04:00
talloc_set_destructor ( result , restore_case_semantics ) ;
1998-07-02 01:49:49 +04:00
2007-07-09 18:43:36 +04:00
return result ;
1998-07-02 01:49:49 +04:00
}
1998-07-08 05:42:05 +04:00
/****************************************************************************
2007-08-13 23:22:07 +04:00
Reply to an NT create and X call on a pipe
1998-07-08 05:42:05 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
2007-08-13 23:22:07 +04:00
static void nt_open_pipe ( char * fname , connection_struct * conn ,
struct smb_request * req , int * ppnum )
2007-07-31 13:22:16 +04:00
{
smb_np_struct * p = NULL ;
int i ;
DEBUG ( 4 , ( " nt_open_pipe: Opening pipe %s. \n " , fname ) ) ;
/* See if it is one we want to handle. */
if ( lp_disable_spoolss ( ) & & strequal ( fname , " \\ spoolss " ) ) {
reply_botherror ( req , NT_STATUS_OBJECT_NAME_NOT_FOUND ,
ERRDOS , ERRbadpipe ) ;
return ;
}
for ( i = 0 ; known_nt_pipes [ i ] ; i + + ) {
if ( strequal ( fname , known_nt_pipes [ i ] ) ) {
break ;
}
}
if ( known_nt_pipes [ i ] = = NULL ) {
reply_botherror ( req , NT_STATUS_OBJECT_NAME_NOT_FOUND ,
ERRDOS , ERRbadpipe ) ;
return ;
}
/* Strip \\ off the name. */
fname + + ;
DEBUG ( 3 , ( " nt_open_pipe: Known pipe %s opening. \n " , fname ) ) ;
p = open_rpc_pipe_p ( fname , conn , req - > vuid ) ;
if ( ! p ) {
reply_doserror ( req , ERRSRV , ERRnofids ) ;
return ;
}
/* TODO: Add pipe to db */
if ( ! store_pipe_opendb ( p ) ) {
DEBUG ( 3 , ( " nt_open_pipe: failed to store %s pipe open. \n " , fname ) ) ;
}
* ppnum = p - > pnum ;
return ;
}
2000-05-23 21:57:51 +04:00
/****************************************************************************
Reply to an NT create and X call for pipes .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-07-31 13:22:16 +04:00
static void do_ntcreate_pipe_open ( connection_struct * conn ,
struct smb_request * req )
2000-05-23 21:57:51 +04:00
{
2007-09-12 03:57:59 +04:00
char * fname = NULL ;
2000-05-23 21:57:51 +04:00
int pnum = - 1 ;
char * p = NULL ;
2007-07-31 13:22:16 +04:00
uint32 flags = IVAL ( req - > inbuf , smb_ntcreate_Flags ) ;
2007-09-12 03:57:59 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2007-07-31 13:22:16 +04:00
2007-09-12 03:57:59 +04:00
srvstr_pull_buf_talloc ( ctx , ( char * ) req - > inbuf , req - > flags2 , & fname ,
smb_buf ( req - > inbuf ) , STR_TERMINATE ) ;
2000-05-23 21:57:51 +04:00
2007-09-12 03:57:59 +04:00
if ( ! fname ) {
reply_botherror ( req , NT_STATUS_OBJECT_NAME_NOT_FOUND ,
ERRDOS , ERRbadpipe ) ;
return ;
}
2007-08-13 23:22:07 +04:00
nt_open_pipe ( fname , conn , req , & pnum ) ;
2001-03-16 06:53:59 +03:00
2007-07-31 13:22:16 +04:00
if ( req - > outbuf ) {
/* error reply */
return ;
2005-07-08 08:51:27 +04:00
}
2000-05-23 21:57:51 +04:00
/*
* Deal with pipe return .
2007-09-12 03:57:59 +04:00
*/
2000-05-23 21:57:51 +04:00
2007-04-08 04:47:49 +04:00
if ( flags & EXTENDED_RESPONSE_REQUIRED ) {
/* This is very strange. We
* return 50 words , but only set
* the wcnt to 42 ? It ' s definately
* what happens on the wire . . . .
*/
2007-07-31 13:22:16 +04:00
reply_outbuf ( req , 50 , 0 ) ;
SCVAL ( req - > outbuf , smb_wct , 42 ) ;
2007-04-08 04:47:49 +04:00
} else {
2007-07-31 13:22:16 +04:00
reply_outbuf ( req , 34 , 0 ) ;
2007-04-08 04:47:49 +04:00
}
2000-05-23 21:57:51 +04:00
2007-07-31 13:22:16 +04:00
p = ( char * ) req - > outbuf + smb_vwv2 ;
2000-05-23 21:57:51 +04:00
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 ) ; /* ? */
2007-04-08 04:47:49 +04:00
p + = 4 ;
if ( flags & EXTENDED_RESPONSE_REQUIRED ) {
2007-06-05 02:29:23 +04:00
p + = 25 ;
2007-04-08 04:47:49 +04:00
SIVAL ( p , 0 , FILE_GENERIC_ALL ) ;
2007-09-12 03:57:59 +04:00
/*
2007-04-08 04:47:49 +04:00
* For pipes W2K3 seems to return
* 0x12019B next .
* This is ( ( FILE_GENERIC_READ | FILE_GENERIC_WRITE ) & ~ FILE_APPEND_DATA )
*/
SIVAL ( p , 4 , ( FILE_GENERIC_READ | FILE_GENERIC_WRITE ) & ~ FILE_APPEND_DATA ) ;
}
2000-05-23 21:57:51 +04:00
DEBUG ( 5 , ( " do_ntcreate_pipe_open: open pipe = %s \n " , fname ) ) ;
2007-08-27 16:04:09 +04:00
chain_reply ( req ) ;
2000-05-23 21:57:51 +04:00
}
2005-07-08 08:51:27 +04:00
/****************************************************************************
Reply to an NT create and X call for a quota file .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-07-31 13:41:21 +04:00
static void reply_ntcreate_and_X_quota ( connection_struct * conn ,
struct smb_request * req ,
enum FAKE_FILE_TYPE fake_file_type ,
const char * fname )
2005-07-08 08:51:27 +04:00
{
char * p ;
2007-07-31 13:41:21 +04:00
uint32 desired_access = IVAL ( req - > inbuf , smb_ntcreate_DesiredAccess ) ;
2006-07-11 22:01:26 +04:00
files_struct * fsp ;
NTSTATUS status ;
2005-07-08 08:51:27 +04:00
2006-07-11 22:01:26 +04:00
status = open_fake_file ( conn , fake_file_type , fname , desired_access ,
& fsp ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-07-31 13:41:21 +04:00
reply_nterror ( req , status ) ;
return ;
2005-07-08 08:51:27 +04:00
}
2007-07-31 13:41:21 +04:00
reply_outbuf ( req , 34 , 0 ) ;
2007-09-12 03:57:59 +04:00
2007-07-31 13:41:21 +04:00
p = ( char * ) req - > outbuf + smb_vwv2 ;
2007-09-12 03:57:59 +04:00
2005-07-08 08:51:27 +04:00
/* SCVAL(p,0,NO_OPLOCK_RETURN); */
p + + ;
SSVAL ( p , 0 , fsp - > fnum ) ;
DEBUG ( 5 , ( " reply_ntcreate_and_X_quota: fnum = %d, open name = %s \n " , fsp - > fnum , fsp - > fsp_name ) ) ;
2007-08-27 16:04:09 +04:00
chain_reply ( req ) ;
2005-07-08 08:51:27 +04:00
}
1998-07-08 05:42:05 +04:00
/****************************************************************************
Reply to an NT create and X call .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-09-30 23:27:04 +04:00
2007-07-31 12:56:08 +04:00
void reply_ntcreate_and_X ( connection_struct * conn ,
struct smb_request * req )
2007-09-12 03:57:59 +04:00
{
2007-09-08 00:57:01 +04:00
char * fname = NULL ;
2007-07-31 12:37:54 +04:00
uint32 flags ;
uint32 access_mask ;
uint32 file_attributes ;
uint32 share_access ;
uint32 create_disposition ;
uint32 create_options ;
uint16 root_dir_fid ;
SMB_BIG_UINT allocation_size ;
1998-08-14 21:38:29 +04:00
/* Breakout the oplock request bits so we can set the
reply bits separately . */
int oplock_request = 0 ;
2005-07-08 08:51:27 +04:00
uint32 fattr = 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 ;
2005-07-08 08:51:27 +04:00
int info = 0 ;
2007-03-07 16:57:32 +03:00
files_struct * fsp = NULL ;
1998-08-14 21:38:29 +04:00
char * p = NULL ;
2006-08-24 20:44:00 +04:00
struct timespec c_timespec ;
struct timespec a_timespec ;
struct timespec m_timespec ;
2007-10-19 04:40:25 +04:00
bool extended_oplock_granted = False ;
2003-10-09 03:21:36 +04:00
NTSTATUS status ;
2007-07-09 18:43:36 +04:00
struct case_semantics_state * case_state = NULL ;
2007-09-11 22:31:29 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2002-09-25 19:19:00 +04:00
2000-10-11 09:31:39 +04:00
START_PROFILE ( SMBntcreateX ) ;
1998-08-14 21:38:29 +04:00
2007-07-31 12:56:08 +04:00
if ( req - > wct < 24 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
return ;
2007-07-31 12:37:54 +04:00
}
2007-07-31 12:56:08 +04:00
flags = IVAL ( req - > inbuf , smb_ntcreate_Flags ) ;
access_mask = IVAL ( req - > inbuf , smb_ntcreate_DesiredAccess ) ;
file_attributes = IVAL ( req - > inbuf , smb_ntcreate_FileAttributes ) ;
share_access = IVAL ( req - > inbuf , smb_ntcreate_ShareAccess ) ;
create_disposition = IVAL ( req - > inbuf , smb_ntcreate_CreateDisposition ) ;
create_options = IVAL ( req - > inbuf , smb_ntcreate_CreateOptions ) ;
root_dir_fid = ( uint16 ) IVAL ( req - > inbuf , smb_ntcreate_RootDirectoryFid ) ;
2007-07-31 12:37:54 +04:00
2007-07-31 12:56:08 +04:00
allocation_size = ( SMB_BIG_UINT ) IVAL ( req - > inbuf , smb_ntcreate_AllocationSize ) ;
2007-07-31 12:37:54 +04:00
# ifdef LARGE_SMB_OFF_T
2007-07-31 12:56:08 +04:00
allocation_size | = ( ( ( SMB_BIG_UINT ) IVAL ( req - > inbuf , smb_ntcreate_AllocationSize + 4 ) ) < < 32 ) ;
2007-07-31 12:37:54 +04:00
# endif
2006-12-16 13:36:25 +03:00
DEBUG ( 10 , ( " reply_ntcreate_and_X: flags = 0x%x, access_mask = 0x%x "
" file_attributes = 0x%x, share_access = 0x%x, "
" create_disposition = 0x%x create_options = 0x%x "
" root_dir_fid = 0x%x \n " ,
2005-07-08 08:51:27 +04:00
( unsigned int ) flags ,
( unsigned int ) access_mask ,
( unsigned int ) file_attributes ,
( unsigned int ) share_access ,
( unsigned int ) create_disposition ,
( unsigned int ) create_options ,
( unsigned int ) root_dir_fid ) ) ;
2002-09-25 19:19:00 +04:00
2007-03-07 17:25:07 +03:00
/*
* If it ' s an IPC , use the pipe handler .
*/
2000-05-23 21:57:51 +04:00
if ( IS_IPC ( conn ) ) {
2000-10-11 09:31:39 +04:00
if ( lp_nt_pipe_support ( ) ) {
2007-07-31 13:22:16 +04:00
do_ntcreate_pipe_open ( conn , req ) ;
2000-10-11 09:31:39 +04:00
END_PROFILE ( SMBntcreateX ) ;
2007-07-31 12:56:08 +04:00
return ;
2000-10-11 09:31:39 +04:00
} else {
2007-07-31 12:56:08 +04:00
reply_doserror ( req , ERRDOS , ERRnoaccess ) ;
2000-10-11 09:31:39 +04:00
END_PROFILE ( SMBntcreateX ) ;
2007-07-31 12:56:08 +04:00
return ;
2000-10-11 09:31:39 +04:00
}
2000-05-23 21:57:51 +04:00
}
2007-03-07 16:57:32 +03:00
2002-09-25 19:19:00 +04:00
if ( create_options & FILE_OPEN_BY_FILE_ID ) {
2007-07-31 12:56:08 +04:00
reply_nterror ( req , NT_STATUS_NOT_SUPPORTED ) ;
2002-09-25 19:19:00 +04:00
END_PROFILE ( SMBntcreateX ) ;
2007-07-31 12:56:08 +04:00
return ;
2002-09-25 19:19:00 +04:00
}
2000-05-23 21:57:51 +04:00
1998-08-14 21:38:29 +04:00
/*
* Get the file name .
*/
1998-09-30 23:27:04 +04:00
2001-11-13 04:35:20 +03:00
if ( root_dir_fid ! = 0 ) {
/*
* This filename is relative to a directory fid .
*/
2007-09-12 03:57:59 +04:00
char * rel_fname = NULL ;
2007-07-31 12:56:08 +04:00
files_struct * dir_fsp = file_fsp (
2007-07-31 16:05:40 +04:00
SVAL ( req - > inbuf , smb_ntcreate_RootDirectoryFid ) ) ;
1998-09-30 23:27:04 +04:00
2001-11-13 04:35:20 +03:00
if ( ! dir_fsp ) {
2007-07-31 12:56:08 +04:00
reply_doserror ( req , ERRDOS , ERRbadfid ) ;
2001-11-13 04:35:20 +03:00
END_PROFILE ( SMBntcreateX ) ;
2007-07-31 12:56:08 +04:00
return ;
2001-11-13 04:35:20 +03:00
}
1998-09-30 23:27:04 +04:00
2001-11-13 04:35:20 +03:00
if ( ! dir_fsp - > is_directory ) {
2002-07-15 14:35:28 +04:00
2007-09-12 03:57:59 +04:00
srvstr_get_path ( ctx , ( char * ) req - > inbuf ,
req - > flags2 , & fname ,
smb_buf ( req - > inbuf ) , 0 ,
2007-07-05 20:36:15 +04:00
STR_TERMINATE , & status ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-07-31 12:56:08 +04:00
reply_nterror ( req , status ) ;
2003-10-09 03:21:36 +04:00
END_PROFILE ( SMBntcreateX ) ;
2007-07-31 12:56:08 +04:00
return ;
2003-10-09 03:21:36 +04:00
}
2002-07-15 14:35:28 +04:00
2007-03-07 16:57:32 +03:00
/*
2001-11-13 04:35:20 +03:00
* Check to see if this is a mac fork of some kind .
*/
1999-12-13 16:27:58 +03:00
2007-09-12 03:57:59 +04:00
if ( is_ntfs_stream_name ( fname ) ) {
2007-07-31 12:56:08 +04:00
reply_nterror (
req , NT_STATUS_OBJECT_PATH_NOT_FOUND ) ;
2001-11-13 04:35:20 +03:00
END_PROFILE ( SMBntcreateX ) ;
2007-07-31 12:56:08 +04:00
return ;
2001-11-13 04:35:20 +03:00
}
2003-02-12 04:06:52 +03:00
/*
we need to handle the case when we get a
relative open relative to a file and the
pathname is blank - this is a reopen !
( hint from demyn plantenberg )
*/
2007-07-31 12:56:08 +04:00
reply_doserror ( req , ERRDOS , ERRbadfid ) ;
2001-11-13 04:35:20 +03:00
END_PROFILE ( SMBntcreateX ) ;
2007-07-31 12:56:08 +04:00
return ;
2001-11-13 04:35:20 +03:00
}
1999-12-13 16:27:58 +03:00
2007-09-24 23:11:42 +04:00
if ( ISDOT ( dir_fsp - > fsp_name ) ) {
/*
* We ' re at the toplevel dir , the final file name
* must not contain . / , as this is filtered out
* normally by srvstr_get_path and unix_convert
* explicitly rejects paths containing . / .
*/
fname = talloc_strdup ( ctx , " " ) ;
if ( ! fname ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
END_PROFILE ( SMBntcreateX ) ;
return ;
}
} else {
size_t dir_name_len = strlen ( dir_fsp - > fsp_name ) ;
1998-09-30 23:27:04 +04:00
2007-09-24 23:11:42 +04:00
/*
* Copy in the base directory name .
*/
1998-09-30 23:27:04 +04:00
2007-09-24 23:11:42 +04:00
fname = TALLOC_ARRAY ( ctx , char , dir_name_len + 2 ) ;
if ( ! fname ) {
reply_nterror (
req , NT_STATUS_NO_MEMORY ) ;
END_PROFILE ( SMBntcreateX ) ;
return ;
}
memcpy ( fname , dir_fsp - > fsp_name , dir_name_len + 1 ) ;
/*
* Ensure it ends in a ' / ' .
* We used TALLOC_SIZE + 2 to add space for the ' / ' .
*/
1998-09-30 23:27:04 +04:00
2007-09-24 23:11:42 +04:00
if ( dir_name_len & &
( fname [ dir_name_len - 1 ] ! = ' \\ ' ) & &
( fname [ dir_name_len - 1 ] ! = ' / ' ) ) {
fname [ dir_name_len ] = ' / ' ;
fname [ dir_name_len + 1 ] = ' \0 ' ;
}
2001-11-13 04:35:20 +03:00
}
1998-09-30 23:27:04 +04:00
2007-09-12 03:57:59 +04:00
srvstr_get_path ( ctx , ( char * ) req - > inbuf , req - > flags2 , & rel_fname ,
smb_buf ( req - > inbuf ) , 0 ,
2007-07-05 20:36:15 +04:00
STR_TERMINATE , & status ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-07-31 12:56:08 +04:00
reply_nterror ( req , status ) ;
2003-10-09 03:21:36 +04:00
END_PROFILE ( SMBntcreateX ) ;
2007-07-31 12:56:08 +04:00
return ;
2003-10-09 03:21:36 +04:00
}
2007-09-12 03:57:59 +04:00
fname = talloc_asprintf ( ctx , " %s%s " ,
fname ,
rel_fname ) ;
if ( ! fname ) {
reply_nterror (
req , NT_STATUS_NO_MEMORY ) ;
END_PROFILE ( SMBntcreateX ) ;
return ;
}
2001-11-13 04:35:20 +03:00
} else {
2007-09-12 03:57:59 +04:00
srvstr_get_path ( ctx , ( char * ) req - > inbuf , req - > flags2 , & fname ,
smb_buf ( req - > inbuf ) , 0 ,
2007-07-05 20:36:15 +04:00
STR_TERMINATE , & status ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-07-31 12:56:08 +04:00
reply_nterror ( req , status ) ;
2003-10-09 03:21:36 +04:00
END_PROFILE ( SMBntcreateX ) ;
2007-07-31 12:56:08 +04:00
return ;
2003-10-09 03:21:36 +04:00
}
2002-07-15 14:35:28 +04:00
2007-03-07 16:57:32 +03:00
/*
2002-07-15 14:35:28 +04:00
* Check to see if this is a mac fork of some kind .
*/
2007-09-12 03:57:59 +04:00
if ( is_ntfs_stream_name ( fname ) ) {
enum FAKE_FILE_TYPE fake_file_type = is_fake_file ( fname ) ;
2005-07-08 08:51:27 +04:00
if ( fake_file_type ! = FAKE_FILE_TYPE_NONE ) {
2003-05-12 05:20:17 +04:00
/*
2005-07-08 08:51:27 +04:00
* Here we go ! support for changing the disk quotas - - metze
2003-05-12 05:20:17 +04:00
*
2005-07-08 08:51:27 +04:00
* We need to fake up to open this MAGIC QUOTA file
* and return a valid FID .
2003-05-12 05:20:17 +04:00
*
* w2k close this file directly after openening
* xp also tries a QUERY_FILE_INFO on the file and then close it
*/
2007-07-31 13:41:21 +04:00
reply_ntcreate_and_X_quota ( conn , req ,
2007-09-12 03:57:59 +04:00
fake_file_type , fname ) ;
2003-05-12 05:20:17 +04:00
} else {
2007-07-31 12:56:08 +04:00
reply_nterror ( req , NT_STATUS_OBJECT_PATH_NOT_FOUND ) ;
2003-05-12 05:20:17 +04:00
}
2007-07-31 13:41:21 +04:00
END_PROFILE ( SMBntcreateX ) ;
return ;
2002-07-15 14:35:28 +04:00
}
2001-11-13 04:35:20 +03:00
}
2007-09-11 22:31:29 +04:00
1998-10-22 20:55:03 +04:00
/*
2007-09-11 22:31:29 +04:00
* Now contruct the smb_open_mode value from the filename ,
2001-11-13 04:35:20 +03:00
* desired access and the share access .
1998-10-22 20:55:03 +04:00
*/
2007-09-11 22:31:29 +04:00
status = resolve_dfspath ( ctx , conn ,
req - > flags2 & FLAGS2_DFS_PATHNAMES ,
2007-09-12 03:57:59 +04:00
fname ,
2007-09-11 22:31:29 +04:00
& fname ) ;
2007-03-12 20:55:24 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
2007-07-31 12:56:08 +04:00
reply_botherror ( req , NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
2007-03-12 20:55:24 +03:00
}
2007-07-31 12:56:08 +04:00
else {
reply_nterror ( req , status ) ;
}
END_PROFILE ( SMBntcreateX ) ;
return ;
2007-03-08 01:12:58 +03:00
}
2000-03-09 01:14:30 +03:00
1999-12-13 16:27:58 +03:00
oplock_request = ( flags & REQUEST_OPLOCK ) ? EXCLUSIVE_OPLOCK : 0 ;
2002-03-07 21:53:37 +03:00
if ( oplock_request ) {
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 .
*/
2007-09-08 00:57:01 +04:00
1998-08-18 02:59:53 +04:00
/*
* Check if POSIX semantics are wanted .
*/
2007-09-08 00:57:01 +04:00
2007-07-09 18:43:36 +04:00
if ( file_attributes & FILE_FLAG_POSIX_SEMANTICS ) {
case_state = set_posix_case_semantics ( NULL , conn ) ;
file_attributes & = ~ FILE_FLAG_POSIX_SEMANTICS ;
}
2007-09-08 00:57:01 +04:00
2007-09-14 02:08:59 +04:00
status = unix_convert ( ctx , conn , fname , False , & fname , NULL , & sbuf ) ;
2007-01-13 02:47:16 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-07-09 18:43:36 +04:00
TALLOC_FREE ( case_state ) ;
2007-07-31 12:56:08 +04:00
reply_nterror ( req , status ) ;
2005-07-08 08:51:27 +04:00
END_PROFILE ( SMBntcreateX ) ;
2007-07-31 12:56:08 +04:00
return ;
2005-07-08 08:51:27 +04:00
}
/* All file access must go through check_name() */
2007-01-17 05:09:37 +03:00
status = check_name ( conn , fname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-07-09 18:43:36 +04:00
TALLOC_FREE ( case_state ) ;
2007-07-31 12:56:08 +04:00
reply_nterror ( req , status ) ;
2005-07-08 08:51:27 +04:00
END_PROFILE ( SMBntcreateX ) ;
2007-07-31 12:56:08 +04:00
return ;
2004-06-11 21:54:23 +04:00
}
2005-02-22 23:55:48 +03:00
/* This is the correct thing to do (check every time) but can_delete is
expensive ( it may have to read the parent directory permissions ) . So
for now we ' re not doing it unless we have a strong hint the client
2007-01-13 05:34:43 +03:00
is really going to delete this file . If the client is forcing FILE_CREATE
let the filesystem take care of the permissions . */
2005-02-22 23:55:48 +03:00
/* Setting FILE_SHARE_DELETE is the hint. */
2007-01-13 05:34:43 +03:00
2007-01-02 15:10:46 +03:00
if ( lp_acl_check_permissions ( SNUM ( conn ) )
2007-01-13 05:34:43 +03:00
& & ( create_disposition ! = FILE_CREATE )
2007-01-02 15:10:46 +03:00
& & ( share_access & FILE_SHARE_DELETE )
2007-01-18 09:19:24 +03:00
& & ( access_mask & DELETE_ACCESS ) ) {
if ( ( dos_mode ( conn , fname , & sbuf ) & FILE_ATTRIBUTE_READONLY ) | |
! can_delete_file_in_directory ( conn , fname ) ) {
2007-07-09 18:43:36 +04:00
TALLOC_FREE ( case_state ) ;
2007-07-31 12:56:08 +04:00
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
2007-01-18 09:19:24 +03:00
END_PROFILE ( SMBntcreateX ) ;
2007-07-31 12:56:08 +04:00
return ;
2007-01-18 09:19:24 +03:00
}
2005-02-11 05:14:49 +03:00
}
2007-06-28 02:45:08 +04:00
#if 0
/* We need to support SeSecurityPrivilege for this. */
2007-07-09 18:43:36 +04:00
if ( ( access_mask & SEC_RIGHT_SYSTEM_SECURITY ) & &
2007-06-28 02:45:08 +04:00
! user_has_privileges ( current_user . nt_user_token ,
& se_security ) ) {
2007-07-09 18:43:36 +04:00
TALLOC_FREE ( case_state ) ;
2007-06-28 02:45:08 +04:00
END_PROFILE ( SMBntcreateX ) ;
return ERROR_NT ( NT_STATUS_PRIVILEGE_NOT_HELD ) ;
}
# endif
2007-03-07 16:57:32 +03: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 ) {
2007-03-07 17:25:07 +03:00
2002-09-25 19:19:00 +04:00
/* Can't open a temp directory. IFS kit test. */
if ( file_attributes & FILE_ATTRIBUTE_TEMPORARY ) {
2007-07-09 18:43:36 +04:00
TALLOC_FREE ( case_state ) ;
2007-07-31 12:56:08 +04:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2002-09-25 19:19:00 +04:00
END_PROFILE ( SMBntcreateX ) ;
2007-07-31 12:56:08 +04:00
return ;
2002-09-25 19:19:00 +04:00
}
2007-03-07 17:25:07 +03:00
oplock_request = 0 ;
2007-07-31 12:56:08 +04:00
status = open_directory ( conn , req , fname , & sbuf ,
2005-07-08 08:51:27 +04:00
access_mask ,
share_access ,
create_disposition ,
create_options ,
2007-07-09 18:43:36 +04:00
file_attributes ,
2006-07-11 22:01:26 +04:00
& info , & fsp ) ;
2005-07-08 08:51:27 +04:00
1998-08-18 02:59:53 +04:00
} else {
2007-03-07 16:57:32 +03:00
1998-08-18 02:59:53 +04:00
/*
* 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 . */
2007-07-31 12:56:08 +04:00
status = open_file_ntcreate ( conn , req , fname , & sbuf ,
2005-07-08 08:51:27 +04:00
access_mask ,
share_access ,
create_disposition ,
create_options ,
2007-07-09 18:43:36 +04:00
file_attributes ,
2005-07-08 08:51:27 +04:00
oplock_request ,
2006-07-11 22:01:26 +04:00
& info , & fsp ) ;
2007-03-07 17:25:07 +03:00
2007-08-16 21:42:34 +04:00
/* We cheat here. There are two cases we
* care about . One 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 . The second is an open
* for a permissions read only , which
* we handle in the open_file_stat case . JRA .
*/
1999-12-13 16:27:58 +03:00
2007-08-16 21:42:34 +04:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_FILE_IS_A_DIRECTORY ) ) {
1999-12-13 16:27:58 +03:00
2007-08-16 21:42:34 +04:00
/*
* Fail the open if it was explicitly a non - directory
* file .
*/
2005-07-08 08:51:27 +04:00
2007-08-16 21:42:34 +04:00
if ( create_options & FILE_NON_DIRECTORY_FILE ) {
TALLOC_FREE ( case_state ) ;
reply_force_nterror ( req ,
NT_STATUS_FILE_IS_A_DIRECTORY ) ;
END_PROFILE ( SMBntcreateX ) ;
return ;
1998-08-14 21:38:29 +04:00
}
2007-08-16 21:42:34 +04:00
oplock_request = 0 ;
status = open_directory ( conn , req , fname ,
& sbuf ,
access_mask ,
share_access ,
create_disposition ,
create_options ,
file_attributes ,
& info , & fsp ) ;
2007-08-16 03:56:08 +04:00
}
1998-08-18 02:59:53 +04:00
}
2007-08-16 03:56:08 +04:00
2007-07-09 18:43:36 +04:00
TALLOC_FREE ( case_state ) ;
2007-03-07 17:25:07 +03:00
2007-08-25 23:47:57 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-16 03:56:08 +04:00
if ( open_was_deferred ( req - > mid ) ) {
/* We have re-scheduled this call. */
2007-08-25 23:47:57 +04:00
END_PROFILE ( SMBntcreateX ) ;
2007-08-16 03:56:08 +04:00
return ;
}
2007-08-16 21:42:34 +04:00
reply_openerror ( req , status ) ;
2007-08-25 23:47:57 +04:00
END_PROFILE ( SMBntcreateX ) ;
2007-08-16 03:56:08 +04:00
return ;
}
1998-08-18 02:59:53 +04:00
file_len = sbuf . st_size ;
2005-07-08 08:51:27 +04:00
fattr = dos_mode ( conn , fname , & sbuf ) ;
if ( fattr = = 0 ) {
fattr = FILE_ATTRIBUTE_NORMAL ;
2005-04-05 05:20:32 +04:00
}
2005-07-08 08:51:27 +04:00
if ( ! fsp - > is_directory & & ( fattr & aDIR ) ) {
2006-02-02 23:44:50 +03:00
close_file ( fsp , ERROR_CLOSE ) ;
2007-07-31 12:56:08 +04:00
reply_doserror ( req , ERRDOS , ERRnoaccess ) ;
2000-10-11 09:31:39 +04:00
END_PROFILE ( SMBntcreateX ) ;
2007-07-31 12:56:08 +04:00
return ;
2007-09-12 03:57:59 +04:00
}
2002-09-25 19:19:00 +04:00
/* Save the requested allocation size. */
2005-07-08 08:51:27 +04:00
if ( ( info = = FILE_WAS_CREATED ) | | ( info = = FILE_WAS_OVERWRITTEN ) ) {
2005-04-01 04:21:55 +04:00
if ( allocation_size & & ( allocation_size > ( SMB_BIG_UINT ) file_len ) ) {
fsp - > initial_allocation_size = smb_roundup ( fsp - > conn , allocation_size ) ;
if ( fsp - > is_directory ) {
2006-02-02 23:44:50 +03:00
close_file ( fsp , ERROR_CLOSE ) ;
2005-04-01 04:21:55 +04:00
/* Can't set allocation size on a directory. */
2007-07-31 12:56:08 +04:00
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
END_PROFILE ( SMBntcreateX ) ;
return ;
2005-04-01 04:21:55 +04:00
}
if ( vfs_allocate_file_space ( fsp , fsp - > initial_allocation_size ) = = - 1 ) {
2006-02-02 23:44:50 +03:00
close_file ( fsp , ERROR_CLOSE ) ;
2007-07-31 12:56:08 +04:00
reply_nterror ( req , NT_STATUS_DISK_FULL ) ;
2005-04-01 04:21:55 +04:00
END_PROFILE ( SMBntcreateX ) ;
2007-07-31 12:56:08 +04:00
return ;
2005-04-01 04:21:55 +04:00
}
} else {
fsp - > initial_allocation_size = smb_roundup ( fsp - > conn , ( SMB_BIG_UINT ) file_len ) ;
2002-09-25 19:19:00 +04:00
}
}
2007-09-12 03:57:59 +04:00
/*
1998-08-18 02:59:53 +04:00
* If the caller set the extended oplock request bit
* and we granted one ( by whatever means ) - set the
* correct bit for extended oplock reply .
*/
2007-03-07 16:57:32 +03:00
2005-04-05 05:20:32 +04:00
if ( oplock_request & & lp_fake_oplocks ( SNUM ( conn ) ) ) {
2002-09-25 19:19:00 +04:00
extended_oplock_granted = True ;
2005-04-05 05:20:32 +04:00
}
2007-03-07 16:57:32 +03:00
2005-04-05 05:20:32 +04:00
if ( oplock_request & & EXCLUSIVE_OPLOCK_TYPE ( fsp - > oplock_type ) ) {
2002-09-25 19:19:00 +04:00
extended_oplock_granted = True ;
2005-04-05 05:20:32 +04:00
}
1999-12-13 16:27:58 +03:00
2007-04-07 10:38:45 +04:00
if ( flags & EXTENDED_RESPONSE_REQUIRED ) {
2007-04-07 10:59:32 +04:00
/* This is very strange. We
* return 50 words , but only set
* the wcnt to 42 ? It ' s definately
* what happens on the wire . . . .
*/
2007-07-31 12:56:08 +04:00
reply_outbuf ( req , 50 , 0 ) ;
SCVAL ( req - > outbuf , smb_wct , 42 ) ;
2007-04-07 10:38:45 +04:00
} else {
2007-07-31 12:56:08 +04:00
reply_outbuf ( req , 34 , 0 ) ;
2007-04-07 10:38:45 +04:00
}
2007-07-31 12:56:08 +04:00
p = ( char * ) req - > outbuf + smb_vwv2 ;
2007-09-12 03:57:59 +04:00
1998-08-14 21:38:29 +04:00
/*
* Currently as we don ' t support level II oplocks we just report
* exclusive & batch here .
*/
1999-12-13 16:27:58 +03:00
2002-09-25 19:19:00 +04:00
if ( extended_oplock_granted ) {
2002-03-07 21:53:37 +03:00
if ( flags & REQUEST_BATCH_OPLOCK ) {
SCVAL ( p , 0 , BATCH_OPLOCK_RETURN ) ;
} else {
SCVAL ( p , 0 , EXCLUSIVE_OPLOCK_RETURN ) ;
}
2005-09-30 21:13:37 +04:00
} else if ( fsp - > oplock_type = = LEVEL_II_OPLOCK ) {
2001-11-13 04:35:20 +03:00
SCVAL ( p , 0 , LEVEL_II_OPLOCK_RETURN ) ;
2002-03-07 21:53:37 +03:00
} else {
1999-12-13 16:27:58 +03:00
SCVAL ( p , 0 , NO_OPLOCK_RETURN ) ;
2002-03-07 21:53:37 +03:00
}
2007-09-12 03:57:59 +04:00
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 ;
2005-07-08 08:51:27 +04:00
if ( ( create_disposition = = FILE_SUPERSEDE ) & & ( info = = FILE_WAS_OVERWRITTEN ) ) {
2002-09-25 19:19:00 +04:00
SIVAL ( p , 0 , FILE_WAS_SUPERSEDED ) ;
2005-07-08 08:51:27 +04:00
} else {
SIVAL ( p , 0 , info ) ;
}
1998-08-14 21:38:29 +04:00
p + = 4 ;
2007-03-07 17:25:07 +03:00
/* Create time. */
2006-08-24 20:44:00 +04:00
c_timespec = get_create_timespec ( & sbuf , lp_fake_dir_create_times ( SNUM ( conn ) ) ) ;
a_timespec = get_atimespec ( & sbuf ) ;
m_timespec = get_mtimespec ( & sbuf ) ;
2001-07-04 05:01:02 +04:00
if ( lp_dos_filetime_resolution ( SNUM ( conn ) ) ) {
2006-08-24 20:44:00 +04:00
dos_filetime_timespec ( & c_timespec ) ;
dos_filetime_timespec ( & a_timespec ) ;
dos_filetime_timespec ( & m_timespec ) ;
2001-07-04 05:01:02 +04:00
}
2007-03-07 17:25:07 +03:00
put_long_date_timespec ( p , c_timespec ) ; /* create time. */
1998-08-18 02:59:53 +04:00
p + = 8 ;
2006-08-24 20:44:00 +04:00
put_long_date_timespec ( p , a_timespec ) ; /* access time */
1998-08-18 02:59:53 +04:00
p + = 8 ;
2006-08-24 20:44:00 +04:00
put_long_date_timespec ( p , m_timespec ) ; /* write time */
1998-08-18 02:59:53 +04:00
p + = 8 ;
2006-08-24 20:44:00 +04:00
put_long_date_timespec ( p , m_timespec ) ; /* change time */
1998-08-18 02:59:53 +04:00
p + = 8 ;
2005-07-08 08:51:27 +04:00
SIVAL ( p , 0 , fattr ) ; /* File Attributes. */
1998-09-18 07:00:20 +04:00
p + = 4 ;
2005-03-03 07:03:36 +03:00
SOFF_T ( p , 0 , get_allocation_size ( conn , fsp , & sbuf ) ) ;
1998-09-12 01:42:18 +04:00
p + = 8 ;
1998-09-18 07:00:20 +04:00
SOFF_T ( p , 0 , file_len ) ;
2004-02-25 05:15:34 +03:00
p + = 8 ;
2005-07-08 08:51:27 +04:00
if ( flags & EXTENDED_RESPONSE_REQUIRED ) {
2004-02-25 05:15:34 +03:00
SSVAL ( p , 2 , 0x7 ) ;
2005-07-08 08:51:27 +04:00
}
2004-02-25 05:15:34 +03:00
p + = 4 ;
1998-08-18 02:59:53 +04:00
SCVAL ( p , 0 , fsp - > is_directory ? 1 : 0 ) ;
2004-02-25 05:15:34 +03:00
2007-04-07 10:38:45 +04:00
if ( flags & EXTENDED_RESPONSE_REQUIRED ) {
uint32 perms = 0 ;
2007-06-05 02:29:23 +04:00
p + = 25 ;
2007-04-07 10:38:45 +04:00
if ( fsp - > is_directory | | can_write_to_file ( conn , fname , & sbuf ) ) {
perms = FILE_GENERIC_ALL ;
} else {
perms = FILE_GENERIC_READ | FILE_EXECUTE ;
}
SIVAL ( p , 0 , perms ) ;
}
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
2007-08-27 16:04:09 +04:00
chain_reply ( req ) ;
2000-10-11 09:31:39 +04:00
END_PROFILE ( SMBntcreateX ) ;
2007-07-31 12:56:08 +04:00
return ;
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 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-08-13 23:22:07 +04:00
static void do_nt_transact_create_pipe ( connection_struct * conn ,
struct smb_request * req ,
uint16 * * ppsetup , uint32 setup_count ,
char * * ppparams , uint32 parameter_count ,
char * * ppdata , uint32 data_count )
2000-05-23 21:57:51 +04:00
{
2007-09-12 03:57:59 +04:00
char * fname = NULL ;
2000-05-23 21:57:51 +04:00
char * params = * ppparams ;
int pnum = - 1 ;
char * p = NULL ;
2003-10-09 03:21:36 +04:00
NTSTATUS status ;
2007-04-08 08:54:44 +04:00
size_t param_len ;
uint32 flags ;
2007-09-12 03:57:59 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2000-05-23 21:57:51 +04:00
/*
* Ensure minimum number of parameters sent .
*/
2003-05-30 03:49:31 +04:00
if ( parameter_count < 54 ) {
DEBUG ( 0 , ( " do_nt_transact_create_pipe - insufficient parameters (%u) \n " , ( unsigned int ) parameter_count ) ) ;
2007-08-13 23:22:07 +04:00
reply_doserror ( req , ERRDOS , ERRnoaccess ) ;
return ;
2000-05-23 21:57:51 +04:00
}
2007-04-08 08:54:44 +04:00
flags = IVAL ( params , 0 ) ;
2007-09-12 03:57:59 +04:00
srvstr_get_path ( ctx , params , req - > flags2 , & fname , params + 53 ,
parameter_count - 53 , STR_TERMINATE ,
2007-07-05 20:36:15 +04:00
& status ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-13 23:22:07 +04:00
reply_nterror ( req , status ) ;
return ;
2003-10-09 03:21:36 +04:00
}
2000-05-23 21:57:51 +04:00
2007-08-13 23:22:07 +04:00
nt_open_pipe ( fname , conn , req , & pnum ) ;
if ( req - > outbuf ) {
/* Error return */
return ;
2005-07-08 08:51:27 +04:00
}
2007-09-12 03:57:59 +04:00
2000-05-23 21:57:51 +04:00
/* Realloc the size of parameters and data we will return */
2007-04-08 08:54:44 +04:00
if ( flags & EXTENDED_RESPONSE_REQUIRED ) {
/* Extended response is 32 more byyes. */
param_len = 101 ;
} else {
param_len = 69 ;
}
params = nttrans_realloc ( ppparams , param_len ) ;
2005-07-08 08:51:27 +04:00
if ( params = = NULL ) {
2007-08-13 23:22:07 +04:00
reply_doserror ( req , ERRDOS , ERRnomem ) ;
return ;
2005-07-08 08:51:27 +04:00
}
2007-09-12 03:57:59 +04:00
2000-05-23 21:57:51 +04:00
p = params ;
SCVAL ( p , 0 , NO_OPLOCK_RETURN ) ;
2007-09-12 03:57:59 +04:00
2000-05-23 21:57:51 +04:00
p + = 2 ;
SSVAL ( p , 0 , pnum ) ;
p + = 2 ;
SIVAL ( p , 0 , FILE_WAS_OPENED ) ;
p + = 8 ;
2007-09-12 03:57:59 +04:00
2000-05-23 21:57:51 +04:00
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 ) ; /* ? */
2007-04-08 08:54:44 +04:00
p + = 4 ;
2007-09-12 03:57:59 +04:00
2007-04-08 08:54:44 +04:00
if ( flags & EXTENDED_RESPONSE_REQUIRED ) {
2007-06-05 02:29:23 +04:00
p + = 25 ;
2007-04-08 08:54:44 +04:00
SIVAL ( p , 0 , FILE_GENERIC_ALL ) ;
2007-09-12 03:57:59 +04:00
/*
2007-04-08 08:54:44 +04:00
* For pipes W2K3 seems to return
* 0x12019B next .
* This is ( ( FILE_GENERIC_READ | FILE_GENERIC_WRITE ) & ~ FILE_APPEND_DATA )
*/
SIVAL ( p , 4 , ( FILE_GENERIC_READ | FILE_GENERIC_WRITE ) & ~ FILE_APPEND_DATA ) ;
}
2000-05-23 21:57:51 +04:00
DEBUG ( 5 , ( " do_nt_transact_create_pipe: open name = %s \n " , fname ) ) ;
2007-09-12 03:57:59 +04:00
2000-05-23 21:57:51 +04:00
/* Send the required number of replies */
2007-08-14 12:24:02 +04:00
send_nt_replies ( req , NT_STATUS_OK , params , param_len , * ppdata , 0 ) ;
2007-09-12 03:57:59 +04:00
2007-08-13 23:22:07 +04:00
return ;
2000-05-23 21:57:51 +04:00
}
2001-01-31 08:14:31 +03:00
/****************************************************************************
Internal fn to set security descriptors .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-07-15 14:35:28 +04:00
static NTSTATUS set_sd ( files_struct * fsp , char * data , uint32 sd_len , uint32 security_info_sent )
2001-01-31 08:14:31 +03:00
{
prs_struct pd ;
SEC_DESC * psd = NULL ;
TALLOC_CTX * mem_ctx ;
2007-06-27 02:49:10 +04:00
NTSTATUS status ;
2007-09-12 03:57:59 +04:00
2004-09-23 04:19:18 +04:00
if ( sd_len = = 0 | | ! lp_nt_acl_support ( SNUM ( fsp - > conn ) ) ) {
2002-07-15 14:35:28 +04:00
return NT_STATUS_OK ;
2001-01-31 08:14:31 +03:00
}
/*
* Init the parse struct we will unmarshall from .
*/
2002-12-20 23:21:31 +03:00
if ( ( mem_ctx = talloc_init ( " set_sd " ) ) = = NULL ) {
2001-01-31 08:14:31 +03:00
DEBUG ( 0 , ( " set_sd: talloc_init failed. \n " ) ) ;
2002-07-15 14:35:28 +04:00
return NT_STATUS_NO_MEMORY ;
2001-01-31 08:14:31 +03:00
}
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 .
*/
2007-09-12 03:57:59 +04:00
2001-01-31 08:14:31 +03:00
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 . .
2007-09-12 03:57:59 +04:00
*/
2001-01-31 08:14:31 +03:00
talloc_destroy ( mem_ctx ) ;
2002-07-15 14:35:28 +04:00
return NT_STATUS_NO_MEMORY ;
2001-01-31 08:14:31 +03:00
}
2007-09-12 03:57:59 +04:00
2006-09-21 02:23:12 +04:00
if ( psd - > owner_sid = = 0 ) {
2001-02-12 19:18:02 +03:00
security_info_sent & = ~ OWNER_SECURITY_INFORMATION ;
2005-07-08 08:51:27 +04:00
}
2006-09-21 02:23:12 +04:00
if ( psd - > group_sid = = 0 ) {
2001-02-12 19:18:02 +03:00
security_info_sent & = ~ GROUP_SECURITY_INFORMATION ;
2005-07-08 08:51:27 +04:00
}
2006-09-21 02:23:12 +04:00
if ( psd - > sacl = = 0 ) {
2001-02-12 19:18:02 +03:00
security_info_sent & = ~ SACL_SECURITY_INFORMATION ;
2005-07-08 08:51:27 +04:00
}
2006-09-21 02:23:12 +04:00
if ( psd - > dacl = = 0 ) {
2001-02-13 01:37:40 +03:00
security_info_sent & = ~ DACL_SECURITY_INFORMATION ;
2005-07-08 08:51:27 +04:00
}
2007-09-12 03:57:59 +04:00
2007-06-27 02:49:10 +04:00
status = SMB_VFS_FSET_NT_ACL ( fsp , fsp - > fh - > fd , security_info_sent , psd ) ;
2007-09-12 03:57:59 +04:00
2001-01-31 08:14:31 +03:00
talloc_destroy ( mem_ctx ) ;
2007-06-27 02:49:10 +04:00
return status ;
2001-01-31 08:14:31 +03:00
}
2005-03-31 04:36:22 +04:00
/****************************************************************************
Read a list of EA names and data from an incoming data buffer . Create an ea_list with them .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-09-12 03:57:59 +04:00
2005-03-31 04:36:22 +04:00
static struct ea_list * read_nttrans_ea_list ( TALLOC_CTX * ctx , const char * pdata , size_t data_size )
{
struct ea_list * ea_list_head = NULL ;
size_t offset = 0 ;
if ( data_size < 4 ) {
return NULL ;
}
while ( offset + 4 < = data_size ) {
size_t next_offset = IVAL ( pdata , offset ) ;
struct ea_list * eal = read_ea_list_entry ( ctx , pdata + offset + 4 , data_size - offset - 4 , NULL ) ;
2006-06-17 02:40:07 +04:00
if ( ! eal ) {
return NULL ;
}
2006-09-18 11:52:16 +04:00
DLIST_ADD_END ( ea_list_head , eal , struct ea_list * ) ;
2005-03-31 04:36:22 +04:00
if ( next_offset = = 0 ) {
break ;
}
offset + = next_offset ;
}
2007-09-08 00:57:01 +04:00
2005-03-31 04:36:22 +04:00
return ea_list_head ;
}
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
2007-08-13 23:03:52 +04:00
static void call_nt_transact_create ( connection_struct * conn ,
struct smb_request * req ,
uint16 * * ppsetup , uint32 setup_count ,
char * * ppparams , uint32 parameter_count ,
char * * ppdata , uint32 data_count ,
uint32 max_data_count )
1998-07-02 22:49:08 +04:00
{
2007-09-08 00:57:01 +04:00
char * fname = NULL ;
2002-07-15 14:35:28 +04:00
char * params = * ppparams ;
char * data = * ppdata ;
/* Breakout the oplock request bits so we can set the reply bits separately. */
int oplock_request = 0 ;
2005-07-08 08:51:27 +04:00
uint32 fattr = 0 ;
2002-07-15 14:35:28 +04:00
SMB_OFF_T file_len = 0 ;
SMB_STRUCT_STAT sbuf ;
2005-07-08 08:51:27 +04:00
int info = 0 ;
2002-07-15 14:35:28 +04:00
files_struct * fsp = NULL ;
char * p = NULL ;
2007-10-19 04:40:25 +04:00
bool extended_oplock_granted = False ;
2002-07-15 14:35:28 +04:00
uint32 flags ;
2005-07-08 08:51:27 +04:00
uint32 access_mask ;
2002-07-15 14:35:28 +04:00
uint32 file_attributes ;
uint32 share_access ;
uint32 create_disposition ;
uint32 create_options ;
uint32 sd_len ;
2005-03-31 04:36:22 +04:00
uint32 ea_len ;
2002-07-15 14:35:28 +04:00
uint16 root_dir_fid ;
2006-08-24 20:44:00 +04:00
struct timespec c_timespec ;
struct timespec a_timespec ;
struct timespec m_timespec ;
2005-03-31 04:36:22 +04:00
struct ea_list * ea_list = NULL ;
char * pdata = NULL ;
2004-03-03 23:55:59 +03:00
NTSTATUS status ;
2007-04-08 08:54:44 +04:00
size_t param_len ;
2007-07-09 18:43:36 +04:00
struct case_semantics_state * case_state = NULL ;
2007-09-11 22:31:29 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2000-03-13 23:05:18 +03:00
2002-07-15 14:35:28 +04:00
DEBUG ( 5 , ( " call_nt_transact_create \n " ) ) ;
/*
* If it ' s an IPC , use the pipe handler .
*/
2000-05-23 21:57:51 +04:00
2002-07-15 14:35:28 +04:00
if ( IS_IPC ( conn ) ) {
2005-07-08 08:51:27 +04:00
if ( lp_nt_pipe_support ( ) ) {
2007-08-13 23:22:07 +04:00
do_nt_transact_create_pipe (
conn , req ,
ppsetup , setup_count ,
ppparams , parameter_count ,
ppdata , data_count ) ;
2007-08-13 23:03:52 +04:00
return ;
2005-07-08 08:51:27 +04:00
} else {
2007-08-13 23:03:52 +04:00
reply_doserror ( req , ERRDOS , ERRnoaccess ) ;
return ;
2005-07-08 08:51:27 +04:00
}
2002-07-15 14:35:28 +04:00
}
2000-05-23 21:57:51 +04:00
2002-07-15 14:35:28 +04:00
/*
* Ensure minimum number of parameters sent .
*/
2000-03-13 23:05:18 +03:00
2003-05-30 03:49:31 +04:00
if ( parameter_count < 54 ) {
DEBUG ( 0 , ( " call_nt_transact_create - insufficient parameters (%u) \n " , ( unsigned int ) parameter_count ) ) ;
2007-08-13 23:03:52 +04:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
return ;
2002-07-15 14:35:28 +04:00
}
2000-03-13 23:05:18 +03:00
2002-07-15 14:35:28 +04:00
flags = IVAL ( params , 0 ) ;
2005-07-08 08:51:27 +04:00
access_mask = IVAL ( params , 8 ) ;
2002-07-15 14:35:28 +04:00
file_attributes = IVAL ( params , 20 ) ;
share_access = IVAL ( params , 24 ) ;
create_disposition = IVAL ( params , 28 ) ;
create_options = IVAL ( params , 32 ) ;
sd_len = IVAL ( params , 36 ) ;
2005-03-31 04:36:22 +04:00
ea_len = IVAL ( params , 40 ) ;
2002-07-15 14:35:28 +04:00
root_dir_fid = ( uint16 ) IVAL ( params , 4 ) ;
1998-07-08 05:42:05 +04:00
2005-03-31 04:36:22 +04:00
/* Ensure the data_len is correct for the sd and ea values given. */
if ( ( ea_len + sd_len > data_count ) | |
( ea_len > data_count ) | | ( sd_len > data_count ) | |
( ea_len + sd_len < ea_len ) | | ( ea_len + sd_len < sd_len ) ) {
2005-03-31 06:12:09 +04:00
DEBUG ( 10 , ( " call_nt_transact_create - ea_len = %u, sd_len = %u, data_count = %u \n " ,
( unsigned int ) ea_len , ( unsigned int ) sd_len , ( unsigned int ) data_count ) ) ;
2007-08-13 23:03:52 +04:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
return ;
2005-03-31 04:36:22 +04:00
}
2005-03-31 06:12:09 +04:00
if ( ea_len ) {
if ( ! lp_ea_support ( SNUM ( conn ) ) ) {
DEBUG ( 10 , ( " call_nt_transact_create - ea_len = %u but EA's not supported. \n " ,
( unsigned int ) ea_len ) ) ;
2007-08-13 23:03:52 +04:00
reply_nterror ( req , NT_STATUS_EAS_NOT_SUPPORTED ) ;
return ;
2005-03-31 06:12:09 +04:00
}
2005-03-31 04:36:22 +04:00
2005-03-31 06:12:09 +04:00
if ( ea_len < 10 ) {
DEBUG ( 10 , ( " call_nt_transact_create - ea_len = %u - too small (should be more than 10) \n " ,
( unsigned int ) ea_len ) ) ;
2007-08-13 23:03:52 +04:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
return ;
2005-03-31 06:12:09 +04:00
}
2005-03-31 04:36:22 +04:00
}
2002-09-25 19:19:00 +04:00
if ( create_options & FILE_OPEN_BY_FILE_ID ) {
2007-08-13 23:03:52 +04:00
reply_nterror ( req , NT_STATUS_NOT_SUPPORTED ) ;
return ;
2002-09-25 19:19:00 +04:00
}
2002-07-15 14:35:28 +04:00
/*
* Get the file name .
*/
1998-07-08 05:42:05 +04:00
2002-07-15 14:35:28 +04:00
if ( root_dir_fid ! = 0 ) {
/*
* This filename is relative to a directory fid .
*/
2007-09-12 03:57:59 +04:00
char * tmpname = NULL ;
2007-07-31 16:05:40 +04:00
files_struct * dir_fsp = file_fsp ( SVAL ( params , 4 ) ) ;
1998-09-30 23:27:04 +04:00
2005-07-08 08:51:27 +04:00
if ( ! dir_fsp ) {
2007-08-13 23:03:52 +04:00
reply_doserror ( req , ERRDOS , ERRbadfid ) ;
return ;
2005-07-08 08:51:27 +04:00
}
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
if ( ! dir_fsp - > is_directory ) {
2007-09-12 03:57:59 +04:00
srvstr_get_path ( ctx , params , req - > flags2 , & fname ,
params + 53 ,
2007-07-05 20:36:15 +04:00
parameter_count - 53 , STR_TERMINATE ,
& status ) ;
2004-03-03 23:55:59 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-13 23:03:52 +04:00
reply_nterror ( req , status ) ;
return ;
2003-10-09 03:21:36 +04:00
}
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
/*
* Check to see if this is a mac fork of some kind .
*/
1999-12-13 16:27:58 +03:00
2007-09-12 03:57:59 +04:00
if ( is_ntfs_stream_name ( fname ) ) {
2007-08-13 23:03:52 +04:00
reply_nterror ( req ,
NT_STATUS_OBJECT_PATH_NOT_FOUND ) ;
return ;
2005-05-06 17:26:54 +04:00
}
1998-09-30 23:27:04 +04:00
2007-08-13 23:03:52 +04:00
reply_doserror ( req , ERRDOS , ERRbadfid ) ;
return ;
2002-07-15 14:35:28 +04:00
}
1998-09-30 23:27:04 +04:00
2007-09-24 23:11:42 +04:00
if ( ISDOT ( dir_fsp - > fsp_name ) ) {
/*
* We ' re at the toplevel dir , the final file name
* must not contain . / , as this is filtered out
* normally by srvstr_get_path and unix_convert
* explicitly rejects paths containing . / .
*/
fname = talloc_strdup ( ctx , " " ) ;
if ( ! fname ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
return ;
}
} else {
size_t dir_name_len = strlen ( dir_fsp - > fsp_name ) ;
1998-09-30 23:27:04 +04:00
2007-09-24 23:11:42 +04:00
/*
* Copy in the base directory name .
*/
1998-09-30 23:27:04 +04:00
2007-09-24 23:11:42 +04:00
fname = TALLOC_ARRAY ( ctx , char , dir_name_len + 2 ) ;
if ( ! fname ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
return ;
}
memcpy ( fname , dir_fsp - > fsp_name , dir_name_len + 1 ) ;
/*
* Ensure it ends in a ' / ' .
* We used TALLOC_SIZE + 2 to add space for the ' / ' .
*/
1998-09-30 23:27:04 +04:00
2007-09-24 23:11:42 +04:00
if ( dir_name_len & &
( fname [ dir_name_len - 1 ] ! = ' \\ ' ) & &
( fname [ dir_name_len - 1 ] ! = ' / ' ) ) {
fname [ dir_name_len ] = ' / ' ;
fname [ dir_name_len + 1 ] = ' \0 ' ;
}
2002-07-15 14:35:28 +04:00
}
1998-07-08 05:42:05 +04:00
2007-09-12 03:57:59 +04:00
srvstr_get_path ( ctx , params , req - > flags2 , & tmpname ,
params + 53 ,
parameter_count - 53 , STR_TERMINATE ,
& status ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
reply_nterror ( req , status ) ;
return ;
}
fname = talloc_asprintf ( ctx , " %s%s " ,
fname ,
tmpname ) ;
if ( ! fname ) {
reply_nterror (
req , NT_STATUS_NO_MEMORY ) ;
return ;
2003-10-09 03:21:36 +04:00
}
2002-07-15 14:35:28 +04:00
} else {
2007-09-12 03:57:59 +04:00
srvstr_get_path ( ctx , params , req - > flags2 , & fname , params + 53 ,
parameter_count - 53 ,
2007-07-05 20:36:15 +04:00
STR_TERMINATE , & status ) ;
2004-03-03 23:55:59 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-13 23:03:52 +04:00
reply_nterror ( req , status ) ;
return ;
2003-10-09 03:21:36 +04:00
}
2002-07-15 14:35:28 +04:00
/*
* Check to see if this is a mac fork of some kind .
*/
2007-09-12 03:57:59 +04:00
if ( is_ntfs_stream_name ( fname ) ) {
2007-08-13 23:03:52 +04:00
reply_nterror ( req , NT_STATUS_OBJECT_PATH_NOT_FOUND ) ;
return ;
2005-05-06 17:26:54 +04:00
}
2002-07-15 14:35:28 +04:00
}
1999-12-13 16:27:58 +03:00
2002-07-15 14:35:28 +04:00
oplock_request = ( flags & REQUEST_OPLOCK ) ? EXCLUSIVE_OPLOCK : 0 ;
2007-03-07 17:25:07 +03:00
if ( oplock_request ) {
oplock_request | = ( flags & REQUEST_BATCH_OPLOCK ) ? BATCH_OPLOCK : 0 ;
}
2002-07-15 14:35:28 +04:00
2007-03-07 16:57:32 +03:00
/*
* Ordinary file or directory .
*/
2007-09-08 00:57:01 +04:00
2002-07-15 14:35:28 +04:00
/*
* Check if POSIX semantics are wanted .
*/
2007-07-09 18:43:36 +04:00
if ( file_attributes & FILE_FLAG_POSIX_SEMANTICS ) {
case_state = set_posix_case_semantics ( NULL , conn ) ;
file_attributes & = ~ FILE_FLAG_POSIX_SEMANTICS ;
}
2007-09-08 00:57:01 +04:00
2007-09-11 22:31:29 +04:00
status = resolve_dfspath ( ctx , conn ,
req - > flags2 & FLAGS2_DFS_PATHNAMES ,
2007-09-12 03:57:59 +04:00
fname ,
2007-09-11 22:31:29 +04:00
& fname ) ;
2007-03-12 20:55:24 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-07-09 18:43:36 +04:00
TALLOC_FREE ( case_state ) ;
2007-03-12 20:55:24 +03:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
2007-08-13 23:03:52 +04:00
reply_botherror ( req , NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
return ;
2007-03-12 20:55:24 +03:00
}
2007-08-13 23:03:52 +04:00
reply_nterror ( req , status ) ;
return ;
2007-03-08 01:12:58 +03:00
}
1998-07-17 02:46:06 +04:00
2007-09-14 02:08:59 +04:00
status = unix_convert ( ctx , conn , fname , False , & fname , NULL , & sbuf ) ;
2007-01-13 02:47:16 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-07-09 18:43:36 +04:00
TALLOC_FREE ( case_state ) ;
2007-08-13 23:03:52 +04:00
reply_nterror ( req , status ) ;
return ;
2004-06-11 21:54:23 +04:00
}
/* All file access must go through check_name() */
2007-01-17 05:09:37 +03:00
status = check_name ( conn , fname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-07-09 18:43:36 +04:00
TALLOC_FREE ( case_state ) ;
2007-08-13 23:03:52 +04:00
reply_nterror ( req , status ) ;
return ;
2004-06-11 21:54:23 +04:00
}
2007-03-07 16:57:32 +03:00
2005-02-24 04:03:35 +03:00
/* This is the correct thing to do (check every time) but can_delete is
expensive ( it may have to read the parent directory permissions ) . So
for now we ' re not doing it unless we have a strong hint the client
2007-01-13 05:34:43 +03:00
is really going to delete this file . If the client is forcing FILE_CREATE
let the filesystem take care of the permissions . */
2005-02-24 04:03:35 +03:00
/* Setting FILE_SHARE_DELETE is the hint. */
2007-01-13 05:34:43 +03:00
2007-01-02 15:10:46 +03:00
if ( lp_acl_check_permissions ( SNUM ( conn ) )
2007-01-13 05:34:43 +03:00
& & ( create_disposition ! = FILE_CREATE )
2007-01-02 15:10:46 +03:00
& & ( share_access & FILE_SHARE_DELETE )
2007-01-18 09:19:24 +03:00
& & ( access_mask & DELETE_ACCESS ) ) {
if ( ( dos_mode ( conn , fname , & sbuf ) & FILE_ATTRIBUTE_READONLY ) | |
! can_delete_file_in_directory ( conn , fname ) ) {
2007-07-09 18:43:36 +04:00
TALLOC_FREE ( case_state ) ;
2007-08-13 23:03:52 +04:00
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
return ;
2007-01-18 09:19:24 +03:00
}
2005-02-11 05:14:49 +03:00
}
2007-07-07 12:46:26 +04:00
#if 0
/* We need to support SeSecurityPrivilege for this. */
2007-07-09 18:43:36 +04:00
if ( ( access_mask & SEC_RIGHT_SYSTEM_SECURITY ) & &
2007-07-07 12:46:26 +04:00
! user_has_privileges ( current_user . nt_user_token ,
& se_security ) ) {
2007-07-09 18:43:36 +04:00
TALLOC_FREE ( case_state ) ;
2007-08-13 23:03:52 +04:00
reply_nterror ( req , NT_STATUS_PRIVILEGE_NOT_HELD ) ;
return ;
2007-07-07 12:46:26 +04:00
}
# endif
2005-03-31 06:12:09 +04:00
if ( ea_len ) {
pdata = data + sd_len ;
2005-03-31 04:36:22 +04:00
2005-03-31 06:12:09 +04:00
/* We have already checked that ea_len <= data_count here. */
2007-08-30 23:48:31 +04:00
ea_list = read_nttrans_ea_list ( talloc_tos ( ) , pdata ,
2006-12-24 20:09:08 +03:00
ea_len ) ;
2005-03-31 06:12:09 +04:00
if ( ! ea_list ) {
2007-07-09 18:43:36 +04:00
TALLOC_FREE ( case_state ) ;
2007-08-13 23:03:52 +04:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
return ;
2005-03-31 06:12:09 +04:00
}
2005-03-31 04:36:22 +04:00
}
2002-07-15 14:35:28 +04:00
/*
* If it ' s a request for a directory open , deal with it separately .
*/
1998-07-08 05:42:05 +04:00
2002-07-15 14:35:28 +04:00
if ( create_options & FILE_DIRECTORY_FILE ) {
1998-07-31 01:18:57 +04:00
2002-09-25 19:19:00 +04:00
/* Can't open a temp directory. IFS kit test. */
if ( file_attributes & FILE_ATTRIBUTE_TEMPORARY ) {
2007-07-09 18:43:36 +04:00
TALLOC_FREE ( case_state ) ;
2007-08-13 23:03:52 +04:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
return ;
2002-09-25 19:19:00 +04:00
}
2002-07-15 14:35:28 +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
2007-03-07 17:25:07 +03:00
oplock_request = 0 ;
2007-08-13 23:03:52 +04:00
status = open_directory ( conn , req , fname , & sbuf ,
2005-07-08 08:51:27 +04:00
access_mask ,
share_access ,
create_disposition ,
create_options ,
2007-07-09 18:43:36 +04:00
file_attributes ,
2006-07-11 22:01:26 +04:00
& info , & fsp ) ;
2002-07-15 14:35:28 +04:00
} else {
1998-07-08 05:42:05 +04:00
2002-07-15 14:35:28 +04:00
/*
* Ordinary file case .
*/
1998-07-08 05:42:05 +04:00
2007-08-13 23:03:52 +04:00
status = open_file_ntcreate ( conn , req , fname , & sbuf ,
2005-07-08 08:51:27 +04:00
access_mask ,
share_access ,
create_disposition ,
create_options ,
2007-07-09 18:43:36 +04:00
file_attributes ,
2005-07-08 08:51:27 +04:00
oplock_request ,
2006-07-11 22:01:26 +04:00
& info , & fsp ) ;
1998-07-08 05:42:05 +04:00
2007-08-16 21:42:34 +04:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_FILE_IS_A_DIRECTORY ) ) {
1998-07-31 01:18:57 +04:00
2007-08-16 21:42:34 +04:00
/*
* Fail the open if it was explicitly a non - directory file .
*/
1998-07-08 05:42:05 +04:00
2007-08-16 21:42:34 +04:00
if ( create_options & FILE_NON_DIRECTORY_FILE ) {
2007-07-09 18:43:36 +04:00
TALLOC_FREE ( case_state ) ;
2007-08-16 21:42:34 +04:00
reply_force_nterror (
req ,
NT_STATUS_FILE_IS_A_DIRECTORY ) ;
2007-08-13 23:03:52 +04:00
return ;
1999-12-13 16:27:58 +03:00
}
2007-08-16 21:42:34 +04:00
oplock_request = 0 ;
status = open_directory ( conn , req , fname ,
& sbuf ,
access_mask ,
share_access ,
create_disposition ,
create_options ,
file_attributes ,
& info , & fsp ) ;
}
}
TALLOC_FREE ( case_state ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( open_was_deferred ( req - > mid ) ) {
/* We have re-scheduled this call. */
return ;
}
reply_openerror ( req , status ) ;
return ;
2002-07-15 14:35:28 +04:00
}
2001-01-31 08:14:31 +03:00
2002-07-15 14:35:28 +04:00
/*
2005-03-30 06:24:47 +04:00
* According to the MS documentation , the only time the security
* descriptor is applied to the opened file is iff we * created * the
* file ; an existing file stays the same .
2007-09-12 03:57:59 +04:00
*
2005-03-30 06:24:47 +04:00
* Also , it seems ( from observation ) that you can open the file with
* any access mask but you can still write the sd . We need to override
* the granted access before we call set_sd
* Patch for bug # 2242 from Tom Lackemann < cessnatomny @ yahoo . com > .
2002-07-15 14:35:28 +04:00
*/
2001-01-31 08:14:31 +03:00
2005-07-08 08:51:27 +04:00
if ( lp_nt_acl_support ( SNUM ( conn ) ) & & sd_len & & info = = FILE_WAS_CREATED ) {
uint32 saved_access_mask = fsp - > access_mask ;
2005-03-30 06:24:47 +04:00
2005-03-31 04:36:22 +04:00
/* We have already checked that sd_len <= data_count here. */
2005-07-08 08:51:27 +04:00
fsp - > access_mask = FILE_GENERIC_ALL ;
2005-03-30 06:24:47 +04:00
2005-03-31 06:12:09 +04:00
status = set_sd ( fsp , data , sd_len , ALL_SECURITY_INFORMATION ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2006-02-02 23:44:50 +03:00
close_file ( fsp , ERROR_CLOSE ) ;
2007-07-09 18:43:36 +04:00
TALLOC_FREE ( case_state ) ;
2007-08-13 23:03:52 +04:00
reply_nterror ( req , status ) ;
return ;
2005-03-30 06:24:47 +04:00
}
2005-07-08 08:51:27 +04:00
fsp - > access_mask = saved_access_mask ;
2005-03-30 06:24:47 +04:00
}
2007-09-12 03:57:59 +04:00
2005-07-08 08:51:27 +04:00
if ( ea_len & & ( info = = FILE_WAS_CREATED ) ) {
2005-03-31 04:36:22 +04:00
status = set_ea ( conn , fsp , fname , ea_list ) ;
2005-03-31 06:12:09 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2006-02-02 23:44:50 +03:00
close_file ( fsp , ERROR_CLOSE ) ;
2007-07-09 18:43:36 +04:00
TALLOC_FREE ( case_state ) ;
2007-08-13 23:03:52 +04:00
reply_nterror ( req , status ) ;
return ;
2005-03-31 04:36:22 +04:00
}
}
2007-07-09 18:43:36 +04:00
TALLOC_FREE ( case_state ) ;
1998-07-31 01:18:57 +04:00
2005-04-05 05:20:32 +04:00
file_len = sbuf . st_size ;
2005-07-08 08:51:27 +04:00
fattr = dos_mode ( conn , fname , & sbuf ) ;
if ( fattr = = 0 ) {
fattr = FILE_ATTRIBUTE_NORMAL ;
2005-04-05 05:20:32 +04:00
}
2005-07-08 08:51:27 +04:00
if ( ! fsp - > is_directory & & ( fattr & aDIR ) ) {
2006-02-02 23:44:50 +03:00
close_file ( fsp , ERROR_CLOSE ) ;
2007-08-13 23:03:52 +04:00
reply_doserror ( req , ERRDOS , ERRnoaccess ) ;
return ;
2007-09-12 03:57:59 +04:00
}
2002-09-25 19:19:00 +04:00
/* Save the requested allocation size. */
2005-07-08 08:51:27 +04:00
if ( ( info = = FILE_WAS_CREATED ) | | ( info = = FILE_WAS_OVERWRITTEN ) ) {
2005-04-01 04:21:55 +04:00
SMB_BIG_UINT allocation_size = ( SMB_BIG_UINT ) IVAL ( params , 12 ) ;
2002-09-25 19:19:00 +04:00
# ifdef LARGE_SMB_OFF_T
2005-04-01 04:21:55 +04:00
allocation_size | = ( ( ( SMB_BIG_UINT ) IVAL ( params , 16 ) ) < < 32 ) ;
2002-09-25 19:19:00 +04:00
# endif
2005-04-01 04:21:55 +04:00
if ( allocation_size & & ( allocation_size > file_len ) ) {
fsp - > initial_allocation_size = smb_roundup ( fsp - > conn , allocation_size ) ;
if ( fsp - > is_directory ) {
2006-02-02 23:44:50 +03:00
close_file ( fsp , ERROR_CLOSE ) ;
2005-04-01 04:21:55 +04:00
/* Can't set allocation size on a directory. */
2007-08-13 23:03:52 +04:00
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
return ;
2005-04-01 04:21:55 +04:00
}
if ( vfs_allocate_file_space ( fsp , fsp - > initial_allocation_size ) = = - 1 ) {
2006-02-02 23:44:50 +03:00
close_file ( fsp , ERROR_CLOSE ) ;
2007-08-13 23:03:52 +04:00
reply_nterror ( req , NT_STATUS_DISK_FULL ) ;
return ;
2005-04-01 04:21:55 +04:00
}
} else {
fsp - > initial_allocation_size = smb_roundup ( fsp - > conn , ( SMB_BIG_UINT ) file_len ) ;
2002-09-25 19:19:00 +04:00
}
}
2007-09-12 03:57:59 +04:00
/*
2005-04-05 05:20:32 +04:00
* If the caller set the extended oplock request bit
* and we granted one ( by whatever means ) - set the
* correct bit for extended oplock reply .
*/
2007-03-07 16:57:32 +03:00
2005-04-05 05:20:32 +04:00
if ( oplock_request & & lp_fake_oplocks ( SNUM ( conn ) ) ) {
extended_oplock_granted = True ;
}
2007-03-07 16:57:32 +03:00
2005-04-05 05:20:32 +04:00
if ( oplock_request & & EXCLUSIVE_OPLOCK_TYPE ( fsp - > oplock_type ) ) {
extended_oplock_granted = True ;
}
2002-07-15 14:35:28 +04:00
/* Realloc the size of parameters and data we will return */
2007-04-08 08:54:44 +04:00
if ( flags & EXTENDED_RESPONSE_REQUIRED ) {
/* Extended response is 32 more byyes. */
param_len = 101 ;
} else {
param_len = 69 ;
}
params = nttrans_realloc ( ppparams , param_len ) ;
2005-07-08 08:51:27 +04:00
if ( params = = NULL ) {
2007-08-13 23:03:52 +04:00
reply_doserror ( req , ERRDOS , ERRnomem ) ;
return ;
2005-07-08 08:51:27 +04:00
}
1998-07-09 04:41:32 +04:00
2002-07-15 14:35:28 +04:00
p = params ;
2005-07-08 08:51:27 +04:00
if ( extended_oplock_granted ) {
2006-12-23 21:55:08 +03:00
if ( flags & REQUEST_BATCH_OPLOCK ) {
SCVAL ( p , 0 , BATCH_OPLOCK_RETURN ) ;
} else {
SCVAL ( p , 0 , EXCLUSIVE_OPLOCK_RETURN ) ;
}
} else if ( fsp - > oplock_type = = LEVEL_II_OPLOCK ) {
2002-07-15 14:35:28 +04:00
SCVAL ( p , 0 , LEVEL_II_OPLOCK_RETURN ) ;
2005-07-08 08:51:27 +04:00
} else {
2002-07-15 14:35:28 +04:00
SCVAL ( p , 0 , NO_OPLOCK_RETURN ) ;
2005-07-08 08:51:27 +04:00
}
2007-09-12 03:57:59 +04:00
2002-07-15 14:35:28 +04:00
p + = 2 ;
SSVAL ( p , 0 , fsp - > fnum ) ;
p + = 2 ;
2005-07-08 08:51:27 +04:00
if ( ( create_disposition = = FILE_SUPERSEDE ) & & ( info = = FILE_WAS_OVERWRITTEN ) ) {
2002-09-25 19:19:00 +04:00
SIVAL ( p , 0 , FILE_WAS_SUPERSEDED ) ;
2005-07-08 08:51:27 +04:00
} else {
SIVAL ( p , 0 , info ) ;
}
2002-07-15 14:35:28 +04:00
p + = 8 ;
2001-07-04 05:01:02 +04:00
2002-07-15 14:35:28 +04:00
/* Create time. */
2006-08-24 20:44:00 +04:00
c_timespec = get_create_timespec ( & sbuf , lp_fake_dir_create_times ( SNUM ( conn ) ) ) ;
a_timespec = get_atimespec ( & sbuf ) ;
m_timespec = get_mtimespec ( & sbuf ) ;
1998-07-09 04:41:32 +04:00
2002-07-15 14:35:28 +04:00
if ( lp_dos_filetime_resolution ( SNUM ( conn ) ) ) {
2006-08-24 20:44:00 +04:00
dos_filetime_timespec ( & c_timespec ) ;
dos_filetime_timespec ( & a_timespec ) ;
dos_filetime_timespec ( & m_timespec ) ;
2002-07-15 14:35:28 +04:00
}
2006-08-24 20:44:00 +04:00
put_long_date_timespec ( p , c_timespec ) ; /* create time. */
2002-07-15 14:35:28 +04:00
p + = 8 ;
2006-08-24 20:44:00 +04:00
put_long_date_timespec ( p , a_timespec ) ; /* access time */
2002-07-15 14:35:28 +04:00
p + = 8 ;
2006-08-24 20:44:00 +04:00
put_long_date_timespec ( p , m_timespec ) ; /* write time */
2002-07-15 14:35:28 +04:00
p + = 8 ;
2006-08-24 20:44:00 +04:00
put_long_date_timespec ( p , m_timespec ) ; /* change time */
2002-07-15 14:35:28 +04:00
p + = 8 ;
2005-07-08 08:51:27 +04:00
SIVAL ( p , 0 , fattr ) ; /* File Attributes. */
2002-07-15 14:35:28 +04:00
p + = 4 ;
2005-03-03 07:03:36 +03:00
SOFF_T ( p , 0 , get_allocation_size ( conn , fsp , & sbuf ) ) ;
2002-07-15 14:35:28 +04:00
p + = 8 ;
SOFF_T ( p , 0 , file_len ) ;
2004-02-25 05:15:34 +03:00
p + = 8 ;
2005-07-08 08:51:27 +04:00
if ( flags & EXTENDED_RESPONSE_REQUIRED ) {
2004-02-25 05:15:34 +03:00
SSVAL ( p , 2 , 0x7 ) ;
2005-07-08 08:51:27 +04:00
}
2004-02-25 05:15:34 +03:00
p + = 4 ;
SCVAL ( p , 0 , fsp - > is_directory ? 1 : 0 ) ;
2002-07-15 14:35:28 +04:00
2007-04-08 08:54:44 +04:00
if ( flags & EXTENDED_RESPONSE_REQUIRED ) {
uint32 perms = 0 ;
2007-06-05 02:29:23 +04:00
p + = 25 ;
2007-04-08 08:54:44 +04:00
if ( fsp - > is_directory | | can_write_to_file ( conn , fname , & sbuf ) ) {
perms = FILE_GENERIC_ALL ;
} else {
perms = FILE_GENERIC_READ | FILE_EXECUTE ;
}
SIVAL ( p , 0 , perms ) ;
}
2002-07-15 14:35:28 +04:00
DEBUG ( 5 , ( " call_nt_transact_create: open name = %s \n " , fname ) ) ;
/* Send the required number of replies */
2007-08-14 12:24:02 +04:00
send_nt_replies ( req , NT_STATUS_OK , params , param_len , * ppdata , 0 ) ;
2002-07-15 14:35:28 +04:00
2007-08-13 23:03:52 +04:00
return ;
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 .
2006-06-20 06:38:28 +04:00
conn POINTER CAN BE NULL HERE !
1998-07-08 05:42:05 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-08-17 19:27:10 +04:00
2007-07-31 14:04:54 +04:00
void reply_ntcancel ( connection_struct * conn , struct smb_request * req )
1998-07-08 05:42:05 +04:00
{
1998-08-14 21:38:29 +04:00
/*
* Go through and cancel any pending change notifies .
*/
2007-09-12 03:57:59 +04:00
2000-10-11 09:31:39 +04:00
START_PROFILE ( SMBntcancel ) ;
2007-07-31 14:04:54 +04:00
remove_pending_change_notify_requests_by_mid ( req - > mid ) ;
remove_pending_lock_requests_by_mid ( req - > mid ) ;
srv_cancel_sign_response ( req - > mid ) ;
2007-09-12 03:57:59 +04:00
2007-07-31 14:04:54 +04:00
DEBUG ( 3 , ( " reply_ntcancel: cancel called on mid = %d. \n " , req - > mid ) ) ;
1998-08-14 21:38:29 +04:00
2000-10-11 09:31:39 +04:00
END_PROFILE ( SMBntcancel ) ;
2007-07-31 14:04:54 +04:00
return ;
1998-07-08 05:42:05 +04:00
}
2004-06-26 03:48:23 +04:00
/****************************************************************************
Copy a file .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-09-14 02:08:59 +04:00
static NTSTATUS copy_internals ( TALLOC_CTX * ctx ,
connection_struct * conn ,
struct smb_request * req ,
const char * oldname_in ,
const char * newname_in ,
uint32 attrs )
2004-06-26 03:48:23 +04:00
{
SMB_STRUCT_STAT sbuf1 , sbuf2 ;
2007-09-08 00:57:01 +04:00
char * oldname = NULL ;
char * newname = NULL ;
char * last_component_oldname = NULL ;
char * last_component_newname = NULL ;
2004-06-26 03:48:23 +04:00
files_struct * fsp1 , * fsp2 ;
2005-07-08 08:51:27 +04:00
uint32 fattr ;
int info ;
2004-06-26 03:48:23 +04:00
SMB_OFF_T ret = - 1 ;
NTSTATUS status = NT_STATUS_OK ;
ZERO_STRUCT ( sbuf1 ) ;
ZERO_STRUCT ( sbuf2 ) ;
2007-01-17 05:09:37 +03:00
if ( ! CAN_WRITE ( conn ) ) {
2004-06-26 03:48:23 +04:00
return NT_STATUS_MEDIA_WRITE_PROTECTED ;
2007-01-17 05:09:37 +03:00
}
2004-06-26 03:48:23 +04:00
2007-09-14 02:08:59 +04:00
status = unix_convert ( ctx , conn , oldname_in , False , & oldname ,
2007-09-08 00:57:01 +04:00
& last_component_oldname , & sbuf1 ) ;
2007-01-13 02:47:16 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
2004-06-26 03:48:23 +04:00
}
2007-01-17 05:09:37 +03:00
status = check_name ( conn , oldname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
2004-06-26 03:48:23 +04:00
}
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
/* Source must already exist. */
if ( ! VALID_STAT ( sbuf1 ) ) {
return NT_STATUS_OBJECT_NAME_NOT_FOUND ;
}
2004-06-26 03:48:23 +04:00
/* Ensure attributes match. */
2005-07-08 08:51:27 +04:00
fattr = dos_mode ( conn , oldname , & sbuf1 ) ;
if ( ( fattr & ~ attrs ) & ( aHIDDEN | aSYSTEM ) ) {
2004-06-26 03:48:23 +04:00
return NT_STATUS_NO_SUCH_FILE ;
2005-07-08 08:51:27 +04:00
}
2004-06-26 03:48:23 +04:00
2007-09-14 02:08:59 +04:00
status = unix_convert ( ctx , conn , newname_in , False , & newname ,
2007-09-08 00:57:01 +04:00
& last_component_newname , & sbuf2 ) ;
2007-01-13 02:47:16 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
2004-06-26 03:48:23 +04:00
}
2007-01-17 05:09:37 +03:00
status = check_name ( conn , newname ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
2004-06-26 03:48:23 +04:00
}
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
/* Disallow if newname already exists. */
if ( VALID_STAT ( sbuf2 ) ) {
return NT_STATUS_OBJECT_NAME_COLLISION ;
}
2004-06-26 03:48:23 +04:00
/* No links from a directory. */
if ( S_ISDIR ( sbuf1 . st_mode ) ) {
return NT_STATUS_FILE_IS_A_DIRECTORY ;
}
/* Ensure this is within the share. */
2007-07-09 13:43:41 +04:00
status = check_reduced_name ( conn , oldname ) ;
2007-01-17 05:09:37 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
2004-06-26 03:48:23 +04:00
}
2007-09-08 00:57:01 +04:00
DEBUG ( 10 , ( " copy_internals: doing file copy %s to %s \n " ,
oldname , newname ) ) ;
2004-06-26 03:48:23 +04:00
2007-07-05 20:26:27 +04:00
status = open_file_ntcreate ( conn , req , oldname , & sbuf1 ,
2005-07-08 08:51:27 +04:00
FILE_READ_DATA , /* Read-only. */
2006-05-30 09:08:15 +04:00
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE ,
2005-07-08 08:51:27 +04:00
FILE_OPEN ,
0 , /* No create options. */
FILE_ATTRIBUTE_NORMAL ,
2006-05-30 09:08:15 +04:00
NO_OPLOCK ,
2006-07-11 22:01:26 +04:00
& info , & fsp1 ) ;
2004-06-26 03:48:23 +04:00
2006-07-11 22:01:26 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2004-06-26 03:48:23 +04:00
return status ;
}
2007-07-05 20:26:27 +04:00
status = open_file_ntcreate ( conn , req , newname , & sbuf2 ,
2006-07-11 22:01:26 +04:00
FILE_WRITE_DATA , /* Read-only. */
2006-05-30 09:08:15 +04:00
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE ,
2005-07-08 08:51:27 +04:00
FILE_CREATE ,
0 , /* No create options. */
fattr ,
2006-05-30 09:08:15 +04:00
NO_OPLOCK ,
2006-07-11 22:01:26 +04:00
& info , & fsp2 ) ;
2004-06-26 03:48:23 +04:00
2006-07-11 22:01:26 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2006-02-02 23:44:50 +03:00
close_file ( fsp1 , ERROR_CLOSE ) ;
2004-06-26 03:48:23 +04:00
return status ;
}
2005-07-08 08:51:27 +04:00
if ( sbuf1 . st_size ) {
2004-06-26 03:48:23 +04:00
ret = vfs_transfer_file ( fsp1 , fsp2 , sbuf1 . st_size ) ;
2005-07-08 08:51:27 +04:00
}
2004-06-26 03:48:23 +04:00
/*
* As we are opening fsp1 read - only we only expect
* an error on close on fsp2 if we are out of space .
* Thus we don ' t look at the error return from the
* close of fsp1 .
*/
2006-02-02 23:44:50 +03:00
close_file ( fsp1 , NORMAL_CLOSE ) ;
2004-06-26 03:48:23 +04:00
/* Ensure the modtime is set correctly on the destination file. */
2007-03-06 02:40:03 +03:00
fsp_set_pending_modtime ( fsp2 , get_mtimespec ( & sbuf1 ) ) ;
2004-06-26 03:48:23 +04:00
2007-02-07 00:05:34 +03:00
status = close_file ( fsp2 , NORMAL_CLOSE ) ;
2004-06-26 03:48:23 +04:00
2006-05-30 03:54:53 +04:00
/* Grrr. We have to do this as open_file_ntcreate adds aARCH when it
creates the file . This isn ' t the correct thing to do in the copy
case . JRA */
2006-12-27 13:57:59 +03:00
file_set_dosmode ( conn , newname , fattr , & sbuf2 ,
parent_dirname ( newname ) ) ;
2004-06-26 03:48:23 +04:00
if ( ret < ( SMB_OFF_T ) sbuf1 . st_size ) {
return NT_STATUS_DISK_FULL ;
}
2007-02-07 00:05:34 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2004-06-26 03:48:23 +04:00
DEBUG ( 3 , ( " copy_internals: Error %s copy file %s to %s \n " ,
nt_errstr ( status ) , oldname , newname ) ) ;
}
return status ;
}
2004-02-24 03:06:08 +03:00
/****************************************************************************
Reply to a NT rename request .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-08-15 00:02:11 +04:00
void reply_ntrename ( connection_struct * conn , struct smb_request * req )
2004-02-24 03:06:08 +03:00
{
2007-09-11 22:31:29 +04:00
char * oldname = NULL ;
char * newname = NULL ;
2004-02-24 03:06:08 +03:00
char * p ;
NTSTATUS status ;
2007-10-19 04:40:25 +04:00
bool src_has_wcard = False ;
bool dest_has_wcard = False ;
2007-08-15 00:02:11 +04:00
uint32 attrs ;
uint16 rename_type ;
2007-09-11 22:31:29 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2004-02-24 03:06:08 +03:00
START_PROFILE ( SMBntrename ) ;
2007-08-15 00:02:11 +04:00
if ( req - > wct < 4 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
END_PROFILE ( SMBntrename ) ;
return ;
}
attrs = SVAL ( req - > inbuf , smb_vwv0 ) ;
rename_type = SVAL ( req - > inbuf , smb_vwv1 ) ;
2007-07-05 20:26:27 +04:00
2007-08-15 00:02:11 +04:00
p = smb_buf ( req - > inbuf ) + 1 ;
2007-09-12 03:57:59 +04:00
p + = srvstr_get_path_wcard ( ctx , ( char * ) req - > inbuf , req - > flags2 , & oldname , p ,
0 , STR_TERMINATE , & status ,
2007-07-05 20:36:15 +04:00
& src_has_wcard ) ;
2004-02-24 03:06:08 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-15 00:02:11 +04:00
reply_nterror ( req , status ) ;
2004-02-24 03:06:08 +03:00
END_PROFILE ( SMBntrename ) ;
2007-08-15 00:02:11 +04:00
return ;
2004-02-24 03:06:08 +03:00
}
2004-03-03 23:55:59 +03:00
2007-09-12 03:57:59 +04:00
if ( is_ntfs_stream_name ( oldname ) ) {
2004-03-03 23:55:59 +03:00
/* Can't rename a stream. */
2007-08-15 00:02:11 +04:00
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
2004-03-03 23:55:59 +03:00
END_PROFILE ( SMBntrename ) ;
2007-08-15 00:02:11 +04:00
return ;
2004-03-03 23:55:59 +03:00
}
2007-09-12 03:57:59 +04:00
if ( ms_has_wild ( oldname ) ) {
2007-08-15 00:02:11 +04:00
reply_nterror ( req , NT_STATUS_OBJECT_PATH_SYNTAX_BAD ) ;
2004-06-26 02:37:50 +04:00
END_PROFILE ( SMBntrename ) ;
2007-08-15 00:02:11 +04:00
return ;
2004-06-26 02:37:50 +04:00
}
2004-02-24 03:06:08 +03:00
p + + ;
2007-09-12 03:57:59 +04:00
p + = srvstr_get_path_wcard ( ctx , ( char * ) req - > inbuf , req - > flags2 , & newname , p ,
0 , STR_TERMINATE , & status ,
2007-07-05 20:36:15 +04:00
& dest_has_wcard ) ;
2004-02-24 03:06:08 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-15 00:02:11 +04:00
reply_nterror ( req , status ) ;
2004-02-24 03:06:08 +03:00
END_PROFILE ( SMBntrename ) ;
2007-08-15 00:02:11 +04:00
return ;
2004-02-24 03:06:08 +03:00
}
2007-09-11 22:31:29 +04:00
status = resolve_dfspath ( ctx , conn ,
req - > flags2 & FLAGS2_DFS_PATHNAMES ,
2007-09-12 03:57:59 +04:00
oldname ,
2007-09-11 22:31:29 +04:00
& oldname ) ;
2007-03-12 20:55:24 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
2007-08-15 00:02:11 +04:00
reply_botherror ( req , NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
END_PROFILE ( SMBntrename ) ;
return ;
2007-03-12 20:55:24 +03:00
}
2007-08-15 00:02:11 +04:00
reply_nterror ( req , status ) ;
END_PROFILE ( SMBntrename ) ;
return ;
2007-03-08 01:12:58 +03:00
}
2007-03-12 20:55:24 +03:00
2007-09-11 22:31:29 +04:00
status = resolve_dfspath ( ctx , conn ,
req - > flags2 & FLAGS2_DFS_PATHNAMES ,
2007-09-12 03:57:59 +04:00
newname ,
2007-09-11 22:31:29 +04:00
& newname ) ;
2007-03-12 20:55:24 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
2007-08-15 00:02:11 +04:00
reply_botherror ( req , NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
END_PROFILE ( SMBntrename ) ;
return ;
2007-03-12 20:55:24 +03:00
}
2007-08-15 00:02:11 +04:00
reply_nterror ( req , status ) ;
END_PROFILE ( SMBntrename ) ;
return ;
2007-03-08 01:12:58 +03:00
}
2004-04-07 03:01:09 +04:00
DEBUG ( 3 , ( " reply_ntrename : %s -> %s \n " , oldname , newname ) ) ;
2007-09-11 22:31:29 +04:00
2004-06-26 03:48:23 +04:00
switch ( rename_type ) {
case RENAME_FLAG_RENAME :
2007-09-13 01:48:20 +04:00
status = rename_internals ( ctx , conn , req , oldname ,
newname , attrs , False , src_has_wcard ,
dest_has_wcard ) ;
2004-06-26 03:48:23 +04:00
break ;
case RENAME_FLAG_HARD_LINK :
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
if ( src_has_wcard | | dest_has_wcard ) {
2006-12-28 03:24:34 +03:00
/* No wildcards. */
status = NT_STATUS_OBJECT_PATH_SYNTAX_BAD ;
} else {
2007-09-14 02:08:59 +04:00
status = hardlink_internals ( ctx ,
conn ,
2007-09-13 01:48:20 +04:00
oldname ,
newname ) ;
2006-12-28 03:24:34 +03:00
}
2004-06-26 03:48:23 +04:00
break ;
case RENAME_FLAG_COPY :
r21672: The cannonical file access pattern should look like this :
srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
status = unix_convert(conn, name, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
status = check_name(conn, name);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
Make sure that every access pattern (including the
wildcard generated paths from unlink, rename, and copy)
do the same. Tidy things up a bit....
Jeremy.
(This used to be commit b8327b21ddf518d34c6cd6c01bd7fc0fd3f63c0c)
2007-03-03 04:35:58 +03:00
if ( src_has_wcard | | dest_has_wcard ) {
2005-10-31 23:11:58 +03:00
/* No wildcards. */
status = NT_STATUS_OBJECT_PATH_SYNTAX_BAD ;
} else {
2007-09-14 02:08:59 +04:00
status = copy_internals ( ctx , conn , req , oldname ,
2007-07-05 20:26:27 +04:00
newname , attrs ) ;
2005-10-31 23:11:58 +03:00
}
2004-06-26 03:48:23 +04:00
break ;
case RENAME_FLAG_MOVE_CLUSTER_INFORMATION :
status = NT_STATUS_INVALID_PARAMETER ;
break ;
default :
status = NT_STATUS_ACCESS_DENIED ; /* Default error. */
break ;
2004-03-04 02:14:23 +03:00
}
2004-02-24 03:06:08 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-15 00:02:11 +04:00
if ( open_was_deferred ( req - > mid ) ) {
2004-06-26 02:37:50 +04:00
/* We have re-scheduled this call. */
2007-08-15 00:02:11 +04:00
END_PROFILE ( SMBntrename ) ;
return ;
2004-06-26 02:37:50 +04:00
}
2007-08-15 00:02:11 +04:00
reply_nterror ( req , status ) ;
END_PROFILE ( SMBntrename ) ;
return ;
2004-02-24 03:06:08 +03:00
}
2007-08-15 00:02:11 +04:00
reply_outbuf ( req , 0 , 0 ) ;
2007-09-12 03:57:59 +04:00
2004-02-24 03:06:08 +03:00
END_PROFILE ( SMBntrename ) ;
2007-08-15 00:02:11 +04:00
return ;
2004-02-24 03:06:08 +03:00
}
2000-06-12 09:32:28 +04:00
/****************************************************************************
2007-09-12 03:57:59 +04:00
Reply to a notify change - queue the request and
2000-06-12 09:32:28 +04:00
don ' t allow a directory to be opened .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-08-17 19:27:10 +04:00
2007-08-14 11:39:11 +04:00
static void call_nt_transact_notify_change ( connection_struct * conn ,
struct smb_request * req ,
uint16 * * ppsetup ,
uint32 setup_count ,
char * * ppparams ,
uint32 parameter_count ,
char * * ppdata , uint32 data_count ,
uint32 max_data_count ,
uint32 max_param_count )
2000-06-12 09:32:28 +04:00
{
2006-06-16 22:42:39 +04:00
uint16 * setup = * ppsetup ;
2002-04-09 22:10:09 +04:00
files_struct * fsp ;
2007-01-17 19:23:45 +03:00
uint32 filter ;
NTSTATUS status ;
2007-10-19 04:40:25 +04:00
bool recursive ;
2000-06-12 09:32:28 +04:00
2005-07-08 08:51:27 +04:00
if ( setup_count < 6 ) {
2007-08-14 11:39:11 +04:00
reply_doserror ( req , ERRDOS , ERRbadfunc ) ;
return ;
2005-07-08 08:51:27 +04:00
}
2003-09-17 23:36:38 +04:00
2007-07-31 16:05:40 +04:00
fsp = file_fsp ( SVAL ( setup , 4 ) ) ;
2007-01-17 19:23:45 +03:00
filter = IVAL ( setup , 0 ) ;
2007-01-31 17:42:56 +03:00
recursive = ( SVAL ( setup , 6 ) ! = 0 ) ? True : False ;
2000-06-12 09:32:28 +04:00
2002-04-09 22:10:09 +04:00
DEBUG ( 3 , ( " call_nt_transact_notify_change \n " ) ) ;
2000-06-12 09:32:28 +04:00
2005-07-08 08:51:27 +04:00
if ( ! fsp ) {
2007-08-14 11:39:11 +04:00
reply_doserror ( req , ERRDOS , ERRbadfid ) ;
return ;
2005-07-08 08:51:27 +04:00
}
2000-06-12 09:32:28 +04:00
2007-01-31 17:42:56 +03:00
{
char * filter_string ;
if ( ! ( filter_string = notify_filter_string ( NULL , filter ) ) ) {
2007-08-14 11:39:11 +04:00
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
return ;
2007-01-31 17:42:56 +03:00
}
DEBUG ( 3 , ( " call_nt_transact_notify_change: notify change "
" called on %s, filter = %s, recursive = %d \n " ,
fsp - > fsp_name , filter_string , recursive ) ) ;
TALLOC_FREE ( filter_string ) ;
}
2007-01-17 19:23:45 +03:00
2005-07-08 08:51:27 +04:00
if ( ( ! fsp - > is_directory ) | | ( conn ! = fsp - > conn ) ) {
2007-08-14 11:39:11 +04:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
return ;
2005-07-08 08:51:27 +04:00
}
2000-06-12 09:32:28 +04:00
2007-01-17 19:23:45 +03:00
if ( fsp - > notify = = NULL ) {
2007-01-31 17:42:56 +03:00
2007-02-02 17:55:21 +03:00
status = change_notify_create ( fsp , filter , recursive ) ;
2007-01-31 17:42:56 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-02-02 17:55:21 +03:00
DEBUG ( 10 , ( " change_notify_create returned %s \n " ,
2007-01-31 17:42:56 +03:00
nt_errstr ( status ) ) ) ;
2007-08-14 11:39:11 +04:00
reply_nterror ( req , status ) ;
return ;
2007-01-31 17:42:56 +03:00
}
2007-01-17 19:23:45 +03:00
}
2007-01-21 14:49:00 +03:00
if ( fsp - > notify - > num_changes ! = 0 ) {
2007-01-17 19:23:45 +03:00
/*
* We ' ve got changes pending , respond immediately
*/
/*
* TODO : write a torture test to check the filtering behaviour
* here .
*/
2007-08-14 11:39:11 +04:00
change_notify_reply ( req - > inbuf , max_param_count , fsp - > notify ) ;
2007-01-17 19:23:45 +03:00
/*
* change_notify_reply ( ) above has independently sent its
* results
*/
2007-08-14 11:39:11 +04:00
return ;
2006-12-31 13:16:03 +03:00
}
2007-01-17 19:23:45 +03:00
/*
* No changes pending , queue the request
*/
2007-08-14 11:39:11 +04:00
status = change_notify_add_request ( req - > inbuf , max_param_count , filter ,
2007-07-18 03:01:02 +04:00
recursive , fsp ) ;
2007-01-17 19:23:45 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-14 11:39:11 +04:00
reply_nterror ( req , status ) ;
2007-01-17 19:23:45 +03:00
}
2007-08-14 11:39:11 +04:00
return ;
2000-06-12 09:32:28 +04:00
}
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
2007-08-14 10:52:30 +04:00
static void call_nt_transact_rename ( connection_struct * conn ,
struct smb_request * req ,
uint16 * * ppsetup , uint32 setup_count ,
char * * ppparams , uint32 parameter_count ,
char * * ppdata , uint32 data_count ,
uint32 max_data_count )
1998-07-08 05:42:05 +04:00
{
2001-09-04 11:13:01 +04:00
char * params = * ppparams ;
2007-09-12 03:57:59 +04:00
char * new_name = NULL ;
2003-05-30 03:49:31 +04:00
files_struct * fsp = NULL ;
2007-10-19 04:40:25 +04:00
bool replace_if_exists = False ;
bool dest_has_wcard = False ;
2001-09-04 11:13:01 +04:00
NTSTATUS status ;
2007-09-12 03:57:59 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
1998-08-03 23:07:55 +04:00
2006-12-27 23:45:12 +03:00
if ( parameter_count < 5 ) {
2007-08-14 10:52:30 +04:00
reply_doserror ( req , ERRDOS , ERRbadfunc ) ;
return ;
2005-07-08 08:51:27 +04:00
}
2003-05-30 03:49:31 +04:00
2007-07-31 16:05:40 +04:00
fsp = file_fsp ( SVAL ( params , 0 ) ) ;
2003-05-30 03:49:31 +04:00
replace_if_exists = ( SVAL ( params , 2 ) & RENAME_REPLACE_IF_EXISTS ) ? True : False ;
2007-08-14 10:52:30 +04:00
if ( ! check_fsp ( conn , req , fsp , & current_user ) ) {
return ;
}
2007-09-12 03:57:59 +04:00
srvstr_get_path_wcard ( ctx , params , req - > flags2 , & new_name , params + 4 ,
parameter_count - 4 ,
2007-07-05 20:36:15 +04:00
STR_TERMINATE , & status , & dest_has_wcard ) ;
2003-10-09 03:21:36 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-14 10:52:30 +04:00
reply_nterror ( req , status ) ;
return ;
2003-10-09 03:21:36 +04:00
}
1998-08-03 23:07:55 +04:00
2007-09-13 01:48:20 +04:00
status = rename_internals ( ctx ,
conn ,
req ,
fsp - > fsp_name ,
new_name ,
0 ,
replace_if_exists ,
False ,
dest_has_wcard ) ;
2007-01-14 22:43:06 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-08-14 10:52:30 +04:00
if ( open_was_deferred ( req - > mid ) ) {
2007-01-14 22:43:06 +03:00
/* We have re-scheduled this call. */
2007-08-14 10:52:30 +04:00
return ;
2007-01-14 22:43:06 +03:00
}
2007-08-14 10:52:30 +04:00
reply_nterror ( req , status ) ;
return ;
2007-01-14 22:43:06 +03:00
}
2000-09-20 23:00:21 +04:00
2001-09-04 11:13:01 +04:00
/*
* Rename was successful .
*/
2007-08-14 12:24:02 +04:00
send_nt_replies ( req , NT_STATUS_OK , NULL , 0 , NULL , 0 ) ;
2007-09-12 03:57:59 +04:00
2007-09-13 01:48:20 +04:00
DEBUG ( 3 , ( " nt transact rename from = %s, to = %s succeeded. \n " ,
2001-09-04 11:13:01 +04:00
fsp - > fsp_name , new_name ) ) ;
2007-09-12 03:57:59 +04:00
2007-08-14 10:52:30 +04:00
return ;
1998-07-08 05:42:05 +04:00
}
2000-09-20 23:00:21 +04:00
2001-10-13 02:00:38 +04:00
/******************************************************************************
Fake up a completely empty SD .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static size_t get_null_nt_acl ( TALLOC_CTX * mem_ctx , SEC_DESC * * ppsd )
{
size_t sd_size ;
* ppsd = make_standard_sec_desc ( mem_ctx , & global_sid_World , & global_sid_World , NULL , & sd_size ) ;
if ( ! * ppsd ) {
DEBUG ( 0 , ( " get_null_nt_acl: Unable to malloc space for security descriptor. \n " ) ) ;
sd_size = 0 ;
}
return sd_size ;
}
1998-08-03 23:07:55 +04:00
1998-07-08 05:42:05 +04:00
/****************************************************************************
2003-05-30 03:49:31 +04:00
Reply to query a security descriptor .
1998-07-08 05:42:05 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
2007-08-14 00:16:33 +04:00
static void call_nt_transact_query_security_desc ( connection_struct * conn ,
struct smb_request * req ,
uint16 * * ppsetup ,
uint32 setup_count ,
char * * ppparams ,
uint32 parameter_count ,
char * * ppdata ,
uint32 data_count ,
uint32 max_data_count )
1999-12-13 16:27:58 +03:00
{
2002-08-17 19:27:10 +04:00
char * params = * ppparams ;
char * data = * ppdata ;
prs_struct pd ;
SEC_DESC * psd = NULL ;
size_t sd_size ;
2003-05-30 03:49:31 +04:00
uint32 security_info_wanted ;
2002-08-17 19:27:10 +04:00
TALLOC_CTX * mem_ctx ;
2003-05-30 03:49:31 +04:00
files_struct * fsp = NULL ;
1999-12-13 16:27:58 +03:00
2005-07-08 08:51:27 +04:00
if ( parameter_count < 8 ) {
2007-08-14 00:16:33 +04:00
reply_doserror ( req , ERRDOS , ERRbadfunc ) ;
return ;
2005-07-08 08:51:27 +04:00
}
1999-12-13 16:27:58 +03:00
2007-07-31 16:05:40 +04:00
fsp = file_fsp ( SVAL ( params , 0 ) ) ;
2005-07-08 08:51:27 +04:00
if ( ! fsp ) {
2007-08-14 00:16:33 +04:00
reply_doserror ( req , ERRDOS , ERRbadfid ) ;
return ;
2005-07-08 08:51:27 +04:00
}
1999-12-13 16:27:58 +03:00
2003-05-30 03:49:31 +04:00
security_info_wanted = IVAL ( params , 4 ) ;
2005-04-12 05:20:23 +04:00
DEBUG ( 3 , ( " call_nt_transact_query_security_desc: file = %s, info_wanted = 0x%x \n " , fsp - > fsp_name ,
( unsigned int ) security_info_wanted ) ) ;
1999-12-13 16:27:58 +03:00
2003-05-12 05:20:17 +04:00
params = nttrans_realloc ( ppparams , 4 ) ;
2005-07-08 08:51:27 +04:00
if ( params = = NULL ) {
2007-08-14 00:16:33 +04:00
reply_doserror ( req , ERRDOS , ERRnomem ) ;
return ;
2005-07-08 08:51:27 +04:00
}
1999-12-13 16:27:58 +03:00
2002-12-20 23:21:31 +03:00
if ( ( mem_ctx = talloc_init ( " call_nt_transact_query_security_desc " ) ) = = NULL ) {
2002-08-17 19:27:10 +04:00
DEBUG ( 0 , ( " call_nt_transact_query_security_desc: talloc_init failed. \n " ) ) ;
2007-08-14 00:16:33 +04:00
reply_doserror ( req , ERRDOS , ERRnomem ) ;
return ;
2002-08-17 19:27:10 +04:00
}
2001-10-13 02:00:38 +04:00
2002-08-17 19:27:10 +04:00
/*
* Get the permissions to return .
*/
1999-12-13 16:27:58 +03:00
2005-07-08 08:51:27 +04:00
if ( ! lp_nt_acl_support ( SNUM ( conn ) ) ) {
2002-08-17 19:27:10 +04:00
sd_size = get_null_nt_acl ( mem_ctx , & psd ) ;
2005-07-08 08:51:27 +04:00
} else {
sd_size = SMB_VFS_FGET_NT_ACL ( fsp , fsp - > fh - > fd , security_info_wanted , & psd ) ;
}
2001-10-13 02:00:38 +04:00
2002-08-17 19:27:10 +04:00
if ( sd_size = = 0 ) {
talloc_destroy ( mem_ctx ) ;
2007-08-14 00:16:33 +04:00
reply_unixerror ( req , ERRDOS , ERRnoaccess ) ;
return ;
2002-08-17 19:27:10 +04:00
}
1999-12-13 16:27:58 +03:00
2005-09-30 21:13:37 +04:00
DEBUG ( 3 , ( " call_nt_transact_query_security_desc: sd_size = %lu. \n " , ( unsigned long ) sd_size ) ) ;
1999-12-13 16:27:58 +03:00
2002-08-17 19:27:10 +04:00
SIVAL ( params , 0 , ( uint32 ) sd_size ) ;
1999-12-13 16:27:58 +03:00
2002-08-17 19:27:10 +04:00
if ( max_data_count < sd_size ) {
1999-12-13 16:27:58 +03:00
2007-08-14 12:24:02 +04:00
send_nt_replies ( req , NT_STATUS_BUFFER_TOO_SMALL ,
params , 4 , * ppdata , 0 ) ;
2002-08-17 19:27:10 +04:00
talloc_destroy ( mem_ctx ) ;
2007-08-14 00:16:33 +04:00
return ;
2002-08-17 19:27:10 +04:00
}
1999-12-13 16:27:58 +03:00
2002-08-17 19:27:10 +04:00
/*
* Allocate the data we will point this at .
*/
1999-12-13 16:27:58 +03:00
2003-05-12 05:20:17 +04:00
data = nttrans_realloc ( ppdata , sd_size ) ;
2002-08-17 19:27:10 +04:00
if ( data = = NULL ) {
talloc_destroy ( mem_ctx ) ;
2007-08-14 00:16:33 +04:00
reply_doserror ( req , ERRDOS , ERRnomem ) ;
return ;
2002-08-17 19:27:10 +04:00
}
1999-12-13 16:27:58 +03:00
2002-08-17 19:27:10 +04:00
/*
* Init the parse struct we will marshall into .
*/
1999-12-13 16:27:58 +03:00
2002-08-17 19:27:10 +04:00
prs_init ( & pd , 0 , mem_ctx , MARSHALL ) ;
2000-05-27 13:19:57 +04:00
2002-08-17 19:27:10 +04:00
/*
* Setup the prs_struct to point at the memory we just
* allocated .
*/
2000-05-27 13:19:57 +04:00
2002-08-17 19:27:10 +04:00
prs_give_memory ( & pd , data , ( uint32 ) sd_size , False ) ;
1999-12-13 16:27:58 +03:00
2002-08-17 19:27:10 +04:00
/*
* Finally , linearize into the outgoing buffer .
*/
1999-12-13 16:27:58 +03:00
2002-08-17 19:27:10 +04:00
if ( ! sec_io_desc ( " sd data " , & psd , & pd , 1 ) ) {
DEBUG ( 0 , ( " call_nt_transact_query_security_desc: Error in marshalling \
1999-12-13 16:27:58 +03:00
security descriptor . \ n " ));
2002-08-17 19:27:10 +04:00
/*
* Return access denied for want of a better error message . .
2007-09-12 03:57:59 +04:00
*/
2002-08-17 19:27:10 +04:00
talloc_destroy ( mem_ctx ) ;
2007-08-14 00:16:33 +04:00
reply_unixerror ( req , ERRDOS , ERRnoaccess ) ;
return ;
2002-08-17 19:27:10 +04:00
}
1999-12-13 16:27:58 +03:00
2002-08-17 19:27:10 +04:00
/*
* Now we can delete the security descriptor .
*/
1999-12-13 16:27:58 +03:00
2002-08-17 19:27:10 +04:00
talloc_destroy ( mem_ctx ) ;
1999-12-13 16:27:58 +03:00
2007-08-14 12:24:02 +04:00
send_nt_replies ( req , NT_STATUS_OK , params , 4 , data , ( int ) sd_size ) ;
2007-08-14 00:16:33 +04:00
return ;
1999-12-13 16:27:58 +03:00
}
/****************************************************************************
2003-05-30 03:49:31 +04:00
Reply to set a security descriptor . Map to UNIX perms or POSIX ACLs .
1999-12-13 16:27:58 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-08-13 23:59:00 +04:00
static void call_nt_transact_set_security_desc ( connection_struct * conn ,
struct smb_request * req ,
uint16 * * ppsetup ,
uint32 setup_count ,
char * * ppparams ,
uint32 parameter_count ,
char * * ppdata ,
uint32 data_count ,
uint32 max_data_count )
1998-07-08 05:42:05 +04:00
{
2001-10-13 02:00:38 +04:00
char * params = * ppparams ;
char * data = * ppdata ;
files_struct * fsp = NULL ;
uint32 security_info_sent = 0 ;
2002-07-15 14:35:28 +04:00
NTSTATUS nt_status ;
1998-11-20 01:37:33 +03:00
2005-07-08 08:51:27 +04:00
if ( parameter_count < 8 ) {
2007-08-13 23:59:00 +04:00
reply_doserror ( req , ERRDOS , ERRbadfunc ) ;
return ;
2005-07-08 08:51:27 +04:00
}
1999-12-13 16:27:58 +03:00
2007-07-31 16:05:40 +04:00
if ( ( fsp = file_fsp ( SVAL ( params , 0 ) ) ) = = NULL ) {
2007-08-13 23:59:00 +04:00
reply_doserror ( req , ERRDOS , ERRbadfid ) ;
return ;
2005-07-08 08:51:27 +04:00
}
1999-12-13 16:27:58 +03:00
2005-07-08 08:51:27 +04:00
if ( ! lp_nt_acl_support ( SNUM ( conn ) ) ) {
2001-10-13 02:00:38 +04:00
goto done ;
2005-07-08 08:51:27 +04:00
}
1999-12-13 16:27:58 +03:00
2001-10-13 02:00:38 +04:00
security_info_sent = IVAL ( params , 4 ) ;
1999-12-13 16:27:58 +03:00
2001-10-13 02:00:38 +04:00
DEBUG ( 3 , ( " call_nt_transact_set_security_desc: file = %s, sent 0x%x \n " , fsp - > fsp_name ,
( unsigned int ) security_info_sent ) ) ;
1999-12-13 16:27:58 +03:00
2005-07-08 08:51:27 +04:00
if ( data_count = = 0 ) {
2007-08-13 23:59:00 +04:00
reply_doserror ( req , ERRDOS , ERRnoaccess ) ;
return ;
2005-07-08 08:51:27 +04:00
}
2002-07-15 14:35:28 +04:00
2005-07-08 08:51:27 +04:00
if ( ! NT_STATUS_IS_OK ( nt_status = set_sd ( fsp , data , data_count , security_info_sent ) ) ) {
2007-08-13 23:59:00 +04:00
reply_nterror ( req , nt_status ) ;
return ;
2005-07-08 08:51:27 +04:00
}
2000-10-05 23:04:41 +04:00
2001-10-13 02:00:38 +04:00
done :
2007-08-14 12:24:02 +04:00
send_nt_replies ( req , NT_STATUS_OK , NULL , 0 , NULL , 0 ) ;
2007-08-13 23:59:00 +04:00
return ;
1998-07-08 05:42:05 +04:00
}
2007-09-12 03:57:59 +04:00
1998-07-08 05:42:05 +04:00
/****************************************************************************
2002-08-17 19:27:10 +04:00
Reply to NT IOCTL
1998-07-08 05:42:05 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-05-30 03:49:31 +04:00
2007-08-13 23:58:28 +04:00
static void call_nt_transact_ioctl ( connection_struct * conn ,
struct smb_request * req ,
uint16 * * ppsetup , uint32 setup_count ,
char * * ppparams , uint32 parameter_count ,
char * * ppdata , uint32 data_count ,
uint32 max_data_count )
1998-07-08 05:42:05 +04:00
{
2003-08-08 01:47:46 +04:00
uint32 function ;
uint16 fidnum ;
files_struct * fsp ;
uint8 isFSctl ;
uint8 compfilter ;
2007-10-19 04:40:25 +04:00
static bool logged_message ;
2003-05-12 05:20:17 +04:00
char * pdata = * ppdata ;
1998-11-20 01:37:33 +03:00
2002-08-17 19:27:10 +04:00
if ( setup_count ! = 8 ) {
DEBUG ( 3 , ( " call_nt_transact_ioctl: invalid setup count %d \n " , setup_count ) ) ;
2007-08-13 23:58:28 +04:00
reply_nterror ( req , NT_STATUS_NOT_SUPPORTED ) ;
return ;
2002-07-15 14:35:28 +04:00
}
2002-08-17 19:27:10 +04:00
2003-08-08 01:47:46 +04:00
function = IVAL ( * ppsetup , 0 ) ;
fidnum = SVAL ( * ppsetup , 4 ) ;
isFSctl = CVAL ( * ppsetup , 6 ) ;
compfilter = CVAL ( * ppsetup , 7 ) ;
DEBUG ( 10 , ( " call_nt_transact_ioctl: function[0x%08X] FID[0x%04X] isFSctl[0x%02X] compfilter[0x%02X] \n " ,
function , fidnum , isFSctl , compfilter ) ) ;
2002-08-17 19:27:10 +04:00
2007-08-07 01:03:03 +04:00
fsp = file_fsp ( fidnum ) ;
2003-08-08 01:47:46 +04:00
/* this check is done in each implemented function case for now
because I don ' t want to break anything . . . - - metze
FSP_BELONGS_CONN ( fsp , conn ) ; */
2002-08-17 19:27:10 +04:00
2003-08-08 01:47:46 +04:00
switch ( function ) {
2003-05-12 05:20:17 +04:00
case FSCTL_SET_SPARSE :
2002-08-17 19:27:10 +04:00
/* pretend this succeeded - tho strictly we should
mark the file sparse ( if the local fs supports it )
so we can know if we need to pre - allocate or not */
2003-05-12 05:20:17 +04:00
2003-08-08 01:47:46 +04:00
DEBUG ( 10 , ( " FSCTL_SET_SPARSE: called on FID[0x%04X](but not implemented) \n " , fidnum ) ) ;
2007-08-14 12:24:02 +04:00
send_nt_replies ( req , NT_STATUS_OK , NULL , 0 , NULL , 0 ) ;
2007-08-13 23:58:28 +04:00
return ;
2007-09-12 03:57:59 +04:00
2007-04-24 01:07:05 +04:00
case FSCTL_CREATE_OR_GET_OBJECT_ID :
{
unsigned char objid [ 16 ] ;
/* This should return the object-id on this file.
* I think I ' ll make this be the inode + dev . JRA .
2003-05-12 05:20:17 +04:00
*/
2007-04-24 01:07:05 +04:00
DEBUG ( 10 , ( " FSCTL_CREATE_OR_GET_OBJECT_ID: called on FID[0x%04X] \n " , fidnum ) ) ;
2007-08-13 23:58:28 +04:00
if ( ! fsp_belongs_conn ( conn , req , fsp , & current_user ) ) {
return ;
}
2007-08-07 01:03:03 +04:00
2007-04-24 01:07:05 +04:00
data_count = 64 ;
pdata = nttrans_realloc ( ppdata , data_count ) ;
if ( pdata = = NULL ) {
2007-08-13 23:58:28 +04:00
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
return ;
2007-04-24 01:07:05 +04:00
}
2007-05-29 13:30:34 +04:00
push_file_id_16 ( pdata , & fsp - > file_id ) ;
2007-04-24 01:07:05 +04:00
memcpy ( pdata + 16 , create_volume_objectid ( conn , objid ) , 16 ) ;
2007-05-29 13:30:34 +04:00
push_file_id_16 ( pdata + 32 , & fsp - > file_id ) ;
2007-08-14 12:24:02 +04:00
send_nt_replies ( req , NT_STATUS_OK , NULL , 0 ,
pdata , data_count ) ;
2007-08-13 23:58:28 +04:00
return ;
2007-04-24 01:07:05 +04:00
}
2003-05-12 05:20:17 +04:00
case FSCTL_GET_REPARSE_POINT :
/* pretend this fail - my winXP does it like this
* - - metze
*/
2003-08-08 01:47:46 +04:00
DEBUG ( 10 , ( " FSCTL_GET_REPARSE_POINT: called on FID[0x%04X](but not implemented) \n " , fidnum ) ) ;
2007-08-13 23:58:28 +04:00
reply_nterror ( req , NT_STATUS_NOT_A_REPARSE_POINT ) ;
return ;
2003-05-12 05:20:17 +04:00
case FSCTL_SET_REPARSE_POINT :
/* pretend this fail - I'm assuming this because of the FSCTL_GET_REPARSE_POINT case.
* - - metze
*/
2003-08-08 01:47:46 +04:00
DEBUG ( 10 , ( " FSCTL_SET_REPARSE_POINT: called on FID[0x%04X](but not implemented) \n " , fidnum ) ) ;
2007-08-13 23:58:28 +04:00
reply_nterror ( req , NT_STATUS_NOT_A_REPARSE_POINT ) ;
return ;
2007-09-12 03:57:59 +04:00
2003-08-08 01:47:46 +04:00
case FSCTL_GET_SHADOW_COPY_DATA : /* don't know if this name is right...*/
{
/*
* This is called to retrieve the number of Shadow Copies ( a . k . a . snapshots )
* and return their volume names . If max_data_count is 16 , then it is just
* asking for the number of volumes and length of the combined names .
*
* pdata is the data allocated by our caller , but that uses
* total_data_count ( which is 0 in our case ) rather than max_data_count .
* Allocate the correct amount and return the pointer to let
* it be deallocated when we return .
*/
SHADOW_COPY_DATA * shadow_data = NULL ;
TALLOC_CTX * shadow_mem_ctx = NULL ;
2007-10-19 04:40:25 +04:00
bool labels = False ;
2003-08-08 01:47:46 +04:00
uint32 labels_data_count = 0 ;
uint32 i ;
char * cur_pdata ;
2007-08-13 23:58:28 +04:00
if ( ! fsp_belongs_conn ( conn , req , fsp , & current_user ) ) {
return ;
}
2003-08-08 01:47:46 +04:00
if ( max_data_count < 16 ) {
DEBUG ( 0 , ( " FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) < 16 is invalid! \n " ,
max_data_count ) ) ;
2007-08-13 23:58:28 +04:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
return ;
2003-08-08 01:47:46 +04:00
}
if ( max_data_count > 16 ) {
labels = True ;
}
shadow_mem_ctx = talloc_init ( " SHADOW_COPY_DATA " ) ;
if ( shadow_mem_ctx = = NULL ) {
DEBUG ( 0 , ( " talloc_init(SHADOW_COPY_DATA) failed! \n " ) ) ;
2007-08-13 23:58:28 +04:00
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
return ;
2003-08-08 01:47:46 +04:00
}
2004-12-07 21:25:53 +03:00
shadow_data = TALLOC_ZERO_P ( shadow_mem_ctx , SHADOW_COPY_DATA ) ;
2003-08-08 01:47:46 +04:00
if ( shadow_data = = NULL ) {
2007-04-28 03:18:41 +04:00
DEBUG ( 0 , ( " TALLOC_ZERO() failed! \n " ) ) ;
2005-02-04 10:01:33 +03:00
talloc_destroy ( shadow_mem_ctx ) ;
2007-08-13 23:58:28 +04:00
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
return ;
2003-08-08 01:47:46 +04:00
}
2007-09-12 03:57:59 +04:00
2003-08-08 01:47:46 +04:00
shadow_data - > mem_ctx = shadow_mem_ctx ;
2007-09-12 03:57:59 +04:00
2003-08-08 01:47:46 +04:00
/*
* Call the VFS routine to actually do the work .
*/
if ( SMB_VFS_GET_SHADOW_COPY_DATA ( fsp , shadow_data , labels ) ! = 0 ) {
talloc_destroy ( shadow_data - > mem_ctx ) ;
if ( errno = = ENOSYS ) {
DEBUG ( 5 , ( " FSCTL_GET_SHADOW_COPY_DATA: connectpath %s, not supported. \n " ,
conn - > connectpath ) ) ;
2007-08-13 23:58:28 +04:00
reply_nterror ( req , NT_STATUS_NOT_SUPPORTED ) ;
return ;
2003-08-08 01:47:46 +04:00
} else {
DEBUG ( 0 , ( " FSCTL_GET_SHADOW_COPY_DATA: connectpath %s, failed. \n " ,
conn - > connectpath ) ) ;
2007-08-13 23:58:28 +04:00
reply_nterror ( req , NT_STATUS_UNSUCCESSFUL ) ;
return ;
2003-08-08 01:47:46 +04:00
}
}
labels_data_count = ( shadow_data - > num_volumes * 2 * sizeof ( SHADOW_COPY_LABEL ) ) + 2 ;
if ( ! labels ) {
data_count = 16 ;
} else {
data_count = 12 + labels_data_count + 4 ;
}
if ( max_data_count < data_count ) {
DEBUG ( 0 , ( " FSCTL_GET_SHADOW_COPY_DATA: max_data_count(%u) too small (%u) bytes needed! \n " ,
max_data_count , data_count ) ) ;
talloc_destroy ( shadow_data - > mem_ctx ) ;
2007-08-13 23:58:28 +04:00
reply_nterror ( req , NT_STATUS_BUFFER_TOO_SMALL ) ;
return ;
2003-08-08 01:47:46 +04:00
}
pdata = nttrans_realloc ( ppdata , data_count ) ;
if ( pdata = = NULL ) {
talloc_destroy ( shadow_data - > mem_ctx ) ;
2007-08-13 23:58:28 +04:00
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
return ;
2007-09-12 03:57:59 +04:00
}
2003-08-08 01:47:46 +04:00
cur_pdata = pdata ;
/* num_volumes 4 bytes */
SIVAL ( pdata , 0 , shadow_data - > num_volumes ) ;
if ( labels ) {
/* num_labels 4 bytes */
SIVAL ( pdata , 4 , shadow_data - > num_volumes ) ;
}
/* needed_data_count 4 bytes */
SIVAL ( pdata , 8 , labels_data_count ) ;
cur_pdata + = 12 ;
DEBUG ( 10 , ( " FSCTL_GET_SHADOW_COPY_DATA: %u volumes for path[%s]. \n " ,
shadow_data - > num_volumes , fsp - > fsp_name ) ) ;
if ( labels & & shadow_data - > labels ) {
for ( i = 0 ; i < shadow_data - > num_volumes ; i + + ) {
2007-08-13 23:58:28 +04:00
srvstr_push ( pdata , req - > flags2 ,
2007-08-02 21:37:38 +04:00
cur_pdata , shadow_data - > labels [ i ] ,
2 * sizeof ( SHADOW_COPY_LABEL ) ,
STR_UNICODE | STR_TERMINATE ) ;
2003-08-08 01:47:46 +04:00
cur_pdata + = 2 * sizeof ( SHADOW_COPY_LABEL ) ;
DEBUGADD ( 10 , ( " Label[%u]: '%s' \n " , i , shadow_data - > labels [ i ] ) ) ;
}
}
talloc_destroy ( shadow_data - > mem_ctx ) ;
2007-08-14 12:24:02 +04:00
send_nt_replies ( req , NT_STATUS_OK , NULL , 0 ,
pdata , data_count ) ;
2003-08-08 01:47:46 +04:00
2007-08-13 23:58:28 +04:00
return ;
2003-08-08 01:47:46 +04:00
}
2007-09-12 03:57:59 +04:00
2003-05-12 05:20:17 +04:00
case FSCTL_FIND_FILES_BY_SID : /* I hope this name is right */
{
2007-09-12 03:57:59 +04:00
/* pretend this succeeded -
*
2003-05-12 05:20:17 +04:00
* we have to send back a list with all files owned by this SID
*
* but I have to check that - - metze
2003-08-08 01:47:46 +04:00
*/
2003-05-12 05:20:17 +04:00
DOM_SID sid ;
uid_t uid ;
2003-08-08 01:47:46 +04:00
size_t sid_len = MIN ( data_count - 4 , SID_MAX_SIZE ) ;
2007-09-12 03:57:59 +04:00
2003-08-08 01:47:46 +04:00
DEBUG ( 10 , ( " FSCTL_FIND_FILES_BY_SID: called on FID[0x%04X] \n " , fidnum ) ) ;
2007-08-13 23:58:28 +04:00
if ( ! fsp_belongs_conn ( conn , req , fsp , & current_user ) ) {
return ;
}
2003-08-08 01:47:46 +04:00
/* unknown 4 bytes: this is not the length of the sid :-( */
/*unknown = IVAL(pdata,0);*/
2007-09-12 03:57:59 +04:00
2003-05-12 05:20:17 +04:00
sid_parse ( pdata + 4 , sid_len , & sid ) ;
2003-08-08 01:47:46 +04:00
DEBUGADD ( 10 , ( " for SID: %s \n " , sid_string_static ( & sid ) ) ) ;
2003-05-12 05:20:17 +04:00
2006-02-04 01:19:41 +03:00
if ( ! sid_to_uid ( & sid , & uid ) ) {
2003-11-03 17:34:25 +03:00
DEBUG ( 0 , ( " sid_to_uid: failed, sid[%s] sid_len[%lu] \n " ,
sid_string_static ( & sid ) , ( unsigned long ) sid_len ) ) ;
2003-05-12 05:20:17 +04:00
uid = ( - 1 ) ;
}
2007-09-12 03:57:59 +04:00
2003-05-12 05:20:17 +04:00
/* we can take a look at the find source :-)
*
* find . / - uid $ uid - name ' * ' is what we need here
*
*
* and send 4 bytes len and then NULL terminated unicode strings
* for each file
*
* but I don ' t know how to deal with the paged results
2003-08-08 01:47:46 +04:00
* ( maybe we can hang the result anywhere in the fsp struct )
2003-05-12 05:20:17 +04:00
*
* we don ' t send all files at once
2007-09-12 03:57:59 +04:00
* and at the next we should * not * start from the beginning ,
* so we have to cache the result
2003-05-12 05:20:17 +04:00
*
* - - metze
*/
2007-09-12 03:57:59 +04:00
2003-05-12 05:20:17 +04:00
/* this works for now... */
2007-08-14 12:24:02 +04:00
send_nt_replies ( req , NT_STATUS_OK , NULL , 0 , NULL , 0 ) ;
2007-08-13 23:58:28 +04:00
return ;
2007-09-12 03:57:59 +04:00
}
2002-08-17 19:27:10 +04:00
default :
if ( ! logged_message ) {
logged_message = True ; /* Only print this once... */
2003-05-12 05:20:17 +04:00
DEBUG ( 0 , ( " call_nt_transact_ioctl(0x%x): Currently not implemented. \n " ,
2003-08-08 01:47:46 +04:00
function ) ) ;
2002-08-17 19:27:10 +04:00
}
}
2007-08-13 23:58:28 +04:00
reply_nterror ( req , NT_STATUS_NOT_SUPPORTED ) ;
1998-07-08 05:42:05 +04:00
}
2003-05-12 05:20:17 +04:00
2003-05-14 18:38:11 +04:00
# ifdef HAVE_SYS_QUOTAS
2003-05-12 05:20:17 +04:00
/****************************************************************************
2007-09-12 03:57:59 +04:00
Reply to get user quota
2003-05-12 05:20:17 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-08-14 09:58:13 +04:00
static void call_nt_transact_get_user_quota ( connection_struct * conn ,
struct smb_request * req ,
uint16 * * ppsetup ,
uint32 setup_count ,
char * * ppparams ,
uint32 parameter_count ,
char * * ppdata ,
uint32 data_count ,
uint32 max_data_count )
2003-05-12 05:20:17 +04:00
{
NTSTATUS nt_status = NT_STATUS_OK ;
char * params = * ppparams ;
char * pdata = * ppdata ;
char * entry ;
int data_len = 0 , param_len = 0 ;
int qt_len = 0 ;
int entry_len = 0 ;
files_struct * fsp = NULL ;
uint16 level = 0 ;
size_t sid_len ;
DOM_SID sid ;
2007-10-19 04:40:25 +04:00
bool start_enum = True ;
2003-05-12 05:20:17 +04:00
SMB_NTQUOTA_STRUCT qt ;
SMB_NTQUOTA_LIST * tmp_list ;
SMB_NTQUOTA_HANDLE * qt_handle = NULL ;
ZERO_STRUCT ( qt ) ;
/* access check */
2006-02-02 23:44:50 +03:00
if ( current_user . ut . uid ! = 0 ) {
2005-02-04 10:01:33 +03:00
DEBUG ( 1 , ( " get_user_quota: access_denied service [%s] user [%s] \n " ,
2003-05-12 05:20:17 +04:00
lp_servicename ( SNUM ( conn ) ) , conn - > user ) ) ;
2007-08-14 09:58:13 +04:00
reply_doserror ( req , ERRDOS , ERRnoaccess ) ;
return ;
2003-05-12 05:20:17 +04:00
}
/*
* Ensure minimum number of parameters sent .
*/
2003-05-30 03:49:31 +04:00
if ( parameter_count < 4 ) {
DEBUG ( 0 , ( " TRANSACT_GET_USER_QUOTA: requires %d >= 4 bytes parameters \n " , parameter_count ) ) ;
2007-08-14 09:58:13 +04:00
reply_doserror ( req , ERRDOS , ERRinvalidparam ) ;
return ;
2003-05-12 05:20:17 +04:00
}
2007-09-12 03:57:59 +04:00
2003-05-12 05:20:17 +04:00
/* maybe we can check the quota_fnum */
2007-07-31 16:05:40 +04:00
fsp = file_fsp ( SVAL ( params , 0 ) ) ;
2003-05-12 05:20:17 +04:00
if ( ! CHECK_NTQUOTA_HANDLE_OK ( fsp , conn ) ) {
DEBUG ( 3 , ( " TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE \n " ) ) ;
2007-08-14 09:58:13 +04:00
reply_nterror ( req , NT_STATUS_INVALID_HANDLE ) ;
return ;
2003-05-12 05:20:17 +04:00
}
2006-07-11 22:01:26 +04:00
/* the NULL pointer checking for fsp->fake_file_handle->pd
2003-05-12 05:20:17 +04:00
* is done by CHECK_NTQUOTA_HANDLE_OK ( )
*/
qt_handle = ( SMB_NTQUOTA_HANDLE * ) fsp - > fake_file_handle - > pd ;
level = SVAL ( params , 2 ) ;
2007-09-12 03:57:59 +04:00
/* unknown 12 bytes leading in params */
2003-05-12 05:20:17 +04:00
switch ( level ) {
case TRANSACT_GET_USER_QUOTA_LIST_CONTINUE :
/* seems that we should continue with the enum here --metze */
2007-09-12 03:57:59 +04:00
if ( qt_handle - > quota_list ! = NULL & &
2003-05-12 05:20:17 +04:00
qt_handle - > tmp_list = = NULL ) {
2007-09-12 03:57:59 +04:00
2003-05-12 05:20:17 +04:00
/* free the list */
free_ntquota_list ( & ( qt_handle - > quota_list ) ) ;
/* Realloc the size of parameters and data we will return */
param_len = 4 ;
params = nttrans_realloc ( ppparams , param_len ) ;
2005-07-08 08:51:27 +04:00
if ( params = = NULL ) {
2007-08-14 09:58:13 +04:00
reply_doserror ( req , ERRDOS , ERRnomem ) ;
return ;
2005-07-08 08:51:27 +04:00
}
2003-05-12 05:20:17 +04:00
data_len = 0 ;
SIVAL ( params , 0 , data_len ) ;
break ;
}
start_enum = False ;
case TRANSACT_GET_USER_QUOTA_LIST_START :
if ( qt_handle - > quota_list = = NULL & &
qt_handle - > tmp_list = = NULL ) {
start_enum = True ;
}
2007-08-14 09:58:13 +04:00
if ( start_enum & & vfs_get_user_ntquota_list ( fsp , & ( qt_handle - > quota_list ) ) ! = 0 ) {
reply_doserror ( req , ERRSRV , ERRerror ) ;
return ;
}
2003-05-12 05:20:17 +04:00
/* Realloc the size of parameters and data we will return */
param_len = 4 ;
params = nttrans_realloc ( ppparams , param_len ) ;
2005-07-08 08:51:27 +04:00
if ( params = = NULL ) {
2007-08-14 09:58:13 +04:00
reply_doserror ( req , ERRDOS , ERRnomem ) ;
return ;
2005-07-08 08:51:27 +04:00
}
2003-05-12 05:20:17 +04:00
/* we should not trust the value in max_data_count*/
max_data_count = MIN ( max_data_count , 2048 ) ;
2007-09-12 03:57:59 +04:00
2003-05-12 05:20:17 +04:00
pdata = nttrans_realloc ( ppdata , max_data_count ) ; /* should be max data count from client*/
2005-07-08 08:51:27 +04:00
if ( pdata = = NULL ) {
2007-08-14 09:58:13 +04:00
reply_doserror ( req , ERRDOS , ERRnomem ) ;
return ;
2005-07-08 08:51:27 +04:00
}
2003-05-12 05:20:17 +04:00
entry = pdata ;
/* set params Size of returned Quota Data 4 bytes*/
/* but set it later when we know it */
2007-09-12 03:57:59 +04:00
2003-05-12 05:20:17 +04:00
/* for each entry push the data */
if ( start_enum ) {
qt_handle - > tmp_list = qt_handle - > quota_list ;
}
tmp_list = qt_handle - > tmp_list ;
for ( ; ( ( tmp_list ! = NULL ) & & ( ( qt_len + 40 + SID_MAX_SIZE ) < max_data_count ) ) ;
tmp_list = tmp_list - > next , entry + = entry_len , qt_len + = entry_len ) {
sid_len = sid_size ( & tmp_list - > quotas - > sid ) ;
entry_len = 40 + sid_len ;
/* nextoffset entry 4 bytes */
SIVAL ( entry , 0 , entry_len ) ;
2007-09-12 03:57:59 +04:00
2003-05-12 05:20:17 +04:00
/* then the len of the SID 4 bytes */
SIVAL ( entry , 4 , sid_len ) ;
2007-09-12 03:57:59 +04:00
2003-05-12 05:20:17 +04:00
/* unknown data 8 bytes SMB_BIG_UINT */
SBIG_UINT ( entry , 8 , ( SMB_BIG_UINT ) 0 ) ; /* this is not 0 in windows...-metze*/
2007-09-12 03:57:59 +04:00
2003-05-12 05:20:17 +04:00
/* the used disk space 8 bytes SMB_BIG_UINT */
SBIG_UINT ( entry , 16 , tmp_list - > quotas - > usedspace ) ;
2007-09-12 03:57:59 +04:00
2003-05-12 05:20:17 +04:00
/* the soft quotas 8 bytes SMB_BIG_UINT */
SBIG_UINT ( entry , 24 , tmp_list - > quotas - > softlim ) ;
2007-09-12 03:57:59 +04:00
2003-05-12 05:20:17 +04:00
/* the hard quotas 8 bytes SMB_BIG_UINT */
SBIG_UINT ( entry , 32 , tmp_list - > quotas - > hardlim ) ;
2007-09-12 03:57:59 +04:00
2003-05-12 05:20:17 +04:00
/* and now the SID */
sid_linearize ( entry + 40 , sid_len , & tmp_list - > quotas - > sid ) ;
}
2007-09-12 03:57:59 +04:00
2003-05-12 05:20:17 +04:00
qt_handle - > tmp_list = tmp_list ;
2007-09-12 03:57:59 +04:00
2003-05-12 05:20:17 +04:00
/* overwrite the offset of the last entry */
SIVAL ( entry - entry_len , 0 , 0 ) ;
data_len = 4 + qt_len ;
/* overwrite the params quota_data_len */
SIVAL ( params , 0 , data_len ) ;
break ;
case TRANSACT_GET_USER_QUOTA_FOR_SID :
2007-09-12 03:57:59 +04:00
/* unknown 4 bytes IVAL(pdata,0) */
2003-05-12 05:20:17 +04:00
if ( data_count < 8 ) {
DEBUG ( 0 , ( " TRANSACT_GET_USER_QUOTA_FOR_SID: requires %d >= %d bytes data \n " , data_count , 8 ) ) ;
2007-08-14 09:58:13 +04:00
reply_doserror ( req , ERRDOS , ERRunknownlevel ) ;
return ;
2003-05-12 05:20:17 +04:00
}
sid_len = IVAL ( pdata , 4 ) ;
2004-12-07 21:25:53 +03:00
/* Ensure this is less than 1mb. */
if ( sid_len > ( 1024 * 1024 ) ) {
2007-08-14 09:58:13 +04:00
reply_doserror ( req , ERRDOS , ERRnomem ) ;
return ;
2004-12-07 21:25:53 +03:00
}
2003-05-12 05:20:17 +04:00
if ( data_count < 8 + sid_len ) {
2003-11-04 17:59:27 +03:00
DEBUG ( 0 , ( " TRANSACT_GET_USER_QUOTA_FOR_SID: requires %d >= %lu bytes data \n " , data_count , ( unsigned long ) ( 8 + sid_len ) ) ) ;
2007-08-14 09:58:13 +04:00
reply_doserror ( req , ERRDOS , ERRunknownlevel ) ;
return ;
2003-05-12 05:20:17 +04:00
}
data_len = 4 + 40 + sid_len ;
if ( max_data_count < data_len ) {
DEBUG ( 0 , ( " TRANSACT_GET_USER_QUOTA_FOR_SID: max_data_count(%d) < data_len(%d) \n " ,
max_data_count , data_len ) ) ;
param_len = 4 ;
SIVAL ( params , 0 , data_len ) ;
data_len = 0 ;
nt_status = NT_STATUS_BUFFER_TOO_SMALL ;
break ;
}
sid_parse ( pdata + 8 , sid_len , & sid ) ;
2007-09-12 03:57:59 +04:00
2003-05-12 05:20:17 +04:00
if ( vfs_get_ntquota ( fsp , SMB_USER_QUOTA_TYPE , & sid , & qt ) ! = 0 ) {
ZERO_STRUCT ( qt ) ;
2007-09-12 03:57:59 +04:00
/*
* we have to return zero ' s in all fields
2003-05-12 05:20:17 +04:00
* instead of returning an error here
* - - metze
*/
}
/* Realloc the size of parameters and data we will return */
param_len = 4 ;
params = nttrans_realloc ( ppparams , param_len ) ;
2005-07-08 08:51:27 +04:00
if ( params = = NULL ) {
2007-08-14 09:58:13 +04:00
reply_doserror ( req , ERRDOS , ERRnomem ) ;
return ;
2005-07-08 08:51:27 +04:00
}
2003-05-12 05:20:17 +04:00
pdata = nttrans_realloc ( ppdata , data_len ) ;
2005-07-08 08:51:27 +04:00
if ( pdata = = NULL ) {
2007-08-14 09:58:13 +04:00
reply_doserror ( req , ERRDOS , ERRnomem ) ;
return ;
2005-07-08 08:51:27 +04:00
}
2003-05-12 05:20:17 +04:00
entry = pdata ;
/* set params Size of returned Quota Data 4 bytes*/
SIVAL ( params , 0 , data_len ) ;
2007-09-12 03:57:59 +04:00
2003-05-12 05:20:17 +04:00
/* nextoffset entry 4 bytes */
SIVAL ( entry , 0 , 0 ) ;
2007-09-12 03:57:59 +04:00
2003-05-12 05:20:17 +04:00
/* then the len of the SID 4 bytes */
SIVAL ( entry , 4 , sid_len ) ;
2007-09-12 03:57:59 +04:00
2003-05-12 05:20:17 +04:00
/* unknown data 8 bytes SMB_BIG_UINT */
SBIG_UINT ( entry , 8 , ( SMB_BIG_UINT ) 0 ) ; /* this is not 0 in windows...-mezte*/
2007-09-12 03:57:59 +04:00
2003-05-12 05:20:17 +04:00
/* the used disk space 8 bytes SMB_BIG_UINT */
SBIG_UINT ( entry , 16 , qt . usedspace ) ;
2007-09-12 03:57:59 +04:00
2003-05-12 05:20:17 +04:00
/* the soft quotas 8 bytes SMB_BIG_UINT */
SBIG_UINT ( entry , 24 , qt . softlim ) ;
2007-09-12 03:57:59 +04:00
2003-05-12 05:20:17 +04:00
/* the hard quotas 8 bytes SMB_BIG_UINT */
SBIG_UINT ( entry , 32 , qt . hardlim ) ;
2007-09-12 03:57:59 +04:00
2003-05-12 05:20:17 +04:00
/* and now the SID */
sid_linearize ( entry + 40 , sid_len , & sid ) ;
break ;
default :
DEBUG ( 0 , ( " do_nt_transact_get_user_quota: fnum %d unknown level 0x%04hX \n " , fsp - > fnum , level ) ) ;
2007-08-14 09:58:13 +04:00
reply_doserror ( req , ERRSRV , ERRerror ) ;
return ;
2003-05-12 05:20:17 +04:00
break ;
}
2007-08-14 12:24:02 +04:00
send_nt_replies ( req , nt_status , params , param_len ,
pdata , data_len ) ;
2003-05-12 05:20:17 +04:00
}
/****************************************************************************
Reply to set user quota
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-08-14 10:21:02 +04:00
static void call_nt_transact_set_user_quota ( connection_struct * conn ,
struct smb_request * req ,
uint16 * * ppsetup ,
uint32 setup_count ,
char * * ppparams ,
uint32 parameter_count ,
char * * ppdata ,
uint32 data_count ,
uint32 max_data_count )
2003-05-12 05:20:17 +04:00
{
char * params = * ppparams ;
char * pdata = * ppdata ;
int data_len = 0 , param_len = 0 ;
SMB_NTQUOTA_STRUCT qt ;
size_t sid_len ;
DOM_SID sid ;
files_struct * fsp = NULL ;
ZERO_STRUCT ( qt ) ;
/* access check */
2006-02-02 23:44:50 +03:00
if ( current_user . ut . uid ! = 0 ) {
2003-05-12 05:20:17 +04:00
DEBUG ( 1 , ( " set_user_quota: access_denied service [%s] user [%s] \n " ,
lp_servicename ( SNUM ( conn ) ) , conn - > user ) ) ;
2007-08-14 10:21:02 +04:00
reply_doserror ( req , ERRDOS , ERRnoaccess ) ;
return ;
2003-05-12 05:20:17 +04:00
}
/*
* Ensure minimum number of parameters sent .
*/
2003-05-30 03:49:31 +04:00
if ( parameter_count < 2 ) {
DEBUG ( 0 , ( " TRANSACT_SET_USER_QUOTA: requires %d >= 2 bytes parameters \n " , parameter_count ) ) ;
2007-08-14 10:21:02 +04:00
reply_doserror ( req , ERRDOS , ERRinvalidparam ) ;
return ;
2003-05-12 05:20:17 +04:00
}
2007-09-12 03:57:59 +04:00
2003-05-12 05:20:17 +04:00
/* maybe we can check the quota_fnum */
2007-07-31 16:05:40 +04:00
fsp = file_fsp ( SVAL ( params , 0 ) ) ;
2003-05-12 05:20:17 +04:00
if ( ! CHECK_NTQUOTA_HANDLE_OK ( fsp , conn ) ) {
DEBUG ( 3 , ( " TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE \n " ) ) ;
2007-08-14 10:21:02 +04:00
reply_nterror ( req , NT_STATUS_INVALID_HANDLE ) ;
return ;
2003-05-12 05:20:17 +04:00
}
if ( data_count < 40 ) {
DEBUG ( 0 , ( " TRANSACT_SET_USER_QUOTA: requires %d >= %d bytes data \n " , data_count , 40 ) ) ;
2007-08-14 10:21:02 +04:00
reply_doserror ( req , ERRDOS , ERRunknownlevel ) ;
return ;
2003-05-12 05:20:17 +04:00
}
/* offset to next quota record.
* 4 bytes IVAL ( pdata , 0 )
* unused here . . .
*/
/* sid len */
sid_len = IVAL ( pdata , 4 ) ;
if ( data_count < 40 + sid_len ) {
2003-11-03 17:34:25 +03:00
DEBUG ( 0 , ( " TRANSACT_SET_USER_QUOTA: requires %d >= %lu bytes data \n " , data_count , ( unsigned long ) 40 + sid_len ) ) ;
2007-08-14 10:21:02 +04:00
reply_doserror ( req , ERRDOS , ERRunknownlevel ) ;
return ;
2003-05-12 05:20:17 +04:00
}
2007-09-12 03:57:59 +04:00
/* unknown 8 bytes in pdata
2003-05-12 05:20:17 +04:00
* maybe its the change time in NTTIME
*/
/* the used space 8 bytes (SMB_BIG_UINT)*/
qt . usedspace = ( SMB_BIG_UINT ) IVAL ( pdata , 16 ) ;
# ifdef LARGE_SMB_OFF_T
qt . usedspace | = ( ( ( SMB_BIG_UINT ) IVAL ( pdata , 20 ) ) < < 32 ) ;
# else /* LARGE_SMB_OFF_T */
if ( ( IVAL ( pdata , 20 ) ! = 0 ) & &
( ( qt . usedspace ! = 0xFFFFFFFF ) | |
2003-05-15 00:22:48 +04:00
( IVAL ( pdata , 20 ) ! = 0xFFFFFFFF ) ) ) {
2003-05-12 05:20:17 +04:00
/* more than 32 bits? */
2007-08-14 10:21:02 +04:00
reply_doserror ( req , ERRDOS , ERRunknownlevel ) ;
return ;
2003-05-12 05:20:17 +04:00
}
# endif /* LARGE_SMB_OFF_T */
/* the soft quotas 8 bytes (SMB_BIG_UINT)*/
qt . softlim = ( SMB_BIG_UINT ) IVAL ( pdata , 24 ) ;
# ifdef LARGE_SMB_OFF_T
qt . softlim | = ( ( ( SMB_BIG_UINT ) IVAL ( pdata , 28 ) ) < < 32 ) ;
# else /* LARGE_SMB_OFF_T */
if ( ( IVAL ( pdata , 28 ) ! = 0 ) & &
( ( qt . softlim ! = 0xFFFFFFFF ) | |
2003-05-15 00:22:48 +04:00
( IVAL ( pdata , 28 ) ! = 0xFFFFFFFF ) ) ) {
2003-05-12 05:20:17 +04:00
/* more than 32 bits? */
2007-08-14 10:21:02 +04:00
reply_doserror ( req , ERRDOS , ERRunknownlevel ) ;
return ;
2003-05-12 05:20:17 +04:00
}
# endif /* LARGE_SMB_OFF_T */
/* the hard quotas 8 bytes (SMB_BIG_UINT)*/
qt . hardlim = ( SMB_BIG_UINT ) IVAL ( pdata , 32 ) ;
# ifdef LARGE_SMB_OFF_T
qt . hardlim | = ( ( ( SMB_BIG_UINT ) IVAL ( pdata , 36 ) ) < < 32 ) ;
# else /* LARGE_SMB_OFF_T */
if ( ( IVAL ( pdata , 36 ) ! = 0 ) & &
( ( qt . hardlim ! = 0xFFFFFFFF ) | |
2003-05-15 00:22:48 +04:00
( IVAL ( pdata , 36 ) ! = 0xFFFFFFFF ) ) ) {
2003-05-12 05:20:17 +04:00
/* more than 32 bits? */
2007-08-14 10:21:02 +04:00
reply_doserror ( req , ERRDOS , ERRunknownlevel ) ;
return ;
2003-05-12 05:20:17 +04:00
}
# endif /* LARGE_SMB_OFF_T */
2007-09-12 03:57:59 +04:00
2003-05-12 05:20:17 +04:00
sid_parse ( pdata + 40 , sid_len , & sid ) ;
DEBUGADD ( 8 , ( " SID: %s \n " , sid_string_static ( & sid ) ) ) ;
/* 44 unknown bytes left... */
if ( vfs_set_ntquota ( fsp , SMB_USER_QUOTA_TYPE , & sid , & qt ) ! = 0 ) {
2007-08-14 10:21:02 +04:00
reply_doserror ( req , ERRSRV , ERRerror ) ;
return ;
2003-05-12 05:20:17 +04:00
}
2007-08-14 12:24:02 +04:00
send_nt_replies ( req , NT_STATUS_OK , params , param_len ,
pdata , data_len ) ;
2003-05-12 05:20:17 +04:00
}
2003-05-14 18:38:11 +04:00
# endif /* HAVE_SYS_QUOTAS */
2003-05-12 05:20:17 +04:00
2007-08-13 19:40:37 +04:00
static void handle_nttrans ( connection_struct * conn ,
struct trans_state * state ,
struct smb_request * req )
2006-04-10 19:33:04 +04:00
{
if ( Protocol > = PROTOCOL_NT1 ) {
2007-08-13 19:40:37 +04:00
req - > flags2 | = 0x40 ; /* IS_LONG_NAME */
SSVAL ( req - > inbuf , smb_flg2 , req - > flags2 ) ;
}
2006-04-10 19:33:04 +04:00
/* Now we must call the relevant NT_TRANS function */
switch ( state - > call ) {
case NT_TRANSACT_CREATE :
2006-05-05 11:15:45 +04:00
{
2007-01-24 17:53:03 +03:00
START_PROFILE ( NT_transact_create ) ;
2007-08-13 23:03:52 +04:00
call_nt_transact_create (
conn , req ,
& state - > setup , state - > setup_count ,
& state - > param , state - > total_param ,
& state - > data , state - > total_data ,
state - > max_data_return ) ;
2007-01-24 17:53:03 +03:00
END_PROFILE ( NT_transact_create ) ;
2006-04-10 19:33:04 +04:00
break ;
2006-05-05 11:15:45 +04:00
}
2006-04-10 19:33:04 +04:00
case NT_TRANSACT_IOCTL :
2006-05-05 11:15:45 +04:00
{
2007-01-24 17:53:03 +03:00
START_PROFILE ( NT_transact_ioctl ) ;
2007-08-13 23:58:28 +04:00
call_nt_transact_ioctl (
conn , req ,
& state - > setup , state - > setup_count ,
& state - > param , state - > total_param ,
& state - > data , state - > total_data ,
state - > max_data_return ) ;
2007-01-24 17:53:03 +03:00
END_PROFILE ( NT_transact_ioctl ) ;
2006-04-10 19:33:04 +04:00
break ;
2006-05-05 11:15:45 +04:00
}
2006-04-10 19:33:04 +04:00
case NT_TRANSACT_SET_SECURITY_DESC :
2006-05-05 11:15:45 +04:00
{
2007-01-24 17:53:03 +03:00
START_PROFILE ( NT_transact_set_security_desc ) ;
2007-08-13 23:59:00 +04:00
call_nt_transact_set_security_desc (
conn , req ,
& state - > setup , state - > setup_count ,
& state - > param , state - > total_param ,
& state - > data , state - > total_data ,
state - > max_data_return ) ;
2007-01-24 17:53:03 +03:00
END_PROFILE ( NT_transact_set_security_desc ) ;
2006-04-10 19:33:04 +04:00
break ;
2006-05-05 11:15:45 +04:00
}
2006-04-10 19:33:04 +04:00
case NT_TRANSACT_NOTIFY_CHANGE :
2006-05-05 11:15:45 +04:00
{
2007-01-24 17:53:03 +03:00
START_PROFILE ( NT_transact_notify_change ) ;
2007-08-14 11:39:11 +04:00
call_nt_transact_notify_change (
conn , req ,
& state - > setup , state - > setup_count ,
& state - > param , state - > total_param ,
& state - > data , state - > total_data ,
state - > max_data_return ,
state - > max_param_return ) ;
2007-01-24 17:53:03 +03:00
END_PROFILE ( NT_transact_notify_change ) ;
2006-04-10 19:33:04 +04:00
break ;
2006-05-05 11:15:45 +04:00
}
2006-04-10 19:33:04 +04:00
case NT_TRANSACT_RENAME :
2006-05-05 11:15:45 +04:00
{
2007-01-24 17:53:03 +03:00
START_PROFILE ( NT_transact_rename ) ;
2007-08-14 10:52:30 +04:00
call_nt_transact_rename (
conn , req ,
& state - > setup , state - > setup_count ,
& state - > param , state - > total_param ,
& state - > data , state - > total_data ,
state - > max_data_return ) ;
2007-01-24 17:53:03 +03:00
END_PROFILE ( NT_transact_rename ) ;
2006-04-10 19:33:04 +04:00
break ;
2006-05-05 11:15:45 +04:00
}
2006-04-10 19:33:04 +04:00
case NT_TRANSACT_QUERY_SECURITY_DESC :
2006-05-05 11:15:45 +04:00
{
2007-01-24 17:53:03 +03:00
START_PROFILE ( NT_transact_query_security_desc ) ;
2007-08-14 00:16:33 +04:00
call_nt_transact_query_security_desc (
conn , req ,
& state - > setup , state - > setup_count ,
& state - > param , state - > total_param ,
& state - > data , state - > total_data ,
state - > max_data_return ) ;
2007-01-24 17:53:03 +03:00
END_PROFILE ( NT_transact_query_security_desc ) ;
2006-04-10 19:33:04 +04:00
break ;
2006-05-05 11:15:45 +04:00
}
2006-04-10 19:33:04 +04:00
# ifdef HAVE_SYS_QUOTAS
case NT_TRANSACT_GET_USER_QUOTA :
2006-05-05 11:15:45 +04:00
{
2007-01-24 17:53:03 +03:00
START_PROFILE ( NT_transact_get_user_quota ) ;
2007-08-14 09:58:13 +04:00
call_nt_transact_get_user_quota (
conn , req ,
& state - > setup , state - > setup_count ,
& state - > param , state - > total_param ,
& state - > data , state - > total_data ,
state - > max_data_return ) ;
2007-01-24 17:53:03 +03:00
END_PROFILE ( NT_transact_get_user_quota ) ;
2006-04-10 19:33:04 +04:00
break ;
2006-05-05 11:15:45 +04:00
}
2006-04-10 19:33:04 +04:00
case NT_TRANSACT_SET_USER_QUOTA :
2006-05-05 11:15:45 +04:00
{
2007-01-24 17:53:03 +03:00
START_PROFILE ( NT_transact_set_user_quota ) ;
2007-08-14 10:21:02 +04:00
call_nt_transact_set_user_quota (
conn , req ,
& state - > setup , state - > setup_count ,
& state - > param , state - > total_param ,
& state - > data , state - > total_data ,
state - > max_data_return ) ;
2007-01-24 17:53:03 +03:00
END_PROFILE ( NT_transact_set_user_quota ) ;
2007-09-12 03:57:59 +04:00
break ;
2006-05-05 11:15:45 +04:00
}
2006-04-10 19:33:04 +04:00
# endif /* HAVE_SYS_QUOTAS */
2006-05-05 11:15:45 +04:00
2006-04-10 19:33:04 +04:00
default :
/* Error in request */
2007-08-03 11:00:19 +04:00
DEBUG ( 0 , ( " handle_nttrans: Unknown request %d in "
" nttrans call \n " , state - > call ) ) ;
2007-08-13 19:40:37 +04:00
reply_doserror ( req , ERRSRV , ERRerror ) ;
return ;
2006-04-10 19:33:04 +04:00
}
2007-08-13 19:40:37 +04:00
return ;
2006-04-10 19:33:04 +04:00
}
1998-07-08 05:42:05 +04:00
/****************************************************************************
Reply to a SMBNTtrans .
1998-05-08 05:22:16 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-08-17 19:27:10 +04:00
2007-08-13 13:12:21 +04:00
void reply_nttrans ( connection_struct * conn , struct smb_request * req )
1998-05-08 05:22:16 +04:00
{
2007-08-13 12:50:09 +04:00
uint32 pscnt ;
uint32 psoff ;
uint32 dscnt ;
uint32 dsoff ;
uint16 function_code ;
2006-04-10 19:33:04 +04:00
NTSTATUS result ;
struct trans_state * state ;
2007-08-13 19:40:37 +04:00
int size ;
2007-08-13 13:12:21 +04:00
2002-08-17 19:27:10 +04:00
START_PROFILE ( SMBnttrans ) ;
2007-08-13 18:29:44 +04:00
if ( req - > wct < 19 ) {
2007-08-13 13:12:21 +04:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2007-08-13 12:50:09 +04:00
END_PROFILE ( SMBnttrans ) ;
2007-08-13 13:12:21 +04:00
return ;
2007-08-13 12:50:09 +04:00
}
2007-08-13 18:29:44 +04:00
size = smb_len ( req - > inbuf ) + 4 ;
pscnt = IVAL ( req - > inbuf , smb_nt_ParameterCount ) ;
psoff = IVAL ( req - > inbuf , smb_nt_ParameterOffset ) ;
dscnt = IVAL ( req - > inbuf , smb_nt_DataCount ) ;
dsoff = IVAL ( req - > inbuf , smb_nt_DataOffset ) ;
function_code = SVAL ( req - > inbuf , smb_nt_Function ) ;
2007-08-13 12:50:09 +04:00
2002-08-17 19:27:10 +04:00
if ( IS_IPC ( conn ) & & ( function_code ! = NT_TRANSACT_CREATE ) ) {
2007-08-13 13:12:21 +04:00
reply_doserror ( req , ERRSRV , ERRaccess ) ;
2002-08-17 19:27:10 +04:00
END_PROFILE ( SMBnttrans ) ;
2007-08-13 13:12:21 +04:00
return ;
2002-08-17 19:27:10 +04:00
}
2007-08-13 18:29:44 +04:00
result = allow_new_trans ( conn - > pending_trans , req - > mid ) ;
2006-04-26 13:43:39 +04:00
if ( ! NT_STATUS_IS_OK ( result ) ) {
2006-04-10 19:33:04 +04:00
DEBUG ( 2 , ( " Got invalid nttrans request: %s \n " , nt_errstr ( result ) ) ) ;
2007-08-13 13:12:21 +04:00
reply_nterror ( req , result ) ;
2006-04-10 19:33:04 +04:00
END_PROFILE ( SMBnttrans ) ;
2007-08-13 13:12:21 +04:00
return ;
2006-04-10 19:33:04 +04:00
}
2006-12-15 03:49:12 +03:00
if ( ( state = TALLOC_P ( conn - > mem_ctx , struct trans_state ) ) = = NULL ) {
2007-08-13 13:12:21 +04:00
reply_doserror ( req , ERRSRV , ERRaccess ) ;
2006-04-10 19:33:04 +04:00
END_PROFILE ( SMBnttrans ) ;
2007-08-13 13:12:21 +04:00
return ;
2006-04-10 19:33:04 +04:00
}
state - > cmd = SMBnttrans ;
2007-08-13 18:29:44 +04:00
state - > mid = req - > mid ;
state - > vuid = req - > vuid ;
state - > total_data = IVAL ( req - > inbuf , smb_nt_TotalDataCount ) ;
2006-04-10 19:33:04 +04:00
state - > data = NULL ;
2007-08-13 18:29:44 +04:00
state - > total_param = IVAL ( req - > inbuf , smb_nt_TotalParameterCount ) ;
2006-04-10 19:33:04 +04:00
state - > param = NULL ;
2007-08-13 18:29:44 +04:00
state - > max_data_return = IVAL ( req - > inbuf , smb_nt_MaxDataCount ) ;
state - > max_param_return = IVAL ( req - > inbuf , smb_nt_MaxParameterCount ) ;
2006-04-10 19:33:04 +04:00
/* setup count is in *words* */
2007-08-13 18:29:44 +04:00
state - > setup_count = 2 * CVAL ( req - > inbuf , smb_nt_SetupCount ) ;
2006-12-15 03:49:12 +03:00
state - > setup = NULL ;
2006-04-10 19:33:04 +04:00
state - > call = function_code ;
2002-08-17 19:27:10 +04:00
2007-09-12 03:57:59 +04:00
/*
2006-04-10 19:33:04 +04:00
* All nttrans messages we handle have smb_wct = = 19 +
* state - > setup_count . Ensure this is so as a sanity check .
2002-08-17 19:27:10 +04:00
*/
2007-08-13 18:29:44 +04:00
if ( req - > wct ! = 19 + ( state - > setup_count / 2 ) ) {
2002-08-17 19:27:10 +04:00
DEBUG ( 2 , ( " Invalid smb_wct %d in nttrans call (should be %d) \n " ,
2007-08-13 18:29:44 +04:00
req - > wct , 19 + ( state - > setup_count / 2 ) ) ) ;
2003-03-07 03:30:47 +03:00
goto bad_param ;
2002-08-17 19:27:10 +04:00
}
2004-12-07 21:25:53 +03:00
/* Don't allow more than 128mb for each value. */
2006-04-10 19:33:04 +04:00
if ( ( state - > total_data > ( 1024 * 1024 * 128 ) ) | |
( state - > total_param > ( 1024 * 1024 * 128 ) ) ) {
2007-08-13 13:12:21 +04:00
reply_doserror ( req , ERRDOS , ERRnomem ) ;
2004-12-07 21:25:53 +03:00
END_PROFILE ( SMBnttrans ) ;
2007-08-13 13:12:21 +04:00
return ;
2004-12-07 21:25:53 +03:00
}
2006-04-10 19:33:04 +04:00
if ( ( dscnt > state - > total_data ) | | ( pscnt > state - > total_param ) )
2003-03-07 03:30:47 +03:00
goto bad_param ;
2002-08-17 19:27:10 +04:00
2006-04-10 19:33:04 +04:00
if ( state - > total_data ) {
/* Can't use talloc here, the core routines do realloc on the
* params and data . */
2006-07-30 20:36:56 +04:00
if ( ( state - > data = ( char * ) SMB_MALLOC ( state - > total_data ) ) = = NULL ) {
2006-04-10 19:33:04 +04:00
DEBUG ( 0 , ( " reply_nttrans: data malloc fail for %u "
2006-06-16 05:32:19 +04:00
" bytes ! \n " , ( unsigned int ) state - > total_data ) ) ;
2006-04-10 19:33:04 +04:00
TALLOC_FREE ( state ) ;
2007-08-13 13:12:21 +04:00
reply_doserror ( req , ERRDOS , ERRnomem ) ;
2006-05-05 11:15:45 +04:00
END_PROFILE ( SMBnttrans ) ;
2007-08-13 13:12:21 +04:00
return ;
2007-09-12 03:57:59 +04:00
}
2006-04-10 19:33:04 +04:00
if ( ( dsoff + dscnt < dsoff ) | | ( dsoff + dscnt < dscnt ) )
2003-03-07 03:30:47 +03:00
goto bad_param ;
2007-08-13 18:29:44 +04:00
if ( ( smb_base ( req - > inbuf ) + dsoff + dscnt
> ( char * ) req - > inbuf + size ) | |
( smb_base ( req - > inbuf ) + dsoff + dscnt < smb_base ( req - > inbuf ) ) )
2003-03-07 03:30:47 +03:00
goto bad_param ;
2007-08-13 18:29:44 +04:00
memcpy ( state - > data , smb_base ( req - > inbuf ) + dsoff , dscnt ) ;
2002-08-17 19:27:10 +04:00
}
2006-04-10 19:33:04 +04:00
if ( state - > total_param ) {
/* Can't use talloc here, the core routines do realloc on the
* params and data . */
2006-07-30 20:36:56 +04:00
if ( ( state - > param = ( char * ) SMB_MALLOC ( state - > total_param ) ) = = NULL ) {
2006-04-10 19:33:04 +04:00
DEBUG ( 0 , ( " reply_nttrans: param malloc fail for %u "
2006-06-16 05:32:19 +04:00
" bytes ! \n " , ( unsigned int ) state - > total_param ) ) ;
2006-04-10 19:33:04 +04:00
SAFE_FREE ( state - > data ) ;
TALLOC_FREE ( state ) ;
2007-08-13 13:12:21 +04:00
reply_doserror ( req , ERRDOS , ERRnomem ) ;
2006-05-05 11:15:45 +04:00
END_PROFILE ( SMBnttrans ) ;
2007-08-13 13:12:21 +04:00
return ;
2007-09-12 03:57:59 +04:00
}
2006-04-10 19:33:04 +04:00
if ( ( psoff + pscnt < psoff ) | | ( psoff + pscnt < pscnt ) )
2003-03-07 03:30:47 +03:00
goto bad_param ;
2007-08-13 18:29:44 +04:00
if ( ( smb_base ( req - > inbuf ) + psoff + pscnt
> ( char * ) req - > inbuf + size ) | |
( smb_base ( req - > inbuf ) + psoff + pscnt < smb_base ( req - > inbuf ) ) )
2003-03-07 03:30:47 +03:00
goto bad_param ;
2007-08-13 18:29:44 +04:00
memcpy ( state - > param , smb_base ( req - > inbuf ) + psoff , pscnt ) ;
2002-08-17 19:27:10 +04:00
}
2006-04-10 19:33:04 +04:00
state - > received_data = dscnt ;
state - > received_param = pscnt ;
if ( state - > setup_count > 0 ) {
DEBUG ( 10 , ( " reply_nttrans: state->setup_count = %d \n " ,
state - > setup_count ) ) ;
2006-07-30 20:36:56 +04:00
state - > setup = ( uint16 * ) TALLOC ( state , state - > setup_count ) ;
2006-04-10 19:33:04 +04:00
if ( state - > setup = = NULL ) {
DEBUG ( 0 , ( " reply_nttrans : Out of memory \n " ) ) ;
SAFE_FREE ( state - > data ) ;
SAFE_FREE ( state - > param ) ;
TALLOC_FREE ( state ) ;
2007-08-13 13:12:21 +04:00
reply_doserror ( req , ERRDOS , ERRnomem ) ;
2006-04-10 19:33:04 +04:00
END_PROFILE ( SMBnttrans ) ;
2007-08-13 13:12:21 +04:00
return ;
2006-04-10 19:33:04 +04:00
}
if ( ( smb_nt_SetupStart + state - > setup_count < smb_nt_SetupStart ) | |
( smb_nt_SetupStart + state - > setup_count < state - > setup_count ) ) {
2003-03-07 03:30:47 +03:00
goto bad_param ;
2005-07-08 08:51:27 +04:00
}
2006-04-10 19:33:04 +04:00
if ( smb_nt_SetupStart + state - > setup_count > size ) {
2003-03-07 03:30:47 +03:00
goto bad_param ;
2005-07-08 08:51:27 +04:00
}
2003-03-07 03:30:47 +03:00
2007-08-13 18:29:44 +04:00
memcpy ( state - > setup , & req - > inbuf [ smb_nt_SetupStart ] ,
state - > setup_count ) ;
2007-03-28 17:34:59 +04:00
dump_data ( 10 , ( uint8 * ) state - > setup , state - > setup_count ) ;
2002-08-17 19:27:10 +04:00
}
2006-04-10 19:33:04 +04:00
if ( ( state - > received_data = = state - > total_data ) & &
( state - > received_param = = state - > total_param ) ) {
2007-08-13 19:40:37 +04:00
handle_nttrans ( conn , state , req ) ;
2006-04-10 19:33:04 +04:00
SAFE_FREE ( state - > param ) ;
SAFE_FREE ( state - > data ) ;
TALLOC_FREE ( state ) ;
END_PROFILE ( SMBnttrans ) ;
2007-08-13 13:12:21 +04:00
return ;
2006-04-10 19:33:04 +04:00
}
2003-08-02 07:06:07 +04:00
2006-04-10 19:33:04 +04:00
DLIST_ADD ( conn - > pending_trans , state ) ;
2002-08-17 19:27:10 +04:00
2006-04-10 19:33:04 +04:00
/* We need to send an interim response then receive the rest
of the parameter / data bytes */
2007-08-13 19:40:37 +04:00
reply_outbuf ( req , 0 , 0 ) ;
show_msg ( ( char * ) req - > outbuf ) ;
2006-04-10 19:33:04 +04:00
END_PROFILE ( SMBnttrans ) ;
2007-08-13 13:12:21 +04:00
return ;
2002-08-17 19:27:10 +04:00
2006-04-10 19:33:04 +04:00
bad_param :
2002-08-17 19:27:10 +04:00
2006-04-10 19:33:04 +04:00
DEBUG ( 0 , ( " reply_nttrans: invalid trans parameters \n " ) ) ;
SAFE_FREE ( state - > data ) ;
SAFE_FREE ( state - > param ) ;
TALLOC_FREE ( state ) ;
2007-08-13 13:12:21 +04:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2006-04-10 19:33:04 +04:00
END_PROFILE ( SMBnttrans ) ;
2007-08-13 13:12:21 +04:00
return ;
2006-04-10 19:33:04 +04:00
}
2007-09-12 03:57:59 +04:00
2006-04-10 19:33:04 +04:00
/****************************************************************************
Reply to a SMBnttranss
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-04-10 10:57:55 +04:00
2007-08-13 13:12:21 +04:00
void reply_nttranss ( connection_struct * conn , struct smb_request * req )
2006-04-10 19:33:04 +04:00
{
unsigned int pcnt , poff , dcnt , doff , pdisp , ddisp ;
struct trans_state * state ;
2003-12-01 09:53:10 +03:00
2007-08-13 19:40:37 +04:00
int size ;
2007-08-13 13:12:21 +04:00
2006-04-10 19:33:04 +04:00
START_PROFILE ( SMBnttranss ) ;
2003-12-01 09:53:10 +03:00
2007-08-13 18:29:44 +04:00
show_msg ( ( char * ) req - > inbuf ) ;
2003-03-07 03:30:47 +03:00
2007-08-13 18:29:44 +04:00
if ( req - > wct < 18 ) {
2007-08-13 13:12:21 +04:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2007-08-13 12:50:09 +04:00
END_PROFILE ( SMBnttranss ) ;
2007-08-13 13:12:21 +04:00
return ;
2007-08-13 12:50:09 +04:00
}
2006-04-10 19:33:04 +04:00
for ( state = conn - > pending_trans ; state ! = NULL ;
state = state - > next ) {
2007-08-13 18:29:44 +04:00
if ( state - > mid = = req - > mid ) {
2006-04-10 19:33:04 +04:00
break ;
}
}
2003-03-07 03:30:47 +03:00
2006-04-10 19:33:04 +04:00
if ( ( state = = NULL ) | | ( state - > cmd ! = SMBnttrans ) ) {
2007-08-13 13:12:21 +04:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2006-04-10 19:33:04 +04:00
END_PROFILE ( SMBnttranss ) ;
2007-08-13 13:12:21 +04:00
return ;
2006-04-10 19:33:04 +04:00
}
2003-03-07 03:30:47 +03:00
2006-04-10 19:33:04 +04:00
/* Revise state->total_param and state->total_data in case they have
changed downwards */
2007-08-13 18:29:44 +04:00
if ( IVAL ( req - > inbuf , smb_nts_TotalParameterCount )
< state - > total_param ) {
state - > total_param = IVAL ( req - > inbuf ,
smb_nts_TotalParameterCount ) ;
2006-04-10 19:33:04 +04:00
}
2007-08-13 18:29:44 +04:00
if ( IVAL ( req - > inbuf , smb_nts_TotalDataCount ) < state - > total_data ) {
state - > total_data = IVAL ( req - > inbuf , smb_nts_TotalDataCount ) ;
2006-04-10 19:33:04 +04:00
}
2003-03-07 03:30:47 +03:00
2007-08-13 18:29:44 +04:00
size = smb_len ( req - > inbuf ) + 4 ;
pcnt = IVAL ( req - > inbuf , smb_nts_ParameterCount ) ;
poff = IVAL ( req - > inbuf , smb_nts_ParameterOffset ) ;
pdisp = IVAL ( req - > inbuf , smb_nts_ParameterDisplacement ) ;
2003-03-07 03:30:47 +03:00
2007-08-13 18:29:44 +04:00
dcnt = IVAL ( req - > inbuf , smb_nts_DataCount ) ;
ddisp = IVAL ( req - > inbuf , smb_nts_DataDisplacement ) ;
doff = IVAL ( req - > inbuf , smb_nts_DataOffset ) ;
2003-03-07 03:30:47 +03:00
2006-04-10 19:33:04 +04:00
state - > received_param + = pcnt ;
state - > received_data + = dcnt ;
2007-09-12 03:57:59 +04:00
2006-04-10 19:33:04 +04:00
if ( ( state - > received_data > state - > total_data ) | |
( state - > received_param > state - > total_param ) )
goto bad_param ;
2003-03-07 03:30:47 +03:00
2006-04-10 19:33:04 +04:00
if ( pcnt ) {
if ( pdisp + pcnt > state - > total_param )
goto bad_param ;
if ( ( pdisp + pcnt < pdisp ) | | ( pdisp + pcnt < pcnt ) )
goto bad_param ;
if ( pdisp > state - > total_param )
goto bad_param ;
2007-08-13 18:29:44 +04:00
if ( ( smb_base ( req - > inbuf ) + poff + pcnt
> ( char * ) req - > inbuf + size ) | |
( smb_base ( req - > inbuf ) + poff + pcnt
< smb_base ( req - > inbuf ) ) )
2006-04-10 19:33:04 +04:00
goto bad_param ;
if ( state - > param + pdisp < state - > param )
goto bad_param ;
2002-08-17 19:27:10 +04:00
2007-08-13 18:29:44 +04:00
memcpy ( state - > param + pdisp , smb_base ( req - > inbuf ) + poff ,
2006-04-10 19:33:04 +04:00
pcnt ) ;
2005-07-08 08:51:27 +04:00
}
2002-08-17 19:27:10 +04:00
2006-04-10 19:33:04 +04:00
if ( dcnt ) {
if ( ddisp + dcnt > state - > total_data )
goto bad_param ;
if ( ( ddisp + dcnt < ddisp ) | | ( ddisp + dcnt < dcnt ) )
goto bad_param ;
if ( ddisp > state - > total_data )
goto bad_param ;
2007-08-13 19:40:37 +04:00
if ( ( smb_base ( req - > inbuf ) + doff + dcnt
2007-08-13 18:29:44 +04:00
> ( char * ) req - > inbuf + size ) | |
2007-08-13 19:40:37 +04:00
( smb_base ( req - > inbuf ) + doff + dcnt
< smb_base ( req - > inbuf ) ) )
2006-04-10 19:33:04 +04:00
goto bad_param ;
if ( state - > data + ddisp < state - > data )
goto bad_param ;
2002-08-17 19:27:10 +04:00
2007-08-13 18:29:44 +04:00
memcpy ( state - > data + ddisp , smb_base ( req - > inbuf ) + doff ,
2007-09-12 03:57:59 +04:00
dcnt ) ;
2002-08-17 19:27:10 +04:00
}
2006-04-10 19:33:04 +04:00
if ( ( state - > received_param < state - > total_param ) | |
( state - > received_data < state - > total_data ) ) {
END_PROFILE ( SMBnttranss ) ;
2007-08-13 13:12:21 +04:00
return ;
2006-04-10 19:33:04 +04:00
}
2002-08-17 19:27:10 +04:00
2007-08-13 19:40:37 +04:00
/*
* construct_reply_common will copy smb_com from inbuf to
* outbuf . SMBnttranss is wrong here .
2006-04-10 19:33:04 +04:00
*/
2007-08-13 19:40:37 +04:00
SCVAL ( req - > inbuf , smb_com , SMBnttrans ) ;
2003-08-02 07:06:07 +04:00
2007-08-13 19:40:37 +04:00
handle_nttrans ( conn , state , req ) ;
2003-03-07 03:30:47 +03:00
2006-04-10 19:33:04 +04:00
DLIST_REMOVE ( conn - > pending_trans , state ) ;
SAFE_FREE ( state - > data ) ;
SAFE_FREE ( state - > param ) ;
TALLOC_FREE ( state ) ;
END_PROFILE ( SMBnttranss ) ;
2007-08-13 13:12:21 +04:00
return ;
2006-04-10 19:33:04 +04:00
bad_param :
DEBUG ( 0 , ( " reply_nttranss: invalid trans parameters \n " ) ) ;
DLIST_REMOVE ( conn - > pending_trans , state ) ;
SAFE_FREE ( state - > data ) ;
SAFE_FREE ( state - > param ) ;
TALLOC_FREE ( state ) ;
2007-08-13 13:12:21 +04:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2006-04-10 19:33:04 +04:00
END_PROFILE ( SMBnttranss ) ;
2007-08-13 13:12:21 +04:00
return ;
1998-05-08 05:22:16 +04:00
}