From 5b4759b75de5d79c7846b227a55cedcc85dbbba2 Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Sun, 21 Aug 2011 22:52:37 +0800 Subject: [PATCH] server: process client control PDUs. --- libfreerdp-core/activation.c | 24 +++++++++- libfreerdp-core/activation.h | 3 +- libfreerdp-core/peer.c | 92 ++++++++++++++++++++++++++++++++++++ libfreerdp-core/rdp.c | 11 ++++- libfreerdp-core/rdp.h | 2 +- 5 files changed, 127 insertions(+), 5 deletions(-) diff --git a/libfreerdp-core/activation.c b/libfreerdp-core/activation.c index ffe899b11..1a9ac85bb 100644 --- a/libfreerdp-core/activation.c +++ b/libfreerdp-core/activation.c @@ -64,6 +64,21 @@ boolean rdp_send_server_synchronize_pdu(rdpRdp* rdp) return True; } +boolean rdp_read_client_synchronize_pdu(STREAM* s) +{ + uint16 messageType; + + if (stream_get_left(s) < 4) + return False; + + stream_read_uint16(s, messageType); /* messageType (2 bytes) */ + if (messageType != SYNCMSGTYPE_SYNC) + return False; + /* targetUser (2 bytes) */ + + return True; +} + boolean rdp_send_client_synchronize_pdu(rdpRdp* rdp) { STREAM* s; @@ -77,11 +92,16 @@ boolean rdp_send_client_synchronize_pdu(rdpRdp* rdp) return True; } -void rdp_read_server_control_pdu(STREAM* s, uint16* action) +boolean rdp_read_control_pdu(STREAM* s, uint16* action) { + if (stream_get_left(s) < 8) + return False; + stream_read_uint16(s, *action); /* action (2 bytes) */ stream_seek_uint16(s); /* grantId (2 bytes) */ stream_seek_uint32(s); /* controlId (4 bytes) */ + + return True; } void rdp_write_client_control_pdu(STREAM* s, uint16 action) @@ -95,7 +115,7 @@ void rdp_recv_server_control_pdu(rdpRdp* rdp, STREAM* s, rdpSettings* settings) { uint16 action; - rdp_read_server_control_pdu(s, &action); + rdp_read_control_pdu(s, &action); if (action == CTRLACTION_COOPERATE) { diff --git a/libfreerdp-core/activation.h b/libfreerdp-core/activation.h index 053112bbd..17a65a762 100644 --- a/libfreerdp-core/activation.h +++ b/libfreerdp-core/activation.h @@ -43,9 +43,10 @@ void rdp_recv_deactivate_all(rdpRdp* rdp, STREAM* s); void rdp_recv_server_synchronize_pdu(rdpRdp* rdp, STREAM* s, rdpSettings* settings); boolean rdp_send_server_synchronize_pdu(rdpRdp* rdp); +boolean rdp_read_client_synchronize_pdu(STREAM* s); boolean rdp_send_client_synchronize_pdu(rdpRdp* rdp); +boolean rdp_read_control_pdu(STREAM* s, uint16* action); void rdp_recv_server_control_pdu(rdpRdp* rdp, STREAM* s, rdpSettings* settings); -void rdp_read_server_control_pdu(STREAM* s, uint16* action); boolean rdp_send_server_control_cooperate_pdu(rdpRdp* rdp); boolean rdp_send_server_control_granted_pdu(rdpRdp* rdp); void rdp_send_client_control_pdu(rdpRdp* rdp, uint16 action); diff --git a/libfreerdp-core/peer.c b/libfreerdp-core/peer.c index c06e49160..72b3392a6 100644 --- a/libfreerdp-core/peer.c +++ b/libfreerdp-core/peer.c @@ -54,6 +54,93 @@ static boolean freerdp_peer_check_fds(freerdp_peer* client) return True; } +static boolean peer_read_data_pdu(rdpPeer* peer, STREAM* s) +{ + uint8 type; + uint16 length; + uint32 share_id; + uint16 action; + + if (!rdp_read_share_data_header(s, &length, &type, &share_id)) + return False; + + switch (type) + { + case DATA_PDU_TYPE_SYNCHRONIZE: + if (!rdp_read_client_synchronize_pdu(s)) + return False; + break; + + case DATA_PDU_TYPE_CONTROL: + if (!rdp_read_control_pdu(s, &action)) + return False; + if (action == CTRLACTION_REQUEST_CONTROL) + { + if (!rdp_send_server_control_granted_pdu(peer->rdp)) + return False; + } + break; + + default: + printf("Data PDU type %d\n", type); + break; + } + + return True; +} + +static boolean peer_read_tpkt_pdu(rdpPeer* peer, STREAM* s) +{ + uint16 length; + uint16 pduType; + uint16 pduLength; + uint16 channelId; + + if (!rdp_read_header(peer->rdp, s, &length, &channelId)) + { + printf("Incorrect RDP header.\n"); + return False; + } + + if (channelId != MCS_GLOBAL_CHANNEL_ID) + { + /* TODO: process channel data from client */ + } + else + { + if (!rdp_read_share_control_header(s, &pduLength, &pduType, &peer->rdp->settings->pdu_source)) + return False; + + switch (pduType) + { + case PDU_TYPE_DATA: + if (!peer_read_data_pdu(peer, s)) + return False; + break; + + default: + printf("Client sent pduType %d\n", pduType); + return False; + } + } + + return True; +} + +static boolean peer_read_fastpath_pdu(rdpPeer* peer, STREAM* s) +{ + printf("FastPath Input PDU\n"); + return True; +} + +static boolean peer_read_pdu(rdpPeer* peer, STREAM* s) +{ + if (tpkt_verify_header(s)) + return peer_read_tpkt_pdu(peer, s); + else + return peer_read_fastpath_pdu(peer, s); +} + static int peer_recv_callback(rdpTransport* transport, STREAM* s, void* extra) { rdpPeer* peer = (rdpPeer*)extra; @@ -95,6 +182,11 @@ static int peer_recv_callback(rdpTransport* transport, STREAM* s, void* extra) return -1; break; + case CONNECTION_STATE_ACTIVE: + if (!peer_read_pdu(peer, s)) + return -1; + break; + default: printf("Invalid state %d\n", peer->rdp->state); return -1; diff --git a/libfreerdp-core/rdp.c b/libfreerdp-core/rdp.c index dfac662ce..4612541d7 100644 --- a/libfreerdp-core/rdp.c +++ b/libfreerdp-core/rdp.c @@ -113,16 +113,25 @@ void rdp_write_share_control_header(STREAM* s, uint16 length, uint16 type, uint1 stream_write_uint16(s, channel_id); /* pduSource */ } -void rdp_read_share_data_header(STREAM* s, uint16* length, uint8* type, uint32* share_id) +boolean rdp_read_share_data_header(STREAM* s, uint16* length, uint8* type, uint32* share_id) { + if (stream_get_left(s) < 12) + return False; + /* Share Data Header */ stream_read_uint32(s, *share_id); /* shareId (4 bytes) */ stream_seek_uint8(s); /* pad1 (1 byte) */ stream_seek_uint8(s); /* streamId (1 byte) */ stream_read_uint16(s, *length); /* uncompressedLength (2 bytes) */ + + if (stream_get_left(s) < *length) + return False; + stream_read_uint8(s, *type); /* pduType2, Data PDU Type (1 byte) */ stream_seek_uint8(s); /* compressedType (1 byte) */ stream_seek_uint16(s); /* compressedLength (2 bytes) */ + + return True; } void rdp_write_share_data_header(STREAM* s, uint16 length, uint8 type, uint32 share_id) diff --git a/libfreerdp-core/rdp.h b/libfreerdp-core/rdp.h index 204a58485..8f49944d4 100644 --- a/libfreerdp-core/rdp.h +++ b/libfreerdp-core/rdp.h @@ -133,7 +133,7 @@ void rdp_write_security_header(STREAM* s, uint16 flags); boolean rdp_read_share_control_header(STREAM* s, uint16* length, uint16* type, uint16* channel_id); void rdp_write_share_control_header(STREAM* s, uint16 length, uint16 type, uint16 channel_id); -void rdp_read_share_data_header(STREAM* s, uint16* length, uint8* type, uint32* share_id); +boolean rdp_read_share_data_header(STREAM* s, uint16* length, uint8* type, uint32* share_id); void rdp_write_share_data_header(STREAM* s, uint16 length, uint8 type, uint32 share_id); STREAM* rdp_send_stream_init(rdpRdp* rdp);