#include <string.h>
#include <winpr/crt.h>
+#include <winpr/stream.h>
#include <freerdp/api.h>
#include <freerdp/crypto/per.h>
-#include <winpr/stream.h>
#include "orders.h"
#include "update.h"
{
BYTE length1;
- stream_seek_BYTE(s);
+ Stream_Seek_BYTE(s);
stream_read_BYTE(s, length1);
- stream_rewind(s, 2);
+ Stream_Rewind(s, 2);
return ((length1 & 0x80) != 0 ? 3 : 2);
}
stream_read_BYTE(s, header);
- if (fastpath != NULL)
+ if (fastpath)
{
fastpath->encryptionFlags = (header & 0xC0) >> 6;
fastpath->numberEvents = (header & 0x3C) >> 2;
stream_read_BYTE(s, header);
- if (fastpath != NULL)
+ if (fastpath)
{
fastpath->encryptionFlags = (header & 0xC0) >> 6;
fastpath->numberEvents = (header & 0x3C) >> 2;
if (!per_read_length(s, length))
return FALSE;
- *length = *length - stream_get_length(s);
+ *length = *length - Stream_GetPosition(s);
return TRUE;
}
{
if (!update_recv_order(update, s))
return FALSE;
+
numberOrders--;
}
rdpUpdate* update = fastpath->rdp->update;
rdpContext* context = update->context;
- if (stream_get_left(s) < 2)
+ if (Stream_GetRemainingLength(s) < 2)
return FALSE;
stream_read_UINT16(s, updateType); /* updateType (2 bytes) */
return status;
}
+const char* fastpath_get_fragmentation_string(BYTE fragmentation)
+{
+ if (fragmentation == FASTPATH_FRAGMENT_SINGLE)
+ return "FASTPATH_FRAGMENT_SINGLE";
+ else if (fragmentation == FASTPATH_FRAGMENT_LAST)
+ return "FASTPATH_FRAGMENT_LAST";
+ else if (fragmentation == FASTPATH_FRAGMENT_FIRST)
+ return "FASTPATH_FRAGMENT_FIRST";
+ else if (fragmentation == FASTPATH_FRAGMENT_NEXT)
+ return "FASTPATH_FRAGMENT_NEXT";
+
+ return "FASTPATH_FRAGMENT_UNKNOWN";
+}
+
static int fastpath_recv_update_data(rdpFastPath* fastpath, wStream* s)
{
int status;
UINT16 size;
+ UINT32 roff;
+ UINT32 rlen;
+ rdpRdp* rdp;
int next_pos;
+ BYTE* buffer;
+ wStream* cs;
UINT32 totalSize;
BYTE updateCode;
BYTE fragmentation;
BYTE compression;
BYTE compressionFlags;
- wStream* update_stream;
- wStream* comp_stream;
- rdpRdp* rdp;
- UINT32 roff;
- UINT32 rlen;
+ rdpTransport* transport;
status = 0;
rdp = fastpath->rdp;
+ transport = fastpath->rdp->transport;
fastpath_read_update_header(s, &updateCode, &fragmentation, &compression);
stream_read_UINT16(s, size);
- if (stream_get_left(s) < size)
+ if (Stream_GetRemainingLength(s) < size)
return -1;
- next_pos = stream_get_pos(s) + size;
- comp_stream = s;
+ cs = s;
+ next_pos = Stream_GetPosition(s) + size;
if (compressionFlags & PACKET_COMPRESSED)
{
if (decompress_rdp(rdp->mppc_dec, s->pointer, size, compressionFlags, &roff, &rlen))
{
- comp_stream = stream_new(0);
- comp_stream->buffer = rdp->mppc_dec->history_buf + roff;
- comp_stream->pointer = comp_stream->buffer;
- comp_stream->capacity = rlen;
- size = comp_stream->capacity;
+ size = rlen;
+ buffer = rdp->mppc_dec->history_buf + roff;
+
+ cs = StreamPool_Take(transport->ReceivePool, size);
+
+ Stream_SetPosition(cs, 0);
+ Stream_Write(cs, buffer, size);
+ Stream_SealLength(cs);
+ Stream_SetPosition(cs, 0);
}
else
{
fprintf(stderr, "decompress_rdp() failed\n");
- stream_seek(s, size);
+ Stream_Seek(s, size);
}
}
- update_stream = NULL;
-
if (fragmentation == FASTPATH_FRAGMENT_SINGLE)
{
+ if (fastpath->fragmentation != -1)
+ {
+ fprintf(stderr, "Unexpected FASTPATH_FRAGMENT_SINGLE\n");
+ return -1;
+ }
+
totalSize = size;
- update_stream = comp_stream;
+ status = fastpath_recv_update(fastpath, updateCode, totalSize, cs);
+
+ if (status < 0)
+ return -1;
}
else
{
if (fragmentation == FASTPATH_FRAGMENT_FIRST)
- stream_set_pos(fastpath->updateData, 0);
+ {
+ if (fastpath->fragmentation != -1)
+ {
+ fprintf(stderr, "Unexpected FASTPATH_FRAGMENT_FIRST\n");
+ return -1;
+ }
- stream_check_size(fastpath->updateData, size);
- stream_copy(fastpath->updateData, comp_stream, size);
+ fastpath->fragmentation = FASTPATH_FRAGMENT_FIRST;
- if (stream_get_length(fastpath->updateData) > rdp->settings->MultifragMaxRequestSize)
- {
- fprintf(stderr, "fastpath PDU is bigger than MultifragMaxRequestSize\n");
- return -1;
- }
+ totalSize = size;
- if (fragmentation == FASTPATH_FRAGMENT_LAST)
+ if (totalSize > transport->settings->MultifragMaxRequestSize)
+ {
+ fprintf(stderr, "Total size (%d) exceeds MultifragMaxRequestSize (%d)\n",
+ totalSize, transport->settings->MultifragMaxRequestSize);
+ return -1;
+ }
+
+ fastpath->updateData = StreamPool_Take(transport->ReceivePool, size);
+ Stream_SetPosition(fastpath->updateData, 0);
+
+ Stream_Copy(fastpath->updateData, cs, size);
+ }
+ else if (fragmentation == FASTPATH_FRAGMENT_NEXT)
{
- update_stream = fastpath->updateData;
- totalSize = stream_get_length(update_stream);
- stream_set_pos(update_stream, 0);
+ if ((fastpath->fragmentation != FASTPATH_FRAGMENT_FIRST) &&
+ (fastpath->fragmentation != FASTPATH_FRAGMENT_NEXT))
+ {
+ fprintf(stderr, "Unexpected FASTPATH_FRAGMENT_NEXT\n");
+ return -1;
+ }
+
+ fastpath->fragmentation = FASTPATH_FRAGMENT_NEXT;
+
+ totalSize = Stream_GetPosition(fastpath->updateData) + size;
+
+ if (totalSize > transport->settings->MultifragMaxRequestSize)
+ {
+ fprintf(stderr, "Total size (%d) exceeds MultifragMaxRequestSize (%d)\n",
+ totalSize, transport->settings->MultifragMaxRequestSize);
+ return -1;
+ }
+
+ Stream_EnsureCapacity(fastpath->updateData, totalSize);
+
+ Stream_Copy(fastpath->updateData, cs, size);
}
- }
+ else if (fragmentation == FASTPATH_FRAGMENT_LAST)
+ {
+ if ((fastpath->fragmentation != FASTPATH_FRAGMENT_FIRST) &&
+ (fastpath->fragmentation != FASTPATH_FRAGMENT_NEXT))
+ {
+ fprintf(stderr, "Unexpected FASTPATH_FRAGMENT_LAST\n");
+ return -1;
+ }
- if (update_stream)
- {
- status = fastpath_recv_update(fastpath, updateCode, totalSize, update_stream);
+ fastpath->fragmentation = -1;
- if (status < 0)
- return -1;
+ totalSize = Stream_GetPosition(fastpath->updateData) + size;
+
+ if (totalSize > transport->settings->MultifragMaxRequestSize)
+ {
+ fprintf(stderr, "Total size (%d) exceeds MultifragMaxRequestSize (%d)\n",
+ totalSize, transport->settings->MultifragMaxRequestSize);
+ return -1;
+ }
+
+ Stream_EnsureCapacity(fastpath->updateData, totalSize);
+
+ Stream_Copy(fastpath->updateData, cs, size);
+
+ Stream_SealLength(fastpath->updateData);
+ Stream_SetPosition(fastpath->updateData, 0);
+
+ status = fastpath_recv_update(fastpath, updateCode, totalSize, fastpath->updateData);
+
+ Stream_Release(fastpath->updateData);
+
+ if (status < 0)
+ return -1;
+ }
}
- stream_set_pos(s, next_pos);
+ Stream_SetPosition(s, next_pos);
- if (comp_stream != s)
- free(comp_stream);
+ if (cs != s)
+ Stream_Release(cs);
return status;
}
IFCALL(update->BeginPaint, update->context);
- while (stream_get_left(s) >= 3)
+ while (Stream_GetRemainingLength(s) >= 3)
{
if (fastpath_recv_update_data(fastpath, s) < 0)
return -1;
{
BYTE eventHeader;
- if (stream_get_left(s) < 1)
+ if (Stream_GetRemainingLength(s) < 1)
return FALSE;
stream_read_BYTE(s, eventHeader); /* eventHeader (1 byte) */
UINT16 flags;
UINT16 code;
- if (stream_get_left(s) < 1)
+ if (Stream_GetRemainingLength(s) < 1)
return FALSE;
stream_read_BYTE(s, code); /* keyCode (1 byte) */
flags = 0;
+
if ((eventFlags & FASTPATH_INPUT_KBDFLAGS_RELEASE))
flags |= KBD_FLAGS_RELEASE;
else
UINT16 xPos;
UINT16 yPos;
- if (stream_get_left(s) < 6)
+ if (Stream_GetRemainingLength(s) < 6)
return FALSE;
stream_read_UINT16(s, pointerFlags); /* pointerFlags (2 bytes) */
UINT16 xPos;
UINT16 yPos;
- if (stream_get_left(s) < 6)
+ if (Stream_GetRemainingLength(s) < 6)
return FALSE;
stream_read_UINT16(s, pointerFlags); /* pointerFlags (2 bytes) */
UINT16 unicodeCode;
UINT16 flags;
- if (stream_get_left(s) < 2)
+ if (Stream_GetRemainingLength(s) < 2)
return FALSE;
stream_read_UINT16(s, unicodeCode); /* unicodeCode (2 bytes) */
flags = 0;
+
if ((eventFlags & FASTPATH_INPUT_KBDFLAGS_RELEASE))
flags |= KBD_FLAGS_RELEASE;
else
* as one additional byte here.
*/
- if (stream_get_left(s) < 1)
+ if (Stream_GetRemainingLength(s) < 1)
return -1;
stream_read_BYTE(s, fastpath->numberEvents); /* eventHeader (1 byte) */
{
UINT32 sec_bytes;
+ sec_bytes = 0;
+
if (rdp->do_crypt)
{
sec_bytes = 8;
+
if (rdp->settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS)
sec_bytes += 4;
}
- else
- sec_bytes = 0;
+
return sec_bytes;
}
rdp = fastpath->rdp;
s = transport_send_stream_init(rdp->transport, 256);
- stream_seek(s, 3); /* fpInputHeader, length1 and length2 */
+
+ 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_Seek(s, fastpath_get_sec_bytes(rdp));
return s;
}
s = fastpath_input_pdu_init_header(fastpath);
stream_write_BYTE(s, eventFlags | (eventCode << 5)); /* eventHeader (1 byte) */
+
return s;
}
rdp = fastpath->rdp;
- length = stream_get_length(s);
+ length = Stream_GetPosition(s);
+
if (length >= (2 << 14))
{
fprintf(stderr, "Maximum FastPath PDU length is 32767\n");
}
eventHeader = FASTPATH_INPUT_ACTION_FASTPATH;
+<<<<<<< HEAD
+ eventHeader |= (1 << 2); /* numberEvents */
+
+=======
eventHeader |= (iNumEvents << 2); /* numberEvents */
+>>>>>>> f1672948ff0b5f6a9d3cda658a18104df3c3d1e4
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, 0);
+ Stream_SetPosition(s, 0);
stream_write_BYTE(s, eventHeader);
sec_bytes = fastpath_get_sec_bytes(fastpath->rdp);
+
/*
- * We always encode length in two bytes, eventhough we could use
+ * We always encode length in two bytes, even though 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.
BYTE* fpInputEvents;
UINT16 fpInputEvents_length;
- fpInputEvents = stream_get_tail(s) + sec_bytes;
+ fpInputEvents = Stream_Pointer(s) + sec_bytes;
fpInputEvents_length = length - 3 - sec_bytes;
+
if (rdp->sec_flags & SEC_SECURE_CHECKSUM)
- security_salted_mac_signature(rdp, fpInputEvents, fpInputEvents_length, TRUE, stream_get_tail(s));
+ security_salted_mac_signature(rdp, fpInputEvents, fpInputEvents_length, TRUE, Stream_Pointer(s));
else
- security_mac_signature(rdp, fpInputEvents, fpInputEvents_length, stream_get_tail(s));
+ security_mac_signature(rdp, fpInputEvents, fpInputEvents_length, Stream_Pointer(s));
+
security_encrypt(fpInputEvents, fpInputEvents_length, rdp);
}
rdp->sec_flags = 0;
- stream_set_pos(s, length);
+ Stream_SetPosition(s, length);
+
if (transport_write(fastpath->rdp->transport, s) < 0)
return FALSE;
wStream* fastpath_update_pdu_init(rdpFastPath* fastpath)
{
wStream* s;
+
s = transport_send_stream_init(fastpath->rdp->transport, FASTPATH_MAX_PACKET_SIZE);
- 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); /* fpOutputHeader, length1 and length2 */
+ Stream_Seek(s, fastpath_get_sec_bytes(fastpath->rdp));
+ Stream_Seek(s, 3); /* updateHeader, size */
+
return s;
}
rdp = fastpath->rdp;
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);
+ totalLength = Stream_GetPosition(s) - (6 + sec_bytes);
+ Stream_SetPosition(s, 0);
update = stream_new(0);
try_comp = rdp->settings->CompressionEnabled;
comp_update = stream_new(0);
- for (fragment = 0; totalLength > 0 || fragment == 0; fragment++)
+ for (fragment = 0; (totalLength > 0) || (fragment == 0); fragment++)
{
stream_get_mark(s, holdp);
ls = s;
comp_flags = 0;
header_bytes = 6 + sec_bytes;
pdu_data_bytes = dlen;
+
if (try_comp)
{
if (compress_rdp(rdp->mppc_enc, ls->pointer + header_bytes, dlen))
}
}
else
+ {
fprintf(stderr, "fastpath_send_update_pdu: mppc_encode failed\n");
+ }
}
totalLength -= dlen;
stream_get_mark(ls, bm);
header = 0;
+
if (sec_bytes > 0)
header |= (FASTPATH_OUTPUT_ENCRYPTED << 6);
+
stream_write_BYTE(ls, header); /* fpOutputHeader (1 byte) */
stream_write_BYTE(ls, 0x80 | (pduLength >> 8)); /* length1 */
stream_write_BYTE(ls, pduLength & 0xFF); /* length2 */
if (sec_bytes > 0)
- stream_seek(ls, sec_bytes);
+ Stream_Seek(ls, sec_bytes);
fastpath_write_update_header(ls, updateCode, fragmentation, comp_flags);
bytes_to_crypt = pdu_data_bytes + 4;
}
else
+ {
bytes_to_crypt = pdu_data_bytes + 3;
+ }
stream_write_UINT16(ls, pdu_data_bytes);
stream_attach(update, bm, pduLength);
- stream_seek(update, pduLength);
+ Stream_Seek(update, pduLength);
if (sec_bytes > 0)
{
/* does this work ? */
ptr_to_crypt = bm + 3 + sec_bytes;
ptr_sig = bm + 3;
+
if (rdp->sec_flags & SEC_SECURE_CHECKSUM)
security_salted_mac_signature(rdp, ptr_to_crypt, bytes_to_crypt, TRUE, ptr_sig);
else
security_mac_signature(rdp, ptr_to_crypt, bytes_to_crypt, ptr_sig);
+
security_encrypt(ptr_to_crypt, bytes_to_crypt, rdp);
}
rdpFastPath* fastpath;
fastpath = (rdpFastPath*) malloc(sizeof(rdpFastPath));
- ZeroMemory(fastpath, sizeof(rdpFastPath));
- fastpath->rdp = rdp;
- fastpath->updateData = stream_new(4096);
+ if (fastpath)
+ {
+ ZeroMemory(fastpath, sizeof(rdpFastPath));
+
+ fastpath->rdp = rdp;
+ fastpath->fragmentation = -1;
+ }
return fastpath;
}
void fastpath_free(rdpFastPath* fastpath)
{
- stream_free(fastpath->updateData);
- free(fastpath);
+ if (fastpath)
+ {
+ free(fastpath);
+ }
}