Esempio n. 1
0
void named_pipe_packet_process(struct tevent_req *subreq)
{
	struct named_pipe_client *npc =
		tevent_req_callback_data(subreq, struct named_pipe_client);
	struct _output_data *out = &npc->p->out_data;
	DATA_BLOB recv_buffer = data_blob_null;
	struct ncacn_packet *pkt;
	NTSTATUS status;
	uint32_t to_send;
	size_t i;
	bool ok;

	status = dcerpc_read_ncacn_packet_recv(subreq, npc, &pkt, &recv_buffer);
	TALLOC_FREE(subreq);
	if (!NT_STATUS_IS_OK(status)) {
		goto fail;
	}

	/* dcerpc_read_ncacn_packet_recv() returns a full PDU */
	npc->p->in_data.pdu_needed_len = 0;
	npc->p->in_data.pdu = recv_buffer;
	if (dcerpc_get_endian_flag(&recv_buffer) & DCERPC_DREP_LE) {
		npc->p->endian = RPC_LITTLE_ENDIAN;
	} else {
		npc->p->endian = RPC_BIG_ENDIAN;
	}
	DEBUG(10, ("PDU is in %s Endian format!\n",
		   npc->p->endian ? "Big" : "Little"));
	process_complete_pdu(npc->p, pkt);

	/* reset pipe state and free PDU */
	npc->p->in_data.pdu.length = 0;
	talloc_free(recv_buffer.data);
	talloc_free(pkt);

	/* this is needed because of the way DCERPC Binds work in
	 * the RPC marshalling code */
	to_send = out->frag.length - out->current_pdu_sent;
	if (to_send > 0) {

		npc->iov = talloc_zero(npc, struct iovec);
		if (!npc->iov) {
			status = NT_STATUS_NO_MEMORY;
			goto fail;
		}
		npc->count = 1;

		npc->iov[0].iov_base = out->frag.data
					+ out->current_pdu_sent;
		npc->iov[0].iov_len = to_send;

		out->current_pdu_sent += to_send;
	}
Esempio n. 2
0
ssize_t process_incoming_data(struct pipes_struct *p, char *data, size_t n)
{
	size_t data_to_copy = MIN(n, RPC_MAX_PDU_FRAG_LEN
					- p->in_data.pdu.length);

	DEBUG(10, ("process_incoming_data: Start: pdu.length = %u, "
		   "pdu_needed_len = %u, incoming data = %u\n",
		   (unsigned int)p->in_data.pdu.length,
		   (unsigned int)p->in_data.pdu_needed_len,
		   (unsigned int)n ));

	if(data_to_copy == 0) {
		/*
		 * This is an error - data is being received and there is no
		 * space in the PDU. Free the received data and go into the
		 * fault state.
		 */
		DEBUG(0, ("process_incoming_data: "
			  "No space in incoming pdu buffer. "
			  "Current size = %u incoming data size = %u\n",
			  (unsigned int)p->in_data.pdu.length,
			  (unsigned int)n));
		set_incoming_fault(p);
		return -1;
	}

	/*
	 * If we have no data already, wait until we get at least
	 * a RPC_HEADER_LEN * number of bytes before we can do anything.
	 */

	if ((p->in_data.pdu_needed_len == 0) &&
	    (p->in_data.pdu.length < RPC_HEADER_LEN)) {
		/*
		 * Always return here. If we have more data then the RPC_HEADER
		 * will be processed the next time around the loop.
		 */
		return fill_rpc_header(p, data, data_to_copy);
	}

	/*
	 * At this point we know we have at least an RPC_HEADER_LEN amount of
	 * data stored in p->in_data.pdu.
	 */

	/*
	 * If pdu_needed_len is zero this is a new pdu.
	 * Check how much more data we need, then loop again.
	 */
	if (p->in_data.pdu_needed_len == 0) {

		bool ok = get_pdu_size(p);
		if (!ok) {
			return -1;
		}
		if (p->in_data.pdu_needed_len > 0) {
			return 0;
		}

		/* If rret == 0 and pdu_needed_len == 0 here we have a PDU
		 * that consists of an RPC_HEADER only. This is a
		 * DCERPC_PKT_SHUTDOWN, DCERPC_PKT_CO_CANCEL or
		 * DCERPC_PKT_ORPHANED pdu type.
		 * Deal with this in process_complete_pdu(). */
	}

	/*
	 * Ok - at this point we have a valid RPC_HEADER.
	 * Keep reading until we have a full pdu.
	 */

	data_to_copy = MIN(data_to_copy, p->in_data.pdu_needed_len);

	/*
	 * Copy as much of the data as we need into the p->in_data.pdu buffer.
	 * pdu_needed_len becomes zero when we have a complete pdu.
	 */

	memcpy((char *)&p->in_data.pdu.data[p->in_data.pdu.length],
		data, data_to_copy);
	p->in_data.pdu.length += data_to_copy;
	p->in_data.pdu_needed_len -= data_to_copy;

	/*
	 * Do we have a complete PDU ?
	 * (return the number of bytes handled in the call)
	 */

	if(p->in_data.pdu_needed_len == 0) {
		process_complete_pdu(p);
		return data_to_copy;
	}

	DEBUG(10, ("process_incoming_data: not a complete PDU yet. "
		   "pdu.length = %u, pdu_needed_len = %u\n",
		   (unsigned int)p->in_data.pdu.length,
		   (unsigned int)p->in_data.pdu_needed_len));

	return (ssize_t)data_to_copy;
}