/****************************************************************************
do a switch on the message type, and return the response size
****************************************************************************/
static int switch_message(int type,char *inbuf,char *outbuf,
							int size,int bufsize, int ProcSockID, int threadid)
{
  int outsize = 0;
  static int num_smb_messages = 
    sizeof(smb_messages) / sizeof(struct smb_message_struct);
  int match;
//  extern int Client;
  connection_struct *conn;
//0703  last_message = type;

  /* make sure this is an SMB packet */
  if (strncmp(smb_base(inbuf),"\377SMB",4) != 0)
  {
//os  	kwait(NULL);
	cyg_thread_yield();
    return(-1);
  }

  for (match=0;match<num_smb_messages;match++)
    if (smb_messages[match].code == type)
      break;

  if (match == num_smb_messages)
  {
//Jesse      outsize = reply_unknown(inbuf,outbuf);
outsize = ERROR(ERRSRV,ERRaccess);
  }
  else
  {
    if (smb_messages[match].fn)
    {
//0609      int flags = smb_messages[match].flags;
//0609      static uint16 last_session_tag = UID_FIELD_INVALID;
	  uint16 session_tag = SVAL(inbuf,smb_uid);	

      /* Ensure this value is replaced in the incoming packet. */
      SSVAL(inbuf,smb_uid,session_tag);

//0703      last_inbuf = inbuf;
	  conn = conn_find(SVAL(inbuf, smb_tid), threadid);

	  if (conn)
	  	  conn->lastused = (msclock() /1000);  //add by ron 7/5/2001

      outsize = smb_messages[match].fn(conn,inbuf,outbuf,size,bufsize, ProcSockID, 
	   								   threadid);
    }
    else
    {
      outsize = reply_unknown(inbuf,outbuf);
    }
  }

  return(outsize);
}
Ejemplo n.º 2
0
int reply_pipe_write_and_X(char *inbuf,char *outbuf,int length,int bufsize)
{
	smb_np_struct *p = get_rpc_pipe_p(inbuf,smb_vwv2);
	uint16 vuid = SVAL(inbuf,smb_uid);
	size_t numtowrite = SVAL(inbuf,smb_vwv10);
	int nwritten = -1;
	int smb_doff = SVAL(inbuf, smb_vwv11);
	BOOL pipe_start_message_raw = ((SVAL(inbuf, smb_vwv7) & (PIPE_START_MESSAGE|PIPE_RAW_MODE)) ==
								(PIPE_START_MESSAGE|PIPE_RAW_MODE));
	char *data;

	if (!p) {
		return(ERROR_DOS(ERRDOS,ERRbadfid));
	}

	if (p->vuid != vuid) {
		return ERROR_NT(NT_STATUS_INVALID_HANDLE);
	}

	data = smb_base(inbuf) + smb_doff;

	if (numtowrite == 0) {
		nwritten = 0;
	} else {
		if(pipe_start_message_raw) {
			/*
			 * For the start of a message in named pipe byte mode,
			 * the first two bytes are a length-of-pdu field. Ignore
			 * them (we don't trust the client). JRA.
			 */
	 	       if(numtowrite < 2) {
				DEBUG(0,("reply_pipe_write_and_X: start of message set and not enough data sent.(%u)\n",
					(unsigned int)numtowrite ));
				return (UNIXERROR(ERRDOS,ERRnoaccess));
			}

			data += 2;
			numtowrite -= 2;
		}                        
		nwritten = write_to_pipe(p, data, numtowrite);
	}

	if ((nwritten == 0 && numtowrite != 0) || (nwritten < 0)) {
		return (UNIXERROR(ERRDOS,ERRnoaccess));
	}
  
	set_message(outbuf,6,0,True);

	nwritten = (pipe_start_message_raw ? nwritten + 2 : nwritten);
	SSVAL(outbuf,smb_vwv2,nwritten);
  
	DEBUG(3,("writeX-IPC pnum=%04x nwritten=%d\n", p->pnum, nwritten));

	return chain_reply(inbuf,outbuf,length,bufsize);
}
//#if 0
int reply_pipe_write_and_X(char *inbuf,char *outbuf,int length,int bufsize, int ProcSockID, int threadid)
{
	pipes_struct *p = get_rpc_pipe_p(inbuf,smb_vwv2, threadid);
	uint32 numtowrite = SVAL(inbuf,smb_vwv10);
	int nwritten = -1;
	int smb_doff = SVAL(inbuf, smb_vwv11);
	int pipe_start_message_raw = ((SVAL(inbuf, smb_vwv7) & (PIPE_START_MESSAGE|PIPE_RAW_MODE)) ==
									(PIPE_START_MESSAGE|PIPE_RAW_MODE));
	char *data;

	if (!p)
		return(ERROR(ERRDOS,ERRbadfid));

	data = smb_base(inbuf) + smb_doff;

	if (numtowrite == 0)
		nwritten = 0;
	else {
		if(pipe_start_message_raw) {
			/*
			 * For the start of a message in named pipe byte mode,
			 * the first two bytes are a length-of-pdu field. Ignore
			 * them (we don't trust the client. JRA.
			 */
		if(numtowrite < 2) {
//0507				DEBUG(0,("reply_pipe_write_and_X: start of message set and not enough data sent.(%u)\n",
//0507					(unsigned int)numtowrite ));
//0507				return (UNIXERROR(ERRDOS,ERRnoaccess));
				return 0;
			}

			data += 2;
			numtowrite -= 2;
	}                        
		nwritten = write_to_pipe(p, data, numtowrite);
	}

	if ((nwritten == 0 && numtowrite != 0) || (nwritten < 0))
//0507		return (UNIXERROR(ERRDOS,ERRnoaccess));
			return 0;	
	set_message(outbuf,6,0,True);

	nwritten = (pipe_start_message_raw ? nwritten + 2 : nwritten);
	SSVAL(outbuf,smb_vwv2,nwritten);
  
//0507	DEBUG(3,("writeX-IPC pnum=%04x nwritten=%d\n",
//0507		 p->pnum, nwritten));

	return chain_reply(inbuf,outbuf,length,bufsize, ProcSockID, threadid);
}
Ejemplo n.º 4
0
bool cli_receive_nt_trans(struct cli_state *cli,
			  char **param, unsigned int *param_len,
			  char **data, unsigned int *data_len)
{
	unsigned int total_data=0;
	unsigned int total_param=0;
	unsigned int this_data,this_param;
	uint8 eclass;
	uint32 ecode;
	bool ret = False;
	uint16_t mid;

	*data_len = *param_len = 0;

	mid = SVAL(cli->outbuf,smb_mid);

	if (!cli_receive_smb(cli)) {
		cli_state_seqnum_remove(cli, mid);
		return False;
	}

	show_msg(cli->inbuf);

	/* sanity check */
	if (CVAL(cli->inbuf,smb_com) != SMBnttrans) {
		DEBUG(0,("Expected SMBnttrans response, got command 0x%02x\n",
			 CVAL(cli->inbuf,smb_com)));
		cli_state_seqnum_remove(cli, mid);
		return(False);
	}

	/*
	 * An NT RPC pipe call can return ERRDOS, ERRmoredata
	 * to a trans call. This is not an error and should not
	 * be treated as such.
	 */
	if (cli_is_dos_error(cli)) {
                cli_dos_error(cli, &eclass, &ecode);
		if (!(eclass == ERRDOS && ecode == ERRmoredata)) {
			goto out;
		}
	}

	/*
	 * Likewise for NT_STATUS_BUFFER_TOO_SMALL
	 */
	if (cli_is_nt_error(cli)) {
		if (!NT_STATUS_EQUAL(cli_nt_error(cli),
				     NT_STATUS_BUFFER_TOO_SMALL)) {
			goto out;
		}
	}

	/* parse out the lengths */
	total_data = IVAL(cli->inbuf,smb_ntr_TotalDataCount);
	total_param = IVAL(cli->inbuf,smb_ntr_TotalParameterCount);
	/* Only allow 16 megs. */
	if (total_param > 16*1024*1024) {
		DEBUG(0,("cli_receive_nt_trans: param buffer too large %d\n",
					total_param));
		goto out;
	}
	if (total_data > 16*1024*1024) {
		DEBUG(0,("cli_receive_nt_trans: data buffer too large %d\n",
					total_data));
		goto out;
	}

	/* allocate it */
	if (total_data) {
		/* We know adding 2 is safe as total_data is less
		 * than 16mb (above). */
		*data = (char *)SMB_REALLOC(*data,total_data+2);
		if (!(*data)) {
			DEBUG(0,("cli_receive_nt_trans: failed to enlarge data buffer to %d\n",total_data));
			goto out;
		}
	}

	if (total_param) {
		/* We know adding 2 is safe as total_param is less
		 * than 16mb (above). */
		*param = (char *)SMB_REALLOC(*param,total_param+2);
		if (!(*param)) {
			DEBUG(0,("cli_receive_nt_trans: failed to enlarge param buffer to %d\n", total_param));
			goto out;
		}
	}

	while (1)  {
		this_data = SVAL(cli->inbuf,smb_ntr_DataCount);
		this_param = SVAL(cli->inbuf,smb_ntr_ParameterCount);

		if (this_data + *data_len > total_data ||
		    this_param + *param_len > total_param) {
			DEBUG(1,("Data overflow in cli_receive_nt_trans\n"));
			goto out;
		}

		if (this_data + *data_len < this_data ||
				this_data + *data_len < *data_len ||
				this_param + *param_len < this_param ||
				this_param + *param_len < *param_len) {
			DEBUG(1,("Data overflow in cli_receive_nt_trans\n"));
			goto out;
		}

		if (this_data) {
			unsigned int data_offset_out = SVAL(cli->inbuf,smb_ntr_DataDisplacement);
			unsigned int data_offset_in = SVAL(cli->inbuf,smb_ntr_DataOffset);

			if (data_offset_out > total_data ||
					data_offset_out + this_data > total_data ||
					data_offset_out + this_data < data_offset_out ||
					data_offset_out + this_data < this_data) {
				DEBUG(1,("Data overflow in cli_receive_nt_trans\n"));
				goto out;
			}
			if (data_offset_in > cli->bufsize ||
					data_offset_in + this_data >  cli->bufsize ||
					data_offset_in + this_data < data_offset_in ||
					data_offset_in + this_data < this_data) {
				DEBUG(1,("Data overflow in cli_receive_nt_trans\n"));
				goto out;
			}

			memcpy(*data + data_offset_out, smb_base(cli->inbuf) + data_offset_in, this_data);
		}

		if (this_param) {
			unsigned int param_offset_out = SVAL(cli->inbuf,smb_ntr_ParameterDisplacement);
			unsigned int param_offset_in = SVAL(cli->inbuf,smb_ntr_ParameterOffset);

			if (param_offset_out > total_param ||
					param_offset_out + this_param > total_param ||
					param_offset_out + this_param < param_offset_out ||
					param_offset_out + this_param < this_param) {
				DEBUG(1,("Param overflow in cli_receive_nt_trans\n"));
				goto out;
			}
			if (param_offset_in > cli->bufsize ||
					param_offset_in + this_param >  cli->bufsize ||
					param_offset_in + this_param < param_offset_in ||
					param_offset_in + this_param < this_param) {
				DEBUG(1,("Param overflow in cli_receive_nt_trans\n"));
				goto out;
			}

			memcpy(*param + param_offset_out, smb_base(cli->inbuf) + param_offset_in, this_param);
		}

		*data_len += this_data;
		*param_len += this_param;

		if (total_data <= *data_len && total_param <= *param_len) {
			ret = True;
			break;
		}

		if (!cli_receive_smb(cli)) {
			goto out;
		}

		show_msg(cli->inbuf);

		/* sanity check */
		if (CVAL(cli->inbuf,smb_com) != SMBnttrans) {
			DEBUG(0,("Expected SMBnttrans response, got command 0x%02x\n",
				 CVAL(cli->inbuf,smb_com)));
			goto out;
		}
		if (cli_is_dos_error(cli)) {
                        cli_dos_error(cli, &eclass, &ecode);
			if(!(eclass == ERRDOS && ecode == ERRmoredata)) {
				goto out;
			}
		}
		/*
		 * Likewise for NT_STATUS_BUFFER_TOO_SMALL
		 */
		if (cli_is_nt_error(cli)) {
			if (!NT_STATUS_EQUAL(cli_nt_error(cli),
					     NT_STATUS_BUFFER_TOO_SMALL)) {
				goto out;
			}
		}

		/* parse out the total lengths again - they can shrink! */
		if (IVAL(cli->inbuf,smb_ntr_TotalDataCount) < total_data)
			total_data = IVAL(cli->inbuf,smb_ntr_TotalDataCount);
		if (IVAL(cli->inbuf,smb_ntr_TotalParameterCount) < total_param)
			total_param = IVAL(cli->inbuf,smb_ntr_TotalParameterCount);

		if (total_data <= *data_len && total_param <= *param_len) {
			ret = True;
			break;
		}
	}

  out:

	cli_state_seqnum_remove(cli, mid);

	if (ret) {
		/* Ensure the last 2 bytes of param and data are 2 null
		 * bytes. These are malloc'ed, but not included in any
		 * length counts. This allows cli_XX string reading functions
		 * to safely null terminate. */
		if (total_data) {
			SSVAL(*data,total_data,0);
		}
		if (total_param) {
			SSVAL(*param,total_param,0);
		}
	}

	return ret;
}
Ejemplo n.º 5
0
bool cli_receive_trans(struct cli_state *cli,int trans,
                              char **param, unsigned int *param_len,
                              char **data, unsigned int *data_len)
{
	unsigned int total_data=0;
	unsigned int total_param=0;
	unsigned int this_data,this_param;
	NTSTATUS status;
	bool ret = False;
	uint16_t mid;

	*data_len = *param_len = 0;

	mid = SVAL(cli->outbuf,smb_mid);

	if (!cli_receive_smb(cli)) {
		cli_state_seqnum_remove(cli, mid);
		return False;
	}

	show_msg(cli->inbuf);

	/* sanity check */
	if (CVAL(cli->inbuf,smb_com) != trans) {
		DEBUG(0,("Expected %s response, got command 0x%02x\n",
			 trans==SMBtrans?"SMBtrans":"SMBtrans2",
			 CVAL(cli->inbuf,smb_com)));
		cli_state_seqnum_remove(cli, mid);
		return False;
	}

	/*
	 * An NT RPC pipe call can return ERRDOS, ERRmoredata
	 * to a trans call. This is not an error and should not
	 * be treated as such. Note that STATUS_NO_MORE_FILES is
	 * returned when a trans2 findfirst/next finishes.
	 * When setting up an encrypted transport we can also
	 * see NT_STATUS_MORE_PROCESSING_REQUIRED here.
         *
         * Vista returns NT_STATUS_INACCESSIBLE_SYSTEM_SHORTCUT if the folder
         * "<share>/Users/All Users" is enumerated.  This is a special pseudo
         * folder, and the response does not have parameters (nor a parameter
         * length).
	 */
	status = cli_nt_error(cli);

	if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
		if (NT_STATUS_IS_ERR(status) ||
                    NT_STATUS_EQUAL(status,STATUS_NO_MORE_FILES) ||
                    NT_STATUS_EQUAL(status,NT_STATUS_INACCESSIBLE_SYSTEM_SHORTCUT)) {
			goto out;
		}
	}

	/* parse out the lengths */
	total_data = SVAL(cli->inbuf,smb_tdrcnt);
	total_param = SVAL(cli->inbuf,smb_tprcnt);

	/* allocate it */
	if (total_data!=0) {
		/* We know adding 2 is safe as total_data is an
		 * SVAL <= 0xFFFF. */
		*data = (char *)SMB_REALLOC(*data,total_data+2);
		if (!(*data)) {
			DEBUG(0,("cli_receive_trans: failed to enlarge data buffer\n"));
			goto out;
		}
	}

	if (total_param!=0) {
		/* We know adding 2 is safe as total_param is an
		 * SVAL <= 0xFFFF. */
		*param = (char *)SMB_REALLOC(*param,total_param+2);
		if (!(*param)) {
			DEBUG(0,("cli_receive_trans: failed to enlarge param buffer\n"));
			goto out;
		}
	}

	for (;;)  {
		this_data = SVAL(cli->inbuf,smb_drcnt);
		this_param = SVAL(cli->inbuf,smb_prcnt);

		if (this_data + *data_len > total_data ||
		    this_param + *param_len > total_param) {
			DEBUG(1,("Data overflow in cli_receive_trans\n"));
			goto out;
		}

		if (this_data + *data_len < this_data ||
				this_data + *data_len < *data_len ||
				this_param + *param_len < this_param ||
				this_param + *param_len < *param_len) {
			DEBUG(1,("Data overflow in cli_receive_trans\n"));
			goto out;
		}

		if (this_data) {
			unsigned int data_offset_out = SVAL(cli->inbuf,smb_drdisp);
			unsigned int data_offset_in = SVAL(cli->inbuf,smb_droff);

			if (data_offset_out > total_data ||
					data_offset_out + this_data > total_data ||
					data_offset_out + this_data < data_offset_out ||
					data_offset_out + this_data < this_data) {
				DEBUG(1,("Data overflow in cli_receive_trans\n"));
				goto out;
			}
			if (data_offset_in > cli->bufsize ||
					data_offset_in + this_data >  cli->bufsize ||
					data_offset_in + this_data < data_offset_in ||
					data_offset_in + this_data < this_data) {
				DEBUG(1,("Data overflow in cli_receive_trans\n"));
				goto out;
			}

			memcpy(*data + data_offset_out, smb_base(cli->inbuf) + data_offset_in, this_data);
		}
		if (this_param) {
			unsigned int param_offset_out = SVAL(cli->inbuf,smb_prdisp);
			unsigned int param_offset_in = SVAL(cli->inbuf,smb_proff);

			if (param_offset_out > total_param ||
					param_offset_out + this_param > total_param ||
					param_offset_out + this_param < param_offset_out ||
					param_offset_out + this_param < this_param) {
				DEBUG(1,("Param overflow in cli_receive_trans\n"));
				goto out;
			}
			if (param_offset_in > cli->bufsize ||
					param_offset_in + this_param >  cli->bufsize ||
					param_offset_in + this_param < param_offset_in ||
					param_offset_in + this_param < this_param) {
				DEBUG(1,("Param overflow in cli_receive_trans\n"));
				goto out;
			}

			memcpy(*param + param_offset_out, smb_base(cli->inbuf) + param_offset_in, this_param);
		}
		*data_len += this_data;
		*param_len += this_param;

		if (total_data <= *data_len && total_param <= *param_len) {
			ret = True;
			break;
		}

		if (!cli_receive_smb(cli)) {
			goto out;
		}

		show_msg(cli->inbuf);

		/* sanity check */
		if (CVAL(cli->inbuf,smb_com) != trans) {
			DEBUG(0,("Expected %s response, got command 0x%02x\n",
				 trans==SMBtrans?"SMBtrans":"SMBtrans2", 
				 CVAL(cli->inbuf,smb_com)));
			goto out;
		}
		if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
			if (NT_STATUS_IS_ERR(cli_nt_error(cli))) {
				goto out;
			}
		}

		/* parse out the total lengths again - they can shrink! */
		if (SVAL(cli->inbuf,smb_tdrcnt) < total_data)
			total_data = SVAL(cli->inbuf,smb_tdrcnt);
		if (SVAL(cli->inbuf,smb_tprcnt) < total_param)
			total_param = SVAL(cli->inbuf,smb_tprcnt);

		if (total_data <= *data_len && total_param <= *param_len) {
			ret = True;
			break;
		}
	}

  out:

	cli_state_seqnum_remove(cli, mid);

	if (ret) {
		/* Ensure the last 2 bytes of param and data are 2 null
		 * bytes. These are malloc'ed, but not included in any
		 * length counts. This allows cli_XX string reading functions
		 * to safely null terminate. */
		if (total_data) {
			SSVAL(*data,total_data,0);
		}
		if (total_param) {
			SSVAL(*param,total_param,0);
		}
	}

	return ret;
}
Ejemplo n.º 6
0
/*
 * This routine checks first for "fast track" processing, as most
 * packets won't need to be copied. Otherwise, it allocates a new
 * packet to hold the incoming data.
 *
 * Note that the final server packet must be the larger of the two;
 * server packets aren't allowed to shrink.
 */
