Esempio n. 1
0
/*
  append raw bytes into the data portion of the request packet
  return the number of bytes added
*/
size_t req_append_bytes(struct smbsrv_request *req, 
			const uint8_t *bytes, size_t byte_len)
{
	req_grow_allocation(req, byte_len + req->out.data_size);
	memcpy(req->out.data + req->out.data_size, bytes, byte_len);
	req_grow_data(req, byte_len + req->out.data_size);
	return byte_len;
}
Esempio n. 2
0
/*
  append variable block (type 5 buffer) into the data portion of the request packet
  return the number of bytes added
*/
size_t req_append_var_block(struct smbsrv_request *req, 
		const uint8_t *bytes, uint16_t byte_len)
{
	req_grow_allocation(req, byte_len + 3 + req->out.data_size);
	SCVAL(req->out.data + req->out.data_size, 0, 5);
	SSVAL(req->out.data + req->out.data_size, 1, byte_len);		/* add field length */
	if (byte_len > 0) {
		memcpy(req->out.data + req->out.data_size + 3, bytes, byte_len);
	}
	req_grow_data(req, byte_len + 3 + req->out.data_size);
	return byte_len + 3;
}
Esempio n. 3
0
/* 
   construct and send an error packet, then destroy the request 
   auto-converts to DOS error format when appropriate
*/
void smbsrv_send_error(struct smbsrv_request *req, NTSTATUS status)
{
	if (req->smb_conn->connection->event.fde == NULL) {
		/* the socket has been destroyed - no point trying to send an error! */
		talloc_free(req);
		return;
	}
	smbsrv_setup_reply(req, 0, 0);

	/* error returns never have any data */
	req_grow_data(req, 0);

	smbsrv_setup_error(req, status);
	smbsrv_send_reply(req);
}
Esempio n. 4
0
/*
  push a string into the data portion of the request packet, growing it if necessary
  this gets quite tricky - please be very careful to cover all cases when modifying this

  if dest is NULL, then put the string at the end of the data portion of the packet

  if dest_len is -1 then no limit applies
*/
size_t req_push_str(struct smbsrv_request *req, uint8_t *dest, const char *str, int dest_len, size_t flags)
{
	size_t len;
	unsigned int grow_size;
	uint8_t *buf0;
	const int max_bytes_per_char = 3;

	if (!(flags & (STR_ASCII|STR_UNICODE))) {
		flags |= (req->flags2 & FLAGS2_UNICODE_STRINGS) ? STR_UNICODE : STR_ASCII;
	}

	if (dest == NULL) {
		dest = req->out.data + req->out.data_size;
	}

	if (dest_len != -1) {
		len = dest_len;
	} else {
		len = (strlen(str)+2) * max_bytes_per_char;
	}

	grow_size = len + PTR_DIFF(dest, req->out.data);
	buf0 = req->out.buffer;

	req_grow_allocation(req, grow_size);

	if (buf0 != req->out.buffer) {
		dest = req->out.buffer + PTR_DIFF(dest, buf0);
	}

	len = push_string(dest, str, len, flags);

	grow_size = len + PTR_DIFF(dest, req->out.data);

	if (grow_size > req->out.data_size) {
		req_grow_data(req, grow_size);
	}

	return len;
}
Esempio n. 5
0
/*
  answer a reconstructed trans request
*/
static void reply_trans_send(struct ntvfs_request *ntvfs)
{
	struct smbsrv_request *req;
	struct trans_op *op;
	struct smb_trans2 *trans;
	uint16_t params_left, data_left;
	uint8_t *params, *data;
	int i;

	SMBSRV_CHECK_ASYNC_STATUS_ERR(op, struct trans_op);
	trans = op->trans;

	/* if this function needs work to form the nttrans reply buffer, then
	   call that now */
	if (op->send_fn != NULL) {
		NTSTATUS status;
		status = op->send_fn(op);
		if (!NT_STATUS_IS_OK(status)) {
			smbsrv_send_error(req, status);
			return;
		}
	}

	params_left = trans->out.params.length;
	data_left   = trans->out.data.length;
	params      = trans->out.params.data;
	data        = trans->out.data.data;

	smbsrv_setup_reply(req, 10 + trans->out.setup_count, 0);

	if (!NT_STATUS_IS_OK(req->ntvfs->async_states->status)) {
		smbsrv_setup_error(req, req->ntvfs->async_states->status);
	}

	/* we need to divide up the reply into chunks that fit into
	   the negotiated buffer size */
	do {
		uint16_t this_data, this_param, max_bytes;
		unsigned int align1 = 1, align2 = (params_left ? 2 : 0);
		struct smbsrv_request *this_req;

		max_bytes = req_max_data(req) - (align1 + align2);

		this_param = params_left;
		if (this_param > max_bytes) {
			this_param = max_bytes;
		}
		max_bytes -= this_param;

		this_data = data_left;
		if (this_data > max_bytes) {
			this_data = max_bytes;
		}

		/* don't destroy unless this is the last chunk */
		if (params_left - this_param != 0 || 
		    data_left - this_data != 0) {
			this_req = smbsrv_setup_secondary_request(req);
		} else {
			this_req = req;
		}

		req_grow_data(this_req, this_param + this_data + (align1 + align2));

		SSVAL(this_req->out.vwv, VWV(0), trans->out.params.length);
		SSVAL(this_req->out.vwv, VWV(1), trans->out.data.length);
		SSVAL(this_req->out.vwv, VWV(2), 0);

		SSVAL(this_req->out.vwv, VWV(3), this_param);
		SSVAL(this_req->out.vwv, VWV(4), align1 + PTR_DIFF(this_req->out.data, this_req->out.hdr));
		SSVAL(this_req->out.vwv, VWV(5), PTR_DIFF(params, trans->out.params.data));

		SSVAL(this_req->out.vwv, VWV(6), this_data);
		SSVAL(this_req->out.vwv, VWV(7), align1 + align2 + 
		      PTR_DIFF(this_req->out.data + this_param, this_req->out.hdr));
		SSVAL(this_req->out.vwv, VWV(8), PTR_DIFF(data, trans->out.data.data));

		SCVAL(this_req->out.vwv, VWV(9), trans->out.setup_count);
		SCVAL(this_req->out.vwv, VWV(9)+1, 0); /* reserved */
		for (i=0;i<trans->out.setup_count;i++) {
			SSVAL(this_req->out.vwv, VWV(10+i), trans->out.setup[i]);
		}

		memset(this_req->out.data, 0, align1);
		if (this_param != 0) {
			memcpy(this_req->out.data + align1, params, this_param);
		}
		memset(this_req->out.data+this_param+align1, 0, align2);
		if (this_data != 0) {
			memcpy(this_req->out.data+this_param+align1+align2, data, this_data);
		}

		params_left -= this_param;
		data_left -= this_data;
		params += this_param;
		data += this_data;

		smbsrv_send_reply(this_req);
	} while (params_left != 0 || data_left != 0);
}