From a406cd6619810ae8a12ecc7682bf25bbe987fb0b Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Wed, 14 Sep 2011 14:14:50 -0700 Subject: [PATCH] got rdp encryption working --- client/X11/CMakeLists.txt | 2 +- client/test/CMakeLists.txt | 2 +- libfreerdp-core/capabilities.c | 39 ++++++++++++++++++++++++++++++++++ libfreerdp-core/fastpath.c | 30 ++++++++++++++++++++++++++ libfreerdp-core/fastpath.h | 1 + libfreerdp-core/peer.c | 13 ++++++++---- libfreerdp-core/rdp.c | 31 +++++++++++++++++++++------ libfreerdp-core/rdp.h | 2 ++ libfreerdp-core/tcp.c | 8 +++---- server/test/CMakeLists.txt | 2 +- 10 files changed, 112 insertions(+), 18 deletions(-) diff --git a/client/X11/CMakeLists.txt b/client/X11/CMakeLists.txt index 38364105d..16442507e 100644 --- a/client/X11/CMakeLists.txt +++ b/client/X11/CMakeLists.txt @@ -60,6 +60,6 @@ target_link_libraries(xfreerdp freerdp-kbd) target_link_libraries(xfreerdp freerdp-rail) target_link_libraries(xfreerdp freerdp-chanman) target_link_libraries(xfreerdp freerdp-utils) -target_link_libraries(xfreerdp ${X11_LIBRARIES}) +target_link_libraries(xfreerdp ${X11_LIBRARIES} dl) install(TARGETS xfreerdp DESTINATION bin) diff --git a/client/test/CMakeLists.txt b/client/test/CMakeLists.txt index 09235b4e1..58d0783ff 100644 --- a/client/test/CMakeLists.txt +++ b/client/test/CMakeLists.txt @@ -23,4 +23,4 @@ add_executable(freerdp-test target_link_libraries(freerdp-test freerdp-core) target_link_libraries(freerdp-test freerdp-gdi) target_link_libraries(freerdp-test freerdp-utils) -target_link_libraries(freerdp-test freerdp-chanman) +target_link_libraries(freerdp-test freerdp-chanman dl) diff --git a/libfreerdp-core/capabilities.c b/libfreerdp-core/capabilities.c index daa697cc9..8c839c500 100644 --- a/libfreerdp-core/capabilities.c +++ b/libfreerdp-core/capabilities.c @@ -1492,17 +1492,25 @@ boolean rdp_read_capability_sets(STREAM* s, rdpSettings* settings, uint16 number uint16 length; uint8 *bm, *em; + printf("rdp_read_capability_sets: numberCapabilities %d\n", numberCapabilities); while (numberCapabilities > 0) { stream_get_mark(s, bm); + freerdp_hexdump(s->p, 4); rdp_read_capability_set_header(s, &length, &type); //printf("%s Capability Set (0x%02X), length:%d\n", CAPSET_TYPE_STRINGS[type], type, length); settings->received_caps[type] = True; em = bm + length; + printf("%d %d\n", stream_get_left(s), length - 4); if (stream_get_left(s) < length - 4) + { + printf("stream problem\n"); return False; + } + + printf("type %d\n", type); switch (type) { @@ -1643,18 +1651,46 @@ boolean rdp_recv_demand_active(rdpRdp* rdp, STREAM* s) uint16 numberCapabilities; uint16 lengthSourceDescriptor; uint16 lengthCombinedCapabilities; + uint32 securityHeader; if (!rdp_read_header(rdp, s, &length, &channelId)) return False; + if (rdp->settings->encryption) + { + stream_read_uint32(s, securityHeader); + if (securityHeader & SEC_SECURE_CHECKSUM) + { + printf("Error: TODO\n"); + return False; + } + if (securityHeader & SEC_ENCRYPT) + { + if (!rdp_decrypt(rdp, s, length - 4)) + { + printf("rdp_decrypt failed\n"); + return False; + } + } + } + if (channelId != MCS_GLOBAL_CHANNEL_ID) + { + printf("channelId bad\n"); return False; + } if (!rdp_read_share_control_header(s, &pduLength, &pduType, &rdp->settings->pdu_source)) + { + printf("rdp_read_share_control_header failed\n"); return False; + } if (pduType != PDU_TYPE_DEMAND_ACTIVE) + { + printf("pduType bad\n"); return False; + } //printf("Demand Active PDU\n"); @@ -1667,7 +1703,10 @@ boolean rdp_recv_demand_active(rdpRdp* rdp, STREAM* s) /* capabilitySets */ if (!rdp_read_capability_sets(s, rdp->settings, numberCapabilities)) + { + printf("rdp_read_capability_sets failes\n"); return False; + } rdp->update->glyph_v2 = (rdp->settings->glyphSupportLevel > GLYPH_SUPPORT_FULL) ? True : False; diff --git a/libfreerdp-core/fastpath.c b/libfreerdp-core/fastpath.c index ce4f8436b..4b01f8319 100644 --- a/libfreerdp-core/fastpath.c +++ b/libfreerdp-core/fastpath.c @@ -74,6 +74,36 @@ uint16 fastpath_read_header(rdpFastPath* fastpath, STREAM* s) return length; } +uint16 fastpath_read_header_rdp(rdpFastPath* fastpath, STREAM* s) +{ + uint8 header; + uint16 length; + uint8 t; + uint16 hs; + + hs = 2; + stream_read_uint8(s, header); + if (fastpath != NULL) + { + fastpath->encryptionFlags = (header & 0xC0) >> 6; + printf("fastpath_read_header: fastpath->encryptionFlags %d\n", fastpath->encryptionFlags); + fastpath->numberEvents = (header & 0x3C) >> 2; + } + + stream_read_uint8(s, length); /* length1 */ + /* If most significant bit is not set, length2 is not presented. */ + if ((length & 0x80)) + { + hs++; + length &= 0x7F; + length <<= 8; + stream_read_uint8(s, t); + length += t; + } + + return length - hs; +} + boolean fastpath_read_security_header(rdpFastPath* fastpath, STREAM* s) { /* TODO: fipsInformation */ diff --git a/libfreerdp-core/fastpath.h b/libfreerdp-core/fastpath.h index 5a6166aef..b5df30fde 100644 --- a/libfreerdp-core/fastpath.h +++ b/libfreerdp-core/fastpath.h @@ -91,6 +91,7 @@ struct rdp_fastpath }; uint16 fastpath_read_header(rdpFastPath* fastpath, STREAM* s); +uint16 fastpath_read_header_rdp(rdpFastPath* fastpath, STREAM* s); boolean fastpath_read_security_header(rdpFastPath* fastpath, STREAM* s); boolean fastpath_recv_updates(rdpFastPath* fastpath, STREAM* s); boolean fastpath_recv_inputs(rdpFastPath* fastpath, STREAM* s); diff --git a/libfreerdp-core/peer.c b/libfreerdp-core/peer.c index 8493977b1..b62862e1f 100644 --- a/libfreerdp-core/peer.c +++ b/libfreerdp-core/peer.c @@ -139,15 +139,20 @@ static boolean peer_recv_fastpath_pdu(rdpPeer* peer, STREAM* s) { uint16 length; - length = fastpath_read_header(peer->rdp->fastpath, s); - if (length == 0 || length > stream_get_size(s)) + length = fastpath_read_header_rdp(peer->rdp->fastpath, s); + if (length == 0 || length > stream_get_left(s)) { printf("incorrect FastPath PDU header length %d\n", length); return False; } - if (!fastpath_read_security_header(peer->rdp->fastpath, s)) - return False; + if (peer->rdp->fastpath->encryptionFlags & FASTPATH_OUTPUT_ENCRYPTED) + { + rdp_decrypt(peer->rdp, s, length); + } + + //if (!fastpath_read_security_header(peer->rdp->fastpath, s)) + // return False; return fastpath_recv_inputs(peer->rdp->fastpath, s); } diff --git a/libfreerdp-core/rdp.c b/libfreerdp-core/rdp.c index 379c34a92..c5b471a17 100644 --- a/libfreerdp-core/rdp.c +++ b/libfreerdp-core/rdp.c @@ -495,10 +495,16 @@ void rdp_recv_data_pdu(rdpRdp* rdp, STREAM* s) * @param length int */ -static boolean rdp_decrypt(rdpRdp* rdp, STREAM* s, int length) +boolean rdp_decrypt(rdpRdp* rdp, STREAM* s, int length) { - printf("rdp_decrypt:\n"); + int cryptlen; + + //printf("rdp_decrypt:\n"); stream_seek(s, 8); /* signature */ + cryptlen = length - 8; + //printf("length %d cryptlen %d\n", length, cryptlen); + security_decrypt(s->p, cryptlen, rdp); + //freerdp_hexdump(s->p, cryptlen); return True; } @@ -532,7 +538,7 @@ static boolean rdp_recv_tpkt_pdu(rdpRdp* rdp, STREAM* s) } if (securityHeader & SEC_ENCRYPT) { - if (!rdp_decrypt(rdp, s, length)) + if (!rdp_decrypt(rdp, s, length - 4)) { printf("rdp_decrypt failed\n"); return False; @@ -576,15 +582,23 @@ static boolean rdp_recv_fastpath_pdu(rdpRdp* rdp, STREAM* s) { uint16 length; - length = fastpath_read_header(rdp->fastpath, s); - if (length == 0 || length > stream_get_size(s)) + length = fastpath_read_header_rdp(rdp->fastpath, s); + + if (length == 0 || length > stream_get_left(s)) { printf("incorrect FastPath PDU header length %d\n", length); return False; } - if (!fastpath_read_security_header(rdp->fastpath, s)) - return False; + printf("rdp_recv_fastpath_pdu: length %d stream size %d\n", length, stream_get_size(s)); + + if (rdp->fastpath->encryptionFlags & FASTPATH_OUTPUT_ENCRYPTED) + { + rdp_decrypt(rdp, s, length); + } + + //if (!fastpath_read_security_header(rdp->fastpath, s)) + // return False; return fastpath_recv_updates(rdp->fastpath, s); } @@ -641,7 +655,10 @@ static int rdp_recv_callback(rdpTransport* transport, STREAM* s, void* extra) case CONNECTION_STATE_CAPABILITY: if (!rdp_client_connect_demand_active(rdp, s)) + { + printf("rdp_client_connect_demand_active failed\n"); return -1; + } break; case CONNECTION_STATE_ACTIVE: diff --git a/libfreerdp-core/rdp.h b/libfreerdp-core/rdp.h index aabd18c9d..10a900757 100644 --- a/libfreerdp-core/rdp.h +++ b/libfreerdp-core/rdp.h @@ -162,4 +162,6 @@ int rdp_check_fds(rdpRdp* rdp); rdpRdp* rdp_new(freerdp* instance); void rdp_free(rdpRdp* rdp); +boolean rdp_decrypt(rdpRdp* rdp, STREAM* s, int length); + #endif /* __RDP_H */ diff --git a/libfreerdp-core/tcp.c b/libfreerdp-core/tcp.c index f32867c52..3d8da999b 100644 --- a/libfreerdp-core/tcp.c +++ b/libfreerdp-core/tcp.c @@ -167,8 +167,8 @@ int tcp_read(rdpTcp* tcp, uint8* data, int length) } else { - printf("tcp_read: length %d\n", status); - freerdp_hexdump(data, status); + //printf("tcp_read: length %d\n", status); + //freerdp_hexdump(data, status); } return status; @@ -180,8 +180,8 @@ int tcp_write(rdpTcp* tcp, uint8* data, int length) status = send(tcp->sockfd, data, length, MSG_NOSIGNAL); - printf("tcp_write: length %d\n", status); - freerdp_hexdump(data, status); + //printf("tcp_write: length %d\n", status); + //freerdp_hexdump(data, status); if (status < 0) { diff --git a/server/test/CMakeLists.txt b/server/test/CMakeLists.txt index 91b7841c6..83374a156 100644 --- a/server/test/CMakeLists.txt +++ b/server/test/CMakeLists.txt @@ -22,4 +22,4 @@ add_executable(freerdp-server-test target_link_libraries(freerdp-server-test freerdp-core) target_link_libraries(freerdp-server-test freerdp-utils) -target_link_libraries(freerdp-server-test freerdp-rfx) +target_link_libraries(freerdp-server-test freerdp-rfx dl)