GUACAMOLE-1059: Merge changes leveraging appropriate FreeRDP checks to verify input stream length.
This commit is contained in:
commit
0bf65ce8b0
@ -135,11 +135,28 @@ void guac_rdpdr_fs_process_set_rename_info(guac_rdp_common_svc* svc,
|
|||||||
wStream* output_stream;
|
wStream* output_stream;
|
||||||
char destination_path[GUAC_RDP_FS_MAX_PATH];
|
char destination_path[GUAC_RDP_FS_MAX_PATH];
|
||||||
|
|
||||||
|
/* Check stream size prior to reading. */
|
||||||
|
if (Stream_GetRemainingLength(input_stream) < 6) {
|
||||||
|
guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Drive Set "
|
||||||
|
"Information Request (FileRenameInformation) PDU does not "
|
||||||
|
"contain the expected number of bytes. File redirection "
|
||||||
|
"may not work as expected.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Read structure */
|
/* Read structure */
|
||||||
Stream_Seek_UINT8(input_stream); /* ReplaceIfExists */
|
Stream_Seek_UINT8(input_stream); /* ReplaceIfExists */
|
||||||
Stream_Seek_UINT8(input_stream); /* RootDirectory */
|
Stream_Seek_UINT8(input_stream); /* RootDirectory */
|
||||||
Stream_Read_UINT32(input_stream, filename_length); /* FileNameLength */
|
Stream_Read_UINT32(input_stream, filename_length); /* FileNameLength */
|
||||||
|
|
||||||
|
if (Stream_GetRemainingLength(input_stream) < filename_length) {
|
||||||
|
guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Drive Set "
|
||||||
|
"Information Request (FileRenameInformation) PDU does not "
|
||||||
|
"contain the expected number of bytes. File redirection "
|
||||||
|
"may not work as expected.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Convert name to UTF-8 */
|
/* Convert name to UTF-8 */
|
||||||
guac_rdp_utf16_to_utf8(Stream_Pointer(input_stream), filename_length/2,
|
guac_rdp_utf16_to_utf8(Stream_Pointer(input_stream), filename_length/2,
|
||||||
destination_path, sizeof(destination_path));
|
destination_path, sizeof(destination_path));
|
||||||
@ -192,6 +209,15 @@ void guac_rdpdr_fs_process_set_allocation_info(guac_rdp_common_svc* svc,
|
|||||||
UINT64 size;
|
UINT64 size;
|
||||||
wStream* output_stream;
|
wStream* output_stream;
|
||||||
|
|
||||||
|
/* Check to make sure the stream has at least 8 bytes (UINT64) */
|
||||||
|
if (Stream_GetRemainingLength(input_stream) < 8) {
|
||||||
|
guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Drive Set "
|
||||||
|
"Information Request (FileAllocationInformation) PDU does not "
|
||||||
|
"contain the expected number of bytes. File redirection "
|
||||||
|
"may not work as expected.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Read new size */
|
/* Read new size */
|
||||||
Stream_Read_UINT64(input_stream, size); /* AllocationSize */
|
Stream_Read_UINT64(input_stream, size); /* AllocationSize */
|
||||||
|
|
||||||
@ -244,6 +270,15 @@ void guac_rdpdr_fs_process_set_end_of_file_info(guac_rdp_common_svc* svc,
|
|||||||
UINT64 size;
|
UINT64 size;
|
||||||
wStream* output_stream;
|
wStream* output_stream;
|
||||||
|
|
||||||
|
/* Check to make sure stream contains at least 8 bytes (UINT64) */
|
||||||
|
if (Stream_GetRemainingLength(input_stream) < 8) {
|
||||||
|
guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Drive Set "
|
||||||
|
"Information Request (FileEndOfFileInformation) PDU does not "
|
||||||
|
"contain the expected number of bytes. File redirection "
|
||||||
|
"may not work as expected.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Read new size */
|
/* Read new size */
|
||||||
Stream_Read_UINT64(input_stream, size); /* AllocationSize */
|
Stream_Read_UINT64(input_stream, size); /* AllocationSize */
|
||||||
|
|
||||||
|
@ -48,6 +48,14 @@ void guac_rdpdr_fs_process_create(guac_rdp_common_svc* svc,
|
|||||||
int create_disposition, create_options, path_length;
|
int create_disposition, create_options, path_length;
|
||||||
char path[GUAC_RDP_FS_MAX_PATH];
|
char path[GUAC_RDP_FS_MAX_PATH];
|
||||||
|
|
||||||
|
/* Check remaining stream data prior to reading. */
|
||||||
|
if (Stream_GetRemainingLength(input_stream) < 32) {
|
||||||
|
guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Create Drive "
|
||||||
|
"Request PDU does not contain the expected number of bytes. "
|
||||||
|
"Drive redirection may not work as expected.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Read "create" information */
|
/* Read "create" information */
|
||||||
Stream_Read_UINT32(input_stream, desired_access);
|
Stream_Read_UINT32(input_stream, desired_access);
|
||||||
Stream_Seek_UINT64(input_stream); /* allocation size */
|
Stream_Seek_UINT64(input_stream); /* allocation size */
|
||||||
@ -57,6 +65,14 @@ void guac_rdpdr_fs_process_create(guac_rdp_common_svc* svc,
|
|||||||
Stream_Read_UINT32(input_stream, create_options);
|
Stream_Read_UINT32(input_stream, create_options);
|
||||||
Stream_Read_UINT32(input_stream, path_length);
|
Stream_Read_UINT32(input_stream, path_length);
|
||||||
|
|
||||||
|
/* Check to make sure the stream contains path_length bytes. */
|
||||||
|
if(Stream_GetRemainingLength(input_stream) < path_length) {
|
||||||
|
guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Create Drive "
|
||||||
|
"Request PDU does not contain the expected number of bytes. "
|
||||||
|
"Drive redirection may not work as expected.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Convert path to UTF-8 */
|
/* Convert path to UTF-8 */
|
||||||
guac_rdp_utf16_to_utf8(Stream_Pointer(input_stream), path_length/2 - 1,
|
guac_rdp_utf16_to_utf8(Stream_Pointer(input_stream), path_length/2 - 1,
|
||||||
path, sizeof(path));
|
path, sizeof(path));
|
||||||
@ -123,6 +139,14 @@ void guac_rdpdr_fs_process_read(guac_rdp_common_svc* svc,
|
|||||||
|
|
||||||
wStream* output_stream;
|
wStream* output_stream;
|
||||||
|
|
||||||
|
/* Check remaining bytes before reading stream. */
|
||||||
|
if (Stream_GetRemainingLength(input_stream) < 12) {
|
||||||
|
guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Drive Read "
|
||||||
|
"Request PDU does not contain the expected number of bytes. "
|
||||||
|
"Drive redirection may not work as expected.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Read packet */
|
/* Read packet */
|
||||||
Stream_Read_UINT32(input_stream, length);
|
Stream_Read_UINT32(input_stream, length);
|
||||||
Stream_Read_UINT64(input_stream, offset);
|
Stream_Read_UINT64(input_stream, offset);
|
||||||
@ -172,6 +196,14 @@ void guac_rdpdr_fs_process_write(guac_rdp_common_svc* svc,
|
|||||||
|
|
||||||
wStream* output_stream;
|
wStream* output_stream;
|
||||||
|
|
||||||
|
/* Check remaining length. */
|
||||||
|
if (Stream_GetRemainingLength(input_stream) < 32) {
|
||||||
|
guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Drive Write "
|
||||||
|
"Request PDU does not contain the expected number of bytes. "
|
||||||
|
"Drive redirection may not work as expected.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Read packet */
|
/* Read packet */
|
||||||
Stream_Read_UINT32(input_stream, length);
|
Stream_Read_UINT32(input_stream, length);
|
||||||
Stream_Read_UINT64(input_stream, offset);
|
Stream_Read_UINT64(input_stream, offset);
|
||||||
@ -181,6 +213,14 @@ void guac_rdpdr_fs_process_write(guac_rdp_common_svc* svc,
|
|||||||
"%s: [file_id=%i] length=%i, offset=%" PRIu64,
|
"%s: [file_id=%i] length=%i, offset=%" PRIu64,
|
||||||
__func__, iorequest->file_id, length, (uint64_t) offset);
|
__func__, iorequest->file_id, length, (uint64_t) offset);
|
||||||
|
|
||||||
|
/* Check to make sure stream contains at least length bytes */
|
||||||
|
if (Stream_GetRemainingLength(input_stream) < length) {
|
||||||
|
guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Drive Write "
|
||||||
|
"Request PDU does not contain the expected number of bytes. "
|
||||||
|
"Drive redirection may not work as expected.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Attempt write */
|
/* Attempt write */
|
||||||
bytes_written = guac_rdp_fs_write((guac_rdp_fs*) device->data,
|
bytes_written = guac_rdp_fs_write((guac_rdp_fs*) device->data,
|
||||||
iorequest->file_id, offset, Stream_Pointer(input_stream), length);
|
iorequest->file_id, offset, Stream_Pointer(input_stream), length);
|
||||||
@ -244,6 +284,14 @@ void guac_rdpdr_fs_process_volume_info(guac_rdp_common_svc* svc,
|
|||||||
|
|
||||||
int fs_information_class;
|
int fs_information_class;
|
||||||
|
|
||||||
|
/* Check remaining length */
|
||||||
|
if (Stream_GetRemainingLength(input_stream) < 4) {
|
||||||
|
guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Drive Query "
|
||||||
|
"Volume Information PDU does not contain the expected number "
|
||||||
|
"of bytes. Drive redirection may not work as expected.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Stream_Read_UINT32(input_stream, fs_information_class);
|
Stream_Read_UINT32(input_stream, fs_information_class);
|
||||||
|
|
||||||
/* Dispatch to appropriate class-specific handler */
|
/* Dispatch to appropriate class-specific handler */
|
||||||
@ -282,6 +330,14 @@ void guac_rdpdr_fs_process_file_info(guac_rdp_common_svc* svc,
|
|||||||
|
|
||||||
int fs_information_class;
|
int fs_information_class;
|
||||||
|
|
||||||
|
/* Check remaining length */
|
||||||
|
if (Stream_GetRemainingLength(input_stream) < 4) {
|
||||||
|
guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Drive Query "
|
||||||
|
"Information PDU does not contain the expected number of "
|
||||||
|
"bytes. Drive redirection may not work as expected.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Stream_Read_UINT32(input_stream, fs_information_class);
|
Stream_Read_UINT32(input_stream, fs_information_class);
|
||||||
|
|
||||||
/* Dispatch to appropriate class-specific handler */
|
/* Dispatch to appropriate class-specific handler */
|
||||||
@ -328,6 +384,14 @@ void guac_rdpdr_fs_process_set_file_info(guac_rdp_common_svc* svc,
|
|||||||
int fs_information_class;
|
int fs_information_class;
|
||||||
int length;
|
int length;
|
||||||
|
|
||||||
|
/* Check remaining length */
|
||||||
|
if (Stream_GetRemainingLength(input_stream) < 32) {
|
||||||
|
guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Drive Set "
|
||||||
|
"Information PDU does not contain the expected number of "
|
||||||
|
"bytes. Drive redirection may not work as expected.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Stream_Read_UINT32(input_stream, fs_information_class);
|
Stream_Read_UINT32(input_stream, fs_information_class);
|
||||||
Stream_Read_UINT32(input_stream, length); /* Length */
|
Stream_Read_UINT32(input_stream, length); /* Length */
|
||||||
Stream_Seek(input_stream, 24); /* Padding */
|
Stream_Seek(input_stream, 24); /* Padding */
|
||||||
@ -406,6 +470,13 @@ void guac_rdpdr_fs_process_query_directory(guac_rdp_common_svc* svc,
|
|||||||
if (file == NULL)
|
if (file == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (Stream_GetRemainingLength(input_stream) < 9) {
|
||||||
|
guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Drive Query "
|
||||||
|
"Directory PDU does not contain the expected number of bytes. "
|
||||||
|
"Drive redirection may not work as expected.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Read main header */
|
/* Read main header */
|
||||||
Stream_Read_UINT32(input_stream, fs_information_class);
|
Stream_Read_UINT32(input_stream, fs_information_class);
|
||||||
Stream_Read_UINT8(input_stream, initial_query);
|
Stream_Read_UINT8(input_stream, initial_query);
|
||||||
@ -414,8 +485,19 @@ void guac_rdpdr_fs_process_query_directory(guac_rdp_common_svc* svc,
|
|||||||
/* If this is the first query, the path is included after padding */
|
/* If this is the first query, the path is included after padding */
|
||||||
if (initial_query) {
|
if (initial_query) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check to make sure Stream has at least the 23 padding bytes in it
|
||||||
|
* prior to seeking.
|
||||||
|
*/
|
||||||
|
if (Stream_GetRemainingLength(input_stream) < (23 + path_length)) {
|
||||||
|
guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Drive Query "
|
||||||
|
"Directory PDU does not contain the expected number of "
|
||||||
|
"bytes. Drive redirection may not work as expected.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Stream_Seek(input_stream, 23); /* Padding */
|
Stream_Seek(input_stream, 23); /* Padding */
|
||||||
|
|
||||||
/* Convert path to UTF-8 */
|
/* Convert path to UTF-8 */
|
||||||
guac_rdp_utf16_to_utf8(Stream_Pointer(input_stream), path_length/2 - 1,
|
guac_rdp_utf16_to_utf8(Stream_Pointer(input_stream), path_length/2 - 1,
|
||||||
file->dir_pattern, sizeof(file->dir_pattern));
|
file->dir_pattern, sizeof(file->dir_pattern));
|
||||||
|
@ -212,6 +212,14 @@ void guac_rdpdr_process_server_announce(guac_rdp_common_svc* svc,
|
|||||||
|
|
||||||
unsigned int major, minor, client_id;
|
unsigned int major, minor, client_id;
|
||||||
|
|
||||||
|
/* Stream should contain at least 8 bytes (UINT16 + UINT16 + UINT32) */
|
||||||
|
if (Stream_GetRemainingLength(input_stream) < 8) {
|
||||||
|
guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Announce "
|
||||||
|
"Request PDU does not contain the expected number of bytes. "
|
||||||
|
"Device redirection may not work as expected.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Stream_Read_UINT16(input_stream, major);
|
Stream_Read_UINT16(input_stream, major);
|
||||||
Stream_Read_UINT16(input_stream, minor);
|
Stream_Read_UINT16(input_stream, minor);
|
||||||
Stream_Read_UINT32(input_stream, client_id);
|
Stream_Read_UINT32(input_stream, client_id);
|
||||||
@ -243,6 +251,14 @@ void guac_rdpdr_process_device_reply(guac_rdp_common_svc* svc,
|
|||||||
unsigned int device_id, ntstatus;
|
unsigned int device_id, ntstatus;
|
||||||
int severity, c, n, facility, code;
|
int severity, c, n, facility, code;
|
||||||
|
|
||||||
|
/* Stream should contain at least 8 bytes (UINT32 + UINT32 ) */
|
||||||
|
if (Stream_GetRemainingLength(input_stream) < 8) {
|
||||||
|
guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Device Announce"
|
||||||
|
"Response PDU does not contain the expected number of bytes."
|
||||||
|
"Device redirection may not work as expected.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Stream_Read_UINT32(input_stream, device_id);
|
Stream_Read_UINT32(input_stream, device_id);
|
||||||
Stream_Read_UINT32(input_stream, ntstatus);
|
Stream_Read_UINT32(input_stream, ntstatus);
|
||||||
|
|
||||||
@ -278,6 +294,14 @@ void guac_rdpdr_process_device_iorequest(guac_rdp_common_svc* svc,
|
|||||||
guac_rdpdr* rdpdr = (guac_rdpdr*) svc->data;
|
guac_rdpdr* rdpdr = (guac_rdpdr*) svc->data;
|
||||||
guac_rdpdr_iorequest iorequest;
|
guac_rdpdr_iorequest iorequest;
|
||||||
|
|
||||||
|
/* Check to make sure the Stream contains at least 20 bytes (5 x UINT32 ). */
|
||||||
|
if (Stream_GetRemainingLength(input_stream) < 20) {
|
||||||
|
guac_client_log(svc->client, GUAC_LOG_WARNING, "Device I/O Request PDU "
|
||||||
|
"does not contain the expected number of bytes. Device "
|
||||||
|
"redirection may not work as expected.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Read header */
|
/* Read header */
|
||||||
Stream_Read_UINT32(input_stream, iorequest.device_id);
|
Stream_Read_UINT32(input_stream, iorequest.device_id);
|
||||||
Stream_Read_UINT32(input_stream, iorequest.file_id);
|
Stream_Read_UINT32(input_stream, iorequest.file_id);
|
||||||
@ -306,6 +330,14 @@ void guac_rdpdr_process_server_capability(guac_rdp_common_svc* svc,
|
|||||||
int count;
|
int count;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
/* Check to make sure the Stream has at least 4 bytes (UINT16 + 2) */
|
||||||
|
if (Stream_GetRemainingLength(input_stream) < 4) {
|
||||||
|
guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Core Capability "
|
||||||
|
"Request PDU does not contain the expected number of bytes."
|
||||||
|
"Device redirection may not work as expected.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Read header */
|
/* Read header */
|
||||||
Stream_Read_UINT16(input_stream, count);
|
Stream_Read_UINT16(input_stream, count);
|
||||||
Stream_Seek(input_stream, 2);
|
Stream_Seek(input_stream, 2);
|
||||||
@ -316,9 +348,27 @@ void guac_rdpdr_process_server_capability(guac_rdp_common_svc* svc,
|
|||||||
int type;
|
int type;
|
||||||
int length;
|
int length;
|
||||||
|
|
||||||
|
/* Make sure Stream has at least 4 bytes (UINT16 + UINT16) */
|
||||||
|
if (Stream_GetRemainingLength(input_stream) < 4) {
|
||||||
|
guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Core "
|
||||||
|
"Capability Request PDU does not contain the expected "
|
||||||
|
"number of bytes. Device redirection may not work as "
|
||||||
|
"expected.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
Stream_Read_UINT16(input_stream, type);
|
Stream_Read_UINT16(input_stream, type);
|
||||||
Stream_Read_UINT16(input_stream, length);
|
Stream_Read_UINT16(input_stream, length);
|
||||||
|
|
||||||
|
/* Make sure Stream has required length remaining for Seek below. */
|
||||||
|
if (Stream_GetRemainingLength(input_stream) < (length - 4)) {
|
||||||
|
guac_client_log(svc->client, GUAC_LOG_WARNING, "Server Core "
|
||||||
|
"Capability Request PDU does not contain the expected "
|
||||||
|
"number of bytes. Device redirection may not work as "
|
||||||
|
"expected.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Ignore all for now */
|
/* Ignore all for now */
|
||||||
guac_client_log(svc->client, GUAC_LOG_DEBUG, "Ignoring server capability set type=0x%04x, length=%i", type, length);
|
guac_client_log(svc->client, GUAC_LOG_DEBUG, "Ignoring server capability set type=0x%04x, length=%i", type, length);
|
||||||
Stream_Seek(input_stream, length - 4);
|
Stream_Seek(input_stream, length - 4);
|
||||||
|
@ -67,12 +67,28 @@ void guac_rdpdr_process_print_job_write(guac_rdp_common_svc* svc,
|
|||||||
int length;
|
int length;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
|
/* Verify that Stream contains at least 32 bytes (UINT32 + 8 + 20) */
|
||||||
|
if (Stream_GetRemainingLength(input_stream) < 32) {
|
||||||
|
guac_client_log(client, GUAC_LOG_WARNING, "Print job write stream does "
|
||||||
|
"not contain the expected number of bytes. Printer redirection "
|
||||||
|
"may not work as expected.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Read buffer of print data */
|
/* Read buffer of print data */
|
||||||
Stream_Read_UINT32(input_stream, length);
|
Stream_Read_UINT32(input_stream, length);
|
||||||
Stream_Seek(input_stream, 8); /* Offset */
|
Stream_Seek(input_stream, 8); /* Offset */
|
||||||
Stream_Seek(input_stream, 20); /* Padding */
|
Stream_Seek(input_stream, 20); /* Padding */
|
||||||
buffer = Stream_Pointer(input_stream);
|
buffer = Stream_Pointer(input_stream);
|
||||||
|
|
||||||
|
/* Verify the stream has at least length number of bytes remaining. */
|
||||||
|
if (Stream_GetRemainingLength(input_stream) < length) {
|
||||||
|
guac_client_log(client, GUAC_LOG_WARNING, "Print job write stream does "
|
||||||
|
"not contain the expected number of bytes. Printer redirection "
|
||||||
|
"may not work as expected.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Write data only if job exists, translating status for RDP */
|
/* Write data only if job exists, translating status for RDP */
|
||||||
if (job != NULL && (length = guac_rdp_print_job_write(job,
|
if (job != NULL && (length = guac_rdp_print_job_write(job,
|
||||||
buffer, length)) >= 0) {
|
buffer, length)) >= 0) {
|
||||||
|
@ -38,6 +38,17 @@ void guac_rdpdr_process_receive(guac_rdp_common_svc* svc,
|
|||||||
int component;
|
int component;
|
||||||
int packet_id;
|
int packet_id;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check that device redirection stream contains at least 4 bytes
|
||||||
|
* (UINT16 + UINT16).
|
||||||
|
*/
|
||||||
|
if (Stream_GetRemainingLength(input_stream) < 4) {
|
||||||
|
guac_client_log(svc->client, GUAC_LOG_WARNING, "Device redirection "
|
||||||
|
"channel PDU header does not contain the expected number of "
|
||||||
|
"bytes. Device redirection may not function as expected.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Read header */
|
/* Read header */
|
||||||
Stream_Read_UINT16(input_stream, component);
|
Stream_Read_UINT16(input_stream, component);
|
||||||
Stream_Read_UINT16(input_stream, packet_id);
|
Stream_Read_UINT16(input_stream, packet_id);
|
||||||
|
@ -50,6 +50,17 @@ void guac_rdpsnd_formats_handler(guac_rdp_common_svc* svc,
|
|||||||
/* Reset own format count */
|
/* Reset own format count */
|
||||||
rdpsnd->format_count = 0;
|
rdpsnd->format_count = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check to make sure the stream has at least 20 bytes (14 byte seek,
|
||||||
|
* 2 x UTF16 reads, and 2 x UTF8 seeks).
|
||||||
|
*/
|
||||||
|
if (Stream_GetRemainingLength(input_stream) < 20) {
|
||||||
|
guac_client_log(client, GUAC_LOG_WARNING, "Server Audio Formats and "
|
||||||
|
"Version PDU does not contain the expected number of bytes. "
|
||||||
|
"Audio redirection may not work as expected.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Format header */
|
/* Format header */
|
||||||
Stream_Seek(input_stream, 14);
|
Stream_Seek(input_stream, 14);
|
||||||
Stream_Read_UINT16(input_stream, server_format_count);
|
Stream_Read_UINT16(input_stream, server_format_count);
|
||||||
@ -96,6 +107,15 @@ void guac_rdpsnd_formats_handler(guac_rdp_common_svc* svc,
|
|||||||
/* Remember position in stream */
|
/* Remember position in stream */
|
||||||
Stream_GetPointer(input_stream, format_start);
|
Stream_GetPointer(input_stream, format_start);
|
||||||
|
|
||||||
|
/* Check to make sure Stream has at least 18 bytes. */
|
||||||
|
if (Stream_GetRemainingLength(input_stream) < 18) {
|
||||||
|
guac_client_log(client, GUAC_LOG_WARNING, "Server Audio "
|
||||||
|
"Formats and Version PDU does not contain the expected "
|
||||||
|
"number of bytes. Audio redirection may not work as "
|
||||||
|
"expected.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Read format */
|
/* Read format */
|
||||||
Stream_Read_UINT16(input_stream, format_tag);
|
Stream_Read_UINT16(input_stream, format_tag);
|
||||||
Stream_Read_UINT16(input_stream, channels);
|
Stream_Read_UINT16(input_stream, channels);
|
||||||
@ -106,6 +126,16 @@ void guac_rdpsnd_formats_handler(guac_rdp_common_svc* svc,
|
|||||||
|
|
||||||
/* Skip past extra data */
|
/* Skip past extra data */
|
||||||
Stream_Read_UINT16(input_stream, body_size);
|
Stream_Read_UINT16(input_stream, body_size);
|
||||||
|
|
||||||
|
/* Check that Stream has at least body_size bytes remaining. */
|
||||||
|
if (Stream_GetRemainingLength(input_stream) < body_size) {
|
||||||
|
guac_client_log(client, GUAC_LOG_WARNING, "Server Audio "
|
||||||
|
"Formats and Version PDU does not contain the expected "
|
||||||
|
"number of bytes. Audio redirection may not work as "
|
||||||
|
"expected.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Stream_Seek(input_stream, body_size);
|
Stream_Seek(input_stream, body_size);
|
||||||
|
|
||||||
/* If PCM, accept */
|
/* If PCM, accept */
|
||||||
@ -205,6 +235,14 @@ void guac_rdpsnd_training_handler(guac_rdp_common_svc* svc,
|
|||||||
|
|
||||||
guac_rdpsnd* rdpsnd = (guac_rdpsnd*) svc->data;
|
guac_rdpsnd* rdpsnd = (guac_rdpsnd*) svc->data;
|
||||||
|
|
||||||
|
/* Check to make sure audio stream contains a minimum number of bytes. */
|
||||||
|
if (Stream_GetRemainingLength(input_stream) < 4) {
|
||||||
|
guac_client_log(svc->client, GUAC_LOG_WARNING, "Audio Training PDU "
|
||||||
|
"does not contain the expected number of bytes. Audio "
|
||||||
|
"redirection may not work as expected.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Read timestamp and data size */
|
/* Read timestamp and data size */
|
||||||
Stream_Read_UINT16(input_stream, rdpsnd->server_timestamp);
|
Stream_Read_UINT16(input_stream, rdpsnd->server_timestamp);
|
||||||
Stream_Read_UINT16(input_stream, data_size);
|
Stream_Read_UINT16(input_stream, data_size);
|
||||||
@ -232,6 +270,14 @@ void guac_rdpsnd_wave_info_handler(guac_rdp_common_svc* svc,
|
|||||||
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
||||||
guac_audio_stream* audio = rdp_client->audio;
|
guac_audio_stream* audio = rdp_client->audio;
|
||||||
|
|
||||||
|
/* Check to make sure audio stream contains a minimum number of bytes. */
|
||||||
|
if (Stream_GetRemainingLength(input_stream) < 12) {
|
||||||
|
guac_client_log(svc->client, GUAC_LOG_WARNING, "Audio WaveInfo PDU "
|
||||||
|
"does not contain the expected number of bytes. Sound may not "
|
||||||
|
"work as expected.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Read wave information */
|
/* Read wave information */
|
||||||
Stream_Read_UINT16(input_stream, rdpsnd->server_timestamp);
|
Stream_Read_UINT16(input_stream, rdpsnd->server_timestamp);
|
||||||
Stream_Read_UINT16(input_stream, format);
|
Stream_Read_UINT16(input_stream, format);
|
||||||
@ -266,6 +312,14 @@ void guac_rdpsnd_wave_handler(guac_rdp_common_svc* svc,
|
|||||||
|
|
||||||
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
||||||
guac_audio_stream* audio = rdp_client->audio;
|
guac_audio_stream* audio = rdp_client->audio;
|
||||||
|
|
||||||
|
/* Verify that the stream has bytes to cover the wave size plus header. */
|
||||||
|
if (Stream_Length(input_stream) < (rdpsnd->incoming_wave_size + 4)) {
|
||||||
|
guac_client_log(svc->client, GUAC_LOG_WARNING, "Audio Wave PDU does "
|
||||||
|
"not contain the expected number of bytes. Sound may not work "
|
||||||
|
"as expected.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Wave Confirmation PDU */
|
/* Wave Confirmation PDU */
|
||||||
wStream* output_stream = Stream_New(NULL, 8);
|
wStream* output_stream = Stream_New(NULL, 8);
|
||||||
|
@ -35,11 +35,19 @@ void guac_rdpsnd_process_receive(guac_rdp_common_svc* svc,
|
|||||||
guac_rdpsnd* rdpsnd = (guac_rdpsnd*) svc->data;
|
guac_rdpsnd* rdpsnd = (guac_rdpsnd*) svc->data;
|
||||||
guac_rdpsnd_pdu_header header;
|
guac_rdpsnd_pdu_header header;
|
||||||
|
|
||||||
|
/* Check that we have at least the 4 byte header (UINT8 + UINT8 + UINT16) */
|
||||||
|
if (Stream_GetRemainingLength(input_stream) < 4) {
|
||||||
|
guac_client_log(svc->client, GUAC_LOG_WARNING, "Audio Stream does not "
|
||||||
|
"contain the expected number of bytes. Audio redirection may "
|
||||||
|
"not work as expected.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Read RDPSND PDU header */
|
/* Read RDPSND PDU header */
|
||||||
Stream_Read_UINT8(input_stream, header.message_type);
|
Stream_Read_UINT8(input_stream, header.message_type);
|
||||||
Stream_Seek_UINT8(input_stream);
|
Stream_Seek_UINT8(input_stream);
|
||||||
Stream_Read_UINT16(input_stream, header.body_size);
|
Stream_Read_UINT16(input_stream, header.body_size);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If next PDU is SNDWAVE (due to receiving WaveInfo PDU previously),
|
* If next PDU is SNDWAVE (due to receiving WaveInfo PDU previously),
|
||||||
* ignore the header and parse as a Wave PDU.
|
* ignore the header and parse as a Wave PDU.
|
||||||
|
@ -116,6 +116,10 @@ static VOID guac_rdp_common_svc_handle_open_event(LPVOID user_param,
|
|||||||
svc->_input_stream = Stream_New(NULL, total_length);
|
svc->_input_stream = Stream_New(NULL, total_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* leave if we don't have a stream. */
|
||||||
|
if (svc->_input_stream == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
/* Add chunk to buffer only if sufficient space remains */
|
/* Add chunk to buffer only if sufficient space remains */
|
||||||
if (Stream_EnsureRemainingCapacity(svc->_input_stream, data_length))
|
if (Stream_EnsureRemainingCapacity(svc->_input_stream, data_length))
|
||||||
Stream_Write(svc->_input_stream, data, data_length);
|
Stream_Write(svc->_input_stream, data, data_length);
|
||||||
@ -137,6 +141,7 @@ static VOID guac_rdp_common_svc_handle_open_event(LPVOID user_param,
|
|||||||
svc->_receive_handler(svc, svc->_input_stream);
|
svc->_receive_handler(svc, svc->_input_stream);
|
||||||
|
|
||||||
Stream_Free(svc->_input_stream, TRUE);
|
Stream_Free(svc->_input_stream, TRUE);
|
||||||
|
svc->_input_stream = NULL;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,10 +35,17 @@
|
|||||||
*
|
*
|
||||||
* @param format
|
* @param format
|
||||||
* The structure to populate with data from the stream.
|
* The structure to populate with data from the stream.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* Zero on success or non-zero if an error occurs processing the format.
|
||||||
*/
|
*/
|
||||||
static void guac_rdp_ai_read_format(wStream* stream,
|
static int guac_rdp_ai_read_format(wStream* stream,
|
||||||
guac_rdp_ai_format* format) {
|
guac_rdp_ai_format* format) {
|
||||||
|
|
||||||
|
/* Check that we have at least 18 bytes (5 x UINT16, 2 x UINT32) */
|
||||||
|
if (Stream_GetRemainingLength(stream) < 18)
|
||||||
|
return 1;
|
||||||
|
|
||||||
/* Read audio format into structure */
|
/* Read audio format into structure */
|
||||||
Stream_Read_UINT16(stream, format->tag); /* wFormatTag */
|
Stream_Read_UINT16(stream, format->tag); /* wFormatTag */
|
||||||
Stream_Read_UINT16(stream, format->channels); /* nChannels */
|
Stream_Read_UINT16(stream, format->channels); /* nChannels */
|
||||||
@ -48,11 +55,19 @@ static void guac_rdp_ai_read_format(wStream* stream,
|
|||||||
Stream_Read_UINT16(stream, format->bps); /* wBitsPerSample */
|
Stream_Read_UINT16(stream, format->bps); /* wBitsPerSample */
|
||||||
Stream_Read_UINT16(stream, format->data_size); /* cbSize */
|
Stream_Read_UINT16(stream, format->data_size); /* cbSize */
|
||||||
|
|
||||||
/* Read arbitrary data block (if applicable) */
|
/* Read arbitrary data block (if applicable) and data is available. */
|
||||||
if (format->data_size != 0) {
|
if (format->data_size != 0) {
|
||||||
|
|
||||||
|
/* Check to make sure Stream contains expected bytes. */
|
||||||
|
if (Stream_GetRemainingLength(stream) < format->data_size)
|
||||||
|
return 1;
|
||||||
|
|
||||||
format->data = Stream_Pointer(stream); /* data */
|
format->data = Stream_Pointer(stream); /* data */
|
||||||
Stream_Seek(stream, format->data_size);
|
Stream_Seek(stream, format->data_size);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,6 +247,14 @@ static void guac_rdp_ai_send_formatchange(IWTSVirtualChannel* channel,
|
|||||||
void guac_rdp_ai_process_version(guac_client* client,
|
void guac_rdp_ai_process_version(guac_client* client,
|
||||||
IWTSVirtualChannel* channel, wStream* stream) {
|
IWTSVirtualChannel* channel, wStream* stream) {
|
||||||
|
|
||||||
|
/* Verify we have at least 4 bytes available (UINT32) */
|
||||||
|
if (Stream_GetRemainingLength(stream) < 4) {
|
||||||
|
guac_client_log(client, GUAC_LOG_WARNING, "Audio input Versoin PDU "
|
||||||
|
"does not contain the expected number of bytes. Audio input "
|
||||||
|
"redirection may not work as expected.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
UINT32 version;
|
UINT32 version;
|
||||||
Stream_Read_UINT32(stream, version);
|
Stream_Read_UINT32(stream, version);
|
||||||
|
|
||||||
@ -258,15 +281,28 @@ void guac_rdp_ai_process_formats(guac_client* client,
|
|||||||
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
||||||
guac_rdp_audio_buffer* audio_buffer = rdp_client->audio_input;
|
guac_rdp_audio_buffer* audio_buffer = rdp_client->audio_input;
|
||||||
|
|
||||||
|
/* Verify we have at least 8 bytes available (2 x UINT32) */
|
||||||
|
if (Stream_GetRemainingLength(stream) < 8) {
|
||||||
|
guac_client_log(client, GUAC_LOG_WARNING, "Audio input Sound Formats "
|
||||||
|
"PDU does not contain the expected number of bytes. Audio "
|
||||||
|
"input redirection may not work as expected.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
UINT32 num_formats;
|
UINT32 num_formats;
|
||||||
Stream_Read_UINT32(stream, num_formats); /* NumFormats */
|
Stream_Read_UINT32(stream, num_formats); /* NumFormats */
|
||||||
Stream_Seek_UINT32(stream); /* cbSizeFormatsPacket (MUST BE IGNORED) */
|
Stream_Seek_UINT32(stream); /* cbSizeFormatsPacket (MUST BE IGNORED) */
|
||||||
|
|
||||||
UINT32 index;
|
UINT32 index;
|
||||||
for (index = 0; index < num_formats; index++) {
|
for (index = 0; index < num_formats; index++) {
|
||||||
|
|
||||||
guac_rdp_ai_format format;
|
guac_rdp_ai_format format;
|
||||||
guac_rdp_ai_read_format(stream, &format);
|
if (guac_rdp_ai_read_format(stream, &format)) {
|
||||||
|
guac_client_log(client, GUAC_LOG_WARNING, "Error occurred "
|
||||||
|
"processing audio input formats. Audio input redirection "
|
||||||
|
"may not work as expected.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Ignore anything but WAVE_FORMAT_PCM */
|
/* Ignore anything but WAVE_FORMAT_PCM */
|
||||||
if (format.tag != GUAC_RDP_WAVE_FORMAT_PCM)
|
if (format.tag != GUAC_RDP_WAVE_FORMAT_PCM)
|
||||||
@ -306,6 +342,14 @@ void guac_rdp_ai_process_open(guac_client* client,
|
|||||||
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
||||||
guac_rdp_audio_buffer* audio_buffer = rdp_client->audio_input;
|
guac_rdp_audio_buffer* audio_buffer = rdp_client->audio_input;
|
||||||
|
|
||||||
|
/* Verify we have at least 8 bytes available (2 x UINT32) */
|
||||||
|
if (Stream_GetRemainingLength(stream) < 8) {
|
||||||
|
guac_client_log(client, GUAC_LOG_WARNING, "Audio input Open PDU does "
|
||||||
|
"not contain the expected number of bytes. Audio input "
|
||||||
|
"redirection may not work as expected.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
UINT32 packet_frames;
|
UINT32 packet_frames;
|
||||||
UINT32 initial_format;
|
UINT32 initial_format;
|
||||||
|
|
||||||
|
@ -52,10 +52,18 @@
|
|||||||
static void guac_rdp_ai_handle_data(guac_client* client,
|
static void guac_rdp_ai_handle_data(guac_client* client,
|
||||||
IWTSVirtualChannel* channel, wStream* stream) {
|
IWTSVirtualChannel* channel, wStream* stream) {
|
||||||
|
|
||||||
|
/* Verify we have at least 1 byte in the stream (UINT8) */
|
||||||
|
if (Stream_GetRemainingLength(stream) < 1) {
|
||||||
|
guac_client_log(client, GUAC_LOG_WARNING, "Audio input PDU header does "
|
||||||
|
"not contain the expected number of bytes. Audio input "
|
||||||
|
"redirection may not work as expected.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* Read message ID from received PDU */
|
/* Read message ID from received PDU */
|
||||||
BYTE message_id;
|
BYTE message_id;
|
||||||
Stream_Read_UINT8(stream, message_id);
|
Stream_Read_UINT8(stream, message_id);
|
||||||
|
|
||||||
/* Invoke appropriate message processor based on ID */
|
/* Invoke appropriate message processor based on ID */
|
||||||
switch (message_id) {
|
switch (message_id) {
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user