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.c604
1 files changed, 316 insertions, 288 deletions
diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c
index 796eb44332..24d64ecfc7 100644
--- a/source3/smbd/nttrans.c
+++ b/source3/smbd/nttrans.c
@@ -1812,19 +1812,6 @@ int reply_ntrename(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)
-{
- START_PROFILE(SMBnttranss);
- DEBUG(4,("Ignoring nttranss of length %d\n",length));
- END_PROFILE(SMBnttranss);
- return(-1);
-}
-
-/****************************************************************************
Reply to a notify change - queue the request and
don't allow a directory to be opened.
****************************************************************************/
@@ -2719,29 +2706,120 @@ static int call_nt_transact_set_user_quota(connection_struct *conn, char *inbuf,
}
#endif /* HAVE_SYS_QUOTAS */
+static int handle_nttrans(connection_struct *conn,
+ struct trans_state *state,
+ char *inbuf, char *outbuf, int size, int bufsize)
+{
+ int outsize;
+
+ if (Protocol >= PROTOCOL_NT1) {
+ SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | 0x40); /* IS_LONG_NAME */
+ }
+
+ /* Now we must call the relevant NT_TRANS function */
+ switch(state->call) {
+ case NT_TRANSACT_CREATE:
+ START_PROFILE_NESTED(NT_transact_create);
+ outsize = call_nt_transact_create(conn, inbuf, outbuf,
+ size, bufsize,
+ (char **)&state->setup, state->setup_count,
+ &state->param, state->total_param,
+ &state->data, state->total_data,
+ state->max_data_return);
+ 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,
+ size, bufsize,
+ (char **)&state->setup, state->setup_count,
+ &state->param, state->total_param,
+ &state->data, state->total_data, state->max_data_return);
+ 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,
+ size, bufsize,
+ (char **)&state->setup, state->setup_count,
+ &state->param, state->total_param,
+ &state->data, state->total_data, state->max_data_return);
+ 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,
+ size, bufsize,
+ (char **)&state->setup, state->setup_count,
+ &state->param, state->total_param,
+ &state->data, state->total_data, state->max_data_return);
+ 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,
+ size, bufsize,
+ (char **)&state->setup, state->setup_count,
+ &state->param, state->total_param,
+ &state->data, state->total_data, state->max_data_return);
+ 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,
+ size, bufsize,
+ (char **)&state->setup, state->setup_count,
+ &state->param, state->total_param,
+ &state->data, state->total_data, state->max_data_return);
+ END_PROFILE_NESTED(NT_transact_query_security_desc);
+ break;
+#ifdef HAVE_SYS_QUOTAS
+ case NT_TRANSACT_GET_USER_QUOTA:
+ START_PROFILE_NESTED(NT_transact_get_user_quota);
+ outsize = call_nt_transact_get_user_quota(conn, inbuf, outbuf,
+ size, bufsize,
+ (char **)&state->setup, state->setup_count,
+ &state->param, state->total_param,
+ &state->data, state->total_data, state->max_data_return);
+ END_PROFILE_NESTED(NT_transact_get_user_quota);
+ break;
+ case NT_TRANSACT_SET_USER_QUOTA:
+ START_PROFILE_NESTED(NT_transact_set_user_quota);
+ outsize = call_nt_transact_set_user_quota(conn, inbuf, outbuf,
+ size, bufsize,
+ (char **)&state->setup, state->setup_count,
+ &state->param, state->total_param,
+ &state->data, state->total_data, state->max_data_return);
+ END_PROFILE_NESTED(NT_transact_set_user_quota);
+ break;
+#endif /* HAVE_SYS_QUOTAS */
+ default:
+ /* Error in request */
+ DEBUG(0,("reply_nttrans: Unknown request %d in nttrans call\n",
+ state->call));
+ return ERROR_DOS(ERRSRV,ERRerror);
+ }
+ return outsize;
+}
+
/****************************************************************************
Reply to a SMBNTtrans.
****************************************************************************/
int reply_nttrans(connection_struct *conn,
- char *inbuf,char *outbuf,int length,int bufsize)
+ char *inbuf,char *outbuf,int size,int bufsize)
{
int outsize = 0;
- uint32 max_data_count = IVAL(inbuf,smb_nt_MaxDataCount);
-#if 0 /* Not used. */
- uint16 max_setup_count = CVAL(inbuf, smb_nt_MaxSetupCount);
- uint32 max_parameter_count = IVAL(inbuf, smb_nt_MaxParameterCount);
-#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* */
+ uint32 pscnt = IVAL(inbuf,smb_nt_ParameterCount);
+ uint32 psoff = IVAL(inbuf,smb_nt_ParameterOffset);
+ uint32 dscnt = IVAL(inbuf,smb_nt_DataCount);
+ uint32 dsoff = IVAL(inbuf,smb_nt_DataOffset);
+
uint16 function_code = SVAL( inbuf, smb_nt_Function);
- char *params = NULL, *data = NULL, *setup = NULL;
- uint32 num_params_sofar, num_data_sofar;
+ NTSTATUS result;
+ struct trans_state *state;
+
START_PROFILE(SMBnttrans);
if (IS_IPC(conn) && (function_code != NT_TRANSACT_CREATE)) {
@@ -2749,319 +2827,269 @@ int reply_nttrans(connection_struct *conn,
return ERROR_DOS(ERRSRV,ERRaccess);
}
- outsize = set_message(outbuf,0,0,True);
+ if (!NT_STATUS_IS_OK(allow_new_trans(conn->pending_trans,
+ SVAL(inbuf, smb_mid)))) {
+ DEBUG(2, ("Got invalid nttrans request: %s\n", nt_errstr(result)));
+ END_PROFILE(SMBnttrans);
+ return ERROR_NT(result);
+ }
+
+ if ((state = TALLOC_P(NULL, struct trans_state)) == NULL) {
+ END_PROFILE(SMBnttrans);
+ return ERROR_DOS(ERRSRV,ERRaccess);
+ }
+
+ state->cmd = SMBnttrans;
+
+ state->mid = SVAL(inbuf,smb_mid);
+ state->vuid = SVAL(inbuf,smb_uid);
+ state->total_data = IVAL(inbuf, smb_nt_TotalDataCount);
+ state->data = NULL;
+ state->total_param = IVAL(inbuf, smb_nt_TotalParameterCount);
+ state->param = NULL;
+ state->max_data_return = IVAL(inbuf,smb_nt_MaxDataCount);
+
+ /* setup count is in *words* */
+ state->setup_count = 2*CVAL(inbuf,smb_nt_SetupCount);
+ state->call = function_code;
/*
- * All nttrans messages we handle have smb_wct == 19 + setup_count.
- * Ensure this is so as a sanity check.
+ * All nttrans messages we handle have smb_wct == 19 +
+ * state->setup_count. Ensure this is so as a sanity check.
*/
- if(CVAL(inbuf, smb_wct) != 19 + (setup_count/2)) {
+ if(CVAL(inbuf, smb_wct) != 19 + (state->setup_count/2)) {
DEBUG(2,("Invalid smb_wct %d in nttrans call (should be %d)\n",
- CVAL(inbuf, smb_wct), 19 + (setup_count/2)));
+ CVAL(inbuf, smb_wct), 19 + (state->setup_count/2)));
goto bad_param;
}
/* Don't allow more than 128mb for each value. */
- if ((total_parameter_count > (1024*1024*128)) || (total_data_count > (1024*1024*128))) {
+ if ((state->total_data > (1024*1024*128)) ||
+ (state->total_param > (1024*1024*128))) {
END_PROFILE(SMBnttrans);
return ERROR_DOS(ERRDOS,ERRnomem);
}
- /* Allocate the space for the setup, the maximum needed parameters and data */
-
- if(setup_count > 0) {
- setup = (char *)SMB_MALLOC(setup_count);
- }
- if (total_parameter_count > 0) {
- params = (char *)SMB_MALLOC(total_parameter_count);
- }
- if (total_data_count > 0) {
- data = (char *)SMB_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)
+ if ((dscnt > state->total_data) || (pscnt > state->total_param))
goto bad_param;
- if(setup) {
- DEBUG(10,("reply_nttrans: setup_count = %d\n", setup_count));
- if ((smb_nt_SetupStart + setup_count < smb_nt_SetupStart) ||
- (smb_nt_SetupStart + setup_count < setup_count)) {
+ if (state->total_data) {
+ /* Can't use talloc here, the core routines do realloc on the
+ * params and data. */
+ if ((state->data = SMB_MALLOC(state->total_data)) == NULL) {
+ DEBUG(0,("reply_nttrans: data malloc fail for %u "
+ "bytes !\n", state->total_data));
+ TALLOC_FREE(state);
+ END_PROFILE(SMBtrans);
+ return(ERROR_DOS(ERRDOS,ERRnomem));
+ }
+ if ((dsoff+dscnt < dsoff) || (dsoff+dscnt < dscnt))
goto bad_param;
- }
- if (smb_nt_SetupStart + setup_count > length) {
+ if ((smb_base(inbuf)+dsoff+dscnt > inbuf + size) ||
+ (smb_base(inbuf)+dsoff+dscnt < smb_base(inbuf)))
goto bad_param;
- }
- memcpy( setup, &inbuf[smb_nt_SetupStart], setup_count);
- dump_data(10, setup, setup_count);
+ memcpy(state->data,smb_base(inbuf)+dsoff,dscnt);
}
- if(params) {
- DEBUG(10,("reply_nttrans: parameter_count = %d\n", parameter_count));
- if ((parameter_offset + parameter_count < parameter_offset) ||
- (parameter_offset + parameter_count < parameter_count)) {
+
+ if (state->total_param) {
+ /* Can't use talloc here, the core routines do realloc on the
+ * params and data. */
+ if ((state->param = SMB_MALLOC(state->total_param)) == NULL) {
+ DEBUG(0,("reply_nttrans: param malloc fail for %u "
+ "bytes !\n", state->total_param));
+ SAFE_FREE(state->data);
+ TALLOC_FREE(state);
+ END_PROFILE(SMBtrans);
+ return(ERROR_DOS(ERRDOS,ERRnomem));
+ }
+ if ((psoff+pscnt < psoff) || (psoff+pscnt < pscnt))
goto bad_param;
- }
- if ((smb_base(inbuf) + parameter_offset + parameter_count > inbuf + length)||
- (smb_base(inbuf) + parameter_offset + parameter_count < smb_base(inbuf))) {
+ if ((smb_base(inbuf)+psoff+pscnt > inbuf + size) ||
+ (smb_base(inbuf)+psoff+pscnt < smb_base(inbuf)))
goto bad_param;
- }
- memcpy( params, smb_base(inbuf) + parameter_offset, parameter_count);
- dump_data(10, params, parameter_count);
+ memcpy(state->param,smb_base(inbuf)+psoff,pscnt);
}
- if(data) {
- DEBUG(10,("reply_nttrans: data_count = %d\n",data_count));
- if ((data_offset + data_count < data_offset) || (data_offset + data_count < data_count)) {
+
+ 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));
+ state->setup = TALLOC(state, state->setup_count);
+ if (state->setup == NULL) {
+ DEBUG(0,("reply_nttrans : Out of memory\n"));
+ SAFE_FREE(state->data);
+ SAFE_FREE(state->param);
+ TALLOC_FREE(state);
+ END_PROFILE(SMBnttrans);
+ return ERROR_DOS(ERRDOS,ERRnomem);
+ }
+
+ if ((smb_nt_SetupStart + state->setup_count < smb_nt_SetupStart) ||
+ (smb_nt_SetupStart + state->setup_count < state->setup_count)) {
goto bad_param;
}
- if ((smb_base(inbuf) + data_offset + data_count > inbuf + length) ||
- (smb_base(inbuf) + data_offset + data_count < smb_base(inbuf))) {
+ if (smb_nt_SetupStart + state->setup_count > size) {
goto bad_param;
}
- memcpy( data, smb_base(inbuf) + data_offset, data_count);
- dump_data(10, data, data_count);
+ memcpy( state->setup, &inbuf[smb_nt_SetupStart], state->setup_count);
+ dump_data(10, (char *)state->setup, state->setup_count);
}
- srv_signing_trans_start(SVAL(inbuf,smb_mid));
+ if ((state->received_data == state->total_data) &&
+ (state->received_param == state->total_param)) {
+ outsize = handle_nttrans(conn, state, inbuf, outbuf,
+ size, bufsize);
+ SAFE_FREE(state->param);
+ SAFE_FREE(state->data);
+ TALLOC_FREE(state);
+ END_PROFILE(SMBnttrans);
+ return outsize;
+ }
- 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);
- srv_signing_trans_stop();
- show_msg(outbuf);
- if (!send_smb(smbd_server_fd(),outbuf)) {
- exit_server("reply_nttrans: send_smb failed.");
- }
+ DLIST_ADD(conn->pending_trans, state);
- while( num_data_sofar < total_data_count || num_params_sofar < total_parameter_count) {
- BOOL ret;
- uint32 parameter_displacement;
- uint32 data_displacement;
+ /* We need to send an interim response then receive the rest
+ of the parameter/data bytes */
+ outsize = set_message(outbuf,0,0,True);
+ show_msg(outbuf);
+ END_PROFILE(SMBnttrans);
+ return outsize;
- ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
+ bad_param:
- /* We need to re-calcuate the new length after we've read the secondary packet. */
- length = smb_len(inbuf) + 4;
+ DEBUG(0,("reply_nttrans: invalid trans parameters\n"));
+ SAFE_FREE(state->data);
+ SAFE_FREE(state->param);
+ TALLOC_FREE(state);
+ END_PROFILE(SMBnttrans);
+ return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+}
+
+/****************************************************************************
+ Reply to a SMBnttranss
+ ****************************************************************************/
- /*
- * The sequence number for the trans reply is always
- * based on the last secondary received.
- */
+int reply_nttranss(connection_struct *conn, char *inbuf,char *outbuf,
+ int size,int bufsize)
+{
+ int outsize = 0;
+ unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
+ struct trans_state *state;
- srv_signing_trans_start(SVAL(inbuf,smb_mid));
+ START_PROFILE(SMBnttranss);
- 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" ));
- }
- goto bad_param;
- }
-
- /* Revise total_params and total_data in case they have changed downwards */
- if (IVAL(inbuf, smb_nts_TotalParameterCount) < total_parameter_count) {
- total_parameter_count = IVAL(inbuf, smb_nts_TotalParameterCount);
- }
- if (IVAL(inbuf, smb_nts_TotalDataCount) < total_data_count) {
- total_data_count = IVAL(inbuf, smb_nts_TotalDataCount);
- }
+ show_msg(inbuf);
- parameter_count = IVAL(inbuf,smb_nts_ParameterCount);
- parameter_offset = IVAL(inbuf, smb_nts_ParameterOffset);
- parameter_displacement = IVAL(inbuf, smb_nts_ParameterDisplacement);
- num_params_sofar += parameter_count;
+ for (state = conn->pending_trans; state != NULL;
+ state = state->next) {
+ if (state->mid == SVAL(inbuf,smb_mid)) {
+ break;
+ }
+ }
- data_count = IVAL(inbuf, smb_nts_DataCount);
- data_displacement = IVAL(inbuf, smb_nts_DataDisplacement);
- data_offset = IVAL(inbuf, smb_nts_DataOffset);
- num_data_sofar += data_count;
+ if ((state == NULL) || (state->cmd != SMBnttrans)) {
+ END_PROFILE(SMBnttranss);
+ return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+ }
- if (num_params_sofar > total_parameter_count || num_data_sofar > total_data_count) {
- DEBUG(0,("reply_nttrans2: data overflow in secondary nttrans packet"));
- goto bad_param;
- }
+ /* Revise state->total_param and state->total_data in case they have
+ changed downwards */
+ if (IVAL(inbuf, smb_nts_TotalParameterCount) < state->total_param) {
+ state->total_param = IVAL(inbuf, smb_nts_TotalParameterCount);
+ }
+ if (IVAL(inbuf, smb_nts_TotalDataCount) < state->total_data) {
+ state->total_data = IVAL(inbuf, smb_nts_TotalDataCount);
+ }
- if (parameter_count) {
- if (parameter_displacement + parameter_count > total_parameter_count) {
- goto bad_param;
- }
- if ((parameter_displacement + parameter_count < parameter_displacement) ||
- (parameter_displacement + parameter_count < parameter_count)) {
- goto bad_param;
- }
- if (parameter_displacement > total_parameter_count) {
- goto bad_param;
- }
- if ((smb_base(inbuf) + parameter_offset + parameter_count > inbuf + length) ||
- (smb_base(inbuf) + parameter_offset + parameter_count < smb_base(inbuf))) {
- goto bad_param;
- }
- if (parameter_displacement + params < params) {
- goto bad_param;
- }
+ pcnt = IVAL(inbuf,smb_nts_ParameterCount);
+ poff = IVAL(inbuf, smb_nts_ParameterOffset);
+ pdisp = IVAL(inbuf, smb_nts_ParameterDisplacement);
- memcpy( &params[parameter_displacement], smb_base(inbuf) + parameter_offset, parameter_count);
- }
+ dcnt = IVAL(inbuf, smb_nts_DataCount);
+ ddisp = IVAL(inbuf, smb_nts_DataDisplacement);
+ doff = IVAL(inbuf, smb_nts_DataOffset);
- if (data_count) {
- if (data_displacement + data_count > total_data_count) {
- goto bad_param;
- }
- if ((data_displacement + data_count < data_displacement) ||
- (data_displacement + data_count < data_count)) {
- goto bad_param;
- }
- if (data_displacement > total_data_count) {
- goto bad_param;
- }
- if ((smb_base(inbuf) + data_offset + data_count > inbuf + length) ||
- (smb_base(inbuf) + data_offset + data_count < smb_base(inbuf))) {
- goto bad_param;
- }
- if (data_displacement + data < data) {
- goto bad_param;
- }
+ state->received_param += pcnt;
+ state->received_data += dcnt;
+
+ if ((state->received_data > state->total_data) ||
+ (state->received_param > state->total_param))
+ goto bad_param;
- memcpy( &data[data_displacement], smb_base(inbuf)+ data_offset, data_count);
- }
- }
- }
+ if (pcnt) {
+ if (pdisp+pcnt > state->total_param)
+ goto bad_param;
+ if ((pdisp+pcnt < pdisp) || (pdisp+pcnt < pcnt))
+ goto bad_param;
+ if (pdisp > state->total_param)
+ goto bad_param;
+ if ((smb_base(inbuf) + poff + pcnt > inbuf + size) ||
+ (smb_base(inbuf) + poff + pcnt < smb_base(inbuf)))
+ goto bad_param;
+ if (state->param + pdisp < state->param)
+ goto bad_param;
- if (Protocol >= PROTOCOL_NT1) {
- SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_IS_LONG_NAME);
+ memcpy(state->param+pdisp,smb_base(inbuf)+poff,
+ pcnt);
}
- /* 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, setup_count,
- &params, total_parameter_count,
- &data, total_data_count, max_data_count);
- 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, total_parameter_count,
- &data, total_data_count, max_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, setup_count,
- &params, total_parameter_count,
- &data, total_data_count, max_data_count);
- 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, setup_count,
- &params, total_parameter_count,
- &data, total_data_count, max_data_count);
- 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, setup_count,
- &params, total_parameter_count,
- &data, total_data_count, max_data_count);
- END_PROFILE_NESTED(NT_transact_rename);
- break;
+ if (dcnt) {
+ if (ddisp+dcnt > state->total_data)
+ goto bad_param;
+ if ((ddisp+dcnt < ddisp) || (ddisp+dcnt < dcnt))
+ goto bad_param;
+ if (ddisp > state->total_data)
+ goto bad_param;
+ if ((smb_base(inbuf) + doff + dcnt > inbuf + size) ||
+ (smb_base(inbuf) + doff + dcnt < smb_base(inbuf)))
+ goto bad_param;
+ if (state->data + ddisp < state->data)
+ goto bad_param;
- 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, setup_count,
- &params, total_parameter_count,
- &data, total_data_count, max_data_count);
- END_PROFILE_NESTED(NT_transact_query_security_desc);
- break;
-#ifdef HAVE_SYS_QUOTAS
- case NT_TRANSACT_GET_USER_QUOTA:
- START_PROFILE_NESTED(NT_transact_get_user_quota);
- outsize = call_nt_transact_get_user_quota(conn, inbuf, outbuf,
- length, bufsize,
- &setup, setup_count,
- &params, total_parameter_count,
- &data, total_data_count, max_data_count);
- END_PROFILE_NESTED(NT_transact_get_user_quota);
- break;
- case NT_TRANSACT_SET_USER_QUOTA:
- START_PROFILE_NESTED(NT_transact_set_user_quota);
- outsize = call_nt_transact_set_user_quota(conn, inbuf, outbuf,
- length, bufsize,
- &setup, setup_count,
- &params, total_parameter_count,
- &data, total_data_count, max_data_count);
- END_PROFILE_NESTED(NT_transact_set_user_quota);
- break;
-#endif /* HAVE_SYS_QUOTAS */
- 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);
- srv_signing_trans_stop();
- return ERROR_DOS(ERRSRV,ERRerror);
+ memcpy(state->data+ddisp, smb_base(inbuf)+doff,
+ dcnt);
}
- /* As we do not know how many data packets will need to be
- returned here the various call_nt_transact_xxxx calls
- must send their own. Thus a call_nt_transact_xxxx routine only
- returns a value other than -1 when it wants to send
- an error packet.
- */
+ if ((state->received_param < state->total_param) ||
+ (state->received_data < state->total_data)) {
+ END_PROFILE(SMBnttranss);
+ return -1;
+ }
- srv_signing_trans_stop();
+ /* construct_reply_common has done us the favor to pre-fill the
+ * command field with SMBnttranss which is wrong :-)
+ */
+ SCVAL(outbuf,smb_com,SMBnttrans);
- 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. */
+ outsize = handle_nttrans(conn, state, inbuf, outbuf,
+ size, bufsize);
- bad_param:
+ DLIST_REMOVE(conn->pending_trans, state);
+ SAFE_FREE(state->data);
+ SAFE_FREE(state->param);
+ TALLOC_FREE(state);
- srv_signing_trans_stop();
- SAFE_FREE(params);
- SAFE_FREE(data);
- SAFE_FREE(setup);
- END_PROFILE(SMBnttrans);
+ if (outsize == 0) {
+ END_PROFILE(SMBnttranss);
+ return(ERROR_DOS(ERRSRV,ERRnosupport));
+ }
+
+ END_PROFILE(SMBnttranss);
+ return(outsize);
+
+ 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);
+ END_PROFILE(SMBnttranss);
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}