summaryrefslogtreecommitdiff
path: root/source3/smbd/nttrans.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/smbd/nttrans.c')
-rw-r--r--source3/smbd/nttrans.c960
1 files changed, 496 insertions, 464 deletions
diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c
index e0a0da7a75..cf69dfddb0 100644
--- a/source3/smbd/nttrans.c
+++ b/source3/smbd/nttrans.c
@@ -28,19 +28,19 @@ 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",
+ "\\netdfs",
+ NULL
};
/* Map generic permissions to file object specific permissions */
@@ -62,184 +62,183 @@ 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.
- */
-
- 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);
- }
+ 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;
- /*
- * Copy the param bytes into the packet.
- */
+ /*
+ * 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));
- if(params_sent_thistime)
- memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
-
- /*
- * Copy in the data bytes
- */
- if(data_sent_thistime)
- memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
- data_alignment_offset,pd,data_sent_thistime);
+ while (params_to_send || data_to_send) {
+
+ /*
+ * Calculate whether we will totally or partially fill this packet.
+ */
+
+ total_sent_thistime = params_to_send + data_to_send +
+ alignment_offset + data_alignment_offset;
+
+ /*
+ * We can never send more than useable_space.
+ */
+
+ total_sent_thistime = MIN(total_sent_thistime, useable_space);
+
+ set_message(outbuf, 18, total_sent_thistime, True);
+
+ /*
+ * Set total params and data to be sent.
+ */
+
+ SIVAL(outbuf,smb_ntr_TotalParameterCount,paramsize);
+ SIVAL(outbuf,smb_ntr_TotalDataCount,datasize);
+
+ /*
+ * Calculate how many parameters and data we can fit into
+ * this packet. Parameters get precedence.
+ */
+
+ params_sent_thistime = MIN(params_to_send,useable_space);
+ data_sent_thistime = useable_space - params_sent_thistime;
+ data_sent_thistime = MIN(data_sent_thistime,data_to_send);
+
+ SIVAL(outbuf,smb_ntr_ParameterCount,params_sent_thistime);
+
+ if(params_sent_thistime == 0) {
+ SIVAL(outbuf,smb_ntr_ParameterOffset,0);
+ SIVAL(outbuf,smb_ntr_ParameterDisplacement,0);
+ } else {
+ /*
+ * smb_ntr_ParameterOffset is the offset from the start of the SMB header to the
+ * parameter bytes, however the first 4 bytes of outbuf are
+ * the Netbios over TCP header. Thus use smb_base() to subtract
+ * them from the calculation.
+ */
+
+ SIVAL(outbuf,smb_ntr_ParameterOffset,
+ ((smb_buf(outbuf)+alignment_offset) - smb_base(outbuf)));
+ /*
+ * Absolute displacement of param bytes sent in this packet.
+ */
+
+ SIVAL(outbuf,smb_ntr_ParameterDisplacement,pp - params);
+ }
+
+ /*
+ * Deal with the data portion.
+ */
+
+ SIVAL(outbuf,smb_ntr_DataCount, data_sent_thistime);
+
+ if(data_sent_thistime == 0) {
+ SIVAL(outbuf,smb_ntr_DataOffset,0);
+ SIVAL(outbuf,smb_ntr_DataDisplacement, 0);
+ } else {
+ /*
+ * The offset of the data bytes is the offset of the
+ * parameter bytes plus the number of parameters being sent this time.
+ */
+
+ SIVAL(outbuf,smb_ntr_DataOffset,((smb_buf(outbuf)+alignment_offset) -
+ smb_base(outbuf)) + params_sent_thistime + data_alignment_offset);
+ SIVAL(outbuf,smb_ntr_DataDisplacement, pd - pdata);
+ }
+
+ /*
+ * Copy the param bytes into the packet.
+ */
+
+ if(params_sent_thistime)
+ memcpy((smb_buf(outbuf)+alignment_offset),pp,params_sent_thistime);
+
+ /*
+ * Copy in the data bytes
+ */
+
+ if(data_sent_thistime)
+ memcpy(smb_buf(outbuf)+alignment_offset+params_sent_thistime+
+ data_alignment_offset,pd,data_sent_thistime);
- DEBUG(9,("nt_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
- params_sent_thistime, data_sent_thistime, useable_space));
- DEBUG(9,("nt_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
- params_to_send, data_to_send, paramsize, datasize));
+ 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.");
+ /* 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;
+ pp += params_sent_thistime;
+ pd += data_sent_thistime;
- params_to_send -= params_sent_thistime;
- data_to_send -= data_sent_thistime;
+ params_to_send -= params_sent_thistime;
+ data_to_send -= data_sent_thistime;
- /*
- * Sanity check
- */
+ /*
+ * Sanity check
+ */
- if(params_to_send < 0 || data_to_send < 0) {
- DEBUG(0,("send_nt_replies failed sanity check pts = %d, dts = %d\n!!!",
- params_to_send, data_to_send));
- return -1;
- }
- }
+ 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;
+ return 0;
}
/****************************************************************************
@@ -852,7 +851,7 @@ int reply_ntcreate_and_X(connection_struct *conn,
p += 8;
SIVAL(p,0,fmode); /* File Attributes. */
p += 4;
- SOFF_T(p, 0, SMB_ROUNDUP_ALLOCATION(file_len));
+ SOFF_T(p, 0, get_allocation_size(&sbuf));
p += 8;
SOFF_T(p,0,file_len);
p += 12;
@@ -1296,7 +1295,7 @@ static int call_nt_transact_create(connection_struct *conn,
p += 8;
SIVAL(p,0,fmode); /* File Attributes. */
p += 4;
- SOFF_T(p, 0, SMB_ROUNDUP_ALLOCATION(file_len));
+ SOFF_T(p, 0, get_allocation_size(&sbuf));
p += 8;
SOFF_T(p,0,file_len);
@@ -1311,6 +1310,7 @@ static int call_nt_transact_create(connection_struct *conn,
/****************************************************************************
Reply to a NT CANCEL request.
****************************************************************************/
+
int reply_ntcancel(connection_struct *conn,
char *inbuf,char *outbuf,int length,int bufsize)
{
@@ -1332,6 +1332,7 @@ int reply_ntcancel(connection_struct *conn,
/****************************************************************************
Reply to an unsolicited SMBNTtranss - just ignore it!
****************************************************************************/
+
int reply_nttranss(connection_struct *conn,
char *inbuf,char *outbuf,int length,int bufsize)
{
@@ -1345,6 +1346,7 @@ 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,
@@ -1445,107 +1447,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;
}
/****************************************************************************
@@ -1592,233 +1594,263 @@ static int call_nt_transact_set_security_desc(connection_struct *conn,
}
/****************************************************************************
- Reply to IOCTL - not implemented - no plans.
+ Reply to NT IOCTL
****************************************************************************/
-
static int call_nt_transact_ioctl(connection_struct *conn,
char *inbuf, char *outbuf, int length,
int bufsize,
- char **ppsetup, char **ppparams, char **ppdata)
+ char **ppsetup, int setup_count,
+ char **ppparams, int parameter_count,
+ char **ppdata, int data_count)
{
- static BOOL logged_message = False;
+ unsigned fnum, control;
+ static BOOL logged_message;
- if(!logged_message) {
- DEBUG(3,("call_nt_transact_ioctl: Currently not implemented.\n"));
- logged_message = True; /* Only print this once... */
+ if (setup_count != 8) {
+ DEBUG(3,("call_nt_transact_ioctl: invalid setup count %d\n", setup_count));
+ return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
}
- return ERROR_DOS(ERRSRV,ERRnosupport);
+
+ fnum = SVAL(*ppsetup, 4);
+ control = IVAL(*ppsetup, 0);
+
+ 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 */
+ 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));
+ }
+ }
+
+ 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)) {
- /*
- * Queue this open message as we are the process of an oplock break.
- */
-
- DEBUG(2,("reply_nttrans: queueing message NT_TRANSACT_CREATE \
-due to being in oplock break state.\n" ));
-
- 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);
- }
+ 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);
+ }
- /* 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)) {
+ 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 (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);
- 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 (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, &params, &data);
- 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. */
+ 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. */
}