libfreerdp-core: refactoring of RPC header parsing

This commit is contained in:
Marc-André Moreau 2012-11-14 18:51:40 -05:00
parent 0dffd7bd49
commit 3aa043584d
3 changed files with 87 additions and 70 deletions

View File

@ -960,33 +960,77 @@ int rpc_recv_fault_pdu(RPC_PDU_HEADER* header)
return 0;
}
int rpc_recv_pdu_header(rdpRpc* rpc, BYTE* header)
{
int status;
int bytesRead;
UINT32 offset;
RPC_PDU_HEADER* pCommonFields;
/* read first 20 bytes to get RPC common fields */
bytesRead = 0;
while (bytesRead < RPC_COMMON_FIELDS_LENGTH)
{
status = tls_read(rpc->tls_out, &header[bytesRead], RPC_COMMON_FIELDS_LENGTH - bytesRead);
if (status < 0)
{
printf("rpc_recv_pdu_header: error reading header\n");
return status;
}
bytesRead += status;
}
rpc_pdu_header_print((RPC_PDU_HEADER*) header);
pCommonFields = ((RPC_PDU_HEADER*) header);
offset = RPC_COMMON_FIELDS_LENGTH;
if (pCommonFields->ptype == PTYPE_RESPONSE)
{
offset += 4;
rpc_offset_align(&offset, 8);
}
else if (pCommonFields->ptype == PTYPE_REQUEST)
{
offset += 4;
rpc_offset_align(&offset, 8);
}
while (bytesRead < offset)
{
status = tls_read(rpc->tls_out, &header[bytesRead], offset - bytesRead);
if (status < 0)
return status;
bytesRead += status;
}
return bytesRead;
}
int rpc_recv_pdu(rdpRpc* rpc)
{
int status;
int headerLength;
int bytesRead = 0;
int totalBytesRead = 0;
RPC_PDU_HEADER* header;
RPC_PDU_HEADER fragHeader;
/* read first 20 bytes to get RPC PDU Header */
ZeroMemory(rpc->buffer, 20);
while (bytesRead < 20)
{
status = tls_read(rpc->tls_out, &rpc->buffer[bytesRead], 20 - bytesRead);
if (status < 0)
{
printf("rpc_recv_pdu: error reading header\n");
return status;
}
bytesRead += status;
}
header = (RPC_PDU_HEADER*) rpc->buffer;
rpc_pdu_header_print(header);
status = rpc_recv_pdu_header(rpc, rpc->buffer);
if (status < 1)
{
printf("rpc_recv_pdu_header: error reading header\n");
return status;
}
headerLength = status;
header = (RPC_PDU_HEADER*) rpc->buffer;
bytesRead += status;
if (header->frag_length > rpc->length)
{
@ -1007,55 +1051,16 @@ int rpc_recv_pdu(rdpRpc* rpc)
bytesRead += status;
}
if (headerLength > RPC_COMMON_FIELDS_LENGTH)
{
printf("RPC Stub Data:\n");
freerdp_hexdump(&rpc->buffer[headerLength], header->frag_length - headerLength);
}
if (!(header->pfc_flags & PFC_LAST_FRAG))
{
totalBytesRead = bytesRead;
CopyMemory(&fragHeader, header, sizeof(RPC_PDU_HEADER));
printf("Fragmented PDU\n");
#if 0
while (!(fragHeader.pfc_flags & PFC_LAST_FRAG))
{
bytesRead = 0;
printf("Reading Fragment Header\n");
while (bytesRead < 20)
{
status = tls_read(rpc->tls_out, &((BYTE*) &fragHeader)[bytesRead], 20 - bytesRead);
if (status < 0)
{
printf("rpc_recv_pdu: error reading fragment header\n");
return status;
}
bytesRead += status;
}
if (fragHeader.frag_length > rpc->length)
{
rpc->length = header->frag_length;
rpc->buffer = (BYTE*) realloc(rpc->buffer, rpc->length);
header = (RPC_PDU_HEADER*) rpc->buffer;
}
while (totalBytesRead < (fragHeader.frag_length - 20))
{
status = tls_read(rpc->tls_out, &rpc->buffer[totalBytesRead], fragHeader.frag_length - totalBytesRead);
if (status < 0)
{
printf("rpc_recv_pdu: error reading fragment\n");
return status;
}
totalBytesRead += status;
}
}
#endif
}
if (header->ptype == PTYPE_RTS) /* RTS PDU */

View File

@ -60,6 +60,16 @@ typedef struct rdp_ntlm_http rdpNtlmHttp;
UINT16 auth_length; \
UINT32 call_id
#define RPC_COMMON_FIELDS_LENGTH 20
/**
* The PDU maximum header length is enough
* to contain either the RPC common fields
* or all fields up to the stub data in PDUs
* that use it (request, response, fault)
*/
#define RPC_PDU_HEADER_MAX_LENGTH 32
struct _rpc_pdu_header
{
DEFINE_RPC_COMMON_FIELDS();
@ -420,7 +430,7 @@ typedef struct
/* optional field for request, only present if the PFC_OBJECT_UUID field is non-zero */
p_uuid_t object; /* 24:16 object UID */
p_uuid_t object; /* 24:16 object UUID */
/* stub data, 8-octet aligned */
@ -612,6 +622,8 @@ UINT32 rpc_offset_pad(UINT32* offset, UINT32 pad);
int rpc_out_write(rdpRpc* rpc, BYTE* data, int length);
int rpc_in_write(rdpRpc* rpc, BYTE* data, int length);
int rpc_recv_pdu_header(rdpRpc* rpc, BYTE* header);
int rpc_recv_pdu(rdpRpc* rpc);
int rpc_out_read(rdpRpc* rpc, BYTE* data, int length);

View File

@ -1101,6 +1101,7 @@ int tsg_read(rdpTsg* tsg, BYTE* data, UINT32 length)
int copyLength;
RPC_PDU_HEADER* header;
rdpRpc* rpc = tsg->rpc;
BYTE buffer[RPC_PDU_HEADER_MAX_LENGTH];
printf("tsg_read: %d, pending: %d\n", length, tsg->pendingPdu);
@ -1121,9 +1122,8 @@ int tsg_read(rdpTsg* tsg, BYTE* data, UINT32 length)
}
else
{
status = rpc_recv_pdu(rpc);
header = (RPC_PDU_HEADER*) rpc->buffer;
status = rpc_recv_pdu_header(rpc, buffer);
header = (RPC_PDU_HEADER*) buffer;
if (header->frag_length == 64)
{