Add Standard RDP encryption suport for fastpath. Both input and output.
This commit is contained in:
parent
9c8a6bd8e9
commit
61aa1dfb79
@ -474,19 +474,48 @@ boolean fastpath_recv_inputs(rdpFastPath* fastpath, STREAM* s)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32 fastpath_get_sec_bytes(rdpRdp* rdp)
|
||||||
|
{
|
||||||
|
uint32 sec_bytes;
|
||||||
|
|
||||||
|
if (rdp->do_crypt)
|
||||||
|
{
|
||||||
|
sec_bytes = 8;
|
||||||
|
if (rdp->settings->encryption_method == ENCRYPTION_METHOD_FIPS)
|
||||||
|
sec_bytes += 4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
sec_bytes = 0;
|
||||||
|
return sec_bytes;
|
||||||
|
}
|
||||||
|
|
||||||
STREAM* fastpath_input_pdu_init(rdpFastPath* fastpath, uint8 eventFlags, uint8 eventCode)
|
STREAM* fastpath_input_pdu_init(rdpFastPath* fastpath, uint8 eventFlags, uint8 eventCode)
|
||||||
{
|
{
|
||||||
|
rdpRdp *rdp;
|
||||||
STREAM* s;
|
STREAM* s;
|
||||||
s = transport_send_stream_init(fastpath->rdp->transport, 127);
|
|
||||||
stream_seek(s, 2); /* fpInputHeader and length1 */
|
rdp = fastpath->rdp;
|
||||||
/* length2 is not necessary since input PDU should not exceed 127 bytes */
|
|
||||||
|
s = transport_send_stream_init(rdp->transport, 256);
|
||||||
|
stream_seek(s, 3); /* fpInputHeader, length1 and length2 */
|
||||||
|
if (rdp->do_crypt) {
|
||||||
|
rdp->sec_flags |= SEC_ENCRYPT;
|
||||||
|
if (rdp->do_secure_checksum)
|
||||||
|
rdp->sec_flags |= SEC_SECURE_CHECKSUM;
|
||||||
|
}
|
||||||
|
stream_seek(s, fastpath_get_sec_bytes(rdp));
|
||||||
stream_write_uint8(s, eventFlags | (eventCode << 5)); /* eventHeader (1 byte) */
|
stream_write_uint8(s, eventFlags | (eventCode << 5)); /* eventHeader (1 byte) */
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean fastpath_send_input_pdu(rdpFastPath* fastpath, STREAM* s)
|
boolean fastpath_send_input_pdu(rdpFastPath* fastpath, STREAM* s)
|
||||||
{
|
{
|
||||||
|
rdpRdp *rdp;
|
||||||
uint16 length;
|
uint16 length;
|
||||||
|
uint8 eventHeader;
|
||||||
|
int sec_bytes;
|
||||||
|
|
||||||
|
rdp = fastpath->rdp;
|
||||||
|
|
||||||
length = stream_get_length(s);
|
length = stream_get_length(s);
|
||||||
if (length > 127)
|
if (length > 127)
|
||||||
@ -495,11 +524,39 @@ boolean fastpath_send_input_pdu(rdpFastPath* fastpath, STREAM* s)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
stream_set_pos(s, 0);
|
eventHeader = FASTPATH_INPUT_ACTION_FASTPATH;
|
||||||
stream_write_uint8(s, (1 << 2));
|
eventHeader |= (1 << 2); /* numberEvents */
|
||||||
stream_write_uint8(s, length);
|
if (rdp->sec_flags & SEC_ENCRYPT)
|
||||||
|
eventHeader |= (FASTPATH_INPUT_ENCRYPTED << 6);
|
||||||
|
if (rdp->sec_flags & SEC_SECURE_CHECKSUM)
|
||||||
|
eventHeader |= (FASTPATH_INPUT_SECURE_CHECKSUM << 6);
|
||||||
|
|
||||||
stream_set_pos(s, length);
|
stream_set_pos(s, 0);
|
||||||
|
stream_write_uint8(s, eventHeader);
|
||||||
|
sec_bytes = fastpath_get_sec_bytes(fastpath->rdp);
|
||||||
|
/*
|
||||||
|
* We always encode length in two bytes, eventhough we could use
|
||||||
|
* only one byte if length <= 0x7F. It is just easier that way,
|
||||||
|
* because we can leave room for fixed-length header, store all
|
||||||
|
* the data first and then store the header.
|
||||||
|
*/
|
||||||
|
stream_write_uint16_be(s, 0x8000 | (length + sec_bytes));
|
||||||
|
|
||||||
|
if (sec_bytes > 0)
|
||||||
|
{
|
||||||
|
uint8* ptr;
|
||||||
|
|
||||||
|
ptr = stream_get_tail(s) + sec_bytes;
|
||||||
|
if (rdp->sec_flags & SEC_SECURE_CHECKSUM)
|
||||||
|
security_salted_mac_signature(rdp, ptr, length - 3, true, stream_get_tail(s));
|
||||||
|
else
|
||||||
|
security_mac_signature(rdp, ptr, length - 3, stream_get_tail(s));
|
||||||
|
security_encrypt(ptr, length - 3, rdp);
|
||||||
|
}
|
||||||
|
|
||||||
|
rdp->sec_flags = 0;
|
||||||
|
|
||||||
|
stream_set_pos(s, length + sec_bytes);
|
||||||
if (transport_write(fastpath->rdp->transport, s) < 0)
|
if (transport_write(fastpath->rdp->transport, s) < 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -511,26 +568,33 @@ STREAM* fastpath_update_pdu_init(rdpFastPath* fastpath)
|
|||||||
STREAM* s;
|
STREAM* s;
|
||||||
s = transport_send_stream_init(fastpath->rdp->transport, FASTPATH_MAX_PACKET_SIZE);
|
s = transport_send_stream_init(fastpath->rdp->transport, FASTPATH_MAX_PACKET_SIZE);
|
||||||
stream_seek(s, 3); /* fpOutputHeader, length1 and length2 */
|
stream_seek(s, 3); /* fpOutputHeader, length1 and length2 */
|
||||||
|
stream_seek(s, fastpath_get_sec_bytes(fastpath->rdp));
|
||||||
stream_seek(s, 3); /* updateHeader, size */
|
stream_seek(s, 3); /* updateHeader, size */
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean fastpath_send_update_pdu(rdpFastPath* fastpath, uint8 updateCode, STREAM* s)
|
boolean fastpath_send_update_pdu(rdpFastPath* fastpath, uint8 updateCode, STREAM* s)
|
||||||
{
|
{
|
||||||
|
rdpRdp *rdp;
|
||||||
uint8* bm;
|
uint8* bm;
|
||||||
|
uint8* ptr;
|
||||||
int fragment;
|
int fragment;
|
||||||
|
int sec_bytes;
|
||||||
uint16 length;
|
uint16 length;
|
||||||
boolean result;
|
boolean result;
|
||||||
uint16 pduLength;
|
uint16 pduLength;
|
||||||
uint16 maxLength;
|
uint16 maxLength;
|
||||||
uint32 totalLength;
|
uint32 totalLength;
|
||||||
uint8 fragmentation;
|
uint8 fragmentation;
|
||||||
|
uint8 header;
|
||||||
STREAM* update;
|
STREAM* update;
|
||||||
|
|
||||||
result = true;
|
result = true;
|
||||||
|
|
||||||
maxLength = FASTPATH_MAX_PACKET_SIZE - 6;
|
rdp = fastpath->rdp;
|
||||||
totalLength = stream_get_length(s) - 6;
|
sec_bytes = fastpath_get_sec_bytes(rdp);
|
||||||
|
maxLength = FASTPATH_MAX_PACKET_SIZE - 6 - sec_bytes;
|
||||||
|
totalLength = stream_get_length(s) - 6 - sec_bytes;
|
||||||
stream_set_pos(s, 0);
|
stream_set_pos(s, 0);
|
||||||
update = stream_new(0);
|
update = stream_new(0);
|
||||||
|
|
||||||
@ -538,7 +602,7 @@ boolean fastpath_send_update_pdu(rdpFastPath* fastpath, uint8 updateCode, STREAM
|
|||||||
{
|
{
|
||||||
length = MIN(maxLength, totalLength);
|
length = MIN(maxLength, totalLength);
|
||||||
totalLength -= length;
|
totalLength -= length;
|
||||||
pduLength = length + 6;
|
pduLength = length + 6 + sec_bytes;
|
||||||
|
|
||||||
if (totalLength == 0)
|
if (totalLength == 0)
|
||||||
fragmentation = (fragment == 0) ? FASTPATH_FRAGMENT_SINGLE : FASTPATH_FRAGMENT_LAST;
|
fragmentation = (fragment == 0) ? FASTPATH_FRAGMENT_SINGLE : FASTPATH_FRAGMENT_LAST;
|
||||||
@ -546,14 +610,28 @@ boolean fastpath_send_update_pdu(rdpFastPath* fastpath, uint8 updateCode, STREAM
|
|||||||
fragmentation = (fragment == 0) ? FASTPATH_FRAGMENT_FIRST : FASTPATH_FRAGMENT_NEXT;
|
fragmentation = (fragment == 0) ? FASTPATH_FRAGMENT_FIRST : FASTPATH_FRAGMENT_NEXT;
|
||||||
|
|
||||||
stream_get_mark(s, bm);
|
stream_get_mark(s, bm);
|
||||||
stream_write_uint8(s, 0); /* fpOutputHeader (1 byte) */
|
header = 0;
|
||||||
|
if (sec_bytes > 0)
|
||||||
|
header |= (FASTPATH_OUTPUT_ENCRYPTED << 6);
|
||||||
|
stream_write_uint8(s, header); /* fpOutputHeader (1 byte) */
|
||||||
stream_write_uint8(s, 0x80 | (pduLength >> 8)); /* length1 */
|
stream_write_uint8(s, 0x80 | (pduLength >> 8)); /* length1 */
|
||||||
stream_write_uint8(s, pduLength & 0xFF); /* length2 */
|
stream_write_uint8(s, pduLength & 0xFF); /* length2 */
|
||||||
|
if (sec_bytes > 0)
|
||||||
|
stream_seek(s, sec_bytes);
|
||||||
fastpath_write_update_header(s, updateCode, fragmentation, 0);
|
fastpath_write_update_header(s, updateCode, fragmentation, 0);
|
||||||
stream_write_uint16(s, length);
|
stream_write_uint16(s, length);
|
||||||
|
|
||||||
stream_attach(update, bm, pduLength);
|
stream_attach(update, bm, pduLength);
|
||||||
stream_seek(update, pduLength);
|
stream_seek(update, pduLength);
|
||||||
|
if (sec_bytes > 0)
|
||||||
|
{
|
||||||
|
ptr = bm + 3 + sec_bytes;
|
||||||
|
if (rdp->sec_flags & SEC_SECURE_CHECKSUM)
|
||||||
|
security_salted_mac_signature(rdp, ptr, length + 3, true, bm + 3);
|
||||||
|
else
|
||||||
|
security_mac_signature(rdp, ptr, length + 3, bm + 3);
|
||||||
|
security_encrypt(ptr, length + 3, rdp);
|
||||||
|
}
|
||||||
if (transport_write(fastpath->rdp->transport, update) < 0)
|
if (transport_write(fastpath->rdp->transport, update) < 0)
|
||||||
{
|
{
|
||||||
stream_detach(update);
|
stream_detach(update);
|
||||||
@ -562,8 +640,8 @@ boolean fastpath_send_update_pdu(rdpFastPath* fastpath, uint8 updateCode, STREAM
|
|||||||
}
|
}
|
||||||
stream_detach(update);
|
stream_detach(update);
|
||||||
|
|
||||||
/* Reserve 6 bytes for the next fragment header, if any. */
|
/* Reserve 6+sec_bytes bytes for the next fragment header, if any. */
|
||||||
stream_seek(s, length - 6);
|
stream_seek(s, length - 6 - sec_bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
stream_free(update);
|
stream_free(update);
|
||||||
|
Loading…
Reference in New Issue
Block a user