From 82bed4a0e86cc8d997c0c646ef866ba28f86d9c5 Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Sun, 21 Aug 2011 15:52:44 +0800 Subject: [PATCH] server: receive client capabilities. --- libfreerdp-core/capabilities.c | 78 +++++++++++++++++++++++++++------- libfreerdp-core/capabilities.h | 1 + libfreerdp-core/connection.c | 10 +++++ libfreerdp-core/connection.h | 1 + libfreerdp-core/peer.c | 5 +++ libfreerdp-core/rdp.c | 7 ++- libfreerdp-core/rdp.h | 2 +- 7 files changed, 87 insertions(+), 17 deletions(-) diff --git a/libfreerdp-core/capabilities.c b/libfreerdp-core/capabilities.c index d05fa47b8..57f25854d 100644 --- a/libfreerdp-core/capabilities.c +++ b/libfreerdp-core/capabilities.c @@ -775,6 +775,7 @@ void rdp_write_glyph_cache_capability_set(STREAM* s, rdpSettings* settings) rdp_write_cache_definition(s, 254, 16); rdp_write_cache_definition(s, 254, 32); rdp_write_cache_definition(s, 254, 64); + rdp_write_cache_definition(s, 254, 128); rdp_write_cache_definition(s, 254, 256); rdp_write_cache_definition(s, 64, 2048); @@ -1425,25 +1426,12 @@ void rdp_write_frame_acknowledge_capability_set(STREAM* s, rdpSettings* settings rdp_capability_set_finish(s, header, CAPSET_TYPE_FRAME_ACKNOWLEDGE); } -void rdp_read_demand_active(STREAM* s, rdpSettings* settings) +boolean rdp_read_capability_sets(STREAM* s, rdpSettings* settings, uint16 numberCapabilities) { uint16 type; uint16 length; uint8 *bm, *em; - uint16 numberCapabilities; - uint16 lengthSourceDescriptor; - uint16 lengthCombinedCapabilities; - //printf("Demand Active PDU\n"); - - stream_read_uint32(s, settings->share_id); /* shareId (4 bytes) */ - stream_read_uint16(s, lengthSourceDescriptor); /* lengthSourceDescriptor (2 bytes) */ - stream_read_uint16(s, lengthCombinedCapabilities); /* lengthCombinedCapabilities (2 bytes) */ - stream_seek(s, lengthSourceDescriptor); /* sourceDescriptor */ - stream_read_uint16(s, numberCapabilities); /* numberCapabilities (2 bytes) */ - stream_seek(s, 2); /* pad2Octets (2 bytes) */ - - /* capabilitySets */ while (numberCapabilities > 0) { stream_get_mark(s, bm); @@ -1453,6 +1441,9 @@ void rdp_read_demand_active(STREAM* s, rdpSettings* settings) settings->received_caps[type] = True; em = bm + length; + if (stream_get_left(s) < length - 4) + return False; + switch (type) { case CAPSET_TYPE_GENERAL: @@ -1568,15 +1559,38 @@ void rdp_read_demand_active(STREAM* s, rdpSettings* settings) break; default: + printf("unknown capability type %d\n", type); break; } if (s->p != em) - printf("incorrect offset, actual:%d expected:%d\n", (int) (s->p - bm), (int) (em - bm)); + printf("incorrect offset, type:%d actual:%d expected:%d\n", + type, (int) (s->p - bm), (int) (em - bm)); stream_set_mark(s, em); numberCapabilities--; } + + return True; +} + +void rdp_read_demand_active(STREAM* s, rdpSettings* settings) +{ + uint16 numberCapabilities; + uint16 lengthSourceDescriptor; + uint16 lengthCombinedCapabilities; + + //printf("Demand Active PDU\n"); + + stream_read_uint32(s, settings->share_id); /* shareId (4 bytes) */ + stream_read_uint16(s, lengthSourceDescriptor); /* lengthSourceDescriptor (2 bytes) */ + stream_read_uint16(s, lengthCombinedCapabilities); /* lengthCombinedCapabilities (2 bytes) */ + stream_seek(s, lengthSourceDescriptor); /* sourceDescriptor */ + stream_read_uint16(s, numberCapabilities); /* numberCapabilities (2 bytes) */ + stream_seek(s, 2); /* pad2Octets (2 bytes) */ + + /* capabilitySets */ + rdp_read_capability_sets(s, settings, numberCapabilities); } void rdp_recv_demand_active(rdpRdp* rdp, STREAM* s, rdpSettings* settings) @@ -1648,6 +1662,40 @@ boolean rdp_send_demand_active(rdpRdp* rdp) return True; } +boolean rdp_read_confirm_active(rdpRdp* rdp, STREAM* s) +{ + uint16 length; + uint16 channelId; + uint16 pduType; + uint16 pduLength; + uint16 lengthSourceDescriptor; + uint16 lengthCombinedCapabilities; + uint16 numberCapabilities; + + if (!rdp_read_header(rdp, s, &length, &channelId)) + return False; + if (channelId != MCS_GLOBAL_CHANNEL_ID) + return False; + + if (!rdp_read_share_control_header(s, &pduLength, &pduType, &rdp->settings->pdu_source)) + return False; + if (pduType != PDU_TYPE_CONFIRM_ACTIVE) + return False; + + stream_seek_uint32(s); /* shareId (4 bytes) */ + stream_seek_uint16(s); /* originatorId (2 bytes) */ + stream_read_uint16(s, lengthSourceDescriptor); /* lengthSourceDescriptor (2 bytes) */ + stream_read_uint16(s, lengthCombinedCapabilities); /* lengthCombinedCapabilities (2 bytes) */ + stream_seek(s, lengthSourceDescriptor); /* sourceDescriptor */ + stream_read_uint16(s, numberCapabilities); /* numberCapabilities (2 bytes) */ + stream_seek(s, 2); /* pad2Octets (2 bytes) */ + + if (!rdp_read_capability_sets(s, rdp->settings, numberCapabilities)) + return False; + + return True; +} + void rdp_write_confirm_active(STREAM* s, rdpSettings* settings) { uint8 *bm, *em, *lm; diff --git a/libfreerdp-core/capabilities.h b/libfreerdp-core/capabilities.h index 6073b7c78..9938efafd 100644 --- a/libfreerdp-core/capabilities.h +++ b/libfreerdp-core/capabilities.h @@ -173,6 +173,7 @@ void rdp_read_demand_active(STREAM* s, rdpSettings* settings); void rdp_recv_demand_active(rdpRdp* rdp, STREAM* s, rdpSettings* settings); void rdp_write_demand_active(STREAM* s, rdpSettings* settings); boolean rdp_send_demand_active(rdpRdp* rdp); +boolean rdp_read_confirm_active(rdpRdp* rdp, STREAM* s); void rdp_write_confirm_active(STREAM* s, rdpSettings* settings); void rdp_send_confirm_active(rdpRdp* rdp); diff --git a/libfreerdp-core/connection.c b/libfreerdp-core/connection.c index 4f50baafe..fb8fe75d9 100644 --- a/libfreerdp-core/connection.c +++ b/libfreerdp-core/connection.c @@ -261,3 +261,13 @@ boolean rdp_server_accept_client_info(rdpRdp* rdp, STREAM* s) return True; } +boolean rdp_server_accept_confirm_active(rdpRdp* rdp, STREAM* s) +{ + if (!rdp_read_confirm_active(rdp, s)) + return False; + + rdp->state = CONNECTION_STATE_ACTIVE; + + return True; +} + diff --git a/libfreerdp-core/connection.h b/libfreerdp-core/connection.h index bd2d2dd9e..a69f7c6e1 100644 --- a/libfreerdp-core/connection.h +++ b/libfreerdp-core/connection.h @@ -51,5 +51,6 @@ boolean rdp_server_accept_mcs_erect_domain_request(rdpRdp* rdp, STREAM* s); boolean rdp_server_accept_mcs_attach_user_request(rdpRdp* rdp, STREAM* s); boolean rdp_server_accept_mcs_channel_join_request(rdpRdp* rdp, STREAM* s); boolean rdp_server_accept_client_info(rdpRdp* rdp, STREAM* s); +boolean rdp_server_accept_confirm_active(rdpRdp* rdp, STREAM* s); #endif /* __CONNECTION_H */ diff --git a/libfreerdp-core/peer.c b/libfreerdp-core/peer.c index badb1bc1d..c06e49160 100644 --- a/libfreerdp-core/peer.c +++ b/libfreerdp-core/peer.c @@ -90,6 +90,11 @@ static int peer_recv_callback(rdpTransport* transport, STREAM* s, void* extra) return -1; break; + case CONNECTION_STATE_LICENSE: + if (!rdp_server_accept_confirm_active(peer->rdp, 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 af15ee984..dfac662ce 100644 --- a/libfreerdp-core/rdp.c +++ b/libfreerdp-core/rdp.c @@ -89,13 +89,18 @@ void rdp_write_security_header(STREAM* s, uint16 flags) stream_write_uint16(s, 0); /* flagsHi (unused) */ } -void rdp_read_share_control_header(STREAM* s, uint16* length, uint16* type, uint16* channel_id) +boolean rdp_read_share_control_header(STREAM* s, uint16* length, uint16* type, uint16* channel_id) { /* Share Control Header */ stream_read_uint16(s, *length); /* totalLength */ stream_read_uint16(s, *type); /* pduType */ stream_read_uint16(s, *channel_id); /* pduSource */ *type &= 0x0F; /* type is in the 4 least significant bits */ + + if (*length - 6 > stream_get_left(s)) + return False; + + return True; } void rdp_write_share_control_header(STREAM* s, uint16 length, uint16 type, uint16 channel_id) diff --git a/libfreerdp-core/rdp.h b/libfreerdp-core/rdp.h index 155cabd34..204a58485 100644 --- a/libfreerdp-core/rdp.h +++ b/libfreerdp-core/rdp.h @@ -130,7 +130,7 @@ struct rdp_rdp void rdp_read_security_header(STREAM* s, uint16* flags); void rdp_write_security_header(STREAM* s, uint16 flags); -void rdp_read_share_control_header(STREAM* s, uint16* length, uint16* type, uint16* channel_id); +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);