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"
2011-02-26 01:20:06 +03:00
# include "system/filesys.h"
2011-03-22 18:57:01 +03:00
# include "smbd/smbd.h"
2009-01-08 14:03:45 +03:00
# include "smbd/globals.h"
2010-08-18 18:44:47 +04:00
# include "fake_file.h"
2010-10-12 08:27:50 +04:00
# include "../libcli/security/security.h"
2010-05-28 04:19:32 +04:00
# include "../librpc/gen_ndr/ndr_security.h"
2011-03-22 18:50:02 +03:00
# include "passdb/lookup_sid.h"
2011-03-24 15:46:20 +03:00
# include "auth.h"
2011-04-14 02:36:23 +04:00
# include "smbprofile.h"
2011-05-06 13:47:43 +04:00
# include "libsmb/libsmb.h"
2013-08-08 00:48:55 +04:00
# include "lib/util_ea.h"
2017-05-26 18:01:53 +03:00
# include "librpc/gen_ndr/ndr_quota.h"
# include "librpc/gen_ndr/ndr_security.h"
1998-05-08 05:22:16 +04:00
2008-10-10 18:26:34 +04:00
extern const struct generic_mapping file_generic_mapping ;
1998-05-08 05:22:16 +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
2011-04-13 17:40:15 +04:00
static void send_nt_replies ( connection_struct * conn ,
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 ;
2009-07-03 15:28:01 +04:00
int alignment_offset = 1 ;
2002-08-17 19:27:10 +04:00
int data_alignment_offset = 0 ;
2014-06-11 16:26:57 +04:00
struct smbXsrv_connection * xconn = req - > xconn ;
2014-05-21 12:56:26 +04:00
int max_send = xconn - > smb1 . sessions . max_send ;
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 ) ;
2009-07-01 14:56:30 +04:00
if ( NT_STATUS_V ( nt_error ) ) {
error_packet_set ( ( char * ) req - > outbuf ,
0 , 0 , nt_error ,
__LINE__ , __FILE__ ) ;
}
2007-08-14 12:44:00 +04:00
show_msg ( ( char * ) req - > outbuf ) ;
2014-06-11 14:55:24 +04:00
if ( ! srv_send_smb ( xconn ,
2009-06-29 17:38:48 +04:00
( char * ) req - > outbuf ,
true , req - > seqnum + 1 ,
IS_CONN_ENCRYPTED ( conn ) ,
& req - > pcd ) ) {
exit_server_cleanly ( " send_nt_replies: srv_send_smb failed. " ) ;
}
TALLOC_FREE ( 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
2008-09-09 00:53:50 +04:00
if ( useable_space < 0 ) {
2008-10-22 18:14:26 +04:00
char * msg = talloc_asprintf (
talloc_tos ( ) ,
" send_nt_replies failed sanity useable_space = %d!!! " ,
useable_space ) ;
DEBUG ( 0 , ( " %s \n " , msg ) ) ;
exit_server_cleanly ( msg ) ;
2008-09-09 00:53:50 +04:00
}
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 .
*/
2008-09-09 00:53:50 +04:00
total_sent_thistime = params_to_send + data_to_send ;
2002-08-17 19:27:10 +04:00
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 ) ;
2008-09-09 00:53:50 +04:00
reply_outbuf ( req , 18 ,
total_sent_thistime + alignment_offset
+ data_alignment_offset ) ;
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 ) ;
2014-06-11 14:55:24 +04:00
if ( ! srv_send_smb ( xconn ,
2008-01-04 23:56:23 +03:00
( char * ) req - > outbuf ,
2009-03-09 11:47:59 +03:00
true , req - > seqnum + 1 ,
2009-02-09 10:10:34 +03:00
IS_CONN_ENCRYPTED ( conn ) ,
& req - > pcd ) ) {
2008-01-04 23:56:23 +03:00
exit_server_cleanly ( " send_nt_replies: srv_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 ) ) ;
2008-09-09 00:53:50 +04:00
exit_server_cleanly ( " send_nt_replies: internal error " ) ;
2002-08-17 19:27:10 +04:00
}
2007-09-12 03:57:59 +04:00
}
2007-08-13 12:33:01 +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 ,
2012-06-28 14:22:07 +04:00
struct smb_request * req , uint16_t * ppnum )
2007-07-31 13:22:16 +04:00
{
2008-10-13 01:01:38 +04:00
files_struct * fsp ;
NTSTATUS status ;
2007-07-31 13:22:16 +04:00
DEBUG ( 4 , ( " nt_open_pipe: Opening pipe %s. \n " , fname ) ) ;
2012-05-28 18:40:36 +04:00
/* Strip \\ off the name if present. */
while ( fname [ 0 ] = = ' \\ ' ) {
fname + + ;
}
2007-07-31 13:22:16 +04:00
2009-01-20 17:21:04 +03:00
status = open_np_file ( req , fname , & fsp ) ;
2008-10-13 01:01:38 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2008-10-25 17:23:36 +04:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_OBJECT_NAME_NOT_FOUND ) ) {
reply_botherror ( req , NT_STATUS_OBJECT_NAME_NOT_FOUND ,
ERRDOS , ERRbadpipe ) ;
return ;
}
2008-10-13 01:01:38 +04:00
reply_nterror ( req , status ) ;
2007-07-31 13:22:16 +04:00
return ;
}
2008-10-13 01:01:38 +04:00
* ppnum = fsp - > fnum ;
2007-07-31 13:22:16 +04:00
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 ;
2012-06-28 14:22:07 +04:00
uint16_t pnum = FNUM_FIELD_INVALID ;
2000-05-23 21:57:51 +04:00
char * p = NULL ;
2015-05-01 05:22:21 +03:00
uint32_t flags = IVAL ( req - > vwv + 3 , 1 ) ;
2007-09-12 03:57:59 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2007-07-31 13:22:16 +04:00
2008-11-02 03:07:46 +03:00
srvstr_pull_req_talloc ( ctx , req , & fname , req - > buf , 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
2012-02-21 16:25:34 +04:00
* the wcnt to 42 ? It ' s definitely
2007-04-08 04:47:49 +04:00
* 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
2012-02-26 19:49:09 +04:00
SSVAL ( req - > outbuf , smb_vwv0 , 0xff ) ; /* andx chain ends */
SSVAL ( req - > outbuf , smb_vwv1 , 0 ) ; /* no andx offset */
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 ) ) ;
}
2009-11-24 08:06:54 +03:00
struct case_semantics_state {
connection_struct * conn ;
bool case_sensitive ;
bool case_preserve ;
bool short_case_preserve ;
} ;
/****************************************************************************
Restore case semantics .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
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 ;
}
/****************************************************************************
Save case semantics .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static struct case_semantics_state * set_posix_case_semantics ( TALLOC_CTX * mem_ctx ,
connection_struct * conn )
{
struct case_semantics_state * result ;
if ( ! ( result = talloc ( mem_ctx , struct case_semantics_state ) ) ) {
return NULL ;
}
result - > conn = conn ;
result - > case_sensitive = conn - > case_sensitive ;
result - > case_preserve = conn - > case_preserve ;
result - > short_case_preserve = conn - > short_case_preserve ;
/* Set to POSIX. */
conn - > case_sensitive = True ;
conn - > case_preserve = True ;
conn - > short_case_preserve = True ;
talloc_set_destructor ( result , restore_case_semantics ) ;
return result ;
}
2007-12-02 00:36:17 +03:00
/****************************************************************************
Reply to an NT create and X call .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-05 02:37:24 +03:00
void reply_ntcreate_and_X ( struct smb_request * req )
2007-12-02 00:36:17 +03:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2009-06-05 05:39:55 +04:00
struct smb_filename * smb_fname = NULL ;
2007-12-02 00:36:17 +03:00
char * fname = NULL ;
2015-05-01 05:22:21 +03:00
uint32_t flags ;
uint32_t access_mask ;
uint32_t file_attributes ;
uint32_t share_access ;
uint32_t create_disposition ;
uint32_t create_options ;
uint16_t root_dir_fid ;
2008-10-14 03:59:36 +04:00
uint64_t allocation_size ;
2007-12-02 00:36:17 +03:00
/* Breakout the oplock request bits so we can set the
reply bits separately . */
2015-05-01 05:22:21 +03:00
uint32_t fattr = 0 ;
2012-04-05 08:53:08 +04:00
off_t file_len = 0 ;
2007-12-02 00:36:17 +03:00
int info = 0 ;
files_struct * fsp = NULL ;
char * p = NULL ;
2009-08-11 02:07:53 +04:00
struct timespec create_timespec ;
2007-12-02 00:36:17 +03:00
struct timespec c_timespec ;
struct timespec a_timespec ;
struct timespec m_timespec ;
NTSTATUS status ;
2007-12-07 14:57:11 +03:00
int oplock_request ;
2007-12-02 00:36:17 +03:00
uint8_t oplock_granted = NO_OPLOCK_RETURN ;
2009-11-24 08:06:54 +03:00
struct case_semantics_state * case_state = NULL ;
2016-10-13 13:42:59 +03:00
uint32_t ucf_flags ;
2007-12-02 00:36:17 +03:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
START_PROFILE ( SMBntcreateX ) ;
if ( req - > wct < 24 ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2009-11-24 08:06:54 +03:00
goto out ;
2007-12-02 00:36:17 +03:00
}
2008-11-02 19:38:41 +03:00
flags = IVAL ( req - > vwv + 3 , 1 ) ;
access_mask = IVAL ( req - > vwv + 7 , 1 ) ;
file_attributes = IVAL ( req - > vwv + 13 , 1 ) ;
share_access = IVAL ( req - > vwv + 15 , 1 ) ;
create_disposition = IVAL ( req - > vwv + 17 , 1 ) ;
create_options = IVAL ( req - > vwv + 19 , 1 ) ;
2015-05-01 05:22:21 +03:00
root_dir_fid = ( uint16_t ) IVAL ( req - > vwv + 5 , 1 ) ;
2007-12-02 00:36:17 +03:00
2011-04-23 12:30:59 +04:00
allocation_size = BVAL ( req - > vwv + 9 , 1 ) ;
2007-12-02 00:36:17 +03:00
2008-11-02 02:59:03 +03:00
srvstr_get_path_req ( ctx , req , & fname , ( const char * ) req - > buf ,
STR_TERMINATE , & status ) ;
2007-12-02 00:36:17 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
reply_nterror ( req , status ) ;
2009-06-05 05:39:55 +04:00
goto out ;
2007-12-02 00:36:17 +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, fname = %s \n " ,
( 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 ,
fname ) ) ;
2008-08-19 18:34:50 +04:00
/*
* we need to remove ignored bits when they come directly from the client
* because we reuse some of them for internal stuff
*/
create_options & = ~ NTCREATEX_OPTIONS_MUST_IGNORE_MASK ;
2007-12-02 00:36:17 +03:00
/*
* If it ' s an IPC , use the pipe handler .
*/
if ( IS_IPC ( conn ) ) {
if ( lp_nt_pipe_support ( ) ) {
do_ntcreate_pipe_open ( conn , req ) ;
2009-06-05 05:39:55 +04:00
goto out ;
2007-12-02 00:36:17 +03:00
}
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
2009-06-05 05:39:55 +04:00
goto out ;
2007-12-02 00:36:17 +03:00
}
2007-12-07 14:57:11 +03:00
oplock_request = ( flags & REQUEST_OPLOCK ) ? EXCLUSIVE_OPLOCK : 0 ;
if ( oplock_request ) {
oplock_request | = ( flags & REQUEST_BATCH_OPLOCK )
? BATCH_OPLOCK : 0 ;
}
2009-11-25 00:02:34 +03:00
if ( file_attributes & FILE_FLAG_POSIX_SEMANTICS ) {
case_state = set_posix_case_semantics ( ctx , conn ) ;
if ( ! case_state ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
goto out ;
}
2009-11-24 08:06:54 +03:00
}
2016-10-13 13:42:59 +03:00
ucf_flags = filename_create_ucf_flags ( req , create_disposition ) ;
2009-06-19 00:13:38 +04:00
status = filename_convert ( ctx ,
2009-06-17 04:23:54 +04:00
conn ,
fname ,
2015-12-22 21:49:08 +03:00
ucf_flags ,
2009-07-24 23:13:07 +04:00
NULL ,
2009-07-21 21:28:28 +04:00
& smb_fname ) ;
2009-06-17 04:23:54 +04:00
2009-11-24 08:06:54 +03:00
TALLOC_FREE ( case_state ) ;
2009-06-17 04:23:54 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
reply_botherror ( req ,
NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
goto out ;
}
reply_nterror ( req , status ) ;
goto out ;
}
2009-11-24 02:01:34 +03:00
/*
* Bug # 6898 - clients using Windows opens should
* never be able to set this attribute into the
* VFS .
*/
file_attributes & = ~ FILE_FLAG_POSIX_SEMANTICS ;
2008-10-21 04:43:45 +04:00
status = SMB_VFS_CREATE_FILE (
conn , /* conn */
req , /* req */
root_dir_fid , /* root_dir_fid */
2009-06-12 23:54:11 +04:00
smb_fname , /* fname */
2008-10-21 04:43:45 +04:00
access_mask , /* access_mask */
share_access , /* share_access */
create_disposition , /* create_disposition*/
create_options , /* create_options */
file_attributes , /* file_attributes */
oplock_request , /* oplock_request */
2013-08-21 17:56:14 +04:00
NULL , /* lease */
2008-10-21 04:43:45 +04:00
allocation_size , /* allocation_size */
2010-03-06 02:10:30 +03:00
0 , /* private_flags */
2008-10-21 04:43:45 +04:00
NULL , /* sd */
NULL , /* ea_list */
& fsp , /* result */
2014-11-26 16:12:51 +03:00
& info , /* pinfo */
NULL , NULL ) ; /* create context */
2007-12-02 00:36:17 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2014-09-16 08:55:39 +04:00
if ( open_was_deferred ( req - > xconn , req - > mid ) ) {
2007-12-02 00:36:17 +03:00
/* We have re-scheduled this call, no error. */
2009-06-05 05:39:55 +04:00
goto out ;
2007-12-02 00:36:17 +03:00
}
2009-12-18 05:31:26 +03:00
reply_openerror ( req , status ) ;
2009-06-05 05:39:55 +04:00
goto out ;
2007-12-02 00:36:17 +03:00
}
2009-08-11 02:07:53 +04:00
/* Ensure we're pointing at the correct stat struct. */
TALLOC_FREE ( smb_fname ) ;
smb_fname = fsp - > fsp_name ;
2007-12-07 14:57:11 +03: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 .
*/
if ( oplock_request & &
( lp_fake_oplocks ( SNUM ( conn ) )
| | EXCLUSIVE_OPLOCK_TYPE ( fsp - > oplock_type ) ) ) {
/*
* Exclusive oplock granted
*/
if ( flags & REQUEST_BATCH_OPLOCK ) {
oplock_granted = BATCH_OPLOCK_RETURN ;
} else {
oplock_granted = EXCLUSIVE_OPLOCK_RETURN ;
}
} else if ( fsp - > oplock_type = = LEVEL_II_OPLOCK ) {
oplock_granted = LEVEL_II_OPLOCK_RETURN ;
} else {
oplock_granted = NO_OPLOCK_RETURN ;
}
2009-06-05 05:39:55 +04:00
file_len = smb_fname - > st . st_ex_size ;
2007-12-02 16:37:44 +03:00
2007-12-02 00:36:17 +03:00
if ( flags & EXTENDED_RESPONSE_REQUIRED ) {
/* This is very strange. We
* return 50 words , but only set
2012-02-21 16:25:34 +04:00
* the wcnt to 42 ? It ' s definitely
2007-12-02 00:36:17 +03:00
* what happens on the wire . . . .
*/
reply_outbuf ( req , 50 , 0 ) ;
SCVAL ( req - > outbuf , smb_wct , 42 ) ;
} else {
reply_outbuf ( req , 34 , 0 ) ;
}
2012-02-26 19:49:09 +04:00
SSVAL ( req - > outbuf , smb_vwv0 , 0xff ) ; /* andx chain ends */
SSVAL ( req - > outbuf , smb_vwv1 , 0 ) ; /* no andx offset */
2007-12-02 00:36:17 +03:00
p = ( char * ) req - > outbuf + smb_vwv2 ;
SCVAL ( p , 0 , oplock_granted ) ;
p + + ;
SSVAL ( p , 0 , fsp - > fnum ) ;
p + = 2 ;
if ( ( create_disposition = = FILE_SUPERSEDE )
& & ( info = = FILE_WAS_OVERWRITTEN ) ) {
SIVAL ( p , 0 , FILE_WAS_SUPERSEDED ) ;
} else {
SIVAL ( p , 0 , info ) ;
}
p + = 4 ;
2009-11-18 01:55:02 +03:00
fattr = dos_mode ( conn , smb_fname ) ;
if ( fattr = = 0 ) {
fattr = FILE_ATTRIBUTE_NORMAL ;
}
2007-12-02 00:36:17 +03:00
/* Create time. */
2009-08-13 00:00:54 +04:00
create_timespec = get_create_timespec ( conn , fsp , smb_fname ) ;
2009-06-05 05:39:55 +04:00
a_timespec = smb_fname - > st . st_ex_atime ;
m_timespec = smb_fname - > st . st_ex_mtime ;
2009-08-13 00:00:54 +04:00
c_timespec = get_change_timespec ( conn , fsp , smb_fname ) ;
2007-12-02 00:36:17 +03:00
if ( lp_dos_filetime_resolution ( SNUM ( conn ) ) ) {
2009-08-11 02:07:53 +04:00
dos_filetime_timespec ( & create_timespec ) ;
2007-12-02 00:36:17 +03:00
dos_filetime_timespec ( & a_timespec ) ;
dos_filetime_timespec ( & m_timespec ) ;
2009-08-11 02:07:53 +04:00
dos_filetime_timespec ( & c_timespec ) ;
2007-12-02 00:36:17 +03:00
}
2009-08-25 07:57:37 +04:00
put_long_date_timespec ( conn - > ts_res , p , create_timespec ) ; /* create time. */
2007-12-02 00:36:17 +03:00
p + = 8 ;
2009-08-25 07:57:37 +04:00
put_long_date_timespec ( conn - > ts_res , p , a_timespec ) ; /* access time */
2007-12-02 00:36:17 +03:00
p + = 8 ;
2009-08-25 07:57:37 +04:00
put_long_date_timespec ( conn - > ts_res , p , m_timespec ) ; /* write time */
2007-12-02 00:36:17 +03:00
p + = 8 ;
2009-08-25 07:57:37 +04:00
put_long_date_timespec ( conn - > ts_res , p , c_timespec ) ; /* change time */
2007-12-02 00:36:17 +03:00
p + = 8 ;
SIVAL ( p , 0 , fattr ) ; /* File Attributes. */
p + = 4 ;
2009-06-05 05:39:55 +04:00
SOFF_T ( p , 0 , SMB_VFS_GET_ALLOC_SIZE ( conn , fsp , & smb_fname - > st ) ) ;
2007-12-02 00:36:17 +03:00
p + = 8 ;
SOFF_T ( p , 0 , file_len ) ;
p + = 8 ;
if ( flags & EXTENDED_RESPONSE_REQUIRED ) {
2009-09-15 02:30:05 +04:00
uint16_t file_status = ( NO_EAS | NO_SUBSTREAMS | NO_REPARSETAG ) ;
2011-10-14 02:41:53 +04:00
unsigned int num_streams = 0 ;
2009-09-15 02:30:05 +04:00
struct stream_struct * streams = NULL ;
2017-03-02 09:39:56 +03:00
if ( lp_ea_support ( SNUM ( conn ) ) ) {
size_t num_names = 0 ;
/* Do we have any EA's ? */
status = get_ea_names_from_file (
ctx , conn , fsp , smb_fname , NULL , & num_names ) ;
if ( NT_STATUS_IS_OK ( status ) & & num_names ) {
file_status & = ~ NO_EAS ;
}
2009-09-15 02:30:05 +04:00
}
2017-03-02 09:39:56 +03:00
2016-03-05 01:16:13 +03:00
status = vfs_streaminfo ( conn , NULL , smb_fname , ctx ,
2009-09-15 02:30:05 +04:00
& num_streams , & streams ) ;
/* There is always one stream, ::$DATA. */
if ( NT_STATUS_IS_OK ( status ) & & num_streams > 1 ) {
file_status & = ~ NO_SUBSTREAMS ;
}
TALLOC_FREE ( streams ) ;
SSVAL ( p , 2 , file_status ) ;
2007-12-02 00:36:17 +03: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 ) {
2015-05-01 05:22:21 +03:00
uint32_t perms = 0 ;
2007-06-05 02:29:23 +04:00
p + = 25 ;
2009-06-05 05:39:55 +04:00
if ( fsp - > is_directory | |
2012-09-14 01:36:57 +04:00
fsp - > can_write | |
2009-06-26 05:19:09 +04:00
can_write_to_file ( conn , smb_fname ) ) {
2007-04-07 10:38:45 +04:00
perms = FILE_GENERIC_ALL ;
} else {
perms = FILE_GENERIC_READ | FILE_EXECUTE ;
}
SIVAL ( p , 0 , perms ) ;
}
2012-06-14 14:52:52 +04:00
DEBUG ( 5 , ( " reply_ntcreate_and_X: %s, open name = %s \n " ,
fsp_fnum_dbg ( fsp ) , smb_fname_str_dbg ( smb_fname ) ) ) ;
1998-08-03 23:07:55 +04:00
2009-06-05 05:39:55 +04:00
out :
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 ,
2015-05-01 05:22:21 +03:00
uint16_t * * ppsetup , uint32_t setup_count ,
char * * ppparams , uint32_t parameter_count ,
char * * ppdata , uint32_t 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 ;
2012-06-28 14:22:07 +04:00
uint16_t pnum = FNUM_FIELD_INVALID ;
2000-05-23 21:57:51 +04:00
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 ;
2015-05-01 05:22:21 +03:00
uint32_t 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 ) ) ;
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2007-08-13 23:22:07 +04:00
return ;
2000-05-23 21:57:51 +04:00
}
2007-04-08 08:54:44 +04:00
flags = IVAL ( params , 0 ) ;
2015-12-23 00:44:10 +03:00
if ( req - > posix_pathnames ) {
2015-12-23 00:26:49 +03:00
srvstr_get_path_posix ( ctx ,
params ,
req - > flags2 ,
& fname ,
params + 53 ,
parameter_count - 53 ,
STR_TERMINATE ,
2007-07-05 20:36:15 +04:00
& status ) ;
2015-12-23 00:26:49 +03:00
} else {
srvstr_get_path ( ctx ,
params ,
req - > flags2 ,
& fname ,
params + 53 ,
parameter_count - 53 ,
STR_TERMINATE ,
& 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 ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
2007-08-13 23:22:07 +04:00
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 */
2008-01-04 23:56:23 +03:00
send_nt_replies ( conn , 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
}
2012-08-30 00:40:29 +04:00
/*********************************************************************
Windows seems to do canonicalization of inheritance bits . Do the
same .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void canonicalize_inheritance_bits ( struct security_descriptor * psd )
{
bool set_auto_inherited = false ;
/*
* We need to filter out the
* SEC_DESC_DACL_AUTO_INHERITED | SEC_DESC_DACL_AUTO_INHERIT_REQ
* bits . If both are set we store SEC_DESC_DACL_AUTO_INHERITED
* as this alters whether SEC_ACE_FLAG_INHERITED_ACE is set
* when an ACE is inherited . Otherwise we zero these bits out .
* See :
*
* http : //social.msdn.microsoft.com/Forums/eu/os_fileservices/thread/11f77b68-731e-407d-b1b3-064750716531
*
* for details .
*/
if ( ( psd - > type & ( SEC_DESC_DACL_AUTO_INHERITED | SEC_DESC_DACL_AUTO_INHERIT_REQ ) )
= = ( SEC_DESC_DACL_AUTO_INHERITED | SEC_DESC_DACL_AUTO_INHERIT_REQ ) ) {
set_auto_inherited = true ;
}
psd - > type & = ~ ( SEC_DESC_DACL_AUTO_INHERITED | SEC_DESC_DACL_AUTO_INHERIT_REQ ) ;
if ( set_auto_inherited ) {
psd - > type | = SEC_DESC_DACL_AUTO_INHERITED ;
}
}
2001-01-31 08:14:31 +03:00
/****************************************************************************
2012-08-30 00:29:34 +04:00
Internal fn to set security descriptors .
2001-01-31 08:14:31 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2012-08-30 00:29:34 +04:00
NTSTATUS set_sd ( files_struct * fsp , struct security_descriptor * psd ,
2010-04-29 01:13:22 +04:00
uint32_t security_info_sent )
2001-01-31 08:14:31 +03:00
{
2007-06-27 02:49:10 +04:00
NTSTATUS status ;
2007-09-12 03:57:59 +04:00
2010-09-10 02:28:43 +04:00
if ( ! CAN_WRITE ( fsp - > conn ) ) {
return NT_STATUS_ACCESS_DENIED ;
}
2010-10-12 04:10:28 +04:00
if ( ! 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
}
2016-01-05 21:52:50 +03:00
if ( S_ISLNK ( fsp - > fsp_name - > st . st_ex_mode ) ) {
DEBUG ( 10 , ( " ACL set on symlink %s denied. \n " ,
fsp_str_dbg ( fsp ) ) ) ;
return NT_STATUS_ACCESS_DENIED ;
}
2008-11-24 05:20:19 +03:00
if ( psd - > owner_sid = = NULL ) {
2010-06-03 01:22:12 +04:00
security_info_sent & = ~ SECINFO_OWNER ;
2005-07-08 08:51:27 +04:00
}
2008-11-24 05:20:19 +03:00
if ( psd - > group_sid = = NULL ) {
2010-06-03 01:25:18 +04:00
security_info_sent & = ~ SECINFO_GROUP ;
2005-07-08 08:51:27 +04:00
}
2007-09-12 03:57:59 +04:00
2010-10-12 04:10:28 +04:00
/* Ensure we have at least one thing set. */
if ( ( security_info_sent & ( SECINFO_OWNER | SECINFO_GROUP | SECINFO_DACL | SECINFO_SACL ) ) = = 0 ) {
2013-08-01 16:16:24 +04:00
/* Just like W2K3 */
return NT_STATUS_OK ;
2010-10-12 04:10:28 +04:00
}
/* Ensure we have the rights to do this. */
if ( security_info_sent & SECINFO_OWNER ) {
if ( ! ( fsp - > access_mask & SEC_STD_WRITE_OWNER ) ) {
return NT_STATUS_ACCESS_DENIED ;
}
}
if ( security_info_sent & SECINFO_GROUP ) {
if ( ! ( fsp - > access_mask & SEC_STD_WRITE_OWNER ) ) {
return NT_STATUS_ACCESS_DENIED ;
}
}
if ( security_info_sent & SECINFO_DACL ) {
if ( ! ( fsp - > access_mask & SEC_STD_WRITE_DAC ) ) {
return NT_STATUS_ACCESS_DENIED ;
}
/* Convert all the generic bits. */
if ( psd - > dacl ) {
security_acl_map_generic ( psd - > dacl , & file_generic_mapping ) ;
}
}
if ( security_info_sent & SECINFO_SACL ) {
if ( ! ( fsp - > access_mask & SEC_FLAG_SYSTEM_SECURITY ) ) {
return NT_STATUS_ACCESS_DENIED ;
}
/* Convert all the generic bits. */
if ( psd - > sacl ) {
security_acl_map_generic ( psd - > sacl , & file_generic_mapping ) ;
}
}
2008-10-09 05:06:58 +04:00
2012-08-30 00:40:29 +04:00
canonicalize_inheritance_bits ( psd ) ;
2008-11-13 06:27:17 +03:00
if ( DEBUGLEVEL > = 10 ) {
2012-08-30 00:29:34 +04:00
DEBUG ( 10 , ( " set_sd for file %s \n " , fsp_str_dbg ( fsp ) ) ) ;
2008-11-13 06:27:17 +03:00
NDR_PRINT_DEBUG ( security_descriptor , psd ) ;
}
2008-05-09 05:09:07 +04:00
status = SMB_VFS_FSET_NT_ACL ( fsp , security_info_sent , psd ) ;
2007-11-25 20:26:52 +03:00
TALLOC_FREE ( psd ) ;
2007-09-12 03:57:59 +04:00
2007-06-27 02:49:10 +04:00
return status ;
2001-01-31 08:14:31 +03:00
}
2012-08-30 00:29:34 +04:00
/****************************************************************************
Internal fn to set security descriptors from a data blob .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
NTSTATUS set_sd_blob ( files_struct * fsp , uint8_t * data , uint32_t sd_len ,
uint32_t security_info_sent )
{
struct security_descriptor * psd = NULL ;
NTSTATUS status ;
if ( sd_len = = 0 ) {
return NT_STATUS_INVALID_PARAMETER ;
}
status = unmarshall_sec_desc ( talloc_tos ( ) , data , sd_len , & psd ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
return set_sd ( fsp , psd , security_info_sent ) ;
}
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 ,
2015-05-01 05:22:21 +03:00
uint16_t * * ppsetup , uint32_t setup_count ,
char * * ppparams , uint32_t parameter_count ,
char * * ppdata , uint32_t data_count ,
uint32_t max_data_count )
1998-07-02 22:49:08 +04:00
{
2009-06-05 05:39:55 +04:00
struct smb_filename * smb_fname = NULL ;
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. */
2015-05-01 05:22:21 +03:00
uint32_t fattr = 0 ;
2012-04-05 08:53:08 +04:00
off_t file_len = 0 ;
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 ;
2015-05-01 05:22:21 +03:00
uint32_t flags ;
uint32_t access_mask ;
uint32_t file_attributes ;
uint32_t share_access ;
uint32_t create_disposition ;
uint32_t create_options ;
uint32_t sd_len ;
2007-12-02 16:55:01 +03:00
struct security_descriptor * sd = NULL ;
2015-05-01 05:22:21 +03:00
uint32_t ea_len ;
uint16_t root_dir_fid ;
2009-08-11 02:07:53 +04:00
struct timespec create_timespec ;
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 ;
2004-03-03 23:55:59 +03:00
NTSTATUS status ;
2007-04-08 08:54:44 +04:00
size_t param_len ;
2008-10-14 03:59:36 +04:00
uint64_t allocation_size ;
2007-12-07 14:57:11 +03:00
int oplock_request ;
2007-12-02 00:36:17 +03:00
uint8_t oplock_granted ;
2009-11-24 08:06:54 +03:00
struct case_semantics_state * case_state = NULL ;
2016-10-13 13:42:59 +03:00
uint32_t ucf_flags ;
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 ) ;
2009-06-05 05:39:55 +04:00
goto out ;
2005-07-08 08:51:27 +04:00
}
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
2009-06-05 05:39:55 +04:00
goto out ;
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 ) ;
2009-06-05 05:39:55 +04:00
goto out ;
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 ) ;
2015-05-01 05:22:21 +03:00
root_dir_fid = ( uint16_t ) IVAL ( params , 4 ) ;
2011-04-23 12:30:59 +04:00
allocation_size = BVAL ( params , 12 ) ;
1998-07-08 05:42:05 +04:00
2008-08-19 18:34:50 +04:00
/*
* we need to remove ignored bits when they come directly from the client
* because we reuse some of them for internal stuff
*/
create_options & = ~ NTCREATEX_OPTIONS_MUST_IGNORE_MASK ;
2015-12-23 00:44:10 +03:00
if ( req - > posix_pathnames ) {
2015-12-23 00:26:49 +03:00
srvstr_get_path_posix ( ctx ,
params ,
req - > flags2 ,
& fname ,
params + 53 ,
parameter_count - 53 ,
STR_TERMINATE ,
& status ) ;
} else {
srvstr_get_path ( ctx ,
params ,
req - > flags2 ,
& fname ,
params + 53 ,
parameter_count - 53 ,
STR_TERMINATE ,
& status ) ;
}
2013-07-16 22:05:10 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
reply_nterror ( req , status ) ;
goto out ;
}
if ( file_attributes & FILE_FLAG_POSIX_SEMANTICS ) {
case_state = set_posix_case_semantics ( ctx , conn ) ;
if ( ! case_state ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
goto out ;
}
}
2016-10-13 13:42:59 +03:00
ucf_flags = filename_create_ucf_flags ( req , create_disposition ) ;
2013-07-16 22:05:10 +04:00
status = filename_convert ( ctx ,
conn ,
fname ,
2015-12-22 21:49:08 +03:00
ucf_flags ,
2013-07-16 22:05:10 +04:00
NULL ,
& smb_fname ) ;
TALLOC_FREE ( case_state ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( NT_STATUS_EQUAL ( status , NT_STATUS_PATH_NOT_COVERED ) ) {
reply_botherror ( req ,
NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
goto out ;
}
reply_nterror ( req , status ) ;
goto out ;
}
2005-03-31 04:36:22 +04:00
/* Ensure the data_len is correct for the sd and ea values given. */
2007-12-01 21:03:25 +03:00
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 ) ) {
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 ) ;
2009-06-05 05:39:55 +04:00
goto out ;
2005-03-31 04:36:22 +04:00
}
2007-12-01 21:16:52 +03:00
if ( sd_len ) {
2007-12-02 16:56:57 +03:00
DEBUG ( 10 , ( " call_nt_transact_create - sd_len = %d \n " ,
sd_len ) ) ;
2007-12-01 21:16:52 +03:00
status = unmarshall_sec_desc ( ctx , ( uint8_t * ) data , sd_len ,
& sd ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 10 , ( " call_nt_transact_create: "
" unmarshall_sec_desc failed: %s \n " ,
nt_errstr ( status ) ) ) ;
reply_nterror ( req , status ) ;
2009-06-05 05:39:55 +04:00
goto out ;
2007-12-01 21:16:52 +03:00
}
}
2005-03-31 06:12:09 +04:00
if ( ea_len ) {
if ( ! lp_ea_support ( SNUM ( conn ) ) ) {
2007-12-01 21:03:25 +03:00
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 ) ;
2009-06-05 05:39:55 +04:00
goto out ;
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 ) {
2007-12-01 21:03:25 +03:00
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 ) ;
2009-06-05 05:39:55 +04:00
goto out ;
2005-03-31 06:12:09 +04:00
}
2007-12-01 17:05:18 +03:00
/* We have already checked that ea_len <= data_count here. */
ea_list = read_nttrans_ea_list ( talloc_tos ( ) , data + sd_len ,
ea_len ) ;
if ( ea_list = = NULL ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2009-06-05 05:39:55 +04:00
goto out ;
2007-12-01 17:05:18 +03:00
}
2013-07-10 02:54:39 +04:00
2016-03-19 07:58:20 +03:00
if ( ! req - > posix_pathnames & &
2016-03-15 21:43:32 +03:00
ea_list_has_invalid_name ( ea_list ) ) {
2013-07-10 02:54:39 +04:00
/* Realloc the size of parameters and data we will return */
if ( flags & EXTENDED_RESPONSE_REQUIRED ) {
/* Extended response is 32 more byyes. */
param_len = 101 ;
} else {
param_len = 69 ;
}
params = nttrans_realloc ( ppparams , param_len ) ;
if ( params = = NULL ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
goto out ;
}
memset ( params , ' \0 ' , param_len ) ;
send_nt_replies ( conn , req , STATUS_INVALID_EA_NAME ,
params , param_len , NULL , 0 ) ;
goto out ;
}
2005-03-31 04:36:22 +04:00
}
2009-06-17 04:23:54 +04:00
oplock_request = ( flags & REQUEST_OPLOCK ) ? EXCLUSIVE_OPLOCK : 0 ;
if ( oplock_request ) {
oplock_request | = ( flags & REQUEST_BATCH_OPLOCK )
? BATCH_OPLOCK : 0 ;
}
2009-11-24 02:01:34 +03:00
/*
* Bug # 6898 - clients using Windows opens should
* never be able to set this attribute into the
* VFS .
*/
file_attributes & = ~ FILE_FLAG_POSIX_SEMANTICS ;
2008-10-21 04:43:45 +04:00
status = SMB_VFS_CREATE_FILE (
conn , /* conn */
req , /* req */
root_dir_fid , /* root_dir_fid */
2009-06-12 23:54:11 +04:00
smb_fname , /* fname */
2008-10-21 04:43:45 +04:00
access_mask , /* access_mask */
share_access , /* share_access */
create_disposition , /* create_disposition*/
create_options , /* create_options */
file_attributes , /* file_attributes */
oplock_request , /* oplock_request */
2013-08-21 17:56:14 +04:00
NULL , /* lease */
2008-10-21 04:43:45 +04:00
allocation_size , /* allocation_size */
2010-03-06 02:10:30 +03:00
0 , /* private_flags */
2008-10-21 04:43:45 +04:00
sd , /* sd */
ea_list , /* ea_list */
& fsp , /* result */
2014-11-26 16:12:51 +03:00
& info , /* pinfo */
NULL , NULL ) ; /* create context */
2007-08-16 21:42:34 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2014-09-16 08:55:39 +04:00
if ( open_was_deferred ( req - > xconn , req - > mid ) ) {
2007-12-02 00:36:17 +03:00
/* We have re-scheduled this call, no error. */
2007-08-13 23:03:52 +04:00
return ;
2005-03-30 06:24:47 +04:00
}
2007-11-25 20:26:52 +03:00
reply_openerror ( req , status ) ;
2009-06-05 05:39:55 +04:00
goto out ;
2007-09-12 03:57:59 +04:00
}
2009-08-11 02:07:53 +04:00
/* Ensure we're pointing at the correct stat struct. */
TALLOC_FREE ( smb_fname ) ;
smb_fname = fsp - > fsp_name ;
2007-12-07 14:57:11 +03: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 .
*/
if ( oplock_request & &
( lp_fake_oplocks ( SNUM ( conn ) )
| | EXCLUSIVE_OPLOCK_TYPE ( fsp - > oplock_type ) ) ) {
/*
* Exclusive oplock granted
*/
if ( flags & REQUEST_BATCH_OPLOCK ) {
oplock_granted = BATCH_OPLOCK_RETURN ;
} else {
oplock_granted = EXCLUSIVE_OPLOCK_RETURN ;
}
} else if ( fsp - > oplock_type = = LEVEL_II_OPLOCK ) {
oplock_granted = LEVEL_II_OPLOCK_RETURN ;
} else {
oplock_granted = NO_OPLOCK_RETURN ;
}
2009-06-05 05:39:55 +04:00
file_len = smb_fname - > st . st_ex_size ;
2007-12-02 16:37:44 +03:00
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 ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
2009-06-05 05:39:55 +04:00
goto out ;
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 ;
2007-12-02 00:36:17 +03:00
SCVAL ( p , 0 , oplock_granted ) ;
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 ;
2007-12-02 00:36:17 +03: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
2009-11-18 01:55:02 +03:00
fattr = dos_mode ( conn , smb_fname ) ;
if ( fattr = = 0 ) {
fattr = FILE_ATTRIBUTE_NORMAL ;
}
2002-07-15 14:35:28 +04:00
/* Create time. */
2009-08-13 00:00:54 +04:00
create_timespec = get_create_timespec ( conn , fsp , smb_fname ) ;
2009-06-05 05:39:55 +04:00
a_timespec = smb_fname - > st . st_ex_atime ;
m_timespec = smb_fname - > st . st_ex_mtime ;
2009-08-13 00:00:54 +04:00
c_timespec = get_change_timespec ( conn , fsp , smb_fname ) ;
1998-07-09 04:41:32 +04:00
2002-07-15 14:35:28 +04:00
if ( lp_dos_filetime_resolution ( SNUM ( conn ) ) ) {
2009-08-11 02:07:53 +04:00
dos_filetime_timespec ( & create_timespec ) ;
2006-08-24 20:44:00 +04:00
dos_filetime_timespec ( & a_timespec ) ;
dos_filetime_timespec ( & m_timespec ) ;
2009-08-11 02:07:53 +04:00
dos_filetime_timespec ( & c_timespec ) ;
2002-07-15 14:35:28 +04:00
}
2009-08-25 07:57:37 +04:00
put_long_date_timespec ( conn - > ts_res , p , create_timespec ) ; /* create time. */
2002-07-15 14:35:28 +04:00
p + = 8 ;
2009-08-25 07:57:37 +04:00
put_long_date_timespec ( conn - > ts_res , p , a_timespec ) ; /* access time */
2002-07-15 14:35:28 +04:00
p + = 8 ;
2009-08-25 07:57:37 +04:00
put_long_date_timespec ( conn - > ts_res , p , m_timespec ) ; /* write time */
2002-07-15 14:35:28 +04:00
p + = 8 ;
2009-08-25 07:57:37 +04:00
put_long_date_timespec ( conn - > ts_res , p , c_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 ;
2009-06-05 05:39:55 +04:00
SOFF_T ( p , 0 , SMB_VFS_GET_ALLOC_SIZE ( conn , fsp , & smb_fname - > st ) ) ;
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 ) {
2010-03-31 03:54:43 +04:00
uint16_t file_status = ( NO_EAS | NO_SUBSTREAMS | NO_REPARSETAG ) ;
2011-10-14 02:41:53 +04:00
unsigned int num_streams = 0 ;
2010-03-31 03:54:43 +04:00
struct stream_struct * streams = NULL ;
2017-03-02 09:39:56 +03:00
if ( lp_ea_support ( SNUM ( conn ) ) ) {
size_t num_names = 0 ;
/* Do we have any EA's ? */
status = get_ea_names_from_file (
ctx , conn , fsp , smb_fname , NULL , & num_names ) ;
if ( NT_STATUS_IS_OK ( status ) & & num_names ) {
file_status & = ~ NO_EAS ;
}
2010-03-31 03:54:43 +04:00
}
2017-03-02 09:39:56 +03:00
2016-03-05 01:16:13 +03:00
status = vfs_streaminfo ( conn , NULL , smb_fname , ctx ,
2010-03-31 03:54:43 +04:00
& num_streams , & streams ) ;
/* There is always one stream, ::$DATA. */
if ( NT_STATUS_IS_OK ( status ) & & num_streams > 1 ) {
file_status & = ~ NO_SUBSTREAMS ;
}
TALLOC_FREE ( streams ) ;
SSVAL ( p , 2 , file_status ) ;
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 ) {
2015-05-01 05:22:21 +03:00
uint32_t perms = 0 ;
2007-06-05 02:29:23 +04:00
p + = 25 ;
2009-06-05 05:39:55 +04:00
if ( fsp - > is_directory | |
2012-09-14 01:36:57 +04:00
fsp - > can_write | |
2009-06-26 05:19:09 +04:00
can_write_to_file ( conn , smb_fname ) ) {
2007-04-08 08:54:44 +04:00
perms = FILE_GENERIC_ALL ;
} else {
perms = FILE_GENERIC_READ | FILE_EXECUTE ;
}
SIVAL ( p , 0 , perms ) ;
}
2009-07-08 23:24:03 +04:00
DEBUG ( 5 , ( " call_nt_transact_create: open name = %s \n " ,
smb_fname_str_dbg ( smb_fname ) ) ) ;
2002-07-15 14:35:28 +04:00
/* Send the required number of replies */
2008-01-04 23:56:23 +03:00
send_nt_replies ( conn , req , NT_STATUS_OK , params , param_len , * ppdata , 0 ) ;
2009-06-05 05:39:55 +04:00
out :
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
2008-01-05 02:37:24 +03:00
void reply_ntcancel ( struct smb_request * req )
1998-07-08 05:42:05 +04:00
{
2014-06-11 16:26:57 +04:00
struct smbXsrv_connection * xconn = req - > xconn ;
2014-06-11 16:26:57 +04:00
struct smbd_server_connection * sconn = req - > sconn ;
2014-05-21 16:44:01 +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 ) ;
2014-05-21 16:44:01 +04:00
srv_cancel_sign_response ( xconn ) ;
2014-06-11 16:26:57 +04:00
remove_pending_change_notify_requests_by_mid ( sconn , req - > mid ) ;
remove_pending_lock_requests_by_mid_smb1 ( sconn , req - > mid ) ;
2007-09-12 03:57:59 +04:00
2010-04-13 08:40:28 +04:00
DEBUG ( 3 , ( " reply_ntcancel: cancel called on mid = %llu. \n " ,
( unsigned long long ) 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 ,
2009-06-19 02:07:14 +04:00
struct smb_filename * smb_fname_src ,
struct smb_filename * smb_fname_dst ,
2015-05-01 05:22:21 +03:00
uint32_t attrs )
2004-06-26 03:48:23 +04:00
{
files_struct * fsp1 , * fsp2 ;
2015-05-01 05:22:21 +03:00
uint32_t fattr ;
2005-07-08 08:51:27 +04:00
int info ;
2012-04-05 08:53:08 +04:00
off_t ret = - 1 ;
2004-06-26 03:48:23 +04:00
NTSTATUS status = NT_STATUS_OK ;
2008-12-24 15:44:44 +03:00
char * parent ;
2004-06-26 03:48:23 +04:00
2007-01-17 05:09:37 +03:00
if ( ! CAN_WRITE ( conn ) ) {
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
status = NT_STATUS_MEDIA_WRITE_PROTECTED ;
goto out ;
2007-01-17 05:09:37 +03:00
}
2004-06-26 03:48:23 +04:00
2009-06-12 23:54:11 +04:00
/* Source must already exist. */
if ( ! VALID_STAT ( smb_fname_src - > st ) ) {
status = NT_STATUS_OBJECT_NAME_NOT_FOUND ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2004-06-26 03:48:23 +04:00
}
/* Ensure attributes match. */
2009-07-08 23:24:03 +04:00
fattr = dos_mode ( conn , smb_fname_src ) ;
2011-04-29 07:23:14 +04:00
if ( ( fattr & ~ attrs ) & ( FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM ) ) {
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
status = NT_STATUS_NO_SUCH_FILE ;
goto out ;
2005-07-08 08:51:27 +04:00
}
2004-06-26 03:48:23 +04:00
2009-06-12 23:54:11 +04:00
/* Disallow if dst file already exists. */
if ( VALID_STAT ( smb_fname_dst - > st ) ) {
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
status = NT_STATUS_OBJECT_NAME_COLLISION ;
goto out ;
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
}
2004-06-26 03:48:23 +04:00
/* No links from a directory. */
2009-06-12 23:54:11 +04:00
if ( S_ISDIR ( smb_fname_src - > st . st_ex_mode ) ) {
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
status = NT_STATUS_FILE_IS_A_DIRECTORY ;
goto out ;
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 " ,
2009-06-12 23:54:11 +04:00
smb_fname_str_dbg ( smb_fname_src ) ,
smb_fname_str_dbg ( smb_fname_dst ) ) ) ;
2004-06-26 03:48:23 +04:00
2008-11-21 05:55:24 +03:00
status = SMB_VFS_CREATE_FILE (
conn , /* conn */
req , /* req */
0 , /* root_dir_fid */
2009-06-12 23:54:11 +04:00
smb_fname_src , /* fname */
2010-11-24 02:59:33 +03:00
FILE_READ_DATA | FILE_READ_ATTRIBUTES |
FILE_READ_EA , /* access_mask */
2008-11-21 05:55:24 +03:00
( FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
FILE_SHARE_DELETE ) ,
FILE_OPEN , /* create_disposition*/
0 , /* create_options */
FILE_ATTRIBUTE_NORMAL , /* file_attributes */
NO_OPLOCK , /* oplock_request */
2013-08-21 17:56:14 +04:00
NULL , /* lease */
2008-11-21 05:55:24 +03:00
0 , /* allocation_size */
2010-03-06 02:10:30 +03:00
0 , /* private_flags */
2008-11-21 05:55:24 +03:00
NULL , /* sd */
NULL , /* ea_list */
& fsp1 , /* result */
2014-11-26 16:12:51 +03:00
& info , /* pinfo */
NULL , NULL ) ; /* create context */
2004-06-26 03:48:23 +04:00
2006-07-11 22:01:26 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2004-06-26 03:48:23 +04:00
}
2008-11-21 05:55:24 +03:00
status = SMB_VFS_CREATE_FILE (
conn , /* conn */
req , /* req */
0 , /* root_dir_fid */
2009-06-12 23:54:11 +04:00
smb_fname_dst , /* fname */
2010-11-24 02:59:33 +03:00
FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES |
FILE_WRITE_EA , /* access_mask */
2008-11-21 05:55:24 +03:00
( FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
FILE_SHARE_DELETE ) ,
FILE_CREATE , /* create_disposition*/
0 , /* create_options */
fattr , /* file_attributes */
NO_OPLOCK , /* oplock_request */
2013-08-21 17:56:14 +04:00
NULL , /* lease */
2008-11-21 05:55:24 +03:00
0 , /* allocation_size */
2010-03-06 02:10:30 +03:00
0 , /* private_flags */
2008-11-21 05:55:24 +03:00
NULL , /* sd */
NULL , /* ea_list */
& fsp2 , /* result */
2014-11-26 16:12:51 +03:00
& info , /* pinfo */
NULL , NULL ) ; /* create context */
2004-06-26 03:48:23 +04:00
2006-07-11 22:01:26 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2008-10-09 18:27:49 +04:00
close_file ( NULL , fsp1 , ERROR_CLOSE ) ;
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
goto out ;
2004-06-26 03:48:23 +04:00
}
2009-06-12 23:54:11 +04:00
if ( smb_fname_src - > st . st_ex_size ) {
ret = vfs_transfer_file ( fsp1 , fsp2 , smb_fname_src - > st . st_ex_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 .
*/
2008-10-09 18:27:49 +04:00
close_file ( NULL , fsp1 , NORMAL_CLOSE ) ;
2004-06-26 03:48:23 +04:00
/* Ensure the modtime is set correctly on the destination file. */
2009-11-06 09:58:12 +03:00
set_close_write_time ( fsp2 , smb_fname_src - > st . st_ex_mtime ) ;
2004-06-26 03:48:23 +04:00
2008-10-09 18:27:49 +04:00
status = close_file ( NULL , fsp2 , NORMAL_CLOSE ) ;
2004-06-26 03:48:23 +04:00
2011-04-29 06:00:57 +04:00
/* Grrr. We have to do this as open_file_ntcreate adds FILE_ATTRIBUTE_ARCHIVE when it
2006-05-30 03:54:53 +04:00
creates the file . This isn ' t the correct thing to do in the copy
case . JRA */
2009-07-07 01:36:16 +04:00
if ( ! parent_dirname ( talloc_tos ( ) , smb_fname_dst - > base_name , & parent ,
NULL ) ) {
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
status = NT_STATUS_NO_MEMORY ;
goto out ;
2008-12-24 15:44:44 +03:00
}
2009-07-07 01:36:16 +04:00
file_set_dosmode ( conn , smb_fname_dst , fattr , parent , false ) ;
2008-12-24 15:44:44 +03:00
TALLOC_FREE ( parent ) ;
2004-06-26 03:48:23 +04:00
2012-04-05 08:53:08 +04:00
if ( ret < ( off_t ) smb_fname_src - > st . st_ex_size ) {
s3: Change unix_convert (and its callers) to use struct smb_filename
This is the first of a series of patches that change path based
operations to operate on a struct smb_filename instead of a char *.
This same concept already exists in source4.
My goals for this series of patches are to eventually:
1) Solve the stream vs. posix filename that contains a colon ambiguity
that currently exists.
2) Make unix_convert the only function that parses the stream name.
3) Clean up the unix_convert API.
4) Change all path based vfs operation to take a struct smb_filename.
5) Make is_ntfs_stream_name() a constant operation that can simply
check the state of struct smb_filename rather than re-parse the
filename.
6) Eliminate the need for split_ntfs_stream_name() to exist.
My strategy is to start from the inside at unix_convert() and work my
way out through the vfs layer, call by call. This first patch does
just that, by changing unix_convert and all of its callers to operate
on struct smb_filename. Since this is such a large change, I plan on
pushing the patches in phases, where each phase keeps full
compatibility and passes make test.
The API of unix_convert has been simplified from:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
bool allow_wcard_last_component,
char **pp_conv_path,
char **pp_saved_last_component,
SMB_STRUCT_STAT *pst)
to:
NTSTATUS unix_convert(TALLOC_CTX *ctx,
connection_struct *conn,
const char *orig_path,
struct smb_filename *smb_fname,
uint32_t ucf_flags)
Currently the smb_filename struct looks like:
struct smb_filename {
char *base_name;
char *stream_name;
char *original_lcomp;
SMB_STRUCT_STAT st;
};
One key point here is the decision to break up the base_name and
stream_name. I have introduced a helper function called
get_full_smb_filename() that takes an smb_filename struct and
allocates the full_name. I changed the callers of unix_convert() to
subsequently call get_full_smb_filename() for the time being, but I
plan to eventually eliminate get_full_smb_filename().
2009-04-08 00:39:57 +04:00
status = NT_STATUS_DISK_FULL ;
goto out ;
}
out :
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 " ,
2009-06-12 23:54:11 +04:00
nt_errstr ( status ) , smb_fname_str_dbg ( smb_fname_src ) ,
smb_fname_str_dbg ( smb_fname_dst ) ) ) ;
2004-06-26 03:48:23 +04:00
}
2009-06-12 23:54:11 +04:00
2004-06-26 03:48:23 +04:00
return status ;
}
2004-02-24 03:06:08 +03:00
/****************************************************************************
Reply to a NT rename request .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-05 02:37:24 +03:00
void reply_ntrename ( struct smb_request * req )
2004-02-24 03:06:08 +03:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2009-06-19 00:13:38 +04:00
struct smb_filename * smb_fname_old = NULL ;
struct smb_filename * smb_fname_new = NULL ;
2007-09-11 22:31:29 +04:00
char * oldname = NULL ;
char * newname = NULL ;
2008-11-01 19:35:48 +03:00
const char * p ;
2004-02-24 03:06:08 +03:00
NTSTATUS status ;
2007-10-19 04:40:25 +04:00
bool src_has_wcard = False ;
bool dest_has_wcard = False ;
2015-05-01 05:22:21 +03:00
uint32_t attrs ;
2017-05-18 22:08:00 +03:00
uint32_t ucf_flags_src = ucf_flags_from_smb_request ( req ) ;
uint32_t ucf_flags_dst = ucf_flags_from_smb_request ( req ) ;
2015-05-01 05:22:21 +03:00
uint16_t rename_type ;
2007-09-11 22:31:29 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
2011-01-21 03:27:56 +03:00
bool stream_rename = false ;
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 ) ;
2009-07-21 21:19:00 +04:00
goto out ;
2007-08-15 00:02:11 +04:00
}
2008-11-02 14:20:47 +03:00
attrs = SVAL ( req - > vwv + 0 , 0 ) ;
rename_type = SVAL ( req - > vwv + 1 , 0 ) ;
2007-07-05 20:26:27 +04:00
2008-11-01 19:35:48 +03:00
p = ( const char * ) req - > buf + 1 ;
2008-11-02 02:59:03 +03:00
p + = srvstr_get_path_req_wcard ( ctx , req , & oldname , p , STR_TERMINATE ,
& status , & 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 ) ;
2009-07-21 21:19:00 +04:00
goto out ;
2004-02-24 03:06:08 +03:00
}
2004-03-03 23:55:59 +03:00
2015-12-23 00:44:10 +03:00
if ( ! req - > posix_pathnames & & ms_has_wild ( oldname ) ) {
2007-08-15 00:02:11 +04:00
reply_nterror ( req , NT_STATUS_OBJECT_PATH_SYNTAX_BAD ) ;
2009-07-21 21:19:00 +04:00
goto out ;
2004-06-26 02:37:50 +04:00
}
2004-02-24 03:06:08 +03:00
p + + ;
2008-11-02 02:59:03 +03:00
p + = srvstr_get_path_req_wcard ( ctx , req , & newname , p , STR_TERMINATE ,
& status , & 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 ) ;
2009-07-21 21:19:00 +04:00
goto out ;
2004-02-24 03:06:08 +03:00
}
2007-09-11 22:31:29 +04:00
2015-12-23 00:44:10 +03:00
if ( ! req - > posix_pathnames ) {
2011-01-21 03:27:56 +03:00
/* The newname must begin with a ':' if the
oldname contains a ' : ' . */
if ( strchr_m ( oldname , ' : ' ) ) {
if ( newname [ 0 ] ! = ' : ' ) {
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
goto out ;
}
stream_rename = true ;
}
2007-03-08 01:12:58 +03:00
}
2007-03-12 20:55:24 +03:00
2009-07-24 22:39:56 +04:00
/*
* If this is a rename operation , allow wildcards and save the
* destination ' s last component .
*/
if ( rename_type = = RENAME_FLAG_RENAME ) {
2017-05-18 22:08:57 +03:00
ucf_flags_src | = UCF_COND_ALLOW_WCARD_LCOMP ;
ucf_flags_dst | = UCF_COND_ALLOW_WCARD_LCOMP | UCF_SAVE_LCOMP ;
2009-07-24 22:39:56 +04:00
}
2009-07-21 21:19:00 +04:00
/* rename_internals() calls unix_convert(), so don't call it here. */
2009-07-24 22:39:56 +04:00
status = filename_convert ( ctx , conn ,
oldname ,
ucf_flags_src ,
NULL ,
& smb_fname_old ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( NT_STATUS_EQUAL ( status ,
NT_STATUS_PATH_NOT_COVERED ) ) {
reply_botherror ( req ,
NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
2009-07-21 21:19:00 +04:00
goto out ;
2007-03-12 20:55:24 +03:00
}
2009-07-24 22:39:56 +04:00
reply_nterror ( req , status ) ;
goto out ;
}
2007-03-08 01:12:58 +03:00
2009-07-24 22:39:56 +04:00
status = filename_convert ( ctx , conn ,
newname ,
ucf_flags_dst ,
& dest_has_wcard ,
& smb_fname_new ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( NT_STATUS_EQUAL ( status ,
NT_STATUS_PATH_NOT_COVERED ) ) {
reply_botherror ( req ,
NT_STATUS_PATH_NOT_COVERED ,
ERRSRV , ERRbadpath ) ;
2009-07-21 21:19:00 +04:00
goto out ;
}
2009-07-24 22:39:56 +04:00
reply_nterror ( req , status ) ;
goto out ;
2009-07-21 21:19:00 +04:00
}
2007-09-11 22:31:29 +04:00
2011-01-21 03:27:56 +03:00
if ( stream_rename ) {
/* smb_fname_new must be the same as smb_fname_old. */
TALLOC_FREE ( smb_fname_new - > base_name ) ;
smb_fname_new - > base_name = talloc_strdup ( smb_fname_new ,
smb_fname_old - > base_name ) ;
if ( ! smb_fname_new - > base_name ) {
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
goto out ;
}
}
2009-07-24 22:39:56 +04:00
DEBUG ( 3 , ( " reply_ntrename: %s -> %s \n " ,
smb_fname_str_dbg ( smb_fname_old ) ,
smb_fname_str_dbg ( smb_fname_new ) ) ) ;
2004-06-26 03:48:23 +04:00
switch ( rename_type ) {
case RENAME_FLAG_RENAME :
2009-07-24 22:39:56 +04:00
status = rename_internals ( ctx , conn , req ,
smb_fname_old , smb_fname_new ,
attrs , False , src_has_wcard ,
dest_has_wcard ,
DELETE_ACCESS ) ;
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 {
2009-07-24 22:39:56 +04:00
status = hardlink_internals ( ctx , conn ,
2010-05-19 05:34:54 +04:00
req ,
false ,
2009-07-24 22:39:56 +04:00
smb_fname_old ,
smb_fname_new ) ;
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 {
2009-06-19 02:07:14 +04:00
status = copy_internals ( ctx , conn , req ,
smb_fname_old ,
smb_fname_new ,
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 ) ) {
2014-09-16 08:55:39 +04:00
if ( open_was_deferred ( req - > xconn , req - > mid ) ) {
2004-06-26 02:37:50 +04:00
/* We have re-scheduled this call. */
2009-07-21 21:19:00 +04:00
goto out ;
2004-06-26 02:37:50 +04:00
}
2007-08-15 00:02:11 +04:00
reply_nterror ( req , status ) ;
2009-07-21 21:19:00 +04:00
goto out ;
2004-02-24 03:06:08 +03:00
}
2007-08-15 00:02:11 +04:00
reply_outbuf ( req , 0 , 0 ) ;
2009-07-21 21:19:00 +04:00
out :
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
2009-06-30 17:01:00 +04:00
static void smbd_smb1_notify_reply ( struct smb_request * req ,
NTSTATUS error_code ,
uint8_t * buf , size_t len )
{
send_nt_replies ( req - > conn , req , error_code , ( char * ) buf , len , NULL , 0 ) ;
}
2007-08-14 11:39:11 +04:00
static void call_nt_transact_notify_change ( connection_struct * conn ,
struct smb_request * req ,
2015-05-01 05:22:21 +03:00
uint16_t * * ppsetup ,
uint32_t setup_count ,
2007-08-14 11:39:11 +04:00
char * * ppparams ,
2015-05-01 05:22:21 +03:00
uint32_t parameter_count ,
char * * ppdata , uint32_t data_count ,
uint32_t max_data_count ,
uint32_t max_param_count )
2000-06-12 09:32:28 +04:00
{
2015-05-01 05:22:21 +03:00
uint16_t * setup = * ppsetup ;
2002-04-09 22:10:09 +04:00
files_struct * fsp ;
2015-05-01 05:22:21 +03:00
uint32_t filter ;
2007-01-17 19:23:45 +03:00
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 ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2007-08-14 11:39:11 +04:00
return ;
2005-07-08 08:51:27 +04:00
}
2003-09-17 23:36:38 +04:00
2008-10-09 17:25:17 +04:00
fsp = file_fsp ( req , 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 ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_INVALID_HANDLE ) ;
2007-08-14 11:39:11 +04:00
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 " ,
2009-07-11 01:50:37 +04:00
fsp_str_dbg ( fsp ) , filter_string , recursive ) ) ;
2007-01-31 17:42:56 +03:00
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
}
2012-06-05 11:37:39 +04:00
if ( change_notify_fsp_has_changes ( fsp ) ) {
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 .
*/
2010-06-12 15:17:51 +04:00
change_notify_reply ( req ,
2009-06-30 00:17:17 +04:00
NT_STATUS_OK ,
max_param_count ,
2009-06-30 17:01:00 +04:00
fsp - > notify ,
smbd_smb1_notify_reply ) ;
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
*/
2008-01-04 23:56:23 +03:00
status = change_notify_add_request ( req ,
max_param_count ,
filter ,
2009-06-30 17:01:00 +04:00
recursive , fsp ,
smbd_smb1_notify_reply ) ;
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 ,
2015-05-01 05:22:21 +03:00
uint16_t * * ppsetup , uint32_t setup_count ,
char * * ppparams , uint32_t parameter_count ,
char * * ppdata , uint32_t data_count ,
uint32_t 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 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 ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2007-08-14 10:52:30 +04:00
return ;
2005-07-08 08:51:27 +04:00
}
2003-05-30 03:49:31 +04:00
2008-10-09 17:25:17 +04:00
fsp = file_fsp ( req , SVAL ( params , 0 ) ) ;
2008-06-19 18:31:59 +04:00
if ( ! check_fsp ( conn , req , fsp ) ) {
2007-08-14 10:52:30 +04:00
return ;
}
2015-12-23 00:44:10 +03:00
if ( req - > posix_pathnames ) {
2015-12-23 00:13:44 +03:00
srvstr_get_path_wcard_posix ( ctx ,
params ,
req - > flags2 ,
& new_name ,
params + 4 ,
parameter_count - 4 ,
STR_TERMINATE ,
& status ,
& dest_has_wcard ) ;
} else {
srvstr_get_path_wcard ( ctx ,
params ,
req - > flags2 ,
& new_name ,
params + 4 ,
parameter_count - 4 ,
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
2001-09-04 11:13:01 +04:00
/*
2008-04-01 14:29:12 +04:00
* W2K3 ignores this request as the RAW - RENAME test
* demonstrates , so we do .
2001-09-04 11:13:01 +04:00
*/
2008-01-04 23:56:23 +03:00
send_nt_replies ( conn , req , NT_STATUS_OK , NULL , 0 , NULL , 0 ) ;
2007-09-12 03:57:59 +04:00
2008-04-01 14:29:12 +04:00
DEBUG ( 3 , ( " nt transact rename from = %s, to = %s ignored! \n " ,
2009-07-11 01:50:37 +04:00
fsp_str_dbg ( fsp ) , 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 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2010-05-18 12:29:34 +04:00
static NTSTATUS get_null_nt_acl ( TALLOC_CTX * mem_ctx , struct security_descriptor * * ppsd )
2001-10-13 02:00:38 +04:00
{
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 " ) ) ;
2007-10-13 23:06:49 +04:00
return NT_STATUS_NO_MEMORY ;
2001-10-13 02:00:38 +04:00
}
2007-10-13 23:06:49 +04:00
return NT_STATUS_OK ;
2001-10-13 02:00:38 +04:00
}
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 .
2014-09-08 14:54:32 +04:00
Callable from SMB1 and SMB2 .
2010-04-27 07:11:59 +04:00
If it returns NT_STATUS_BUFFER_TOO_SMALL , pdata_size is initialized with
the required size .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
NTSTATUS smbd_do_query_security_desc ( connection_struct * conn ,
TALLOC_CTX * mem_ctx ,
files_struct * fsp ,
uint32_t security_info_wanted ,
uint32_t max_data_count ,
uint8_t * * ppmarshalled_sd ,
size_t * psd_size )
{
NTSTATUS status ;
2010-05-18 12:29:34 +04:00
struct security_descriptor * psd = NULL ;
2012-10-10 04:50:27 +04:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
2010-04-27 07:11:59 +04:00
/*
* Get the permissions to return .
*/
2010-10-21 03:31:18 +04:00
if ( ( security_info_wanted & SECINFO_SACL ) & &
! ( fsp - > access_mask & SEC_FLAG_SYSTEM_SECURITY ) ) {
2012-03-28 07:32:11 +04:00
DEBUG ( 10 , ( " Access to SACL denied. \n " ) ) ;
2012-10-11 15:29:43 +04:00
TALLOC_FREE ( frame ) ;
2010-10-21 03:31:18 +04:00
return NT_STATUS_ACCESS_DENIED ;
}
if ( ( security_info_wanted & ( SECINFO_DACL | SECINFO_OWNER | SECINFO_GROUP ) ) & &
! ( fsp - > access_mask & SEC_STD_READ_CONTROL ) ) {
2012-03-28 07:32:11 +04:00
DEBUG ( 10 , ( " Access to DACL, OWNER, or GROUP denied. \n " ) ) ;
2012-10-11 15:29:43 +04:00
TALLOC_FREE ( frame ) ;
2010-10-21 03:31:18 +04:00
return NT_STATUS_ACCESS_DENIED ;
}
2016-01-05 21:38:28 +03:00
if ( S_ISLNK ( fsp - > fsp_name - > st . st_ex_mode ) ) {
DEBUG ( 10 , ( " ACL get on symlink %s denied. \n " ,
fsp_str_dbg ( fsp ) ) ) ;
TALLOC_FREE ( frame ) ;
return NT_STATUS_ACCESS_DENIED ;
}
2011-09-22 00:33:38 +04:00
if ( security_info_wanted & ( SECINFO_DACL | SECINFO_OWNER |
SECINFO_GROUP | SECINFO_SACL ) ) {
/* Don't return SECINFO_LABEL if anything else was
requested . See bug # 8458. */
security_info_wanted & = ~ SECINFO_LABEL ;
}
2010-04-27 07:11:59 +04:00
if ( ! lp_nt_acl_support ( SNUM ( conn ) ) ) {
2012-10-10 04:50:27 +04:00
status = get_null_nt_acl ( frame , & psd ) ;
2011-09-22 00:33:38 +04:00
} else if ( security_info_wanted & SECINFO_LABEL ) {
/* Like W2K3 return a null object. */
2012-10-10 04:50:27 +04:00
status = get_null_nt_acl ( frame , & psd ) ;
2010-04-27 07:11:59 +04:00
} else {
status = SMB_VFS_FGET_NT_ACL (
2012-10-10 04:50:27 +04:00
fsp , security_info_wanted , frame , & psd ) ;
2010-04-27 07:11:59 +04:00
}
if ( ! NT_STATUS_IS_OK ( status ) ) {
2012-10-11 15:29:43 +04:00
TALLOC_FREE ( frame ) ;
2010-04-27 07:11:59 +04:00
return status ;
}
2010-10-12 04:10:28 +04:00
if ( ! ( security_info_wanted & SECINFO_OWNER ) ) {
psd - > owner_sid = NULL ;
}
if ( ! ( security_info_wanted & SECINFO_GROUP ) ) {
psd - > group_sid = NULL ;
}
if ( ! ( security_info_wanted & SECINFO_DACL ) ) {
2011-11-30 04:31:18 +04:00
psd - > type & = ~ SEC_DESC_DACL_PRESENT ;
2010-10-12 04:10:28 +04:00
psd - > dacl = NULL ;
}
if ( ! ( security_info_wanted & SECINFO_SACL ) ) {
2011-11-30 04:31:18 +04:00
psd - > type & = ~ SEC_DESC_SACL_PRESENT ;
2010-10-12 04:10:28 +04:00
psd - > sacl = NULL ;
}
2010-04-27 07:11:59 +04:00
/* If the SACL/DACL is NULL, but was requested, we mark that it is
* present in the reply to match Windows behavior */
if ( psd - > sacl = = NULL & &
2010-06-03 01:29:16 +04:00
security_info_wanted & SECINFO_SACL )
2010-04-27 07:11:59 +04:00
psd - > type | = SEC_DESC_SACL_PRESENT ;
if ( psd - > dacl = = NULL & &
2010-06-03 01:35:44 +04:00
security_info_wanted & SECINFO_DACL )
2010-04-27 07:11:59 +04:00
psd - > type | = SEC_DESC_DACL_PRESENT ;
2011-09-22 00:33:38 +04:00
if ( security_info_wanted & SECINFO_LABEL ) {
/* Like W2K3 return a null object. */
psd - > owner_sid = NULL ;
psd - > group_sid = NULL ;
psd - > dacl = NULL ;
psd - > sacl = NULL ;
psd - > type & = ~ ( SEC_DESC_DACL_PRESENT | SEC_DESC_SACL_PRESENT ) ;
}
2010-05-10 02:42:06 +04:00
* psd_size = ndr_size_security_descriptor ( psd , 0 ) ;
2010-04-27 07:11:59 +04:00
DEBUG ( 3 , ( " smbd_do_query_security_desc: sd_size = %lu. \n " ,
( unsigned long ) * psd_size ) ) ;
if ( DEBUGLEVEL > = 10 ) {
DEBUG ( 10 , ( " smbd_do_query_security_desc for file %s \n " ,
fsp_str_dbg ( fsp ) ) ) ;
NDR_PRINT_DEBUG ( security_descriptor , psd ) ;
}
if ( max_data_count < * psd_size ) {
2012-10-10 04:50:27 +04:00
TALLOC_FREE ( frame ) ;
2010-04-27 07:11:59 +04:00
return NT_STATUS_BUFFER_TOO_SMALL ;
}
status = marshall_sec_desc ( mem_ctx , psd ,
ppmarshalled_sd , psd_size ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2012-10-10 04:50:27 +04:00
TALLOC_FREE ( frame ) ;
2010-04-27 07:11:59 +04:00
return status ;
}
2012-10-10 04:50:27 +04:00
TALLOC_FREE ( frame ) ;
2010-04-27 07:11:59 +04:00
return NT_STATUS_OK ;
}
/****************************************************************************
SMB1 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 ,
2015-05-01 05:22:21 +03:00
uint16_t * * ppsetup ,
uint32_t setup_count ,
2007-08-14 00:16:33 +04:00
char * * ppparams ,
2015-05-01 05:22:21 +03:00
uint32_t parameter_count ,
2007-08-14 00:16:33 +04:00
char * * ppdata ,
2015-05-01 05:22:21 +03:00
uint32_t data_count ,
uint32_t 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 ;
2010-04-27 07:11:59 +04:00
size_t sd_size = 0 ;
2015-05-01 05:22:21 +03:00
uint32_t security_info_wanted ;
2003-05-30 03:49:31 +04:00
files_struct * fsp = NULL ;
2007-10-13 23:06:49 +04:00
NTSTATUS status ;
2010-04-27 07:11:59 +04:00
uint8_t * marshalled_sd = NULL ;
1999-12-13 16:27:58 +03:00
2005-07-08 08:51:27 +04:00
if ( parameter_count < 8 ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2007-08-14 00:16:33 +04:00
return ;
2005-07-08 08:51:27 +04:00
}
1999-12-13 16:27:58 +03:00
2008-10-09 17:25:17 +04:00
fsp = file_fsp ( req , SVAL ( params , 0 ) ) ;
2005-07-08 08:51:27 +04:00
if ( ! fsp ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_INVALID_HANDLE ) ;
2007-08-14 00:16:33 +04:00
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 ) ;
2009-07-11 01:50:37 +04:00
DEBUG ( 3 , ( " call_nt_transact_query_security_desc: file = %s, "
" info_wanted = 0x%x \n " , fsp_str_dbg ( fsp ) ,
( 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 ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
2007-08-14 00:16:33 +04:00
return ;
2005-07-08 08:51:27 +04:00
}
1999-12-13 16:27:58 +03:00
2002-08-17 19:27:10 +04:00
/*
* Get the permissions to return .
*/
1999-12-13 16:27:58 +03:00
2010-04-27 07:11:59 +04:00
status = smbd_do_query_security_desc ( conn ,
talloc_tos ( ) ,
fsp ,
2014-08-20 15:58:38 +04:00
security_info_wanted &
SMB_SUPPORTED_SECINFO_FLAGS ,
2010-04-27 07:11:59 +04:00
max_data_count ,
& marshalled_sd ,
& sd_size ) ;
if ( NT_STATUS_EQUAL ( status , NT_STATUS_BUFFER_TOO_SMALL ) ) {
SIVAL ( params , 0 , ( uint32_t ) sd_size ) ;
send_nt_replies ( conn , req , NT_STATUS_BUFFER_TOO_SMALL ,
params , 4 , NULL , 0 ) ;
return ;
}
2007-10-13 23:06:49 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
reply_nterror ( req , status ) ;
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
2010-04-27 07:11:59 +04:00
SMB_ASSERT ( sd_size > 0 ) ;
2007-10-13 23:06:49 +04:00
2010-04-27 07:11:59 +04:00
SIVAL ( params , 0 , ( uint32_t ) sd_size ) ;
1999-12-13 16:27:58 +03:00
2007-11-25 20:26:52 +03:00
if ( max_data_count < sd_size ) {
2008-01-04 23:56:23 +03:00
send_nt_replies ( conn , req , NT_STATUS_BUFFER_TOO_SMALL ,
2010-04-27 07:11:59 +04:00
params , 4 , NULL , 0 ) ;
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
/*
2010-04-27 07:11:59 +04:00
* Allocate the data we will return .
2002-08-17 19:27:10 +04:00
*/
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 ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
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
2010-04-27 07:11:59 +04:00
memcpy ( data , marshalled_sd , sd_size ) ;
1999-12-13 16:27:58 +03:00
2008-01-04 23:56:23 +03:00
send_nt_replies ( conn , req , NT_STATUS_OK , params , 4 , data , ( int ) sd_size ) ;
2007-11-25 20:26:52 +03:00
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 ,
2015-05-01 05:22:21 +03:00
uint16_t * * ppsetup ,
uint32_t setup_count ,
2007-08-13 23:59:00 +04:00
char * * ppparams ,
2015-05-01 05:22:21 +03:00
uint32_t parameter_count ,
2007-08-13 23:59:00 +04:00
char * * ppdata ,
2015-05-01 05:22:21 +03:00
uint32_t data_count ,
uint32_t 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 ;
2015-05-01 05:22:21 +03:00
uint32_t security_info_sent = 0 ;
2007-11-25 20:26:52 +03:00
NTSTATUS status ;
1998-11-20 01:37:33 +03:00
2005-07-08 08:51:27 +04:00
if ( parameter_count < 8 ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2007-08-13 23:59:00 +04:00
return ;
2005-07-08 08:51:27 +04:00
}
1999-12-13 16:27:58 +03:00
2008-10-09 17:25:17 +04:00
if ( ( fsp = file_fsp ( req , SVAL ( params , 0 ) ) ) = = NULL ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_INVALID_HANDLE ) ;
2007-08-13 23:59:00 +04:00
return ;
2005-07-08 08:51:27 +04:00
}
1999-12-13 16:27:58 +03:00
2010-09-09 07:54:38 +04:00
if ( ! CAN_WRITE ( fsp - > conn ) ) {
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
return ;
}
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
2009-07-11 01:50:37 +04:00
DEBUG ( 3 , ( " call_nt_transact_set_security_desc: file = %s, sent 0x%x \n " ,
fsp_str_dbg ( fsp ) , ( 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 ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_INVALID_PARAMETER ) ;
2007-08-13 23:59:00 +04:00
return ;
2005-07-08 08:51:27 +04:00
}
2002-07-15 14:35:28 +04:00
2015-05-01 05:22:21 +03:00
status = set_sd_blob ( fsp , ( uint8_t * ) data , data_count ,
2014-08-20 15:58:38 +04:00
security_info_sent & SMB_SUPPORTED_SECINFO_FLAGS ) ;
2007-11-25 20:26:52 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
reply_nterror ( req , status ) ;
2007-08-13 23:59:00 +04:00
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 :
2008-01-04 23:56:23 +03:00
send_nt_replies ( conn , 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 ,
2015-05-01 05:22:21 +03:00
uint16_t * * ppsetup , uint32_t setup_count ,
char * * ppparams , uint32_t parameter_count ,
char * * ppdata , uint32_t data_count ,
uint32_t max_data_count )
1998-07-08 05:42:05 +04:00
{
2011-09-16 22:52:22 +04:00
NTSTATUS status ;
2015-05-01 05:22:21 +03:00
uint32_t function ;
uint16_t fidnum ;
2003-08-08 01:47:46 +04:00
files_struct * fsp ;
2015-05-01 05:22:21 +03:00
uint8_t isFSctl ;
uint8_t compfilter ;
2011-09-16 22:52:22 +04:00
char * out_data = NULL ;
2015-05-01 05:22:21 +03:00
uint32_t out_data_len = 0 ;
2003-05-12 05:20:17 +04:00
char * pdata = * ppdata ;
2011-09-16 22:52:22 +04:00
TALLOC_CTX * ctx = talloc_tos ( ) ;
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 ) ;
2011-09-16 22:52:22 +04:00
DEBUG ( 10 , ( " call_nt_transact_ioctl: function[0x%08X] FID[0x%04X] isFSctl[0x%02X] compfilter[0x%02X] \n " ,
2003-08-08 01:47:46 +04:00
function , fidnum , isFSctl , compfilter ) ) ;
2002-08-17 19:27:10 +04:00
2008-10-09 17:25:17 +04:00
fsp = file_fsp ( req , fidnum ) ;
2010-11-18 19:24:00 +03:00
2011-09-16 22:52:22 +04:00
/*
* We don ' t really implement IOCTLs , especially on files .
*/
if ( ! isFSctl ) {
DEBUG ( 10 , ( " isFSctl: 0x%02X indicates IOCTL, not FSCTL! \n " ,
isFSctl ) ) ;
reply_nterror ( req , NT_STATUS_NOT_SUPPORTED ) ;
2007-08-13 23:58:28 +04:00
return ;
2010-11-18 19:24:00 +03:00
}
2009-02-16 10:45:28 +03:00
2011-09-16 22:52:22 +04:00
/* Has to be for an open file! */
if ( ! check_fsp_open ( conn , req , fsp ) ) {
2007-08-13 23:58:28 +04:00
return ;
2007-04-24 01:07:05 +04:00
}
2011-09-16 22:52:22 +04:00
SMB_PERFCOUNT_SET_IOCTL ( & req - > pcd , function ) ;
2010-04-06 06:33:55 +04:00
2011-09-16 22:52:22 +04:00
/*
* out_data might be allocated by the VFS module , but talloc should be
* used , and should be cleaned up when the request ends .
*/
status = SMB_VFS_FSCTL ( fsp ,
ctx ,
function ,
req - > flags2 ,
( uint8_t * ) pdata ,
data_count ,
( uint8_t * * ) & out_data ,
max_data_count ,
& out_data_len ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
reply_nterror ( req , status ) ;
} else {
send_nt_replies ( conn , req , NT_STATUS_OK , NULL , 0 , out_data , out_data_len ) ;
2002-08-17 19:27:10 +04:00
}
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
2017-05-26 18:01:53 +03:00
static enum ndr_err_code fill_qtlist_from_sids ( TALLOC_CTX * mem_ctx ,
struct files_struct * fsp ,
SMB_NTQUOTA_HANDLE * qt_handle ,
struct dom_sid * sids ,
uint32_t elems )
2003-05-12 05:20:17 +04:00
{
2018-08-07 23:48:58 +03:00
uint32_t i ;
2017-05-26 18:01:53 +03:00
TALLOC_CTX * list_ctx = NULL ;
2003-05-12 05:20:17 +04:00
2017-05-26 18:01:53 +03:00
list_ctx = talloc_init ( " quota_sid_list " ) ;
2003-05-12 05:20:17 +04:00
2017-05-26 18:01:53 +03:00
if ( list_ctx = = NULL ) {
DBG_ERR ( " failed to allocate \n " ) ;
return NDR_ERR_ALLOC ;
2003-05-12 05:20:17 +04:00
}
2007-09-12 03:57:59 +04:00
2017-05-26 18:01:53 +03:00
if ( qt_handle - > quota_list ! = NULL ) {
free_ntquota_list ( & ( qt_handle - > quota_list ) ) ;
2003-05-12 05:20:17 +04:00
}
2017-05-26 18:01:53 +03:00
for ( i = 0 ; i < elems ; i + + ) {
SMB_NTQUOTA_STRUCT qt ;
SMB_NTQUOTA_LIST * list_item ;
2018-08-07 23:49:16 +03:00
bool ok ;
2003-05-12 05:20:17 +04:00
2017-05-26 18:01:53 +03:00
if ( ! NT_STATUS_IS_OK ( vfs_get_ntquota ( fsp ,
SMB_USER_QUOTA_TYPE ,
& sids [ i ] , & qt ) ) ) {
/* non fatal error, return empty item in result */
ZERO_STRUCT ( qt ) ;
continue ;
}
2003-05-12 05:20:17 +04:00
2017-05-26 18:01:53 +03:00
list_item = talloc_zero ( list_ctx , SMB_NTQUOTA_LIST ) ;
if ( list_item = = NULL ) {
DBG_ERR ( " failed to allocate \n " ) ;
return NDR_ERR_ALLOC ;
}
2003-05-12 05:20:17 +04:00
2018-08-07 23:49:16 +03:00
ok = sid_to_uid ( & sids [ i ] , & list_item - > uid ) ;
if ( ! ok ) {
char buf [ DOM_SID_STR_BUFLEN ] ;
dom_sid_string_buf ( & sids [ i ] , buf , sizeof ( buf ) ) ;
DBG_WARNING ( " Could not convert SID %s to uid \n " , buf ) ;
/* No idea what to return here... */
return NDR_ERR_INVALID_POINTER ;
}
2017-05-26 18:01:53 +03:00
list_item - > quotas = talloc_zero ( list_item , SMB_NTQUOTA_STRUCT ) ;
if ( list_item - > quotas = = NULL ) {
DBG_ERR ( " failed to allocate \n " ) ;
return NDR_ERR_ALLOC ;
}
2003-05-12 05:20:17 +04:00
2017-05-26 18:01:53 +03:00
* list_item - > quotas = qt ;
list_item - > mem_ctx = list_ctx ;
DLIST_ADD ( qt_handle - > quota_list , list_item ) ;
}
qt_handle - > tmp_list = qt_handle - > quota_list ;
return NDR_ERR_SUCCESS ;
}
2003-05-12 05:20:17 +04:00
2017-05-26 18:01:53 +03:00
static enum ndr_err_code extract_sids_from_buf ( TALLOC_CTX * mem_ctx ,
uint32_t sidlistlength ,
DATA_BLOB * sid_buf ,
struct dom_sid * * sids ,
uint32_t * num )
{
DATA_BLOB blob ;
uint32_t i = 0 ;
enum ndr_err_code err ;
struct sid_list_elem {
struct sid_list_elem * prev , * next ;
struct dom_sid sid ;
} ;
struct sid_list_elem * sid_list = NULL ;
struct sid_list_elem * iter = NULL ;
TALLOC_CTX * list_ctx = talloc_init ( " sid_list " ) ;
if ( ! list_ctx ) {
DBG_ERR ( " OOM \n " ) ;
err = NDR_ERR_ALLOC ;
goto done ;
}
2003-05-12 05:20:17 +04:00
2017-05-26 18:01:53 +03:00
* num = 0 ;
* sids = NULL ;
2003-05-12 05:20:17 +04:00
2017-05-26 18:01:53 +03:00
if ( sidlistlength ) {
uint32_t offset = 0 ;
struct ndr_pull * ndr_pull = NULL ;
2003-05-12 05:20:17 +04:00
2017-05-26 18:01:53 +03:00
if ( sidlistlength > sid_buf - > length ) {
DBG_ERR ( " sid_list_length 0x%x exceeds "
" available bytes %zx \n " ,
sidlistlength ,
sid_buf - > length ) ;
err = NDR_ERR_OFFSET ;
goto done ;
}
while ( true ) {
struct file_get_quota_info info ;
struct sid_list_elem * item = NULL ;
uint32_t new_offset = 0 ;
blob . data = sid_buf - > data + offset ;
blob . length = sidlistlength - offset ;
ndr_pull = ndr_pull_init_blob ( & blob , list_ctx ) ;
if ( ! ndr_pull ) {
DBG_ERR ( " OOM \n " ) ;
err = NDR_ERR_ALLOC ;
goto done ;
2005-07-08 08:51:27 +04:00
}
2017-05-26 18:01:53 +03:00
err = ndr_pull_file_get_quota_info ( ndr_pull ,
NDR_SCALARS | NDR_BUFFERS , & info ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( err ) ) {
DBG_ERR ( " Failed to pull file_get_quota_info "
" from sidlist buffer \n " ) ;
goto done ;
2005-07-08 08:51:27 +04:00
}
2017-05-26 18:01:53 +03:00
item = talloc_zero ( list_ctx , struct sid_list_elem ) ;
if ( ! item ) {
DBG_ERR ( " OOM \n " ) ;
err = NDR_ERR_ALLOC ;
goto done ;
2003-05-12 05:20:17 +04:00
}
2017-05-26 18:01:53 +03:00
item - > sid = info . sid ;
DLIST_ADD ( sid_list , item ) ;
i + + ;
if ( i = = UINT32_MAX ) {
DBG_ERR ( " Integer overflow \n " ) ;
err = NDR_ERR_ARRAY_SIZE ;
goto done ;
2003-05-12 05:20:17 +04:00
}
2017-05-26 18:01:53 +03:00
new_offset = info . next_entry_offset ;
2003-05-12 05:20:17 +04:00
2017-05-26 18:01:53 +03:00
/* if new_offset == 0 no more sid(s) to read. */
if ( new_offset = = 0 ) {
break ;
2004-12-07 21:25:53 +03:00
}
2003-05-12 05:20:17 +04:00
2017-05-26 18:01:53 +03:00
/* Integer wrap? */
if ( ( offset + new_offset ) < offset ) {
DBG_ERR ( " Integer wrap while adding "
" new_offset 0x%x to current "
" buffer offset 0x%x \n " ,
new_offset , offset ) ;
err = NDR_ERR_OFFSET ;
goto done ;
2003-05-12 05:20:17 +04:00
}
2017-05-26 18:01:53 +03:00
offset + = new_offset ;
2003-05-12 05:20:17 +04:00
2017-05-26 18:01:53 +03:00
/* check if new offset is outside buffer boundry. */
if ( offset > = sidlistlength ) {
DBG_ERR ( " bufsize 0x%x exceeded by "
" new offset 0x%x) \n " ,
sidlistlength ,
offset ) ;
err = NDR_ERR_OFFSET ;
goto done ;
2010-09-16 02:40:15 +04:00
}
2017-05-26 18:01:53 +03:00
}
* sids = talloc_zero_array ( mem_ctx , struct dom_sid , i ) ;
2018-08-07 23:50:52 +03:00
if ( * sids = = NULL ) {
2017-05-26 18:01:53 +03:00
DBG_ERR ( " OOM \n " ) ;
err = NDR_ERR_ALLOC ;
goto done ;
}
2007-09-12 03:57:59 +04:00
2017-05-26 18:01:53 +03:00
* num = i ;
2003-05-12 05:20:17 +04:00
2017-05-26 18:01:53 +03:00
for ( iter = sid_list , i = 0 ; iter ; iter = iter - > next , i + + ) {
( * sids ) [ i ] = iter - > sid ;
DBG_DEBUG ( " quota SID[%u] %s \n " ,
( unsigned int ) i ,
sid_string_dbg ( & iter - > sid ) ) ;
}
}
err = NDR_ERR_SUCCESS ;
done :
TALLOC_FREE ( list_ctx ) ;
return err ;
}
2003-05-12 05:20:17 +04:00
2017-05-26 18:01:53 +03:00
NTSTATUS smbd_do_query_getinfo_quota ( TALLOC_CTX * mem_ctx ,
files_struct * fsp ,
bool restart_scan ,
bool return_single ,
uint32_t sid_list_length ,
DATA_BLOB * sid_buf ,
uint32_t max_data_count ,
uint8_t * * p_data ,
uint32_t * p_data_size )
{
NTSTATUS status ;
SMB_NTQUOTA_HANDLE * qt_handle = NULL ;
SMB_NTQUOTA_LIST * qt_list = NULL ;
DATA_BLOB blob = data_blob_null ;
enum ndr_err_code err ;
2003-05-12 05:20:17 +04:00
2017-05-26 18:01:53 +03:00
qt_handle =
( SMB_NTQUOTA_HANDLE * ) fsp - > fake_file_handle - > private_data ;
2003-05-12 05:20:17 +04:00
2017-05-26 18:01:53 +03:00
if ( sid_list_length ) {
struct dom_sid * sids ;
uint32_t elems = 0 ;
/*
* error check pulled offsets and lengths for wrap and
* exceeding available bytes .
*/
if ( sid_list_length > sid_buf - > length ) {
DBG_ERR ( " sid_list_length 0x%x exceeds "
" available bytes %zx \n " ,
sid_list_length ,
sid_buf - > length ) ;
return NT_STATUS_INVALID_PARAMETER ;
}
2007-09-12 03:57:59 +04:00
2017-05-26 18:01:53 +03:00
err = extract_sids_from_buf ( mem_ctx , sid_list_length ,
sid_buf , & sids , & elems ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( err ) | | elems = = 0 ) {
return NT_STATUS_INVALID_PARAMETER ;
}
err = fill_qtlist_from_sids ( mem_ctx ,
fsp ,
qt_handle ,
sids ,
elems ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( err ) ) {
return NT_STATUS_INVALID_PARAMETER ;
}
} else if ( restart_scan ) {
if ( vfs_get_user_ntquota_list ( fsp ,
& ( qt_handle - > quota_list ) ) ! = 0 ) {
return NT_STATUS_INTERNAL_ERROR ;
}
} else {
if ( qt_handle - > quota_list ! = NULL & &
qt_handle - > tmp_list = = NULL ) {
free_ntquota_list ( & ( qt_handle - > quota_list ) ) ;
}
}
2007-09-12 03:57:59 +04:00
2017-05-26 18:01:53 +03:00
if ( restart_scan ! = 0 ) {
qt_list = qt_handle - > quota_list ;
} else {
qt_list = qt_handle - > tmp_list ;
}
status = fill_quota_buffer ( mem_ctx , qt_list ,
return_single ! = 0 ,
max_data_count ,
& blob ,
& qt_handle - > tmp_list ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
if ( blob . length > max_data_count ) {
return NT_STATUS_BUFFER_TOO_SMALL ;
}
2007-09-12 03:57:59 +04:00
2017-05-26 18:01:53 +03:00
* p_data = blob . data ;
* p_data_size = blob . length ;
return NT_STATUS_OK ;
}
2007-09-12 03:57:59 +04:00
2017-05-26 18:01:53 +03:00
/****************************************************************************
Reply to get user quota
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-09-12 03:57:59 +04:00
2017-05-26 18:01:53 +03:00
static void call_nt_transact_get_user_quota ( connection_struct * conn ,
struct smb_request * req ,
uint16_t * * ppsetup ,
uint32_t setup_count ,
char * * ppparams ,
uint32_t parameter_count ,
char * * ppdata ,
uint32_t data_count ,
uint32_t max_data_count )
{
NTSTATUS nt_status = NT_STATUS_OK ;
char * params = * ppparams ;
char * pdata = * ppdata ;
int data_len = 0 ;
int param_len = 0 ;
files_struct * fsp = NULL ;
DATA_BLOB blob = data_blob_null ;
struct nttrans_query_quota_params info = { 0 } ;
enum ndr_err_code err ;
TALLOC_CTX * tmp_ctx = NULL ;
uint32_t resp_len = 0 ;
uint8_t * resp_data = 0 ;
2007-09-12 03:57:59 +04:00
2017-05-26 18:01:53 +03:00
tmp_ctx = talloc_init ( " ntquota_list " ) ;
if ( ! tmp_ctx ) {
nt_status = NT_STATUS_NO_MEMORY ;
goto error ;
}
2007-09-12 03:57:59 +04:00
2017-05-26 18:01:53 +03:00
/* access check */
if ( get_current_uid ( conn ) ! = sec_initial_uid ( ) ) {
DEBUG ( 1 , ( " get_user_quota: access_denied service [%s] user "
" [%s] \n " , lp_servicename ( talloc_tos ( ) , SNUM ( conn ) ) ,
conn - > session_info - > unix_info - > unix_name ) ) ;
nt_status = NT_STATUS_ACCESS_DENIED ;
goto error ;
}
blob . data = ( uint8_t * ) params ;
blob . length = parameter_count ;
err = ndr_pull_struct_blob ( & blob , tmp_ctx , & info ,
( ndr_pull_flags_fn_t ) ndr_pull_nttrans_query_quota_params ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( err ) ) {
DEBUG ( 0 , ( " TRANSACT_GET_USER_QUOTA: failed to pull "
" query_quota_params. " ) ) ;
nt_status = NT_STATUS_INVALID_PARAMETER ;
goto error ;
}
DBG_DEBUG ( " info.return_single_entry = %u, info.restart_scan = %u, "
" info.sid_list_length = %u, info.start_sid_length = %u, "
" info.start_sid_offset = %u \n " ,
( unsigned int ) info . return_single_entry ,
( unsigned int ) info . restart_scan ,
( unsigned int ) info . sid_list_length ,
( unsigned int ) info . start_sid_length ,
( unsigned int ) info . start_sid_offset ) ;
/* set blob to point at data for further parsing */
blob . data = ( uint8_t * ) pdata ;
blob . length = data_count ;
/*
* Although MS - SMB ref is ambiguous here , a microsoft client will
* only ever send a start sid ( as part of a list ) with
* sid_list_length & start_sid_offset both set to the actual list
* length . Note : Only a single result is returned in this case
* In the case where either start_sid_offset or start_sid_length
* are set alone or if both set ( but have different values ) then
* it seems windows will return a number of entries from the start
* of the list of users with quotas set . This behaviour is undocumented
* and windows clients do not send messages of that type . As such we
* currently will reject these requests .
*/
if ( info . start_sid_length
| | ( info . sid_list_length ! = info . start_sid_offset ) ) {
DBG_ERR ( " TRANSACT_GET_USER_QUOTA: unsupported single or "
" compound sid format \n " ) ;
nt_status = NT_STATUS_INVALID_PARAMETER ;
goto error ;
}
2003-05-12 05:20:17 +04:00
2017-05-26 18:01:53 +03:00
/* maybe we can check the quota_fnum */
fsp = file_fsp ( req , info . fid ) ;
if ( ! check_fsp_ntquota_handle ( conn , req , fsp ) ) {
DEBUG ( 3 , ( " TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE \n " ) ) ;
nt_status = NT_STATUS_INVALID_HANDLE ;
goto error ;
}
nt_status = smbd_do_query_getinfo_quota ( tmp_ctx ,
fsp ,
info . restart_scan ,
info . return_single_entry ,
info . sid_list_length ,
& blob ,
max_data_count ,
& resp_data ,
& resp_len ) ;
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
if ( ! NT_STATUS_EQUAL ( nt_status , NT_STATUS_NO_MORE_ENTRIES ) ) {
goto error ;
}
nt_status = NT_STATUS_OK ;
}
2003-05-12 05:20:17 +04:00
2017-05-26 18:01:53 +03:00
param_len = 4 ;
params = nttrans_realloc ( ppparams , param_len ) ;
if ( params = = NULL ) {
nt_status = NT_STATUS_NO_MEMORY ;
goto error ;
2003-05-12 05:20:17 +04:00
}
2017-05-26 18:01:53 +03:00
data_len = resp_len ;
SIVAL ( params , 0 , data_len ) ;
pdata = nttrans_realloc ( ppdata , data_len ) ;
memcpy ( pdata , resp_data , data_len ) ;
TALLOC_FREE ( tmp_ctx ) ;
2008-01-04 23:56:23 +03:00
send_nt_replies ( conn , req , nt_status , params , param_len ,
2007-08-14 12:24:02 +04:00
pdata , data_len ) ;
2017-05-26 18:01:53 +03:00
return ;
error :
TALLOC_FREE ( tmp_ctx ) ;
reply_nterror ( req , nt_status ) ;
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 ,
2015-05-01 05:22:21 +03:00
uint16_t * * ppsetup ,
uint32_t setup_count ,
2007-08-14 10:21:02 +04:00
char * * ppparams ,
2015-05-01 05:22:21 +03:00
uint32_t parameter_count ,
2007-08-14 10:21:02 +04:00
char * * ppdata ,
2015-05-01 05:22:21 +03:00
uint32_t data_count ,
uint32_t 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 ;
2017-05-26 18:01:53 +03:00
struct file_quota_information info = { 0 } ;
enum ndr_err_code err ;
2010-05-21 05:25:01 +04:00
struct dom_sid sid ;
2017-05-26 18:01:53 +03:00
DATA_BLOB inblob ;
2003-05-12 05:20:17 +04:00
files_struct * fsp = NULL ;
2017-05-26 18:01:53 +03:00
TALLOC_CTX * ctx = NULL ;
NTSTATUS status = NT_STATUS_OK ;
2003-05-12 05:20:17 +04:00
ZERO_STRUCT ( qt ) ;
/* access check */
2017-03-22 23:06:13 +03:00
if ( get_current_uid ( conn ) ! = sec_initial_uid ( ) ) {
2008-05-08 18:06:42 +04:00
DEBUG ( 1 , ( " set_user_quota: access_denied service [%s] user "
2012-07-18 09:37:23 +04:00
" [%s] \n " , lp_servicename ( talloc_tos ( ) , SNUM ( conn ) ) ,
2011-07-15 09:55:31 +04:00
conn - > session_info - > unix_info - > unix_name ) ) ;
2017-05-26 18:01:53 +03:00
status = NT_STATUS_ACCESS_DENIED ;
goto error ;
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 ) ) ;
2017-05-26 18:01:53 +03:00
status = NT_STATUS_INVALID_PARAMETER ;
goto error ;
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 */
2008-10-09 17:25:17 +04:00
fsp = file_fsp ( req , SVAL ( params , 0 ) ) ;
2008-06-19 20:46:57 +04:00
if ( ! check_fsp_ntquota_handle ( conn , req , fsp ) ) {
2003-05-12 05:20:17 +04:00
DEBUG ( 3 , ( " TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE \n " ) ) ;
2017-05-26 18:01:53 +03:00
status = NT_STATUS_INVALID_HANDLE ;
goto error ;
2003-05-12 05:20:17 +04:00
}
2017-05-26 18:01:53 +03:00
ctx = talloc_init ( " set_user_quota " ) ;
if ( ! ctx ) {
status = NT_STATUS_NO_MEMORY ;
goto error ;
2003-05-12 05:20:17 +04:00
}
2017-05-26 18:01:53 +03:00
inblob . data = ( uint8_t * ) pdata ;
inblob . length = data_count ;
2003-05-12 05:20:17 +04:00
2017-05-26 18:01:53 +03:00
err = ndr_pull_struct_blob (
& inblob ,
ctx ,
& info ,
( ndr_pull_flags_fn_t ) ndr_pull_file_quota_information ) ;
2003-05-12 05:20:17 +04:00
2017-05-26 18:01:53 +03:00
if ( ! NDR_ERR_CODE_IS_SUCCESS ( err ) ) {
DEBUG ( 0 , ( " TRANSACT_SET_USER_QUOTA: failed to pull "
" file_quota_information \n " ) ) ;
status = NT_STATUS_INVALID_PARAMETER ;
goto error ;
2003-05-12 05:20:17 +04:00
}
2017-05-26 18:01:53 +03:00
qt . usedspace = info . quota_used ;
2003-05-12 05:20:17 +04:00
2017-05-26 18:01:53 +03:00
qt . softlim = info . quota_threshold ;
2007-09-12 03:57:59 +04:00
2017-05-26 18:01:53 +03:00
qt . hardlim = info . quota_limit ;
2010-09-16 02:40:15 +04:00
2017-05-26 18:01:53 +03:00
sid = info . sid ;
2003-05-12 05:20:17 +04:00
if ( vfs_set_ntquota ( fsp , SMB_USER_QUOTA_TYPE , & sid , & qt ) ! = 0 ) {
2017-05-26 18:01:53 +03:00
status = NT_STATUS_INTERNAL_ERROR ;
goto error ;
2003-05-12 05:20:17 +04:00
}
2008-01-04 23:56:23 +03:00
send_nt_replies ( conn , req , NT_STATUS_OK , params , param_len ,
2007-08-14 12:24:02 +04:00
pdata , data_len ) ;
2017-05-26 18:01:53 +03:00
TALLOC_FREE ( ctx ) ;
return ;
error :
TALLOC_FREE ( ctx ) ;
reply_nterror ( req , status ) ;
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
{
2009-11-23 18:33:26 +03:00
if ( get_Protocol ( ) > = PROTOCOL_NT1 ) {
2007-08-13 19:40:37 +04:00
req - > flags2 | = 0x40 ; /* IS_LONG_NAME */
2011-05-05 21:41:59 +04:00
SSVAL ( discard_const_p ( uint8_t , req - > inbuf ) , smb_flg2 , req - > flags2 ) ;
2007-08-13 19:40:37 +04:00
}
2009-02-09 10:10:34 +03:00
SMB_PERFCOUNT_SET_SUBOP ( & req - > pcd , state - > call ) ;
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 ) ) ;
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_INVALID_LEVEL ) ;
2007-08-13 19:40:37 +04:00
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
2008-01-05 02:37:24 +03:00
void reply_nttrans ( struct smb_request * req )
1998-05-08 05:22:16 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2008-04-08 08:11:16 +04:00
uint32_t pscnt ;
uint32_t psoff ;
uint32_t dscnt ;
uint32_t dsoff ;
2015-05-01 05:22:21 +03:00
uint16_t function_code ;
2006-04-10 19:33:04 +04:00
NTSTATUS result ;
struct trans_state * state ;
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
}
2008-11-02 19:38:41 +03:00
pscnt = IVAL ( req - > vwv + 9 , 1 ) ;
psoff = IVAL ( req - > vwv + 11 , 1 ) ;
dscnt = IVAL ( req - > vwv + 13 , 1 ) ;
dsoff = IVAL ( req - > vwv + 15 , 1 ) ;
function_code = SVAL ( req - > vwv + 18 , 0 ) ;
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 ) ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_ACCESS_DENIED ) ;
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
}
2011-06-07 05:38:41 +04:00
if ( ( state = talloc ( conn , struct trans_state ) ) = = NULL ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
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 ;
2008-11-02 19:38:41 +03:00
state - > total_data = IVAL ( req - > vwv + 3 , 1 ) ;
2006-04-10 19:33:04 +04:00
state - > data = NULL ;
2008-11-02 19:38:41 +03:00
state - > total_param = IVAL ( req - > vwv + 1 , 1 ) ;
2006-04-10 19:33:04 +04:00
state - > param = NULL ;
2008-11-02 19:38:41 +03:00
state - > max_data_return = IVAL ( req - > vwv + 7 , 1 ) ;
state - > max_param_return = IVAL ( req - > vwv + 5 , 1 ) ;
2006-04-10 19:33:04 +04:00
/* setup count is in *words* */
2008-11-02 19:38:41 +03:00
state - > setup_count = 2 * CVAL ( req - > vwv + 17 , 1 ) ;
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
2008-09-09 16:43:20 +04:00
DEBUG ( 10 , ( " num_setup=%u, "
" param_total=%u, this_param=%u, max_param=%u, "
" data_total=%u, this_data=%u, max_data=%u, "
" param_offset=%u, data_offset=%u \n " ,
( unsigned ) state - > setup_count ,
( unsigned ) state - > total_param , ( unsigned ) pscnt ,
( unsigned ) state - > max_param_return ,
( unsigned ) state - > total_data , ( unsigned ) dscnt ,
( unsigned ) state - > max_data_return ,
( unsigned ) psoff , ( unsigned ) dsoff ) ) ;
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 ) ) ) {
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
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 ) {
2008-11-08 19:08:57 +03:00
if ( trans_oob ( state - > total_data , 0 , dscnt )
| | trans_oob ( smb_len ( req - > inbuf ) , dsoff , dscnt ) ) {
goto bad_param ;
}
2006-04-10 19:33:04 +04:00
/* 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 ) ;
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
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
}
2008-04-08 08:11:16 +04:00
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 ) {
2008-11-08 19:08:57 +03:00
if ( trans_oob ( state - > total_param , 0 , pscnt )
| | trans_oob ( smb_len ( req - > inbuf ) , psoff , pscnt ) ) {
goto bad_param ;
}
2006-04-10 19:33:04 +04:00
/* 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 ) ;
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
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
}
2008-04-08 08:11:16 +04:00
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 ) ) ;
2008-11-08 18:14:12 +03:00
/*
* No overflow possible here , state - > setup_count is an
* unsigned int , being filled by a single byte from
* CVAL ( req - > vwv + 13 , 0 ) above . The cast in the comparison
* below is not necessary , it ' s here to clarify things . The
* validity of req - > vwv and req - > wct has been checked in
* init_smb_request already .
*/
if ( ( state - > setup_count / 2 ) + 19 > ( unsigned int ) req - > wct ) {
goto bad_param ;
}
2015-05-01 05:22:21 +03:00
state - > setup = ( uint16_t * ) 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 ) ;
2009-12-21 22:05:25 +03:00
reply_nterror ( req , NT_STATUS_NO_MEMORY ) ;
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
}
2008-11-06 14:14:08 +03:00
memcpy ( state - > setup , req - > vwv + 19 , state - > setup_count ) ;
2015-05-01 05:22:21 +03:00
dump_data ( 10 , ( uint8_t * ) 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
2008-01-05 02:37:24 +03:00
void reply_nttranss ( struct smb_request * req )
2006-04-10 19:33:04 +04:00
{
2008-01-05 02:37:24 +03:00
connection_struct * conn = req - > conn ;
2008-04-08 08:11:16 +04:00
uint32_t pcnt , poff , dcnt , doff , pdisp , ddisp ;
2006-04-10 19:33:04 +04:00
struct trans_state * state ;
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
2011-05-05 21:41:59 +04:00
show_msg ( ( const char * ) req - > inbuf ) ;
2003-03-07 03:30:47 +03:00
2012-06-16 08:10:37 +04:00
/* Windows clients expect all replies to
an NT transact secondary ( SMBnttranss 0xA1 )
to have a command code of NT transact
( SMBnttrans 0xA0 ) . See bug # 8989 for details . */
req - > cmd = SMBnttrans ;
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 */
2008-11-02 19:38:41 +03:00
if ( IVAL ( req - > vwv + 1 , 1 ) < state - > total_param ) {
state - > total_param = IVAL ( req - > vwv + 1 , 1 ) ;
2006-04-10 19:33:04 +04:00
}
2008-11-02 19:38:41 +03:00
if ( IVAL ( req - > vwv + 3 , 1 ) < state - > total_data ) {
state - > total_data = IVAL ( req - > vwv + 3 , 1 ) ;
2006-04-10 19:33:04 +04:00
}
2003-03-07 03:30:47 +03:00
2008-11-02 19:38:41 +03:00
pcnt = IVAL ( req - > vwv + 5 , 1 ) ;
poff = IVAL ( req - > vwv + 7 , 1 ) ;
pdisp = IVAL ( req - > vwv + 9 , 1 ) ;
2003-03-07 03:30:47 +03:00
2008-11-02 19:38:41 +03:00
dcnt = IVAL ( req - > vwv + 11 , 1 ) ;
doff = IVAL ( req - > vwv + 13 , 1 ) ;
ddisp = IVAL ( req - > vwv + 15 , 1 ) ;
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 ) {
2008-11-08 19:08:57 +03:00
if ( trans_oob ( state - > total_param , pdisp , pcnt )
| | trans_oob ( smb_len ( req - > inbuf ) , poff , pcnt ) ) {
2006-04-10 19:33:04 +04:00
goto bad_param ;
2008-04-08 08:11:16 +04:00
}
2008-11-08 19:08:57 +03:00
memcpy ( state - > param + pdisp , smb_base ( req - > inbuf ) + poff , 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 ) {
2008-11-08 19:08:57 +03:00
if ( trans_oob ( state - > total_data , ddisp , dcnt )
| | trans_oob ( smb_len ( req - > inbuf ) , doff , dcnt ) ) {
2006-04-10 19:33:04 +04:00
goto bad_param ;
2008-04-08 08:11:16 +04:00
}
2008-11-08 19:08:57 +03:00
memcpy ( state - > data + ddisp , smb_base ( req - > inbuf ) + doff , 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
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
}