Ejemplo n.º 1
0
Archivo: rpc.c Proyecto: d0rian/FreeRDP
int rpc_recv_pdu_header(rdpRpc* rpc, BYTE* header)
{
	int status;
	int bytesRead;
	UINT32 offset;
    
	/* Read common header fields */
    
	bytesRead = 0;
    
	while (bytesRead < RPC_COMMON_FIELDS_LENGTH)
	{
		status = rpc_out_read(rpc, &header[bytesRead], RPC_COMMON_FIELDS_LENGTH - bytesRead);
        
		if (status < 0)
		{
			printf("rpc_recv_pdu_header: error reading header\n");
			return status;
		}
        
		bytesRead += status;
	}

	rpc_get_stub_data_info(rpc, header, &offset, NULL);

	while (bytesRead < offset)
	{
		status = rpc_out_read(rpc, &header[bytesRead], offset - bytesRead);
        
		if (status < 0)
			return status;
        
		bytesRead += status;
	}
    
	return bytesRead;
}
Ejemplo n.º 2
0
Archivo: rpc.c Proyecto: atong/FreeRDP
int rpc_recv_bind_ack_pdu(rdpRpc* rpc)
{
    BYTE* p;
    STREAM* s;
    int status;
    BYTE* pdu;
    BYTE* auth_data;
    RPC_PDU_HEADER header;
    int pdu_length = 0x8FFF;

    pdu = malloc(pdu_length);

    if (pdu == NULL)
        return -1;

    status = rpc_out_read(rpc, pdu, pdu_length);

    if (status > 0)
    {
        s = stream_new(0);
        stream_attach(s, pdu, pdu_length);
        rpc_pdu_header_read(s, &header);
        stream_detach(s);
        stream_free(s);

        auth_data = malloc(header.auth_length);

        if (auth_data == NULL)
        {
            free(pdu);
            return -1;
        }

        p = (pdu + (header.frag_length - header.auth_length));
        memcpy(auth_data, p, header.auth_length);

        rpc->ntlm->inputBuffer.pvBuffer = auth_data;
        rpc->ntlm->inputBuffer.cbBuffer = header.auth_length;

        ntlm_authenticate(rpc->ntlm);
    }

    free(pdu);
    return status;
}
Ejemplo n.º 3
0
int rpc_client_on_read_event(rdpRpc* rpc)
{
	int position;
	int status = -1;
	rpcconn_common_hdr_t* header;

	if (!rpc->client->RecvFrag)
		rpc->client->RecvFrag = rpc_client_fragment_pool_take(rpc);

	position = Stream_GetPosition(rpc->client->RecvFrag);

	if (Stream_GetPosition(rpc->client->RecvFrag) < RPC_COMMON_FIELDS_LENGTH)
	{
		status = rpc_out_read(rpc, Stream_Pointer(rpc->client->RecvFrag),
				RPC_COMMON_FIELDS_LENGTH - Stream_GetPosition(rpc->client->RecvFrag));

		if (status < 0)
		{
			fprintf(stderr, "rpc_client_frag_read: error reading header\n");
			return -1;
		}

		Stream_Seek(rpc->client->RecvFrag, status);
	}

	if (Stream_GetPosition(rpc->client->RecvFrag) >= RPC_COMMON_FIELDS_LENGTH)
	{
		header = (rpcconn_common_hdr_t*) Stream_Buffer(rpc->client->RecvFrag);

		if (header->frag_length > rpc->max_recv_frag)
		{
			fprintf(stderr, "rpc_client_frag_read: invalid fragment size: %d (max: %d)\n",
					header->frag_length, rpc->max_recv_frag);
			winpr_HexDump(Stream_Buffer(rpc->client->RecvFrag), Stream_GetPosition(rpc->client->RecvFrag));
			return -1;
		}

		if (Stream_GetPosition(rpc->client->RecvFrag) < header->frag_length)
		{
			status = rpc_out_read(rpc, Stream_Pointer(rpc->client->RecvFrag),
					header->frag_length - Stream_GetPosition(rpc->client->RecvFrag));

			if (status < 0)
			{
				fprintf(stderr, "rpc_client_frag_read: error reading fragment body\n");
				return -1;
			}

			Stream_Seek(rpc->client->RecvFrag, status);
		}
	}
	else
	{
		return status;
	}

	if (status < 0)
		return -1;

	status = Stream_GetPosition(rpc->client->RecvFrag) - position;

	if (Stream_GetPosition(rpc->client->RecvFrag) >= header->frag_length)
	{
		/* complete fragment received */

		Stream_Length(rpc->client->RecvFrag) = Stream_GetPosition(rpc->client->RecvFrag);
		Stream_SetPosition(rpc->client->RecvFrag, 0);

		Queue_Enqueue(rpc->client->FragmentQueue, rpc->client->RecvFrag);
		rpc->client->RecvFrag = NULL;

		rpc_client_on_fragment_received_event(rpc);
	}

	return status;
}
Ejemplo n.º 4
0
int rpc_read(rdpRpc* rpc, uint8* data, int length)
{
	int status;
	int read = 0;
	int data_length;
	uint16 frag_length;
	uint16 auth_length;
	uint8 auth_pad_length;
	uint32 call_id = -1;
	int rpc_length = length + 0xFF;
	uint8* rpc_data = xmalloc(rpc_length);

	if (rpc_data == NULL)
	{
		printf("rpc_read error: memory allocation failed\n") ;
		return -1 ;
	}

	if (rpc->read_buffer_len > 0)
	{
		if (rpc->read_buffer_len > (uint32) length)
		{
			printf("rpc_read error: receiving buffer is not large enough\n");
			xfree(rpc_data) ;
			return -1;
		}

		memcpy(data, rpc->read_buffer, rpc->read_buffer_len);
		read += rpc->read_buffer_len;
		xfree(rpc->read_buffer);
		rpc->read_buffer_len = 0;
	}

	while (true)
	{
		status = rpc_out_read(rpc, rpc_data, rpc_length);

		if (status == 0)
		{
			xfree(rpc_data);
			return read;
		}
		else if (status < 0)
		{
			printf("Error! rpc_out_read() returned negative value. BytesSent: %d, BytesReceived: %d\n",
					rpc->VirtualConnection->DefaultInChannel->BytesSent,
					rpc->VirtualConnection->DefaultOutChannel->BytesReceived);

			xfree(rpc_data);
			return status;
		}

		frag_length = *(uint16*)(rpc_data + 8);
		auth_length = *(uint16*)(rpc_data + 10);
		call_id = *(uint32*)(rpc_data + 12);
		status = *(uint32*)(rpc_data + 16); /* alloc_hint */
		auth_pad_length = *(rpc_data + frag_length - auth_length - 6); /* -6 = -8 + 2 (sec_trailer + 2) */

		/* data_length must be calculated because alloc_hint carries size of more than one pdu */
		data_length = frag_length - auth_length - 24 - 8 - auth_pad_length; /* 24 is header; 8 is sec_trailer */

		if (status == 4)
			continue;

		if (read + data_length > length) /* if read data is greater then given buffer */
		{
			rpc->read_buffer_len = read + data_length - length;
			rpc->read_buffer = xmalloc(rpc->read_buffer_len);

			data_length -= rpc->read_buffer_len;

			memcpy(rpc->read_buffer, rpc_data + 24 + data_length, rpc->read_buffer_len);
		}

		memcpy(data + read, rpc_data + 24, data_length);

		read += data_length;

		if (status > data_length && read < length)
			continue;

		break;
	}

	xfree(rpc_data);
	return read;
}
Ejemplo n.º 5
0
Archivo: rpc.c Proyecto: d0rian/FreeRDP
int rpc_recv_pdu_fragment(rdpRpc* rpc)
{
	int status;
	int headerLength;
	int bytesRead = 0;
	rpcconn_hdr_t* header;

	WaitForSingleObject(rpc->VirtualConnection->DefaultInChannel->Mutex, INFINITE);

	status = rpc_recv_pdu_header(rpc, rpc->FragBuffer);
    
	if (status < 1)
	{
		printf("rpc_recv_pdu_header: error reading header\n");
		return status;
	}
    
	headerLength = status;
	header = (rpcconn_hdr_t*) rpc->FragBuffer;
	bytesRead += status;
	
	if (header->common.frag_length > rpc->FragBufferSize)
	{
		rpc->FragBufferSize = header->common.frag_length;
		rpc->FragBuffer = (BYTE*) realloc(rpc->FragBuffer, rpc->FragBufferSize);
		header = (rpcconn_hdr_t*) rpc->FragBuffer;
	}

	while (bytesRead < header->common.frag_length)
	{
		status = rpc_out_read(rpc, &rpc->FragBuffer[bytesRead], header->common.frag_length - bytesRead);

		if (status < 0)
		{
			printf("rpc_recv_pdu: error reading fragment\n");
			return status;
		}

		bytesRead += status;
	}

	ReleaseMutex(rpc->VirtualConnection->DefaultInChannel->Mutex);

	if (header->common.ptype == PTYPE_RTS) /* RTS PDU */
	{
		if (rpc->VirtualConnection->State < VIRTUAL_CONNECTION_STATE_OPENED)
			return header->common.frag_length;

		printf("Receiving Out-of-Sequence RTS PDU\n");
		rts_recv_out_of_sequence_pdu(rpc, rpc->FragBuffer, header->common.frag_length);

		return rpc_recv_pdu_fragment(rpc);
	}
	else if (header->common.ptype == PTYPE_FAULT)
	{
		rpc_recv_fault_pdu(header);
		return -1;
	}

	rpc->VirtualConnection->DefaultOutChannel->BytesReceived += header->common.frag_length;
	rpc->VirtualConnection->DefaultOutChannel->ReceiverAvailableWindow -= header->common.frag_length;

#if 0
	printf("BytesReceived: %d ReceiverAvailableWindow: %d ReceiveWindow: %d\n",
			rpc->VirtualConnection->DefaultOutChannel->BytesReceived,
			rpc->VirtualConnection->DefaultOutChannel->ReceiverAvailableWindow,
			rpc->ReceiveWindow);
#endif

	if (rpc->VirtualConnection->DefaultOutChannel->ReceiverAvailableWindow < (rpc->ReceiveWindow / 2))
	{
		printf("Sending Flow Control Ack PDU\n");
		rts_send_flow_control_ack_pdu(rpc);
	}

#ifdef WITH_DEBUG_RPC
	rpc_pdu_header_print((rpcconn_hdr_t*) header);
	printf("rpc_recv_pdu_fragment: length: %d\n", header->common.frag_length);
	freerdp_hexdump(rpc->FragBuffer, header->common.frag_length);
	printf("\n");
#endif

	return header->common.frag_length;
}