static int
smb_receive_trans2(struct smb_sb_info *server,
		   int *ldata, unsigned char **data,
		   int *lparm, unsigned char **parm)
{
	unsigned char *inbuf, *base, *rcv_buf = NULL;
	unsigned int parm_disp, parm_offset, parm_count, parm_tot, parm_len = 0;
	unsigned int data_disp, data_offset, data_count, data_tot, data_len = 0;
	unsigned int total_p = 0, total_d = 0, buf_len = 0;
	int result;

	while (1)
	{
		result = smb_receive(server);
		if (result < 0)
			goto out;
		inbuf = server->packet;
		if (server->rcls != 0)
		{
			*parm = *data = inbuf;
			*ldata = *lparm = 0;
			goto out;
		}
		/*
		 * Extract the control data from the packet.
		 */
		data_tot    = WVAL(inbuf, smb_tdrcnt);
		parm_tot    = WVAL(inbuf, smb_tprcnt);
		parm_disp   = WVAL(inbuf, smb_prdisp);
		parm_offset = WVAL(inbuf, smb_proff);
		parm_count  = WVAL(inbuf, smb_prcnt);
		data_disp   = WVAL(inbuf, smb_drdisp);
		data_offset = WVAL(inbuf, smb_droff);
		data_count  = WVAL(inbuf, smb_drcnt);
		base = smb_base(inbuf);

		/*
		 * Assume success and increment lengths.
		 */
		parm_len += parm_count;
		data_len += data_count;

		if (!rcv_buf)
		{
			/*
			 * Check for fast track processing ... just this packet.
			 */
			if (parm_count == parm_tot && data_count == data_tot)
			{
				VERBOSE("fast track, parm=%u %u %u, data=%u %u %u\n",
					parm_disp, parm_offset, parm_count, 
					data_disp, data_offset, data_count);

				*parm  = base + parm_offset;
				*data  = base + data_offset;
				goto success;
			}

			if (parm_tot > TRANS2_MAX_TRANSFER ||
	  		    data_tot > TRANS2_MAX_TRANSFER)
				goto out_too_long;

			/*
			 * Save the total parameter and data length.
			 */
			total_d = data_tot;
			total_p = parm_tot;

			buf_len = total_d + total_p;
			if (server->packet_size > buf_len)
				buf_len = server->packet_size;
			buf_len = smb_round_length(buf_len);

			rcv_buf = smb_vmalloc(buf_len);
			if (!rcv_buf)
				goto out_no_mem;
			*parm = rcv_buf;
			*data = rcv_buf + total_p;
		}
		else if (data_tot > total_d || parm_tot > total_p)
			goto out_data_grew;

		if (parm_disp + parm_count > total_p)
			goto out_bad_parm;
		if (data_disp + data_count > total_d)
			goto out_bad_data;
		memcpy(*parm + parm_disp, base + parm_offset, parm_count);
		memcpy(*data + data_disp, base + data_offset, data_count);

		PARANOIA("copied, parm=%u of %u, data=%u of %u\n",
			 parm_len, parm_tot, data_len, data_tot);

		/*
		 * Check whether we've received all of the data. Note that
		 * we use the packet totals -- total lengths might shrink!
		 */
		if (data_len >= data_tot && parm_len >= parm_tot)
			break;
	}

	/*
	 * Install the new packet.  Note that it's possible, though
	 * unlikely, that the new packet could be smaller than the
	 * old one, in which case we just copy the data.
	 */
	inbuf = server->packet;
	if (buf_len >= server->packet_size)
	{
		server->packet_size = buf_len;
		server->packet = rcv_buf;
		rcv_buf = inbuf;
	} else {
		PARANOIA("copying data, old size=%d, new size=%u\n",
			 server->packet_size, buf_len);
		memcpy(inbuf, rcv_buf, parm_len + data_len);
	}

success:
	*ldata = data_len;
	*lparm = parm_len;
out:
	if (rcv_buf)
		smb_vfree(rcv_buf);
	return result;

out_no_mem:
	printk(KERN_ERR "smb_receive_trans2: couldn't allocate data area\n");
	result = -ENOMEM;
	goto out;
out_too_long:
	printk(KERN_ERR "smb_receive_trans2: data/param too long, data=%d, parm=%d\n",
	       data_tot, parm_tot);
	goto out_error;
out_data_grew:
	printk(KERN_ERR "smb_receive_trans2: data/params grew!\n");
	goto out_error;
out_bad_parm:
	printk(KERN_ERR "smb_receive_trans2: invalid parms, disp=%d, cnt=%d, tot=%d\n",
	       parm_disp, parm_count, parm_tot);
	goto out_error;
out_bad_data:
	printk(KERN_ERR "smb_receive_trans2: invalid data, disp=%d, cnt=%d, tot=%d\n",
	       data_disp, data_count, data_tot);
out_error:
	result = -EIO;
	goto out;
}
Ejemplo n.º 7
0
void reply_pipe_write_and_X(struct smb_request *req)
{
	smb_np_struct *p = get_rpc_pipe_p(SVAL(req->inbuf,smb_vwv2));
	size_t numtowrite = SVAL(req->inbuf,smb_vwv10);
	int nwritten = -1;
	int smb_doff = SVAL(req->inbuf, smb_vwv11);
	bool pipe_start_message_raw =
		((SVAL(req->inbuf, smb_vwv7)
		  & (PIPE_START_MESSAGE|PIPE_RAW_MODE))
		 == (PIPE_START_MESSAGE|PIPE_RAW_MODE));
	char *data;

	if (!p) {
		reply_doserror(req, ERRDOS, ERRbadfid);
		return;
	}

	if (p->vuid != req->vuid) {
		reply_nterror(req, NT_STATUS_INVALID_HANDLE);
		return;
	}

	data = smb_base(req->inbuf) + smb_doff;

	if (numtowrite == 0) {
		nwritten = 0;
	} else {
		if(pipe_start_message_raw) {
			/*
			 * For the start of a message in named pipe byte mode,
			 * the first two bytes are a length-of-pdu field. Ignore
			 * them (we don't trust the client). JRA.
			 */
	 	       if(numtowrite < 2) {
				DEBUG(0,("reply_pipe_write_and_X: start of "
					 "message set and not enough data "
					 "sent.(%u)\n",
					 (unsigned int)numtowrite ));
				reply_unixerror(req, ERRDOS, ERRnoaccess);
				return;
			}

			data += 2;
			numtowrite -= 2;
		}                        
		nwritten = write_to_pipe(p, data, numtowrite);
	}

	if ((nwritten == 0 && numtowrite != 0) || (nwritten < 0)) {
		reply_unixerror(req, ERRDOS,ERRnoaccess);
		return;
	}

	reply_outbuf(req, 6, 0);

	nwritten = (pipe_start_message_raw ? nwritten + 2 : nwritten);
	SSVAL(req->outbuf,smb_vwv2,nwritten);
  
	DEBUG(3,("writeX-IPC pnum=%04x nwritten=%d\n", p->pnum, nwritten));

	chain_reply(req);
}