diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.c b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.c index 0f453038..1ea67016 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.c +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages-file-info.c @@ -135,11 +135,28 @@ void guac_rdpdr_fs_process_set_rename_info(guac_rdp_common_svc* svc, wStream* output_stream; 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 */ Stream_Seek_UINT8(input_stream); /* ReplaceIfExists */ Stream_Seek_UINT8(input_stream); /* RootDirectory */ 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 */ guac_rdp_utf16_to_utf8(Stream_Pointer(input_stream), filename_length/2, destination_path, sizeof(destination_path)); @@ -192,6 +209,15 @@ void guac_rdpdr_fs_process_set_allocation_info(guac_rdp_common_svc* svc, UINT64 size; 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 */ 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; 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 */ Stream_Read_UINT64(input_stream, size); /* AllocationSize */ diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.c b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.c index 529eea57..facba6f3 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.c +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-fs-messages.c @@ -48,6 +48,14 @@ void guac_rdpdr_fs_process_create(guac_rdp_common_svc* svc, int create_disposition, create_options, path_length; 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 */ Stream_Read_UINT32(input_stream, desired_access); 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, 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 */ guac_rdp_utf16_to_utf8(Stream_Pointer(input_stream), path_length/2 - 1, path, sizeof(path)); @@ -123,6 +139,14 @@ void guac_rdpdr_fs_process_read(guac_rdp_common_svc* svc, 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 */ Stream_Read_UINT32(input_stream, length); Stream_Read_UINT64(input_stream, offset); @@ -172,6 +196,14 @@ void guac_rdpdr_fs_process_write(guac_rdp_common_svc* svc, 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 */ Stream_Read_UINT32(input_stream, length); 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, __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 */ bytes_written = guac_rdp_fs_write((guac_rdp_fs*) device->data, 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; + /* 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); /* 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; + /* 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); /* 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 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, length); /* Length */ 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) 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 */ Stream_Read_UINT32(input_stream, fs_information_class); 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 (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 */ - + /* Convert path to UTF-8 */ guac_rdp_utf16_to_utf8(Stream_Pointer(input_stream), path_length/2 - 1, file->dir_pattern, sizeof(file->dir_pattern)); diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-messages.c b/src/protocols/rdp/channels/rdpdr/rdpdr-messages.c index 28a27e67..5fee4658 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-messages.c +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-messages.c @@ -212,6 +212,14 @@ void guac_rdpdr_process_server_announce(guac_rdp_common_svc* svc, 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, minor); 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; 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, 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_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 */ Stream_Read_UINT32(input_stream, iorequest.device_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 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 */ Stream_Read_UINT16(input_stream, count); Stream_Seek(input_stream, 2); @@ -316,9 +348,27 @@ void guac_rdpdr_process_server_capability(guac_rdp_common_svc* svc, int type; 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, 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 */ 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); diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr-printer.c b/src/protocols/rdp/channels/rdpdr/rdpdr-printer.c index d90116f5..4ff70535 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr-printer.c +++ b/src/protocols/rdp/channels/rdpdr/rdpdr-printer.c @@ -67,12 +67,28 @@ void guac_rdpdr_process_print_job_write(guac_rdp_common_svc* svc, int length; 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 */ Stream_Read_UINT32(input_stream, length); Stream_Seek(input_stream, 8); /* Offset */ Stream_Seek(input_stream, 20); /* Padding */ 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 */ if (job != NULL && (length = guac_rdp_print_job_write(job, buffer, length)) >= 0) { diff --git a/src/protocols/rdp/channels/rdpdr/rdpdr.c b/src/protocols/rdp/channels/rdpdr/rdpdr.c index e04bc9d7..68bb73e4 100644 --- a/src/protocols/rdp/channels/rdpdr/rdpdr.c +++ b/src/protocols/rdp/channels/rdpdr/rdpdr.c @@ -38,6 +38,17 @@ void guac_rdpdr_process_receive(guac_rdp_common_svc* svc, int component; 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 */ Stream_Read_UINT16(input_stream, component); Stream_Read_UINT16(input_stream, packet_id); diff --git a/src/protocols/rdp/channels/rdpsnd/rdpsnd-messages.c b/src/protocols/rdp/channels/rdpsnd/rdpsnd-messages.c index 1d69e069..c057cd11 100644 --- a/src/protocols/rdp/channels/rdpsnd/rdpsnd-messages.c +++ b/src/protocols/rdp/channels/rdpsnd/rdpsnd-messages.c @@ -50,6 +50,17 @@ void guac_rdpsnd_formats_handler(guac_rdp_common_svc* svc, /* Reset own format count */ 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 */ Stream_Seek(input_stream, 14); 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 */ 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 */ Stream_Read_UINT16(input_stream, format_tag); Stream_Read_UINT16(input_stream, channels); @@ -106,6 +126,16 @@ void guac_rdpsnd_formats_handler(guac_rdp_common_svc* svc, /* Skip past extra data */ 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); /* If PCM, accept */ @@ -205,6 +235,14 @@ void guac_rdpsnd_training_handler(guac_rdp_common_svc* svc, 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 */ Stream_Read_UINT16(input_stream, rdpsnd->server_timestamp); 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_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 */ Stream_Read_UINT16(input_stream, rdpsnd->server_timestamp); 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_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 */ wStream* output_stream = Stream_New(NULL, 8); diff --git a/src/protocols/rdp/channels/rdpsnd/rdpsnd.c b/src/protocols/rdp/channels/rdpsnd/rdpsnd.c index be6034d2..40b53150 100644 --- a/src/protocols/rdp/channels/rdpsnd/rdpsnd.c +++ b/src/protocols/rdp/channels/rdpsnd/rdpsnd.c @@ -35,11 +35,19 @@ void guac_rdpsnd_process_receive(guac_rdp_common_svc* svc, guac_rdpsnd* rdpsnd = (guac_rdpsnd*) svc->data; 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 */ Stream_Read_UINT8(input_stream, header.message_type); Stream_Seek_UINT8(input_stream); Stream_Read_UINT16(input_stream, header.body_size); - + /* * If next PDU is SNDWAVE (due to receiving WaveInfo PDU previously), * ignore the header and parse as a Wave PDU. diff --git a/src/protocols/rdp/plugins/guac-common-svc/guac-common-svc.c b/src/protocols/rdp/plugins/guac-common-svc/guac-common-svc.c index 535cb453..91dee29b 100644 --- a/src/protocols/rdp/plugins/guac-common-svc/guac-common-svc.c +++ b/src/protocols/rdp/plugins/guac-common-svc/guac-common-svc.c @@ -116,6 +116,10 @@ static VOID guac_rdp_common_svc_handle_open_event(LPVOID user_param, 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 */ if (Stream_EnsureRemainingCapacity(svc->_input_stream, 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); Stream_Free(svc->_input_stream, TRUE); + svc->_input_stream = NULL; } diff --git a/src/protocols/rdp/plugins/guacai/guacai-messages.c b/src/protocols/rdp/plugins/guacai/guacai-messages.c index 38f7a7c4..eb9a79da 100644 --- a/src/protocols/rdp/plugins/guacai/guacai-messages.c +++ b/src/protocols/rdp/plugins/guacai/guacai-messages.c @@ -35,10 +35,17 @@ * * @param format * 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) { + /* 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 */ Stream_Read_UINT16(stream, format->tag); /* wFormatTag */ 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->data_size); /* cbSize */ - /* Read arbitrary data block (if applicable) */ + /* Read arbitrary data block (if applicable) and data is available. */ 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 */ 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, 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; 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_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; Stream_Read_UINT32(stream, num_formats); /* NumFormats */ Stream_Seek_UINT32(stream); /* cbSizeFormatsPacket (MUST BE IGNORED) */ - + UINT32 index; for (index = 0; index < num_formats; index++) { 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 */ 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_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 initial_format; diff --git a/src/protocols/rdp/plugins/guacai/guacai.c b/src/protocols/rdp/plugins/guacai/guacai.c index 15de8655..b5383c4f 100644 --- a/src/protocols/rdp/plugins/guacai/guacai.c +++ b/src/protocols/rdp/plugins/guacai/guacai.c @@ -52,10 +52,18 @@ static void guac_rdp_ai_handle_data(guac_client* client, 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 */ BYTE message_id; Stream_Read_UINT8(stream, message_id); - + /* Invoke appropriate message processor based on ID */ switch (message_id) {