summaryrefslogtreecommitdiffstats
path: root/source/smbd/nttrans.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/smbd/nttrans.c')
-rw-r--r--source/smbd/nttrans.c1200
1 files changed, 664 insertions, 536 deletions
diff --git a/source/smbd/nttrans.c b/source/smbd/nttrans.c
index 1f3bbd488e5..b80cac8d3c3 100644
--- a/source/smbd/nttrans.c
+++ b/source/smbd/nttrans.c
@@ -1,5 +1,6 @@
/*
- Unix SMB/CIFS implementation.
+ Unix SMB/Netbios implementation.
+ Version 1.9.
SMB NT transaction handling
Copyright (C) Jeremy Allison 1994-1998
@@ -28,28 +29,30 @@ extern BOOL case_preserve;
extern BOOL short_case_preserve;
static char *known_nt_pipes[] = {
- "\\LANMAN",
- "\\srvsvc",
- "\\samr",
- "\\wkssvc",
- "\\NETLOGON",
- "\\ntlsa",
- "\\ntsvcs",
- "\\lsass",
- "\\lsarpc",
- "\\winreg",
- "\\spoolss",
- "\\netdfs",
- NULL
+ "\\LANMAN",
+ "\\srvsvc",
+ "\\samr",
+ "\\wkssvc",
+ "\\NETLOGON",
+ "\\ntlsa",
+ "\\ntsvcs",
+ "\\lsass",
+ "\\lsarpc",
+ "\\winreg",
+ "\\spoolss",
+#ifdef WITH_MSDFS
+ "\\netdfs",
+#endif
+ NULL
};
/* Map generic permissions to file object specific permissions */
struct generic_mapping file_generic_mapping = {
- FILE_GENERIC_READ,
- FILE_GENERIC_WRITE,
- FILE_GENERIC_EXECUTE,
- FILE_GENERIC_ALL
+ FILE_GENERIC_READ,
+ FILE_GENERIC_WRITE,
+ FILE_GENERIC_EXECUTE,
+ FILE_GENERIC_ALL
};
/****************************************************************************
@@ -62,183 +65,257 @@ struct generic_mapping file_generic_mapping = {
static int send_nt_replies(char *inbuf, char *outbuf, int bufsize, NTSTATUS nt_error, char *params,
int paramsize, char *pdata, int datasize)
{
- extern int max_send;
- int data_to_send = datasize;
- int params_to_send = paramsize;
- int useable_space;
- char *pp = params;
- char *pd = pdata;
- int params_sent_thistime, data_sent_thistime, total_sent_thistime;
- int alignment_offset = 3;
- int data_alignment_offset = 0;
-
- /*
- * Initially set the wcnt area to be 18 - this is true for all
- * transNT replies.
- */
+ extern int max_send;
+ int data_to_send = datasize;
+ int params_to_send = paramsize;
+ int useable_space;
+ char *pp = params;
+ char *pd = pdata;
+ int params_sent_thistime, data_sent_thistime, total_sent_thistime;
+ int alignment_offset = 3;
+ int data_alignment_offset = 0;
+
+ /*
+ * Initially set the wcnt area to be 18 - this is true for all
+ * transNT replies.
+ */
+
+ set_message(outbuf,18,0,True);
+
+ if(NT_STATUS_V(nt_error)) {
+ ERROR_NT(nt_error);
+ }
+
+ /*
+ * If there genuinely are no parameters or data to send just send
+ * the empty packet.
+ */
+
+ if(params_to_send == 0 && data_to_send == 0) {
+ if (!send_smb(smbd_server_fd(),outbuf))
+ exit_server("send_nt_replies: send_smb failed.");
+ return 0;
+ }
+
+ /*
+ * When sending params and data ensure that both are nicely aligned.
+ * Only do this alignment when there is also data to send - else
+ * can cause NT redirector problems.
+ */
+
+ if (((params_to_send % 4) != 0) && (data_to_send != 0))
+ data_alignment_offset = 4 - (params_to_send % 4);
+
+ /*
+ * Space is bufsize minus Netbios over TCP header minus SMB header.
+ * The alignment_offset is to align the param bytes on a four byte
+ * boundary (2 bytes for data len, one byte pad).
+ * NT needs this to work correctly.
+ */
+
+ useable_space = bufsize - ((smb_buf(outbuf)+
+ alignment_offset+data_alignment_offset) -
+ outbuf);
+
+ /*
+ * useable_space can never be more than max_send minus the
+ * alignment offset.
+ */
+
+ useable_space = MIN(useable_space,
+ max_send - (alignment_offset+data_alignment_offset));
+
+
+ while (params_to_send || data_to_send) {
+
+ /*
+ * Calculate whether we will totally or partially fill this packet.
+ */
+
+ total_sent_thistime = params_to_send + data_to_send +
+ alignment_offset + data_alignment_offset;
+
+ /*
+ * We can never send more than useable_space.
+ */
+
+ total_sent_thistime = MIN(total_sent_thistime, useable_space);
+
+ set_message(outbuf, 18, total_sent_thistime, True);
+
+ /*
+ * Set total params and data to be sent.
+ */
+
+ SIVAL(outbuf,smb_ntr_TotalParameterCount,paramsize);
+ SIVAL(outbuf,smb_ntr_TotalDataCount,datasize);
+
+ /*
+ * Calculate how many parameters and data we can fit into
+ * this packet. Parameters get precedence.
+ */
+
+ params_sent_thistime = MIN(params_to_send,useable_space);
+ data_sent_thistime = useable_space - params_sent_thistime;
+ data_sent_thistime = MIN(data_sent_thistime,data_to_send);
+
+ SIVAL(outbuf,smb_ntr_ParameterCount,params_sent_thistime);
+
+ if(params_sent_thistime == 0) {
+ SIVAL(outbuf,smb_ntr_ParameterOffset,0);
+ SIVAL(outbuf,smb_ntr_ParameterDisplacement,0);
+ } else {
+ /*
+ * smb_ntr_ParameterOffset is the offset from the start of the SMB header to the
+ * parameter bytes, however the first 4 bytes of outbuf are
+ * the Netbios over TCP header. Thus use smb_base() to subtract
+ * them from the calculation.
+ */
+
+ SIVAL(outbuf,smb_ntr_ParameterOffset,
+ ((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
+ /*
+ * Absolute displacement of param bytes sent in this packet.
+ */
+
+ SIVAL(outbuf,smb_ntr_ParameterDisplacement,pp - params);
+ }
+
+ /*
+ * Deal with the data portion.
+ */
+
+ SIVAL(outbuf,smb_ntr_DataCount, data_sent_thistime);
+
+ if(data_sent_thistime == 0) {
+ SIVAL(outbuf,smb_ntr_DataOffset,0);
+ SIVAL(outbuf,smb_ntr_DataDisplacement, 0);
+ } else {
+ /*
+ * The offset of the data bytes is the offset of the
+ * parameter bytes plus the number of parameters being sent this time.
+ */
+
+ SIVAL(outbuf,smb_ntr_DataOffset,((smb_buf(outbuf)+alignment_offset) -
+ smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
+ SIVAL(outbuf,smb_ntr_DataDisplacement, pd - pdata);
+ }
- set_message(outbuf,18,0,True);
+ /*
+ * Copy the param bytes into the packet.
+ */
- if (NT_STATUS_V(nt_error))
- ERROR_NT(nt_error);
+ if(params_sent_thistime)
+ memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
+
+ /*
+ * Copy in the data bytes
+ */
- /*
- * If there genuinely are no parameters or data to send just send
- * the empty packet.
- */
-
- if(params_to_send == 0 && data_to_send == 0) {
- if (!send_smb(smbd_server_fd(),outbuf))
- exit_server("send_nt_replies: send_smb failed.");
- return 0;
- }
+ if(data_sent_thistime)
+ memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
+ data_alignment_offset,pd,data_sent_thistime);
+
+ DEBUG(9,("nt_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
+ params_sent_thistime, data_sent_thistime, useable_space));
+ DEBUG(9,("nt_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
+ params_to_send, data_to_send, paramsize, datasize));
+
+ /* Send the packet */
+ if (!send_smb(smbd_server_fd(),outbuf))
+ exit_server("send_nt_replies: send_smb failed.");
+
+ pp += params_sent_thistime;
+ pd += data_sent_thistime;
+
+ params_to_send -= params_sent_thistime;
+ data_to_send -= data_sent_thistime;
- /*
- * 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.
- */
+ /*
+ * Sanity check
+ */
- if (((params_to_send % 4) != 0) && (data_to_send != 0))
- data_alignment_offset = 4 - (params_to_send % 4);
+ if(params_to_send < 0 || data_to_send < 0) {
+ DEBUG(0,("send_nt_replies failed sanity check pts = %d, dts = %d\n!!!",
+ params_to_send, data_to_send));
+ return -1;
+ }
+ }
- /*
- * Space is bufsize minus Netbios over TCP header minus SMB header.
- * The alignment_offset is to align the param bytes on a four byte
- * boundary (2 bytes for data len, one byte pad).
- * NT needs this to work correctly.
- */
+ return 0;
+}
- useable_space = bufsize - ((smb_buf(outbuf)+
- alignment_offset+data_alignment_offset) -
- outbuf);
+/****************************************************************************
+ (Hopefully) temporary call to fix bugs in NT5.0beta2. This OS sends unicode
+ strings in NT calls AND DOESN'T SET THE UNICODE BIT !!!!!!!
+****************************************************************************/
+static void get_filename( char *fname, char *inbuf, int data_offset, int data_len, int fname_len)
+{
/*
- * useable_space can never be more than max_send minus the
- * alignment offset.
+ * We need various heuristics here to detect a unicode string... JRA.
*/
- useable_space = MIN(useable_space,
- max_send - (alignment_offset+data_alignment_offset));
-
-
- while (params_to_send || data_to_send) {
-
- /*
- * Calculate whether we will totally or partially fill this packet.
- */
-
- total_sent_thistime = params_to_send + data_to_send +
- alignment_offset + data_alignment_offset;
-
- /*
- * We can never send more than useable_space.
- */
-
- total_sent_thistime = MIN(total_sent_thistime, useable_space);
-
- set_message(outbuf, 18, total_sent_thistime, True);
+ DEBUG(10,("get_filename: data_offset = %d, data_len = %d, fname_len = %d\n",
+ data_offset, data_len, fname_len ));
+ if(data_len - fname_len > 1) {
/*
- * Set total params and data to be sent.
+ * NT 5.0 Beta 2 has kindly sent us a UNICODE string
+ * without bothering to set the unicode bit. How kind.
+ *
+ * Firstly - ensure that the data offset is aligned
+ * on a 2 byte boundary - add one if not.
*/
+ fname_len = fname_len/2;
+ if(data_offset & 1)
+ data_offset++;
+ pstrcpy(fname, dos_unistrn2((uint16 *)(inbuf+data_offset), fname_len));
+ } else {
+ StrnCpy(fname,inbuf+data_offset,fname_len);
+ fname[fname_len] = '\0';
+ }
+}
- SIVAL(outbuf,smb_ntr_TotalParameterCount,paramsize);
- SIVAL(outbuf,smb_ntr_TotalDataCount,datasize);
-
- /*
- * Calculate how many parameters and data we can fit into
- * this packet. Parameters get precedence.
- */
-
- params_sent_thistime = MIN(params_to_send,useable_space);
- data_sent_thistime = useable_space - params_sent_thistime;
- data_sent_thistime = MIN(data_sent_thistime,data_to_send);
-
- SIVAL(outbuf,smb_ntr_ParameterCount,params_sent_thistime);
-
- if(params_sent_thistime == 0) {
- SIVAL(outbuf,smb_ntr_ParameterOffset,0);
- SIVAL(outbuf,smb_ntr_ParameterDisplacement,0);
- } else {
- /*
- * smb_ntr_ParameterOffset is the offset from the start of the SMB header to the
- * parameter bytes, however the first 4 bytes of outbuf are
- * the Netbios over TCP header. Thus use smb_base() to subtract
- * them from the calculation.
- */
-
- SIVAL(outbuf,smb_ntr_ParameterOffset,
- ((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
- /*
- * Absolute displacement of param bytes sent in this packet.
- */
-
- SIVAL(outbuf,smb_ntr_ParameterDisplacement,pp - params);
- }
-
- /*
- * Deal with the data portion.
- */
-
- SIVAL(outbuf,smb_ntr_DataCount, data_sent_thistime);
-
- if(data_sent_thistime == 0) {
- SIVAL(outbuf,smb_ntr_DataOffset,0);
- SIVAL(outbuf,smb_ntr_DataDisplacement, 0);
- } else {
- /*
- * The offset of the data bytes is the offset of the
- * parameter bytes plus the number of parameters being sent this time.
- */
-
- SIVAL(outbuf,smb_ntr_DataOffset,((smb_buf(outbuf)+alignment_offset) -
- smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
- SIVAL(outbuf,smb_ntr_DataDisplacement, pd - pdata);
- }
+/****************************************************************************
+ Fix bugs in Win2000 final release. In trans calls this OS sends unicode
+ strings AND DOESN'T SET THE UNICODE BIT !!!!!!!
+****************************************************************************/
- /*
- * Copy the param bytes into the packet.
- */
+static void get_filename_transact( char *fname, char *inbuf, int data_offset, int data_len, int fname_len)
+{
+ DEBUG(10,("get_filename_transact: data_offset = %d, data_len = %d, fname_len = %d\n",
+ data_offset, data_len, fname_len ));
- if(params_sent_thistime)
- memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
+ /*
+ * Win2K sends a unicode filename plus one extra alingment byte.
+ * WinNT4.x send an ascii string with multiple garbage bytes on
+ * the end here.
+ */
- /*
- * Copy in the data bytes
- */
+ /*
+ * We need various heuristics here to detect a unicode string... JRA.
+ */
- if(data_sent_thistime)
- memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
- data_alignment_offset,pd,data_sent_thistime);
-
- DEBUG(9,("nt_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
- params_sent_thistime, data_sent_thistime, useable_space));
- DEBUG(9,("nt_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
- params_to_send, data_to_send, paramsize, datasize));
-
- /* Send the packet */
- if (!send_smb(smbd_server_fd(),outbuf))
- exit_server("send_nt_replies: send_smb failed.");
-
- pp += params_sent_thistime;
- pd += data_sent_thistime;
-
- params_to_send -= params_sent_thistime;
- data_to_send -= data_sent_thistime;
+ if( ((fname_len % 2) == 0) &&
+ (
+ (data_len == 1) ||
+ (inbuf[data_offset] == '\0') ||
+ ((fname_len > 1) && (inbuf[data_offset+1] == '\\') && (inbuf[data_offset+2] == '\0'))
+ )) {
/*
- * Sanity check
+ * Ensure that the data offset is aligned
+ * on a 2 byte boundary - add one if not.
*/
-
- if(params_to_send < 0 || data_to_send < 0) {
- DEBUG(0,("send_nt_replies failed sanity check pts = %d, dts = %d\n!!!",
- params_to_send, data_to_send));
- return -1;
- }
- }
-
- return 0;
+ fname_len = fname_len/2;
+ if(data_offset & 1)
+ data_offset++;
+ pstrcpy(fname, dos_unistrn2((uint16 *)(inbuf+data_offset), fname_len));
+ } else {
+ StrnCpy(fname,inbuf+data_offset,fname_len);
+ fname[fname_len] = '\0';
+ }
}
/****************************************************************************
@@ -319,7 +396,7 @@ static int map_create_disposition( uint32 create_disposition)
}
DEBUG(10,("map_create_disposition: Mapped create_disposition 0x%lx to 0x%x\n",
- (unsigned long)create_disposition, ret ));
+ (unsigned long)create_disposition, ret ));
return ret;
}
@@ -372,9 +449,9 @@ static int map_share_mode( char *fname, uint32 create_options,
if (smb_open_mode == -1) {
if(*desired_access & (DELETE_ACCESS|WRITE_DAC_ACCESS|WRITE_OWNER_ACCESS|SYNCHRONIZE_ACCESS|
- FILE_EXECUTE|FILE_READ_ATTRIBUTES|
- FILE_READ_EA|FILE_WRITE_EA|SYSTEM_SECURITY_ACCESS|
- FILE_WRITE_ATTRIBUTES|READ_CONTROL_ACCESS)) {
+ FILE_EXECUTE|FILE_READ_ATTRIBUTES|
+ FILE_READ_EA|FILE_WRITE_EA|SYSTEM_SECURITY_ACCESS|
+ FILE_WRITE_ATTRIBUTES|READ_CONTROL_ACCESS)) {
smb_open_mode = DOS_OPEN_RDONLY;
} else if(*desired_access == 0) {
@@ -457,7 +534,7 @@ to open_mode 0x%x\n", (unsigned long)*desired_access, (unsigned long)share_acces
static int nt_open_pipe(char *fname, connection_struct *conn,
char *inbuf, char *outbuf, int *ppnum)
{
- smb_np_struct *p = NULL;
+ pipes_struct *p = NULL;
uint16 vuid = SVAL(inbuf, smb_uid);
int i;
@@ -501,9 +578,11 @@ static int do_ntcreate_pipe_open(connection_struct *conn,
int ret;
int pnum = -1;
char *p = NULL;
+ uint32 fname_len = MIN(((uint32)SVAL(inbuf,smb_ntcreate_NameLength)),
+ ((uint32)sizeof(fname)-1));
- srvstr_pull_buf(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE);
-
+ get_filename(fname, inbuf, smb_buf(inbuf)-inbuf,
+ smb_buflen(inbuf),fname_len);
if ((ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum)) != 0)
return ret;
@@ -547,6 +626,8 @@ int reply_ntcreate_and_X(connection_struct *conn,
uint32 share_access = IVAL(inbuf,smb_ntcreate_ShareAccess);
uint32 create_disposition = IVAL(inbuf,smb_ntcreate_CreateDisposition);
uint32 create_options = IVAL(inbuf,smb_ntcreate_CreateOptions);
+ uint32 fname_len = MIN(((uint32)SVAL(inbuf,smb_ntcreate_NameLength)),
+ ((uint32)sizeof(fname)-1));
uint16 root_dir_fid = (uint16)IVAL(inbuf,smb_ntcreate_RootDirectoryFid);
SMB_OFF_T allocation_size = 0;
int smb_ofun;
@@ -572,7 +653,7 @@ int reply_ntcreate_and_X(connection_struct *conn,
file_attributes = 0x%x, share_access = 0x%x, create_disposition = 0x%x \
create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attributes,
share_access, create_disposition,
- create_options, root_dir_fid ));
+ root_dir_fid, create_options ));
/* If it's an IPC, use the pipe handler. */
@@ -619,13 +700,14 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
if(!dir_fsp->is_directory) {
- srvstr_pull_buf(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE);
+ get_filename(&fname[0], inbuf, smb_buf(inbuf)-inbuf,
+ smb_buflen(inbuf),fname_len);
/*
* Check to see if this is a mac fork of some kind.
*/
- if( strchr_m(fname, ':')) {
+ if( strchr(fname, ':')) {
END_PROFILE(SMBntcreateX);
return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
}
@@ -649,15 +731,29 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
dir_name_len++;
}
- srvstr_pull_buf(inbuf, &fname[dir_name_len], smb_buf(inbuf), sizeof(fname)-dir_name_len, STR_TERMINATE);
+ /*
+ * This next calculation can refuse a correct filename if we're dealing
+ * with the Win2k unicode bug, but that would be rare. JRA.
+ */
+
+ if(fname_len + dir_name_len >= sizeof(pstring)) {
+ END_PROFILE(SMBntcreateX);
+ return(ERROR_DOS(ERRSRV,ERRfilespecs));
+ }
+
+ get_filename(&fname[dir_name_len], inbuf, smb_buf(inbuf)-inbuf,
+ smb_buflen(inbuf),fname_len);
+
} else {
- srvstr_pull_buf(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE);
+
+ get_filename(fname, inbuf, smb_buf(inbuf)-inbuf,
+ smb_buflen(inbuf),fname_len);
/*
* Check to see if this is a mac fork of some kind.
*/
- if( strchr_m(fname, ':')) {
+ if( strchr(fname, ':')) {
END_PROFILE(SMBntcreateX);
return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
}
@@ -738,7 +834,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
fsp = open_file_shared1(conn,fname,&sbuf,
desired_access,
smb_open_mode,
- smb_ofun,unixmode, oplock_request,
+ smb_ofun, unixmode, oplock_request,
&rmode,&smb_action);
if (!fsp) {
@@ -788,6 +884,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
restore_case_semantics(file_attributes);
set_bad_path_error(errno, bad_path);
+
END_PROFILE(SMBntcreateX);
return(UNIXERROR(ERRDOS,ERRnoaccess));
}
@@ -834,7 +931,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
extended_oplock_granted = True;
-#if 0
+#if 0
/* W2K sends back 42 words here ! If we do the same it breaks offline sync. Go figure... ? JRA. */
set_message(outbuf,42,0,True);
#else
@@ -889,7 +986,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", flags, desired_access, file_attrib
p += 8;
SIVAL(p,0,fmode); /* File Attributes. */
p += 4;
- SOFF_T(p, 0, get_allocation_size(fsp,&sbuf));
+ SOFF_T(p, 0, get_allocation_size(fsp, &sbuf));
p += 8;
SOFF_T(p,0,file_len);
p += 12;
@@ -912,6 +1009,7 @@ static int do_nt_transact_create_pipe( connection_struct *conn,
char **ppdata)
{
pstring fname;
+ uint32 fname_len;
int total_parameter_count = (int)IVAL(inbuf, smb_nt_TotalParameterCount);
char *params = *ppparams;
int ret;
@@ -927,29 +1025,32 @@ static int do_nt_transact_create_pipe( connection_struct *conn,
return ERROR_DOS(ERRDOS,ERRnoaccess);
}
- srvstr_pull(inbuf, fname, params+53, sizeof(fname), total_parameter_count-53, STR_TERMINATE);
+ fname_len = MIN(((uint32)IVAL(params,44)),((uint32)sizeof(fname)-1));
+
+ get_filename_transact(&fname[0], params, 53,
+ total_parameter_count - 53 - fname_len, fname_len);
if ((ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum)) != 0)
return ret;
-
+
/* Realloc the size of parameters and data we will return */
params = Realloc(*ppparams, 69);
if(params == NULL)
return ERROR_DOS(ERRDOS,ERRnomem);
-
+
*ppparams = params;
-
+
memset((char *)params,'\0',69);
-
+
p = params;
SCVAL(p,0,NO_OPLOCK_RETURN);
-
+
p += 2;
SSVAL(p,0,pnum);
p += 2;
SIVAL(p,0,FILE_WAS_OPENED);
p += 8;
-
+
p += 32;
SIVAL(p,0,FILE_ATTRIBUTE_NORMAL); /* File Attributes. */
p += 20;
@@ -957,12 +1058,12 @@ static int do_nt_transact_create_pipe( connection_struct *conn,
SSVAL(p,0,FILE_TYPE_MESSAGE_MODE_PIPE);
/* Device state. */
SSVAL(p,2, 0x5FF); /* ? */
-
+
DEBUG(5,("do_nt_transact_create_pipe: open name = %s\n", fname));
-
+
/* Send the required number of replies */
send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, params, 69, *ppdata, 0);
-
+
return -1;
}
@@ -970,15 +1071,17 @@ static int do_nt_transact_create_pipe( connection_struct *conn,
Internal fn to set security descriptors.
****************************************************************************/
-static NTSTATUS set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 security_info_sent)
+static BOOL set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 security_info_sent, int *pdef_class,uint32 *pdef_code)
{
prs_struct pd;
SEC_DESC *psd = NULL;
TALLOC_CTX *mem_ctx;
BOOL ret;
-
+
if (sd_len == 0) {
- return NT_STATUS_OK;
+ *pdef_class = 0;
+ *pdef_code = 0;
+ return True;
}
/*
@@ -987,7 +1090,9 @@ static NTSTATUS set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 secu
if ((mem_ctx = talloc_init()) == NULL) {
DEBUG(0,("set_sd: talloc_init failed.\n"));
- return NT_STATUS_NO_MEMORY;
+ *pdef_class = ERRDOS;
+ *pdef_code = ERRnomem;
+ return False;
}
prs_init(&pd, 0, mem_ctx, UNMARSHALL);
@@ -1009,9 +1114,11 @@ static NTSTATUS set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 secu
* Return access denied for want of a better error message..
*/
talloc_destroy(mem_ctx);
- return NT_STATUS_NO_MEMORY;
+ *pdef_class = ERRDOS;
+ *pdef_code = ERRnomem;
+ return False;
}
-
+
if (psd->off_owner_sid==0)
security_info_sent &= ~OWNER_SECURITY_INFORMATION;
if (psd->off_grp_sid==0)
@@ -1022,15 +1129,19 @@ static NTSTATUS set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 secu
security_info_sent &= ~DACL_SECURITY_INFORMATION;
ret = fsp->conn->vfs_ops.fset_nt_acl( fsp, fsp->fd, security_info_sent, psd);
-
+
if (!ret) {
talloc_destroy(mem_ctx);
- return NT_STATUS_ACCESS_DENIED;
+ *pdef_class = ERRDOS;
+ *pdef_code = ERRnoaccess;
+ return False;
}
-
+
talloc_destroy(mem_ctx);
-
- return NT_STATUS_OK;
+
+ *pdef_class = 0;
+ *pdef_code = 0;
+ return True;
}
/****************************************************************************
@@ -1063,14 +1174,16 @@ static int call_nt_transact_create(connection_struct *conn,
uint32 share_access;
uint32 create_disposition;
uint32 create_options;
+ uint32 fname_len;
uint32 sd_len;
uint16 root_dir_fid;
- SMB_OFF_T allocation_size = 0;
+ SMB_OFF_T allocation_size;
int smb_ofun;
int smb_open_mode;
int smb_attr;
+ int error_class;
+ uint32 error_code;
time_t c_time;
- NTSTATUS nt_status;
DEBUG(5,("call_nt_transact_create\n"));
@@ -1102,6 +1215,7 @@ static int call_nt_transact_create(connection_struct *conn,
create_disposition = IVAL(params,28);
create_options = IVAL(params,32);
sd_len = IVAL(params,36);
+ fname_len = MIN(((uint32)IVAL(params,44)),((uint32)sizeof(fname)-1));
root_dir_fid = (uint16)IVAL(params,4);
smb_attr = (file_attributes & SAMBA_ATTRIBUTES_MASK);
@@ -1134,17 +1248,17 @@ static int call_nt_transact_create(connection_struct *conn,
return ERROR_DOS(ERRDOS,ERRbadfid);
if(!dir_fsp->is_directory) {
-
- srvstr_pull(inbuf, fname, params+53, sizeof(fname), total_parameter_count-53, STR_TERMINATE);
+ get_filename_transact(&fname[0], params, 53,
+ total_parameter_count - 53 - fname_len, fname_len);
/*
* Check to see if this is a mac fork of some kind.
*/
- if( strchr_m(fname, ':'))
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ if( strchr(fname, ':'))
+ return(ERROR_BOTH(NT_STATUS_OBJECT_PATH_NOT_FOUND,ERRDOS,ERRbadpath));
- return ERROR_DOS(ERRDOS,ERRbadfid);
+ return(ERROR_DOS(ERRDOS,ERRbadfid));
}
/*
@@ -1163,17 +1277,27 @@ static int call_nt_transact_create(connection_struct *conn,
dir_name_len++;
}
- srvstr_pull(inbuf, &fname[dir_name_len], params+53, sizeof(fname)-dir_name_len,
- total_parameter_count-53, STR_TERMINATE);
+ /*
+ * This next calculation can refuse a correct filename if we're dealing
+ * with the Win2k unicode bug, but that would be rare. JRA.
+ */
+
+ if(fname_len + dir_name_len >= sizeof(pstring))
+ return(ERROR_DOS(ERRSRV,ERRfilespecs));
+
+ get_filename_transact(&fname[dir_name_len], params, 53,
+ total_parameter_count - 53 - fname_len, fname_len);
+
} else {
- srvstr_pull(inbuf, fname, params+53, sizeof(fname), total_parameter_count-53, STR_TERMINATE);
+ get_filename_transact(&fname[0], params, 53,
+ total_parameter_count - 53 - fname_len, fname_len);
/*
* Check to see if this is a mac fork of some kind.
*/
- if( strchr_m(fname, ':'))
- return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
+ if( strchr(fname, ':'))
+ return(ERROR_BOTH(NT_STATUS_OBJECT_PATH_NOT_FOUND,ERRDOS,ERRbadpath));
}
/*
@@ -1182,7 +1306,7 @@ static int call_nt_transact_create(connection_struct *conn,
*/
if((smb_open_mode = map_share_mode( fname, create_options, &desired_access,
- share_access, file_attributes)) == -1)
+ share_access, file_attributes)) == -1)
return ERROR_DOS(ERRDOS,ERRnoaccess);
oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
@@ -1234,9 +1358,8 @@ static int call_nt_transact_create(connection_struct *conn,
* Ordinary file case.
*/
- fsp = open_file_shared1(conn,fname,&sbuf,desired_access,
- smb_open_mode,smb_ofun,unixmode,
- oplock_request,&rmode,&smb_action);
+ fsp = open_file_shared1(conn,fname,&sbuf,desired_access,smb_open_mode,smb_ofun,unixmode,
+ oplock_request,&rmode,&smb_action);
if (!fsp) {
@@ -1254,15 +1377,17 @@ static int call_nt_transact_create(connection_struct *conn,
oplock_request = 0;
fsp = open_directory(conn, fname, &sbuf, desired_access, smb_open_mode, smb_ofun, unixmode, &smb_action);
-
+
if(!fsp) {
restore_case_semantics(file_attributes);
set_bad_path_error(errno, bad_path);
return(UNIXERROR(ERRDOS,ERRnoaccess));
}
} else {
+
restore_case_semantics(file_attributes);
set_bad_path_error(errno, bad_path);
+
return(UNIXERROR(ERRDOS,ERRnoaccess));
}
}
@@ -1295,12 +1420,12 @@ static int call_nt_transact_create(connection_struct *conn,
* Now try and apply the desired SD.
*/
- if (sd_len && !NT_STATUS_IS_OK(nt_status = set_sd( fsp, data, sd_len, ALL_SECURITY_INFORMATION))) {
+ if (sd_len && !set_sd( fsp, data, sd_len, ALL_SECURITY_INFORMATION, &error_class, &error_code)) {
close_file(fsp,False);
restore_case_semantics(file_attributes);
- return ERROR_NT(nt_status);
+ return ERROR_DOS(error_class, error_code);
}
-
+
restore_case_semantics(file_attributes);
/* Save the requested allocation size. */
@@ -1416,7 +1541,6 @@ int reply_nttranss(connection_struct *conn,
Reply to a notify change - queue the request and
don't allow a directory to be opened.
****************************************************************************/
-
static int call_nt_transact_notify_change(connection_struct *conn,
char *inbuf, char *outbuf, int length,
int bufsize,
@@ -1461,12 +1585,15 @@ static int call_nt_transact_rename(connection_struct *conn,
files_struct *fsp = file_fsp(params, 0);
BOOL replace_if_exists = (SVAL(params,2) & RENAME_REPLACE_IF_EXISTS) ? True : False;
NTSTATUS status;
+ uint32 fname_len = MIN((((uint32)IVAL(inbuf,smb_nt_TotalParameterCount)-4)),
+ ((uint32)sizeof(new_name)-1));
CHECK_FSP(fsp, conn);
- srvstr_pull(inbuf, new_name, params+4, sizeof(new_name), -1, STR_TERMINATE);
+ StrnCpy(new_name,params+4,fname_len);
+ new_name[fname_len] = '\0';
status = rename_internals(conn, fsp->fsp_name,
- new_name, replace_if_exists);
+ new_name, replace_if_exists);
if (!NT_STATUS_IS_OK(status))
return ERROR_NT(status);
@@ -1474,15 +1601,15 @@ static int call_nt_transact_rename(connection_struct *conn,
* Rename was successful.
*/
send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0);
-
+
DEBUG(3,("nt transact rename from = %s, to = %s succeeded.\n",
- fsp->fsp_name, new_name));
-
+ fsp->fsp_name, new_name));
+
/*
* Win2k needs a changenotify request response before it will
* update after a rename..
*/
-
+
process_pending_change_notify_queue((time_t)0);
return -1;
@@ -1502,7 +1629,7 @@ static size_t get_null_nt_acl(TALLOC_CTX *mem_ctx, SEC_DESC **ppsd)
DEBUG(0,("get_null_nt_acl: Unable to malloc space for security descriptor.\n"));
sd_size = 0;
}
-
+
return sd_size;
}
@@ -1517,107 +1644,107 @@ static int call_nt_transact_query_security_desc(connection_struct *conn,
int length, int bufsize,
char **ppsetup, char **ppparams, char **ppdata)
{
- uint32 max_data_count = IVAL(inbuf,smb_nt_MaxDataCount);
- char *params = *ppparams;
- char *data = *ppdata;
- prs_struct pd;
- SEC_DESC *psd = NULL;
- size_t sd_size;
- TALLOC_CTX *mem_ctx;
+ uint32 max_data_count = IVAL(inbuf,smb_nt_MaxDataCount);
+ char *params = *ppparams;
+ char *data = *ppdata;
+ prs_struct pd;
+ SEC_DESC *psd = NULL;
+ size_t sd_size;
+ TALLOC_CTX *mem_ctx;
- files_struct *fsp = file_fsp(params,0);
+ files_struct *fsp = file_fsp(params,0);
- if(!fsp)
- return ERROR_DOS(ERRDOS,ERRbadfid);
+ if(!fsp)
+ return ERROR_DOS(ERRDOS,ERRbadfid);
- DEBUG(3,("call_nt_transact_query_security_desc: file = %s\n", fsp->fsp_name ));
+ DEBUG(3,("call_nt_transact_query_security_desc: file = %s\n", fsp->fsp_name ));
- params = Realloc(*ppparams, 4);
- if(params == NULL)
- return ERROR_DOS(ERRDOS,ERRnomem);
+ params = Realloc(*ppparams, 4);
+ if(params == NULL)
+ return ERROR_DOS(ERRDOS,ERRnomem);
- *ppparams = params;
+ *ppparams = params;
- if ((mem_ctx = talloc_init()) == NULL) {
- DEBUG(0,("call_nt_transact_query_security_desc: talloc_init failed.\n"));
- return ERROR_DOS(ERRDOS,ERRnomem);
- }
+ if ((mem_ctx = talloc_init()) == NULL) {
+ DEBUG(0,("call_nt_transact_query_security_desc: talloc_init failed.\n"));
+ return ERROR_DOS(ERRDOS,ERRnomem);
+ }
- /*
- * Get the permissions to return.
- */
+ /*
+ * Get the permissions to return.
+ */
- if (!lp_nt_acl_support(SNUM(conn)))
- sd_size = get_null_nt_acl(mem_ctx, &psd);
- else
- sd_size = conn->vfs_ops.fget_nt_acl(fsp, fsp->fd, &psd);
+ if (!lp_nt_acl_support(SNUM(conn)))
+ sd_size = get_null_nt_acl(mem_ctx, &psd);
+ else
+ sd_size = conn->vfs_ops.fget_nt_acl(fsp, fsp->fd, &psd);
- if (sd_size == 0) {
- talloc_destroy(mem_ctx);
- return(UNIXERROR(ERRDOS,ERRnoaccess));
- }
+ if (sd_size == 0) {
+ talloc_destroy(mem_ctx);
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
+ }
- DEBUG(3,("call_nt_transact_query_security_desc: sd_size = %d.\n",(int)sd_size));
+ DEBUG(3,("call_nt_transact_query_security_desc: sd_size = %d.\n",(int)sd_size));
- SIVAL(params,0,(uint32)sd_size);
+ SIVAL(params,0,(uint32)sd_size);
- if(max_data_count < sd_size) {
+ if(max_data_count < sd_size) {
- send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_BUFFER_TOO_SMALL,
- params, 4, *ppdata, 0);
- talloc_destroy(mem_ctx);
- return -1;
- }
+ send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_BUFFER_TOO_SMALL,
+ params, 4, *ppdata, 0);
+ talloc_destroy(mem_ctx);
+ return -1;
+ }
- /*
- * Allocate the data we will point this at.
- */
+ /*
+ * Allocate the data we will point this at.
+ */
- data = Realloc(*ppdata, sd_size);
- if(data == NULL) {
- talloc_destroy(mem_ctx);
- return ERROR_DOS(ERRDOS,ERRnomem);
- }
+ data = Realloc(*ppdata, sd_size);
+ if(data == NULL) {
+ talloc_destroy(mem_ctx);
+ return ERROR_DOS(ERRDOS,ERRnomem);
+ }
- *ppdata = data;
+ *ppdata = data;
- memset(data, '\0', sd_size);
+ memset(data, '\0', sd_size);
- /*
- * Init the parse struct we will marshall into.
- */
+ /*
+ * Init the parse struct we will marshall into.
+ */
- prs_init(&pd, 0, mem_ctx, MARSHALL);
+ prs_init(&pd, 0, mem_ctx, MARSHALL);
- /*
- * Setup the prs_struct to point at the memory we just
- * allocated.
- */
+ /*
+ * Setup the prs_struct to point at the memory we just
+ * allocated.
+ */
- prs_give_memory( &pd, data, (uint32)sd_size, False);
+ prs_give_memory( &pd, data, (uint32)sd_size, False);
- /*
- * Finally, linearize into the outgoing buffer.
- */
+ /*
+ * Finally, linearize into the outgoing buffer.
+ */
- if(!sec_io_desc( "sd data", &psd, &pd, 1)) {
- DEBUG(0,("call_nt_transact_query_security_desc: Error in marshalling \
+ if(!sec_io_desc( "sd data", &psd, &pd, 1)) {
+ DEBUG(0,("call_nt_transact_query_security_desc: Error in marshalling \
security descriptor.\n"));
- /*
- * Return access denied for want of a better error message..
- */
- talloc_destroy(mem_ctx);
- return(UNIXERROR(ERRDOS,ERRnoaccess));
- }
+ /*
+ * Return access denied for want of a better error message..
+ */
+ talloc_destroy(mem_ctx);
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
+ }
- /*
- * Now we can delete the security descriptor.
- */
+ /*
+ * Now we can delete the security descriptor.
+ */
- talloc_destroy(mem_ctx);
+ talloc_destroy(mem_ctx);
- send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, params, 4, data, (int)sd_size);
- return -1;
+ send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, params, 4, data, (int)sd_size);
+ return -1;
}
/****************************************************************************
@@ -1635,7 +1762,8 @@ static int call_nt_transact_set_security_desc(connection_struct *conn,
uint32 total_data_count = (uint32)IVAL(inbuf, smb_nts_TotalDataCount);
files_struct *fsp = NULL;
uint32 security_info_sent = 0;
- NTSTATUS nt_status;
+ int error_class;
+ uint32 error_code;
if(total_parameter_count < 8)
return ERROR_DOS(ERRDOS,ERRbadfunc);
@@ -1654,8 +1782,8 @@ static int call_nt_transact_set_security_desc(connection_struct *conn,
if (total_data_count == 0)
return ERROR_DOS(ERRDOS, ERRnoaccess);
- if (!NT_STATUS_IS_OK(nt_status = set_sd( fsp, data, total_data_count, security_info_sent)))
- return ERROR_NT(nt_status);
+ if (!set_sd( fsp, data, total_data_count, security_info_sent, &error_class, &error_code))
+ return ERROR_DOS(error_class, error_code);
done:
@@ -1664,263 +1792,263 @@ static int call_nt_transact_set_security_desc(connection_struct *conn,
}
/****************************************************************************
- Reply to NT IOCTL
+ Reply to IOCTL.
****************************************************************************/
+
static int call_nt_transact_ioctl(connection_struct *conn,
- char *inbuf, char *outbuf, int length,
- int bufsize,
- char **ppsetup, int setup_count,
- char **ppparams, int parameter_count,
- char **ppdata, int data_count)
+ char *inbuf, char *outbuf, int length,
+ int bufsize,
+ char **ppsetup, int setup_count,
+ char **ppparams, int parameter_count,
+ char **ppdata, int data_count)
{
unsigned fnum, control;
static BOOL logged_message;
-
+
if (setup_count != 8) {
DEBUG(3,("call_nt_transact_ioctl: invalid setup count %d\n", setup_count));
return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
}
-
+
fnum = SVAL(*ppsetup, 4);
control = IVAL(*ppsetup, 0);
-
- DEBUG(6,("call_nt_transact_ioctl: fnum=%d control=0x%x\n",
- fnum, control));
-
+
+ DEBUG(6,("call_nt_transact_ioctl: fnum=%d control=0x%x\n",
+ fnum, control));
+
switch (control) {
case NTIOCTL_SET_SPARSE:
/* pretend this succeeded - tho strictly we should
- mark the file sparse (if the local fs supports it)
- so we can know if we need to pre-allocate or not */
+ mark the file sparse (if the local fs supports it)
+ so we can know if we need to pre-allocate or not */
send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0);
return -1;
-
+
default:
if (!logged_message) {
logged_message = True; /* Only print this once... */
DEBUG(3,("call_nt_transact_ioctl(0x%x): Currently not implemented.\n",
- control));
+ control));
}
}
-
+
return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
}
/****************************************************************************
Reply to a SMBNTtrans.
****************************************************************************/
-
int reply_nttrans(connection_struct *conn,
- char *inbuf,char *outbuf,int length,int bufsize)
+ char *inbuf,char *outbuf,int length,int bufsize)
{
- int outsize = 0;
+ int outsize = 0;
#if 0 /* Not used. */
- uint16 max_setup_count = CVAL(inbuf, smb_nt_MaxSetupCount);
- uint32 max_parameter_count = IVAL(inbuf, smb_nt_MaxParameterCount);
- uint32 max_data_count = IVAL(inbuf,smb_nt_MaxDataCount);
+ uint16 max_setup_count = CVAL(inbuf, smb_nt_MaxSetupCount);
+ uint32 max_parameter_count = IVAL(inbuf, smb_nt_MaxParameterCount);
+ uint32 max_data_count = IVAL(inbuf,smb_nt_MaxDataCount);
#endif /* Not used. */
- uint32 total_parameter_count = IVAL(inbuf, smb_nt_TotalParameterCount);
- uint32 total_data_count = IVAL(inbuf, smb_nt_TotalDataCount);
- uint32 parameter_count = IVAL(inbuf,smb_nt_ParameterCount);
- uint32 parameter_offset = IVAL(inbuf,smb_nt_ParameterOffset);
- uint32 data_count = IVAL(inbuf,smb_nt_DataCount);
- uint32 data_offset = IVAL(inbuf,smb_nt_DataOffset);
- uint16 setup_count = 2*CVAL(inbuf,smb_nt_SetupCount); /* setup count is in *words* */
- uint16 function_code = SVAL( inbuf, smb_nt_Function);
- char *params = NULL, *data = NULL, *setup = NULL;
- uint32 num_params_sofar, num_data_sofar;
- START_PROFILE(SMBnttrans);
-
- if(global_oplock_break &&
- ((function_code == NT_TRANSACT_CREATE) ||
- (function_code == NT_TRANSACT_RENAME))) {
- /*
- * Queue this open message as we are the process of an oplock break.
- */
-
- DEBUG(2,("reply_nttrans: queueing message code 0x%x \
+ uint32 total_parameter_count = IVAL(inbuf, smb_nt_TotalParameterCount);
+ uint32 total_data_count = IVAL(inbuf, smb_nt_TotalDataCount);
+ uint32 parameter_count = IVAL(inbuf,smb_nt_ParameterCount);
+ uint32 parameter_offset = IVAL(inbuf,smb_nt_ParameterOffset);
+ uint32 data_count = IVAL(inbuf,smb_nt_DataCount);
+ uint32 data_offset = IVAL(inbuf,smb_nt_DataOffset);
+ uint16 setup_count = 2*CVAL(inbuf,smb_nt_SetupCount); /* setup count is in *words* */
+ uint16 function_code = SVAL( inbuf, smb_nt_Function);
+ char *params = NULL, *data = NULL, *setup = NULL;
+ uint32 num_params_sofar, num_data_sofar;
+ START_PROFILE(SMBnttrans);
+
+ if(global_oplock_break &&
+ ((function_code == NT_TRANSACT_CREATE) ||
+ (function_code == NT_TRANSACT_RENAME))) {
+ /*
+ * Queue this open message as we are the process of an oplock break.
+ */
+
+ DEBUG(2,("reply_nttrans: queueing message code 0x%x \
due to being in oplock break state.\n", (unsigned int)function_code ));
- push_oplock_pending_smb_message( inbuf, length);
- END_PROFILE(SMBnttrans);
- return -1;
- }
-
- if (IS_IPC(conn) && (function_code != NT_TRANSACT_CREATE)) {
- END_PROFILE(SMBnttrans);
- return ERROR_DOS(ERRSRV,ERRaccess);
- }
-
- outsize = set_message(outbuf,0,0,True);
-
- /*
- * All nttrans messages we handle have smb_wct == 19 + setup_count.
- * Ensure this is so as a sanity check.
- */
-
- if(CVAL(inbuf, smb_wct) != 19 + (setup_count/2)) {
- DEBUG(2,("Invalid smb_wct %d in nttrans call (should be %d)\n",
- CVAL(inbuf, smb_wct), 19 + (setup_count/2)));
- END_PROFILE(SMBnttrans);
- return ERROR_DOS(ERRSRV,ERRerror);
- }
+ push_oplock_pending_smb_message( inbuf, length);
+ END_PROFILE(SMBnttrans);
+ return -1;
+ }
+
+ if (IS_IPC(conn) && (function_code != NT_TRANSACT_CREATE)) {
+ END_PROFILE(SMBnttrans);
+ return ERROR_DOS(ERRSRV,ERRaccess);
+ }
+
+ outsize = set_message(outbuf,0,0,True);
+
+ /*
+ * All nttrans messages we handle have smb_wct == 19 + setup_count.
+ * Ensure this is so as a sanity check.
+ */
+
+ if(CVAL(inbuf, smb_wct) != 19 + (setup_count/2)) {
+ DEBUG(2,("Invalid smb_wct %d in nttrans call (should be %d)\n",
+ CVAL(inbuf, smb_wct), 19 + (setup_count/2)));
+ END_PROFILE(SMBnttrans);
+ return ERROR_DOS(ERRSRV,ERRerror);
+ }
- /* Allocate the space for the setup, the maximum needed parameters and data */
-
- if(setup_count > 0)
- setup = (char *)malloc(setup_count);
- if (total_parameter_count > 0)
- params = (char *)malloc(total_parameter_count);
- if (total_data_count > 0)
- data = (char *)malloc(total_data_count);
+ /* Allocate the space for the setup, the maximum needed parameters and data */
+
+ if(setup_count > 0)
+ setup = (char *)malloc(setup_count);
+ if (total_parameter_count > 0)
+ params = (char *)malloc(total_parameter_count);
+ if (total_data_count > 0)
+ data = (char *)malloc(total_data_count);
- if ((total_parameter_count && !params) || (total_data_count && !data) ||
- (setup_count && !setup)) {
- SAFE_FREE(setup);
- SAFE_FREE(params);
- SAFE_FREE(data);
- DEBUG(0,("reply_nttrans : Out of memory\n"));
- END_PROFILE(SMBnttrans);
- return ERROR_DOS(ERRDOS,ERRnomem);
- }
-
- /* Copy the param and data bytes sent with this request into the params buffer */
- num_params_sofar = parameter_count;
- num_data_sofar = data_count;
-
- if (parameter_count > total_parameter_count || data_count > total_data_count)
- exit_server("reply_nttrans: invalid sizes in packet.");
-
- if(setup) {
- memcpy( setup, &inbuf[smb_nt_SetupStart], setup_count);
- DEBUG(10,("reply_nttrans: setup_count = %d\n", setup_count));
- dump_data(10, setup, setup_count);
- }
- if(params) {
- memcpy( params, smb_base(inbuf) + parameter_offset, parameter_count);
- DEBUG(10,("reply_nttrans: parameter_count = %d\n", parameter_count));
- dump_data(10, params, parameter_count);
- }
- if(data) {
- memcpy( data, smb_base(inbuf) + data_offset, data_count);
- DEBUG(10,("reply_nttrans: data_count = %d\n",data_count));
- dump_data(10, data, data_count);
- }
-
- if(num_data_sofar < total_data_count || num_params_sofar < total_parameter_count) {
- /* We need to send an interim response then receive the rest
- of the parameter/data bytes */
- outsize = set_message(outbuf,0,0,True);
- if (!send_smb(smbd_server_fd(),outbuf))
- exit_server("reply_nttrans: send_smb failed.");
-
- while( num_data_sofar < total_data_count || num_params_sofar < total_parameter_count) {
- BOOL ret;
-
- ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
-
- if((ret && (CVAL(inbuf, smb_com) != SMBnttranss)) || !ret) {
- outsize = set_message(outbuf,0,0,True);
- if(ret) {
- DEBUG(0,("reply_nttrans: Invalid secondary nttrans packet\n"));
- } else {
- DEBUG(0,("reply_nttrans: %s in getting secondary nttrans response.\n",
- (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
- }
- SAFE_FREE(params);
- SAFE_FREE(data);
- SAFE_FREE(setup);
- END_PROFILE(SMBnttrans);
- return ERROR_DOS(ERRSRV,ERRerror);
- }
-
- /* Revise total_params and total_data in case they have changed downwards */
- total_parameter_count = IVAL(inbuf, smb_nts_TotalParameterCount);
- total_data_count = IVAL(inbuf, smb_nts_TotalDataCount);
- num_params_sofar += (parameter_count = IVAL(inbuf,smb_nts_ParameterCount));
- num_data_sofar += ( data_count = IVAL(inbuf, smb_nts_DataCount));
- if (num_params_sofar > total_parameter_count || num_data_sofar > total_data_count)
- exit_server("reply_nttrans2: data overflow in secondary nttrans packet");
-
- memcpy( &params[ IVAL(inbuf, smb_nts_ParameterDisplacement)],
- smb_base(inbuf) + IVAL(inbuf, smb_nts_ParameterOffset), parameter_count);
- memcpy( &data[IVAL(inbuf, smb_nts_DataDisplacement)],
- smb_base(inbuf)+ IVAL(inbuf, smb_nts_DataOffset), data_count);
- }
+ if ((total_parameter_count && !params) || (total_data_count && !data) ||
+ (setup_count && !setup)) {
+ safe_free(setup);
+ safe_free(params);
+ safe_free(data);
+ DEBUG(0,("reply_nttrans : Out of memory\n"));
+ END_PROFILE(SMBnttrans);
+ return ERROR_DOS(ERRDOS,ERRnomem);
+ }
+
+ /* Copy the param and data bytes sent with this request into
+ the params buffer */
+ num_params_sofar = parameter_count;
+ num_data_sofar = data_count;
+
+ if (parameter_count > total_parameter_count || data_count > total_data_count)
+ exit_server("reply_nttrans: invalid sizes in packet.");
+
+ if(setup) {
+ memcpy( setup, &inbuf[smb_nt_SetupStart], setup_count);
+ DEBUG(10,("reply_nttrans: setup_count = %d\n", setup_count));
+ dump_data(10, setup, setup_count);
+ }
+ if(params) {
+ memcpy( params, smb_base(inbuf) + parameter_offset, parameter_count);
+ DEBUG(10,("reply_nttrans: parameter_count = %d\n", parameter_count));
+ dump_data(10, params, parameter_count);
+ }
+ if(data) {
+ memcpy( data, smb_base(inbuf) + data_offset, data_count);
+ DEBUG(10,("reply_nttrans: data_count = %d\n",data_count));
+ dump_data(10, data, data_count);
+ }
+
+ if(num_data_sofar < total_data_count || num_params_sofar < total_parameter_count) {
+ /* We need to send an interim response then receive the rest
+ of the parameter/data bytes */
+ outsize = set_message(outbuf,0,0,True);
+ if (!send_smb(smbd_server_fd(),outbuf))
+ exit_server("reply_nttrans: send_smb failed.");
+
+ while( num_data_sofar < total_data_count || num_params_sofar < total_parameter_count) {
+ BOOL ret;
+
+ ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
+
+ if((ret && (CVAL(inbuf, smb_com) != SMBnttranss)) || !ret) {
+ outsize = set_message(outbuf,0,0,True);
+ if(ret) {
+ DEBUG(0,("reply_nttrans: Invalid secondary nttrans packet\n"));
+ } else {
+ DEBUG(0,("reply_nttrans: %s in getting secondary nttrans response.\n",
+ (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
}
-
- if (Protocol >= PROTOCOL_NT1)
- SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_IS_LONG_NAME);
-
- /* Now we must call the relevant NT_TRANS function */
- switch(function_code) {
- case NT_TRANSACT_CREATE:
- START_PROFILE_NESTED(NT_transact_create);
- outsize = call_nt_transact_create(conn, inbuf, outbuf,
- length, bufsize,
- &setup, &params, &data);
- END_PROFILE_NESTED(NT_transact_create);
- break;
- case NT_TRANSACT_IOCTL:
- START_PROFILE_NESTED(NT_transact_ioctl);
- outsize = call_nt_transact_ioctl(conn, inbuf, outbuf,
- length, bufsize,
- &setup, setup_count,
- &params, parameter_count,
- &data, data_count);
- END_PROFILE_NESTED(NT_transact_ioctl);
- break;
- case NT_TRANSACT_SET_SECURITY_DESC:
- START_PROFILE_NESTED(NT_transact_set_security_desc);
- outsize = call_nt_transact_set_security_desc(conn, inbuf, outbuf,
- length, bufsize,
- &setup, &params, &data);
- END_PROFILE_NESTED(NT_transact_set_security_desc);
- break;
- case NT_TRANSACT_NOTIFY_CHANGE:
- START_PROFILE_NESTED(NT_transact_notify_change);
- outsize = call_nt_transact_notify_change(conn, inbuf, outbuf,
- length, bufsize,
- &setup, &params, &data);
- END_PROFILE_NESTED(NT_transact_notify_change);
- break;
- case NT_TRANSACT_RENAME:
- START_PROFILE_NESTED(NT_transact_rename);
- outsize = call_nt_transact_rename(conn, inbuf, outbuf,
- length, bufsize,
- &setup, &params, &data);
- END_PROFILE_NESTED(NT_transact_rename);
- break;
-
- case NT_TRANSACT_QUERY_SECURITY_DESC:
- START_PROFILE_NESTED(NT_transact_query_security_desc);
- outsize = call_nt_transact_query_security_desc(conn, inbuf, outbuf,
- length, bufsize,
- &setup, &params, &data);
- END_PROFILE_NESTED(NT_transact_query_security_desc);
- break;
- default:
- /* Error in request */
- DEBUG(0,("reply_nttrans: Unknown request %d in nttrans call\n", function_code));
- SAFE_FREE(setup);
- SAFE_FREE(params);
- SAFE_FREE(data);
- END_PROFILE(SMBnttrans);
- return ERROR_DOS(ERRSRV,ERRerror);
- }
-
- /* As we do not know how many data packets will need to be
- returned here the various call_nt_transact_xxxx calls
- must send their own. Thus a call_nt_transact_xxxx routine only
- returns a value other than -1 when it wants to send
- an error packet.
- */
-
- SAFE_FREE(setup);
- SAFE_FREE(params);
- SAFE_FREE(data);
+ SAFE_FREE(params);
+ SAFE_FREE(data);
+ SAFE_FREE(setup);
END_PROFILE(SMBnttrans);
- return outsize; /* If a correct response was needed the call_nt_transact_xxxx
- calls have already sent it. If outsize != -1 then it is
- returning an error packet. */
+ return ERROR_DOS(ERRSRV,ERRerror);
+ }
+
+ /* Revise total_params and total_data in case they have changed downwards */
+ total_parameter_count = IVAL(inbuf, smb_nts_TotalParameterCount);
+ total_data_count = IVAL(inbuf, smb_nts_TotalDataCount);
+ num_params_sofar += (parameter_count = IVAL(inbuf,smb_nts_ParameterCount));
+ num_data_sofar += ( data_count = IVAL(inbuf, smb_nts_DataCount));
+ if (num_params_sofar > total_parameter_count || num_data_sofar > total_data_count)
+ exit_server("reply_nttrans2: data overflow in secondary nttrans packet");
+
+ memcpy( &params[ IVAL(inbuf, smb_nts_ParameterDisplacement)],
+ smb_base(inbuf) + IVAL(inbuf, smb_nts_ParameterOffset), parameter_count);
+ memcpy( &data[IVAL(inbuf, smb_nts_DataDisplacement)],
+ smb_base(inbuf)+ IVAL(inbuf, smb_nts_DataOffset), data_count);
+ }
+ }
+
+ if (Protocol >= PROTOCOL_NT1)
+ SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_IS_LONG_NAME);
+
+ /* Now we must call the relevant NT_TRANS function */
+ switch(function_code) {
+ case NT_TRANSACT_CREATE:
+ START_PROFILE_NESTED(NT_transact_create);
+ outsize = call_nt_transact_create(conn, inbuf, outbuf, length, bufsize,
+ &setup, &params, &data);
+ END_PROFILE_NESTED(NT_transact_create);
+ break;
+ case NT_TRANSACT_IOCTL:
+ START_PROFILE_NESTED(NT_transact_ioctl);
+ outsize = call_nt_transact_ioctl(conn, inbuf, outbuf,
+ length, bufsize,
+ &setup, setup_count,
+ &params, parameter_count,
+ &data, data_count);
+ END_PROFILE_NESTED(NT_transact_ioctl);
+ break;
+ case NT_TRANSACT_SET_SECURITY_DESC:
+ START_PROFILE_NESTED(NT_transact_set_security_desc);
+ outsize = call_nt_transact_set_security_desc(conn, inbuf, outbuf,
+ length, bufsize,
+ &setup, &params, &data);
+ END_PROFILE_NESTED(NT_transact_set_security_desc);
+ break;
+ case NT_TRANSACT_NOTIFY_CHANGE:
+ START_PROFILE_NESTED(NT_transact_notify_change);
+ outsize = call_nt_transact_notify_change(conn, inbuf, outbuf,
+ length, bufsize,
+ &setup, &params, &data);
+ END_PROFILE_NESTED(NT_transact_notify_change);
+ break;
+ case NT_TRANSACT_RENAME:
+ START_PROFILE_NESTED(NT_transact_rename);
+ outsize = call_nt_transact_rename(conn, inbuf, outbuf, length,
+ bufsize,
+ &setup, &params, &data);
+ END_PROFILE_NESTED(NT_transact_rename);
+ break;
+
+ case NT_TRANSACT_QUERY_SECURITY_DESC:
+ START_PROFILE_NESTED(NT_transact_query_security_desc);
+ outsize = call_nt_transact_query_security_desc(conn, inbuf, outbuf,
+ length, bufsize,
+ &setup, &params, &data);
+ END_PROFILE_NESTED(NT_transact_query_security_desc);
+ break;
+ default:
+ /* Error in request */
+ DEBUG(0,("reply_nttrans: Unknown request %d in nttrans call\n", function_code));
+ SAFE_FREE(setup);
+ SAFE_FREE(params);
+ SAFE_FREE(data);
+ END_PROFILE(SMBnttrans);
+ return ERROR_DOS(ERRSRV,ERRerror);
+ }
+
+ /* As we do not know how many data packets will need to be
+ returned here the various call_nt_transact_xxxx calls
+ must send their own. Thus a call_nt_transact_xxxx routine only
+ returns a value other than -1 when it wants to send
+ an error packet.
+ */
+
+ SAFE_FREE(setup);
+ SAFE_FREE(params);
+ SAFE_FREE(data);
+ END_PROFILE(SMBnttrans);
+ return outsize; /* If a correct response was needed the call_nt_transact_xxxx
+ calls have already sent it. If outsize != -1 then it is
+ returning an error packet. */
}