diff --git a/libfreerdp/core/rpc.c b/libfreerdp/core/rpc.c index 9799a6f7f..4a9693671 100644 --- a/libfreerdp/core/rpc.c +++ b/libfreerdp/core/rpc.c @@ -960,16 +960,45 @@ int rpc_recv_fault_pdu(RPC_PDU_HEADER* header) return 0; } +BOOL rpc_get_stub_data_info(rdpRpc* rpc, BYTE* header, UINT32* offset, UINT32* length) +{ + RPC_PDU_HEADER* pCommonFields; + + *offset = RPC_COMMON_FIELDS_LENGTH; + pCommonFields = ((RPC_PDU_HEADER*) header); + + 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); + } + else + { + return FALSE; + } + + if (length) + { + *length = pCommonFields->frag_length - (pCommonFields->auth_length + *offset); + } + + return TRUE; +} + int rpc_recv_pdu_header(rdpRpc* rpc, BYTE* header) { int status; int bytesRead; - UINT32 offset; - RPC_PDU_HEADER* pCommonFields; + UINT32 offset; /* read first 20 bytes to get RPC common fields */ - bytesRead = 0; + bytesRead = 0; while (bytesRead < RPC_COMMON_FIELDS_LENGTH) { @@ -985,52 +1014,40 @@ int rpc_recv_pdu_header(rdpRpc* rpc, BYTE* header) } 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); + rpc_get_stub_data_info(rpc, header, &offset, NULL); + + while (bytesRead < offset) + { + status = tls_read(rpc->tls_out, &header[bytesRead], offset - bytesRead); - if (status < 0) - return status; + if (status < 0) + return status; - bytesRead += status; - } + bytesRead += status; + } - return bytesRead; + return bytesRead; } int rpc_recv_pdu(rdpRpc* rpc) { int status; - int headerLength; + int headerLength; int bytesRead = 0; RPC_PDU_HEADER* header; - status = rpc_recv_pdu_header(rpc, rpc->buffer); + status = rpc_recv_pdu_header(rpc, rpc->buffer); - if (status < 1) - { - printf("rpc_recv_pdu_header: error reading header\n"); - return status; - } + if (status < 1) + { + printf("rpc_recv_pdu_header: error reading header\n"); + return status; + } - headerLength = status; - header = (RPC_PDU_HEADER*) rpc->buffer; - bytesRead += status; + headerLength = status; + header = (RPC_PDU_HEADER*) rpc->buffer; + bytesRead += status; if (header->frag_length > rpc->length) { @@ -1051,12 +1068,6 @@ 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)) { diff --git a/libfreerdp/core/rpc.h b/libfreerdp/core/rpc.h index da7969572..d670f54b0 100644 --- a/libfreerdp/core/rpc.h +++ b/libfreerdp/core/rpc.h @@ -622,6 +622,7 @@ 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); +BOOL rpc_get_stub_data_info(rdpRpc* rpc, BYTE* header, UINT32* offset, UINT32* length); int rpc_recv_pdu_header(rdpRpc* rpc, BYTE* header); int rpc_recv_pdu(rdpRpc* rpc); diff --git a/libfreerdp/core/tsg.c b/libfreerdp/core/tsg.c index a6aa6357a..b93e1050e 100644 --- a/libfreerdp/core/tsg.c +++ b/libfreerdp/core/tsg.c @@ -1098,32 +1098,31 @@ BOOL tsg_connect(rdpTsg* tsg, const char* hostname, UINT16 port) int tsg_read(rdpTsg* tsg, BYTE* data, UINT32 length) { int status; - int copyLength; + 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); + printf("tsg_read: %d, pending: %d\n", length, tsg->PendingPdu); - if (tsg->pendingPdu) + if (tsg->PendingPdu) { header = (RPC_PDU_HEADER*) rpc->buffer; - copyLength = (tsg->bytesAvailable > length) ? length : tsg->bytesAvailable; + CopyLength = (tsg->BytesAvailable > length) ? length : tsg->BytesAvailable; - CopyMemory(data, &rpc->buffer[tsg->bytesRead], copyLength); - tsg->bytesAvailable -= copyLength; - tsg->bytesRead += copyLength; + CopyMemory(data, &rpc->buffer[tsg->StubOffset + tsg->BytesRead], CopyLength); + tsg->BytesAvailable -= CopyLength; + tsg->BytesRead += CopyLength; - if (tsg->bytesAvailable < 1) - tsg->pendingPdu = FALSE; + if (tsg->BytesAvailable < 1) + tsg->PendingPdu = FALSE; - return copyLength; + return CopyLength; } else { - status = rpc_recv_pdu_header(rpc, buffer); - header = (RPC_PDU_HEADER*) buffer; + status = rpc_recv_pdu(rpc); + header = (RPC_PDU_HEADER*) rpc->buffer; if (header->frag_length == 64) { @@ -1131,17 +1130,26 @@ int tsg_read(rdpTsg* tsg, BYTE* data, UINT32 length) return tsg_read(tsg, data, length); } - tsg->pendingPdu = TRUE; - tsg->bytesAvailable = header->frag_length; - tsg->bytesRead = 0; + if (!rpc_get_stub_data_info(rpc, rpc->buffer, &tsg->StubOffset, &tsg->StubLength)) + { + printf("tsg_read error: expected stub\n"); + return -1; + } - copyLength = (tsg->bytesAvailable > length) ? length : tsg->bytesAvailable; + tsg->PendingPdu = TRUE; + tsg->BytesAvailable = tsg->StubLength; + tsg->BytesRead = 0; - CopyMemory(data, &rpc->buffer[tsg->bytesRead], copyLength); - tsg->bytesAvailable -= copyLength; - tsg->bytesRead += copyLength; + printf("RPC Stub (offset: %d length: %d):\n", tsg->StubOffset, tsg->StubLength); + freerdp_hexdump(&rpc->buffer[tsg->StubOffset], tsg->StubLength); - return copyLength; + CopyLength = (tsg->BytesAvailable > length) ? length : tsg->BytesAvailable; + + CopyMemory(data, &rpc->buffer[tsg->StubOffset + tsg->BytesRead], CopyLength); + tsg->BytesAvailable -= CopyLength; + tsg->BytesRead += CopyLength; + + return CopyLength; } } @@ -1161,7 +1169,7 @@ rdpTsg* tsg_new(rdpTransport* transport) tsg->transport = transport; tsg->settings = transport->settings; tsg->rpc = rpc_new(tsg->transport); - tsg->pendingPdu = FALSE; + tsg->PendingPdu = FALSE; } return tsg; diff --git a/libfreerdp/core/tsg.h b/libfreerdp/core/tsg.h index c0e7b0896..abadd845c 100644 --- a/libfreerdp/core/tsg.h +++ b/libfreerdp/core/tsg.h @@ -45,9 +45,11 @@ struct rdp_tsg UINT16 Port; LPWSTR Hostname; LPWSTR MachineName; - BOOL pendingPdu; - BOOL bytesRead; - BOOL bytesAvailable; + BOOL PendingPdu; + BOOL BytesRead; + BOOL BytesAvailable; + UINT32 StubOffset; + UINT32 StubLength; rdpSettings* settings; rdpTransport* transport; CONTEXT_HANDLE TunnelContext;