diff --git a/libfreerdp/core/peer.c b/libfreerdp/core/peer.c index 5adb4bf4f..0d7b56f78 100644 --- a/libfreerdp/core/peer.c +++ b/libfreerdp/core/peer.c @@ -379,6 +379,11 @@ static int peer_recv_tpkt_pdu(freerdp_peer* client, wStream* s) return -1; break; + case PDU_TYPE_FLOW_RESPONSE: + case PDU_TYPE_FLOW_STOP: + case PDU_TYPE_FLOW_TEST: + break; + default: WLog_ERR(TAG, "Client sent pduType %d", pduType); return -1; diff --git a/libfreerdp/core/rdp.c b/libfreerdp/core/rdp.c index 914140b7c..3439a9cee 100644 --- a/libfreerdp/core/rdp.c +++ b/libfreerdp/core/rdp.c @@ -112,6 +112,15 @@ BOOL rdp_read_share_control_header(wStream* s, UINT16* length, UINT16* type, UIN /* Share Control Header */ Stream_Read_UINT16(s, *length); /* totalLength */ + /* If length is 0x8000 then we actually got a flow control PDU that we should ignore + http://msdn.microsoft.com/en-us/library/cc240576.aspx */ + if (*length == 0x8000) + { + rdp_read_flow_control_pdu(s, type); + *length = 8; /* Flow control PDU is 8 bytes */ + return TRUE; + } + if (((size_t) *length - 2) > Stream_GetRemainingLength(s)) return FALSE; @@ -894,12 +903,36 @@ int rdp_recv_out_of_sequence_pdu(rdpRdp* rdp, wStream* s) { return rdp_recv_enhanced_security_redirection_packet(rdp, s); } + else if (type == PDU_TYPE_FLOW_RESPONSE || + type == PDU_TYPE_FLOW_STOP || + type == PDU_TYPE_FLOW_TEST) + { + return 0; + } else { return -1; } } +void rdp_read_flow_control_pdu(wStream* s, UINT16* type) +{ + /* + * Read flow control PDU - documented in FlowPDU section in T.128 + * http://www.itu.int/rec/T-REC-T.128-199802-S/en + * The specification for the PDU has pad8bits listed BEFORE pduTypeFlow. + * However, so far pad8bits has always been observed to arrive AFTER pduTypeFlow. + * Switched the order of these two fields to match this observation. + */ + UINT8 pduType; + Stream_Read_UINT8(s, pduType); /* pduTypeFlow */ + *type = pduType; + Stream_Seek_UINT8(s); /* pad8bits */ + Stream_Seek_UINT8(s); /* flowIdentifier */ + Stream_Seek_UINT8(s); /* flowNumber */ + Stream_Seek_UINT16(s); /* pduSource */ +} + /** * Decrypt an RDP packet.\n * @param rdp RDP module @@ -1058,6 +1091,11 @@ static int rdp_recv_tpkt_pdu(rdpRdp* rdp, wStream* s) case PDU_TYPE_SERVER_REDIRECTION: return rdp_recv_enhanced_security_redirection_packet(rdp, s); break; + + case PDU_TYPE_FLOW_RESPONSE: + case PDU_TYPE_FLOW_STOP: + case PDU_TYPE_FLOW_TEST: + break; default: WLog_ERR(TAG, "incorrect PDU type: 0x%04X", pduType); diff --git a/libfreerdp/core/rdp.h b/libfreerdp/core/rdp.h index 68edca9bd..4b6a84781 100644 --- a/libfreerdp/core/rdp.h +++ b/libfreerdp/core/rdp.h @@ -83,6 +83,10 @@ #define PDU_TYPE_DATA 0x7 #define PDU_TYPE_SERVER_REDIRECTION 0xA +#define PDU_TYPE_FLOW_TEST 0x41 +#define PDU_TYPE_FLOW_RESPONSE 0x42 +#define PDU_TYPE_FLOW_STOP 0x43 + #define FINALIZE_SC_SYNCHRONIZE_PDU 0x01 #define FINALIZE_SC_CONTROL_COOPERATE_PDU 0x02 #define FINALIZE_SC_CONTROL_GRANTED_PDU 0x04 @@ -206,6 +210,8 @@ int rdp_recv_message_channel_pdu(rdpRdp* rdp, wStream* s); int rdp_recv_out_of_sequence_pdu(rdpRdp* rdp, wStream* s); +void rdp_read_flow_control_pdu(wStream* s, UINT16* type); + void rdp_set_blocking_mode(rdpRdp* rdp, BOOL blocking); int rdp_check_fds(rdpRdp* rdp);